1/*! @name videojs-vr @version 1.7.2 @license Apache-2.0 */ 2(function (global, factory) { 3 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('global/window'), require('global/document'), require('video.js')) : 4 typeof define === 'function' && define.amd ? define(['global/window', 'global/document', 'video.js'], factory) : 5 (global = global || self, global.videojsVr = factory(global.window, global.document, global.videojs)); 6 }(this, (function (window$1, document$1, videojs) { 'use strict'; 7 8 window$1 = window$1 && window$1.hasOwnProperty('default') ? window$1['default'] : window$1; 9 document$1 = document$1 && document$1.hasOwnProperty('default') ? document$1['default'] : document$1; 10 videojs = videojs && videojs.hasOwnProperty('default') ? videojs['default'] : videojs; 11 12 function _assertThisInitialized(self) { 13 if (self === void 0) { 14 throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 15 } 16 17 return self; 18 } 19 20 var assertThisInitialized = _assertThisInitialized; 21 22 function _inheritsLoose(subClass, superClass) { 23 subClass.prototype = Object.create(superClass.prototype); 24 subClass.prototype.constructor = subClass; 25 subClass.__proto__ = superClass; 26 } 27 28 var inheritsLoose = _inheritsLoose; 29 30 var version = "1.7.2"; 31 32 var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; 33 34 function unwrapExports (x) { 35 return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; 36 } 37 38 function createCommonjsModule(fn, module) { 39 return module = { exports: {} }, fn(module, module.exports), module.exports; 40 } 41 42 var webvrPolyfill = createCommonjsModule(function (module, exports) { 43 /** 44 * @license 45 * webvr-polyfill 46 * Copyright (c) 2015-2017 Google 47 * Licensed under the Apache License, Version 2.0 (the "License"); 48 * you may not use this file except in compliance with the License. 49 * You may obtain a copy of the License at 50 * 51 * http://www.apache.org/licenses/LICENSE-2.0 52 * 53 * Unless required by applicable law or agreed to in writing, software 54 * distributed under the License is distributed on an "AS IS" BASIS, 55 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 56 * See the License for the specific language governing permissions and 57 * limitations under the License. 58 */ 59 60 /** 61 * @license 62 * cardboard-vr-display 63 * Copyright (c) 2015-2017 Google 64 * Licensed under the Apache License, Version 2.0 (the "License"); 65 * you may not use this file except in compliance with the License. 66 * You may obtain a copy of the License at 67 * 68 * http://www.apache.org/licenses/LICENSE-2.0 69 * 70 * Unless required by applicable law or agreed to in writing, software 71 * distributed under the License is distributed on an "AS IS" BASIS, 72 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 73 * See the License for the specific language governing permissions and 74 * limitations under the License. 75 */ 76 77 /** 78 * @license 79 * webvr-polyfill-dpdb 80 * Copyright (c) 2017 Google 81 * Licensed under the Apache License, Version 2.0 (the "License"); 82 * you may not use this file except in compliance with the License. 83 * You may obtain a copy of the License at 84 * 85 * http://www.apache.org/licenses/LICENSE-2.0 86 * 87 * Unless required by applicable law or agreed to in writing, software 88 * distributed under the License is distributed on an "AS IS" BASIS, 89 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 90 * See the License for the specific language governing permissions and 91 * limitations under the License. 92 */ 93 94 /** 95 * @license 96 * wglu-preserve-state 97 * Copyright (c) 2016, Brandon Jones. 98 * 99 * Permission is hereby granted, free of charge, to any person obtaining a copy 100 * of this software and associated documentation files (the "Software"), to deal 101 * in the Software without restriction, including without limitation the rights 102 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 103 * copies of the Software, and to permit persons to whom the Software is 104 * furnished to do so, subject to the following conditions: 105 * 106 * The above copyright notice and this permission notice shall be included in 107 * all copies or substantial portions of the Software. 108 * 109 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 110 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 111 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 112 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 113 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 114 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 115 * THE SOFTWARE. 116 */ 117 118 /** 119 * @license 120 * nosleep.js 121 * Copyright (c) 2017, Rich Tibbett 122 * 123 * Permission is hereby granted, free of charge, to any person obtaining a copy 124 * of this software and associated documentation files (the "Software"), to deal 125 * in the Software without restriction, including without limitation the rights 126 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 127 * copies of the Software, and to permit persons to whom the Software is 128 * furnished to do so, subject to the following conditions: 129 * 130 * The above copyright notice and this permission notice shall be included in 131 * all copies or substantial portions of the Software. 132 * 133 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 134 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 135 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 136 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 137 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 138 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 139 * THE SOFTWARE. 140 */ 141 142 (function (global, factory) { 143 module.exports = factory() ; 144 }(commonjsGlobal, (function () { 145 var commonjsGlobal$1 = typeof window !== 'undefined' ? window : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {}; 146 147 148 149 function unwrapExports (x) { 150 return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, 'default') ? x['default'] : x; 151 } 152 153 function createCommonjsModule(fn, module) { 154 return module = { exports: {} }, fn(module, module.exports), module.exports; 155 } 156 157 var race = function race(promises) { 158 if (Promise.race) { 159 return Promise.race(promises); 160 } 161 return new Promise(function (resolve, reject) { 162 for (var i = 0; i < promises.length; i++) { 163 promises[i].then(resolve, reject); 164 } 165 }); 166 }; 167 168 var isMobile = function isMobile() { 169 return (/Android/i.test(navigator.userAgent) || /iPhone|iPad|iPod/i.test(navigator.userAgent) 170 ); 171 }; 172 var copyArray = function copyArray(source, dest) { 173 for (var i = 0, n = source.length; i < n; i++) { 174 dest[i] = source[i]; 175 } 176 }; 177 var extend = function extend(dest, src) { 178 for (var key in src) { 179 if (src.hasOwnProperty(key)) { 180 dest[key] = src[key]; 181 } 182 } 183 return dest; 184 }; 185 186 var cardboardVrDisplay = createCommonjsModule(function (module, exports
186) { 187 /** 188 * @license 189 * cardboard-vr-display 190 * Copyright (c) 2015-2017 Google 191 * Licensed under the Apache License, Version 2.0 (the "License"); 192 * you may not use this file except in compliance with the License. 193 * You may obtain a copy of the License at 194 * 195 * http://www.apache.org/licenses/LICENSE-2.0 196 * 197 * Unless required by applicable law or agreed to in writing, software 198 * distributed under the License is distributed on an "AS IS" BASIS, 199 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 * See the License for the specific language governing permissions and 201 * limitations under the License. 202 */ 203 /** 204 * @license 205 * gl-preserve-state 206 * Copyright (c) 2016, Brandon Jones. 207 * 208 * Permission is hereby granted, free of charge, to any person obtaining a copy 209 * of this software and associated documentation files (the "Software"), to deal 210 * in the Software without restriction, including without limitation the rights 211 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 212 * copies of the Software, and to permit persons to whom the Software is 213 * furnished to do so, subject to the following conditions: 214 * 215 * The above copyright notice and this permission notice shall be included in 216 * all copies or substantial portions of the Software. 217 * 218 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 219 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 220 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 221 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 222 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 223 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 224 * THE SOFTWARE. 225 */ 226 /** 227 * @license 228 * webvr-polyfill-dpdb 229 * Copyright (c) 2015-2017 Google 230 * Licensed under the Apache License, Version 2.0 (the "License"); 231 * you may not use this file except in compliance with the License. 232 * You may obtain a copy of the License at 233 * 234 * http://www.apache.org/licenses/LICENSE-2.0 235 * 236 * Unless required by applicable law or agreed to in writing, software 237 * distributed under the License is distributed on an "AS IS" BASIS, 238 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 239 * See the License for the specific language governing permissions and 240 * limitations under the License. 241 */ 242 /** 243 * @license 244 * nosleep.js 245 * Copyright (c) 2017, Rich Tibbett 246 * 247 * Permission is hereby granted, free of charge, to any person obtaining a copy 248 * of this software and associated documentation files (the "Software"), to deal 249 * in the Software without restriction, including without limitation the rights 250 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 251 * copies of the Software, and to permit persons to whom the Software is 252 * furnished to do so, subject to the following conditions: 253 * 254 * The above copyright notice and this permission notice shall be included in 255 * all copies or substantial portions of the Software. 256 * 257 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 258 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 259 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 260 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 261 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 262 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 263 * THE SOFTWARE. 264 */ 265 (function (global, factory) { 266 module.exports = factory(); 267 }(commonjsGlobal$1, (function () { var classCallCheck = function (instance, Constructor) { 268 if (!(instance instanceof Constructor)) { 269 throw new TypeError("Cannot call a class as a function"); 270 } 271 }; 272 var createClass = function () { 273 function defineProperties(target, props) { 274 for (var i = 0; i < props.length; i++) { 275 var descriptor = props[i]; 276 descriptor.enumerable = descriptor.enumerable || false; 277 descriptor.configurable = true; 278 if ("value" in descriptor) descriptor.writable = true;
vendor: 26,977 bytes, lines 279-1033
279 Object.defineProperty(target, descriptor.key, descriptor); 280 } 281 } 282 return function (Constructor, protoProps, staticProps) { 283 if (protoProps) defineProperties(Constructor.prototype, protoProps); 284 if (staticProps) defineProperties(Constructor, staticProps); 285 return Constructor; 286 }; 287 }(); 288 var slicedToArray = function () { 289 function sliceIterator(arr, i) { 290 var _arr = []; 291 var _n = true; 292 var _d = false; 293 var _e = undefined; 294 try { 295 for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { 296 _arr.push(_s.value); 297 if (i && _arr.length === i) break; 298 } 299 } catch (err) { 300 _d = true; 301 _e = err; 302 } finally { 303 try { 304 if (!_n && _i["return"]) _i["return"](); 305 } finally { 306 if (_d) throw _e; 307 } 308 } 309 return _arr; 310 } 311 return function (arr, i) { 312 if (Array.isArray(arr)) { 313 return arr; 314 } else if (Symbol.iterator in Object(arr)) { 315 return sliceIterator(arr, i); 316 } else { 317 throw new TypeError("Invalid attempt to destructure non-iterable instance"); 318 } 319 }; 320 }(); 321 var MIN_TIMESTEP = 0.001; 322 var MAX_TIMESTEP = 1; 323 var base64 = function base64(mimeType, _base) { 324 return 'data:' + mimeType + ';base64,' + _base; 325 }; 326 var lerp = function lerp(a, b, t) { 327 return a + (b - a) * t; 328 }; 329 var isIOS = function () { 330 var isIOS = /iPad|iPhone|iPod/.test(navigator.platform); 331 return function () { 332 return isIOS; 333 }; 334 }(); 335 var isWebViewAndroid = function () { 336 var isWebViewAndroid = navigator.userAgent.indexOf('Version') !== -1 && navigator.userAgent.indexOf('Android') !== -1 && navigator.userAgent.indexOf('Chrome') !== -1; 337 return function () { 338 return isWebViewAndroid; 339 }; 340 }(); 341 var isSafari = function () { 342 var isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent); 343 return function () { 344 return isSafari; 345 }; 346 }(); 347 var isFirefoxAndroid = function () { 348 var isFirefoxAndroid = navigator.userAgent.indexOf('Firefox') !== -1 && navigator.userAgent.indexOf('Android') !== -1; 349 return function () { 350 return isFirefoxAndroid; 351 }; 352 }(); 353 var getChromeVersion = function () { 354 var match = navigator.userAgent.match(/.*Chrome\/([0-9]+)/); 355 var value = match ? parseInt(match[1], 10) : null; 356 return function () { 357 return value; 358 }; 359 }(); 360 var isChromeWithoutDeviceMotion = function () { 361 var value = false; 362 if (getChromeVersion() === 65) { 363 var match = navigator.userAgent.match(/.*Chrome\/([0-9\.]*)/); 364 if (match) { 365 var _match$1$split = match[1].split('.'), 366 _match$1$split2 = slicedToArray(_match$1$split, 4), 367 major = _match$1$split2[0], 368 minor = _match$1$split2[1], 369 branch = _match$1$split2[2], 370 build = _match$1$split2[3]; 371 value = parseInt(branch, 10) === 3325 && parseInt(build, 10) < 148; 372 } 373 } 374 return function () { 375 return value; 376 }; 377 }(); 378 var isR7 = function () { 379 var isR7 = navigator.userAgent.indexOf('R7 Build') !== -1; 380 return function () { 381 return isR7; 382 }; 383 }(); 384 var isLandscapeMode = function isLandscapeMode() { 385 var rtn = window.orientation == 90 || window.orientation == -90; 386 return isR7() ? !rtn : rtn; 387 }; 388 var isTimestampDeltaValid = function isTimestampDeltaValid(timestampDeltaS) { 389 if (isNaN(timestampDeltaS)) { 390 return false; 391 } 392 if (timestampDeltaS <= MIN_TIMESTEP) { 393 return false; 394 } 395 if (timestampDeltaS > MAX_TIMESTEP) { 396 return false; 397 } 398 return true; 399 }; 400 var getScreenWidth = function getScreenWidth() { 401 return Math.max(window.screen.width, window.screen.height) * window.devicePixelRatio; 402 }; 403 var getScreenHeight = function getScreenHeight() { 404 return Math.min(window.screen.width, window.screen.height) * window.devicePixelRatio; 405 }; 406 var requestFullscreen = function requestFullscreen(element) { 407 if (isWebViewAndroid()) { 408 return false; 409 } 410 if (element.requestFullscreen) { 411 element.requestFullscreen(); 412 } else if (element.webkitRequestFullscreen) { 413 element.webkitRequestFullscreen(); 414 } else if (element.mozRequestFullScreen) { 415 element.mozRequestFullScreen(); 416 } else if (element.msRequestFullscreen) { 417 element.msRequestFullscreen(); 418 } else { 419 return false; 420 } 421 return true; 422 }; 423 var exitFullscreen = function exitFullscreen() { 424 if (document.exitFullscreen) { 425 document.exitFullscreen(); 426 } else if (document.webkitExitFullscreen) { 427 document.webkitExitFullscreen(); 428 } else if (document.mozCancelFullScreen) { 429 document.mozCancelFullScreen(); 430 } else if (document.msExitFullscreen) { 431 document.msExitFullscreen(); 432 } else { 433 return false; 434 } 435 return true; 436 }; 437 var getFullscreenElement = function getFullscreenElement() { 438 return document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement; 439 }; 440 var linkProgram = function linkProgram(gl, vertexSource, fragmentSource, attribLocationMap) { 441 var vertexShader = gl.createShader(gl.VERTEX_SHADER); 442 gl.shaderSource(vertexShader, vertexSource); 443 gl.compileShader(vertexShader); 444 var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); 445 gl.shaderSource(fragmentShader, fragmentSource); 446 gl.compileShader(fragmentShader); 447 var program = gl.createProgram(); 448 gl.attachShader(program, vertexShader); 449 gl.attachShader(program, fragmentShader); 450 for (var attribName in attribLocationMap) { 451 gl.bindAttribLocation(program, attribLocationMap[attribName], attribName); 452 }gl.linkProgram(program); 453 gl.deleteShader(vertexShader); 454 gl.deleteShader(fragmentShader); 455 return program; 456 }; 457 var getProgramUniforms = function getProgramUniforms(gl, program) { 458 var uniforms = {}; 459 var uniformCount = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS); 460 var uniformName = ''; 461 for (var i = 0; i < uniformCount; i++) { 462 var uniformInfo = gl.getActiveUniform(program, i); 463 uniformName = uniformInfo.name.replace('[0]', ''); 464 uniforms[uniformName] = gl.getUniformLocation(program, uniformName); 465 } 466 return uniforms; 467 }; 468 var orthoMatrix = function orthoMatrix(out, left, right, bottom, top, near, far) { 469 var lr = 1 / (left - right), 470 bt = 1 / (bottom - top), 471 nf = 1 / (near - far); 472 out[0] = -2 * lr; 473 out[1] = 0; 474 out[2] = 0; 475 out[3] = 0; 476 out[4] = 0; 477 out[5] = -2 * bt; 478 out[6] = 0; 479 out[7] = 0; 480 out[8] = 0; 481 out[9] = 0; 482 out[10] = 2 * nf; 483 out[11] = 0; 484 out[12] = (left + right) * lr; 485 out[13] = (top + bottom) * bt; 486 out[14] = (far + near) * nf; 487 out[15] = 1; 488 return out; 489 }; 490 var isMobile = function isMobile() { 491 var check = false; 492 (function (a) { 493 if (/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0, 4))) check = true; 494 })(navigator.userAgent || navigator.vendor || window.opera); 495 return check; 496 }; 497 var extend = function extend(dest, src) { 498 for (var key in src) { 499 if (src.hasOwnProperty(key)) { 500 dest[key] = src[key]; 501 } 502 } 503 return dest; 504 }; 505 var safariCssSizeWorkaround = function safariCssSizeWorkaround(canvas) { 506 if (isIOS()) { 507 var width = canvas.style.width; 508 var height = canvas.style.height; 509 canvas.style.width = parseInt(width) + 1 + 'px'; 510 canvas.style.height = parseInt(height) + 'px'; 511 setTimeout(function () { 512 canvas.style.width = width; 513 canvas.style.height = height; 514 }, 100); 515 } 516 window.canvas = canvas; 517 }; 518 var frameDataFromPose = function () { 519 var piOver180 = Math.PI / 180.0; 520 var rad45 = Math.PI * 0.25; 521 function mat4_perspectiveFromFieldOfView(out, fov, near, far) { 522 var upTan = Math.tan(fov ? fov.upDegrees * piOver180 : rad45), 523 downTan = Math.tan(fov ? fov.downDegrees * piOver180 : rad45), 524 leftTan = Math.tan(fov ? fov.leftDegrees * piOver180 : rad45), 525 rightTan = Math.tan(fov ? fov.rightDegrees * piOver180 : rad45), 526 xScale = 2.0 / (leftTan + rightTan), 527 yScale = 2.0 / (upTan + downTan); 528 out[0] = xScale; 529 out[1] = 0.0; 530 out[2] = 0.0; 531 out[3] = 0.0; 532 out[4] = 0.0; 533 out[5] = yScale; 534 out[6] = 0.0; 535 out[7] = 0.0; 536 out[8] = -((leftTan - rightTan) * xScale * 0.5); 537 out[9] = (upTan - downTan) * yScale * 0.5; 538 out[10] = far / (near - far); 539 out[11] = -1.0; 540 out[12] = 0.0; 541 out[13] = 0.0; 542 out[14] = far * near / (near - far); 543 out[15] = 0.0; 544 return out; 545 } 546 function mat4_fromRotationTranslation(out, q, v) { 547 var x = q[0], 548 y = q[1], 549 z = q[2], 550 w = q[3], 551 x2 = x + x, 552 y2 = y + y, 553 z2 = z + z, 554 xx = x * x2, 555 xy = x * y2, 556 xz = x * z2, 557 yy = y * y2, 558 yz = y * z2, 559 zz = z * z2, 560 wx = w * x2, 561 wy = w * y2, 562 wz = w * z2; 563 out[0] = 1 - (yy + zz); 564 out[1] = xy + wz; 565 out[2] = xz - wy; 566 out[3] = 0; 567 out[4] = xy - wz; 568 out[5] = 1 - (xx + zz); 569 out[6] = yz + wx; 570 out[7] = 0; 571 out[8] = xz + wy; 572 out[9] = yz - wx; 573 out[10] = 1 - (xx + yy); 574 out[11] = 0; 575 out[12] = v[0]; 576 out[13] = v[1]; 577 out[14] = v[2]; 578 out[15] = 1; 579 return out; 580 } 581 function mat4_translate(out, a, v) { 582 var x = v[0], 583 y = v[1], 584 z = v[2], 585 a00, 586 a01, 587 a02, 588 a03, 589 a10, 590 a11, 591 a12, 592 a13, 593 a20, 594 a21, 595 a22, 596 a23; 597 if (a === out) { 598 out[12] = a[0] * x + a[4] * y + a[8] * z + a[12]; 599 out[13] = a[1] * x + a[5] * y + a[9] * z + a[13]; 600 out[14] = a[2] * x + a[6] * y + a[10] * z + a[14]; 601 out[15] = a[3] * x + a[7] * y + a[11] * z + a[15]; 602 } else { 603 a00 = a[0];a01 = a[1];a02 = a[2];a03 = a[3]; 604 a10 = a[4];a11 = a[5];a12 = a[6];a13 = a[7]; 605 a20 = a[8];a21 = a[9];a22 = a[10];a23 = a[11]; 606 out[0] = a00;out[1] = a01;out[2] = a02;out[3] = a03; 607 out[4] = a10;out[5] = a11;out[6] = a12;out[7] = a13; 608 out[8] = a20;out[9] = a21;out[10] = a22;out[11] = a23; 609 out[12] = a00 * x + a10 * y + a20 * z + a[12]; 610 out[13] = a01 * x + a11 * y + a21 * z + a[13]; 611 out[14] = a02 * x + a12 * y + a22 * z + a[14]; 612 out[15] = a03 * x + a13 * y + a23 * z + a[15]; 613 } 614 return out; 615 } 616 function mat4_invert(out, a) { 617 var a00 = a[0], 618 a01 = a[1], 619 a02 = a[2], 620 a03 = a[3], 621 a10 = a[4], 622 a11 = a[5], 623 a12 = a[6], 624 a13 = a[7], 625 a20 = a[8], 626 a21 = a[9], 627 a22 = a[10], 628 a23 = a[11], 629 a30 = a[12], 630 a31 = a[13], 631 a32 = a[14], 632 a33 = a[15], 633 b00 = a00 * a11 - a01 * a10, 634 b01 = a00 * a12 - a02 * a10, 635 b02 = a00 * a13 - a03 * a10, 636 b03 = a01 * a12 - a02 * a11, 637 b04 = a01 * a13 - a03 * a11, 638 b05 = a02 * a13 - a03 * a12, 639 b06 = a20 * a31 - a21 * a30, 640 b07 = a20 * a32 - a22 * a30, 641 b08 = a20 * a33 - a23 * a30, 642 b09 = a21 * a32 - a22 * a31, 643 b10 = a21 * a33 - a23 * a31, 644 b11 = a22 * a33 - a23 * a32, 645 det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06; 646 if (!det) { 647 return null; 648 } 649 det = 1.0 / det; 650 out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det; 651 out[1] = (a02 * b10 - a01 * b11 - a03 * b09) * det; 652 out[2] = (a31 * b05 - a32 * b04 + a33 * b03) * det; 653 out[3] = (a22 * b04 - a21 * b05 - a23 * b03) * det; 654 out[4] = (a12 * b08 - a10 * b11 - a13 * b07) * det; 655 out[5] = (a00 * b11 - a02 * b08 + a03 * b07) * det; 656 out[6] = (a32 * b02 - a30 * b05 - a33 * b01) * det; 657 out[7] = (a20 * b05 - a22 * b02 + a23 * b01) * det; 658 out[8] = (a10 * b10 - a11 * b08 + a13 * b06) * det; 659 out[9] = (a01 * b08 - a00 * b10 - a03 * b06) * det; 660 out[10] = (a30 * b04 - a31 * b02 + a33 * b00) * det; 661 out[11] = (a21 * b02 - a20 * b04 - a23 * b00) * det; 662 out[12] = (a11 * b07 - a10 * b09 - a12 * b06) * det; 663 out[13] = (a00 * b09 - a01 * b07 + a02 * b06) * det; 664 out[14] = (a31 * b01 - a30 * b03 - a32 * b00) * det; 665 out[15] = (a20 * b03 - a21 * b01 + a22 * b00) * det; 666 return out; 667 } 668 var defaultOrientation = new Float32Array([0, 0, 0, 1]); 669 var defaultPosition = new Float32Array([0, 0, 0]); 670 function updateEyeMatrices(projection, view, pose, fov, offset, vrDisplay) { 671 mat4_perspectiveFromFieldOfView(projection, fov || null, vrDisplay.depthNear, vrDisplay.depthFar); 672 var orientation = pose.orientation || defaultOrientation; 673 var position = pose.position || defaultPosition; 674 mat4_fromRotationTranslation(view, orientation, position); 675 if (offset) mat4_translate(view, view, offset); 676 mat4_invert(view, view); 677 } 678 return function (frameData, pose, vrDisplay) { 679 if (!frameData || !pose) return false; 680 frameData.pose = pose; 681 frameData.timestamp = pose.timestamp; 682 updateEyeMatrices(frameData.leftProjectionMatrix, frameData.leftViewMatrix, pose, vrDisplay._getFieldOfView("left"), vrDisplay._getEyeOffset("left"), vrDisplay); 683 updateEyeMatrices(frameData.rightProjectionMatrix, frameData.rightViewMatrix, pose, vrDisplay._getFieldOfView("right"), vrDisplay._getEyeOffset("right"), vrDisplay); 684 return true; 685 }; 686 }(); 687 var isInsideCrossOriginIFrame = function isInsideCrossOriginIFrame() { 688 var isFramed = window.self !== window.top; 689 var refOrigin = getOriginFromUrl(document.referrer); 690 var thisOrigin = getOriginFromUrl(window.location.href); 691 return isFramed && refOrigin !== thisOrigin; 692 }; 693 var getOriginFromUrl = function getOriginFromUrl(url) { 694 var domainIdx; 695 var protoSepIdx = url.indexOf("://"); 696 if (protoSepIdx !== -1) { 697 domainIdx = protoSepIdx + 3; 698 } else { 699 domainIdx = 0; 700 } 701 var domainEndIdx = url.indexOf('/', domainIdx); 702 if (domainEndIdx === -1) { 703 domainEndIdx = url.length; 704 } 705 return url.substring(0, domainEndIdx); 706 }; 707 var getQuaternionAngle = function getQuaternionAngle(quat) { 708 if (quat.w > 1) { 709 console.warn('getQuaternionAngle: w > 1'); 710 return 0; 711 } 712 var angle = 2 * Math.acos(quat.w); 713 return angle; 714 }; 715 var warnOnce = function () { 716 var observedWarnings = {}; 717 return function (key, message) { 718 if (observedWarnings[key] === undefined) { 719 console.warn('webvr-polyfill: ' + message); 720 observedWarnings[key] = true; 721 } 722 }; 723 }(); 724 var deprecateWarning = function deprecateWarning(deprecated, suggested) { 725 var alternative = suggested ? 'Please use ' + suggested + ' instead.' : ''; 726 warnOnce(deprecated, deprecated + ' has been deprecated. ' + 'This may not work on native WebVR displays. ' + alternative); 727 }; 728 function WGLUPreserveGLState(gl, bindings, callback) { 729 if (!bindings) { 730 callback(gl); 731 return; 732 } 733 var boundValues = []; 734 var activeTexture = null; 735 for (var i = 0; i < bindings.length; ++i) { 736 var binding = bindings[i]; 737 switch (binding) { 738 case gl.TEXTURE_BINDING_2D: 739 case gl.TEXTURE_BINDING_CUBE_MAP: 740 var textureUnit = bindings[++i]; 741 if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) { 742 console.error("TEXTURE_BINDING_2D or TEXTURE_BINDING_CUBE_MAP must be followed by a valid texture unit"); 743 boundValues.push(null, null); 744 break; 745 } 746 if (!activeTexture) { 747 activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); 748 } 749 gl.activeTexture(textureUnit); 750 boundValues.push(gl.getParameter(binding), null); 751 break; 752 case gl.ACTIVE_TEXTURE: 753 activeTexture = gl.getParameter(gl.ACTIVE_TEXTURE); 754 boundValues.push(null); 755 break; 756 default: 757 boundValues.push(gl.getParameter(binding)); 758 break; 759 } 760 } 761 callback(gl); 762 for (var i = 0; i < bindings.length; ++i) { 763 var binding = bindings[i]; 764 var boundValue = boundValues[i]; 765 switch (binding) { 766 case gl.ACTIVE_TEXTURE: 767 break; 768 case gl.ARRAY_BUFFER_BINDING: 769 gl.bindBuffer(gl.ARRAY_BUFFER, boundValue); 770 break; 771 case gl.COLOR_CLEAR_VALUE: 772 gl.clearColor(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); 773 break; 774 case gl.COLOR_WRITEMASK: 775 gl.colorMask(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); 776 break; 777 case gl.CURRENT_PROGRAM: 778 gl.useProgram(boundValue); 779 break; 780 case gl.ELEMENT_ARRAY_BUFFER_BINDING: 781 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, boundValue); 782 break; 783 case gl.FRAMEBUFFER_BINDING: 784 gl.bindFramebuffer(gl.FRAMEBUFFER, boundValue); 785 break; 786 case gl.RENDERBUFFER_BINDING: 787 gl.bindRenderbuffer(gl.RENDERBUFFER, boundValue); 788 break; 789 case gl.TEXTURE_BINDING_2D: 790 var textureUnit = bindings[++i]; 791 if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) 792 break; 793 gl.activeTexture(textureUnit); 794 gl.bindTexture(gl.TEXTURE_2D, boundValue); 795 break; 796 case gl.TEXTURE_BINDING_CUBE_MAP: 797 var textureUnit = bindings[++i]; 798 if (textureUnit < gl.TEXTURE0 || textureUnit > gl.TEXTURE31) 799 break; 800 gl.activeTexture(textureUnit); 801 gl.bindTexture(gl.TEXTURE_CUBE_MAP, boundValue); 802 break; 803 case gl.VIEWPORT: 804 gl.viewport(boundValue[0], boundValue[1], boundValue[2], boundValue[3]); 805 break; 806 case gl.BLEND: 807 case gl.CULL_FACE: 808 case gl.DEPTH_TEST: 809 case gl.SCISSOR_TEST: 810 case gl.STENCIL_TEST: 811 if (boundValue) { 812 gl.enable(binding); 813 } else { 814 gl.disable(binding); 815 } 816 break; 817 default: 818 console.log("No GL restore behavior for 0x" + binding.toString(16)); 819 break; 820 } 821 if (activeTexture) { 822 gl.activeTexture(activeTexture); 823 } 824 } 825 } 826 var glPreserveState = WGLUPreserveGLState; 827 var distortionVS = ['attribute vec2 position;', 'attribute vec3 texCoord;', 'varying vec2 vTexCoord;', 'uniform vec4 viewportOffsetScale[2];', 'void main() {', ' vec4 viewport = viewportOffsetScale[int(texCoord.z)];', ' vTexCoord = (texCoord.xy * viewport.zw) + viewport.xy;', ' gl_Position = vec4( position, 1.0, 1.0 );', '}'].join('\n'); 828 var distortionFS = ['precision mediump float;', 'uniform sampler2D diffuse;', 'varying vec2 vTexCoord;', 'void main() {', ' gl_FragColor = texture2D(diffuse, vTexCoord);', '}'].join('\n'); 829 function CardboardDistorter(gl, cardboardUI, bufferScale, dirtySubmitFrameBindings) { 830 this.gl = gl; 831 this.cardboardUI = cardboardUI; 832 this.bufferScale = bufferScale; 833 this.dirtySubmitFrameBindings = dirtySubmitFrameBindings; 834 this.ctxAttribs = gl.getContextAttributes(); 835 this.meshWidth = 20; 836 this.meshHeight = 20; 837 this.bufferWidth = gl.drawingBufferWidth; 838 this.bufferHeight = gl.drawingBufferHeight; 839 this.realBindFramebuffer = gl.bindFramebuffer; 840 this.realEnable = gl.enable; 841 this.realDisable = gl.disable; 842 this.realColorMask = gl.colorMask; 843 this.realClearColor = gl.clearColor; 844 this.realViewport = gl.viewport; 845 if (!isIOS()) { 846 this.realCanvasWidth = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'width'); 847 this.realCanvasHeight = Object.getOwnPropertyDescriptor(gl.canvas.__proto__, 'height'); 848 } 849 this.isPatched = false; 850 this.lastBoundFramebuffer = null; 851 this.cullFace = false; 852 this.depthTest = false; 853 this.blend = false; 854 this.scissorTest = false; 855 this.stencilTest = false; 856 this.viewport = [0, 0, 0, 0]; 857 this.colorMask = [true, true, true, true]; 858 this.clearColor = [0, 0, 0, 0]; 859 this.attribs = { 860 position: 0, 861 texCoord: 1 862 }; 863 this.program = linkProgram(gl, distortionVS, distortionFS, this.attribs); 864 this.uniforms = getProgramUniforms(gl, this.program); 865 this.viewportOffsetScale = new Float32Array(8); 866 this.setTextureBounds(); 867 this.vertexBuffer = gl.createBuffer(); 868 this.indexBuffer = gl.createBuffer(); 869 this.indexCount = 0; 870 this.renderTarget = gl.createTexture(); 871 this.framebuffer = gl.createFramebuffer(); 872 this.depthStencilBuffer = null; 873 this.depthBuffer = null; 874 this.stencilBuffer = null; 875 if (this.ctxAttribs.depth && this.ctxAttribs.stencil) { 876 this.depthStencilBuffer = gl.createRenderbuffer(); 877 } else if (this.ctxAttribs.depth) { 878 this.depthBuffer = gl.createRenderbuffer(); 879 } else if (this.ctxAttribs.stencil) { 880 this.stencilBuffer = gl.createRenderbuffer(); 881 } 882 this.patch(); 883 this.onResize(); 884 } 885 CardboardDistorter.prototype.destroy = function () { 886 var gl = this.gl; 887 this.unpatch(); 888 gl.deleteProgram(this.program); 889 gl.deleteBuffer(this.vertexBuffer); 890 gl.deleteBuffer(this.indexBuffer); 891 gl.deleteTexture(this.renderTarget); 892 gl.deleteFramebuffer(this.framebuffer); 893 if (this.depthStencilBuffer) { 894 gl.deleteRenderbuffer(this.depthStencilBuffer); 895 } 896 if (this.depthBuffer) { 897 gl.deleteRenderbuffer(this.depthBuffer); 898 } 899 if (this.stencilBuffer) { 900 gl.deleteRenderbuffer(this.stencilBuffer); 901 } 902 if (this.cardboardUI) { 903 this.cardboardUI.destroy(); 904 } 905 }; 906 CardboardDistorter.prototype.onResize = function () { 907 var gl = this.gl; 908 var self = this; 909 var glState = [gl.RENDERBUFFER_BINDING, gl.TEXTURE_BINDING_2D, gl.TEXTURE0]; 910 glPreserveState(gl, glState, function (gl) { 911 self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); 912 if (self.scissorTest) { 913 self.realDisable.call(gl, gl.SCISSOR_TEST); 914 } 915 self.realColorMask.call(gl, true, true, true, true); 916 self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 917 self.realClearColor.call(gl, 0, 0, 0, 1); 918 gl.clear(gl.COLOR_BUFFER_BIT); 919 self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.framebuffer); 920 gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); 921 gl.texImage2D(gl.TEXTURE_2D, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, self.bufferWidth, self.bufferHeight, 0, self.ctxAttribs.alpha ? gl.RGBA : gl.RGB, gl.UNSIGNED_BYTE, null); 922 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 923 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 924 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 925 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 926 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, self.renderTarget, 0); 927 if (self.ctxAttribs.depth && self.ctxAttribs.stencil) { 928 gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthStencilBuffer); 929 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, self.bufferWidth, self.bufferHeight); 930 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, self.depthStencilBuffer); 931 } else if (self.ctxAttribs.depth) { 932 gl.bindRenderbuffer(gl.RENDERBUFFER, self.depthBuffer); 933 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, self.bufferWidth, self.bufferHeight); 934 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, self.depthBuffer); 935 } else if (self.ctxAttribs.stencil) { 936 gl.bindRenderbuffer(gl.RENDERBUFFER, self.stencilBuffer); 937 gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, self.bufferWidth, self.bufferHeight); 938 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, self.stencilBuffer); 939 } 940 if (!gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE) { 941 console.error('Framebuffer incomplete!'); 942 } 943 self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer); 944 if (self.scissorTest) { 945 self.realEnable.call(gl, gl.SCISSOR_TEST); 946 } 947 self.realColorMask.apply(gl, self.colorMask); 948 self.realViewport.apply(gl, self.viewport); 949 self.realClearColor.apply(gl, self.clearColor); 950 }); 951 if (this.cardboardUI) { 952 this.cardboardUI.onResize(); 953 } 954 }; 955 CardboardDistorter.prototype.patch = function () { 956 if (this.isPatched) { 957 return; 958 } 959 var self = this; 960 var canvas = this.gl.canvas; 961 var gl = this.gl; 962 if (!isIOS()) { 963 canvas.width = getScreenWidth() * this.bufferScale; 964 canvas.height = getScreenHeight() * this.bufferScale; 965 Object.defineProperty(canvas, 'width', { 966 configurable: true, 967 enumerable: true, 968 get: function get() { 969 return self.bufferWidth; 970 }, 971 set: function set(value) { 972 self.bufferWidth = value; 973 self.realCanvasWidth.set.call(canvas, value); 974 self.onResize(); 975 } 976 }); 977 Object.defineProperty(canvas, 'height', { 978 configurable: true, 979 enumerable: true, 980 get: function get() { 981 return self.bufferHeight; 982 }, 983 set: function set(value) { 984 self.bufferHeight = value; 985 self.realCanvasHeight.set.call(canvas, value); 986 self.onResize(); 987 } 988 }); 989 } 990 this.lastBoundFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING); 991 if (this.lastBoundFramebuffer == null) { 992 this.lastBoundFramebuffer = this.framebuffer; 993 this.gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer); 994 } 995 this.gl.bindFramebuffer = function (target, framebuffer) { 996 self.lastBoundFramebuffer = framebuffer ? framebuffer : self.framebuffer; 997 self.realBindFramebuffer.call(gl, target, self.lastBoundFramebuffer); 998 }; 999 this.cullFace = gl.getParameter(gl.CULL_FACE); 1000 this.depthTest = gl.getParameter(gl.DEPTH_TEST); 1001 this.blend = gl.getParameter(gl.BLEND); 1002 this.scissorTest = gl.getParameter(gl.SCISSOR_TEST); 1003 this.stencilTest = gl.getParameter(gl.STENCIL_TEST); 1004 gl.enable = function (pname) { 1005 switch (pname) { 1006 case gl.CULL_FACE: 1007 self.cullFace = true;break; 1008 case gl.DEPTH_TEST: 1009 self.depthTest = true;break; 1010 case gl.BLEND: 1011 self.blend = true;break; 1012 case gl.SCISSOR_TEST: 1013 self.scissorTest = true;break; 1014 case gl.STENCIL_TEST: 1015 self.stencilTest = true;break; 1016 } 1017 self.realEnable.call(gl, pname); 1018 }; 1019 gl.disable = function (pname) { 1020 switch (pname) { 1021 case gl.CULL_FACE: 1022 self.cullFace = false;break; 1023 case gl.DEPTH_TEST: 1024 self.depthTest = false;break; 1025 case gl.BLEND: 1026 self.blend = false;break; 1027 case gl.SCISSOR_TEST: 1028 self.scissorTest = false;break; 1029 case gl.STENCIL_TEST: 1030 self.stencilTest = false;break; 1031 } 1032 self.realDisable.call(gl, pname); 1033 };
vendor: 13,898 bytes, lines 1034-1398
1034 this.colorMask = gl.getParameter(gl.COLOR_WRITEMASK); 1035 gl.colorMask = function (r, g, b, a) { 1036 self.colorMask[0] = r; 1037 self.colorMask[1] = g; 1038 self.colorMask[2] = b; 1039 self.colorMask[3] = a; 1040 self.realColorMask.call(gl, r, g, b, a); 1041 }; 1042 this.clearColor = gl.getParameter(gl.COLOR_CLEAR_VALUE); 1043 gl.clearColor = function (r, g, b, a) { 1044 self.clearColor[0] = r; 1045 self.clearColor[1] = g; 1046 self.clearColor[2] = b; 1047 self.clearColor[3] = a; 1048 self.realClearColor.call(gl, r, g, b, a); 1049 }; 1050 this.viewport = gl.getParameter(gl.VIEWPORT); 1051 gl.viewport = function (x, y, w, h) { 1052 self.viewport[0] = x; 1053 self.viewport[1] = y; 1054 self.viewport[2] = w; 1055 self.viewport[3] = h; 1056 self.realViewport.call(gl, x, y, w, h); 1057 }; 1058 this.isPatched = true; 1059 safariCssSizeWorkaround(canvas); 1060 }; 1061 CardboardDistorter.prototype.unpatch = function () { 1062 if (!this.isPatched) { 1063 return; 1064 } 1065 var gl = this.gl; 1066 var canvas = this.gl.canvas; 1067 if (!isIOS()) { 1068 Object.defineProperty(canvas, 'width', this.realCanvasWidth); 1069 Object.defineProperty(canvas, 'height', this.realCanvasHeight); 1070 } 1071 canvas.width = this.bufferWidth; 1072 canvas.height = this.bufferHeight; 1073 gl.bindFramebuffer = this.realBindFramebuffer; 1074 gl.enable = this.realEnable; 1075 gl.disable = this.realDisable; 1076 gl.colorMask = this.realColorMask; 1077 gl.clearColor = this.realClearColor; 1078 gl.viewport = this.realViewport; 1079 if (this.lastBoundFramebuffer == this.framebuffer) { 1080 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 1081 } 1082 this.isPatched = false; 1083 setTimeout(function () { 1084 safariCssSizeWorkaround(canvas); 1085 }, 1); 1086 }; 1087 CardboardDistorter.prototype.setTextureBounds = function (leftBounds, rightBounds) { 1088 if (!leftBounds) { 1089 leftBounds = [0, 0, 0.5, 1]; 1090 } 1091 if (!rightBounds) { 1092 rightBounds = [0.5, 0, 0.5, 1]; 1093 } 1094 this.viewportOffsetScale[0] = leftBounds[0]; 1095 this.viewportOffsetScale[1] = leftBounds[1]; 1096 this.viewportOffsetScale[2] = leftBounds[2]; 1097 this.viewportOffsetScale[3] = leftBounds[3]; 1098 this.viewportOffsetScale[4] = rightBounds[0]; 1099 this.viewportOffsetScale[5] = rightBounds[1]; 1100 this.viewportOffsetScale[6] = rightBounds[2]; 1101 this.viewportOffsetScale[7] = rightBounds[3]; 1102 }; 1103 CardboardDistorter.prototype.submitFrame = function () { 1104 var gl = this.gl; 1105 var self = this; 1106 var glState = []; 1107 if (!this.dirtySubmitFrameBindings) { 1108 glState.push(gl.CURRENT_PROGRAM, gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING, gl.TEXTURE_BINDING_2D, gl.TEXTURE0); 1109 } 1110 glPreserveState(gl, glState, function (gl) { 1111 self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, null); 1112 if (self.cullFace) { 1113 self.realDisable.call(gl, gl.CULL_FACE); 1114 } 1115 if (self.depthTest) { 1116 self.realDisable.call(gl, gl.DEPTH_TEST); 1117 } 1118 if (self.blend) { 1119 self.realDisable.call(gl, gl.BLEND); 1120 } 1121 if (self.scissorTest) { 1122 self.realDisable.call(gl, gl.SCISSOR_TEST); 1123 } 1124 if (self.stencilTest) { 1125 self.realDisable.call(gl, gl.STENCIL_TEST); 1126 } 1127 self.realColorMask.call(gl, true, true, true, true); 1128 self.realViewport.call(gl, 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 1129 if (self.ctxAttribs.alpha || isIOS()) { 1130 self.realClearColor.call(gl, 0, 0, 0, 1); 1131 gl.clear(gl.COLOR_BUFFER_BIT); 1132 } 1133 gl.useProgram(self.program); 1134 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); 1135 gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); 1136 gl.enableVertexAttribArray(self.attribs.position); 1137 gl.enableVertexAttribArray(self.attribs.texCoord); 1138 gl.vertexAttribPointer(self.attribs.position, 2, gl.FLOAT, false, 20, 0); 1139 gl.vertexAttribPointer(self.attribs.texCoord, 3, gl.FLOAT, false, 20, 8); 1140 gl.activeTexture(gl.TEXTURE0); 1141 gl.uniform1i(self.uniforms.diffuse, 0); 1142 gl.bindTexture(gl.TEXTURE_2D, self.renderTarget); 1143 gl.uniform4fv(self.uniforms.viewportOffsetScale, self.viewportOffsetScale); 1144 gl.drawElements(gl.TRIANGLES, self.indexCount, gl.UNSIGNED_SHORT, 0); 1145 if (self.cardboardUI) { 1146 self.cardboardUI.renderNoState(); 1147 } 1148 self.realBindFramebuffer.call(self.gl, gl.FRAMEBUFFER, self.framebuffer); 1149 if (!self.ctxAttribs.preserveDrawingBuffer) { 1150 self.realClearColor.call(gl, 0, 0, 0, 0); 1151 gl.clear(gl.COLOR_BUFFER_BIT); 1152 } 1153 if (!self.dirtySubmitFrameBindings) { 1154 self.realBindFramebuffer.call(gl, gl.FRAMEBUFFER, self.lastBoundFramebuffer); 1155 } 1156 if (self.cullFace) { 1157 self.realEnable.call(gl, gl.CULL_FACE); 1158 } 1159 if (self.depthTest) { 1160 self.realEnable.call(gl, gl.DEPTH_TEST); 1161 } 1162 if (self.blend) { 1163 self.realEnable.call(gl, gl.BLEND); 1164 } 1165 if (self.scissorTest) { 1166 self.realEnable.call(gl, gl.SCISSOR_TEST); 1167 } 1168 if (self.stencilTest) { 1169 self.realEnable.call(gl, gl.STENCIL_TEST); 1170 } 1171 self.realColorMask.apply(gl, self.colorMask); 1172 self.realViewport.apply(gl, self.viewport); 1173 if (self.ctxAttribs.alpha || !self.ctxAttribs.preserveDrawingBuffer) { 1174 self.realClearColor.apply(gl, self.clearColor); 1175 } 1176 }); 1177 if (isIOS()) { 1178 var canvas = gl.canvas; 1179 if (canvas.width != self.bufferWidth || canvas.height != self.bufferHeight) { 1180 self.bufferWidth = canvas.width; 1181 self.bufferHeight = canvas.height; 1182 self.onResize(); 1183 } 1184 } 1185 }; 1186 CardboardDistorter.prototype.updateDeviceInfo = function (deviceInfo) { 1187 var gl = this.gl; 1188 var self = this; 1189 var glState = [gl.ARRAY_BUFFER_BINDING, gl.ELEMENT_ARRAY_BUFFER_BINDING]; 1190 glPreserveState(gl, glState, function (gl) { 1191 var vertices = self.computeMeshVertices_(self.meshWidth, self.meshHeight, deviceInfo); 1192 gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); 1193 gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); 1194 if (!self.indexCount) { 1195 var indices = self.computeMeshIndices_(self.meshWidth, self.meshHeight); 1196 gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, self.indexBuffer); 1197 gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); 1198 self.indexCount = indices.length; 1199 } 1200 }); 1201 }; 1202 CardboardDistorter.prototype.computeMeshVertices_ = function (width, height, deviceInfo) { 1203 var vertices = new Float32Array(2 * width * height * 5); 1204 var lensFrustum = deviceInfo.getLeftEyeVisibleTanAngles(); 1205 var noLensFrustum = deviceInfo.getLeftEyeNoLensTanAngles(); 1206 var viewport = deviceInfo.getLeftEyeVisibleScreenRect(noLensFrustum); 1207 var vidx = 0; 1208 for (var e = 0; e < 2; e++) { 1209 for (var j = 0; j < height; j++) { 1210 for (var i = 0; i < width; i++, vidx++) { 1211 var u = i / (width - 1); 1212 var v = j / (height - 1); 1213 var s = u; 1214 var t = v; 1215 var x = lerp(lensFrustum[0], lensFrustum[2], u); 1216 var y = lerp(lensFrustum[3], lensFrustum[1], v); 1217 var d = Math.sqrt(x * x + y * y); 1218 var r = deviceInfo.distortion.distortInverse(d); 1219 var p = x * r / d; 1220 var q = y * r / d; 1221 u = (p - noLensFrustum[0]) / (noLensFrustum[2] - noLensFrustum[0]); 1222 v = (q - noLensFrustum[3]) / (noLensFrustum[1] - noLensFrustum[3]); 1223 u = (viewport.x + u * viewport.width - 0.5) * 2.0; 1224 v = (viewport.y + v * viewport.height - 0.5) * 2.0; 1225 vertices[vidx * 5 + 0] = u; 1226 vertices[vidx * 5 + 1] = v; 1227 vertices[vidx * 5 + 2] = s; 1228 vertices[vidx * 5 + 3] = t; 1229 vertices[vidx * 5 + 4] = e; 1230 } 1231 } 1232 var w = lensFrustum[2] - lensFrustum[0]; 1233 lensFrustum[0] = -(w + lensFrustum[0]); 1234 lensFrustum[2] = w - lensFrustum[2]; 1235 w = noLensFrustum[2] - noLensFrustum[0]; 1236 noLensFrustum[0] = -(w + noLensFrustum[0]); 1237 noLensFrustum[2] = w - noLensFrustum[2]; 1238 viewport.x = 1 - (viewport.x + viewport.width); 1239 } 1240 return vertices; 1241 }; 1242 CardboardDistorter.prototype.computeMeshIndices_ = function (width, height) { 1243 var indices = new Uint16Array(2 * (width - 1) * (height - 1) * 6); 1244 var halfwidth = width / 2; 1245 var halfheight = height / 2; 1246 var vidx = 0; 1247 var iidx = 0; 1248 for (var e = 0; e < 2; e++) { 1249 for (var j = 0; j < height; j++) { 1250 for (var i = 0; i < width; i++, vidx++) { 1251 if (i == 0 || j == 0) continue; 1252 if (i <= halfwidth == j <= halfheight) { 1253 indices[iidx++] = vidx; 1254 indices[iidx++] = vidx - width - 1; 1255 indices[iidx++] = vidx - width; 1256 indices[iidx++] = vidx - width - 1; 1257 indices[iidx++] = vidx; 1258 indices[iidx++] = vidx - 1; 1259 } else { 1260 indices[iidx++] = vidx - 1; 1261 indices[iidx++] = vidx - width; 1262 indices[iidx++] = vidx; 1263 indices[iidx++] = vidx - width; 1264 indices[iidx++] = vidx - 1; 1265 indices[iidx++] = vidx - width - 1; 1266 } 1267 } 1268 } 1269 } 1270 return indices; 1271 }; 1272 CardboardDistorter.prototype.getOwnPropertyDescriptor_ = function (proto, attrName) { 1273 var descriptor = Object.getOwnPropertyDescriptor(proto, attrName); 1274 if (descriptor.get === undefined || descriptor.set === undefined) { 1275 descriptor.configurable = true; 1276 descriptor.enumerable = true; 1277 descriptor.get = function () { 1278 return this.getAttribute(attrName); 1279 }; 1280 descriptor.set = function (val) { 1281 this.setAttribute(attrName, val); 1282 }; 1283 } 1284 return descriptor; 1285 }; 1286 var uiVS = ['attribute vec2 position;', 'uniform mat4 projectionMat;', 'void main() {', ' gl_Position = projectionMat * vec4( position, -1.0, 1.0 );', '}'].join('\n'); 1287 var uiFS = ['precision mediump float;', 'uniform vec4 color;', 'void main() {', ' gl_FragColor = color;', '}'].join('\n'); 1288 var DEG2RAD = Math.PI / 180.0; 1289 var kAnglePerGearSection = 60; 1290 var kOuterRimEndAngle = 12; 1291 var kInnerRimBeginAngle = 20; 1292 var kOuterRadius = 1; 1293 var kMiddleRadius = 0.75; 1294 var kInnerRadius = 0.3125; 1295 var kCenterLineThicknessDp = 4; 1296 var kButtonWidthDp = 28; 1297 var kTouchSlopFactor = 1.5; 1298 function CardboardUI(gl) { 1299 this.gl = gl; 1300 this.attribs = { 1301 position: 0 1302 }; 1303 this.program = linkProgram(gl, uiVS, uiFS, this.attribs); 1304 this.uniforms = getProgramUniforms(gl, this.program); 1305 this.vertexBuffer = gl.createBuffer(); 1306 this.gearOffset = 0; 1307 this.gearVertexCount = 0; 1308 this.arrowOffset = 0; 1309 this.arrowVertexCount = 0; 1310 this.projMat = new Float32Array(16); 1311 this.listener = null; 1312 this.onResize(); 1313 } 1314 CardboardUI.prototype.destroy = function () { 1315 var gl = this.gl; 1316 if (this.listener) { 1317 gl.canvas.removeEventListener('click', this.listener, false); 1318 } 1319 gl.deleteProgram(this.program); 1320 gl.deleteBuffer(this.vertexBuffer); 1321 }; 1322 CardboardUI.prototype.listen = function (optionsCallback, backCallback) { 1323 var canvas = this.gl.canvas; 1324 this.listener = function (event) { 1325 var midline = canvas.clientWidth / 2; 1326 var buttonSize = kButtonWidthDp * kTouchSlopFactor; 1327 if (event.clientX > midline - buttonSize && event.clientX < midline + buttonSize && event.clientY > canvas.clientHeight - buttonSize) { 1328 optionsCallback(event); 1329 } 1330 else if (event.clientX < buttonSize && event.clientY < buttonSize) { 1331 backCallback(event); 1332 } 1333 }; 1334 canvas.addEventListener('click', this.listener, false); 1335 }; 1336 CardboardUI.prototype.onResize = function () { 1337 var gl = this.gl; 1338 var self = this; 1339 var glState = [gl.ARRAY_BUFFER_BINDING]; 1340 glPreserveState(gl, glState, function (gl) { 1341 var vertices = []; 1342 var midline = gl.drawingBufferWidth / 2; 1343 var physicalPixels = Math.max(screen.width, screen.height) * window.devicePixelRatio; 1344 var scalingRatio = gl.drawingBufferWidth / physicalPixels; 1345 var dps = scalingRatio * window.devicePixelRatio; 1346 var lineWidth = kCenterLineThicknessDp * dps / 2; 1347 var buttonSize = kButtonWidthDp * kTouchSlopFactor * dps; 1348 var buttonScale = kButtonWidthDp * dps / 2; 1349 var buttonBorder = (kButtonWidthDp * kTouchSlopFactor - kButtonWidthDp) * dps; 1350 vertices.push(midline - lineWidth, buttonSize); 1351 vertices.push(midline - lineWidth, gl.drawingBufferHeight); 1352 vertices.push(midline + lineWidth, buttonSize); 1353 vertices.push(midline + lineWidth, gl.drawingBufferHeight); 1354 self.gearOffset = vertices.length / 2; 1355 function addGearSegment(theta, r) { 1356 var angle = (90 - theta) * DEG2RAD; 1357 var x = Math.cos(angle); 1358 var y = Math.sin(angle); 1359 vertices.push(kInnerRadius * x * buttonScale + midline, kInnerRadius * y * buttonScale + buttonScale); 1360 vertices.push(r * x * buttonScale + midline, r * y * buttonScale + buttonScale); 1361 } 1362 for (var i = 0; i <= 6; i++) { 1363 var segmentTheta = i * kAnglePerGearSection; 1364 addGearSegment(segmentTheta, kOuterRadius); 1365 addGearSegment(segmentTheta + kOuterRimEndAngle, kOuterRadius); 1366 addGearSegment(segmentTheta + kInnerRimBeginAngle, kMiddleRadius); 1367 addGearSegment(segmentTheta + (kAnglePerGearSection - kInnerRimBeginAngle), kMiddleRadius); 1368 addGearSegment(segmentTheta + (kAnglePerGearSection - kOuterRimEndAngle), kOuterRadius); 1369 } 1370 self.gearVertexCount = vertices.length / 2 - self.gearOffset; 1371 self.arrowOffset = vertices.length / 2; 1372 function addArrowVertex(x, y) { 1373 vertices.push(buttonBorder + x, gl.drawingBufferHeight - buttonBorder - y); 1374 } 1375 var angledLineWidth = lineWidth / Math.sin(45 * DEG2RAD); 1376 addArrowVertex(0, buttonScale); 1377 addArrowVertex(buttonScale, 0); 1378 addArrowVertex(buttonScale + angledLineWidth, angledLineWidth); 1379 addArrowVertex(angledLineWidth, buttonScale + angledLineWidth); 1380 addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); 1381 addArrowVertex(0, buttonScale); 1382 addArrowVertex(buttonScale, buttonScale * 2); 1383 addArrowVertex(buttonScale + angledLineWidth, buttonScale * 2 - angledLineWidth); 1384 addArrowVertex(angledLineWidth, buttonScale - angledLineWidth); 1385 addArrowVertex(0, buttonScale); 1386 addArrowVertex(angledLineWidth, buttonScale - lineWidth); 1387 addArrowVertex(kButtonWidthDp * dps, buttonScale - lineWidth); 1388 addArrowVertex(angledLineWidth, buttonScale + lineWidth); 1389 addArrowVertex(kButtonWidthDp * dps, buttonScale + lineWidth); 1390 self.arrowVertexCount = vertices.length / 2 - self.arrowOffset; 1391 gl.bindBuffer(gl.ARRAY_BUFFER, self.vertexBuffer); 1392 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); 1393 }); 1394 }; 1395 CardboardUI.prototype.render = function () { 1396 var gl = this.gl; 1397 var self = this; 1398 var glState = [gl.CULL_FACE, gl.DEPTH_TEST, gl.BLEND, gl.SCISSOR_TEST, gl.STENCIL_TEST, gl.COLOR_WRITEMA
vendor: 18,151 bytes, lines 1398-1928
1398SK, gl.VIEWPORT, gl.CURRENT_PROGRAM, gl.ARRAY_BUFFER_BINDING]; 1399 glPreserveState(gl, glState, function (gl) { 1400 gl.disable(gl.CULL_FACE); 1401 gl.disable(gl.DEPTH_TEST); 1402 gl.disable(gl.BLEND); 1403 gl.disable(gl.SCISSOR_TEST); 1404 gl.disable(gl.STENCIL_TEST); 1405 gl.colorMask(true, true, true, true); 1406 gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight); 1407 self.renderNoState(); 1408 }); 1409 }; 1410 CardboardUI.prototype.renderNoState = function () { 1411 var gl = this.gl; 1412 gl.useProgram(this.program); 1413 gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffer); 1414 gl.enableVertexAttribArray(this.attribs.position); 1415 gl.vertexAttribPointer(this.attribs.position, 2, gl.FLOAT, false, 8, 0); 1416 gl.uniform4f(this.uniforms.color, 1.0, 1.0, 1.0, 1.0); 1417 orthoMatrix(this.projMat, 0, gl.drawingBufferWidth, 0, gl.drawingBufferHeight, 0.1, 1024.0); 1418 gl.uniformMatrix4fv(this.uniforms.projectionMat, false, this.projMat); 1419 gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 1420 gl.drawArrays(gl.TRIANGLE_STRIP, this.gearOffset, this.gearVertexCount); 1421 gl.drawArrays(gl.TRIANGLE_STRIP, this.arrowOffset, this.arrowVertexCount); 1422 }; 1423 function Distortion(coefficients) { 1424 this.coefficients = coefficients; 1425 } 1426 Distortion.prototype.distortInverse = function (radius) { 1427 var r0 = 0; 1428 var r1 = 1; 1429 var dr0 = radius - this.distort(r0); 1430 while (Math.abs(r1 - r0) > 0.0001 ) { 1431 var dr1 = radius - this.distort(r1); 1432 var r2 = r1 - dr1 * ((r1 - r0) / (dr1 - dr0)); 1433 r0 = r1; 1434 r1 = r2; 1435 dr0 = dr1; 1436 } 1437 return r1; 1438 }; 1439 Distortion.prototype.distort = function (radius) { 1440 var r2 = radius * radius; 1441 var ret = 0; 1442 for (var i = 0; i < this.coefficients.length; i++) { 1443 ret = r2 * (ret + this.coefficients[i]); 1444 } 1445 return (ret + 1) * radius; 1446 }; 1447 var degToRad = Math.PI / 180; 1448 var radToDeg = 180 / Math.PI; 1449 var Vector3 = function Vector3(x, y, z) { 1450 this.x = x || 0; 1451 this.y = y || 0; 1452 this.z = z || 0; 1453 }; 1454 Vector3.prototype = { 1455 constructor: Vector3, 1456 set: function set(x, y, z) { 1457 this.x = x; 1458 this.y = y; 1459 this.z = z; 1460 return this; 1461 }, 1462 copy: function copy(v) { 1463 this.x = v.x; 1464 this.y = v.y; 1465 this.z = v.z; 1466 return this; 1467 }, 1468 length: function length() { 1469 return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); 1470 }, 1471 normalize: function normalize() { 1472 var scalar = this.length(); 1473 if (scalar !== 0) { 1474 var invScalar = 1 / scalar; 1475 this.multiplyScalar(invScalar); 1476 } else { 1477 this.x = 0; 1478 this.y = 0; 1479 this.z = 0; 1480 } 1481 return this; 1482 }, 1483 multiplyScalar: function multiplyScalar(scalar) { 1484 this.x *= scalar; 1485 this.y *= scalar; 1486 this.z *= scalar; 1487 }, 1488 applyQuaternion: function applyQuaternion(q) { 1489 var x = this.x; 1490 var y = this.y; 1491 var z = this.z; 1492 var qx = q.x; 1493 var qy = q.y; 1494 var qz = q.z; 1495 var qw = q.w; 1496 var ix = qw * x + qy * z - qz * y; 1497 var iy = qw * y + qz * x - qx * z; 1498 var iz = qw * z + qx * y - qy * x; 1499 var iw = -qx * x - qy * y - qz * z; 1500 this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy; 1501 this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz; 1502 this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx; 1503 return this; 1504 }, 1505 dot: function dot(v) { 1506 return this.x * v.x + this.y * v.y + this.z * v.z; 1507 }, 1508 crossVectors: function crossVectors(a, b) { 1509 var ax = a.x, 1510 ay = a.y, 1511 az = a.z; 1512 var bx = b.x, 1513 by = b.y, 1514 bz = b.z; 1515 this.x = ay * bz - az * by; 1516 this.y = az * bx - ax * bz; 1517 this.z = ax * by - ay * bx; 1518 return this; 1519 } 1520 }; 1521 var Quaternion = function Quaternion(x, y, z, w) { 1522 this.x = x || 0; 1523 this.y = y || 0; 1524 this.z = z || 0; 1525 this.w = w !== undefined ? w : 1; 1526 }; 1527 Quaternion.prototype = { 1528 constructor: Quaternion, 1529 set: function set(x, y, z, w) { 1530 this.x = x; 1531 this.y = y; 1532 this.z = z; 1533 this.w = w; 1534 return this; 1535 }, 1536 copy: function copy(quaternion) { 1537 this.x = quaternion.x; 1538 this.y = quaternion.y; 1539 this.z = quaternion.z; 1540 this.w = quaternion.w; 1541 return this; 1542 }, 1543 setFromEulerXYZ: function setFromEulerXYZ(x, y, z) { 1544 var c1 = Math.cos(x / 2); 1545 var c2 = Math.cos(y / 2); 1546 var c3 = Math.cos(z / 2); 1547 var s1 = Math.sin(x / 2); 1548 var s2 = Math.sin(y / 2); 1549 var s3 = Math.sin(z / 2); 1550 this.x = s1 * c2 * c3 + c1 * s2 * s3; 1551 this.y = c1 * s2 * c3 - s1 * c2 * s3; 1552 this.z = c1 * c2 * s3 + s1 * s2 * c3; 1553 this.w = c1 * c2 * c3 - s1 * s2 * s3; 1554 return this; 1555 }, 1556 setFromEulerYXZ: function setFromEulerYXZ(x, y, z) { 1557 var c1 = Math.cos(x / 2); 1558 var c2 = Math.cos(y / 2); 1559 var c3 = Math.cos(z / 2); 1560 var s1 = Math.sin(x / 2); 1561 var s2 = Math.sin(y / 2); 1562 var s3 = Math.sin(z / 2); 1563 this.x = s1 * c2 * c3 + c1 * s2 * s3; 1564 this.y = c1 * s2 * c3 - s1 * c2 * s3; 1565 this.z = c1 * c2 * s3 - s1 * s2 * c3; 1566 this.w = c1 * c2 * c3 + s1 * s2 * s3; 1567 return this; 1568 }, 1569 setFromAxisAngle: function setFromAxisAngle(axis, angle) { 1570 var halfAngle = angle / 2, 1571 s = Math.sin(halfAngle); 1572 this.x = axis.x * s; 1573 this.y = axis.y * s; 1574 this.z = axis.z * s; 1575 this.w = Math.cos(halfAngle); 1576 return this; 1577 }, 1578 multiply: function multiply(q) { 1579 return this.multiplyQuaternions(this, q); 1580 }, 1581 multiplyQuaternions: function multiplyQuaternions(a, b) { 1582 var qax = a.x, 1583 qay = a.y, 1584 qaz = a.z, 1585 qaw = a.w; 1586 var qbx = b.x, 1587 qby = b.y, 1588 qbz = b.z, 1589 qbw = b.w; 1590 this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; 1591 this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; 1592 this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; 1593 this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; 1594 return this; 1595 }, 1596 inverse: function inverse() { 1597 this.x *= -1; 1598 this.y *= -1; 1599 this.z *= -1; 1600 this.normalize(); 1601 return this; 1602 }, 1603 normalize: function normalize() { 1604 var l = Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w); 1605 if (l === 0) { 1606 this.x = 0; 1607 this.y = 0; 1608 this.z = 0; 1609 this.w = 1; 1610 } else { 1611 l = 1 / l; 1612 this.x = this.x * l; 1613 this.y = this.y * l; 1614 this.z = this.z * l; 1615 this.w = this.w * l; 1616 } 1617 return this; 1618 }, 1619 slerp: function slerp(qb, t) { 1620 if (t === 0) return this; 1621 if (t === 1) return this.copy(qb); 1622 var x = this.x, 1623 y = this.y, 1624 z = this.z, 1625 w = this.w; 1626 var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z; 1627 if (cosHalfTheta < 0) { 1628 this.w = -qb.w; 1629 this.x = -qb.x; 1630 this.y = -qb.y; 1631 this.z = -qb.z; 1632 cosHalfTheta = -cosHalfTheta; 1633 } else { 1634 this.copy(qb); 1635 } 1636 if (cosHalfTheta >= 1.0) { 1637 this.w = w; 1638 this.x = x; 1639 this.y = y; 1640 this.z = z; 1641 return this; 1642 } 1643 var halfTheta = Math.acos(cosHalfTheta); 1644 var sinHalfTheta = Math.sqrt(1.0 - cosHalfTheta * cosHalfTheta); 1645 if (Math.abs(sinHalfTheta) < 0.001) { 1646 this.w = 0.5 * (w + this.w); 1647 this.x = 0.5 * (x + this.x); 1648 this.y = 0.5 * (y + this.y); 1649 this.z = 0.5 * (z + this.z); 1650 return this; 1651 } 1652 var ratioA = Math.sin((1 - t) * halfTheta) / sinHalfTheta, 1653 ratioB = Math.sin(t * halfTheta) / sinHalfTheta; 1654 this.w = w * ratioA + this.w * ratioB; 1655 this.x = x * ratioA + this.x * ratioB; 1656 this.y = y * ratioA + this.y * ratioB; 1657 this.z = z * ratioA + this.z * ratioB; 1658 return this; 1659 }, 1660 setFromUnitVectors: function () { 1661 var v1, r; 1662 var EPS = 0.000001; 1663 return function (vFrom, vTo) { 1664 if (v1 === undefined) v1 = new Vector3(); 1665 r = vFrom.dot(vTo) + 1; 1666 if (r < EPS) { 1667 r = 0; 1668 if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) { 1669 v1.set(-vFrom.y, vFrom.x, 0); 1670 } else { 1671 v1.set(0, -vFrom.z, vFrom.y); 1672 } 1673 } else { 1674 v1.crossVectors(vFrom, vTo); 1675 } 1676 this.x = v1.x; 1677 this.y = v1.y; 1678 this.z = v1.z; 1679 this.w = r; 1680 this.normalize(); 1681 return this; 1682 }; 1683 }() 1684 }; 1685 function Device(params) { 1686 this.width = params.width || getScreenWidth(); 1687 this.height = params.height || getScreenHeight(); 1688 this.widthMeters = params.widthMeters; 1689 this.heightMeters = params.heightMeters; 1690 this.bevelMeters = params.bevelMeters; 1691 } 1692 var DEFAULT_ANDROID = new Device({ 1693 widthMeters: 0.110, 1694 heightMeters: 0.062, 1695 bevelMeters: 0.004 1696 }); 1697 var DEFAULT_IOS = new Device({ 1698 widthMeters: 0.1038, 1699 heightMeters: 0.0584, 1700 bevelMeters: 0.004 1701 }); 1702 var Viewers = { 1703 CardboardV1: new CardboardViewer({ 1704 id: 'CardboardV1', 1705 label: 'Cardboard I/O 2014', 1706 fov: 40, 1707 interLensDistance: 0.060, 1708 baselineLensDistance: 0.035, 1709 screenLensDistance: 0.042, 1710 distortionCoefficients: [0.441, 0.156], 1711 inverseCoefficients: [-0.4410035, 0.42756155, -0.4804439, 0.5460139, -0.58821183, 0.5733938, -0.48303202, 0.33299083, -0.17573841, 0.0651772, -0.01488963, 0.001559834] 1712 }), 1713 CardboardV2: new CardboardViewer({ 1714 id: 'CardboardV2', 1715 label: 'Cardboard I/O 2015', 1716 fov: 60, 1717 interLensDistance: 0.064, 1718 baselineLensDistance: 0.035, 1719 screenLensDistance: 0.039, 1720 distortionCoefficients: [0.34, 0.55], 1721 inverseCoefficients: [-0.33836704, -0.18162185, 0.862655, -1.2462051, 1.0560602, -0.58208317, 0.21609078, -0.05444823, 0.009177956, -9.904169E-4, 6.183535E-5, -1.6981803E-6] 1722 }) 1723 }; 1724 function DeviceInfo(deviceParams, additionalViewers) { 1725 this.viewer = Viewers.CardboardV2; 1726 this.updateDeviceParams(deviceParams); 1727 this.distortion = new Distortion(this.viewer.distortionCoefficients); 1728 for (var i = 0; i < additionalViewers.length; i++) { 1729 var viewer = additionalViewers[i]; 1730 Viewers[viewer.id] = new CardboardViewer(viewer); 1731 } 1732 } 1733 DeviceInfo.prototype.updateDeviceParams = function (deviceParams) { 1734 this.device = this.determineDevice_(deviceParams) || this.device; 1735 }; 1736 DeviceInfo.prototype.getDevice = function () { 1737 return this.device; 1738 }; 1739 DeviceInfo.prototype.setViewer = function (viewer) { 1740 this.viewer = viewer; 1741 this.distortion = new Distortion(this.viewer.distortionCoefficients); 1742 }; 1743 DeviceInfo.prototype.determineDevice_ = function (deviceParams) { 1744 if (!deviceParams) { 1745 if (isIOS()) { 1746 console.warn('Using fallback iOS device measurements.'); 1747 return DEFAULT_IOS; 1748 } else { 1749 console.warn('Using fallback Android device measurements.'); 1750 return DEFAULT_ANDROID; 1751 } 1752 } 1753 var METERS_PER_INCH = 0.0254; 1754 var metersPerPixelX = METERS_PER_INCH / deviceParams.xdpi; 1755 var metersPerPixelY = METERS_PER_INCH / deviceParams.ydpi; 1756 var width = getScreenWidth(); 1757 var height = getScreenHeight(); 1758 return new Device({ 1759 widthMeters: metersPerPixelX * width, 1760 heightMeters: metersPerPixelY * height, 1761 bevelMeters: deviceParams.bevelMm * 0.001 1762 }); 1763 }; 1764 DeviceInfo.prototype.getDistortedFieldOfViewLeftEye = function () { 1765 var viewer = this.viewer; 1766 var device = this.device; 1767 var distortion = this.distortion; 1768 var eyeToScreenDistance = viewer.screenLensDistance; 1769 var outerDist = (device.widthMeters - viewer.interLensDistance) / 2; 1770 var innerDist = viewer.interLensDistance / 2; 1771 var bottomDist = viewer.baselineLensDistance - device.bevelMeters; 1772 var topDist = device.heightMeters - bottomDist; 1773 var outerAngle = radToDeg * Math.atan(distortion.distort(outerDist / eyeToScreenDistance)); 1774 var innerAngle = radToDeg * Math.atan(distortion.distort(innerDist / eyeToScreenDistance)); 1775 var bottomAngle = radToDeg * Math.atan(distortion.distort(bottomDist / eyeToScreenDistance)); 1776 var topAngle = radToDeg * Math.atan(distortion.distort(topDist / eyeToScreenDistance)); 1777 return { 1778 leftDegrees: Math.min(outerAngle, viewer.fov), 1779 rightDegrees: Math.min(innerAngle, viewer.fov), 1780 downDegrees: Math.min(bottomAngle, viewer.fov), 1781 upDegrees: Math.min(topAngle, viewer.fov) 1782 }; 1783 }; 1784 DeviceInfo.prototype.getLeftEyeVisibleTanAngles = function () { 1785 var viewer = this.viewer; 1786 var device = this.device; 1787 var distortion = this.distortion; 1788 var fovLeft = Math.tan(-degToRad * viewer.fov); 1789 var fovTop = Math.tan(degToRad * viewer.fov); 1790 var fovRight = Math.tan(degToRad * viewer.fov); 1791 var fovBottom = Math.tan(-degToRad * viewer.fov); 1792 var halfWidth = device.widthMeters / 4; 1793 var halfHeight = device.heightMeters / 2; 1794 var verticalLensOffset = viewer.baselineLensDistance - device.bevelMeters - halfHeight; 1795 var centerX = viewer.interLensDistance / 2 - halfWidth; 1796 var centerY = -verticalLensOffset; 1797 var centerZ = viewer.screenLensDistance; 1798 var screenLeft = distortion.distort((centerX - halfWidth) / centerZ); 1799 var screenTop = distortion.distort((centerY + halfHeight) / centerZ); 1800 var screenRight = distortion.distort((centerX + halfWidth) / centerZ); 1801 var screenBottom = distortion.distort((centerY - halfHeight) / centerZ); 1802 var result = new Float32Array(4); 1803 result[0] = Math.max(fovLeft, screenLeft); 1804 result[1] = Math.min(fovTop, screenTop); 1805 result[2] = Math.min(fovRight, screenRight); 1806 result[3] = Math.max(fovBottom, screenBottom); 1807 return result; 1808 }; 1809 DeviceInfo.prototype.getLeftEyeNoLensTanAngles = function () { 1810 var viewer = this.viewer; 1811 var device = this.device; 1812 var distortion = this.distortion; 1813 var result = new Float32Array(4); 1814 var fovLeft = distortion.distortInverse(Math.tan(-degToRad * viewer.fov)); 1815 var fovTop = distortion.distortInverse(Math.tan(degToRad * viewer.fov)); 1816 var fovRight = distortion.distortInverse(Math.tan(degToRad * viewer.fov)); 1817 var fovBottom = distortion.distortInverse(Math.tan(-degToRad * viewer.fov)); 1818 var halfWidth = device.widthMeters / 4; 1819 var halfHeight = device.heightMeters / 2; 1820 var verticalLensOffset = viewer.baselineLensDistance - device.bevelMeters - halfHeight; 1821 var centerX = viewer.interLensDistance / 2 - halfWidth; 1822 var centerY = -verticalLensOffset; 1823 var centerZ = viewer.screenLensDistance; 1824 var screenLeft = (centerX - halfWidth) / centerZ; 1825 var screenTop = (centerY + halfHeight) / centerZ; 1826 var screenRight = (centerX + halfWidth) / centerZ; 1827 var screenBottom = (centerY - halfHeight) / centerZ; 1828 result[0] = Math.max(fovLeft, screenLeft); 1829 result[1] = Math.min(fovTop, screenTop); 1830 result[2] = Math.min(fovRight, screenRight); 1831 result[3] = Math.max(fovBottom, screenBottom); 1832 return result; 1833 }; 1834 DeviceInfo.prototype.getLeftEyeVisibleScreenRect = function (undistortedFrustum) { 1835 var viewer = this.viewer; 1836 var device = this.device; 1837 var dist = viewer.screenLensDistance; 1838 var eyeX = (device.widthMeters - viewer.interLensDistance) / 2; 1839 var eyeY = viewer.baselineLensDistance - device.bevelMeters; 1840 var left = (undistortedFrustum[0] * dist + eyeX) / device.widthMeters; 1841 var top = (undistortedFrustum[1] * dist + eyeY) / device.heightMeters; 1842 var right = (undistortedFrustum[2] * dist + eyeX) / device.widthMeters; 1843 var bottom = (undistortedFrustum[3] * dist + eyeY) / device.heightMeters; 1844 return { 1845 x: left, 1846 y: bottom, 1847 width: right - left, 1848 height: top - bottom 1849 }; 1850 }; 1851 DeviceInfo.prototype.getFieldOfViewLeftEye = function (opt_isUndistorted) { 1852 return opt_isUndistorted ? this.getUndistortedFieldOfViewLeftEye() : this.getDistortedFieldOfViewLeftEye(); 1853 }; 1854 DeviceInfo.prototype.getFieldOfViewRightEye = function (opt_isUndistorted) { 1855 var fov = this.getFieldOfViewLeftEye(opt_isUndistorted); 1856 return { 1857 leftDegrees: fov.rightDegrees, 1858 rightDegrees: fov.leftDegrees, 1859 upDegrees: fov.upDegrees, 1860 downDegrees: fov.downDegrees 1861 }; 1862 }; 1863 DeviceInfo.prototype.getUndistortedFieldOfViewLeftEye = function () { 1864 var p = this.getUndistortedParams_(); 1865 return { 1866 leftDegrees: radToDeg * Math.atan(p.outerDist), 1867 rightDegrees: radToDeg * Math.atan(p.innerDist), 1868 downDegrees: radToDeg * Math.atan(p.bottomDist), 1869 upDegrees: radToDeg * Math.atan(p.topDist) 1870 }; 1871 }; 1872 DeviceInfo.prototype.getUndistortedViewportLeftEye = function () { 1873 var p = this.getUndistortedParams_(); 1874 var viewer = this.viewer; 1875 var device = this.device; 1876 var eyeToScreenDistance = viewer.screenLensDistance; 1877 var screenWidth = device.widthMeters / eyeToScreenDistance; 1878 var screenHeight = device.heightMeters / eyeToScreenDistance; 1879 var xPxPerTanAngle = device.width / screenWidth; 1880 var yPxPerTanAngle = device.height / screenHeight; 1881 var x = Math.round((p.eyePosX - p.outerDist) * xPxPerTanAngle); 1882 var y = Math.round((p.eyePosY - p.bottomDist) * yPxPerTanAngle); 1883 return { 1884 x: x, 1885 y: y, 1886 width: Math.round((p.eyePosX + p.innerDist) * xPxPerTanAngle) - x, 1887 height: Math.round((p.eyePosY + p.topDist) * yPxPerTanAngle) - y 1888 }; 1889 }; 1890 DeviceInfo.prototype.getUndistortedParams_ = function () { 1891 var viewer = this.viewer; 1892 var device = this.device; 1893 var distortion = this.distortion; 1894 var eyeToScreenDistance = viewer.screenLensDistance; 1895 var halfLensDistance = viewer.interLensDistance / 2 / eyeToScreenDistance; 1896 var screenWidth = device.widthMeters / eyeToScreenDistance; 1897 var screenHeight = device.heightMeters / eyeToScreenDistance; 1898 var eyePosX = screenWidth / 2 - halfLensDistance; 1899 var eyePosY = (viewer.baselineLensDistance - device.bevelMeters) / eyeToScreenDistance; 1900 var maxFov = viewer.fov; 1901 var viewerMax = distortion.distortInverse(Math.tan(degToRad * maxFov)); 1902 var outerDist = Math.min(eyePosX, viewerMax); 1903 var innerDist = Math.min(halfLensDistance, viewerMax); 1904 var bottomDist = Math.min(eyePosY, viewerMax); 1905 var topDist = Math.min(screenHeight - eyePosY, viewerMax); 1906 return { 1907 outerDist: outerDist, 1908 innerDist: innerDist, 1909 topDist: topDist, 1910 bottomDist: bottomDist, 1911 eyePosX: eyePosX, 1912 eyePosY: eyePosY 1913 }; 1914 }; 1915 function CardboardViewer(params) { 1916 this.id = params.id; 1917 this.label = params.label; 1918 this.fov = params.fov; 1919 this.interLensDistance = params.interLensDistance; 1920 this.baselineLensDistance = params.baselineLensDistance; 1921 this.screenLensDistance = params.screenLensDistance; 1922 this.distortionCoefficients = params.distortionCoefficients; 1923 this.inverseCoefficients = params.inverseCoefficients; 1924 } 1925 DeviceInfo.Viewers = Viewers; 1926 var format = 1; 1927 var last_updated = "2018-02-20T22:55:10Z"; 1928 var devices = [{"type":"android","rules":[{"mdmh":"asus/*/Nexus 7/*"},{"ua":"Nexus 7"}],"dpi":[320.8,323],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"asus/*/ASUS_Z00AD/*"},{"ua":"ASUS_Z00AD"}],"dpi":[403,404.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel XL/*"},{"ua":"Pixel XL"}],"dpi":[537.9,533],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Google/*/Pixel/*"},{"ua":"Pixel"}
1928],"dpi":[432.6,436.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC6435LVW/*"},{"ua":"HTC6435LVW"}],"dpi":[449.7,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One XL/*"},{"ua":"HTC One XL"}],"dpi":[315.3,314.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"htc/*/Nexus 9/*"},{"ua":"Nexus 9"}],"dpi":289,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One M9/*"},{"ua":"HTC One M9"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One_M8/*"},{"ua":"HTC One_M8"}],"dpi":[449.7,447.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"HTC/*/HTC One/*"},{"ua":"HTC One"}],"dpi":472.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Huawei/*/Nexus 6P/*"},{"ua":"Nexus 6P"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LENOVO/*/Lenovo PB2-690Y/*"},{"ua":"Lenovo PB2-690Y"}],"dpi":[457.2,454.713],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5X/*"},{"ua":"Nexus 5X"}],"dpi":[422,419.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS345/*"},{"ua":"LGMS345"}],"dpi":[221.7,219.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D800/*"},{"ua":"LG-D800"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/LG-D850/*"},{"ua":"LG-D850"}],"dpi":[537.9,541.9],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"LGE/*/VS985 4G/*"},{"ua":"VS985 4G"}],"dpi":[537.9,535.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 5/*"},{"ua":"Nexus 5 B"}],"dpi":[442.4,444.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/Nexus 4/*"},{"ua":"Nexus 4"}],"dpi":[319.8,318.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LG-P769/*"},{"ua":"LG-P769"}],"dpi":[240.6,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGMS323/*"},{"ua":"LGMS323"}],"dpi":[206.6,204.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"LGE/*/LGLS996/*"},{"ua":"LGLS996"}],"dpi":[403.4,401.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/4560MMX/*"},{"ua":"4560MMX"}],"dpi":[240,219.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/A250/*"},{"ua":"Micromax A250"}],"dpi":[480,446.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Micromax/*/Micromax AQ4501/*"},{"ua":"Micromax AQ4501"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/G5/*"},{"ua":"Moto G (5) Plus"}],"dpi":[403.4,403],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/DROID RAZR/*"},{"ua":"DROID RAZR"}],"dpi":[368.1,256.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT830C/*"},{"ua":"XT830C"}],"dpi":[254,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1021/*"},{"ua":"XT1021"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1023/*"},{"ua":"XT1023"}],"dpi":[254,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1028/*"},{"ua":"XT1028"}],"dpi":[326.6,327.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1034/*"},{"ua":"XT1034"}],"dpi":[326.6,328.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1053/*"},{"ua":"XT1053"}],"dpi":[315.3,316.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1562/*"},{"ua":"XT1562"}],"dpi":[403.4,402.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/Nexus 6/*"},{"ua":"Nexus 6 B"}],"dpi":[494.3,489.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1063/*"},{"ua":"XT1063"}
1928],"dpi":[295,296.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/XT1064/*"},{"ua":"XT1064"}],"dpi":[295,295.6],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1092/*"},{"ua":"XT1092"}],"dpi":[422,424.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"motorola/*/XT1095/*"},{"ua":"XT1095"}],"dpi":[422,423.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"motorola/*/G4/*"},{"ua":"Moto G (4)"}],"dpi":401,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/A0001/*"},{"ua":"A0001"}],"dpi":[403.4,401],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE E1005/*"},{"ua":"ONE E1005"}],"dpi":[442.4,441.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A2005/*"},{"ua":"ONE A2005"}],"dpi":[391.9,405.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONEPLUS A5000/*"},{"ua":"ONEPLUS A5000 "}],"dpi":[403.411,399.737],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"OnePlus/*/ONE A5010/*"},{"ua":"ONEPLUS A5010"}],"dpi":[403,400],"bw":2,"ac":1000},{"type":"android","rules":[{"mdmh":"OPPO/*/X909/*"},{"ua":"X909"}],"dpi":[442.4,444.1],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9082/*"},{"ua":"GT-I9082"}],"dpi":[184.7,185.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G360P/*"},{"ua":"SM-G360P"}],"dpi":[196.7,205.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Nexus S/*"},{"ua":"Nexus S"}],"dpi":[234.5,229.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[304.8,303.9],"bw":5,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T230NU/*"},{"ua":"SM-T230NU"}],"dpi":216,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-T399/*"},{"ua":"SGH-T399"}],"dpi":[217.7,231.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SGH-M919/*"},{"ua":"SGH-M919"}],"dpi":[440.8,437.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N9005/*"},{"ua":"SM-N9005"}],"dpi":[386.4,387],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SM-N900A/*"},{"ua":"SAMSUNG-SM-N900A"}],"dpi":[386.4,387.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9500/*"},{"ua":"GT-I9500"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9505/*"},{"ua":"GT-I9505"}],"dpi":439.4,"bw":4,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900F/*"},{"ua":"SM-G900F"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G900M/*"},{"ua":"SM-G900M"}],"dpi":[415.6,431.6],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G800F/*"},{"ua":"SM-G800F"}],"dpi":326.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G906S/*"},{"ua":"SM-G906S"}],"dpi":[562.7,572.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300/*"},{"ua":"GT-I9300"}],"dpi":[306.7,304.8],"bw":5,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-T535/*"},{"ua":"SM-T535"}],"dpi":[142.6,136.4],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920C/*"},{"ua":"SM-N920C"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920P/*"},{"ua":"SM-N920P"}],"dpi":[386.3655,390.144],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N920W8/*"},{"ua":"SM-N920W8"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9300I/*"},{"ua":"GT-I9300I"}],"dpi":[304.8,305.8],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-I9195/*"},{"ua":"GT-I9195"}],"dpi":[249.4,256.7],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-L520/*"},{"ua":"SPH-L520"}],"dpi":[249.4,255.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SAMSUNG-SGH-I717/*"},{"ua":"SAMSUNG-SGH-I717"}],"dpi":285.8,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SPH-D710/*"},{"ua":"SPH-D710"}],"dpi":[217.7,204.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/GT-N7100/*"},{"ua":"GT-N7100"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SCH-I605/*"},{"ua":"SCH-I605"}],"dpi":265.1,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/Galaxy Nexus/*"},{"ua":"Galaxy Nexus"}],"dpi":[315.3,314.2],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910H/*"},{"ua":"SM-N910H"}],"dpi":[515.1,518],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-N910C/*"},{"ua":"SM-N910C"}],"dpi":[515.2,520.2],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G130M/*"},{"ua":"SM-G130M"}],"dpi":[165.9,164.8],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G928I/*"},{"ua":"SM-G928I"}],"dpi":[515.1,518.4],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920F/*"},{"ua":"SM-G920F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G920P/*"},{"ua":"SM-G920P"}],"dpi":[522.5,577],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925F/*"},{"ua":"SM-G925F"}],"dpi":580.6,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G925V/*"},{"ua":"SM-G925V"}],"dpi":[522.5,576.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G930F/*"},{"ua":"SM-G930F"}],"dpi":576.6,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G935F/*"},{"ua":"SM-G935F"}],"dpi":533,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G950F/*"},{"ua":"SM-G950F"}],"dpi":[562.707,565.293],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"samsung/*/SM-G955U/*"},{"ua":"SM-G955U"}],"dpi":[522.514,525.762],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/C6903/*"},{"ua":"C6903"}],"dpi":[442.5,443.3],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"Sony/*/D6653/*"},{"ua":"D6653"}],"dpi":[428.6,427.6],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6653/*"},{"ua":"E6653"}],"dpi":[428.6,425.7],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/E6853/*"},{"ua":"E6853"}],"dpi":[403.4,401.9],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Sony/*/SGP321/*"},{"ua":"SGP321"}],"dpi":[224.7,224.1],"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"TCT/*/ALCATEL ONE TOUCH Fierce/*"},{"ua":"ALCATEL ONE TOUCH Fierce"}],"dpi":[240,247.5],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"THL/*/thl 5000/*"},{"ua":"thl 5000"}],"dpi":[480,443.3],"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"Fly/*/IQ4412/*"},{"ua":"IQ4412"}],"dpi":307.9,"bw":3,"ac":1000},{"type":"android","rules":[{"mdmh":"ZTE/*/ZTE Blade L2/*"},{"ua":"ZTE Blade L2"}],"dpi":240,"bw":3,"ac":500},{"type":"android","rules":[{"mdmh":"BENEVE/*/VR518/*"},{"ua":"VR518"}],"dpi":480,"bw":3,"ac":500}
vendor: 9,300 bytes, lines 1928-2178
1928,{"type":"ios","rules":[{"res":[640,960]}],"dpi":[325.1,328.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[640,1136]}],"dpi":[317.1,320.2],"bw":3,"ac":1000},{"type":"ios","rules":[{"res":[750,1334]}],"dpi":326.4,"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1242,2208]}],"dpi":[453.6,458.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2001]}],"dpi":[410.9,415.4],"bw":4,"ac":1000},{"type":"ios","rules":[{"res":[1125,2436]}],"dpi":458,"bw":4,"ac":1000}]; 1929 var DPDB_CACHE = { 1930 format: format, 1931 last_updated: last_updated, 1932 devices: devices 1933 }; 1934 function Dpdb(url, onDeviceParamsUpdated) { 1935 this.dpdb = DPDB_CACHE; 1936 this.recalculateDeviceParams_(); 1937 if (url) { 1938 this.onDeviceParamsUpdated = onDeviceParamsUpdated; 1939 var xhr = new XMLHttpRequest(); 1940 var obj = this; 1941 xhr.open('GET', url, true); 1942 xhr.addEventListener('load', function () { 1943 obj.loading = false; 1944 if (xhr.status >= 200 && xhr.status <= 299) { 1945 obj.dpdb = JSON.parse(xhr.response); 1946 obj.recalculateDeviceParams_(); 1947 } else { 1948 console.error('Error loading online DPDB!'); 1949 } 1950 }); 1951 xhr.send(); 1952 } 1953 } 1954 Dpdb.prototype.getDeviceParams = function () { 1955 return this.deviceParams; 1956 }; 1957 Dpdb.prototype.recalculateDeviceParams_ = function () { 1958 var newDeviceParams = this.calcDeviceParams_(); 1959 if (newDeviceParams) { 1960 this.deviceParams = newDeviceParams; 1961 if (this.onDeviceParamsUpdated) { 1962 this.onDeviceParamsUpdated(this.deviceParams); 1963 } 1964 } else { 1965 console.error('Failed to recalculate device parameters.'); 1966 } 1967 }; 1968 Dpdb.prototype.calcDeviceParams_ = function () { 1969 var db = this.dpdb; 1970 if (!db) { 1971 console.error('DPDB not available.'); 1972 return null; 1973 } 1974 if (db.format != 1) { 1975 console.error('DPDB has unexpected format version.'); 1976 return null; 1977 } 1978 if (!db.devices || !db.devices.length) { 1979 console.error('DPDB does not have a devices section.'); 1980 return null; 1981 } 1982 var userAgent = navigator.userAgent || navigator.vendor || window.opera; 1983 var width = getScreenWidth(); 1984 var height = getScreenHeight(); 1985 if (!db.devices) { 1986 console.error('DPDB has no devices section.'); 1987 return null; 1988 } 1989 for (var i = 0; i < db.devices.length; i++) { 1990 var device = db.devices[i]; 1991 if (!device.rules) { 1992 console.warn('Device[' + i + '] has no rules section.'); 1993 continue; 1994 } 1995 if (device.type != 'ios' && device.type != 'android') { 1996 console.warn('Device[' + i + '] has invalid type.'); 1997 continue; 1998 } 1999 if (isIOS() != (device.type == 'ios')) continue; 2000 var matched = false; 2001 for (var j = 0; j < device.rules.length; j++) { 2002 var rule = device.rules[j]; 2003 if (this.matchRule_(rule, userAgent, width, height)) { 2004 matched = true; 2005 break; 2006 } 2007 } 2008 if (!matched) continue; 2009 var xdpi = device.dpi[0] || device.dpi; 2010 var ydpi = device.dpi[1] || device.dpi; 2011 return new DeviceParams({ xdpi: xdpi, ydpi: ydpi, bevelMm: device.bw }); 2012 } 2013 console.warn('No DPDB device match.'); 2014 return null; 2015 }; 2016 Dpdb.prototype.matchRule_ = function (rule, ua, screenWidth, screenHeight) { 2017 if (!rule.ua && !rule.res) return false; 2018 if (rule.ua && ua.indexOf(rule.ua) < 0) return false; 2019 if (rule.res) { 2020 if (!rule.res[0] || !rule.res[1]) return false; 2021 var resX = rule.res[0]; 2022 var resY = rule.res[1]; 2023 if (Math.min(screenWidth, screenHeight) != Math.min(resX, resY) || Math.max(screenWidth, screenHeight) != Math.max(resX, resY)) { 2024 return false; 2025 } 2026 } 2027 return true; 2028 }; 2029 function DeviceParams(params) { 2030 this.xdpi = params.xdpi; 2031 this.ydpi = params.ydpi; 2032 this.bevelMm = params.bevelMm; 2033 } 2034 function SensorSample(sample, timestampS) { 2035 this.set(sample, timestampS); 2036 } 2037 SensorSample.prototype.set = function (sample, timestampS) { 2038 this.sample = sample; 2039 this.timestampS = timestampS; 2040 }; 2041 SensorSample.prototype.copy = function (sensorSample) { 2042 this.set(sensorSample.sample, sensorSample.timestampS); 2043 }; 2044 function ComplementaryFilter(kFilter, isDebug) { 2045 this.kFilter = kFilter; 2046 this.isDebug = isDebug; 2047 this.currentAccelMeasurement = new SensorSample(); 2048 this.currentGyroMeasurement = new SensorSample(); 2049 this.previousGyroMeasurement = new SensorSample(); 2050 if (isIOS()) { 2051 this.filterQ = new Quaternion(-1, 0, 0, 1); 2052 } else { 2053 this.filterQ = new Quaternion(1, 0, 0, 1); 2054 } 2055 this.previousFilterQ = new Quaternion(); 2056 this.previousFilterQ.copy(this.filterQ); 2057 this.accelQ = new Quaternion(); 2058 this.isOrientationInitialized = false; 2059 this.estimatedGravity = new Vector3(); 2060 this.measuredGravity = new Vector3(); 2061 this.gyroIntegralQ = new Quaternion(); 2062 } 2063 ComplementaryFilter.prototype.addAccelMeasurement = function (vector, timestampS) { 2064 this.currentAccelMeasurement.set(vector, timestampS); 2065 }; 2066 ComplementaryFilter.prototype.addGyroMeasurement = function (vector, timestampS) { 2067 this.currentGyroMeasurement.set(vector, timestampS); 2068 var deltaT = timestampS - this.previousGyroMeasurement.timestampS; 2069 if (isTimestampDeltaValid(deltaT)) { 2070 this.run_(); 2071 } 2072 this.previousGyroMeasurement.copy(this.currentGyroMeasurement); 2073 }; 2074 ComplementaryFilter.prototype.run_ = function () { 2075 if (!this.isOrientationInitialized) { 2076 this.accelQ = this.accelToQuaternion_(this.currentAccelMeasurement.sample); 2077 this.previousFilterQ.copy(this.accelQ); 2078 this.isOrientationInitialized = true; 2079 return; 2080 } 2081 var deltaT = this.currentGyroMeasurement.timestampS - this.previousGyroMeasurement.timestampS; 2082 var gyroDeltaQ = this.gyroToQuaternionDelta_(this.currentGyroMeasurement.sample, deltaT); 2083 this.gyroIntegralQ.multiply(gyroDeltaQ); 2084 this.filterQ.copy(this.previousFilterQ); 2085 this.filterQ.multiply(gyroDeltaQ); 2086 var invFilterQ = new Quaternion(); 2087 invFilterQ.copy(this.filterQ); 2088 invFilterQ.inverse(); 2089 this.estimatedGravity.set(0, 0, -1); 2090 this.estimatedGravity.applyQuaternion(invFilterQ); 2091 this.estimatedGravity.normalize(); 2092 this.measuredGravity.copy(this.currentAccelMeasurement.sample); 2093 this.measuredGravity.normalize(); 2094 var deltaQ = new Quaternion(); 2095 deltaQ.setFromUnitVectors(this.estimatedGravity, this.measuredGravity); 2096 deltaQ.inverse(); 2097 if (this.isDebug) { 2098 console.log('Delta: %d deg, G_est: (%s, %s, %s), G_meas: (%s, %s, %s)', radToDeg * getQuaternionAngle(deltaQ), this.estimatedGravity.x.toFixed(1), this.estimatedGravity.y.toFixed(1), this.estimatedGravity.z.toFixed(1), this.measuredGravity.x.toFixed(1), this.measuredGravity.y.toFixed(1), this.measuredGravity.z.toFixed(1)); 2099 } 2100 var targetQ = new Quaternion(); 2101 targetQ.copy(this.filterQ); 2102 targetQ.multiply(deltaQ); 2103 this.filterQ.slerp(targetQ, 1 - this.kFilter); 2104 this.previousFilterQ.copy(this.filterQ); 2105 }; 2106 ComplementaryFilter.prototype.getOrientation = function () { 2107 return this.filterQ; 2108 }; 2109 ComplementaryFilter.prototype.accelToQuaternion_ = function (accel) { 2110 var normAccel = new Vector3(); 2111 normAccel.copy(accel); 2112 normAccel.normalize(); 2113 var quat = new Quaternion(); 2114 quat.setFromUnitVectors(new Vector3(0, 0, -1), normAccel); 2115 quat.inverse(); 2116 return quat; 2117 }; 2118 ComplementaryFilter.prototype.gyroToQuaternionDelta_ = function (gyro, dt) { 2119 var quat = new Quaternion(); 2120 var axis = new Vector3(); 2121 axis.copy(gyro); 2122 axis.normalize(); 2123 quat.setFromAxisAngle(axis, gyro.length() * dt); 2124 return quat; 2125 }; 2126 function PosePredictor(predictionTimeS, isDebug) { 2127 this.predictionTimeS = predictionTimeS; 2128 this.isDebug = isDebug; 2129 this.previousQ = new Quaternion(); 2130 this.previousTimestampS = null; 2131 this.deltaQ = new Quaternion(); 2132 this.outQ = new Quaternion(); 2133 } 2134 PosePredictor.prototype.getPrediction = function (currentQ, gyro, timestampS) { 2135 if (!this.previousTimestampS) { 2136 this.previousQ.copy(currentQ); 2137 this.previousTimestampS = timestampS; 2138 return currentQ; 2139 } 2140 var axis = new Vector3(); 2141 axis.copy(gyro); 2142 axis.normalize(); 2143 var angularSpeed = gyro.length(); 2144 if (angularSpeed < degToRad * 20) { 2145 if (this.isDebug) { 2146 console.log('Moving slowly, at %s deg/s: no prediction', (radToDeg * angularSpeed).toFixed(1)); 2147 } 2148 this.outQ.copy(currentQ); 2149 this.previousQ.copy(currentQ); 2150 return this.outQ; 2151 } 2152 var predictAngle = angularSpeed * this.predictionTimeS; 2153 this.deltaQ.setFromAxisAngle(axis, predictAngle); 2154 this.outQ.copy(this.previousQ); 2155 this.outQ.multiply(this.deltaQ); 2156 this.previousQ.copy(currentQ); 2157 this.previousTimestampS = timestampS; 2158 return this.outQ; 2159 }; 2160 function FusionPoseSensor(kFilter, predictionTime, yawOnly, isDebug) { 2161 this.yawOnly = yawOnly; 2162 this.accelerometer = new Vector3(); 2163 this.gyroscope = new Vector3(); 2164 this.filter = new ComplementaryFilter(kFilter, isDebug); 2165 this.posePredictor = new PosePredictor(predictionTime, isDebug); 2166 this.isFirefoxAndroid = isFirefoxAndroid(); 2167 this.isIOS = isIOS(); 2168 var chromeVersion = getChromeVersion(); 2169 this.isDeviceMotionInRadians = !this.isIOS && chromeVersion && chromeVersion < 66; 2170 this.isWithoutDeviceMotion = isChromeWithoutDeviceMotion(); 2171 this.filterToWorldQ = new Quaternion(); 2172 if (isIOS()) { 2173 this.filterToWorldQ.setFromAxisAngle(new Vector3(1, 0, 0), Math.PI / 2); 2174 } else { 2175 this.filterToWorldQ.setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2); 2176 } 2177 this.inverseWorldToScreenQ = new Quaternion(); 2178 this.worldToScreenQ = new Quaternion();
vendor: 7,633 bytes, lines 2179-2385
2179 this.originalPoseAdjustQ = new Quaternion(); 2180 this.originalPoseAdjustQ.setFromAxisAngle(new Vector3(0, 0, 1), -window.orientation * Math.PI / 180); 2181 this.setScreenTransform_(); 2182 if (isLandscapeMode()) { 2183 this.filterToWorldQ.multiply(this.inverseWorldToScreenQ); 2184 } 2185 this.resetQ = new Quaternion(); 2186 this.orientationOut_ = new Float32Array(4); 2187 this.start(); 2188 } 2189 FusionPoseSensor.prototype.getPosition = function () { 2190 return null; 2191 }; 2192 FusionPoseSensor.prototype.getOrientation = function () { 2193 var orientation = void 0; 2194 if (this.isWithoutDeviceMotion && this._deviceOrientationQ) { 2195 this.deviceOrientationFixQ = this.deviceOrientationFixQ || function () { 2196 var z = new Quaternion().setFromAxisAngle(new Vector3(0, 0, -1), 0); 2197 var y = new Quaternion(); 2198 if (window.orientation === -90) { 2199 y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / -2); 2200 } else { 2201 y.setFromAxisAngle(new Vector3(0, 1, 0), Math.PI / 2); 2202 } 2203 return z.multiply(y); 2204 }(); 2205 this.deviceOrientationFilterToWorldQ = this.deviceOrientationFilterToWorldQ || function () { 2206 var q = new Quaternion(); 2207 q.setFromAxisAngle(new Vector3(1, 0, 0), -Math.PI / 2); 2208 return q; 2209 }(); 2210 orientation = this._deviceOrientationQ; 2211 var out = new Quaternion(); 2212 out.copy(orientation); 2213 out.multiply(this.deviceOrientationFilterToWorldQ); 2214 out.multiply(this.resetQ); 2215 out.multiply(this.worldToScreenQ); 2216 out.multiplyQuaternions(this.deviceOrientationFixQ, out); 2217 if (this.yawOnly) { 2218 out.x = 0; 2219 out.z = 0; 2220 out.normalize(); 2221 } 2222 this.orientationOut_[0] = out.x; 2223 this.orientationOut_[1] = out.y; 2224 this.orientationOut_[2] = out.z; 2225 this.orientationOut_[3] = out.w; 2226 return this.orientationOut_; 2227 } else { 2228 var filterOrientation = this.filter.getOrientation(); 2229 orientation = this.posePredictor.getPrediction(filterOrientation, this.gyroscope, this.previousTimestampS); 2230 } 2231 var out = new Quaternion(); 2232 out.copy(this.filterToWorldQ); 2233 out.multiply(this.resetQ); 2234 out.multiply(orientation); 2235 out.multiply(this.worldToScreenQ); 2236 if (this.yawOnly) { 2237 out.x = 0; 2238 out.z = 0; 2239 out.normalize(); 2240 } 2241 this.orientationOut_[0] = out.x; 2242 this.orientationOut_[1] = out.y; 2243 this.orientationOut_[2] = out.z; 2244 this.orientationOut_[3] = out.w; 2245 return this.orientationOut_; 2246 }; 2247 FusionPoseSensor.prototype.resetPose = function () { 2248 this.resetQ.copy(this.filter.getOrientation()); 2249 this.resetQ.x = 0; 2250 this.resetQ.y = 0; 2251 this.resetQ.z *= -1; 2252 this.resetQ.normalize(); 2253 if (isLandscapeMode()) { 2254 this.resetQ.multiply(this.inverseWorldToScreenQ); 2255 } 2256 this.resetQ.multiply(this.originalPoseAdjustQ); 2257 }; 2258 FusionPoseSensor.prototype.onDeviceOrientation_ = function (e) { 2259 this._deviceOrientationQ = this._deviceOrientationQ || new Quaternion(); 2260 var alpha = e.alpha, 2261 beta = e.beta, 2262 gamma = e.gamma; 2263 alpha = (alpha || 0) * Math.PI / 180; 2264 beta = (beta || 0) * Math.PI / 180; 2265 gamma = (gamma || 0) * Math.PI / 180; 2266 this._deviceOrientationQ.setFromEulerYXZ(beta, alpha, -gamma); 2267 }; 2268 FusionPoseSensor.prototype.onDeviceMotion_ = function (deviceMotion) { 2269 this.updateDeviceMotion_(deviceMotion); 2270 }; 2271 FusionPoseSensor.prototype.updateDeviceMotion_ = function (deviceMotion) { 2272 var accGravity = deviceMotion.accelerationIncludingGravity; 2273 var rotRate = deviceMotion.rotationRate; 2274 var timestampS = deviceMotion.timeStamp / 1000; 2275 var deltaS = timestampS - this.previousTimestampS; 2276 if (deltaS < 0) { 2277 warnOnce('fusion-pose-sensor:invalid:non-monotonic', 'Invalid timestamps detected: non-monotonic timestamp from devicemotion'); 2278 this.previousTimestampS = timestampS; 2279 return; 2280 } else if (deltaS <= MIN_TIMESTEP || deltaS > MAX_TIMESTEP) { 2281 warnOnce('fusion-pose-sensor:invalid:outside-threshold', 'Invalid timestamps detected: Timestamp from devicemotion outside expected range.'); 2282 this.previousTimestampS = timestampS; 2283 return; 2284 } 2285 this.accelerometer.set(-accGravity.x, -accGravity.y, -accGravity.z); 2286 if (isR7()) { 2287 this.gyroscope.set(-rotRate.beta, rotRate.alpha, rotRate.gamma); 2288 } else { 2289 this.gyroscope.set(rotRate.alpha, rotRate.beta, rotRate.gamma); 2290 } 2291 if (!this.isDeviceMotionInRadians) { 2292 this.gyroscope.multiplyScalar(Math.PI / 180); 2293 } 2294 this.filter.addAccelMeasurement(this.accelerometer, timestampS); 2295 this.filter.addGyroMeasurement(this.gyroscope, timestampS); 2296 this.previousTimestampS = timestampS; 2297 }; 2298 FusionPoseSensor.prototype.onOrientationChange_ = function (screenOrientation) { 2299 this.setScreenTransform_(); 2300 }; 2301 FusionPoseSensor.prototype.onMessage_ = function (event) { 2302 var message = event.data; 2303 if (!message || !message.type) { 2304 return; 2305 } 2306 var type = message.type.toLowerCase(); 2307 if (type !== 'devicemotion') { 2308 return; 2309 } 2310 this.updateDeviceMotion_(message.deviceMotionEvent); 2311 }; 2312 FusionPoseSensor.prototype.setScreenTransform_ = function () { 2313 this.worldToScreenQ.set(0, 0, 0, 1); 2314 switch (window.orientation) { 2315 case 0: 2316 break; 2317 case 90: 2318 this.worldToScreenQ.setFromAxisAngle(new Vector3(0, 0, 1), -Math.PI / 2); 2319 break; 2320 case -90: 2321 this.worldToScreenQ.setFromAxisAngle(new Vector3(0, 0, 1), Math.PI / 2); 2322 break; 2323 } 2324 this.inverseWorldToScreenQ.copy(this.worldToScreenQ); 2325 this.inverseWorldToScreenQ.inverse(); 2326 }; 2327 FusionPoseSensor.prototype.start = function () { 2328 this.onDeviceMotionCallback_ = this.onDeviceMotion_.bind(this); 2329 this.onOrientationChangeCallback_ = this.onOrientationChange_.bind(this); 2330 this.onMessageCallback_ = this.onMessage_.bind(this); 2331 this.onDeviceOrientationCallback_ = this.onDeviceOrientation_.bind(this); 2332 if (isIOS() && isInsideCrossOriginIFrame()) { 2333 window.addEventListener('message', this.onMessageCallback_); 2334 } 2335 window.addEventListener('orientationchange', this.onOrientationChangeCallback_); 2336 if (this.isWithoutDeviceMotion) { 2337 window.addEventListener('deviceorientation', this.onDeviceOrientationCallback_); 2338 } else { 2339 window.addEventListener('devicemotion', this.onDeviceMotionCallback_); 2340 } 2341 }; 2342 FusionPoseSensor.prototype.stop = function () { 2343 window.removeEventListener('devicemotion', this.onDeviceMotionCallback_); 2344 window.removeEventListener('deviceorientation', this.onDeviceOrientationCallback_); 2345 window.removeEventListener('orientationchange', this.onOrientationChangeCallback_); 2346 window.removeEventListener('message', this.onMessageCallback_); 2347 }; 2348 var SENSOR_FREQUENCY = 60; 2349 var X_AXIS = new Vector3(1, 0, 0); 2350 var Z_AXIS = new Vector3(0, 0, 1); 2351 var orientation = {}; 2352 if (screen.orientation) { 2353 orientation = screen.orientation; 2354 } else if (screen.msOrientation) { 2355 orientation = screen.msOrientation; 2356 } else { 2357 Object.defineProperty(orientation, 'angle', { 2358 get: function get$$1() { 2359 return window.orientation || 0; 2360 } 2361 }); 2362 } 2363 var SENSOR_TO_VR = new Quaternion(); 2364 SENSOR_TO_VR.setFromAxisAngle(X_AXIS, -Math.PI / 2); 2365 SENSOR_TO_VR.multiply(new Quaternion().setFromAxisAngle(Z_AXIS, Math.PI / 2)); 2366 var PoseSensor = function () { 2367 function PoseSensor(config) { 2368 classCallCheck(this, PoseSensor); 2369 this.config = config; 2370 this.sensor = null; 2371 this.fusionSensor = null; 2372 this._out = new Float32Array(4); 2373 this.api = null; 2374 this.errors = []; 2375 this._sensorQ = new Quaternion(); 2376 this._worldToScreenQ = new Quaternion(); 2377 this._outQ = new Quaternion(); 2378 this._onSensorRead = this._onSensorRead.bind(this); 2379 this._onSensorError = this._onSensorError.bind(this); 2380 this._onOrientationChange = this._onOrientationChange.bind(this); 2381 this._onOrientationChange(); 2382 this.init(); 2383 } 2384 createClass(PoseSensor, [{ 2385 key: 'init',
vendor: 5,556 bytes, lines 2386-2474
2386 value: function init() { 2387 var sensor = null; 2388 try { 2389 sensor = new RelativeOrientationSensor({ frequency: SENSOR_FREQUENCY }); 2390 sensor.addEventListener('error', this._onSensorError); 2391 } catch (error) { 2392 this.errors.push(error); 2393 if (error.name === 'SecurityError') { 2394 console.error('Cannot construct sensors due to the Feature Policy'); 2395 console.warn('Attempting to fall back using "devicemotion"; however this will ' + 'fail in the future without correct permissions.'); 2396 this.useDeviceMotion(); 2397 } else if (error.name === 'ReferenceError') { 2398 this.useDeviceMotion(); 2399 } else { 2400 console.error(error); 2401 } 2402 } 2403 if (sensor) { 2404 this.api = 'sensor'; 2405 this.sensor = sensor; 2406 this.sensor.addEventListener('reading', this._onSensorRead); 2407 this.sensor.start(); 2408 } 2409 window.addEventListener('orientationchange', this._onOrientationChange); 2410 } 2411 }, { 2412 key: 'useDeviceMotion', 2413 value: function useDeviceMotion() { 2414 this.api = 'devicemotion'; 2415 this.fusionSensor = new FusionPoseSensor(this.config.K_FILTER, this.config.PREDICTION_TIME_S, this.config.YAW_ONLY, this.config.DEBUG); 2416 if (this.sensor) { 2417 this.sensor.removeEventListener('reading', this._onSensorRead); 2418 this.sensor.removeEventListener('error', this._onSensorError); 2419 this.sensor = null; 2420 } 2421 } 2422 }, { 2423 key: 'getOrientation', 2424 value: function getOrientation() { 2425 if (this.fusionSensor) { 2426 return this.fusionSensor.getOrientation(); 2427 } 2428 if (!this.sensor || !this.sensor.quaternion) { 2429 this._out[0] = this._out[1] = this._out[2] = 0; 2430 this._out[3] = 1; 2431 return this._out; 2432 } 2433 var q = this.sensor.quaternion; 2434 this._sensorQ.set(q[0], q[1], q[2], q[3]); 2435 var out = this._outQ; 2436 out.copy(SENSOR_TO_VR); 2437 out.multiply(this._sensorQ); 2438 out.multiply(this._worldToScreenQ); 2439 if (this.config.YAW_ONLY) { 2440 out.x = out.z = 0; 2441 out.normalize(); 2442 } 2443 this._out[0] = out.x; 2444 this._out[1] = out.y; 2445 this._out[2] = out.z; 2446 this._out[3] = out.w; 2447 return this._out; 2448 } 2449 }, { 2450 key: '_onSensorError', 2451 value: function _onSensorError(event) { 2452 this.errors.push(event.error); 2453 if (event.error.name === 'NotAllowedError') { 2454 console.error('Permission to access sensor was denied'); 2455 } else if (event.error.name === 'NotReadableError') { 2456 console.error('Sensor could not be read'); 2457 } else { 2458 console.error(event.error); 2459 } 2460 this.useDeviceMotion(); 2461 } 2462 }, { 2463 key: '_onSensorRead', 2464 value: function _onSensorRead() {} 2465 }, { 2466 key: '_onOrientationChange', 2467 value: function _onOrientationChange() { 2468 var angle = -orientation.angle * Math.PI / 180; 2469 this._worldToScreenQ.setFromAxisAngle(Z_AXIS, angle); 2470 } 2471 }]); 2472 return PoseSensor; 2473 }(); 2474 var rotateInstructionsAsset = 'PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+Cjxzdmcgd2lkdGg9IjE5OHB4IiBoZWlnaHQ9IjI0MHB4IiB2aWV3Qm94PSIwIDAgMTk4IDI0MCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWxuczpza2V0Y2g9Imh0dHA6Ly93d3cuYm9oZW1pYW5jb2RpbmcuY29tL3NrZXRjaC9ucyI+CiAgICA8IS0tIEdlbmVyYXRvcjogU2tldGNoIDMuMy4zICgxMjA4MSkgLSBodHRwOi8vd3d3LmJvaGVtaWFuY29kaW5nLmNvbS9za2V0Y2ggLS0+CiAgICA8dGl0bGU+dHJhbnNpdGlvbjwvdGl0bGU+CiAgICA8ZGVzYz5DcmVhdGVkIHdpdGggU2tldGNoLjwvZGVzYz4KICAgIDxkZWZzPjwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIHNrZXRjaDp0eXBlPSJNU1BhZ2UiPgogICAgICAgIDxnIGlkPSJ0cmFuc2l0aW9uIiBza2V0Y2g6dHlwZT0iTVNBcnRib2FyZEdyb3VwIj4KICAgICAgICAgICAgPGcgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTQtKy1JbXBvcnRlZC1MYXllcnMtQ29weS0rLUltcG9ydGVkLUxheWVycy1Db3B5LTItQ29weSIgc2tldGNoOnR5cGU9Ik1TTGF5ZXJHcm91cCI+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHktNCIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDEwNy4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjYyNSwyLjUyNyBDMTQ5LjYyNSwyLjUyNyAxNTUuODA1LDYuMDk2IDE1Ni4zNjIsNi40MTggTDE1Ni4zNjIsNy4zMDQgQzE1Ni4zNjIsNy40ODEgMTU2LjM3NSw3LjY2NCAxNTYuNCw3Ljg1MyBDMTU2LjQxLDcuOTM0IDE1Ni40Miw4LjAxNSAxNTYuNDI3LDguMDk1IEMxNTYuNTY3LDkuNTEgMTU3LjQwMSwxMS4wOTMgMTU4LjUzMiwxMi4wOTQgTDE2NC4yNTIsMTcuMTU2IEwxNjQuMzMzLDE3LjA2NiBDMTY0LjMzMywxNy4wNjYgMTY4LjcxNSwxNC41MzYgMTY5LjU2OCwxNC4wNDIgQzE3MS4wMjUsMTQuODgzIDE5NS41MzgsMjkuMDM1IDE5NS41MzgsMjkuMDM1IEwxOTUuNTM4LDgzLjAzNiBDMTk1LjUzOCw4My44MDcgMTk1LjE1Miw4NC4yNTMgMTk0LjU5LDg0LjI1MyBDMTk0LjM1Nyw4NC4yNTMgMTk0LjA5NSw4NC4xNzcgMTkzLjgxOCw4NC4wMTcgTDE2OS44NTEsNzAuMTc5IEwxNjkuODM3LDcwLjIwMyBMMTQyLjUxNSw4NS45NzggTDE0MS42NjUsODQuNjU1IEMxMzYuOTM0LDgzLjEyNiAxMzEuOTE3LDgxLjkxNSAxMjYuNzE0LDgxLjA0NSBDMTI2LjcwOSw4MS4wNiAxMjYuNzA3LDgxLjA2OSAxMjYuNzA3LDgxLjA2OSBMMTIxLjY0LDk4LjAzIEwxMTMuNzQ5LDEwMi41ODYgTDExMy43MTIsMTAyLjUyMyBMMTEzLjcxMiwxMzAuMTEzIEMxMTMuNzEyLDEzMC44ODUgMTEzLjMyNiwxMzEuMzMgMTEyLjc2NCwxMzEuMzMgQzExMi41MzIsMTMxLjMzIDExMi4yNjksMTMxLjI1NCAxMTEuOTkyLDEzMS4wOTQgTDY5LjUxOSwxMDYuNTcyIEM2OC41NjksMTA2LjAyMyA2Ny43OTksMTA0LjY5NSA2Ny43OTksMTAzLjYwNSBMNjcuNzk5LDEwMi41NyBMNjcuNzc4LDEwMi42MTcgQzY3LjI3LDEwMi4zOTMgNjYuNjQ4LDEwMi4yNDkgNjUuOTYyLDEwMi4yMTggQzY1Ljg3NSwxMDIuMjE0IDY1Ljc4OCwxMDIuMjEyIDY1LjcwMSwxMDIuMjEyIEM2NS42MDYsMTAyLjIxMiA2NS41MTEsMTAyLjIxNSA2NS40MTYsMTAyLjIxOSBDNjUuMTk1LDEwMi4yMjkgNjQuOTc0LDEwMi4yMzUgNjQuNzU0LDEwMi4yMzUgQzY0LjMzMSwxMDIuMjM1IDYzLjkxMSwxMDIuMjE2IDYzLjQ5OCwxMDIuMTc4IEM2MS44NDMsMTAyLjAyNSA2MC4yOTgsMTAxLjU3OCA1OS4wOTQsMTAwLjg4MiBMMTIuNTE4LDczLjk5MiBMMTIuNTIzLDc0LjAwNCBMMi4yNDUsNTUuMjU0IEMxLjI0NCw1My40MjcgMi4wMDQsNTEuMDM4IDMuOTQzLDQ5LjkxOCBMNTkuOTU0LDE3LjU3MyB
2474DNjAuNjI2LDE3LjE4NSA2MS4zNSwxNy4wMDEgNjIuMDUzLDE3LjAwMSBDNjMuMzc5LDE3LjAwMSA2NC42MjUsMTcuNjYgNjUuMjgsMTguODU0IEw2NS4yODUsMTguODUxIEw2NS41MTIsMTkuMjY0IEw2NS41MDYsMTkuMjY4IEM2NS45MDksMjAuMDAzIDY2LjQwNSwyMC42OCA2Ni45ODMsMjEuMjg2IEw2Ny4yNiwyMS41NTYgQzY5LjE3NCwyMy40MDYgNzEuNzI4LDI0LjM1NyA3NC4zNzMsMjQuMzU3IEM3Ni4zMjIsMjQuMzU3IDc4LjMyMSwyMy44NCA4MC4xNDgsMjIuNzg1IEM4MC4xNjEsMjIuNzg1IDg3LjQ2NywxOC41NjYgODcuNDY3LDE4LjU2NiBDODguMTM5LDE4LjE3OCA4OC44NjMsMTcuOTk0IDg5LjU2NiwxNy45OTQgQzkwLjg5MiwxNy45OTQgOTIuMTM4LDE4LjY1MiA5Mi43OTIsMTkuODQ3IEw5Ni4wNDIsMjUuNzc1IEw5Ni4wNjQsMjUuNzU3IEwxMDIuODQ5LDI5LjY3NCBMMTAyLjc0NCwyOS40OTIgTDE0OS42MjUsMi41MjcgTTE0OS42MjUsMC44OTIgQzE0OS4zNDMsMC44OTIgMTQ5LjA2MiwwLjk2NSAxNDguODEsMS4xMSBMMTAyLjY0MSwyNy42NjYgTDk3LjIzMSwyNC41NDIgTDk0LjIyNiwxOS4wNjEgQzkzLjMxMywxNy4zOTQgOTEuNTI3LDE2LjM1OSA4OS41NjYsMTYuMzU4IEM4OC41NTUsMTYuMzU4IDg3LjU0NiwxNi42MzIgODYuNjQ5LDE3LjE1IEM4My44NzgsMTguNzUgNzkuNjg3LDIxLjE2OSA3OS4zNzQsMjEuMzQ1IEM3OS4zNTksMjEuMzUzIDc5LjM0NSwyMS4zNjEgNzkuMzMsMjEuMzY5IEM3Ny43OTgsMjIuMjU0IDc2LjA4NCwyMi43MjIgNzQuMzczLDIyLjcyMiBDNzIuMDgxLDIyLjcyMiA2OS45NTksMjEuODkgNjguMzk3LDIwLjM4IEw2OC4xNDUsMjAuMTM1IEM2Ny43MDYsMTkuNjcyIDY3LjMyMywxOS4xNTYgNjcuMDA2LDE4LjYwMSBDNjYuOTg4LDE4LjU1OSA2Ni45NjgsMTguNTE5IDY2Ljk0NiwxOC40NzkgTDY2LjcxOSwxOC4wNjUgQzY2LjY5LDE4LjAxMiA2Ni42NTgsMTcuOTYgNjYuNjI0LDE3LjkxMSBDNjUuNjg2LDE2LjMzNyA2My45NTEsMTUuMzY2IDYyLjA1MywxNS4zNjYgQzYxLjA0MiwxNS4zNjYgNjAuMDMzLDE1LjY0IDU5LjEzNiwxNi4xNTggTDMuMTI1LDQ4LjUwMiBDMC40MjYsNTAuMDYxIC0wLjYxMyw1My40NDIgMC44MTEsNTYuMDQgTDExLjA4OSw3NC43OSBDMTEuMjY2LDc1LjExMyAxMS41MzcsNzUuMzUzIDExLjg1LDc1LjQ5NCBMNTguMjc2LDEwMi4yOTggQzU5LjY3OSwxMDMuMTA4IDYxLjQzMywxMDMuNjMgNjMuMzQ4LDEwMy44MDYgQzYzLjgxMiwxMDMuODQ4IDY0LjI4NSwxMDMuODcgNjQuNzU0LDEwMy44NyBDNjUsMTAzLjg3IDY1LjI0OSwxMDMuODY0IDY1LjQ5NCwxMDMuODUyIEM2NS41NjMsMTAzLjg0OSA2NS42MzIsMTAzLjg0NyA2NS43MDEsMTAzLjg0NyBDNjUuNzY0LDEwMy44NDcgNjUuODI4LDEwMy44NDkgNjUuODksMTAzLjg1MiBDNjUuOTg2LDEwMy44NTYgNjYuMDgsMTAzLjg2MyA2Ni4xNzMsMTAzLjg3NCBDNjYuMjgyLDEwNS40NjcgNjcuMzMyLDEwNy4xOTcgNjguNzAyLDEwNy45ODggTDExMS4xNzQsMTMyLjUxIEMxMTEuNjk4LDEzMi44MTIgMTEyLjIzMiwxMzIuOTY1IDExMi43NjQsMTMyLjk2NSBDMTE0LjI2MSwxMzIuOTY1IDExNS4zNDcsMTMxLjc2NSAxMTUuMzQ3LDEzMC4xMTMgTDExNS4zNDcsMTAzLjU1MSBMMTIyLjQ1OCw5OS40NDYgQzEyMi44MTksOTkuMjM3IDEyMy4wODcsOTguODk4IDEyMy4yMDcsOTguNDk4IEwxMjcuODY1LDgyLjkwNSBDMTMyLjI3OSw4My43MDIgMTM2LjU1Nyw4NC43NTMgMTQwLjYwNyw4Ni4wMzMgTDE0MS4xNCw4Ni44NjIgQzE0MS40NTEsODcuMzQ2IDE0MS45NzcsODcuNjEzIDE0Mi41MTYsODcuNjEzIEMxNDIuNzk0LDg3LjYxMyAxNDMuMDc2LDg3LjU0MiAxNDMuMzMzLDg3LjM5MyBMMTY5Ljg2NSw3Mi4wNzYgTDE5Myw4NS40MzMgQzE5My41MjMsODUuNzM1IDE5NC4wNTgsODUuODg4IDE5NC41OSw4NS44ODggQzE5Ni4wODcsODUuODg4IDE5Ny4xNzMsODQuNjg5IDE5Ny4xNzMsODMuMDM2IEwxOTcuMTczLDI5LjAzNSBDMTk3LjE3MywyOC40NTEgMTk2Ljg2MSwyNy45MTEgMTk2LjM1NSwyNy42MTkgQzE5Ni4zNTUsMjcuNjE5IDE3MS44NDMsMTMuNDY3IDE3MC4zODUsMTIuNjI2IEMxNzAuMTMyLDEyLjQ4IDE2OS44NSwxMi40MDcgMTY5LjU2OCwxMi40MDcgQzE2OS4yODUsMTIuNDA3IDE2OS4wMDIsMTIuNDgxIDE2OC43NDksMTIuNjI3IEMxNjguMTQzLDEyLjk3OCAxNjUuNzU2LDE0LjM1NyAxNjQuNDI0LDE1LjEyNSBMMTU5LjYxNSwxMC44NyBDMTU4Ljc5NiwxMC4xNDUgMTU4LjE1NCw4LjkzNyAxNTguMDU0LDcuOTM0IEMxNTguMDQ1LDcuODM3IDE1OC4wMzQsNy43MzkgMTU4LjAyMSw3LjY0IEMxNTguMDA1LDcuNTIzIDE1Ny45OTgsNy40MSAxNTcuOTk4LDcuMzA0IEwxNTcuOTk4LDYuNDE4IEMxNTcuOTk4LDUuODM0IDE1Ny42ODYsNS4yOTUgMTU3LjE4MSw1LjAwMiBDMTU2LjYyNCw0LjY4IDE1MC40NDIsMS4xMTEgMTUwLjQ0MiwxLjExMSBDMTUwLjE4OSwwLjk2NSAxNDkuOTA3LDAuODkyIDE0OS42MjUsMC44OTIiIGlkPSJGaWxsLTEiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTYuMDI3LDI1LjYzNiBMMTQyLjYwMyw1Mi41MjcgQzE0My44MDcsNTMuMjIyIDE0NC41ODIsNTQuMTE0IDE0NC44NDUsNTUuMDY4IEwxNDQuODM1LDU1LjA3NSBMNjMuNDYxLDEwMi4wNTcgTDYzLjQ2LDEwMi4wNTcgQzYxLjgwNiwxMDEuOTA1IDYwLjI2MSwxMDEuNDU3IDU5LjA1NywxMDAuNzYyIEwxMi40ODEsNzMuODcxIEw5Ni4wMjcsMjUuNjM2IiBpZD0iRmlsbC0yIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYzLjQ2MSwxMDIuMTc0IEM2My40NTMsMTAyLjE3NCA2My40NDYsMTAyLjE3NCA2My40MzksMTAyLjE3MiBDNjEuNzQ2LDEwMi4wMTYgNjAuMjExLDEwMS41NjMgNTguOTk4LDEwMC44NjMgTDEyLjQyMiw3My45NzMgQzEyLjM4Niw3My45NTIgMTIuMzY0LDczLjkxNCAxMi4zNjQsNzMuODcxIEMxMi4zNjQsNzMuODMgMTIuMzg2LDczLjc5MSAxMi40MjIsNzMuNzcgTDk1Ljk2OCwyNS41MzUgQzk2LjAwNCwyNS41MTQgOTYuMDQ5LDI1LjUxNCA5Ni4wODUsMjUuNTM1IEwxNDIuNjYxLDUyLjQyNiBDMTQzLjg4OCw1My4xMzQgMTQ0LjY4Miw1NC4wMzggMTQ0Ljk1Nyw1NS4wMzcgQzE0NC45Nyw1NS4wODMgMTQ0Ljk1Myw1NS4xMzMgMTQ0LjkxNSw1NS4xNjEgQzE0NC45MTEsNTUuMTY1IDE0NC44OTgsNTUuMTc0IDE0NC44OTQsNTUuMTc3IEw2My41MTksMTAyLjE1OCBDNjMuNTAxLDEwMi4xNjkgNjMuNDgxLDEwMi4xNzQgNjMuNDYxLDEwMi4xNzQgTDYzLjQ2MSwxMDIuMTc0IFogTTEyLjcxNCw3My44NzEgTDU5LjExNSwxMDAuNjYxIEM2MC4yOTMsMTAxLjM0MSA2MS43ODYsMTAxLjc4MiA2My40MzUsMTAxLjkzNyBMMTQ0LjcwNyw1NS4wMTUgQzE0NC40MjgsNTQuMTA4IDE0My42ODIsNTMuMjg1IDE0Mi41NDQsNTIuNjI4IEw5Ni4wMjcsMjUuNzcxIEwxMi43MTQsNzMuODcxIEwxMi43MTQsNzMuODcxIFoiIGlkPSJGaWxsLTMiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ4LjMyNyw1OC40NzEgQzE0OC4xNDUsNTguNDggMTQ3Ljk2Miw1OC40OCAxNDcuNzgxLDU4LjQ3MiBDMTQ1Ljg4Nyw1OC4zODkgMTQ0LjQ3OSw1Ny40MzQgMTQ0LjYzNiw1Ni4zNCB
2474DMTQ0LjY4OSw1NS45NjcgMTQ0LjY2NCw1NS41OTcgMTQ0LjU2NCw1NS4yMzUgTDYzLjQ2MSwxMDIuMDU3IEM2NC4wODksMTAyLjExNSA2NC43MzMsMTAyLjEzIDY1LjM3OSwxMDIuMDk5IEM2NS41NjEsMTAyLjA5IDY1Ljc0MywxMDIuMDkgNjUuOTI1LDEwMi4wOTggQzY3LjgxOSwxMDIuMTgxIDY5LjIyNywxMDMuMTM2IDY5LjA3LDEwNC4yMyBMMTQ4LjMyNyw1OC40NzEiIGlkPSJGaWxsLTQiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNjkuMDcsMTA0LjM0NyBDNjkuMDQ4LDEwNC4zNDcgNjkuMDI1LDEwNC4zNCA2OS4wMDUsMTA0LjMyNyBDNjguOTY4LDEwNC4zMDEgNjguOTQ4LDEwNC4yNTcgNjguOTU1LDEwNC4yMTMgQzY5LDEwMy44OTYgNjguODk4LDEwMy41NzYgNjguNjU4LDEwMy4yODggQzY4LjE1MywxMDIuNjc4IDY3LjEwMywxMDIuMjY2IDY1LjkyLDEwMi4yMTQgQzY1Ljc0MiwxMDIuMjA2IDY1LjU2MywxMDIuMjA3IDY1LjM4NSwxMDIuMjE1IEM2NC43NDIsMTAyLjI0NiA2NC4wODcsMTAyLjIzMiA2My40NSwxMDIuMTc0IEM2My4zOTksMTAyLjE2OSA2My4zNTgsMTAyLjEzMiA2My4zNDcsMTAyLjA4MiBDNjMuMzM2LDEwMi4wMzMgNjMuMzU4LDEwMS45ODEgNjMuNDAyLDEwMS45NTYgTDE0NC41MDYsNTUuMTM0IEMxNDQuNTM3LDU1LjExNiAxNDQuNTc1LDU1LjExMyAxNDQuNjA5LDU1LjEyNyBDMTQ0LjY0Miw1NS4xNDEgMTQ0LjY2OCw1NS4xNyAxNDQuNjc3LDU1LjIwNCBDMTQ0Ljc4MSw1NS41ODUgMTQ0LjgwNiw1NS45NzIgMTQ0Ljc1MSw1Ni4zNTcgQzE0NC43MDYsNTYuNjczIDE0NC44MDgsNTYuOTk0IDE0NS4wNDcsNTcuMjgyIEMxNDUuNTUzLDU3Ljg5MiAxNDYuNjAyLDU4LjMwMyAxNDcuNzg2LDU4LjM1NSBDMTQ3Ljk2NCw1OC4zNjMgMTQ4LjE0Myw1OC4zNjMgMTQ4LjMyMSw1OC4zNTQgQzE0OC4zNzcsNTguMzUyIDE0OC40MjQsNTguMzg3IDE0OC40MzksNTguNDM4IEMxNDguNDU0LDU4LjQ5IDE0OC40MzIsNTguNTQ1IDE0OC4zODUsNTguNTcyIEw2OS4xMjksMTA0LjMzMSBDNjkuMTExLDEwNC4zNDIgNjkuMDksMTA0LjM0NyA2OS4wNywxMDQuMzQ3IEw2OS4wNywxMDQuMzQ3IFogTTY1LjY2NSwxMDEuOTc1IEM2NS43NTQsMTAxLjk3NSA2NS44NDIsMTAxLjk3NyA2NS45MywxMDEuOTgxIEM2Ny4xOTYsMTAyLjAzNyA2OC4yODMsMTAyLjQ2OSA2OC44MzgsMTAzLjEzOSBDNjkuMDY1LDEwMy40MTMgNjkuMTg4LDEwMy43MTQgNjkuMTk4LDEwNC4wMjEgTDE0Ny44ODMsNTguNTkyIEMxNDcuODQ3LDU4LjU5MiAxNDcuODExLDU4LjU5MSAxNDcuNzc2LDU4LjU4OSBDMTQ2LjUwOSw1OC41MzMgMTQ1LjQyMiw1OC4xIDE0NC44NjcsNTcuNDMxIEMxNDQuNTg1LDU3LjA5MSAxNDQuNDY1LDU2LjcwNyAxNDQuNTIsNTYuMzI0IEMxNDQuNTYzLDU2LjAyMSAxNDQuNTUyLDU1LjcxNiAxNDQuNDg4LDU1LjQxNCBMNjMuODQ2LDEwMS45NyBDNjQuMzUzLDEwMi4wMDIgNjQuODY3LDEwMi4wMDYgNjUuMzc0LDEwMS45ODIgQzY1LjQ3MSwxMDEuOTc3IDY1LjU2OCwxMDEuOTc1IDY1LjY2NSwxMDEuOTc1IEw2NS42NjUsMTAxLjk3NSBaIiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTIuMjA4LDU1LjEzNCBDMS4yMDcsNTMuMzA3IDEuOTY3LDUwLjkxNyAzLjkwNiw0OS43OTcgTDU5LjkxNywxNy40NTMgQzYxLjg1NiwxNi4zMzMgNjQuMjQxLDE2LjkwNyA2NS4yNDMsMTguNzM0IEw2NS40NzUsMTkuMTQ0IEM2NS44NzIsMTkuODgyIDY2LjM2OCwyMC41NiA2Ni45NDUsMjEuMTY1IEw2Ny4yMjMsMjEuNDM1IEM3MC41NDgsMjQuNjQ5IDc1LjgwNiwyNS4xNTEgODAuMTExLDIyLjY2NSBMODcuNDMsMTguNDQ1IEM4OS4zNywxNy4zMjYgOTEuNzU0LDE3Ljg5OSA5Mi43NTUsMTkuNzI3IEw5Ni4wMDUsMjUuNjU1IEwxMi40ODYsNzMuODg0IEwyLjIwOCw1NS4xMzQgWiIgaWQ9IkZpbGwtNiIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMi40ODYsNzQuMDAxIEMxMi40NzYsNzQuMDAxIDEyLjQ2NSw3My45OTkgMTIuNDU1LDczLjk5NiBDMTIuNDI0LDczLjk4OCAxMi4zOTksNzMuOTY3IDEyLjM4NCw3My45NCBMMi4xMDYsNTUuMTkgQzEuMDc1LDUzLjMxIDEuODU3LDUwLjg0NSAzLjg0OCw0OS42OTYgTDU5Ljg1OCwxNy4zNTIgQzYwLjUyNSwxNi45NjcgNjEuMjcxLDE2Ljc2NCA2Mi4wMTYsMTYuNzY0IEM2My40MzEsMTYuNzY0IDY0LjY2NiwxNy40NjYgNjUuMzI3LDE4LjY0NiBDNjUuMzM3LDE4LjY1NCA2NS4zNDUsMTguNjYzIDY1LjM1MSwxOC42NzQgTDY1LjU3OCwxOS4wODggQzY1LjU4NCwxOS4xIDY1LjU4OSwxOS4xMTIgNjUuNTkxLDE5LjEyNiBDNjUuOTg1LDE5LjgzOCA2Ni40NjksMjAuNDk3IDY3LjAzLDIxLjA4NSBMNjcuMzA1LDIxLjM1MSBDNjkuMTUxLDIzLjEzNyA3MS42NDksMjQuMTIgNzQuMzM2LDI0LjEyIEM3Ni4zMTMsMjQuMTIgNzguMjksMjMuNTgyIDgwLjA1MywyMi41NjMgQzgwLjA2NCwyMi41NTcgODAuMDc2LDIyLjU1MyA4MC4wODgsMjIuNTUgTDg3LjM3MiwxOC4zNDQgQzg4LjAzOCwxNy45NTkgODguNzg0LDE3Ljc1NiA4OS41MjksMTcuNzU2IEM5MC45NTYsMTcuNzU2IDkyLjIwMSwxOC40NzIgOTIuODU4LDE5LjY3IEw5Ni4xMDcsMjUuNTk5IEM5Ni4xMzgsMjUuNjU0IDk2LjExOCwyNS43MjQgOTYuMDYzLDI1Ljc1NiBMMTIuNTQ1LDczLjk4NSBDMTIuNTI2LDczLjk5NiAxMi41MDYsNzQuMDAxIDEyLjQ4Niw3NC4wMDEgTDEyLjQ4Niw3NC4wMDEgWiBNNjIuMDE2LDE2Ljk5NyBDNjEuMzEyLDE2Ljk5NyA2MC42MDYsMTcuMTkgNTkuOTc1LDE3LjU1NCBMMy45NjUsNDkuODk5IEMyLjA4Myw1MC45ODUgMS4zNDEsNTMuMzA4IDIuMzEsNTUuMDc4IEwxMi41MzEsNzMuNzIzIEw5NS44NDgsMjUuNjExIEw5Mi42NTMsMTkuNzgyIEM5Mi4wMzgsMTguNjYgOTAuODcsMTcuOTkgODkuNTI5LDE3Ljk5IEM4OC44MjUsMTcuOTkgODguMTE5LDE4LjE4MiA4Ny40ODksMTguNTQ3IEw4MC4xNzIsMjIuNzcyIEM4MC4xNjEsMjIuNzc4IDgwLjE0OSwyMi43ODIgODAuMTM3LDIyLjc4NSBDNzguMzQ2LDIzLjgxMSA3Ni4zNDEsMjQuMzU0IDc0LjMzNiwyNC4zNTQgQzcxLjU4OCwyNC4zNTQgNjkuMDMzLDIzLjM0NyA2Ny4xNDIsMjEuNTE5IEw2Ni44NjQsMjEuMjQ5IEM2Ni4yNzcsMjAuNjM0IDY1Ljc3NCwxOS45NDcgNjUuMzY3LDE5LjIwMyBDNjUuMzYsMTkuMTkyIDY1LjM1NiwxOS4xNzkgNjUuMzU0LDE5LjE2NiBMNjUuMTYzLDE4LjgxOSBDNjUuMTU0LDE4LjgxMSA2NS4xNDYsMTguODAxIDY1LjE0LDE4Ljc5IEM2NC41MjUsMTcuNjY3IDYzLjM1NywxNi45OTcgNjIuMDE2LDE2Ljk5NyBMNjIuMDE2LDE2Ljk5NyBaIiBpZD0iRmlsbC03IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTQyLjQzNCw0OC44MDggTDQyLjQzNCw0OC44MDggQzM5LjkyNCw0OC44MDcgMzcuNzM3LDQ3LjU1IDM2LjU4Miw0NS40NDMgQzM0Ljc3MSw0Mi4xMzkgMzYuMTQ0LDM3LjgwOSAzOS42NDEsMzUuNzg5IEw1MS45MzIsMjguNjkxIEM1My4xMDMsMjguMDE1IDU0LjQxMywyNy42NTggNTUuNzIxLDI3LjY1OCBDNTguMjMxLDI3LjY1OCA2MC40MTgsMjguOTE2IDYxLjU3MywzMS4wMjMgQzYzLjM4NCwzNC4zMjcgNjIuMDEyLDM4LjY1NyA1OC41MTQsNDAuNjc3IEw0Ni4yMjMsNDcuNzc1IEM0NS4wNTMsNDguNDUgNDMuNzQyLDQ4LjgwOCA0Mi40MzQsNDguODA4IEw0Mi40MzQsNDguODA4IFogTTU1LjcyMSwyOC4xMjUgQzU0LjQ5NSwyOC4xMjUgNTMuMjY1LDI4LjQ2MSA1Mi4xNjYsMjkuMDk2IEwzOS44NzUsMzYuMTk0IEMzNi41OTYsMzguMDg3IDM1LjMwMiw0Mi4xMzYgMzYuOTkyLDQ1LjIxOCBDMzguMDYzLDQ3LjE3MyA0MC4wOTgsNDguMzQgNDIuNDM0LDQ4LjM0IEM0My42NjEsNDguMzQgNDQuODksNDguMDA1IDQ1Ljk5LDQ3LjM3IEw1OC4yODEsNDAuMjcyIEM2MS41NiwzOC4zNzkgNjIuODUzLDM0LjMzIDYxLjE2NCwzMS4yNDggQzYwLjA5MiwyOS4yOTMgNTguMDU4LDI4LjEyNSA1NS43MjEsMjguMTI1IEw1NS43MjEsMjguMTI1IFoiIGlkPSJGaWxsLTgiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTQ5LjU4OCwyLjQwNyBDMTQ5LjU4OCwyLjQwNyAxNTUuNzY4LDUuOTc1IDE1Ni4zMjUsNi4yOTcgTDE1Ni4zMjUsNy4xODQgQzE1Ni4zMjUsNy4zNiAxNTYuMzM4LDcuNTQ0IDE1Ni4zNjIsNy43MzMgQzE1Ni4zNzMsNy44MTQgMTU2LjM4Miw3Ljg5NCAxNTYuMzksNy45NzUgQzE1Ni41Myw5LjM5IDE1Ny4zNjMsMTAuOTczIDE1OC40OTUsMTEuOTc0IEwxNjUuODkxLDE4LjUxOSBDMTY2LjA2OCwxOC42NzUgMTY2LjI0OSwxOC44MTQgMTY2LjQzMiwxOC45MzQgQzE2OC4wMTEsMTkuOTc0IDE2OS4zODIsMTkuNCAxNjkuNDk0LDE3LjY1MiBDMTY5LjU0MywxNi44NjggMTY5LjU1MSwxNi4wNTcgMTY5LjUxNywxNS4yMjMgTDE2OS41MTQsMTUuMDYzIEwxNjkuNTE0LDEzLjkxMiBDMTcwLjc4LDE0LjY0MiAxOTUuNTAxLDI4LjkxNSAxOTUuNTAxLDI4LjkxNSBMMTk1LjUwMSw4Mi45MTUgQzE5NS41MDEsODQuMDA1IDE5NC43MzEsODQuNDQ1IDE5My43ODEsODMuODk3IEwxNTEuMzA4LDU5LjM3NCBDMTUwLjM1OCw1OC44MjYgMTQ5LjU4OCw1Ny40OTcgMTQ5LjU4OCw1Ni40MDggTDE0OS41ODgsMjIuMzc1IiBpZD0iRmlsbC05IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE5NC41NTMsODQuMjUgQzE5NC4yOTYsODQuMjUgMTk0LjAxMyw4NC4xNjUgMTkzLjcyMiw4My45OTcgTDE1MS4yNSw1OS40NzYgQzE1MC4yNjksNTguOTA5IDE0OS40NzEsNTcuNTMzIDE0OS40NzEsNTYuNDA4IEwxNDkuNDcxLDIyLjM3NSBMMTQ5LjcwNSwyMi4zNzUgTDE0OS43MDUsNTYuNDA4IEMxNDkuNzA1LDU3LjQ1OSAxNTAuNDUsNTguNzQ0IDE1MS4zNjYsNTkuMjc0IEwxOTMuODM5LDgzLjc5NSBDMTk0LjI2Myw4NC4wNCAxOTQuNjU1LDg0LjA4MyAxOTQuOTQyLDgzLjkxNyBDMTk1LjIyNyw4My43NTMgMTk1LjM4NCw4My4zOTcgMTk1LjM4NCw4Mi45MTUgTDE5NS4zODQsMjguOTgyIEMxOTQuMTAyLDI4LjI0MiAxNzIuMTA0LDE1LjU0MiAxNjkuNjMxLDE0LjExNCBMMTY5LjYzNCwxNS4yMiBDMTY5LjY2OCwxNi4wNTIgMTY5LjY2LDE2Ljg3NCAxNjkuNjEsMTcuNjU5IEMxNjkuNTU2LDE4LjUwMyAxNjkuMjE0LDE
24745LjEyMyAxNjguNjQ3LDE5LjQwNSBDMTY4LjAyOCwxOS43MTQgMTY3LjE5NywxOS41NzggMTY2LjM2NywxOS4wMzIgQzE2Ni4xODEsMTguOTA5IDE2NS45OTUsMTguNzY2IDE2NS44MTQsMTguNjA2IEwxNTguNDE3LDEyLjA2MiBDMTU3LjI1OSwxMS4wMzYgMTU2LjQxOCw5LjQzNyAxNTYuMjc0LDcuOTg2IEMxNTYuMjY2LDcuOTA3IDE1Ni4yNTcsNy44MjcgMTU2LjI0Nyw3Ljc0OCBDMTU2LjIyMSw3LjU1NSAxNTYuMjA5LDcuMzY1IDE1Ni4yMDksNy4xODQgTDE1Ni4yMDksNi4zNjQgQzE1NS4zNzUsNS44ODMgMTQ5LjUyOSwyLjUwOCAxNDkuNTI5LDIuNTA4IEwxNDkuNjQ2LDIuMzA2IEMxNDkuNjQ2LDIuMzA2IDE1NS44MjcsNS44NzQgMTU2LjM4NCw2LjE5NiBMMTU2LjQ0Miw2LjIzIEwxNTYuNDQyLDcuMTg0IEMxNTYuNDQyLDcuMzU1IDE1Ni40NTQsNy41MzUgMTU2LjQ3OCw3LjcxNyBDMTU2LjQ4OSw3LjggMTU2LjQ5OSw3Ljg4MiAxNTYuNTA3LDcuOTYzIEMxNTYuNjQ1LDkuMzU4IDE1Ny40NTUsMTAuODk4IDE1OC41NzIsMTEuODg2IEwxNjUuOTY5LDE4LjQzMSBDMTY2LjE0MiwxOC41ODQgMTY2LjMxOSwxOC43MiAxNjYuNDk2LDE4LjgzNyBDMTY3LjI1NCwxOS4zMzYgMTY4LDE5LjQ2NyAxNjguNTQzLDE5LjE5NiBDMTY5LjAzMywxOC45NTMgMTY5LjMyOSwxOC40MDEgMTY5LjM3NywxNy42NDUgQzE2OS40MjcsMTYuODY3IDE2OS40MzQsMTYuMDU0IDE2OS40MDEsMTUuMjI4IEwxNjkuMzk3LDE1LjA2NSBMMTY5LjM5NywxMy43MSBMMTY5LjU3MiwxMy44MSBDMTcwLjgzOSwxNC41NDEgMTk1LjU1OSwyOC44MTQgMTk1LjU1OSwyOC44MTQgTDE5NS42MTgsMjguODQ3IEwxOTUuNjE4LDgyLjkxNSBDMTk1LjYxOCw4My40ODQgMTk1LjQyLDgzLjkxMSAxOTUuMDU5LDg0LjExOSBDMTk0LjkwOCw4NC4yMDYgMTk0LjczNyw4NC4yNSAxOTQuNTUzLDg0LjI1IiBpZD0iRmlsbC0xMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDUuNjg1LDU2LjE2MSBMMTY5LjgsNzAuMDgzIEwxNDMuODIyLDg1LjA4MSBMMTQyLjM2LDg0Ljc3NCBDMTM1LjgyNiw4Mi42MDQgMTI4LjczMiw4MS4wNDYgMTIxLjM0MSw4MC4xNTggQzExNi45NzYsNzkuNjM0IDExMi42NzgsODEuMjU0IDExMS43NDMsODMuNzc4IEMxMTEuNTA2LDg0LjQxNCAxMTEuNTAzLDg1LjA3MSAxMTEuNzMyLDg1LjcwNiBDMTEzLjI3LDg5Ljk3MyAxMTUuOTY4LDk0LjA2OSAxMTkuNzI3LDk3Ljg0MSBMMTIwLjI1OSw5OC42ODYgQzEyMC4yNiw5OC42ODUgOTQuMjgyLDExMy42ODMgOTQuMjgyLDExMy42ODMgTDcwLjE2Nyw5OS43NjEgTDE0NS42ODUsNTYuMTYxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik05NC4yODIsMTEzLjgxOCBMOTQuMjIzLDExMy43ODUgTDY5LjkzMyw5OS43NjEgTDcwLjEwOCw5OS42NiBMMTQ1LjY4NSw1Ni4wMjYgTDE0NS43NDMsNTYuMDU5IEwxNzAuMDMzLDcwLjA4MyBMMTQzLjg0Miw4NS4yMDUgTDE0My43OTcsODUuMTk1IEMxNDMuNzcyLDg1LjE5IDE0Mi4zMzYsODQuODg4IDE0Mi4zMzYsODQuODg4IEMxMzUuNzg3LDgyLjcxNCAxMjguNzIzLDgxLjE2MyAxMjEuMzI3LDgwLjI3NCBDMTIwLjc4OCw4MC4yMDkgMTIwLjIzNiw4MC4xNzcgMTE5LjY4OSw4MC4xNzcgQzExNS45MzEsODAuMTc3IDExMi42MzUsODEuNzA4IDExMS44NTIsODMuODE5IEMxMTEuNjI0LDg0LjQzMiAxMTEuNjIxLDg1LjA1MyAxMTEuODQyLDg1LjY2NyBDMTEzLjM3Nyw4OS45MjUgMTE2LjA1OCw5My45OTMgMTE5LjgxLDk3Ljc1OCBMMTE5LjgyNiw5Ny43NzkgTDEyMC4zNTIsOTguNjE0IEMxMjAuMzU0LDk4LjYxNyAxMjAuMzU2LDk4LjYyIDEyMC4zNTgsOTguNjI0IEwxMjAuNDIyLDk4LjcyNiBMMTIwLjMxNyw5OC43ODcgQzEyMC4yNjQsOTguODE4IDk0LjU5OSwxMTMuNjM1IDk0LjM0LDExMy43ODUgTDk0LjI4MiwxMTMuODE4IEw5NC4yODIsMTEzLjgxOCBaIE03MC40MDEsOTkuNzYxIEw5NC4yODIsMTEzLjU0OSBMMTE5LjA4NCw5OS4yMjkgQzExOS42Myw5OC45MTQgMTE5LjkzLDk4Ljc0IDEyMC4xMDEsOTguNjU0IEwxMTkuNjM1LDk3LjkxNCBDMTE1Ljg2NCw5NC4xMjcgMTEzLjE2OCw5MC4wMzMgMTExLjYyMiw4NS43NDYgQzExMS4zODIsODUuMDc5IDExMS4zODYsODQuNDA0IDExMS42MzMsODMuNzM4IEMxMTIuNDQ4LDgxLjUzOSAxMTUuODM2LDc5Ljk0MyAxMTkuNjg5LDc5Ljk0MyBDMTIwLjI0Niw3OS45NDMgMTIwLjgwNiw3OS45NzYgMTIxLjM1NSw4MC4wNDIgQzEyOC43NjcsODAuOTMzIDEzNS44NDYsODIuNDg3IDE0Mi4zOTYsODQuNjYzIEMxNDMuMjMyLDg0LjgzOCAxNDMuNjExLDg0LjkxNyAxNDMuNzg2LDg0Ljk2NyBMMTY5LjU2Niw3MC4wODMgTDE0NS42ODUsNTYuMjk1IEw3MC40MDEsOTkuNzYxIEw3MC40MDEsOTkuNzYxIFoiIGlkPSJGaWxsLTEyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2Ny4yMywxOC45NzkgTDE2Ny4yMyw2OS44NSBMMTM5LjkwOSw4NS42MjMgTDEzMy40NDgsNzEuNDU2IEMxMzIuNTM4LDY5LjQ2IDEzMC4wMiw2OS43MTggMTI3LjgyNCw3Mi4wMyBDMTI2Ljc2OSw3My4xNCAxMjUuOTMxLDc0LjU4NSAxMjUuNDk0LDc2LjA0OCBMMTE5LjAzNCw5Ny42NzYgTDkxLjcxMiwxMTMuNDUgTDkxLjcxMiw2Mi41NzkgTDE2Ny4yMywxOC45NzkiIGlkPSJGaWxsLTEzIiBmaWxsPSIjRkZGRkZGIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTkxLjcxMiwxMTMuNTY3IEM5MS42OTIsMTEzLjU2NyA5MS42NzIsMTEzLjU2MSA5MS42NTMsMTEzLjU1MSBDOTEuNjE4LDExMy41MyA5MS41OTUsMTEzLjQ5MiA5MS41OTUsMTEzLjQ1IEw5MS41OTUsNjIuNTc5IEM5MS41OTUsNjIuNTM3IDkxLjYxOCw2Mi40OTkgOTEuNjUzLDYyLjQ3OCBMMTY3LjE3MiwxOC44NzggQzE2Ny4yMDgsMTguODU3IDE2Ny4yNTIsMTguODU3IDE2Ny4yODgsMTguODc4IEMxNjcuMzI0LDE4Ljg5OSAxNjcuMzQ3LDE4LjkzNyAxNjcuMzQ3LDE4Ljk3OSBMMTY3LjM0Nyw2OS44NSBDMTY3LjM0Nyw2OS44OTEgMTY3LjMyNCw2OS45MyAxNjcuMjg4LDY5Ljk1IEwxMzkuOTY3LDg1LjcyNSBDMTM5LjkzOSw4NS43NDEgMTM5LjkwNSw4NS43NDUgMTM5Ljg3Myw4NS43MzUgQzEzOS44NDIsODUuNzI1IDEzOS44MTYsODUuNzAyIDEzOS44MDIsODUuNjcyIEwxMzMuMzQyLDcxLjUwNCBDMTMyLjk2Nyw3MC42ODIgMTMyLjI4LDcwLjIyOSAxMzEuNDA4LDcwLjIyOSBDMTMwLjMxOSw3MC4yMjkgMTI5LjA0NCw3MC45MTUgMTI3LjkwOCw3Mi4xMSBDMTI2Ljg3NCw3My4yIDEyNi4wMzQsNzQuNjQ3IDEyNS42MDYsNzYuMDgyIEwxMTkuMTQ2LDk3LjcwOSBDMTE5LjEzNyw5Ny43MzggMTE5LjExOCw5Ny43NjIgMTE5LjA5Miw5Ny43NzcgTDkxLjc3LDExMy41NTEgQzkxLjc1MiwxMTMuNTYxIDkxLjczMiwxMTMuNTY3IDkxLjcxMiwxMTMuNTY3IEw5MS43MTIsMTEzLjU2NyBaIE05MS44MjksNjIuNjQ3IEw5MS44MjksMTEzLjI0OCBMMTE4LjkzNSw5Ny41OTggTDEyNS4zODIsNzYuMDE1IEMxMjUuODI3LDc0LjUyNSAxMjYuNjY0LDczLjA4MSAxMjcuNzM5LDcxLjk1IEM
2474xMjguOTE5LDcwLjcwOCAxMzAuMjU2LDY5Ljk5NiAxMzEuNDA4LDY5Ljk5NiBDMTMyLjM3Nyw2OS45OTYgMTMzLjEzOSw3MC40OTcgMTMzLjU1NCw3MS40MDcgTDEzOS45NjEsODUuNDU4IEwxNjcuMTEzLDY5Ljc4MiBMMTY3LjExMywxOS4xODEgTDkxLjgyOSw2Mi42NDcgTDkxLjgyOSw2Mi42NDcgWiIgaWQ9IkZpbGwtMTQiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTY4LjU0MywxOS4yMTMgTDE2OC41NDMsNzAuMDgzIEwxNDEuMjIxLDg1Ljg1NyBMMTM0Ljc2MSw3MS42ODkgQzEzMy44NTEsNjkuNjk0IDEzMS4zMzMsNjkuOTUxIDEyOS4xMzcsNzIuMjYzIEMxMjguMDgyLDczLjM3NCAxMjcuMjQ0LDc0LjgxOSAxMjYuODA3LDc2LjI4MiBMMTIwLjM0Niw5Ny45MDkgTDkzLjAyNSwxMTMuNjgzIEw5My4wMjUsNjIuODEzIEwxNjguNTQzLDE5LjIxMyIgaWQ9IkZpbGwtMTUiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTMuMDI1LDExMy44IEM5My4wMDUsMTEzLjggOTIuOTg0LDExMy43OTUgOTIuOTY2LDExMy43ODUgQzkyLjkzMSwxMTMuNzY0IDkyLjkwOCwxMTMuNzI1IDkyLjkwOCwxMTMuNjg0IEw5Mi45MDgsNjIuODEzIEM5Mi45MDgsNjIuNzcxIDkyLjkzMSw2Mi43MzMgOTIuOTY2LDYyLjcxMiBMMTY4LjQ4NCwxOS4xMTIgQzE2OC41MiwxOS4wOSAxNjguNTY1LDE5LjA5IDE2OC42MDEsMTkuMTEyIEMxNjguNjM3LDE5LjEzMiAxNjguNjYsMTkuMTcxIDE2OC42NiwxOS4yMTIgTDE2OC42Niw3MC4wODMgQzE2OC42Niw3MC4xMjUgMTY4LjYzNyw3MC4xNjQgMTY4LjYwMSw3MC4xODQgTDE0MS4yOCw4NS45NTggQzE0MS4yNTEsODUuOTc1IDE0MS4yMTcsODUuOTc5IDE0MS4xODYsODUuOTY4IEMxNDEuMTU0LDg1Ljk1OCAxNDEuMTI5LDg1LjkzNiAxNDEuMTE1LDg1LjkwNiBMMTM0LjY1NSw3MS43MzggQzEzNC4yOCw3MC45MTUgMTMzLjU5Myw3MC40NjMgMTMyLjcyLDcwLjQ2MyBDMTMxLjYzMiw3MC40NjMgMTMwLjM1Nyw3MS4xNDggMTI5LjIyMSw3Mi4zNDQgQzEyOC4xODYsNzMuNDMzIDEyNy4zNDcsNzQuODgxIDEyNi45MTksNzYuMzE1IEwxMjAuNDU4LDk3Ljk0MyBDMTIwLjQ1LDk3Ljk3MiAxMjAuNDMxLDk3Ljk5NiAxMjAuNDA1LDk4LjAxIEw5My4wODMsMTEzLjc4NSBDOTMuMDY1LDExMy43OTUgOTMuMDQ1LDExMy44IDkzLjAyNSwxMTMuOCBMOTMuMDI1LDExMy44IFogTTkzLjE0Miw2Mi44ODEgTDkzLjE0MiwxMTMuNDgxIEwxMjAuMjQ4LDk3LjgzMiBMMTI2LjY5NSw3Ni4yNDggQzEyNy4xNCw3NC43NTggMTI3Ljk3Nyw3My4zMTUgMTI5LjA1Miw3Mi4xODMgQzEzMC4yMzEsNzAuOTQyIDEzMS41NjgsNzAuMjI5IDEzMi43Miw3MC4yMjkgQzEzMy42ODksNzAuMjI5IDEzNC40NTIsNzAuNzMxIDEzNC44NjcsNzEuNjQxIEwxNDEuMjc0LDg1LjY5MiBMMTY4LjQyNiw3MC4wMTYgTDE2OC40MjYsMTkuNDE1IEw5My4xNDIsNjIuODgxIEw5My4xNDIsNjIuODgxIFoiIGlkPSJGaWxsLTE2IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS44LDcwLjA4MyBMMTQyLjQ3OCw4NS44NTcgTDEzNi4wMTgsNzEuNjg5IEMxMzUuMTA4LDY5LjY5NCAxMzIuNTksNjkuOTUxIDEzMC4zOTMsNzIuMjYzIEMxMjkuMzM5LDczLjM3NCAxMjguNSw3NC44MTkgMTI4LjA2NCw3Ni4yODIgTDEyMS42MDMsOTcuOTA5IEw5NC4yODIsMTEzLjY4MyBMOTQuMjgyLDYyLjgxMyBMMTY5LjgsMTkuMjEzIEwxNjkuOCw3MC4wODMgWiIgaWQ9IkZpbGwtMTciIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNOTQuMjgyLDExMy45MTcgQzk0LjI0MSwxMTMuOTE3IDk0LjIwMSwxMTMuOTA3IDk0LjE2NSwxMTMuODg2IEM5NC4wOTMsMTEzLjg0NSA5NC4wNDgsMTEzLjc2NyA5NC4wNDgsMTEzLjY4NCBMOTQuMDQ4LDYyLjgxMyBDOTQuMDQ4LDYyLjczIDk0LjA5Myw2Mi42NTIgOTQuMTY1LDYyLjYxMSBMMTY5LjY4MywxOS4wMSBDMTY5Ljc1NSwxOC45NjkgMTY5Ljg0NCwxOC45NjkgMTY5LjkxNywxOS4wMSBDMTY5Ljk4OSwxOS4wNTIgMTcwLjAzMywxOS4xMjkgMTcwLjAzMywxOS4yMTIgTDE3MC4wMzMsNzAuMDgzIEMxNzAuMDMzLDcwLjE2NiAxNjkuOTg5LDcwLjI0NCAxNjkuOTE3LDcwLjI4NSBMMTQyLjU5NSw4Ni4wNiBDMTQyLjUzOCw4Ni4wOTIgMTQyLjQ2OSw4Ni4xIDE0Mi40MDcsODYuMDggQzE0Mi4zNDQsODYuMDYgMTQyLjI5Myw4Ni4wMTQgMTQyLjI2Niw4NS45NTQgTDEzNS44MDUsNzEuNzg2IEMxMzUuNDQ1LDcwLjk5NyAxMzQuODEzLDcwLjU4IDEzMy45NzcsNzAuNTggQzEzMi45MjEsNzAuNTggMTMxLjY3Niw3MS4yNTIgMTMwLjU2Miw3Mi40MjQgQzEyOS41NCw3My41MDEgMTI4LjcxMSw3NC45MzEgMTI4LjI4Nyw3Ni4zNDggTDEyMS44MjcsOTcuOTc2IEMxMjEuODEsOTguMDM0IDEyMS43NzEsOTguMDgyIDEyMS43Miw5OC4xMTIgTDk0LjM5OCwxMTMuODg2IEM5NC4zNjIsMTEzLjkwNyA5NC4zMjIsMTEzLjkxNyA5NC4yODIsMTEzLjkxNyBMOTQuMjgyLDExMy45MTcgWiBNOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDExMy4yNzkgTDEyMS40MDYsOTcuNzU0IEwxMjcuODQsNzYuMjE1IEMxMjguMjksNzQuNzA4IDEyOS4xMzcsNzMuMjQ3IDEzMC4yMjQsNzIuMTAzIEMxMzEuNDI1LDcwLjgzOCAxMzIuNzkzLDcwLjExMiAxMzMuOTc3LDcwLjExMiBDMTM0Ljk5NSw3MC4xMTIgMTM1Ljc5NSw3MC42MzggMTM2LjIzLDcxLjU5MiBMMTQyLjU4NCw4NS41MjYgTDE2OS41NjYsNjkuOTQ4IEwxNjkuNTY2LDE5LjYxNyBMOTQuNTE1LDYyLjk0OCBMOTQuNTE1LDYyLjk0OCBaIiBpZD0iRmlsbC0xOCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMDkuODk0LDkyLjk0MyBMMTA5Ljg5NCw5Mi45NDMgQzEwOC4xMiw5Mi45NDMgMTA2LjY1Myw5Mi4yMTggMTA1LjY1LDkwLjgyMyBDMTA1LjU4Myw5MC43MzEgMTA1LjU5Myw5MC42MSAxMDUuNjczLDkwLjUyOSBDMTA1Ljc1Myw5MC40NDggMTA1Ljg4LDkwLjQ0IDEwNS45NzQsOTAuNTA2IEMxMDYuNzU0LDkxLjA1MyAxMDcuNjc5LDkxLjMzMyAxMDguNzI0LDkxLjMzMyBDMTEwLjA0Nyw5MS4zMzMgMTExLjQ3OCw5MC44OTQgMTEyLjk4LDkwLjAyNyBDMTE4LjI5MSw4Ni45NiAxMjIuNjExLDc5LjUwOSAxMjIuNjExLDczLjQxNiBDMTIyLjYxMSw3MS40ODkgMTIyLjE2OSw2OS44NTYgMTIxLjMzMyw2OC42OTIgQzEyMS4yNjYsNjguNiAxMjEuMjc2LDY4LjQ3MyAxMjEuMzU2LDY4LjM5MiBDMTIxLjQzNiw2OC4zMTEgMTIxLjU2Myw2OC4yOTkgMTIxLjY1Niw2OC4zNjUgQzEyMy4zMjcsNjkuNTM3IDEyNC4yNDcsNzEuNzQ2IDEyNC4yNDcsNzQuNTg0IEMxMjQuMjQ3LDgwLjgyNiAxMTkuODIxLDg4LjQ0NyAxMTQuMzgyLDkxLjU4NyBDMTEyLjgwOCw5Mi40OTUgMTExLjI5OCw5Mi45NDMgMTA5Ljg5NCw5Mi45NDMgTDEwOS44OTQsOTIuOTQzIFogTTEwNi45MjUsOTEuNDAxIEMxMDcuNzM4LDkyLjA1MiAxMDguNzQ1LDkyLjI3OCAxMDkuODkzLDkyLjI3OCBMMTA5Ljg5NCw5Mi4yNzggQzExMS4y
2474MTUsOTIuMjc4IDExMi42NDcsOTEuOTUxIDExNC4xNDgsOTEuMDg0IEMxMTkuNDU5LDg4LjAxNyAxMjMuNzgsODAuNjIxIDEyMy43OCw3NC41MjggQzEyMy43OCw3Mi41NDkgMTIzLjMxNyw3MC45MjkgMTIyLjQ1NCw2OS43NjcgQzEyMi44NjUsNzAuODAyIDEyMy4wNzksNzIuMDQyIDEyMy4wNzksNzMuNDAyIEMxMjMuMDc5LDc5LjY0NSAxMTguNjUzLDg3LjI4NSAxMTMuMjE0LDkwLjQyNSBDMTExLjY0LDkxLjMzNCAxMTAuMTMsOTEuNzQyIDEwOC43MjQsOTEuNzQyIEMxMDguMDgzLDkxLjc0MiAxMDcuNDgxLDkxLjU5MyAxMDYuOTI1LDkxLjQwMSBMMTA2LjkyNSw5MS40MDEgWiIgaWQ9IkZpbGwtMTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjA5Nyw5MC4yMyBDMTE4LjQ4MSw4Ny4xMjIgMTIyLjg0NSw3OS41OTQgMTIyLjg0NSw3My40MTYgQzEyMi44NDUsNzEuMzY1IDEyMi4zNjIsNjkuNzI0IDEyMS41MjIsNjguNTU2IEMxMTkuNzM4LDY3LjMwNCAxMTcuMTQ4LDY3LjM2MiAxMTQuMjY1LDY5LjAyNiBDMTA4Ljg4MSw3Mi4xMzQgMTA0LjUxNyw3OS42NjIgMTA0LjUxNyw4NS44NCBDMTA0LjUxNyw4Ny44OTEgMTA1LDg5LjUzMiAxMDUuODQsOTAuNyBDMTA3LjYyNCw5MS45NTIgMTEwLjIxNCw5MS44OTQgMTEzLjA5Nyw5MC4yMyIgaWQ9IkZpbGwtMjAiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTA4LjcyNCw5MS42MTQgTDEwOC43MjQsOTEuNjE0IEMxMDcuNTgyLDkxLjYxNCAxMDYuNTY2LDkxLjQwMSAxMDUuNzA1LDkwLjc5NyBDMTA1LjY4NCw5MC43ODMgMTA1LjY2NSw5MC44MTEgMTA1LjY1LDkwLjc5IEMxMDQuNzU2LDg5LjU0NiAxMDQuMjgzLDg3Ljg0MiAxMDQuMjgzLDg1LjgxNyBDMTA0LjI4Myw3OS41NzUgMTA4LjcwOSw3MS45NTMgMTE0LjE0OCw2OC44MTIgQzExNS43MjIsNjcuOTA0IDExNy4yMzIsNjcuNDQ5IDExOC42MzgsNjcuNDQ5IEMxMTkuNzgsNjcuNDQ5IDEyMC43OTYsNjcuNzU4IDEyMS42NTYsNjguMzYyIEMxMjEuNjc4LDY4LjM3NyAxMjEuNjk3LDY4LjM5NyAxMjEuNzEyLDY4LjQxOCBDMTIyLjYwNiw2OS42NjIgMTIzLjA3OSw3MS4zOSAxMjMuMDc5LDczLjQxNSBDMTIzLjA3OSw3OS42NTggMTE4LjY1Myw4Ny4xOTggMTEzLjIxNCw5MC4zMzggQzExMS42NCw5MS4yNDcgMTEwLjEzLDkxLjYxNCAxMDguNzI0LDkxLjYxNCBMMTA4LjcyNCw5MS42MTQgWiBNMTA2LjAwNiw5MC41MDUgQzEwNi43OCw5MS4wMzcgMTA3LjY5NCw5MS4yODEgMTA4LjcyNCw5MS4yODEgQzExMC4wNDcsOTEuMjgxIDExMS40NzgsOTAuODY4IDExMi45OCw5MC4wMDEgQzExOC4yOTEsODYuOTM1IDEyMi42MTEsNzkuNDk2IDEyMi42MTEsNzMuNDAzIEMxMjIuNjExLDcxLjQ5NCAxMjIuMTc3LDY5Ljg4IDEyMS4zNTYsNjguNzE4IEMxMjAuNTgyLDY4LjE4NSAxMTkuNjY4LDY3LjkxOSAxMTguNjM4LDY3LjkxOSBDMTE3LjMxNSw2Ny45MTkgMTE1Ljg4Myw2OC4zNiAxMTQuMzgyLDY5LjIyNyBDMTA5LjA3MSw3Mi4yOTMgMTA0Ljc1MSw3OS43MzMgMTA0Ljc1MSw4NS44MjYgQzEwNC43NTEsODcuNzM1IDEwNS4xODUsODkuMzQzIDEwNi4wMDYsOTAuNTA1IEwxMDYuMDA2LDkwLjUwNSBaIiBpZD0iRmlsbC0yMSIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNDkuMzE4LDcuMjYyIEwxMzkuMzM0LDE2LjE0IEwxNTUuMjI3LDI3LjE3MSBMMTYwLjgxNiwyMS4wNTkgTDE0OS4zMTgsNy4yNjIiIGlkPSJGaWxsLTIyIiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE2OS42NzYsMTMuODQgTDE1OS45MjgsMTkuNDY3IEMxNTYuMjg2LDIxLjU3IDE1MC40LDIxLjU4IDE0Ni43ODEsMTkuNDkxIEMxNDMuMTYxLDE3LjQwMiAxNDMuMTgsMTQuMDAzIDE0Ni44MjIsMTEuOSBMMTU2LjMxNyw2LjI5MiBMMTQ5LjU4OCwyLjQwNyBMNjcuNzUyLDQ5LjQ3OCBMMTEzLjY3NSw3NS45OTIgTDExNi43NTYsNzQuMjEzIEMxMTcuMzg3LDczLjg0OCAxMTcuNjI1LDczLjMxNSAxMTcuMzc0LDcyLjgyMyBDMTE1LjAxNyw2OC4xOTEgMTE0Ljc4MSw2My4yNzcgMTE2LjY5MSw1OC41NjEgQzEyMi4zMjksNDQuNjQxIDE0MS4yLDMzLjc0NiAxNjUuMzA5LDMwLjQ5MSBDMTczLjQ3OCwyOS4zODggMTgxLjk4OSwyOS41MjQgMTkwLjAxMywzMC44ODUgQzE5MC44NjUsMzEuMDMgMTkxLjc4OSwzMC44OTMgMTkyLjQyLDMwLjUyOCBMMTk1LjUwMSwyOC43NSBMMTY5LjY3NiwxMy44NCIgaWQ9IkZpbGwtMjMiIGZpbGw9IiNGQUZBRkEiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3Ni40NTkgQzExMy41OTQsNzYuNDU5IDExMy41MTQsNzYuNDM4IDExMy40NDIsNzYuMzk3IEw2Ny41MTgsNDkuODgyIEM2Ny4zNzQsNDkuNzk5IDY3LjI4NCw0OS42NDUgNjcuMjg1LDQ5LjQ3OCBDNjcuMjg1LDQ5LjMxMSA2Ny4zNzQsNDkuMTU3IDY3LjUxOSw0OS4wNzMgTDE0OS4zNTUsMi4wMDIgQzE0OS40OTksMS45MTkgMTQ5LjY3NywxLjkxOSAxNDkuODIxLDIuMDAyIEwxNTYuNTUsNS44ODcgQzE1Ni43NzQsNi4wMTcgMTU2Ljg1LDYuMzAyIDE1Ni43MjIsNi41MjYgQzE1Ni41OTIsNi43NDkgMTU2LjMwNyw2LjgyNiAxNTYuMDgzLDYuNjk2IEwxNDkuNTg3LDIuOTQ2IEw2OC42ODcsNDkuNDc5IEwxMTMuNjc1LDc1LjQ1MiBMMTE2LjUyMyw3My44MDggQzExNi43MTUsNzMuNjk3IDExNy4xNDMsNzMuMzk5IDExNi45NTgsNzMuMDM1IEMxMTQuNTQyLDY4LjI4NyAxMTQuMyw2My4yMjEgMTE2LjI1OCw1OC4zODUgQzExOS4wNjQsNTEuNDU4IDEyNS4xNDMsNDUuMTQzIDEzMy44NCw0MC4xMjIgQzE0Mi40OTcsMzUuMTI0IDE1My4zNTgsMzEuNjMzIDE2NS4yNDcsMzAuMDI4IEMxNzMuNDQ1LDI4LjkyMSAxODIuMDM3LDI5LjA1OCAxOTAuMDkxLDMwLjQyNSBDMTkwLjgzLDMwLjU1IDE5MS42NTIsMzAuNDMyIDE5Mi4xODYsMzAuMTI0IEwxOTQuNTY3LDI4Ljc1IEwxNjkuNDQyLDE0LjI0NCBDMTY5LjIxOSwxNC4xMTUgMTY5LjE0MiwxMy44MjkgMTY5LjI3MSwxMy42MDYgQzE2OS40LDEzLjM4MiAxNjkuNjg1LDEzLjMwNiAxNjkuOTA5LDEzLjQzNSBMMTk1LjczNCwyOC4zNDUgQzE5NS44NzksMjguNDI4IDE5NS45NjgsMjguNTgzIDE5NS45NjgsMjguNzUgQzE5NS45NjgsMjguOTE2IDE5NS44NzksMjkuMDcxIDE5NS43MzQsMjkuMTU0IEwxOTIuNjUzLDMwLjkzMyBDMTkxLjkzMiwzMS4zNSAxOTAuODksMzEuNTA4IDE4OS45MzUsMzEuMzQ2IEMxODEuOTcyLDI5Ljk5NSAxNzMuNDc4LDI5Ljg2IDE2NS4zNzIsMzAuOTU0IEMxNTMuNjAyLDMyLjU0MyAxNDIuODYsMzUuOTkzIDEzNC4zMDcsNDAuOTMxIEMxMjUuNzkzLDQ1Ljg0NyAxMTkuODUxLDUyLjAwNCAxMTcuMTI0LDU4LjczNiBDMTE1LjI3LDYzLjMxNCAxMTUuNTAxLDY4LjExMiAxMTcuNzksNzIuNjExIEMxMTguMTYsNzMuMzM2IDExNy44NDUsNzQuMTI0IDExNi45OSw3NC42MTcgTDExMy45MDksNzYuMzk3IEMxMTMuODM2LDc2LjQzOCAxMTMuNzU2LDc2LjQ1OSAxMTMuNjc1LDc2LjQ1OSIgaWQ9IkZpbGwtMjQiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUzLjMxNiwyMS4yNzkgQzE1MC45MDMsMjEuMjc5IDE0OC40OTUsMjAuNzUxIDE0Ni42NjQsMTkuNjkzIEMxNDQuODQ2LDE4LjY0NCAxNDMuODQ0LDE3LjIzMiAxNDMuODQ0LDE1LjcxOCBDMTQzLjg0NCwxNC4xOTEgMTQ0Ljg2LDEyLjc2MyAxNDYuNzA1LDExLjY5OCBMMTU2LjE5OCw2LjA5MSBDMTU2LjMwOSw2LjAyNSAxNTYuNDUyLDYuMDYyIDE1Ni41MTgsNi4xNzMgQzE1Ni41ODMsNi4yODQgMTU2LjU0Nyw2LjQyNyAxNTYuNDM2LDYuNDkzIEwxNDYuOTQsMTIuMTAyIEMxNDUuMjQ0LDEzLjA4MSAxNDQuMzEyLDE0LjM2NSAxNDQuMzEyLDE1LjcxOCBDMTQ0LjMxMiwxNy4wNTggMTQ1LjIzL
2474DE4LjMyNiAxNDYuODk3LDE5LjI4OSBDMTUwLjQ0NiwyMS4zMzggMTU2LjI0LDIxLjMyNyAxNTkuODExLDE5LjI2NSBMMTY5LjU1OSwxMy42MzcgQzE2OS42NywxMy41NzMgMTY5LjgxMywxMy42MTEgMTY5Ljg3OCwxMy43MjMgQzE2OS45NDMsMTMuODM0IDE2OS45MDQsMTMuOTc3IDE2OS43OTMsMTQuMDQyIEwxNjAuMDQ1LDE5LjY3IEMxNTguMTg3LDIwLjc0MiAxNTUuNzQ5LDIxLjI3OSAxNTMuMzE2LDIxLjI3OSIgaWQ9IkZpbGwtMjUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEzLjY3NSw3NS45OTIgTDY3Ljc2Miw0OS40ODQiIGlkPSJGaWxsLTI2IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMy42NzUsNzYuMzQyIEMxMTMuNjE1LDc2LjM0MiAxMTMuNTU1LDc2LjMyNyAxMTMuNSw3Ni4yOTUgTDY3LjU4Nyw0OS43ODcgQzY3LjQxOSw0OS42OSA2Ny4zNjIsNDkuNDc2IDY3LjQ1OSw0OS4zMDkgQzY3LjU1Niw0OS4xNDEgNjcuNzcsNDkuMDgzIDY3LjkzNyw0OS4xOCBMMTEzLjg1LDc1LjY4OCBDMTE0LjAxOCw3NS43ODUgMTE0LjA3NSw3NiAxMTMuOTc4LDc2LjE2NyBDMTEzLjkxNCw3Ni4yNzkgMTEzLjc5Niw3Ni4zNDIgMTEzLjY3NSw3Ni4zNDIiIGlkPSJGaWxsLTI3IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY3Ljc2Miw0OS40ODQgTDY3Ljc2MiwxMDMuNDg1IEM2Ny43NjIsMTA0LjU3NSA2OC41MzIsMTA1LjkwMyA2OS40ODIsMTA2LjQ1MiBMMTExLjk1NSwxMzAuOTczIEMxMTIuOTA1LDEzMS41MjIgMTEzLjY3NSwxMzEuMDgzIDExMy42NzUsMTI5Ljk5MyBMMTEzLjY3NSw3NS45OTIiIGlkPSJGaWxsLTI4IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTExMi43MjcsMTMxLjU2MSBDMTEyLjQzLDEzMS41NjEgMTEyLjEwNywxMzEuNDY2IDExMS43OCwxMzEuMjc2IEw2OS4zMDcsMTA2Ljc1NSBDNjguMjQ0LDEwNi4xNDIgNjcuNDEyLDEwNC43MDUgNjcuNDEyLDEwMy40ODUgTDY3LjQxMiw0OS40ODQgQzY3LjQxMiw0OS4yOSA2Ny41NjksNDkuMTM0IDY3Ljc2Miw0OS4xMzQgQzY3Ljk1Niw0OS4xMzQgNjguMTEzLDQ5LjI5IDY4LjExMyw0OS40ODQgTDY4LjExMywxMDMuNDg1IEM2OC4xMTMsMTA0LjQ0NSA2OC44MiwxMDUuNjY1IDY5LjY1NywxMDYuMTQ4IEwxMTIuMTMsMTMwLjY3IEMxMTIuNDc0LDEzMC44NjggMTEyLjc5MSwxMzAuOTEzIDExMywxMzAuNzkyIEMxMTMuMjA2LDEzMC42NzMgMTEzLjMyNSwxMzAuMzgxIDExMy4zMjUsMTI5Ljk5MyBMMTEzLjMyNSw3NS45OTIgQzExMy4zMjUsNzUuNzk4IDExMy40ODIsNzUuNjQxIDExMy42NzUsNzUuNjQxIEMxMTMuODY5LDc1LjY0MSAxMTQuMDI1LDc1Ljc5OCAxMTQuMDI1LDc1Ljk5MiBMMTE0LjAyNSwxMjkuOTkzIEMxMTQuMDI1LDEzMC42NDggMTEzLjc4NiwxMzEuMTQ3IDExMy4zNSwxMzEuMzk5IEMxMTMuMTYyLDEzMS41MDcgMTEyLjk1MiwxMzEuNTYxIDExMi43MjcsMTMxLjU2MSIgaWQ9IkZpbGwtMjkiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTEyLjg2LDQwLjUxMiBDMTEyLjg2LDQwLjUxMiAxMTIuODYsNDAuNTEyIDExMi44NTksNDAuNTEyIEMxMTAuNTQxLDQwLjUxMiAxMDguMzYsMzkuOTkgMTA2LjcxNywzOS4wNDEgQzEwNS4wMTIsMzguMDU3IDEwNC4wNzQsMzYuNzI2IDEwNC4wNzQsMzUuMjkyIEMxMDQuMDc0LDMzLjg0NyAxMDUuMDI2LDMyLjUwMSAxMDYuNzU0LDMxLjUwNCBMMTE4Ljc5NSwyNC41NTEgQzEyMC40NjMsMjMuNTg5IDEyMi42NjksMjMuMDU4IDEyNS4wMDcsMjMuMDU4IEMxMjcuMzI1LDIzLjA1OCAxMjkuNTA2LDIzLjU4MSAxMzEuMTUsMjQuNTMgQzEzMi44NTQsMjUuNTE0IDEzMy43OTMsMjYuODQ1IDEzMy43OTMsMjguMjc4IEMxMzMuNzkzLDI5LjcyNCAxMzIuODQxLDMxLjA2OSAxMzEuMTEzLDMyLjA2NyBMMTE5LjA3MSwzOS4wMTkgQzExNy40MDMsMzkuOTgyIDExNS4xOTcsNDAuNTEyIDExMi44Niw0MC41MTIgTDExMi44Niw0MC41MTIgWiBNMTI1LjAwNywyMy43NTkgQzEyMi43OSwyMy43NTkgMTIwLjcwOSwyNC4yNTYgMTE5LjE0NiwyNS4xNTggTDEwNy4xMDQsMzIuMTEgQzEwNS42MDIsMzIuOTc4IDEwNC43NzQsMzQuMTA4IDEwNC43NzQsMzUuMjkyIEMxMDQuNzc0LDM2LjQ2NSAxMDUuNTg5LDM3LjU4MSAxMDcuMDY3LDM4LjQzNCBDMTA4LjYwNSwzOS4zMjMgMTEwLjY2MywzOS44MTIgMTEyLjg1OSwzOS44MTIgTDExMi44NiwzOS44MTIgQzExNS4wNzYsMzkuODEyIDExNy4xNTgsMzkuMzE1IDExOC43MjEsMzguNDEzIEwxMzAuNzYyLDMxLjQ2IEMxMzIuMjY0LDMwLjU5MyAxMzMuMDkyLDI5LjQ2MyAxMzMuMDkyLDI4LjI3OCBDMTMzLjA5MiwyNy4xMDYgMTMyLjI3OCwyNS45OSAxMzAuOCwyNS4xMzYgQzEyOS4yNjEsMjQuMjQ4IDEyNy4yMDQsMjMuNzU5IDEyNS4wMDcsMjMuNzU5IEwxMjUuMDA3LDIzLjc1OSBaIiBpZD0iRmlsbC0zMCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNjUuNjMsMTYuMjE5IEwxNTkuODk2LDE5LjUzIEMxNTYuNzI5LDIxLjM1OCAxNTEuNjEsMjEuMzY3IDE0OC40NjMsMTkuNTUgQzE0NS4zMTYsMTcuNzMzIDE0NS4zMzIsMTQuNzc4IDE0OC40OTksMTIuOTQ5IEwxNTQuMjMzLDkuNjM5IEwxNjUuNjMsMTYuMjE5IiBpZD0iRmlsbC0zMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xNTQuMjMzLDEwLjQ0OCBMMTY0LjIyOCwxNi4yMTkgTDE1OS41NDYsMTguOTIzIEMxNTguMTEyLDE
24745Ljc1IDE1Ni4xOTQsMjAuMjA2IDE1NC4xNDcsMjAuMjA2IEMxNTIuMTE4LDIwLjIwNiAxNTAuMjI0LDE5Ljc1NyAxNDguODE0LDE4Ljk0MyBDMTQ3LjUyNCwxOC4xOTkgMTQ2LjgxNCwxNy4yNDkgMTQ2LjgxNCwxNi4yNjkgQzE0Ni44MTQsMTUuMjc4IDE0Ny41MzcsMTQuMzE0IDE0OC44NSwxMy41NTYgTDE1NC4yMzMsMTAuNDQ4IE0xNTQuMjMzLDkuNjM5IEwxNDguNDk5LDEyLjk0OSBDMTQ1LjMzMiwxNC43NzggMTQ1LjMxNiwxNy43MzMgMTQ4LjQ2MywxOS41NSBDMTUwLjAzMSwyMC40NTUgMTUyLjA4NiwyMC45MDcgMTU0LjE0NywyMC45MDcgQzE1Ni4yMjQsMjAuOTA3IDE1OC4zMDYsMjAuNDQ3IDE1OS44OTYsMTkuNTMgTDE2NS42MywxNi4yMTkgTDE1NC4yMzMsOS42MzkiIGlkPSJGaWxsLTMyIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NS40NDUsNzIuNjY3IEwxNDUuNDQ1LDcyLjY2NyBDMTQzLjY3Miw3Mi42NjcgMTQyLjIwNCw3MS44MTcgMTQxLjIwMiw3MC40MjIgQzE0MS4xMzUsNzAuMzMgMTQxLjE0NSw3MC4xNDcgMTQxLjIyNSw3MC4wNjYgQzE0MS4zMDUsNjkuOTg1IDE0MS40MzIsNjkuOTQ2IDE0MS41MjUsNzAuMDExIEMxNDIuMzA2LDcwLjU1OSAxNDMuMjMxLDcwLjgyMyAxNDQuMjc2LDcwLjgyMiBDMTQ1LjU5OCw3MC44MjIgMTQ3LjAzLDcwLjM3NiAxNDguNTMyLDY5LjUwOSBDMTUzLjg0Miw2Ni40NDMgMTU4LjE2Myw1OC45ODcgMTU4LjE2Myw1Mi44OTQgQzE1OC4xNjMsNTAuOTY3IDE1Ny43MjEsNDkuMzMyIDE1Ni44ODQsNDguMTY4IEMxNTYuODE4LDQ4LjA3NiAxNTYuODI4LDQ3Ljk0OCAxNTYuOTA4LDQ3Ljg2NyBDMTU2Ljk4OCw0Ny43ODYgMTU3LjExNCw0Ny43NzQgMTU3LjIwOCw0Ny44NCBDMTU4Ljg3OCw0OS4wMTIgMTU5Ljc5OCw1MS4yMiAxNTkuNzk4LDU0LjA1OSBDMTU5Ljc5OCw2MC4zMDEgMTU1LjM3Myw2OC4wNDYgMTQ5LjkzMyw3MS4xODYgQzE0OC4zNiw3Mi4wOTQgMTQ2Ljg1LDcyLjY2NyAxNDUuNDQ1LDcyLjY2NyBMMTQ1LjQ0NSw3Mi42NjcgWiBNMTQyLjQ3Niw3MSBDMTQzLjI5LDcxLjY1MSAxNDQuMjk2LDcyLjAwMiAxNDUuNDQ1LDcyLjAwMiBDMTQ2Ljc2Nyw3Mi4wMDIgMTQ4LjE5OCw3MS41NSAxNDkuNyw3MC42ODIgQzE1NS4wMSw2Ny42MTcgMTU5LjMzMSw2MC4xNTkgMTU5LjMzMSw1NC4wNjUgQzE1OS4zMzEsNTIuMDg1IDE1OC44NjgsNTAuNDM1IDE1OC4wMDYsNDkuMjcyIEMxNTguNDE3LDUwLjMwNyAxNTguNjMsNTEuNTMyIDE1OC42Myw1Mi44OTIgQzE1OC42Myw1OS4xMzQgMTU0LjIwNSw2Ni43NjcgMTQ4Ljc2NSw2OS45MDcgQzE0Ny4xOTIsNzAuODE2IDE0NS42ODEsNzEuMjgzIDE0NC4yNzYsNzEuMjgzIEMxNDMuNjM0LDcxLjI4MyAxNDMuMDMzLDcxLjE5MiAxNDIuNDc2LDcxIEwxNDIuNDc2LDcxIFoiIGlkPSJGaWxsLTMzIiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0OC42NDgsNjkuNzA0IEMxNTQuMDMyLDY2LjU5NiAxNTguMzk2LDU5LjA2OCAxNTguMzk2LDUyLjg5MSBDMTU4LjM5Niw1MC44MzkgMTU3LjkxMyw0OS4xOTggMTU3LjA3NCw0OC4wMyBDMTU1LjI4OSw0Ni43NzggMTUyLjY5OSw0Ni44MzYgMTQ5LjgxNiw0OC41MDEgQzE0NC40MzMsNTEuNjA5IDE0MC4wNjgsNTkuMTM3IDE0MC4wNjgsNjUuMzE0IEMxNDAuMDY4LDY3LjM2NSAxNDAuNTUyLDY5LjAwNiAxNDEuMzkxLDcwLjE3NCBDMTQzLjE3Niw3MS40MjcgMTQ1Ljc2NSw3MS4zNjkgMTQ4LjY0OCw2OS43MDQiIGlkPSJGaWxsLTM0IiBmaWxsPSIjRkFGQUZBIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTE0NC4yNzYsNzEuMjc2IEwxNDQuMjc2LDcxLjI3NiBDMTQzLjEzMyw3MS4yNzYgMTQyLjExOCw3MC45NjkgMTQxLjI1Nyw3MC4zNjUgQzE0MS4yMzYsNzAuMzUxIDE0MS4yMTcsNzAuMzMyIDE0MS4yMDIsNzAuMzExIEMxNDAuMzA3LDY5LjA2NyAxMzkuODM1LDY3LjMzOSAxMzkuODM1LDY1LjMxNCBDMTM5LjgzNSw1OS4wNzMgMTQ0LjI2LDUxLjQzOSAxNDkuNyw0OC4yOTggQzE1MS4yNzMsNDcuMzkgMTUyLjc4NCw0Ni45MjkgMTU0LjE4OSw0Ni45MjkgQzE1NS4zMzIsNDYuOTI5IDE1Ni4zNDcsNDcuMjM2IDE1Ny4yMDgsNDcuODM5IEMxNTcuMjI5LDQ3Ljg1NCAxNTcuMjQ4LDQ3Ljg3MyAxNTcuMjYzLDQ3Ljg5NCBDMTU4LjE1Nyw0OS4xMzggMTU4LjYzLDUwLjg2NSAxNTguNjMsNTIuODkxIEMxNTguNjMsNTkuMTMyIDE1NC4yMDUsNjYuNzY2IDE0OC43NjUsNjkuOTA3IEMxNDcuMTkyLDcwLjgxNSAxNDUuNjgxLDcxLjI3NiAxNDQuMjc2LDcxLjI3NiBMMTQ0LjI3Niw3MS4yNzYgWiBNMTQxLjU1OCw3MC4xMDQgQzE0Mi4zMzEsNzAuNjM3IDE0My4yNDUsNzEuMDA1IDE0NC4yNzYsNzEuMDA1IEMxNDUuNTk4LDcxLjAwNSAxNDcuMDMsNzAuNDY3IDE0OC41MzIsNjkuNiBDMTUzLjg0Miw2Ni41MzQgMTU4LjE2Myw1OS4wMzMgMTU4LjE2Myw1Mi45MzkgQzE1OC4xNjMsNTEuMDMxIDE1Ny43MjksNDkuMzg1IDE1Ni45MDcsNDguMjIzIEMxNTYuMTMzLDQ3LjY5MSAxNTUuMjE5LDQ3LjQwOSAxNTQuMTg5LDQ3LjQwOSBDMTUyLjg2Nyw0Ny40MDkgMTUxLjQzNSw0Ny44NDIgMTQ5LjkzMyw0OC43MDkgQzE0NC42MjMsNTEuNzc1IDE0MC4zMDIsNTkuMjczIDE0MC4zMDIsNjUuMzY2IEMxNDAuMzAyLDY3LjI3NiAxNDAuNzM2LDY4Ljk0MiAxNDEuNTU4LDcwLjEwNCBMMTQxLjU1OCw3MC4xMDQgWiIgaWQ9IkZpbGwtMzUiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTUwLjcyLDY1LjM2MSBMMTUwLjM1Nyw2NS4wNjYgQzE1MS4xNDcsNjQuMDkyIDE1MS44NjksNjMuMDQgMTUyLjUwNSw2MS45MzggQzE1My4zMTMsNjAuNTM5IDE1My45NzgsNTkuMDY3IDE1NC40ODIsNTcuNTYzIEwxNTQuOTI1LDU3LjcxMiBDMTU0LjQxMiw1OS4yNDUgMTUzLjczMyw2MC43NDUgMTUyLjkxLDYyLjE3MiBDMTUyLjI2Miw2My4yOTUgMTUxLjUyNSw2NC4zNjggMTUwLjcyLDY1LjM2MSIgaWQ9IkZpbGwtMzYiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE1LjkxNyw4NC41MTQgTDExNS41NTQsODQuMjIgQzExNi4zNDQsODMuMjQ1IDExNy4wNjYsODIuMTk0IDExNy43MDIsODEuMDkyIEMxMTguNTEsNzkuNjkyIDExOS4xNzUsNzguMjIgMTE5LjY3OCw3Ni43MTcgTDEyMC4xMjEsNzYuODY1IEMxMTkuNjA4LDc4LjM5OCAxMTguOTMsNzkuODk5IDExOC4xMDYsODEuMzI2IEMxMTcuNDU4LDgyLjQ0OCAxMTYuNzIyLDgzLjUyMSAxMTUuOTE3LDg0LjUxNCIgaWQ9IkZpbGwtMzciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTE0LDEzMC40NzYgTDExNCwxMzAuMDA4IEwxMTQsNzYuMDUyIEwxMTQsNzUuNTg0IEwxMTQsNzYuMDUyIEwxMTQsMTMwLjAwOCBMMTE0LDEzMC40NzYiIGlkPSJGaWxsLTM4IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iSW1wb3J0ZWQtTGF5ZXJzLUNvcHkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDYyLjAwMDAwMCwgMC4wMDAwMDApIiBza2V0Y2g6dHlwZT0iTVNTaGFwZUdyb3VwIj4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTkuODIyLDM3LjQ3NCBDMTkuODM5LDM3LjMzOSAxOS43NDcsMzcuMTk0IDE5LjU1NSwzNy4wODIgQzE5LjIyOCwzNi44OTQgMTguNzI5LDM2Ljg3MiAxOC40NDYsMzcuMDM3IEwxMi40MzQsNDAuNTA4IEMxMi4zMDMsNDAuNTg0IDEyLjI0LDQwLjY4NiAxMi4yNDMsNDAuNzkzIEMxMi4yNDUsNDAuOTI1IDEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQxLjM3MSBMMTIuMjQ1LDQxLjQxNCBMMTIuMjM4LDQxLjU0MiBDOC4xNDgsNDMuODg3IDUuNjQ3LDQ1LjMyMSA1LjY0Nyw0NS4zMjEgQzUuNjQ2LDQ1LjMyMSAzLjU3LDQ2LjM2NyAyLjg2LDUwLjUxMyBDMi44Niw1MC41MTMgMS45NDgsNTcuNDc0IDEuOTYyLDcwLjI1OCBDMS45NzcsODIuODI4IDIuNTY4LDg3LjMyOCAzLjEyOSw5MS42MDkgQzMuMzQ5LDkzLjI5MyA2LjEzLDkzLjczNCA2LjEzLDkzLjczNCBDNi40NjEsOTMuNzc0IDYuODI4LDkzLjcwNyA3LjIxLDkzLjQ4NiBMODIuNDgzLDQ5LjkzNSBDODQuMjkxLDQ4Ljg2NiA4NS4xNSw0Ni4yMTYgODUuNTM5LDQzLjY1MSBDODYuNzUyLDM1LjY2MSA4Ny4yMTQsMTAuNjczIDg1LjI2NCwzLjc3MyBDODUuMDY4LDMuMDggODQuNzU0LDIuNjkgODQuMzk2LDIuNDkxIEw4Mi4zMSwxLjcwMSBDODEuNTgzLDEuNzI5IDgwLjg5NCwyLjE2OCA4MC43NzYsMi4yMzYgQzgwLjYzNiwyLjMxNyA0MS44MDcsMjQuNTg1IDIwLjAzMiwzNy4wNzIgTDE5LjgyMiwzNy40NzQiIGlkPSJGaWxsLTEiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNODIuMzExLDEuNzAxIEw4NC4zOTYsMi40OTEgQzg0Ljc1NCwyLjY5IDg1LjA2OCwzLjA4IDg1LjI2NCwzLjc3MyBDODcuMjEzLDEwLjY3MyA4Ni43NTEsMzUuNjYgODUuNTM5LDQzLjY1MSBDODUuMTQ5LDQ2LjIxNiA4NC4yOSw0OC44NjYgODIuNDgzLDQ5LjkzNSB
2474MNy4yMSw5My40ODYgQzYuODk3LDkzLjY2NyA2LjU5NSw5My43NDQgNi4zMTQsOTMuNzQ0IEw2LjEzMSw5My43MzMgQzYuMTMxLDkzLjczNCAzLjM0OSw5My4yOTMgMy4xMjgsOTEuNjA5IEMyLjU2OCw4Ny4zMjcgMS45NzcsODIuODI4IDEuOTYzLDcwLjI1OCBDMS45NDgsNTcuNDc0IDIuODYsNTAuNTEzIDIuODYsNTAuNTEzIEMzLjU3LDQ2LjM2NyA1LjY0Nyw0NS4zMjEgNS42NDcsNDUuMzIxIEM1LjY0Nyw0NS4zMjEgOC4xNDgsNDMuODg3IDEyLjIzOCw0MS41NDIgTDEyLjI0NSw0MS40MTQgTDEyLjI0NSw0MS4zNzEgQzEyLjI0NSw0MS4yNTQgMTIuMjQ1LDQwLjkyNSAxMi4yNDMsNDAuNzkzIEMxMi4yNCw0MC42ODYgMTIuMzAyLDQwLjU4MyAxMi40MzQsNDAuNTA4IEwxOC40NDYsMzcuMDM2IEMxOC41NzQsMzYuOTYyIDE4Ljc0NiwzNi45MjYgMTguOTI3LDM2LjkyNiBDMTkuMTQ1LDM2LjkyNiAxOS4zNzYsMzYuOTc5IDE5LjU1NCwzNy4wODIgQzE5Ljc0NywzNy4xOTQgMTkuODM5LDM3LjM0IDE5LjgyMiwzNy40NzQgTDIwLjAzMywzNy4wNzIgQzQxLjgwNiwyNC41ODUgODAuNjM2LDIuMzE4IDgwLjc3NywyLjIzNiBDODAuODk0LDIuMTY4IDgxLjU4MywxLjcyOSA4Mi4zMTEsMS43MDEgTTgyLjMxMSwwLjcwNCBMODIuMjcyLDAuNzA1IEM4MS42NTQsMC43MjggODAuOTg5LDAuOTQ5IDgwLjI5OCwxLjM2MSBMODAuMjc3LDEuMzczIEM4MC4xMjksMS40NTggNTkuNzY4LDEzLjEzNSAxOS43NTgsMzYuMDc5IEMxOS41LDM1Ljk4MSAxOS4yMTQsMzUuOTI5IDE4LjkyNywzNS45MjkgQzE4LjU2MiwzNS45MjkgMTguMjIzLDM2LjAxMyAxNy45NDcsMzYuMTczIEwxMS45MzUsMzkuNjQ0IEMxMS40OTMsMzkuODk5IDExLjIzNiw0MC4zMzQgMTEuMjQ2LDQwLjgxIEwxMS4yNDcsNDAuOTYgTDUuMTY3LDQ0LjQ0NyBDNC43OTQsNDQuNjQ2IDIuNjI1LDQ1Ljk3OCAxLjg3Nyw1MC4zNDUgTDEuODcxLDUwLjM4NCBDMS44NjIsNTAuNDU0IDAuOTUxLDU3LjU1NyAwLjk2NSw3MC4yNTkgQzAuOTc5LDgyLjg3OSAxLjU2OCw4Ny4zNzUgMi4xMzcsOTEuNzI0IEwyLjEzOSw5MS43MzkgQzIuNDQ3LDk0LjA5NCA1LjYxNCw5NC42NjIgNS45NzUsOTQuNzE5IEw2LjAwOSw5NC43MjMgQzYuMTEsOTQuNzM2IDYuMjEzLDk0Ljc0MiA2LjMxNCw5NC43NDIgQzYuNzksOTQuNzQyIDcuMjYsOTQuNjEgNy43MSw5NC4zNSBMODIuOTgzLDUwLjc5OCBDODQuNzk0LDQ5LjcyNyA4NS45ODIsNDcuMzc1IDg2LjUyNSw0My44MDEgQzg3LjcxMSwzNS45ODcgODguMjU5LDEwLjcwNSA4Ni4yMjQsMy41MDIgQzg1Ljk3MSwyLjYwOSA4NS41MiwxLjk3NSA4NC44ODEsMS42MiBMODQuNzQ5LDEuNTU4IEw4Mi42NjQsMC43NjkgQzgyLjU1MSwwLjcyNSA4Mi40MzEsMC43MDQgODIuMzExLDAuNzA0IiBpZD0iRmlsbC0yIiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTY2LjI2NywxMS41NjUgTDY3Ljc2MiwxMS45OTkgTDExLjQyMyw0NC4zMjUiIGlkPSJGaWxsLTMiIGZpbGw9IiNGRkZGRkYiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMjAyLDkwLjU0NSBDMTIuMDI5LDkwLjU0NSAxMS44NjIsOTAuNDU1IDExLjc2OSw5MC4yOTUgQzExLjYzMiw5MC4wNTcgMTEuNzEzLDg5Ljc1MiAxMS45NTIsODkuNjE0IEwzMC4zODksNzguOTY5IEMzMC42MjgsNzguODMxIDMwLjkzMyw3OC45MTMgMzEuMDcxLDc5LjE1MiBDMzEuMjA4LDc5LjM5IDMxLjEyNyw3OS42OTYgMzAuODg4LDc5LjgzMyBMMTIuNDUxLDkwLjQ3OCBMMTIuMjAyLDkwLjU0NSIgaWQ9IkZpbGwtNCIgZmlsbD0iIzYwN0Q4QiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMy43NjQsNDIuNjU0IEwxMy42NTYsNDIuNTkyIEwxMy43MDIsNDIuNDIxIEwxOC44MzcsMzkuNDU3IEwxOS4wMDcsMzkuNTAyIEwxOC45NjIsMzkuNjczIEwxMy44MjcsNDIuNjM3IEwxMy43NjQsNDIuNjU0IiBpZD0iRmlsbC01IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTguNTIsOTAuMzc1IEw4LjUyLDQ2LjQyMSBMOC41ODMsNDYuMzg1IEw3NS44NCw3LjU1NCBMNzUuODQsNTEuNTA4IEw3NS43NzgsNTEuNTQ0IEw4LjUyLDkwLjM3NSBMOC41Miw5MC4zNzUgWiBNOC43Nyw0Ni41NjQgTDguNzcsODkuOTQ0IEw3NS41OTEsNTEuMzY1IEw3NS41OTEsNy45ODUgTDguNzcsNDYuNTY0IEw4Ljc3LDQ2LjU2NCBaIiBpZD0iRmlsbC02IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTI0Ljk4Niw4My4xODIgQzI0Ljc1Niw4My4zMzEgMjQuMzc0LDgzLjU2NiAyNC4xMzcsODMuNzA1IEwxMi42MzIsOTAuNDA2IEMxMi4zOTUsOTAuNTQ1IDEyLjQyNiw5MC42NTggMTIuNyw5MC42NTggTDEzLjI2NSw5MC42NTggQzEzLjU0LDkwLjY1OCAxMy45NTgsOTAuNTQ1IDE0LjE5NSw5MC40MDYgTDI1LjcsODMuNzA1IEMyNS45MzcsODMuNTY2IDI2LjEyOCw4My40NTIgMjYuMTI1LDgzLjQ0OSBDMjYuMTIyLDgzLjQ0NyAyNi4xMTksODMuMjIgMjYuMTE5LDgyLjk0NiBDMjYuMTE5LDgyLjY3MiAyNS45MzEsODIuNTY5IDI1LjcwMSw4Mi43MTkgTDI0Ljk4Niw4My4xODIiIGlkPSJGaWxsLTciIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTMuMjY2LDkwLjc4MiBMMTIuNyw5MC43ODIgQzEyLjUsOTAuNzgyIDEyLjM4NCw5MC43MjYgMTIuMzU0LDkwLjYxNiBDMTIuMzI0LDkwLjUwNiAxMi4zOTcsOTAuMzk5IDEyLjU2OSw5MC4yOTkgTDI0LjA3NCw4My41OTcgQzI0LjMxLDgzLjQ1OSAyNC42ODksODMuMjI2IDI0LjkxOCw4My4wNzggTDI1LjYzMyw4Mi42MTQgQzI1LjcyMyw4Mi41NTUgMjUuODEzLDgyLjUyNSAyNS44OTksODIuNTI1IEMyNi4wNzEsODIuNTI1IDI2LjI0NCw4Mi42NTUgMjYuMjQ0LDgyLjk0NiBDMjYuMjQ0LDgzLjE2IDI2LjI0NSw4My4zMDkgMjYuMjQ3LDgzLjM4MyBMMjYuMjUzLDgzLjM4NyBMMjYuMjQ5LDgzLjQ1NiBDMjYuMjQ2LDgzLjUzMSAyNi4yNDYsODMuNTMxIDI1Ljc2Myw4My44MTIgTDE0LjI1OCw5MC41MTQgQzE0LDkwLjY2NSAxMy41NjQsOTAuNzgyIDEzLjI2Niw5MC43ODIgTDEzLjI2Niw5MC43ODIgWiBNMTIuNjY2LDkwLjUzMiBMMTIuNyw5MC41MzMgTDEzLjI2Niw5MC41MzMgQzEzLjUxOCw5MC41MzMgMTMuOTE1LDkwLjQyNSAxNC4xMzIsOTAuMjk5IEwyNS42MzcsODMuNTk3IEMyNS44MDUsODMuNDk5IDI1LjkzMSw4My40MjQgMjUuOTk4LDgzLjM4MyBDMjUuOTk0LDgzLjI5OSAyNS45OTQsODMuMTY1IDI1Ljk5NCw4Mi45NDYgTDI1Ljg5OSw4Mi43NzUgTDI1Ljc2OCw4Mi44MjQgTDI1LjA1NCw4My4yODcgQzI0LjgyMiw4My40MzcgMjQuNDM4LDgzLjY3MyAyNC4yLDgzLjgxMiBMMTIuNjk1LDkwLjUxNCBMMTIuNjY2LDkwLjUzMiBMMTIuNjY2LDkwLjUzMiBaIiBpZD0iRmlsbC04IiBmaWxsPSIjNjA3RDhCIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEzLjI2Niw4OS44NzEgTDEyLjcsODkuODcxIEMxMi41LDg5Ljg3MSAxMi4zODQsODkuODE1IDEyLjM1NCw4OS43MDUgQzEyLjMyNCw4OS41OTUgMTIuMzk3LDg5LjQ4OCAxMi41NjksODkuMzg4IEwyNC4wNzQsODIuNjg2IEMyNC4zMzIsODIuNTM1IDI0Ljc2OCw4Mi40MTggMjUuMDY3LDgyLjQxOCBMMjUuNjMyLDgyLjQxOCBDMjUuODMyLDgyLjQxOCAyNS45NDgsODIuNDc0IDI1Ljk3OCw4Mi41ODQgQzI2LjAwOCw4Mi42OTQgMjUuOTM1LDgyLjgwMSAyNS43NjMsODIuOTAxIEwxNC4yNTgsODkuNjAzIEMxNCw4OS43NTQgMTMuNTY0LDg5Ljg3MSAxMy4yNjYsODkuODcxIEwxMy4yNjYsODkuODcxIFogTTEyLjY2Niw4OS42MjEgTDEyLjcsODkuNjIyIEwxMy4yNjYsODkuNjIyIEMxMy41MTgsODkuNjIyIDEzLjkxNSw4OS41MTUgMTQuMTMyLDg5LjM4OCBMMjUuNjM3LDgyLjY4NiB
2474MMjUuNjY3LDgyLjY2OCBMMjUuNjMyLDgyLjY2NyBMMjUuMDY3LDgyLjY2NyBDMjQuODE1LDgyLjY2NyAyNC40MTgsODIuNzc1IDI0LjIsODIuOTAxIEwxMi42OTUsODkuNjAzIEwxMi42NjYsODkuNjIxIEwxMi42NjYsODkuNjIxIFoiIGlkPSJGaWxsLTkiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNMTIuMzcsOTAuODAxIEwxMi4zNyw4OS41NTQgTDEyLjM3LDkwLjgwMSIgaWQ9IkZpbGwtMTAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNi4xMyw5My45MDEgQzUuMzc5LDkzLjgwOCA0LjgxNiw5My4xNjQgNC42OTEsOTIuNTI1IEMzLjg2LDg4LjI4NyAzLjU0LDgzLjc0MyAzLjUyNiw3MS4xNzMgQzMuNTExLDU4LjM4OSA0LjQyMyw1MS40MjggNC40MjMsNTEuNDI4IEM1LjEzNCw0Ny4yODIgNy4yMSw0Ni4yMzYgNy4yMSw0Ni4yMzYgQzcuMjEsNDYuMjM2IDgxLjY2NywzLjI1IDgyLjA2OSwzLjAxNyBDODIuMjkyLDIuODg4IDg0LjU1NiwxLjQzMyA4NS4yNjQsMy45NCBDODcuMjE0LDEwLjg0IDg2Ljc1MiwzNS44MjcgODUuNTM5LDQzLjgxOCBDODUuMTUsNDYuMzgzIDg0LjI5MSw0OS4wMzMgODIuNDgzLDUwLjEwMSBMNy4yMSw5My42NTMgQzYuODI4LDkzLjg3NCA2LjQ2MSw5My45NDEgNi4xMyw5My45MDEgQzYuMTMsOTMuOTAxIDMuMzQ5LDkzLjQ2IDMuMTI5LDkxLjc3NiBDMi41NjgsODcuNDk1IDEuOTc3LDgyLjk5NSAxLjk2Miw3MC40MjUgQzEuOTQ4LDU3LjY0MSAyLjg2LDUwLjY4IDIuODYsNTAuNjggQzMuNTcsNDYuNTM0IDUuNjQ3LDQ1LjQ4OSA1LjY0Nyw0NS40ODkgQzUuNjQ2LDQ1LjQ4OSA4LjA2NSw0NC4wOTIgMTIuMjQ1LDQxLjY3OSBMMTMuMTE2LDQxLjU2IEwxOS43MTUsMzcuNzMgTDE5Ljc2MSwzNy4yNjkgTDYuMTMsOTMuOTAxIiBpZD0iRmlsbC0xMSIgZmlsbD0iI0ZBRkFGQSI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjMxNyw5NC4xNjEgTDYuMTAyLDk0LjE0OCBMNi4xMDEsOTQuMTQ4IEw1Ljg1Nyw5NC4xMDEgQzUuMTM4LDkzLjk0NSAzLjA4NSw5My4zNjUgMi44ODEsOTEuODA5IEMyLjMxMyw4Ny40NjkgMS43MjcsODIuOTk2IDEuNzEzLDcwLjQyNSBDMS42OTksNTcuNzcxIDIuNjA0LDUwLjcxOCAyLjYxMyw1MC42NDggQzMuMzM4LDQ2LjQxNyA1LjQ0NSw0NS4zMSA1LjUzNSw0NS4yNjYgTDEyLjE2Myw0MS40MzkgTDEzLjAzMyw0MS4zMiBMMTkuNDc5LDM3LjU3OCBMMTkuNTEzLDM3LjI0NCBDMTkuNTI2LDM3LjEwNyAxOS42NDcsMzcuMDA4IDE5Ljc4NiwzNy4wMjEgQzE5LjkyMiwzNy4wMzQgMjAuMDIzLDM3LjE1NiAyMC4wMDksMzcuMjkzIEwxOS45NSwzNy44ODIgTDEzLjE5OCw0MS44MDEgTDEyLjMyOCw0MS45MTkgTDUuNzcyLDQ1LjcwNCBDNS43NDEsNDUuNzIgMy43ODIsNDYuNzcyIDMuMTA2LDUwLjcyMiBDMy4wOTksNTAuNzgyIDIuMTk4LDU3LjgwOCAyLjIxMiw3MC40MjQgQzIuMjI2LDgyLjk2MyAyLjgwOSw4Ny40MiAzLjM3Myw5MS43MjkgQzMuNDY0LDkyLjQyIDQuMDYyLDkyLjg4MyA0LjY4Miw5My4xODEgQzQuNTY2LDkyLjk4NCA0LjQ4Niw5Mi43NzYgNC40NDYsOTIuNTcyIEMzLjY2NSw4OC41ODggMy4yOTEsODQuMzcgMy4yNzYsNzEuMTczIEMzLjI2Miw1OC41MiA0LjE2Nyw1MS40NjYgNC4xNzYsNTEuMzk2IEM0LjkwMSw0Ny4xNjUgNy4wMDgsNDYuMDU5IDcuMDk4LDQ2LjAxNCBDNy4wOTQsNDYuMDE1IDgxLjU0MiwzLjAzNCA4MS45NDQsMi44MDIgTDgxLjk3MiwyLjc4NSBDODIuODc2LDIuMjQ3IDgzLjY5MiwyLjA5NyA4NC4zMzIsMi4zNTIgQzg0Ljg4NywyLjU3MyA4NS4yODEsMy4wODUgODUuNTA0LDMuODcyIEM4Ny41MTgsMTEgODYuOTY0LDM2LjA5MSA4NS43ODUsNDMuODU1IEM4NS4yNzgsNDcuMTk2IDg0LjIxLDQ5LjM3IDgyLjYxLDUwLjMxNyBMNy4zMzUsOTMuODY5IEM2Ljk5OSw5NC4wNjMgNi42NTgsOTQuMTYxIDYuMzE3LDk0LjE2MSBMNi4zMTcsOTQuMTYxIFogTTYuMTcsOTMuNjU0IEM2LjQ2Myw5My42OSA2Ljc3NCw5My42MTcgNy4wODUsOTMuNDM3IEw4Mi4zNTgsNDkuODg2IEM4NC4xODEsNDguODA4IDg0Ljk2LDQ1Ljk3MSA4NS4yOTIsNDMuNzggQzg2LjQ2NiwzNi4wNDkgODcuMDIzLDExLjA4NSA4NS4wMjQsNC4wMDggQzg0Ljg0NiwzLjM3NyA4NC41NTEsMi45NzYgODQuMTQ4LDIuODE2IEM4My42NjQsMi42MjMgODIuOTgyLDIuNzY0IDgyLjIyNywzLjIxMyBMODIuMTkzLDMuMjM0IEM4MS43OTEsMy40NjYgNy4zMzUsNDYuNDUyIDcuMzM1LDQ2LjQ1MiBDNy4zMDQsNDYuNDY5IDUuMzQ2LDQ3LjUyMSA0LjY2OSw1MS40NzEgQzQuNjYyLDUxLjUzIDMuNzYxLDU4LjU1NiAzLjc3NSw3MS4xNzMgQzMuNzksODQuMzI4IDQuMTYxLDg4LjUyNCA0LjkzNiw5Mi40NzYgQzUuMDI2LDkyLjkzNyA1LjQxMiw5My40NTkgNS45NzMsOTMuNjE1IEM2LjA4Nyw5My42NCA2LjE1OCw5My42NTIgNi4xNjksOTMuNjU0IEw2LjE3LDkzLjY1NCBMNi4xNyw5My42NTQgWiIgaWQ9IkZpbGwtMTIiIGZpbGw9IiM0NTVBNjQiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4zMTcsNjguOTgyIEM3LjgwNiw2OC43MDEgOC4yMDIsNjguOTI2IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNi44MjksNzEuMjk0IDYuNDMzLDcxLjA2OSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIiBpZD0iRmlsbC0xMyIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik02LjkyLDcxLjEzMyBDNi42MzEsNzEuMTMzIDYuNDMzLDcwLjkwNSA2LjQzMyw3MC41MDggQzYuNDMzLDY5Ljk0OCA2LjgyOSw2OS4yNjUgNy4zMTcsNjguOTgyIEM3LjQ2LDY4LjkgNy41OTUsNjguODYxIDcuNzE0LDY4Ljg2MSBDOC4wMDMsNjguODYxIDguMjAyLDY5LjA5IDguMjAyLDY5LjQ4NyBDOC4yMDIsNzAuMDQ3IDcuODA2LDcwLjczIDcuMzE3LDcxLjAxMiBDNy4xNzQsNzEuMDk0IDcuMDM5LDcxLjEzMyA2LjkyLDcxLjEzMyBNNy43MTQsNjguNjc0IEM3LjU1Nyw2OC42NzQgNy4zOTIsNjguNzIzIDcuMjI0LDY4LjgyMSBDNi42NzYsNjkuMTM4IDYuMjQ2L
2474DY5Ljg3OSA2LjI0Niw3MC41MDggQzYuMjQ2LDcwLjk5NCA2LjUxNyw3MS4zMiA2LjkyLDcxLjMyIEM3LjA3OCw3MS4zMiA3LjI0Myw3MS4yNzEgNy40MTEsNzEuMTc0IEM3Ljk1OSw3MC44NTcgOC4zODksNzAuMTE3IDguMzg5LDY5LjQ4NyBDOC4zODksNjkuMDAxIDguMTE3LDY4LjY3NCA3LjcxNCw2OC42NzQiIGlkPSJGaWxsLTE0IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTYuOTIsNzAuOTQ3IEM2LjY0OSw3MC45NDcgNi42MjEsNzAuNjQgNi42MjEsNzAuNTA4IEM2LjYyMSw3MC4wMTcgNi45ODIsNjkuMzkyIDcuNDExLDY5LjE0NSBDNy41MjEsNjkuMDgyIDcuNjI1LDY5LjA0OSA3LjcxNCw2OS4wNDkgQzcuOTg2LDY5LjA0OSA4LjAxNSw2OS4zNTUgOC4wMTUsNjkuNDg3IEM4LjAxNSw2OS45NzggNy42NTIsNzAuNjAzIDcuMjI0LDcwLjg1MSBDNy4xMTUsNzAuOTE0IDcuMDEsNzAuOTQ3IDYuOTIsNzAuOTQ3IE03LjcxNCw2OC44NjEgQzcuNTk1LDY4Ljg2MSA3LjQ2LDY4LjkgNy4zMTcsNjguOTgyIEM2LjgyOSw2OS4yNjUgNi40MzMsNjkuOTQ4IDYuNDMzLDcwLjUwOCBDNi40MzMsNzAuOTA1IDYuNjMxLDcxLjEzMyA2LjkyLDcxLjEzMyBDNy4wMzksNzEuMTMzIDcuMTc0LDcxLjA5NCA3LjMxNyw3MS4wMTIgQzcuODA2LDcwLjczIDguMjAyLDcwLjA0NyA4LjIwMiw2OS40ODcgQzguMjAyLDY5LjA5IDguMDAzLDY4Ljg2MSA3LjcxNCw2OC44NjEiIGlkPSJGaWxsLTE1IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTcuNDQ0LDg1LjM1IEM3LjcwOCw4NS4xOTggNy45MjEsODUuMzE5IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuOTI1IDcuNzA4LDg2LjI5MiA3LjQ0NCw4Ni40NDQgQzcuMTgxLDg2LjU5NyA2Ljk2Nyw4Ni40NzUgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IiBpZD0iRmlsbC0xNiIgZmlsbD0iI0ZGRkZGRiI+PC9wYXRoPgogICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik03LjIzLDg2LjUxIEM3LjA3NCw4Ni41MSA2Ljk2Nyw4Ni4zODcgNi45NjcsODYuMTczIEM2Ljk2Nyw4NS44NzEgNy4xODEsODUuNTAyIDcuNDQ0LDg1LjM1IEM3LjUyMSw4NS4zMDUgNy41OTQsODUuMjg0IDcuNjU4LDg1LjI4NCBDNy44MTQsODUuMjg0IDcuOTIxLDg1LjQwOCA3LjkyMSw4NS42MjIgQzcuOTIxLDg1LjkyNSA3LjcwOCw4Ni4yOTIgNy40NDQsODYuNDQ0IEM3LjM2Nyw4Ni40ODkgNy4yOTQsODYuNTEgNy4yMyw4Ni41MSBNNy42NTgsODUuMDk4IEM3LjU1OCw4NS4wOTggNy40NTUsODUuMTI3IDcuMzUxLDg1LjE4OCBDNy4wMzEsODUuMzczIDYuNzgxLDg1LjgwNiA2Ljc4MSw4Ni4xNzMgQzYuNzgxLDg2LjQ4MiA2Ljk2Niw4Ni42OTcgNy4yMyw4Ni42OTcgQzcuMzMsODYuNjk3IDcuNDMzLDg2LjY2NiA3LjUzOCw4Ni42MDcgQzcuODU4LDg2LjQyMiA4LjEwOCw4NS45ODkgOC4xMDgsODUuNjIyIEM4LjEwOCw4NS4zMTMgNy45MjMsODUuMDk4IDcuNjU4LDg1LjA5OCIgaWQ9IkZpbGwtMTciIGZpbGw9IiM4MDk3QTIiPjwvcGF0aD4KICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPSJNNy4yMyw4Ni4zMjIgTDcuMTU0LDg2LjE3MyBDNy4xNTQsODUuOTM4IDcuMzMzLDg1LjYyOSA3LjUzOCw4NS41MTIgTDcuNjU4LDg1LjQ3MSBMNy43MzQsODUuNjIyIEM3LjczNCw4NS44NTYgNy41NTUsODYuMTY0IDcuMzUxLDg2LjI4MiBMNy4yMyw4Ni4zMjIgTTcuNjU4LDg1LjI4NCBDNy41OTQsODUuMjg0IDcuNTIxLDg1LjMwNSA3LjQ0NCw4NS4zNSBDNy4xODEsODUuNTAyIDYuOTY3LDg1Ljg3MSA2Ljk2Nyw4Ni4xNzMgQzYuOTY3LDg2LjM4NyA3LjA3NCw4Ni41MSA3LjIzLDg2LjUxIEM3LjI5NCw4Ni41MSA3LjM2Nyw4Ni40ODkgNy40NDQsODYuNDQ0IEM3LjcwOCw4Ni4yOTIgNy45MjEsODUuOTI1IDcuOTIxLDg1LjYyMiBDNy45MjEsODUuNDA4IDcuODE0LDg1LjI4NCA3LjY1OCw4NS4yODQiIGlkPSJGaWxsLTE4IiBmaWxsPSIjODA5N0EyIj48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTc3LjI3OCw3Ljc2OSBMNzcuMjc4LDUxLjQzNiBMMTAuMjA4LDkwLjE2IEwxMC4yMDgsNDYuNDkzIEw3Ny4yNzgsNy43NjkiIGlkPSJGaWxsLTE5IiBmaWxsPSIjNDU1QTY0Ij48L3BhdGg+CiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD0iTTEwLjA4Myw5MC4zNzUgTDEwLjA4Myw0Ni40MjEgTDEwLjE0Niw0Ni4zODUgTDc3LjQwMyw3LjU1NCBMNzcuNDAzLDUxLjUwOCBMNzcuMzQxLDUxLjU0NCBMMTAuMDgzLDkwLjM3NSBMMTAuMDgzLDkwLjM3NSBaIE0xMC4zMzMsNDYuNTY0IEwxMC4zMzMsODkuOTQ0IEw3Ny4xNTQsNTEuMzY1IEw3Ny4xNTQsNy45ODUgTDEwLjMzMyw0Ni41NjQgTDEwLjMzMyw0Ni41NjQgWiIgaWQ9IkZpbGwtMjAiIGZpbGw9IiM2MDdEOEIiPjwvcGF0aD4KICAgICAgICAgICAgICAgIDwvZz4KICAgICAgICAgICAgICAgIDxwYXRoIGQ9Ik0xMjUuNzM3LDg4LjY0NyBMMTE4LjA5OCw5MS45ODEgTDExOC4wOTgsODQgTDEwNi42MzksODguNzEzIEwxMDYuNjM5LDk2Ljk4MiBMOTksMTAwLjMxNSBMMTEyLjM2OSwxMDMuOTYxIEwxMjUuNzM3LDg4LjY0NyIgaWQ9IkltcG9ydGVkLUxheWVycy1Db3B5LTIiIGZpbGw9IiM0NTVBNjQiIHNrZXRjaDp0eXBlPSJNU1NoYXBlR3JvdXAiPjwvcGF0aD4KICAgICAgICAgICAgPC9nPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+'; 2475 function RotateInstructions() { 2476 this.loadIcon_(); 2477 var overlay = document.createElement('div'); 2478 var s = overlay.style; 2479 s.position = 'fixed'; 2480 s.top = 0; 2481 s.right = 0; 2482 s.bottom = 0; 2483 s.left = 0; 2484 s.backgroundColor = 'gray'; 2485 s.fontFamily = 'sans-serif'; 2486 s.zIndex = 1000000; 2487 var img = document.createElement('img'); 2488 img.src = this.icon; 2489 var s = img.style; 2490 s.marginLeft = '25%'; 2491 s.marginTop = '25%'; 2492 s.width = '50%'; 2493 overlay.appendChild(img); 2494 var text = document.createElement('div'); 2495 var s = text.style; 2496 s.textAlign = 'center'; 2497 s.fontSize = '16px'; 2498 s.lineHeight = '24px'; 2499 s.margin = '24px 25%'; 2500 s.width = '50%'; 2501 text.innerHTML = 'Place your phone into your Cardboard viewer.'; 2502 overlay.appendChild(text); 2503 var snackbar = document.createElement('div'); 2504 var s = snackbar.style; 2505 s.backgroundColor = '#CFD8DC'; 2506 s.position = 'fixed'; 2507 s.bottom = 0; 2508 s.width = '100%'; 2509 s.height = '48px'; 2510 s.padding = '14px 24px'; 2511 s.boxSizing = 'border-box'; 2512 s.color = '#656A6B'; 2513 overlay.appendChild(snackbar); 2514 var snackbarText = document.createElement('div'); 2515 snackbarText.style.float = 'left'; 2516 snackbarText.innerHTML = 'No Cardboard viewer?'; 2517 var snackbarButton = document.createElement('a'); 2518 snackbarButton.href = 'https://www.google.com/get/cardboard/get-cardboard/'; 2519 snackbarButton.innerHTML = 'get one'; 2520 snackbarButton.target = '_blank'; 2521 var s = snackbarButton.style; 2522 s.float = 'right'; 2523 s.fontWeight = 600; 2524 s.textTransform = 'uppercase'; 2525 s.borderLeft = '1px solid gray'; 2526 s.paddingLeft = '24px';
vendor: 4,328 bytes, lines 2527-2662
2527 s.textDecoration = 'none'; 2528 s.color = '#656A6B'; 2529 snackbar.appendChild(snackbarText); 2530 snackbar.appendChild(snackbarButton); 2531 this.overlay = overlay; 2532 this.text = text; 2533 this.hide(); 2534 } 2535 RotateInstructions.prototype.show = function (parent) { 2536 if (!parent && !this.overlay.parentElement) { 2537 document.body.appendChild(this.overlay); 2538 } else if (parent) { 2539 if (this.overlay.parentElement && this.overlay.parentElement != parent) this.overlay.parentElement.removeChild(this.overlay); 2540 parent.appendChild(this.overlay); 2541 } 2542 this.overlay.style.display = 'block'; 2543 var img = this.overlay.querySelector('img'); 2544 var s = img.style; 2545 if (isLandscapeMode()) { 2546 s.width = '20%'; 2547 s.marginLeft = '40%'; 2548 s.marginTop = '3%'; 2549 } else { 2550 s.width = '50%'; 2551 s.marginLeft = '25%'; 2552 s.marginTop = '25%'; 2553 } 2554 }; 2555 RotateInstructions.prototype.hide = function () { 2556 this.overlay.style.display = 'none'; 2557 }; 2558 RotateInstructions.prototype.showTemporarily = function (ms, parent) { 2559 this.show(parent); 2560 this.timer = setTimeout(this.hide.bind(this), ms); 2561 }; 2562 RotateInstructions.prototype.disableShowTemporarily = function () { 2563 clearTimeout(this.timer); 2564 }; 2565 RotateInstructions.prototype.update = function () { 2566 this.disableShowTemporarily(); 2567 if (!isLandscapeMode() && isMobile()) { 2568 this.show(); 2569 } else { 2570 this.hide(); 2571 } 2572 }; 2573 RotateInstructions.prototype.loadIcon_ = function () { 2574 this.icon = base64('image/svg+xml', rotateInstructionsAsset); 2575 }; 2576 var DEFAULT_VIEWER = 'CardboardV1'; 2577 var VIEWER_KEY = 'WEBVR_CARDBOARD_VIEWER'; 2578 var CLASS_NAME = 'webvr-polyfill-viewer-selector'; 2579 function ViewerSelector(defaultViewer) { 2580 try { 2581 this.selectedKey = localStorage.getItem(VIEWER_KEY); 2582 } catch (error) { 2583 console.error('Failed to load viewer profile: %s', error); 2584 } 2585 if (!this.selectedKey) { 2586 this.selectedKey = defaultViewer || DEFAULT_VIEWER; 2587 } 2588 this.dialog = this.createDialog_(DeviceInfo.Viewers); 2589 this.root = null; 2590 this.onChangeCallbacks_ = []; 2591 } 2592 ViewerSelector.prototype.show = function (root) { 2593 this.root = root; 2594 root.appendChild(this.dialog); 2595 var selected = this.dialog.querySelector('#' + this.selectedKey); 2596 selected.checked = true; 2597 this.dialog.style.display = 'block'; 2598 }; 2599 ViewerSelector.prototype.hide = function () { 2600 if (this.root && this.root.contains(this.dialog)) { 2601 this.root.removeChild(this.dialog); 2602 } 2603 this.dialog.style.display = 'none'; 2604 }; 2605 ViewerSelector.prototype.getCurrentViewer = function () { 2606 return DeviceInfo.Viewers[this.selectedKey]; 2607 }; 2608 ViewerSelector.prototype.getSelectedKey_ = function () { 2609 var input = this.dialog.querySelector('input[name=field]:checked'); 2610 if (input) { 2611 return input.id; 2612 } 2613 return null; 2614 }; 2615 ViewerSelector.prototype.onChange = function (cb) { 2616 this.onChangeCallbacks_.push(cb); 2617 }; 2618 ViewerSelector.prototype.fireOnChange_ = function (viewer) { 2619 for (var i = 0; i < this.onChangeCallbacks_.length; i++) { 2620 this.onChangeCallbacks_[i](viewer); 2621 } 2622 }; 2623 ViewerSelector.prototype.onSave_ = function () { 2624 this.selectedKey = this.getSelectedKey_(); 2625 if (!this.selectedKey || !DeviceInfo.Viewers[this.selectedKey]) { 2626 console.error('ViewerSelector.onSave_: this should never happen!'); 2627 return; 2628 } 2629 this.fireOnChange_(DeviceInfo.Viewers[this.selectedKey]); 2630 try { 2631 localStorage.setItem(VIEWER_KEY, this.selectedKey); 2632 } catch (error) { 2633 console.error('Failed to save viewer profile: %s', error); 2634 } 2635 this.hide(); 2636 }; 2637 ViewerSelector.prototype.createDialog_ = function (options) { 2638 var container = document.createElement('div'); 2639 container.classList.add(CLASS_NAME); 2640 container.style.display = 'none'; 2641 var overlay = document.createElement('div'); 2642 var s = overlay.style; 2643 s.position = 'fixed'; 2644 s.left = 0; 2645 s.top = 0; 2646 s.width = '100%'; 2647 s.height = '100%'; 2648 s.background = 'rgba(0, 0, 0, 0.3)'; 2649 overlay.addEventListener('click', this.hide.bind(this)); 2650 var width = 280; 2651 var dialog = document.createElement('div'); 2652 var s = dialog.style; 2653 s.boxSizing = 'border-box'; 2654 s.position = 'fixed'; 2655 s.top = '24px'; 2656 s.left = '50%'; 2657 s.marginLeft = -width / 2 + 'px'; 2658 s.width = width + 'px'; 2659 s.padding = '24px'; 2660 s.overflow = 'hidden'; 2661 s.background = '#fafafa'; 2662 s.fontFamily = "'Roboto', sans-serif";
vendor: 8,869 bytes, lines 2663-2818
2663 s.boxShadow = '0px 5px 20px #666'; 2664 dialog.appendChild(this.createH1_('Select your viewer')); 2665 for (var id in options) { 2666 dialog.appendChild(this.createChoice_(id, options[id].label)); 2667 } 2668 dialog.appendChild(this.createButton_('Save', this.onSave_.bind(this))); 2669 container.appendChild(overlay); 2670 container.appendChild(dialog); 2671 return container; 2672 }; 2673 ViewerSelector.prototype.createH1_ = function (name) { 2674 var h1 = document.createElement('h1'); 2675 var s = h1.style; 2676 s.color = 'black'; 2677 s.fontSize = '20px'; 2678 s.fontWeight = 'bold'; 2679 s.marginTop = 0; 2680 s.marginBottom = '24px'; 2681 h1.innerHTML = name; 2682 return h1; 2683 }; 2684 ViewerSelector.prototype.createChoice_ = function (id, name) { 2685 var div = document.createElement('div'); 2686 div.style.marginTop = '8px'; 2687 div.style.color = 'black'; 2688 var input = document.createElement('input'); 2689 input.style.fontSize = '30px'; 2690 input.setAttribute('id', id); 2691 input.setAttribute('type', 'radio'); 2692 input.setAttribute('value', id); 2693 input.setAttribute('name', 'field'); 2694 var label = document.createElement('label'); 2695 label.style.marginLeft = '4px'; 2696 label.setAttribute('for', id); 2697 label.innerHTML = name; 2698 div.appendChild(input); 2699 div.appendChild(label); 2700 return div; 2701 }; 2702 ViewerSelector.prototype.createButton_ = function (label, onclick) { 2703 var button = document.createElement('button'); 2704 button.innerHTML = label; 2705 var s = button.style; 2706 s.float = 'right'; 2707 s.textTransform = 'uppercase'; 2708 s.color = '#1094f7'; 2709 s.fontSize = '14px'; 2710 s.letterSpacing = 0; 2711 s.border = 0; 2712 s.background = 'none'; 2713 s.marginTop = '16px'; 2714 button.addEventListener('click', onclick); 2715 return button; 2716 }; 2717 var commonjsGlobal$$1 = typeof window !== 'undefined' ? window : typeof commonjsGlobal$1 !== 'undefined' ? commonjsGlobal$1 : typeof self !== 'undefined' ? self : {}; 2718 function unwrapExports$$1 (x) { 2719 return x && x.__esModule ? x['default'] : x; 2720 } 2721 function createCommonjsModule$$1(fn, module) { 2722 return module = { exports: {} }, fn(module, module.exports), module.exports; 2723 } 2724 var NoSleep = createCommonjsModule$$1(function (module, exports) { 2725 (function webpackUniversalModuleDefinition(root, factory) { 2726 module.exports = factory(); 2727 })(commonjsGlobal$$1, function() { 2728 return (function(modules) { 2729 var installedModules = {}; 2730 function __webpack_require__(moduleId) { 2731 if(installedModules[moduleId]) { 2732 return installedModules[moduleId].exports; 2733 } 2734 var module = installedModules[moduleId] = { 2735 i: moduleId, 2736 l: false, 2737 exports: {} 2738 }; 2739 modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 2740 module.l = true; 2741 return module.exports; 2742 } 2743 __webpack_require__.m = modules; 2744 __webpack_require__.c = installedModules; 2745 __webpack_require__.d = function(exports, name, getter) { 2746 if(!__webpack_require__.o(exports, name)) { 2747 Object.defineProperty(exports, name, { 2748 configurable: false, 2749 enumerable: true, 2750 get: getter 2751 }); 2752 } 2753 }; 2754 __webpack_require__.n = function(module) { 2755 var getter = module && module.__esModule ? 2756 function getDefault() { return module['default']; } : 2757 function getModuleExports() { return module; }; 2758 __webpack_require__.d(getter, 'a', getter); 2759 return getter; 2760 }; 2761 __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; 2762 __webpack_require__.p = ""; 2763 return __webpack_require__(__webpack_require__.s = 0); 2764 }) 2765 ([ 2766 (function(module, exports, __webpack_require__) { 2767 var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { 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); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 2768 function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 2769 var mediaFile = __webpack_require__(1); 2770 var oldIOS = typeof navigator !== 'undefined' && parseFloat(('' + (/CPU.*OS ([0-9_]{3,4})[0-9_]{0,1}|(CPU like).*AppleWebKit.*Mobile/i.exec(navigator.userAgent) || [0, ''])[1]).replace('undefined', '3_2').replace('_', '.').replace('_', '')) < 10 && !window.MSStream; 2771 var NoSleep = function () { 2772 function NoSleep() { 2773 _classCallCheck(this, NoSleep); 2774 if (oldIOS) { 2775 this.noSleepTimer = null; 2776 } else { 2777 this.noSleepVideo = document.createElement('video'); 2778 this.noSleepVideo.setAttribute('playsinline', ''); 2779 this.noSleepVideo.setAttribute('src', mediaFile); 2780 this.noSleepVideo.addEventListener('timeupdate', function (e) { 2781 if (this.noSleepVideo.currentTime > 0.5) { 2782 this.noSleepVideo.currentTime = Math.random(); 2783 } 2784 }.bind(this)); 2785 } 2786 } 2787 _createClass(NoSleep, [{ 2788 key: 'enable', 2789 value: function enable() { 2790 if (oldIOS) { 2791 this.disable(); 2792 this.noSleepTimer = window.setInterval(function () { 2793 window.location.href = '/'; 2794 window.setTimeout(window.stop, 0); 2795 }, 15000); 2796 } else { 2797 this.noSleepVideo.play(); 2798 } 2799 } 2800 }, { 2801 key: 'disable', 2802 value: function disable() { 2803 if (oldIOS) { 2804 if (this.noSleepTimer) { 2805 window.clearInterval(this.noSleepTimer); 2806 this.noSleepTimer = null; 2807 } 2808 } else { 2809 this.noSleepVideo.pause(); 2810 } 2811 } 2812 }]); 2813 return NoSleep; 2814 }(); 2815 module.exports = NoSleep; 2816 }), 2817 (function(module, exports, __webpack_require__) { 2818 module.exports = 'data:video/mp4;base64,AAAAIGZ0eXBtcDQyAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAACKBtZGF0AAAC8wYF///v3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE0MiByMjQ3OSBkZDc5YTYxIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAxNCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTEgcmVmPTEgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9MiBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0wIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MCA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0wIHRocmVhZHM9NiBsb29rYWhlYWRfdGhyZWFkcz0xIHNsaWNlZF90aHJlYWRzPTAgbnI9MCBkZWNpbWF0ZT0xIGludGVybGFjZWQ9MCBibHVyYXlfY29tcGF0PTAgY29uc3RyYWluZWRfaW50cmE9MCBiZnJhbWVzPTMgYl9weXJhbWlkPTIgYl9hZGFwdD0xIGJfYmlhcz0wIGRpcmVjdD0xIHdlaWdodGI9MSBvcGVuX2dvcD0wIHdlaWdodHA9MSBrZXlpbnQ9MzAwIGtleWludF9taW49MzAgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD0xMCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIwLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IHZidl9tYXhyYXRlPTIwMDAwIHZidl9idWZzaXplPTI1MDAwIGNyZl9tYXg9MC4wIG5hbF9ocmQ9bm9uZSBmaWxsZXI9MCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAAOWWIhAA3//p+C7v8tDDSTjf97w55i3SbRPO4ZY+hkjD5hbkAkL3zpJ6h/LR1CAABzgB1kqqzUorlhQAAAAxBmiQYhn/+qZYADLgAAAAJQZ5CQhX/AAj5IQADQGgcIQADQGgcAAAACQGeYUQn/wALKCEAA0BoHAAAAAkBnmNEJ/8ACykhAANAaBwhAANAaBwAAAANQZpoNExDP/6plgAMuSEAA0BoHAAAAAtBnoZFESwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBnqVEJ/8ACykhAANAaBwAAAAJAZ6nRCf/AAsoIQADQGgcIQADQGgcAAAADUGarDRMQz/+qZYADLghAANAaBwAAAALQZ7KRRUsK/8ACPkhAANAaBwAAAAJAZ7pRCf/AAsoIQADQGgcIQADQGgcAAAACQGe60Qn/wALKCEAA0BoHAAAAA1BmvA0TEM//qmWAAy5IQADQGgcIQADQGgcAAAAC0GfDkUVLCv/AAj5IQADQGgcAAAACQGfLUQn/wALKSEAA0BoHCEAA0BoHAAAAAkBny9EJ/8ACyghAANAaBwAAAANQZs0NExDP/6plgAMuCEAA0BoHAAAAAtBn1JFFSwr/wAI+SEAA0BoHCEAA0BoHAAAAAkBn3FEJ/8ACyghAANAaBwAAAAJAZ9zRCf/AAsoIQADQGgcIQADQGgcAAAADUGbeDRMQz/+qZYADLkhAANAaBwAAAALQZ+WRRUsK/8ACPghAANAaBwhAANAaBwAAAAJAZ+1RCf/AAspIQADQGgcAAAACQGft0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bm7w0TEM//qmWAAy4IQADQGgcAAAAC0Gf2kUVLCv/AAj5IQADQGgcAAAACQGf+UQn/wALKCEAA0BoHCEAA0BoHAAAAAkBn/tEJ/8ACykhAANAaBwAAAANQZvgNExDP/6plgAMuSEAA0BoHCEAA0BoHAAAAAtBnh5FFSwr/wAI+CEAA0BoHAAAAAkBnj1EJ/8ACyghAANAaBwhAANAaBwAAAAJAZ4/RCf/AAspIQADQGgcAAAADUGaJDRMQz/+qZYADLghAANAaBwAAAALQZ5CRRUsK/8ACPkhAANAaBwhAANAaBwAAAAJAZ5hRCf/AAsoIQADQGgcAAAACQGeY0Qn/wALKSEAA0BoHCEAA0BoHAAAAA1Bmmg0TEM//qmWAAy5IQADQGgcAAAAC0GehkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGepUQn/wALKSEAA0BoHAAAAAkBnqdEJ/8ACyghAANAaBwAAAANQZqsNExDP/6plgAMuCEAA0BoHCEAA0BoHAAAAAtBnspFFSwr/wAI+SEAA0BoHAAAAAkBnulEJ/8ACyghAANAaBwhAANAaBwAAAAJAZ7rRCf/AAsoIQADQGgcAAAADUGa8DRMQz/+qZYADLkhAANAaBwhAANAaBwAAAALQZ8ORRUsK/8ACPkhAANAaBwAAAAJAZ8tRCf/AAspIQADQGgcIQADQGgcAAAACQGfL0Qn/wALKCEAA0BoHAAAAA1BmzQ0TEM//qmWAAy4IQADQGgcAAAAC0GfUkUVLCv/AAj5IQADQGgcIQADQGgcAAAACQGfcUQn/wALKCEAA0BoHAAAAAkBn3NEJ/8ACyghAANAaBwhAANAaBwAAAANQZt4NExC//6plgAMuSEAA0BoHAAAAAtBn5ZFFSwr/wAI+CEAA0BoHCEAA0BoHAAAAAkBn7VEJ/8ACykhAANAaBwAAAAJAZ+3RCf/AAspIQADQGgcAAAADUGbuzRMQn/+nhAAYsAhAANAaBwhAANAaBwAAAAJQZ/aQhP/AAspIQADQGgcAAAACQGf+U
2818Qn/wALKCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHCEAA0BoHAAACiFtb292AAAAbG12aGQAAAAA1YCCX9WAgl8AAAPoAAAH/AABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAGGlvZHMAAAAAEICAgAcAT////v7/AAAF+XRyYWsAAABcdGtoZAAAAAPVgIJf1YCCXwAAAAEAAAAAAAAH0AAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAygAAAMoAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAB9AAABdwAAEAAAAABXFtZGlhAAAAIG1kaGQAAAAA1YCCX9WAgl8AAV+QAAK/IFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAUcbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAAE3HN0YmwAAACYc3RzZAAAAAAAAAABAAAAiGF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAygDKAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAyYXZjQwFNQCj/4QAbZ01AKOyho3ySTUBAQFAAAAMAEAAr8gDxgxlgAQAEaO+G8gAAABhzdHRzAAAAAAAAAAEAAAA8AAALuAAAABRzdHNzAAAAAAAAAAEAAAABAAAB8GN0dHMAAAAAAAAAPAAAAAEAABdwAAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAADqYAAAAAQAAF3AAAAABAAAAAAAAAAEAAAu4AAAAAQAAOpgAAAABAAAXcAAAAAEAAAAAAAAAAQAAC7gAAAABAAA6mAAAAAEAABdwAAAAAQAAAAAAAAABAAALuAAAAAEAAC7gAAAAAQAAF3AAAAABAAAAAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAEEc3RzegAAAAAAAAAAAAAAPAAAAzQAAAAQAAAADQAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAAPAAAADQAAAA0AAAARAAAADwAAAA0AAAANAAAAEQAAAA8AAAANAAAADQAAABEAAAANAAAADQAAAQBzdGNvAAAAAAAAADwAAAAwAAADZAAAA3QAAAONAAADoAAAA7kAAAPQAAAD6wAAA/4AAAQXAAAELgAABEMAAARcAAAEbwAABIwAAAShAAAEugAABM0AAATkAAAE/wAABRIAAAUrAAAFQgAABV0AAAVwAAAFiQAABaAAAAW1AAAFzgAABeEAAAX+AAAGEwAABiwAAAY/AAAGVgAABnEAAAaEAAAGnQAABrQAAAbPAAAG4gAABvUAAAcSAAAHJwAAB0AAAAdTAAAHcAAAB4UAAAeeAAAHsQAAB8gAAAfjAAAH9gAACA8AAAgmAAAIQQAACFQAAAhnAAAIhAAACJcAAAMsdHJhawAAAFx0a2hkAAAAA9WAgl/VgIJfAAAAAgAAAAAAAAf8AAAAAAAAAAAAAAABAQAAAAABAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAACsm1kaWEAAAAgbWRoZAAAAADVgIJf1YCCXwAArEQAAWAAVcQAAAAAACdoZGxyAAAAAAAAAABzb3VuAAAAAAAAAAAAAAAAU3RlcmVvAAAAAmNtaW5mAAAAEHNtaGQAAAAAAAAAAAAAACRkaW5mAAAAHGRyZWYAAAAAAAAAAQAAAAx1cmwgAAAAAQAAAidzdGJsAAAAZ3N0c2QAAAAAAAAAAQAAAFdtcDRhAAAAAAAAAAEAAAAAAAAAAAACABAAAAAArEQAAAAAADNlc2RzAAAAAAOAgIAiAAIABICAgBRAFQAAAAADDUAAAAAABYCAgAISEAaAgIABAgAAABhzdHRzAAAAAAAAAAEAAABYAAAEAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAAAGAAAAWAAAAXBzdGNvAAAAAAAAAFgAAAOBAAADhwAAA5oAAAOtAAADswAAA8oAAAPfAAAD5QAAA/gAAAQLAAAEEQAABCgAAAQ9AAAEUAAABFYAAARpAAAEgAAABIYAAASbAAAErgAABLQAAATHAAAE3gAABPMAAAT5AAAFDAAABR8AAAUlAAAFPAAABVEAAAVXAAAFagAABX0AAAWDAAAFmgAABa8AAAXCAAAFyAAABdsAAAXyAAAF+AAABg0AAAYgAAAGJgAABjkAAAZQAAAGZQAABmsAAAZ+AAAGkQAABpcAAAauAAAGwwAABskAAAbcAAAG7wAABwYAAAcMAAAHIQAABzQAAAc6AAAHTQAAB2QAAAdqAAAHfwAAB5IAAAeYAAAHqwAAB8IAAAfXAAAH3QAAB/AAAAgDAAAICQAACCAAAAg1AAAIOwAACE4AAAhhAAAIeAAACH4AAAiRAAAIpAAACKoAAAiwAAAItgAACLwAAAjCAAAAFnVkdGEAAAAObmFtZVN0ZXJlbwAAAHB1ZHRhAAAAaG1ldGEAAAAAAAAAIWhkbHIAAAAAAAAAAG1kaXJhcHBsAAAAAAAAAAAAAAAAO2lsc3QAAAAzqXRvbwAAACtkYXRhAAAAAQAAAABIYW5kQnJha2UgMC4xMC4yIDIwMTUwNjExMDA='; 2819 }) 2820 ]); 2821 }); 2822 }); 2823 var NoSleep$1 = unwrapExports$$1(NoSleep); 2824 var nextDisplayId = 1000; 2825 var defaultLeftBounds = [0, 0, 0.5, 1]; 2826 var defaultRightBounds = [0.5, 0, 0.5, 1]; 2827 var raf = window.requestAnimationFrame; 2828 var caf = window.cancelAnimationFrame; 2829 function VRFrameData() { 2830 this.leftProjectionMatrix = new Float32Array(16);
vendor: 23,756 bytes, lines 2831-3499
2831 this.leftViewMatrix = new Float32Array(16); 2832 this.rightProjectionMatrix = new Float32Array(16); 2833 this.rightViewMatrix = new Float32Array(16); 2834 this.pose = null; 2835 } 2836 function VRDisplayCapabilities(config) { 2837 Object.defineProperties(this, { 2838 hasPosition: { 2839 writable: false, enumerable: true, value: config.hasPosition 2840 }, 2841 hasExternalDisplay: { 2842 writable: false, enumerable: true, value: config.hasExternalDisplay 2843 }, 2844 canPresent: { 2845 writable: false, enumerable: true, value: config.canPresent 2846 }, 2847 maxLayers: { 2848 writable: false, enumerable: true, value: config.maxLayers 2849 }, 2850 hasOrientation: { 2851 enumerable: true, get: function get() { 2852 deprecateWarning('VRDisplayCapabilities.prototype.hasOrientation', 'VRDisplay.prototype.getFrameData'); 2853 return config.hasOrientation; 2854 } 2855 } 2856 }); 2857 } 2858 function VRDisplay(config) { 2859 config = config || {}; 2860 var USE_WAKELOCK = 'wakelock' in config ? config.wakelock : true; 2861 this.isPolyfilled = true; 2862 this.displayId = nextDisplayId++; 2863 this.displayName = ''; 2864 this.depthNear = 0.01; 2865 this.depthFar = 10000.0; 2866 this.isPresenting = false; 2867 Object.defineProperty(this, 'isConnected', { 2868 get: function get() { 2869 deprecateWarning('VRDisplay.prototype.isConnected', 'VRDisplayCapabilities.prototype.hasExternalDisplay'); 2870 return false; 2871 } 2872 }); 2873 this.capabilities = new VRDisplayCapabilities({ 2874 hasPosition: false, 2875 hasOrientation: false, 2876 hasExternalDisplay: false, 2877 canPresent: false, 2878 maxLayers: 1 2879 }); 2880 this.stageParameters = null; 2881 this.waitingForPresent_ = false; 2882 this.layer_ = null; 2883 this.originalParent_ = null; 2884 this.fullscreenElement_ = null; 2885 this.fullscreenWrapper_ = null; 2886 this.fullscreenElementCachedStyle_ = null; 2887 this.fullscreenEventTarget_ = null; 2888 this.fullscreenChangeHandler_ = null; 2889 this.fullscreenErrorHandler_ = null; 2890 if (USE_WAKELOCK && isMobile()) { 2891 this.wakelock_ = new NoSleep$1(); 2892 } 2893 } 2894 VRDisplay.prototype.getFrameData = function (frameData) { 2895 return frameDataFromPose(frameData, this._getPose(), this); 2896 }; 2897 VRDisplay.prototype.getPose = function () { 2898 deprecateWarning('VRDisplay.prototype.getPose', 'VRDisplay.prototype.getFrameData'); 2899 return this._getPose(); 2900 }; 2901 VRDisplay.prototype.resetPose = function () { 2902 deprecateWarning('VRDisplay.prototype.resetPose'); 2903 return this._resetPose(); 2904 }; 2905 VRDisplay.prototype.getImmediatePose = function () { 2906 deprecateWarning('VRDisplay.prototype.getImmediatePose', 'VRDisplay.prototype.getFrameData'); 2907 return this._getPose(); 2908 }; 2909 VRDisplay.prototype.requestAnimationFrame = function (callback) { 2910 return raf(callback); 2911 }; 2912 VRDisplay.prototype.cancelAnimationFrame = function (id) { 2913 return caf(id); 2914 }; 2915 VRDisplay.prototype.wrapForFullscreen = function (element) { 2916 if (isIOS()) { 2917 return element; 2918 } 2919 if (!this.fullscreenWrapper_) { 2920 this.fullscreenWrapper_ = document.createElement('div'); 2921 var cssProperties = ['height: ' + Math.min(screen.height, screen.width) + 'px !important', 'top: 0 !important', 'left: 0 !important', 'right: 0 !important', 'border: 0', 'margin: 0', 'padding: 0', 'z-index: 999999 !important', 'position: fixed']; 2922 this.fullscreenWrapper_.setAttribute('style', cssProperties.join('; ') + ';'); 2923 this.fullscreenWrapper_.classList.add('webvr-polyfill-fullscreen-wrapper'); 2924 } 2925 if (this.fullscreenElement_ == element) { 2926 return this.fullscreenWrapper_; 2927 } 2928 if (this.fullscreenElement_) { 2929 if (this.originalParent_) { 2930 this.originalParent_.appendChild(this.fullscreenElement_); 2931 } else { 2932 this.fullscreenElement_.parentElement.removeChild(this.fullscreenElement_); 2933 } 2934 } 2935 this.fullscreenElement_ = element; 2936 this.originalParent_ = element.parentElement; 2937 if (!this.originalParent_) { 2938 document.body.appendChild(element); 2939 } 2940 if (!this.fullscreenWrapper_.parentElement) { 2941 var parent = this.fullscreenElement_.parentElement; 2942 parent.insertBefore(this.fullscreenWrapper_, this.fullscreenElement_); 2943 parent.removeChild(this.fullscreenElement_); 2944 } 2945 this.fullscreenWrapper_.insertBefore(this.fullscreenElement_, this.fullscreenWrapper_.firstChild); 2946 this.fullscreenElementCachedStyle_ = this.fullscreenElement_.getAttribute('style'); 2947 var self = this; 2948 function applyFullscreenElementStyle() { 2949 if (!self.fullscreenElement_) { 2950 return; 2951 } 2952 var cssProperties = ['position: absolute', 'top: 0', 'left: 0', 'width: ' + Math.max(screen.width, screen.height) + 'px', 'height: ' + Math.min(screen.height, screen.width) + 'px', 'border: 0', 'margin: 0', 'padding: 0']; 2953 self.fullscreenElement_.setAttribute('style', cssProperties.join('; ') + ';'); 2954 } 2955 applyFullscreenElementStyle(); 2956 return this.fullscreenWrapper_; 2957 }; 2958 VRDisplay.prototype.removeFullscreenWrapper = function () { 2959 if (!this.fullscreenElement_) { 2960 return; 2961 } 2962 var element = this.fullscreenElement_; 2963 if (this.fullscreenElementCachedStyle_) { 2964 element.setAttribute('style', this.fullscreenElementCachedStyle_); 2965 } else { 2966 element.removeAttribute('style'); 2967 } 2968 this.fullscreenElement_ = null; 2969 this.fullscreenElementCachedStyle_ = null; 2970 var parent = this.fullscreenWrapper_.parentElement; 2971 this.fullscreenWrapper_.removeChild(element); 2972 if (this.originalParent_ === parent) { 2973 parent.insertBefore(element, this.fullscreenWrapper_); 2974 } 2975 else if (this.originalParent_) { 2976 this.originalParent_.appendChild(element); 2977 } 2978 parent.removeChild(this.fullscreenWrapper_); 2979 return element; 2980 }; 2981 VRDisplay.prototype.requestPresent = function (layers) { 2982 var wasPresenting = this.isPresenting; 2983 var self = this; 2984 if (!(layers instanceof Array)) { 2985 deprecateWarning('VRDisplay.prototype.requestPresent with non-array argument', 'an array of VRLayers as the first argument'); 2986 layers = [layers]; 2987 } 2988 return new Promise(function (resolve, reject) { 2989 if (!self.capabilities.canPresent) { 2990 reject(new Error('VRDisplay is not capable of presenting.')); 2991 return; 2992 } 2993 if (layers.length == 0 || layers.length > self.capabilities.maxLayers) { 2994 reject(new Error('Invalid number of layers.')); 2995 return; 2996 } 2997 var incomingLayer = layers[0]; 2998 if (!incomingLayer.source) { 2999 resolve(); 3000 return; 3001 } 3002 var leftBounds = incomingLayer.leftBounds || defaultLeftBounds; 3003 var rightBounds = incomingLayer.rightBounds || defaultRightBounds; 3004 if (wasPresenting) { 3005 var layer = self.layer_; 3006 if (layer.source !== incomingLayer.source) { 3007 layer.source = incomingLayer.source; 3008 } 3009 for (var i = 0; i < 4; i++) { 3010 layer.leftBounds[i] = leftBounds[i]; 3011 layer.rightBounds[i] = rightBounds[i]; 3012 } 3013 self.wrapForFullscreen(self.layer_.source); 3014 self.updatePresent_(); 3015 resolve(); 3016 return; 3017 } 3018 self.layer_ = { 3019 predistorted: incomingLayer.predistorted, 3020 source: incomingLayer.source, 3021 leftBounds: leftBounds.slice(0), 3022 rightBounds: rightBounds.slice(0) 3023 }; 3024 self.waitingForPresent_ = false; 3025 if (self.layer_ && self.layer_.source) { 3026 var fullscreenElement = self.wrapForFullscreen(self.layer_.source); 3027 var onFullscreenChange = function onFullscreenChange() { 3028 var actualFullscreenElement = getFullscreenElement(); 3029 self.isPresenting = fullscreenElement === actualFullscreenElement; 3030 if (self.isPresenting) { 3031 if (screen.orientation && screen.orientation.lock) { 3032 screen.orientation.lock('landscape-primary').catch(function (error) { 3033 console.error('screen.orientation.lock() failed due to', error.message); 3034 }); 3035 } 3036 self.waitingForPresent_ = false; 3037 self.beginPresent_(); 3038 resolve(); 3039 } else { 3040 if (screen.orientation && screen.orientation.unlock) { 3041 screen.orientation.unlock(); 3042 } 3043 self.removeFullscreenWrapper(); 3044 self.disableWakeLock(); 3045 self.endPresent_(); 3046 self.removeFullscreenListeners_(); 3047 } 3048 self.fireVRDisplayPresentChange_(); 3049 }; 3050 var onFullscreenError = function onFullscreenError() { 3051 if (!self.waitingForPresent_) { 3052 return; 3053 } 3054 self.removeFullscreenWrapper(); 3055 self.removeFullscreenListeners_(); 3056 self.disableWakeLock(); 3057 self.waitingForPresent_ = false; 3058 self.isPresenting = false; 3059 reject(new Error('Unable to present.')); 3060 }; 3061 self.addFullscreenListeners_(fullscreenElement, onFullscreenChange, onFullscreenError); 3062 if (requestFullscreen(fullscreenElement)) { 3063 self.enableWakeLock(); 3064 self.waitingForPresent_ = true; 3065 } else if (isIOS() || isWebViewAndroid()) { 3066 self.enableWakeLock(); 3067 self.isPresenting = true; 3068 self.beginPresent_(); 3069 self.fireVRDisplayPresentChange_(); 3070 resolve(); 3071 } 3072 } 3073 if (!self.waitingForPresent_ && !isIOS()) { 3074 exitFullscreen(); 3075 reject(new Error('Unable to present.')); 3076 } 3077 }); 3078 }; 3079 VRDisplay.prototype.exitPresent = function () { 3080 var wasPresenting = this.isPresenting; 3081 var self = this; 3082 this.isPresenting = false; 3083 this.layer_ = null; 3084 this.disableWakeLock(); 3085 return new Promise(function (resolve, reject) { 3086 if (wasPresenting) { 3087 if (!exitFullscreen() && isIOS()) { 3088 self.endPresent_(); 3089 self.fireVRDisplayPresentChange_(); 3090 } 3091 if (isWebViewAndroid()) { 3092 self.removeFullscreenWrapper(); 3093 self.removeFullscreenListeners_(); 3094 self.endPresent_(); 3095 self.fireVRDisplayPresentChange_(); 3096 } 3097 resolve(); 3098 } else { 3099 reject(new Error('Was not presenting to VRDisplay.')); 3100 } 3101 }); 3102 }; 3103 VRDisplay.prototype.getLayers = function () { 3104 if (this.layer_) { 3105 return [this.layer_]; 3106 } 3107 return []; 3108 }; 3109 VRDisplay.prototype.fireVRDisplayPresentChange_ = function () { 3110 var event = new CustomEvent('vrdisplaypresentchange', { detail: { display: this } }); 3111 window.dispatchEvent(event); 3112 }; 3113 VRDisplay.prototype.fireVRDisplayConnect_ = function () { 3114 var event = new CustomEvent('vrdisplayconnect', { detail: { display: this } }); 3115 window.dispatchEvent(event); 3116 }; 3117 VRDisplay.prototype.addFullscreenListeners_ = function (element, changeHandler, errorHandler) { 3118 this.removeFullscreenListeners_(); 3119 this.fullscreenEventTarget_ = element; 3120 this.fullscreenChangeHandler_ = changeHandler; 3121 this.fullscreenErrorHandler_ = errorHandler; 3122 if (changeHandler) { 3123 if (document.fullscreenEnabled) { 3124 element.addEventListener('fullscreenchange', changeHandler, false); 3125 } else if (document.webkitFullscreenEnabled) { 3126 element.addEventListener('webkitfullscreenchange', changeHandler, false); 3127 } else if (document.mozFullScreenEnabled) { 3128 document.addEventListener('mozfullscreenchange', changeHandler, false); 3129 } else if (document.msFullscreenEnabled) { 3130 element.addEventListener('msfullscreenchange', changeHandler, false); 3131 } 3132 } 3133 if (errorHandler) { 3134 if (document.fullscreenEnabled) { 3135 element.addEventListener('fullscreenerror', errorHandler, false); 3136 } else if (document.webkitFullscreenEnabled) { 3137 element.addEventListener('webkitfullscreenerror', errorHandler, false); 3138 } else if (document.mozFullScreenEnabled) { 3139 document.addEventListener('mozfullscreenerror', errorHandler, false); 3140 } else if (document.msFullscreenEnabled) { 3141 element.addEventListener('msfullscreenerror', errorHandler, false); 3142 } 3143 } 3144 }; 3145 VRDisplay.prototype.removeFullscreenListeners_ = function () { 3146 if (!this.fullscreenEventTarget_) return; 3147 var element = this.fullscreenEventTarget_; 3148 if (this.fullscreenChangeHandler_) { 3149 var changeHandler = this.fullscreenChangeHandler_; 3150 element.removeEventListener('fullscreenchange', changeHandler, false); 3151 element.removeEventListener('webkitfullscreenchange', changeHandler, false); 3152 document.removeEventListener('mozfullscreenchange', changeHandler, false); 3153 element.removeEventListener('msfullscreenchange', changeHandler, false); 3154 } 3155 if (this.fullscreenErrorHandler_) { 3156 var errorHandler = this.fullscreenErrorHandler_; 3157 element.removeEventListener('fullscreenerror', errorHandler, false); 3158 element.removeEventListener('webkitfullscreenerror', errorHandler, false); 3159 document.removeEventListener('mozfullscreenerror', errorHandler, false); 3160 element.removeEventListener('msfullscreenerror', errorHandler, false); 3161 } 3162 this.fullscreenEventTarget_ = null; 3163 this.fullscreenChangeHandler_ = null; 3164 this.fullscreenErrorHandler_ = null; 3165 }; 3166 VRDisplay.prototype.enableWakeLock = function () { 3167 if (this.wakelock_) { 3168 this.wakelock_.enable(); 3169 } 3170 }; 3171 VRDisplay.prototype.disableWakeLock = function () { 3172 if (this.wakelock_) { 3173 this.wakelock_.disable(); 3174 } 3175 }; 3176 VRDisplay.prototype.beginPresent_ = function () { 3177 }; 3178 VRDisplay.prototype.endPresent_ = function () { 3179 }; 3180 VRDisplay.prototype.submitFrame = function (pose) { 3181 }; 3182 VRDisplay.prototype.getEyeParameters = function (whichEye) { 3183 return null; 3184 }; 3185 var config = { 3186 ADDITIONAL_VIEWERS: [], 3187 DEFAULT_VIEWER: '', 3188 MOBILE_WAKE_LOCK: true, 3189 DEBUG: false, 3190 DPDB_URL: 'https://dpdb.webvr.rocks/dpdb.json', 3191 K_FILTER: 0.98, 3192 PREDICTION_TIME_S: 0.040, 3193 CARDBOARD_UI_DISABLED: false, 3194 ROTATE_INSTRUCTIONS_DISABLED: false, 3195 YAW_ONLY: false, 3196 BUFFER_SCALE: 0.5, 3197 DIRTY_SUBMIT_FRAME_BINDINGS: false 3198 }; 3199 var Eye = { 3200 LEFT: 'left', 3201 RIGHT: 'right' 3202 }; 3203 function CardboardVRDisplay(config$$1) { 3204 var defaults = extend({}, config); 3205 config$$1 = extend(defaults, config$$1 || {}); 3206 VRDisplay.call(this, { 3207 wakelock: config$$1.MOBILE_WAKE_LOCK 3208 }); 3209 this.config = config$$1; 3210 this.displayName = 'Cardboard VRDisplay'; 3211 this.capabilities = new VRDisplayCapabilities({ 3212 hasPosition: false, 3213 hasOrientation: true, 3214 hasExternalDisplay: false, 3215 canPresent: true, 3216 maxLayers: 1 3217 }); 3218 this.stageParameters = null; 3219 this.bufferScale_ = this.config.BUFFER_SCALE; 3220 this.poseSensor_ = new PoseSensor(this.config); 3221 this.distorter_ = null; 3222 this.cardboardUI_ = null; 3223 this.dpdb_ = new Dpdb(this.config.DPDB_URL, this.onDeviceParamsUpdated_.bind(this)); 3224 this.deviceInfo_ = new DeviceInfo(this.dpdb_.getDeviceParams(), config$$1.ADDITIONAL_VIEWERS); 3225 this.viewerSelector_ = new ViewerSelector(config$$1.DEFAULT_VIEWER); 3226 this.viewerSelector_.onChange(this.onViewerChanged_.bind(this)); 3227 this.deviceInfo_.setViewer(this.viewerSelector_.getCurrentViewer()); 3228 if (!this.config.ROTATE_INSTRUCTIONS_DISABLED) { 3229 this.rotateInstructions_ = new RotateInstructions(); 3230 } 3231 if (isIOS()) { 3232 window.addEventListener('resize', this.onResize_.bind(this)); 3233 } 3234 } 3235 CardboardVRDisplay.prototype = Object.create(VRDisplay.prototype); 3236 CardboardVRDisplay.prototype._getPose = function () { 3237 return { 3238 position: null, 3239 orientation: this.poseSensor_.getOrientation(), 3240 linearVelocity: null, 3241 linearAcceleration: null, 3242 angularVelocity: null, 3243 angularAcceleration: null 3244 }; 3245 }; 3246 CardboardVRDisplay.prototype._resetPose = function () { 3247 if (this.poseSensor_.resetPose) { 3248 this.poseSensor_.resetPose(); 3249 } 3250 }; 3251 CardboardVRDisplay.prototype._getFieldOfView = function (whichEye) { 3252 var fieldOfView; 3253 if (whichEye == Eye.LEFT) { 3254 fieldOfView = this.deviceInfo_.getFieldOfViewLeftEye(); 3255 } else if (whichEye == Eye.RIGHT) { 3256 fieldOfView = this.deviceInfo_.getFieldOfViewRightEye(); 3257 } else { 3258 console.error('Invalid eye provided: %s', whichEye); 3259 return null; 3260 } 3261 return fieldOfView; 3262 }; 3263 CardboardVRDisplay.prototype._getEyeOffset = function (whichEye) { 3264 var offset; 3265 if (whichEye == Eye.LEFT) { 3266 offset = [-this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0]; 3267 } else if (whichEye == Eye.RIGHT) { 3268 offset = [this.deviceInfo_.viewer.interLensDistance * 0.5, 0.0, 0.0]; 3269 } else { 3270 console.error('Invalid eye provided: %s', whichEye); 3271 return null; 3272 } 3273 return offset; 3274 }; 3275 CardboardVRDisplay.prototype.getEyeParameters = function (whichEye) { 3276 var offset = this._getEyeOffset(whichEye); 3277 var fieldOfView = this._getFieldOfView(whichEye); 3278 var eyeParams = { 3279 offset: offset, 3280 renderWidth: this.deviceInfo_.device.width * 0.5 * this.bufferScale_, 3281 renderHeight: this.deviceInfo_.device.height * this.bufferScale_ 3282 }; 3283 Object.defineProperty(eyeParams, 'fieldOfView', { 3284 enumerable: true, 3285 get: function get() { 3286 deprecateWarning('VRFieldOfView', 'VRFrameData\'s projection matrices'); 3287 return fieldOfView; 3288 } 3289 }); 3290 return eyeParams; 3291 }; 3292 CardboardVRDisplay.prototype.onDeviceParamsUpdated_ = function (newParams) { 3293 if (this.config.DEBUG) { 3294 console.log('DPDB reported that device params were updated.'); 3295 } 3296 this.deviceInfo_.updateDeviceParams(newParams); 3297 if (this.distorter_) { 3298 this.distorter_.updateDeviceInfo(this.deviceInfo_); 3299 } 3300 }; 3301 CardboardVRDisplay.prototype.updateBounds_ = function () { 3302 if (this.layer_ && this.distorter_ && (this.layer_.leftBounds || this.layer_.rightBounds)) { 3303 this.distorter_.setTextureBounds(this.layer_.leftBounds, this.layer_.rightBounds); 3304 } 3305 }; 3306 CardboardVRDisplay.prototype.beginPresent_ = function () { 3307 var gl = this.layer_.source.getContext('webgl'); 3308 if (!gl) gl = this.layer_.source.getContext('experimental-webgl'); 3309 if (!gl) gl = this.layer_.source.getContext('webgl2'); 3310 if (!gl) return; 3311 if (this.layer_.predistorted) { 3312 if (!this.config.CARDBOARD_UI_DISABLED) { 3313 gl.canvas.width = getScreenWidth() * this.bufferScale_; 3314 gl.canvas.height = getScreenHeight() * this.bufferScale_; 3315 this.cardboardUI_ = new CardboardUI(gl); 3316 } 3317 } else { 3318 if (!this.config.CARDBOARD_UI_DISABLED) { 3319 this.cardboardUI_ = new CardboardUI(gl); 3320 } 3321 this.distorter_ = new CardboardDistorter(gl, this.cardboardUI_, this.config.BUFFER_SCALE, this.config.DIRTY_SUBMIT_FRAME_BINDINGS); 3322 this.distorter_.updateDeviceInfo(this.deviceInfo_); 3323 } 3324 if (this.cardboardUI_) { 3325 this.cardboardUI_.listen(function (e) { 3326 this.viewerSelector_.show(this.layer_.source.parentElement); 3327 e.stopPropagation(); 3328 e.preventDefault(); 3329 }.bind(this), function (e) { 3330 this.exitPresent(); 3331 e.stopPropagation(); 3332 e.preventDefault(); 3333 }.bind(this)); 3334 } 3335 if (this.rotateInstructions_) { 3336 if (isLandscapeMode() && isMobile()) { 3337 this.rotateInstructions_.showTemporarily(3000, this.layer_.source.parentElement); 3338 } else { 3339 this.rotateInstructions_.update(); 3340 } 3341 } 3342 this.orientationHandler = this.onOrientationChange_.bind(this); 3343 window.addEventListener('orientationchange', this.orientationHandler); 3344 this.vrdisplaypresentchangeHandler = this.updateBounds_.bind(this); 3345 window.addEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler); 3346 this.fireVRDisplayDeviceParamsChange_(); 3347 }; 3348 CardboardVRDisplay.prototype.endPresent_ = function () { 3349 if (this.distorter_) { 3350 this.distorter_.destroy(); 3351 this.distorter_ = null; 3352 } 3353 if (this.cardboardUI_) { 3354 this.cardboardUI_.destroy(); 3355 this.cardboardUI_ = null; 3356 } 3357 if (this.rotateInstructions_) { 3358 this.rotateInstructions_.hide(); 3359 } 3360 this.viewerSelector_.hide(); 3361 window.removeEventListener('orientationchange', this.orientationHandler); 3362 window.removeEventListener('vrdisplaypresentchange', this.vrdisplaypresentchangeHandler); 3363 }; 3364 CardboardVRDisplay.prototype.updatePresent_ = function () { 3365 this.endPresent_(); 3366 this.beginPresent_(); 3367 }; 3368 CardboardVRDisplay.prototype.submitFrame = function (pose) { 3369 if (this.distorter_) { 3370 this.updateBounds_(); 3371 this.distorter_.submitFrame(); 3372 } else if (this.cardboardUI_ && this.layer_) { 3373 var canvas = this.layer_.source.getContext('webgl').canvas; 3374 if (canvas.width != this.lastWidth || canvas.height != this.lastHeight) { 3375 this.cardboardUI_.onResize(); 3376 } 3377 this.lastWidth = canvas.width; 3378 this.lastHeight = canvas.height; 3379 this.cardboardUI_.render(); 3380 } 3381 }; 3382 CardboardVRDisplay.prototype.onOrientationChange_ = function (e) { 3383 this.viewerSelector_.hide(); 3384 if (this.rotateInstructions_) { 3385 this.rotateInstructions_.update(); 3386 } 3387 this.onResize_(); 3388 }; 3389 CardboardVRDisplay.prototype.onResize_ = function (e) { 3390 if (this.layer_) { 3391 var gl = this.layer_.source.getContext('webgl'); 3392 var cssProperties = ['position: absolute', 'top: 0', 'left: 0', 3393 'width: 100vw', 'height: 100vh', 'border: 0', 'margin: 0', 3394 'padding: 0px', 'box-sizing: content-box']; 3395 gl.canvas.setAttribute('style', cssProperties.join('; ') + ';'); 3396 safariCssSizeWorkaround(gl.canvas); 3397 } 3398 }; 3399 CardboardVRDisplay.prototype.onViewerChanged_ = function (viewer) { 3400 this.deviceInfo_.setViewer(viewer); 3401 if (this.distorter_) { 3402 this.distorter_.updateDeviceInfo(this.deviceInfo_); 3403 } 3404 this.fireVRDisplayDeviceParamsChange_(); 3405 }; 3406 CardboardVRDisplay.prototype.fireVRDisplayDeviceParamsChange_ = function () { 3407 var event = new CustomEvent('vrdisplaydeviceparamschange', { 3408 detail: { 3409 vrdisplay: this, 3410 deviceInfo: this.deviceInfo_ 3411 } 3412 }); 3413 window.dispatchEvent(event); 3414 }; 3415 CardboardVRDisplay.VRFrameData = VRFrameData; 3416 CardboardVRDisplay.VRDisplay = VRDisplay; 3417 return CardboardVRDisplay; 3418 }))); 3419 }); 3420 var CardboardVRDisplay = unwrapExports(cardboardVrDisplay); 3421 3422 var version = "0.10.6"; 3423 3424 var DefaultConfig = { 3425 ADDITIONAL_VIEWERS: [], 3426 DEFAULT_VIEWER: '', 3427 PROVIDE_MOBILE_VRDISPLAY: true, 3428 GET_VR_DISPLAYS_TIMEOUT: 1000, 3429 MOBILE_WAKE_LOCK: true, 3430 DEBUG: false, 3431 DPDB_URL: 'https://dpdb.webvr.rocks/dpdb.json', 3432 K_FILTER: 0.98, 3433 PREDICTION_TIME_S: 0.040, 3434 TOUCH_PANNER_DISABLED: true, 3435 CARDBOARD_UI_DISABLED: false, 3436 ROTATE_INSTRUCTIONS_DISABLED: false, 3437 YAW_ONLY: false, 3438 BUFFER_SCALE: 0.5, 3439 DIRTY_SUBMIT_FRAME_BINDINGS: false 3440 }; 3441 3442 function WebVRPolyfill(config) { 3443 this.config = extend(extend({}, DefaultConfig), config); 3444 this.polyfillDisplays = []; 3445 this.enabled = false; 3446 this.hasNative = 'getVRDisplays' in navigator; 3447 this.native = {}; 3448 this.native.getVRDisplays = navigator.getVRDisplays; 3449 this.native.VRFrameData = window.VRFrameData; 3450 this.native.VRDisplay = window.VRDisplay; 3451 if (!this.hasNative || this.config.PROVIDE_MOBILE_VRDISPLAY && isMobile()) { 3452 this.enable(); 3453 this.getVRDisplays().then(function (displays) { 3454 if (displays && displays[0] && displays[0].fireVRDisplayConnect_) { 3455 displays[0].fireVRDisplayConnect_(); 3456 } 3457 }); 3458 } 3459 } 3460 WebVRPolyfill.prototype.getPolyfillDisplays = function () { 3461 if (this._polyfillDisplaysPopulated) { 3462 return this.polyfillDisplays; 3463 } 3464 if (isMobile()) { 3465 var vrDisplay = new CardboardVRDisplay({ 3466 ADDITIONAL_VIEWERS: this.config.ADDITIONAL_VIEWERS, 3467 DEFAULT_VIEWER: this.config.DEFAULT_VIEWER, 3468 MOBILE_WAKE_LOCK: this.config.MOBILE_WAKE_LOCK, 3469 DEBUG: this.config.DEBUG, 3470 DPDB_URL: this.config.DPDB_URL, 3471 CARDBOARD_UI_DISABLED: this.config.CARDBOARD_UI_DISABLED, 3472 K_FILTER: this.config.K_FILTER, 3473 PREDICTION_TIME_S: this.config.PREDICTION_TIME_S, 3474 TOUCH_PANNER_DISABLED: this.config.TOUCH_PANNER_DISABLED, 3475 ROTATE_INSTRUCTIONS_DISABLED: this.config.ROTATE_INSTRUCTIONS_DISABLED, 3476 YAW_ONLY: this.config.YAW_ONLY, 3477 BUFFER_SCALE: this.config.BUFFER_SCALE, 3478 DIRTY_SUBMIT_FRAME_BINDINGS: this.config.DIRTY_SUBMIT_FRAME_BINDINGS 3479 }); 3480 this.polyfillDisplays.push(vrDisplay); 3481 } 3482 this._polyfillDisplaysPopulated = true; 3483 return this.polyfillDisplays; 3484 }; 3485 WebVRPolyfill.prototype.enable = function () { 3486 this.enabled = true; 3487 if (this.hasNative && this.native.VRFrameData) { 3488 var NativeVRFrameData = this.native.VRFrameData; 3489 var nativeFrameData = new this.native.VRFrameData(); 3490 var nativeGetFrameData = this.native.VRDisplay.prototype.getFrameData; 3491 window.VRDisplay.prototype.getFrameData = function (frameData) { 3492 if (frameData instanceof NativeVRFrameData) { 3493 nativeGetFrameData.call(this, frameData); 3494 return; 3495 } 3496 nativeGetFrameData.call(this, nativeFrameData); 3497 frameData.pose = nativeFrameData.pose; 3498 copyArray(nativeFrameData.leftProjectionMatrix, frameData.leftProjectionMatrix); 3499 copyArray(nativeFrameData.rightProjectionMatrix, frameData.rightProjectionMatrix);
3500 copyArray(nativeFrameData.leftViewMatrix, frameData.leftViewMatrix); 3501 copyArray(nativeFrameData.rightViewMatrix, frameData.rightViewMatrix); 3502 }; 3503 } 3504 navigator.getVRDisplays = this.getVRDisplays.bind(this); 3505 window.VRDisplay = CardboardVRDisplay.VRDisplay; 3506 window.VRFrameData = CardboardVRDisplay.VRFrameData; 3507 }; 3508 WebVRPolyfill.prototype.getVRDisplays = function () { 3509 var _this = this; 3510 var config = this.config; 3511 if (!this.hasNative) { 3512 return Promise.resolve(this.getPolyfillDisplays()); 3513 } 3514 var timeoutId; 3515 var vrDisplaysNative = this.native.getVRDisplays.call(navigator); 3516 var timeoutPromise = new Promise(function (resolve) { 3517 timeoutId = setTimeout(function () { 3518 console.warn('Native WebVR implementation detected, but `getVRDisplays()` failed to resolve. Falling back to polyfill.'); 3519 resolve([]); 3520 }, config.GET_VR_DISPLAYS_TIMEOUT); 3521 }); 3522 return race([vrDisplaysNative, timeoutPromise]).then(function (nativeDisplays) { 3523 clearTimeout(timeoutId); 3524 return nativeDisplays.length > 0 ? nativeDisplays : _this.getPolyfillDisplays(); 3525 }); 3526 }; 3527 WebVRPolyfill.version = version; 3528 WebVRPolyfill.VRFrameData = CardboardVRDisplay.VRFrameData; 3529 WebVRPolyfill.VRDisplay = CardboardVRDisplay.VRDisplay; 3530 3531 3532 var webvrPolyfill = Object.freeze({ 3533 default: WebVRPolyfill 3534 }); 3535 3536 var require$$0 = ( webvrPolyfill && WebVRPolyfill ) || webvrPolyfill; 3537 3538 if (typeof commonjsGlobal$1 !== 'undefined' && commonjsGlobal$1.window) { 3539 if (!commonjsGlobal$1.document) { 3540 commonjsGlobal$1.document = commonjsGlobal$1.window.document; 3541 } 3542 if (!commonjsGlobal$1.navigator) { 3543 commonjsGlobal$1.navigator = commonjsGlobal$1.window.navigator; 3544 } 3545 } 3546 var src = require$$0; 3547 3548 return src; 3549 3550 }))); 3551 }); 3552 3553 var WebVRPolyfill = unwrapExports(webvrPolyfill); 3554 3555 // Polyfills 3556 3557 if ( Number.EPSILON === undefined ) { 3558 3559 Number.EPSILON = Math.pow( 2, - 52 ); 3560 3561 } 3562 3563 if ( Number.isInteger === undefined ) { 3564 3565 // Missing in IE 3566 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger 3567 3568 Number.isInteger = function ( value ) { 3569 3570 return typeof value === 'number' && isFinite( value ) && Math.floor( value ) === value; 3571 3572 }; 3573 3574 } 3575 3576 // 3577 3578 if ( Math.sign === undefined ) { 3579 3580 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign 3581 3582 Math.sign = function ( x ) { 3583 3584 return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : + x; 3585 3586 }; 3587 3588 } 3589 3590 if ( 'name' in Function.prototype === false ) { 3591 3592 // Missing in IE 3593 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name 3594 3595 Object.defineProperty( Function.prototype, 'name', { 3596 3597 get: function () { 3598 3599 return this.toString().match( /^\s*function\s*([^\(\s]*)/ )[ 1 ]; 3600 3601 } 3602 3603 } ); 3604 3605 } 3606 3607 if ( Object.assign === undefined ) { 3608 3609 // Missing in IE 3610 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign 3611 3612 ( function () { 3613 3614 Object.assign = function ( target ) { 3615 3616 if ( target === undefined || target === null ) { 3617 3618 throw new TypeError( 'Cannot convert undefined or null to object' ); 3619 3620 } 3621 3622 var output = Object( target ); 3623 3624 for ( var index = 1; index < arguments.length; index ++ ) { 3625 3626 var source = arguments[ index ]; 3627 3628 if ( source !== undefined && source !== null ) { 3629 3630 for ( var nextKey in source ) { 3631 3632 if ( Object.prototype.hasOwnProperty.call( source, nextKey ) ) { 3633 3634 output[ nextKey ] = source[ nextKey ]; 3635 3636 } 3637 3638 } 3639 3640 } 3641 3642 } 3643 3644 return output; 3645 3646 }; 3647 3648 } )(); 3649 3650 } 3651 3652 /** 3653 * https://github.com/mrdoob/eventdispatcher.js/ 3654 */ 3655 3656 function EventDispatcher() {} 3657 3658 Object.assign( EventDispatcher.prototype, { 3659
vendor: 103,161 bytes, lines 3660-8707
3660 addEventListener: function ( type, listener ) { 3661 3662 if ( this._listeners === undefined ) this._listeners = {}; 3663 3664 var listeners = this._listeners; 3665 3666 if ( listeners[ type ] === undefined ) { 3667 3668 listeners[ type ] = []; 3669 3670 } 3671 3672 if ( listeners[ type ].indexOf( listener ) === - 1 ) { 3673 3674 listeners[ type ].push( listener ); 3675 3676 } 3677 3678 }, 3679 3680 hasEventListener: function ( type, listener ) { 3681 3682 if ( this._listeners === undefined ) return false; 3683 3684 var listeners = this._listeners; 3685 3686 return listeners[ type ] !== undefined && listeners[ type ].indexOf( listener ) !== - 1; 3687 3688 }, 3689 3690 removeEventListener: function ( type, listener ) { 3691 3692 if ( this._listeners === undefined ) return; 3693 3694 var listeners = this._listeners; 3695 var listenerArray = listeners[ type ]; 3696 3697 if ( listenerArray !== undefined ) { 3698 3699 var index = listenerArray.indexOf( listener ); 3700 3701 if ( index !== - 1 ) { 3702 3703 listenerArray.splice( index, 1 ); 3704 3705 } 3706 3707 } 3708 3709 }, 3710 3711 dispatchEvent: function ( event ) { 3712 3713 if ( this._listeners === undefined ) return; 3714 3715 var listeners = this._listeners; 3716 var listenerArray = listeners[ event.type ]; 3717 3718 if ( listenerArray !== undefined ) { 3719 3720 event.target = this; 3721 3722 var array = listenerArray.slice( 0 ); 3723 3724 for ( var i = 0, l = array.length; i < l; i ++ ) { 3725 3726 array[ i ].call( this, event ); 3727 3728 } 3729 3730 } 3731 3732 } 3733 3734 } ); 3735 3736 var REVISION = '93'; 3737 var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 }; 3738 var CullFaceNone = 0; 3739 var CullFaceBack = 1; 3740 var CullFaceFront = 2; 3741 var PCFShadowMap = 1; 3742 var PCFSoftShadowMap = 2; 3743 var FrontSide = 0; 3744 var BackSide = 1; 3745 var DoubleSide = 2; 3746 var FlatShading = 1; 3747 var NoColors = 0; 3748 var FaceColors = 1; 3749 var VertexColors = 2; 3750 var NoBlending = 0; 3751 var NormalBlending = 1; 3752 var AdditiveBlending = 2; 3753 var SubtractiveBlending = 3; 3754 var MultiplyBlending = 4; 3755 var CustomBlending = 5; 3756 var AddEquation = 100; 3757 var SubtractEquation = 101; 3758 var ReverseSubtractEquation = 102; 3759 var MinEquation = 103; 3760 var MaxEquation = 104; 3761 var ZeroFactor = 200; 3762 var OneFactor = 201; 3763 var SrcColorFactor = 202; 3764 var OneMinusSrcColorFactor = 203; 3765 var SrcAlphaFactor = 204; 3766 var OneMinusSrcAlphaFactor = 205; 3767 var DstAlphaFactor = 206; 3768 var OneMinusDstAlphaFactor = 207; 3769 var DstColorFactor = 208; 3770 var OneMinusDstColorFactor = 209; 3771 var SrcAlphaSaturateFactor = 210; 3772 var NeverDepth = 0; 3773 var AlwaysDepth = 1; 3774 var LessDepth = 2; 3775 var LessEqualDepth = 3; 3776 var EqualDepth = 4; 3777 var GreaterEqualDepth = 5; 3778 var GreaterDepth = 6; 3779 var NotEqualDepth = 7; 3780 var MultiplyOperation = 0; 3781 var MixOperation = 1; 3782 var AddOperation = 2; 3783 var NoToneMapping = 0; 3784 var LinearToneMapping = 1; 3785 var ReinhardToneMapping = 2; 3786 var Uncharted2ToneMapping = 3; 3787 var CineonToneMapping = 4; 3788 var UVMapping = 300; 3789 var CubeReflectionMapping = 301; 3790 var CubeRefractionMapping = 302; 3791 var EquirectangularReflectionMapping = 303; 3792 var EquirectangularRefractionMapping = 304; 3793 var SphericalReflectionMapping = 305; 3794 var CubeUVReflectionMapping = 306; 3795 var CubeUVRefractionMapping = 307; 3796 var RepeatWrapping = 1000; 3797 var ClampToEdgeWrapping = 1001; 3798 var MirroredRepeatWrapping = 1002; 3799 var NearestFilter = 1003; 3800 var NearestMipMapNearestFilter = 1004; 3801 var NearestMipMapLinearFilter = 1005; 3802 var LinearFilter = 1006; 3803 var LinearMipMapNearestFilter = 1007; 3804 var LinearMipMapLinearFilter = 1008; 3805 var UnsignedByteType = 1009; 3806 var ByteType = 1010; 3807 var ShortType = 1011; 3808 var UnsignedShortType = 1012; 3809 var IntType = 1013; 3810 var UnsignedIntType = 1014; 3811 var FloatType = 1015; 3812 var HalfFloatType = 1016; 3813 var UnsignedShort4444Type = 1017; 3814 var UnsignedShort5551Type = 1018; 3815 var UnsignedShort565Type = 1019; 3816 var UnsignedInt248Type = 1020; 3817 var AlphaFormat = 1021; 3818 var RGBFormat = 1022; 3819 var RGBAFormat = 1023; 3820 var LuminanceFormat = 1024; 3821 var LuminanceAlphaFormat = 1025; 3822 var DepthFormat = 1026; 3823 var DepthStencilFormat = 1027; 3824 var RGB_S3TC_DXT1_Format = 33776; 3825 var RGBA_S3TC_DXT1_Format = 33777; 3826 var RGBA_S3TC_DXT3_Format = 33778; 3827 var RGBA_S3TC_DXT5_Format = 33779; 3828 var RGB_PVRTC_4BPPV1_Format = 35840; 3829 var RGB_PVRTC_2BPPV1_Format = 35841; 3830 var RGBA_PVRTC_4BPPV1_Format = 35842; 3831 var RGBA_PVRTC_2BPPV1_Format = 35843; 3832 var RGB_ETC1_Format = 36196; 3833 var RGBA_ASTC_4x4_Format = 37808; 3834 var RGBA_ASTC_5x4_Format = 37809; 3835 var RGBA_ASTC_5x5_Format = 37810; 3836 var RGBA_ASTC_6x5_Format = 37811; 3837 var RGBA_ASTC_6x6_Format = 37812; 3838 var RGBA_ASTC_8x5_Format = 37813; 3839 var RGBA_ASTC_8x6_Format = 37814; 3840 var RGBA_ASTC_8x8_Format = 37815; 3841 var RGBA_ASTC_10x5_Format = 37816; 3842 var RGBA_ASTC_10x6_Format = 37817; 3843 var RGBA_ASTC_10x8_Format = 37818; 3844 var RGBA_ASTC_10x10_Format = 37819; 3845 var RGBA_ASTC_12x10_Format = 37820; 3846 var RGBA_ASTC_12x12_Format = 37821; 3847 var LoopOnce = 2200; 3848 var LoopRepeat = 2201; 3849 var LoopPingPong = 2202; 3850 var InterpolateDiscrete = 2300; 3851 var InterpolateLinear = 2301; 3852 var InterpolateSmooth = 2302; 3853 var ZeroCurvatureEnding = 2400; 3854 var ZeroSlopeEnding = 2401; 3855 var WrapAroundEnding = 2402; 3856 var TrianglesDrawMode = 0; 3857 var TriangleStripDrawMode = 1; 3858 var TriangleFanDrawMode = 2; 3859 var LinearEncoding = 3000; 3860 var sRGBEncoding = 3001; 3861 var GammaEncoding = 3007; 3862 var RGBEEncoding = 3002; 3863 var RGBM7Encoding = 3004; 3864 var RGBM16Encoding = 3005; 3865 var RGBDEncoding = 3006; 3866 var BasicDepthPacking = 3200; 3867 var RGBADepthPacking = 3201; 3868 3869 /** 3870 * @author alteredq / http://alteredqualia.com/ 3871 * @author mrdoob / http://mrdoob.com/ 3872 */ 3873 3874 var _Math = { 3875 3876 DEG2RAD: Math.PI / 180, 3877 RAD2DEG: 180 / Math.PI, 3878 3879 generateUUID: ( function () { 3880 3881 // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/21963136#21963136 3882 3883 var lut = []; 3884 3885 for ( var i = 0; i < 256; i ++ ) { 3886 3887 lut[ i ] = ( i < 16 ? '0' : '' ) + ( i ).toString( 16 ); 3888 3889 } 3890 3891 return function generateUUID() { 3892 3893 var d0 = Math.random() * 0xffffffff | 0; 3894 var d1 = Math.random() * 0xffffffff | 0; 3895 var d2 = Math.random() * 0xffffffff | 0; 3896 var d3 = Math.random() * 0xffffffff | 0; 3897 var uuid = lut[ d0 & 0xff ] + lut[ d0 >> 8 & 0xff ] + lut[ d0 >> 16 & 0xff ] + lut[ d0 >> 24 & 0xff ] + '-' + 3898 lut[ d1 & 0xff ] + lut[ d1 >> 8 & 0xff ] + '-' + lut[ d1 >> 16 & 0x0f | 0x40 ] + lut[ d1 >> 24 & 0xff ] + '-' + 3899 lut[ d2 & 0x3f | 0x80 ] + lut[ d2 >> 8 & 0xff ] + '-' + lut[ d2 >> 16 & 0xff ] + lut[ d2 >> 24 & 0xff ] + 3900 lut[ d3 & 0xff ] + lut[ d3 >> 8 & 0xff ] + lut[ d3 >> 16 & 0xff ] + lut[ d3 >> 24 & 0xff ]; 3901 3902 // .toUpperCase() here flattens concatenated strings to save heap memory space. 3903 return uuid.toUpperCase(); 3904 3905 }; 3906 3907 } )(), 3908 3909 clamp: function ( value, min, max ) { 3910 3911 return Math.max( min, Math.min( max, value ) ); 3912 3913 }, 3914 3915 // compute euclidian modulo of m % n 3916 // https://en.wikipedia.org/wiki/Modulo_operation 3917 3918 euclideanModulo: function ( n, m ) { 3919 3920 return ( ( n % m ) + m ) % m; 3921 3922 }, 3923 3924 // Linear mapping from range <a1, a2> to range <b1, b2> 3925 3926 mapLinear: function ( x, a1, a2, b1, b2 ) { 3927 3928 return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); 3929 3930 }, 3931 3932 // https://en.wikipedia.org/wiki/Linear_interpolation 3933 3934 lerp: function ( x, y, t ) { 3935 3936 return ( 1 - t ) * x + t * y; 3937 3938 }, 3939 3940 // http://en.wikipedia.org/wiki/Smoothstep 3941 3942 smoothstep: function ( x, min, max ) { 3943 3944 if ( x <= min ) return 0; 3945 if ( x >= max ) return 1; 3946 3947 x = ( x - min ) / ( max - min ); 3948 3949 return x * x * ( 3 - 2 * x ); 3950 3951 }, 3952 3953 smootherstep: function ( x, min, max ) { 3954 3955 if ( x <= min ) return 0; 3956 if ( x >= max ) return 1; 3957 3958 x = ( x - min ) / ( max - min ); 3959 3960 return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); 3961 3962 }, 3963 3964 // Random integer from <low, high> interval 3965 3966 randInt: function ( low, high ) { 3967 3968 return low + Math.floor( Math.random() * ( high - low + 1 ) ); 3969 3970 }, 3971 3972 // Random float from <low, high> interval 3973 3974 randFloat: function ( low, high ) { 3975 3976 return low + Math.random() * ( high - low ); 3977 3978 }, 3979 3980 // Random float from <-range/2, range/2> interval 3981 3982 randFloatSpread: function ( range ) { 3983 3984 return range * ( 0.5 - Math.random() ); 3985 3986 }, 3987 3988 degToRad: function ( degrees ) { 3989 3990 return degrees * _Math.DEG2RAD; 3991 3992 }, 3993 3994 radToDeg: function ( radians ) { 3995 3996 return radians * _Math.RAD2DEG; 3997 3998 }, 3999 4000 isPowerOfTwo: function ( value ) { 4001 4002 return ( value & ( value - 1 ) ) === 0 && value !== 0; 4003 4004 }, 4005 4006 ceilPowerOfTwo: function ( value ) { 4007 4008 return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); 4009 4010 }, 4011 4012 floorPowerOfTwo: function ( value ) { 4013 4014 return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); 4015 4016 } 4017 4018 }; 4019 4020 /** 4021 * @author mrdoob / http://mrdoob.com/ 4022 * @author philogb / http://blog.thejit.org/ 4023 * @author egraether / http://egraether.com/ 4024 * @author zz85 / http://www.lab4games.net/zz85/blog 4025 */ 4026 4027 function Vector2( x, y ) { 4028 4029 this.x = x || 0; 4030 this.y = y || 0; 4031 4032 } 4033 4034 Object.defineProperties( Vector2.prototype, { 4035 4036 "width": { 4037 4038 get: function () { 4039 4040 return this.x; 4041 4042 }, 4043 4044 set: function ( value ) { 4045 4046 this.x = value; 4047 4048 } 4049 4050 }, 4051 4052 "height": { 4053 4054 get: function () { 4055 4056 return this.y; 4057 4058 }, 4059 4060 set: function ( value ) { 4061 4062 this.y = value; 4063 4064 } 4065 4066 } 4067 4068 } ); 4069 4070 Object.assign( Vector2.prototype, { 4071 4072 isVector2: true, 4073 4074 set: function ( x, y ) { 4075 4076 this.x = x; 4077 this.y = y; 4078 4079 return this; 4080 4081 }, 4082 4083 setScalar: function ( scalar ) { 4084 4085 this.x = scalar; 4086 this.y = scalar; 4087 4088 return this; 4089 4090 }, 4091 4092 setX: function ( x ) { 4093 4094 this.x = x; 4095 4096 return this; 4097 4098 }, 4099 4100 setY: function ( y ) { 4101 4102 this.y = y; 4103 4104 return this; 4105 4106 }, 4107 4108 setComponent: function ( index, value ) { 4109 4110 switch ( index ) { 4111 4112 case 0: this.x = value; break; 4113 case 1: this.y = value; break; 4114 default: throw new Error( 'index is out of range: ' + index ); 4115 4116 } 4117 4118 return this; 4119 4120 }, 4121 4122 getComponent: function ( index ) { 4123 4124 switch ( index ) { 4125 4126 case 0: return this.x; 4127 case 1: return this.y; 4128 default: throw new Error( 'index is out of range: ' + index ); 4129 4130 } 4131 4132 }, 4133 4134 clone: function () { 4135 4136 return new this.constructor( this.x, this.y ); 4137 4138 }, 4139 4140 copy: function ( v ) { 4141 4142 this.x = v.x; 4143 this.y = v.y; 4144 4145 return this; 4146 4147 }, 4148 4149 add: function ( v, w ) { 4150 4151 if ( w !== undefined ) { 4152 4153 console.warn( 'THREE.Vector2: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); 4154 return this.addVectors( v, w ); 4155 4156 } 4157 4158 this.x += v.x; 4159 this.y += v.y; 4160 4161 return this; 4162 4163 }, 4164 4165 addScalar: function ( s ) { 4166 4167 this.x += s; 4168 this.y += s; 4169 4170 return this; 4171 4172 }, 4173 4174 addVectors: function ( a, b ) { 4175 4176 this.x = a.x + b.x; 4177 this.y = a.y + b.y; 4178 4179 return this; 4180 4181 }, 4182 4183 addScaledVector: function ( v, s ) { 4184 4185 this.x += v.x * s; 4186 this.y += v.y * s; 4187 4188 return this; 4189 4190 }, 4191 4192 sub: function ( v, w ) { 4193 4194 if ( w !== undefined ) { 4195 4196 console.warn( 'THREE.Vector2: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); 4197 return this.subVectors( v, w ); 4198 4199 } 4200 4201 this.x -= v.x; 4202 this.y -= v.y; 4203 4204 return this; 4205 4206 }, 4207 4208 subScalar: function ( s ) { 4209 4210 this.x -= s; 4211 this.y -= s; 4212 4213 return this; 4214 4215 }, 4216 4217 subVectors: function ( a, b ) { 4218 4219 this.x = a.x - b.x; 4220 this.y = a.y - b.y; 4221 4222 return this; 4223 4224 }, 4225 4226 multiply: function ( v ) { 4227 4228 this.x *= v.x; 4229 this.y *= v.y; 4230 4231 return this; 4232 4233 }, 4234 4235 multiplyScalar: function ( scalar ) { 4236 4237 this.x *= scalar; 4238 this.y *= scalar; 4239 4240 return this; 4241 4242 }, 4243 4244 divide: function ( v ) { 4245 4246 this.x /= v.x; 4247 this.y /= v.y; 4248 4249 return this; 4250 4251 }, 4252 4253 divideScalar: function ( scalar ) { 4254 4255 return this.multiplyScalar( 1 / scalar ); 4256 4257 }, 4258 4259 applyMatrix3: function ( m ) { 4260 4261 var x = this.x, y = this.y; 4262 var e = m.elements; 4263 4264 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; 4265 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; 4266 4267 return this; 4268 4269 }, 4270 4271 min: function ( v ) { 4272 4273 this.x = Math.min( this.x, v.x ); 4274 this.y = Math.min( this.y, v.y ); 4275 4276 return this; 4277 4278 }, 4279 4280 max: function ( v ) { 4281 4282 this.x = Math.max( this.x, v.x ); 4283 this.y = Math.max( this.y, v.y ); 4284 4285 return this; 4286 4287 }, 4288 4289 clamp: function ( min, max ) { 4290 4291 // assumes min < max, componentwise 4292 4293 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 4294 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 4295 4296 return this; 4297 4298 }, 4299 4300 clampScalar: function () { 4301 4302 var min = new Vector2(); 4303 var max = new Vector2(); 4304 4305 return function clampScalar( minVal, maxVal ) { 4306 4307 min.set( minVal, minVal ); 4308 max.set( maxVal, maxVal ); 4309 4310 return this.clamp( min, max ); 4311 4312 }; 4313 4314 }(), 4315 4316 clampLength: function ( min, max ) { 4317 4318 var length = this.length(); 4319 4320 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 4321 4322 }, 4323 4324 floor: function () { 4325 4326 this.x = Math.floor( this.x ); 4327 this.y = Math.floor( this.y ); 4328 4329 return this; 4330 4331 }, 4332 4333 ceil: function () { 4334 4335 this.x = Math.ceil( this.x ); 4336 this.y = Math.ceil( this.y ); 4337 4338 return this; 4339 4340 }, 4341 4342 round: function () { 4343 4344 this.x = Math.round( this.x ); 4345 this.y = Math.round( this.y ); 4346 4347 return this; 4348 4349 }, 4350 4351 roundToZero: function () { 4352 4353 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); 4354 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); 4355 4356 return this; 4357 4358 }, 4359 4360 negate: function () { 4361 4362 this.x = - this.x; 4363 this.y = - this.y; 4364 4365 return this; 4366 4367 }, 4368 4369 dot: function ( v ) { 4370 4371 return this.x * v.x + this.y * v.y; 4372 4373 }, 4374 4375 lengthSq: function () { 4376 4377 return this.x * this.x + this.y * this.y; 4378 4379 }, 4380 4381 length: function () { 4382 4383 return Math.sqrt( this.x * this.x + this.y * this.y ); 4384 4385 }, 4386 4387 manhattanLength: function () { 4388 4389 return Math.abs( this.x ) + Math.abs( this.y ); 4390 4391 }, 4392 4393 normalize: function () { 4394 4395 return this.divideScalar( this.length() || 1 ); 4396 4397 }, 4398 4399 angle: function () { 4400 4401 // computes the angle in radians with respect to the positive x-axis 4402 4403 var angle = Math.atan2( this.y, this.x ); 4404 4405 if ( angle < 0 ) angle += 2 * Math.PI; 4406 4407 return angle; 4408 4409 }, 4410 4411 distanceTo: function ( v ) { 4412 4413 return Math.sqrt( this.distanceToSquared( v ) ); 4414 4415 }, 4416 4417 distanceToSquared: function ( v ) { 4418 4419 var dx = this.x - v.x, dy = this.y - v.y; 4420 return dx * dx + dy * dy; 4421 4422 }, 4423 4424 manhattanDistanceTo: function ( v ) { 4425 4426 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); 4427 4428 }, 4429 4430 setLength: function ( length ) { 4431 4432 return this.normalize().multiplyScalar( length ); 4433 4434 }, 4435 4436 lerp: function ( v, alpha ) { 4437 4438 this.x += ( v.x - this.x ) * alpha; 4439 this.y += ( v.y - this.y ) * alpha; 4440 4441 return this; 4442 4443 }, 4444 4445 lerpVectors: function ( v1, v2, alpha ) { 4446 4447 return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); 4448 4449 }, 4450 4451 equals: function ( v ) { 4452 4453 return ( ( v.x === this.x ) && ( v.y === this.y ) ); 4454 4455 }, 4456 4457 fromArray: function ( array, offset ) { 4458 4459 if ( offset === undefined ) offset = 0; 4460 4461 this.x = array[ offset ]; 4462 this.y = array[ offset + 1 ]; 4463 4464 return this; 4465 4466 }, 4467 4468 toArray: function ( array, offset ) { 4469 4470 if ( array === undefined ) array = []; 4471 if ( offset === undefined ) offset = 0; 4472 4473 array[ offset ] = this.x; 4474 array[ offset + 1 ] = this.y; 4475 4476 return array; 4477 4478 }, 4479 4480 fromBufferAttribute: function ( attribute, index, offset ) { 4481 4482 if ( offset !== undefined ) { 4483 4484 console.warn( 'THREE.Vector2: offset has been removed from .fromBufferAttribute().' ); 4485 4486 } 4487 4488 this.x = attribute.getX( index ); 4489 this.y = attribute.getY( index ); 4490 4491 return this; 4492 4493 }, 4494 4495 rotateAround: function ( center, angle ) { 4496 4497 var c = Math.cos( angle ), s = Math.sin( angle ); 4498 4499 var x = this.x - center.x; 4500 var y = this.y - center.y; 4501 4502 this.x = x * c - y * s + center.x; 4503 this.y = x * s + y * c + center.y; 4504 4505 return this; 4506 4507 } 4508 4509 } ); 4510 4511 /** 4512 * @author mrdoob / http://mrdoob.com/ 4513 * @author supereggbert / http://www.paulbrunt.co.uk/ 4514 * @author philogb / http://blog.thejit.org/ 4515 * @author jordi_ros / http://plattsoft.com 4516 * @author D1plo1d / http://github.com/D1plo1d 4517 * @author alteredq / http://alteredqualia.com/ 4518 * @author mikael emtinger / http://gomo.se/ 4519 * @author timknip / http://www.floorplanner.com/ 4520 * @author bhouston / http://clara.io 4521 * @author WestLangley / http://github.com/WestLangley 4522 */ 4523 4524 function Matrix4() { 4525 4526 this.elements = [ 4527 4528 1, 0, 0, 0, 4529 0, 1, 0, 0, 4530 0, 0, 1, 0, 4531 0, 0, 0, 1 4532 4533 ]; 4534 4535 if ( arguments.length > 0 ) { 4536 4537 console.error( 'THREE.Matrix4: the constructor no longer reads arguments. use .set() instead.' ); 4538 4539 } 4540 4541 } 4542 4543 Object.assign( Matrix4.prototype, { 4544 4545 isMatrix4: true, 4546 4547 set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { 4548 4549 var te = this.elements; 4550 4551 te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; 4552 te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; 4553 te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; 4554 te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; 4555 4556 return this; 4557 4558 }, 4559 4560 identity: function () { 4561 4562 this.set( 4563 4564 1, 0, 0, 0, 4565 0, 1, 0, 0, 4566 0, 0, 1, 0, 4567 0, 0, 0, 1 4568 4569 ); 4570 4571 return this; 4572 4573 }, 4574 4575 clone: function () { 4576 4577 return new Matrix4().fromArray( this.elements ); 4578 4579 }, 4580 4581 copy: function ( m ) { 4582 4583 var te = this.elements; 4584 var me = m.elements; 4585 4586 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ]; 4587 te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; 4588 te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ]; 4589 te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ]; 4590 4591 return this; 4592 4593 }, 4594 4595 copyPosition: function ( m ) { 4596 4597 var te = this.elements, me = m.elements; 4598 4599 te[ 12 ] = me[ 12 ]; 4600 te[ 13 ] = me[ 13 ]; 4601 te[ 14 ] = me[ 14 ]; 4602 4603 return this; 4604 4605 }, 4606 4607 extractBasis: function ( xAxis, yAxis, zAxis ) { 4608 4609 xAxis.setFromMatrixColumn( this, 0 ); 4610 yAxis.setFromMatrixColumn( this, 1 ); 4611 zAxis.setFromMatrixColumn( this, 2 ); 4612 4613 return this; 4614 4615 }, 4616 4617 makeBasis: function ( xAxis, yAxis, zAxis ) { 4618 4619 this.set( 4620 xAxis.x, yAxis.x, zAxis.x, 0, 4621 xAxis.y, yAxis.y, zAxis.y, 0, 4622 xAxis.z, yAxis.z, zAxis.z, 0, 4623 0, 0, 0, 1 4624 ); 4625 4626 return this; 4627 4628 }, 4629 4630 extractRotation: function () { 4631 4632 var v1 = new Vector3(); 4633 4634 return function extractRotation( m ) { 4635 4636 // this method does not support reflection matrices 4637 4638 var te = this.elements; 4639 var me = m.elements; 4640 4641 var scaleX = 1 / v1.setFromMatrixColumn( m, 0 ).length(); 4642 var scaleY = 1 / v1.setFromMatrixColumn( m, 1 ).length(); 4643 var scaleZ = 1 / v1.setFromMatrixColumn( m, 2 ).length(); 4644 4645 te[ 0 ] = me[ 0 ] * scaleX; 4646 te[ 1 ] = me[ 1 ] * scaleX; 4647 te[ 2 ] = me[ 2 ] * scaleX; 4648 te[ 3 ] = 0; 4649 4650 te[ 4 ] = me[ 4 ] * scaleY; 4651 te[ 5 ] = me[ 5 ] * scaleY; 4652 te[ 6 ] = me[ 6 ] * scaleY; 4653 te[ 7 ] = 0; 4654 4655 te[ 8 ] = me[ 8 ] * scaleZ; 4656 te[ 9 ] = me[ 9 ] * scaleZ; 4657 te[ 10 ] = me[ 10 ] * scaleZ; 4658 te[ 11 ] = 0; 4659 4660 te[ 12 ] = 0; 4661 te[ 13 ] = 0; 4662 te[ 14 ] = 0; 4663 te[ 15 ] = 1; 4664 4665 return this; 4666 4667 }; 4668 4669 }(), 4670 4671 makeRotationFromEuler: function ( euler ) { 4672 4673 if ( ! ( euler && euler.isEuler ) ) { 4674 4675 console.error( 'THREE.Matrix4: .makeRotationFromEuler() now expects a Euler rotation rather than a Vector3 and order.' ); 4676 4677 } 4678 4679 var te = this.elements; 4680 4681 var x = euler.x, y = euler.y, z = euler.z; 4682 var a = Math.cos( x ), b = Math.sin( x ); 4683 var c = Math.cos( y ), d = Math.sin( y ); 4684 var e = Math.cos( z ), f = Math.sin( z ); 4685 4686 if ( euler.order === 'XYZ' ) { 4687 4688 var ae = a * e, af = a * f, be = b * e, bf = b * f; 4689 4690 te[ 0 ] = c * e; 4691 te[ 4 ] = - c * f; 4692 te[ 8 ] = d; 4693 4694 te[ 1 ] = af + be * d; 4695 te[ 5 ] = ae - bf * d; 4696 te[ 9 ] = - b * c; 4697 4698 te[ 2 ] = bf - ae * d; 4699 te[ 6 ] = be + af * d; 4700 te[ 10 ] = a * c; 4701 4702 } else if ( euler.order === 'YXZ' ) { 4703 4704 var ce = c * e, cf = c * f, de = d * e, df = d * f; 4705 4706 te[ 0 ] = ce + df * b; 4707 te[ 4 ] = de * b - cf; 4708 te[ 8 ] = a * d; 4709 4710 te[ 1 ] = a * f; 4711 te[ 5 ] = a * e; 4712 te[ 9 ] = - b; 4713 4714 te[ 2 ] = cf * b - de; 4715 te[ 6 ] = df + ce * b; 4716 te[ 10 ] = a * c; 4717 4718 } else if ( euler.order === 'ZXY' ) { 4719 4720 var ce = c * e, cf = c * f, de = d * e, df = d * f; 4721 4722 te[ 0 ] = ce - df * b; 4723 te[ 4 ] = - a * f; 4724 te[ 8 ] = de + cf * b; 4725 4726 te[ 1 ] = cf + de * b; 4727 te[ 5 ] = a * e; 4728 te[ 9 ] = df - ce * b; 4729 4730 te[ 2 ] = - a * d; 4731 te[ 6 ] = b; 4732 te[ 10 ] = a * c; 4733 4734 } else if ( euler.order === 'ZYX' ) { 4735 4736 var ae = a * e, af = a * f, be = b * e, bf = b * f; 4737 4738 te[ 0 ] = c * e; 4739 te[ 4 ] = be * d - af; 4740 te[ 8 ] = ae * d + bf; 4741 4742 te[ 1 ] = c * f; 4743 te[ 5 ] = bf * d + ae; 4744 te[ 9 ] = af * d - be; 4745 4746 te[ 2 ] = - d; 4747 te[ 6 ] = b * c; 4748 te[ 10 ] = a * c; 4749 4750 } else if ( euler.order === 'YZX' ) { 4751 4752 var ac = a * c, ad = a * d, bc = b * c, bd = b * d; 4753 4754 te[ 0 ] = c * e; 4755 te[ 4 ] = bd - ac * f; 4756 te[ 8 ] = bc * f + ad; 4757 4758 te[ 1 ] = f; 4759 te[ 5 ] = a * e; 4760 te[ 9 ] = - b * e; 4761 4762 te[ 2 ] = - d * e; 4763 te[ 6 ] = ad * f + bc; 4764 te[ 10 ] = ac - bd * f; 4765 4766 } else if ( euler.order === 'XZY' ) { 4767 4768 var ac = a * c, ad = a * d, bc = b * c, bd = b * d; 4769 4770 te[ 0 ] = c * e; 4771 te[ 4 ] = - f; 4772 te[ 8 ] = d * e; 4773 4774 te[ 1 ] = ac * f + bd; 4775 te[ 5 ] = a * e; 4776 te[ 9 ] = ad * f - bc; 4777 4778 te[ 2 ] = bc * f - ad; 4779 te[ 6 ] = b * e; 4780 te[ 10 ] = bd * f + ac; 4781 4782 } 4783 4784 // bottom row 4785 te[ 3 ] = 0; 4786 te[ 7 ] = 0; 4787 te[ 11 ] = 0; 4788 4789 // last column 4790 te[ 12 ] = 0; 4791 te[ 13 ] = 0; 4792 te[ 14 ] = 0; 4793 te[ 15 ] = 1; 4794 4795 return this; 4796 4797 }, 4798 4799 makeRotationFromQuaternion: function () { 4800 4801 var zero = new Vector3( 0, 0, 0 ); 4802 var one = new Vector3( 1, 1, 1 ); 4803 4804 return function makeRotationFromQuaternion( q ) { 4805 4806 return this.compose( zero, q, one ); 4807 4808 }; 4809 4810 }(), 4811 4812 lookAt: function () { 4813 4814 var x = new Vector3(); 4815 var y = new Vector3(); 4816 var z = new Vector3(); 4817 4818 return function lookAt( eye, target, up ) { 4819 4820 var te = this.elements; 4821 4822 z.subVectors( eye, target ); 4823 4824 if ( z.lengthSq() === 0 ) { 4825 4826 // eye and target are in the same position 4827 4828 z.z = 1; 4829 4830 } 4831 4832 z.normalize(); 4833 x.crossVectors( up, z ); 4834 4835 if ( x.lengthSq() === 0 ) { 4836 4837 // up and z are parallel 4838 4839 if ( Math.abs( up.z ) === 1 ) { 4840 4841 z.x += 0.0001; 4842 4843 } else { 4844 4845 z.z += 0.0001; 4846 4847 } 4848 4849 z.normalize(); 4850 x.crossVectors( up, z ); 4851 4852 } 4853 4854 x.normalize(); 4855 y.crossVectors( z, x ); 4856 4857 te[ 0 ] = x.x; te[ 4 ] = y.x; te[ 8 ] = z.x; 4858 te[ 1 ] = x.y; te[ 5 ] = y.y; te[ 9 ] = z.y; 4859 te[ 2 ] = x.z; te[ 6 ] = y.z; te[ 10 ] = z.z; 4860 4861 return this; 4862 4863 }; 4864 4865 }(), 4866 4867 multiply: function ( m, n ) { 4868 4869 if ( n !== undefined ) { 4870 4871 console.warn( 'THREE.Matrix4: .multiply() now only accepts one argument. Use .multiplyMatrices( a, b ) instead.' ); 4872 return this.multiplyMatrices( m, n ); 4873 4874 } 4875 4876 return this.multiplyMatrices( this, m ); 4877 4878 }, 4879 4880 premultiply: function ( m ) { 4881 4882 return this.multiplyMatrices( m, this ); 4883 4884 }, 4885 4886 multiplyMatrices: function ( a, b ) { 4887 4888 var ae = a.elements; 4889 var be = b.elements; 4890 var te = this.elements; 4891 4892 var a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; 4893 var a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; 4894 var a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; 4895 var a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; 4896 4897 var b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; 4898 var b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; 4899 var b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; 4900 var b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; 4901 4902 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; 4903 te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; 4904 te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; 4905 te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; 4906 4907 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; 4908 te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; 4909 te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; 4910 te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; 4911 4912 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; 4913 te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; 4914 te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; 4915 te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; 4916 4917 te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; 4918 te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; 4919 te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; 4920 te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; 4921 4922 return this; 4923 4924 }, 4925 4926 multiplyScalar: function ( s ) { 4927 4928 var te = this.elements; 4929 4930 te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s; 4931 te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s; 4932 te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s; 4933 te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s; 4934 4935 return this; 4936 4937 }, 4938 4939 applyToBufferAttribute: function () { 4940 4941 var v1 = new Vector3(); 4942 4943 return function applyToBufferAttribute( attribute ) { 4944 4945 for ( var i = 0, l = attribute.count; i < l; i ++ ) { 4946 4947 v1.x = attribute.getX( i ); 4948 v1.y = attribute.getY( i ); 4949 v1.z = attribute.getZ( i ); 4950 4951 v1.applyMatrix4( this ); 4952 4953 attribute.setXYZ( i, v1.x, v1.y, v1.z ); 4954 4955 } 4956 4957 return attribute; 4958 4959 }; 4960 4961 }(), 4962 4963 determinant: function () { 4964 4965 var te = this.elements; 4966 4967 var n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; 4968 var n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; 4969 var n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; 4970 var n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; 4971 4972 //TODO: make this more efficient 4973 //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) 4974 4975 return ( 4976 n41 * ( 4977 + n14 * n23 * n32 4978 - n13 * n24 * n32 4979 - n14 * n22 * n33 4980 + n12 * n24 * n33 4981 + n13 * n22 * n34 4982 - n12 * n23 * n34 4983 ) + 4984 n42 * ( 4985 + n11 * n23 * n34 4986 - n11 * n24 * n33 4987 + n14 * n21 * n33 4988 - n13 * n21 * n34 4989 + n13 * n24 * n31 4990 - n14 * n23 * n31 4991 ) + 4992 n43 * ( 4993 + n11 * n24 * n32 4994 - n11 * n22 * n34 4995 - n14 * n21 * n32 4996 + n12 * n21 * n34 4997 + n14 * n22 * n31 4998 - n12 * n24 * n31 4999 ) + 5000 n44 * ( 5001 - n13 * n22 * n31 5002 - n11 * n23 * n32 5003 + n11 * n22 * n33 5004 + n13 * n21 * n32 5005 - n12 * n21 * n33 5006 + n12 * n23 * n31 5007 ) 5008 5009 ); 5010 5011 }, 5012 5013 transpose: function () { 5014 5015 var te = this.elements; 5016 var tmp; 5017 5018 tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp; 5019 tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp; 5020 tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp; 5021 5022 tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp; 5023 tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp; 5024 tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp; 5025 5026 return this; 5027 5028 }, 5029 5030 setPosition: function ( v ) { 5031 5032 var te = this.elements; 5033 5034 te[ 12 ] = v.x; 5035 te[ 13 ] = v.y; 5036 te[ 14 ] = v.z; 5037 5038 return this; 5039 5040 }, 5041 5042 getInverse: function ( m, throwOnDegenerate ) { 5043 5044 // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm 5045 var te = this.elements, 5046 me = m.elements, 5047 5048 n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], n41 = me[ 3 ], 5049 n12 = me[ 4 ], n22 = me[ 5 ], n32 = me[ 6 ], n42 = me[ 7 ], 5050 n13 = me[ 8 ], n23 = me[ 9 ], n33 = me[ 10 ], n43 = me[ 11 ], 5051 n14 = me[ 12 ], n24 = me[ 13 ], n34 = me[ 14 ], n44 = me[ 15 ], 5052 5053 t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, 5054 t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, 5055 t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, 5056 t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; 5057 5058 var det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; 5059 5060 if ( det === 0 ) { 5061 5062 var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0"; 5063 5064 if ( throwOnDegenerate === true ) { 5065 5066 throw new Error( msg ); 5067 5068 } else { 5069 5070 console.warn( msg ); 5071 5072 } 5073 5074 return this.identity(); 5075 5076 } 5077 5078 var detInv = 1 / det; 5079 5080 te[ 0 ] = t11 * detInv; 5081 te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv; 5082 te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv; 5083 te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv; 5084 5085 te[ 4 ] = t12 * detInv; 5086 te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv; 5087 te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv; 5088 te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv; 5089 5090 te[ 8 ] = t13 * detInv; 5091 te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv; 5092 te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv; 5093 te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv; 5094 5095 te[ 12 ] = t14 * detInv; 5096 te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv; 5097 te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv; 5098 te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv; 5099 5100 return this; 5101 5102 }, 5103 5104 scale: function ( v ) { 5105 5106 var te = this.elements; 5107 var x = v.x, y = v.y, z = v.z; 5108 5109 te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; 5110 te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; 5111 te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; 5112 te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; 5113 5114 return this; 5115 5116 }, 5117 5118 getMaxScaleOnAxis: function () { 5119 5120 var te = this.elements; 5121 5122 var scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; 5123 var scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; 5124 var scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; 5125 5126 return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); 5127 5128 }, 5129 5130 makeTranslation: function ( x, y, z ) { 5131 5132 this.set( 5133 5134 1, 0, 0, x, 5135 0, 1, 0, y, 5136 0, 0, 1, z, 5137 0, 0, 0, 1 5138 5139 ); 5140 5141 return this; 5142 5143 }, 5144 5145 makeRotationX: function ( theta ) { 5146 5147 var c = Math.cos( theta ), s = Math.sin( theta ); 5148 5149 this.set( 5150 5151 1, 0, 0, 0, 5152 0, c, - s, 0, 5153 0, s, c, 0, 5154 0, 0, 0, 1 5155 5156 ); 5157 5158 return this; 5159 5160 }, 5161 5162 makeRotationY: function ( theta ) { 5163 5164 var c = Math.cos( theta ), s = Math.sin( theta ); 5165 5166 this.set( 5167 5168 c, 0, s, 0, 5169 0, 1, 0, 0, 5170 - s, 0, c, 0, 5171 0, 0, 0, 1 5172 5173 ); 5174 5175 return this; 5176 5177 }, 5178 5179 makeRotationZ: function ( theta ) { 5180 5181 var c = Math.cos( theta ), s = Math.sin( theta ); 5182 5183 this.set( 5184 5185 c, - s, 0, 0, 5186 s, c, 0, 0, 5187 0, 0, 1, 0, 5188 0, 0, 0, 1 5189 5190 ); 5191 5192 return this; 5193 5194 }, 5195 5196 makeRotationAxis: function ( axis, angle ) { 5197 5198 // Based on http://www.gamedev.net/reference/articles/article1199.asp 5199 5200 var c = Math.cos( angle ); 5201 var s = Math.sin( angle ); 5202 var t = 1 - c; 5203 var x = axis.x, y = axis.y, z = axis.z; 5204 var tx = t * x, ty = t * y; 5205 5206 this.set( 5207 5208 tx * x + c, tx * y - s * z, tx * z + s * y, 0, 5209 tx * y + s * z, ty * y + c, ty * z - s * x, 0, 5210 tx * z - s * y, ty * z + s * x, t * z * z + c, 0, 5211 0, 0, 0, 1 5212 5213 ); 5214 5215 return this; 5216 5217 }, 5218 5219 makeScale: function ( x, y, z ) { 5220 5221 this.set( 5222 5223 x, 0, 0, 0, 5224 0, y, 0, 0, 5225 0, 0, z, 0, 5226 0, 0, 0, 1 5227 5228 ); 5229 5230 return this; 5231 5232 }, 5233 5234 makeShear: function ( x, y, z ) { 5235 5236 this.set( 5237 5238 1, y, z, 0, 5239 x, 1, z, 0, 5240 x, y, 1, 0, 5241 0, 0, 0, 1 5242 5243 ); 5244 5245 return this; 5246 5247 }, 5248 5249 compose: function ( position, quaternion, scale ) { 5250 5251 var te = this.elements; 5252 5253 var x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; 5254 var x2 = x + x, y2 = y + y, z2 = z + z; 5255 var xx = x * x2, xy = x * y2, xz = x * z2; 5256 var yy = y * y2, yz = y * z2, zz = z * z2; 5257 var wx = w * x2, wy = w * y2, wz = w * z2; 5258 5259 var sx = scale.x, sy = scale.y, sz = scale.z; 5260 5261 te[ 0 ] = ( 1 - ( yy + zz ) ) * sx; 5262 te[ 1 ] = ( xy + wz ) * sx; 5263 te[ 2 ] = ( xz - wy ) * sx; 5264 te[ 3 ] = 0; 5265 5266 te[ 4 ] = ( xy - wz ) * sy; 5267 te[ 5 ] = ( 1 - ( xx + zz ) ) * sy; 5268 te[ 6 ] = ( yz + wx ) * sy; 5269 te[ 7 ] = 0; 5270 5271 te[ 8 ] = ( xz + wy ) * sz; 5272 te[ 9 ] = ( yz - wx ) * sz; 5273 te[ 10 ] = ( 1 - ( xx + yy ) ) * sz; 5274 te[ 11 ] = 0; 5275 5276 te[ 12 ] = position.x; 5277 te[ 13 ] = position.y; 5278 te[ 14 ] = position.z; 5279 te[ 15 ] = 1; 5280 5281 return this; 5282 5283 }, 5284 5285 decompose: function () { 5286 5287 var vector = new Vector3(); 5288 var matrix = new Matrix4(); 5289 5290 return function decompose( position, quaternion, scale ) { 5291 5292 var te = this.elements; 5293 5294 var sx = vector.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); 5295 var sy = vector.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); 5296 var sz = vector.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); 5297 5298 // if determine is negative, we need to invert one scale 5299 var det = this.determinant(); 5300 if ( det < 0 ) sx = - sx; 5301 5302 position.x = te[ 12 ]; 5303 position.y = te[ 13 ]; 5304 position.z = te[ 14 ]; 5305 5306 // scale the rotation part 5307 matrix.copy( this ); 5308 5309 var invSX = 1 / sx; 5310 var invSY = 1 / sy; 5311 var invSZ = 1 / sz; 5312 5313 matrix.elements[ 0 ] *= invSX; 5314 matrix.elements[ 1 ] *= invSX; 5315 matrix.elements[ 2 ] *= invSX; 5316 5317 matrix.elements[ 4 ] *= invSY; 5318 matrix.elements[ 5 ] *= invSY; 5319 matrix.elements[ 6 ] *= invSY; 5320 5321 matrix.elements[ 8 ] *= invSZ; 5322 matrix.elements[ 9 ] *= invSZ; 5323 matrix.elements[ 10 ] *= invSZ; 5324 5325 quaternion.setFromRotationMatrix( matrix ); 5326 5327 scale.x = sx; 5328 scale.y = sy; 5329 scale.z = sz; 5330 5331 return this; 5332 5333 }; 5334 5335 }(), 5336 5337 makePerspective: function ( left, right, top, bottom, near, far ) { 5338 5339 if ( far === undefined ) { 5340 5341 console.warn( 'THREE.Matrix4: .makePerspective() has been redefined and has a new signature. Please check the docs.' ); 5342 5343 } 5344 5345 var te = this.elements; 5346 var x = 2 * near / ( right - left ); 5347 var y = 2 * near / ( top - bottom ); 5348 5349 var a = ( right + left ) / ( right - left ); 5350 var b = ( top + bottom ) / ( top - bottom ); 5351 var c = - ( far + near ) / ( far - near ); 5352 var d = - 2 * far * near / ( far - near ); 5353 5354 te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; 5355 te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; 5356 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; 5357 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; 5358 5359 return this; 5360 5361 }, 5362 5363 makeOrthographic: function ( left, right, top, bottom, near, far ) { 5364 5365 var te = this.elements; 5366 var w = 1.0 / ( right - left ); 5367 var h = 1.0 / ( top - bottom ); 5368 var p = 1.0 / ( far - near ); 5369 5370 var x = ( right + left ) * w; 5371 var y = ( top + bottom ) * h; 5372 var z = ( far + near ) * p; 5373 5374 te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; 5375 te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; 5376 te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z; 5377 te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; 5378 5379 return this; 5380 5381 }, 5382 5383 equals: function ( matrix ) { 5384 5385 var te = this.elements; 5386 var me = matrix.elements; 5387 5388 for ( var i = 0; i < 16; i ++ ) { 5389 5390 if ( te[ i ] !== me[ i ] ) return false; 5391 5392 } 5393 5394 return true; 5395 5396 }, 5397 5398 fromArray: function ( array, offset ) { 5399 5400 if ( offset === undefined ) offset = 0; 5401 5402 for ( var i = 0; i < 16; i ++ ) { 5403 5404 this.elements[ i ] = array[ i + offset ]; 5405 5406 } 5407 5408 return this; 5409 5410 }, 5411 5412 toArray: function ( array, offset ) { 5413 5414 if ( array === undefined ) array = []; 5415 if ( offset === undefined ) offset = 0; 5416 5417 var te = this.elements; 5418 5419 array[ offset ] = te[ 0 ]; 5420 array[ offset + 1 ] = te[ 1 ]; 5421 array[ offset + 2 ] = te[ 2 ]; 5422 array[ offset + 3 ] = te[ 3 ]; 5423 5424 array[ offset + 4 ] = te[ 4 ]; 5425 array[ offset + 5 ] = te[ 5 ]; 5426 array[ offset + 6 ] = te[ 6 ]; 5427 array[ offset + 7 ] = te[ 7 ]; 5428 5429 array[ offset + 8 ] = te[ 8 ]; 5430 array[ offset + 9 ] = te[ 9 ]; 5431 array[ offset + 10 ] = te[ 10 ]; 5432 array[ offset + 11 ] = te[ 11 ]; 5433 5434 array[ offset + 12 ] = te[ 12 ]; 5435 array[ offset + 13 ] = te[ 13 ]; 5436 array[ offset + 14 ] = te[ 14 ]; 5437 array[ offset + 15 ] = te[ 15 ]; 5438 5439 return array; 5440 5441 } 5442 5443 } ); 5444 5445 /** 5446 * @author mikael emtinger / http://gomo.se/ 5447 * @author alteredq / http://alteredqualia.com/ 5448 * @author WestLangley / http://github.com/WestLangley 5449 * @author bhouston / http://clara.io 5450 */ 5451 5452 function Quaternion( x, y, z, w ) { 5453 5454 this._x = x || 0; 5455 this._y = y || 0; 5456 this._z = z || 0; 5457 this._w = ( w !== undefined ) ? w : 1; 5458 5459 } 5460 5461 Object.assign( Quaternion, { 5462 5463 slerp: function ( qa, qb, qm, t ) { 5464 5465 return qm.copy( qa ).slerp( qb, t ); 5466 5467 }, 5468 5469 slerpFlat: function ( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { 5470 5471 // fuzz-free, array-based Quaternion SLERP operation 5472 5473 var x0 = src0[ srcOffset0 + 0 ], 5474 y0 = src0[ srcOffset0 + 1 ], 5475 z0 = src0[ srcOffset0 + 2 ], 5476 w0 = src0[ srcOffset0 + 3 ], 5477 5478 x1 = src1[ srcOffset1 + 0 ], 5479 y1 = src1[ srcOffset1 + 1 ], 5480 z1 = src1[ srcOffset1 + 2 ], 5481 w1 = src1[ srcOffset1 + 3 ]; 5482 5483 if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { 5484 5485 var s = 1 - t, 5486 5487 cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, 5488 5489 dir = ( cos >= 0 ? 1 : - 1 ), 5490 sqrSin = 1 - cos * cos; 5491 5492 // Skip the Slerp for tiny steps to avoid numeric problems: 5493 if ( sqrSin > Number.EPSILON ) { 5494 5495 var sin = Math.sqrt( sqrSin ), 5496 len = Math.atan2( sin, cos * dir ); 5497 5498 s = Math.sin( s * len ) / sin; 5499 t = Math.sin( t * len ) / sin; 5500 5501 } 5502 5503 var tDir = t * dir; 5504 5505 x0 = x0 * s + x1 * tDir; 5506 y0 = y0 * s + y1 * tDir; 5507 z0 = z0 * s + z1 * tDir; 5508 w0 = w0 * s + w1 * tDir; 5509 5510 // Normalize in case we just did a lerp: 5511 if ( s === 1 - t ) { 5512 5513 var f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); 5514 5515 x0 *= f; 5516 y0 *= f; 5517 z0 *= f; 5518 w0 *= f; 5519 5520 } 5521 5522 } 5523 5524 dst[ dstOffset ] = x0; 5525 dst[ dstOffset + 1 ] = y0; 5526 dst[ dstOffset + 2 ] = z0; 5527 dst[ dstOffset + 3 ] = w0; 5528 5529 } 5530 5531 } ); 5532 5533 Object.defineProperties( Quaternion.prototype, { 5534 5535 x: { 5536 5537 get: function () { 5538 5539 return this._x; 5540 5541 }, 5542 5543 set: function ( value ) { 5544 5545 this._x = value; 5546 this.onChangeCallback(); 5547 5548 } 5549 5550 }, 5551 5552 y: { 5553 5554 get: function () { 5555 5556 return this._y; 5557 5558 }, 5559 5560 set: function ( value ) { 5561 5562 this._y = value; 5563 this.onChangeCallback(); 5564 5565 } 5566 5567 }, 5568 5569 z: { 5570 5571 get: function () { 5572 5573 return this._z; 5574 5575 }, 5576 5577 set: function ( value ) { 5578 5579 this._z = value; 5580 this.onChangeCallback(); 5581 5582 } 5583 5584 }, 5585 5586 w: { 5587 5588 get: function () { 5589 5590 return this._w; 5591 5592 }, 5593 5594 set: function ( value ) { 5595 5596 this._w = value; 5597 this.onChangeCallback(); 5598 5599 } 5600 5601 } 5602 5603 } ); 5604 5605 Object.assign( Quaternion.prototype, { 5606 5607 set: function ( x, y, z, w ) { 5608 5609 this._x = x; 5610 this._y = y; 5611 this._z = z; 5612 this._w = w; 5613 5614 this.onChangeCallback(); 5615 5616 return this; 5617 5618 }, 5619 5620 clone: function () { 5621 5622 return new this.constructor( this._x, this._y, this._z, this._w ); 5623 5624 }, 5625 5626 copy: function ( quaternion ) { 5627 5628 this._x = quaternion.x; 5629 this._y = quaternion.y; 5630 this._z = quaternion.z; 5631 this._w = quaternion.w; 5632 5633 this.onChangeCallback(); 5634 5635 return this; 5636 5637 }, 5638 5639 setFromEuler: function ( euler, update ) { 5640 5641 if ( ! ( euler && euler.isEuler ) ) { 5642 5643 throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' ); 5644 5645 } 5646 5647 var x = euler._x, y = euler._y, z = euler._z, order = euler.order; 5648 5649 // http://www.mathworks.com/matlabcentral/fileexchange/ 5650 // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ 5651 // content/SpinCalc.m 5652 5653 var cos = Math.cos; 5654 var sin = Math.sin; 5655 5656 var c1 = cos( x / 2 ); 5657 var c2 = cos( y / 2 ); 5658 var c3 = cos( z / 2 ); 5659 5660 var s1 = sin( x / 2 ); 5661 var s2 = sin( y / 2 ); 5662 var s3 = sin( z / 2 ); 5663 5664 if ( order === 'XYZ' ) { 5665 5666 this._x = s1 * c2 * c3 + c1 * s2 * s3; 5667 this._y = c1 * s2 * c3 - s1 * c2 * s3; 5668 this._z = c1 * c2 * s3 + s1 * s2 * c3; 5669 this._w = c1 * c2 * c3 - s1 * s2 * s3; 5670 5671 } else if ( order === 'YXZ' ) { 5672 5673 this._x = s1 * c2 * c3 + c1 * s2 * s3; 5674 this._y = c1 * s2 * c3 - s1 * c2 * s3; 5675 this._z = c1 * c2 * s3 - s1 * s2 * c3; 5676 this._w = c1 * c2 * c3 + s1 * s2 * s3; 5677 5678 } else if ( order === 'ZXY' ) { 5679 5680 this._x = s1 * c2 * c3 - c1 * s2 * s3; 5681 this._y = c1 * s2 * c3 + s1 * c2 * s3; 5682 this._z = c1 * c2 * s3 + s1 * s2 * c3; 5683 this._w = c1 * c2 * c3 - s1 * s2 * s3; 5684 5685 } else if ( order === 'ZYX' ) { 5686 5687 this._x = s1 * c2 * c3 - c1 * s2 * s3; 5688 this._y = c1 * s2 * c3 + s1 * c2 * s3; 5689 this._z = c1 * c2 * s3 - s1 * s2 * c3; 5690 this._w = c1 * c2 * c3 + s1 * s2 * s3; 5691 5692 } else if ( order === 'YZX' ) { 5693 5694 this._x = s1 * c2 * c3 + c1 * s2 * s3; 5695 this._y = c1 * s2 * c3 + s1 * c2 * s3; 5696 this._z = c1 * c2 * s3 - s1 * s2 * c3; 5697 this._w = c1 * c2 * c3 - s1 * s2 * s3; 5698 5699 } else if ( order === 'XZY' ) { 5700 5701 this._x = s1 * c2 * c3 - c1 * s2 * s3; 5702 this._y = c1 * s2 * c3 - s1 * c2 * s3; 5703 this._z = c1 * c2 * s3 + s1 * s2 * c3; 5704 this._w = c1 * c2 * c3 + s1 * s2 * s3; 5705 5706 } 5707 5708 if ( update !== false ) this.onChangeCallback(); 5709 5710 return this; 5711 5712 }, 5713 5714 setFromAxisAngle: function ( axis, angle ) { 5715 5716 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm 5717 5718 // assumes axis is normalized 5719 5720 var halfAngle = angle / 2, s = Math.sin( halfAngle ); 5721 5722 this._x = axis.x * s; 5723 this._y = axis.y * s; 5724 this._z = axis.z * s; 5725 this._w = Math.cos( halfAngle ); 5726 5727 this.onChangeCallback(); 5728 5729 return this; 5730 5731 }, 5732 5733 setFromRotationMatrix: function ( m ) { 5734 5735 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm 5736 5737 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 5738 5739 var te = m.elements, 5740 5741 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 5742 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 5743 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], 5744 5745 trace = m11 + m22 + m33, 5746 s; 5747 5748 if ( trace > 0 ) { 5749 5750 s = 0.5 / Math.sqrt( trace + 1.0 ); 5751 5752 this._w = 0.25 / s; 5753 this._x = ( m32 - m23 ) * s; 5754 this._y = ( m13 - m31 ) * s; 5755 this._z = ( m21 - m12 ) * s; 5756 5757 } else if ( m11 > m22 && m11 > m33 ) { 5758 5759 s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); 5760 5761 this._w = ( m32 - m23 ) / s; 5762 this._x = 0.25 * s; 5763 this._y = ( m12 + m21 ) / s; 5764 this._z = ( m13 + m31 ) / s; 5765 5766 } else if ( m22 > m33 ) { 5767 5768 s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); 5769 5770 this._w = ( m13 - m31 ) / s; 5771 this._x = ( m12 + m21 ) / s; 5772 this._y = 0.25 * s; 5773 this._z = ( m23 + m32 ) / s; 5774 5775 } else { 5776 5777 s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); 5778 5779 this._w = ( m21 - m12 ) / s; 5780 this._x = ( m13 + m31 ) / s; 5781 this._y = ( m23 + m32 ) / s; 5782 this._z = 0.25 * s; 5783 5784 } 5785 5786 this.onChangeCallback(); 5787 5788 return this; 5789 5790 }, 5791 5792 setFromUnitVectors: function () { 5793 5794 // assumes direction vectors vFrom and vTo are normalized 5795 5796 var v1 = new Vector3(); 5797 var r; 5798 5799 var EPS = 0.000001; 5800 5801 return function setFromUnitVectors( vFrom, vTo ) { 5802 5803 if ( v1 === undefined ) v1 = new Vector3(); 5804 5805 r = vFrom.dot( vTo ) + 1; 5806 5807 if ( r < EPS ) { 5808 5809 r = 0; 5810 5811 if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { 5812 5813 v1.set( - vFrom.y, vFrom.x, 0 ); 5814 5815 } else { 5816 5817 v1.set( 0, - vFrom.z, vFrom.y ); 5818 5819 } 5820 5821 } else { 5822 5823 v1.crossVectors( vFrom, vTo ); 5824 5825 } 5826 5827 this._x = v1.x; 5828 this._y = v1.y; 5829 this._z = v1.z; 5830 this._w = r; 5831 5832 return this.normalize(); 5833 5834 }; 5835 5836 }(), 5837 5838 inverse: function () { 5839 5840 // quaternion is assumed to have unit length 5841 5842 return this.conjugate(); 5843 5844 }, 5845 5846 conjugate: function () { 5847 5848 this._x *= - 1; 5849 this._y *= - 1; 5850 this._z *= - 1; 5851 5852 this.onChangeCallback(); 5853 5854 return this; 5855 5856 }, 5857 5858 dot: function ( v ) { 5859 5860 return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w; 5861 5862 }, 5863 5864 lengthSq: function () { 5865 5866 return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w; 5867 5868 }, 5869 5870 length: function () { 5871 5872 return Math.sqrt( this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w ); 5873 5874 }, 5875 5876 normalize: function () { 5877 5878 var l = this.length(); 5879 5880 if ( l === 0 ) { 5881 5882 this._x = 0; 5883 this._y = 0; 5884 this._z = 0; 5885 this._w = 1; 5886 5887 } else { 5888 5889 l = 1 / l; 5890 5891 this._x = this._x * l; 5892 this._y = this._y * l; 5893 this._z = this._z * l; 5894 this._w = this._w * l; 5895 5896 } 5897 5898 this.onChangeCallback(); 5899 5900 return this; 5901 5902 }, 5903 5904 multiply: function ( q, p ) { 5905 5906 if ( p !== undefined ) { 5907 5908 console.warn( 'THREE.Quaternion: .multiply() now only accepts one argument. Use .multiplyQuaternions( a, b ) instead.' ); 5909 return this.multiplyQuaternions( q, p ); 5910 5911 } 5912 5913 return this.multiplyQuaternions( this, q ); 5914 5915 }, 5916 5917 premultiply: function ( q ) { 5918 5919 return this.multiplyQuaternions( q, this ); 5920 5921 }, 5922 5923 multiplyQuaternions: function ( a, b ) { 5924 5925 // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm 5926 5927 var qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; 5928 var qbx = b._x, qby = b._y, qbz = b._z, qbw = b._w; 5929 5930 this._x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby; 5931 this._y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz; 5932 this._z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx; 5933 this._w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz; 5934 5935 this.onChangeCallback(); 5936 5937 return this; 5938 5939 }, 5940 5941 slerp: function ( qb, t ) { 5942 5943 if ( t === 0 ) return this; 5944 if ( t === 1 ) return this.copy( qb ); 5945 5946 var x = this._x, y = this._y, z = this._z, w = this._w; 5947 5948 // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ 5949 5950 var cosHalfTheta = w * qb._w + x * qb._x + y * qb._y + z * qb._z; 5951 5952 if ( cosHalfTheta < 0 ) { 5953 5954 this._w = - qb._w; 5955 this._x = - qb._x; 5956 this._y = - qb._y; 5957 this._z = - qb._z; 5958 5959 cosHalfTheta = - cosHalfTheta; 5960 5961 } else { 5962 5963 this.copy( qb ); 5964 5965 } 5966 5967 if ( cosHalfTheta >= 1.0 ) { 5968 5969 this._w = w; 5970 this._x = x; 5971 this._y = y; 5972 this._z = z; 5973 5974 return this; 5975 5976 } 5977 5978 var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta ); 5979 5980 if ( Math.abs( sinHalfTheta ) < 0.001 ) { 5981 5982 this._w = 0.5 * ( w + this._w ); 5983 this._x = 0.5 * ( x + this._x ); 5984 this._y = 0.5 * ( y + this._y ); 5985 this._z = 0.5 * ( z + this._z ); 5986 5987 return this; 5988 5989 } 5990 5991 var halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); 5992 var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta, 5993 ratioB = Math.sin( t * halfTheta ) / sinHalfTheta; 5994 5995 this._w = ( w * ratioA + this._w * ratioB ); 5996 this._x = ( x * ratioA + this._x * ratioB ); 5997 this._y = ( y * ratioA + this._y * ratioB ); 5998 this._z = ( z * ratioA + this._z * ratioB ); 5999 6000 this.onChangeCallback(); 6001 6002 return this; 6003 6004 }, 6005 6006 equals: function ( quaternion ) { 6007 6008 return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); 6009 6010 }, 6011 6012 fromArray: function ( array, offset ) { 6013 6014 if ( offset === undefined ) offset = 0; 6015 6016 this._x = array[ offset ]; 6017 this._y = array[ offset + 1 ]; 6018 this._z = array[ offset + 2 ]; 6019 this._w = array[ offset + 3 ]; 6020 6021 this.onChangeCallback(); 6022 6023 return this; 6024 6025 }, 6026 6027 toArray: function ( array, offset ) { 6028 6029 if ( array === undefined ) array = []; 6030 if ( offset === undefined ) offset = 0; 6031 6032 array[ offset ] = this._x; 6033 array[ offset + 1 ] = this._y; 6034 array[ offset + 2 ] = this._z; 6035 array[ offset + 3 ] = this._w; 6036 6037 return array; 6038 6039 }, 6040 6041 onChange: function ( callback ) { 6042 6043 this.onChangeCallback = callback; 6044 6045 return this; 6046 6047 }, 6048 6049 onChangeCallback: function () {} 6050 6051 } ); 6052 6053 /** 6054 * @author mrdoob / http://mrdoob.com/ 6055 * @author kile / http://kile.stravaganza.org/ 6056 * @author philogb / http://blog.thejit.org/ 6057 * @author mikael emtinger / http://gomo.se/ 6058 * @author egraether / http://egraether.com/ 6059 * @author WestLangley / http://github.com/WestLangley 6060 */ 6061 6062 function Vector3( x, y, z ) { 6063 6064 this.x = x || 0; 6065 this.y = y || 0; 6066 this.z = z || 0; 6067 6068 } 6069 6070 Object.assign( Vector3.prototype, { 6071 6072 isVector3: true, 6073 6074 set: function ( x, y, z ) { 6075 6076 this.x = x; 6077 this.y = y; 6078 this.z = z; 6079 6080 return this; 6081 6082 }, 6083 6084 setScalar: function ( scalar ) { 6085 6086 this.x = scalar; 6087 this.y = scalar; 6088 this.z = scalar; 6089 6090 return this; 6091 6092 }, 6093 6094 setX: function ( x ) { 6095 6096 this.x = x; 6097 6098 return this; 6099 6100 }, 6101 6102 setY: function ( y ) { 6103 6104 this.y = y; 6105 6106 return this; 6107 6108 }, 6109 6110 setZ: function ( z ) { 6111 6112 this.z = z; 6113 6114 return this; 6115 6116 }, 6117 6118 setComponent: function ( index, value ) { 6119 6120 switch ( index ) { 6121 6122 case 0: this.x = value; break; 6123 case 1: this.y = value; break; 6124 case 2: this.z = value; break; 6125 default: throw new Error( 'index is out of range: ' + index ); 6126 6127 } 6128 6129 return this; 6130 6131 }, 6132 6133 getComponent: function ( index ) { 6134 6135 switch ( index ) { 6136 6137 case 0: return this.x; 6138 case 1: return this.y; 6139 case 2: return this.z; 6140 default: throw new Error( 'index is out of range: ' + index ); 6141 6142 } 6143 6144 }, 6145 6146 clone: function () { 6147 6148 return new this.constructor( this.x, this.y, this.z ); 6149 6150 }, 6151 6152 copy: function ( v ) { 6153 6154 this.x = v.x; 6155 this.y = v.y; 6156 this.z = v.z; 6157 6158 return this; 6159 6160 }, 6161 6162 add: function ( v, w ) { 6163 6164 if ( w !== undefined ) { 6165 6166 console.warn( 'THREE.Vector3: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); 6167 return this.addVectors( v, w ); 6168 6169 } 6170 6171 this.x += v.x; 6172 this.y += v.y; 6173 this.z += v.z; 6174 6175 return this; 6176 6177 }, 6178 6179 addScalar: function ( s ) { 6180 6181 this.x += s; 6182 this.y += s; 6183 this.z += s; 6184 6185 return this; 6186 6187 }, 6188 6189 addVectors: function ( a, b ) { 6190 6191 this.x = a.x + b.x; 6192 this.y = a.y + b.y; 6193 this.z = a.z + b.z; 6194 6195 return this; 6196 6197 }, 6198 6199 addScaledVector: function ( v, s ) { 6200 6201 this.x += v.x * s; 6202 this.y += v.y * s; 6203 this.z += v.z * s; 6204 6205 return this; 6206 6207 }, 6208 6209 sub: function ( v, w ) { 6210 6211 if ( w !== undefined ) { 6212 6213 console.warn( 'THREE.Vector3: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); 6214 return this.subVectors( v, w ); 6215 6216 } 6217 6218 this.x -= v.x; 6219 this.y -= v.y; 6220 this.z -= v.z; 6221 6222 return this; 6223 6224 }, 6225 6226 subScalar: function ( s ) { 6227 6228 this.x -= s; 6229 this.y -= s; 6230 this.z -= s; 6231 6232 return this; 6233 6234 }, 6235 6236 subVectors: function ( a, b ) { 6237 6238 this.x = a.x - b.x; 6239 this.y = a.y - b.y; 6240 this.z = a.z - b.z; 6241 6242 return this; 6243 6244 }, 6245 6246 multiply: function ( v, w ) { 6247 6248 if ( w !== undefined ) { 6249 6250 console.warn( 'THREE.Vector3: .multiply() now only accepts one argument. Use .multiplyVectors( a, b ) instead.' ); 6251 return this.multiplyVectors( v, w ); 6252 6253 } 6254 6255 this.x *= v.x; 6256 this.y *= v.y; 6257 this.z *= v.z; 6258 6259 return this; 6260 6261 }, 6262 6263 multiplyScalar: function ( scalar ) { 6264 6265 this.x *= scalar; 6266 this.y *= scalar; 6267 this.z *= scalar; 6268 6269 return this; 6270 6271 }, 6272 6273 multiplyVectors: function ( a, b ) { 6274 6275 this.x = a.x * b.x; 6276 this.y = a.y * b.y; 6277 this.z = a.z * b.z; 6278 6279 return this; 6280 6281 }, 6282 6283 applyEuler: function () { 6284 6285 var quaternion = new Quaternion(); 6286 6287 return function applyEuler( euler ) { 6288 6289 if ( ! ( euler && euler.isEuler ) ) { 6290 6291 console.error( 'THREE.Vector3: .applyEuler() now expects an Euler rotation rather than a Vector3 and order.' ); 6292 6293 } 6294 6295 return this.applyQuaternion( quaternion.setFromEuler( euler ) ); 6296 6297 }; 6298 6299 }(), 6300 6301 applyAxisAngle: function () { 6302 6303 var quaternion = new Quaternion(); 6304 6305 return function applyAxisAngle( axis, angle ) { 6306 6307 return this.applyQuaternion( quaternion.setFromAxisAngle( axis, angle ) ); 6308 6309 }; 6310 6311 }(), 6312 6313 applyMatrix3: function ( m ) { 6314 6315 var x = this.x, y = this.y, z = this.z; 6316 var e = m.elements; 6317 6318 this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; 6319 this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; 6320 this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; 6321 6322 return this; 6323 6324 }, 6325 6326 applyMatrix4: function ( m ) { 6327 6328 var x = this.x, y = this.y, z = this.z; 6329 var e = m.elements; 6330 6331 var w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); 6332 6333 this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; 6334 this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; 6335 this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; 6336 6337 return this; 6338 6339 }, 6340 6341 applyQuaternion: function ( q ) { 6342 6343 var x = this.x, y = this.y, z = this.z; 6344 var qx = q.x, qy = q.y, qz = q.z, qw = q.w; 6345 6346 // calculate quat * vector 6347 6348 var ix = qw * x + qy * z - qz * y; 6349 var iy = qw * y + qz * x - qx * z; 6350 var iz = qw * z + qx * y - qy * x; 6351 var iw = - qx * x - qy * y - qz * z; 6352 6353 // calculate result * inverse quat 6354 6355 this.x = ix * qw + iw * - qx + iy * - qz - iz * - qy; 6356 this.y = iy * qw + iw * - qy + iz * - qx - ix * - qz; 6357 this.z = iz * qw + iw * - qz + ix * - qy - iy * - qx; 6358 6359 return this; 6360 6361 }, 6362 6363 project: function () { 6364 6365 var matrix = new Matrix4(); 6366 6367 return function project( camera ) { 6368 6369 matrix.multiplyMatrices( camera.projectionMatrix, matrix.getInverse( camera.matrixWorld ) ); 6370 return this.applyMatrix4( matrix ); 6371 6372 }; 6373 6374 }(), 6375 6376 unproject: function () { 6377 6378 var matrix = new Matrix4(); 6379 6380 return function unproject( camera ) { 6381 6382 matrix.multiplyMatrices( camera.matrixWorld, matrix.getInverse( camera.projectionMatrix ) ); 6383 return this.applyMatrix4( matrix ); 6384 6385 }; 6386 6387 }(), 6388 6389 transformDirection: function ( m ) { 6390 6391 // input: THREE.Matrix4 affine matrix 6392 // vector interpreted as a direction 6393 6394 var x = this.x, y = this.y, z = this.z; 6395 var e = m.elements; 6396 6397 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; 6398 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; 6399 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; 6400 6401 return this.normalize(); 6402 6403 }, 6404 6405 divide: function ( v ) { 6406 6407 this.x /= v.x; 6408 this.y /= v.y; 6409 this.z /= v.z; 6410 6411 return this; 6412 6413 }, 6414 6415 divideScalar: function ( scalar ) { 6416 6417 return this.multiplyScalar( 1 / scalar ); 6418 6419 }, 6420 6421 min: function ( v ) { 6422 6423 this.x = Math.min( this.x, v.x ); 6424 this.y = Math.min( this.y, v.y ); 6425 this.z = Math.min( this.z, v.z ); 6426 6427 return this; 6428 6429 }, 6430 6431 max: function ( v ) { 6432 6433 this.x = Math.max( this.x, v.x ); 6434 this.y = Math.max( this.y, v.y ); 6435 this.z = Math.max( this.z, v.z ); 6436 6437 return this; 6438 6439 }, 6440 6441 clamp: function ( min, max ) { 6442 6443 // assumes min < max, componentwise 6444 6445 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 6446 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 6447 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 6448 6449 return this; 6450 6451 }, 6452 6453 clampScalar: function () { 6454 6455 var min = new Vector3(); 6456 var max = new Vector3(); 6457 6458 return function clampScalar( minVal, maxVal ) { 6459 6460 min.set( minVal, minVal, minVal ); 6461 max.set( maxVal, maxVal, maxVal ); 6462 6463 return this.clamp( min, max ); 6464 6465 }; 6466 6467 }(), 6468 6469 clampLength: function ( min, max ) { 6470 6471 var length = this.length(); 6472 6473 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 6474 6475 }, 6476 6477 floor: function () { 6478 6479 this.x = Math.floor( this.x ); 6480 this.y = Math.floor( this.y ); 6481 this.z = Math.floor( this.z ); 6482 6483 return this; 6484 6485 }, 6486 6487 ceil: function () { 6488 6489 this.x = Math.ceil( this.x ); 6490 this.y = Math.ceil( this.y ); 6491 this.z = Math.ceil( this.z ); 6492 6493 return this; 6494 6495 }, 6496 6497 round: function () { 6498 6499 this.x = Math.round( this.x ); 6500 this.y = Math.round( this.y ); 6501 this.z = Math.round( this.z ); 6502 6503 return this; 6504 6505 }, 6506 6507 roundToZero: function () { 6508 6509 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); 6510 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); 6511 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); 6512 6513 return this; 6514 6515 }, 6516 6517 negate: function () { 6518 6519 this.x = - this.x; 6520 this.y = - this.y; 6521 this.z = - this.z; 6522 6523 return this; 6524 6525 }, 6526 6527 dot: function ( v ) { 6528 6529 return this.x * v.x + this.y * v.y + this.z * v.z; 6530 6531 }, 6532 6533 // TODO lengthSquared? 6534 6535 lengthSq: function () { 6536 6537 return this.x * this.x + this.y * this.y + this.z * this.z; 6538 6539 }, 6540 6541 length: function () { 6542 6543 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z ); 6544 6545 }, 6546 6547 manhattanLength: function () { 6548 6549 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ); 6550 6551 }, 6552 6553 normalize: function () { 6554 6555 return this.divideScalar( this.length() || 1 ); 6556 6557 }, 6558 6559 setLength: function ( length ) { 6560 6561 return this.normalize().multiplyScalar( length ); 6562 6563 }, 6564 6565 lerp: function ( v, alpha ) { 6566 6567 this.x += ( v.x - this.x ) * alpha; 6568 this.y += ( v.y - this.y ) * alpha; 6569 this.z += ( v.z - this.z ) * alpha; 6570 6571 return this; 6572 6573 }, 6574 6575 lerpVectors: function ( v1, v2, alpha ) { 6576 6577 return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); 6578 6579 }, 6580 6581 cross: function ( v, w ) { 6582 6583 if ( w !== undefined ) { 6584 6585 console.warn( 'THREE.Vector3: .cross() now only accepts one argument. Use .crossVectors( a, b ) instead.' ); 6586 return this.crossVectors( v, w ); 6587 6588 } 6589 6590 return this.crossVectors( this, v ); 6591 6592 }, 6593 6594 crossVectors: function ( a, b ) { 6595 6596 var ax = a.x, ay = a.y, az = a.z; 6597 var bx = b.x, by = b.y, bz = b.z; 6598 6599 this.x = ay * bz - az * by; 6600 this.y = az * bx - ax * bz; 6601 this.z = ax * by - ay * bx; 6602 6603 return this; 6604 6605 }, 6606 6607 projectOnVector: function ( vector ) { 6608 6609 var scalar = vector.dot( this ) / vector.lengthSq(); 6610 6611 return this.copy( vector ).multiplyScalar( scalar ); 6612 6613 }, 6614 6615 projectOnPlane: function () { 6616 6617 var v1 = new Vector3(); 6618 6619 return function projectOnPlane( planeNormal ) { 6620 6621 v1.copy( this ).projectOnVector( planeNormal ); 6622 6623 return this.sub( v1 ); 6624 6625 }; 6626 6627 }(), 6628 6629 reflect: function () { 6630 6631 // reflect incident vector off plane orthogonal to normal 6632 // normal is assumed to have unit length 6633 6634 var v1 = new Vector3(); 6635 6636 return function reflect( normal ) { 6637 6638 return this.sub( v1.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); 6639 6640 }; 6641 6642 }(), 6643 6644 angleTo: function ( v ) { 6645 6646 var theta = this.dot( v ) / ( Math.sqrt( this.lengthSq() * v.lengthSq() ) ); 6647 6648 // clamp, to handle numerical problems 6649 6650 return Math.acos( _Math.clamp( theta, - 1, 1 ) ); 6651 6652 }, 6653 6654 distanceTo: function ( v ) { 6655 6656 return Math.sqrt( this.distanceToSquared( v ) ); 6657 6658 }, 6659 6660 distanceToSquared: function ( v ) { 6661 6662 var dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; 6663 6664 return dx * dx + dy * dy + dz * dz; 6665 6666 }, 6667 6668 manhattanDistanceTo: function ( v ) { 6669 6670 return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); 6671 6672 }, 6673 6674 setFromSpherical: function ( s ) { 6675 6676 var sinPhiRadius = Math.sin( s.phi ) * s.radius; 6677 6678 this.x = sinPhiRadius * Math.sin( s.theta ); 6679 this.y = Math.cos( s.phi ) * s.radius; 6680 this.z = sinPhiRadius * Math.cos( s.theta ); 6681 6682 return this; 6683 6684 }, 6685 6686 setFromCylindrical: function ( c ) { 6687 6688 this.x = c.radius * Math.sin( c.theta ); 6689 this.y = c.y; 6690 this.z = c.radius * Math.cos( c.theta ); 6691 6692 return this; 6693 6694 }, 6695 6696 setFromMatrixPosition: function ( m ) { 6697 6698 var e = m.elements; 6699 6700 this.x = e[ 12 ]; 6701 this.y = e[ 13 ]; 6702 this.z = e[ 14 ]; 6703 6704 return this; 6705 6706 }, 6707 6708 setFromMatrixScale: function ( m ) { 6709 6710 var sx = this.setFromMatrixColumn( m, 0 ).length(); 6711 var sy = this.setFromMatrixColumn( m, 1 ).length(); 6712 var sz = this.setFromMatrixColumn( m, 2 ).length(); 6713 6714 this.x = sx; 6715 this.y = sy; 6716 this.z = sz; 6717 6718 return this; 6719 6720 }, 6721 6722 setFromMatrixColumn: function ( m, index ) { 6723 6724 return this.fromArray( m.elements, index * 4 ); 6725 6726 }, 6727 6728 equals: function ( v ) { 6729 6730 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); 6731 6732 }, 6733 6734 fromArray: function ( array, offset ) { 6735 6736 if ( offset === undefined ) offset = 0; 6737 6738 this.x = array[ offset ]; 6739 this.y = array[ offset + 1 ]; 6740 this.z = array[ offset + 2 ]; 6741 6742 return this; 6743 6744 }, 6745 6746 toArray: function ( array, offset ) { 6747 6748 if ( array === undefined ) array = []; 6749 if ( offset === undefined ) offset = 0; 6750 6751 array[ offset ] = this.x; 6752 array[ offset + 1 ] = this.y; 6753 array[ offset + 2 ] = this.z; 6754 6755 return array; 6756 6757 }, 6758 6759 fromBufferAttribute: function ( attribute, index, offset ) { 6760 6761 if ( offset !== undefined ) { 6762 6763 console.warn( 'THREE.Vector3: offset has been removed from .fromBufferAttribute().' ); 6764 6765 } 6766 6767 this.x = attribute.getX( index ); 6768 this.y = attribute.getY( index ); 6769 this.z = attribute.getZ( index ); 6770 6771 return this; 6772 6773 } 6774 6775 } ); 6776 6777 /** 6778 * @author alteredq / http://alteredqualia.com/ 6779 * @author WestLangley / http://github.com/WestLangley 6780 * @author bhouston / http://clara.io 6781 * @author tschw 6782 */ 6783 6784 function Matrix3() { 6785 6786 this.elements = [ 6787 6788 1, 0, 0, 6789 0, 1, 0, 6790 0, 0, 1 6791 6792 ]; 6793 6794 if ( arguments.length > 0 ) { 6795 6796 console.error( 'THREE.Matrix3: the constructor no longer reads arguments. use .set() instead.' ); 6797 6798 } 6799 6800 } 6801 6802 Object.assign( Matrix3.prototype, { 6803 6804 isMatrix3: true, 6805 6806 set: function ( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { 6807 6808 var te = this.elements; 6809 6810 te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31; 6811 te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32; 6812 te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33; 6813 6814 return this; 6815 6816 }, 6817 6818 identity: function () { 6819 6820 this.set( 6821 6822 1, 0, 0, 6823 0, 1, 0, 6824 0, 0, 1 6825 6826 ); 6827 6828 return this; 6829 6830 }, 6831 6832 clone: function () { 6833 6834 return new this.constructor().fromArray( this.elements ); 6835 6836 }, 6837 6838 copy: function ( m ) { 6839 6840 var te = this.elements; 6841 var me = m.elements; 6842 6843 te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; 6844 te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; 6845 te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ]; 6846 6847 return this; 6848 6849 }, 6850 6851 setFromMatrix4: function ( m ) { 6852 6853 var me = m.elements; 6854 6855 this.set( 6856 6857 me[ 0 ], me[ 4 ], me[ 8 ], 6858 me[ 1 ], me[ 5 ], me[ 9 ], 6859 me[ 2 ], me[ 6 ], me[ 10 ] 6860 6861 ); 6862 6863 return this; 6864 6865 }, 6866 6867 applyToBufferAttribute: function () { 6868 6869 var v1 = new Vector3(); 6870 6871 return function applyToBufferAttribute( attribute ) { 6872 6873 for ( var i = 0, l = attribute.count; i < l; i ++ ) { 6874 6875 v1.x = attribute.getX( i ); 6876 v1.y = attribute.getY( i ); 6877 v1.z = attribute.getZ( i ); 6878 6879 v1.applyMatrix3( this ); 6880 6881 attribute.setXYZ( i, v1.x, v1.y, v1.z ); 6882 6883 } 6884 6885 return attribute; 6886 6887 }; 6888 6889 }(), 6890 6891 multiply: function ( m ) { 6892 6893 return this.multiplyMatrices( this, m ); 6894 6895 }, 6896 6897 premultiply: function ( m ) { 6898 6899 return this.multiplyMatrices( m, this ); 6900 6901 }, 6902 6903 multiplyMatrices: function ( a, b ) { 6904 6905 var ae = a.elements; 6906 var be = b.elements; 6907 var te = this.elements; 6908 6909 var a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ]; 6910 var a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ]; 6911 var a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ]; 6912 6913 var b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ]; 6914 var b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ]; 6915 var b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ]; 6916 6917 te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; 6918 te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; 6919 te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; 6920 6921 te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; 6922 te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; 6923 te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; 6924 6925 te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; 6926 te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; 6927 te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; 6928 6929 return this; 6930 6931 }, 6932 6933 multiplyScalar: function ( s ) { 6934 6935 var te = this.elements; 6936 6937 te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s; 6938 te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s; 6939 te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s; 6940 6941 return this; 6942 6943 }, 6944 6945 determinant: function () { 6946 6947 var te = this.elements; 6948 6949 var a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], 6950 d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], 6951 g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; 6952 6953 return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; 6954 6955 }, 6956 6957 getInverse: function ( matrix, throwOnDegenerate ) { 6958 6959 if ( matrix && matrix.isMatrix4 ) { 6960 6961 console.error( "THREE.Matrix3: .getInverse() no longer takes a Matrix4 argument." ); 6962 6963 } 6964 6965 var me = matrix.elements, 6966 te = this.elements, 6967 6968 n11 = me[ 0 ], n21 = me[ 1 ], n31 = me[ 2 ], 6969 n12 = me[ 3 ], n22 = me[ 4 ], n32 = me[ 5 ], 6970 n13 = me[ 6 ], n23 = me[ 7 ], n33 = me[ 8 ], 6971 6972 t11 = n33 * n22 - n32 * n23, 6973 t12 = n32 * n13 - n33 * n12, 6974 t13 = n23 * n12 - n22 * n13, 6975 6976 det = n11 * t11 + n21 * t12 + n31 * t13; 6977 6978 if ( det === 0 ) { 6979 6980 var msg = "THREE.Matrix3: .getInverse() can't invert matrix, determinant is 0"; 6981 6982 if ( throwOnDegenerate === true ) { 6983 6984 throw new Error( msg ); 6985 6986 } else { 6987 6988 console.warn( msg ); 6989 6990 } 6991 6992 return this.identity(); 6993 6994 } 6995 6996 var detInv = 1 / det; 6997 6998 te[ 0 ] = t11 * detInv; 6999 te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; 7000 te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; 7001 7002 te[ 3 ] = t12 * detInv; 7003 te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; 7004 te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; 7005 7006 te[ 6 ] = t13 * detInv; 7007 te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; 7008 te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; 7009 7010 return this; 7011 7012 }, 7013 7014 transpose: function () { 7015 7016 var tmp, m = this.elements; 7017 7018 tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; 7019 tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; 7020 tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; 7021 7022 return this; 7023 7024 }, 7025 7026 getNormalMatrix: function ( matrix4 ) { 7027 7028 return this.setFromMatrix4( matrix4 ).getInverse( this ).transpose(); 7029 7030 }, 7031 7032 transposeIntoArray: function ( r ) { 7033 7034 var m = this.elements; 7035 7036 r[ 0 ] = m[ 0 ]; 7037 r[ 1 ] = m[ 3 ]; 7038 r[ 2 ] = m[ 6 ]; 7039 r[ 3 ] = m[ 1 ]; 7040 r[ 4 ] = m[ 4 ]; 7041 r[ 5 ] = m[ 7 ]; 7042 r[ 6 ] = m[ 2 ]; 7043 r[ 7 ] = m[ 5 ]; 7044 r[ 8 ] = m[ 8 ]; 7045 7046 return this; 7047 7048 }, 7049 7050 setUvTransform: function ( tx, ty, sx, sy, rotation, cx, cy ) { 7051 7052 var c = Math.cos( rotation ); 7053 var s = Math.sin( rotation ); 7054 7055 this.set( 7056 sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, 7057 - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, 7058 0, 0, 1 7059 ); 7060 7061 }, 7062 7063 scale: function ( sx, sy ) { 7064 7065 var te = this.elements; 7066 7067 te[ 0 ] *= sx; te[ 3 ] *= sx; te[ 6 ] *= sx; 7068 te[ 1 ] *= sy; te[ 4 ] *= sy; te[ 7 ] *= sy; 7069 7070 return this; 7071 7072 }, 7073 7074 rotate: function ( theta ) { 7075 7076 var c = Math.cos( theta ); 7077 var s = Math.sin( theta ); 7078 7079 var te = this.elements; 7080 7081 var a11 = te[ 0 ], a12 = te[ 3 ], a13 = te[ 6 ]; 7082 var a21 = te[ 1 ], a22 = te[ 4 ], a23 = te[ 7 ]; 7083 7084 te[ 0 ] = c * a11 + s * a21; 7085 te[ 3 ] = c * a12 + s * a22; 7086 te[ 6 ] = c * a13 + s * a23; 7087 7088 te[ 1 ] = - s * a11 + c * a21; 7089 te[ 4 ] = - s * a12 + c * a22; 7090 te[ 7 ] = - s * a13 + c * a23; 7091 7092 return this; 7093 7094 }, 7095 7096 translate: function ( tx, ty ) { 7097 7098 var te = this.elements; 7099 7100 te[ 0 ] += tx * te[ 2 ]; te[ 3 ] += tx * te[ 5 ]; te[ 6 ] += tx * te[ 8 ]; 7101 te[ 1 ] += ty * te[ 2 ]; te[ 4 ] += ty * te[ 5 ]; te[ 7 ] += ty * te[ 8 ]; 7102 7103 return this; 7104 7105 }, 7106 7107 equals: function ( matrix ) { 7108 7109 var te = this.elements; 7110 var me = matrix.elements; 7111 7112 for ( var i = 0; i < 9; i ++ ) { 7113 7114 if ( te[ i ] !== me[ i ] ) return false; 7115 7116 } 7117 7118 return true; 7119 7120 }, 7121 7122 fromArray: function ( array, offset ) { 7123 7124 if ( offset === undefined ) offset = 0; 7125 7126 for ( var i = 0; i < 9; i ++ ) { 7127 7128 this.elements[ i ] = array[ i + offset ]; 7129 7130 } 7131 7132 return this; 7133 7134 }, 7135 7136 toArray: function ( array, offset ) { 7137 7138 if ( array === undefined ) array = []; 7139 if ( offset === undefined ) offset = 0; 7140 7141 var te = this.elements; 7142 7143 array[ offset ] = te[ 0 ]; 7144 array[ offset + 1 ] = te[ 1 ]; 7145 array[ offset + 2 ] = te[ 2 ]; 7146 7147 array[ offset + 3 ] = te[ 3 ]; 7148 array[ offset + 4 ] = te[ 4 ]; 7149 array[ offset + 5 ] = te[ 5 ]; 7150 7151 array[ offset + 6 ] = te[ 6 ]; 7152 array[ offset + 7 ] = te[ 7 ]; 7153 array[ offset + 8 ] = te[ 8 ]; 7154 7155 return array; 7156 7157 } 7158 7159 } ); 7160 7161 /** 7162 * @author mrdoob / http://mrdoob.com/ 7163 * @author alteredq / http://alteredqualia.com/ 7164 * @author szimek / https://github.com/szimek/ 7165 */ 7166 7167 var textureId = 0; 7168 7169 function Texture( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { 7170 7171 Object.defineProperty( this, 'id', { value: textureId ++ } ); 7172 7173 this.uuid = _Math.generateUUID(); 7174 7175 this.name = ''; 7176 7177 this.image = image !== undefined ? image : Texture.DEFAULT_IMAGE; 7178 this.mipmaps = []; 7179 7180 this.mapping = mapping !== undefined ? mapping : Texture.DEFAULT_MAPPING; 7181 7182 this.wrapS = wrapS !== undefined ? wrapS : ClampToEdgeWrapping; 7183 this.wrapT = wrapT !== undefined ? wrapT : ClampToEdgeWrapping; 7184 7185 this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; 7186 this.minFilter = minFilter !== undefined ? minFilter : LinearMipMapLinearFilter; 7187 7188 this.anisotropy = anisotropy !== undefined ? anisotropy : 1; 7189 7190 this.format = format !== undefined ? format : RGBAFormat; 7191 this.type = type !== undefined ? type : UnsignedByteType; 7192 7193 this.offset = new Vector2( 0, 0 ); 7194 this.repeat = new Vector2( 1, 1 ); 7195 this.center = new Vector2( 0, 0 ); 7196 this.rotation = 0; 7197 7198 this.matrixAutoUpdate = true; 7199 this.matrix = new Matrix3(); 7200 7201 this.generateMipmaps = true; 7202 this.premultiplyAlpha = false; 7203 this.flipY = true; 7204 this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) 7205 7206 // Values of encoding !== THREE.LinearEncoding only supported on map, envMap and emissiveMap. 7207 // 7208 // Also changing the encoding after already used by a Material will not automatically make the Material 7209 // update. You need to explicitly call Material.needsUpdate to trigger it to recompile. 7210 this.encoding = encoding !== undefined ? encoding : LinearEncoding; 7211 7212 this.version = 0; 7213 this.onUpdate = null; 7214 7215 } 7216 7217 Texture.DEFAULT_IMAGE = undefined; 7218 Texture.DEFAULT_MAPPING = UVMapping; 7219 7220 Texture.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { 7221 7222 constructor: Texture, 7223 7224 isTexture: true, 7225 7226 updateMatrix: function () { 7227 7228 this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); 7229 7230 }, 7231 7232 clone: function () { 7233 7234 return new this.constructor().copy( this ); 7235 7236 }, 7237 7238 copy: function ( source ) { 7239 7240 this.name = source.name; 7241 7242 this.image = source.image; 7243 this.mipmaps = source.mipmaps.slice( 0 ); 7244 7245 this.mapping = source.mapping; 7246 7247 this.wrapS = source.wrapS; 7248 this.wrapT = source.wrapT; 7249 7250 this.magFilter = source.magFilter; 7251 this.minFilter = source.minFilter; 7252 7253 this.anisotropy = source.anisotropy; 7254 7255 this.format = source.format; 7256 this.type = source.type; 7257 7258 this.offset.copy( source.offset ); 7259 this.repeat.copy( source.repeat ); 7260 this.center.copy( source.center ); 7261 this.rotation = source.rotation; 7262 7263 this.matrixAutoUpdate = source.matrixAutoUpdate; 7264 this.matrix.copy( source.matrix ); 7265 7266 this.generateMipmaps = source.generateMipmaps; 7267 this.premultiplyAlpha = source.premultiplyAlpha; 7268 this.flipY = source.flipY; 7269 this.unpackAlignment = source.unpackAlignment; 7270 this.encoding = source.encoding; 7271 7272 return this; 7273 7274 }, 7275 7276 toJSON: function ( meta ) { 7277 7278 var isRootObject = ( meta === undefined || typeof meta === 'string' ); 7279 7280 if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { 7281 7282 return meta.textures[ this.uuid ]; 7283 7284 } 7285 7286 function getDataURL( image ) { 7287 7288 var canvas; 7289 7290 if ( image instanceof HTMLCanvasElement ) { 7291 7292 canvas = image; 7293 7294 } else { 7295 7296 canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); 7297 canvas.width = image.width; 7298 canvas.height = image.height; 7299 7300 var context = canvas.getContext( '2d' ); 7301 7302 if ( image instanceof ImageData ) { 7303 7304 context.putImageData( image, 0, 0 ); 7305 7306 } else { 7307 7308 context.drawImage( image, 0, 0, image.width, image.height ); 7309 7310 } 7311 7312 } 7313 7314 if ( canvas.width > 2048 || canvas.height > 2048 ) { 7315 7316 return canvas.toDataURL( 'image/jpeg', 0.6 ); 7317 7318 } else { 7319 7320 return canvas.toDataURL( 'image/png' ); 7321 7322 } 7323 7324 } 7325 7326 var output = { 7327 7328 metadata: { 7329 version: 4.5, 7330 type: 'Texture', 7331 generator: 'Texture.toJSON' 7332 }, 7333 7334 uuid: this.uuid, 7335 name: this.name, 7336 7337 mapping: this.mapping, 7338 7339 repeat: [ this.repeat.x, this.repeat.y ], 7340 offset: [ this.offset.x, this.offset.y ], 7341 center: [ this.center.x, this.center.y ], 7342 rotation: this.rotation, 7343 7344 wrap: [ this.wrapS, this.wrapT ], 7345 7346 format: this.format, 7347 minFilter: this.minFilter, 7348 magFilter: this.magFilter, 7349 anisotropy: this.anisotropy, 7350 7351 flipY: this.flipY 7352 7353 }; 7354 7355 if ( this.image !== undefined ) { 7356 7357 // TODO: Move to THREE.Image 7358 7359 var image = this.image; 7360 7361 if ( image.uuid === undefined ) { 7362 7363 image.uuid = _Math.generateUUID(); // UGH 7364 7365 } 7366 7367 if ( ! isRootObject && meta.images[ image.uuid ] === undefined ) { 7368 7369 meta.images[ image.uuid ] = { 7370 uuid: image.uuid, 7371 url: getDataURL( image ) 7372 }; 7373 7374 } 7375 7376 output.image = image.uuid; 7377 7378 } 7379 7380 if ( ! isRootObject ) { 7381 7382 meta.textures[ this.uuid ] = output; 7383 7384 } 7385 7386 return output; 7387 7388 }, 7389 7390 dispose: function () { 7391 7392 this.dispatchEvent( { type: 'dispose' } ); 7393 7394 }, 7395 7396 transformUv: function ( uv ) { 7397 7398 if ( this.mapping !== UVMapping ) return; 7399 7400 uv.applyMatrix3( this.matrix ); 7401 7402 if ( uv.x < 0 || uv.x > 1 ) { 7403 7404 switch ( this.wrapS ) { 7405 7406 case RepeatWrapping: 7407 7408 uv.x = uv.x - Math.floor( uv.x ); 7409 break; 7410 7411 case ClampToEdgeWrapping: 7412 7413 uv.x = uv.x < 0 ? 0 : 1; 7414 break; 7415 7416 case MirroredRepeatWrapping: 7417 7418 if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { 7419 7420 uv.x = Math.ceil( uv.x ) - uv.x; 7421 7422 } else { 7423 7424 uv.x = uv.x - Math.floor( uv.x ); 7425 7426 } 7427 break; 7428 7429 } 7430 7431 } 7432 7433 if ( uv.y < 0 || uv.y > 1 ) { 7434 7435 switch ( this.wrapT ) { 7436 7437 case RepeatWrapping: 7438 7439 uv.y = uv.y - Math.floor( uv.y ); 7440 break; 7441 7442 case ClampToEdgeWrapping: 7443 7444 uv.y = uv.y < 0 ? 0 : 1; 7445 break; 7446 7447 case MirroredRepeatWrapping: 7448 7449 if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { 7450 7451 uv.y = Math.ceil( uv.y ) - uv.y; 7452 7453 } else { 7454 7455 uv.y = uv.y - Math.floor( uv.y ); 7456 7457 } 7458 break; 7459 7460 } 7461 7462 } 7463 7464 if ( this.flipY ) { 7465 7466 uv.y = 1 - uv.y; 7467 7468 } 7469 7470 } 7471 7472 } ); 7473 7474 Object.defineProperty( Texture.prototype, "needsUpdate", { 7475 7476 set: function ( value ) { 7477 7478 if ( value === true ) this.version ++; 7479 7480 } 7481 7482 } ); 7483 7484 /** 7485 * @author supereggbert / http://www.paulbrunt.co.uk/ 7486 * @author philogb / http://blog.thejit.org/ 7487 * @author mikael emtinger / http://gomo.se/ 7488 * @author egraether / http://egraether.com/ 7489 * @author WestLangley / http://github.com/WestLangley 7490 */ 7491 7492 function Vector4( x, y, z, w ) { 7493 7494 this.x = x || 0; 7495 this.y = y || 0; 7496 this.z = z || 0; 7497 this.w = ( w !== undefined ) ? w : 1; 7498 7499 } 7500 7501 Object.assign( Vector4.prototype, { 7502 7503 isVector4: true, 7504 7505 set: function ( x, y, z, w ) { 7506 7507 this.x = x; 7508 this.y = y; 7509 this.z = z; 7510 this.w = w; 7511 7512 return this; 7513 7514 }, 7515 7516 setScalar: function ( scalar ) { 7517 7518 this.x = scalar; 7519 this.y = scalar; 7520 this.z = scalar; 7521 this.w = scalar; 7522 7523 return this; 7524 7525 }, 7526 7527 setX: function ( x ) { 7528 7529 this.x = x; 7530 7531 return this; 7532 7533 }, 7534 7535 setY: function ( y ) { 7536 7537 this.y = y; 7538 7539 return this; 7540 7541 }, 7542 7543 setZ: function ( z ) { 7544 7545 this.z = z; 7546 7547 return this; 7548 7549 }, 7550 7551 setW: function ( w ) { 7552 7553 this.w = w; 7554 7555 return this; 7556 7557 }, 7558 7559 setComponent: function ( index, value ) { 7560 7561 switch ( index ) { 7562 7563 case 0: this.x = value; break; 7564 case 1: this.y = value; break; 7565 case 2: this.z = value; break; 7566 case 3: this.w = value; break; 7567 default: throw new Error( 'index is out of range: ' + index ); 7568 7569 } 7570 7571 return this; 7572 7573 }, 7574 7575 getComponent: function ( index ) { 7576 7577 switch ( index ) { 7578 7579 case 0: return this.x; 7580 case 1: return this.y; 7581 case 2: return this.z; 7582 case 3: return this.w; 7583 default: throw new Error( 'index is out of range: ' + index ); 7584 7585 } 7586 7587 }, 7588 7589 clone: function () { 7590 7591 return new this.constructor( this.x, this.y, this.z, this.w ); 7592 7593 }, 7594 7595 copy: function ( v ) { 7596 7597 this.x = v.x; 7598 this.y = v.y; 7599 this.z = v.z; 7600 this.w = ( v.w !== undefined ) ? v.w : 1; 7601 7602 return this; 7603 7604 }, 7605 7606 add: function ( v, w ) { 7607 7608 if ( w !== undefined ) { 7609 7610 console.warn( 'THREE.Vector4: .add() now only accepts one argument. Use .addVectors( a, b ) instead.' ); 7611 return this.addVectors( v, w ); 7612 7613 } 7614 7615 this.x += v.x; 7616 this.y += v.y; 7617 this.z += v.z; 7618 this.w += v.w; 7619 7620 return this; 7621 7622 }, 7623 7624 addScalar: function ( s ) { 7625 7626 this.x += s; 7627 this.y += s; 7628 this.z += s; 7629 this.w += s; 7630 7631 return this; 7632 7633 }, 7634 7635 addVectors: function ( a, b ) { 7636 7637 this.x = a.x + b.x; 7638 this.y = a.y + b.y; 7639 this.z = a.z + b.z; 7640 this.w = a.w + b.w; 7641 7642 return this; 7643 7644 }, 7645 7646 addScaledVector: function ( v, s ) { 7647 7648 this.x += v.x * s; 7649 this.y += v.y * s; 7650 this.z += v.z * s; 7651 this.w += v.w * s; 7652 7653 return this; 7654 7655 }, 7656 7657 sub: function ( v, w ) { 7658 7659 if ( w !== undefined ) { 7660 7661 console.warn( 'THREE.Vector4: .sub() now only accepts one argument. Use .subVectors( a, b ) instead.' ); 7662 return this.subVectors( v, w ); 7663 7664 } 7665 7666 this.x -= v.x; 7667 this.y -= v.y; 7668 this.z -= v.z; 7669 this.w -= v.w; 7670 7671 return this; 7672 7673 }, 7674 7675 subScalar: function ( s ) { 7676 7677 this.x -= s; 7678 this.y -= s; 7679 this.z -= s; 7680 this.w -= s; 7681 7682 return this; 7683 7684 }, 7685 7686 subVectors: function ( a, b ) { 7687 7688 this.x = a.x - b.x; 7689 this.y = a.y - b.y; 7690 this.z = a.z - b.z; 7691 this.w = a.w - b.w; 7692 7693 return this; 7694 7695 }, 7696 7697 multiplyScalar: function ( scalar ) { 7698 7699 this.x *= scalar; 7700 this.y *= scalar; 7701 this.z *= scalar; 7702 this.w *= scalar; 7703 7704 return this; 7705 7706 }, 7707 7708 applyMatrix4: function ( m ) { 7709 7710 var x = this.x, y = this.y, z = this.z, w = this.w; 7711 var e = m.elements; 7712 7713 this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; 7714 this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; 7715 this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; 7716 this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; 7717 7718 return this; 7719 7720 }, 7721 7722 divideScalar: function ( scalar ) { 7723 7724 return this.multiplyScalar( 1 / scalar ); 7725 7726 }, 7727 7728 setAxisAngleFromQuaternion: function ( q ) { 7729 7730 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm 7731 7732 // q is assumed to be normalized 7733 7734 this.w = 2 * Math.acos( q.w ); 7735 7736 var s = Math.sqrt( 1 - q.w * q.w ); 7737 7738 if ( s < 0.0001 ) { 7739 7740 this.x = 1; 7741 this.y = 0; 7742 this.z = 0; 7743 7744 } else { 7745 7746 this.x = q.x / s; 7747 this.y = q.y / s; 7748 this.z = q.z / s; 7749 7750 } 7751 7752 return this; 7753 7754 }, 7755 7756 setAxisAngleFromRotationMatrix: function ( m ) { 7757 7758 // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm 7759 7760 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 7761 7762 var angle, x, y, z, // variables for result 7763 epsilon = 0.01, // margin to allow for rounding errors 7764 epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees 7765 7766 te = m.elements, 7767 7768 m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], 7769 m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], 7770 m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 7771 7772 if ( ( Math.abs( m12 - m21 ) < epsilon ) && 7773 ( Math.abs( m13 - m31 ) < epsilon ) && 7774 ( Math.abs( m23 - m32 ) < epsilon ) ) { 7775 7776 // singularity found 7777 // first check for identity matrix which must have +1 for all terms 7778 // in leading diagonal and zero in other terms 7779 7780 if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && 7781 ( Math.abs( m13 + m31 ) < epsilon2 ) && 7782 ( Math.abs( m23 + m32 ) < epsilon2 ) && 7783 ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { 7784 7785 // this singularity is identity matrix so angle = 0 7786 7787 this.set( 1, 0, 0, 0 ); 7788 7789 return this; // zero angle, arbitrary axis 7790 7791 } 7792 7793 // otherwise this singularity is angle = 180 7794 7795 angle = Math.PI; 7796 7797 var xx = ( m11 + 1 ) / 2; 7798 var yy = ( m22 + 1 ) / 2; 7799 var zz = ( m33 + 1 ) / 2; 7800 var xy = ( m12 + m21 ) / 4; 7801 var xz = ( m13 + m31 ) / 4; 7802 var yz = ( m23 + m32 ) / 4; 7803 7804 if ( ( xx > yy ) && ( xx > zz ) ) { 7805 7806 // m11 is the largest diagonal term 7807 7808 if ( xx < epsilon ) { 7809 7810 x = 0; 7811 y = 0.707106781; 7812 z = 0.707106781; 7813 7814 } else { 7815 7816 x = Math.sqrt( xx ); 7817 y = xy / x; 7818 z = xz / x; 7819 7820 } 7821 7822 } else if ( yy > zz ) { 7823 7824 // m22 is the largest diagonal term 7825 7826 if ( yy < epsilon ) { 7827 7828 x = 0.707106781; 7829 y = 0; 7830 z = 0.707106781; 7831 7832 } else { 7833 7834 y = Math.sqrt( yy ); 7835 x = xy / y; 7836 z = yz / y; 7837 7838 } 7839 7840 } else { 7841 7842 // m33 is the largest diagonal term so base result on this 7843 7844 if ( zz < epsilon ) { 7845 7846 x = 0.707106781; 7847 y = 0.707106781; 7848 z = 0; 7849 7850 } else { 7851 7852 z = Math.sqrt( zz ); 7853 x = xz / z; 7854 y = yz / z; 7855 7856 } 7857 7858 } 7859 7860 this.set( x, y, z, angle ); 7861 7862 return this; // return 180 deg rotation 7863 7864 } 7865 7866 // as we have reached here there are no singularities so we can handle normally 7867 7868 var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + 7869 ( m13 - m31 ) * ( m13 - m31 ) + 7870 ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize 7871 7872 if ( Math.abs( s ) < 0.001 ) s = 1; 7873 7874 // prevent divide by zero, should not happen if matrix is orthogonal and should be 7875 // caught by singularity test above, but I've left it in just in case 7876 7877 this.x = ( m32 - m23 ) / s; 7878 this.y = ( m13 - m31 ) / s; 7879 this.z = ( m21 - m12 ) / s; 7880 this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); 7881 7882 return this; 7883 7884 }, 7885 7886 min: function ( v ) { 7887 7888 this.x = Math.min( this.x, v.x ); 7889 this.y = Math.min( this.y, v.y ); 7890 this.z = Math.min( this.z, v.z ); 7891 this.w = Math.min( this.w, v.w ); 7892 7893 return this; 7894 7895 }, 7896 7897 max: function ( v ) { 7898 7899 this.x = Math.max( this.x, v.x ); 7900 this.y = Math.max( this.y, v.y ); 7901 this.z = Math.max( this.z, v.z ); 7902 this.w = Math.max( this.w, v.w ); 7903 7904 return this; 7905 7906 }, 7907 7908 clamp: function ( min, max ) { 7909 7910 // assumes min < max, componentwise 7911 7912 this.x = Math.max( min.x, Math.min( max.x, this.x ) ); 7913 this.y = Math.max( min.y, Math.min( max.y, this.y ) ); 7914 this.z = Math.max( min.z, Math.min( max.z, this.z ) ); 7915 this.w = Math.max( min.w, Math.min( max.w, this.w ) ); 7916 7917 return this; 7918 7919 }, 7920 7921 clampScalar: function () { 7922 7923 var min, max; 7924 7925 return function clampScalar( minVal, maxVal ) { 7926 7927 if ( min === undefined ) { 7928 7929 min = new Vector4(); 7930 max = new Vector4(); 7931 7932 } 7933 7934 min.set( minVal, minVal, minVal, minVal ); 7935 max.set( maxVal, maxVal, maxVal, maxVal ); 7936 7937 return this.clamp( min, max ); 7938 7939 }; 7940 7941 }(), 7942 7943 clampLength: function ( min, max ) { 7944 7945 var length = this.length(); 7946 7947 return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); 7948 7949 }, 7950 7951 floor: function () { 7952 7953 this.x = Math.floor( this.x ); 7954 this.y = Math.floor( this.y ); 7955 this.z = Math.floor( this.z ); 7956 this.w = Math.floor( this.w ); 7957 7958 return this; 7959 7960 }, 7961 7962 ceil: function () { 7963 7964 this.x = Math.ceil( this.x ); 7965 this.y = Math.ceil( this.y ); 7966 this.z = Math.ceil( this.z ); 7967 this.w = Math.ceil( this.w ); 7968 7969 return this; 7970 7971 }, 7972 7973 round: function () { 7974 7975 this.x = Math.round( this.x ); 7976 this.y = Math.round( this.y ); 7977 this.z = Math.round( this.z ); 7978 this.w = Math.round( this.w ); 7979 7980 return this; 7981 7982 }, 7983 7984 roundToZero: function () { 7985 7986 this.x = ( this.x < 0 ) ? Math.ceil( this.x ) : Math.floor( this.x ); 7987 this.y = ( this.y < 0 ) ? Math.ceil( this.y ) : Math.floor( this.y ); 7988 this.z = ( this.z < 0 ) ? Math.ceil( this.z ) : Math.floor( this.z ); 7989 this.w = ( this.w < 0 ) ? Math.ceil( this.w ) : Math.floor( this.w ); 7990 7991 return this; 7992 7993 }, 7994 7995 negate: function () { 7996 7997 this.x = - this.x; 7998 this.y = - this.y; 7999 this.z = - this.z; 8000 this.w = - this.w; 8001 8002 return this; 8003 8004 }, 8005 8006 dot: function ( v ) { 8007 8008 return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w; 8009 8010 }, 8011 8012 lengthSq: function () { 8013 8014 return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w; 8015 8016 }, 8017 8018 length: function () { 8019 8020 return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w ); 8021 8022 }, 8023 8024 manhattanLength: function () { 8025 8026 return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); 8027 8028 }, 8029 8030 normalize: function () { 8031 8032 return this.divideScalar( this.length() || 1 ); 8033 8034 }, 8035 8036 setLength: function ( length ) { 8037 8038 return this.normalize().multiplyScalar( length ); 8039 8040 }, 8041 8042 lerp: function ( v, alpha ) { 8043 8044 this.x += ( v.x - this.x ) * alpha; 8045 this.y += ( v.y - this.y ) * alpha; 8046 this.z += ( v.z - this.z ) * alpha; 8047 this.w += ( v.w - this.w ) * alpha; 8048 8049 return this; 8050 8051 }, 8052 8053 lerpVectors: function ( v1, v2, alpha ) { 8054 8055 return this.subVectors( v2, v1 ).multiplyScalar( alpha ).add( v1 ); 8056 8057 }, 8058 8059 equals: function ( v ) { 8060 8061 return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); 8062 8063 }, 8064 8065 fromArray: function ( array, offset ) { 8066 8067 if ( offset === undefined ) offset = 0; 8068 8069 this.x = array[ offset ]; 8070 this.y = array[ offset + 1 ]; 8071 this.z = array[ offset + 2 ]; 8072 this.w = array[ offset + 3 ]; 8073 8074 return this; 8075 8076 }, 8077 8078 toArray: function ( array, offset ) { 8079 8080 if ( array === undefined ) array = []; 8081 if ( offset === undefined ) offset = 0; 8082 8083 array[ offset ] = this.x; 8084 array[ offset + 1 ] = this.y; 8085 array[ offset + 2 ] = this.z; 8086 array[ offset + 3 ] = this.w; 8087 8088 return array; 8089 8090 }, 8091 8092 fromBufferAttribute: function ( attribute, index, offset ) { 8093 8094 if ( offset !== undefined ) { 8095 8096 console.warn( 'THREE.Vector4: offset has been removed from .fromBufferAttribute().' ); 8097 8098 } 8099 8100 this.x = attribute.getX( index ); 8101 this.y = attribute.getY( index ); 8102 this.z = attribute.getZ( index ); 8103 this.w = attribute.getW( index ); 8104 8105 return this; 8106 8107 } 8108 8109 } ); 8110 8111 /** 8112 * @author szimek / https://github.com/szimek/ 8113 * @author alteredq / http://alteredqualia.com/ 8114 * @author Marius Kintel / https://github.com/kintel 8115 */ 8116 8117 /* 8118 In options, we can specify: 8119 * Texture parameters for an auto-generated target texture 8120 * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers 8121 */ 8122 function WebGLRenderTarget( width, height, options ) { 8123 8124 this.width = width; 8125 this.height = height; 8126 8127 this.scissor = new Vector4( 0, 0, width, height ); 8128 this.scissorTest = false; 8129 8130 this.viewport = new Vector4( 0, 0, width, height ); 8131 8132 options = options || {}; 8133 8134 if ( options.minFilter === undefined ) options.minFilter = LinearFilter; 8135 8136 this.texture = new Texture( undefined, undefined, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.encoding ); 8137 8138 this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : true; 8139 8140 this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true; 8141 this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true; 8142 this.depthTexture = options.depthTexture !== undefined ? options.depthTexture : null; 8143 8144 } 8145 8146 WebGLRenderTarget.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { 8147 8148 constructor: WebGLRenderTarget, 8149 8150 isWebGLRenderTarget: true, 8151 8152 setSize: function ( width, height ) { 8153 8154 if ( this.width !== width || this.height !== height ) { 8155 8156 this.width = width; 8157 this.height = height; 8158 8159 this.dispose(); 8160 8161 } 8162 8163 this.viewport.set( 0, 0, width, height ); 8164 this.scissor.set( 0, 0, width, height ); 8165 8166 }, 8167 8168 clone: function () { 8169 8170 return new this.constructor().copy( this ); 8171 8172 }, 8173 8174 copy: function ( source ) { 8175 8176 this.width = source.width; 8177 this.height = source.height; 8178 8179 this.viewport.copy( source.viewport ); 8180 8181 this.texture = source.texture.clone(); 8182 8183 this.depthBuffer = source.depthBuffer; 8184 this.stencilBuffer = source.stencilBuffer; 8185 this.depthTexture = source.depthTexture; 8186 8187 return this; 8188 8189 }, 8190 8191 dispose: function () { 8192 8193 this.dispatchEvent( { type: 'dispose' } ); 8194 8195 } 8196 8197 } ); 8198 8199 /** 8200 * @author alteredq / http://alteredqualia.com 8201 */ 8202 8203 function WebGLRenderTargetCube( width, height, options ) { 8204 8205 WebGLRenderTarget.call( this, width, height, options ); 8206 8207 this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5 8208 this.activeMipMapLevel = 0; 8209 8210 } 8211 8212 WebGLRenderTargetCube.prototype = Object.create( WebGLRenderTarget.prototype ); 8213 WebGLRenderTargetCube.prototype.constructor = WebGLRenderTargetCube; 8214 8215 WebGLRenderTargetCube.prototype.isWebGLRenderTargetCube = true; 8216 8217 /** 8218 * @author alteredq / http://alteredqualia.com/ 8219 */ 8220 8221 function DataTexture( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { 8222 8223 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); 8224 8225 this.image = { data: data, width: width, height: height }; 8226 8227 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; 8228 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; 8229 8230 this.generateMipmaps = false; 8231 this.flipY = false; 8232 this.unpackAlignment = 1; 8233 8234 } 8235 8236 DataTexture.prototype = Object.create( Texture.prototype ); 8237 DataTexture.prototype.constructor = DataTexture; 8238 8239 DataTexture.prototype.isDataTexture = true; 8240 8241 /** 8242 * @author bhouston / http://clara.io 8243 * @author WestLangley / http://github.com/WestLangley 8244 */ 8245 8246 function Box3( min, max ) { 8247 8248 this.min = ( min !== undefined ) ? min : new Vector3( + Infinity, + Infinity, + Infinity ); 8249 this.max = ( max !== undefined ) ? max : new Vector3( - Infinity, - Infinity, - Infinity ); 8250 8251 } 8252 8253 Object.assign( Box3.prototype, { 8254 8255 isBox3: true, 8256 8257 set: function ( min, max ) { 8258 8259 this.min.copy( min ); 8260 this.max.copy( max ); 8261 8262 return this; 8263 8264 }, 8265 8266 setFromArray: function ( array ) { 8267 8268 var minX = + Infinity; 8269 var minY = + Infinity; 8270 var minZ = + Infinity; 8271 8272 var maxX = - Infinity; 8273 var maxY = - Infinity; 8274 var maxZ = - Infinity; 8275 8276 for ( var i = 0, l = array.length; i < l; i += 3 ) { 8277 8278 var x = array[ i ]; 8279 var y = array[ i + 1 ]; 8280 var z = array[ i + 2 ]; 8281 8282 if ( x < minX ) minX = x; 8283 if ( y < minY ) minY = y; 8284 if ( z < minZ ) minZ = z; 8285 8286 if ( x > maxX ) maxX = x; 8287 if ( y > maxY ) maxY = y; 8288 if ( z > maxZ ) maxZ = z; 8289 8290 } 8291 8292 this.min.set( minX, minY, minZ ); 8293 this.max.set( maxX, maxY, maxZ ); 8294 8295 return this; 8296 8297 }, 8298 8299 setFromBufferAttribute: function ( attribute ) { 8300 8301 var minX = + Infinity; 8302 var minY = + Infinity; 8303 var minZ = + Infinity; 8304 8305 var maxX = - Infinity; 8306 var maxY = - Infinity; 8307 var maxZ = - Infinity; 8308 8309 for ( var i = 0, l = attribute.count; i < l; i ++ ) { 8310 8311 var x = attribute.getX( i ); 8312 var y = attribute.getY( i ); 8313 var z = attribute.getZ( i ); 8314 8315 if ( x < minX ) minX = x; 8316 if ( y < minY ) minY = y; 8317 if ( z < minZ ) minZ = z; 8318 8319 if ( x > maxX ) maxX = x; 8320 if ( y > maxY ) maxY = y; 8321 if ( z > maxZ ) maxZ = z; 8322 8323 } 8324 8325 this.min.set( minX, minY, minZ ); 8326 this.max.set( maxX, maxY, maxZ ); 8327 8328 return this; 8329 8330 }, 8331 8332 setFromPoints: function ( points ) { 8333 8334 this.makeEmpty(); 8335 8336 for ( var i = 0, il = points.length; i < il; i ++ ) { 8337 8338 this.expandByPoint( points[ i ] ); 8339 8340 } 8341 8342 return this; 8343 8344 }, 8345 8346 setFromCenterAndSize: function () { 8347 8348 var v1 = new Vector3(); 8349 8350 return function setFromCenterAndSize( center, size ) { 8351 8352 var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); 8353 8354 this.min.copy( center ).sub( halfSize ); 8355 this.max.copy( center ).add( halfSize ); 8356 8357 return this; 8358 8359 }; 8360 8361 }(), 8362 8363 setFromObject: function ( object ) { 8364 8365 this.makeEmpty(); 8366 8367 return this.expandByObject( object ); 8368 8369 }, 8370 8371 clone: function () { 8372 8373 return new this.constructor().copy( this ); 8374 8375 }, 8376 8377 copy: function ( box ) { 8378 8379 this.min.copy( box.min ); 8380 this.max.copy( box.max ); 8381 8382 return this; 8383 8384 }, 8385 8386 makeEmpty: function () { 8387 8388 this.min.x = this.min.y = this.min.z = + Infinity; 8389 this.max.x = this.max.y = this.max.z = - Infinity; 8390 8391 return this; 8392 8393 }, 8394 8395 isEmpty: function () { 8396 8397 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 8398 8399 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); 8400 8401 }, 8402 8403 getCenter: function ( target ) { 8404 8405 if ( target === undefined ) { 8406 8407 console.warn( 'THREE.Box3: .getCenter() target is now required' ); 8408 target = new Vector3(); 8409 8410 } 8411 8412 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 8413 8414 }, 8415 8416 getSize: function ( target ) { 8417 8418 if ( target === undefined ) { 8419 8420 console.warn( 'THREE.Box3: .getSize() target is now required' ); 8421 target = new Vector3(); 8422 8423 } 8424 8425 return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); 8426 8427 }, 8428 8429 expandByPoint: function ( point ) { 8430 8431 this.min.min( point ); 8432 this.max.max( point ); 8433 8434 return this; 8435 8436 }, 8437 8438 expandByVector: function ( vector ) { 8439 8440 this.min.sub( vector ); 8441 this.max.add( vector ); 8442 8443 return this; 8444 8445 }, 8446 8447 expandByScalar: function ( scalar ) { 8448 8449 this.min.addScalar( - scalar ); 8450 this.max.addScalar( scalar ); 8451 8452 return this; 8453 8454 }, 8455 8456 expandByObject: function () { 8457 8458 // Computes the world-axis-aligned bounding box of an object (including its children), 8459 // accounting for both the object's, and children's, world transforms 8460 8461 var scope, i, l; 8462 8463 var v1 = new Vector3(); 8464 8465 function traverse( node ) { 8466 8467 var geometry = node.geometry; 8468 8469 if ( geometry !== undefined ) { 8470 8471 if ( geometry.isGeometry ) { 8472 8473 var vertices = geometry.vertices; 8474 8475 for ( i = 0, l = vertices.length; i < l; i ++ ) { 8476 8477 v1.copy( vertices[ i ] ); 8478 v1.applyMatrix4( node.matrixWorld ); 8479 8480 scope.expandByPoint( v1 ); 8481 8482 } 8483 8484 } else if ( geometry.isBufferGeometry ) { 8485 8486 var attribute = geometry.attributes.position; 8487 8488 if ( attribute !== undefined ) { 8489 8490 for ( i = 0, l = attribute.count; i < l; i ++ ) { 8491 8492 v1.fromBufferAttribute( attribute, i ).applyMatrix4( node.matrixWorld ); 8493 8494 scope.expandByPoint( v1 ); 8495 8496 } 8497 8498 } 8499 8500 } 8501 8502 } 8503 8504 } 8505 8506 return function expandByObject( object ) { 8507 8508 scope = this; 8509 8510 object.updateMatrixWorld( true ); 8511 8512 object.traverse( traverse ); 8513 8514 return this; 8515 8516 }; 8517 8518 }(), 8519 8520 containsPoint: function ( point ) { 8521 8522 return point.x < this.min.x || point.x > this.max.x || 8523 point.y < this.min.y || point.y > this.max.y || 8524 point.z < this.min.z || point.z > this.max.z ? false : true; 8525 8526 }, 8527 8528 containsBox: function ( box ) { 8529 8530 return this.min.x <= box.min.x && box.max.x <= this.max.x && 8531 this.min.y <= box.min.y && box.max.y <= this.max.y && 8532 this.min.z <= box.min.z && box.max.z <= this.max.z; 8533 8534 }, 8535 8536 getParameter: function ( point, target ) { 8537 8538 // This can potentially have a divide by zero if the box 8539 // has a size dimension of 0. 8540 8541 if ( target === undefined ) { 8542 8543 console.warn( 'THREE.Box3: .getParameter() target is now required' ); 8544 target = new Vector3(); 8545 8546 } 8547 8548 return target.set( 8549 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 8550 ( point.y - this.min.y ) / ( this.max.y - this.min.y ), 8551 ( point.z - this.min.z ) / ( this.max.z - this.min.z ) 8552 ); 8553 8554 }, 8555 8556 intersectsBox: function ( box ) { 8557 8558 // using 6 splitting planes to rule out intersections. 8559 return box.max.x < this.min.x || box.min.x > this.max.x || 8560 box.max.y < this.min.y || box.min.y > this.max.y || 8561 box.max.z < this.min.z || box.min.z > this.max.z ? false : true; 8562 8563 }, 8564 8565 intersectsSphere: ( function () { 8566 8567 var closestPoint = new Vector3(); 8568 8569 return function intersectsSphere( sphere ) { 8570 8571 // Find the point on the AABB closest to the sphere center. 8572 this.clampPoint( sphere.center, closestPoint ); 8573 8574 // If that point is inside the sphere, the AABB and sphere intersect. 8575 return closestPoint.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); 8576 8577 }; 8578 8579 } )(), 8580 8581 intersectsPlane: function ( plane ) { 8582 8583 // We compute the minimum and maximum dot product values. If those values 8584 // are on the same side (back or front) of the plane, then there is no intersection. 8585 8586 var min, max; 8587 8588 if ( plane.normal.x > 0 ) { 8589 8590 min = plane.normal.x * this.min.x; 8591 max = plane.normal.x * this.max.x; 8592 8593 } else { 8594 8595 min = plane.normal.x * this.max.x; 8596 max = plane.normal.x * this.min.x; 8597 8598 } 8599 8600 if ( plane.normal.y > 0 ) { 8601 8602 min += plane.normal.y * this.min.y; 8603 max += plane.normal.y * this.max.y; 8604 8605 } else { 8606 8607 min += plane.normal.y * this.max.y; 8608 max += plane.normal.y * this.min.y; 8609 8610 } 8611 8612 if ( plane.normal.z > 0 ) { 8613 8614 min += plane.normal.z * this.min.z; 8615 max += plane.normal.z * this.max.z; 8616 8617 } else { 8618 8619 min += plane.normal.z * this.max.z; 8620 max += plane.normal.z * this.min.z; 8621 8622 } 8623 8624 return ( min <= plane.constant && max >= plane.constant ); 8625 8626 }, 8627 8628 intersectsTriangle: ( function () { 8629 8630 // triangle centered vertices 8631 var v0 = new Vector3(); 8632 var v1 = new Vector3(); 8633 var v2 = new Vector3(); 8634 8635 // triangle edge vectors 8636 var f0 = new Vector3(); 8637 var f1 = new Vector3(); 8638 var f2 = new Vector3(); 8639 8640 var testAxis = new Vector3(); 8641 8642 var center = new Vector3(); 8643 var extents = new Vector3(); 8644 8645 var triangleNormal = new Vector3(); 8646 8647 function satForAxes( axes ) { 8648 8649 var i, j; 8650 8651 for ( i = 0, j = axes.length - 3; i <= j; i += 3 ) { 8652 8653 testAxis.fromArray( axes, i ); 8654 // project the aabb onto the seperating axis 8655 var r = extents.x * Math.abs( testAxis.x ) + extents.y * Math.abs( testAxis.y ) + extents.z * Math.abs( testAxis.z ); 8656 // project all 3 vertices of the triangle onto the seperating axis 8657 var p0 = v0.dot( testAxis ); 8658 var p1 = v1.dot( testAxis ); 8659 var p2 = v2.dot( testAxis ); 8660 // actual test, basically see if either of the most extreme of the triangle points intersects r 8661 if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { 8662 8663 // points of the projected triangle are outside the projected half-length of the aabb 8664 // the axis is seperating and we can exit 8665 return false; 8666 8667 } 8668 8669 } 8670 8671 return true; 8672 8673 } 8674 8675 return function intersectsTriangle( triangle ) { 8676 8677 if ( this.isEmpty() ) { 8678 8679 return false; 8680 8681 } 8682 8683 // compute box center and extents 8684 this.getCenter( center ); 8685 extents.subVectors( this.max, center ); 8686 8687 // translate triangle to aabb origin 8688 v0.subVectors( triangle.a, center ); 8689 v1.subVectors( triangle.b, center ); 8690 v2.subVectors( triangle.c, center ); 8691 8692 // compute edge vectors for triangle 8693 f0.subVectors( v1, v0 ); 8694 f1.subVectors( v2, v1 ); 8695 f2.subVectors( v0, v2 ); 8696 8697 // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb 8698 // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation 8699 // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) 8700 var axes = [ 8701 0, - f0.z, f0.y, 0, - f1.z, f1.y, 0, - f2.z, f2.y, 8702 f0.z, 0, - f0.x, f1.z, 0, - f1.x, f2.z, 0, - f2.x, 8703 - f0.y, f0.x, 0, - f1.y, f1.x, 0, - f2.y, f2.x, 0 8704 ]; 8705 if ( ! satForAxes( axes ) ) { 8706 8707 return false;
8708 8709 } 8710 8711 // test 3 face normals from the aabb 8712 axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; 8713 if ( ! satForAxes( axes ) ) { 8714 8715 return false; 8716 8717 } 8718 8719 // finally testing the face normal of the triangle 8720 // use already existing triangle edge vectors here 8721 triangleNormal.crossVectors( f0, f1 ); 8722 axes = [ triangleNormal.x, triangleNormal.y, triangleNormal.z ]; 8723 return satForAxes( axes ); 8724 8725 }; 8726 8727 } )(), 8728 8729 clampPoint: function ( point, target ) { 8730 8731 if ( target === undefined ) { 8732 8733 console.warn( 'THREE.Box3: .clampPoint() target is now required' ); 8734 target = new Vector3(); 8735 8736 } 8737 8738 return target.copy( point ).clamp( this.min, this.max ); 8739 8740 }, 8741 8742 distanceToPoint: function () { 8743 8744 var v1 = new Vector3(); 8745 8746 return function distanceToPoint( point ) { 8747 8748 var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); 8749 return clampedPoint.sub( point ).length(); 8750 8751 }; 8752 8753 }(), 8754 8755 getBoundingSphere: function () { 8756 8757 var v1 = new Vector3(); 8758 8759 return function getBoundingSphere( target ) { 8760 8761 if ( target === undefined ) { 8762 8763 console.warn( 'THREE.Box3: .getBoundingSphere() target is now required' ); 8764 target = new Sphere(); 8765 8766 } 8767 8768 this.getCenter( target.center ); 8769 8770 target.radius = this.getSize( v1 ).length() * 0.5; 8771 8772 return target; 8773 8774 }; 8775 8776 }(), 8777 8778 intersect: function ( box ) { 8779 8780 this.min.max( box.min ); 8781 this.max.min( box.max ); 8782 8783 // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. 8784 if ( this.isEmpty() ) this.makeEmpty(); 8785 8786 return this; 8787 8788 }, 8789 8790 union: function ( box ) { 8791 8792 this.min.min( box.min ); 8793 this.max.max( box.max ); 8794 8795 return this; 8796 8797 }, 8798 8799 applyMatrix4: function ( matrix ) { 8800 8801 // transform of empty box is an empty box. 8802 if ( this.isEmpty( ) ) return this; 8803 8804 var m = matrix.elements; 8805 8806 var xax = m[ 0 ] * this.min.x, xay = m[ 1 ] * this.min.x, xaz = m[ 2 ] * this.min.x; 8807 var xbx = m[ 0 ] * this.max.x, xby = m[ 1 ] * this.max.x, xbz = m[ 2 ] * this.max.x; 8808 var yax = m[ 4 ] * this.min.y, yay = m[ 5 ] * this.min.y, yaz = m[ 6 ] * this.min.y; 8809 var ybx = m[ 4 ] * this.max.y, yby = m[ 5 ] * this.max.y, ybz = m[ 6 ] * this.max.y; 8810 var zax = m[ 8 ] * this.min.z, zay = m[ 9 ] * this.min.z, zaz = m[ 10 ] * this.min.z; 8811 var zbx = m[ 8 ] * this.max.z, zby = m[ 9 ] * this.max.z, zbz = m[ 10 ] * this.max.z; 8812 8813 this.min.x = Math.min( xax, xbx ) + Math.min( yax, ybx ) + Math.min( zax, zbx ) + m[ 12 ]; 8814 this.min.y = Math.min( xay, xby ) + Math.min( yay, yby ) + Math.min( zay, zby ) + m[ 13 ]; 8815 this.min.z = Math.min( xaz, xbz ) + Math.min( yaz, ybz ) + Math.min( zaz, zbz ) + m[ 14 ]; 8816 this.max.x = Math.max( xax, xbx ) + Math.max( yax, ybx ) + Math.max( zax, zbx ) + m[ 12 ]; 8817 this.max.y = Math.max( xay, xby ) + Math.max( yay, yby ) + Math.max( zay, zby ) + m[ 13 ]; 8818 this.max.z = Math.max( xaz, xbz ) + Math.max( yaz, ybz ) + Math.max( zaz, zbz ) + m[ 14 ]; 8819 8820 return this; 8821 8822 }, 8823 8824 translate: function ( offset ) { 8825 8826 this.min.add( offset ); 8827 this.max.add( offset ); 8828 8829 return this; 8830 8831 }, 8832 8833 equals: function ( box ) { 8834 8835 return box.min.equals( this.min ) && box.max.equals( this.max ); 8836 8837 } 8838 8839 } ); 8840 8841 /** 8842 * @author bhouston / http://clara.io 8843 * @author mrdoob / http://mrdoob.com/ 8844 */ 8845 8846 function Sphere( center, radius ) { 8847 8848 this.center = ( center !== undefined ) ? center : new Vector3(); 8849 this.radius = ( radius !== undefined ) ? radius : 0; 8850 8851 } 8852 8853 Object.assign( Sphere.prototype, { 8854
vendor: 7,519 bytes, lines 8855-9247
8855 set: function ( center, radius ) { 8856 8857 this.center.copy( center ); 8858 this.radius = radius; 8859 8860 return this; 8861 8862 }, 8863 8864 setFromPoints: function () { 8865 8866 var box = new Box3(); 8867 8868 return function setFromPoints( points, optionalCenter ) { 8869 8870 var center = this.center; 8871 8872 if ( optionalCenter !== undefined ) { 8873 8874 center.copy( optionalCenter ); 8875 8876 } else { 8877 8878 box.setFromPoints( points ).getCenter( center ); 8879 8880 } 8881 8882 var maxRadiusSq = 0; 8883 8884 for ( var i = 0, il = points.length; i < il; i ++ ) { 8885 8886 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); 8887 8888 } 8889 8890 this.radius = Math.sqrt( maxRadiusSq ); 8891 8892 return this; 8893 8894 }; 8895 8896 }(), 8897 8898 clone: function () { 8899 8900 return new this.constructor().copy( this ); 8901 8902 }, 8903 8904 copy: function ( sphere ) { 8905 8906 this.center.copy( sphere.center ); 8907 this.radius = sphere.radius; 8908 8909 return this; 8910 8911 }, 8912 8913 empty: function () { 8914 8915 return ( this.radius <= 0 ); 8916 8917 }, 8918 8919 containsPoint: function ( point ) { 8920 8921 return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); 8922 8923 }, 8924 8925 distanceToPoint: function ( point ) { 8926 8927 return ( point.distanceTo( this.center ) - this.radius ); 8928 8929 }, 8930 8931 intersectsSphere: function ( sphere ) { 8932 8933 var radiusSum = this.radius + sphere.radius; 8934 8935 return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); 8936 8937 }, 8938 8939 intersectsBox: function ( box ) { 8940 8941 return box.intersectsSphere( this ); 8942 8943 }, 8944 8945 intersectsPlane: function ( plane ) { 8946 8947 return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; 8948 8949 }, 8950 8951 clampPoint: function ( point, target ) { 8952 8953 var deltaLengthSq = this.center.distanceToSquared( point ); 8954 8955 if ( target === undefined ) { 8956 8957 console.warn( 'THREE.Sphere: .clampPoint() target is now required' ); 8958 target = new Vector3(); 8959 8960 } 8961 8962 target.copy( point ); 8963 8964 if ( deltaLengthSq > ( this.radius * this.radius ) ) { 8965 8966 target.sub( this.center ).normalize(); 8967 target.multiplyScalar( this.radius ).add( this.center ); 8968 8969 } 8970 8971 return target; 8972 8973 }, 8974 8975 getBoundingBox: function ( target ) { 8976 8977 if ( target === undefined ) { 8978 8979 console.warn( 'THREE.Sphere: .getBoundingBox() target is now required' ); 8980 target = new Box3(); 8981 8982 } 8983 8984 target.set( this.center, this.center ); 8985 target.expandByScalar( this.radius ); 8986 8987 return target; 8988 8989 }, 8990 8991 applyMatrix4: function ( matrix ) { 8992 8993 this.center.applyMatrix4( matrix ); 8994 this.radius = this.radius * matrix.getMaxScaleOnAxis(); 8995 8996 return this; 8997 8998 }, 8999 9000 translate: function ( offset ) { 9001 9002 this.center.add( offset ); 9003 9004 return this; 9005 9006 }, 9007 9008 equals: function ( sphere ) { 9009 9010 return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); 9011 9012 } 9013 9014 } ); 9015 9016 /** 9017 * @author bhouston / http://clara.io 9018 */ 9019 9020 function Plane( normal, constant ) { 9021 9022 // normal is assumed to be normalized 9023 9024 this.normal = ( normal !== undefined ) ? normal : new Vector3( 1, 0, 0 ); 9025 this.constant = ( constant !== undefined ) ? constant : 0; 9026 9027 } 9028 9029 Object.assign( Plane.prototype, { 9030 9031 set: function ( normal, constant ) { 9032 9033 this.normal.copy( normal ); 9034 this.constant = constant; 9035 9036 return this; 9037 9038 }, 9039 9040 setComponents: function ( x, y, z, w ) { 9041 9042 this.normal.set( x, y, z ); 9043 this.constant = w; 9044 9045 return this; 9046 9047 }, 9048 9049 setFromNormalAndCoplanarPoint: function ( normal, point ) { 9050 9051 this.normal.copy( normal ); 9052 this.constant = - point.dot( this.normal ); 9053 9054 return this; 9055 9056 }, 9057 9058 setFromCoplanarPoints: function () { 9059 9060 var v1 = new Vector3(); 9061 var v2 = new Vector3(); 9062 9063 return function setFromCoplanarPoints( a, b, c ) { 9064 9065 var normal = v1.subVectors( c, b ).cross( v2.subVectors( a, b ) ).normalize(); 9066 9067 // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? 9068 9069 this.setFromNormalAndCoplanarPoint( normal, a ); 9070 9071 return this; 9072 9073 }; 9074 9075 }(), 9076 9077 clone: function () { 9078 9079 return new this.constructor().copy( this ); 9080 9081 }, 9082 9083 copy: function ( plane ) { 9084 9085 this.normal.copy( plane.normal ); 9086 this.constant = plane.constant; 9087 9088 return this; 9089 9090 }, 9091 9092 normalize: function () { 9093 9094 // Note: will lead to a divide by zero if the plane is invalid. 9095 9096 var inverseNormalLength = 1.0 / this.normal.length(); 9097 this.normal.multiplyScalar( inverseNormalLength ); 9098 this.constant *= inverseNormalLength; 9099 9100 return this; 9101 9102 }, 9103 9104 negate: function () { 9105 9106 this.constant *= - 1; 9107 this.normal.negate(); 9108 9109 return this; 9110 9111 }, 9112 9113 distanceToPoint: function ( point ) { 9114 9115 return this.normal.dot( point ) + this.constant; 9116 9117 }, 9118 9119 distanceToSphere: function ( sphere ) { 9120 9121 return this.distanceToPoint( sphere.center ) - sphere.radius; 9122 9123 }, 9124 9125 projectPoint: function ( point, target ) { 9126 9127 if ( target === undefined ) { 9128 9129 console.warn( 'THREE.Plane: .projectPoint() target is now required' ); 9130 target = new Vector3(); 9131 9132 } 9133 9134 return target.copy( this.normal ).multiplyScalar( - this.distanceToPoint( point ) ).add( point ); 9135 9136 }, 9137 9138 intersectLine: function () { 9139 9140 var v1 = new Vector3(); 9141 9142 return function intersectLine( line, target ) { 9143 9144 if ( target === undefined ) { 9145 9146 console.warn( 'THREE.Plane: .intersectLine() target is now required' ); 9147 target = new Vector3(); 9148 9149 } 9150 9151 var direction = line.delta( v1 ); 9152 9153 var denominator = this.normal.dot( direction ); 9154 9155 if ( denominator === 0 ) { 9156 9157 // line is coplanar, return origin 9158 if ( this.distanceToPoint( line.start ) === 0 ) { 9159 9160 return target.copy( line.start ); 9161 9162 } 9163 9164 // Unsure if this is the correct method to handle this case. 9165 return undefined; 9166 9167 } 9168 9169 var t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; 9170 9171 if ( t < 0 || t > 1 ) { 9172 9173 return undefined; 9174 9175 } 9176 9177 return target.copy( direction ).multiplyScalar( t ).add( line.start ); 9178 9179 }; 9180 9181 }(), 9182 9183 intersectsLine: function ( line ) { 9184 9185 // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. 9186 9187 var startSign = this.distanceToPoint( line.start ); 9188 var endSign = this.distanceToPoint( line.end ); 9189 9190 return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); 9191 9192 }, 9193 9194 intersectsBox: function ( box ) { 9195 9196 return box.intersectsPlane( this ); 9197 9198 }, 9199 9200 intersectsSphere: function ( sphere ) { 9201 9202 return sphere.intersectsPlane( this ); 9203 9204 }, 9205 9206 coplanarPoint: function ( target ) { 9207 9208 if ( target === undefined ) { 9209 9210 console.warn( 'THREE.Plane: .coplanarPoint() target is now required' ); 9211 target = new Vector3(); 9212 9213 } 9214 9215 return target.copy( this.normal ).multiplyScalar( - this.constant ); 9216 9217 }, 9218 9219 applyMatrix4: function () { 9220 9221 var v1 = new Vector3(); 9222 var m1 = new Matrix3(); 9223 9224 return function applyMatrix4( matrix, optionalNormalMatrix ) { 9225 9226 var normalMatrix = optionalNormalMatrix || m1.getNormalMatrix( matrix ); 9227 9228 var referencePoint = this.coplanarPoint( v1 ).applyMatrix4( matrix ); 9229 9230 var normal = this.normal.applyMatrix3( normalMatrix ).normalize(); 9231 9232 this.constant = - referencePoint.dot( normal ); 9233 9234 return this; 9235 9236 }; 9237 9238 }(), 9239 9240 translate: function ( offset ) { 9241 9242 this.constant -= offset.dot( this.normal ); 9243 9244 return this; 9245 9246 }, 9247
vendor: 4,243 bytes, lines 9248-9439
9248 equals: function ( plane ) { 9249 9250 return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); 9251 9252 } 9253 9254 } ); 9255 9256 /** 9257 * @author mrdoob / http://mrdoob.com/ 9258 * @author alteredq / http://alteredqualia.com/ 9259 * @author bhouston / http://clara.io 9260 */ 9261 9262 function Frustum( p0, p1, p2, p3, p4, p5 ) { 9263 9264 this.planes = [ 9265 9266 ( p0 !== undefined ) ? p0 : new Plane(), 9267 ( p1 !== undefined ) ? p1 : new Plane(), 9268 ( p2 !== undefined ) ? p2 : new Plane(), 9269 ( p3 !== undefined ) ? p3 : new Plane(), 9270 ( p4 !== undefined ) ? p4 : new Plane(), 9271 ( p5 !== undefined ) ? p5 : new Plane() 9272 9273 ]; 9274 9275 } 9276 9277 Object.assign( Frustum.prototype, { 9278 9279 set: function ( p0, p1, p2, p3, p4, p5 ) { 9280 9281 var planes = this.planes; 9282 9283 planes[ 0 ].copy( p0 ); 9284 planes[ 1 ].copy( p1 ); 9285 planes[ 2 ].copy( p2 ); 9286 planes[ 3 ].copy( p3 ); 9287 planes[ 4 ].copy( p4 ); 9288 planes[ 5 ].copy( p5 ); 9289 9290 return this; 9291 9292 }, 9293 9294 clone: function () { 9295 9296 return new this.constructor().copy( this ); 9297 9298 }, 9299 9300 copy: function ( frustum ) { 9301 9302 var planes = this.planes; 9303 9304 for ( var i = 0; i < 6; i ++ ) { 9305 9306 planes[ i ].copy( frustum.planes[ i ] ); 9307 9308 } 9309 9310 return this; 9311 9312 }, 9313 9314 setFromMatrix: function ( m ) { 9315 9316 var planes = this.planes; 9317 var me = m.elements; 9318 var me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; 9319 var me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; 9320 var me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; 9321 var me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ]; 9322 9323 planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize(); 9324 planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize(); 9325 planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize(); 9326 planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize(); 9327 planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); 9328 planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); 9329 9330 return this; 9331 9332 }, 9333 9334 intersectsObject: function () { 9335 9336 var sphere = new Sphere(); 9337 9338 return function intersectsObject( object ) { 9339 9340 var geometry = object.geometry; 9341 9342 if ( geometry.boundingSphere === null ) 9343 geometry.computeBoundingSphere(); 9344 9345 sphere.copy( geometry.boundingSphere ) 9346 .applyMatrix4( object.matrixWorld ); 9347 9348 return this.intersectsSphere( sphere ); 9349 9350 }; 9351 9352 }(), 9353 9354 intersectsSprite: function () { 9355 9356 var sphere = new Sphere(); 9357 9358 return function intersectsSprite( sprite ) { 9359 9360 sphere.center.set( 0, 0, 0 ); 9361 sphere.radius = 0.7071067811865476; 9362 sphere.applyMatrix4( sprite.matrixWorld ); 9363 9364 return this.intersectsSphere( sphere ); 9365 9366 }; 9367 9368 }(), 9369 9370 intersectsSphere: function ( sphere ) { 9371 9372 var planes = this.planes; 9373 var center = sphere.center; 9374 var negRadius = - sphere.radius; 9375 9376 for ( var i = 0; i < 6; i ++ ) { 9377 9378 var distance = planes[ i ].distanceToPoint( center ); 9379 9380 if ( distance < negRadius ) { 9381 9382 return false; 9383 9384 } 9385 9386 } 9387 9388 return true; 9389 9390 }, 9391 9392 intersectsBox: function () { 9393 9394 var p1 = new Vector3(), 9395 p2 = new Vector3(); 9396 9397 return function intersectsBox( box ) { 9398 9399 var planes = this.planes; 9400 9401 for ( var i = 0; i < 6; i ++ ) { 9402 9403 var plane = planes[ i ]; 9404 9405 p1.x = plane.normal.x > 0 ? box.min.x : box.max.x; 9406 p2.x = plane.normal.x > 0 ? box.max.x : box.min.x; 9407 p1.y = plane.normal.y > 0 ? box.min.y : box.max.y; 9408 p2.y = plane.normal.y > 0 ? box.max.y : box.min.y; 9409 p1.z = plane.normal.z > 0 ? box.min.z : box.max.z; 9410 p2.z = plane.normal.z > 0 ? box.max.z : box.min.z; 9411 9412 var d1 = plane.distanceToPoint( p1 ); 9413 var d2 = plane.distanceToPoint( p2 ); 9414 9415 // if both outside plane, no intersection 9416 9417 if ( d1 < 0 && d2 < 0 ) { 9418 9419 return false; 9420 9421 } 9422 9423 } 9424 9425 return true; 9426 9427 }; 9428 9429 }(), 9430 9431 containsPoint: function ( point ) { 9432 9433 var planes = this.planes; 9434 9435 for ( var i = 0; i < 6; i ++ ) { 9436 9437 if ( planes[ i ].distanceToPoint( point ) < 0 ) { 9438 9439 return false;
9440 9441 } 9442 9443 } 9444 9445 return true; 9446 9447 } 9448 9449 } ); 9450 9451 var alphamap_fragment = "#ifdef USE_ALPHAMAP\n\tdiffuseColor.a *= texture2D( alphaMap, vUv ).g;\n#endif\n"; 9452 9453 var alphamap_pars_fragment = "#ifdef USE_ALPHAMAP\n\tuniform sampler2D alphaMap;\n#endif\n"; 9454 9455 var alphatest_fragment = "#ifdef ALPHATEST\n\tif ( diffuseColor.a < ALPHATEST ) discard;\n#endif\n"; 9456 9457 var aomap_fragment = "#ifdef USE_AOMAP\n\tfloat ambientOcclusion = ( texture2D( aoMap, vUv2 ).r - 1.0 ) * aoMapIntensity + 1.0;\n\treflectedLight.indirectDiffuse *= ambientOcclusion;\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\treflectedLight.indirectSpecular *= computeSpecularOcclusion( dotNV, ambientOcclusion, material.specularRoughness );\n\t#endif\n#endif\n"; 9458 9459 var aomap_pars_fragment = "#ifdef USE_AOMAP\n\tuniform sampler2D aoMap;\n\tuniform float aoMapIntensity;\n#endif"; 9460 9461 var begin_vertex = "\nvec3 transformed = vec3( position );\n"; 9462 9463 var beginnormal_vertex = "\nvec3 objectNormal = vec3( normal );\n"; 9464 9465 var bsdfs = "float punctualLightIntensityToIrradianceFactor( const in float lightDistance, const in float cutoffDistance, const in float decayExponent ) {\n\tif( decayExponent > 0.0 ) {\n#if defined ( PHYSICALLY_CORRECT_LIGHTS )\n\t\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\t\tfloat maxDistanceCutoffFactor = pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t\treturn distanceFalloff * maxDistanceCutoffFactor;
9465\n#else\n\t\treturn pow( saturate( -lightDistance / cutoffDistance + 1.0 ), decayExponent );\n#endif\n\t}\n\treturn 1.0;\n}\nvec3 BRDF_Diffuse_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 specularColor, const in float dotLH ) {\n\tfloat fresnel = exp2( ( -5.55473 * dotLH - 6.98316 ) * dotLH );\n\treturn ( 1.0 - specularColor ) * fresnel + specularColor;\n}\nfloat G_GGX_Smith( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gl = dotNL + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\tfloat gv = dotNV + sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\treturn 1.0 / ( gl * gv );\n}\nfloat G_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\nvec3 BRDF_Specular_GGX( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat alpha = pow2( roughness );\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNL = saturate( dot( geometry.normal, incidentLight.direction ) );\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );
9465\n\tfloat G = G_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\tfloat D = D_GGX( alpha, dotNH );\n\treturn F * ( G * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 0.0 ) ? v : 0.5 * inversesqrt( max( 1.0 - x * x, 1e-7 ) ) - v;\n\treturn cross( v1, v2 ) * theta_sintheta;\n}\nvec3 LTC_Evaluate( const in vec3 N, const in vec3 V, const in vec3 P, const in mat3 mInv, const in vec3 rectCoords[ 4 ] ) {\n\tvec3 v1 = rectCoords[ 1 ] - rectCoords[ 0 ];\n\tvec3 v2 = rectCoords[ 3 ] - rectCoords[ 0 ];\n\tvec3 lightNormal = cross( v1, v2 );\n\tif( dot( lightNormal, P - rectCoords[ 0 ] ) < 0.0 ) return vec3( 0.0 );\n\tvec3 T1, T2;\n\tT1 = normalize( V - N * dot( V, N ) );\n\tT2 = - cross( N, T1 );\n\tmat3 mat = mInv * transposeMat3( mat3( T1, T2, N ) );\n\tvec3 coords[ 4 ];\n\tcoords[ 0 ] = mat * ( rectCoords[ 0 ] - P );\n\tcoords[ 1 ] = mat * ( rectCoords[ 1 ] - P );\n\tcoords[ 2 ] = mat * ( rectCoords[ 2 ] - P );\n\tcoords[ 3 ] = mat * ( rectCoords[ 3 ] - P );\n\tcoords[ 0 ] = normalize( coords[ 0 ] );\n\tcoords[ 1 ] = normalize( coords[ 1 ] );\n\tcoords[ 2 ] = normalize( coords[ 2 ] );\n\tcoords[ 3 ] = normalize( coords[ 3 ] );\n\tvec3 vectorFormFactor = vec3( 0.0 );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 0 ], coords[ 1 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 1 ], coords[ 2 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 2 ], coords[ 3 ] );\n\tvectorFormFactor += LTC_EdgeVectorFormFactor( coords[ 3 ], coords[ 0 ] );\n\tfloat result = LTC_ClippedSphereFormFactor( vectorFormFactor );\n\treturn vec3( result );\n}\nvec3 BRDF_Specular_GGX_Environment( const in GeometricContext geometry, const in vec3 specularColor, const in float roughness ) {\n\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\tconst vec4 c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 );\n\tconst vec4 c1 = vec4( 1, 0.0425, 1.04, - 0.04 );\n\tvec4 r = roughness * c0 + c1;\n\tfloat a004 = min( r.x * r.x, exp2( - 9.28 * dotNV ) ) * r.x + r.y;\n\tvec2 AB = vec2( -1.04, 1.04 ) * a004 + r.zw;\n\treturn specularColor * AB.x + AB.y;\n}\nfloat G_BlinnPhong_Implicit( ) {\n\treturn 0.25;\n}\nfloat D_BlinnPhong( const in float shininess, const in float dotNH ) {\n\treturn RECIPROCAL_PI * ( shininess * 0.5 + 1.0 ) * pow( dotNH, shininess );\n}\nvec3 BRDF_Specular_BlinnPhong( const in IncidentLight incidentLight, const in GeometricContext geometry, const in vec3 specularColor, const in float shininess ) {\n\tvec3 halfDir = normalize( incidentLight.direction + geometry.viewDir );\n\tfloat dotNH = saturate( dot( geometry.normal, halfDir ) );\n\tfloat dotLH = saturate( dot( incidentLight.direction, halfDir ) );\n\tvec3 F = F_Schlick( specularColor, dotLH );\n\tfloat G = G_BlinnPhong_Implicit( );\n\tfloat D = D_BlinnPhong( shininess, dotNH );\n\treturn F * ( G * D );\n}\nfloat GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\treturn ( 2.0 / pow2( ggxRoughness + 0.0001 ) - 2.0 );\n}\nfloat BlinnExponentToGGXRoughness( const in float blinnExponent ) {\n\treturn sqrt( 2.0 / ( blinnExponent + 2.0 ) );\n}\n"; 9466 9467 var bumpmap_pars_fragment = "#ifdef USE_BUMPMAP\n\tuniform sampler2D bumpMap;\n\tuniform float bumpScale;\n\tvec2 dHdxy_fwd() {\n\t\tvec2 dSTdx = dFdx( vUv );\n\t\tvec2 dSTdy = dFdy( vUv );\n\t\tfloat Hll = bumpScale * texture2D( bumpMap, vUv ).x;\n\t\tfloat dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;\n\t\tfloat dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;\n\t\treturn vec2( dBx, dBy );\n\t}
9467\n\tvec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {\n\t\tvec3 vSigmaX = vec3( dFdx( surf_pos.x ), dFdx( surf_pos.y ), dFdx( surf_pos.z ) );\n\t\tvec3 vSigmaY = vec3( dFdy( surf_pos.x ), dFdy( surf_pos.y ), dFdy( surf_pos.z ) );\n\t\tvec3 vN = surf_norm;\n\t\tvec3 R1 = cross( vSigmaY, vN );\n\t\tvec3 R2 = cross( vN, vSigmaX );\n\t\tfloat fDet = dot( vSigmaX, R1 );\n\t\tfDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\tvec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );\n\t\treturn normalize( abs( fDet ) * surf_norm - vGrad );\n\t}\n#endif\n"; 9468 9469 var clipping_planes_fragment = "#if NUM_CLIPPING_PLANES > 0\n\tvec4 plane;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\tplane = clippingPlanes[ i ];\n\t\tif ( dot( vViewPosition, plane.xyz ) > plane.w ) discard;\n\t}\n\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\tbool clipped = true;\n\t\t#pragma unroll_loop\n\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tclipped = ( dot( vViewPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t}\n\t\tif ( clipped ) discard;\n\t#endif\n#endif\n"; 9470 9471 var clipping_planes_pars_fragment = "#if NUM_CLIPPING_PLANES > 0\n\t#if ! defined( PHYSICAL ) && ! defined( PHONG )\n\t\tvarying vec3 vViewPosition;\n\t#endif\n\tuniform vec4 clippingPlanes[ NUM_CLIPPING_PLANES ];\n#endif\n"; 9472 9473 var clipping_planes_pars_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvarying vec3 vViewPosition;\n#endif\n"; 9474 9475 var clipping_planes_vertex = "#if NUM_CLIPPING_PLANES > 0 && ! defined( PHYSICAL ) && ! defined( PHONG )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n"; 9476 9477 var color_fragment = "#ifdef USE_COLOR\n\tdiffuseColor.rgb *= vColor;\n#endif"; 9478 9479 var color_pars_fragment = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif\n"; 9480 9481 var color_pars_vertex = "#ifdef USE_COLOR\n\tvarying vec3 vColor;\n#endif"; 9482 9483 var color_vertex = "#ifdef USE_COLOR\n\tvColor.xyz = color.xyz;\n#endif"; 9484 9485 var common = "#define PI 3.14159265359\n#define PI2 6.28318530718\n#define PI_HALF 1.5707963267949\n#define RECIPROCAL_PI 0.31830988618\n#define RECIPROCAL_PI2 0.15915494\n#define LOG2 1.442695\n#define EPSILON 1e-6\n#define saturate(a) clamp( a, 0.0, 1.0 )\n#define whiteCompliment(a) ( 1.0 - saturate( a ) )\nfloat pow2( const in float x ) { return x*x; }\nfloat pow3( const in float x ) { return x*x*x; }\nfloat pow4( const in float x ) { float x2 = x*x; return x2*x2; }\nfloat average( const in vec3 color ) { return dot( color, vec3( 0.3333 ) ); }\nhighp float rand( const in vec2 uv ) {\n\tconst highp float a = 12.9898, b = 78.233, c = 43758.5453;\n\thighp float dt = dot( uv.xy, vec2( a,b ) ), sn = mod( dt, PI );\n\treturn fract(sin(sn) * c);\n}\nstruct IncidentLight {\n\tvec3 color;\n\tvec3 direction;\n\tbool visible;\n};\nstruct ReflectedLight {\n\tvec3 directDiffuse;\n\tvec3 directSpecular;\n\tvec3 indirectDiffuse;\n\tvec3 indirectSpecular;\n};\nstruct GeometricContext {\n\tvec3 position;\n\tvec3 normal;\n\tvec3 viewDir;\n};\nvec3 transformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( matrix * vec4( dir, 0.0 ) ).xyz );\n}\nvec3 inverseTransformDirection( in vec3 dir, in mat4 matrix ) {\n\treturn normalize( ( vec4( dir, 0.0 ) * matrix ).xyz );\n}\nvec3 projectOnPlane(in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\tfloat distance = dot( planeNormal, point - pointOnPlane );\n\treturn - distance * planeNormal + point;\n}\nfloat sideOfPlane( in vec3 point, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn sign( dot( point - pointOnPlane, planeNormal ) );\n}\nvec3 linePlaneIntersect( in vec3 pointOnLine, in vec3 lineDirection, in vec3 pointOnPlane, in vec3 planeNormal ) {\n\treturn lineDirection * ( dot( planeNormal, pointOnPlane - pointOnLine ) / dot( planeNormal, lineDirection ) ) + pointOnLine;\n}\nmat3 transposeMat3( const in mat3 m ) {\n\tmat3 tmp;\n\ttmp[ 0 ] = vec3( m[ 0 ].x, m[ 1 ].x, m[ 2 ].x );\n\ttmp[ 1 ] = vec3( m[ 0 ].y, m[ 1 ].y, m[ 2 ].y );\n\ttmp[ 2 ] = vec3( m[ 0 ].z, m[ 1 ].z, m[ 2 ].z );\n\treturn tmp;\n}\nfloat linearToRelativeLuminance( const in vec3 color ) {\n\tvec3 weights = vec3( 0.2126, 0.7152, 0.0722 );\n\treturn dot( weights, color.rgb );\n}\n"; 9486 9487 var cube_uv_reflection_fragment = "#ifdef ENVMAP_TYPE_CUBE_UV\n#define cubeUV_textureSize (1024.0)\nint getFaceFromDirection(vec3 direction) {\n\tvec3 absDirection = abs(direction);\n\tint face = -1;\n\tif( absDirection.x > absDirection.z ) {\n\t\tif(absDirection.x > absDirection.y )\n\t\t\tface = direction.x > 0.0 ? 0 : 3;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\telse {\n\t\tif(absDirection.z > absDirection.y )\n\t\t\tface = direction.z > 0.0 ? 2 : 5;\n\t\telse\n\t\t\tface = direction.y > 0.0 ? 1 : 4;\n\t}\n\treturn face;\n}\n#define cubeUV_maxLods1 (log2(cubeUV_textureSize*0.25) - 1.0)\n#define cubeUV_rangeClamp (exp2((6.0 - 1.0) * 2.0))\nvec2 MipLevelInfo( vec3 vec, float roughnessLevel, float roughness ) {\n\tfloat scale = exp2(cubeUV_maxLods1 - roughnessLevel);\n\tfloat dxRoughness = dFdx(roughness);\n\tfloat dyRoughness = dFdy(roughness);\n\tvec3 dx = dFdx( vec * scale * dxRoughness );\n\tvec3 dy = dFdy( vec * scale * dyRoughness );\n\tfloat d = max( dot( dx, dx ), dot( dy, dy ) );\n\td = clamp(d, 1.0, cubeUV_rangeClamp);
9487\n\tfloat mipLevel = 0.5 * log2(d);\n\treturn vec2(floor(mipLevel), fract(mipLevel));\n}\n#define cubeUV_maxLods2 (log2(cubeUV_textureSize*0.25) - 2.0)\n#define cubeUV_rcpTextureSize (1.0 / cubeUV_textureSize)\nvec2 getCubeUV(vec3 direction, float roughnessLevel, float mipLevel) {\n\tmipLevel = roughnessLevel > cubeUV_maxLods2 - 3.0 ? 0.0 : mipLevel;\n\tfloat a = 16.0 * cubeUV_rcpTextureSize;\n\tvec2 exp2_packed = exp2( vec2( roughnessLevel, mipLevel ) );\n\tvec2 rcp_exp2_packed = vec2( 1.0 ) / exp2_packed;\n\tfloat powScale = exp2_packed.x * exp2_packed.y;\n\tfloat scale = rcp_exp2_packed.x * rcp_exp2_packed.y * 0.25;\n\tfloat mipOffset = 0.75*(1.0 - rcp_exp2_packed.y) * rcp_exp2_packed.x;\n\tbool bRes = mipLevel == 0.0;\n\tscale = bRes && (scale < a) ? a : scale;\n\tvec3 r;\n\tvec2 offset;\n\tint face = getFaceFromDirection(direction);\n\tfloat rcpPowScale = 1.0 / powScale;\n\tif( face == 0) {\n\t\tr = vec3(direction.x, -direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 1) {\n\t\tr = vec3(direction.y, direction.x, direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 2) {\n\t\tr = vec3(direction.z, direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.75 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? a : offset.y;\n\t}\n\telse if( face == 3) {\n\t\tr = vec3(direction.x, direction.z, direction.y);\n\t\toffset = vec2(0.0+mipOffset,0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse if( face == 4) {\n\t\tr = vec3(direction.y, direction.x, -direction.z);\n\t\toffset = vec2(scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\telse {\n\t\tr = vec3(direction.z, -direction.x, direction.y);\n\t\toffset = vec2(2.0*scale+mipOffset, 0.5 * rcpPowScale);\n\t\toffset.y = bRes && (offset.y < 2.0*a) ? 0.0 : offset.y;\n\t}\n\tr = normalize(r);\n\tfloat texelOffset = 0.5 * cubeUV_rcpTextureSize;\n\tvec2 s = ( r.yz / abs( r.x ) + vec2( 1.0 ) ) * 0.5;\n\tvec2 base = offset + vec2( texelOffset );\n\treturn base + s * ( scale - 2.0 * texelOffset );\n}\n#define cubeUV_maxLods3 (log2(cubeUV_textureSize*0.25) - 3.0)\nvec4 textureCubeUV(vec3 reflectedDirection, float roughness ) {\n\tfloat roughnessVal = roughness* cubeUV_maxLods3;\n\tfloat r1 = floor(roughnessVal);\n\tfloat r2 = r1 + 1.0;\n\tfloat t = fract(roughnessVal);\n\tvec2 mipInfo = MipLevelInfo(reflectedDirection, r1, roughness);\n\tfloat s = mipInfo.y;\n\tfloat level0 = mipInfo.x;\n\tfloat level1 = level0 + 1.0;\n\tlevel1 = level1 > 5.0 ? 5.0 : level1;\n\tlevel0 += min( floor( s + 0.5 ), 5.0 );\n\tvec2 uv_10 = getCubeUV(reflectedDirection, r1, level0);\n\tvec4 color10 = envMapTexelToLinear(texture2D(envMap, uv_10));\n\tvec2 uv_20 = getCubeUV(reflectedDirection, r2, level0);\n\tvec4 color20 = envMapTexelToLinear(texture2D(envMap, uv_20));\n\tvec4 result = mix(color10, color20, t);\n\treturn vec4(result.rgb, 1.0);\n}\n#endif\n"; 9488 9489 var defaultnormal_vertex = "vec3 transformedNormal = normalMatrix * objectNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n"; 9490 9491 var displacementmap_pars_vertex = "#ifdef USE_DISPLACEMENTMAP\n\tuniform sampler2D displacementMap;\n\tuniform float displacementScale;\n\tuniform float displacementBias;\n#endif\n"; 9492 9493 var displacementmap_vertex = "#ifdef USE_DISPLACEMENTMAP\n\ttransformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );\n#endif\n"; 9494 9495 var emissivemap_fragment = "#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vUv );\n\temissiveColor.rgb = emissiveMapTexelToLinear( emissiveColor ).rgb;\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif\n"; 9496 9497 var emissivemap_pars_fragment = "#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif\n"; 9498 9499 var encodings_fragment = " gl_FragColor = linearToOutputTexel( gl_FragColor );\n"; 9500 9501 var encodings_pars_fragment = "\nvec4 LinearToLinear( in vec4 value ) {\n\treturn value;\n}\nvec4 GammaToLinear( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( gammaFactor ) ), value.w );\n}\nvec4 LinearToGamma( in vec4 value, in float gammaFactor ) {\n\treturn vec4( pow( value.xyz, vec3( 1.0 / gammaFactor ) ), value.w );\n}\nvec4 sRGBToLinear( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb * 0.9478672986 + vec3( 0.0521327014 ), vec3( 2.4 ) ), value.rgb * 0.0773993808, vec3( lessThanEqual( value.rgb, vec3( 0.04045 ) ) ) ), value.w );\n}\nvec4 LinearTosRGB( in vec4 value ) {\n\treturn vec4( mix( pow( value.rgb, vec3( 0.41666 ) ) * 1.055 - vec3( 0.055 ), value.rgb * 12.92, vec3( lessThanEqual( value.rgb, vec3( 0.0031308 ) ) ) ), value.w );\n}\nvec4 RGBEToLinear( in vec4 value ) {\n\treturn vec4( value.rgb * exp2( value.a * 255.0 - 128.0 ), 1.0 );\n}
9501\nvec4 LinearToRGBE( in vec4 value ) {\n\tfloat maxComponent = max( max( value.r, value.g ), value.b );\n\tfloat fExp = clamp( ceil( log2( maxComponent ) ), -128.0, 127.0 );\n\treturn vec4( value.rgb / exp2( fExp ), ( fExp + 128.0 ) / 255.0 );\n}\nvec4 RGBMToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.xyz * value.w * maxRange, 1.0 );\n}\nvec4 LinearToRGBM( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat M = clamp( maxRGB / maxRange, 0.0, 1.0 );\n\tM = ceil( M * 255.0 ) / 255.0;\n\treturn vec4( value.rgb / ( M * maxRange ), M );\n}\nvec4 RGBDToLinear( in vec4 value, in float maxRange ) {\n\treturn vec4( value.rgb * ( ( maxRange / 255.0 ) / value.a ), 1.0 );\n}\nvec4 LinearToRGBD( in vec4 value, in float maxRange ) {\n\tfloat maxRGB = max( value.x, max( value.g, value.b ) );\n\tfloat D = max( maxRange / maxRGB, 1.0 );\n\tD = min( floor( D ) / 255.0, 1.0 );\n\treturn vec4( value.rgb * ( D * ( 255.0 / maxRange ) ), D );\n}\nconst mat3 cLogLuvM = mat3( 0.2209, 0.3390, 0.4184, 0.1138, 0.6780, 0.7319, 0.0102, 0.1130, 0.2969 );\nvec4 LinearToLogLuv( in vec4 value ) {\n\tvec3 Xp_Y_XYZp = value.rgb * cLogLuvM;\n\tXp_Y_XYZp = max(Xp_Y_XYZp, vec3(1e-6, 1e-6, 1e-6));\n\tvec4 vResult;\n\tvResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;\n\tfloat Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;\n\tvResult.w = fract(Le);\n\tvResult.z = (Le - (floor(vResult.w*255.0))/255.0)/255.0;\n\treturn vResult;\n}\nconst mat3 cLogLuvInverseM = mat3( 6.0014, -2.7008, -1.7996, -1.3320, 3.1029, -5.7721, 0.3008, -1.0882, 5.6268 );\nvec4 LogLuvToLinear( in vec4 value ) {\n\tfloat Le = value.z * 255.0 + value.w;\n\tvec3 Xp_Y_XYZp;\n\tXp_Y_XYZp.y = exp2((Le - 127.0) / 2.0);\n\tXp_Y_XYZp.z = Xp_Y_XYZp.y / value.y;\n\tXp_Y_XYZp.x = value.x * Xp_Y_XYZp.z;\n\tvec3 vRGB = Xp_Y_XYZp.rgb * cLogLuvInverseM;\n\treturn vec4( max(vRGB, 0.0), 1.0 );\n}\n"; 9502 9503 var envmap_fragment = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#else\n\t\tvec3 reflectVec = vReflect;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 envColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );\n\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\tvec2 sampleUV;\n\t\treflectVec = normalize( reflectVec );\n\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\tvec4 envColor = texture2D( envMap, sampleUV );\n\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\treflectVec = normalize( reflectVec );\n\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0, 0.0, 1.0 ) );\n\t\tvec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );\n\t#else\n\t\tvec4 envColor = vec4( 0.0 );\n\t#endif\n\tenvColor = envMapTexelToLinear( envColor );\n\t#ifdef ENVMAP_BLENDING_MULTIPLY\n\t\toutgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_MIX )\n\t\toutgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );\n\t#elif defined( ENVMAP_BLENDING_ADD )\n\t\toutgoingLight += envColor.xyz * specularStrength * reflectivity;\n\t#endif\n#endif\n"; 9504 9505 var envmap_pars_fragment = "#if defined( USE_ENVMAP ) || defined( PHYSICAL )\n\tuniform float reflectivity;\n\tuniform float envMapIntensity;\n#endif\n#ifdef USE_ENVMAP\n\t#if ! defined( PHYSICAL ) && ( defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) )\n\t\tvarying vec3 vWorldPosition;\n\t#endif\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tuniform samplerCube envMap;\n\t#else\n\t\tuniform sampler2D envMap;\n\t#endif\n\tuniform float flipEnvMap;\n\tuniform int maxMipLevel;\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG ) || defined( PHYSICAL )\n\t\tuniform float refractionRatio;\n\t#else\n\t\tvarying vec3 vReflect;\n\t#endif\n#endif\n"; 9506 9507 var envmap_pars_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvarying vec3 vWorldPosition;\n\t#else\n\t\tvarying vec3 vReflect;\n\t\tuniform float refractionRatio;\n\t#endif\n#endif\n"; 9508 9509 var envmap_vertex = "#ifdef USE_ENVMAP\n\t#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( PHONG )\n\t\tvWorldPosition = worldPosition.xyz;
9509\n\t#else\n\t\tvec3 cameraToVertex = normalize( worldPosition.xyz - cameraPosition );\n\t\tvec3 worldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvReflect = reflect( cameraToVertex, worldNormal );\n\t\t#else\n\t\t\tvReflect = refract( cameraToVertex, worldNormal, refractionRatio );\n\t\t#endif\n\t#endif\n#endif\n"; 9510 9511 var fog_vertex = "\n#ifdef USE_FOG\nfogDepth = -mvPosition.z;\n#endif"; 9512 9513 var fog_pars_vertex = "#ifdef USE_FOG\n varying float fogDepth;\n#endif\n"; 9514 9515 var fog_fragment = "#ifdef USE_FOG\n\t#ifdef FOG_EXP2\n\t\tfloat fogFactor = whiteCompliment( exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 ) );\n\t#else\n\t\tfloat fogFactor = smoothstep( fogNear, fogFar, fogDepth );\n\t#endif\n\tgl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );\n#endif\n"; 9516 9517 var fog_pars_fragment = "#ifdef USE_FOG\n\tuniform vec3 fogColor;\n\tvarying float fogDepth;\n\t#ifdef FOG_EXP2\n\t\tuniform float fogDensity;\n\t#else\n\t\tuniform float fogNear;\n\t\tuniform float fogFar;\n\t#endif\n#endif\n"; 9518 9519 var gradientmap_pars_fragment = "#ifdef TOON\n\tuniform sampler2D gradientMap;\n\tvec3 getGradientIrradiance( vec3 normal, vec3 lightDirection ) {\n\t\tfloat dotNL = dot( normal, lightDirection );\n\t\tvec2 coord = vec2( dotNL * 0.5 + 0.5, 0.0 );\n\t\t#ifdef USE_GRADIENTMAP\n\t\t\treturn texture2D( gradientMap, coord ).rgb;\n\t\t#else\n\t\t\treturn ( coord.x < 0.7 ) ? vec3( 0.7 ) : vec3( 1.0 );\n\t\t#endif\n\t}\n#endif\n"; 9520 9521 var lightmap_fragment = "#ifdef USE_LIGHTMAP\n\treflectedLight.indirectDiffuse += PI * texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n#endif\n"; 9522 9523 var lightmap_pars_fragment = "#ifdef USE_LIGHTMAP\n\tuniform sampler2D lightMap;\n\tuniform float lightMapIntensity;\n#endif"; 9524 9525 var lights_lambert_vertex = "vec3 diffuse = vec3( 1.0 );\nGeometricContext geometry;\ngeometry.position = mvPosition.xyz;\ngeometry.normal = normalize( transformedNormal );\ngeometry.viewDir = normalize( -mvPosition.xyz );\nGeometricContext backGeometry;\nbackGeometry.position = geometry.position;\nbackGeometry.normal = -geometry.normal;\nbackGeometry.viewDir = geometry.viewDir;\nvLightFront = vec3( 0.0 );\n#ifdef DOUBLE_SIDED\n\tvLightBack = vec3( 0.0 );\n#endif\nIncidentLight directLight;\nfloat dotNL;\nvec3 directLightColor_Diffuse;\n#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tgetPointDirectLightIrradiance( pointLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tgetSpotDirectLightIrradiance( spotLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tgetDirectionalDirectLightIrradiance( directionalLights[ i ], geometry, directLight );\n\t\tdotNL = dot( geometry.normal, directLight.direction );\n\t\tdirectLightColor_Diffuse = PI * directLight.color;\n\t\tvLightFront += saturate( dotNL ) * directLightColor_Diffuse;\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += saturate( -dotNL ) * directLightColor_Diffuse;\n\t\t#endif\n\t}\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\tvLightFront += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t#ifdef DOUBLE_SIDED\n\t\t\tvLightBack += getHemisphereLightIrradiance( hemisphereLights[ i ], backGeometry );\n\t\t#endif\n\t}\n#endif\n"; 9526 9527 var lights_pars_begin = "uniform vec3 ambientLightColor;\nvec3 getAmbientLightIrradiance( const in vec3 ambientLightColor ) {\n\tvec3 irradiance = ambientLightColor;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treturn irradiance;\n}\n#if NUM_DIR_LIGHTS > 0\n\tstruct DirectionalLight {\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform DirectionalLight directionalLights[ NUM_DIR_LIGHTS ];\n\tvoid getDirectionalDirectLightIrradiance( const in DirectionalLight directionalLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tdirectLight.color = directionalLight.color;\n\t\tdirectLight.direction = directionalLight.direction;\n\t\tdirectLight.visible = true;\n\t}\n#endif\n#if NUM_POINT_LIGHTS > 0\n\tstruct PointLight {\n\t\tvec3 position;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t\tfloat shadowCameraNear;\n\t\tfloat shadowCameraFar;\n\t};\n\tuniform PointLight pointLights[ NUM_POINT_LIGHTS ];\n\tvoid getPointDirectLightIrradiance( const in PointLight pointLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = pointLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tdirectLight.color = pointLight.color;\n\t\tdirectLight.color *= punctualLightIntensityToIrradianceFactor( lightDistance, pointLight.distance, pointLight.decay );\n\t\tdirectLight.visible = ( directLight.color != vec3( 0.0 ) );\n\t}
9527\n#endif\n#if NUM_SPOT_LIGHTS > 0\n\tstruct SpotLight {\n\t\tvec3 position;\n\t\tvec3 direction;\n\t\tvec3 color;\n\t\tfloat distance;\n\t\tfloat decay;\n\t\tfloat coneCos;\n\t\tfloat penumbraCos;\n\t\tint shadow;\n\t\tfloat shadowBias;\n\t\tfloat shadowRadius;\n\t\tvec2 shadowMapSize;\n\t};\n\tuniform SpotLight spotLights[ NUM_SPOT_LIGHTS ];\n\tvoid getSpotDirectLightIrradiance( const in SpotLight spotLight, const in GeometricContext geometry, out IncidentLight directLight ) {\n\t\tvec3 lVector = spotLight.position - geometry.position;\n\t\tdirectLight.direction = normalize( lVector );\n\t\tfloat lightDistance = length( lVector );\n\t\tfloat angleCos = dot( directLight.direction, spotLight.direction );\n\t\tif ( angleCos > spotLight.coneCos ) {\n\t\t\tfloat spotEffect = smoothstep( spotLight.coneCos, spotLight.penumbraCos, angleCos );\n\t\t\tdirectLight.color = spotLight.color;\n\t\t\tdirectLight.color *= spotEffect * punctualLightIntensityToIrradianceFactor( lightDistance, spotLight.distance, spotLight.decay );\n\t\t\tdirectLight.visible = true;\n\t\t} else {\n\t\t\tdirectLight.color = vec3( 0.0 );\n\t\t\tdirectLight.visible = false;\n\t\t}\n\t}\n#endif\n#if NUM_RECT_AREA_LIGHTS > 0\n\tstruct RectAreaLight {\n\t\tvec3 color;\n\t\tvec3 position;\n\t\tvec3 halfWidth;\n\t\tvec3 halfHeight;\n\t};\n\tuniform sampler2D ltc_1;\tuniform sampler2D ltc_2;\n\tuniform RectAreaLight rectAreaLights[ NUM_RECT_AREA_LIGHTS ];\n#endif\n#if NUM_HEMI_LIGHTS > 0\n\tstruct HemisphereLight {\n\t\tvec3 direction;\n\t\tvec3 skyColor;\n\t\tvec3 groundColor;\n\t};\n\tuniform HemisphereLight hemisphereLights[ NUM_HEMI_LIGHTS ];\n\tvec3 getHemisphereLightIrradiance( const in HemisphereLight hemiLight, const in GeometricContext geometry ) {\n\t\tfloat dotNL = dot( geometry.normal, hemiLight.direction );\n\t\tfloat hemiDiffuseWeight = 0.5 * dotNL + 0.5;\n\t\tvec3 irradiance = mix( hemiLight.groundColor, hemiLight.skyColor, hemiDiffuseWeight );\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tirradiance *= PI;\n\t\t#endif\n\t\treturn irradiance;\n\t}\n#endif\n"; 9528 9529 var lights_pars_maps = "#if defined( USE_ENVMAP ) && defined( PHYSICAL )\n\tvec3 getLightProbeIndirectIrradiance( const in GeometricContext geometry, const in int maxMIPLevel ) {\n\t\tvec3 worldNormal = inverseTransformDirection( geometry.normal, viewMatrix );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryVec, float( maxMIPLevel ) );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryVec = vec3( flipEnvMap * worldNormal.x, worldNormal.yz );\n\t\t\tvec4 envMapColor = textureCubeUV( queryVec, 1.0 );\n\t\t#else\n\t\t\tvec4 envMapColor = vec4( 0.0 );\n\t\t#endif\n\t\treturn PI * envMapColor.rgb * envMapIntensity;\n\t}\n\tfloat getSpecularMIPLevel( const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\tfloat maxMIPLevelScalar = float( maxMIPLevel );\n\t\tfloat desiredMIPLevel = maxMIPLevelScalar + 0.79248 - 0.5 * log2( pow2( blinnShininessExponent ) + 1.0 );\n\t\treturn clamp( desiredMIPLevel, 0.0, maxMIPLevelScalar );\n\t}\n\tvec3 getLightProbeIndirectRadiance( const in GeometricContext geometry, const in float blinnShininessExponent, const in int maxMIPLevel ) {\n\t\t#ifdef ENVMAP_MODE_REFLECTION\n\t\t\tvec3 reflectVec = reflect( -geometry.viewDir, geometry.normal );\n\t\t#else\n\t\t\tvec3 reflectVec = refract( -geometry.viewDir, geometry.normal, refractionRatio );\n\t\t#endif\n\t\treflectVec = inverseTransformDirection( reflectVec, viewMatrix );\n\t\tfloat specularMIPLevel = getSpecularMIPLevel( blinnShininessExponent, maxMIPLevel );\n\t\t#ifdef ENVMAP_TYPE_CUBE\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = textureCubeLodEXT( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = textureCube( envMap, queryReflectVec, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\t\tvec3 queryReflectVec = vec3( flipEnvMap * reflectVec.x, reflectVec.yz );\n\t\t\tvec4 envMapColor = textureCubeUV(queryReflectVec, BlinnExponentToGGXRoughness(blinnShinine
9529ssExponent));\n\t\t#elif defined( ENVMAP_TYPE_EQUIREC )\n\t\t\tvec2 sampleUV;\n\t\t\tsampleUV.y = asin( clamp( reflectVec.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\t\t\tsampleUV.x = atan( reflectVec.z, reflectVec.x ) * RECIPROCAL_PI2 + 0.5;\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, sampleUV, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, sampleUV, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#elif defined( ENVMAP_TYPE_SPHERE )\n\t\t\tvec3 reflectView = normalize( ( viewMatrix * vec4( reflectVec, 0.0 ) ).xyz + vec3( 0.0,0.0,1.0 ) );\n\t\t\t#ifdef TEXTURE_LOD_EXT\n\t\t\t\tvec4 envMapColor = texture2DLodEXT( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#else\n\t\t\t\tvec4 envMapColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5, specularMIPLevel );\n\t\t\t#endif\n\t\t\tenvMapColor.rgb = envMapTexelToLinear( envMapColor ).rgb;\n\t\t#endif\n\t\treturn envMapColor.rgb * envMapIntensity;\n\t}\n#endif\n"; 9530 9531 var lights_phong_fragment = "BlinnPhongMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb;\nmaterial.specularColor = specular;\nmaterial.specularShininess = shininess;\nmaterial.specularStrength = specularStrength;\n"; 9532 9533 var lights_phong_pars_fragment = "varying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\nstruct BlinnPhongMaterial {\n\tvec3\tdiffuseColor;\n\tvec3\tspecularColor;\n\tfloat\tspecularShininess;\n\tfloat\tspecularStrength;\n};\nvoid RE_Direct_BlinnPhong( const in IncidentLight directLight, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifdef TOON\n\t\tvec3 irradiance = getGradientIrradiance( geometry.normal, directLight.direction ) * directLight.color;\n\t#else\n\t\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\t\tvec3 irradiance = dotNL * directLight.color;\n\t#endif\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\treflectedLight.directDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_Specular_BlinnPhong( directLight, geometry, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in GeometricContext geometry, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\n#define RE_Direct\t\t\t\tRE_Direct_BlinnPhong\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_BlinnPhong\n#define Material_LightProbeLOD( material )\t(0)\n"; 9534 9535 var lights_physical_fragment = "PhysicalMaterial material;\nmaterial.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );\nmaterial.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );\n#ifdef STANDARD\n\tmaterial.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );\n#else\n\tmaterial.specularColor = mix( vec3( MAXIMUM_SPECULAR_COEFFICIENT * pow2( reflectivity ) ), diffuseColor.rgb, metalnessFactor );\n\tmaterial.clearCoat = saturate( clearCoat );\tmaterial.clearCoatRoughness = clamp( clearCoatRoughness, 0.04, 1.0 );\n#endif\n"; 9536 9537 var lights_physical_pars_fragment = "struct PhysicalMaterial {\n\tvec3\tdiffuseColor;\n\tfloat\tspecularRoughness;\n\tvec3\tspecularColor;\n\t#ifndef STANDARD\n\t\tfloat clearCoat;\n\t\tfloat clearCoatRoughness;\n\t#endif\n};\n#define MAXIMUM_SPECULAR_COEFFICIENT 0.16\n#define DEFAULT_SPECULAR_COEFFICIENT 0.04\nfloat clearCoatDHRApprox( const in float roughness, const in float dotNL ) {\n\treturn DEFAULT_SPECULAR_COEFFICIENT + ( 1.0 - DEFAULT_SPECULAR_COEFFICIENT ) * ( pow( 1.0 - dotNL, 5.0 ) * pow( 1.0 - roughness, 2.0 ) );\n}\n#if NUM_RECT_AREA_LIGHTS > 0\n\tvoid RE_Direct_RectArea_Physical( const in RectAreaLight rectAreaLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometry.normal;\n\t\tvec3 viewDir = geometry.viewDir;\n\t\tvec3 position = geometry.position;
9537\n\t\tvec3 lightPos = rectAreaLight.position;\n\t\tvec3 halfWidth = rectAreaLight.halfWidth;\n\t\tvec3 halfHeight = rectAreaLight.halfHeight;\n\t\tvec3 lightColor = rectAreaLight.color;\n\t\tfloat roughness = material.specularRoughness;\n\t\tvec3 rectCoords[ 4 ];\n\t\trectCoords[ 0 ] = lightPos - halfWidth - halfHeight;\t\trectCoords[ 1 ] = lightPos + halfWidth - halfHeight;\n\t\trectCoords[ 2 ] = lightPos + halfWidth + halfHeight;\n\t\trectCoords[ 3 ] = lightPos - halfWidth + halfHeight;\n\t\tvec2 uv = LTC_Uv( normal, viewDir, roughness );\n\t\tvec4 t1 = texture2D( ltc_1, uv );\n\t\tvec4 t2 = texture2D( ltc_2, uv );\n\t\tmat3 mInv = mat3(\n\t\t\tvec3( t1.x, 0, t1.y ),\n\t\t\tvec3( 0, 1, 0 ),\n\t\t\tvec3( t1.z, 0, t1.w )\n\t\t);\n\t\tvec3 fresnel = ( material.specularColor * t2.x + ( vec3( 1.0 ) - material.specularColor ) * t2.y );\n\t\treflectedLight.directSpecular += lightColor * fresnel * LTC_Evaluate( normal, viewDir, position, mInv, rectCoords );\n\t\treflectedLight.directDiffuse += lightColor * material.diffuseColor * LTC_Evaluate( normal, viewDir, position, mat3( 1.0 ), rectCoords );\n\t}\n#endif\nvoid RE_Direct_Physical( const in IncidentLight directLight, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometry.normal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\tirradiance *= PI;\n\t#endif\n\t#ifndef STANDARD\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.directSpecular += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Specular_GGX( directLight, geometry, material.specularColor, material.specularRoughness );\n\treflectedLight.directDiffuse += ( 1.0 - clearCoatDHR ) * irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n\t#ifndef STANDARD\n\t\treflectedLight.directSpecular += irradiance * material.clearCoat * BRDF_Specular_GGX( directLight, geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\treflectedLight.indirectDiffuse += irradiance * BRDF_Diffuse_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectSpecular_Physical( const in vec3 radiance, const in vec3 clearCoatRadiance, const in GeometricContext geometry, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t#ifndef STANDARD\n\t\tfloat dotNV = saturate( dot( geometry.normal, geometry.viewDir ) );\n\t\tfloat dotNL = dotNV;\n\t\tfloat clearCoatDHR = material.clearCoat * clearCoatDHRApprox( material.clearCoatRoughness, dotNL );\n\t#else\n\t\tfloat clearCoatDHR = 0.0;\n\t#endif\n\treflectedLight.indirectSpecular += ( 1.0 - clearCoatDHR ) * radiance * BRDF_Specular_GGX_Environment( geometry, material.specularColor, material.specularRoughness );\n\t#ifndef STANDARD\n\t\treflectedLight.indirectSpecular += clearCoatRadiance * material.clearCoat * BRDF_Specular_GGX_Environment( geometry, vec3( DEFAULT_SPECULAR_COEFFICIENT ), material.clearCoatRoughness );\n\t#endif\n}\n#define RE_Direct\t\t\t\tRE_Direct_Physical\n#define RE_Direct_RectArea\t\tRE_Direct_RectArea_Physical\n#define RE_IndirectDiffuse\t\tRE_IndirectDiffuse_Physical\n#define RE_IndirectSpecular\t\tRE_IndirectSpecular_Physical\n#define Material_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.specularRoughness )\n#define Material_ClearCoat_BlinnShininessExponent( material ) GGXRoughnessToBlinnExponent( material.clearCoatRoughness )\nfloat computeSpecularOcclusion( const in float dotNV, const in float ambientOcclusion, const in float roughness ) {\n\treturn saturate( pow( dotNV + ambientOcclusion, exp2( - 16.0 * roughness - 1.0 ) ) - 1.0 + ambientOcclusion );\n}\n"; 9538 9539 var lights_fragment_begin = "\nGeometricContext geometry;\ngeometry.position = - vViewPosition;\ngeometry.normal = normal;\ngeometry.viewDir = normalize( vViewPosition );\nIncidentLight directLight;\n#if ( NUM_POINT_LIGHTS > 0 ) && defined( RE_Direct )\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tgetPointDirectLightIrradiance( pointLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( pointLight.shadow, directLight.visible ) ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}
9539\n#endif\n#if ( NUM_SPOT_LIGHTS > 0 ) && defined( RE_Direct )\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tgetSpotDirectLightIrradiance( spotLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( spotLight.shadow, directLight.visible ) ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_DIR_LIGHTS > 0 ) && defined( RE_Direct )\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tgetDirectionalDirectLightIrradiance( directionalLight, geometry, directLight );\n\t\t#ifdef USE_SHADOWMAP\n\t\tdirectLight.color *= all( bvec2( directionalLight.shadow, directLight.visible ) ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if ( NUM_RECT_AREA_LIGHTS > 0 ) && defined( RE_Direct_RectArea )\n\tRectAreaLight rectAreaLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_RECT_AREA_LIGHTS; i ++ ) {\n\t\trectAreaLight = rectAreaLights[ i ];\n\t\tRE_Direct_RectArea( rectAreaLight, geometry, material, reflectedLight );\n\t}\n#endif\n#if defined( RE_IndirectDiffuse )\n\tvec3 irradiance = getAmbientLightIrradiance( ambientLightColor );\n\t#if ( NUM_HEMI_LIGHTS > 0 )\n\t\t#pragma unroll_loop\n\t\tfor ( int i = 0; i < NUM_HEMI_LIGHTS; i ++ ) {\n\t\t\tirradiance += getHemisphereLightIrradiance( hemisphereLights[ i ], geometry );\n\t\t}\n\t#endif\n#endif\n#if defined( RE_IndirectSpecular )\n\tvec3 radiance = vec3( 0.0 );\n\tvec3 clearCoatRadiance = vec3( 0.0 );\n#endif\n"; 9540 9541 var lights_fragment_maps = "#if defined( RE_IndirectDiffuse )\n\t#ifdef USE_LIGHTMAP\n\t\tvec3 lightMapIrradiance = texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t\t#ifndef PHYSICALLY_CORRECT_LIGHTS\n\t\t\tlightMapIrradiance *= PI;\n\t\t#endif\n\t\tirradiance += lightMapIrradiance;\n\t#endif\n\t#if defined( USE_ENVMAP ) && defined( PHYSICAL ) && defined( ENVMAP_TYPE_CUBE_UV )\n\t\tirradiance += getLightProbeIndirectIrradiance( geometry, maxMipLevel );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\tradiance += getLightProbeIndirectRadiance( geometry, Material_BlinnShininessExponent( material ), maxMipLevel );\n\t#ifndef STANDARD\n\t\tclearCoatRadiance += getLightProbeIndirectRadiance( geometry, Material_ClearCoat_BlinnShininessExponent( material ), maxMipLevel );\n\t#endif\n#endif\n"; 9542 9543 var lights_fragment_end = "#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometry, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, clearCoatRadiance, geometry, material, reflectedLight );\n#endif\n"; 9544 9545 var logdepthbuf_fragment = "#if defined( USE_LOGDEPTHBUF ) && defined( USE_LOGDEPTHBUF_EXT )\n\tgl_FragDepthEXT = log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif"; 9546 9547 var logdepthbuf_pars_fragment = "#ifdef USE_LOGDEPTHBUF\n\tuniform float logDepthBufFC;\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n#endif\n"; 9548 9549 var logdepthbuf_pars_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvarying float vFragDepth;\n\t#endif\n\tuniform float logDepthBufFC;\n#endif"; 9550 9551 var logdepthbuf_vertex = "#ifdef USE_LOGDEPTHBUF\n\t#ifdef USE_LOGDEPTHBUF_EXT\n\t\tvFragDepth = 1.0 + gl_Position.w;\n\t#else\n\t\tgl_Position.z = log2( max( EPSILON, gl_Position.w + 1.0 ) ) * logDepthBufFC - 1.0;\n\t\tgl_Position.z *= gl_Position.w;\n\t#endif\n#endif\n"; 9552 9553 var map_fragment = "#ifdef USE_MAP\n\tvec4 texelColor = texture2D( map, vUv );\n\ttexelColor = mapTexelToLinear( texelColor );\n\tdiffuseColor *= texelColor;\n#endif\n"; 9554 9555 var map_pars_fragment = "#ifdef USE_MAP\n\tuniform sampler2D map;\n#endif\n"; 9556 9557 var map_particle_fragment = "#ifdef USE_MAP\n\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\tvec4 mapTexel = texture2D( map, uv );\n\tdiffuseColor *= mapTexelToLinear( mapTexel );\n#endif\n"; 9558 9559 var map_particle_pars_fragment = "#ifdef USE_MAP\n\tuniform mat3 uvTransform;\n\tuniform sampler2D map;\n#endif\n"; 9560 9561 var metalnessmap_fragment = "float metalnessFactor = metalness;\n#ifdef USE_METALNESSMAP\n\tvec4 texelMetalness = texture2D( metalnessMap, vUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif\n"; 9562 9563 var metalnessmap_pars_fragment = "#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif"; 9564 9565 var morphnormal_vertex = "#ifdef USE_MORPHNORMALS\n\tobjectNormal += ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];\n\tobjectNormal += ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];\n\tobjectNormal += ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];\n\tobjectNormal += ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];\n#endif\n"; 9566 9567 var morphtarget_pars_vertex = "#ifdef USE_MORPHTARGETS\n\t#ifndef USE_MORPHNORMALS\n\tuniform float morphTargetInfluences[ 8 ];\n\t#else\n\tuniform float morphTargetInfluences[ 4 ];\n\t#endif\n#endif"; 9568 9569 var morphtarget_vertex = "#ifdef USE_MORPHTARGETS\n\ttransformed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];\n\ttransformed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];\n\ttransformed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];\n\ttransformed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];\n\t#ifndef USE_MORPHNORMALS\n\ttransformed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];\n\ttransformed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];\n\ttransformed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];\n\ttransformed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];\n\t#endif\n#endif\n"; 9570 9571 var normal_fragment_begin = "#ifdef FLAT_SHADED\n\tvec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );\n\tvec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );\n\tvec3 normal = normalize( cross( fdx, fdy ) );\n#else\n\tvec3 normal = normalize( vNormal );\n\t#ifdef DOUBLE_SIDED\n\t\tnormal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t#endif\n#endif\n"; 9572 9573 var normal_fragment_maps = "#ifdef USE_NORMALMAP\n\tnormal = perturbN
9573ormal2Arb( -vViewPosition, normal );\n#elif defined( USE_BUMPMAP )\n\tnormal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );\n#endif\n"; 9574 9575 var normalmap_pars_fragment = "#ifdef USE_NORMALMAP\n\tuniform sampler2D normalMap;\n\tuniform vec2 normalScale;\n\tvec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {\n\t\tvec3 q0 = vec3( dFdx( eye_pos.x ), dFdx( eye_pos.y ), dFdx( eye_pos.z ) );\n\t\tvec3 q1 = vec3( dFdy( eye_pos.x ), dFdy( eye_pos.y ), dFdy( eye_pos.z ) );\n\t\tvec2 st0 = dFdx( vUv.st );\n\t\tvec2 st1 = dFdy( vUv.st );\n\t\tfloat scale = sign( st1.t * st0.s - st0.t * st1.s );\n\t\tvec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );\n\t\tvec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );\n\t\tvec3 N = normalize( surf_norm );\n\t\tmat3 tsn = mat3( S, T, N );\n\t\tvec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;\n\t\tmapN.xy *= normalScale;\n\t\tmapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );\n\t\treturn normalize( tsn * mapN );\n\t}\n#endif\n"; 9576 9577 var packing = "vec3 packNormalToRGB( const in vec3 normal ) {\n\treturn normalize( normal ) * 0.5 + 0.5;\n}\nvec3 unpackRGBToNormal( const in vec3 rgb ) {\n\treturn 2.0 * rgb.xyz - 1.0;\n}\nconst float PackUpscale = 256. / 255.;const float UnpackDownscale = 255. / 256.;\nconst vec3 PackFactors = vec3( 256. * 256. * 256., 256. * 256., 256. );\nconst vec4 UnpackFactors = UnpackDownscale / vec4( PackFactors, 1. );\nconst float ShiftRight8 = 1. / 256.;\nvec4 packDepthToRGBA( const in float v ) {\n\tvec4 r = vec4( fract( v * PackFactors ), v );\n\tr.yzw -= r.xyz * ShiftRight8;\treturn r * PackUpscale;\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors );\n}\nfloat viewZToOrthographicDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn ( viewZ + near ) / ( near - far );\n}\nfloat orthographicDepthToViewZ( const in float linearClipZ, const in float near, const in float far ) {\n\treturn linearClipZ * ( near - far ) - near;\n}\nfloat viewZToPerspectiveDepth( const in float viewZ, const in float near, const in float far ) {\n\treturn (( near + viewZ ) * far ) / (( far - near ) * viewZ );\n}\nfloat perspectiveDepthToViewZ( const in float invClipZ, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * invClipZ - far );\n}\n"; 9578 9579 var premultiplied_alpha_fragment = "#ifdef PREMULTIPLIED_ALPHA\n\tgl_FragColor.rgb *= gl_FragColor.a;\n#endif\n"; 9580 9581 var project_vertex = "vec4 mvPosition = modelViewMatrix * vec4( transformed, 1.0 );\ngl_Position = projectionMatrix * mvPosition;\n"; 9582 9583 var dithering_fragment = "#if defined( DITHERING )\n gl_FragColor.rgb = dithering( gl_FragColor.rgb );\n#endif\n"; 9584 9585 var dithering_pars_fragment = "#if defined( DITHERING )\n\tvec3 dithering( vec3 color ) {\n\t\tfloat grid_position = rand( gl_FragCoord.xy );\n\t\tvec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );\n\t\tdither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );\n\t\treturn color + dither_shift_RGB;\n\t}\n#endif\n"; 9586 9587 var roughnessmap_fragment = "float roughnessFactor = roughness;\n#ifdef USE_ROUGHNESSMAP\n\tvec4 texelRoughness = texture2D( roughnessMap, vUv );\n\troughnessFactor *= texelRoughness.g;\n#endif\n"; 9588 9589 var roughnessmap_pars_fragment = "#ifdef USE_ROUGHNESSMAP\n\tuniform sampler2D roughnessMap;\n#endif"; 9590 9591 var shadowmap_pars_fragment = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform sampler2D directionalShadowMap[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform sampler2D spotShadowMap[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform sampler2D pointShadowMap[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n\tfloat texture2DCompare( sampler2D depths, vec2 uv, float compare ) {\n\t\treturn step( compare, unpackRGBAToDepth( texture2D( depths, uv ) ) );\n\t}\n\tfloat texture2DShadowLerp( sampler2D depths, vec2 size, vec2 uv, float compare ) {\n\t\tconst vec2 offset = vec2( 0.0, 1.0 );\n\t\tvec2 texelSize = vec2( 1.0 ) / size;\n\t\tvec2 centroidUV = floor( uv * size + 0.5 ) / size;\n\t\tfloat lb = texture2DCompare( depths, centroidUV + texelSize * offset.xx, compare );\n\t\tfloat lt = texture2DCompare( depths, centroidUV + texelSize * offset.xy, compare );\n\t\tfloat rb = texture2DCompare( depths, centroidUV + texelSize * offset.yx, compare );\n\t\tfloat rt = texture2DCompare( depths, centroidUV + texelSize * offset.yy, compare );\n\t\tvec2 f = fract( uv * size + 0.5 );\n\t\tfloat a = mix( lb, lt, f.y );\n\t\tfloat b = mix( rb, rt, f.y );\n\t\tfloat c = mix( a, b, f.x );\n\t\treturn c;\n\t}\n\tfloat getShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord ) {\n\t\tfloat shadow = 1.0;\n\t\tshadowCoord.xyz /= shadowCoord.w;\n\t\tshadowCoord.z += shadowBias;\n\t\tbvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );\n\t\tbool inFrustum = all( inFrustumVec );\n\t\tbvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );\n\t\tbool frustumTest = all( frustumTestVec );\n\t\tif ( frustumTest ) {\n\t\t#if defined( SHADOWMAP_TYPE_PCF )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DCompare( shadowMap, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#elif defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 texelSize = vec2( 1.0 ) / shadowMapSize;\n\t\t\tfloat dx0 = - texelSize.x * shadowRadius;\n\t\t\tfloat dy0 = - texelSize.y * shadowRadius;\n\t\t\tfloat dx1 = + texelSize.x * shadowRadius;\n\t\t\tfloat dy1 = + texelSize.y * shadowRadius;\n\t\t\tshadow = (\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy, shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, 0.0 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( 0.0, dy1 ), shadowCoord.z ) +\n\t\t\t\ttexture2DShadowLerp( shadowMap, shadowMapSize, shadowCoord.xy + vec2( dx1, dy1 ), shadowCoord.z )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\tshadow = texture2DCompare( shadowMap, shadowCoord.xy, shadowCoord.z );\n\t\t#endif\n\t\t}\n\t\treturn shadow;\n\t}\n\tvec2 cubeToUV( vec3 v, float texelSizeY ) {\n\t\tvec3 absV = abs( v );\n\t\tfloat scaleToCube = 1.0 / max( absV.x, max( absV.y, absV.z ) );\n\t\tabsV *= scaleToCube;\n\t\tv *= scaleToCube * ( 1.0 - 2.0 * texelSizeY );\n\t\tvec2 planar = v.xy;\n\t\tfloat almostATexel = 1.5 * texelSizeY;\n\t\tfloat almostOne = 1.0 - almostATexel;\n\t\tif ( absV.z >= almostOne ) {\n\t\t\tif ( v.z > 0.0 )\n\t\t\t\tplanar.x = 4.0 - v.x;\n\t\t} else if ( absV.x >= almostOne ) {\n\t\t\tfloat signX = sign( v.x );\n\t\t\tplanar.x = v.z * signX + 2.0 * signX;\n\t\t} else if ( absV.y >= almostOne ) {\n\t\t\tfloat signY = sign( v.y );\n\t\t\tplanar.x = v.x + 2.0 * signY + 2.0;\n\t\t\tplanar.y = v.z * signY - 2.0;\n\t\t}\n\t\treturn vec2( 0.125, 0.25 ) * planar + vec2( 0.375, 0.75 );\n\t}\n\tfloat getPointShadow( sampler2D shadowMap, vec2 shadowMapSize, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\tfloat dp = ( length( lightToPosition ) - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );
9591\t\tdp += shadowBias;\n\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT )\n\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\treturn (\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t) * ( 1.0 / 9.0 );\n\t\t#else\n\t\t\treturn texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t#endif\n\t}\n#endif\n"; 9592 9593 var shadowmap_pars_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t\tuniform mat4 directionalShadowMatrix[ NUM_DIR_LIGHTS ];\n\t\tvarying vec4 vDirectionalShadowCoord[ NUM_DIR_LIGHTS ];\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t\tuniform mat4 spotShadowMatrix[ NUM_SPOT_LIGHTS ];\n\t\tvarying vec4 vSpotShadowCoord[ NUM_SPOT_LIGHTS ];\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t\tuniform mat4 pointShadowMatrix[ NUM_POINT_LIGHTS ];\n\t\tvarying vec4 vPointShadowCoord[ NUM_POINT_LIGHTS ];\n\t#endif\n#endif\n"; 9594 9595 var shadowmap_vertex = "#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tvSpotShadowCoord[ i ] = spotShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * worldPosition;\n\t}\n\t#endif\n#endif\n"; 9596 9597 var shadowmask_pars_fragment = "float getShadowMask() {\n\tfloat shadow = 1.0;\n\t#ifdef USE_SHADOWMAP\n\t#if NUM_DIR_LIGHTS > 0\n\tDirectionalLight directionalLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_DIR_LIGHTS; i ++ ) {\n\t\tdirectionalLight = directionalLights[ i ];\n\t\tshadow *= bool( directionalLight.shadow ) ? getShadow( directionalShadowMap[ i ], directionalLight.shadowMapSize, directionalLight.shadowBias, directionalLight.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_SPOT_LIGHTS > 0\n\tSpotLight spotLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_SPOT_LIGHTS; i ++ ) {\n\t\tspotLight = spotLights[ i ];\n\t\tshadow *= bool( spotLight.shadow ) ? getShadow( spotShadowMap[ i ], spotLight.shadowMapSize, spotLight.shadowBias, spotLight.shadowRadius, vSpotShadowCoord[ i ] ) : 1.0;\n\t}\n\t#endif\n\t#if NUM_POINT_LIGHTS > 0\n\tPointLight pointLight;\n\t#pragma unroll_loop\n\tfor ( int i = 0; i < NUM_POINT_LIGHTS; i ++ ) {\n\t\tpointLight = pointLights[ i ];\n\t\tshadow *= bool( pointLight.shadow ) ? getPointShadow( pointShadowMap[ i ], pointLight.shadowMapSize, pointLight.shadowBias, pointLight.shadowRadius, vPointShadowCoord[ i ], pointLight.shadowCameraNear, pointLight.shadowCameraFar ) : 1.0;\n\t}\n\t#endif\n\t#endif\n\treturn shadow;\n}\n"; 9598 9599 var skinbase_vertex = "#ifdef USE_SKINNING\n\tmat4 boneMatX = getBoneMatrix( skinIndex.x );\n\tmat4 boneMatY = getBoneMatrix( skinIndex.y );\n\tmat4 boneMatZ = getBoneMatrix( skinIndex.z );\n\tmat4 boneMatW = getBoneMatrix( skinIndex.w );\n#endif"; 9600 9601 var skinning_pars_vertex = "#ifdef USE_SKINNING\n\tuniform mat4 bindMatrix;\n\tuniform mat4 bindMatrixInverse;\n\t#ifdef BONE_TEXTURE\n\t\tuniform sampler2D boneTexture;\n\t\tuniform int boneTextureSize;\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tfloat j = i * 4.0;\n\t\t\tfloat x = mod( j, float( boneTextureSize ) );\n\t\t\tfloat y = floor( j / float( boneTextureSize ) );\n\t\t\tfloat dx = 1.0 / float( boneTextureSize );\n\t\t\tfloat dy = 1.0 / float( boneTextureSize );\n\t\t\ty = dy * ( y + 0.5 );\n\t\t\tvec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );\n\t\t\tvec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );\n\t\t\tvec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );\n\t\t\tvec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );\n\t\t\tmat4 bone = mat4( v1, v2, v3, v4 );\n\t\t\treturn bone;\n\t\t}\n\t#else\n\t\tuniform mat4 boneMatrices[ MAX_BONES ];\n\t\tmat4 getBoneMatrix( const in float i ) {\n\t\t\tmat4 bone = boneMatrices[ int(i) ];\n\t\t\treturn bone;\n\t\t}\n\t#endif\n#endif\n"; 9602 9603 var skinning_vertex = "#ifdef USE_SKINNING\n\tvec4 skinVertex = bindMatrix * vec4( transformed, 1.0 );\n\tvec4 skinned = vec4( 0.0 );\n\tskinned += boneMatX * skinVertex * skinWeight.x;\n\tskinned += boneMatY * skinVertex * skinWeight.y;\n\tskinned += boneMatZ * skinVertex * skinWeight.z;\n\tskinned += boneMatW * skinVertex * skinWeight.w;\n\ttransformed = ( bindMatrixInverse * skinned ).xyz;\n#endif\n"; 9604 9605 var skinnormal_vertex = "#ifdef USE_SKINNING\n\tmat4 skinMatrix = mat4( 0.0 );\n\tskinMatrix += skinWeight.x * boneMatX;\n\tskinMatrix += skinWeight.y * boneMatY;\n\tskinMatrix += skinWeight.z * boneMatZ;\n\tskinMatrix += skinWeight.w * boneMatW;
9605\n\tskinMatrix = bindMatrixInverse * skinMatrix * bindMatrix;\n\tobjectNormal = vec4( skinMatrix * vec4( objectNormal, 0.0 ) ).xyz;\n#endif\n"; 9606 9607 var specularmap_fragment = "float specularStrength;\n#ifdef USE_SPECULARMAP\n\tvec4 texelSpecular = texture2D( specularMap, vUv );\n\tspecularStrength = texelSpecular.r;\n#else\n\tspecularStrength = 1.0;\n#endif"; 9608 9609 var specularmap_pars_fragment = "#ifdef USE_SPECULARMAP\n\tuniform sampler2D specularMap;\n#endif"; 9610 9611 var tonemapping_fragment = "#if defined( TONE_MAPPING )\n gl_FragColor.rgb = toneMapping( gl_FragColor.rgb );\n#endif\n"; 9612 9613 var tonemapping_pars_fragment = "#ifndef saturate\n\t#define saturate(a) clamp( a, 0.0, 1.0 )\n#endif\nuniform float toneMappingExposure;\nuniform float toneMappingWhitePoint;\nvec3 LinearToneMapping( vec3 color ) {\n\treturn toneMappingExposure * color;\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\n#define Uncharted2Helper( x ) max( ( ( x * ( 0.15 * x + 0.10 * 0.50 ) + 0.20 * 0.02 ) / ( x * ( 0.15 * x + 0.50 ) + 0.20 * 0.30 ) ) - 0.02 / 0.30, vec3( 0.0 ) )\nvec3 Uncharted2ToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( Uncharted2Helper( color ) / Uncharted2Helper( vec3( toneMappingWhitePoint ) ) );\n}\nvec3 OptimizedCineonToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\tcolor = max( vec3( 0.0 ), color - 0.004 );\n\treturn pow( ( color * ( 6.2 * color + 0.5 ) ) / ( color * ( 6.2 * color + 1.7 ) + 0.06 ), vec3( 2.2 ) );\n}\n"; 9614 9615 var uv_pars_fragment = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n#endif"; 9616 9617 var uv_pars_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\n"; 9618 9619 var uv_vertex = "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP ) || defined( USE_ALPHAMAP ) || defined( USE_EMISSIVEMAP ) || defined( USE_ROUGHNESSMAP ) || defined( USE_METALNESSMAP )\n\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n#endif"; 9620 9621 var uv2_pars_fragment = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvarying vec2 vUv2;\n#endif"; 9622 9623 var uv2_pars_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tattribute vec2 uv2;\n\tvarying vec2 vUv2;\n#endif"; 9624 9625 var uv2_vertex = "#if defined( USE_LIGHTMAP ) || defined( USE_AOMAP )\n\tvUv2 = uv2;\n#endif"; 9626 9627 var worldpos_vertex = "#if defined( USE_ENVMAP ) || defined( DISTANCE ) || defined ( USE_SHADOWMAP )\n\tvec4 worldPosition = modelMatrix * vec4( transformed, 1.0 );\n#endif\n"; 9628 9629 var cube_frag = "uniform samplerCube tCube;\nuniform float tFlip;\nuniform float opacity;\nvarying vec3 vWorldPosition;\nvoid main() {\n\tgl_FragColor = textureCube( tCube, vec3( tFlip * vWorldPosition.x, vWorldPosition.yz ) );\n\tgl_FragColor.a *= opacity;\n}\n"; 9630 9631 var cube_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\tgl_Position.z = gl_Position.w;\n}\n"; 9632 9633 var depth_frag = "#if DEPTH_PACKING == 3200\n\tuniform float opacity;\n#endif\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#if DEPTH_PACKING == 3200\n\t\tdiffuseColor.a = opacity;\n\t#endif\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <logdepthbuf_fragment>\n\t#if DEPTH_PACKING == 3200\n\t\tgl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );\n\t#elif DEPTH_PACKING == 3201\n\t\tgl_FragColor = packDepthToRGBA( gl_FragCoord.z );\n\t#endif\n}\n"; 9634 9635 var depth_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n}\n"; 9636 9637 var distanceRGBA_frag = "#define DISTANCE\nuniform vec3 referencePosition;\nuniform float nearDistance;\nuniform float farDistance;\nvarying vec3 vWorldPosition;\n#include <common>\n#include <packing>\n#include <uv_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main () {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include <map_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\tfloat dist = length( vWorldPosition - referencePosition );\n\tdist = ( dist - nearDistance ) / ( farDistance - nearDistance );\n\tdist = saturate( dist );\n\tgl_FragColor = packDepthToRGBA( dist );\n}\n"; 9638 9639 var distanceRGBA_vert = "#define DISTANCE\nvarying vec3 vWorldPosition;\n#include <common>\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_DISPLACEMENTMAP\n\t\t#include <beginnormal_vertex>\n\t\t#include <morphnormal_vertex>\n\t\t#include <skinnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\tvWorldPosition = worldPosition.xyz;\n}\n"; 9640 9641 var equirect_frag = "uniform sampler2D tEquirect;\nvarying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvec3 direction = normalize( vWorldPosition );\n\tvec2 sampleUV;\n\tsampleUV.y = asin( clamp( direction.y, - 1.0, 1.0 ) ) * RECIPROCAL_PI + 0.5;\n\tsampleUV.x = atan( direction.z, direction.x ) * RECIPROCAL_PI2 + 0.5;\n\tgl_FragColor = texture2D( tEquirect, sampleUV );\n}\n"; 9642 9643 var equirect_vert = "varying vec3 vWorldPosition;\n#include <common>\nvoid main() {\n\tvWorldPosition = transformDirection( position, modelMatrix );\n\t#include <begin_vertex>\n\t#include <project_vertex>\n}\n"; 9644 9645 var linedashed_frag = "uniform vec3 diffuse;\nuniform float opacity;\nuniform float dashSize;\nuniform float totalSize;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <color_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n"; 9646 9647 var linedashed_vert = "uniform float scale;\nattribute float lineDistance;\nvarying float vLineDistance;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\tvLineDistance = scale * lineDistance;\n\tvec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );\n\tgl_Position = projectionMatrix * mvPosition;\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <fog_vertex>\n}\n"; 9648 9649 var meshbasic_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\t#ifdef USE_LIGHTMAP\n\t\treflectedLight.indirectDiffuse += texture2D( lightMap, vUv2 ).xyz * lightMapIntensity;\n\t#else\n\t\treflectedLight.indirectDiffuse += vec3( 1.0 );\n\t#endif\n\t#include <aomap_fragment>\n\treflectedLight.indirectDiffuse *= diffuseColor.rgb;\n\tvec3 outgoingLight = reflectedLight.indirectDiffuse;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n"; 9650 9651 var meshbasic_vert = "#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <skinbase_vertex>\n\t#ifdef USE_ENVMAP\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <worldpos_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <envmap_vertex>\n\t#include <fog_vertex>\n}\n"; 9652 9653 var meshlambert_frag = "uniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float opacity;\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <fog_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <emissivemap_fragment>\n\treflectedLight.indirectDiffuse = getAmbientLightIrradiance( ambientLightColor );\n\t#include <lightmap_fragment>\n\treflectedLight.indirectDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb );\n\t#ifdef DOUBLE_SIDED\n\t\treflectedLight.directDiffuse = ( gl_FrontFacing ) ? vLightFront : vLightBack;\n\t#else\n\t\treflectedLight.directDiffuse = vLightFront;\n\t#endif\n\treflectedLight.directDiffuse *= BRDF_Diffuse_Lambert( diffuseColor.rgb ) * getShadowMask();\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n"; 9654 9655 var meshlambert_vert = "#define LAMBERT\nvarying vec3 vLightFront;\n#ifdef DOUBLE_SIDED\n\tvarying vec3 vLightBack;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <envmap_pars_vertex>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <lights_lambert_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n"; 9656 9657 var meshphong_frag = "#define PHONG\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform vec3 specular;\nuniform float shininess;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <gradientmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <lights_phong_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <specularmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <specularmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_phong_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\t#include <envmap_fragment>\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n"; 9658 9659 var meshphong_vert = "#define PHONG\nvarying vec3 vView
9659Position;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <envmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <envmap_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n"; 9660 9661 var meshphysical_frag = "#define PHYSICAL\nuniform vec3 diffuse;\nuniform vec3 emissive;\nuniform float roughness;\nuniform float metalness;\nuniform float opacity;\n#ifndef STANDARD\n\tuniform float clearCoat;\n\tuniform float clearCoatRoughness;\n#endif\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <packing>\n#include <dithering_pars_fragment>\n#include <color_pars_fragment>\n#include <uv_pars_fragment>\n#include <uv2_pars_fragment>\n#include <map_pars_fragment>\n#include <alphamap_pars_fragment>\n#include <aomap_pars_fragment>\n#include <lightmap_pars_fragment>\n#include <emissivemap_pars_fragment>\n#include <envmap_pars_fragment>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <cube_uv_reflection_fragment>\n#include <lights_pars_begin>\n#include <lights_pars_maps>\n#include <lights_physical_pars_fragment>\n#include <shadowmap_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <roughnessmap_pars_fragment>\n#include <metalnessmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\tReflectedLight reflectedLight = ReflectedLight( vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ), vec3( 0.0 ) );\n\tvec3 totalEmissiveRadiance = emissive;\n\t#include <logdepthbuf_fragment>\n\t#include <map_fragment>\n\t#include <color_fragment>\n\t#include <alphamap_fragment>\n\t#include <alphatest_fragment>\n\t#include <roughnessmap_fragment>\n\t#include <metalnessmap_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\t#include <emissivemap_fragment>\n\t#include <lights_physical_fragment>\n\t#include <lights_fragment_begin>\n\t#include <lights_fragment_maps>\n\t#include <lights_fragment_end>\n\t#include <aomap_fragment>\n\tvec3 outgoingLight = reflectedLight.directDiffuse + reflectedLight.indirectDiffuse + reflectedLight.directSpecular + reflectedLight.indirectSpecular + totalEmissiveRadiance;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n\t#include <premultiplied_alpha_fragment>\n\t#include <dithering_fragment>\n}\n"; 9662 9663 var meshphysical_vert = "#define PHYSICAL\nvarying vec3 vViewPosition;\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <common>\n#include <uv_pars_vertex>\n#include <uv2_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <shadowmap_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <uv2_vertex>\n\t#include <color_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\tvViewPosition = - mvPosition.xyz;\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n"; 9664 9665 var normal_frag = "#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <packing>\n#include <uv_pars_fragment>\n#include <bumpmap_pars_fragment>\n#include <normalmap_pars_fragment>\n#include <logdepthbuf_pars_fragment>\nvoid main() {\n\t#include <logdepthbuf_fragment>\n\t#include <normal_fragment_begin>\n\t#include <normal_fragment_maps>\n\tgl_FragColor = vec4( packNormalToRGB( normal ), opacity );\n}\n"; 9666 9667 var normal_vert = "#define NORMAL\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvarying vec3 vViewPosition;\n#endif\n#ifndef FLAT_SHADED\n\tvarying vec3 vNormal;\n#endif\n#include <uv_pars_vertex>\n#include <displacementmap_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <skinning_pars_vertex>\n#include <logdepthbuf_pars_vertex>\nvoid main() {\n\t#include <uv_vertex>\n\t#include <beginnormal_vertex>\n\t#include <morphnormal_vertex>\n\t#include <skinbase_vertex>\n\t#include <skinnormal_vertex>\n\t#include <defaultnormal_vertex>\n#ifndef FLAT_SHADED\n\tvNormal = normalize( transformedNormal );\n#endif\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <skinning_vertex>\n\t#include <displacementmap_vertex>\n\t#include <project_vertex>\n\t#include <logdepthbuf_vertex>\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}\n"; 9668 9669 var points_frag = "uniform vec3 diffuse;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <color_pars_fragment>\n#include <map_particle_pars_fragment>\n#include <fog_pars_fragment>\n#include <logdepthbuf_pars_fragment>\n#include <clipping_planes_pars_fragment>\nvoid main() {\n\t#include <clipping_planes_fragment>\n\tvec3 outgoingLight = vec3( 0.0 );\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include <logdepthbuf_fragment>\n\t#include <map_particle_fragment>\n\t#include <color_fragment>\n\t#include <alphatest_fragment>\n\toutgoingLight = diffuseColor.rgb;\n\tgl_FragColor = vec4( outgoingLight, diffuseColor.a );\n\t#include <premultiplied_alpha_fragment>\n\t#include <tonemapping_fragment>\n\t#include <encodings_fragment>\n\t#include <fog_fragment>\n}\n"; 9670 9671 var points_vert = "uniform float size;\nuniform float scale;\n#include <common>\n#include <color_pars_vertex>\n#include <fog_pars_vertex>\n#include <morphtarget_pars_vertex>\n#include <logdepthbuf_pars_vertex>\n#include <clipping_planes_pars_vertex>\nvoid main() {\n\t#include <color_vertex>\n\t#include <begin_vertex>\n\t#include <morphtarget_vertex>\n\t#include <project_vertex>\n\t#ifdef USE_SIZEATTENUATION\n\t\tgl_PointSize = size * ( scale / - mvPosition.z );\n\t#else\n\t\tgl_PointSize = size;\n\t#endif\n\t#include <logdepthbuf_vertex>\n\t#include <clipping_planes_vertex>\n\t#include <worldpos_vertex>\n\t#include <fog_vertex>\n}\n"; 9672 9673 var shadow_frag = "uniform vec3 color;\nuniform float opacity;\n#include <common>\n#include <packing>\n#include <fog_pars_fragment>\n#include <bsdfs>\n#include <lights_pars_begin>\n#include <shadowmap_pars_fragment>\n#include <shadowmask_pars_fragment>\nvoid main() {\n\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include <fog_fragment>\n}\n"; 9674 9675 var shadow_vert = "#include <fog_pars_vertex>\n#include <shadowmap_pars_vertex>\nvoid main() {\n\t#include <begin_vertex>\n\t#include <project_vertex>\n\t#include <worldpos_vertex>\n\t#include <shadowmap_vertex>\n\t#include <fog_vertex>\n}\n"; 9676 9677 var ShaderChunk = { 9678 alphamap_fragment: alphamap_fragment, 9679 alphamap_pars_fragment: alphamap_pars_fragment, 9680 alphatest_fragment: alphatest_fragment, 9681 aomap_fragment: aomap_fragment, 9682 aomap_pars_fragment: aomap_pars_fragment, 9683 begin_vertex: begin_vertex, 9684 beginnormal_vertex: beginnormal_vertex, 9685 bsdfs: bsdfs, 9686 bumpmap_pars_fragment: bumpmap_pars_fragment, 9687 clipping_planes_fragment: clipping_planes_fragment, 9688 clipping_planes_pars_fragment: clipping_planes_pars_fragment, 9689 clipping_planes_pars_vertex: clipping_planes_pars_vertex, 9690 clipping_planes_vertex: clipping_planes_vertex, 9691 color_fragment: color_fragment, 9692 color_pars_fragment: color_pars_fragment, 9693 color_pars_vertex: color_pars_vertex, 9694 color_vertex: color_vertex, 9695 common: common, 9696 cube_uv_reflection_fragment: cube_uv_reflection_fragment, 9697 defaultnormal_vertex: defaultnormal_vertex, 9698 displacementmap_pars_vertex: displacementmap_pars_vertex, 9699 displacementmap_vertex: displacementmap_vertex, 9700 emissivemap_fragment: emissivemap_fragment, 9701 emissivemap_pars_fragment: emissivemap_pars_fragment, 9702 encodings_fragment: encodings_fragment, 9703 encodings_pars_fragment: encodings_pars_fragment, 9704 envmap_fragment: envmap_fragment, 9705 envmap_pars_fragment: envmap_pars_fragment, 9706 envmap_pars_vertex: envmap_pars_vertex, 9707 envmap_vertex: envmap_vertex, 9708 fog_vertex: fog_vertex, 9709 fog_pars_vertex: fog_pars_vertex, 9710 fog_fragment: fog_fragment, 9711 fog_pars_fragment: fog_pars_fragment, 9712 gradientmap_pars_fragment: gradientmap_pars_fragment, 9713 lightmap_fragment: lightmap_fragment, 9714 lightmap_pars_fragment: lightmap_pars_fragment, 9715 lights_lambert_vertex: lights_lambert_vertex, 9716 lights_pars_begin: lights_pars_begin, 9717 lights_pars_maps: lights_pars_maps, 9718 lights_phong_fragment: lights_phong_fragment, 9719 lights_phong_pars_fragment: lights_phong_pars_fragment, 9720 lights_physical_fragment: lights_physical_fragment, 9721 lights_physical_pars_fragment: lights_physical_pars_fragment, 9722 lights_fragment_begin: lights_fragment_begin, 9723 lights_fragment_maps: lights_fragment_maps, 9724 lights_fragment_end: lights_fragment_end, 9725 logdepthbuf_fragment: logdepthbuf_fragment, 9726 logdepthbuf_pars_fragment: logdepthbuf_pars_fragment, 9727 logdepthbuf_pars_vertex: logdepthbuf_pars_vertex, 9728 logdepthbuf_vertex: logdepthbuf_vertex, 9729 map_fragment: map_fragment, 9730 map_pars_fragment: map_pars_fragment, 9731 map_particle_fragment: map_particle_fragment, 9732 map_particle_pars_fragment: map_particle_pars_fragment, 9733 metalnessmap_fragment: metalnessmap_fragment, 9734 metalnessmap_pars_fragment: metalnessmap_pars_fragment, 9735 morphnormal_vertex: morphnormal_vertex, 9736 morphtarget_pars_vertex: morphtarget_pars_vertex, 9737 morphtarget_vertex: morphtarget_vertex, 9738 normal_fragment_begin: normal_fragment_begin, 9739 normal_fragment_maps: normal_fragment_maps, 9740 normalmap_pars_fragment: normalmap_pars_fragment, 9741 packing: packing, 9742 premultiplied_alpha_fragment: premultiplied_alpha_fragment, 9743 project_vertex: project_vertex, 9744 dithering_fragment: dithering_fragment, 9745 dithering_pars_fragment: dithering_pars_fragment, 9746 roughnessmap_fragment: roughnessmap_fragment, 9747 roughnessmap_pars_fragment: roughnessmap_pars_fragment, 9748 shadowmap_pars_fragment: shadowmap_pars_fragment, 9749 shadowmap_pars_vertex: shadowmap_pars_vertex, 9750 shadowmap_vertex: shadowmap_vertex, 9751 shadowmask_pars_fragment: shadowmask_pars_fragment, 9752 skinbase_vertex: skinbase_vertex, 9753 skinning_pars_vertex: skinning_pars_vertex, 9754 skinning_vertex: skinning_vertex, 9755 skinnormal_vertex: skinnormal_vertex, 9756 specularmap_fragment: specularmap_fragment, 9757 specularmap_pars_fragment: specularmap_pars_fragment, 9758 tonemapping_fragment: tonemapping_fragment, 9759 tonemapping_pars_fragment: tonemapping_pars_fragment, 9760 uv_pars_fragment: uv_pars_fragment, 9761 uv_pars_vertex: uv_pars_vertex, 9762 uv_vertex: uv_vertex, 9763 uv2_pars_fragment: uv2_pars_fragment, 9764 uv2_pars_vertex: uv2_pars_vertex, 9765 uv2_vertex: uv2_vertex, 9766 worldpos_vertex: worldpos_vertex, 9767 9768 cube_frag: cube_frag, 9769 cube_vert: cube_vert, 9770 depth_frag: depth_frag, 9771 depth_vert: depth_vert, 9772 distanceRGBA_frag: distanceRGBA_frag, 9773 distanceRGBA_vert: distanceRGBA_vert, 9774 equirect_frag: equirect_frag, 9775 equirect_vert: equirect_vert, 9776 linedashed_frag: linedashed_frag, 9777 linedashed_vert: linedashed_vert, 9778 meshbasic_frag: meshbasic_frag, 9779 meshbasic_vert: meshbasic_vert, 9780 meshlambert_frag: meshlambert_frag, 9781 meshlambert_vert: meshlambert_vert, 9782 meshphong_frag: meshphong_frag, 9783 meshphong_vert: meshphong_vert, 9784 meshphysical_frag: meshphysical_frag, 9785 meshphysical_vert: meshphysical_vert, 9786 normal_frag: normal_frag, 9787 normal_vert: normal_vert, 9788 points_frag: points_frag, 9789 points_vert: points_vert, 9790 shadow_frag: shadow_frag, 9791 shadow_vert: shadow_vert 9792 }; 9793 9794 /** 9795 * Uniform Utilities 9796 */ 9797 9798 var UniformsUtils = { 9799 9800 merge: function ( uniforms ) { 9801 9802 var merged = {}; 9803 9804 for ( var u = 0; u < uniforms.length; u ++ ) { 9805 9806 var tmp = this.clone( uniforms[ u ] ); 9807 9808 for ( var p in tmp ) { 9809 9810 merged[ p ] = tmp[ p ]; 9811 9812 } 9813 9814 } 9815 9816 return merged; 9817 9818 }, 9819
vendor: 16,770 bytes, lines 9820-10585
9820 clone: function ( uniforms_src ) { 9821 9822 var uniforms_dst = {}; 9823 9824 for ( var u in uniforms_src ) { 9825 9826 uniforms_dst[ u ] = {}; 9827 9828 for ( var p in uniforms_src[ u ] ) { 9829 9830 var parameter_src = uniforms_src[ u ][ p ]; 9831 9832 if ( parameter_src && ( parameter_src.isColor || 9833 parameter_src.isMatrix3 || parameter_src.isMatrix4 || 9834 parameter_src.isVector2 || parameter_src.isVector3 || parameter_src.isVector4 || 9835 parameter_src.isTexture ) ) { 9836 9837 uniforms_dst[ u ][ p ] = parameter_src.clone(); 9838 9839 } else if ( Array.isArray( parameter_src ) ) { 9840 9841 uniforms_dst[ u ][ p ] = parameter_src.slice(); 9842 9843 } else { 9844 9845 uniforms_dst[ u ][ p ] = parameter_src; 9846 9847 } 9848 9849 } 9850 9851 } 9852 9853 return uniforms_dst; 9854 9855 } 9856 9857 }; 9858 9859 /** 9860 * @author mrdoob / http://mrdoob.com/ 9861 */ 9862 9863 var ColorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, 9864 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, 9865 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, 9866 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, 9867 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, 9868 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, 9869 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, 9870 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, 9871 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, 9872 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, 9873 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, 9874 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, 9875 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, 9876 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, 9877 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, 9878 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, 9879 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, 9880 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, 9881 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, 9882 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, 9883 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, 9884 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, 9885 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, 9886 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; 9887 9888 function Color( r, g, b ) { 9889 9890 if ( g === undefined && b === undefined ) { 9891 9892 // r is THREE.Color, hex or string 9893 return this.set( r ); 9894 9895 } 9896 9897 return this.setRGB( r, g, b ); 9898 9899 } 9900 9901 Object.assign( Color.prototype, { 9902 9903 isColor: true, 9904 9905 r: 1, g: 1, b: 1, 9906 9907 set: function ( value ) { 9908 9909 if ( value && value.isColor ) { 9910 9911 this.copy( value ); 9912 9913 } else if ( typeof value === 'number' ) { 9914 9915 this.setHex( value ); 9916 9917 } else if ( typeof value === 'string' ) { 9918 9919 this.setStyle( value ); 9920 9921 } 9922 9923 return this; 9924 9925 }, 9926 9927 setScalar: function ( scalar ) { 9928 9929 this.r = scalar; 9930 this.g = scalar; 9931 this.b = scalar; 9932 9933 return this; 9934 9935 }, 9936 9937 setHex: function ( hex ) { 9938 9939 hex = Math.floor( hex ); 9940 9941 this.r = ( hex >> 16 & 255 ) / 255; 9942 this.g = ( hex >> 8 & 255 ) / 255; 9943 this.b = ( hex & 255 ) / 255; 9944 9945 return this; 9946 9947 }, 9948 9949 setRGB: function ( r, g, b ) { 9950 9951 this.r = r; 9952 this.g = g; 9953 this.b = b; 9954 9955 return this; 9956 9957 }, 9958 9959 setHSL: function () { 9960 9961 function hue2rgb( p, q, t ) { 9962 9963 if ( t < 0 ) t += 1; 9964 if ( t > 1 ) t -= 1; 9965 if ( t < 1 / 6 ) return p + ( q - p ) * 6 * t; 9966 if ( t < 1 / 2 ) return q; 9967 if ( t < 2 / 3 ) return p + ( q - p ) * 6 * ( 2 / 3 - t ); 9968 return p; 9969 9970 } 9971 9972 return function setHSL( h, s, l ) { 9973 9974 // h,s,l ranges are in 0.0 - 1.0 9975 h = _Math.euclideanModulo( h, 1 ); 9976 s = _Math.clamp( s, 0, 1 ); 9977 l = _Math.clamp( l, 0, 1 ); 9978 9979 if ( s === 0 ) { 9980 9981 this.r = this.g = this.b = l; 9982 9983 } else { 9984 9985 var p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); 9986 var q = ( 2 * l ) - p; 9987 9988 this.r = hue2rgb( q, p, h + 1 / 3 ); 9989 this.g = hue2rgb( q, p, h ); 9990 this.b = hue2rgb( q, p, h - 1 / 3 ); 9991 9992 } 9993 9994 return this; 9995 9996 }; 9997 9998 }(), 9999 10000 setStyle: function ( style ) { 10001 10002 function handleAlpha( string ) { 10003 10004 if ( string === undefined ) return; 10005 10006 if ( parseFloat( string ) < 1 ) { 10007 10008 console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); 10009 10010 } 10011 10012 } 10013 10014 10015 var m; 10016 10017 if ( m = /^((?:rgb|hsl)a?)\(\s*([^\)]*)\)/.exec( style ) ) { 10018 10019 // rgb / hsl 10020 10021 var color; 10022 var name = m[ 1 ]; 10023 var components = m[ 2 ]; 10024 10025 switch ( name ) { 10026 10027 case 'rgb': 10028 case 'rgba': 10029 10030 if ( color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { 10031 10032 // rgb(255,0,0) rgba(255,0,0,0.5) 10033 this.r = Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255; 10034 this.g = Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255; 10035 this.b = Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255; 10036 10037 handleAlpha( color[ 5 ] ); 10038 10039 return this; 10040 10041 } 10042 10043 if ( color = /^(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { 10044 10045 // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) 10046 this.r = Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100; 10047 this.g = Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100; 10048 this.b = Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100; 10049 10050 handleAlpha( color[ 5 ] ); 10051 10052 return this; 10053 10054 } 10055 10056 break; 10057 10058 case 'hsl': 10059 case 'hsla': 10060 10061 if ( color = /^([0-9]*\.?[0-9]+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(,\s*([0-9]*\.?[0-9]+)\s*)?$/.exec( components ) ) { 10062 10063 // hsl(120,50%,50%) hsla(120,50%,50%,0.5) 10064 var h = parseFloat( color[ 1 ] ) / 360; 10065 var s = parseInt( color[ 2 ], 10 ) / 100; 10066 var l = parseInt( color[ 3 ], 10 ) / 100; 10067 10068 handleAlpha( color[ 5 ] ); 10069 10070 return this.setHSL( h, s, l ); 10071 10072 } 10073 10074 break; 10075 10076 } 10077 10078 } else if ( m = /^\#([A-Fa-f0-9]+)$/.exec( style ) ) { 10079 10080 // hex color 10081 10082 var hex = m[ 1 ]; 10083 var size = hex.length; 10084 10085 if ( size === 3 ) { 10086 10087 // #ff0 10088 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 0 ), 16 ) / 255; 10089 this.g = parseInt( hex.charAt( 1 ) + hex.charAt( 1 ), 16 ) / 255; 10090 this.b = parseInt( hex.charAt( 2 ) + hex.charAt( 2 ), 16 ) / 255; 10091 10092 return this; 10093 10094 } else if ( size === 6 ) { 10095 10096 // #ff0000 10097 this.r = parseInt( hex.charAt( 0 ) + hex.charAt( 1 ), 16 ) / 255; 10098 this.g = parseInt( hex.charAt( 2 ) + hex.charAt( 3 ), 16 ) / 255; 10099 this.b = parseInt( hex.charAt( 4 ) + hex.charAt( 5 ), 16 ) / 255; 10100 10101 return this; 10102 10103 } 10104 10105 } 10106 10107 if ( style && style.length > 0 ) { 10108 10109 // color keywords 10110 var hex = ColorKeywords[ style ]; 10111 10112 if ( hex !== undefined ) { 10113 10114 // red 10115 this.setHex( hex ); 10116 10117 } else { 10118 10119 // unknown color 10120 console.warn( 'THREE.Color: Unknown color ' + style ); 10121 10122 } 10123 10124 } 10125 10126 return this; 10127 10128 }, 10129 10130 clone: function () { 10131 10132 return new this.constructor( this.r, this.g, this.b ); 10133 10134 }, 10135 10136 copy: function ( color ) { 10137 10138 this.r = color.r; 10139 this.g = color.g; 10140 this.b = color.b; 10141 10142 return this; 10143 10144 }, 10145 10146 copyGammaToLinear: function ( color, gammaFactor ) { 10147 10148 if ( gammaFactor === undefined ) gammaFactor = 2.0; 10149 10150 this.r = Math.pow( color.r, gammaFactor ); 10151 this.g = Math.pow( color.g, gammaFactor ); 10152 this.b = Math.pow( color.b, gammaFactor ); 10153 10154 return this; 10155 10156 }, 10157 10158 copyLinearToGamma: function ( color, gammaFactor ) { 10159 10160 if ( gammaFactor === undefined ) gammaFactor = 2.0; 10161 10162 var safeInverse = ( gammaFactor > 0 ) ? ( 1.0 / gammaFactor ) : 1.0; 10163 10164 this.r = Math.pow( color.r, safeInverse ); 10165 this.g = Math.pow( color.g, safeInverse ); 10166 this.b = Math.pow( color.b, safeInverse ); 10167 10168 return this; 10169 10170 }, 10171 10172 convertGammaToLinear: function ( gammaFactor ) { 10173 10174 this.copyGammaToLinear( this, gammaFactor ); 10175 10176 return this; 10177 10178 }, 10179 10180 convertLinearToGamma: function ( gammaFactor ) { 10181 10182 this.copyLinearToGamma( this, gammaFactor ); 10183 10184 return this; 10185 10186 }, 10187 10188 getHex: function () { 10189 10190 return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0; 10191 10192 }, 10193 10194 getHexString: function () { 10195 10196 return ( '000000' + this.getHex().toString( 16 ) ).slice( - 6 ); 10197 10198 }, 10199 10200 getHSL: function ( target ) { 10201 10202 // h,s,l ranges are in 0.0 - 1.0 10203 10204 if ( target === undefined ) { 10205 10206 console.warn( 'THREE.Color: .getHSL() target is now required' ); 10207 target = { h: 0, s: 0, l: 0 }; 10208 10209 } 10210 10211 var r = this.r, g = this.g, b = this.b; 10212 10213 var max = Math.max( r, g, b ); 10214 var min = Math.min( r, g, b ); 10215 10216 var hue, saturation; 10217 var lightness = ( min + max ) / 2.0; 10218 10219 if ( min === max ) { 10220 10221 hue = 0; 10222 saturation = 0; 10223 10224 } else { 10225 10226 var delta = max - min; 10227 10228 saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); 10229 10230 switch ( max ) { 10231 10232 case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; 10233 case g: hue = ( b - r ) / delta + 2; break; 10234 case b: hue = ( r - g ) / delta + 4; break; 10235 10236 } 10237 10238 hue /= 6; 10239 10240 } 10241 10242 target.h = hue; 10243 target.s = saturation; 10244 target.l = lightness; 10245 10246 return target; 10247 10248 }, 10249 10250 getStyle: function () { 10251 10252 return 'rgb(' + ( ( this.r * 255 ) | 0 ) + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')'; 10253 10254 }, 10255 10256 offsetHSL: function () { 10257 10258 var hsl = {}; 10259 10260 return function ( h, s, l ) { 10261 10262 this.getHSL( hsl ); 10263 10264 hsl.h += h; hsl.s += s; hsl.l += l; 10265 10266 this.setHSL( hsl.h, hsl.s, hsl.l ); 10267 10268 return this; 10269 10270 }; 10271 10272 }(), 10273 10274 add: function ( color ) { 10275 10276 this.r += color.r; 10277 this.g += color.g; 10278 this.b += color.b; 10279 10280 return this; 10281 10282 }, 10283 10284 addColors: function ( color1, color2 ) { 10285 10286 this.r = color1.r + color2.r; 10287 this.g = color1.g + color2.g; 10288 this.b = color1.b + color2.b; 10289 10290 return this; 10291 10292 }, 10293 10294 addScalar: function ( s ) { 10295 10296 this.r += s; 10297 this.g += s; 10298 this.b += s; 10299 10300 return this; 10301 10302 }, 10303 10304 sub: function ( color ) { 10305 10306 this.r = Math.max( 0, this.r - color.r ); 10307 this.g = Math.max( 0, this.g - color.g ); 10308 this.b = Math.max( 0, this.b - color.b ); 10309 10310 return this; 10311 10312 }, 10313 10314 multiply: function ( color ) { 10315 10316 this.r *= color.r; 10317 this.g *= color.g; 10318 this.b *= color.b; 10319 10320 return this; 10321 10322 }, 10323 10324 multiplyScalar: function ( s ) { 10325 10326 this.r *= s; 10327 this.g *= s; 10328 this.b *= s; 10329 10330 return this; 10331 10332 }, 10333 10334 lerp: function ( color, alpha ) { 10335 10336 this.r += ( color.r - this.r ) * alpha; 10337 this.g += ( color.g - this.g ) * alpha; 10338 this.b += ( color.b - this.b ) * alpha; 10339 10340 return this; 10341 10342 }, 10343 10344 equals: function ( c ) { 10345 10346 return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); 10347 10348 }, 10349 10350 fromArray: function ( array, offset ) { 10351 10352 if ( offset === undefined ) offset = 0; 10353 10354 this.r = array[ offset ]; 10355 this.g = array[ offset + 1 ]; 10356 this.b = array[ offset + 2 ]; 10357 10358 return this; 10359 10360 }, 10361 10362 toArray: function ( array, offset ) { 10363 10364 if ( array === undefined ) array = []; 10365 if ( offset === undefined ) offset = 0; 10366 10367 array[ offset ] = this.r; 10368 array[ offset + 1 ] = this.g; 10369 array[ offset + 2 ] = this.b; 10370 10371 return array; 10372 10373 }, 10374 10375 toJSON: function () { 10376 10377 return this.getHex(); 10378 10379 } 10380 10381 } ); 10382 10383 /** 10384 * Uniforms library for shared webgl shaders 10385 */ 10386 10387 var UniformsLib = { 10388 10389 common: { 10390 10391 diffuse: { value: new Color( 0xeeeeee ) }, 10392 opacity: { value: 1.0 }, 10393 10394 map: { value: null }, 10395 uvTransform: { value: new Matrix3() }, 10396 10397 alphaMap: { value: null }, 10398 10399 }, 10400 10401 specularmap: { 10402 10403 specularMap: { value: null }, 10404 10405 }, 10406 10407 envmap: { 10408 10409 envMap: { value: null }, 10410 flipEnvMap: { value: - 1 }, 10411 reflectivity: { value: 1.0 }, 10412 refractionRatio: { value: 0.98 }, 10413 maxMipLevel: { value: 0 } 10414 10415 }, 10416 10417 aomap: { 10418 10419 aoMap: { value: null }, 10420 aoMapIntensity: { value: 1 } 10421 10422 }, 10423 10424 lightmap: { 10425 10426 lightMap: { value: null }, 10427 lightMapIntensity: { value: 1 } 10428 10429 }, 10430 10431 emissivemap: { 10432 10433 emissiveMap: { value: null } 10434 10435 }, 10436 10437 bumpmap: { 10438 10439 bumpMap: { value: null }, 10440 bumpScale: { value: 1 } 10441 10442 }, 10443 10444 normalmap: { 10445 10446 normalMap: { value: null }, 10447 normalScale: { value: new Vector2( 1, 1 ) } 10448 10449 }, 10450 10451 displacementmap: { 10452 10453 displacementMap: { value: null }, 10454 displacementScale: { value: 1 }, 10455 displacementBias: { value: 0 } 10456 10457 }, 10458 10459 roughnessmap: { 10460 10461 roughnessMap: { value: null } 10462 10463 }, 10464 10465 metalnessmap: { 10466 10467 metalnessMap: { value: null } 10468 10469 }, 10470 10471 gradientmap: { 10472 10473 gradientMap: { value: null } 10474 10475 }, 10476 10477 fog: { 10478 10479 fogDensity: { value: 0.00025 }, 10480 fogNear: { value: 1 }, 10481 fogFar: { value: 2000 }, 10482 fogColor: { value: new Color( 0xffffff ) } 10483 10484 }, 10485 10486 lights: { 10487 10488 ambientLightColor: { value: [] }, 10489 10490 directionalLights: { value: [], properties: { 10491 direction: {}, 10492 color: {}, 10493 10494 shadow: {}, 10495 shadowBias: {}, 10496 shadowRadius: {}, 10497 shadowMapSize: {} 10498 } }, 10499 10500 directionalShadowMap: { value: [] }, 10501 directionalShadowMatrix: { value: [] }, 10502 10503 spotLights: { value: [], properties: { 10504 color: {}, 10505 position: {}, 10506 direction: {}, 10507 distance: {}, 10508 coneCos: {}, 10509 penumbraCos: {}, 10510 decay: {}, 10511 10512 shadow: {}, 10513 shadowBias: {}, 10514 shadowRadius: {}, 10515 shadowMapSize: {} 10516 } }, 10517 10518 spotShadowMap: { value: [] }, 10519 spotShadowMatrix: { value: [] }, 10520 10521 pointLights: { value: [], properties: { 10522 color: {}, 10523 position: {}, 10524 decay: {}, 10525 distance: {}, 10526 10527 shadow: {}, 10528 shadowBias: {}, 10529 shadowRadius: {}, 10530 shadowMapSize: {}, 10531 shadowCameraNear: {}, 10532 shadowCameraFar: {} 10533 } }, 10534 10535 pointShadowMap: { value: [] }, 10536 pointShadowMatrix: { value: [] }, 10537 10538 hemisphereLights: { value: [], properties: { 10539 direction: {}, 10540 skyColor: {}, 10541 groundColor: {} 10542 } }, 10543 10544 // TODO (abelnation): RectAreaLight BRDF data needs to be moved from example to main src 10545 rectAreaLights: { value: [], properties: { 10546 color: {}, 10547 position: {}, 10548 width: {}, 10549 height: {} 10550 } } 10551 10552 }, 10553 10554 points: { 10555 10556 diffuse: { value: new Color( 0xeeeeee ) }, 10557 opacity: { value: 1.0 }, 10558 size: { value: 1.0 }, 10559 scale: { value: 1.0 }, 10560 map: { value: null }, 10561 uvTransform: { value: new Matrix3() } 10562 10563 } 10564 10565 }; 10566 10567 /** 10568 * @author alteredq / http://alteredqualia.com/ 10569 * @author mrdoob / http://mrdoob.com/ 10570 * @author mikael emtinger / http://gomo.se/ 10571 */ 10572 10573 var ShaderLib = { 10574 10575 basic: { 10576 10577 uniforms: UniformsUtils.merge( [ 10578 UniformsLib.common, 10579 UniformsLib.specularmap, 10580 UniformsLib.envmap, 10581 UniformsLib.aomap, 10582 UniformsLib.lightmap, 10583 UniformsLib.fog 10584 ] ), 10585
10586 vertexShader: ShaderChunk.meshbasic_vert, 10587 fragmentShader: ShaderChunk.meshbasic_frag 10588 10589 }, 10590 10591 lambert: { 10592 10593 uniforms: UniformsUtils.merge( [ 10594 UniformsLib.common, 10595 UniformsLib.specularmap, 10596 UniformsLib.envmap, 10597 UniformsLib.aomap, 10598 UniformsLib.lightmap, 10599 UniformsLib.emissivemap, 10600 UniformsLib.fog, 10601 UniformsLib.lights, 10602 { 10603 emissive: { value: new Color( 0x000000 ) } 10604 } 10605 ] ), 10606 10607 vertexShader: ShaderChunk.meshlambert_vert, 10608 fragmentShader: ShaderChunk.meshlambert_frag 10609 10610 }, 10611 10612 phong: { 10613 10614 uniforms: UniformsUtils.merge( [ 10615 UniformsLib.common, 10616 UniformsLib.specularmap, 10617 UniformsLib.envmap, 10618 UniformsLib.aomap, 10619 UniformsLib.lightmap, 10620 UniformsLib.emissivemap, 10621 UniformsLib.bumpmap, 10622 UniformsLib.normalmap, 10623 UniformsLib.displacementmap, 10624 UniformsLib.gradientmap, 10625 UniformsLib.fog, 10626 UniformsLib.lights, 10627 { 10628 emissive: { value: new Color( 0x000000 ) }, 10629 specular: { value: new Color( 0x111111 ) }, 10630 shininess: { value: 30 } 10631 } 10632 ] ), 10633 10634 vertexShader: ShaderChunk.meshphong_vert, 10635 fragmentShader: ShaderChunk.meshphong_frag 10636 10637 }, 10638 10639 standard: { 10640 10641 uniforms: UniformsUtils.merge( [ 10642 UniformsLib.common, 10643 UniformsLib.envmap, 10644 UniformsLib.aomap, 10645 UniformsLib.lightmap, 10646 UniformsLib.emissivemap, 10647 UniformsLib.bumpmap, 10648 UniformsLib.normalmap, 10649 UniformsLib.displacementmap, 10650 UniformsLib.roughnessmap, 10651 UniformsLib.metalnessmap, 10652 UniformsLib.fog, 10653 UniformsLib.lights, 10654 { 10655 emissive: { value: new Color( 0x000000 ) }, 10656 roughness: { value: 0.5 }, 10657 metalness: { value: 0.5 }, 10658 envMapIntensity: { value: 1 } // temporary 10659 } 10660 ] ), 10661 10662 vertexShader: ShaderChunk.meshphysical_vert, 10663 fragmentShader: ShaderChunk.meshphysical_frag 10664 10665 }, 10666 10667 points: { 10668 10669 uniforms: UniformsUtils.merge( [ 10670 UniformsLib.points, 10671 UniformsLib.fog 10672 ] ), 10673
vendor: 2,046 bytes, lines 10674-10780
10674 vertexShader: ShaderChunk.points_vert, 10675 fragmentShader: ShaderChunk.points_frag 10676 10677 }, 10678 10679 dashed: { 10680 10681 uniforms: UniformsUtils.merge( [ 10682 UniformsLib.common, 10683 UniformsLib.fog, 10684 { 10685 scale: { value: 1 }, 10686 dashSize: { value: 1 }, 10687 totalSize: { value: 2 } 10688 } 10689 ] ), 10690 10691 vertexShader: ShaderChunk.linedashed_vert, 10692 fragmentShader: ShaderChunk.linedashed_frag 10693 10694 }, 10695 10696 depth: { 10697 10698 uniforms: UniformsUtils.merge( [ 10699 UniformsLib.common, 10700 UniformsLib.displacementmap 10701 ] ), 10702 10703 vertexShader: ShaderChunk.depth_vert, 10704 fragmentShader: ShaderChunk.depth_frag 10705 10706 }, 10707 10708 normal: { 10709 10710 uniforms: UniformsUtils.merge( [ 10711 UniformsLib.common, 10712 UniformsLib.bumpmap, 10713 UniformsLib.normalmap, 10714 UniformsLib.displacementmap, 10715 { 10716 opacity: { value: 1.0 } 10717 } 10718 ] ), 10719 10720 vertexShader: ShaderChunk.normal_vert, 10721 fragmentShader: ShaderChunk.normal_frag 10722 10723 }, 10724 10725 /* ------------------------------------------------------------------------- 10726 // Cube map shader 10727 ------------------------------------------------------------------------- */ 10728 10729 cube: { 10730 10731 uniforms: { 10732 tCube: { value: null }, 10733 tFlip: { value: - 1 }, 10734 opacity: { value: 1.0 } 10735 }, 10736 10737 vertexShader: ShaderChunk.cube_vert, 10738 fragmentShader: ShaderChunk.cube_frag 10739 10740 }, 10741 10742 equirect: { 10743 10744 uniforms: { 10745 tEquirect: { value: null }, 10746 }, 10747 10748 vertexShader: ShaderChunk.equirect_vert, 10749 fragmentShader: ShaderChunk.equirect_frag 10750 10751 }, 10752 10753 distanceRGBA: { 10754 10755 uniforms: UniformsUtils.merge( [ 10756 UniformsLib.common, 10757 UniformsLib.displacementmap, 10758 { 10759 referencePosition: { value: new Vector3() }, 10760 nearDistance: { value: 1 }, 10761 farDistance: { value: 1000 } 10762 } 10763 ] ), 10764 10765 vertexShader: ShaderChunk.distanceRGBA_vert, 10766 fragmentShader: ShaderChunk.distanceRGBA_frag 10767 10768 }, 10769 10770 shadow: { 10771 10772 uniforms: UniformsUtils.merge( [ 10773 UniformsLib.lights, 10774 UniformsLib.fog, 10775 { 10776 color: { value: new Color( 0x00000 ) }, 10777 opacity: { value: 1.0 } 10778 }, 10779 ] ), 10780
vendor: 15,977 bytes, lines 10781-11681
10781 vertexShader: ShaderChunk.shadow_vert, 10782 fragmentShader: ShaderChunk.shadow_frag 10783 10784 } 10785 10786 }; 10787 10788 ShaderLib.physical = { 10789 10790 uniforms: UniformsUtils.merge( [ 10791 ShaderLib.standard.uniforms, 10792 { 10793 clearCoat: { value: 0 }, 10794 clearCoatRoughness: { value: 0 } 10795 } 10796 ] ), 10797 10798 vertexShader: ShaderChunk.meshphysical_vert, 10799 fragmentShader: ShaderChunk.meshphysical_frag 10800 10801 }; 10802 10803 /** 10804 * @author mrdoob / http://mrdoob.com/ 10805 */ 10806 10807 function WebGLAnimation() { 10808 10809 var context = null; 10810 var isAnimating = false; 10811 var animationLoop = null; 10812 10813 function onAnimationFrame( time, frame ) { 10814 10815 if ( isAnimating === false ) return; 10816 10817 animationLoop( time, frame ); 10818 10819 context.requestAnimationFrame( onAnimationFrame ); 10820 10821 } 10822 10823 return { 10824 10825 start: function () { 10826 10827 if ( isAnimating === true ) return; 10828 if ( animationLoop === null ) return; 10829 10830 context.requestAnimationFrame( onAnimationFrame ); 10831 10832 isAnimating = true; 10833 10834 }, 10835 10836 stop: function () { 10837 10838 isAnimating = false; 10839 10840 }, 10841 10842 setAnimationLoop: function ( callback ) { 10843 10844 animationLoop = callback; 10845 10846 }, 10847 10848 setContext: function ( value ) { 10849 10850 context = value; 10851 10852 } 10853 10854 }; 10855 10856 } 10857 10858 /** 10859 * @author mrdoob / http://mrdoob.com/ 10860 */ 10861 10862 function WebGLAttributes( gl ) { 10863 10864 var buffers = new WeakMap(); 10865 10866 function createBuffer( attribute, bufferType ) { 10867 10868 var array = attribute.array; 10869 var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW; 10870 10871 var buffer = gl.createBuffer(); 10872 10873 gl.bindBuffer( bufferType, buffer ); 10874 gl.bufferData( bufferType, array, usage ); 10875 10876 attribute.onUploadCallback(); 10877 10878 var type = gl.FLOAT; 10879 10880 if ( array instanceof Float32Array ) { 10881 10882 type = gl.FLOAT; 10883 10884 } else if ( array instanceof Float64Array ) { 10885 10886 console.warn( 'THREE.WebGLAttributes: Unsupported data buffer format: Float64Array.' ); 10887 10888 } else if ( array instanceof Uint16Array ) { 10889 10890 type = gl.UNSIGNED_SHORT; 10891 10892 } else if ( array instanceof Int16Array ) { 10893 10894 type = gl.SHORT; 10895 10896 } else if ( array instanceof Uint32Array ) { 10897 10898 type = gl.UNSIGNED_INT; 10899 10900 } else if ( array instanceof Int32Array ) { 10901 10902 type = gl.INT; 10903 10904 } else if ( array instanceof Int8Array ) { 10905 10906 type = gl.BYTE; 10907 10908 } else if ( array instanceof Uint8Array ) { 10909 10910 type = gl.UNSIGNED_BYTE; 10911 10912 } 10913 10914 return { 10915 buffer: buffer, 10916 type: type, 10917 bytesPerElement: array.BYTES_PER_ELEMENT, 10918 version: attribute.version 10919 }; 10920 10921 } 10922 10923 function updateBuffer( buffer, attribute, bufferType ) { 10924 10925 var array = attribute.array; 10926 var updateRange = attribute.updateRange; 10927 10928 gl.bindBuffer( bufferType, buffer ); 10929 10930 if ( attribute.dynamic === false ) { 10931 10932 gl.bufferData( bufferType, array, gl.STATIC_DRAW ); 10933 10934 } else if ( updateRange.count === - 1 ) { 10935 10936 // Not using update ranges 10937 10938 gl.bufferSubData( bufferType, 0, array ); 10939 10940 } else if ( updateRange.count === 0 ) { 10941 10942 console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' ); 10943 10944 } else { 10945 10946 gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, 10947 array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) ); 10948 10949 updateRange.count = - 1; // reset range 10950 10951 } 10952 10953 } 10954 10955 // 10956 10957 function get( attribute ) { 10958 10959 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 10960 10961 return buffers.get( attribute ); 10962 10963 } 10964 10965 function remove( attribute ) { 10966 10967 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 10968 10969 var data = buffers.get( attribute ); 10970 10971 if ( data ) { 10972 10973 gl.deleteBuffer( data.buffer ); 10974 10975 buffers.delete( attribute ); 10976 10977 } 10978 10979 } 10980 10981 function update( attribute, bufferType ) { 10982 10983 if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; 10984 10985 var data = buffers.get( attribute ); 10986 10987 if ( data === undefined ) { 10988 10989 buffers.set( attribute, createBuffer( attribute, bufferType ) ); 10990 10991 } else if ( data.version < attribute.version ) { 10992 10993 updateBuffer( data.buffer, attribute, bufferType ); 10994 10995 data.version = attribute.version; 10996 10997 } 10998 10999 } 11000 11001 return { 11002 11003 get: get, 11004 remove: remove, 11005 update: update 11006 11007 }; 11008 11009 } 11010 11011 /** 11012 * @author mrdoob / http://mrdoob.com/ 11013 * @author WestLangley / http://github.com/WestLangley 11014 * @author bhouston / http://clara.io 11015 */ 11016 11017 function Euler( x, y, z, order ) { 11018 11019 this._x = x || 0; 11020 this._y = y || 0; 11021 this._z = z || 0; 11022 this._order = order || Euler.DefaultOrder; 11023 11024 } 11025 11026 Euler.RotationOrders = [ 'XYZ', 'YZX', 'ZXY', 'XZY', 'YXZ', 'ZYX' ]; 11027 11028 Euler.DefaultOrder = 'XYZ'; 11029 11030 Object.defineProperties( Euler.prototype, { 11031 11032 x: { 11033 11034 get: function () { 11035 11036 return this._x; 11037 11038 }, 11039 11040 set: function ( value ) { 11041 11042 this._x = value; 11043 this.onChangeCallback(); 11044 11045 } 11046 11047 }, 11048 11049 y: { 11050 11051 get: function () { 11052 11053 return this._y; 11054 11055 }, 11056 11057 set: function ( value ) { 11058 11059 this._y = value; 11060 this.onChangeCallback(); 11061 11062 } 11063 11064 }, 11065 11066 z: { 11067 11068 get: function () { 11069 11070 return this._z; 11071 11072 }, 11073 11074 set: function ( value ) { 11075 11076 this._z = value; 11077 this.onChangeCallback(); 11078 11079 } 11080 11081 }, 11082 11083 order: { 11084 11085 get: function () { 11086 11087 return this._order; 11088 11089 }, 11090 11091 set: function ( value ) { 11092 11093 this._order = value; 11094 this.onChangeCallback(); 11095 11096 } 11097 11098 } 11099 11100 } ); 11101 11102 Object.assign( Euler.prototype, { 11103 11104 isEuler: true, 11105 11106 set: function ( x, y, z, order ) { 11107 11108 this._x = x; 11109 this._y = y; 11110 this._z = z; 11111 this._order = order || this._order; 11112 11113 this.onChangeCallback(); 11114 11115 return this; 11116 11117 }, 11118 11119 clone: function () { 11120 11121 return new this.constructor( this._x, this._y, this._z, this._order ); 11122 11123 }, 11124 11125 copy: function ( euler ) { 11126 11127 this._x = euler._x; 11128 this._y = euler._y; 11129 this._z = euler._z; 11130 this._order = euler._order; 11131 11132 this.onChangeCallback(); 11133 11134 return this; 11135 11136 }, 11137 11138 setFromRotationMatrix: function ( m, order, update ) { 11139 11140 var clamp = _Math.clamp; 11141 11142 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 11143 11144 var te = m.elements; 11145 var m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; 11146 var m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; 11147 var m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; 11148 11149 order = order || this._order; 11150 11151 if ( order === 'XYZ' ) { 11152 11153 this._y = Math.asin( clamp( m13, - 1, 1 ) ); 11154 11155 if ( Math.abs( m13 ) < 0.99999 ) { 11156 11157 this._x = Math.atan2( - m23, m33 ); 11158 this._z = Math.atan2( - m12, m11 ); 11159 11160 } else { 11161 11162 this._x = Math.atan2( m32, m22 ); 11163 this._z = 0; 11164 11165 } 11166 11167 } else if ( order === 'YXZ' ) { 11168 11169 this._x = Math.asin( - clamp( m23, - 1, 1 ) ); 11170 11171 if ( Math.abs( m23 ) < 0.99999 ) { 11172 11173 this._y = Math.atan2( m13, m33 ); 11174 this._z = Math.atan2( m21, m22 ); 11175 11176 } else { 11177 11178 this._y = Math.atan2( - m31, m11 ); 11179 this._z = 0; 11180 11181 } 11182 11183 } else if ( order === 'ZXY' ) { 11184 11185 this._x = Math.asin( clamp( m32, - 1, 1 ) ); 11186 11187 if ( Math.abs( m32 ) < 0.99999 ) { 11188 11189 this._y = Math.atan2( - m31, m33 ); 11190 this._z = Math.atan2( - m12, m22 ); 11191 11192 } else { 11193 11194 this._y = 0; 11195 this._z = Math.atan2( m21, m11 ); 11196 11197 } 11198 11199 } else if ( order === 'ZYX' ) { 11200 11201 this._y = Math.asin( - clamp( m31, - 1, 1 ) ); 11202 11203 if ( Math.abs( m31 ) < 0.99999 ) { 11204 11205 this._x = Math.atan2( m32, m33 ); 11206 this._z = Math.atan2( m21, m11 ); 11207 11208 } else { 11209 11210 this._x = 0; 11211 this._z = Math.atan2( - m12, m22 ); 11212 11213 } 11214 11215 } else if ( order === 'YZX' ) { 11216 11217 this._z = Math.asin( clamp( m21, - 1, 1 ) ); 11218 11219 if ( Math.abs( m21 ) < 0.99999 ) { 11220 11221 this._x = Math.atan2( - m23, m22 ); 11222 this._y = Math.atan2( - m31, m11 ); 11223 11224 } else { 11225 11226 this._x = 0; 11227 this._y = Math.atan2( m13, m33 ); 11228 11229 } 11230 11231 } else if ( order === 'XZY' ) { 11232 11233 this._z = Math.asin( - clamp( m12, - 1, 1 ) ); 11234 11235 if ( Math.abs( m12 ) < 0.99999 ) { 11236 11237 this._x = Math.atan2( m32, m22 ); 11238 this._y = Math.atan2( m13, m11 ); 11239 11240 } else { 11241 11242 this._x = Math.atan2( - m23, m33 ); 11243 this._y = 0; 11244 11245 } 11246 11247 } else { 11248 11249 console.warn( 'THREE.Euler: .setFromRotationMatrix() given unsupported order: ' + order ); 11250 11251 } 11252 11253 this._order = order; 11254 11255 if ( update !== false ) this.onChangeCallback(); 11256 11257 return this; 11258 11259 }, 11260 11261 setFromQuaternion: function () { 11262 11263 var matrix = new Matrix4(); 11264 11265 return function setFromQuaternion( q, order, update ) { 11266 11267 matrix.makeRotationFromQuaternion( q ); 11268 11269 return this.setFromRotationMatrix( matrix, order, update ); 11270 11271 }; 11272 11273 }(), 11274 11275 setFromVector3: function ( v, order ) { 11276 11277 return this.set( v.x, v.y, v.z, order || this._order ); 11278 11279 }, 11280 11281 reorder: function () { 11282 11283 // WARNING: this discards revolution information -bhouston 11284 11285 var q = new Quaternion(); 11286 11287 return function reorder( newOrder ) { 11288 11289 q.setFromEuler( this ); 11290 11291 return this.setFromQuaternion( q, newOrder ); 11292 11293 }; 11294 11295 }(), 11296 11297 equals: function ( euler ) { 11298 11299 return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); 11300 11301 }, 11302 11303 fromArray: function ( array ) { 11304 11305 this._x = array[ 0 ]; 11306 this._y = array[ 1 ]; 11307 this._z = array[ 2 ]; 11308 if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; 11309 11310 this.onChangeCallback(); 11311 11312 return this; 11313 11314 }, 11315 11316 toArray: function ( array, offset ) { 11317 11318 if ( array === undefined ) array = []; 11319 if ( offset === undefined ) offset = 0; 11320 11321 array[ offset ] = this._x; 11322 array[ offset + 1 ] = this._y; 11323 array[ offset + 2 ] = this._z; 11324 array[ offset + 3 ] = this._order; 11325 11326 return array; 11327 11328 }, 11329 11330 toVector3: function ( optionalResult ) { 11331 11332 if ( optionalResult ) { 11333 11334 return optionalResult.set( this._x, this._y, this._z ); 11335 11336 } else { 11337 11338 return new Vector3( this._x, this._y, this._z ); 11339 11340 } 11341 11342 }, 11343 11344 onChange: function ( callback ) { 11345 11346 this.onChangeCallback = callback; 11347 11348 return this; 11349 11350 }, 11351 11352 onChangeCallback: function () {} 11353 11354 } ); 11355 11356 /** 11357 * @author mrdoob / http://mrdoob.com/ 11358 */ 11359 11360 function Layers() { 11361 11362 this.mask = 1 | 0; 11363 11364 } 11365 11366 Object.assign( Layers.prototype, { 11367 11368 set: function ( channel ) { 11369 11370 this.mask = 1 << channel | 0; 11371 11372 }, 11373 11374 enable: function ( channel ) { 11375 11376 this.mask |= 1 << channel | 0; 11377 11378 }, 11379 11380 toggle: function ( channel ) { 11381 11382 this.mask ^= 1 << channel | 0; 11383 11384 }, 11385 11386 disable: function ( channel ) { 11387 11388 this.mask &= ~ ( 1 << channel | 0 ); 11389 11390 }, 11391 11392 test: function ( layers ) { 11393 11394 return ( this.mask & layers.mask ) !== 0; 11395 11396 } 11397 11398 } ); 11399 11400 /** 11401 * @author mrdoob / http://mrdoob.com/ 11402 * @author mikael emtinger / http://gomo.se/ 11403 * @author alteredq / http://alteredqualia.com/ 11404 * @author WestLangley / http://github.com/WestLangley 11405 * @author elephantatwork / www.elephantatwork.ch 11406 */ 11407 11408 var object3DId = 0; 11409 11410 function Object3D() { 11411 11412 Object.defineProperty( this, 'id', { value: object3DId ++ } ); 11413 11414 this.uuid = _Math.generateUUID(); 11415 11416 this.name = ''; 11417 this.type = 'Object3D'; 11418 11419 this.parent = null; 11420 this.children = []; 11421 11422 this.up = Object3D.DefaultUp.clone(); 11423 11424 var position = new Vector3(); 11425 var rotation = new Euler(); 11426 var quaternion = new Quaternion(); 11427 var scale = new Vector3( 1, 1, 1 ); 11428 11429 function onRotationChange() { 11430 11431 quaternion.setFromEuler( rotation, false ); 11432 11433 } 11434 11435 function onQuaternionChange() { 11436 11437 rotation.setFromQuaternion( quaternion, undefined, false ); 11438 11439 } 11440 11441 rotation.onChange( onRotationChange ); 11442 quaternion.onChange( onQuaternionChange ); 11443 11444 Object.defineProperties( this, { 11445 position: { 11446 enumerable: true, 11447 value: position 11448 }, 11449 rotation: { 11450 enumerable: true, 11451 value: rotation 11452 }, 11453 quaternion: { 11454 enumerable: true, 11455 value: quaternion 11456 }, 11457 scale: { 11458 enumerable: true, 11459 value: scale 11460 }, 11461 modelViewMatrix: { 11462 value: new Matrix4() 11463 }, 11464 normalMatrix: { 11465 value: new Matrix3() 11466 } 11467 } ); 11468 11469 this.matrix = new Matrix4(); 11470 this.matrixWorld = new Matrix4(); 11471 11472 this.matrixAutoUpdate = Object3D.DefaultMatrixAutoUpdate; 11473 this.matrixWorldNeedsUpdate = false; 11474 11475 this.layers = new Layers(); 11476 this.visible = true; 11477 11478 this.castShadow = false; 11479 this.receiveShadow = false; 11480 11481 this.frustumCulled = true; 11482 this.renderOrder = 0; 11483 11484 this.userData = {}; 11485 11486 } 11487 11488 Object3D.DefaultUp = new Vector3( 0, 1, 0 ); 11489 Object3D.DefaultMatrixAutoUpdate = true; 11490 11491 Object3D.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { 11492 11493 constructor: Object3D, 11494 11495 isObject3D: true, 11496 11497 onBeforeRender: function () {}, 11498 onAfterRender: function () {}, 11499 11500 applyMatrix: function ( matrix ) { 11501 11502 this.matrix.multiplyMatrices( matrix, this.matrix ); 11503 11504 this.matrix.decompose( this.position, this.quaternion, this.scale ); 11505 11506 }, 11507 11508 applyQuaternion: function ( q ) { 11509 11510 this.quaternion.premultiply( q ); 11511 11512 return this; 11513 11514 }, 11515 11516 setRotationFromAxisAngle: function ( axis, angle ) { 11517 11518 // assumes axis is normalized 11519 11520 this.quaternion.setFromAxisAngle( axis, angle ); 11521 11522 }, 11523 11524 setRotationFromEuler: function ( euler ) { 11525 11526 this.quaternion.setFromEuler( euler, true ); 11527 11528 }, 11529 11530 setRotationFromMatrix: function ( m ) { 11531 11532 // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) 11533 11534 this.quaternion.setFromRotationMatrix( m ); 11535 11536 }, 11537 11538 setRotationFromQuaternion: function ( q ) { 11539 11540 // assumes q is normalized 11541 11542 this.quaternion.copy( q ); 11543 11544 }, 11545 11546 rotateOnAxis: function () { 11547 11548 // rotate object on axis in object space 11549 // axis is assumed to be normalized 11550 11551 var q1 = new Quaternion(); 11552 11553 return function rotateOnAxis( axis, angle ) { 11554 11555 q1.setFromAxisAngle( axis, angle ); 11556 11557 this.quaternion.multiply( q1 ); 11558 11559 return this; 11560 11561 }; 11562 11563 }(), 11564 11565 rotateOnWorldAxis: function () { 11566 11567 // rotate object on axis in world space 11568 // axis is assumed to be normalized 11569 // method assumes no rotated parent 11570 11571 var q1 = new Quaternion(); 11572 11573 return function rotateOnWorldAxis( axis, angle ) { 11574 11575 q1.setFromAxisAngle( axis, angle ); 11576 11577 this.quaternion.premultiply( q1 ); 11578 11579 return this; 11580 11581 }; 11582 11583 }(), 11584 11585 rotateX: function () { 11586 11587 var v1 = new Vector3( 1, 0, 0 ); 11588 11589 return function rotateX( angle ) { 11590 11591 return this.rotateOnAxis( v1, angle ); 11592 11593 }; 11594 11595 }(), 11596 11597 rotateY: function () { 11598 11599 var v1 = new Vector3( 0, 1, 0 ); 11600 11601 return function rotateY( angle ) { 11602 11603 return this.rotateOnAxis( v1, angle ); 11604 11605 }; 11606 11607 }(), 11608 11609 rotateZ: function () { 11610 11611 var v1 = new Vector3( 0, 0, 1 ); 11612 11613 return function rotateZ( angle ) { 11614 11615 return this.rotateOnAxis( v1, angle ); 11616 11617 }; 11618 11619 }(), 11620 11621 translateOnAxis: function () { 11622 11623 // translate object by distance along axis in object space 11624 // axis is assumed to be normalized 11625 11626 var v1 = new Vector3(); 11627 11628 return function translateOnAxis( axis, distance ) { 11629 11630 v1.copy( axis ).applyQuaternion( this.quaternion ); 11631 11632 this.position.add( v1.multiplyScalar( distance ) ); 11633 11634 return this; 11635 11636 }; 11637 11638 }(), 11639 11640 translateX: function () { 11641 11642 var v1 = new Vector3( 1, 0, 0 ); 11643 11644 return function translateX( distance ) { 11645 11646 return this.translateOnAxis( v1, distance ); 11647 11648 }; 11649 11650 }(), 11651 11652 translateY: function () { 11653 11654 var v1 = new Vector3( 0, 1, 0 ); 11655 11656 return function translateY( distance ) { 11657 11658 return this.translateOnAxis( v1, distance ); 11659 11660 }; 11661 11662 }(), 11663 11664 translateZ: function () { 11665 11666 var v1 = new Vector3( 0, 0, 1 ); 11667 11668 return function translateZ( distance ) { 11669 11670 return this.translateOnAxis( v1, distance ); 11671 11672 }; 11673 11674 }(), 11675 11676 localToWorld: function ( vector ) { 11677 11678 return vector.applyMatrix4( this.matrixWorld ); 11679 11680 }, 11681
11682 worldToLocal: function () { 11683 11684 var m1 = new Matrix4(); 11685 11686 return function worldToLocal( vector ) { 11687 11688 return vector.applyMatrix4( m1.getInverse( this.matrixWorld ) ); 11689 11690 }; 11691 11692 }(), 11693 11694 lookAt: function () { 11695 11696 // This method does not support objects with rotated and/or translated parent(s) 11697 11698 var m1 = new Matrix4(); 11699 var vector = new Vector3(); 11700 11701 return function lookAt( x, y, z ) { 11702 11703 if ( x.isVector3 ) { 11704 11705 vector.copy( x ); 11706 11707 } else { 11708 11709 vector.set( x, y, z ); 11710 11711 } 11712 11713 if ( this.isCamera ) { 11714 11715 m1.lookAt( this.position, vector, this.up ); 11716 11717 } else { 11718 11719 m1.lookAt( vector, this.position, this.up ); 11720 11721 } 11722 11723 this.quaternion.setFromRotationMatrix( m1 ); 11724 11725 }; 11726 11727 }(), 11728 11729 add: function ( object ) { 11730 11731 if ( arguments.length > 1 ) { 11732 11733 for ( var i = 0; i < arguments.length; i ++ ) { 11734 11735 this.add( arguments[ i ] ); 11736 11737 } 11738 11739 return this; 11740 11741 } 11742 11743 if ( object === this ) { 11744 11745 console.error( "THREE.Object3D.add: object can't be added as a child of itself.", object ); 11746 return this; 11747 11748 } 11749 11750 if ( ( object && object.isObject3D ) ) { 11751 11752 if ( object.parent !== null ) { 11753 11754 object.parent.remove( object ); 11755 11756 } 11757 11758 object.parent = this; 11759 object.dispatchEvent( { type: 'added' } ); 11760 11761 this.children.push( object ); 11762 11763 } else { 11764 11765 console.error( "THREE.Object3D.add: object not an instance of THREE.Object3D.", object ); 11766 11767 } 11768 11769 return this; 11770 11771 }, 11772 11773 remove: function ( object ) { 11774 11775 if ( arguments.length > 1 ) { 11776 11777 for ( var i = 0; i < arguments.length; i ++ ) { 11778 11779 this.remove( arguments[ i ] ); 11780 11781 } 11782 11783 return this; 11784 11785 } 11786 11787 var index = this.children.indexOf( object ); 11788 11789 if ( index !== - 1 ) { 11790 11791 object.parent = null; 11792 11793 object.dispatchEvent( { type: 'removed' } ); 11794 11795 this.children.splice( index, 1 ); 11796 11797 } 11798 11799 return this; 11800 11801 }, 11802 11803 getObjectById: function ( id ) { 11804 11805 return this.getObjectByProperty( 'id', id ); 11806 11807 }, 11808 11809 getObjectByName: function ( name ) { 11810 11811 return this.getObjectByProperty( 'name', name ); 11812 11813 }, 11814 11815 getObjectByProperty: function ( name, value ) { 11816 11817 if ( this[ name ] === value ) return this; 11818 11819 for ( var i = 0, l = this.children.length; i < l; i ++ ) { 11820 11821 var child = this.children[ i ]; 11822 var object = child.getObjectByProperty( name, value ); 11823 11824 if ( object !== undefined ) { 11825 11826 return object; 11827 11828 } 11829 11830 } 11831 11832 return undefined; 11833 11834 }, 11835 11836 getWorldPosition: function ( target ) { 11837 11838 if ( target === undefined ) { 11839 11840 console.warn( 'THREE.Object3D: .getWorldPosition() target is now required' ); 11841 target = new Vector3(); 11842 11843 } 11844 11845 this.updateMatrixWorld( true ); 11846 11847 return target.setFromMatrixPosition( this.matrixWorld ); 11848 11849 }, 11850 11851 getWorldQuaternion: function () { 11852 11853 var position = new Vector3(); 11854 var scale = new Vector3(); 11855 11856 return function getWorldQuaternion( target ) { 11857 11858 if ( target === undefined ) { 11859 11860 console.warn( 'THREE.Object3D: .getWorldQuaternion() target is now required' ); 11861 target = new Quaternion(); 11862 11863 } 11864 11865 this.updateMatrixWorld( true ); 11866 11867 this.matrixWorld.decompose( position, target, scale ); 11868 11869 return target; 11870 11871 }; 11872 11873 }(), 11874 11875 getWorldScale: function () { 11876 11877 var position = new Vector3(); 11878 var quaternion = new Quaternion(); 11879 11880 return function getWorldScale( target ) { 11881 11882 if ( target === undefined ) { 11883 11884 console.warn( 'THREE.Object3D: .getWorldScale() target is now required' ); 11885 target = new Vector3(); 11886 11887 } 11888 11889 this.updateMatrixWorld( true ); 11890 11891 this.matrixWorld.decompose( position, quaternion, target ); 11892 11893 return target; 11894 11895 }; 11896 11897 }(), 11898 11899 getWorldDirection: function () { 11900 11901 var quaternion = new Quaternion(); 11902 11903 return function getWorldDirection( target ) { 11904 11905 if ( target === undefined ) { 11906 11907 console.warn( 'THREE.Object3D: .getWorldDirection() target is now required' ); 11908 target = new Vector3(); 11909 11910 } 11911 11912 this.getWorldQuaternion( quaternion ); 11913 11914 return target.set( 0, 0, 1 ).applyQuaternion( quaternion ); 11915 11916 }; 11917 11918 }(), 11919 11920 raycast: function () {}, 11921 11922 traverse: function ( callback ) { 11923 11924 callback( this ); 11925 11926 var children = this.children; 11927 11928 for ( var i = 0, l = children.length; i < l; i ++ ) { 11929 11930 children[ i ].traverse( callback ); 11931 11932 } 11933 11934 }, 11935
vendor: 11,333 bytes, lines 11936-12460
11936 traverseVisible: function ( callback ) { 11937 11938 if ( this.visible === false ) return; 11939 11940 callback( this ); 11941 11942 var children = this.children; 11943 11944 for ( var i = 0, l = children.length; i < l; i ++ ) { 11945 11946 children[ i ].traverseVisible( callback ); 11947 11948 } 11949 11950 }, 11951 11952 traverseAncestors: function ( callback ) { 11953 11954 var parent = this.parent; 11955 11956 if ( parent !== null ) { 11957 11958 callback( parent ); 11959 11960 parent.traverseAncestors( callback ); 11961 11962 } 11963 11964 }, 11965 11966 updateMatrix: function () { 11967 11968 this.matrix.compose( this.position, this.quaternion, this.scale ); 11969 11970 this.matrixWorldNeedsUpdate = true; 11971 11972 }, 11973 11974 updateMatrixWorld: function ( force ) { 11975 11976 if ( this.matrixAutoUpdate ) this.updateMatrix(); 11977 11978 if ( this.matrixWorldNeedsUpdate || force ) { 11979 11980 if ( this.parent === null ) { 11981 11982 this.matrixWorld.copy( this.matrix ); 11983 11984 } else { 11985 11986 this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); 11987 11988 } 11989 11990 this.matrixWorldNeedsUpdate = false; 11991 11992 force = true; 11993 11994 } 11995 11996 // update children 11997 11998 var children = this.children; 11999 12000 for ( var i = 0, l = children.length; i < l; i ++ ) { 12001 12002 children[ i ].updateMatrixWorld( force ); 12003 12004 } 12005 12006 }, 12007 12008 toJSON: function ( meta ) { 12009 12010 // meta is a string when called from JSON.stringify 12011 var isRootObject = ( meta === undefined || typeof meta === 'string' ); 12012 12013 var output = {}; 12014 12015 // meta is a hash used to collect geometries, materials. 12016 // not providing it implies that this is the root object 12017 // being serialized. 12018 if ( isRootObject ) { 12019 12020 // initialize meta obj 12021 meta = { 12022 geometries: {}, 12023 materials: {}, 12024 textures: {}, 12025 images: {}, 12026 shapes: {} 12027 }; 12028 12029 output.metadata = { 12030 version: 4.5, 12031 type: 'Object', 12032 generator: 'Object3D.toJSON' 12033 }; 12034 12035 } 12036 12037 // standard Object3D serialization 12038 12039 var object = {}; 12040 12041 object.uuid = this.uuid; 12042 object.type = this.type; 12043 12044 if ( this.name !== '' ) object.name = this.name; 12045 if ( this.castShadow === true ) object.castShadow = true; 12046 if ( this.receiveShadow === true ) object.receiveShadow = true; 12047 if ( this.visible === false ) object.visible = false; 12048 if ( this.frustumCulled === false ) object.frustumCulled = false; 12049 if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder; 12050 if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData; 12051 12052 object.matrix = this.matrix.toArray(); 12053 12054 if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; 12055 12056 // 12057 12058 function serialize( library, element ) { 12059 12060 if ( library[ element.uuid ] === undefined ) { 12061 12062 library[ element.uuid ] = element.toJSON( meta ); 12063 12064 } 12065 12066 return element.uuid; 12067 12068 } 12069 12070 if ( this.geometry !== undefined ) { 12071 12072 object.geometry = serialize( meta.geometries, this.geometry ); 12073 12074 var parameters = this.geometry.parameters; 12075 12076 if ( parameters !== undefined && parameters.shapes !== undefined ) { 12077 12078 var shapes = parameters.shapes; 12079 12080 if ( Array.isArray( shapes ) ) { 12081 12082 for ( var i = 0, l = shapes.length; i < l; i ++ ) { 12083 12084 var shape = shapes[ i ]; 12085 12086 serialize( meta.shapes, shape ); 12087 12088 } 12089 12090 } else { 12091 12092 serialize( meta.shapes, shapes ); 12093 12094 } 12095 12096 } 12097 12098 } 12099 12100 if ( this.material !== undefined ) { 12101 12102 if ( Array.isArray( this.material ) ) { 12103 12104 var uuids = []; 12105 12106 for ( var i = 0, l = this.material.length; i < l; i ++ ) { 12107 12108 uuids.push( serialize( meta.materials, this.material[ i ] ) ); 12109 12110 } 12111 12112 object.material = uuids; 12113 12114 } else { 12115 12116 object.material = serialize( meta.materials, this.material ); 12117 12118 } 12119 12120 } 12121 12122 // 12123 12124 if ( this.children.length > 0 ) { 12125 12126 object.children = []; 12127 12128 for ( var i = 0; i < this.children.length; i ++ ) { 12129 12130 object.children.push( this.children[ i ].toJSON( meta ).object ); 12131 12132 } 12133 12134 } 12135 12136 if ( isRootObject ) { 12137 12138 var geometries = extractFromCache( meta.geometries ); 12139 var materials = extractFromCache( meta.materials ); 12140 var textures = extractFromCache( meta.textures ); 12141 var images = extractFromCache( meta.images ); 12142 var shapes = extractFromCache( meta.shapes ); 12143 12144 if ( geometries.length > 0 ) output.geometries = geometries; 12145 if ( materials.length > 0 ) output.materials = materials; 12146 if ( textures.length > 0 ) output.textures = textures; 12147 if ( images.length > 0 ) output.images = images; 12148 if ( shapes.length > 0 ) output.shapes = shapes; 12149 12150 } 12151 12152 output.object = object; 12153 12154 return output; 12155 12156 // extract data from the cache hash 12157 // remove metadata on each item 12158 // and return as array 12159 function extractFromCache( cache ) { 12160 12161 var values = []; 12162 for ( var key in cache ) { 12163 12164 var data = cache[ key ]; 12165 delete data.metadata; 12166 values.push( data ); 12167 12168 } 12169 return values; 12170 12171 } 12172 12173 }, 12174 12175 clone: function ( recursive ) { 12176 12177 return new this.constructor().copy( this, recursive ); 12178 12179 }, 12180 12181 copy: function ( source, recursive ) { 12182 12183 if ( recursive === undefined ) recursive = true; 12184 12185 this.name = source.name; 12186 12187 this.up.copy( source.up ); 12188 12189 this.position.copy( source.position ); 12190 this.quaternion.copy( source.quaternion ); 12191 this.scale.copy( source.scale ); 12192 12193 this.matrix.copy( source.matrix ); 12194 this.matrixWorld.copy( source.matrixWorld ); 12195 12196 this.matrixAutoUpdate = source.matrixAutoUpdate; 12197 this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; 12198 12199 this.layers.mask = source.layers.mask; 12200 this.visible = source.visible; 12201 12202 this.castShadow = source.castShadow; 12203 this.receiveShadow = source.receiveShadow; 12204 12205 this.frustumCulled = source.frustumCulled; 12206 this.renderOrder = source.renderOrder; 12207 12208 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 12209 12210 if ( recursive === true ) { 12211 12212 for ( var i = 0; i < source.children.length; i ++ ) { 12213 12214 var child = source.children[ i ]; 12215 this.add( child.clone() ); 12216 12217 } 12218 12219 } 12220 12221 return this; 12222 12223 } 12224 12225 } ); 12226 12227 /** 12228 * @author mrdoob / http://mrdoob.com/ 12229 * @author mikael emtinger / http://gomo.se/ 12230 * @author WestLangley / http://github.com/WestLangley 12231 */ 12232 12233 function Camera() { 12234 12235 Object3D.call( this ); 12236 12237 this.type = 'Camera'; 12238 12239 this.matrixWorldInverse = new Matrix4(); 12240 this.projectionMatrix = new Matrix4(); 12241 12242 } 12243 12244 Camera.prototype = Object.assign( Object.create( Object3D.prototype ), { 12245 12246 constructor: Camera, 12247 12248 isCamera: true, 12249 12250 copy: function ( source, recursive ) { 12251 12252 Object3D.prototype.copy.call( this, source, recursive ); 12253 12254 this.matrixWorldInverse.copy( source.matrixWorldInverse ); 12255 this.projectionMatrix.copy( source.projectionMatrix ); 12256 12257 return this; 12258 12259 }, 12260 12261 getWorldDirection: function () { 12262 12263 var quaternion = new Quaternion(); 12264 12265 return function getWorldDirection( target ) { 12266 12267 if ( target === undefined ) { 12268 12269 console.warn( 'THREE.Camera: .getWorldDirection() target is now required' ); 12270 target = new Vector3(); 12271 12272 } 12273 12274 this.getWorldQuaternion( quaternion ); 12275 12276 return target.set( 0, 0, - 1 ).applyQuaternion( quaternion ); 12277 12278 }; 12279 12280 }(), 12281 12282 updateMatrixWorld: function ( force ) { 12283 12284 Object3D.prototype.updateMatrixWorld.call( this, force ); 12285 12286 this.matrixWorldInverse.getInverse( this.matrixWorld ); 12287 12288 }, 12289 12290 clone: function () { 12291 12292 return new this.constructor().copy( this ); 12293 12294 } 12295 12296 } ); 12297 12298 /** 12299 * @author alteredq / http://alteredqualia.com/ 12300 * @author arose / http://github.com/arose 12301 */ 12302 12303 function OrthographicCamera( left, right, top, bottom, near, far ) { 12304 12305 Camera.call( this ); 12306 12307 this.type = 'OrthographicCamera'; 12308 12309 this.zoom = 1; 12310 this.view = null; 12311 12312 this.left = left; 12313 this.right = right; 12314 this.top = top; 12315 this.bottom = bottom; 12316 12317 this.near = ( near !== undefined ) ? near : 0.1; 12318 this.far = ( far !== undefined ) ? far : 2000; 12319 12320 this.updateProjectionMatrix(); 12321 12322 } 12323 12324 OrthographicCamera.prototype = Object.assign( Object.create( Camera.prototype ), { 12325 12326 constructor: OrthographicCamera, 12327 12328 isOrthographicCamera: true, 12329 12330 copy: function ( source, recursive ) { 12331 12332 Camera.prototype.copy.call( this, source, recursive ); 12333 12334 this.left = source.left; 12335 this.right = source.right; 12336 this.top = source.top; 12337 this.bottom = source.bottom; 12338 this.near = source.near; 12339 this.far = source.far; 12340 12341 this.zoom = source.zoom; 12342 this.view = source.view === null ? null : Object.assign( {}, source.view ); 12343 12344 return this; 12345 12346 }, 12347 12348 setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) { 12349 12350 if ( this.view === null ) { 12351 12352 this.view = { 12353 enabled: true, 12354 fullWidth: 1, 12355 fullHeight: 1, 12356 offsetX: 0, 12357 offsetY: 0, 12358 width: 1, 12359 height: 1 12360 }; 12361 12362 } 12363 12364 this.view.enabled = true; 12365 this.view.fullWidth = fullWidth; 12366 this.view.fullHeight = fullHeight; 12367 this.view.offsetX = x; 12368 this.view.offsetY = y; 12369 this.view.width = width; 12370 this.view.height = height; 12371 12372 this.updateProjectionMatrix(); 12373 12374 }, 12375 12376 clearViewOffset: function () { 12377 12378 if ( this.view !== null ) { 12379 12380 this.view.enabled = false; 12381 12382 } 12383 12384 this.updateProjectionMatrix(); 12385 12386 }, 12387 12388 updateProjectionMatrix: function () { 12389 12390 var dx = ( this.right - this.left ) / ( 2 * this.zoom ); 12391 var dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); 12392 var cx = ( this.right + this.left ) / 2; 12393 var cy = ( this.top + this.bottom ) / 2; 12394 12395 var left = cx - dx; 12396 var right = cx + dx; 12397 var top = cy + dy; 12398 var bottom = cy - dy; 12399 12400 if ( this.view !== null && this.view.enabled ) { 12401 12402 var zoomW = this.zoom / ( this.view.width / this.view.fullWidth ); 12403 var zoomH = this.zoom / ( this.view.height / this.view.fullHeight ); 12404 var scaleW = ( this.right - this.left ) / this.view.width; 12405 var scaleH = ( this.top - this.bottom ) / this.view.height; 12406 12407 left += scaleW * ( this.view.offsetX / zoomW ); 12408 right = left + scaleW * ( this.view.width / zoomW ); 12409 top -= scaleH * ( this.view.offsetY / zoomH ); 12410 bottom = top - scaleH * ( this.view.height / zoomH ); 12411 12412 } 12413 12414 this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far ); 12415 12416 }, 12417 12418 toJSON: function ( meta ) { 12419 12420 var data = Object3D.prototype.toJSON.call( this, meta ); 12421 12422 data.object.zoom = this.zoom; 12423 data.object.left = this.left; 12424 data.object.right = this.right; 12425 data.object.top = this.top; 12426 data.object.bottom = this.bottom; 12427 data.object.near = this.near; 12428 data.object.far = this.far; 12429 12430 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 12431 12432 return data; 12433 12434 } 12435 12436 } ); 12437 12438 /** 12439 * @author mrdoob / http://mrdoob.com/ 12440 * @author alteredq / http://alteredqualia.com/ 12441 */ 12442 12443 function Face3( a, b, c, normal, color, materialIndex ) { 12444 12445 this.a = a; 12446 this.b = b; 12447 this.c = c; 12448 12449 this.normal = ( normal && normal.isVector3 ) ? normal : new Vector3(); 12450 this.vertexNormals = Array.isArray( normal ) ? normal : []; 12451 12452 this.color = ( color && color.isColor ) ? color : new Color(); 12453 this.vertexColors = Array.isArray( color ) ? color : []; 12454 12455 this.materialIndex = materialIndex !== undefined ? materialIndex : 0; 12456 12457 } 12458 12459 Object.assign( Face3.prototype, { 12460
vendor: 5,662 bytes, lines 12461-12750
12461 clone: function () { 12462 12463 return new this.constructor().copy( this ); 12464 12465 }, 12466 12467 copy: function ( source ) { 12468 12469 this.a = source.a; 12470 this.b = source.b; 12471 this.c = source.c; 12472 12473 this.normal.copy( source.normal ); 12474 this.color.copy( source.color ); 12475 12476 this.materialIndex = source.materialIndex; 12477 12478 for ( var i = 0, il = source.vertexNormals.length; i < il; i ++ ) { 12479 12480 this.vertexNormals[ i ] = source.vertexNormals[ i ].clone(); 12481 12482 } 12483 12484 for ( var i = 0, il = source.vertexColors.length; i < il; i ++ ) { 12485 12486 this.vertexColors[ i ] = source.vertexColors[ i ].clone(); 12487 12488 } 12489 12490 return this; 12491 12492 } 12493 12494 } ); 12495 12496 /** 12497 * @author mrdoob / http://mrdoob.com/ 12498 * @author kile / http://kile.stravaganza.org/ 12499 * @author alteredq / http://alteredqualia.com/ 12500 * @author mikael emtinger / http://gomo.se/ 12501 * @author zz85 / http://www.lab4games.net/zz85/blog 12502 * @author bhouston / http://clara.io 12503 */ 12504 12505 var geometryId = 0; // Geometry uses even numbers as Id 12506 12507 function Geometry() { 12508 12509 Object.defineProperty( this, 'id', { value: geometryId += 2 } ); 12510 12511 this.uuid = _Math.generateUUID(); 12512 12513 this.name = ''; 12514 this.type = 'Geometry'; 12515 12516 this.vertices = []; 12517 this.colors = []; 12518 this.faces = []; 12519 this.faceVertexUvs = [[]]; 12520 12521 this.morphTargets = []; 12522 this.morphNormals = []; 12523 12524 this.skinWeights = []; 12525 this.skinIndices = []; 12526 12527 this.lineDistances = []; 12528 12529 this.boundingBox = null; 12530 this.boundingSphere = null; 12531 12532 // update flags 12533 12534 this.elementsNeedUpdate = false; 12535 this.verticesNeedUpdate = false; 12536 this.uvsNeedUpdate = false; 12537 this.normalsNeedUpdate = false; 12538 this.colorsNeedUpdate = false; 12539 this.lineDistancesNeedUpdate = false; 12540 this.groupsNeedUpdate = false; 12541 12542 } 12543 12544 Geometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { 12545 12546 constructor: Geometry, 12547 12548 isGeometry: true, 12549 12550 applyMatrix: function ( matrix ) { 12551 12552 var normalMatrix = new Matrix3().getNormalMatrix( matrix ); 12553 12554 for ( var i = 0, il = this.vertices.length; i < il; i ++ ) { 12555 12556 var vertex = this.vertices[ i ]; 12557 vertex.applyMatrix4( matrix ); 12558 12559 } 12560 12561 for ( var i = 0, il = this.faces.length; i < il; i ++ ) { 12562 12563 var face = this.faces[ i ]; 12564 face.normal.applyMatrix3( normalMatrix ).normalize(); 12565 12566 for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { 12567 12568 face.vertexNormals[ j ].applyMatrix3( normalMatrix ).normalize(); 12569 12570 } 12571 12572 } 12573 12574 if ( this.boundingBox !== null ) { 12575 12576 this.computeBoundingBox(); 12577 12578 } 12579 12580 if ( this.boundingSphere !== null ) { 12581 12582 this.computeBoundingSphere(); 12583 12584 } 12585 12586 this.verticesNeedUpdate = true; 12587 this.normalsNeedUpdate = true; 12588 12589 return this; 12590 12591 }, 12592 12593 rotateX: function () { 12594 12595 // rotate geometry around world x-axis 12596 12597 var m1 = new Matrix4(); 12598 12599 return function rotateX( angle ) { 12600 12601 m1.makeRotationX( angle ); 12602 12603 this.applyMatrix( m1 ); 12604 12605 return this; 12606 12607 }; 12608 12609 }(), 12610 12611 rotateY: function () { 12612 12613 // rotate geometry around world y-axis 12614 12615 var m1 = new Matrix4(); 12616 12617 return function rotateY( angle ) { 12618 12619 m1.makeRotationY( angle ); 12620 12621 this.applyMatrix( m1 ); 12622 12623 return this; 12624 12625 }; 12626 12627 }(), 12628 12629 rotateZ: function () { 12630 12631 // rotate geometry around world z-axis 12632 12633 var m1 = new Matrix4(); 12634 12635 return function rotateZ( angle ) { 12636 12637 m1.makeRotationZ( angle ); 12638 12639 this.applyMatrix( m1 ); 12640 12641 return this; 12642 12643 }; 12644 12645 }(), 12646 12647 translate: function () { 12648 12649 // translate geometry 12650 12651 var m1 = new Matrix4(); 12652 12653 return function translate( x, y, z ) { 12654 12655 m1.makeTranslation( x, y, z ); 12656 12657 this.applyMatrix( m1 ); 12658 12659 return this; 12660 12661 }; 12662 12663 }(), 12664 12665 scale: function () { 12666 12667 // scale geometry 12668 12669 var m1 = new Matrix4(); 12670 12671 return function scale( x, y, z ) { 12672 12673 m1.makeScale( x, y, z ); 12674 12675 this.applyMatrix( m1 ); 12676 12677 return this; 12678 12679 }; 12680 12681 }(), 12682 12683 lookAt: function () { 12684 12685 var obj = new Object3D(); 12686 12687 return function lookAt( vector ) { 12688 12689 obj.lookAt( vector ); 12690 12691 obj.updateMatrix(); 12692 12693 this.applyMatrix( obj.matrix ); 12694 12695 }; 12696 12697 }(), 12698 12699 fromBufferGeometry: function ( geometry ) { 12700 12701 var scope = this; 12702 12703 var indices = geometry.index !== null ? geometry.index.array : undefined; 12704 var attributes = geometry.attributes; 12705 12706 var positions = attributes.position.array; 12707 var normals = attributes.normal !== undefined ? attributes.normal.array : undefined; 12708 var colors = attributes.color !== undefined ? attributes.color.array : undefined; 12709 var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined; 12710 var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined; 12711 12712 if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = []; 12713 12714 var tempNormals = []; 12715 var tempUVs = []; 12716 var tempUVs2 = []; 12717 12718 for ( var i = 0, j = 0; i < positions.length; i += 3, j += 2 ) { 12719 12720 scope.vertices.push( new Vector3( positions[ i ], positions[ i + 1 ], positions[ i + 2 ] ) ); 12721 12722 if ( normals !== undefined ) { 12723 12724 tempNormals.push( new Vector3( normals[ i ], normals[ i + 1 ], normals[ i + 2 ] ) ); 12725 12726 } 12727 12728 if ( colors !== undefined ) { 12729 12730 scope.colors.push( new Color( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] ) ); 12731 12732 } 12733 12734 if ( uvs !== undefined ) { 12735 12736 tempUVs.push( new Vector2( uvs[ j ], uvs[ j + 1 ] ) ); 12737 12738 } 12739 12740 if ( uvs2 !== undefined ) { 12741 12742 tempUVs2.push( new Vector2( uvs2[ j ], uvs2[ j + 1 ] ) ); 12743 12744 } 12745 12746 } 12747 12748 function addFace( a, b, c, materialIndex ) { 12749 12750 var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].
vendor: 89,242 bytes, lines 12750-16884
12750clone(), tempNormals[ c ].clone() ] : []; 12751 var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : []; 12752 12753 var face = new Face3( a, b, c, vertexNormals, vertexColors, materialIndex ); 12754 12755 scope.faces.push( face ); 12756 12757 if ( uvs !== undefined ) { 12758 12759 scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ].clone(), tempUVs[ b ].clone(), tempUVs[ c ].clone() ] ); 12760 12761 } 12762 12763 if ( uvs2 !== undefined ) { 12764 12765 scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] ); 12766 12767 } 12768 12769 } 12770 12771 var groups = geometry.groups; 12772 12773 if ( groups.length > 0 ) { 12774 12775 for ( var i = 0; i < groups.length; i ++ ) { 12776 12777 var group = groups[ i ]; 12778 12779 var start = group.start; 12780 var count = group.count; 12781 12782 for ( var j = start, jl = start + count; j < jl; j += 3 ) { 12783 12784 if ( indices !== undefined ) { 12785 12786 addFace( indices[ j ], indices[ j + 1 ], indices[ j + 2 ], group.materialIndex ); 12787 12788 } else { 12789 12790 addFace( j, j + 1, j + 2, group.materialIndex ); 12791 12792 } 12793 12794 } 12795 12796 } 12797 12798 } else { 12799 12800 if ( indices !== undefined ) { 12801 12802 for ( var i = 0; i < indices.length; i += 3 ) { 12803 12804 addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] ); 12805 12806 } 12807 12808 } else { 12809 12810 for ( var i = 0; i < positions.length / 3; i += 3 ) { 12811 12812 addFace( i, i + 1, i + 2 ); 12813 12814 } 12815 12816 } 12817 12818 } 12819 12820 this.computeFaceNormals(); 12821 12822 if ( geometry.boundingBox !== null ) { 12823 12824 this.boundingBox = geometry.boundingBox.clone(); 12825 12826 } 12827 12828 if ( geometry.boundingSphere !== null ) { 12829 12830 this.boundingSphere = geometry.boundingSphere.clone(); 12831 12832 } 12833 12834 return this; 12835 12836 }, 12837 12838 center: function () { 12839 12840 var offset = new Vector3(); 12841 12842 return function center() { 12843 12844 this.computeBoundingBox(); 12845 12846 this.boundingBox.getCenter( offset ).negate(); 12847 12848 this.translate( offset.x, offset.y, offset.z ); 12849 12850 return this; 12851 12852 }; 12853 12854 }(), 12855 12856 normalize: function () { 12857 12858 this.computeBoundingSphere(); 12859 12860 var center = this.boundingSphere.center; 12861 var radius = this.boundingSphere.radius; 12862 12863 var s = radius === 0 ? 1 : 1.0 / radius; 12864 12865 var matrix = new Matrix4(); 12866 matrix.set( 12867 s, 0, 0, - s * center.x, 12868 0, s, 0, - s * center.y, 12869 0, 0, s, - s * center.z, 12870 0, 0, 0, 1 12871 ); 12872 12873 this.applyMatrix( matrix ); 12874 12875 return this; 12876 12877 }, 12878 12879 computeFaceNormals: function () { 12880 12881 var cb = new Vector3(), ab = new Vector3(); 12882 12883 for ( var f = 0, fl = this.faces.length; f < fl; f ++ ) { 12884 12885 var face = this.faces[ f ]; 12886 12887 var vA = this.vertices[ face.a ]; 12888 var vB = this.vertices[ face.b ]; 12889 var vC = this.vertices[ face.c ]; 12890 12891 cb.subVectors( vC, vB ); 12892 ab.subVectors( vA, vB ); 12893 cb.cross( ab ); 12894 12895 cb.normalize(); 12896 12897 face.normal.copy( cb ); 12898 12899 } 12900 12901 }, 12902 12903 computeVertexNormals: function ( areaWeighted ) { 12904 12905 if ( areaWeighted === undefined ) areaWeighted = true; 12906 12907 var v, vl, f, fl, face, vertices; 12908 12909 vertices = new Array( this.vertices.length ); 12910 12911 for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { 12912 12913 vertices[ v ] = new Vector3(); 12914 12915 } 12916 12917 if ( areaWeighted ) { 12918 12919 // vertex normals weighted by triangle areas 12920 // http://www.iquilezles.org/www/articles/normals/normals.htm 12921 12922 var vA, vB, vC; 12923 var cb = new Vector3(), ab = new Vector3(); 12924 12925 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { 12926 12927 face = this.faces[ f ]; 12928 12929 vA = this.vertices[ face.a ]; 12930 vB = this.vertices[ face.b ]; 12931 vC = this.vertices[ face.c ]; 12932 12933 cb.subVectors( vC, vB ); 12934 ab.subVectors( vA, vB ); 12935 cb.cross( ab ); 12936 12937 vertices[ face.a ].add( cb ); 12938 vertices[ face.b ].add( cb ); 12939 vertices[ face.c ].add( cb ); 12940 12941 } 12942 12943 } else { 12944 12945 this.computeFaceNormals(); 12946 12947 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { 12948 12949 face = this.faces[ f ]; 12950 12951 vertices[ face.a ].add( face.normal ); 12952 vertices[ face.b ].add( face.normal ); 12953 vertices[ face.c ].add( face.normal ); 12954 12955 } 12956 12957 } 12958 12959 for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) { 12960 12961 vertices[ v ].normalize(); 12962 12963 } 12964 12965 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { 12966 12967 face = this.faces[ f ]; 12968 12969 var vertexNormals = face.vertexNormals; 12970 12971 if ( vertexNormals.length === 3 ) { 12972 12973 vertexNormals[ 0 ].copy( vertices[ face.a ] ); 12974 vertexNormals[ 1 ].copy( vertices[ face.b ] ); 12975 vertexNormals[ 2 ].copy( vertices[ face.c ] ); 12976 12977 } else { 12978 12979 vertexNormals[ 0 ] = vertices[ face.a ].clone(); 12980 vertexNormals[ 1 ] = vertices[ face.b ].clone(); 12981 vertexNormals[ 2 ] = vertices[ face.c ].clone(); 12982 12983 } 12984 12985 } 12986 12987 if ( this.faces.length > 0 ) { 12988 12989 this.normalsNeedUpdate = true; 12990 12991 } 12992 12993 }, 12994 12995 computeFlatVertexNormals: function () { 12996 12997 var f, fl, face; 12998 12999 this.computeFaceNormals(); 13000 13001 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { 13002 13003 face = this.faces[ f ]; 13004 13005 var vertexNormals = face.vertexNormals; 13006 13007 if ( vertexNormals.length === 3 ) { 13008 13009 vertexNormals[ 0 ].copy( face.normal ); 13010 vertexNormals[ 1 ].copy( face.normal ); 13011 vertexNormals[ 2 ].copy( face.normal ); 13012 13013 } else { 13014 13015 vertexNormals[ 0 ] = face.normal.clone(); 13016 vertexNormals[ 1 ] = face.normal.clone(); 13017 vertexNormals[ 2 ] = face.normal.clone(); 13018 13019 } 13020 13021 } 13022 13023 if ( this.faces.length > 0 ) { 13024 13025 this.normalsNeedUpdate = true; 13026 13027 } 13028 13029 }, 13030 13031 computeMorphNormals: function () { 13032 13033 var i, il, f, fl, face; 13034 13035 // save original normals 13036 // - create temp variables on first access 13037 // otherwise just copy (for faster repeated calls) 13038 13039 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { 13040 13041 face = this.faces[ f ]; 13042 13043 if ( ! face.__originalFaceNormal ) { 13044 13045 face.__originalFaceNormal = face.normal.clone(); 13046 13047 } else { 13048 13049 face.__originalFaceNormal.copy( face.normal ); 13050 13051 } 13052 13053 if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = []; 13054 13055 for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) { 13056 13057 if ( ! face.__originalVertexNormals[ i ] ) { 13058 13059 face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone(); 13060 13061 } else { 13062 13063 face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] ); 13064 13065 } 13066 13067 } 13068 13069 } 13070 13071 // use temp geometry to compute face and vertex normals for each morph 13072 13073 var tmpGeo = new Geometry(); 13074 tmpGeo.faces = this.faces; 13075 13076 for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) { 13077 13078 // create on first access 13079 13080 if ( ! this.morphNormals[ i ] ) { 13081 13082 this.morphNormals[ i ] = {}; 13083 this.morphNormals[ i ].faceNormals = []; 13084 this.morphNormals[ i ].vertexNormals = []; 13085 13086 var dstNormalsFace = this.morphNormals[ i ].faceNormals; 13087 var dstNormalsVertex = this.morphNormals[ i ].vertexNormals; 13088 13089 var faceNormal, vertexNormals; 13090 13091 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { 13092 13093 faceNormal = new Vector3(); 13094 vertexNormals = { a: new Vector3(), b: new Vector3(), c: new Vector3() }; 13095 13096 dstNormalsFace.push( faceNormal ); 13097 dstNormalsVertex.push( vertexNormals ); 13098 13099 } 13100 13101 } 13102 13103 var morphNormals = this.morphNormals[ i ]; 13104 13105 // set vertices to morph target 13106 13107 tmpGeo.vertices = this.morphTargets[ i ].vertices; 13108 13109 // compute morph normals 13110 13111 tmpGeo.computeFaceNormals(); 13112 tmpGeo.computeVertexNormals(); 13113 13114 // store morph normals 13115 13116 var faceNormal, vertexNormals; 13117 13118 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { 13119 13120 face = this.faces[ f ]; 13121 13122 faceNormal = morphNormals.faceNormals[ f ]; 13123 vertexNormals = morphNormals.vertexNormals[ f ]; 13124 13125 faceNormal.copy( face.normal ); 13126 13127 vertexNormals.a.copy( face.vertexNormals[ 0 ] ); 13128 vertexNormals.b.copy( face.vertexNormals[ 1 ] ); 13129 vertexNormals.c.copy( face.vertexNormals[ 2 ] ); 13130 13131 } 13132 13133 } 13134 13135 // restore original normals 13136 13137 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) { 13138 13139 face = this.faces[ f ]; 13140 13141 face.normal = face.__originalFaceNormal; 13142 face.vertexNormals = face.__originalVertexNormals; 13143 13144 } 13145 13146 }, 13147 13148 computeBoundingBox: function () { 13149 13150 if ( this.boundingBox === null ) { 13151 13152 this.boundingBox = new Box3(); 13153 13154 } 13155 13156 this.boundingBox.setFromPoints( this.vertices ); 13157 13158 }, 13159 13160 computeBoundingSphere: function () { 13161 13162 if ( this.boundingSphere === null ) { 13163 13164 this.boundingSphere = new Sphere(); 13165 13166 } 13167 13168 this.boundingSphere.setFromPoints( this.vertices ); 13169 13170 }, 13171 13172 merge: function ( geometry, matrix, materialIndexOffset ) { 13173 13174 if ( ! ( geometry && geometry.isGeometry ) ) { 13175 13176 console.error( 'THREE.Geometry.merge(): geometry not an instance of THREE.Geometry.', geometry ); 13177 return; 13178 13179 } 13180 13181 var normalMatrix, 13182 vertexOffset = this.vertices.length, 13183 vertices1 = this.vertices, 13184 vertices2 = geometry.vertices, 13185 faces1 = this.faces, 13186 faces2 = geometry.faces, 13187 uvs1 = this.faceVertexUvs[ 0 ], 13188 uvs2 = geometry.faceVertexUvs[ 0 ], 13189 colors1 = this.colors, 13190 colors2 = geometry.colors; 13191 13192 if ( materialIndexOffset === undefined ) materialIndexOffset = 0; 13193 13194 if ( matrix !== undefined ) { 13195 13196 normalMatrix = new Matrix3().getNormalMatrix( matrix ); 13197 13198 } 13199 13200 // vertices 13201 13202 for ( var i = 0, il = vertices2.length; i < il; i ++ ) { 13203 13204 var vertex = vertices2[ i ]; 13205 13206 var vertexCopy = vertex.clone(); 13207 13208 if ( matrix !== undefined ) vertexCopy.applyMatrix4( matrix ); 13209 13210 vertices1.push( vertexCopy ); 13211 13212 } 13213 13214 // colors 13215 13216 for ( var i = 0, il = colors2.length; i < il; i ++ ) { 13217 13218 colors1.push( colors2[ i ].clone() ); 13219 13220 } 13221 13222 // faces 13223 13224 for ( i = 0, il = faces2.length; i < il; i ++ ) { 13225 13226 var face = faces2[ i ], faceCopy, normal, color, 13227 faceVertexNormals = face.vertexNormals, 13228 faceVertexColors = face.vertexColors; 13229 13230 faceCopy = new Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset ); 13231 faceCopy.normal.copy( face.normal ); 13232 13233 if ( normalMatrix !== undefined ) { 13234 13235 faceCopy.normal.applyMatrix3( normalMatrix ).normalize(); 13236 13237 } 13238 13239 for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) { 13240 13241 normal = faceVertexNormals[ j ].clone(); 13242 13243 if ( normalMatrix !== undefined ) { 13244 13245 normal.applyMatrix3( normalMatrix ).normalize(); 13246 13247 } 13248 13249 faceCopy.vertexNormals.push( normal ); 13250 13251 } 13252 13253 faceCopy.color.copy( face.color ); 13254 13255 for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) { 13256 13257 color = faceVertexColors[ j ]; 13258 faceCopy.vertexColors.push( color.clone() ); 13259 13260 } 13261 13262 faceCopy.materialIndex = face.materialIndex + materialIndexOffset; 13263 13264 faces1.push( faceCopy ); 13265 13266 } 13267 13268 // uvs 13269 13270 for ( i = 0, il = uvs2.length; i < il; i ++ ) { 13271 13272 var uv = uvs2[ i ], uvCopy = []; 13273 13274 if ( uv === undefined ) { 13275 13276 continue; 13277 13278 } 13279 13280 for ( var j = 0, jl = uv.length; j < jl; j ++ ) { 13281 13282 uvCopy.push( uv[ j ].clone() ); 13283 13284 } 13285 13286 uvs1.push( uvCopy ); 13287 13288 } 13289 13290 }, 13291 13292 mergeMesh: function ( mesh ) { 13293 13294 if ( ! ( mesh && mesh.isMesh ) ) { 13295 13296 console.error( 'THREE.Geometry.mergeMesh(): mesh not an instance of THREE.Mesh.', mesh ); 13297 return; 13298 13299 } 13300 13301 if ( mesh.matrixAutoUpdate ) mesh.updateMatrix(); 13302 13303 this.merge( mesh.geometry, mesh.matrix ); 13304 13305 }, 13306 13307 /* 13308 * Checks for duplicate vertices with hashmap. 13309 * Duplicated vertices are removed 13310 * and faces' vertices are updated. 13311 */ 13312 13313 mergeVertices: function () { 13314 13315 var verticesMap = {}; // Hashmap for looking up vertices by position coordinates (and making sure they are unique) 13316 var unique = [], changes = []; 13317 13318 var v, key; 13319 var precisionPoints = 4; // number of decimal points, e.g. 4 for epsilon of 0.0001 13320 var precision = Math.pow( 10, precisionPoints ); 13321 var i, il, face; 13322 var indices, j, jl; 13323 13324 for ( i = 0, il = this.vertices.length; i < il; i ++ ) { 13325 13326 v = this.vertices[ i ]; 13327 key = Math.round( v.x * precision ) + '_' + Math.round( v.y * precision ) + '_' + Math.round( v.z * precision ); 13328 13329 if ( verticesMap[ key ] === undefined ) { 13330 13331 verticesMap[ key ] = i; 13332 unique.push( this.vertices[ i ] ); 13333 changes[ i ] = unique.length - 1; 13334 13335 } else { 13336 13337 //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]); 13338 changes[ i ] = changes[ verticesMap[ key ] ]; 13339 13340 } 13341 13342 } 13343 13344 13345 // if faces are completely degenerate after merging vertices, we 13346 // have to remove them from the geometry. 13347 var faceIndicesToRemove = []; 13348 13349 for ( i = 0, il = this.faces.length; i < il; i ++ ) { 13350 13351 face = this.faces[ i ]; 13352 13353 face.a = changes[ face.a ]; 13354 face.b = changes[ face.b ]; 13355 face.c = changes[ face.c ]; 13356 13357 indices = [ face.a, face.b, face.c ]; 13358 13359 // if any duplicate vertices are found in a Face3 13360 // we have to remove the face as nothing can be saved 13361 for ( var n = 0; n < 3; n ++ ) { 13362 13363 if ( indices[ n ] === indices[ ( n + 1 ) % 3 ] ) { 13364 13365 faceIndicesToRemove.push( i ); 13366 break; 13367 13368 } 13369 13370 } 13371 13372 } 13373 13374 for ( i = faceIndicesToRemove.length - 1; i >= 0; i -- ) { 13375 13376 var idx = faceIndicesToRemove[ i ]; 13377 13378 this.faces.splice( idx, 1 ); 13379 13380 for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) { 13381 13382 this.faceVertexUvs[ j ].splice( idx, 1 ); 13383 13384 } 13385 13386 } 13387 13388 // Use unique set of vertices 13389 13390 var diff = this.vertices.length - unique.length; 13391 this.vertices = unique; 13392 return diff; 13393 13394 }, 13395 13396 setFromPoints: function ( points ) { 13397 13398 this.vertices = []; 13399 13400 for ( var i = 0, l = points.length; i < l; i ++ ) { 13401 13402 var point = points[ i ]; 13403 this.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) ); 13404 13405 } 13406 13407 return this; 13408 13409 }, 13410 13411 sortFacesByMaterialIndex: function () { 13412 13413 var faces = this.faces; 13414 var length = faces.length; 13415 13416 // tag faces 13417 13418 for ( var i = 0; i < length; i ++ ) { 13419 13420 faces[ i ]._id = i; 13421 13422 } 13423 13424 // sort faces 13425 13426 function materialIndexSort( a, b ) { 13427 13428 return a.materialIndex - b.materialIndex; 13429 13430 } 13431 13432 faces.sort( materialIndexSort ); 13433 13434 // sort uvs 13435 13436 var uvs1 = this.faceVertexUvs[ 0 ]; 13437 var uvs2 = this.faceVertexUvs[ 1 ]; 13438 13439 var newUvs1, newUvs2; 13440 13441 if ( uvs1 && uvs1.length === length ) newUvs1 = []; 13442 if ( uvs2 && uvs2.length === length ) newUvs2 = []; 13443 13444 for ( var i = 0; i < length; i ++ ) { 13445 13446 var id = faces[ i ]._id; 13447 13448 if ( newUvs1 ) newUvs1.push( uvs1[ id ] ); 13449 if ( newUvs2 ) newUvs2.push( uvs2[ id ] ); 13450 13451 } 13452 13453 if ( newUvs1 ) this.faceVertexUvs[ 0 ] = newUvs1; 13454 if ( newUvs2 ) this.faceVertexUvs[ 1 ] = newUvs2; 13455 13456 }, 13457 13458 toJSON: function () { 13459 13460 var data = { 13461 metadata: { 13462 version: 4.5, 13463 type: 'Geometry', 13464 generator: 'Geometry.toJSON' 13465 } 13466 }; 13467 13468 // standard Geometry serialization 13469 13470 data.uuid = this.uuid; 13471 data.type = this.type; 13472 if ( this.name !== '' ) data.name = this.name; 13473 13474 if ( this.parameters !== undefined ) { 13475 13476 var parameters = this.parameters; 13477 13478 for ( var key in parameters ) { 13479 13480 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; 13481 13482 } 13483 13484 return data; 13485 13486 } 13487 13488 var vertices = []; 13489 13490 for ( var i = 0; i < this.vertices.length; i ++ ) { 13491 13492 var vertex = this.vertices[ i ]; 13493 vertices.push( vertex.x, vertex.y, vertex.z ); 13494 13495 } 13496 13497 var faces = []; 13498 var normals = []; 13499 var normalsHash = {}; 13500 var colors = []; 13501 var colorsHash = {}; 13502 var uvs = []; 13503 var uvsHash = {}; 13504 13505 for ( var i = 0; i < this.faces.length; i ++ ) { 13506 13507 var face = this.faces[ i ]; 13508 13509 var hasMaterial = true; 13510 var hasFaceUv = false; // deprecated 13511 var hasFaceVertexUv = this.faceVertexUvs[ 0 ][ i ] !== undefined; 13512 var hasFaceNormal = face.normal.length() > 0; 13513 var hasFaceVertexNormal = face.vertexNormals.length > 0; 13514 var hasFaceColor = face.color.r !== 1 || face.color.g !== 1 || face.color.b !== 1; 13515 var hasFaceVertexColor = face.vertexColors.length > 0; 13516 13517 var faceType = 0; 13518 13519 faceType = setBit( faceType, 0, 0 ); // isQuad 13520 faceType = setBit( faceType, 1, hasMaterial ); 13521 faceType = setBit( faceType, 2, hasFaceUv ); 13522 faceType = setBit( faceType, 3, hasFaceVertexUv ); 13523 faceType = setBit( faceType, 4, hasFaceNormal ); 13524 faceType = setBit( faceType, 5, hasFaceVertexNormal ); 13525 faceType = setBit( faceType, 6, hasFaceColor ); 13526 faceType = setBit( faceType, 7, hasFaceVertexColor ); 13527 13528 faces.push( faceType ); 13529 faces.push( face.a, face.b, face.c ); 13530 faces.push( face.materialIndex ); 13531 13532 if ( hasFaceVertexUv ) { 13533 13534 var faceVertexUvs = this.faceVertexUvs[ 0 ][ i ]; 13535 13536 faces.push( 13537 getUvIndex( faceVertexUvs[ 0 ] ), 13538 getUvIndex( faceVertexUvs[ 1 ] ), 13539 getUvIndex( faceVertexUvs[ 2 ] ) 13540 ); 13541 13542 } 13543 13544 if ( hasFaceNormal ) { 13545 13546 faces.push( getNormalIndex( face.normal ) ); 13547 13548 } 13549 13550 if ( hasFaceVertexNormal ) { 13551 13552 var vertexNormals = face.vertexNormals; 13553 13554 faces.push( 13555 getNormalIndex( vertexNormals[ 0 ] ), 13556 getNormalIndex( vertexNormals[ 1 ] ), 13557 getNormalIndex( vertexNormals[ 2 ] ) 13558 ); 13559 13560 } 13561 13562 if ( hasFaceColor ) { 13563 13564 faces.push( getColorIndex( face.color ) ); 13565 13566 } 13567 13568 if ( hasFaceVertexColor ) { 13569 13570 var vertexColors = face.vertexColors; 13571 13572 faces.push( 13573 getColorIndex( vertexColors[ 0 ] ), 13574 getColorIndex( vertexColors[ 1 ] ), 13575 getColorIndex( vertexColors[ 2 ] ) 13576 ); 13577 13578 } 13579 13580 } 13581 13582 function setBit( value, position, enabled ) { 13583 13584 return enabled ? value | ( 1 << position ) : value & ( ~ ( 1 << position ) ); 13585 13586 } 13587 13588 function getNormalIndex( normal ) { 13589 13590 var hash = normal.x.toString() + normal.y.toString() + normal.z.toString(); 13591 13592 if ( normalsHash[ hash ] !== undefined ) { 13593 13594 return normalsHash[ hash ]; 13595 13596 } 13597 13598 normalsHash[ hash ] = normals.length / 3; 13599 normals.push( normal.x, normal.y, normal.z ); 13600 13601 return normalsHash[ hash ]; 13602 13603 } 13604 13605 function getColorIndex( color ) { 13606 13607 var hash = color.r.toString() + color.g.toString() + color.b.toString(); 13608 13609 if ( colorsHash[ hash ] !== undefined ) { 13610 13611 return colorsHash[ hash ]; 13612 13613 } 13614 13615 colorsHash[ hash ] = colors.length; 13616 colors.push( color.getHex() ); 13617 13618 return colorsHash[ hash ]; 13619 13620 } 13621 13622 function getUvIndex( uv ) { 13623 13624 var hash = uv.x.toString() + uv.y.toString(); 13625 13626 if ( uvsHash[ hash ] !== undefined ) { 13627 13628 return uvsHash[ hash ]; 13629 13630 } 13631 13632 uvsHash[ hash ] = uvs.length / 2; 13633 uvs.push( uv.x, uv.y ); 13634 13635 return uvsHash[ hash ]; 13636 13637 } 13638 13639 data.data = {}; 13640 13641 data.data.vertices = vertices; 13642 data.data.normals = normals; 13643 if ( colors.length > 0 ) data.data.colors = colors; 13644 if ( uvs.length > 0 ) data.data.uvs = [ uvs ]; // temporal backward compatibility 13645 data.data.faces = faces; 13646 13647 return data; 13648 13649 }, 13650 13651 clone: function () { 13652 13653 /* 13654 // Handle primitives 13655 13656 var parameters = this.parameters; 13657 13658 if ( parameters !== undefined ) { 13659 13660 var values = []; 13661 13662 for ( var key in parameters ) { 13663 13664 values.push( parameters[ key ] ); 13665 13666 } 13667 13668 var geometry = Object.create( this.constructor.prototype ); 13669 this.constructor.apply( geometry, values ); 13670 return geometry; 13671 13672 } 13673 13674 return new this.constructor().copy( this ); 13675 */ 13676 13677 return new Geometry().copy( this ); 13678 13679 }, 13680 13681 copy: function ( source ) { 13682 13683 var i, il, j, jl, k, kl; 13684 13685 // reset 13686 13687 this.vertices = []; 13688 this.colors = []; 13689 this.faces = []; 13690 this.faceVertexUvs = [[]]; 13691 this.morphTargets = []; 13692 this.morphNormals = []; 13693 this.skinWeights = []; 13694 this.skinIndices = []; 13695 this.lineDistances = []; 13696 this.boundingBox = null; 13697 this.boundingSphere = null; 13698 13699 // name 13700 13701 this.name = source.name; 13702 13703 // vertices 13704 13705 var vertices = source.vertices; 13706 13707 for ( i = 0, il = vertices.length; i < il; i ++ ) { 13708 13709 this.vertices.push( vertices[ i ].clone() ); 13710 13711 } 13712 13713 // colors 13714 13715 var colors = source.colors; 13716 13717 for ( i = 0, il = colors.length; i < il; i ++ ) { 13718 13719 this.colors.push( colors[ i ].clone() ); 13720 13721 } 13722 13723 // faces 13724 13725 var faces = source.faces; 13726 13727 for ( i = 0, il = faces.length; i < il; i ++ ) { 13728 13729 this.faces.push( faces[ i ].clone() ); 13730 13731 } 13732 13733 // face vertex uvs 13734 13735 for ( i = 0, il = source.faceVertexUvs.length; i < il; i ++ ) { 13736 13737 var faceVertexUvs = source.faceVertexUvs[ i ]; 13738 13739 if ( this.faceVertexUvs[ i ] === undefined ) { 13740 13741 this.faceVertexUvs[ i ] = []; 13742 13743 } 13744 13745 for ( j = 0, jl = faceVertexUvs.length; j < jl; j ++ ) { 13746 13747 var uvs = faceVertexUvs[ j ], uvsCopy = []; 13748 13749 for ( k = 0, kl = uvs.length; k < kl; k ++ ) { 13750 13751 var uv = uvs[ k ]; 13752 13753 uvsCopy.push( uv.clone() ); 13754 13755 } 13756 13757 this.faceVertexUvs[ i ].push( uvsCopy ); 13758 13759 } 13760 13761 } 13762 13763 // morph targets 13764 13765 var morphTargets = source.morphTargets; 13766 13767 for ( i = 0, il = morphTargets.length; i < il; i ++ ) { 13768 13769 var morphTarget = {}; 13770 morphTarget.name = morphTargets[ i ].name; 13771 13772 // vertices 13773 13774 if ( morphTargets[ i ].vertices !== undefined ) { 13775 13776 morphTarget.vertices = []; 13777 13778 for ( j = 0, jl = morphTargets[ i ].vertices.length; j < jl; j ++ ) { 13779 13780 morphTarget.vertices.push( morphTargets[ i ].vertices[ j ].clone() ); 13781 13782 } 13783 13784 } 13785 13786 // normals 13787 13788 if ( morphTargets[ i ].normals !== undefined ) { 13789 13790 morphTarget.normals = []; 13791 13792 for ( j = 0, jl = morphTargets[ i ].normals.length; j < jl; j ++ ) { 13793 13794 morphTarget.normals.push( morphTargets[ i ].normals[ j ].clone() ); 13795 13796 } 13797 13798 } 13799 13800 this.morphTargets.push( morphTarget ); 13801 13802 } 13803 13804 // morph normals 13805 13806 var morphNormals = source.morphNormals; 13807 13808 for ( i = 0, il = morphNormals.length; i < il; i ++ ) { 13809 13810 var morphNormal = {}; 13811 13812 // vertex normals 13813 13814 if ( morphNormals[ i ].vertexNormals !== undefined ) { 13815 13816 morphNormal.vertexNormals = []; 13817 13818 for ( j = 0, jl = morphNormals[ i ].vertexNormals.length; j < jl; j ++ ) { 13819 13820 var srcVertexNormal = morphNormals[ i ].vertexNormals[ j ]; 13821 var destVertexNormal = {}; 13822 13823 destVertexNormal.a = srcVertexNormal.a.clone(); 13824 destVertexNormal.b = srcVertexNormal.b.clone(); 13825 destVertexNormal.c = srcVertexNormal.c.clone(); 13826 13827 morphNormal.vertexNormals.push( destVertexNormal ); 13828 13829 } 13830 13831 } 13832 13833 // face normals 13834 13835 if ( morphNormals[ i ].faceNormals !== undefined ) { 13836 13837 morphNormal.faceNormals = []; 13838 13839 for ( j = 0, jl = morphNormals[ i ].faceNormals.length; j < jl; j ++ ) { 13840 13841 morphNormal.faceNormals.push( morphNormals[ i ].faceNormals[ j ].clone() ); 13842 13843 } 13844 13845 } 13846 13847 this.morphNormals.push( morphNormal ); 13848 13849 } 13850 13851 // skin weights 13852 13853 var skinWeights = source.skinWeights; 13854 13855 for ( i = 0, il = skinWeights.length; i < il; i ++ ) { 13856 13857 this.skinWeights.push( skinWeights[ i ].clone() ); 13858 13859 } 13860 13861 // skin indices 13862 13863 var skinIndices = source.skinIndices; 13864 13865 for ( i = 0, il = skinIndices.length; i < il; i ++ ) { 13866 13867 this.skinIndices.push( skinIndices[ i ].clone() ); 13868 13869 } 13870 13871 // line distances 13872 13873 var lineDistances = source.lineDistances; 13874 13875 for ( i = 0, il = lineDistances.length; i < il; i ++ ) { 13876 13877 this.lineDistances.push( lineDistances[ i ] ); 13878 13879 } 13880 13881 // bounding box 13882 13883 var boundingBox = source.boundingBox; 13884 13885 if ( boundingBox !== null ) { 13886 13887 this.boundingBox = boundingBox.clone(); 13888 13889 } 13890 13891 // bounding sphere 13892 13893 var boundingSphere = source.boundingSphere; 13894 13895 if ( boundingSphere !== null ) { 13896 13897 this.boundingSphere = boundingSphere.clone(); 13898 13899 } 13900 13901 // update flags 13902 13903 this.elementsNeedUpdate = source.elementsNeedUpdate; 13904 this.verticesNeedUpdate = source.verticesNeedUpdate; 13905 this.uvsNeedUpdate = source.uvsNeedUpdate; 13906 this.normalsNeedUpdate = source.normalsNeedUpdate; 13907 this.colorsNeedUpdate = source.colorsNeedUpdate; 13908 this.lineDistancesNeedUpdate = source.lineDistancesNeedUpdate; 13909 this.groupsNeedUpdate = source.groupsNeedUpdate; 13910 13911 return this; 13912 13913 }, 13914 13915 dispose: function () { 13916 13917 this.dispatchEvent( { type: 'dispose' } ); 13918 13919 } 13920 13921 } ); 13922 13923 /** 13924 * @author mrdoob / http://mrdoob.com/ 13925 */ 13926 13927 function BufferAttribute( array, itemSize, normalized ) { 13928 13929 if ( Array.isArray( array ) ) { 13930 13931 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); 13932 13933 } 13934 13935 this.name = ''; 13936 13937 this.array = array; 13938 this.itemSize = itemSize; 13939 this.count = array !== undefined ? array.length / itemSize : 0; 13940 this.normalized = normalized === true; 13941 13942 this.dynamic = false; 13943 this.updateRange = { offset: 0, count: - 1 }; 13944 13945 this.version = 0; 13946 13947 } 13948 13949 Object.defineProperty( BufferAttribute.prototype, 'needsUpdate', { 13950 13951 set: function ( value ) { 13952 13953 if ( value === true ) this.version ++; 13954 13955 } 13956 13957 } ); 13958 13959 Object.assign( BufferAttribute.prototype, { 13960 13961 isBufferAttribute: true, 13962 13963 onUploadCallback: function () {}, 13964 13965 setArray: function ( array ) { 13966 13967 if ( Array.isArray( array ) ) { 13968 13969 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); 13970 13971 } 13972 13973 this.count = array !== undefined ? array.length / this.itemSize : 0; 13974 this.array = array; 13975 13976 return this; 13977 13978 }, 13979 13980 setDynamic: function ( value ) { 13981 13982 this.dynamic = value; 13983 13984 return this; 13985 13986 }, 13987 13988 copy: function ( source ) { 13989 13990 this.name = source.name; 13991 this.array = new source.array.constructor( source.array ); 13992 this.itemSize = source.itemSize; 13993 this.count = source.count; 13994 this.normalized = source.normalized; 13995 13996 this.dynamic = source.dynamic; 13997 13998 return this; 13999 14000 }, 14001 14002 copyAt: function ( index1, attribute, index2 ) { 14003 14004 index1 *= this.itemSize; 14005 index2 *= attribute.itemSize; 14006 14007 for ( var i = 0, l = this.itemSize; i < l; i ++ ) { 14008 14009 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 14010 14011 } 14012 14013 return this; 14014 14015 }, 14016 14017 copyArray: function ( array ) { 14018 14019 this.array.set( array ); 14020 14021 return this; 14022 14023 }, 14024 14025 copyColorsArray: function ( colors ) { 14026 14027 var array = this.array, offset = 0; 14028 14029 for ( var i = 0, l = colors.length; i < l; i ++ ) { 14030 14031 var color = colors[ i ]; 14032 14033 if ( color === undefined ) { 14034 14035 console.warn( 'THREE.BufferAttribute.copyColorsArray(): color is undefined', i ); 14036 color = new Color(); 14037 14038 } 14039 14040 array[ offset ++ ] = color.r; 14041 array[ offset ++ ] = color.g; 14042 array[ offset ++ ] = color.b; 14043 14044 } 14045 14046 return this; 14047 14048 }, 14049 14050 copyVector2sArray: function ( vectors ) { 14051 14052 var array = this.array, offset = 0; 14053 14054 for ( var i = 0, l = vectors.length; i < l; i ++ ) { 14055 14056 var vector = vectors[ i ]; 14057 14058 if ( vector === undefined ) { 14059 14060 console.warn( 'THREE.BufferAttribute.copyVector2sArray(): vector is undefined', i ); 14061 vector = new Vector2(); 14062 14063 } 14064 14065 array[ offset ++ ] = vector.x; 14066 array[ offset ++ ] = vector.y; 14067 14068 } 14069 14070 return this; 14071 14072 }, 14073 14074 copyVector3sArray: function ( vectors ) { 14075 14076 var array = this.array, offset = 0; 14077 14078 for ( var i = 0, l = vectors.length; i < l; i ++ ) { 14079 14080 var vector = vectors[ i ]; 14081 14082 if ( vector === undefined ) { 14083 14084 console.warn( 'THREE.BufferAttribute.copyVector3sArray(): vector is undefined', i ); 14085 vector = new Vector3(); 14086 14087 } 14088 14089 array[ offset ++ ] = vector.x; 14090 array[ offset ++ ] = vector.y; 14091 array[ offset ++ ] = vector.z; 14092 14093 } 14094 14095 return this; 14096 14097 }, 14098 14099 copyVector4sArray: function ( vectors ) { 14100 14101 var array = this.array, offset = 0; 14102 14103 for ( var i = 0, l = vectors.length; i < l; i ++ ) { 14104 14105 var vector = vectors[ i ]; 14106 14107 if ( vector === undefined ) { 14108 14109 console.warn( 'THREE.BufferAttribute.copyVector4sArray(): vector is undefined', i ); 14110 vector = new Vector4(); 14111 14112 } 14113 14114 array[ offset ++ ] = vector.x; 14115 array[ offset ++ ] = vector.y; 14116 array[ offset ++ ] = vector.z; 14117 array[ offset ++ ] = vector.w; 14118 14119 } 14120 14121 return this; 14122 14123 }, 14124 14125 set: function ( value, offset ) { 14126 14127 if ( offset === undefined ) offset = 0; 14128 14129 this.array.set( value, offset ); 14130 14131 return this; 14132 14133 }, 14134 14135 getX: function ( index ) { 14136 14137 return this.array[ index * this.itemSize ]; 14138 14139 }, 14140 14141 setX: function ( index, x ) { 14142 14143 this.array[ index * this.itemSize ] = x; 14144 14145 return this; 14146 14147 }, 14148 14149 getY: function ( index ) { 14150 14151 return this.array[ index * this.itemSize + 1 ]; 14152 14153 }, 14154 14155 setY: function ( index, y ) { 14156 14157 this.array[ index * this.itemSize + 1 ] = y; 14158 14159 return this; 14160 14161 }, 14162 14163 getZ: function ( index ) { 14164 14165 return this.array[ index * this.itemSize + 2 ]; 14166 14167 }, 14168 14169 setZ: function ( index, z ) { 14170 14171 this.array[ index * this.itemSize + 2 ] = z; 14172 14173 return this; 14174 14175 }, 14176 14177 getW: function ( index ) { 14178 14179 return this.array[ index * this.itemSize + 3 ]; 14180 14181 }, 14182 14183 setW: function ( index, w ) { 14184 14185 this.array[ index * this.itemSize + 3 ] = w; 14186 14187 return this; 14188 14189 }, 14190 14191 setXY: function ( index, x, y ) { 14192 14193 index *= this.itemSize; 14194 14195 this.array[ index + 0 ] = x; 14196 this.array[ index + 1 ] = y; 14197 14198 return this; 14199 14200 }, 14201 14202 setXYZ: function ( index, x, y, z ) { 14203 14204 index *= this.itemSize; 14205 14206 this.array[ index + 0 ] = x; 14207 this.array[ index + 1 ] = y; 14208 this.array[ index + 2 ] = z; 14209 14210 return this; 14211 14212 }, 14213 14214 setXYZW: function ( index, x, y, z, w ) { 14215 14216 index *= this.itemSize; 14217 14218 this.array[ index + 0 ] = x; 14219 this.array[ index + 1 ] = y; 14220 this.array[ index + 2 ] = z; 14221 this.array[ index + 3 ] = w; 14222 14223 return this; 14224 14225 }, 14226 14227 onUpload: function ( callback ) { 14228 14229 this.onUploadCallback = callback; 14230 14231 return this; 14232 14233 }, 14234 14235 clone: function () { 14236 14237 return new this.constructor( this.array, this.itemSize ).copy( this ); 14238 14239 } 14240 14241 } ); 14242 14243 // 14244 14245 function Int8BufferAttribute( array, itemSize, normalized ) { 14246 14247 BufferAttribute.call( this, new Int8Array( array ), itemSize, normalized ); 14248 14249 } 14250 14251 Int8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); 14252 Int8BufferAttribute.prototype.constructor = Int8BufferAttribute; 14253 14254 14255 function Uint8BufferAttribute( array, itemSize, normalized ) { 14256 14257 BufferAttribute.call( this, new Uint8Array( array ), itemSize, normalized ); 14258 14259 } 14260 14261 Uint8BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); 14262 Uint8BufferAttribute.prototype.constructor = Uint8BufferAttribute; 14263 14264 14265 function Uint8ClampedBufferAttribute( array, itemSize, normalized ) { 14266 14267 BufferAttribute.call( this, new Uint8ClampedArray( array ), itemSize, normalized ); 14268 14269 } 14270 14271 Uint8ClampedBufferAttribute.prototype = Object.create( BufferAttribute.prototype ); 14272 Uint8ClampedBufferAttribute.prototype.constructor = Uint8ClampedBufferAttribute; 14273 14274 14275 function Int16BufferAttribute( array, itemSize, normalized ) { 14276 14277 BufferAttribute.call( this, new Int16Array( array ), itemSize, normalized ); 14278 14279 } 14280 14281 Int16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); 14282 Int16BufferAttribute.prototype.constructor = Int16BufferAttribute; 14283 14284 14285 function Uint16BufferAttribute( array, itemSize, normalized ) { 14286 14287 BufferAttribute.call( this, new Uint16Array( array ), itemSize, normalized ); 14288 14289 } 14290 14291 Uint16BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); 14292 Uint16BufferAttribute.prototype.constructor = Uint16BufferAttribute; 14293 14294 14295 function Int32BufferAttribute( array, itemSize, normalized ) { 14296 14297 BufferAttribute.call( this, new Int32Array( array ), itemSize, normalized ); 14298 14299 } 14300 14301 Int32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); 14302 Int32BufferAttribute.prototype.constructor = Int32BufferAttribute; 14303 14304 14305 function Uint32BufferAttribute( array, itemSize, normalized ) { 14306 14307 BufferAttribute.call( this, new Uint32Array( array ), itemSize, normalized ); 14308 14309 } 14310 14311 Uint32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); 14312 Uint32BufferAttribute.prototype.constructor = Uint32BufferAttribute; 14313 14314 14315 function Float32BufferAttribute( array, itemSize, normalized ) { 14316 14317 BufferAttribute.call( this, new Float32Array( array ), itemSize, normalized ); 14318 14319 } 14320 14321 Float32BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); 14322 Float32BufferAttribute.prototype.constructor = Float32BufferAttribute; 14323 14324 14325 function Float64BufferAttribute( array, itemSize, normalized ) { 14326 14327 BufferAttribute.call( this, new Float64Array( array ), itemSize, normalized ); 14328 14329 } 14330 14331 Float64BufferAttribute.prototype = Object.create( BufferAttribute.prototype ); 14332 Float64BufferAttribute.prototype.constructor = Float64BufferAttribute; 14333 14334 /** 14335 * @author mrdoob / http://mrdoob.com/ 14336 */ 14337 14338 function DirectGeometry() { 14339 14340 this.vertices = []; 14341 this.normals = []; 14342 this.colors = []; 14343 this.uvs = []; 14344 this.uvs2 = []; 14345 14346 this.groups = []; 14347 14348 this.morphTargets = {}; 14349 14350 this.skinWeights = []; 14351 this.skinIndices = []; 14352 14353 // this.lineDistances = []; 14354 14355 this.boundingBox = null; 14356 this.boundingSphere = null; 14357 14358 // update flags 14359 14360 this.verticesNeedUpdate = false; 14361 this.normalsNeedUpdate = false; 14362 this.colorsNeedUpdate = false; 14363 this.uvsNeedUpdate = false; 14364 this.groupsNeedUpdate = false; 14365 14366 } 14367 14368 Object.assign( DirectGeometry.prototype, { 14369 14370 computeGroups: function ( geometry ) { 14371 14372 var group; 14373 var groups = []; 14374 var materialIndex = undefined; 14375 14376 var faces = geometry.faces; 14377 14378 for ( var i = 0; i < faces.length; i ++ ) { 14379 14380 var face = faces[ i ]; 14381 14382 // materials 14383 14384 if ( face.materialIndex !== materialIndex ) { 14385 14386 materialIndex = face.materialIndex; 14387 14388 if ( group !== undefined ) { 14389 14390 group.count = ( i * 3 ) - group.start; 14391 groups.push( group ); 14392 14393 } 14394 14395 group = { 14396 start: i * 3, 14397 materialIndex: materialIndex 14398 }; 14399 14400 } 14401 14402 } 14403 14404 if ( group !== undefined ) { 14405 14406 group.count = ( i * 3 ) - group.start; 14407 groups.push( group ); 14408 14409 } 14410 14411 this.groups = groups; 14412 14413 }, 14414 14415 fromGeometry: function ( geometry ) { 14416 14417 var faces = geometry.faces; 14418 var vertices = geometry.vertices; 14419 var faceVertexUvs = geometry.faceVertexUvs; 14420 14421 var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0; 14422 var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0; 14423 14424 // morphs 14425 14426 var morphTargets = geometry.morphTargets; 14427 var morphTargetsLength = morphTargets.length; 14428 14429 var morphTargetsPosition; 14430 14431 if ( morphTargetsLength > 0 ) { 14432 14433 morphTargetsPosition = []; 14434 14435 for ( var i = 0; i < morphTargetsLength; i ++ ) { 14436 14437 morphTargetsPosition[ i ] = []; 14438 14439 } 14440 14441 this.morphTargets.position = morphTargetsPosition; 14442 14443 } 14444 14445 var morphNormals = geometry.morphNormals; 14446 var morphNormalsLength = morphNormals.length; 14447 14448 var morphTargetsNormal; 14449 14450 if ( morphNormalsLength > 0 ) { 14451 14452 morphTargetsNormal = []; 14453 14454 for ( var i = 0; i < morphNormalsLength; i ++ ) { 14455 14456 morphTargetsNormal[ i ] = []; 14457 14458 } 14459 14460 this.morphTargets.normal = morphTargetsNormal; 14461 14462 } 14463 14464 // skins 14465 14466 var skinIndices = geometry.skinIndices; 14467 var skinWeights = geometry.skinWeights; 14468 14469 var hasSkinIndices = skinIndices.length === vertices.length; 14470 var hasSkinWeights = skinWeights.length === vertices.length; 14471 14472 // 14473 14474 if ( faces.length === 0 ) { 14475 14476 console.error( 'THREE.DirectGeometry: Faceless geometries are not supported.' ); 14477 14478 } 14479 14480 for ( var i = 0; i < faces.length; i ++ ) { 14481 14482 var face = faces[ i ]; 14483 14484 this.vertices.push( vertices[ face.a ], vertices[ face.b ], vertices[ face.c ] ); 14485 14486 var vertexNormals = face.vertexNormals; 14487 14488 if ( vertexNormals.length === 3 ) { 14489 14490 this.normals.push( vertexNormals[ 0 ], vertexNormals[ 1 ], vertexNormals[ 2 ] ); 14491 14492 } else { 14493 14494 var normal = face.normal; 14495 14496 this.normals.push( normal, normal, normal ); 14497 14498 } 14499 14500 var vertexColors = face.vertexColors; 14501 14502 if ( vertexColors.length === 3 ) { 14503 14504 this.colors.push( vertexColors[ 0 ], vertexColors[ 1 ], vertexColors[ 2 ] ); 14505 14506 } else { 14507 14508 var color = face.color; 14509 14510 this.colors.push( color, color, color ); 14511 14512 } 14513 14514 if ( hasFaceVertexUv === true ) { 14515 14516 var vertexUvs = faceVertexUvs[ 0 ][ i ]; 14517 14518 if ( vertexUvs !== undefined ) { 14519 14520 this.uvs.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); 14521 14522 } else { 14523 14524 console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i ); 14525 14526 this.uvs.push( new Vector2(), new Vector2(), new Vector2() ); 14527 14528 } 14529 14530 } 14531 14532 if ( hasFaceVertexUv2 === true ) { 14533 14534 var vertexUvs = faceVertexUvs[ 1 ][ i ]; 14535 14536 if ( vertexUvs !== undefined ) { 14537 14538 this.uvs2.push( vertexUvs[ 0 ], vertexUvs[ 1 ], vertexUvs[ 2 ] ); 14539 14540 } else { 14541 14542 console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i ); 14543 14544 this.uvs2.push( new Vector2(), new Vector2(), new Vector2() ); 14545 14546 } 14547 14548 } 14549 14550 // morphs 14551 14552 for ( var j = 0; j < morphTargetsLength; j ++ ) { 14553 14554 var morphTarget = morphTargets[ j ].vertices; 14555 14556 morphTargetsPosition[ j ].push( morphTarget[ face.a ], morphTarget[ face.b ], morphTarget[ face.c ] ); 14557 14558 } 14559 14560 for ( var j = 0; j < morphNormalsLength; j ++ ) { 14561 14562 var morphNormal = morphNormals[ j ].vertexNormals[ i ]; 14563 14564 morphTargetsNormal[ j ].push( morphNormal.a, morphNormal.b, morphNormal.c ); 14565 14566 } 14567 14568 // skins 14569 14570 if ( hasSkinIndices ) { 14571 14572 this.skinIndices.push( skinIndices[ face.a ], skinIndices[ face.b ], skinIndices[ face.c ] ); 14573 14574 } 14575 14576 if ( hasSkinWeights ) { 14577 14578 this.skinWeights.push( skinWeights[ face.a ], skinWeights[ face.b ], skinWeights[ face.c ] ); 14579 14580 } 14581 14582 } 14583 14584 this.computeGroups( geometry ); 14585 14586 this.verticesNeedUpdate = geometry.verticesNeedUpdate; 14587 this.normalsNeedUpdate = geometry.normalsNeedUpdate; 14588 this.colorsNeedUpdate = geometry.colorsNeedUpdate; 14589 this.uvsNeedUpdate = geometry.uvsNeedUpdate; 14590 this.groupsNeedUpdate = geometry.groupsNeedUpdate; 14591 14592 return this; 14593 14594 } 14595 14596 } ); 14597 14598 /** 14599 * @author mrdoob / http://mrdoob.com/ 14600 */ 14601 14602 function arrayMax( array ) { 14603 14604 if ( array.length === 0 ) return - Infinity; 14605 14606 var max = array[ 0 ]; 14607 14608 for ( var i = 1, l = array.length; i < l; ++ i ) { 14609 14610 if ( array[ i ] > max ) max = array[ i ]; 14611 14612 } 14613 14614 return max; 14615 14616 } 14617 14618 /** 14619 * @author alteredq / http://alteredqualia.com/ 14620 * @author mrdoob / http://mrdoob.com/ 14621 */ 14622 14623 var bufferGeometryId = 1; // BufferGeometry uses odd numbers as Id 14624 14625 function BufferGeometry() { 14626 14627 Object.defineProperty( this, 'id', { value: bufferGeometryId += 2 } ); 14628 14629 this.uuid = _Math.generateUUID(); 14630 14631 this.name = ''; 14632 this.type = 'BufferGeometry'; 14633 14634 this.index = null; 14635 this.attributes = {}; 14636 14637 this.morphAttributes = {}; 14638 14639 this.groups = []; 14640 14641 this.boundingBox = null; 14642 this.boundingSphere = null; 14643 14644 this.drawRange = { start: 0, count: Infinity }; 14645 14646 this.userData = {}; 14647 14648 } 14649 14650 BufferGeometry.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { 14651 14652 constructor: BufferGeometry, 14653 14654 isBufferGeometry: true, 14655 14656 getIndex: function () { 14657 14658 return this.index; 14659 14660 }, 14661 14662 setIndex: function ( index ) { 14663 14664 if ( Array.isArray( index ) ) { 14665 14666 this.index = new ( arrayMax( index ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); 14667 14668 } else { 14669 14670 this.index = index; 14671 14672 } 14673 14674 }, 14675 14676 addAttribute: function ( name, attribute ) { 14677 14678 if ( ! ( attribute && attribute.isBufferAttribute ) && ! ( attribute && attribute.isInterleavedBufferAttribute ) ) { 14679 14680 console.warn( 'THREE.BufferGeometry: .addAttribute() now expects ( name, attribute ).' ); 14681 14682 return this.addAttribute( name, new BufferAttribute( arguments[ 1 ], arguments[ 2 ] ) ); 14683 14684 } 14685 14686 if ( name === 'index' ) { 14687 14688 console.warn( 'THREE.BufferGeometry.addAttribute: Use .setIndex() for index attribute.' ); 14689 this.setIndex( attribute ); 14690 14691 return this; 14692 14693 } 14694 14695 this.attributes[ name ] = attribute; 14696 14697 return this; 14698 14699 }, 14700 14701 getAttribute: function ( name ) { 14702 14703 return this.attributes[ name ]; 14704 14705 }, 14706 14707 removeAttribute: function ( name ) { 14708 14709 delete this.attributes[ name ]; 14710 14711 return this; 14712 14713 }, 14714 14715 addGroup: function ( start, count, materialIndex ) { 14716 14717 this.groups.push( { 14718 14719 start: start, 14720 count: count, 14721 materialIndex: materialIndex !== undefined ? materialIndex : 0 14722 14723 } ); 14724 14725 }, 14726 14727 clearGroups: function () { 14728 14729 this.groups = []; 14730 14731 }, 14732 14733 setDrawRange: function ( start, count ) { 14734 14735 this.drawRange.start = start; 14736 this.drawRange.count = count; 14737 14738 }, 14739 14740 applyMatrix: function ( matrix ) { 14741 14742 var position = this.attributes.position; 14743 14744 if ( position !== undefined ) { 14745 14746 matrix.applyToBufferAttribute( position ); 14747 position.needsUpdate = true; 14748 14749 } 14750 14751 var normal = this.attributes.normal; 14752 14753 if ( normal !== undefined ) { 14754 14755 var normalMatrix = new Matrix3().getNormalMatrix( matrix ); 14756 14757 normalMatrix.applyToBufferAttribute( normal ); 14758 normal.needsUpdate = true; 14759 14760 } 14761 14762 if ( this.boundingBox !== null ) { 14763 14764 this.computeBoundingBox(); 14765 14766 } 14767 14768 if ( this.boundingSphere !== null ) { 14769 14770 this.computeBoundingSphere(); 14771 14772 } 14773 14774 return this; 14775 14776 }, 14777 14778 rotateX: function () { 14779 14780 // rotate geometry around world x-axis 14781 14782 var m1 = new Matrix4(); 14783 14784 return function rotateX( angle ) { 14785 14786 m1.makeRotationX( angle ); 14787 14788 this.applyMatrix( m1 ); 14789 14790 return this; 14791 14792 }; 14793 14794 }(), 14795 14796 rotateY: function () { 14797 14798 // rotate geometry around world y-axis 14799 14800 var m1 = new Matrix4(); 14801 14802 return function rotateY( angle ) { 14803 14804 m1.makeRotationY( angle ); 14805 14806 this.applyMatrix( m1 ); 14807 14808 return this; 14809 14810 }; 14811 14812 }(), 14813 14814 rotateZ: function () { 14815 14816 // rotate geometry around world z-axis 14817 14818 var m1 = new Matrix4(); 14819 14820 return function rotateZ( angle ) { 14821 14822 m1.makeRotationZ( angle ); 14823 14824 this.applyMatrix( m1 ); 14825 14826 return this; 14827 14828 }; 14829 14830 }(), 14831 14832 translate: function () { 14833 14834 // translate geometry 14835 14836 var m1 = new Matrix4(); 14837 14838 return function translate( x, y, z ) { 14839 14840 m1.makeTranslation( x, y, z ); 14841 14842 this.applyMatrix( m1 ); 14843 14844 return this; 14845 14846 }; 14847 14848 }(), 14849 14850 scale: function () { 14851 14852 // scale geometry 14853 14854 var m1 = new Matrix4(); 14855 14856 return function scale( x, y, z ) { 14857 14858 m1.makeScale( x, y, z ); 14859 14860 this.applyMatrix( m1 ); 14861 14862 return this; 14863 14864 }; 14865 14866 }(), 14867 14868 lookAt: function () { 14869 14870 var obj = new Object3D(); 14871 14872 return function lookAt( vector ) { 14873 14874 obj.lookAt( vector ); 14875 14876 obj.updateMatrix(); 14877 14878 this.applyMatrix( obj.matrix ); 14879 14880 }; 14881 14882 }(), 14883 14884 center: function () { 14885 14886 var offset = new Vector3(); 14887 14888 return function center() { 14889 14890 this.computeBoundingBox(); 14891 14892 this.boundingBox.getCenter( offset ).negate(); 14893 14894 this.translate( offset.x, offset.y, offset.z ); 14895 14896 return this; 14897 14898 }; 14899 14900 }(), 14901 14902 setFromObject: function ( object ) { 14903 14904 // console.log( 'THREE.BufferGeometry.setFromObject(). Converting', object, this ); 14905 14906 var geometry = object.geometry; 14907 14908 if ( object.isPoints || object.isLine ) { 14909 14910 var positions = new Float32BufferAttribute( geometry.vertices.length * 3, 3 ); 14911 var colors = new Float32BufferAttribute( geometry.colors.length * 3, 3 ); 14912 14913 this.addAttribute( 'position', positions.copyVector3sArray( geometry.vertices ) ); 14914 this.addAttribute( 'color', colors.copyColorsArray( geometry.colors ) ); 14915 14916 if ( geometry.lineDistances && geometry.lineDistances.length === geometry.vertices.length ) { 14917 14918 var lineDistances = new Float32BufferAttribute( geometry.lineDistances.length, 1 ); 14919 14920 this.addAttribute( 'lineDistance', lineDistances.copyArray( geometry.lineDistances ) ); 14921 14922 } 14923 14924 if ( geometry.boundingSphere !== null ) { 14925 14926 this.boundingSphere = geometry.boundingSphere.clone(); 14927 14928 } 14929 14930 if ( geometry.boundingBox !== null ) { 14931 14932 this.boundingBox = geometry.boundingBox.clone(); 14933 14934 } 14935 14936 } else if ( object.isMesh ) { 14937 14938 if ( geometry && geometry.isGeometry ) { 14939 14940 this.fromGeometry( geometry ); 14941 14942 } 14943 14944 } 14945 14946 return this; 14947 14948 }, 14949 14950 setFromPoints: function ( points ) { 14951 14952 var position = []; 14953 14954 for ( var i = 0, l = points.length; i < l; i ++ ) { 14955 14956 var point = points[ i ]; 14957 position.push( point.x, point.y, point.z || 0 ); 14958 14959 } 14960 14961 this.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); 14962 14963 return this; 14964 14965 }, 14966 14967 updateFromObject: function ( object ) { 14968 14969 var geometry = object.geometry; 14970 14971 if ( object.isMesh ) { 14972 14973 var direct = geometry.__directGeometry; 14974 14975 if ( geometry.elementsNeedUpdate === true ) { 14976 14977 direct = undefined; 14978 geometry.elementsNeedUpdate = false; 14979 14980 } 14981 14982 if ( direct === undefined ) { 14983 14984 return this.fromGeometry( geometry ); 14985 14986 } 14987 14988 direct.verticesNeedUpdate = geometry.verticesNeedUpdate; 14989 direct.normalsNeedUpdate = geometry.normalsNeedUpdate; 14990 direct.colorsNeedUpdate = geometry.colorsNeedUpdate; 14991 direct.uvsNeedUpdate = geometry.uvsNeedUpdate; 14992 direct.groupsNeedUpdate = geometry.groupsNeedUpdate; 14993 14994 geometry.verticesNeedUpdate = false; 14995 geometry.normalsNeedUpdate = false; 14996 geometry.colorsNeedUpdate = false; 14997 geometry.uvsNeedUpdate = false; 14998 geometry.groupsNeedUpdate = false; 14999 15000 geometry = direct; 15001 15002 } 15003 15004 var attribute; 15005 15006 if ( geometry.verticesNeedUpdate === true ) { 15007 15008 attribute = this.attributes.position; 15009 15010 if ( attribute !== undefined ) { 15011 15012 attribute.copyVector3sArray( geometry.vertices ); 15013 attribute.needsUpdate = true; 15014 15015 } 15016 15017 geometry.verticesNeedUpdate = false; 15018 15019 } 15020 15021 if ( geometry.normalsNeedUpdate === true ) { 15022 15023 attribute = this.attributes.normal; 15024 15025 if ( attribute !== undefined ) { 15026 15027 attribute.copyVector3sArray( geometry.normals ); 15028 attribute.needsUpdate = true; 15029 15030 } 15031 15032 geometry.normalsNeedUpdate = false; 15033 15034 } 15035 15036 if ( geometry.colorsNeedUpdate === true ) { 15037 15038 attribute = this.attributes.color; 15039 15040 if ( attribute !== undefined ) { 15041 15042 attribute.copyColorsArray( geometry.colors ); 15043 attribute.needsUpdate = true; 15044 15045 } 15046 15047 geometry.colorsNeedUpdate = false; 15048 15049 } 15050 15051 if ( geometry.uvsNeedUpdate ) { 15052 15053 attribute = this.attributes.uv; 15054 15055 if ( attribute !== undefined ) { 15056 15057 attribute.copyVector2sArray( geometry.uvs ); 15058 attribute.needsUpdate = true; 15059 15060 } 15061 15062 geometry.uvsNeedUpdate = false; 15063 15064 } 15065 15066 if ( geometry.lineDistancesNeedUpdate ) { 15067 15068 attribute = this.attributes.lineDistance; 15069 15070 if ( attribute !== undefined ) { 15071 15072 attribute.copyArray( geometry.lineDistances ); 15073 attribute.needsUpdate = true; 15074 15075 } 15076 15077 geometry.lineDistancesNeedUpdate = false; 15078 15079 } 15080 15081 if ( geometry.groupsNeedUpdate ) { 15082 15083 geometry.computeGroups( object.geometry ); 15084 this.groups = geometry.groups; 15085 15086 geometry.groupsNeedUpdate = false; 15087 15088 } 15089 15090 return this; 15091 15092 }, 15093 15094 fromGeometry: function ( geometry ) { 15095 15096 geometry.__directGeometry = new DirectGeometry().fromGeometry( geometry ); 15097 15098 return this.fromDirectGeometry( geometry.__directGeometry ); 15099 15100 }, 15101 15102 fromDirectGeometry: function ( geometry ) { 15103 15104 var positions = new Float32Array( geometry.vertices.length * 3 ); 15105 this.addAttribute( 'position', new BufferAttribute( positions, 3 ).copyVector3sArray( geometry.vertices ) ); 15106 15107 if ( geometry.normals.length > 0 ) { 15108 15109 var normals = new Float32Array( geometry.normals.length * 3 ); 15110 this.addAttribute( 'normal', new BufferAttribute( normals, 3 ).copyVector3sArray( geometry.normals ) ); 15111 15112 } 15113 15114 if ( geometry.colors.length > 0 ) { 15115 15116 var colors = new Float32Array( geometry.colors.length * 3 ); 15117 this.addAttribute( 'color', new BufferAttribute( colors, 3 ).copyColorsArray( geometry.colors ) ); 15118 15119 } 15120 15121 if ( geometry.uvs.length > 0 ) { 15122 15123 var uvs = new Float32Array( geometry.uvs.length * 2 ); 15124 this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ).copyVector2sArray( geometry.uvs ) ); 15125 15126 } 15127 15128 if ( geometry.uvs2.length > 0 ) { 15129 15130 var uvs2 = new Float32Array( geometry.uvs2.length * 2 ); 15131 this.addAttribute( 'uv2', new BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) ); 15132 15133 } 15134 15135 // groups 15136 15137 this.groups = geometry.groups; 15138 15139 // morphs 15140 15141 for ( var name in geometry.morphTargets ) { 15142 15143 var array = []; 15144 var morphTargets = geometry.morphTargets[ name ]; 15145 15146 for ( var i = 0, l = morphTargets.length; i < l; i ++ ) { 15147 15148 var morphTarget = morphTargets[ i ]; 15149 15150 var attribute = new Float32BufferAttribute( morphTarget.length * 3, 3 ); 15151 15152 array.push( attribute.copyVector3sArray( morphTarget ) ); 15153 15154 } 15155 15156 this.morphAttributes[ name ] = array; 15157 15158 } 15159 15160 // skinning 15161 15162 if ( geometry.skinIndices.length > 0 ) { 15163 15164 var skinIndices = new Float32BufferAttribute( geometry.skinIndices.length * 4, 4 ); 15165 this.addAttribute( 'skinIndex', skinIndices.copyVector4sArray( geometry.skinIndices ) ); 15166 15167 } 15168 15169 if ( geometry.skinWeights.length > 0 ) { 15170 15171 var skinWeights = new Float32BufferAttribute( geometry.skinWeights.length * 4, 4 ); 15172 this.addAttribute( 'skinWeight', skinWeights.copyVector4sArray( geometry.skinWeights ) ); 15173 15174 } 15175 15176 // 15177 15178 if ( geometry.boundingSphere !== null ) { 15179 15180 this.boundingSphere = geometry.boundingSphere.clone(); 15181 15182 } 15183 15184 if ( geometry.boundingBox !== null ) { 15185 15186 this.boundingBox = geometry.boundingBox.clone(); 15187 15188 } 15189 15190 return this; 15191 15192 }, 15193 15194 computeBoundingBox: function () { 15195 15196 if ( this.boundingBox === null ) { 15197 15198 this.boundingBox = new Box3(); 15199 15200 } 15201 15202 var position = this.attributes.position; 15203 15204 if ( position !== undefined ) { 15205 15206 this.boundingBox.setFromBufferAttribute( position ); 15207 15208 } else { 15209 15210 this.boundingBox.makeEmpty(); 15211 15212 } 15213 15214 if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { 15215 15216 console.error( 'THREE.BufferGeometry.computeBoundingBox: Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); 15217 15218 } 15219 15220 }, 15221 15222 computeBoundingSphere: function () { 15223 15224 var box = new Box3(); 15225 var vector = new Vector3(); 15226 15227 return function computeBoundingSphere() { 15228 15229 if ( this.boundingSphere === null ) { 15230 15231 this.boundingSphere = new Sphere(); 15232 15233 } 15234 15235 var position = this.attributes.position; 15236 15237 if ( position ) { 15238 15239 var center = this.boundingSphere.center; 15240 15241 box.setFromBufferAttribute( position ); 15242 box.getCenter( center ); 15243 15244 // hoping to find a boundingSphere with a radius smaller than the 15245 // boundingSphere of the boundingBox: sqrt(3) smaller in the best case 15246 15247 var maxRadiusSq = 0; 15248 15249 for ( var i = 0, il = position.count; i < il; i ++ ) { 15250 15251 vector.x = position.getX( i ); 15252 vector.y = position.getY( i ); 15253 vector.z = position.getZ( i ); 15254 maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); 15255 15256 } 15257 15258 this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); 15259 15260 if ( isNaN( this.boundingSphere.radius ) ) { 15261 15262 console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); 15263 15264 } 15265 15266 } 15267 15268 }; 15269 15270 }(), 15271 15272 computeFaceNormals: function () { 15273 15274 // backwards compatibility 15275 15276 }, 15277 15278 computeVertexNormals: function () { 15279 15280 var index = this.index; 15281 var attributes = this.attributes; 15282 var groups = this.groups; 15283 15284 if ( attributes.position ) { 15285 15286 var positions = attributes.position.array; 15287 15288 if ( attributes.normal === undefined ) { 15289 15290 this.addAttribute( 'normal', new BufferAttribute( new Float32Array( positions.length ), 3 ) ); 15291 15292 } else { 15293 15294 // reset existing normals to zero 15295 15296 var array = attributes.normal.array; 15297 15298 for ( var i = 0, il = array.length; i < il; i ++ ) { 15299 15300 array[ i ] = 0; 15301 15302 } 15303 15304 } 15305 15306 var normals = attributes.normal.array; 15307 15308 var vA, vB, vC; 15309 var pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); 15310 var cb = new Vector3(), ab = new Vector3(); 15311 15312 // indexed elements 15313 15314 if ( index ) { 15315 15316 var indices = index.array; 15317 15318 if ( groups.length === 0 ) { 15319 15320 this.addGroup( 0, indices.length ); 15321 15322 } 15323 15324 for ( var j = 0, jl = groups.length; j < jl; ++ j ) { 15325 15326 var group = groups[ j ]; 15327 15328 var start = group.start; 15329 var count = group.count; 15330 15331 for ( var i = start, il = start + count; i < il; i += 3 ) { 15332 15333 vA = indices[ i + 0 ] * 3; 15334 vB = indices[ i + 1 ] * 3; 15335 vC = indices[ i + 2 ] * 3; 15336 15337 pA.fromArray( positions, vA ); 15338 pB.fromArray( positions, vB ); 15339 pC.fromArray( positions, vC ); 15340 15341 cb.subVectors( pC, pB ); 15342 ab.subVectors( pA, pB ); 15343 cb.cross( ab ); 15344 15345 normals[ vA ] += cb.x; 15346 normals[ vA + 1 ] += cb.y; 15347 normals[ vA + 2 ] += cb.z; 15348 15349 normals[ vB ] += cb.x; 15350 normals[ vB + 1 ] += cb.y; 15351 normals[ vB + 2 ] += cb.z; 15352 15353 normals[ vC ] += cb.x; 15354 normals[ vC + 1 ] += cb.y; 15355 normals[ vC + 2 ] += cb.z; 15356 15357 } 15358 15359 } 15360 15361 } else { 15362 15363 // non-indexed elements (unconnected triangle soup) 15364 15365 for ( var i = 0, il = positions.length; i < il; i += 9 ) { 15366 15367 pA.fromArray( positions, i ); 15368 pB.fromArray( positions, i + 3 ); 15369 pC.fromArray( positions, i + 6 ); 15370 15371 cb.subVectors( pC, pB ); 15372 ab.subVectors( pA, pB ); 15373 cb.cross( ab ); 15374 15375 normals[ i ] = cb.x; 15376 normals[ i + 1 ] = cb.y; 15377 normals[ i + 2 ] = cb.z; 15378 15379 normals[ i + 3 ] = cb.x; 15380 normals[ i + 4 ] = cb.y; 15381 normals[ i + 5 ] = cb.z; 15382 15383 normals[ i + 6 ] = cb.x; 15384 normals[ i + 7 ] = cb.y; 15385 normals[ i + 8 ] = cb.z; 15386 15387 } 15388 15389 } 15390 15391 this.normalizeNormals(); 15392 15393 attributes.normal.needsUpdate = true; 15394 15395 } 15396 15397 }, 15398 15399 merge: function ( geometry, offset ) { 15400 15401 if ( ! ( geometry && geometry.isBufferGeometry ) ) { 15402 15403 console.error( 'THREE.BufferGeometry.merge(): geometry not an instance of THREE.BufferGeometry.', geometry ); 15404 return; 15405 15406 } 15407 15408 if ( offset === undefined ) { 15409 15410 offset = 0; 15411 15412 console.warn( 15413 'THREE.BufferGeometry.merge(): Overwriting original geometry, starting at offset=0. ' 15414 + 'Use BufferGeometryUtils.mergeBufferGeometries() for lossless merge.' 15415 ); 15416 15417 } 15418 15419 var attributes = this.attributes; 15420 15421 for ( var key in attributes ) { 15422 15423 if ( geometry.attributes[ key ] === undefined ) continue; 15424 15425 var attribute1 = attributes[ key ]; 15426 var attributeArray1 = attribute1.array; 15427 15428 var attribute2 = geometry.attributes[ key ]; 15429 var attributeArray2 = attribute2.array; 15430 15431 var attributeSize = attribute2.itemSize; 15432 15433 for ( var i = 0, j = attributeSize * offset; i < attributeArray2.length; i ++, j ++ ) { 15434 15435 attributeArray1[ j ] = attributeArray2[ i ]; 15436 15437 } 15438 15439 } 15440 15441 return this; 15442 15443 }, 15444 15445 normalizeNormals: function () { 15446 15447 var vector = new Vector3(); 15448 15449 return function normalizeNormals() { 15450 15451 var normals = this.attributes.normal; 15452 15453 for ( var i = 0, il = normals.count; i < il; i ++ ) { 15454 15455 vector.x = normals.getX( i ); 15456 vector.y = normals.getY( i ); 15457 vector.z = normals.getZ( i ); 15458 15459 vector.normalize(); 15460 15461 normals.setXYZ( i, vector.x, vector.y, vector.z ); 15462 15463 } 15464 15465 }; 15466 15467 }(), 15468 15469 toNonIndexed: function () { 15470 15471 if ( this.index === null ) { 15472 15473 console.warn( 'THREE.BufferGeometry.toNonIndexed(): Geometry is already non-indexed.' ); 15474 return this; 15475 15476 } 15477 15478 var geometry2 = new BufferGeometry(); 15479 15480 var indices = this.index.array; 15481 var attributes = this.attributes; 15482 15483 for ( var name in attributes ) { 15484 15485 var attribute = attributes[ name ]; 15486 15487 var array = attribute.array; 15488 var itemSize = attribute.itemSize; 15489 15490 var array2 = new array.constructor( indices.length * itemSize ); 15491 15492 var index = 0, index2 = 0; 15493 15494 for ( var i = 0, l = indices.length; i < l; i ++ ) { 15495 15496 index = indices[ i ] * itemSize; 15497 15498 for ( var j = 0; j < itemSize; j ++ ) { 15499 15500 array2[ index2 ++ ] = array[ index ++ ]; 15501 15502 } 15503 15504 } 15505 15506 geometry2.addAttribute( name, new BufferAttribute( array2, itemSize ) ); 15507 15508 } 15509 15510 var groups = this.groups; 15511 15512 for ( var i = 0, l = groups.length; i < l; i ++ ) { 15513 15514 var group = groups[ i ]; 15515 geometry2.addGroup( group.start, group.count, group.materialIndex ); 15516 15517 } 15518 15519 return geometry2; 15520 15521 }, 15522 15523 toJSON: function () { 15524 15525 var data = { 15526 metadata: { 15527 version: 4.5, 15528 type: 'BufferGeometry', 15529 generator: 'BufferGeometry.toJSON' 15530 } 15531 }; 15532 15533 // standard BufferGeometry serialization 15534 15535 data.uuid = this.uuid; 15536 data.type = this.type; 15537 if ( this.name !== '' ) data.name = this.name; 15538 if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; 15539 15540 if ( this.parameters !== undefined ) { 15541 15542 var parameters = this.parameters; 15543 15544 for ( var key in parameters ) { 15545 15546 if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; 15547 15548 } 15549 15550 return data; 15551 15552 } 15553 15554 data.data = { attributes: {} }; 15555 15556 var index = this.index; 15557 15558 if ( index !== null ) { 15559 15560 var array = Array.prototype.slice.call( index.array ); 15561 15562 data.data.index = { 15563 type: index.array.constructor.name, 15564 array: array 15565 }; 15566 15567 } 15568 15569 var attributes = this.attributes; 15570 15571 for ( var key in attributes ) { 15572 15573 var attribute = attributes[ key ]; 15574 15575 var array = Array.prototype.slice.call( attribute.array ); 15576 15577 data.data.attributes[ key ] = { 15578 itemSize: attribute.itemSize, 15579 type: attribute.array.constructor.name, 15580 array: array, 15581 normalized: attribute.normalized 15582 }; 15583 15584 } 15585 15586 var groups = this.groups; 15587 15588 if ( groups.length > 0 ) { 15589 15590 data.data.groups = JSON.parse( JSON.stringify( groups ) ); 15591 15592 } 15593 15594 var boundingSphere = this.boundingSphere; 15595 15596 if ( boundingSphere !== null ) { 15597 15598 data.data.boundingSphere = { 15599 center: boundingSphere.center.toArray(), 15600 radius: boundingSphere.radius 15601 }; 15602 15603 } 15604 15605 return data; 15606 15607 }, 15608 15609 clone: function () { 15610 15611 /* 15612 // Handle primitives 15613 15614 var parameters = this.parameters; 15615 15616 if ( parameters !== undefined ) { 15617 15618 var values = []; 15619 15620 for ( var key in parameters ) { 15621 15622 values.push( parameters[ key ] ); 15623 15624 } 15625 15626 var geometry = Object.create( this.constructor.prototype ); 15627 this.constructor.apply( geometry, values ); 15628 return geometry; 15629 15630 } 15631 15632 return new this.constructor().copy( this ); 15633 */ 15634 15635 return new BufferGeometry().copy( this ); 15636 15637 }, 15638 15639 copy: function ( source ) { 15640 15641 var name, i, l; 15642 15643 // reset 15644 15645 this.index = null; 15646 this.attributes = {}; 15647 this.morphAttributes = {}; 15648 this.groups = []; 15649 this.boundingBox = null; 15650 this.boundingSphere = null; 15651 15652 // name 15653 15654 this.name = source.name; 15655 15656 // index 15657 15658 var index = source.index; 15659 15660 if ( index !== null ) { 15661 15662 this.setIndex( index.clone() ); 15663 15664 } 15665 15666 // attributes 15667 15668 var attributes = source.attributes; 15669 15670 for ( name in attributes ) { 15671 15672 var attribute = attributes[ name ]; 15673 this.addAttribute( name, attribute.clone() ); 15674 15675 } 15676 15677 // morph attributes 15678 15679 var morphAttributes = source.morphAttributes; 15680 15681 for ( name in morphAttributes ) { 15682 15683 var array = []; 15684 var morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes 15685 15686 for ( i = 0, l = morphAttribute.length; i < l; i ++ ) { 15687 15688 array.push( morphAttribute[ i ].clone() ); 15689 15690 } 15691 15692 this.morphAttributes[ name ] = array; 15693 15694 } 15695 15696 // groups 15697 15698 var groups = source.groups; 15699 15700 for ( i = 0, l = groups.length; i < l; i ++ ) { 15701 15702 var group = groups[ i ]; 15703 this.addGroup( group.start, group.count, group.materialIndex ); 15704 15705 } 15706 15707 // bounding box 15708 15709 var boundingBox = source.boundingBox; 15710 15711 if ( boundingBox !== null ) { 15712 15713 this.boundingBox = boundingBox.clone(); 15714 15715 } 15716 15717 // bounding sphere 15718 15719 var boundingSphere = source.boundingSphere; 15720 15721 if ( boundingSphere !== null ) { 15722 15723 this.boundingSphere = boundingSphere.clone(); 15724 15725 } 15726 15727 // draw range 15728 15729 this.drawRange.start = source.drawRange.start; 15730 this.drawRange.count = source.drawRange.count; 15731 15732 // user data 15733 15734 this.userData = source.userData; 15735 15736 return this; 15737 15738 }, 15739 15740 dispose: function () { 15741 15742 this.dispatchEvent( { type: 'dispose' } ); 15743 15744 } 15745 15746 } ); 15747 15748 /** 15749 * @author mrdoob / http://mrdoob.com/ 15750 * @author Mugen87 / https://github.com/Mugen87 15751 */ 15752 15753 // BoxGeometry 15754 15755 function BoxGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { 15756 15757 Geometry.call( this ); 15758 15759 this.type = 'BoxGeometry'; 15760 15761 this.parameters = { 15762 width: width, 15763 height: height, 15764 depth: depth, 15765 widthSegments: widthSegments, 15766 heightSegments: heightSegments, 15767 depthSegments: depthSegments 15768 }; 15769 15770 this.fromBufferGeometry( new BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) ); 15771 this.mergeVertices(); 15772 15773 } 15774 15775 BoxGeometry.prototype = Object.create( Geometry.prototype ); 15776 BoxGeometry.prototype.constructor = BoxGeometry; 15777 15778 // BoxBufferGeometry 15779 15780 function BoxBufferGeometry( width, height, depth, widthSegments, heightSegments, depthSegments ) { 15781 15782 BufferGeometry.call( this ); 15783 15784 this.type = 'BoxBufferGeometry'; 15785 15786 this.parameters = { 15787 width: width, 15788 height: height, 15789 depth: depth, 15790 widthSegments: widthSegments, 15791 heightSegments: heightSegments, 15792 depthSegments: depthSegments 15793 }; 15794 15795 var scope = this; 15796 15797 width = width || 1; 15798 height = height || 1; 15799 depth = depth || 1; 15800 15801 // segments 15802 15803 widthSegments = Math.floor( widthSegments ) || 1; 15804 heightSegments = Math.floor( heightSegments ) || 1; 15805 depthSegments = Math.floor( depthSegments ) || 1; 15806 15807 // buffers 15808 15809 var indices = []; 15810 var vertices = []; 15811 var normals = []; 15812 var uvs = []; 15813 15814 // helper variables 15815 15816 var numberOfVertices = 0; 15817 var groupStart = 0; 15818 15819 // build each side of the box geometry 15820 15821 buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px 15822 buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx 15823 buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py 15824 buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny 15825 buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz 15826 buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz 15827 15828 // build geometry 15829 15830 this.setIndex( indices ); 15831 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 15832 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 15833 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 15834 15835 function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { 15836 15837 var segmentWidth = width / gridX; 15838 var segmentHeight = height / gridY; 15839 15840 var widthHalf = width / 2; 15841 var heightHalf = height / 2; 15842 var depthHalf = depth / 2; 15843 15844 var gridX1 = gridX + 1; 15845 var gridY1 = gridY + 1; 15846 15847 var vertexCounter = 0; 15848 var groupCount = 0; 15849 15850 var ix, iy; 15851 15852 var vector = new Vector3(); 15853 15854 // generate vertices, normals and uvs 15855 15856 for ( iy = 0; iy < gridY1; iy ++ ) { 15857 15858 var y = iy * segmentHeight - heightHalf; 15859 15860 for ( ix = 0; ix < gridX1; ix ++ ) { 15861 15862 var x = ix * segmentWidth - widthHalf; 15863 15864 // set values to correct vector component 15865 15866 vector[ u ] = x * udir; 15867 vector[ v ] = y * vdir; 15868 vector[ w ] = depthHalf; 15869 15870 // now apply vector to vertex buffer 15871 15872 vertices.push( vector.x, vector.y, vector.z ); 15873 15874 // set values to correct vector component 15875 15876 vector[ u ] = 0; 15877 vector[ v ] = 0; 15878 vector[ w ] = depth > 0 ? 1 : - 1; 15879 15880 // now apply vector to normal buffer 15881 15882 normals.push( vector.x, vector.y, vector.z ); 15883 15884 // uvs 15885 15886 uvs.push( ix / gridX ); 15887 uvs.push( 1 - ( iy / gridY ) ); 15888 15889 // counters 15890 15891 vertexCounter += 1; 15892 15893 } 15894 15895 } 15896 15897 // indices 15898 15899 // 1. you need three indices to draw a single face 15900 // 2. a single segment consists of two faces 15901 // 3. so we need to generate six (2*3) indices per segment 15902 15903 for ( iy = 0; iy < gridY; iy ++ ) { 15904 15905 for ( ix = 0; ix < gridX; ix ++ ) { 15906 15907 var a = numberOfVertices + ix + gridX1 * iy; 15908 var b = numberOfVertices + ix + gridX1 * ( iy + 1 ); 15909 var c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); 15910 var d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; 15911 15912 // faces 15913 15914 indices.push( a, b, d ); 15915 indices.push( b, c, d ); 15916 15917 // increase counter 15918 15919 groupCount += 6; 15920 15921 } 15922 15923 } 15924 15925 // add a group to the geometry. this will ensure multi material support 15926 15927 scope.addGroup( groupStart, groupCount, materialIndex ); 15928 15929 // calculate new start value for groups 15930 15931 groupStart += groupCount; 15932 15933 // update total number of vertices 15934 15935 numberOfVertices += vertexCounter; 15936 15937 } 15938 15939 } 15940 15941 BoxBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 15942 BoxBufferGeometry.prototype.constructor = BoxBufferGeometry; 15943 15944 /** 15945 * @author mrdoob / http://mrdoob.com/ 15946 * @author Mugen87 / https://github.com/Mugen87 15947 */ 15948 15949 // PlaneGeometry 15950 15951 function PlaneGeometry( width, height, widthSegments, heightSegments ) { 15952 15953 Geometry.call( this ); 15954 15955 this.type = 'PlaneGeometry'; 15956 15957 this.parameters = { 15958 width: width, 15959 height: height, 15960 widthSegments: widthSegments, 15961 heightSegments: heightSegments 15962 }; 15963 15964 this.fromBufferGeometry( new PlaneBufferGeometry( width, height, widthSegments, heightSegments ) ); 15965 this.mergeVertices(); 15966 15967 } 15968 15969 PlaneGeometry.prototype = Object.create( Geometry.prototype ); 15970 PlaneGeometry.prototype.constructor = PlaneGeometry; 15971 15972 // PlaneBufferGeometry 15973 15974 function PlaneBufferGeometry( width, height, widthSegments, heightSegments ) { 15975 15976 BufferGeometry.call( this ); 15977 15978 this.type = 'PlaneBufferGeometry'; 15979 15980 this.parameters = { 15981 width: width, 15982 height: height, 15983 widthSegments: widthSegments, 15984 heightSegments: heightSegments 15985 }; 15986 15987 width = width || 1; 15988 height = height || 1; 15989 15990 var width_half = width / 2; 15991 var height_half = height / 2; 15992 15993 var gridX = Math.floor( widthSegments ) || 1; 15994 var gridY = Math.floor( heightSegments ) || 1; 15995 15996 var gridX1 = gridX + 1; 15997 var gridY1 = gridY + 1; 15998 15999 var segment_width = width / gridX; 16000 var segment_height = height / gridY; 16001 16002 var ix, iy; 16003 16004 // buffers 16005 16006 var indices = []; 16007 var vertices = []; 16008 var normals = []; 16009 var uvs = []; 16010 16011 // generate vertices, normals and uvs 16012 16013 for ( iy = 0; iy < gridY1; iy ++ ) { 16014 16015 var y = iy * segment_height - height_half; 16016 16017 for ( ix = 0; ix < gridX1; ix ++ ) { 16018 16019 var x = ix * segment_width - width_half; 16020 16021 vertices.push( x, - y, 0 ); 16022 16023 normals.push( 0, 0, 1 ); 16024 16025 uvs.push( ix / gridX ); 16026 uvs.push( 1 - ( iy / gridY ) ); 16027 16028 } 16029 16030 } 16031 16032 // indices 16033 16034 for ( iy = 0; iy < gridY; iy ++ ) { 16035 16036 for ( ix = 0; ix < gridX; ix ++ ) { 16037 16038 var a = ix + gridX1 * iy; 16039 var b = ix + gridX1 * ( iy + 1 ); 16040 var c = ( ix + 1 ) + gridX1 * ( iy + 1 ); 16041 var d = ( ix + 1 ) + gridX1 * iy; 16042 16043 // faces 16044 16045 indices.push( a, b, d ); 16046 indices.push( b, c, d ); 16047 16048 } 16049 16050 } 16051 16052 // build geometry 16053 16054 this.setIndex( indices ); 16055 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 16056 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 16057 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 16058 16059 } 16060 16061 PlaneBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 16062 PlaneBufferGeometry.prototype.constructor = PlaneBufferGeometry; 16063 16064 /** 16065 * @author mrdoob / http://mrdoob.com/ 16066 * @author alteredq / http://alteredqualia.com/ 16067 */ 16068 16069 var materialId = 0; 16070 16071 function Material() { 16072 16073 Object.defineProperty( this, 'id', { value: materialId ++ } ); 16074 16075 this.uuid = _Math.generateUUID(); 16076 16077 this.name = ''; 16078 this.type = 'Material'; 16079 16080 this.fog = true; 16081 this.lights = true; 16082 16083 this.blending = NormalBlending; 16084 this.side = FrontSide; 16085 this.flatShading = false; 16086 this.vertexColors = NoColors; // THREE.NoColors, THREE.VertexColors, THREE.FaceColors 16087 16088 this.opacity = 1; 16089 this.transparent = false; 16090 16091 this.blendSrc = SrcAlphaFactor; 16092 this.blendDst = OneMinusSrcAlphaFactor; 16093 this.blendEquation = AddEquation; 16094 this.blendSrcAlpha = null; 16095 this.blendDstAlpha = null; 16096 this.blendEquationAlpha = null; 16097 16098 this.depthFunc = LessEqualDepth; 16099 this.depthTest = true; 16100 this.depthWrite = true; 16101 16102 this.clippingPlanes = null; 16103 this.clipIntersection = false; 16104 this.clipShadows = false; 16105 16106 this.shadowSide = null; 16107 16108 this.colorWrite = true; 16109 16110 this.precision = null; // override the renderer's default precision for this material 16111 16112 this.polygonOffset = false; 16113 this.polygonOffsetFactor = 0; 16114 this.polygonOffsetUnits = 0; 16115 16116 this.dithering = false; 16117 16118 this.alphaTest = 0; 16119 this.premultipliedAlpha = false; 16120 16121 this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer 16122 16123 this.visible = true; 16124 16125 this.userData = {}; 16126 16127 this.needsUpdate = true; 16128 16129 } 16130 16131 Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { 16132 16133 constructor: Material, 16134 16135 isMaterial: true, 16136 16137 onBeforeCompile: function () {}, 16138 16139 setValues: function ( values ) { 16140 16141 if ( values === undefined ) return; 16142 16143 for ( var key in values ) { 16144 16145 var newValue = values[ key ]; 16146 16147 if ( newValue === undefined ) { 16148 16149 console.warn( "THREE.Material: '" + key + "' parameter is undefined." ); 16150 continue; 16151 16152 } 16153 16154 // for backward compatability if shading is set in the constructor 16155 if ( key === 'shading' ) { 16156 16157 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); 16158 this.flatShading = ( newValue === FlatShading ) ? true : false; 16159 continue; 16160 16161 } 16162 16163 var currentValue = this[ key ]; 16164 16165 if ( currentValue === undefined ) { 16166 16167 console.warn( "THREE." + this.type + ": '" + key + "' is not a property of this material." ); 16168 continue; 16169 16170 } 16171 16172 if ( currentValue && currentValue.isColor ) { 16173 16174 currentValue.set( newValue ); 16175 16176 } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { 16177 16178 currentValue.copy( newValue ); 16179 16180 } else if ( key === 'overdraw' ) { 16181 16182 // ensure overdraw is backwards-compatible with legacy boolean type 16183 this[ key ] = Number( newValue ); 16184 16185 } else { 16186 16187 this[ key ] = newValue; 16188 16189 } 16190 16191 } 16192 16193 }, 16194 16195 toJSON: function ( meta ) { 16196 16197 var isRoot = ( meta === undefined || typeof meta === 'string' ); 16198 16199 if ( isRoot ) { 16200 16201 meta = { 16202 textures: {}, 16203 images: {} 16204 }; 16205 16206 } 16207 16208 var data = { 16209 metadata: { 16210 version: 4.5, 16211 type: 'Material', 16212 generator: 'Material.toJSON' 16213 } 16214 }; 16215 16216 // standard Material serialization 16217 data.uuid = this.uuid; 16218 data.type = this.type; 16219 16220 if ( this.name !== '' ) data.name = this.name; 16221 16222 if ( this.color && this.color.isColor ) data.color = this.color.getHex(); 16223 16224 if ( this.roughness !== undefined ) data.roughness = this.roughness; 16225 if ( this.metalness !== undefined ) data.metalness = this.metalness; 16226 16227 if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); 16228 if ( this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; 16229 16230 if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); 16231 if ( this.shininess !== undefined ) data.shininess = this.shininess; 16232 if ( this.clearCoat !== undefined ) data.clearCoat = this.clearCoat; 16233 if ( this.clearCoatRoughness !== undefined ) data.clearCoatRoughness = this.clearCoatRoughness; 16234 16235 if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; 16236 if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; 16237 if ( this.lightMap && this.lightMap.isTexture ) data.lightMap = this.lightMap.toJSON( meta ).uuid; 16238 16239 if ( this.aoMap && this.aoMap.isTexture ) { 16240 16241 data.aoMap = this.aoMap.toJSON( meta ).uuid; 16242 data.aoMapIntensity = this.aoMapIntensity; 16243 16244 } 16245 16246 if ( this.bumpMap && this.bumpMap.isTexture ) { 16247 16248 data.bumpMap = this.bumpMap.toJSON( meta ).uuid; 16249 data.bumpScale = this.bumpScale; 16250 16251 } 16252 16253 if ( this.normalMap && this.normalMap.isTexture ) { 16254 16255 data.normalMap = this.normalMap.toJSON( meta ).uuid; 16256 data.normalScale = this.normalScale.toArray(); 16257 16258 } 16259 16260 if ( this.displacementMap && this.displacementMap.isTexture ) { 16261 16262 data.displacementMap = this.displacementMap.toJSON( meta ).uuid; 16263 data.displacementScale = this.displacementScale; 16264 data.displacementBias = this.displacementBias; 16265 16266 } 16267 16268 if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; 16269 if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; 16270 16271 if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; 16272 if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; 16273 16274 if ( this.envMap && this.envMap.isTexture ) { 16275 16276 data.envMap = this.envMap.toJSON( meta ).uuid; 16277 data.reflectivity = this.reflectivity; // Scale behind envMap 16278 16279 } 16280 16281 if ( this.gradientMap && this.gradientMap.isTexture ) { 16282 16283 data.gradientMap = this.gradientMap.toJSON( meta ).uuid; 16284 16285 } 16286 16287 if ( this.size !== undefined ) data.size = this.size; 16288 if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; 16289 16290 if ( this.blending !== NormalBlending ) data.blending = this.blending; 16291 if ( this.flatShading === true ) data.flatShading = this.flatShading; 16292 if ( this.side !== FrontSide ) data.side = this.side; 16293 if ( this.vertexColors !== NoColors ) data.vertexColors = this.vertexColors; 16294 16295 if ( this.opacity < 1 ) data.opacity = this.opacity; 16296 if ( this.transparent === true ) data.transparent = this.transparent; 16297 16298 data.depthFunc = this.depthFunc; 16299 data.depthTest = this.depthTest; 16300 data.depthWrite = this.depthWrite; 16301 16302 // rotation (SpriteMaterial) 16303 if ( this.rotation !== 0 ) data.rotation = this.rotation; 16304 16305 if ( this.linewidth !== 1 ) data.linewidth = this.linewidth; 16306 if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; 16307 if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; 16308 if ( this.scale !== undefined ) data.scale = this.scale; 16309 16310 if ( this.dithering === true ) data.dithering = true; 16311 16312 if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; 16313 if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha; 16314 16315 if ( this.wireframe === true ) data.wireframe = this.wireframe; 16316 if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; 16317 if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; 16318 if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; 16319 16320 if ( this.morphTargets === true ) data.morphTargets = true; 16321 if ( this.skinning === true ) data.skinning = true; 16322 16323 if ( this.visible === false ) data.visible = false; 16324 if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData; 16325 16326 // TODO: Copied from Object3D.toJSON 16327 16328 function extractFromCache( cache ) { 16329 16330 var values = []; 16331 16332 for ( var key in cache ) { 16333 16334 var data = cache[ key ]; 16335 delete data.metadata; 16336 values.push( data ); 16337 16338 } 16339 16340 return values; 16341 16342 } 16343 16344 if ( isRoot ) { 16345 16346 var textures = extractFromCache( meta.textures ); 16347 var images = extractFromCache( meta.images ); 16348 16349 if ( textures.length > 0 ) data.textures = textures; 16350 if ( images.length > 0 ) data.images = images; 16351 16352 } 16353 16354 return data; 16355 16356 }, 16357 16358 clone: function () { 16359 16360 return new this.constructor().copy( this ); 16361 16362 }, 16363 16364 copy: function ( source ) { 16365 16366 this.name = source.name; 16367 16368 this.fog = source.fog; 16369 this.lights = source.lights; 16370 16371 this.blending = source.blending; 16372 this.side = source.side; 16373 this.flatShading = source.flatShading; 16374 this.vertexColors = source.vertexColors; 16375 16376 this.opacity = source.opacity; 16377 this.transparent = source.transparent; 16378 16379 this.blendSrc = source.blendSrc; 16380 this.blendDst = source.blendDst; 16381 this.blendEquation = source.blendEquation; 16382 this.blendSrcAlpha = source.blendSrcAlpha; 16383 this.blendDstAlpha = source.blendDstAlpha; 16384 this.blendEquationAlpha = source.blendEquationAlpha; 16385 16386 this.depthFunc = source.depthFunc; 16387 this.depthTest = source.depthTest; 16388 this.depthWrite = source.depthWrite; 16389 16390 this.colorWrite = source.colorWrite; 16391 16392 this.precision = source.precision; 16393 16394 this.polygonOffset = source.polygonOffset; 16395 this.polygonOffsetFactor = source.polygonOffsetFactor; 16396 this.polygonOffsetUnits = source.polygonOffsetUnits; 16397 16398 this.dithering = source.dithering; 16399 16400 this.alphaTest = source.alphaTest; 16401 this.premultipliedAlpha = source.premultipliedAlpha; 16402 16403 this.overdraw = source.overdraw; 16404 16405 this.visible = source.visible; 16406 this.userData = JSON.parse( JSON.stringify( source.userData ) ); 16407 16408 this.clipShadows = source.clipShadows; 16409 this.clipIntersection = source.clipIntersection; 16410 16411 var srcPlanes = source.clippingPlanes, 16412 dstPlanes = null; 16413 16414 if ( srcPlanes !== null ) { 16415 16416 var n = srcPlanes.length; 16417 dstPlanes = new Array( n ); 16418 16419 for ( var i = 0; i !== n; ++ i ) 16420 dstPlanes[ i ] = srcPlanes[ i ].clone(); 16421 16422 } 16423 16424 this.clippingPlanes = dstPlanes; 16425 16426 this.shadowSide = source.shadowSide; 16427 16428 return this; 16429 16430 }, 16431 16432 dispose: function () { 16433 16434 this.dispatchEvent( { type: 'dispose' } ); 16435 16436 } 16437 16438 } ); 16439 16440 /** 16441 * @author mrdoob / http://mrdoob.com/ 16442 * @author alteredq / http://alteredqualia.com/ 16443 * 16444 * parameters = { 16445 * color: <hex>, 16446 * opacity: <float>, 16447 * map: new THREE.Texture( <Image> ), 16448 * 16449 * lightMap: new THREE.Texture( <Image> ), 16450 * lightMapIntensity: <float> 16451 * 16452 * aoMap: new THREE.Texture( <Image> ), 16453 * aoMapIntensity: <float> 16454 * 16455 * specularMap: new THREE.Texture( <Image> ), 16456 * 16457 * alphaMap: new THREE.Texture( <Image> ), 16458 * 16459 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ), 16460 * combine: THREE.Multiply, 16461 * reflectivity: <float>, 16462 * refractionRatio: <float>, 16463 * 16464 * depthTest: <bool>, 16465 * depthWrite: <bool>, 16466 * 16467 * wireframe: <boolean>, 16468 * wireframeLinewidth: <float>, 16469 * 16470 * skinning: <bool>, 16471 * morphTargets: <bool> 16472 * } 16473 */ 16474 16475 function MeshBasicMaterial( parameters ) { 16476 16477 Material.call( this ); 16478 16479 this.type = 'MeshBasicMaterial'; 16480 16481 this.color = new Color( 0xffffff ); // emissive 16482 16483 this.map = null; 16484 16485 this.lightMap = null; 16486 this.lightMapIntensity = 1.0; 16487 16488 this.aoMap = null; 16489 this.aoMapIntensity = 1.0; 16490 16491 this.specularMap = null; 16492 16493 this.alphaMap = null; 16494 16495 this.envMap = null; 16496 this.combine = MultiplyOperation; 16497 this.reflectivity = 1; 16498 this.refractionRatio = 0.98; 16499 16500 this.wireframe = false; 16501 this.wireframeLinewidth = 1; 16502 this.wireframeLinecap = 'round'; 16503 this.wireframeLinejoin = 'round'; 16504 16505 this.skinning = false; 16506 this.morphTargets = false; 16507 16508 this.lights = false; 16509 16510 this.setValues( parameters ); 16511 16512 } 16513 16514 MeshBasicMaterial.prototype = Object.create( Material.prototype ); 16515 MeshBasicMaterial.prototype.constructor = MeshBasicMaterial; 16516 16517 MeshBasicMaterial.prototype.isMeshBasicMaterial = true; 16518 16519 MeshBasicMaterial.prototype.copy = function ( source ) { 16520 16521 Material.prototype.copy.call( this, source ); 16522 16523 this.color.copy( source.color ); 16524 16525 this.map = source.map; 16526 16527 this.lightMap = source.lightMap; 16528 this.lightMapIntensity = source.lightMapIntensity; 16529 16530 this.aoMap = source.aoMap; 16531 this.aoMapIntensity = source.aoMapIntensity; 16532 16533 this.specularMap = source.specularMap; 16534 16535 this.alphaMap = source.alphaMap; 16536 16537 this.envMap = source.envMap; 16538 this.combine = source.combine; 16539 this.reflectivity = source.reflectivity; 16540 this.refractionRatio = source.refractionRatio; 16541 16542 this.wireframe = source.wireframe; 16543 this.wireframeLinewidth = source.wireframeLinewidth; 16544 this.wireframeLinecap = source.wireframeLinecap; 16545 this.wireframeLinejoin = source.wireframeLinejoin; 16546 16547 this.skinning = source.skinning; 16548 this.morphTargets = source.morphTargets; 16549 16550 return this; 16551 16552 }; 16553 16554 /** 16555 * @author alteredq / http://alteredqualia.com/ 16556 * 16557 * parameters = { 16558 * defines: { "label" : "value" }, 16559 * uniforms: { "parameter1": { value: 1.0 }, "parameter2": { value2: 2 } }, 16560 * 16561 * fragmentShader: <string>, 16562 * vertexShader: <string>, 16563 * 16564 * wireframe: <boolean>, 16565 * wireframeLinewidth: <float>, 16566 * 16567 * lights: <bool>, 16568 * 16569 * skinning: <bool>, 16570 * morphTargets: <bool>, 16571 * morphNormals: <bool> 16572 * } 16573 */ 16574 16575 function ShaderMaterial( parameters ) { 16576 16577 Material.call( this ); 16578 16579 this.type = 'ShaderMaterial'; 16580 16581 this.defines = {}; 16582 this.uniforms = {}; 16583 16584 this.vertexShader = 'void main() {\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}'; 16585 this.fragmentShader = 'void main() {\n\tgl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 );\n}'; 16586 16587 this.linewidth = 1; 16588 16589 this.wireframe = false; 16590 this.wireframeLinewidth = 1; 16591 16592 this.fog = false; // set to use scene fog 16593 this.lights = false; // set to use scene lights 16594 this.clipping = false; // set to use user-defined clipping planes 16595 16596 this.skinning = false; // set to use skinning attribute streams 16597 this.morphTargets = false; // set to use morph targets 16598 this.morphNormals = false; // set to use morph normals 16599 16600 this.extensions = { 16601 derivatives: false, // set to use derivatives 16602 fragDepth: false, // set to use fragment depth values 16603 drawBuffers: false, // set to use draw buffers 16604 shaderTextureLOD: false // set to use shader texture LOD 16605 }; 16606 16607 // When rendered geometry doesn't include these attributes but the material does, 16608 // use these default values in WebGL. This avoids errors when buffer data is missing. 16609 this.defaultAttributeValues = { 16610 'color': [ 1, 1, 1 ], 16611 'uv': [ 0, 0 ], 16612 'uv2': [ 0, 0 ] 16613 }; 16614 16615 this.index0AttributeName = undefined; 16616 this.uniformsNeedUpdate = false; 16617 16618 if ( parameters !== undefined ) { 16619 16620 if ( parameters.attributes !== undefined ) { 16621 16622 console.error( 'THREE.ShaderMaterial: attributes should now be defined in THREE.BufferGeometry instead.' ); 16623 16624 } 16625 16626 this.setValues( parameters ); 16627 16628 } 16629 16630 } 16631 16632 ShaderMaterial.prototype = Object.create( Material.prototype ); 16633 ShaderMaterial.prototype.constructor = ShaderMaterial; 16634 16635 ShaderMaterial.prototype.isShaderMaterial = true; 16636 16637 ShaderMaterial.prototype.copy = function ( source ) { 16638 16639 Material.prototype.copy.call( this, source ); 16640 16641 this.fragmentShader = source.fragmentShader; 16642 this.vertexShader = source.vertexShader; 16643 16644 this.uniforms = UniformsUtils.clone( source.uniforms ); 16645 16646 this.defines = Object.assign( {}, source.defines ); 16647 16648 this.wireframe = source.wireframe; 16649 this.wireframeLinewidth = source.wireframeLinewidth; 16650 16651 this.lights = source.lights; 16652 this.clipping = source.clipping; 16653 16654 this.skinning = source.skinning; 16655 16656 this.morphTargets = source.morphTargets; 16657 this.morphNormals = source.morphNormals; 16658 16659 this.extensions = source.extensions; 16660 16661 return this; 16662 16663 }; 16664 16665 ShaderMaterial.prototype.toJSON = function ( meta ) { 16666 16667 var data = Material.prototype.toJSON.call( this, meta ); 16668 16669 data.uniforms = this.uniforms; 16670 data.vertexShader = this.vertexShader; 16671 data.fragmentShader = this.fragmentShader; 16672 16673 return data; 16674 16675 }; 16676 16677 /** 16678 * @author bhouston / http://clara.io 16679 */ 16680 16681 function Ray( origin, direction ) { 16682 16683 this.origin = ( origin !== undefined ) ? origin : new Vector3(); 16684 this.direction = ( direction !== undefined ) ? direction : new Vector3(); 16685 16686 } 16687 16688 Object.assign( Ray.prototype, { 16689 16690 set: function ( origin, direction ) { 16691 16692 this.origin.copy( origin ); 16693 this.direction.copy( direction ); 16694 16695 return this; 16696 16697 }, 16698 16699 clone: function () { 16700 16701 return new this.constructor().copy( this ); 16702 16703 }, 16704 16705 copy: function ( ray ) { 16706 16707 this.origin.copy( ray.origin ); 16708 this.direction.copy( ray.direction ); 16709 16710 return this; 16711 16712 }, 16713 16714 at: function ( t, target ) { 16715 16716 if ( target === undefined ) { 16717 16718 console.warn( 'THREE.Ray: .at() target is now required' ); 16719 target = new Vector3(); 16720 16721 } 16722 16723 return target.copy( this.direction ).multiplyScalar( t ).add( this.origin ); 16724 16725 }, 16726 16727 lookAt: function ( v ) { 16728 16729 this.direction.copy( v ).sub( this.origin ).normalize(); 16730 16731 return this; 16732 16733 }, 16734 16735 recast: function () { 16736 16737 var v1 = new Vector3(); 16738 16739 return function recast( t ) { 16740 16741 this.origin.copy( this.at( t, v1 ) ); 16742 16743 return this; 16744 16745 }; 16746 16747 }(), 16748 16749 closestPointToPoint: function ( point, target ) { 16750 16751 if ( target === undefined ) { 16752 16753 console.warn( 'THREE.Ray: .closestPointToPoint() target is now required' ); 16754 target = new Vector3(); 16755 16756 } 16757 16758 target.subVectors( point, this.origin ); 16759 16760 var directionDistance = target.dot( this.direction ); 16761 16762 if ( directionDistance < 0 ) { 16763 16764 return target.copy( this.origin ); 16765 16766 } 16767 16768 return target.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); 16769 16770 }, 16771 16772 distanceToPoint: function ( point ) { 16773 16774 return Math.sqrt( this.distanceSqToPoint( point ) ); 16775 16776 }, 16777 16778 distanceSqToPoint: function () { 16779 16780 var v1 = new Vector3(); 16781 16782 return function distanceSqToPoint( point ) { 16783 16784 var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction ); 16785 16786 // point behind the ray 16787 16788 if ( directionDistance < 0 ) { 16789 16790 return this.origin.distanceToSquared( point ); 16791 16792 } 16793 16794 v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin ); 16795 16796 return v1.distanceToSquared( point ); 16797 16798 }; 16799 16800 }(), 16801 16802 distanceSqToSegment: function () { 16803 16804 var segCenter = new Vector3(); 16805 var segDir = new Vector3(); 16806 var diff = new Vector3(); 16807 16808 return function distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { 16809 16810 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteDistRaySegment.h 16811 // It returns the min distance between the ray and the segment 16812 // defined by v0 and v1 16813 // It can also set two optional targets : 16814 // - The closest point on the ray 16815 // - The closest point on the segment 16816 16817 segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); 16818 segDir.copy( v1 ).sub( v0 ).normalize(); 16819 diff.copy( this.origin ).sub( segCenter ); 16820 16821 var segExtent = v0.distanceTo( v1 ) * 0.5; 16822 var a01 = - this.direction.dot( segDir ); 16823 var b0 = diff.dot( this.direction ); 16824 var b1 = - diff.dot( segDir ); 16825 var c = diff.lengthSq(); 16826 var det = Math.abs( 1 - a01 * a01 ); 16827 var s0, s1, sqrDist, extDet; 16828 16829 if ( det > 0 ) { 16830 16831 // The ray and segment are not parallel. 16832 16833 s0 = a01 * b1 - b0; 16834 s1 = a01 * b0 - b1; 16835 extDet = segExtent * det; 16836 16837 if ( s0 >= 0 ) { 16838 16839 if ( s1 >= - extDet ) { 16840 16841 if ( s1 <= extDet ) { 16842 16843 // region 0 16844 // Minimum at interior points of ray and segment. 16845 16846 var invDet = 1 / det; 16847 s0 *= invDet; 16848 s1 *= invDet; 16849 sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; 16850 16851 } else { 16852 16853 // region 1 16854 16855 s1 = segExtent; 16856 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 16857 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 16858 16859 } 16860 16861 } else { 16862 16863 // region 5 16864 16865 s1 = - segExtent; 16866 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 16867 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 16868 16869 } 16870 16871 } else { 16872 16873 if ( s1 <= - extDet ) { 16874 16875 // region 4 16876 16877 s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); 16878 s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 16879 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 16880 16881 } else if ( s1 <= extDet ) { 16882 16883 // region 3 16884
vendor: 4,199 bytes, lines 16885-17074
16885 s0 = 0; 16886 s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); 16887 sqrDist = s1 * ( s1 + 2 * b1 ) + c; 16888 16889 } else { 16890 16891 // region 2 16892 16893 s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); 16894 s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); 16895 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 16896 16897 } 16898 16899 } 16900 16901 } else { 16902 16903 // Ray and segment are parallel. 16904 16905 s1 = ( a01 > 0 ) ? - segExtent : segExtent; 16906 s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); 16907 sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; 16908 16909 } 16910 16911 if ( optionalPointOnRay ) { 16912 16913 optionalPointOnRay.copy( this.direction ).multiplyScalar( s0 ).add( this.origin ); 16914 16915 } 16916 16917 if ( optionalPointOnSegment ) { 16918 16919 optionalPointOnSegment.copy( segDir ).multiplyScalar( s1 ).add( segCenter ); 16920 16921 } 16922 16923 return sqrDist; 16924 16925 }; 16926 16927 }(), 16928 16929 intersectSphere: function () { 16930 16931 var v1 = new Vector3(); 16932 16933 return function intersectSphere( sphere, target ) { 16934 16935 v1.subVectors( sphere.center, this.origin ); 16936 var tca = v1.dot( this.direction ); 16937 var d2 = v1.dot( v1 ) - tca * tca; 16938 var radius2 = sphere.radius * sphere.radius; 16939 16940 if ( d2 > radius2 ) return null; 16941 16942 var thc = Math.sqrt( radius2 - d2 ); 16943 16944 // t0 = first intersect point - entrance on front of sphere 16945 var t0 = tca - thc; 16946 16947 // t1 = second intersect point - exit point on back of sphere 16948 var t1 = tca + thc; 16949 16950 // test to see if both t0 and t1 are behind the ray - if so, return null 16951 if ( t0 < 0 && t1 < 0 ) return null; 16952 16953 // test to see if t0 is behind the ray: 16954 // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, 16955 // in order to always return an intersect point that is in front of the ray. 16956 if ( t0 < 0 ) return this.at( t1, target ); 16957 16958 // else t0 is in front of the ray, so return the first collision point scaled by t0 16959 return this.at( t0, target ); 16960 16961 }; 16962 16963 }(), 16964 16965 intersectsSphere: function ( sphere ) { 16966 16967 return this.distanceToPoint( sphere.center ) <= sphere.radius; 16968 16969 }, 16970 16971 distanceToPlane: function ( plane ) { 16972 16973 var denominator = plane.normal.dot( this.direction ); 16974 16975 if ( denominator === 0 ) { 16976 16977 // line is coplanar, return origin 16978 if ( plane.distanceToPoint( this.origin ) === 0 ) { 16979 16980 return 0; 16981 16982 } 16983 16984 // Null is preferable to undefined since undefined means.... it is undefined 16985 16986 return null; 16987 16988 } 16989 16990 var t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; 16991 16992 // Return if the ray never intersects the plane 16993 16994 return t >= 0 ? t : null; 16995 16996 }, 16997 16998 intersectPlane: function ( plane, target ) { 16999 17000 var t = this.distanceToPlane( plane ); 17001 17002 if ( t === null ) { 17003 17004 return null; 17005 17006 } 17007 17008 return this.at( t, target ); 17009 17010 }, 17011 17012 intersectsPlane: function ( plane ) { 17013 17014 // check if the ray lies on the plane first 17015 17016 var distToPoint = plane.distanceToPoint( this.origin ); 17017 17018 if ( distToPoint === 0 ) { 17019 17020 return true; 17021 17022 } 17023 17024 var denominator = plane.normal.dot( this.direction ); 17025 17026 if ( denominator * distToPoint < 0 ) { 17027 17028 return true; 17029 17030 } 17031 17032 // ray origin is behind the plane (and is pointing behind it) 17033 17034 return false; 17035 17036 }, 17037 17038 intersectBox: function ( box, target ) { 17039 17040 var tmin, tmax, tymin, tymax, tzmin, tzmax; 17041 17042 var invdirx = 1 / this.direction.x, 17043 invdiry = 1 / this.direction.y, 17044 invdirz = 1 / this.direction.z; 17045 17046 var origin = this.origin; 17047 17048 if ( invdirx >= 0 ) { 17049 17050 tmin = ( box.min.x - origin.x ) * invdirx; 17051 tmax = ( box.max.x - origin.x ) * invdirx; 17052 17053 } else { 17054 17055 tmin = ( box.max.x - origin.x ) * invdirx; 17056 tmax = ( box.min.x - origin.x ) * invdirx; 17057 17058 } 17059 17060 if ( invdiry >= 0 ) { 17061 17062 tymin = ( box.min.y - origin.y ) * invdiry; 17063 tymax = ( box.max.y - origin.y ) * invdiry; 17064 17065 } else { 17066 17067 tymin = ( box.max.y - origin.y ) * invdiry; 17068 tymax = ( box.min.y - origin.y ) * invdiry; 17069 17070 } 17071 17072 if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; 17073 17074 // These lines also handle the case where tmin or tmax is NaN
vendor: 7,806 bytes, lines 17075-17452
17075 // (result of 0 * Infinity). x !== x returns true if x is NaN 17076 17077 if ( tymin > tmin || tmin !== tmin ) tmin = tymin; 17078 17079 if ( tymax < tmax || tmax !== tmax ) tmax = tymax; 17080 17081 if ( invdirz >= 0 ) { 17082 17083 tzmin = ( box.min.z - origin.z ) * invdirz; 17084 tzmax = ( box.max.z - origin.z ) * invdirz; 17085 17086 } else { 17087 17088 tzmin = ( box.max.z - origin.z ) * invdirz; 17089 tzmax = ( box.min.z - origin.z ) * invdirz; 17090 17091 } 17092 17093 if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; 17094 17095 if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; 17096 17097 if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; 17098 17099 //return point closest to the ray (positive side) 17100 17101 if ( tmax < 0 ) return null; 17102 17103 return this.at( tmin >= 0 ? tmin : tmax, target ); 17104 17105 }, 17106 17107 intersectsBox: ( function () { 17108 17109 var v = new Vector3(); 17110 17111 return function intersectsBox( box ) { 17112 17113 return this.intersectBox( box, v ) !== null; 17114 17115 }; 17116 17117 } )(), 17118 17119 intersectTriangle: function () { 17120 17121 // Compute the offset origin, edges, and normal. 17122 var diff = new Vector3(); 17123 var edge1 = new Vector3(); 17124 var edge2 = new Vector3(); 17125 var normal = new Vector3(); 17126 17127 return function intersectTriangle( a, b, c, backfaceCulling, target ) { 17128 17129 // from http://www.geometrictools.com/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h 17130 17131 edge1.subVectors( b, a ); 17132 edge2.subVectors( c, a ); 17133 normal.crossVectors( edge1, edge2 ); 17134 17135 // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, 17136 // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by 17137 // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) 17138 // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) 17139 // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) 17140 var DdN = this.direction.dot( normal ); 17141 var sign; 17142 17143 if ( DdN > 0 ) { 17144 17145 if ( backfaceCulling ) return null; 17146 sign = 1; 17147 17148 } else if ( DdN < 0 ) { 17149 17150 sign = - 1; 17151 DdN = - DdN; 17152 17153 } else { 17154 17155 return null; 17156 17157 } 17158 17159 diff.subVectors( this.origin, a ); 17160 var DdQxE2 = sign * this.direction.dot( edge2.crossVectors( diff, edge2 ) ); 17161 17162 // b1 < 0, no intersection 17163 if ( DdQxE2 < 0 ) { 17164 17165 return null; 17166 17167 } 17168 17169 var DdE1xQ = sign * this.direction.dot( edge1.cross( diff ) ); 17170 17171 // b2 < 0, no intersection 17172 if ( DdE1xQ < 0 ) { 17173 17174 return null; 17175 17176 } 17177 17178 // b1+b2 > 1, no intersection 17179 if ( DdQxE2 + DdE1xQ > DdN ) { 17180 17181 return null; 17182 17183 } 17184 17185 // Line intersects triangle, check if ray does. 17186 var QdN = - sign * diff.dot( normal ); 17187 17188 // t < 0, no intersection 17189 if ( QdN < 0 ) { 17190 17191 return null; 17192 17193 } 17194 17195 // Ray intersects triangle. 17196 return this.at( QdN / DdN, target ); 17197 17198 }; 17199 17200 }(), 17201 17202 applyMatrix4: function ( matrix4 ) { 17203 17204 this.origin.applyMatrix4( matrix4 ); 17205 this.direction.transformDirection( matrix4 ); 17206 17207 return this; 17208 17209 }, 17210 17211 equals: function ( ray ) { 17212 17213 return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); 17214 17215 } 17216 17217 } ); 17218 17219 /** 17220 * @author bhouston / http://clara.io 17221 */ 17222 17223 function Line3( start, end ) { 17224 17225 this.start = ( start !== undefined ) ? start : new Vector3(); 17226 this.end = ( end !== undefined ) ? end : new Vector3(); 17227 17228 } 17229 17230 Object.assign( Line3.prototype, { 17231 17232 set: function ( start, end ) { 17233 17234 this.start.copy( start ); 17235 this.end.copy( end ); 17236 17237 return this; 17238 17239 }, 17240 17241 clone: function () { 17242 17243 return new this.constructor().copy( this ); 17244 17245 }, 17246 17247 copy: function ( line ) { 17248 17249 this.start.copy( line.start ); 17250 this.end.copy( line.end ); 17251 17252 return this; 17253 17254 }, 17255 17256 getCenter: function ( target ) { 17257 17258 if ( target === undefined ) { 17259 17260 console.warn( 'THREE.Line3: .getCenter() target is now required' ); 17261 target = new Vector3(); 17262 17263 } 17264 17265 return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); 17266 17267 }, 17268 17269 delta: function ( target ) { 17270 17271 if ( target === undefined ) { 17272 17273 console.warn( 'THREE.Line3: .delta() target is now required' ); 17274 target = new Vector3(); 17275 17276 } 17277 17278 return target.subVectors( this.end, this.start ); 17279 17280 }, 17281 17282 distanceSq: function () { 17283 17284 return this.start.distanceToSquared( this.end ); 17285 17286 }, 17287 17288 distance: function () { 17289 17290 return this.start.distanceTo( this.end ); 17291 17292 }, 17293 17294 at: function ( t, target ) { 17295 17296 if ( target === undefined ) { 17297 17298 console.warn( 'THREE.Line3: .at() target is now required' ); 17299 target = new Vector3(); 17300 17301 } 17302 17303 return this.delta( target ).multiplyScalar( t ).add( this.start ); 17304 17305 }, 17306 17307 closestPointToPointParameter: function () { 17308 17309 var startP = new Vector3(); 17310 var startEnd = new Vector3(); 17311 17312 return function closestPointToPointParameter( point, clampToLine ) { 17313 17314 startP.subVectors( point, this.start ); 17315 startEnd.subVectors( this.end, this.start ); 17316 17317 var startEnd2 = startEnd.dot( startEnd ); 17318 var startEnd_startP = startEnd.dot( startP ); 17319 17320 var t = startEnd_startP / startEnd2; 17321 17322 if ( clampToLine ) { 17323 17324 t = _Math.clamp( t, 0, 1 ); 17325 17326 } 17327 17328 return t; 17329 17330 }; 17331 17332 }(), 17333 17334 closestPointToPoint: function ( point, clampToLine, target ) { 17335 17336 var t = this.closestPointToPointParameter( point, clampToLine ); 17337 17338 if ( target === undefined ) { 17339 17340 console.warn( 'THREE.Line3: .closestPointToPoint() target is now required' ); 17341 target = new Vector3(); 17342 17343 } 17344 17345 return this.delta( target ).multiplyScalar( t ).add( this.start ); 17346 17347 }, 17348 17349 applyMatrix4: function ( matrix ) { 17350 17351 this.start.applyMatrix4( matrix ); 17352 this.end.applyMatrix4( matrix ); 17353 17354 return this; 17355 17356 }, 17357 17358 equals: function ( line ) { 17359 17360 return line.start.equals( this.start ) && line.end.equals( this.end ); 17361 17362 } 17363 17364 } ); 17365 17366 /** 17367 * @author bhouston / http://clara.io 17368 * @author mrdoob / http://mrdoob.com/ 17369 */ 17370 17371 function Triangle( a, b, c ) { 17372 17373 this.a = ( a !== undefined ) ? a : new Vector3(); 17374 this.b = ( b !== undefined ) ? b : new Vector3(); 17375 this.c = ( c !== undefined ) ? c : new Vector3(); 17376 17377 } 17378 17379 Object.assign( Triangle, { 17380 17381 getNormal: function () { 17382 17383 var v0 = new Vector3(); 17384 17385 return function getNormal( a, b, c, target ) { 17386 17387 if ( target === undefined ) { 17388 17389 console.warn( 'THREE.Triangle: .getNormal() target is now required' ); 17390 target = new Vector3(); 17391 17392 } 17393 17394 target.subVectors( c, b ); 17395 v0.subVectors( a, b ); 17396 target.cross( v0 ); 17397 17398 var targetLengthSq = target.lengthSq(); 17399 if ( targetLengthSq > 0 ) { 17400 17401 return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); 17402 17403 } 17404 17405 return target.set( 0, 0, 0 ); 17406 17407 }; 17408 17409 }(), 17410 17411 // static/instance method to calculate barycentric coordinates 17412 // based on: http://www.blackpawn.com/texts/pointinpoly/default.html 17413 getBarycoord: function () { 17414 17415 var v0 = new Vector3(); 17416 var v1 = new Vector3(); 17417 var v2 = new Vector3(); 17418 17419 return function getBarycoord( point, a, b, c, target ) { 17420 17421 v0.subVectors( c, a ); 17422 v1.subVectors( b, a ); 17423 v2.subVectors( point, a ); 17424 17425 var dot00 = v0.dot( v0 ); 17426 var dot01 = v0.dot( v1 ); 17427 var dot02 = v0.dot( v2 ); 17428 var dot11 = v1.dot( v1 ); 17429 var dot12 = v1.dot( v2 ); 17430 17431 var denom = ( dot00 * dot11 - dot01 * dot01 ); 17432 17433 if ( target === undefined ) { 17434 17435 console.warn( 'THREE.Triangle: .getBarycoord() target is now required' ); 17436 target = new Vector3(); 17437 17438 } 17439 17440 // collinear or singular triangle 17441 if ( denom === 0 ) { 17442 17443 // arbitrary location outside of triangle? 17444 // not sure if this is the best idea, maybe should be returning undefined 17445 return target.set( - 2, - 1, - 1 ); 17446 17447 } 17448 17449 var invDenom = 1 / denom; 17450 var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; 17451 var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; 17452
17453 // barycentric coordinates must always sum to 1 17454 return target.set( 1 - u - v, v, u ); 17455 17456 }; 17457 17458 }(), 17459 17460 containsPoint: function () { 17461 17462 var v1 = new Vector3(); 17463 17464 return function containsPoint( point, a, b, c ) { 17465 17466 Triangle.getBarycoord( point, a, b, c, v1 ); 17467 17468 return ( v1.x >= 0 ) && ( v1.y >= 0 ) && ( ( v1.x + v1.y ) <= 1 ); 17469 17470 }; 17471 17472 }() 17473 17474 } ); 17475 17476 Object.assign( Triangle.prototype, { 17477 17478 set: function ( a, b, c ) { 17479 17480 this.a.copy( a ); 17481 this.b.copy( b ); 17482 this.c.copy( c ); 17483 17484 return this; 17485 17486 }, 17487 17488 setFromPointsAndIndices: function ( points, i0, i1, i2 ) { 17489 17490 this.a.copy( points[ i0 ] ); 17491 this.b.copy( points[ i1 ] ); 17492 this.c.copy( points[ i2 ] ); 17493 17494 return this; 17495 17496 }, 17497 17498 clone: function () { 17499 17500 return new this.constructor().copy( this ); 17501 17502 }, 17503 17504 copy: function ( triangle ) { 17505 17506 this.a.copy( triangle.a ); 17507 this.b.copy( triangle.b ); 17508 this.c.copy( triangle.c ); 17509 17510 return this; 17511 17512 }, 17513 17514 getArea: function () { 17515 17516 var v0 = new Vector3(); 17517 var v1 = new Vector3(); 17518 17519 return function getArea() { 17520 17521 v0.subVectors( this.c, this.b ); 17522 v1.subVectors( this.a, this.b ); 17523 17524 return v0.cross( v1 ).length() * 0.5; 17525 17526 }; 17527 17528 }(), 17529 17530 getMidpoint: function ( target ) { 17531 17532 if ( target === undefined ) { 17533 17534 console.warn( 'THREE.Triangle: .getMidpoint() target is now required' ); 17535 target = new Vector3(); 17536 17537 } 17538 17539 return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); 17540 17541 }, 17542 17543 getNormal: function ( target ) { 17544 17545 return Triangle.getNormal( this.a, this.b, this.c, target ); 17546 17547 }, 17548 17549 getPlane: function ( target ) { 17550 17551 if ( target === undefined ) { 17552 17553 console.warn( 'THREE.Triangle: .getPlane() target is now required' ); 17554 target = new Vector3(); 17555 17556 } 17557 17558 return target.setFromCoplanarPoints( this.a, this.b, this.c ); 17559 17560 }, 17561 17562 getBarycoord: function ( point, target ) { 17563 17564 return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); 17565 17566 }, 17567 17568 containsPoint: function ( point ) { 17569 17570 return Triangle.containsPoint( point, this.a, this.b, this.c ); 17571 17572 }, 17573 17574 intersectsBox: function ( box ) { 17575 17576 return box.intersectsTriangle( this ); 17577 17578 }, 17579 17580 closestPointToPoint: function () { 17581 17582 var plane = new Plane(); 17583 var edgeList = [ new Line3(), new Line3(), new Line3() ]; 17584 var projectedPoint = new Vector3(); 17585 var closestPoint = new Vector3(); 17586 17587 return function closestPointToPoint( point, target ) { 17588 17589 if ( target === undefined ) { 17590 17591 console.warn( 'THREE.Triangle: .closestPointToPoint() target is now required' ); 17592 target = new Vector3(); 17593 17594 } 17595 17596 var minDistance = Infinity; 17597 17598 // project the point onto the plane of the triangle 17599 17600 plane.setFromCoplanarPoints( this.a, this.b, this.c ); 17601 plane.projectPoint( point, projectedPoint ); 17602 17603 // check if the projection lies within the triangle 17604 17605 if ( this.containsPoint( projectedPoint ) === true ) { 17606 17607 // if so, this is the closest point 17608 17609 target.copy( projectedPoint ); 17610 17611 } else { 17612 17613 // if not, the point falls outside the triangle. the target is the closest point to the triangle's edges or vertices 17614 17615 edgeList[ 0 ].set( this.a, this.b ); 17616 edgeList[ 1 ].set( this.b, this.c ); 17617 edgeList[ 2 ].set( this.c, this.a ); 17618 17619 for ( var i = 0; i < edgeList.length; i ++ ) { 17620 17621 edgeList[ i ].closestPointToPoint( projectedPoint, true, closestPoint ); 17622 17623 var distance = projectedPoint.distanceToSquared( closestPoint ); 17624 17625 if ( distance < minDistance ) { 17626 17627 minDistance = distance; 17628 17629 target.copy( closestPoint ); 17630 17631 } 17632 17633 } 17634 17635 } 17636 17637 return target; 17638 17639 }; 17640 17641 }(), 17642 17643 equals: function ( triangle ) { 17644 17645 return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); 17646 17647 } 17648 17649 } ); 17650 17651 /** 17652 * @author mrdoob / http://mrdoob.com/ 17653 * @author alteredq / http://alteredqualia.com/ 17654 * @author mikael emtinger / http://gomo.se/ 17655 * @author jonobr1 / http://jonobr1.com/ 17656 */ 17657 17658 function Mesh( geometry, material ) { 17659 17660 Object3D.call( this ); 17661 17662 this.type = 'Mesh'; 17663 17664 this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); 17665 this.material = material !== undefined ? material : new MeshBasicMaterial( { color: Math.random() * 0xffffff } ); 17666 17667 this.drawMode = TrianglesDrawMode; 17668 17669 this.updateMorphTargets(); 17670 17671 } 17672 17673 Mesh.prototype = Object.assign( Object.create( Object3D.prototype ), { 17674 17675 constructor: Mesh, 17676 17677 isMesh: true, 17678 17679 setDrawMode: function ( value ) { 17680 17681 this.drawMode = value; 17682 17683 }, 17684
vendor: 8,365 bytes, lines 17685-18042
17685 copy: function ( source ) { 17686 17687 Object3D.prototype.copy.call( this, source ); 17688 17689 this.drawMode = source.drawMode; 17690 17691 if ( source.morphTargetInfluences !== undefined ) { 17692 17693 this.morphTargetInfluences = source.morphTargetInfluences.slice(); 17694 17695 } 17696 17697 if ( source.morphTargetDictionary !== undefined ) { 17698 17699 this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); 17700 17701 } 17702 17703 return this; 17704 17705 }, 17706 17707 updateMorphTargets: function () { 17708 17709 var geometry = this.geometry; 17710 var m, ml, name; 17711 17712 if ( geometry.isBufferGeometry ) { 17713 17714 var morphAttributes = geometry.morphAttributes; 17715 var keys = Object.keys( morphAttributes ); 17716 17717 if ( keys.length > 0 ) { 17718 17719 var morphAttribute = morphAttributes[ keys[ 0 ] ]; 17720 17721 if ( morphAttribute !== undefined ) { 17722 17723 this.morphTargetInfluences = []; 17724 this.morphTargetDictionary = {}; 17725 17726 for ( m = 0, ml = morphAttribute.length; m < ml; m ++ ) { 17727 17728 name = morphAttribute[ m ].name || String( m ); 17729 17730 this.morphTargetInfluences.push( 0 ); 17731 this.morphTargetDictionary[ name ] = m; 17732 17733 } 17734 17735 } 17736 17737 } 17738 17739 } else { 17740 17741 var morphTargets = geometry.morphTargets; 17742 17743 if ( morphTargets !== undefined && morphTargets.length > 0 ) { 17744 17745 this.morphTargetInfluences = []; 17746 this.morphTargetDictionary = {}; 17747 17748 for ( m = 0, ml = morphTargets.length; m < ml; m ++ ) { 17749 17750 name = morphTargets[ m ].name || String( m ); 17751 17752 this.morphTargetInfluences.push( 0 ); 17753 this.morphTargetDictionary[ name ] = m; 17754 17755 } 17756 17757 } 17758 17759 } 17760 17761 }, 17762 17763 raycast: ( function () { 17764 17765 var inverseMatrix = new Matrix4(); 17766 var ray = new Ray(); 17767 var sphere = new Sphere(); 17768 17769 var vA = new Vector3(); 17770 var vB = new Vector3(); 17771 var vC = new Vector3(); 17772 17773 var tempA = new Vector3(); 17774 var tempB = new Vector3(); 17775 var tempC = new Vector3(); 17776 17777 var uvA = new Vector2(); 17778 var uvB = new Vector2(); 17779 var uvC = new Vector2(); 17780 17781 var barycoord = new Vector3(); 17782 17783 var intersectionPoint = new Vector3(); 17784 var intersectionPointWorld = new Vector3(); 17785 17786 function uvIntersection( point, p1, p2, p3, uv1, uv2, uv3 ) { 17787 17788 Triangle.getBarycoord( point, p1, p2, p3, barycoord ); 17789 17790 uv1.multiplyScalar( barycoord.x ); 17791 uv2.multiplyScalar( barycoord.y ); 17792 uv3.multiplyScalar( barycoord.z ); 17793 17794 uv1.add( uv2 ).add( uv3 ); 17795 17796 return uv1.clone(); 17797 17798 } 17799 17800 function checkIntersection( object, material, raycaster, ray, pA, pB, pC, point ) { 17801 17802 var intersect; 17803 17804 if ( material.side === BackSide ) { 17805 17806 intersect = ray.intersectTriangle( pC, pB, pA, true, point ); 17807 17808 } else { 17809 17810 intersect = ray.intersectTriangle( pA, pB, pC, material.side !== DoubleSide, point ); 17811 17812 } 17813 17814 if ( intersect === null ) return null; 17815 17816 intersectionPointWorld.copy( point ); 17817 intersectionPointWorld.applyMatrix4( object.matrixWorld ); 17818 17819 var distance = raycaster.ray.origin.distanceTo( intersectionPointWorld ); 17820 17821 if ( distance < raycaster.near || distance > raycaster.far ) return null; 17822 17823 return { 17824 distance: distance, 17825 point: intersectionPointWorld.clone(), 17826 object: object 17827 }; 17828 17829 } 17830 17831 function checkBufferGeometryIntersection( object, raycaster, ray, position, uv, a, b, c ) { 17832 17833 vA.fromBufferAttribute( position, a ); 17834 vB.fromBufferAttribute( position, b ); 17835 vC.fromBufferAttribute( position, c ); 17836 17837 var intersection = checkIntersection( object, object.material, raycaster, ray, vA, vB, vC, intersectionPoint ); 17838 17839 if ( intersection ) { 17840 17841 if ( uv ) { 17842 17843 uvA.fromBufferAttribute( uv, a ); 17844 uvB.fromBufferAttribute( uv, b ); 17845 uvC.fromBufferAttribute( uv, c ); 17846 17847 intersection.uv = uvIntersection( intersectionPoint, vA, vB, vC, uvA, uvB, uvC ); 17848 17849 } 17850 17851 var face = new Face3( a, b, c ); 17852 Triangle.getNormal( vA, vB, vC, face.normal ); 17853 17854 intersection.face = face; 17855 17856 } 17857 17858 return intersection; 17859 17860 } 17861 17862 return function raycast( raycaster, intersects ) { 17863 17864 var geometry = this.geometry; 17865 var material = this.material; 17866 var matrixWorld = this.matrixWorld; 17867 17868 if ( material === undefined ) return; 17869 17870 // Checking boundingSphere distance to ray 17871 17872 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 17873 17874 sphere.copy( geometry.boundingSphere ); 17875 sphere.applyMatrix4( matrixWorld ); 17876 17877 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; 17878 17879 // 17880 17881 inverseMatrix.getInverse( matrixWorld ); 17882 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); 17883 17884 // Check boundingBox before continuing 17885 17886 if ( geometry.boundingBox !== null ) { 17887 17888 if ( ray.intersectsBox( geometry.boundingBox ) === false ) return; 17889 17890 } 17891 17892 var intersection; 17893 17894 if ( geometry.isBufferGeometry ) { 17895 17896 var a, b, c; 17897 var index = geometry.index; 17898 var position = geometry.attributes.position; 17899 var uv = geometry.attributes.uv; 17900 var i, l; 17901 17902 if ( index !== null ) { 17903 17904 // indexed buffer geometry 17905 17906 for ( i = 0, l = index.count; i < l; i += 3 ) { 17907 17908 a = index.getX( i ); 17909 b = index.getX( i + 1 ); 17910 c = index.getX( i + 2 ); 17911 17912 intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); 17913 17914 if ( intersection ) { 17915 17916 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics 17917 intersects.push( intersection ); 17918 17919 } 17920 17921 } 17922 17923 } else if ( position !== undefined ) { 17924 17925 // non-indexed buffer geometry 17926 17927 for ( i = 0, l = position.count; i < l; i += 3 ) { 17928 17929 a = i; 17930 b = i + 1; 17931 c = i + 2; 17932 17933 intersection = checkBufferGeometryIntersection( this, raycaster, ray, position, uv, a, b, c ); 17934 17935 if ( intersection ) { 17936 17937 intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics 17938 intersects.push( intersection ); 17939 17940 } 17941 17942 } 17943 17944 } 17945 17946 } else if ( geometry.isGeometry ) { 17947 17948 var fvA, fvB, fvC; 17949 var isMultiMaterial = Array.isArray( material ); 17950 17951 var vertices = geometry.vertices; 17952 var faces = geometry.faces; 17953 var uvs; 17954 17955 var faceVertexUvs = geometry.faceVertexUvs[ 0 ]; 17956 if ( faceVertexUvs.length > 0 ) uvs = faceVertexUvs; 17957 17958 for ( var f = 0, fl = faces.length; f < fl; f ++ ) { 17959 17960 var face = faces[ f ]; 17961 var faceMaterial = isMultiMaterial ? material[ face.materialIndex ] : material; 17962 17963 if ( faceMaterial === undefined ) continue; 17964 17965 fvA = vertices[ face.a ]; 17966 fvB = vertices[ face.b ]; 17967 fvC = vertices[ face.c ]; 17968 17969 if ( faceMaterial.morphTargets === true ) { 17970 17971 var morphTargets = geometry.morphTargets; 17972 var morphInfluences = this.morphTargetInfluences; 17973 17974 vA.set( 0, 0, 0 ); 17975 vB.set( 0, 0, 0 ); 17976 vC.set( 0, 0, 0 ); 17977 17978 for ( var t = 0, tl = morphTargets.length; t < tl; t ++ ) { 17979 17980 var influence = morphInfluences[ t ]; 17981 17982 if ( influence === 0 ) continue; 17983 17984 var targets = morphTargets[ t ].vertices; 17985 17986 vA.addScaledVector( tempA.subVectors( targets[ face.a ], fvA ), influence ); 17987 vB.addScaledVector( tempB.subVectors( targets[ face.b ], fvB ), influence ); 17988 vC.addScaledVector( tempC.subVectors( targets[ face.c ], fvC ), influence ); 17989 17990 } 17991 17992 vA.add( fvA ); 17993 vB.add( fvB ); 17994 vC.add( fvC ); 17995 17996 fvA = vA; 17997 fvB = vB; 17998 fvC = vC; 17999 18000 } 18001 18002 intersection = checkIntersection( this, faceMaterial, raycaster, ray, fvA, fvB, fvC, intersectionPoint ); 18003 18004 if ( intersection ) { 18005 18006 if ( uvs && uvs[ f ] ) { 18007 18008 var uvs_f = uvs[ f ]; 18009 uvA.copy( uvs_f[ 0 ] ); 18010 uvB.copy( uvs_f[ 1 ] ); 18011 uvC.copy( uvs_f[ 2 ] ); 18012 18013 intersection.uv = uvIntersection( intersectionPoint, fvA, fvB, fvC, uvA, uvB, uvC ); 18014 18015 } 18016 18017 intersection.face = face; 18018 intersection.faceIndex = f; 18019 intersects.push( intersection ); 18020 18021 } 18022 18023 } 18024 18025 } 18026 18027 }; 18028 18029 }() ), 18030 18031 clone: function () { 18032 18033 return new this.constructor( this.geometry, this.material ).copy( this ); 18034 18035 } 18036 18037 } ); 18038 18039 /** 18040 * @author mrdoob / http://mrdoob.com/ 18041 */ 18042
18043 function WebGLBackground( renderer, state, objects, premultipliedAlpha ) { 18044 18045 var clearColor = new Color( 0x000000 ); 18046 var clearAlpha = 0; 18047 18048 var planeCamera, planeMesh; 18049 var boxMesh; 18050 18051 function render( renderList, scene, camera, forceClear ) { 18052 18053 var background = scene.background; 18054 18055 if ( background === null ) { 18056 18057 setClear( clearColor, clearAlpha ); 18058 18059 } else if ( background && background.isColor ) { 18060 18061 setClear( background, 1 ); 18062 forceClear = true; 18063 18064 } 18065 18066 if ( renderer.autoClear || forceClear ) { 18067 18068 renderer.clear( renderer.autoClearColor, renderer.autoClearDepth, renderer.autoClearStencil ); 18069 18070 } 18071 18072 if ( background && background.isCubeTexture ) { 18073 18074 if ( boxMesh === undefined ) { 18075 18076 boxMesh = new Mesh( 18077 new BoxBufferGeometry( 1, 1, 1 ), 18078 new ShaderMaterial( { 18079 uniforms: ShaderLib.cube.uniforms, 18080 vertexShader: ShaderLib.cube.vertexShader, 18081 fragmentShader: ShaderLib.cube.fragmentShader, 18082 side: BackSide, 18083 depthTest: true, 18084 depthWrite: false, 18085 fog: false 18086 } ) 18087 ); 18088 18089 boxMesh.geometry.removeAttribute( 'normal' ); 18090 boxMesh.geometry.removeAttribute( 'uv' ); 18091 18092 boxMesh.onBeforeRender = function ( renderer, scene, camera ) { 18093 18094 this.matrixWorld.copyPosition( camera.matrixWorld ); 18095 18096 }; 18097 18098 objects.update( boxMesh ); 18099 18100 } 18101 18102 boxMesh.material.uniforms.tCube.value = background; 18103 18104 renderList.push( boxMesh, boxMesh.geometry, boxMesh.material, 0, null ); 18105 18106 } else if ( background && background.isTexture ) { 18107 18108 if ( planeCamera === undefined ) { 18109 18110 planeCamera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); 18111 18112 planeMesh = new Mesh( 18113 new PlaneBufferGeometry( 2, 2 ), 18114 new MeshBasicMaterial( { depthTest: false, depthWrite: false, fog: false } ) 18115 ); 18116 18117 objects.update( planeMesh ); 18118 18119 } 18120 18121 planeMesh.material.map = background; 18122 18123 // TODO Push this to renderList 18124 18125 renderer.renderBufferDirect( planeCamera, null, planeMesh.geometry, planeMesh.material, planeMesh, null ); 18126 18127 } 18128 18129 } 18130 18131 function setClear( color, alpha ) { 18132 18133 state.buffers.color.setClear( color.r, color.g, color.b, alpha, premultipliedAlpha ); 18134 18135 } 18136 18137 return { 18138 18139 getClearColor: function () { 18140 18141 return clearColor; 18142 18143 }, 18144 setClearColor: function ( color, alpha ) { 18145 18146 clearColor.set( color ); 18147 clearAlpha = alpha !== undefined ? alpha : 1; 18148 setClear( clearColor, clearAlpha ); 18149 18150 }, 18151 getClearAlpha: function () { 18152 18153 return clearAlpha; 18154 18155 }, 18156 setClearAlpha: function ( alpha ) { 18157 18158 clearAlpha = alpha; 18159 setClear( clearColor, clearAlpha ); 18160 18161 }, 18162 render: render 18163 18164 }; 18165 18166 } 18167 18168 /** 18169 * @author mrdoob / http://mrdoob.com/ 18170 */ 18171 18172 function WebGLBufferRenderer( gl, extensions, info ) { 18173 18174 var mode; 18175 18176 function setMode( value ) { 18177 18178 mode = value; 18179 18180 } 18181 18182 function render( start, count ) { 18183 18184 gl.drawArrays( mode, start, count ); 18185 18186 info.update( count, mode ); 18187 18188 } 18189 18190 function renderInstances( geometry, start, count ) { 18191 18192 var extension = extensions.get( 'ANGLE_instanced_arrays' ); 18193 18194 if ( extension === null ) { 18195 18196 console.error( 'THREE.WebGLBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); 18197 return; 18198 18199 } 18200 18201 extension.drawArraysInstancedANGLE( mode, start, count, geometry.maxInstancedCount ); 18202 18203 info.update( count, mode, geometry.maxInstancedCount ); 18204 18205 } 18206 18207 // 18208 18209 this.setMode = setMode; 18210 this.render = render; 18211 this.renderInstances = renderInstances; 18212 18213 } 18214 18215 /** 18216 * @author mrdoob / http://mrdoob.com/ 18217 */ 18218 18219 function WebGLCapabilities( gl, extensions, parameters ) { 18220 18221 var maxAnisotropy; 18222 18223 function getMaxAnisotropy() { 18224 18225 if ( maxAnisotropy !== undefined ) return maxAnisotropy; 18226 18227 var extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 18228 18229 if ( extension !== null ) { 18230 18231 maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); 18232 18233 } else { 18234 18235 maxAnisotropy = 0; 18236 18237 } 18238 18239 return maxAnisotropy; 18240 18241 } 18242 18243 function getMaxPrecision( precision ) { 18244 18245 if ( precision === 'highp' ) { 18246 18247 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.HIGH_FLOAT ).precision > 0 && 18248 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.HIGH_FLOAT ).precision > 0 ) { 18249 18250 return 'highp'; 18251 18252 } 18253 18254 precision = 'mediump'; 18255 18256 } 18257 18258 if ( precision === 'mediump' ) { 18259 18260 if ( gl.getShaderPrecisionFormat( gl.VERTEX_SHADER, gl.MEDIUM_FLOAT ).precision > 0 && 18261 gl.getShaderPrecisionFormat( gl.FRAGMENT_SHADER, gl.MEDIUM_FLOAT ).precision > 0 ) { 18262 18263 return 'mediump'; 18264 18265 } 18266 18267 } 18268 18269 return 'lowp'; 18270 18271 } 18272 18273 var precision = parameters.precision !== undefined ? parameters.precision : 'highp'; 18274 var maxPrecision = getMaxPrecision( precision ); 18275 18276 if ( maxPrecision !== precision ) { 18277 18278 console.warn( 'THREE.WebGLRenderer:', precision, 'not supported, using', maxPrecision, 'instead.' ); 18279 precision = maxPrecision; 18280 18281 } 18282 18283 var logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; 18284 18285 var maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); 18286 var maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); 18287 var maxTextureSize = gl.getParameter( gl.MAX_TEXTURE_SIZE ); 18288 var maxCubemapSize = gl.getParameter( gl.MAX_CUBE_MAP_TEXTURE_SIZE ); 18289 18290 var maxAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); 18291 var maxVertexUniforms = gl.getParameter( gl.MAX_VERTEX_UNIFORM_VECTORS ); 18292 var maxVaryings = gl.getParameter( gl.MAX_VARYING_VECTORS ); 18293 var maxFragmentUniforms = gl.getParameter( gl.MAX_FRAGMENT_UNIFORM_VECTORS ); 18294 18295 var vertexTextures = maxVertexTextures > 0; 18296 var floatFragmentTextures = !! extensions.get( 'OES_texture_float' ); 18297 var floatVertexTextures = vertexTextures && floatFragmentTextures; 18298 18299 return { 18300 18301 getMaxAnisotropy: getMaxAnisotropy, 18302 getMaxPrecision: getMaxPrecision,
vendor: 29,920 bytes, lines 18303-19826
18303 18304 precision: precision, 18305 logarithmicDepthBuffer: logarithmicDepthBuffer, 18306 18307 maxTextures: maxTextures, 18308 maxVertexTextures: maxVertexTextures, 18309 maxTextureSize: maxTextureSize, 18310 maxCubemapSize: maxCubemapSize, 18311 18312 maxAttributes: maxAttributes, 18313 maxVertexUniforms: maxVertexUniforms, 18314 maxVaryings: maxVaryings, 18315 maxFragmentUniforms: maxFragmentUniforms, 18316 18317 vertexTextures: vertexTextures, 18318 floatFragmentTextures: floatFragmentTextures, 18319 floatVertexTextures: floatVertexTextures 18320 18321 }; 18322 18323 } 18324 18325 /** 18326 * @author tschw 18327 */ 18328 18329 function WebGLClipping() { 18330 18331 var scope = this, 18332 18333 globalState = null, 18334 numGlobalPlanes = 0, 18335 localClippingEnabled = false, 18336 renderingShadows = false, 18337 18338 plane = new Plane(), 18339 viewNormalMatrix = new Matrix3(), 18340 18341 uniform = { value: null, needsUpdate: false }; 18342 18343 this.uniform = uniform; 18344 this.numPlanes = 0; 18345 this.numIntersection = 0; 18346 18347 this.init = function ( planes, enableLocalClipping, camera ) { 18348 18349 var enabled = 18350 planes.length !== 0 || 18351 enableLocalClipping || 18352 // enable state of previous frame - the clipping code has to 18353 // run another frame in order to reset the state: 18354 numGlobalPlanes !== 0 || 18355 localClippingEnabled; 18356 18357 localClippingEnabled = enableLocalClipping; 18358 18359 globalState = projectPlanes( planes, camera, 0 ); 18360 numGlobalPlanes = planes.length; 18361 18362 return enabled; 18363 18364 }; 18365 18366 this.beginShadows = function () { 18367 18368 renderingShadows = true; 18369 projectPlanes( null ); 18370 18371 }; 18372 18373 this.endShadows = function () { 18374 18375 renderingShadows = false; 18376 resetGlobalState(); 18377 18378 }; 18379 18380 this.setState = function ( planes, clipIntersection, clipShadows, camera, cache, fromCache ) { 18381 18382 if ( ! localClippingEnabled || planes === null || planes.length === 0 || renderingShadows && ! clipShadows ) { 18383 18384 // there's no local clipping 18385 18386 if ( renderingShadows ) { 18387 18388 // there's no global clipping 18389 18390 projectPlanes( null ); 18391 18392 } else { 18393 18394 resetGlobalState(); 18395 18396 } 18397 18398 } else { 18399 18400 var nGlobal = renderingShadows ? 0 : numGlobalPlanes, 18401 lGlobal = nGlobal * 4, 18402 18403 dstArray = cache.clippingState || null; 18404 18405 uniform.value = dstArray; // ensure unique state 18406 18407 dstArray = projectPlanes( planes, camera, lGlobal, fromCache ); 18408 18409 for ( var i = 0; i !== lGlobal; ++ i ) { 18410 18411 dstArray[ i ] = globalState[ i ]; 18412 18413 } 18414 18415 cache.clippingState = dstArray; 18416 this.numIntersection = clipIntersection ? this.numPlanes : 0; 18417 this.numPlanes += nGlobal; 18418 18419 } 18420 18421 18422 }; 18423 18424 function resetGlobalState() { 18425 18426 if ( uniform.value !== globalState ) { 18427 18428 uniform.value = globalState; 18429 uniform.needsUpdate = numGlobalPlanes > 0; 18430 18431 } 18432 18433 scope.numPlanes = numGlobalPlanes; 18434 scope.numIntersection = 0; 18435 18436 } 18437 18438 function projectPlanes( planes, camera, dstOffset, skipTransform ) { 18439 18440 var nPlanes = planes !== null ? planes.length : 0, 18441 dstArray = null; 18442 18443 if ( nPlanes !== 0 ) { 18444 18445 dstArray = uniform.value; 18446 18447 if ( skipTransform !== true || dstArray === null ) { 18448 18449 var flatSize = dstOffset + nPlanes * 4, 18450 viewMatrix = camera.matrixWorldInverse; 18451 18452 viewNormalMatrix.getNormalMatrix( viewMatrix ); 18453 18454 if ( dstArray === null || dstArray.length < flatSize ) { 18455 18456 dstArray = new Float32Array( flatSize ); 18457 18458 } 18459 18460 for ( var i = 0, i4 = dstOffset; i !== nPlanes; ++ i, i4 += 4 ) { 18461 18462 plane.copy( planes[ i ] ).applyMatrix4( viewMatrix, viewNormalMatrix ); 18463 18464 plane.normal.toArray( dstArray, i4 ); 18465 dstArray[ i4 + 3 ] = plane.constant; 18466 18467 } 18468 18469 } 18470 18471 uniform.value = dstArray; 18472 uniform.needsUpdate = true; 18473 18474 } 18475 18476 scope.numPlanes = nPlanes; 18477 18478 return dstArray; 18479 18480 } 18481 18482 } 18483 18484 /** 18485 * @author mrdoob / http://mrdoob.com/ 18486 */ 18487 18488 function WebGLExtensions( gl ) { 18489 18490 var extensions = {}; 18491 18492 return { 18493 18494 get: function ( name ) { 18495 18496 if ( extensions[ name ] !== undefined ) { 18497 18498 return extensions[ name ]; 18499 18500 } 18501 18502 var extension; 18503 18504 switch ( name ) { 18505 18506 case 'WEBGL_depth_texture': 18507 extension = gl.getExtension( 'WEBGL_depth_texture' ) || gl.getExtension( 'MOZ_WEBGL_depth_texture' ) || gl.getExtension( 'WEBKIT_WEBGL_depth_texture' ); 18508 break; 18509 18510 case 'EXT_texture_filter_anisotropic': 18511 extension = gl.getExtension( 'EXT_texture_filter_anisotropic' ) || gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) || gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' ); 18512 break; 18513 18514 case 'WEBGL_compressed_texture_s3tc': 18515 extension = gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' ); 18516 break; 18517 18518 case 'WEBGL_compressed_texture_pvrtc': 18519 extension = gl.getExtension( 'WEBGL_compressed_texture_pvrtc' ) || gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_pvrtc' ); 18520 break; 18521 18522 default: 18523 extension = gl.getExtension( name ); 18524 18525 } 18526 18527 if ( extension === null ) { 18528 18529 console.warn( 'THREE.WebGLRenderer: ' + name + ' extension not supported.' ); 18530 18531 } 18532 18533 extensions[ name ] = extension; 18534 18535 return extension; 18536 18537 } 18538 18539 }; 18540 18541 } 18542 18543 /** 18544 * @author mrdoob / http://mrdoob.com/ 18545 */ 18546 18547 function WebGLGeometries( gl, attributes, info ) { 18548 18549 var geometries = {}; 18550 var wireframeAttributes = {}; 18551 18552 function onGeometryDispose( event ) { 18553 18554 var geometry = event.target; 18555 var buffergeometry = geometries[ geometry.id ]; 18556 18557 if ( buffergeometry.index !== null ) { 18558 18559 attributes.remove( buffergeometry.index ); 18560 18561 } 18562 18563 for ( var name in buffergeometry.attributes ) { 18564 18565 attributes.remove( buffergeometry.attributes[ name ] ); 18566 18567 } 18568 18569 geometry.removeEventListener( 'dispose', onGeometryDispose ); 18570 18571 delete geometries[ geometry.id ]; 18572 18573 // TODO Remove duplicate code 18574 18575 var attribute = wireframeAttributes[ geometry.id ]; 18576 18577 if ( attribute ) { 18578 18579 attributes.remove( attribute ); 18580 delete wireframeAttributes[ geometry.id ]; 18581 18582 } 18583 18584 attribute = wireframeAttributes[ buffergeometry.id ]; 18585 18586 if ( attribute ) { 18587 18588 attributes.remove( attribute ); 18589 delete wireframeAttributes[ buffergeometry.id ]; 18590 18591 } 18592 18593 // 18594 18595 info.memory.geometries --; 18596 18597 } 18598 18599 function get( object, geometry ) { 18600 18601 var buffergeometry = geometries[ geometry.id ]; 18602 18603 if ( buffergeometry ) return buffergeometry; 18604 18605 geometry.addEventListener( 'dispose', onGeometryDispose ); 18606 18607 if ( geometry.isBufferGeometry ) { 18608 18609 buffergeometry = geometry; 18610 18611 } else if ( geometry.isGeometry ) { 18612 18613 if ( geometry._bufferGeometry === undefined ) { 18614 18615 geometry._bufferGeometry = new BufferGeometry().setFromObject( object ); 18616 18617 } 18618 18619 buffergeometry = geometry._bufferGeometry; 18620 18621 } 18622 18623 geometries[ geometry.id ] = buffergeometry; 18624 18625 info.memory.geometries ++; 18626 18627 return buffergeometry; 18628 18629 } 18630 18631 function update( geometry ) { 18632 18633 var index = geometry.index; 18634 var geometryAttributes = geometry.attributes; 18635 18636 if ( index !== null ) { 18637 18638 attributes.update( index, gl.ELEMENT_ARRAY_BUFFER ); 18639 18640 } 18641 18642 for ( var name in geometryAttributes ) { 18643 18644 attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER ); 18645 18646 } 18647 18648 // morph targets 18649 18650 var morphAttributes = geometry.morphAttributes; 18651 18652 for ( var name in morphAttributes ) { 18653 18654 var array = morphAttributes[ name ]; 18655 18656 for ( var i = 0, l = array.length; i < l; i ++ ) { 18657 18658 attributes.update( array[ i ], gl.ARRAY_BUFFER ); 18659 18660 } 18661 18662 } 18663 18664 } 18665 18666 function getWireframeAttribute( geometry ) { 18667 18668 var attribute = wireframeAttributes[ geometry.id ]; 18669 18670 if ( attribute ) return attribute; 18671 18672 var indices = []; 18673 18674 var geometryIndex = geometry.index; 18675 var geometryAttributes = geometry.attributes; 18676 18677 // console.time( 'wireframe' ); 18678 18679 if ( geometryIndex !== null ) { 18680 18681 var array = geometryIndex.array; 18682 18683 for ( var i = 0, l = array.length; i < l; i += 3 ) { 18684 18685 var a = array[ i + 0 ]; 18686 var b = array[ i + 1 ]; 18687 var c = array[ i + 2 ]; 18688 18689 indices.push( a, b, b, c, c, a ); 18690 18691 } 18692 18693 } else { 18694 18695 var array = geometryAttributes.position.array; 18696 18697 for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { 18698 18699 var a = i + 0; 18700 var b = i + 1; 18701 var c = i + 2; 18702 18703 indices.push( a, b, b, c, c, a ); 18704 18705 } 18706 18707 } 18708 18709 // console.timeEnd( 'wireframe' ); 18710 18711 attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); 18712 18713 attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER ); 18714 18715 wireframeAttributes[ geometry.id ] = attribute; 18716 18717 return attribute; 18718 18719 } 18720 18721 return { 18722 18723 get: get, 18724 update: update, 18725 18726 getWireframeAttribute: getWireframeAttribute 18727 18728 }; 18729 18730 } 18731 18732 /** 18733 * @author mrdoob / http://mrdoob.com/ 18734 */ 18735 18736 function WebGLIndexedBufferRenderer( gl, extensions, info ) { 18737 18738 var mode; 18739 18740 function setMode( value ) { 18741 18742 mode = value; 18743 18744 } 18745 18746 var type, bytesPerElement; 18747 18748 function setIndex( value ) { 18749 18750 type = value.type; 18751 bytesPerElement = value.bytesPerElement; 18752 18753 } 18754 18755 function render( start, count ) { 18756 18757 gl.drawElements( mode, count, type, start * bytesPerElement ); 18758 18759 info.update( count, mode ); 18760 18761 } 18762 18763 function renderInstances( geometry, start, count ) { 18764 18765 var extension = extensions.get( 'ANGLE_instanced_arrays' ); 18766 18767 if ( extension === null ) { 18768 18769 console.error( 'THREE.WebGLIndexedBufferRenderer: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); 18770 return; 18771 18772 } 18773 18774 extension.drawElementsInstancedANGLE( mode, count, type, start * bytesPerElement, geometry.maxInstancedCount ); 18775 18776 info.update( count, mode, geometry.maxInstancedCount ); 18777 18778 } 18779 18780 // 18781 18782 this.setMode = setMode; 18783 this.setIndex = setIndex; 18784 this.render = render; 18785 this.renderInstances = renderInstances; 18786 18787 } 18788 18789 /** 18790 * @author Mugen87 / https://github.com/Mugen87 18791 */ 18792 18793 function WebGLInfo( gl ) { 18794 18795 var memory = { 18796 geometries: 0, 18797 textures: 0 18798 }; 18799 18800 var render = { 18801 frame: 0, 18802 calls: 0, 18803 triangles: 0, 18804 points: 0, 18805 lines: 0 18806 }; 18807 18808 function update( count, mode, instanceCount ) { 18809 18810 instanceCount = instanceCount || 1; 18811 18812 render.calls ++; 18813 18814 switch ( mode ) { 18815 18816 case gl.TRIANGLES: 18817 render.triangles += instanceCount * ( count / 3 ); 18818 break; 18819 18820 case gl.TRIANGLE_STRIP: 18821 case gl.TRIANGLE_FAN: 18822 render.triangles += instanceCount * ( count - 2 ); 18823 break; 18824 18825 case gl.LINES: 18826 render.lines += instanceCount * ( count / 2 ); 18827 break; 18828 18829 case gl.LINE_STRIP: 18830 render.lines += instanceCount * ( count - 1 ); 18831 break; 18832 18833 case gl.LINE_LOOP: 18834 render.lines += instanceCount * count; 18835 break; 18836 18837 case gl.POINTS: 18838 render.points += instanceCount * count; 18839 break; 18840 18841 default: 18842 console.error( 'THREE.WebGLInfo: Unknown draw mode:', mode ); 18843 break; 18844 18845 } 18846 18847 } 18848 18849 function reset() { 18850 18851 render.frame ++; 18852 render.calls = 0; 18853 render.triangles = 0; 18854 render.points = 0; 18855 render.lines = 0; 18856 18857 } 18858 18859 return { 18860 memory: memory, 18861 render: render, 18862 programs: null, 18863 autoReset: true, 18864 reset: reset, 18865 update: update 18866 }; 18867 18868 } 18869 18870 /** 18871 * @author mrdoob / http://mrdoob.com/ 18872 */ 18873 18874 function absNumericalSort( a, b ) { 18875 18876 return Math.abs( b[ 1 ] ) - Math.abs( a[ 1 ] ); 18877 18878 } 18879 18880 function WebGLMorphtargets( gl ) { 18881 18882 var influencesList = {}; 18883 var morphInfluences = new Float32Array( 8 ); 18884 18885 function update( object, geometry, material, program ) { 18886 18887 var objectInfluences = object.morphTargetInfluences; 18888 18889 var length = objectInfluences.length; 18890 18891 var influences = influencesList[ geometry.id ]; 18892 18893 if ( influences === undefined ) { 18894 18895 // initialise list 18896 18897 influences = []; 18898 18899 for ( var i = 0; i < length; i ++ ) { 18900 18901 influences[ i ] = [ i, 0 ]; 18902 18903 } 18904 18905 influencesList[ geometry.id ] = influences; 18906 18907 } 18908 18909 var morphTargets = material.morphTargets && geometry.morphAttributes.position; 18910 var morphNormals = material.morphNormals && geometry.morphAttributes.normal; 18911 18912 // Remove current morphAttributes 18913 18914 for ( var i = 0; i < length; i ++ ) { 18915 18916 var influence = influences[ i ]; 18917 18918 if ( influence[ 1 ] !== 0 ) { 18919 18920 if ( morphTargets ) geometry.removeAttribute( 'morphTarget' + i ); 18921 if ( morphNormals ) geometry.removeAttribute( 'morphNormal' + i ); 18922 18923 } 18924 18925 } 18926 18927 // Collect influences 18928 18929 for ( var i = 0; i < length; i ++ ) { 18930 18931 var influence = influences[ i ]; 18932 18933 influence[ 0 ] = i; 18934 influence[ 1 ] = objectInfluences[ i ]; 18935 18936 } 18937 18938 influences.sort( absNumericalSort ); 18939 18940 // Add morphAttributes 18941 18942 for ( var i = 0; i < 8; i ++ ) { 18943 18944 var influence = influences[ i ]; 18945 18946 if ( influence ) { 18947 18948 var index = influence[ 0 ]; 18949 var value = influence[ 1 ]; 18950 18951 if ( value ) { 18952 18953 if ( morphTargets ) geometry.addAttribute( 'morphTarget' + i, morphTargets[ index ] ); 18954 if ( morphNormals ) geometry.addAttribute( 'morphNormal' + i, morphNormals[ index ] ); 18955 18956 morphInfluences[ i ] = value; 18957 continue; 18958 18959 } 18960 18961 } 18962 18963 morphInfluences[ i ] = 0; 18964 18965 } 18966 18967 program.getUniforms().setValue( gl, 'morphTargetInfluences', morphInfluences ); 18968 18969 } 18970 18971 return { 18972 18973 update: update 18974 18975 }; 18976 18977 } 18978 18979 /** 18980 * @author mrdoob / http://mrdoob.com/ 18981 */ 18982 18983 function WebGLObjects( geometries, info ) { 18984 18985 var updateList = {}; 18986 18987 function update( object ) { 18988 18989 var frame = info.render.frame; 18990 18991 var geometry = object.geometry; 18992 var buffergeometry = geometries.get( object, geometry ); 18993 18994 // Update once per frame 18995 18996 if ( updateList[ buffergeometry.id ] !== frame ) { 18997 18998 if ( geometry.isGeometry ) { 18999 19000 buffergeometry.updateFromObject( object ); 19001 19002 } 19003 19004 geometries.update( buffergeometry ); 19005 19006 updateList[ buffergeometry.id ] = frame; 19007 19008 } 19009 19010 return buffergeometry; 19011 19012 } 19013 19014 function dispose() { 19015 19016 updateList = {}; 19017 19018 } 19019 19020 return { 19021 19022 update: update, 19023 dispose: dispose 19024 19025 }; 19026 19027 } 19028 19029 /** 19030 * @author mrdoob / http://mrdoob.com/ 19031 */ 19032 19033 function CubeTexture( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ) { 19034 19035 images = images !== undefined ? images : []; 19036 mapping = mapping !== undefined ? mapping : CubeReflectionMapping; 19037 19038 Texture.call( this, images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); 19039 19040 this.flipY = false; 19041 19042 } 19043 19044 CubeTexture.prototype = Object.create( Texture.prototype ); 19045 CubeTexture.prototype.constructor = CubeTexture; 19046 19047 CubeTexture.prototype.isCubeTexture = true; 19048 19049 Object.defineProperty( CubeTexture.prototype, 'images', { 19050 19051 get: function () { 19052 19053 return this.image; 19054 19055 }, 19056 19057 set: function ( value ) { 19058 19059 this.image = value; 19060 19061 } 19062 19063 } ); 19064 19065 /** 19066 * @author tschw 19067 * 19068 * Uniforms of a program. 19069 * Those form a tree structure with a special top-level container for the root, 19070 * which you get by calling 'new WebGLUniforms( gl, program, renderer )'. 19071 * 19072 * 19073 * Properties of inner nodes including the top-level container: 19074 * 19075 * .seq - array of nested uniforms 19076 * .map - nested uniforms by name 19077 * 19078 * 19079 * Methods of all nodes except the top-level container: 19080 * 19081 * .setValue( gl, value, [renderer] ) 19082 * 19083 * uploads a uniform value(s) 19084 * the 'renderer' parameter is needed for sampler uniforms 19085 * 19086 * 19087 * Static methods of the top-level container (renderer factorizations): 19088 * 19089 * .upload( gl, seq, values, renderer ) 19090 * 19091 * sets uniforms in 'seq' to 'values[id].value' 19092 * 19093 * .seqWithValue( seq, values ) : filteredSeq 19094 * 19095 * filters 'seq' entries with corresponding entry in values 19096 * 19097 * 19098 * Methods of the top-level container (renderer factorizations): 19099 * 19100 * .setValue( gl, name, value ) 19101 * 19102 * sets uniform with name 'name' to 'value' 19103 * 19104 * .set( gl, obj, prop ) 19105 * 19106 * sets uniform from object and property with same name than uniform 19107 * 19108 * .setOptional( gl, obj, prop ) 19109 * 19110 * like .set for an optional property of the object 19111 * 19112 */ 19113 19114 var emptyTexture = new Texture(); 19115 var emptyCubeTexture = new CubeTexture(); 19116 19117 // --- Base for inner nodes (including the root) --- 19118 19119 function UniformContainer() { 19120 19121 this.seq = []; 19122 this.map = {}; 19123 19124 } 19125 19126 // --- Utilities --- 19127 19128 // Array Caches (provide typed arrays for temporary by size) 19129 19130 var arrayCacheF32 = []; 19131 var arrayCacheI32 = []; 19132 19133 // Float32Array caches used for uploading Matrix uniforms 19134 19135 var mat4array = new Float32Array( 16 ); 19136 var mat3array = new Float32Array( 9 ); 19137 var mat2array = new Float32Array( 4 ); 19138 19139 // Flattening for arrays of vectors and matrices 19140 19141 function flatten( array, nBlocks, blockSize ) { 19142 19143 var firstElem = array[ 0 ]; 19144 19145 if ( firstElem <= 0 || firstElem > 0 ) return array; 19146 // unoptimized: ! isNaN( firstElem ) 19147 // see http://jacksondunstan.com/articles/983 19148 19149 var n = nBlocks * blockSize, 19150 r = arrayCacheF32[ n ]; 19151 19152 if ( r === undefined ) { 19153 19154 r = new Float32Array( n ); 19155 arrayCacheF32[ n ] = r; 19156 19157 } 19158 19159 if ( nBlocks !== 0 ) { 19160 19161 firstElem.toArray( r, 0 ); 19162 19163 for ( var i = 1, offset = 0; i !== nBlocks; ++ i ) { 19164 19165 offset += blockSize; 19166 array[ i ].toArray( r, offset ); 19167 19168 } 19169 19170 } 19171 19172 return r; 19173 19174 } 19175 19176 function arraysEqual( a, b ) { 19177 19178 if ( a.length !== b.length ) return false; 19179 19180 for ( var i = 0, l = a.length; i < l; i ++ ) { 19181 19182 if ( a[ i ] !== b[ i ] ) return false; 19183 19184 } 19185 19186 return true; 19187 19188 } 19189 19190 function copyArray( a, b ) { 19191 19192 for ( var i = 0, l = b.length; i < l; i ++ ) { 19193 19194 a[ i ] = b[ i ]; 19195 19196 } 19197 19198 } 19199 19200 // Texture unit allocation 19201 19202 function allocTexUnits( renderer, n ) { 19203 19204 var r = arrayCacheI32[ n ]; 19205 19206 if ( r === undefined ) { 19207 19208 r = new Int32Array( n ); 19209 arrayCacheI32[ n ] = r; 19210 19211 } 19212 19213 for ( var i = 0; i !== n; ++ i ) 19214 r[ i ] = renderer.allocTextureUnit(); 19215 19216 return r; 19217 19218 } 19219 19220 // --- Setters --- 19221 19222 // Note: Defining these methods externally, because they come in a bunch 19223 // and this way their names minify. 19224 19225 // Single scalar 19226 19227 function setValue1f( gl, v ) { 19228 19229 var cache = this.cache; 19230 19231 if ( cache[ 0 ] === v ) return; 19232 19233 gl.uniform1f( this.addr, v ); 19234 19235 cache[ 0 ] = v; 19236 19237 } 19238 19239 function setValue1i( gl, v ) { 19240 19241 var cache = this.cache; 19242 19243 if ( cache[ 0 ] === v ) return; 19244 19245 gl.uniform1i( this.addr, v ); 19246 19247 cache[ 0 ] = v; 19248 19249 } 19250 19251 // Single float vector (from flat array or THREE.VectorN) 19252 19253 function setValue2fv( gl, v ) { 19254 19255 var cache = this.cache; 19256 19257 if ( v.x !== undefined ) { 19258 19259 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y ) { 19260 19261 gl.uniform2f( this.addr, v.x, v.y ); 19262 19263 cache[ 0 ] = v.x; 19264 cache[ 1 ] = v.y; 19265 19266 } 19267 19268 } else { 19269 19270 if ( arraysEqual( cache, v ) ) return; 19271 19272 gl.uniform2fv( this.addr, v ); 19273 19274 copyArray( cache, v ); 19275 19276 } 19277 19278 } 19279 19280 function setValue3fv( gl, v ) { 19281 19282 var cache = this.cache; 19283 19284 if ( v.x !== undefined ) { 19285 19286 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z ) { 19287 19288 gl.uniform3f( this.addr, v.x, v.y, v.z ); 19289 19290 cache[ 0 ] = v.x; 19291 cache[ 1 ] = v.y; 19292 cache[ 2 ] = v.z; 19293 19294 } 19295 19296 } else if ( v.r !== undefined ) { 19297 19298 if ( cache[ 0 ] !== v.r || cache[ 1 ] !== v.g || cache[ 2 ] !== v.b ) { 19299 19300 gl.uniform3f( this.addr, v.r, v.g, v.b ); 19301 19302 cache[ 0 ] = v.r; 19303 cache[ 1 ] = v.g; 19304 cache[ 2 ] = v.b; 19305 19306 } 19307 19308 } else { 19309 19310 if ( arraysEqual( cache, v ) ) return; 19311 19312 gl.uniform3fv( this.addr, v ); 19313 19314 copyArray( cache, v ); 19315 19316 } 19317 19318 } 19319 19320 function setValue4fv( gl, v ) { 19321 19322 var cache = this.cache; 19323 19324 if ( v.x !== undefined ) { 19325 19326 if ( cache[ 0 ] !== v.x || cache[ 1 ] !== v.y || cache[ 2 ] !== v.z || cache[ 3 ] !== v.w ) { 19327 19328 gl.uniform4f( this.addr, v.x, v.y, v.z, v.w ); 19329 19330 cache[ 0 ] = v.x; 19331 cache[ 1 ] = v.y; 19332 cache[ 2 ] = v.z; 19333 cache[ 3 ] = v.w; 19334 19335 } 19336 19337 } else { 19338 19339 if ( arraysEqual( cache, v ) ) return; 19340 19341 gl.uniform4fv( this.addr, v ); 19342 19343 copyArray( cache, v ); 19344 19345 } 19346 19347 } 19348 19349 // Single matrix (from flat array or MatrixN) 19350 19351 function setValue2fm( gl, v ) { 19352 19353 var cache = this.cache; 19354 var elements = v.elements; 19355 19356 if ( elements === undefined ) { 19357 19358 if ( arraysEqual( cache, v ) ) return; 19359 19360 gl.uniformMatrix2fv( this.addr, false, v ); 19361 19362 copyArray( cache, v ); 19363 19364 } else { 19365 19366 if ( arraysEqual( cache, elements ) ) return; 19367 19368 mat2array.set( elements ); 19369 19370 gl.uniformMatrix2fv( this.addr, false, mat2array ); 19371 19372 copyArray( cache, elements ); 19373 19374 } 19375 19376 } 19377 19378 function setValue3fm( gl, v ) { 19379 19380 var cache = this.cache; 19381 var elements = v.elements; 19382 19383 if ( elements === undefined ) { 19384 19385 if ( arraysEqual( cache, v ) ) return; 19386 19387 gl.uniformMatrix3fv( this.addr, false, v ); 19388 19389 copyArray( cache, v ); 19390 19391 } else { 19392 19393 if ( arraysEqual( cache, elements ) ) return; 19394 19395 mat3array.set( elements ); 19396 19397 gl.uniformMatrix3fv( this.addr, false, mat3array ); 19398 19399 copyArray( cache, elements ); 19400 19401 } 19402 19403 } 19404 19405 function setValue4fm( gl, v ) { 19406 19407 var cache = this.cache; 19408 var elements = v.elements; 19409 19410 if ( elements === undefined ) { 19411 19412 if ( arraysEqual( cache, v ) ) return; 19413 19414 gl.uniformMatrix4fv( this.addr, false, v ); 19415 19416 copyArray( cache, v ); 19417 19418 } else { 19419 19420 if ( arraysEqual( cache, elements ) ) return; 19421 19422 mat4array.set( elements ); 19423 19424 gl.uniformMatrix4fv( this.addr, false, mat4array ); 19425 19426 copyArray( cache, elements ); 19427 19428 } 19429 19430 } 19431 19432 // Single texture (2D / Cube) 19433 19434 function setValueT1( gl, v, renderer ) { 19435 19436 var cache = this.cache; 19437 var unit = renderer.allocTextureUnit(); 19438 19439 if ( cache[ 0 ] !== unit ) { 19440 19441 gl.uniform1i( this.addr, unit ); 19442 cache[ 0 ] = unit; 19443 19444 } 19445 19446 renderer.setTexture2D( v || emptyTexture, unit ); 19447 19448 } 19449 19450 function setValueT6( gl, v, renderer ) { 19451 19452 var cache = this.cache; 19453 var unit = renderer.allocTextureUnit(); 19454 19455 if ( cache[ 0 ] !== unit ) { 19456 19457 gl.uniform1i( this.addr, unit ); 19458 cache[ 0 ] = unit; 19459 19460 } 19461 19462 renderer.setTextureCube( v || emptyCubeTexture, unit ); 19463 19464 } 19465 19466 // Integer / Boolean vectors or arrays thereof (always flat arrays) 19467 19468 function setValue2iv( gl, v ) { 19469 19470 var cache = this.cache; 19471 19472 if ( arraysEqual( cache, v ) ) return; 19473 19474 gl.uniform2iv( this.addr, v ); 19475 19476 copyArray( cache, v ); 19477 19478 } 19479 19480 function setValue3iv( gl, v ) { 19481 19482 var cache = this.cache; 19483 19484 if ( arraysEqual( cache, v ) ) return; 19485 19486 gl.uniform3iv( this.addr, v ); 19487 19488 copyArray( cache, v ); 19489 19490 } 19491 19492 function setValue4iv( gl, v ) { 19493 19494 var cache = this.cache; 19495 19496 if ( arraysEqual( cache, v ) ) return; 19497 19498 gl.uniform4iv( this.addr, v ); 19499 19500 copyArray( cache, v ); 19501 19502 } 19503 19504 // Helper to pick the right setter for the singular case 19505 19506 function getSingularSetter( type ) { 19507 19508 switch ( type ) { 19509 19510 case 0x1406: return setValue1f; // FLOAT 19511 case 0x8b50: return setValue2fv; // _VEC2 19512 case 0x8b51: return setValue3fv; // _VEC3 19513 case 0x8b52: return setValue4fv; // _VEC4 19514 19515 case 0x8b5a: return setValue2fm; // _MAT2 19516 case 0x8b5b: return setValue3fm; // _MAT3 19517 case 0x8b5c: return setValue4fm; // _MAT4 19518 19519 case 0x8b5e: case 0x8d66: return setValueT1; // SAMPLER_2D, SAMPLER_EXTERNAL_OES 19520 case 0x8b60: return setValueT6; // SAMPLER_CUBE 19521 19522 case 0x1404: case 0x8b56: return setValue1i; // INT, BOOL 19523 case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 19524 case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 19525 case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 19526 19527 } 19528 19529 } 19530 19531 // Array of scalars 19532 19533 function setValue1fv( gl, v ) { 19534 19535 var cache = this.cache; 19536 19537 if ( arraysEqual( cache, v ) ) return; 19538 19539 gl.uniform1fv( this.addr, v ); 19540 19541 copyArray( cache, v ); 19542 19543 } 19544 function setValue1iv( gl, v ) { 19545 19546 var cache = this.cache; 19547 19548 if ( arraysEqual( cache, v ) ) return; 19549 19550 gl.uniform1iv( this.addr, v ); 19551 19552 copyArray( cache, v ); 19553 19554 } 19555 19556 // Array of vectors (flat or from THREE classes) 19557 19558 function setValueV2a( gl, v ) { 19559 19560 var cache = this.cache; 19561 var data = flatten( v, this.size, 2 ); 19562 19563 if ( arraysEqual( cache, data ) ) return; 19564 19565 gl.uniform2fv( this.addr, data ); 19566 19567 this.updateCache( data ); 19568 19569 } 19570 19571 function setValueV3a( gl, v ) { 19572 19573 var cache = this.cache; 19574 var data = flatten( v, this.size, 3 ); 19575 19576 if ( arraysEqual( cache, data ) ) return; 19577 19578 gl.uniform3fv( this.addr, data ); 19579 19580 this.updateCache( data ); 19581 19582 } 19583 19584 function setValueV4a( gl, v ) { 19585 19586 var cache = this.cache; 19587 var data = flatten( v, this.size, 4 ); 19588 19589 if ( arraysEqual( cache, data ) ) return; 19590 19591 gl.uniform4fv( this.addr, data ); 19592 19593 this.updateCache( data ); 19594 19595 } 19596 19597 // Array of matrices (flat or from THREE clases) 19598 19599 function setValueM2a( gl, v ) { 19600 19601 var cache = this.cache; 19602 var data = flatten( v, this.size, 4 ); 19603 19604 if ( arraysEqual( cache, data ) ) return; 19605 19606 gl.uniformMatrix2fv( this.addr, false, data ); 19607 19608 this.updateCache( data ); 19609 19610 } 19611 19612 function setValueM3a( gl, v ) { 19613 19614 var cache = this.cache; 19615 var data = flatten( v, this.size, 9 ); 19616 19617 if ( arraysEqual( cache, data ) ) return; 19618 19619 gl.uniformMatrix3fv( this.addr, false, data ); 19620 19621 this.updateCache( data ); 19622 19623 } 19624 19625 function setValueM4a( gl, v ) { 19626 19627 var cache = this.cache; 19628 var data = flatten( v, this.size, 16 ); 19629 19630 if ( arraysEqual( cache, data ) ) return; 19631 19632 gl.uniformMatrix4fv( this.addr, false, data ); 19633 19634 this.updateCache( data ); 19635 19636 } 19637 19638 // Array of textures (2D / Cube) 19639 19640 function setValueT1a( gl, v, renderer ) { 19641 19642 var cache = this.cache; 19643 var n = v.length; 19644 19645 var units = allocTexUnits( renderer, n ); 19646 19647 if ( arraysEqual( cache, units ) === false ) { 19648 19649 gl.uniform1iv( this.addr, units ); 19650 copyArray( cache, units ); 19651 19652 } 19653 19654 for ( var i = 0; i !== n; ++ i ) { 19655 19656 renderer.setTexture2D( v[ i ] || emptyTexture, units[ i ] ); 19657 19658 } 19659 19660 } 19661 19662 function setValueT6a( gl, v, renderer ) { 19663 19664 var cache = this.cache; 19665 var n = v.length; 19666 19667 var units = allocTexUnits( renderer, n ); 19668 19669 if ( arraysEqual( cache, units ) === false ) { 19670 19671 gl.uniform1iv( this.addr, units ); 19672 copyArray( cache, units ); 19673 19674 } 19675 19676 for ( var i = 0; i !== n; ++ i ) { 19677 19678 renderer.setTextureCube( v[ i ] || emptyCubeTexture, units[ i ] ); 19679 19680 } 19681 19682 } 19683 19684 // Helper to pick the right setter for a pure (bottom-level) array 19685 19686 function getPureArraySetter( type ) { 19687 19688 switch ( type ) { 19689 19690 case 0x1406: return setValue1fv; // FLOAT 19691 case 0x8b50: return setValueV2a; // _VEC2 19692 case 0x8b51: return setValueV3a; // _VEC3 19693 case 0x8b52: return setValueV4a; // _VEC4 19694 19695 case 0x8b5a: return setValueM2a; // _MAT2 19696 case 0x8b5b: return setValueM3a; // _MAT3 19697 case 0x8b5c: return setValueM4a; // _MAT4 19698 19699 case 0x8b5e: return setValueT1a; // SAMPLER_2D 19700 case 0x8b60: return setValueT6a; // SAMPLER_CUBE 19701 19702 case 0x1404: case 0x8b56: return setValue1iv; // INT, BOOL 19703 case 0x8b53: case 0x8b57: return setValue2iv; // _VEC2 19704 case 0x8b54: case 0x8b58: return setValue3iv; // _VEC3 19705 case 0x8b55: case 0x8b59: return setValue4iv; // _VEC4 19706 19707 } 19708 19709 } 19710 19711 // --- Uniform Classes --- 19712 19713 function SingleUniform( id, activeInfo, addr ) { 19714 19715 this.id = id; 19716 this.addr = addr; 19717 this.cache = []; 19718 this.setValue = getSingularSetter( activeInfo.type ); 19719 19720 // this.path = activeInfo.name; // DEBUG 19721 19722 } 19723 19724 function PureArrayUniform( id, activeInfo, addr ) { 19725 19726 this.id = id; 19727 this.addr = addr; 19728 this.cache = []; 19729 this.size = activeInfo.size; 19730 this.setValue = getPureArraySetter( activeInfo.type ); 19731 19732 // this.path = activeInfo.name; // DEBUG 19733 19734 } 19735 19736 PureArrayUniform.prototype.updateCache = function ( data ) { 19737 19738 var cache = this.cache; 19739 19740 if ( data instanceof Float32Array && cache.length !== data.length ) { 19741 19742 this.cache = new Float32Array( data.length ); 19743 19744 } 19745 19746 copyArray( cache, data ); 19747 19748 }; 19749 19750 function StructuredUniform( id ) { 19751 19752 this.id = id; 19753 19754 UniformContainer.call( this ); // mix-in 19755 19756 } 19757 19758 StructuredUniform.prototype.setValue = function ( gl, value ) { 19759 19760 // Note: Don't need an extra 'renderer' parameter, since samplers 19761 // are not allowed in structured uniforms. 19762 19763 var seq = this.seq; 19764 19765 for ( var i = 0, n = seq.length; i !== n; ++ i ) { 19766 19767 var u = seq[ i ]; 19768 u.setValue( gl, value[ u.id ] ); 19769 19770 } 19771 19772 }; 19773 19774 // --- Top-level --- 19775 19776 // Parser - builds up the property tree from the path strings 19777 19778 var RePathPart = /([\w\d_]+)(\])?(\[|\.)?/g; 19779 19780 // extracts 19781 // - the identifier (member name or array index) 19782 // - followed by an optional right bracket (found when array index) 19783 // - followed by an optional left bracket or dot (type of subscript) 19784 // 19785 // Note: These portions can be read in a non-overlapping fashion and 19786 // allow straightforward parsing of the hierarchy that WebGL encodes 19787 // in the uniform names. 19788 19789 function addUniform( container, uniformObject ) { 19790 19791 container.seq.push( uniformObject ); 19792 container.map[ uniformObject.id ] = uniformObject; 19793 19794 } 19795 19796 function parseUniform( activeInfo, addr, container ) { 19797 19798 var path = activeInfo.name, 19799 pathLength = path.length; 19800 19801 // reset RegExp object, because of the early exit of a previous run 19802 RePathPart.lastIndex = 0; 19803 19804 while ( true ) { 19805 19806 var match = RePathPart.exec( path ), 19807 matchEnd = RePathPart.lastIndex, 19808 19809 id = match[ 1 ], 19810 idIsIndex = match[ 2 ] === ']', 19811 subscript = match[ 3 ]; 19812 19813 if ( idIsIndex ) id = id | 0; // convert to integer 19814 19815 if ( subscript === undefined || subscript === '[' && matchEnd + 2 === pathLength ) { 19816 19817 // bare name or "pure" bottom-level array "[0]" suffix 19818 19819 addUniform( container, subscript === undefined ? 19820 new SingleUniform( id, activeInfo, addr ) : 19821 new PureArrayUniform( id, activeInfo, addr ) ); 19822 19823 break; 19824 19825 } else { 19826
vendor: 6,229 bytes, lines 19827-20102
19827 // step into inner node / create it in case it doesn't exist 19828 19829 var map = container.map, next = map[ id ]; 19830 19831 if ( next === undefined ) { 19832 19833 next = new StructuredUniform( id ); 19834 addUniform( container, next ); 19835 19836 } 19837 19838 container = next; 19839 19840 } 19841 19842 } 19843 19844 } 19845 19846 // Root Container 19847 19848 function WebGLUniforms( gl, program, renderer ) { 19849 19850 UniformContainer.call( this ); 19851 19852 this.renderer = renderer; 19853 19854 var n = gl.getProgramParameter( program, gl.ACTIVE_UNIFORMS ); 19855 19856 for ( var i = 0; i < n; ++ i ) { 19857 19858 var info = gl.getActiveUniform( program, i ), 19859 addr = gl.getUniformLocation( program, info.name ); 19860 19861 parseUniform( info, addr, this ); 19862 19863 } 19864 19865 } 19866 19867 WebGLUniforms.prototype.setValue = function ( gl, name, value ) { 19868 19869 var u = this.map[ name ]; 19870 19871 if ( u !== undefined ) u.setValue( gl, value, this.renderer ); 19872 19873 }; 19874 19875 WebGLUniforms.prototype.setOptional = function ( gl, object, name ) { 19876 19877 var v = object[ name ]; 19878 19879 if ( v !== undefined ) this.setValue( gl, name, v ); 19880 19881 }; 19882 19883 19884 // Static interface 19885 19886 WebGLUniforms.upload = function ( gl, seq, values, renderer ) { 19887 19888 for ( var i = 0, n = seq.length; i !== n; ++ i ) { 19889 19890 var u = seq[ i ], 19891 v = values[ u.id ]; 19892 19893 if ( v.needsUpdate !== false ) { 19894 19895 // note: always updating when .needsUpdate is undefined 19896 u.setValue( gl, v.value, renderer ); 19897 19898 } 19899 19900 } 19901 19902 }; 19903 19904 WebGLUniforms.seqWithValue = function ( seq, values ) { 19905 19906 var r = []; 19907 19908 for ( var i = 0, n = seq.length; i !== n; ++ i ) { 19909 19910 var u = seq[ i ]; 19911 if ( u.id in values ) r.push( u ); 19912 19913 } 19914 19915 return r; 19916 19917 }; 19918 19919 /** 19920 * @author mrdoob / http://mrdoob.com/ 19921 */ 19922 19923 function addLineNumbers( string ) { 19924 19925 var lines = string.split( '\n' ); 19926 19927 for ( var i = 0; i < lines.length; i ++ ) { 19928 19929 lines[ i ] = ( i + 1 ) + ': ' + lines[ i ]; 19930 19931 } 19932 19933 return lines.join( '\n' ); 19934 19935 } 19936 19937 function WebGLShader( gl, type, string ) { 19938 19939 var shader = gl.createShader( type ); 19940 19941 gl.shaderSource( shader, string ); 19942 gl.compileShader( shader ); 19943 19944 if ( gl.getShaderParameter( shader, gl.COMPILE_STATUS ) === false ) { 19945 19946 console.error( 'THREE.WebGLShader: Shader couldn\'t compile.' ); 19947 19948 } 19949 19950 if ( gl.getShaderInfoLog( shader ) !== '' ) { 19951 19952 console.warn( 'THREE.WebGLShader: gl.getShaderInfoLog()', type === gl.VERTEX_SHADER ? 'vertex' : 'fragment', gl.getShaderInfoLog( shader ), addLineNumbers( string ) ); 19953 19954 } 19955 19956 // --enable-privileged-webgl-extension 19957 // console.log( type, gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( shader ) ); 19958 19959 return shader; 19960 19961 } 19962 19963 /** 19964 * @author mrdoob / http://mrdoob.com/ 19965 */ 19966 19967 var programIdCount = 0; 19968 19969 function getEncodingComponents( encoding ) { 19970 19971 switch ( encoding ) { 19972 19973 case LinearEncoding: 19974 return [ 'Linear', '( value )' ]; 19975 case sRGBEncoding: 19976 return [ 'sRGB', '( value )' ]; 19977 case RGBEEncoding: 19978 return [ 'RGBE', '( value )' ]; 19979 case RGBM7Encoding: 19980 return [ 'RGBM', '( value, 7.0 )' ]; 19981 case RGBM16Encoding: 19982 return [ 'RGBM', '( value, 16.0 )' ]; 19983 case RGBDEncoding: 19984 return [ 'RGBD', '( value, 256.0 )' ]; 19985 case GammaEncoding: 19986 return [ 'Gamma', '( value, float( GAMMA_FACTOR ) )' ]; 19987 default: 19988 throw new Error( 'unsupported encoding: ' + encoding ); 19989 19990 } 19991 19992 } 19993 19994 function getTexelDecodingFunction( functionName, encoding ) { 19995 19996 var components = getEncodingComponents( encoding ); 19997 return 'vec4 ' + functionName + '( vec4 value ) { return ' + components[ 0 ] + 'ToLinear' + components[ 1 ] + '; }'; 19998 19999 } 20000 20001 function getTexelEncodingFunction( functionName, encoding ) { 20002 20003 var components = getEncodingComponents( encoding ); 20004 return 'vec4 ' + functionName + '( vec4 value ) { return LinearTo' + components[ 0 ] + components[ 1 ] + '; }'; 20005 20006 } 20007 20008 function getToneMappingFunction( functionName, toneMapping ) { 20009 20010 var toneMappingName; 20011 20012 switch ( toneMapping ) { 20013 20014 case LinearToneMapping: 20015 toneMappingName = 'Linear'; 20016 break; 20017 20018 case ReinhardToneMapping: 20019 toneMappingName = 'Reinhard'; 20020 break; 20021 20022 case Uncharted2ToneMapping: 20023 toneMappingName = 'Uncharted2'; 20024 break; 20025 20026 case CineonToneMapping: 20027 toneMappingName = 'OptimizedCineon'; 20028 break; 20029 20030 default: 20031 throw new Error( 'unsupported toneMapping: ' + toneMapping ); 20032 20033 } 20034 20035 return 'vec3 ' + functionName + '( vec3 color ) { return ' + toneMappingName + 'ToneMapping( color ); }'; 20036 20037 } 20038 20039 function generateExtensions( extensions, parameters, rendererExtensions ) { 20040 20041 extensions = extensions || {}; 20042 20043 var chunks = [ 20044 ( extensions.derivatives || parameters.envMapCubeUV || parameters.bumpMap || parameters.normalMap || parameters.flatShading ) ? '#extension GL_OES_standard_derivatives : enable' : '', 20045 ( extensions.fragDepth || parameters.logarithmicDepthBuffer ) && rendererExtensions.get( 'EXT_frag_depth' ) ? '#extension GL_EXT_frag_depth : enable' : '', 20046 ( extensions.drawBuffers ) && rendererExtensions.get( 'WEBGL_draw_buffers' ) ? '#extension GL_EXT_draw_buffers : require' : '', 20047 ( extensions.shaderTextureLOD || parameters.envMap ) && rendererExtensions.get( 'EXT_shader_texture_lod' ) ? '#extension GL_EXT_shader_texture_lod : enable' : '' 20048 ]; 20049 20050 return chunks.filter( filterEmptyLine ).join( '\n' ); 20051 20052 } 20053 20054 function generateDefines( defines ) { 20055 20056 var chunks = []; 20057 20058 for ( var name in defines ) { 20059 20060 var value = defines[ name ]; 20061 20062 if ( value === false ) continue; 20063 20064 chunks.push( '#define ' + name + ' ' + value ); 20065 20066 } 20067 20068 return chunks.join( '\n' ); 20069 20070 } 20071 20072 function fetchAttributeLocations( gl, program ) { 20073 20074 var attributes = {}; 20075 20076 var n = gl.getProgramParameter( program, gl.ACTIVE_ATTRIBUTES ); 20077 20078 for ( var i = 0; i < n; i ++ ) { 20079 20080 var info = gl.getActiveAttrib( program, i ); 20081 var name = info.name; 20082 20083 // console.log( 'THREE.WebGLProgram: ACTIVE VERTEX ATTRIBUTE:', name, i ); 20084 20085 attributes[ name ] = gl.getAttribLocation( program, name ); 20086 20087 } 20088 20089 return attributes; 20090 20091 } 20092 20093 function filterEmptyLine( string ) { 20094 20095 return string !== ''; 20096 20097 } 20098 20099 function replaceLightNums( string, parameters ) { 20100 20101 return string 20102 .replace( /NUM_DIR_LIGHTS/g, parameters.numDirLights )
vendor: 12,929 bytes, lines 20103-20513
20103 .replace( /NUM_SPOT_LIGHTS/g, parameters.numSpotLights ) 20104 .replace( /NUM_RECT_AREA_LIGHTS/g, parameters.numRectAreaLights ) 20105 .replace( /NUM_POINT_LIGHTS/g, parameters.numPointLights ) 20106 .replace( /NUM_HEMI_LIGHTS/g, parameters.numHemiLights ); 20107 20108 } 20109 20110 function replaceClippingPlaneNums( string, parameters ) { 20111 20112 return string 20113 .replace( /NUM_CLIPPING_PLANES/g, parameters.numClippingPlanes ) 20114 .replace( /UNION_CLIPPING_PLANES/g, ( parameters.numClippingPlanes - parameters.numClipIntersection ) ); 20115 20116 } 20117 20118 function parseIncludes( string ) { 20119 20120 var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm; 20121 20122 function replace( match, include ) { 20123 20124 var replace = ShaderChunk[ include ]; 20125 20126 if ( replace === undefined ) { 20127 20128 throw new Error( 'Can not resolve #include <' + include + '>' ); 20129 20130 } 20131 20132 return parseIncludes( replace ); 20133 20134 } 20135 20136 return string.replace( pattern, replace ); 20137 20138 } 20139 20140 function unrollLoops( string ) { 20141 20142 var pattern = /#pragma unroll_loop[\s]+?for \( int i \= (\d+)\; i < (\d+)\; i \+\+ \) \{([\s\S]+?)(?=\})\}/g; 20143 20144 function replace( match, start, end, snippet ) { 20145 20146 var unroll = ''; 20147 20148 for ( var i = parseInt( start ); i < parseInt( end ); i ++ ) { 20149 20150 unroll += snippet.replace( /\[ i \]/g, '[ ' + i + ' ]' ); 20151 20152 } 20153 20154 return unroll; 20155 20156 } 20157 20158 return string.replace( pattern, replace ); 20159 20160 } 20161 20162 function WebGLProgram( renderer, extensions, code, material, shader, parameters ) { 20163 20164 var gl = renderer.context; 20165 20166 var defines = material.defines; 20167 20168 var vertexShader = shader.vertexShader; 20169 var fragmentShader = shader.fragmentShader; 20170 20171 var shadowMapTypeDefine = 'SHADOWMAP_TYPE_BASIC'; 20172 20173 if ( parameters.shadowMapType === PCFShadowMap ) { 20174 20175 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF'; 20176 20177 } else if ( parameters.shadowMapType === PCFSoftShadowMap ) { 20178 20179 shadowMapTypeDefine = 'SHADOWMAP_TYPE_PCF_SOFT'; 20180 20181 } 20182 20183 var envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 20184 var envMapModeDefine = 'ENVMAP_MODE_REFLECTION'; 20185 var envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; 20186 20187 if ( parameters.envMap ) { 20188 20189 switch ( material.envMap.mapping ) { 20190 20191 case CubeReflectionMapping: 20192 case CubeRefractionMapping: 20193 envMapTypeDefine = 'ENVMAP_TYPE_CUBE'; 20194 break; 20195 20196 case CubeUVReflectionMapping: 20197 case CubeUVRefractionMapping: 20198 envMapTypeDefine = 'ENVMAP_TYPE_CUBE_UV'; 20199 break; 20200 20201 case EquirectangularReflectionMapping: 20202 case EquirectangularRefractionMapping: 20203 envMapTypeDefine = 'ENVMAP_TYPE_EQUIREC'; 20204 break; 20205 20206 case SphericalReflectionMapping: 20207 envMapTypeDefine = 'ENVMAP_TYPE_SPHERE'; 20208 break; 20209 20210 } 20211 20212 switch ( material.envMap.mapping ) { 20213 20214 case CubeRefractionMapping: 20215 case EquirectangularRefractionMapping: 20216 envMapModeDefine = 'ENVMAP_MODE_REFRACTION'; 20217 break; 20218 20219 } 20220 20221 switch ( material.combine ) { 20222 20223 case MultiplyOperation: 20224 envMapBlendingDefine = 'ENVMAP_BLENDING_MULTIPLY'; 20225 break; 20226 20227 case MixOperation: 20228 envMapBlendingDefine = 'ENVMAP_BLENDING_MIX'; 20229 break; 20230 20231 case AddOperation: 20232 envMapBlendingDefine = 'ENVMAP_BLENDING_ADD'; 20233 break; 20234 20235 } 20236 20237 } 20238 20239 var gammaFactorDefine = ( renderer.gammaFactor > 0 ) ? renderer.gammaFactor : 1.0; 20240 20241 // console.log( 'building new program ' ); 20242 20243 // 20244 20245 var customExtensions = generateExtensions( material.extensions, parameters, extensions ); 20246 20247 var customDefines = generateDefines( defines ); 20248 20249 // 20250 20251 var program = gl.createProgram(); 20252 20253 var prefixVertex, prefixFragment; 20254 20255 if ( material.isRawShaderMaterial ) { 20256 20257 prefixVertex = [ 20258 20259 customDefines 20260 20261 ].filter( filterEmptyLine ).join( '\n' ); 20262 20263 if ( prefixVertex.length > 0 ) { 20264 20265 prefixVertex += '\n'; 20266 20267 } 20268 20269 prefixFragment = [ 20270 20271 customExtensions, 20272 customDefines 20273 20274 ].filter( filterEmptyLine ).join( '\n' ); 20275 20276 if ( prefixFragment.length > 0 ) { 20277 20278 prefixFragment += '\n'; 20279 20280 } 20281 20282 } else { 20283 20284 prefixVertex = [ 20285 20286 'precision ' + parameters.precision + ' float;', 20287 'precision ' + parameters.precision + ' int;', 20288 20289 '#define SHADER_NAME ' + shader.name, 20290 20291 customDefines, 20292 20293 parameters.supportsVertexTextures ? '#define VERTEX_TEXTURES' : '', 20294 20295 '#define GAMMA_FACTOR ' + gammaFactorDefine, 20296 20297 '#define MAX_BONES ' + parameters.maxBones, 20298 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', 20299 ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', 20300 20301 parameters.map ? '#define USE_MAP' : '', 20302 parameters.envMap ? '#define USE_ENVMAP' : '', 20303 parameters.envMap ? '#define ' + envMapModeDefine : '', 20304 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 20305 parameters.aoMap ? '#define USE_AOMAP' : '', 20306 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 20307 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 20308 parameters.normalMap ? '#define USE_NORMALMAP' : '', 20309 parameters.displacementMap && parameters.supportsVertexTextures ? '#define USE_DISPLACEMENTMAP' : '', 20310 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 20311 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 20312 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 20313 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 20314 parameters.vertexColors ? '#define USE_COLOR' : '', 20315 20316 parameters.flatShading ? '#define FLAT_SHADED' : '', 20317 20318 parameters.skinning ? '#define USE_SKINNING' : '', 20319 parameters.useVertexTexture ? '#define BONE_TEXTURE' : '', 20320 20321 parameters.morphTargets ? '#define USE_MORPHTARGETS' : '', 20322 parameters.morphNormals && parameters.flatShading === false ? '#define USE_MORPHNORMALS' : '', 20323 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 20324 parameters.flipSided ? '#define FLIP_SIDED' : '', 20325 20326 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 20327 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 20328 20329 parameters.sizeAttenuation ? '#define USE_SIZEATTENUATION' : '', 20330 20331 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 20332 parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', 20333 20334 'uniform mat4 modelMatrix;', 20335 'uniform mat4 modelViewMatrix;', 20336 'uniform mat4 projectionMatrix;', 20337 'uniform mat4 viewMatrix;', 20338 'uniform mat3 normalMatrix;', 20339 'uniform vec3 cameraPosition;', 20340 20341 'attribute vec3 position;', 20342 'attribute vec3 normal;', 20343 'attribute vec2 uv;', 20344 20345 '#ifdef USE_COLOR', 20346 20347 ' attribute vec3 color;', 20348 20349 '#endif', 20350 20351 '#ifdef USE_MORPHTARGETS', 20352 20353 ' attribute vec3 morphTarget0;', 20354 ' attribute vec3 morphTarget1;', 20355 ' attribute vec3 morphTarget2;', 20356 ' attribute vec3 morphTarget3;', 20357 20358 ' #ifdef USE_MORPHNORMALS', 20359 20360 ' attribute vec3 morphNormal0;', 20361 ' attribute vec3 morphNormal1;', 20362 ' attribute vec3 morphNormal2;', 20363 ' attribute vec3 morphNormal3;', 20364 20365 ' #else', 20366 20367 ' attribute vec3 morphTarget4;', 20368 ' attribute vec3 morphTarget5;', 20369 ' attribute vec3 morphTarget6;', 20370 ' attribute vec3 morphTarget7;', 20371 20372 ' #endif', 20373 20374 '#endif', 20375 20376 '#ifdef USE_SKINNING', 20377 20378 ' attribute vec4 skinIndex;', 20379 ' attribute vec4 skinWeight;', 20380 20381 '#endif', 20382 20383 '\n' 20384 20385 ].filter( filterEmptyLine ).join( '\n' ); 20386 20387 prefixFragment = [ 20388 20389 customExtensions, 20390 20391 'precision ' + parameters.precision + ' float;', 20392 'precision ' + parameters.precision + ' int;', 20393 20394 '#define SHADER_NAME ' + shader.name, 20395 20396 customDefines, 20397 20398 parameters.alphaTest ? '#define ALPHATEST ' + parameters.alphaTest + ( parameters.alphaTest % 1 ? '' : '.0' ) : '', // add '.0' if integer 20399 20400 '#define GAMMA_FACTOR ' + gammaFactorDefine, 20401 20402 ( parameters.useFog && parameters.fog ) ? '#define USE_FOG' : '', 20403 ( parameters.useFog && parameters.fogExp ) ? '#define FOG_EXP2' : '', 20404 20405 parameters.map ? '#define USE_MAP' : '', 20406 parameters.envMap ? '#define USE_ENVMAP' : '', 20407 parameters.envMap ? '#define ' + envMapTypeDefine : '', 20408 parameters.envMap ? '#define ' + envMapModeDefine : '', 20409 parameters.envMap ? '#define ' + envMapBlendingDefine : '', 20410 parameters.lightMap ? '#define USE_LIGHTMAP' : '', 20411 parameters.aoMap ? '#define USE_AOMAP' : '', 20412 parameters.emissiveMap ? '#define USE_EMISSIVEMAP' : '', 20413 parameters.bumpMap ? '#define USE_BUMPMAP' : '', 20414 parameters.normalMap ? '#define USE_NORMALMAP' : '', 20415 parameters.specularMap ? '#define USE_SPECULARMAP' : '', 20416 parameters.roughnessMap ? '#define USE_ROUGHNESSMAP' : '', 20417 parameters.metalnessMap ? '#define USE_METALNESSMAP' : '', 20418 parameters.alphaMap ? '#define USE_ALPHAMAP' : '', 20419 parameters.vertexColors ? '#define USE_COLOR' : '', 20420 20421 parameters.gradientMap ? '#define USE_GRADIENTMAP' : '', 20422 20423 parameters.flatShading ? '#define FLAT_SHADED' : '', 20424 20425 parameters.doubleSided ? '#define DOUBLE_SIDED' : '', 20426 parameters.flipSided ? '#define FLIP_SIDED' : '', 20427 20428 parameters.shadowMapEnabled ? '#define USE_SHADOWMAP' : '', 20429 parameters.shadowMapEnabled ? '#define ' + shadowMapTypeDefine : '', 20430 20431 parameters.premultipliedAlpha ? '#define PREMULTIPLIED_ALPHA' : '', 20432 20433 parameters.physicallyCorrectLights ? '#define PHYSICALLY_CORRECT_LIGHTS' : '', 20434 20435 parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', 20436 parameters.logarithmicDepthBuffer && extensions.get( 'EXT_frag_depth' ) ? '#define USE_LOGDEPTHBUF_EXT' : '', 20437 20438 parameters.envMap && extensions.get( 'EXT_shader_texture_lod' ) ? '#define TEXTURE_LOD_EXT' : '', 20439 20440 'uniform mat4 viewMatrix;', 20441 'uniform vec3 cameraPosition;', 20442 20443 ( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '', 20444 ( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below 20445 ( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '', 20446 20447 parameters.dithering ? '#define DITHERING' : '', 20448 20449 ( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below 20450 parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '', 20451 parameters.envMapEncoding ? getTexelDecodingFunction( 'envMapTexelToLinear', parameters.envMapEncoding ) : '', 20452 parameters.emissiveMapEncoding ? getTexelDecodingFunction( 'emissiveMapTexelToLinear', parameters.emissiveMapEncoding ) : '', 20453 parameters.outputEncoding ? getTexelEncodingFunction( 'linearToOutputTexel', parameters.outputEncoding ) : '', 20454 20455 parameters.depthPacking ? '#define DEPTH_PACKING ' + material.depthPacking : '', 20456 20457 '\n' 20458 20459 ].filter( filterEmptyLine ).join( '\n' ); 20460 20461 } 20462 20463 vertexShader = parseIncludes( vertexShader ); 20464 vertexShader = replaceLightNums( vertexShader, parameters ); 20465 vertexShader = replaceClippingPlaneNums( vertexShader, parameters ); 20466 20467 fragmentShader = parseIncludes( fragmentShader ); 20468 fragmentShader = replaceLightNums( fragmentShader, parameters ); 20469 fragmentShader = replaceClippingPlaneNums( fragmentShader, parameters ); 20470 20471 vertexShader = unrollLoops( vertexShader ); 20472 fragmentShader = unrollLoops( fragmentShader ); 20473 20474 var vertexGlsl = prefixVertex + vertexShader; 20475 var fragmentGlsl = prefixFragment + fragmentShader; 20476 20477 // console.log( '*VERTEX*', vertexGlsl ); 20478 // console.log( '*FRAGMENT*', fragmentGlsl ); 20479 20480 var glVertexShader = WebGLShader( gl, gl.VERTEX_SHADER, vertexGlsl ); 20481 var glFragmentShader = WebGLShader( gl, gl.FRAGMENT_SHADER, fragmentGlsl ); 20482 20483 gl.attachShader( program, glVertexShader ); 20484 gl.attachShader( program, glFragmentShader ); 20485 20486 // Force a particular attribute to index 0. 20487 20488 if ( material.index0AttributeName !== undefined ) { 20489 20490 gl.bindAttribLocation( program, 0, material.index0AttributeName ); 20491 20492 } else if ( parameters.morphTargets === true ) { 20493 20494 // programs with morphTargets displace position out of attribute 0 20495 gl.bindAttribLocation( program, 0, 'position' ); 20496 20497 } 20498 20499 gl.linkProgram( program ); 20500 20501 var programLog = gl.getProgramInfoLog( program ).trim(); 20502 var vertexLog = gl.getShaderInfoLog( glVertexShader ).trim(); 20503 var fragmentLog = gl.getShaderInfoLog( glFragmentShader ).trim(); 20504 20505 var runnable = true; 20506 var haveDiagnostics = true; 20507 20508 // console.log( '**VERTEX**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glVertexShader ) ); 20509 // console.log( '**FRAGMENT**', gl.getExtension( 'WEBGL_debug_shaders' ).getTranslatedShaderSource( glFragmentShader ) ); 20510 20511 if ( gl.getProgramParameter( program, gl.LINK_STATUS ) === false ) { 20512 20513 runnable = false;
vendor: 4,320 bytes, lines 20514-20699
20514 20515 console.error( 'THREE.WebGLProgram: shader error: ', gl.getError(), 'gl.VALIDATE_STATUS', gl.getProgramParameter( program, gl.VALIDATE_STATUS ), 'gl.getProgramInfoLog', programLog, vertexLog, fragmentLog ); 20516 20517 } else if ( programLog !== '' ) { 20518 20519 console.warn( 'THREE.WebGLProgram: gl.getProgramInfoLog()', programLog ); 20520 20521 } else if ( vertexLog === '' || fragmentLog === '' ) { 20522 20523 haveDiagnostics = false; 20524 20525 } 20526 20527 if ( haveDiagnostics ) { 20528 20529 this.diagnostics = { 20530 20531 runnable: runnable, 20532 material: material, 20533 20534 programLog: programLog, 20535 20536 vertexShader: { 20537 20538 log: vertexLog, 20539 prefix: prefixVertex 20540 20541 }, 20542 20543 fragmentShader: { 20544 20545 log: fragmentLog, 20546 prefix: prefixFragment 20547 20548 } 20549 20550 }; 20551 20552 } 20553 20554 // clean up 20555 20556 gl.deleteShader( glVertexShader ); 20557 gl.deleteShader( glFragmentShader ); 20558 20559 // set up caching for uniform locations 20560 20561 var cachedUniforms; 20562 20563 this.getUniforms = function () { 20564 20565 if ( cachedUniforms === undefined ) { 20566 20567 cachedUniforms = new WebGLUniforms( gl, program, renderer ); 20568 20569 } 20570 20571 return cachedUniforms; 20572 20573 }; 20574 20575 // set up caching for attribute locations 20576 20577 var cachedAttributes; 20578 20579 this.getAttributes = function () { 20580 20581 if ( cachedAttributes === undefined ) { 20582 20583 cachedAttributes = fetchAttributeLocations( gl, program ); 20584 20585 } 20586 20587 return cachedAttributes; 20588 20589 }; 20590 20591 // free resource 20592 20593 this.destroy = function () { 20594 20595 gl.deleteProgram( program ); 20596 this.program = undefined; 20597 20598 }; 20599 20600 // DEPRECATED 20601 20602 Object.defineProperties( this, { 20603 20604 uniforms: { 20605 get: function () { 20606 20607 console.warn( 'THREE.WebGLProgram: .uniforms is now .getUniforms().' ); 20608 return this.getUniforms(); 20609 20610 } 20611 }, 20612 20613 attributes: { 20614 get: function () { 20615 20616 console.warn( 'THREE.WebGLProgram: .attributes is now .getAttributes().' ); 20617 return this.getAttributes(); 20618 20619 } 20620 } 20621 20622 } ); 20623 20624 20625 // 20626 20627 this.name = shader.name; 20628 this.id = programIdCount ++; 20629 this.code = code; 20630 this.usedTimes = 1; 20631 this.program = program; 20632 this.vertexShader = glVertexShader; 20633 this.fragmentShader = glFragmentShader; 20634 20635 return this; 20636 20637 } 20638 20639 /** 20640 * @author mrdoob / http://mrdoob.com/ 20641 */ 20642 20643 function WebGLPrograms( renderer, extensions, capabilities ) { 20644 20645 var programs = []; 20646 20647 var shaderIDs = { 20648 MeshDepthMaterial: 'depth', 20649 MeshDistanceMaterial: 'distanceRGBA', 20650 MeshNormalMaterial: 'normal', 20651 MeshBasicMaterial: 'basic', 20652 MeshLambertMaterial: 'lambert', 20653 MeshPhongMaterial: 'phong', 20654 MeshToonMaterial: 'phong', 20655 MeshStandardMaterial: 'physical', 20656 MeshPhysicalMaterial: 'physical', 20657 LineBasicMaterial: 'basic', 20658 LineDashedMaterial: 'dashed', 20659 PointsMaterial: 'points', 20660 ShadowMaterial: 'shadow' 20661 }; 20662 20663 var parameterNames = [ 20664 "precision", "supportsVertexTextures", "map", "mapEncoding", "envMap", "envMapMode", "envMapEncoding", 20665 "lightMap", "aoMap", "emissiveMap", "emissiveMapEncoding", "bumpMap", "normalMap", "displacementMap", "specularMap", 20666 "roughnessMap", "metalnessMap", "gradientMap", 20667 "alphaMap", "combine", "vertexColors", "fog", "useFog", "fogExp", 20668 "flatShading", "sizeAttenuation", "logarithmicDepthBuffer", "skinning", 20669 "maxBones", "useVertexTexture", "morphTargets", "morphNormals", 20670 "maxMorphTargets", "maxMorphNormals", "premultipliedAlpha", 20671 "numDirLights", "numPointLights", "numSpotLights", "numHemiLights", "numRectAreaLights", 20672 "shadowMapEnabled", "shadowMapType", "toneMapping", 'physicallyCorrectLights', 20673 "alphaTest", "doubleSided", "flipSided", "numClippingPlanes", "numClipIntersection", "depthPacking", "dithering" 20674 ]; 20675 20676 20677 function allocateBones( object ) { 20678 20679 var skeleton = object.skeleton; 20680 var bones = skeleton.bones; 20681 20682 if ( capabilities.floatVertexTextures ) { 20683 20684 return 1024; 20685 20686 } else { 20687 20688 // default for when object is not specified 20689 // ( for example when prebuilding shader to be used with multiple objects ) 20690 // 20691 // - leave some extra space for other uniforms 20692 // - limit here is ANGLE's 254 max uniform vectors 20693 // (up to 54 should be safe) 20694 20695 var nVertexUniforms = capabilities.maxVertexUniforms; 20696 var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 ); 20697 20698 var maxBones = Math.min( nVertexMatrices, bones.length ); 20699
20700 if ( maxBones < bones.length ) { 20701 20702 console.warn( 'THREE.WebGLRenderer: Skeleton has ' + bones.length + ' bones. This GPU supports ' + maxBones + '.' ); 20703 return 0; 20704 20705 } 20706 20707 return maxBones; 20708 20709 } 20710 20711 } 20712 20713 function getTextureEncodingFromMap( map, gammaOverrideLinear ) { 20714 20715 var encoding; 20716 20717 if ( ! map ) { 20718 20719 encoding = LinearEncoding; 20720 20721 } else if ( map.isTexture ) { 20722 20723 encoding = map.encoding; 20724 20725 } else if ( map.isWebGLRenderTarget ) { 20726 20727 console.warn( "THREE.WebGLPrograms.getTextureEncodingFromMap: don't use render targets as textures. Use their .texture property instead." ); 20728 encoding = map.texture.encoding; 20729 20730 } 20731 20732 // add backwards compatibility for WebGLRenderer.gammaInput/gammaOutput parameter, should probably be removed at some point. 20733 if ( encoding === LinearEncoding && gammaOverrideLinear ) { 20734 20735 encoding = GammaEncoding; 20736 20737 } 20738 20739 return encoding; 20740 20741 } 20742 20743 this.getParameters = function ( material, lights, shadows, fog, nClipPlanes, nClipIntersection, object ) { 20744 20745 var shaderID = shaderIDs[ material.type ]; 20746 20747 // heuristics to create shader parameters according to lights in the scene 20748 // (not to blow over maxLights budget) 20749 20750 var maxBones = object.isSkinnedMesh ? allocateBones( object ) : 0; 20751 var precision = capabilities.precision; 20752 20753 if ( material.precision !== null ) { 20754 20755 precision = capabilities.getMaxPrecision( material.precision ); 20756 20757 if ( precision !== material.precision ) { 20758 20759 console.warn( 'THREE.WebGLProgram.getParameters:', material.precision, 'not supported, using', precision, 'instead.' ); 20760 20761 } 20762 20763 } 20764 20765 var currentRenderTarget = renderer.getRenderTarget(); 20766 20767 var parameters = { 20768 20769 shaderID: shaderID, 20770 20771 precision: precision, 20772 supportsVertexTextures: capabilities.vertexTextures, 20773 outputEncoding: getTextureEncodingFromMap( ( ! currentRenderTarget ) ? null : currentRenderTarget.texture, renderer.gammaOutput ), 20774 map: !! material.map, 20775 mapEncoding: getTextureEncodingFromMap( material.map, renderer.gammaInput ), 20776 envMap: !! material.envMap, 20777 envMapMode: material.envMap && material.envMap.mapping, 20778 envMapEncoding: getTextureEncodingFromMap( material.envMap, renderer.gammaInput ), 20779 envMapCubeUV: ( !! material.envMap ) && ( ( material.envMap.mapping === CubeUVReflectionMapping ) || ( material.envMap.mapping === CubeUVRefractionMapping ) ), 20780 lightMap: !! material.lightMap, 20781 aoMap: !! material.aoMap, 20782 emissiveMap: !! material.emissiveMap, 20783 emissiveMapEncoding: getTextureEncodingFromMap( material.emissiveMap, renderer.gammaInput ), 20784 bumpMap: !! material.bumpMap, 20785 normalMap: !! material.normalMap, 20786 displacementMap: !! material.displacementMap, 20787 roughnessMap: !! material.roughnessMap, 20788 metalnessMap: !! material.metalnessMap, 20789 specularMap: !! material.specularMap, 20790 alphaMap: !! material.alphaMap, 20791 20792 gradientMap: !! material.gradientMap, 20793 20794 combine: material.combine, 20795 20796 vertexColors: material.vertexColors, 20797 20798 fog: !! fog, 20799 useFog: material.fog, 20800 fogExp: ( fog && fog.isFogExp2 ), 20801 20802 flatShading: material.flatShading, 20803 20804 sizeAttenuation: material.sizeAttenuation, 20805 logarithmicDepthBuffer: capabilities.logarithmicDepthBuffer, 20806 20807 skinning: material.skinning && maxBones > 0, 20808 maxBones: maxBones, 20809 useVertexTexture: capabilities.floatVertexTextures, 20810 20811 morphTargets: material.morphTargets, 20812 morphNormals: material.morphNormals, 20813 maxMorphTargets: renderer.maxMorphTargets, 20814 maxMorphNormals: renderer.maxMorphNormals, 20815 20816 numDirLights: lights.directional.length, 20817 numPointLights: lights.point.length, 20818 numSpotLights: lights.spot.length, 20819 numRectAreaLights: lights.rectArea.length, 20820 numHemiLights: lights.hemi.length, 20821 20822 numClippingPlanes: nClipPlanes, 20823 numClipIntersection: nClipIntersection, 20824 20825 dithering: material.dithering, 20826 20827 shadowMapEnabled: renderer.shadowMap.enabled && object.receiveShadow && shadows.length > 0, 20828 shadowMapType: renderer.shadowMap.type, 20829 20830 toneMapping: renderer.toneMapping, 20831 physicallyCorrectLights: renderer.physicallyCorrectLights, 20832 20833 premultipliedAlpha: material.premultipliedAlpha, 20834 20835 alphaTest: material.alphaTest, 20836 doubleSided: material.side === DoubleSide, 20837 flipSided: material.side === BackSide, 20838 20839 depthPacking: ( material.depthPacking !== undefined ) ? material.depthPacking : false 20840 20841 }; 20842 20843 return parameters; 20844 20845 }; 20846 20847 this.getProgramCode = function ( material, parameters ) { 20848 20849 var array = []; 20850 20851 if ( parameters.shaderID ) { 20852 20853 array.push( parameters.shaderID ); 20854 20855 } else { 20856
20857 array.push( material.fragmentShader ); 20858 array.push( material.vertexShader ); 20859 20860 } 20861 20862 if ( material.defines !== undefined ) { 20863 20864 for ( var name in material.defines ) { 20865 20866 array.push( name ); 20867 array.push( material.defines[ name ] ); 20868 20869 } 20870 20871 } 20872 20873 for ( var i = 0; i < parameterNames.length; i ++ ) { 20874 20875 array.push( parameters[ parameterNames[ i ] ] ); 20876 20877 } 20878 20879 array.push( material.onBeforeCompile.toString() ); 20880 20881 array.push( renderer.gammaOutput ); 20882 20883 return array.join(); 20884 20885 }; 20886 20887 this.acquireProgram = function ( material, shader, parameters, code ) { 20888 20889 var program; 20890 20891 // Check if code has been already compiled 20892 for ( var p = 0, pl = programs.length; p < pl; p ++ ) { 20893 20894 var programInfo = programs[ p ]; 20895 20896 if ( programInfo.code === code ) { 20897 20898 program = programInfo; 20899 ++ program.usedTimes; 20900 20901 break; 20902 20903 } 20904 20905 } 20906 20907 if ( program === undefined ) { 20908 20909 program = new WebGLProgram( renderer, extensions, code, material, shader, parameters ); 20910 programs.push( program ); 20911 20912 } 20913 20914 return program; 20915 20916 }; 20917 20918 this.releaseProgram = function ( program ) { 20919 20920 if ( -- program.usedTimes === 0 ) { 20921 20922 // Remove from unordered set 20923 var i = programs.indexOf( program ); 20924 programs[ i ] = programs[ programs.length - 1 ]; 20925 programs.pop(); 20926 20927 // Free WebGL resources 20928 program.destroy(); 20929 20930 } 20931 20932 }; 20933 20934 // Exposed for resource monitoring & error feedback via renderer.info: 20935 this.programs = programs; 20936 20937 } 20938 20939 /** 20940 * @author fordacious / fordacious.github.io 20941 */ 20942 20943 function WebGLProperties() { 20944 20945 var properties = new WeakMap(); 20946 20947 function get( object ) { 20948 20949 var map = properties.get( object ); 20950 20951 if ( map === undefined ) { 20952 20953 map = {}; 20954 properties.set( object, map ); 20955 20956 } 20957 20958 return map; 20959 20960 } 20961 20962 function remove( object ) { 20963 20964 properties.delete( object ); 20965 20966 } 20967 20968 function update( object, key, value ) { 20969 20970 properties.get( object )[ key ] = value; 20971 20972 } 20973 20974 function dispose() { 20975 20976 properties = new WeakMap(); 20977 20978 } 20979 20980 return { 20981 get: get, 20982 remove: remove, 20983 update: update, 20984 dispose: dispose 20985 }; 20986 20987 } 20988 20989 /** 20990 * @author mrdoob / http://mrdoob.com/ 20991 */ 20992 20993 function painterSortStable( a, b ) { 20994 20995 if ( a.renderOrder !== b.renderOrder ) { 20996 20997 return a.renderOrder - b.renderOrder; 20998 20999 } else if ( a.program && b.program && a.program !== b.program ) { 21000 21001 return a.program.id - b.program.id; 21002 21003 } else if ( a.material.id !== b.material.id ) { 21004 21005 return a.material.id - b.material.id; 21006 21007 } else if ( a.z !== b.z ) { 21008 21009 return a.z - b.z; 21010 21011 } else { 21012 21013 return a.id - b.id; 21014 21015 } 21016 21017 } 21018 21019 function reversePainterSortStable( a, b ) { 21020 21021 if ( a.renderOrder !== b.renderOrder ) { 21022 21023 return a.renderOrder - b.renderOrder; 21024 21025 } if ( a.z !== b.z ) { 21026 21027 return b.z - a.z; 21028 21029 } else { 21030 21031 return a.id - b.id; 21032 21033 } 21034 21035 } 21036 21037 function WebGLRenderList() { 21038 21039 var renderItems = []; 21040 var renderItemsIndex = 0; 21041 21042 var opaque = []; 21043 var transparent = []; 21044 21045 function init() { 21046 21047 renderItemsIndex = 0; 21048 21049 opaque.length = 0; 21050 transparent.length = 0; 21051 21052 } 21053 21054 function push( object, geometry, material, z, group ) { 21055 21056 var renderItem = renderItems[ renderItemsIndex ]; 21057 21058 if ( renderItem === undefined ) { 21059 21060 renderItem = { 21061 id: object.id, 21062 object: object, 21063 geometry: geometry, 21064 material: material, 21065 program: material.program, 21066 renderOrder: object.renderOrder, 21067 z: z, 21068 group: group 21069 }; 21070 21071 renderItems[ renderItemsIndex ] = renderItem; 21072 21073 } else { 21074 21075 renderItem.id = object.id; 21076 renderItem.object = object; 21077 renderItem.geometry = geometry; 21078 renderItem.material = material; 21079 renderItem.program = material.program; 21080 renderItem.renderOrder = object.renderOrder; 21081 renderItem.z = z; 21082 renderItem.group = group; 21083 21084 } 21085 21086 ( material.transparent === true ? transparent : opaque ).push( renderItem ); 21087 21088 renderItemsIndex ++; 21089 21090 } 21091 21092 function sort() { 21093 21094 if ( opaque.length > 1 ) opaque.sort( painterSortStable ); 21095 if ( transparent.length > 1 ) transparent.sort( reversePainterSortStable ); 21096 21097 } 21098 21099 return { 21100 opaque: opaque, 21101 transparent: transparent, 21102 21103 init: init, 21104 push: push, 21105 21106 sort: sort 21107 }; 21108 21109 } 21110 21111 function WebGLRenderLists() { 21112 21113 var lists = {}; 21114 21115 function get( scene, camera ) { 21116 21117 var hash = scene.id + ',' + camera.id; 21118 var list = lists[ hash ]; 21119 21120 if ( list === undefined ) { 21121 21122 // console.log( 'THREE.WebGLRenderLists:', hash ); 21123 21124 list = new WebGLRenderList(); 21125 lists[ hash ] = list; 21126 21127 } 21128 21129 return list; 21130 21131 } 21132 21133 function dispose() { 21134 21135 lists = {}; 21136 21137 } 21138 21139 return { 21140 get: get,
vendor: 4,154 bytes, lines 21141-21339
21141 dispose: dispose 21142 }; 21143 21144 } 21145 21146 /** 21147 * @author mrdoob / http://mrdoob.com/ 21148 */ 21149 21150 function UniformsCache() { 21151 21152 var lights = {}; 21153 21154 return { 21155 21156 get: function ( light ) { 21157 21158 if ( lights[ light.id ] !== undefined ) { 21159 21160 return lights[ light.id ]; 21161 21162 } 21163 21164 var uniforms; 21165 21166 switch ( light.type ) { 21167 21168 case 'DirectionalLight': 21169 uniforms = { 21170 direction: new Vector3(), 21171 color: new Color(), 21172 21173 shadow: false, 21174 shadowBias: 0, 21175 shadowRadius: 1, 21176 shadowMapSize: new Vector2() 21177 }; 21178 break; 21179 21180 case 'SpotLight': 21181 uniforms = { 21182 position: new Vector3(), 21183 direction: new Vector3(), 21184 color: new Color(), 21185 distance: 0, 21186 coneCos: 0, 21187 penumbraCos: 0, 21188 decay: 0, 21189 21190 shadow: false, 21191 shadowBias: 0, 21192 shadowRadius: 1, 21193 shadowMapSize: new Vector2() 21194 }; 21195 break; 21196 21197 case 'PointLight': 21198 uniforms = { 21199 position: new Vector3(), 21200 color: new Color(), 21201 distance: 0, 21202 decay: 0, 21203 21204 shadow: false, 21205 shadowBias: 0, 21206 shadowRadius: 1, 21207 shadowMapSize: new Vector2(), 21208 shadowCameraNear: 1, 21209 shadowCameraFar: 1000 21210 }; 21211 break; 21212 21213 case 'HemisphereLight': 21214 uniforms = { 21215 direction: new Vector3(), 21216 skyColor: new Color(), 21217 groundColor: new Color() 21218 }; 21219 break; 21220 21221 case 'RectAreaLight': 21222 uniforms = { 21223 color: new Color(), 21224 position: new Vector3(), 21225 halfWidth: new Vector3(), 21226 halfHeight: new Vector3() 21227 // TODO (abelnation): set RectAreaLight shadow uniforms 21228 }; 21229 break; 21230 21231 } 21232 21233 lights[ light.id ] = uniforms; 21234 21235 return uniforms; 21236 21237 } 21238 21239 }; 21240 21241 } 21242 21243 var count = 0; 21244 21245 function WebGLLights() { 21246 21247 var cache = new UniformsCache(); 21248 21249 var state = { 21250 21251 id: count ++, 21252 21253 hash: '', 21254 21255 ambient: [ 0, 0, 0 ], 21256 directional: [], 21257 directionalShadowMap: [], 21258 directionalShadowMatrix: [], 21259 spot: [], 21260 spotShadowMap: [], 21261 spotShadowMatrix: [], 21262 rectArea: [], 21263 point: [], 21264 pointShadowMap: [], 21265 pointShadowMatrix: [], 21266 hemi: [] 21267 21268 }; 21269 21270 var vector3 = new Vector3(); 21271 var matrix4 = new Matrix4(); 21272 var matrix42 = new Matrix4(); 21273 21274 function setup( lights, shadows, camera ) { 21275 21276 var r = 0, g = 0, b = 0; 21277 21278 var directionalLength = 0; 21279 var pointLength = 0; 21280 var spotLength = 0; 21281 var rectAreaLength = 0; 21282 var hemiLength = 0; 21283 21284 var viewMatrix = camera.matrixWorldInverse; 21285 21286 for ( var i = 0, l = lights.length; i < l; i ++ ) { 21287 21288 var light = lights[ i ]; 21289 21290 var color = light.color; 21291 var intensity = light.intensity; 21292 var distance = light.distance; 21293 21294 var shadowMap = ( light.shadow && light.shadow.map ) ? light.shadow.map.texture : null; 21295 21296 if ( light.isAmbientLight ) { 21297 21298 r += color.r * intensity; 21299 g += color.g * intensity; 21300 b += color.b * intensity; 21301 21302 } else if ( light.isDirectionalLight ) { 21303 21304 var uniforms = cache.get( light ); 21305 21306 uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); 21307 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21308 vector3.setFromMatrixPosition( light.target.matrixWorld ); 21309 uniforms.direction.sub( vector3 ); 21310 uniforms.direction.transformDirection( viewMatrix ); 21311 21312 uniforms.shadow = light.castShadow; 21313 21314 if ( light.castShadow ) { 21315 21316 var shadow = light.shadow; 21317 21318 uniforms.shadowBias = shadow.bias; 21319 uniforms.shadowRadius = shadow.radius; 21320 uniforms.shadowMapSize = shadow.mapSize; 21321 21322 } 21323 21324 state.directionalShadowMap[ directionalLength ] = shadowMap; 21325 state.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix; 21326 state.directional[ directionalLength ] = uniforms; 21327 21328 directionalLength ++; 21329 21330 } else if ( light.isSpotLight ) { 21331 21332 var uniforms = cache.get( light ); 21333 21334 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21335 uniforms.position.applyMatrix4( viewMatrix ); 21336 21337 uniforms.color.copy( color ).multiplyScalar( intensity ); 21338 uniforms.distance = distance; 21339
21340 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21341 vector3.setFromMatrixPosition( light.target.matrixWorld ); 21342 uniforms.direction.sub( vector3 ); 21343 uniforms.direction.transformDirection( viewMatrix ); 21344 21345 uniforms.coneCos = Math.cos( light.angle ); 21346 uniforms.penumbraCos = Math.cos( light.angle * ( 1 - light.penumbra ) ); 21347 uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; 21348 21349 uniforms.shadow = light.castShadow; 21350 21351 if ( light.castShadow ) { 21352 21353 var shadow = light.shadow; 21354 21355 uniforms.shadowBias = shadow.bias; 21356 uniforms.shadowRadius = shadow.radius; 21357 uniforms.shadowMapSize = shadow.mapSize; 21358 21359 } 21360 21361 state.spotShadowMap[ spotLength ] = shadowMap; 21362 state.spotShadowMatrix[ spotLength ] = light.shadow.matrix; 21363 state.spot[ spotLength ] = uniforms; 21364 21365 spotLength ++; 21366 21367 } else if ( light.isRectAreaLight ) { 21368 21369 var uniforms = cache.get( light ); 21370 21371 // (a) intensity is the total visible light emitted 21372 //uniforms.color.copy( color ).multiplyScalar( intensity / ( light.width * light.height * Math.PI ) ); 21373 21374 // (b) intensity is the brightness of the light 21375 uniforms.color.copy( color ).multiplyScalar( intensity ); 21376 21377 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21378 uniforms.position.applyMatrix4( viewMatrix ); 21379 21380 // extract local rotation of light to derive width/height half vectors 21381 matrix42.identity(); 21382 matrix4.copy( light.matrixWorld ); 21383 matrix4.premultiply( viewMatrix ); 21384 matrix42.extractRotation( matrix4 ); 21385 21386 uniforms.halfWidth.set( light.width * 0.5, 0.0, 0.0 ); 21387 uniforms.halfHeight.set( 0.0, light.height * 0.5, 0.0 ); 21388 21389 uniforms.halfWidth.applyMatrix4( matrix42 ); 21390 uniforms.halfHeight.applyMatrix4( matrix42 ); 21391 21392 // TODO (abelnation): RectAreaLight distance? 21393 // uniforms.distance = distance; 21394 21395 state.rectArea[ rectAreaLength ] = uniforms; 21396 21397 rectAreaLength ++; 21398 21399 } else if ( light.isPointLight ) { 21400 21401 var uniforms = cache.get( light ); 21402 21403 uniforms.position.setFromMatrixPosition( light.matrixWorld ); 21404 uniforms.position.applyMatrix4( viewMatrix ); 21405 21406 uniforms.color.copy( light.color ).multiplyScalar( light.intensity ); 21407 uniforms.distance = light.distance; 21408 uniforms.decay = ( light.distance === 0 ) ? 0.0 : light.decay; 21409 21410 uniforms.shadow = light.castShadow; 21411 21412 if ( light.castShadow ) { 21413 21414 var shadow = light.shadow; 21415 21416 uniforms.shadowBias = shadow.bias; 21417 uniforms.shadowRadius = shadow.radius; 21418 uniforms.shadowMapSize = shadow.mapSize; 21419 uniforms.shadowCameraNear = shadow.camera.near; 21420 uniforms.shadowCameraFar = shadow.camera.far; 21421 21422 } 21423 21424 state.pointShadowMap[ pointLength ] = shadowMap; 21425 state.pointShadowMatrix[ pointLength ] = light.shadow.matrix; 21426 state.point[ pointLength ] = uniforms; 21427 21428 pointLength ++; 21429 21430 } else if ( light.isHemisphereLight ) { 21431 21432 var uniforms = cache.get( light ); 21433 21434 uniforms.direction.setFromMatrixPosition( light.matrixWorld ); 21435 uniforms.direction.transformDirection( viewMatrix ); 21436 uniforms.direction.normalize(); 21437 21438 uniforms.skyColor.copy( light.color ).multiplyScalar( intensity ); 21439 uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity ); 21440 21441 state.hemi[ hemiLength ] = uniforms; 21442 21443 hemiLength ++; 21444 21445 } 21446 21447 } 21448 21449 state.ambient[ 0 ] = r; 21450 state.ambient[ 1 ] = g; 21451 state.ambient[ 2 ] = b; 21452 21453 state.directional.length = directionalLength; 21454 state.spot.length = spotLength; 21455 state.rectArea.length = rectAreaLength; 21456 state.point.length = pointLength; 21457 state.hemi.length = hemiLength; 21458 21459 state.hash = state.id + ',' + directionalLength + ',' + pointLength + ',' + spotLength + ',' + rectAreaLength + ',' + hemiLength + ',' + shadows.length; 21460 21461 } 21462 21463 return { 21464 setup: setup, 21465 state: state 21466 }; 21467 21468 } 21469 21470 /** 21471 * @author Mugen87 / https://github.com/Mugen87 21472 */ 21473 21474 function WebGLRenderState() { 21475 21476 var lights = new WebGLLights(); 21477 21478 var lightsArray = []; 21479 var shadowsArray = []; 21480 var spritesArray = []; 21481
vendor: 4,489 bytes, lines 21482-21712
21482 function init() { 21483 21484 lightsArray.length = 0; 21485 shadowsArray.length = 0; 21486 spritesArray.length = 0; 21487 21488 } 21489 21490 function pushLight( light ) { 21491 21492 lightsArray.push( light ); 21493 21494 } 21495 21496 function pushShadow( shadowLight ) { 21497 21498 shadowsArray.push( shadowLight ); 21499 21500 } 21501 21502 function pushSprite( shadowLight ) { 21503 21504 spritesArray.push( shadowLight ); 21505 21506 } 21507 21508 function setupLights( camera ) { 21509 21510 lights.setup( lightsArray, shadowsArray, camera ); 21511 21512 } 21513 21514 var state = { 21515 lightsArray: lightsArray, 21516 shadowsArray: shadowsArray, 21517 spritesArray: spritesArray, 21518 21519 lights: lights 21520 }; 21521 21522 return { 21523 init: init, 21524 state: state, 21525 setupLights: setupLights, 21526 21527 pushLight: pushLight, 21528 pushShadow: pushShadow, 21529 pushSprite: pushSprite 21530 }; 21531 21532 } 21533 21534 function WebGLRenderStates() { 21535 21536 var renderStates = {}; 21537 21538 function get( scene, camera ) { 21539 21540 var hash = scene.id + ',' + camera.id; 21541 21542 var renderState = renderStates[ hash ]; 21543 21544 if ( renderState === undefined ) { 21545 21546 renderState = new WebGLRenderState(); 21547 renderStates[ hash ] = renderState; 21548 21549 } 21550 21551 return renderState; 21552 21553 } 21554 21555 function dispose() { 21556 21557 renderStates = {}; 21558 21559 } 21560 21561 return { 21562 get: get, 21563 dispose: dispose 21564 }; 21565 21566 } 21567 21568 /** 21569 * @author mrdoob / http://mrdoob.com/ 21570 * @author alteredq / http://alteredqualia.com/ 21571 * @author bhouston / https://clara.io 21572 * @author WestLangley / http://github.com/WestLangley 21573 * 21574 * parameters = { 21575 * 21576 * opacity: <float>, 21577 * 21578 * map: new THREE.Texture( <Image> ), 21579 * 21580 * alphaMap: new THREE.Texture( <Image> ), 21581 * 21582 * displacementMap: new THREE.Texture( <Image> ), 21583 * displacementScale: <float>, 21584 * displacementBias: <float>, 21585 * 21586 * wireframe: <boolean>, 21587 * wireframeLinewidth: <float> 21588 * } 21589 */ 21590 21591 function MeshDepthMaterial( parameters ) { 21592 21593 Material.call( this ); 21594 21595 this.type = 'MeshDepthMaterial'; 21596 21597 this.depthPacking = BasicDepthPacking; 21598 21599 this.skinning = false; 21600 this.morphTargets = false; 21601 21602 this.map = null; 21603 21604 this.alphaMap = null; 21605 21606 this.displacementMap = null; 21607 this.displacementScale = 1; 21608 this.displacementBias = 0; 21609 21610 this.wireframe = false; 21611 this.wireframeLinewidth = 1; 21612 21613 this.fog = false; 21614 this.lights = false; 21615 21616 this.setValues( parameters ); 21617 21618 } 21619 21620 MeshDepthMaterial.prototype = Object.create( Material.prototype ); 21621 MeshDepthMaterial.prototype.constructor = MeshDepthMaterial; 21622 21623 MeshDepthMaterial.prototype.isMeshDepthMaterial = true; 21624 21625 MeshDepthMaterial.prototype.copy = function ( source ) { 21626 21627 Material.prototype.copy.call( this, source ); 21628 21629 this.depthPacking = source.depthPacking; 21630 21631 this.skinning = source.skinning; 21632 this.morphTargets = source.morphTargets; 21633 21634 this.map = source.map; 21635 21636 this.alphaMap = source.alphaMap; 21637 21638 this.displacementMap = source.displacementMap; 21639 this.displacementScale = source.displacementScale; 21640 this.displacementBias = source.displacementBias; 21641 21642 this.wireframe = source.wireframe; 21643 this.wireframeLinewidth = source.wireframeLinewidth; 21644 21645 return this; 21646 21647 }; 21648 21649 /** 21650 * @author WestLangley / http://github.com/WestLangley 21651 * 21652 * parameters = { 21653 * 21654 * referencePosition: <float>, 21655 * nearDistance: <float>, 21656 * farDistance: <float>, 21657 * 21658 * skinning: <bool>, 21659 * morphTargets: <bool>, 21660 * 21661 * map: new THREE.Texture( <Image> ), 21662 * 21663 * alphaMap: new THREE.Texture( <Image> ), 21664 * 21665 * displacementMap: new THREE.Texture( <Image> ), 21666 * displacementScale: <float>, 21667 * displacementBias: <float> 21668 * 21669 * } 21670 */ 21671 21672 function MeshDistanceMaterial( parameters ) { 21673 21674 Material.call( this ); 21675 21676 this.type = 'MeshDistanceMaterial'; 21677 21678 this.referencePosition = new Vector3(); 21679 this.nearDistance = 1; 21680 this.farDistance = 1000; 21681 21682 this.skinning = false; 21683 this.morphTargets = false; 21684 21685 this.map = null; 21686 21687 this.alphaMap = null; 21688 21689 this.displacementMap = null; 21690 this.displacementScale = 1; 21691 this.displacementBias = 0; 21692 21693 this.fog = false; 21694 this.lights = false; 21695 21696 this.setValues( parameters ); 21697 21698 } 21699 21700 MeshDistanceMaterial.prototype = Object.create( Material.prototype ); 21701 MeshDistanceMaterial.prototype.constructor = MeshDistanceMaterial; 21702 21703 MeshDistanceMaterial.prototype.isMeshDistanceMaterial = true; 21704 21705 MeshDistanceMaterial.prototype.copy = function ( source ) { 21706 21707 Material.prototype.copy.call( this, source ); 21708 21709 this.referencePosition.copy( source.referencePosition ); 21710 this.nearDistance = source.nearDistance; 21711 this.farDistance = source.farDistance; 21712
21713 this.skinning = source.skinning; 21714 this.morphTargets = source.morphTargets; 21715 21716 this.map = source.map; 21717 21718 this.alphaMap = source.alphaMap; 21719 21720 this.displacementMap = source.displacementMap; 21721 this.displacementScale = source.displacementScale; 21722 this.displacementBias = source.displacementBias; 21723 21724 return this; 21725 21726 }; 21727 21728 /** 21729 * @author alteredq / http://alteredqualia.com/ 21730 * @author mrdoob / http://mrdoob.com/ 21731 */ 21732 21733 function WebGLShadowMap( _renderer, _objects, maxTextureSize ) { 21734 21735 var _frustum = new Frustum(), 21736 _projScreenMatrix = new Matrix4(), 21737 21738 _shadowMapSize = new Vector2(), 21739 _maxShadowMapSize = new Vector2( maxTextureSize, maxTextureSize ), 21740 21741 _lookTarget = new Vector3(), 21742 _lightPositionWorld = new Vector3(), 21743 21744 _MorphingFlag = 1, 21745 _SkinningFlag = 2, 21746 21747 _NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1, 21748 21749 _depthMaterials = new Array( _NumberOfMaterialVariants ), 21750 _distanceMaterials = new Array( _NumberOfMaterialVariants ), 21751 21752 _materialCache = {}; 21753 21754 var shadowSide = { 0: BackSide, 1: FrontSide, 2: DoubleSide }; 21755 21756 var cubeDirections = [ 21757 new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), 21758 new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) 21759 ]; 21760 21761 var cubeUps = [ 21762 new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), 21763 new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) 21764 ]; 21765 21766 var cube2DViewPorts = [ 21767 new Vector4(), new Vector4(), new Vector4(), 21768 new Vector4(), new Vector4(), new Vector4() 21769 ]; 21770 21771 // init 21772 21773 for ( var i = 0; i !== _NumberOfMaterialVariants; ++ i ) { 21774 21775 var useMorphing = ( i & _MorphingFlag ) !== 0; 21776 var useSkinning = ( i & _SkinningFlag ) !== 0; 21777 21778 var depthMaterial = new MeshDepthMaterial( { 21779 21780 depthPacking: RGBADepthPacking, 21781 21782 morphTargets: useMorphing, 21783 skinning: useSkinning 21784 21785 } ); 21786 21787 _depthMaterials[ i ] = depthMaterial; 21788 21789 // 21790 21791 var distanceMaterial = new MeshDistanceMaterial( { 21792 21793 morphTargets: useMorphing, 21794 skinning: useSkinning 21795 21796 } ); 21797 21798 _distanceMaterials[ i ] = distanceMaterial; 21799 21800 } 21801 21802 // 21803 21804 var scope = this; 21805 21806 this.enabled = false; 21807 21808 this.autoUpdate = true; 21809 this.needsUpdate = false; 21810 21811 this.type = PCFShadowMap; 21812 21813 this.render = function ( lights, scene, camera ) { 21814 21815 if ( scope.enabled === false ) return; 21816 if ( scope.autoUpdate === false && scope.needsUpdate === false ) return; 21817 21818 if ( lights.length === 0 ) return; 21819 21820 // TODO Clean up (needed in case of contextlost) 21821 var _gl = _renderer.context; 21822 var _state = _renderer.state; 21823 21824 // Set GL state for depth map. 21825 _state.disable( _gl.BLEND ); 21826 _state.buffers.color.setClear( 1, 1, 1, 1 ); 21827 _state.buffers.depth.setTest( true ); 21828 _state.setScissorTest( false ); 21829 21830 // render depth map 21831 21832 var faceCount; 21833 21834 for ( var i = 0, il = lights.length; i < il; i ++ ) { 21835 21836 var light = lights[ i ]; 21837 var shadow = light.shadow; 21838 var isPointLight = light && light.isPointLight; 21839 21840 if ( shadow === undefined ) { 21841 21842 console.warn( 'THREE.WebGLShadowMap:', light, 'has no shadow.' ); 21843 continue; 21844 21845 } 21846 21847 var shadowCamera = shadow.camera; 21848 21849 _shadowMapSize.copy( shadow.mapSize ); 21850 _shadowMapSize.min( _maxShadowMapSize ); 21851 21852 if ( isPointLight ) { 21853 21854 var vpWidth = _shadowMapSize.x; 21855 var vpHeight = _shadowMapSize.y; 21856 21857 // These viewports map a cube-map onto a 2D texture with the 21858 // following orientation: 21859 // 21860 // xzXZ 21861 // y Y 21862 // 21863 // X - Positive x direction 21864 // x - Negative x direction 21865 // Y - Positive y direction 21866 // y - Negative y direction 21867 // Z - Positive z direction 21868 // z - Negative z direction 21869 21870 // positive X 21871 cube2DViewPorts[ 0 ].set( vpWidth * 2, vpHeight, vpWidth, vpHeight ); 21872 // negative X 21873 cube2DViewPorts[ 1 ].set( 0, vpHeight, vpWidth, vpHeight ); 21874 // positive Z 21875 cube2DViewPorts[ 2 ].set( vpWidth * 3, vpHeight, vpWidth, vpHeight ); 21876 // negative Z 21877 cube2DViewPorts[ 3 ].set( vpWidth, vpHeight, vpWidth, vpHeight ); 21878 // positive Y 21879 cube2DViewPorts[ 4 ].set( vpWidth * 3, 0, vpWidth, vpHeight ); 21880 // negative Y 21881 cube2DViewPorts[ 5 ].set( vpWidth, 0, vpWidth, vpHeight ); 21882 21883 _shadowMapSize.x *= 4.0; 21884 _shadowMapSize.y *= 2.0; 21885 21886 } 21887 21888 if ( shadow.map === null ) { 21889 21890 var pars = { minFilter: NearestFilter, magFilter: NearestFilter, format: RGBAFormat }; 21891 21892 shadow.map = new WebGLRenderTarget( _shadowMapSize.x, _shadowMapSize.y, pars ); 21893 shadow.map.texture.name = light.name + ".shadowMap"; 21894 21895 shadowCamera.updateProjectionMatrix(); 21896 21897 } 21898 21899 if ( shadow.isSpotLightShadow ) { 21900 21901 shadow.update( light ); 21902 21903 } 21904 21905 var shadowMap = shadow.map; 21906 var shadowMatrix = shadow.matrix; 21907 21908 _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); 21909 shadowCamera.position.copy( _lightPositionWorld ); 21910 21911 if ( isPointLight ) { 21912 21913 faceCount = 6; 21914 21915 // for point lights we set the shadow matrix to be a translation-only matrix 21916 // equal to inverse of the light's position 21917 21918 shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); 21919 21920 } else { 21921
21922 faceCount = 1; 21923 21924 _lookTarget.setFromMatrixPosition( light.target.matrixWorld ); 21925 shadowCamera.lookAt( _lookTarget ); 21926 shadowCamera.updateMatrixWorld(); 21927 21928 // compute shadow matrix 21929 21930 shadowMatrix.set( 21931 0.5, 0.0, 0.0, 0.5, 21932 0.0, 0.5, 0.0, 0.5, 21933 0.0, 0.0, 0.5, 0.5, 21934 0.0, 0.0, 0.0, 1.0 21935 ); 21936 21937 shadowMatrix.multiply( shadowCamera.projectionMatrix ); 21938 shadowMatrix.multiply( shadowCamera.matrixWorldInverse ); 21939 21940 } 21941 21942 _renderer.setRenderTarget( shadowMap ); 21943 _renderer.clear(); 21944 21945 // render shadow map for each cube face (if omni-directional) or 21946 // run a single pass if not 21947 21948 for ( var face = 0; face < faceCount; face ++ ) { 21949 21950 if ( isPointLight ) { 21951 21952 _lookTarget.copy( shadowCamera.position ); 21953 _lookTarget.add( cubeDirections[ face ] ); 21954 shadowCamera.up.copy( cubeUps[ face ] ); 21955 shadowCamera.lookAt( _lookTarget ); 21956 shadowCamera.updateMatrixWorld(); 21957 21958 var vpDimensions = cube2DViewPorts[ face ]; 21959 _state.viewport( vpDimensions ); 21960 21961 } 21962 21963 // update camera matrices and frustum 21964 21965 _projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); 21966 _frustum.setFromMatrix( _projScreenMatrix ); 21967 21968 // set object matrices & frustum culling 21969 21970 renderObject( scene, camera, shadowCamera, isPointLight ); 21971 21972 } 21973 21974 } 21975 21976 scope.needsUpdate = false; 21977 21978 }; 21979 21980 function getDepthMaterial( object, material, isPointLight, lightPositionWorld, shadowCameraNear, shadowCameraFar ) { 21981 21982 var geometry = object.geometry; 21983 21984 var result = null; 21985 21986 var materialVariants = _depthMaterials; 21987 var customMaterial = object.customDepthMaterial; 21988 21989 if ( isPointLight ) { 21990 21991 materialVariants = _distanceMaterials; 21992 customMaterial = object.customDistanceMaterial; 21993 21994 } 21995 21996 if ( ! customMaterial ) { 21997 21998 var useMorphing = false; 21999 22000 if ( material.morphTargets ) { 22001 22002 if ( geometry && geometry.isBufferGeometry ) { 22003 22004 useMorphing = geometry.morphAttributes && geometry.morphAttributes.position && geometry.morphAttributes.position.length > 0; 22005 22006 } else if ( geometry && geometry.isGeometry ) { 22007 22008 useMorphing = geometry.morphTargets && geometry.morphTargets.length > 0; 22009 22010 } 22011 22012 } 22013 22014 if ( object.isSkinnedMesh && material.skinning === false ) { 22015 22016 console.warn( 'THREE.WebGLShadowMap: THREE.SkinnedMesh with material.skinning set to false:', object ); 22017 22018 } 22019 22020 var useSkinning = object.isSkinnedMesh && material.skinning; 22021 22022 var variantIndex = 0; 22023 22024 if ( useMorphing ) variantIndex |= _MorphingFlag; 22025 if ( useSkinning ) variantIndex |= _SkinningFlag; 22026 22027 result = materialVariants[ variantIndex ]; 22028 22029 } else { 22030 22031 result = customMaterial; 22032 22033 } 22034 22035 if ( _renderer.localClippingEnabled &&
22036 material.clipShadows === true && 22037 material.clippingPlanes.length !== 0 ) { 22038 22039 // in this case we need a unique material instance reflecting the 22040 // appropriate state 22041 22042 var keyA = result.uuid, keyB = material.uuid; 22043 22044 var materialsForVariant = _materialCache[ keyA ]; 22045 22046 if ( materialsForVariant === undefined ) { 22047 22048 materialsForVariant = {}; 22049 _materialCache[ keyA ] = materialsForVariant; 22050 22051 } 22052 22053 var cachedMaterial = materialsForVariant[ keyB ]; 22054 22055 if ( cachedMaterial === undefined ) { 22056 22057 cachedMaterial = result.clone(); 22058 materialsForVariant[ keyB ] = cachedMaterial; 22059 22060 } 22061 22062 result = cachedMaterial; 22063 22064 } 22065 22066 result.visible = material.visible; 22067 result.wireframe = material.wireframe; 22068 22069 result.side = ( material.shadowSide != null ) ? material.shadowSide : shadowSide[ material.side ]; 22070 22071 result.clipShadows = material.clipShadows; 22072 result.clippingPlanes = material.clippingPlanes; 22073 result.clipIntersection = material.clipIntersection; 22074 22075 result.wireframeLinewidth = material.wireframeLinewidth; 22076 result.linewidth = material.linewidth; 22077 22078 if ( isPointLight && result.isMeshDistanceMaterial ) { 22079 22080 result.referencePosition.copy( lightPositionWorld ); 22081 result.nearDistance = shadowCameraNear; 22082 result.farDistance = shadowCameraFar; 22083 22084 } 22085 22086 return result; 22087 22088 } 22089 22090 function renderObject( object, camera, shadowCamera, isPointLight ) { 22091 22092 if ( object.visible === false ) return; 22093 22094 var visible = object.layers.test( camera.layers ); 22095 22096 if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) { 22097 22098 if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) { 22099 22100 object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld ); 22101 22102 var geometry = _objects.update( object ); 22103 var material = object.material; 22104 22105 if ( Array.isArray( material ) ) { 22106 22107 var groups = geometry.groups; 22108 22109 for ( var k = 0, kl = groups.length; k < kl; k ++ ) { 22110 22111 var group = groups[ k ]; 22112 var groupMaterial = material[ group.materialIndex ]; 22113 22114 if ( groupMaterial && groupMaterial.visible ) { 22115 22116 var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); 22117 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group ); 22118 22119 } 22120 22121 } 22122 22123 } else if ( material.visible ) { 22124 22125 var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld, shadowCamera.near, shadowCamera.far ); 22126 _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); 22127 22128 } 22129 22130 } 22131 22132 } 22133 22134 var children = object.children; 22135 22136 for ( var i = 0, l = children.length; i < l; i ++ ) { 22137 22138 renderObject( children[ i ], camera, shadowCamera, isPointLight ); 22139 22140 } 22141 22142 } 22143 22144 } 22145 22146 /** 22147 * @author mrdoob / http://mrdoob.com/ 22148 */ 22149 22150 function CanvasTexture( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 22151 22152 Texture.call( this, canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 22153 22154 this.needsUpdate = true; 22155 22156 } 22157 22158 CanvasTexture.prototype = Object.create( Texture.prototype ); 22159 CanvasTexture.prototype.constructor = CanvasTexture; 22160 CanvasTexture.prototype.isCanvasTexture = true; 22161 22162 /** 22163 * @author mikael emtinger / http://gomo.se/ 22164 * @author alteredq / http://alteredqualia.com/ 22165 */ 22166 22167 function WebGLSpriteRenderer( renderer, gl, state, textures, capabilities ) { 22168 22169 var vertexBuffer, elementBuffer; 22170 var program, attributes, uniforms; 22171 22172 var texture; 22173 22174 // decompose matrixWorld 22175 22176 var spritePosition = new Vector3(); 22177 var spriteRotation = new Quaternion(); 22178 var spriteScale = new Vector3(); 22179 22180 function init() { 22181 22182 var vertices = new Float32Array( [ 22183 - 0.5, - 0.5, 0, 0, 22184 0.5, - 0.5, 1, 0, 22185 0.5, 0.5, 1, 1, 22186 - 0.5, 0.5, 0, 1 22187 ] ); 22188 22189 var faces = new Uint16Array( [ 22190 0, 1, 2, 22191 0, 2, 3 22192 ] ); 22193 22194 vertexBuffer = gl.createBuffer(); 22195 elementBuffer = gl.createBuffer(); 22196 22197 gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); 22198 gl.bufferData( gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW ); 22199 22200 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); 22201 gl.bufferData( gl.ELEMENT_ARRAY_BUFFER, faces, gl.STATIC_DRAW ); 22202 22203 program = createProgram(); 22204 22205 attributes = { 22206 position: gl.getAttribLocation( program, 'position' ), 22207 uv: gl.getAttribLocation( program, 'uv' ) 22208 }; 22209 22210 uniforms = { 22211 uvOffset: gl.getUniformLocation( program, 'uvOffset' ), 22212 uvScale: gl.getUniformLocation( program, 'uvScale' ), 22213 22214 rotation: gl.getUniformLocation( program, 'rotation' ), 22215 center: gl.getUniformLocation( program, 'center' ), 22216 scale: gl.getUniformLocation( program, 'scale' ), 22217 22218 color: gl.getUniformLocation( program, 'color' ), 22219 map: gl.getUniformLocation( program, 'map' ), 22220 opacity: gl.getUniformLocation( program, 'opacity' ), 22221 22222 modelViewMatrix: gl.getUniformLocation( program, 'modelViewMatrix' ), 22223 projectionMatrix: gl.getUniformLocation( program, 'projectionMatrix' ), 22224 22225 fogType: gl.getUniformLocation( program, 'fogType' ), 22226 fogDensity: gl.getUniformLocation( program, 'fogDensity' ), 22227 fogNear: gl.getUniformLocation( program, 'fogNear' ), 22228 fogFar: gl.getUniformLocation( program, 'fogFar' ), 22229 fogColor: gl.getUniformLocation( program, 'fogColor' ), 22230 fogDepth: gl.getUniformLocation( program, 'fogDepth' ), 22231 22232 alphaTest: gl.getUniformLocation( program, 'alphaTest' ) 22233 }; 22234 22235 var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); 22236 canvas.width = 8; 22237 canvas.height = 8; 22238 22239 var context = canvas.getContext( '2d' ); 22240 context.fillStyle = 'white'; 22241 context.fillRect( 0, 0, 8, 8 ); 22242 22243 texture = new CanvasTexture( canvas ); 22244 22245 } 22246 22247 this.render = function ( sprites, scene, camera ) { 22248 22249 if ( sprites.length === 0 ) return; 22250 22251 // setup gl 22252 22253 if ( program === undefined ) { 22254 22255 init(); 22256 22257 } 22258 22259 state.useProgram( program ); 22260 22261 state.initAttributes(); 22262 state.enableAttribute( attributes.position ); 22263 state.enableAttribute( attributes.uv ); 22264 state.disableUnusedAttributes(); 22265 22266 state.disable( gl.CULL_FACE ); 22267 state.enable( gl.BLEND ); 22268 22269 gl.bindBuffer( gl.ARRAY_BUFFER, vertexBuffer ); 22270 gl.vertexAttribPointer( attributes.position, 2, gl.FLOAT, false, 2 * 8, 0 ); 22271 gl.vertexAttribPointer( attributes.uv, 2, gl.FLOAT, false, 2 * 8, 8 ); 22272 22273 gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer ); 22274 22275 gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera.projectionMatrix.elements ); 22276 22277 state.activeTexture( gl.TEXTURE0 ); 22278 gl.uniform1i( uniforms.map, 0 ); 22279 22280 var oldFogType = 0; 22281 var sceneFogType = 0; 22282 var fog = scene.fog; 22283 22284 if ( fog ) { 22285 22286 gl.uniform3f( uniforms.fogColor, fog.color.r, fog.color.g, fog.color.b ); 22287 22288 if ( fog.isFog ) { 22289 22290 gl.uniform1f( uniforms.fogNear, fog.near ); 22291 gl.uniform1f( uniforms.fogFar, fog.far ); 22292 22293 gl.uniform1i( uniforms.fogType, 1 ); 22294 oldFogType = 1; 22295 sceneFogType = 1; 22296 22297 } else if ( fog.isFogExp2 ) { 22298 22299 gl.uniform1f( uniforms.fogDensity, fog.density ); 22300 22301 gl.uniform1i( uniforms.fogType, 2 ); 22302 oldFogType = 2; 22303 sceneFogType = 2; 22304 22305 } 22306 22307 } else { 22308
22309 gl.uniform1i( uniforms.fogType, 0 ); 22310 oldFogType = 0; 22311 sceneFogType = 0; 22312 22313 } 22314 22315 22316 // update positions and sort 22317 22318 for ( var i = 0, l = sprites.length; i < l; i ++ ) { 22319 22320 var sprite = sprites[ i ]; 22321 22322 sprite.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, sprite.matrixWorld ); 22323 sprite.z = - sprite.modelViewMatrix.elements[ 14 ]; 22324 22325 } 22326 22327 sprites.sort( painterSortStable ); 22328 22329 // render all sprites 22330 22331 var scale = []; 22332 var center = []; 22333 22334 for ( var i = 0, l = sprites.length; i < l; i ++ ) { 22335 22336 var sprite = sprites[ i ]; 22337 var material = sprite.material; 22338 22339 if ( material.visible === false ) continue; 22340 22341 sprite.onBeforeRender( renderer, scene, camera, undefined, material, undefined ); 22342 22343 gl.uniform1f( uniforms.alphaTest, material.alphaTest ); 22344 gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite.modelViewMatrix.elements ); 22345 22346 sprite.matrixWorld.decompose( spritePosition, spriteRotation, spriteScale ); 22347 22348 scale[ 0 ] = spriteScale.x; 22349 scale[ 1 ] = spriteScale.y; 22350 22351 center[ 0 ] = sprite.center.x - 0.5; 22352 center[ 1 ] = sprite.center.y - 0.5; 22353 22354 var fogType = 0; 22355 22356 if ( scene.fog && material.fog ) { 22357 22358 fogType = sceneFogType; 22359 22360 } 22361 22362 if ( oldFogType !== fogType ) { 22363 22364 gl.uniform1i( uniforms.fogType, fogType ); 22365 oldFogType = fogType; 22366 22367 } 22368 22369 if ( material.map !== null ) { 22370 22371 gl.uniform2f( uniforms.uvOffset, material.map.offset.x, material.map.offset.y ); 22372 gl.uniform2f( uniforms.uvScale, material.map.repeat.x, material.map.repeat.y ); 22373 22374 } else { 22375 22376 gl.uniform2f( uniforms.uvOffset, 0, 0 ); 22377 gl.uniform2f( uniforms.uvScale, 1, 1 ); 22378 22379 } 22380 22381 gl.uniform1f( uniforms.opacity, material.opacity ); 22382 gl.uniform3f( uniforms.color, material.color.r, material.color.g, material.color.b ); 22383 22384 gl.uniform1f( uniforms.rotation, material.rotation ); 22385 gl.uniform2fv( uniforms.center, center ); 22386 gl.uniform2fv( uniforms.scale, scale ); 22387 22388 state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ); 22389 state.buffers.depth.setTest( material.depthTest ); 22390 state.buffers.depth.setMask( material.depthWrite ); 22391 state.buffers.color.setMask( material.colorWrite ); 22392 22393 textures.setTexture2D( material.map || texture, 0 ); 22394 22395 gl.drawElements( gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0 ); 22396 22397 sprite.onAfterRender( renderer, scene, camera, undefined, material, undefined ); 22398 22399 } 22400 22401 // restore gl 22402 22403 state.enable( gl.CULL_FACE ); 22404 22405 state.reset(); 22406 22407 }; 22408 22409 function createProgram() { 22410 22411 var program = gl.createProgram(); 22412 22413 var vertexShader = gl.createShader( gl.VERTEX_SHADER ); 22414 var fragmentShader = gl.createShader( gl.FRAGMENT_SHADER ); 22415 22416 gl.shaderSource( vertexShader, [ 22417 22418 'precision ' + capabilities.precision + ' float;', 22419 22420 '#define SHADER_NAME ' + 'SpriteMaterial', 22421 22422 'uniform mat4 modelViewMatrix;', 22423 'uniform mat4 projectionMatrix;', 22424 'uniform float rotation;', 22425 'uniform vec2 center;', 22426 'uniform vec2 scale;', 22427 'uniform vec2 uvOffset;', 22428 'uniform vec2 uvScale;', 22429 22430 'attribute vec2 position;', 22431 'attribute vec2 uv;', 22432 22433 'varying vec2 vUV;', 22434 'varying float fogDepth;', 22435 22436 'void main() {', 22437 22438 ' vUV = uvOffset + uv * uvScale;', 22439 22440 ' vec2 alignedPosition = ( position - center ) * scale;', 22441 22442 ' vec2 rotatedPosition;', 22443 ' rotatedPosition.x = cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y;', 22444 ' rotatedPosition.y = sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y;', 22445 22446 ' vec4 mvPosition;', 22447 22448 ' mvPosition = modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );', 22449 ' mvPosition.xy += rotatedPosition;', 22450 22451 ' gl_Position = projectionMatrix * mvPosition;', 22452 22453 ' fogDepth = - mvPosition.z;', 22454 22455 '}' 22456 22457 ].join( '\n' ) ); 22458 22459 gl.shaderSource( fragmentShader, [ 22460 22461 'precision ' + capabilities.precision + ' float;', 22462 22463 '#define SHADER_NAME ' + 'SpriteMaterial', 22464 22465 'uniform vec3 color;', 22466 'uniform sampler2D map;', 22467 'uniform float opacity;', 22468 22469 'uniform int fogType;', 22470 'uniform vec3 fogColor;', 22471 'uniform float fogDensity;', 22472 'uniform float fogNear;', 22473 'uniform float fogFar;', 22474 'uniform float alphaTest;', 22475 22476 'varying vec2 vUV;', 22477 'varying float fogDepth;', 22478 22479 'void main() {', 22480 22481 ' vec4 texture = texture2D( map, vUV );', 22482 22483 ' gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );', 22484 22485 ' if ( gl_FragColor.a < alphaTest ) discard;', 22486 22487 ' if ( fogType > 0 ) {', 22488 22489 ' float fogFactor = 0.0;', 22490 22491 ' if ( fogType == 1 ) {', 22492 22493 ' fogFactor = smoothstep( fogNear, fogFar, fogDepth );', 22494 22495 ' } else {', 22496 22497 ' const float LOG2 = 1.442695;', 22498 ' fogFactor = exp2( - fogDensity * fogDensity * fogDepth * fogDepth * LOG2 );', 22499 ' fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );', 22500 22501 ' }', 22502 22503 ' gl_FragColor.rgb = mix( gl_FragColor.rgb, fogColor, fogFactor );', 22504 22505 ' }', 22506 22507 '}' 22508 22509 ].join( '\n' ) ); 22510 22511 gl.compileShader( vertexShader ); 22512 gl.compileShader( fragmentShader ); 22513 22514 gl.attachShader( program, vertexShader ); 22515 gl.attachShader( program, fragmentShader ); 22516 22517 gl.linkProgram( program ); 22518 22519 return program; 22520
vendor: 9,601 bytes, lines 22521-23016
22521 } 22522 22523 function painterSortStable( a, b ) { 22524 22525 if ( a.renderOrder !== b.renderOrder ) { 22526 22527 return a.renderOrder - b.renderOrder; 22528 22529 } else if ( a.z !== b.z ) { 22530 22531 return b.z - a.z; 22532 22533 } else { 22534 22535 return b.id - a.id; 22536 22537 } 22538 22539 } 22540 22541 } 22542 22543 /** 22544 * @author mrdoob / http://mrdoob.com/ 22545 */ 22546 22547 function WebGLState( gl, extensions, utils ) { 22548 22549 function ColorBuffer() { 22550 22551 var locked = false; 22552 22553 var color = new Vector4(); 22554 var currentColorMask = null; 22555 var currentColorClear = new Vector4( 0, 0, 0, 0 ); 22556 22557 return { 22558 22559 setMask: function ( colorMask ) { 22560 22561 if ( currentColorMask !== colorMask && ! locked ) { 22562 22563 gl.colorMask( colorMask, colorMask, colorMask, colorMask ); 22564 currentColorMask = colorMask; 22565 22566 } 22567 22568 }, 22569 22570 setLocked: function ( lock ) { 22571 22572 locked = lock; 22573 22574 }, 22575 22576 setClear: function ( r, g, b, a, premultipliedAlpha ) { 22577 22578 if ( premultipliedAlpha === true ) { 22579 22580 r *= a; g *= a; b *= a; 22581 22582 } 22583 22584 color.set( r, g, b, a ); 22585 22586 if ( currentColorClear.equals( color ) === false ) { 22587 22588 gl.clearColor( r, g, b, a ); 22589 currentColorClear.copy( color ); 22590 22591 } 22592 22593 }, 22594 22595 reset: function () { 22596 22597 locked = false; 22598 22599 currentColorMask = null; 22600 currentColorClear.set( - 1, 0, 0, 0 ); // set to invalid state 22601 22602 } 22603 22604 }; 22605 22606 } 22607 22608 function DepthBuffer() { 22609 22610 var locked = false; 22611 22612 var currentDepthMask = null; 22613 var currentDepthFunc = null; 22614 var currentDepthClear = null; 22615 22616 return { 22617 22618 setTest: function ( depthTest ) { 22619 22620 if ( depthTest ) { 22621 22622 enable( gl.DEPTH_TEST ); 22623 22624 } else { 22625 22626 disable( gl.DEPTH_TEST ); 22627 22628 } 22629 22630 }, 22631 22632 setMask: function ( depthMask ) { 22633 22634 if ( currentDepthMask !== depthMask && ! locked ) { 22635 22636 gl.depthMask( depthMask ); 22637 currentDepthMask = depthMask; 22638 22639 } 22640 22641 }, 22642 22643 setFunc: function ( depthFunc ) { 22644 22645 if ( currentDepthFunc !== depthFunc ) { 22646 22647 if ( depthFunc ) { 22648 22649 switch ( depthFunc ) { 22650 22651 case NeverDepth: 22652 22653 gl.depthFunc( gl.NEVER ); 22654 break; 22655 22656 case AlwaysDepth: 22657 22658 gl.depthFunc( gl.ALWAYS ); 22659 break; 22660 22661 case LessDepth: 22662 22663 gl.depthFunc( gl.LESS ); 22664 break; 22665 22666 case LessEqualDepth: 22667 22668 gl.depthFunc( gl.LEQUAL ); 22669 break; 22670 22671 case EqualDepth: 22672 22673 gl.depthFunc( gl.EQUAL ); 22674 break; 22675 22676 case GreaterEqualDepth: 22677 22678 gl.depthFunc( gl.GEQUAL ); 22679 break; 22680 22681 case GreaterDepth: 22682 22683 gl.depthFunc( gl.GREATER ); 22684 break; 22685 22686 case NotEqualDepth: 22687 22688 gl.depthFunc( gl.NOTEQUAL ); 22689 break; 22690 22691 default: 22692 22693 gl.depthFunc( gl.LEQUAL ); 22694 22695 } 22696 22697 } else { 22698 22699 gl.depthFunc( gl.LEQUAL ); 22700 22701 } 22702 22703 currentDepthFunc = depthFunc; 22704 22705 } 22706 22707 }, 22708 22709 setLocked: function ( lock ) { 22710 22711 locked = lock; 22712 22713 }, 22714 22715 setClear: function ( depth ) { 22716 22717 if ( currentDepthClear !== depth ) { 22718 22719 gl.clearDepth( depth ); 22720 currentDepthClear = depth; 22721 22722 } 22723 22724 }, 22725 22726 reset: function () { 22727 22728 locked = false; 22729 22730 currentDepthMask = null; 22731 currentDepthFunc = null; 22732 currentDepthClear = null; 22733 22734 } 22735 22736 }; 22737 22738 } 22739 22740 function StencilBuffer() { 22741 22742 var locked = false; 22743 22744 var currentStencilMask = null; 22745 var currentStencilFunc = null; 22746 var currentStencilRef = null; 22747 var currentStencilFuncMask = null; 22748 var currentStencilFail = null; 22749 var currentStencilZFail = null; 22750 var currentStencilZPass = null; 22751 var currentStencilClear = null; 22752 22753 return { 22754 22755 setTest: function ( stencilTest ) { 22756 22757 if ( stencilTest ) { 22758 22759 enable( gl.STENCIL_TEST ); 22760 22761 } else { 22762 22763 disable( gl.STENCIL_TEST ); 22764 22765 } 22766 22767 }, 22768 22769 setMask: function ( stencilMask ) { 22770 22771 if ( currentStencilMask !== stencilMask && ! locked ) { 22772 22773 gl.stencilMask( stencilMask ); 22774 currentStencilMask = stencilMask; 22775 22776 } 22777 22778 }, 22779 22780 setFunc: function ( stencilFunc, stencilRef, stencilMask ) { 22781 22782 if ( currentStencilFunc !== stencilFunc || 22783 currentStencilRef !== stencilRef || 22784 currentStencilFuncMask !== stencilMask ) { 22785 22786 gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); 22787 22788 currentStencilFunc = stencilFunc; 22789 currentStencilRef = stencilRef; 22790 currentStencilFuncMask = stencilMask; 22791 22792 } 22793 22794 }, 22795 22796 setOp: function ( stencilFail, stencilZFail, stencilZPass ) { 22797 22798 if ( currentStencilFail !== stencilFail || 22799 currentStencilZFail !== stencilZFail || 22800 currentStencilZPass !== stencilZPass ) { 22801 22802 gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); 22803 22804 currentStencilFail = stencilFail; 22805 currentStencilZFail = stencilZFail; 22806 currentStencilZPass = stencilZPass; 22807 22808 } 22809 22810 }, 22811 22812 setLocked: function ( lock ) { 22813 22814 locked = lock; 22815 22816 }, 22817 22818 setClear: function ( stencil ) { 22819 22820 if ( currentStencilClear !== stencil ) { 22821 22822 gl.clearStencil( stencil ); 22823 currentStencilClear = stencil; 22824 22825 } 22826 22827 }, 22828 22829 reset: function () { 22830 22831 locked = false; 22832 22833 currentStencilMask = null; 22834 currentStencilFunc = null; 22835 currentStencilRef = null; 22836 currentStencilFuncMask = null; 22837 currentStencilFail = null; 22838 currentStencilZFail = null; 22839 currentStencilZPass = null; 22840 currentStencilClear = null; 22841 22842 } 22843 22844 }; 22845 22846 } 22847 22848 // 22849 22850 var colorBuffer = new ColorBuffer(); 22851 var depthBuffer = new DepthBuffer(); 22852 var stencilBuffer = new StencilBuffer(); 22853 22854 var maxVertexAttributes = gl.getParameter( gl.MAX_VERTEX_ATTRIBS ); 22855 var newAttributes = new Uint8Array( maxVertexAttributes ); 22856 var enabledAttributes = new Uint8Array( maxVertexAttributes ); 22857 var attributeDivisors = new Uint8Array( maxVertexAttributes ); 22858 22859 var capabilities = {}; 22860 22861 var compressedTextureFormats = null; 22862 22863 var currentProgram = null; 22864 22865 var currentBlending = null; 22866 var currentBlendEquation = null; 22867 var currentBlendSrc = null; 22868 var currentBlendDst = null; 22869 var currentBlendEquationAlpha = null; 22870 var currentBlendSrcAlpha = null; 22871 var currentBlendDstAlpha = null; 22872 var currentPremultipledAlpha = false; 22873 22874 var currentFlipSided = null; 22875 var currentCullFace = null; 22876 22877 var currentLineWidth = null; 22878 22879 var currentPolygonOffsetFactor = null; 22880 var currentPolygonOffsetUnits = null; 22881 22882 var maxTextures = gl.getParameter( gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS ); 22883 22884 var lineWidthAvailable = false; 22885 var version = 0; 22886 var glVersion = gl.getParameter( gl.VERSION ); 22887 22888 if ( glVersion.indexOf( 'WebGL' ) !== - 1 ) { 22889 22890 version = parseFloat( /^WebGL\ ([0-9])/.exec( glVersion )[ 1 ] ); 22891 lineWidthAvailable = ( version >= 1.0 ); 22892 22893 } else if ( glVersion.indexOf( 'OpenGL ES' ) !== - 1 ) { 22894 22895 version = parseFloat( /^OpenGL\ ES\ ([0-9])/.exec( glVersion )[ 1 ] ); 22896 lineWidthAvailable = ( version >= 2.0 ); 22897 22898 } 22899 22900 var currentTextureSlot = null; 22901 var currentBoundTextures = {}; 22902 22903 var currentScissor = new Vector4(); 22904 var currentViewport = new Vector4(); 22905 22906 function createTexture( type, target, count ) { 22907 22908 var data = new Uint8Array( 4 ); // 4 is required to match default unpack alignment of 4. 22909 var texture = gl.createTexture(); 22910 22911 gl.bindTexture( type, texture ); 22912 gl.texParameteri( type, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); 22913 gl.texParameteri( type, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); 22914 22915 for ( var i = 0; i < count; i ++ ) { 22916 22917 gl.texImage2D( target + i, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); 22918 22919 } 22920 22921 return texture; 22922 22923 } 22924 22925 var emptyTextures = {}; 22926 emptyTextures[ gl.TEXTURE_2D ] = createTexture( gl.TEXTURE_2D, gl.TEXTURE_2D, 1 ); 22927 emptyTextures[ gl.TEXTURE_CUBE_MAP ] = createTexture( gl.TEXTURE_CUBE_MAP, gl.TEXTURE_CUBE_MAP_POSITIVE_X, 6 ); 22928 22929 // init 22930 22931 colorBuffer.setClear( 0, 0, 0, 1 ); 22932 depthBuffer.setClear( 1 ); 22933 stencilBuffer.setClear( 0 ); 22934 22935 enable( gl.DEPTH_TEST ); 22936 depthBuffer.setFunc( LessEqualDepth ); 22937 22938 setFlipSided( false ); 22939 setCullFace( CullFaceBack ); 22940 enable( gl.CULL_FACE ); 22941 22942 enable( gl.BLEND ); 22943 setBlending( NormalBlending ); 22944 22945 // 22946 22947 function initAttributes() { 22948 22949 for ( var i = 0, l = newAttributes.length; i < l; i ++ ) { 22950 22951 newAttributes[ i ] = 0; 22952 22953 } 22954 22955 } 22956 22957 function enableAttribute( attribute ) { 22958 22959 enableAttributeAndDivisor( attribute, 0 ); 22960 22961 } 22962 22963 function enableAttributeAndDivisor( attribute, meshPerAttribute ) { 22964 22965 newAttributes[ attribute ] = 1; 22966 22967 if ( enabledAttributes[ attribute ] === 0 ) { 22968 22969 gl.enableVertexAttribArray( attribute ); 22970 enabledAttributes[ attribute ] = 1; 22971 22972 } 22973 22974 if ( attributeDivisors[ attribute ] !== meshPerAttribute ) { 22975 22976 var extension = extensions.get( 'ANGLE_instanced_arrays' ); 22977 22978 extension.vertexAttribDivisorANGLE( attribute, meshPerAttribute ); 22979 attributeDivisors[ attribute ] = meshPerAttribute; 22980 22981 } 22982 22983 } 22984 22985 function disableUnusedAttributes() { 22986 22987 for ( var i = 0, l = enabledAttributes.length; i !== l; ++ i ) { 22988 22989 if ( enabledAttributes[ i ] !== newAttributes[ i ] ) { 22990 22991 gl.disableVertexAttribArray( i ); 22992 enabledAttributes[ i ] = 0; 22993 22994 } 22995 22996 } 22997 22998 } 22999 23000 function enable( id ) { 23001 23002 if ( capabilities[ id ] !== true ) { 23003 23004 gl.enable( id ); 23005 capabilities[ id ] = true; 23006 23007 } 23008 23009 } 23010 23011 function disable( id ) { 23012 23013 if ( capabilities[ id ] !== false ) { 23014 23015 gl.disable( id ); 23016 capabilities[ id ] = false;
23017 23018 } 23019 23020 } 23021 23022 function getCompressedTextureFormats() { 23023 23024 if ( compressedTextureFormats === null ) { 23025 23026 compressedTextureFormats = []; 23027 23028 if ( extensions.get( 'WEBGL_compressed_texture_pvrtc' ) || 23029 extensions.get( 'WEBGL_compressed_texture_s3tc' ) || 23030 extensions.get( 'WEBGL_compressed_texture_etc1' ) || 23031 extensions.get( 'WEBGL_compressed_texture_astc' ) ) { 23032 23033 var formats = gl.getParameter( gl.COMPRESSED_TEXTURE_FORMATS ); 23034 23035 for ( var i = 0; i < formats.length; i ++ ) { 23036 23037 compressedTextureFormats.push( formats[ i ] ); 23038 23039 } 23040 23041 } 23042 23043 } 23044 23045 return compressedTextureFormats; 23046 23047 } 23048 23049 function useProgram( program ) { 23050 23051 if ( currentProgram !== program ) { 23052 23053 gl.useProgram( program ); 23054 23055 currentProgram = program; 23056 23057 return true; 23058 23059 } 23060 23061 return false; 23062 23063 } 23064 23065 function setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { 23066 23067 if ( blending !== NoBlending ) { 23068 23069 enable( gl.BLEND ); 23070 23071 } else { 23072 23073 disable( gl.BLEND ); 23074 23075 } 23076 23077 if ( blending !== CustomBlending ) { 23078 23079 if ( blending !== currentBlending || premultipliedAlpha !== currentPremultipledAlpha ) { 23080 23081 switch ( blending ) { 23082 23083 case AdditiveBlending: 23084 23085 if ( premultipliedAlpha ) { 23086 23087 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); 23088 gl.blendFuncSeparate( gl.ONE, gl.ONE, gl.ONE, gl.ONE ); 23089 23090 } else { 23091 23092 gl.blendEquation( gl.FUNC_ADD ); 23093 gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); 23094 23095 } 23096 break; 23097 23098 case SubtractiveBlending: 23099 23100 if ( premultipliedAlpha ) { 23101 23102 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); 23103 gl.blendFuncSeparate( gl.ZERO, gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ONE_MINUS_SRC_ALPHA ); 23104 23105 } else { 23106 23107 gl.blendEquation( gl.FUNC_ADD ); 23108 gl.blendFunc( gl.ZERO, gl.ONE_MINUS_SRC_COLOR ); 23109 23110 } 23111 break; 23112 23113 case MultiplyBlending: 23114 23115 if ( premultipliedAlpha ) { 23116 23117 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); 23118 gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); 23119 23120 } else { 23121 23122 gl.blendEquation( gl.FUNC_ADD ); 23123 gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); 23124 23125 } 23126 break; 23127 23128 default: 23129 23130 if ( premultipliedAlpha ) { 23131 23132 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); 23133 gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); 23134 23135 } else { 23136 23137 gl.blendEquationSeparate( gl.FUNC_ADD, gl.FUNC_ADD ); 23138 gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); 23139 23140 } 23141 23142 } 23143 23144 } 23145 23146 currentBlendEquation = null; 23147 currentBlendSrc = null; 23148 currentBlendDst = null; 23149 currentBlendEquationAlpha = null; 23150 currentBlendSrcAlpha = null; 23151 currentBlendDstAlpha = null; 23152 23153 } else { 23154 23155 blendEquationAlpha = blendEquationAlpha || blendEquation; 23156 blendSrcAlpha = blendSrcAlpha || blendSrc; 23157 blendDstAlpha = blendDstAlpha || blendDst; 23158 23159 if ( blendEquation !== currentBlendEquation || blendEquationAlpha !== currentBlendEquationAlpha ) { 23160 23161 gl.blendEquationSeparate( utils.convert( blendEquation ), utils.convert( blendEquationAlpha ) ); 23162 23163 currentBlendEquation = blendEquation; 23164 currentBlendEquationAlpha = blendEquationAlpha; 23165 23166 } 23167 23168 if ( blendSrc !== currentBlendSrc || blendDst !== currentBlendDst || blendSrcAlpha !== currentBlendSrcAlpha || blendDstAlpha !== currentBlendDstAlpha ) { 23169 23170 gl.blendFuncSeparate( utils.convert( blendSrc ), utils.convert( blendDst ), utils.convert( blendSrcAlpha ), utils.convert( blendDstAlpha ) ); 23171 23172 currentBlendSrc = blendSrc; 23173 currentBlendDst = blendDst; 23174 currentBlendSrcAlpha = blendSrcAlpha; 23175 currentBlendDstAlpha = blendDstAlpha; 23176 23177 } 23178 23179 } 23180 23181 currentBlending = blending; 23182 currentPremultipledAlpha = premultipliedAlpha; 23183 23184 } 23185 23186 function setMaterial( material, frontFaceCW ) { 23187 23188 material.side === DoubleSide 23189 ? disable( gl.CULL_FACE ) 23190 : enable( gl.CULL_FACE ); 23191 23192 var flipSided = ( material.side === BackSide ); 23193 if ( frontFaceCW ) flipSided = ! flipSided; 23194 23195 setFlipSided( flipSided ); 23196 23197 material.transparent === true 23198 ? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ) 23199 : setBlending( NoBlending ); 23200 23201 depthBuffer.setFunc( material.depthFunc ); 23202 depthBuffer.setTest( material.depthTest ); 23203 depthBuffer.setMask( material.depthWrite ); 23204 colorBuffer.setMask( material.colorWrite ); 23205 23206 setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); 23207 23208 } 23209 23210 // 23211 23212 function setFlipSided( flipSided ) { 23213 23214 if ( currentFlipSided !== flipSided ) { 23215 23216 if ( flipSided ) { 23217 23218 gl.frontFace( gl.CW ); 23219 23220 } else { 23221
vendor: 4,155 bytes, lines 23222-23465
23222 gl.frontFace( gl.CCW ); 23223 23224 } 23225 23226 currentFlipSided = flipSided; 23227 23228 } 23229 23230 } 23231 23232 function setCullFace( cullFace ) { 23233 23234 if ( cullFace !== CullFaceNone ) { 23235 23236 enable( gl.CULL_FACE ); 23237 23238 if ( cullFace !== currentCullFace ) { 23239 23240 if ( cullFace === CullFaceBack ) { 23241 23242 gl.cullFace( gl.BACK ); 23243 23244 } else if ( cullFace === CullFaceFront ) { 23245 23246 gl.cullFace( gl.FRONT ); 23247 23248 } else { 23249 23250 gl.cullFace( gl.FRONT_AND_BACK ); 23251 23252 } 23253 23254 } 23255 23256 } else { 23257 23258 disable( gl.CULL_FACE ); 23259 23260 } 23261 23262 currentCullFace = cullFace; 23263 23264 } 23265 23266 function setLineWidth( width ) { 23267 23268 if ( width !== currentLineWidth ) { 23269 23270 if ( lineWidthAvailable ) gl.lineWidth( width ); 23271 23272 currentLineWidth = width; 23273 23274 } 23275 23276 } 23277 23278 function setPolygonOffset( polygonOffset, factor, units ) { 23279 23280 if ( polygonOffset ) { 23281 23282 enable( gl.POLYGON_OFFSET_FILL ); 23283 23284 if ( currentPolygonOffsetFactor !== factor || currentPolygonOffsetUnits !== units ) { 23285 23286 gl.polygonOffset( factor, units ); 23287 23288 currentPolygonOffsetFactor = factor; 23289 currentPolygonOffsetUnits = units; 23290 23291 } 23292 23293 } else { 23294 23295 disable( gl.POLYGON_OFFSET_FILL ); 23296 23297 } 23298 23299 } 23300 23301 function setScissorTest( scissorTest ) { 23302 23303 if ( scissorTest ) { 23304 23305 enable( gl.SCISSOR_TEST ); 23306 23307 } else { 23308 23309 disable( gl.SCISSOR_TEST ); 23310 23311 } 23312 23313 } 23314 23315 // texture 23316 23317 function activeTexture( webglSlot ) { 23318 23319 if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; 23320 23321 if ( currentTextureSlot !== webglSlot ) { 23322 23323 gl.activeTexture( webglSlot ); 23324 currentTextureSlot = webglSlot; 23325 23326 } 23327 23328 } 23329 23330 function bindTexture( webglType, webglTexture ) { 23331 23332 if ( currentTextureSlot === null ) { 23333 23334 activeTexture(); 23335 23336 } 23337 23338 var boundTexture = currentBoundTextures[ currentTextureSlot ]; 23339 23340 if ( boundTexture === undefined ) { 23341 23342 boundTexture = { type: undefined, texture: undefined }; 23343 currentBoundTextures[ currentTextureSlot ] = boundTexture; 23344 23345 } 23346 23347 if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { 23348 23349 gl.bindTexture( webglType, webglTexture || emptyTextures[ webglType ] ); 23350 23351 boundTexture.type = webglType; 23352 boundTexture.texture = webglTexture; 23353 23354 } 23355 23356 } 23357 23358 function compressedTexImage2D() { 23359 23360 try { 23361 23362 gl.compressedTexImage2D.apply( gl, arguments ); 23363 23364 } catch ( error ) { 23365 23366 console.error( 'THREE.WebGLState:', error ); 23367 23368 } 23369 23370 } 23371 23372 function texImage2D() { 23373 23374 try { 23375 23376 gl.texImage2D.apply( gl, arguments ); 23377 23378 } catch ( error ) { 23379 23380 console.error( 'THREE.WebGLState:', error ); 23381 23382 } 23383 23384 } 23385 23386 // 23387 23388 function scissor( scissor ) { 23389 23390 if ( currentScissor.equals( scissor ) === false ) { 23391 23392 gl.scissor( scissor.x, scissor.y, scissor.z, scissor.w ); 23393 currentScissor.copy( scissor ); 23394 23395 } 23396 23397 } 23398 23399 function viewport( viewport ) { 23400 23401 if ( currentViewport.equals( viewport ) === false ) { 23402 23403 gl.viewport( viewport.x, viewport.y, viewport.z, viewport.w ); 23404 currentViewport.copy( viewport ); 23405 23406 } 23407 23408 } 23409 23410 // 23411 23412 function reset() { 23413 23414 for ( var i = 0; i < enabledAttributes.length; i ++ ) { 23415 23416 if ( enabledAttributes[ i ] === 1 ) { 23417 23418 gl.disableVertexAttribArray( i ); 23419 enabledAttributes[ i ] = 0; 23420 23421 } 23422 23423 } 23424 23425 capabilities = {}; 23426 23427 compressedTextureFormats = null; 23428 23429 currentTextureSlot = null; 23430 currentBoundTextures = {}; 23431 23432 currentProgram = null; 23433 23434 currentBlending = null; 23435 23436 currentFlipSided = null; 23437 currentCullFace = null; 23438 23439 colorBuffer.reset(); 23440 depthBuffer.reset(); 23441 stencilBuffer.reset(); 23442 23443 } 23444 23445 return { 23446 23447 buffers: { 23448 color: colorBuffer, 23449 depth: depthBuffer, 23450 stencil: stencilBuffer 23451 }, 23452 23453 initAttributes: initAttributes, 23454 enableAttribute: enableAttribute, 23455 enableAttributeAndDivisor: enableAttributeAndDivisor, 23456 disableUnusedAttributes: disableUnusedAttributes, 23457 enable: enable, 23458 disable: disable, 23459 getCompressedTextureFormats: getCompressedTextureFormats, 23460 23461 useProgram: useProgram, 23462 23463 setBlending: setBlending, 23464 setMaterial: setMaterial, 23465
23466 setFlipSided: setFlipSided, 23467 setCullFace: setCullFace, 23468 23469 setLineWidth: setLineWidth, 23470 setPolygonOffset: setPolygonOffset, 23471 23472 setScissorTest: setScissorTest, 23473 23474 activeTexture: activeTexture, 23475 bindTexture: bindTexture, 23476 compressedTexImage2D: compressedTexImage2D, 23477 texImage2D: texImage2D, 23478 23479 scissor: scissor, 23480 viewport: viewport, 23481 23482 reset: reset 23483 23484 }; 23485 23486 } 23487 23488 /** 23489 * @author mrdoob / http://mrdoob.com/ 23490 */ 23491 23492 function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ) { 23493 23494 var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext ); /* global WebGL2RenderingContext */ 23495 var _videoTextures = {}; 23496 var _canvas; 23497 23498 // 23499 23500 function clampToMaxSize( image, maxSize ) { 23501 23502 if ( image.width > maxSize || image.height > maxSize ) { 23503 23504 if ( 'data' in image ) { 23505 23506 console.warn( 'THREE.WebGLRenderer: image in DataTexture is too big (' + image.width + 'x' + image.height + ').' ); 23507 return; 23508 23509 } 23510 23511 // Warning: Scaling through the canvas will only work with images that use 23512 // premultiplied alpha. 23513 23514 var scale = maxSize / Math.max( image.width, image.height ); 23515 23516 var canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); 23517 canvas.width = Math.floor( image.width * scale ); 23518 canvas.height = Math.floor( image.height * scale ); 23519 23520 var context = canvas.getContext( '2d' ); 23521 context.drawImage( image, 0, 0, image.width, image.height, 0, 0, canvas.width, canvas.height ); 23522 23523 console.warn( 'THREE.WebGLRenderer: image is too big (' + image.width + 'x' + image.height + '). Resized to ' + canvas.width + 'x' + canvas.height, image ); 23524 23525 return canvas; 23526 23527 } 23528 23529 return image; 23530 23531 } 23532 23533 function isPowerOfTwo( image ) { 23534 23535 return _Math.isPowerOfTwo( image.width ) && _Math.isPowerOfTwo( image.height ); 23536 23537 } 23538 23539 function makePowerOfTwo( image ) { 23540 23541 if ( image instanceof HTMLImageElement || image instanceof HTMLCanvasElement || image instanceof ImageBitmap ) { 23542 23543 if ( _canvas === undefined ) _canvas = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ); 23544 23545 _canvas.width = _Math.floorPowerOfTwo( image.width ); 23546 _canvas.height = _Math.floorPowerOfTwo( image.height ); 23547 23548 var context = _canvas.getContext( '2d' ); 23549 context.drawImage( image, 0, 0, _canvas.width, _canvas.height ); 23550 23551 console.warn( 'THREE.WebGLRenderer: image is not power of two (' + image.width + 'x' + image.height + '). Resized to ' + _canvas.width + 'x' + _canvas.height, image ); 23552 23553 return _canvas; 23554 23555 } 23556 23557 return image; 23558 23559 } 23560 23561 function textureNeedsPowerOfTwo( texture ) { 23562 23563 return ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) || 23564 ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ); 23565 23566 } 23567 23568 function textureNeedsGenerateMipmaps( texture, isPowerOfTwo ) { 23569 23570 return texture.generateMipmaps && isPowerOfTwo && 23571 texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter; 23572 23573 } 23574 23575 function generateMipmap( target, texture, width, height ) { 23576 23577 _gl.generateMipmap( target ); 23578 23579 var textureProperties = properties.get( texture ); 23580 23581 // Note: Math.log( x ) * Math.LOG2E used instead of Math.log2( x ) which is not supported by IE11 23582 textureProperties.__maxMipLevel = Math.log( Math.max( width, height ) ) * Math.LOG2E; 23583 23584 } 23585 23586 // Fallback filters for non-power-of-2 textures 23587 23588 function filterFallback( f ) { 23589 23590 if ( f === NearestFilter || f === NearestMipMapNearestFilter || f === NearestMipMapLinearFilter ) { 23591 23592 return _gl.NEAREST; 23593 23594 } 23595 23596 return _gl.LINEAR; 23597 23598 } 23599 23600 // 23601 23602 function onTextureDispose( event ) { 23603 23604 var texture = event.target; 23605 23606 texture.removeEventListener( 'dispose', onTextureDispose ); 23607 23608 deallocateTexture( texture ); 23609 23610 if ( texture.isVideoTexture ) { 23611 23612 delete _videoTextures[ texture.id ]; 23613 23614 } 23615 23616 info.memory.textures --; 23617 23618 } 23619 23620 function onRenderTargetDispose( event ) { 23621 23622 var renderTarget = event.target; 23623 23624 renderTarget.removeEventListener( 'dispose', onRenderTargetDispose ); 23625 23626 deallocateRenderTarget( renderTarget ); 23627 23628 info.memory.textures --; 23629 23630 } 23631 23632 // 23633 23634 function deallocateTexture( texture ) { 23635 23636 var textureProperties = properties.get( texture ); 23637 23638 if ( texture.image && textureProperties.__image__webglTextureCube ) { 23639 23640 // cube texture 23641 23642 _gl.deleteTexture( textureProperties.__image__webglTextureCube ); 23643 23644 } else { 23645
vendor: 4,521 bytes, lines 23646-23813
23646 // 2D texture 23647 23648 if ( textureProperties.__webglInit === undefined ) return; 23649 23650 _gl.deleteTexture( textureProperties.__webglTexture ); 23651 23652 } 23653 23654 // remove all webgl properties 23655 properties.remove( texture ); 23656 23657 } 23658 23659 function deallocateRenderTarget( renderTarget ) { 23660 23661 var renderTargetProperties = properties.get( renderTarget ); 23662 var textureProperties = properties.get( renderTarget.texture ); 23663 23664 if ( ! renderTarget ) return; 23665 23666 if ( textureProperties.__webglTexture !== undefined ) { 23667 23668 _gl.deleteTexture( textureProperties.__webglTexture ); 23669 23670 } 23671 23672 if ( renderTarget.depthTexture ) { 23673 23674 renderTarget.depthTexture.dispose(); 23675 23676 } 23677 23678 if ( renderTarget.isWebGLRenderTargetCube ) { 23679 23680 for ( var i = 0; i < 6; i ++ ) { 23681 23682 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer[ i ] ); 23683 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer[ i ] ); 23684 23685 } 23686 23687 } else { 23688 23689 _gl.deleteFramebuffer( renderTargetProperties.__webglFramebuffer ); 23690 if ( renderTargetProperties.__webglDepthbuffer ) _gl.deleteRenderbuffer( renderTargetProperties.__webglDepthbuffer ); 23691 23692 } 23693 23694 properties.remove( renderTarget.texture ); 23695 properties.remove( renderTarget ); 23696 23697 } 23698 23699 // 23700 23701 23702 23703 function setTexture2D( texture, slot ) { 23704 23705 var textureProperties = properties.get( texture ); 23706 23707 if ( texture.isVideoTexture ) updateVideoTexture( texture ); 23708 23709 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 23710 23711 var image = texture.image; 23712 23713 if ( image === undefined ) { 23714 23715 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is undefined', texture ); 23716 23717 } else if ( image.complete === false ) { 23718 23719 console.warn( 'THREE.WebGLRenderer: Texture marked for update but image is incomplete', texture ); 23720 23721 } else { 23722 23723 uploadTexture( textureProperties, texture, slot ); 23724 return; 23725 23726 } 23727 23728 } 23729 23730 state.activeTexture( _gl.TEXTURE0 + slot ); 23731 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); 23732 23733 } 23734 23735 function setTextureCube( texture, slot ) { 23736 23737 var textureProperties = properties.get( texture ); 23738 23739 if ( texture.image.length === 6 ) { 23740 23741 if ( texture.version > 0 && textureProperties.__version !== texture.version ) { 23742 23743 if ( ! textureProperties.__image__webglTextureCube ) { 23744 23745 texture.addEventListener( 'dispose', onTextureDispose ); 23746 23747 textureProperties.__image__webglTextureCube = _gl.createTexture(); 23748 23749 info.memory.textures ++; 23750 23751 } 23752 23753 state.activeTexture( _gl.TEXTURE0 + slot ); 23754 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); 23755 23756 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); 23757 23758 var isCompressed = ( texture && texture.isCompressedTexture ); 23759 var isDataTexture = ( texture.image[ 0 ] && texture.image[ 0 ].isDataTexture ); 23760 23761 var cubeImage = []; 23762 23763 for ( var i = 0; i < 6; i ++ ) { 23764 23765 if ( ! isCompressed && ! isDataTexture ) { 23766 23767 cubeImage[ i ] = clampToMaxSize( texture.image[ i ], capabilities.maxCubemapSize ); 23768 23769 } else { 23770 23771 cubeImage[ i ] = isDataTexture ? texture.image[ i ].image : texture.image[ i ]; 23772 23773 } 23774 23775 } 23776 23777 var image = cubeImage[ 0 ], 23778 isPowerOfTwoImage = isPowerOfTwo( image ), 23779 glFormat = utils.convert( texture.format ), 23780 glType = utils.convert( texture.type ); 23781 23782 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isPowerOfTwoImage ); 23783 23784 for ( var i = 0; i < 6; i ++ ) { 23785 23786 if ( ! isCompressed ) { 23787 23788 if ( isDataTexture ) { 23789 23790 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, cubeImage[ i ].width, cubeImage[ i ].height, 0, glFormat, glType, cubeImage[ i ].data ); 23791 23792 } else { 23793 23794 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] ); 23795 23796 } 23797 23798 } else { 23799 23800 var mipmap, mipmaps = cubeImage[ i ].mipmaps; 23801 23802 for ( var j = 0, jl = mipmaps.length; j < jl; j ++ ) { 23803 23804 mipmap = mipmaps[ j ]; 23805 23806 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { 23807 23808 if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { 23809 23810 state.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 23811 23812 } else { 23813
23814 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .setTextureCube()' ); 23815 23816 } 23817 23818 } else { 23819 23820 state.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 23821 23822 } 23823 23824 } 23825 23826 } 23827 23828 } 23829 23830 if ( ! isCompressed ) { 23831 23832 textureProperties.__maxMipLevel = 0; 23833 23834 } else { 23835 23836 textureProperties.__maxMipLevel = mipmaps.length - 1; 23837 23838 } 23839 23840 if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { 23841 23842 // We assume images for cube map have the same size. 23843 generateMipmap( _gl.TEXTURE_CUBE_MAP, texture, image.width, image.height ); 23844 23845 } 23846 23847 textureProperties.__version = texture.version; 23848 23849 if ( texture.onUpdate ) texture.onUpdate( texture ); 23850 23851 } else { 23852 23853 state.activeTexture( _gl.TEXTURE0 + slot ); 23854 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__image__webglTextureCube ); 23855 23856 } 23857 23858 } 23859 23860 } 23861 23862 function setTextureCubeDynamic( texture, slot ) { 23863 23864 state.activeTexture( _gl.TEXTURE0 + slot ); 23865 state.bindTexture( _gl.TEXTURE_CUBE_MAP, properties.get( texture ).__webglTexture ); 23866 23867 } 23868 23869 function setTextureParameters( textureType, texture, isPowerOfTwoImage ) { 23870 23871 var extension; 23872 23873 if ( isPowerOfTwoImage ) { 23874 23875 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, utils.convert( texture.wrapS ) ); 23876 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, utils.convert( texture.wrapT ) ); 23877 23878 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, utils.convert( texture.magFilter ) ); 23879 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, utils.convert( texture.minFilter ) ); 23880 23881 } else { 23882 23883 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE ); 23884 _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE ); 23885 23886 if ( texture.wrapS !== ClampToEdgeWrapping || texture.wrapT !== ClampToEdgeWrapping ) { 23887 23888 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.wrapS and Texture.wrapT should be set to THREE.ClampToEdgeWrapping.', texture ); 23889 23890 } 23891 23892 _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) ); 23893 _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) ); 23894 23895 if ( texture.minFilter !== NearestFilter && texture.minFilter !== LinearFilter ) { 23896 23897 console.warn( 'THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter should be set to THREE.NearestFilter or THREE.LinearFilter.', texture ); 23898 23899 } 23900 23901 } 23902 23903 extension = extensions.get( 'EXT_texture_filter_anisotropic' ); 23904 23905 if ( extension ) { 23906 23907 if ( texture.type === FloatType && extensions.get( 'OES_texture_float_linear' ) === null ) return; 23908 if ( texture.type === HalfFloatType && extensions.get( 'OES_texture_half_float_linear' ) === null ) return; 23909 23910 if ( texture.anisotropy > 1 || properties.get( texture ).__currentAnisotropy ) { 23911 23912 _gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, capabilities.getMaxAnisotropy() ) ); 23913 properties.get( texture ).__currentAnisotropy = texture.anisotropy; 23914 23915 } 23916 23917 } 23918 23919 } 23920 23921 function uploadTexture( textureProperties, texture, slot ) { 23922 23923 if ( textureProperties.__webglInit === undefined ) { 23924 23925 textureProperties.__webglInit = true; 23926 23927 texture.addEventListener( 'dispose', onTextureDispose ); 23928 23929 textureProperties.__webglTexture = _gl.createTexture(); 23930 23931 info.memory.textures ++; 23932 23933 } 23934 23935 state.activeTexture( _gl.TEXTURE0 + slot ); 23936 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); 23937 23938 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); 23939 _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); 23940 _gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); 23941 23942 var image = clampToMaxSize( texture.image, capabilities.maxTextureSize ); 23943 23944 if ( textureNeedsPowerOfTwo( texture ) && isPowerOfTwo( image ) === false ) { 23945 23946 image = makePowerOfTwo( image ); 23947 23948 } 23949 23950 var isPowerOfTwoImage = isPowerOfTwo( image ), 23951 glFormat = utils.convert( texture.format ), 23952 glType = utils.convert( texture.type ); 23953 23954 setTextureParameters( _gl.TEXTURE_2D, texture, isPowerOfTwoImage ); 23955 23956 var mipmap, mipmaps = texture.mipmaps; 23957 23958 if ( texture.isDepthTexture ) { 23959 23960 // populate depth texture with dummy data 23961 23962 var internalFormat = _gl.DEPTH_COMPONENT; 23963 23964 if ( texture.type === FloatType ) { 23965
23966 if ( ! _isWebGL2 ) throw new Error( 'Float Depth Texture only supported in WebGL2.0' ); 23967 internalFormat = _gl.DEPTH_COMPONENT32F; 23968 23969 } else if ( _isWebGL2 ) { 23970 23971 // WebGL 2.0 requires signed internalformat for glTexImage2D 23972 internalFormat = _gl.DEPTH_COMPONENT16; 23973 23974 } 23975 23976 if ( texture.format === DepthFormat && internalFormat === _gl.DEPTH_COMPONENT ) { 23977 23978 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are 23979 // DEPTH_COMPONENT and type is not UNSIGNED_SHORT or UNSIGNED_INT 23980 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 23981 if ( texture.type !== UnsignedShortType && texture.type !== UnsignedIntType ) { 23982 23983 console.warn( 'THREE.WebGLRenderer: Use UnsignedShortType or UnsignedIntType for DepthFormat DepthTexture.' ); 23984 23985 texture.type = UnsignedShortType; 23986 glType = utils.convert( texture.type ); 23987 23988 } 23989 23990 } 23991 23992 // Depth stencil textures need the DEPTH_STENCIL internal format 23993 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 23994 if ( texture.format === DepthStencilFormat ) { 23995 23996 internalFormat = _gl.DEPTH_STENCIL; 23997 23998 // The error INVALID_OPERATION is generated by texImage2D if format and internalformat are 23999 // DEPTH_STENCIL and type is not UNSIGNED_INT_24_8_WEBGL. 24000 // (https://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/) 24001 if ( texture.type !== UnsignedInt248Type ) { 24002 24003 console.warn( 'THREE.WebGLRenderer: Use UnsignedInt248Type for DepthStencilFormat DepthTexture.' ); 24004 24005 texture.type = UnsignedInt248Type; 24006 glType = utils.convert( texture.type ); 24007 24008 } 24009 24010 } 24011 24012 state.texImage2D( _gl.TEXTURE_2D, 0, internalFormat, image.width, image.height, 0, glFormat, glType, null ); 24013 24014 } else if ( texture.isDataTexture ) { 24015 24016 // use manually created mipmaps if available 24017 // if there are no manual mipmaps 24018 // set 0 level mipmap and then use GL to generate other mipmap levels 24019 24020 if ( mipmaps.length > 0 && isPowerOfTwoImage ) { 24021 24022 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { 24023 24024 mipmap = mipmaps[ i ]; 24025 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 24026 24027 } 24028 24029 texture.generateMipmaps = false; 24030 textureProperties.__maxMipLevel = mipmaps.length - 1; 24031 24032 } else { 24033 24034 state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data ); 24035 textureProperties.__maxMipLevel = 0; 24036 24037 } 24038 24039 } else if ( texture.isCompressedTexture ) { 24040 24041 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { 24042 24043 mipmap = mipmaps[ i ]; 24044 24045 if ( texture.format !== RGBAFormat && texture.format !== RGBFormat ) { 24046 24047 if ( state.getCompressedTextureFormats().indexOf( glFormat ) > - 1 ) { 24048 24049 state.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data ); 24050 24051 } else { 24052 24053 console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); 24054 24055 } 24056 24057 } else { 24058 24059 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data ); 24060 24061 } 24062 24063 } 24064 24065 textureProperties.__maxMipLevel = mipmaps.length - 1; 24066 24067 } else { 24068 24069 // regular Texture (image, video, canvas) 24070 24071 // use manually created mipmaps if available 24072 // if there are no manual mipmaps 24073 // set 0 level mipmap and then use GL to generate other mipmap levels 24074 24075 if ( mipmaps.length > 0 && isPowerOfTwoImage ) { 24076 24077 for ( var i = 0, il = mipmaps.length; i < il; i ++ ) { 24078 24079 mipmap = mipmaps[ i ]; 24080 state.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap ); 24081 24082 } 24083 24084 texture.generateMipmaps = false; 24085 textureProperties.__maxMipLevel = mipmaps.length - 1; 24086 24087 } else { 24088 24089 state.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, image ); 24090 textureProperties.__maxMipLevel = 0; 24091 24092 } 24093 24094 } 24095 24096 if ( textureNeedsGenerateMipmaps( texture, isPowerOfTwoImage ) ) { 24097 24098 generateMipmap( _gl.TEXTURE_2D, texture, image.width, image.height ); 24099 24100 } 24101 24102 textureProperties.__version = texture.version; 24103 24104 if ( texture.onUpdate ) texture.onUpdate( texture ); 24105 24106 } 24107 24108 // Render targets 24109 24110 // Setup storage for target texture and bind it to correct framebuffer 24111 function setupFrameBufferTexture( framebuffer, renderTarget, attachment, textureTarget ) { 24112 24113 var glFormat = utils.convert( renderTarget.texture.format ); 24114 var glType = utils.convert( renderTarget.texture.type ); 24115 state.texImage2D( textureTarget, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null ); 24116 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 24117 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, attachment, textureTarget, properties.get( renderTarget.texture ).__webglTexture, 0 ); 24118 _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); 24119 24120 } 24121 24122 // Setup storage for internal depth/stencil buffers and bind to correct framebuffer 24123 function setupRenderBufferStorage( renderbuffer, renderTarget ) { 24124 24125 _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer ); 24126 24127 if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) { 24128 24129 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height ); 24130 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); 24131 24132 } else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) { 24133 24134 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height ); 24135 _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer ); 24136 24137 } else { 24138
vendor: 4,660 bytes, lines 24139-24289
24139 // FIXME: We don't support !depth !stencil 24140 _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height ); 24141 24142 } 24143 24144 _gl.bindRenderbuffer( _gl.RENDERBUFFER, null ); 24145 24146 } 24147 24148 // Setup resources for a Depth Texture for a FBO (needs an extension) 24149 function setupDepthTexture( framebuffer, renderTarget ) { 24150 24151 var isCube = ( renderTarget && renderTarget.isWebGLRenderTargetCube ); 24152 if ( isCube ) throw new Error( 'Depth Texture with cube render targets is not supported' ); 24153 24154 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 24155 24156 if ( ! ( renderTarget.depthTexture && renderTarget.depthTexture.isDepthTexture ) ) { 24157 24158 throw new Error( 'renderTarget.depthTexture must be an instance of THREE.DepthTexture' ); 24159 24160 } 24161 24162 // upload an empty depth texture with framebuffer size 24163 if ( ! properties.get( renderTarget.depthTexture ).__webglTexture || 24164 renderTarget.depthTexture.image.width !== renderTarget.width || 24165 renderTarget.depthTexture.image.height !== renderTarget.height ) { 24166 24167 renderTarget.depthTexture.image.width = renderTarget.width; 24168 renderTarget.depthTexture.image.height = renderTarget.height; 24169 renderTarget.depthTexture.needsUpdate = true; 24170 24171 } 24172 24173 setTexture2D( renderTarget.depthTexture, 0 ); 24174 24175 var webglDepthTexture = properties.get( renderTarget.depthTexture ).__webglTexture; 24176 24177 if ( renderTarget.depthTexture.format === DepthFormat ) { 24178 24179 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); 24180 24181 } else if ( renderTarget.depthTexture.format === DepthStencilFormat ) { 24182 24183 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.TEXTURE_2D, webglDepthTexture, 0 ); 24184 24185 } else { 24186 24187 throw new Error( 'Unknown depthTexture format' ); 24188 24189 } 24190 24191 } 24192 24193 // Setup GL resources for a non-texture depth buffer 24194 function setupDepthRenderbuffer( renderTarget ) { 24195 24196 var renderTargetProperties = properties.get( renderTarget ); 24197 24198 var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); 24199 24200 if ( renderTarget.depthTexture ) { 24201 24202 if ( isCube ) throw new Error( 'target.depthTexture not supported in Cube render targets' ); 24203 24204 setupDepthTexture( renderTargetProperties.__webglFramebuffer, renderTarget ); 24205 24206 } else { 24207 24208 if ( isCube ) { 24209 24210 renderTargetProperties.__webglDepthbuffer = []; 24211 24212 for ( var i = 0; i < 6; i ++ ) { 24213 24214 _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer[ i ] ); 24215 renderTargetProperties.__webglDepthbuffer[ i ] = _gl.createRenderbuffer(); 24216 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer[ i ], renderTarget ); 24217 24218 } 24219 24220 } else { 24221 24222 _gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer ); 24223 renderTargetProperties.__webglDepthbuffer = _gl.createRenderbuffer(); 24224 setupRenderBufferStorage( renderTargetProperties.__webglDepthbuffer, renderTarget ); 24225 24226 } 24227 24228 } 24229 24230 _gl.bindFramebuffer( _gl.FRAMEBUFFER, null ); 24231 24232 } 24233 24234 // Set up GL resources for the render target 24235 function setupRenderTarget( renderTarget ) { 24236 24237 var renderTargetProperties = properties.get( renderTarget ); 24238 var textureProperties = properties.get( renderTarget.texture ); 24239 24240 renderTarget.addEventListener( 'dispose', onRenderTargetDispose ); 24241 24242 textureProperties.__webglTexture = _gl.createTexture(); 24243 24244 info.memory.textures ++; 24245 24246 var isCube = ( renderTarget.isWebGLRenderTargetCube === true ); 24247 var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); 24248 24249 // Setup framebuffer 24250 24251 if ( isCube ) { 24252 24253 renderTargetProperties.__webglFramebuffer = []; 24254 24255 for ( var i = 0; i < 6; i ++ ) { 24256 24257 renderTargetProperties.__webglFramebuffer[ i ] = _gl.createFramebuffer(); 24258 24259 } 24260 24261 } else { 24262 24263 renderTargetProperties.__webglFramebuffer = _gl.createFramebuffer(); 24264 24265 } 24266 24267 // Setup color buffer 24268 24269 if ( isCube ) { 24270 24271 state.bindTexture( _gl.TEXTURE_CUBE_MAP, textureProperties.__webglTexture ); 24272 setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, isTargetPowerOfTwo ); 24273 24274 for ( var i = 0; i < 6; i ++ ) { 24275 24276 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer[ i ], renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i ); 24277 24278 } 24279 24280 if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) { 24281 24282 generateMipmap( _gl.TEXTURE_CUBE_MAP, renderTarget.texture, renderTarget.width, renderTarget.height ); 24283 24284 } 24285 24286 state.bindTexture( _gl.TEXTURE_CUBE_MAP, null ); 24287 24288 } else { 24289
24290 state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture ); 24291 setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, isTargetPowerOfTwo ); 24292 setupFrameBufferTexture( renderTargetProperties.__webglFramebuffer, renderTarget, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_2D ); 24293 24294 if ( textureNeedsGenerateMipmaps( renderTarget.texture, isTargetPowerOfTwo ) ) { 24295 24296 generateMipmap( _gl.TEXTURE_2D, renderTarget.texture, renderTarget.width, renderTarget.height ); 24297 24298 } 24299 24300 state.bindTexture( _gl.TEXTURE_2D, null ); 24301 24302 } 24303 24304 // Setup depth and stencil buffers 24305 24306 if ( renderTarget.depthBuffer ) { 24307 24308 setupDepthRenderbuffer( renderTarget ); 24309 24310 } 24311 24312 } 24313 24314 function updateRenderTargetMipmap( renderTarget ) { 24315 24316 var texture = renderTarget.texture; 24317 var isTargetPowerOfTwo = isPowerOfTwo( renderTarget ); 24318 24319 if ( textureNeedsGenerateMipmaps( texture, isTargetPowerOfTwo ) ) { 24320 24321 var target = renderTarget.isWebGLRenderTargetCube ? _gl.TEXTURE_CUBE_MAP : _gl.TEXTURE_2D; 24322 var webglTexture = properties.get( texture ).__webglTexture; 24323 24324 state.bindTexture( target, webglTexture ); 24325 generateMipmap( target, texture, renderTarget.width, renderTarget.height ); 24326 state.bindTexture( target, null ); 24327 24328 } 24329 24330 } 24331 24332 function updateVideoTexture( texture ) { 24333 24334 var id = texture.id; 24335 var frame = info.render.frame; 24336 24337 // Check the last frame we updated the VideoTexture 24338 24339 if ( _videoTextures[ id ] !== frame ) { 24340 24341 _videoTextures[ id ] = frame; 24342 texture.update(); 24343 24344 } 24345 24346 } 24347 24348 this.setTexture2D = setTexture2D; 24349 this.setTextureCube = setTextureCube; 24350 this.setTextureCubeDynamic = setTextureCubeDynamic; 24351 this.setupRenderTarget = setupRenderTarget; 24352 this.updateRenderTargetMipmap = updateRenderTargetMipmap; 24353 24354 } 24355 24356 /** 24357 * @author thespite / http://www.twitter.com/thespite 24358 */ 24359 24360 function WebGLUtils( gl, extensions ) { 24361 24362 function convert( p ) { 24363 24364 var extension; 24365 24366 if ( p === RepeatWrapping ) return gl.REPEAT; 24367 if ( p === ClampToEdgeWrapping ) return gl.CLAMP_TO_EDGE; 24368 if ( p === MirroredRepeatWrapping ) return gl.MIRRORED_REPEAT; 24369 24370 if ( p === NearestFilter ) return gl.NEAREST; 24371 if ( p === NearestMipMapNearestFilter ) return gl.NEAREST_MIPMAP_NEAREST; 24372 if ( p === NearestMipMapLinearFilter ) return gl.NEAREST_MIPMAP_LINEAR; 24373 24374 if ( p === LinearFilter ) return gl.LINEAR; 24375 if ( p === LinearMipMapNearestFilter ) return gl.LINEAR_MIPMAP_NEAREST; 24376 if ( p === LinearMipMapLinearFilter ) return gl.LINEAR_MIPMAP_LINEAR; 24377 24378 if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; 24379 if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; 24380 if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; 24381 if ( p === UnsignedShort565Type ) return gl.UNSIGNED_SHORT_5_6_5; 24382 24383 if ( p === ByteType ) return gl.BYTE; 24384 if ( p === ShortType ) return gl.SHORT; 24385 if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; 24386 if ( p === IntType ) return gl.INT; 24387 if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; 24388 if ( p === FloatType ) return gl.FLOAT; 24389 24390 if ( p === HalfFloatType ) { 24391 24392 extension = extensions.get( 'OES_texture_half_float' ); 24393 24394 if ( extension !== null ) return extension.HALF_FLOAT_OES; 24395 24396 } 24397 24398 if ( p === AlphaFormat ) return gl.ALPHA; 24399 if ( p === RGBFormat ) return gl.RGB; 24400 if ( p === RGBAFormat ) return gl.RGBA; 24401 if ( p === LuminanceFormat ) return gl.LUMINANCE; 24402 if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; 24403 if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; 24404 if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; 24405 24406 if ( p === AddEquation ) return gl.FUNC_ADD; 24407 if ( p === SubtractEquation ) return gl.FUNC_SUBTRACT; 24408 if ( p === ReverseSubtractEquation ) return gl.FUNC_REVERSE_SUBTRACT; 24409 24410 if ( p === ZeroFactor ) return gl.ZERO; 24411 if ( p === OneFactor ) return gl.ONE; 24412 if ( p === SrcColorFactor ) return gl.SRC_COLOR; 24413 if ( p === OneMinusSrcColorFactor ) return gl.ONE_MINUS_SRC_COLOR; 24414 if ( p === SrcAlphaFactor ) return gl.SRC_ALPHA; 24415 if ( p === OneMinusSrcAlphaFactor ) return gl.ONE_MINUS_SRC_ALPHA; 24416 if ( p === DstAlphaFactor ) return gl.DST_ALPHA; 24417 if ( p === OneMinusDstAlphaFactor ) return gl.ONE_MINUS_DST_ALPHA; 24418
vendor: 9,846 bytes, lines 24419-24801
24419 if ( p === DstColorFactor ) return gl.DST_COLOR; 24420 if ( p === OneMinusDstColorFactor ) return gl.ONE_MINUS_DST_COLOR; 24421 if ( p === SrcAlphaSaturateFactor ) return gl.SRC_ALPHA_SATURATE; 24422 24423 if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || 24424 p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { 24425 24426 extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); 24427 24428 if ( extension !== null ) { 24429 24430 if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; 24431 if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; 24432 if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; 24433 if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; 24434 24435 } 24436 24437 } 24438 24439 if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || 24440 p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { 24441 24442 extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); 24443 24444 if ( extension !== null ) { 24445 24446 if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; 24447 if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; 24448 if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; 24449 if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; 24450 24451 } 24452 24453 } 24454 24455 if ( p === RGB_ETC1_Format ) { 24456 24457 extension = extensions.get( 'WEBGL_compressed_texture_etc1' ); 24458 24459 if ( extension !== null ) return extension.COMPRESSED_RGB_ETC1_WEBGL; 24460 24461 } 24462 24463 if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || 24464 p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || 24465 p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || 24466 p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || 24467 p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) { 24468 24469 extension = extensions.get( 'WEBGL_compressed_texture_astc' ); 24470 24471 if ( extension !== null ) { 24472 24473 return p; 24474 24475 } 24476 24477 } 24478 24479 if ( p === MinEquation || p === MaxEquation ) { 24480 24481 extension = extensions.get( 'EXT_blend_minmax' ); 24482 24483 if ( extension !== null ) { 24484 24485 if ( p === MinEquation ) return extension.MIN_EXT; 24486 if ( p === MaxEquation ) return extension.MAX_EXT; 24487 24488 } 24489 24490 } 24491 24492 if ( p === UnsignedInt248Type ) { 24493 24494 extension = extensions.get( 'WEBGL_depth_texture' ); 24495 24496 if ( extension !== null ) return extension.UNSIGNED_INT_24_8_WEBGL; 24497 24498 } 24499 24500 return 0; 24501 24502 } 24503 24504 return { convert: convert }; 24505 24506 } 24507 24508 /** 24509 * @author mrdoob / http://mrdoob.com/ 24510 * @author greggman / http://games.greggman.com/ 24511 * @author zz85 / http://www.lab4games.net/zz85/blog 24512 * @author tschw 24513 */ 24514 24515 function PerspectiveCamera( fov, aspect, near, far ) { 24516 24517 Camera.call( this ); 24518 24519 this.type = 'PerspectiveCamera'; 24520 24521 this.fov = fov !== undefined ? fov : 50; 24522 this.zoom = 1; 24523 24524 this.near = near !== undefined ? near : 0.1; 24525 this.far = far !== undefined ? far : 2000; 24526 this.focus = 10; 24527 24528 this.aspect = aspect !== undefined ? aspect : 1; 24529 this.view = null; 24530 24531 this.filmGauge = 35; // width of the film (default in millimeters) 24532 this.filmOffset = 0; // horizontal film offset (same unit as gauge) 24533 24534 this.updateProjectionMatrix(); 24535 24536 } 24537 24538 PerspectiveCamera.prototype = Object.assign( Object.create( Camera.prototype ), { 24539 24540 constructor: PerspectiveCamera, 24541 24542 isPerspectiveCamera: true, 24543 24544 copy: function ( source, recursive ) { 24545 24546 Camera.prototype.copy.call( this, source, recursive ); 24547 24548 this.fov = source.fov; 24549 this.zoom = source.zoom; 24550 24551 this.near = source.near; 24552 this.far = source.far; 24553 this.focus = source.focus; 24554 24555 this.aspect = source.aspect; 24556 this.view = source.view === null ? null : Object.assign( {}, source.view ); 24557 24558 this.filmGauge = source.filmGauge; 24559 this.filmOffset = source.filmOffset; 24560 24561 return this; 24562 24563 }, 24564 24565 /** 24566 * Sets the FOV by focal length in respect to the current .filmGauge. 24567 * 24568 * The default film gauge is 35, so that the focal length can be specified for 24569 * a 35mm (full frame) camera. 24570 * 24571 * Values for focal length and film gauge must have the same unit. 24572 */ 24573 setFocalLength: function ( focalLength ) { 24574 24575 // see http://www.bobatkins.com/photography/technical/field_of_view.html 24576 var vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; 24577 24578 this.fov = _Math.RAD2DEG * 2 * Math.atan( vExtentSlope ); 24579 this.updateProjectionMatrix(); 24580 24581 }, 24582 24583 /** 24584 * Calculates the focal length from the current .fov and .filmGauge. 24585 */ 24586 getFocalLength: function () { 24587 24588 var vExtentSlope = Math.tan( _Math.DEG2RAD * 0.5 * this.fov ); 24589 24590 return 0.5 * this.getFilmHeight() / vExtentSlope; 24591 24592 }, 24593 24594 getEffectiveFOV: function () { 24595 24596 return _Math.RAD2DEG * 2 * Math.atan( 24597 Math.tan( _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom ); 24598 24599 }, 24600 24601 getFilmWidth: function () { 24602 24603 // film not completely covered in portrait format (aspect < 1) 24604 return this.filmGauge * Math.min( this.aspect, 1 ); 24605 24606 }, 24607 24608 getFilmHeight: function () { 24609 24610 // film not completely covered in landscape format (aspect > 1) 24611 return this.filmGauge / Math.max( this.aspect, 1 ); 24612 24613 }, 24614 24615 /** 24616 * Sets an offset in a larger frustum. This is useful for multi-window or 24617 * multi-monitor/multi-machine setups. 24618 * 24619 * For example, if you have 3x2 monitors and each monitor is 1920x1080 and 24620 * the monitors are in grid like this 24621 * 24622 * +---+---+---+ 24623 * | A | B | C | 24624 * +---+---+---+ 24625 * | D | E | F | 24626 * +---+---+---+ 24627 * 24628 * then for each monitor you would call it like this 24629 * 24630 * var w = 1920; 24631 * var h = 1080; 24632 * var fullWidth = w * 3; 24633 * var fullHeight = h * 2; 24634 * 24635 * --A-- 24636 * camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); 24637 * --B-- 24638 * camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); 24639 * --C-- 24640 * camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); 24641 * --D-- 24642 * camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); 24643 * --E-- 24644 * camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); 24645 * --F-- 24646 * camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); 24647 * 24648 * Note there is no reason monitors have to be the same size or in a grid. 24649 */ 24650 setViewOffset: function ( fullWidth, fullHeight, x, y, width, height ) { 24651 24652 this.aspect = fullWidth / fullHeight; 24653 24654 if ( this.view === null ) { 24655 24656 this.view = { 24657 enabled: true, 24658 fullWidth: 1, 24659 fullHeight: 1, 24660 offsetX: 0, 24661 offsetY: 0, 24662 width: 1, 24663 height: 1 24664 }; 24665 24666 } 24667 24668 this.view.enabled = true; 24669 this.view.fullWidth = fullWidth; 24670 this.view.fullHeight = fullHeight; 24671 this.view.offsetX = x; 24672 this.view.offsetY = y; 24673 this.view.width = width; 24674 this.view.height = height; 24675 24676 this.updateProjectionMatrix(); 24677 24678 }, 24679 24680 clearViewOffset: function () { 24681 24682 if ( this.view !== null ) { 24683 24684 this.view.enabled = false; 24685 24686 } 24687 24688 this.updateProjectionMatrix(); 24689 24690 }, 24691 24692 updateProjectionMatrix: function () { 24693 24694 var near = this.near, 24695 top = near * Math.tan( 24696 _Math.DEG2RAD * 0.5 * this.fov ) / this.zoom, 24697 height = 2 * top, 24698 width = this.aspect * height, 24699 left = - 0.5 * width, 24700 view = this.view; 24701 24702 if ( this.view !== null && this.view.enabled ) { 24703 24704 var fullWidth = view.fullWidth, 24705 fullHeight = view.fullHeight; 24706 24707 left += view.offsetX * width / fullWidth; 24708 top -= view.offsetY * height / fullHeight; 24709 width *= view.width / fullWidth; 24710 height *= view.height / fullHeight; 24711 24712 } 24713 24714 var skew = this.filmOffset; 24715 if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); 24716 24717 this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far ); 24718 24719 }, 24720 24721 toJSON: function ( meta ) { 24722 24723 var data = Object3D.prototype.toJSON.call( this, meta ); 24724 24725 data.object.fov = this.fov; 24726 data.object.zoom = this.zoom; 24727 24728 data.object.near = this.near; 24729 data.object.far = this.far; 24730 data.object.focus = this.focus; 24731 24732 data.object.aspect = this.aspect; 24733 24734 if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); 24735 24736 data.object.filmGauge = this.filmGauge; 24737 data.object.filmOffset = this.filmOffset; 24738 24739 return data; 24740 24741 } 24742 24743 } ); 24744 24745 /** 24746 * @author mrdoob / http://mrdoob.com/ 24747 */ 24748 24749 function ArrayCamera( array ) { 24750 24751 PerspectiveCamera.call( this ); 24752 24753 this.cameras = array || []; 24754 24755 } 24756 24757 ArrayCamera.prototype = Object.assign( Object.create( PerspectiveCamera.prototype ), { 24758 24759 constructor: ArrayCamera, 24760 24761 isArrayCamera: true 24762 24763 } ); 24764 24765 /** 24766 * @author mrdoob / http://mrdoob.com/ 24767 */ 24768 24769 function WebVRManager( renderer ) { 24770 24771 var scope = this; 24772 24773 var device = null; 24774 var frameData = null; 24775 24776 var poseTarget = null; 24777 24778 var standingMatrix = new Matrix4(); 24779 var standingMatrixInverse = new Matrix4(); 24780 24781 if ( typeof window !== 'undefined' && 'VRFrameData' in window ) { 24782 24783 frameData = new window.VRFrameData(); 24784 window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false ); 24785 24786 } 24787 24788 var matrixWorldInverse = new Matrix4(); 24789 var tempQuaternion = new Quaternion(); 24790 var tempPosition = new Vector3(); 24791 24792 var cameraL = new PerspectiveCamera(); 24793 cameraL.bounds = new Vector4( 0.0, 0.0, 0.5, 1.0 ); 24794 cameraL.layers.enable( 1 ); 24795 24796 var cameraR = new PerspectiveCamera(); 24797 cameraR.bounds = new Vector4( 0.5, 0.0, 0.5, 1.0 ); 24798 cameraR.layers.enable( 2 ); 24799 24800 var cameraVR = new ArrayCamera( [ cameraL, cameraR ] ); 24801 cameraVR.layers.enable( 1 );
24802 cameraVR.layers.enable( 2 ); 24803 24804 // 24805 24806 function isPresenting() { 24807 24808 return device !== null && device.isPresenting === true; 24809 24810 } 24811 24812 var currentSize, currentPixelRatio; 24813 24814 function onVRDisplayPresentChange() { 24815 24816 if ( isPresenting() ) { 24817 24818 var eyeParameters = device.getEyeParameters( 'left' ); 24819 var renderWidth = eyeParameters.renderWidth; 24820 var renderHeight = eyeParameters.renderHeight; 24821 24822 currentPixelRatio = renderer.getPixelRatio(); 24823 currentSize = renderer.getSize(); 24824 24825 renderer.setDrawingBufferSize( renderWidth * 2, renderHeight, 1 ); 24826 24827 animation.start(); 24828 24829 } else if ( scope.enabled ) { 24830 24831 renderer.setDrawingBufferSize( currentSize.width, currentSize.height, currentPixelRatio ); 24832 24833 animation.stop(); 24834 24835 } 24836 24837 } 24838 24839 // 24840 24841 this.enabled = false; 24842 this.userHeight = 1.6; 24843 24844 this.getDevice = function () { 24845 24846 return device; 24847 24848 }; 24849 24850 this.setDevice = function ( value ) { 24851 24852 if ( value !== undefined ) device = value; 24853 24854 animation.setContext( value ); 24855 24856 }; 24857 24858 this.setPoseTarget = function ( object ) { 24859 24860 if ( object !== undefined ) poseTarget = object; 24861 24862 }; 24863 24864 this.getCamera = function ( camera ) { 24865 24866 if ( device === null ) return camera; 24867 24868 device.depthNear = camera.near; 24869 device.depthFar = camera.far; 24870 24871 device.getFrameData( frameData ); 24872 24873 // 24874 24875 var stageParameters = device.stageParameters; 24876 24877 if ( stageParameters ) { 24878 24879 standingMatrix.fromArray( stageParameters.sittingToStandingTransform ); 24880 24881 } else { 24882 24883 standingMatrix.makeTranslation( 0, scope.userHeight, 0 ); 24884 24885 } 24886 24887 24888 var pose = frameData.pose; 24889 var poseObject = poseTarget !== null ? poseTarget : camera; 24890 24891 // We want to manipulate poseObject by its position and quaternion components since users may rely on them. 24892 poseObject.matrix.copy( standingMatrix ); 24893 poseObject.matrix.decompose( poseObject.position, poseObject.quaternion, poseObject.scale ); 24894 24895 if ( pose.orientation !== null ) { 24896 24897 tempQuaternion.fromArray( pose.orientation ); 24898 poseObject.quaternion.multiply( tempQuaternion ); 24899 24900 } 24901 24902 if ( pose.position !== null ) { 24903 24904 tempQuaternion.setFromRotationMatrix( standingMatrix ); 24905 tempPosition.fromArray( pose.position ); 24906 tempPosition.applyQuaternion( tempQuaternion ); 24907 poseObject.position.add( tempPosition ); 24908 24909 } 24910 24911 poseObject.updateMatrixWorld(); 24912 24913 if ( device.isPresenting === false ) return camera; 24914 24915 // 24916 24917 cameraL.near = camera.near; 24918 cameraR.near = camera.near; 24919 24920 cameraL.far = camera.far; 24921 cameraR.far = camera.far; 24922 24923 cameraVR.matrixWorld.copy( camera.matrixWorld ); 24924 cameraVR.matrixWorldInverse.copy( camera.matrixWorldInverse ); 24925 24926 cameraL.matrixWorldInverse.fromArray( frameData.leftViewMatrix ); 24927 cameraR.matrixWorldInverse.fromArray( frameData.rightViewMatrix ); 24928 24929 // TODO (mrdoob) Double check this code 24930 24931 standingMatrixInverse.getInverse( standingMatrix ); 24932 24933 cameraL.matrixWorldInverse.multiply( standingMatrixInverse ); 24934 cameraR.matrixWorldInverse.multiply( standingMatrixInverse ); 24935 24936 var parent = poseObject.parent; 24937 24938 if ( parent !== null ) { 24939 24940 matrixWorldInverse.getInverse( parent.matrixWorld ); 24941 24942 cameraL.matrixWorldInverse.multiply( matrixWorldInverse ); 24943 cameraR.matrixWorldInverse.multiply( matrixWorldInverse ); 24944 24945 } 24946 24947 // envMap and Mirror needs camera.matrixWorld 24948 24949 cameraL.matrixWorld.getInverse( cameraL.matrixWorldInverse ); 24950 cameraR.matrixWorld.getInverse( cameraR.matrixWorldInverse ); 24951 24952 cameraL.projectionMatrix.fromArray( frameData.leftProjectionMatrix ); 24953 cameraR.projectionMatrix.fromArray( frameData.rightProjectionMatrix ); 24954 24955 // HACK (mrdoob) 24956 // https://github.com/w3c/webvr/issues/203 24957 24958 cameraVR.projectionMatrix.copy( cameraL.projectionMatrix ); 24959 24960 // 24961 24962 var layers = device.getLayers(); 24963 24964 if ( layers.length ) { 24965 24966 var layer = layers[ 0 ]; 24967 24968 if ( layer.leftBounds !== null && layer.leftBounds.length === 4 ) { 24969 24970 cameraL.bounds.fromArray( layer.leftBounds ); 24971 24972 } 24973 24974 if ( layer.rightBounds !== null && layer.rightBounds.length === 4 ) { 24975 24976 cameraR.bounds.fromArray( layer.rightBounds ); 24977 24978 } 24979 24980 } 24981 24982 return cameraVR; 24983 24984 }; 24985
24986 this.getStandingMatrix = function () { 24987 24988 return standingMatrix; 24989 24990 }; 24991 24992 this.isPresenting = isPresenting; 24993 24994 // Animation Loop 24995 24996 var animation = new WebGLAnimation(); 24997 24998 this.setAnimationLoop = function ( callback ) { 24999 25000 animation.setAnimationLoop( callback ); 25001 25002 }; 25003 25004 this.submitFrame = function () { 25005 25006 if ( isPresenting() ) device.submitFrame(); 25007 25008 }; 25009 25010 this.dispose = function () { 25011 25012 if ( typeof window !== 'undefined' ) { 25013 25014 window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange ); 25015 25016 } 25017 25018 }; 25019 25020 } 25021 25022 /** 25023 * @author mrdoob / http://mrdoob.com/ 25024 */ 25025 25026 function WebXRManager( renderer ) { 25027 25028 var gl = renderer.context; 25029 25030 var device = null; 25031 var session = null; 25032 25033 var frameOfRef = null; 25034 25035 var pose = null; 25036 25037 function isPresenting() { 25038 25039 return session !== null && frameOfRef !== null; 25040 25041 } 25042 25043 // 25044 25045 var cameraL = new PerspectiveCamera(); 25046 cameraL.layers.enable( 1 ); 25047 cameraL.viewport = new Vector4(); 25048 25049 var cameraR = new PerspectiveCamera(); 25050 cameraR.layers.enable( 2 ); 25051 cameraR.viewport = new Vector4(); 25052 25053 var cameraVR = new ArrayCamera( [ cameraL, cameraR ] ); 25054 cameraVR.layers.enable( 1 ); 25055 cameraVR.layers.enable( 2 ); 25056 25057 // 25058 25059 this.enabled = false; 25060 25061 this.getDevice = function () { 25062 25063 return device; 25064 25065 }; 25066 25067 this.setDevice = function ( value ) { 25068 25069 if ( value !== undefined ) device = value; 25070 25071 gl.setCompatibleXRDevice( value ); 25072 25073 }; 25074 25075 // 25076 25077 this.setSession = function ( value, options ) { 25078 25079 session = value; 25080 25081 if ( session !== null ) { 25082 25083 session.addEventListener( 'end', function () { 25084 25085 renderer.setFramebuffer( null ); 25086 animation.stop(); 25087 25088 } ); 25089 25090 session.baseLayer = new XRWebGLLayer( session, gl ); 25091 session.requestFrameOfReference( options.frameOfReferenceType ).then( function ( value ) { 25092 25093 frameOfRef = value; 25094 25095 renderer.setFramebuffer( session.baseLayer.framebuffer ); 25096 25097 animation.setContext( session ); 25098 animation.start(); 25099 25100 } ); 25101 25102 } 25103 25104 }; 25105 25106 function updateCamera( camera, parent ) { 25107 25108 if ( parent === null ) { 25109 25110 camera.matrixWorld.copy( camera.matrix ); 25111 25112 } else { 25113 25114 camera.matrixWorld.multiplyMatrices( parent.matrixWorld, camera.matrix ); 25115 25116 } 25117 25118 camera.matrixWorldInverse.getInverse( camera.matrixWorld ); 25119 25120 } 25121 25122 this.getCamera = function ( camera ) { 25123 25124 if ( isPresenting() ) { 25125 25126 var parent = camera.parent; 25127 var cameras = cameraVR.cameras; 25128 25129 // apply camera.parent to cameraVR 25130 25131 updateCamera( cameraVR, parent ); 25132 25133 for ( var i = 0; i < cameras.length; i ++ ) { 25134 25135 updateCamera( cameras[ i ], parent ); 25136 25137 } 25138 25139 // update camera and its children 25140 25141 camera.matrixWorld.copy( cameraVR.matrixWorld ); 25142 25143 var children = camera.children; 25144 25145 for ( var i = 0, l = children.length; i < l; i ++ ) { 25146 25147 children[ i ].updateMatrixWorld( true ); 25148 25149 } 25150 25151 return cameraVR; 25152 25153 } 25154 25155 return camera; 25156 25157 }; 25158 25159 this.isPresenting = isPresenting; 25160 25161 // Animation Loop 25162 25163 var onAnimationFrameCallback = null; 25164 25165 function onAnimationFrame( time, frame ) { 25166 25167 pose = frame.getDevicePose( frameOfRef ); 25168 25169 var layer = session.baseLayer; 25170 var views = frame.views; 25171 25172 for ( var i = 0; i < views.length; i ++ ) { 25173 25174 var view = views[ i ]; 25175 var viewport = layer.getViewport( view ); 25176 var viewMatrix = pose.getViewMatrix( view ); 25177 25178 var camera = cameraVR.cameras[ i ]; 25179 camera.matrix.fromArray( viewMatrix ).getInverse( camera.matrix ); 25180 camera.projectionMatrix.fromArray( view.projectionMatrix ); 25181 camera.viewport.set( viewport.x, viewport.y, viewport.width, viewport.height ); 25182 25183 if ( i === 0 ) { 25184 25185 cameraVR.matrix.copy( camera.matrix ); 25186 25187 // HACK (mrdoob) 25188 // https://github.com/w3c/webvr/issues/203 25189 25190 cameraVR.projectionMatrix.copy( camera.projectionMatrix ); 25191 25192 } 25193 25194 } 25195 25196 if ( onAnimationFrameCallback ) onAnimationFrameCallback(); 25197 25198 } 25199 25200 var animation = new WebGLAnimation(); 25201 animation.setAnimationLoop( onAnimationFrame ); 25202 25203 this.setAnimationLoop = function ( callback ) { 25204 25205 onAnimationFrameCallback = callback; 25206 25207 }; 25208 25209 // DEPRECATED 25210
vendor: 11,442 bytes, lines 25211-25704
25211 this.getStandingMatrix = function () { 25212 25213 console.warn( 'THREE.WebXRManager: getStandingMatrix() is no longer needed.' ); 25214 return new THREE.Matrix4(); 25215 25216 }; 25217 25218 this.submitFrame = function () {}; 25219 25220 } 25221 25222 /** 25223 * @author supereggbert / http://www.paulbrunt.co.uk/ 25224 * @author mrdoob / http://mrdoob.com/ 25225 * @author alteredq / http://alteredqualia.com/ 25226 * @author szimek / https://github.com/szimek/ 25227 * @author tschw 25228 */ 25229 25230 function WebGLRenderer( parameters ) { 25231 25232 console.log( 'THREE.WebGLRenderer', REVISION ); 25233 25234 parameters = parameters || {}; 25235 25236 var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElementNS( 'http://www.w3.org/1999/xhtml', 'canvas' ), 25237 _context = parameters.context !== undefined ? parameters.context : null, 25238 25239 _alpha = parameters.alpha !== undefined ? parameters.alpha : false, 25240 _depth = parameters.depth !== undefined ? parameters.depth : true, 25241 _stencil = parameters.stencil !== undefined ? parameters.stencil : true, 25242 _antialias = parameters.antialias !== undefined ? parameters.antialias : false, 25243 _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true, 25244 _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false, 25245 _powerPreference = parameters.powerPreference !== undefined ? parameters.powerPreference : 'default'; 25246 25247 var currentRenderList = null; 25248 var currentRenderState = null; 25249 25250 // public properties 25251 25252 this.domElement = _canvas; 25253 this.context = null; 25254 25255 // clearing 25256 25257 this.autoClear = true; 25258 this.autoClearColor = true; 25259 this.autoClearDepth = true; 25260 this.autoClearStencil = true; 25261 25262 // scene graph 25263 25264 this.sortObjects = true; 25265 25266 // user-defined clipping 25267 25268 this.clippingPlanes = []; 25269 this.localClippingEnabled = false; 25270 25271 // physically based shading 25272 25273 this.gammaFactor = 2.0; // for backwards compatibility 25274 this.gammaInput = false; 25275 this.gammaOutput = false; 25276 25277 // physical lights 25278 25279 this.physicallyCorrectLights = false; 25280 25281 // tone mapping 25282 25283 this.toneMapping = LinearToneMapping; 25284 this.toneMappingExposure = 1.0; 25285 this.toneMappingWhitePoint = 1.0; 25286 25287 // morphs 25288 25289 this.maxMorphTargets = 8; 25290 this.maxMorphNormals = 4; 25291 25292 // internal properties 25293 25294 var _this = this, 25295 25296 _isContextLost = false, 25297 25298 // internal state cache 25299 25300 _framebuffer = null, 25301 25302 _currentRenderTarget = null, 25303 _currentFramebuffer = null, 25304 _currentMaterialId = - 1, 25305 _currentGeometryProgram = '', 25306 25307 _currentCamera = null, 25308 _currentArrayCamera = null, 25309 25310 _currentViewport = new Vector4(), 25311 _currentScissor = new Vector4(), 25312 _currentScissorTest = null, 25313 25314 // 25315 25316 _usedTextureUnits = 0, 25317 25318 // 25319 25320 _width = _canvas.width, 25321 _height = _canvas.height, 25322 25323 _pixelRatio = 1, 25324 25325 _viewport = new Vector4( 0, 0, _width, _height ), 25326 _scissor = new Vector4( 0, 0, _width, _height ), 25327 _scissorTest = false, 25328 25329 // frustum 25330 25331 _frustum = new Frustum(), 25332 25333 // clipping 25334 25335 _clipping = new WebGLClipping(), 25336 _clippingEnabled = false, 25337 _localClippingEnabled = false, 25338 25339 // camera matrices cache 25340 25341 _projScreenMatrix = new Matrix4(), 25342 25343 _vector3 = new Vector3(); 25344 25345 function getTargetPixelRatio() { 25346 25347 return _currentRenderTarget === null ? _pixelRatio : 1; 25348 25349 } 25350 25351 // initialize 25352 25353 var _gl; 25354 25355 try { 25356 25357 var contextAttributes = { 25358 alpha: _alpha, 25359 depth: _depth, 25360 stencil: _stencil, 25361 antialias: _antialias, 25362 premultipliedAlpha: _premultipliedAlpha, 25363 preserveDrawingBuffer: _preserveDrawingBuffer, 25364 powerPreference: _powerPreference 25365 }; 25366 25367 // event listeners must be registered before WebGL context is created, see #12753 25368 25369 _canvas.addEventListener( 'webglcontextlost', onContextLost, false ); 25370 _canvas.addEventListener( 'webglcontextrestored', onContextRestore, false ); 25371 25372 _gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes ); 25373 25374 if ( _gl === null ) { 25375 25376 if ( _canvas.getContext( 'webgl' ) !== null ) { 25377 25378 throw new Error( 'Error creating WebGL context with your selected attributes.' ); 25379 25380 } else { 25381 25382 throw new Error( 'Error creating WebGL context.' ); 25383 25384 } 25385 25386 } 25387 25388 // Some experimental-webgl implementations do not have getShaderPrecisionFormat 25389 25390 if ( _gl.getShaderPrecisionFormat === undefined ) { 25391 25392 _gl.getShaderPrecisionFormat = function () { 25393 25394 return { 'rangeMin': 1, 'rangeMax': 1, 'precision': 1 }; 25395 25396 }; 25397 25398 } 25399 25400 } catch ( error ) { 25401 25402 console.error( 'THREE.WebGLRenderer: ' + error.message ); 25403 25404 } 25405 25406 var extensions, capabilities, state, info; 25407 var properties, textures, attributes, geometries, objects; 25408 var programCache, renderLists, renderStates; 25409 25410 var background, morphtargets, bufferRenderer, indexedBufferRenderer; 25411 var spriteRenderer; 25412 25413 var utils; 25414 25415 function initGLContext() { 25416 25417 extensions = new WebGLExtensions( _gl ); 25418 extensions.get( 'WEBGL_depth_texture' ); 25419 extensions.get( 'OES_texture_float' ); 25420 extensions.get( 'OES_texture_float_linear' ); 25421 extensions.get( 'OES_texture_half_float' ); 25422 extensions.get( 'OES_texture_half_float_linear' ); 25423 extensions.get( 'OES_standard_derivatives' ); 25424 extensions.get( 'OES_element_index_uint' ); 25425 extensions.get( 'ANGLE_instanced_arrays' ); 25426 25427 utils = new WebGLUtils( _gl, extensions ); 25428 25429 capabilities = new WebGLCapabilities( _gl, extensions, parameters ); 25430 25431 state = new WebGLState( _gl, extensions, utils ); 25432 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); 25433 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); 25434 25435 info = new WebGLInfo( _gl ); 25436 properties = new WebGLProperties(); 25437 textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); 25438 attributes = new WebGLAttributes( _gl ); 25439 geometries = new WebGLGeometries( _gl, attributes, info ); 25440 objects = new WebGLObjects( geometries, info ); 25441 morphtargets = new WebGLMorphtargets( _gl ); 25442 programCache = new WebGLPrograms( _this, extensions, capabilities ); 25443 renderLists = new WebGLRenderLists(); 25444 renderStates = new WebGLRenderStates(); 25445 25446 background = new WebGLBackground( _this, state, objects, _premultipliedAlpha ); 25447 25448 bufferRenderer = new WebGLBufferRenderer( _gl, extensions, info ); 25449 indexedBufferRenderer = new WebGLIndexedBufferRenderer( _gl, extensions, info ); 25450 25451 spriteRenderer = new WebGLSpriteRenderer( _this, _gl, state, textures, capabilities ); 25452 25453 info.programs = programCache.programs; 25454 25455 _this.context = _gl; 25456 _this.capabilities = capabilities; 25457 _this.extensions = extensions; 25458 _this.properties = properties; 25459 _this.renderLists = renderLists; 25460 _this.state = state; 25461 _this.info = info; 25462 25463 } 25464 25465 initGLContext(); 25466 25467 // vr 25468 25469 var vr = ( 'xr' in navigator ) ? new WebXRManager( _this ) : new WebVRManager( _this ); 25470 25471 this.vr = vr; 25472 25473 // shadow map 25474 25475 var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize ); 25476 25477 this.shadowMap = shadowMap; 25478 25479 // API 25480 25481 this.getContext = function () { 25482 25483 return _gl; 25484 25485 }; 25486 25487 this.getContextAttributes = function () { 25488 25489 return _gl.getContextAttributes(); 25490 25491 }; 25492 25493 this.forceContextLoss = function () { 25494 25495 var extension = extensions.get( 'WEBGL_lose_context' ); 25496 if ( extension ) extension.loseContext(); 25497 25498 }; 25499 25500 this.forceContextRestore = function () { 25501 25502 var extension = extensions.get( 'WEBGL_lose_context' ); 25503 if ( extension ) extension.restoreContext(); 25504 25505 }; 25506 25507 this.getPixelRatio = function () { 25508 25509 return _pixelRatio; 25510 25511 }; 25512 25513 this.setPixelRatio = function ( value ) { 25514 25515 if ( value === undefined ) return; 25516 25517 _pixelRatio = value; 25518 25519 this.setSize( _width, _height, false ); 25520 25521 }; 25522 25523 this.getSize = function () { 25524 25525 return { 25526 width: _width, 25527 height: _height 25528 }; 25529 25530 }; 25531 25532 this.setSize = function ( width, height, updateStyle ) { 25533 25534 if ( vr.isPresenting() ) { 25535 25536 console.warn( 'THREE.WebGLRenderer: Can\'t change size while VR device is presenting.' ); 25537 return; 25538 25539 } 25540 25541 _width = width; 25542 _height = height; 25543 25544 _canvas.width = width * _pixelRatio; 25545 _canvas.height = height * _pixelRatio; 25546 25547 if ( updateStyle !== false ) { 25548 25549 _canvas.style.width = width + 'px'; 25550 _canvas.style.height = height + 'px'; 25551 25552 } 25553 25554 this.setViewport( 0, 0, width, height ); 25555 25556 }; 25557 25558 this.getDrawingBufferSize = function () { 25559 25560 return { 25561 width: _width * _pixelRatio, 25562 height: _height * _pixelRatio 25563 }; 25564 25565 }; 25566 25567 this.setDrawingBufferSize = function ( width, height, pixelRatio ) { 25568 25569 _width = width; 25570 _height = height; 25571 25572 _pixelRatio = pixelRatio; 25573 25574 _canvas.width = width * pixelRatio; 25575 _canvas.height = height * pixelRatio; 25576 25577 this.setViewport( 0, 0, width, height ); 25578 25579 }; 25580 25581 this.getCurrentViewport = function () { 25582 25583 return _currentViewport; 25584 25585 }; 25586 25587 this.setViewport = function ( x, y, width, height ) { 25588 25589 _viewport.set( x, _height - y - height, width, height ); 25590 state.viewport( _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ) ); 25591 25592 }; 25593 25594 this.setScissor = function ( x, y, width, height ) { 25595 25596 _scissor.set( x, _height - y - height, width, height ); 25597 state.scissor( _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ) ); 25598 25599 }; 25600 25601 this.setScissorTest = function ( boolean ) { 25602 25603 state.setScissorTest( _scissorTest = boolean ); 25604 25605 }; 25606 25607 // Clearing 25608 25609 this.getClearColor = function () { 25610 25611 return background.getClearColor(); 25612 25613 }; 25614 25615 this.setClearColor = function () { 25616 25617 background.setClearColor.apply( background, arguments ); 25618 25619 }; 25620 25621 this.getClearAlpha = function () { 25622 25623 return background.getClearAlpha(); 25624 25625 }; 25626 25627 this.setClearAlpha = function () { 25628 25629 background.setClearAlpha.apply( background, arguments ); 25630 25631 }; 25632 25633 this.clear = function ( color, depth, stencil ) { 25634 25635 var bits = 0; 25636 25637 if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT; 25638 if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT; 25639 if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT; 25640 25641 _gl.clear( bits ); 25642 25643 }; 25644 25645 this.clearColor = function () { 25646 25647 this.clear( true, false, false ); 25648 25649 }; 25650 25651 this.clearDepth = function () { 25652 25653 this.clear( false, true, false ); 25654 25655 }; 25656 25657 this.clearStencil = function () { 25658 25659 this.clear( false, false, true ); 25660 25661 }; 25662 25663 this.clearTarget = function ( renderTarget, color, depth, stencil ) { 25664 25665 this.setRenderTarget( renderTarget ); 25666 this.clear( color, depth, stencil ); 25667 25668 }; 25669 25670 // 25671 25672 this.dispose = function () { 25673 25674 _canvas.removeEventListener( 'webglcontextlost', onContextLost, false ); 25675 _canvas.removeEventListener( 'webglcontextrestored', onContextRestore, false ); 25676 25677 renderLists.dispose(); 25678 renderStates.dispose(); 25679 properties.dispose(); 25680 objects.dispose(); 25681 25682 vr.dispose(); 25683 25684 animation.stop(); 25685 25686 }; 25687 25688 // Events 25689 25690 function onContextLost( event ) { 25691 25692 event.preventDefault(); 25693 25694 console.log( 'THREE.WebGLRenderer: Context Lost.' ); 25695 25696 _isContextLost = true; 25697 25698 } 25699 25700 function onContextRestore( /* event */ ) { 25701 25702 console.log( 'THREE.WebGLRenderer: Context Restored.' ); 25703 25704 _isContextLost = false;
25705 25706 initGLContext(); 25707 25708 } 25709 25710 function onMaterialDispose( event ) { 25711 25712 var material = event.target; 25713 25714 material.removeEventListener( 'dispose', onMaterialDispose ); 25715 25716 deallocateMaterial( material ); 25717 25718 } 25719 25720 // Buffer deallocation 25721 25722 function deallocateMaterial( material ) { 25723 25724 releaseMaterialProgramReference( material ); 25725 25726 properties.remove( material ); 25727 25728 } 25729 25730 25731 function releaseMaterialProgramReference( material ) { 25732 25733 var programInfo = properties.get( material ).program; 25734 25735 material.program = undefined; 25736 25737 if ( programInfo !== undefined ) { 25738 25739 programCache.releaseProgram( programInfo ); 25740 25741 } 25742 25743 } 25744 25745 // Buffer rendering 25746 25747 function renderObjectImmediate( object, program, material ) { 25748 25749 object.render( function ( object ) { 25750 25751 _this.renderBufferImmediate( object, program, material ); 25752 25753 } ); 25754 25755 } 25756 25757 this.renderBufferImmediate = function ( object, program, material ) { 25758 25759 state.initAttributes(); 25760 25761 var buffers = properties.get( object ); 25762 25763 if ( object.hasPositions && ! buffers.position ) buffers.position = _gl.createBuffer(); 25764 if ( object.hasNormals && ! buffers.normal ) buffers.normal = _gl.createBuffer(); 25765 if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer(); 25766 if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer(); 25767 25768 var programAttributes = program.getAttributes(); 25769 25770 if ( object.hasPositions ) { 25771 25772 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position ); 25773 _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW ); 25774 25775 state.enableAttribute( programAttributes.position ); 25776 _gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 ); 25777 25778 } 25779 25780 if ( object.hasNormals ) { 25781 25782 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.normal ); 25783 25784 if ( ! material.isMeshPhongMaterial && 25785 ! material.isMeshStandardMaterial && 25786 ! material.isMeshNormalMaterial && 25787 material.flatShading === true ) { 25788 25789 for ( var i = 0, l = object.count * 3; i < l; i += 9 ) { 25790 25791 var array = object.normalArray; 25792 25793 var nx = ( array[ i + 0 ] + array[ i + 3 ] + array[ i + 6 ] ) / 3; 25794 var ny = ( array[ i + 1 ] + array[ i + 4 ] + array[ i + 7 ] ) / 3; 25795 var nz = ( array[ i + 2 ] + array[ i + 5 ] + array[ i + 8 ] ) / 3; 25796 25797 array[ i + 0 ] = nx; 25798 array[ i + 1 ] = ny; 25799 array[ i + 2 ] = nz; 25800 25801 array[ i + 3 ] = nx; 25802 array[ i + 4 ] = ny; 25803 array[ i + 5 ] = nz; 25804 25805 array[ i + 6 ] = nx; 25806 array[ i + 7 ] = ny; 25807 array[ i + 8 ] = nz; 25808 25809 } 25810 25811 } 25812 25813 _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW ); 25814 25815 state.enableAttribute( programAttributes.normal ); 25816 25817 _gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 ); 25818 25819 } 25820 25821 if ( object.hasUvs && material.map ) { 25822 25823 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv ); 25824 _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW ); 25825 25826 state.enableAttribute( programAttributes.uv ); 25827 25828 _gl.vertexAttribPointer( programAttributes.uv, 2, _gl.FLOAT, false, 0, 0 ); 25829 25830 } 25831 25832 if ( object.hasColors && material.vertexColors !== NoColors ) { 25833 25834 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color ); 25835 _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW ); 25836 25837 state.enableAttribute( programAttributes.color ); 25838 25839 _gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 ); 25840 25841 } 25842 25843 state.disableUnusedAttributes(); 25844 25845 _gl.drawArrays( _gl.TRIANGLES, 0, object.count ); 25846 25847 object.count = 0; 25848 25849 }; 25850 25851 this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) { 25852 25853 var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); 25854 25855 state.setMaterial( material, frontFaceCW ); 25856 25857 var program = setProgram( camera, fog, material, object ); 25858 var geometryProgram = geometry.id + '_' + program.id + '_' + ( material.wireframe === true ); 25859 25860 var updateBuffers = false; 25861 25862 if ( geometryProgram !== _currentGeometryProgram ) { 25863 25864 _currentGeometryProgram = geometryProgram; 25865 updateBuffers = true; 25866 25867 } 25868 25869 if ( object.morphTargetInfluences ) { 25870 25871 morphtargets.update( object, geometry, material, program ); 25872 25873 updateBuffers = true; 25874 25875 } 25876 25877 // 25878 25879 var index = geometry.index; 25880 var position = geometry.attributes.position; 25881 var rangeFactor = 1; 25882 25883 if ( material.wireframe === true ) { 25884 25885 index = geometries.getWireframeAttribute( geometry ); 25886 rangeFactor = 2; 25887 25888 } 25889 25890 var attribute; 25891 var renderer = bufferRenderer; 25892 25893 if ( index !== null ) { 25894 25895 attribute = attributes.get( index ); 25896 25897 renderer = indexedBufferRenderer; 25898 renderer.setIndex( attribute ); 25899 25900 } 25901 25902 if ( updateBuffers ) { 25903 25904 setupVertexAttributes( material, program, geometry ); 25905 25906 if ( index !== null ) { 25907 25908 _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attribute.buffer ); 25909 25910 } 25911 25912 } 25913 25914 // 25915 25916 var dataCount = Infinity; 25917 25918 if ( index !== null ) { 25919 25920 dataCount = index.count; 25921 25922 } else if ( position !== undefined ) { 25923 25924 dataCount = position.count; 25925 25926 } 25927 25928 var rangeStart = geometry.drawRange.start * rangeFactor; 25929 var rangeCount = geometry.drawRange.count * rangeFactor; 25930 25931 var groupStart = group !== null ? group.start * rangeFactor : 0; 25932 var groupCount = group !== null ? group.count * rangeFactor : Infinity; 25933 25934 var drawStart = Math.max( rangeStart, groupStart ); 25935 var drawEnd = Math.min( dataCount, rangeStart + rangeCount, groupStart + groupCount ) - 1; 25936 25937 var drawCount = Math.max( 0, drawEnd - drawStart + 1 ); 25938 25939 if ( drawCount === 0 ) return; 25940 25941 // 25942 25943 if ( object.isMesh ) { 25944 25945 if ( material.wireframe === true ) { 25946 25947 state.setLineWidth( material.wireframeLinewidth * getTargetPixelRatio() ); 25948 renderer.setMode( _gl.LINES ); 25949 25950 } else { 25951
vendor: 4,537 bytes, lines 25952-26148
25952 switch ( object.drawMode ) { 25953 25954 case TrianglesDrawMode: 25955 renderer.setMode( _gl.TRIANGLES ); 25956 break; 25957 25958 case TriangleStripDrawMode: 25959 renderer.setMode( _gl.TRIANGLE_STRIP ); 25960 break; 25961 25962 case TriangleFanDrawMode: 25963 renderer.setMode( _gl.TRIANGLE_FAN ); 25964 break; 25965 25966 } 25967 25968 } 25969 25970 25971 } else if ( object.isLine ) { 25972 25973 var lineWidth = material.linewidth; 25974 25975 if ( lineWidth === undefined ) lineWidth = 1; // Not using Line*Material 25976 25977 state.setLineWidth( lineWidth * getTargetPixelRatio() ); 25978 25979 if ( object.isLineSegments ) { 25980 25981 renderer.setMode( _gl.LINES ); 25982 25983 } else if ( object.isLineLoop ) { 25984 25985 renderer.setMode( _gl.LINE_LOOP ); 25986 25987 } else { 25988 25989 renderer.setMode( _gl.LINE_STRIP ); 25990 25991 } 25992 25993 } else if ( object.isPoints ) { 25994 25995 renderer.setMode( _gl.POINTS ); 25996 25997 } 25998 25999 if ( geometry && geometry.isInstancedBufferGeometry ) { 26000 26001 if ( geometry.maxInstancedCount > 0 ) { 26002 26003 renderer.renderInstances( geometry, drawStart, drawCount ); 26004 26005 } 26006 26007 } else { 26008 26009 renderer.render( drawStart, drawCount ); 26010 26011 } 26012 26013 }; 26014 26015 function setupVertexAttributes( material, program, geometry ) { 26016 26017 if ( geometry && geometry.isInstancedBufferGeometry ) { 26018 26019 if ( extensions.get( 'ANGLE_instanced_arrays' ) === null ) { 26020 26021 console.error( 'THREE.WebGLRenderer.setupVertexAttributes: using THREE.InstancedBufferGeometry but hardware does not support extension ANGLE_instanced_arrays.' ); 26022 return; 26023 26024 } 26025 26026 } 26027 26028 state.initAttributes(); 26029 26030 var geometryAttributes = geometry.attributes; 26031 26032 var programAttributes = program.getAttributes(); 26033 26034 var materialDefaultAttributeValues = material.defaultAttributeValues; 26035 26036 for ( var name in programAttributes ) { 26037 26038 var programAttribute = programAttributes[ name ]; 26039 26040 if ( programAttribute >= 0 ) { 26041 26042 var geometryAttribute = geometryAttributes[ name ]; 26043 26044 if ( geometryAttribute !== undefined ) { 26045 26046 var normalized = geometryAttribute.normalized; 26047 var size = geometryAttribute.itemSize; 26048 26049 var attribute = attributes.get( geometryAttribute ); 26050 26051 // TODO Attribute may not be available on context restore 26052 26053 if ( attribute === undefined ) continue; 26054 26055 var buffer = attribute.buffer; 26056 var type = attribute.type; 26057 var bytesPerElement = attribute.bytesPerElement; 26058 26059 if ( geometryAttribute.isInterleavedBufferAttribute ) { 26060 26061 var data = geometryAttribute.data; 26062 var stride = data.stride; 26063 var offset = geometryAttribute.offset; 26064 26065 if ( data && data.isInstancedInterleavedBuffer ) { 26066 26067 state.enableAttributeAndDivisor( programAttribute, data.meshPerAttribute ); 26068 26069 if ( geometry.maxInstancedCount === undefined ) { 26070 26071 geometry.maxInstancedCount = data.meshPerAttribute * data.count; 26072 26073 } 26074 26075 } else { 26076 26077 state.enableAttribute( programAttribute ); 26078 26079 } 26080 26081 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); 26082 _gl.vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement ); 26083 26084 } else { 26085 26086 if ( geometryAttribute.isInstancedBufferAttribute ) { 26087 26088 state.enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute ); 26089 26090 if ( geometry.maxInstancedCount === undefined ) { 26091 26092 geometry.maxInstancedCount = geometryAttribute.meshPerAttribute * geometryAttribute.count; 26093 26094 } 26095 26096 } else { 26097 26098 state.enableAttribute( programAttribute ); 26099 26100 } 26101 26102 _gl.bindBuffer( _gl.ARRAY_BUFFER, buffer ); 26103 _gl.vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 ); 26104 26105 } 26106 26107 } else if ( materialDefaultAttributeValues !== undefined ) { 26108 26109 var value = materialDefaultAttributeValues[ name ]; 26110 26111 if ( value !== undefined ) { 26112 26113 switch ( value.length ) { 26114 26115 case 2: 26116 _gl.vertexAttrib2fv( programAttribute, value ); 26117 break; 26118 26119 case 3: 26120 _gl.vertexAttrib3fv( programAttribute, value ); 26121 break; 26122 26123 case 4: 26124 _gl.vertexAttrib4fv( programAttribute, value ); 26125 break; 26126 26127 default: 26128 _gl.vertexAttrib1fv( programAttribute, value ); 26129 26130 } 26131 26132 } 26133 26134 } 26135 26136 } 26137 26138 } 26139 26140 state.disableUnusedAttributes(); 26141 26142 } 26143 26144 // Compile 26145 26146 this.compile = function ( scene, camera ) { 26147 26148 currentRenderState = renderStates.get( scene, camera );
26149 currentRenderState.init(); 26150 26151 scene.traverse( function ( object ) { 26152 26153 if ( object.isLight ) { 26154 26155 currentRenderState.pushLight( object ); 26156 26157 if ( object.castShadow ) { 26158 26159 currentRenderState.pushShadow( object ); 26160 26161 } 26162 26163 } 26164 26165 } ); 26166 26167 currentRenderState.setupLights( camera ); 26168 26169 scene.traverse( function ( object ) { 26170 26171 if ( object.material ) { 26172 26173 if ( Array.isArray( object.material ) ) { 26174 26175 for ( var i = 0; i < object.material.length; i ++ ) { 26176 26177 initMaterial( object.material[ i ], scene.fog, object ); 26178 26179 } 26180 26181 } else { 26182 26183 initMaterial( object.material, scene.fog, object ); 26184 26185 } 26186 26187 } 26188 26189 } ); 26190 26191 }; 26192 26193 // Animation Loop 26194 26195 var onAnimationFrameCallback = null; 26196 26197 function onAnimationFrame() { 26198 26199 if ( vr.isPresenting() ) return; 26200 if ( onAnimationFrameCallback ) onAnimationFrameCallback(); 26201 26202 } 26203 26204 var animation = new WebGLAnimation(); 26205 animation.setAnimationLoop( onAnimationFrame ); 26206 animation.setContext( window ); 26207 26208 this.setAnimationLoop = function ( callback ) { 26209 26210 onAnimationFrameCallback = callback; 26211 vr.setAnimationLoop( callback ); 26212 26213 animation.start(); 26214 26215 }; 26216 26217 // Rendering 26218 26219 this.render = function ( scene, camera, renderTarget, forceClear ) { 26220 26221 if ( ! ( camera && camera.isCamera ) ) { 26222 26223 console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' ); 26224 return; 26225 26226 } 26227 26228 if ( _isContextLost ) return; 26229 26230 // reset caching for this frame 26231 26232 _currentGeometryProgram = ''; 26233 _currentMaterialId = - 1; 26234 _currentCamera = null; 26235 26236 // update scene graph 26237 26238 if ( scene.autoUpdate === true ) scene.updateMatrixWorld(); 26239 26240 // update camera matrices and frustum 26241 26242 if ( camera.parent === null ) camera.updateMatrixWorld(); 26243 26244 if ( vr.enabled ) { 26245 26246 camera = vr.getCamera( camera ); 26247 26248 } 26249 26250 // 26251 26252 currentRenderState = renderStates.get( scene, camera ); 26253 currentRenderState.init(); 26254 26255 scene.onBeforeRender( _this, scene, camera, renderTarget ); 26256 26257 _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); 26258 _frustum.setFromMatrix( _projScreenMatrix ); 26259 26260 _localClippingEnabled = this.localClippingEnabled; 26261 _clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera ); 26262 26263 currentRenderList = renderLists.get( scene, camera ); 26264 currentRenderList.init(); 26265 26266 projectObject( scene, camera, _this.sortObjects ); 26267 26268 if ( _this.sortObjects === true ) { 26269 26270 currentRenderList.sort(); 26271 26272 } 26273 26274 // 26275 26276 if ( _clippingEnabled ) _clipping.beginShadows(); 26277 26278 var shadowsArray = currentRenderState.state.shadowsArray; 26279 26280 shadowMap.render( shadowsArray, scene, camera ); 26281 26282 currentRenderState.setupLights( camera ); 26283 26284 if ( _clippingEnabled ) _clipping.endShadows(); 26285 26286 // 26287 26288 if ( this.info.autoReset ) this.info.reset(); 26289 26290 if ( renderTarget === undefined ) { 26291 26292 renderTarget = null; 26293 26294 } 26295 26296 this.setRenderTarget( renderTarget ); 26297 26298 // 26299 26300 background.render( currentRenderList, scene, camera, forceClear ); 26301 26302 // render scene 26303 26304 var opaqueObjects = currentRenderList.opaque; 26305 var transparentObjects = currentRenderList.transparent; 26306 26307 if ( scene.overrideMaterial ) { 26308 26309 var overrideMaterial = scene.overrideMaterial; 26310 26311 if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera, overrideMaterial ); 26312 if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera, overrideMaterial ); 26313 26314 } else { 26315 26316 // opaque pass (front-to-back order) 26317 26318 if ( opaqueObjects.length ) renderObjects( opaqueObjects, scene, camera ); 26319 26320 // transparent pass (back-to-front order) 26321 26322 if ( transparentObjects.length ) renderObjects( transparentObjects, scene, camera ); 26323 26324 } 26325 26326 // custom renderers 26327 26328 var spritesArray = currentRenderState.state.spritesArray; 26329 26330 spriteRenderer.render( spritesArray, scene, camera ); 26331 26332 // Generate mipmap if we're using any kind of mipmap filtering 26333 26334 if ( renderTarget ) { 26335 26336 textures.updateRenderTargetMipmap( renderTarget ); 26337 26338 } 26339 26340 // Ensure depth buffer writing is enabled so it can be cleared on next render 26341 26342 state.buffers.depth.setTest( true ); 26343 state.buffers.depth.setMask( true ); 26344 state.buffers.color.setMask( true ); 26345 26346 state.setPolygonOffset( false ); 26347 26348 scene.onAfterRender( _this, scene, camera ); 26349 26350 if ( vr.enabled ) { 26351 26352 vr.submitFrame(); 26353 26354 } 26355 26356 // _gl.finish(); 26357 26358 currentRenderList = null; 26359 currentRenderState = null; 26360 26361 }; 26362 26363 /* 26364 // TODO Duplicated code (Frustum) 26365 26366 var _sphere = new Sphere(); 26367 26368 function isObjectViewable( object ) { 26369 26370 var geometry = object.geometry; 26371 26372 if ( geometry.boundingSphere === null ) 26373 geometry.computeBoundingSphere(); 26374 26375 _sphere.copy( geometry.boundingSphere ). 26376 applyMatrix4( object.matrixWorld ); 26377 26378 return isSphereViewable( _sphere ); 26379 26380 } 26381 26382 function isSpriteViewable( sprite ) { 26383 26384 _sphere.center.set( 0, 0, 0 ); 26385 _sphere.radius = 0.7071067811865476; 26386 _sphere.applyMatrix4( sprite.matrixWorld ); 26387 26388 return isSphereViewable( _sphere ); 26389 26390 } 26391 26392 function isSphereViewable( sphere ) { 26393 26394 if ( ! _frustum.intersectsSphere( sphere ) ) return false;
26395 26396 var numPlanes = _clipping.numPlanes; 26397 26398 if ( numPlanes === 0 ) return true; 26399 26400 var planes = _this.clippingPlanes, 26401 26402 center = sphere.center, 26403 negRad = - sphere.radius, 26404 i = 0; 26405 26406 do { 26407 26408 // out when deeper than radius in the negative halfspace 26409 if ( planes[ i ].distanceToPoint( center ) < negRad ) return false; 26410 26411 } while ( ++ i !== numPlanes ); 26412 26413 return true; 26414 26415 } 26416 */ 26417 26418 function projectObject( object, camera, sortObjects ) { 26419 26420 if ( object.visible === false ) return; 26421 26422 var visible = object.layers.test( camera.layers ); 26423 26424 if ( visible ) { 26425 26426 if ( object.isLight ) { 26427 26428 currentRenderState.pushLight( object ); 26429 26430 if ( object.castShadow ) { 26431 26432 currentRenderState.pushShadow( object ); 26433 26434 } 26435 26436 } else if ( object.isSprite ) { 26437 26438 if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { 26439 26440 currentRenderState.pushSprite( object ); 26441 26442 } 26443 26444 } else if ( object.isImmediateRenderObject ) { 26445 26446 if ( sortObjects ) { 26447 26448 _vector3.setFromMatrixPosition( object.matrixWorld ) 26449 .applyMatrix4( _projScreenMatrix ); 26450 26451 } 26452 26453 currentRenderList.push( object, null, object.material, _vector3.z, null ); 26454 26455 } else if ( object.isMesh || object.isLine || object.isPoints ) { 26456 26457 if ( object.isSkinnedMesh ) { 26458 26459 object.skeleton.update(); 26460 26461 } 26462 26463 if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { 26464 26465 if ( sortObjects ) { 26466 26467 _vector3.setFromMatrixPosition( object.matrixWorld ) 26468 .applyMatrix4( _projScreenMatrix ); 26469 26470 } 26471 26472 var geometry = objects.update( object ); 26473 var material = object.material; 26474 26475 if ( Array.isArray( material ) ) { 26476 26477 var groups = geometry.groups; 26478 26479 for ( var i = 0, l = groups.length; i < l; i ++ ) { 26480 26481 var group = groups[ i ]; 26482 var groupMaterial = material[ group.materialIndex ]; 26483 26484 if ( groupMaterial && groupMaterial.visible ) { 26485 26486 currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group ); 26487 26488 } 26489 26490 } 26491 26492 } else if ( material.visible ) { 26493 26494 currentRenderList.push( object, geometry, material, _vector3.z, null ); 26495 26496 } 26497 26498 } 26499 26500 } 26501 26502 } 26503 26504 var children = object.children; 26505 26506 for ( var i = 0, l = children.length; i < l; i ++ ) { 26507 26508 projectObject( children[ i ], camera, sortObjects ); 26509 26510 } 26511 26512 } 26513 26514 function renderObjects( renderList, scene, camera, overrideMaterial ) { 26515 26516 for ( var i = 0, l = renderList.length; i < l; i ++ ) { 26517 26518 var renderItem = renderList[ i ]; 26519 26520 var object = renderItem.object; 26521 var geometry = renderItem.geometry; 26522 var material = overrideMaterial === undefined ? renderItem.material : overrideMaterial; 26523 var group = renderItem.group; 26524 26525 if ( camera.isArrayCamera ) { 26526 26527 _currentArrayCamera = camera; 26528 26529 var cameras = camera.cameras; 26530 26531 for ( var j = 0, jl = cameras.length; j < jl; j ++ ) { 26532 26533 var camera2 = cameras[ j ]; 26534 26535 if ( object.layers.test( camera2.layers ) ) { 26536 26537 if ( 'viewport' in camera2 ) { // XR 26538 26539 state.viewport( _currentViewport.copy( camera2.viewport ) ); 26540 26541 } else { 26542 26543 var bounds = camera2.bounds; 26544 26545 var x = bounds.x * _width; 26546 var y = bounds.y * _height; 26547 var width = bounds.z * _width; 26548 var height = bounds.w * _height; 26549 26550 state.viewport( _currentViewport.set( x, y, width, height ).multiplyScalar( _pixelRatio ) ); 26551 26552 } 26553 26554 renderObject( object, scene, camera2, geometry, material, group ); 26555 26556 } 26557 26558 } 26559 26560 } else { 26561 26562 _currentArrayCamera = null; 26563 26564 renderObject( object, scene, camera, geometry, material, group ); 26565 26566 } 26567 26568 } 26569 26570 } 26571 26572 function renderObject( object, scene, camera, geometry, material, group ) { 26573 26574 object.onBeforeRender( _this, scene, camera, geometry, material, group ); 26575 currentRenderState = renderStates.get( scene, _currentArrayCamera || camera ); 26576 26577 object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); 26578 object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); 26579 26580 if ( object.isImmediateRenderObject ) { 26581 26582 var frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); 26583 26584 state.setMaterial( material, frontFaceCW ); 26585 26586 var program = setProgram( camera, scene.fog, material, object ); 26587 26588 _currentGeometryProgram = ''; 26589
26590 renderObjectImmediate( object, program, material ); 26591 26592 } else { 26593 26594 _this.renderBufferDirect( camera, scene.fog, geometry, material, object, group ); 26595 26596 } 26597 26598 object.onAfterRender( _this, scene, camera, geometry, material, group ); 26599 currentRenderState = renderStates.get( scene, _currentArrayCamera || camera ); 26600 26601 } 26602 26603 function initMaterial( material, fog, object ) { 26604 26605 var materialProperties = properties.get( material ); 26606 26607 var lights = currentRenderState.state.lights; 26608 var shadowsArray = currentRenderState.state.shadowsArray; 26609 26610 var parameters = programCache.getParameters( 26611 material, lights.state, shadowsArray, fog, _clipping.numPlanes, _clipping.numIntersection, object ); 26612 26613 var code = programCache.getProgramCode( material, parameters ); 26614 26615 var program = materialProperties.program; 26616 var programChange = true; 26617 26618 if ( program === undefined ) { 26619 26620 // new material 26621 material.addEventListener( 'dispose', onMaterialDispose ); 26622 26623 } else if ( program.code !== code ) { 26624 26625 // changed glsl or parameters 26626 releaseMaterialProgramReference( material ); 26627 26628 } else if ( materialProperties.lightsHash !== lights.state.hash ) { 26629 26630 properties.update( material, 'lightsHash', lights.state.hash ); 26631 programChange = false; 26632 26633 } else if ( parameters.shaderID !== undefined ) { 26634 26635 // same glsl and uniform list 26636 return; 26637 26638 } else { 26639 26640 // only rebuild uniform list 26641 programChange = false; 26642 26643 } 26644 26645 if ( programChange ) { 26646 26647 if ( parameters.shaderID ) { 26648 26649 var shader = ShaderLib[ parameters.shaderID ]; 26650 26651 materialProperties.shader = { 26652 name: material.type, 26653 uniforms: UniformsUtils.clone( shader.uniforms ), 26654 vertexShader: shader.vertexShader, 26655 fragmentShader: shader.fragmentShader 26656 }; 26657 26658 } else { 26659 26660 materialProperties.shader = { 26661 name: material.type, 26662 uniforms: material.uniforms, 26663 vertexShader: material.vertexShader, 26664 fragmentShader: material.fragmentShader 26665 }; 26666 26667 } 26668 26669 material.onBeforeCompile( materialProperties.shader, _this ); 26670 26671 program = programCache.acquireProgram( material, materialProperties.shader, parameters, code ); 26672 26673 materialProperties.program = program; 26674 material.program = program; 26675 26676 } 26677 26678 var programAttributes = program.getAttributes(); 26679 26680 if ( material.morphTargets ) { 26681 26682 material.numSupportedMorphTargets = 0; 26683 26684 for ( var i = 0; i < _this.maxMorphTargets; i ++ ) { 26685 26686 if ( programAttributes[ 'morphTarget' + i ] >= 0 ) { 26687 26688 material.numSupportedMorphTargets ++; 26689 26690 } 26691 26692 } 26693 26694 } 26695 26696 if ( material.morphNormals ) { 26697 26698 material.numSupportedMorphNormals = 0; 26699 26700 for ( var i = 0; i < _this.maxMorphNormals; i ++ ) { 26701 26702 if ( programAttributes[ 'morphNormal' + i ] >= 0 ) { 26703 26704 material.numSupportedMorphNormals ++; 26705 26706 } 26707 26708 } 26709 26710 } 26711 26712 var uniforms = materialProperties.shader.uniforms; 26713 26714 if ( ! material.isShaderMaterial && 26715 ! material.isRawShaderMaterial || 26716 material.clipping === true ) { 26717 26718 materialProperties.numClippingPlanes = _clipping.numPlanes; 26719 materialProperties.numIntersection = _clipping.numIntersection; 26720 uniforms.clippingPlanes = _clipping.uniform; 26721 26722 } 26723 26724 materialProperties.fog = fog; 26725 26726 // store the light setup it was created for 26727 26728 materialProperties.lightsHash = lights.state.hash; 26729 26730 if ( material.lights ) { 26731 26732 // wire up the material to this renderer's lighting state 26733 26734 uniforms.ambientLightColor.value = lights.state.ambient; 26735 uniforms.directionalLights.value = lights.state.directional; 26736 uniforms.spotLights.value = lights.state.spot; 26737 uniforms.rectAreaLights.value = lights.state.rectArea; 26738 uniforms.pointLights.value = lights.state.point; 26739 uniforms.hemisphereLights.value = lights.state.hemi; 26740 26741 uniforms.directionalShadowMap.value = lights.state.directionalShadowMap; 26742 uniforms.directionalShadowMatrix.value = lights.state.directionalShadowMatrix; 26743 uniforms.spotShadowMap.value = lights.state.spotShadowMap; 26744 uniforms.spotShadowMatrix.value = lights.state.spotShadowMatrix; 26745 uniforms.pointShadowMap.value = lights.state.pointShadowMap; 26746 uniforms.pointShadowMatrix.value = lights.state.pointShadowMatrix; 26747 // TODO (abelnation): add area lights shadow info to uniforms 26748 26749 } 26750 26751 var progUniforms = materialProperties.program.getUniforms(), 26752 uniformsList = 26753 WebGLUniforms.seqWithValue( progUniforms.seq, uniforms ); 26754 26755 materialProperties.uniformsList = uniformsList; 26756 26757 } 26758 26759 function setProgram( camera, fog, material, object ) { 26760 26761 _usedTextureUnits = 0; 26762 26763 var materialProperties = properties.get( material ); 26764 var lights = currentRenderState.state.lights; 26765
26766 if ( _clippingEnabled ) { 26767 26768 if ( _localClippingEnabled || camera !== _currentCamera ) { 26769 26770 var useCache = 26771 camera === _currentCamera && 26772 material.id === _currentMaterialId; 26773 26774 // we might want to call this function with some ClippingGroup 26775 // object instead of the material, once it becomes feasible 26776 // (#8465, #8379) 26777 _clipping.setState( 26778 material.clippingPlanes, material.clipIntersection, material.clipShadows, 26779 camera, materialProperties, useCache ); 26780 26781 } 26782 26783 } 26784 26785 if ( material.needsUpdate === false ) { 26786 26787 if ( materialProperties.program === undefined ) { 26788 26789 material.needsUpdate = true; 26790 26791 } else if ( material.fog && materialProperties.fog !== fog ) { 26792 26793 material.needsUpdate = true; 26794 26795 } else if ( material.lights && materialProperties.lightsHash !== lights.state.hash ) { 26796 26797 material.needsUpdate = true; 26798 26799 } else if ( materialProperties.numClippingPlanes !== undefined && 26800 ( materialProperties.numClippingPlanes !== _clipping.numPlanes || 26801 materialProperties.numIntersection !== _clipping.numIntersection ) ) { 26802 26803 material.needsUpdate = true; 26804 26805 } 26806 26807 } 26808 26809 if ( material.needsUpdate ) { 26810 26811 initMaterial( material, fog, object ); 26812 material.needsUpdate = false; 26813 26814 } 26815 26816 var refreshProgram = false; 26817 var refreshMaterial = false; 26818 var refreshLights = false; 26819 26820 var program = materialProperties.program, 26821 p_uniforms = program.getUniforms(), 26822 m_uniforms = materialProperties.shader.uniforms; 26823 26824 if ( state.useProgram( program.program ) ) { 26825 26826 refreshProgram = true; 26827 refreshMaterial = true; 26828 refreshLights = true; 26829 26830 } 26831 26832 if ( material.id !== _currentMaterialId ) { 26833 26834 _currentMaterialId = material.id; 26835 26836 refreshMaterial = true; 26837 26838 } 26839 26840 if ( refreshProgram || camera !== _currentCamera ) { 26841 26842 p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); 26843 26844 if ( capabilities.logarithmicDepthBuffer ) { 26845 26846 p_uniforms.setValue( _gl, 'logDepthBufFC', 26847 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); 26848 26849 } 26850 26851 // Avoid unneeded uniform updates per ArrayCamera's sub-camera 26852 26853 if ( _currentCamera !== ( _currentArrayCamera || camera ) ) { 26854 26855 _currentCamera = ( _currentArrayCamera || camera ); 26856 26857 // lighting uniforms depend on the camera so enforce an update 26858 // now, in case this material supports lights - or later, when 26859 // the next material that does gets activated: 26860 26861 refreshMaterial = true; // set to true on material change 26862 refreshLights = true; // remains set until update done 26863 26864 } 26865 26866 // load material specific uniforms 26867 // (shader material also gets them for the sake of genericity) 26868 26869 if ( material.isShaderMaterial || 26870 material.isMeshPhongMaterial || 26871 material.isMeshStandardMaterial || 26872 material.envMap ) { 26873 26874 var uCamPos = p_uniforms.map.cameraPosition; 26875 26876 if ( uCamPos !== undefined ) { 26877 26878 uCamPos.setValue( _gl, 26879 _vector3.setFromMatrixPosition( camera.matrixWorld ) ); 26880 26881 } 26882 26883 } 26884 26885 if ( material.isMeshPhongMaterial || 26886 material.isMeshLambertMaterial || 26887 material.isMeshBasicMaterial || 26888 material.isMeshStandardMaterial || 26889 material.isShaderMaterial || 26890 material.skinning ) { 26891 26892 p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); 26893 26894 } 26895 26896 } 26897 26898 // skinning uniforms must be set even if material didn't change 26899 // auto-setting of texture unit for bone texture must go before other textures 26900 // not sure why, but otherwise weird things happen 26901 26902 if ( material.skinning ) { 26903 26904 p_uniforms.setOptional( _gl, object, 'bindMatrix' ); 26905 p_uniforms.setOptional( _gl, object, 'bindMatrixInverse' ); 26906 26907 var skeleton = object.skeleton; 26908 26909 if ( skeleton ) { 26910 26911 var bones = skeleton.bones; 26912 26913 if ( capabilities.floatVertexTextures ) { 26914 26915 if ( skeleton.boneTexture === undefined ) { 26916 26917 // layout (1 matrix = 4 pixels) 26918 // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) 26919 // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) 26920 // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) 26921 // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) 26922 // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) 26923 26924 26925 var size = Math.sqrt( bones.length * 4 ); // 4 pixels needed for 1 matrix
vendor: 4,185 bytes, lines 26926-27079
26926 size = _Math.ceilPowerOfTwo( size ); 26927 size = Math.max( size, 4 ); 26928 26929 var boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel 26930 boneMatrices.set( skeleton.boneMatrices ); // copy current values 26931 26932 var boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); 26933 boneTexture.needsUpdate = true; 26934 26935 skeleton.boneMatrices = boneMatrices; 26936 skeleton.boneTexture = boneTexture; 26937 skeleton.boneTextureSize = size; 26938 26939 } 26940 26941 p_uniforms.setValue( _gl, 'boneTexture', skeleton.boneTexture ); 26942 p_uniforms.setValue( _gl, 'boneTextureSize', skeleton.boneTextureSize ); 26943 26944 } else { 26945 26946 p_uniforms.setOptional( _gl, skeleton, 'boneMatrices' ); 26947 26948 } 26949 26950 } 26951 26952 } 26953 26954 if ( refreshMaterial ) { 26955 26956 p_uniforms.setValue( _gl, 'toneMappingExposure', _this.toneMappingExposure ); 26957 p_uniforms.setValue( _gl, 'toneMappingWhitePoint', _this.toneMappingWhitePoint ); 26958 26959 if ( material.lights ) { 26960 26961 // the current material requires lighting info 26962 26963 // note: all lighting uniforms are always set correctly 26964 // they simply reference the renderer's state for their 26965 // values 26966 // 26967 // use the current material's .needsUpdate flags to set 26968 // the GL state when required 26969 26970 markUniformsLightsNeedsUpdate( m_uniforms, refreshLights ); 26971 26972 } 26973 26974 // refresh uniforms common to several materials 26975 26976 if ( fog && material.fog ) { 26977 26978 refreshUniformsFog( m_uniforms, fog ); 26979 26980 } 26981 26982 if ( material.isMeshBasicMaterial ) { 26983 26984 refreshUniformsCommon( m_uniforms, material ); 26985 26986 } else if ( material.isMeshLambertMaterial ) { 26987 26988 refreshUniformsCommon( m_uniforms, material ); 26989 refreshUniformsLambert( m_uniforms, material ); 26990 26991 } else if ( material.isMeshPhongMaterial ) { 26992 26993 refreshUniformsCommon( m_uniforms, material ); 26994 26995 if ( material.isMeshToonMaterial ) { 26996 26997 refreshUniformsToon( m_uniforms, material ); 26998 26999 } else { 27000 27001 refreshUniformsPhong( m_uniforms, material ); 27002 27003 } 27004 27005 } else if ( material.isMeshStandardMaterial ) { 27006 27007 refreshUniformsCommon( m_uniforms, material ); 27008 27009 if ( material.isMeshPhysicalMaterial ) { 27010 27011 refreshUniformsPhysical( m_uniforms, material ); 27012 27013 } else { 27014 27015 refreshUniformsStandard( m_uniforms, material ); 27016 27017 } 27018 27019 } else if ( material.isMeshDepthMaterial ) { 27020 27021 refreshUniformsCommon( m_uniforms, material ); 27022 refreshUniformsDepth( m_uniforms, material ); 27023 27024 } else if ( material.isMeshDistanceMaterial ) { 27025 27026 refreshUniformsCommon( m_uniforms, material ); 27027 refreshUniformsDistance( m_uniforms, material ); 27028 27029 } else if ( material.isMeshNormalMaterial ) { 27030 27031 refreshUniformsCommon( m_uniforms, material ); 27032 refreshUniformsNormal( m_uniforms, material ); 27033 27034 } else if ( material.isLineBasicMaterial ) { 27035 27036 refreshUniformsLine( m_uniforms, material ); 27037 27038 if ( material.isLineDashedMaterial ) { 27039 27040 refreshUniformsDash( m_uniforms, material ); 27041 27042 } 27043 27044 } else if ( material.isPointsMaterial ) { 27045 27046 refreshUniformsPoints( m_uniforms, material ); 27047 27048 } else if ( material.isShadowMaterial ) { 27049 27050 m_uniforms.color.value = material.color; 27051 m_uniforms.opacity.value = material.opacity; 27052 27053 } 27054 27055 // RectAreaLight Texture 27056 // TODO (mrdoob): Find a nicer implementation 27057 27058 if ( m_uniforms.ltc_1 !== undefined ) m_uniforms.ltc_1.value = UniformsLib.LTC_1; 27059 if ( m_uniforms.ltc_2 !== undefined ) m_uniforms.ltc_2.value = UniformsLib.LTC_2; 27060 27061 WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this ); 27062 27063 } 27064 27065 if ( material.isShaderMaterial && material.uniformsNeedUpdate === true ) { 27066 27067 WebGLUniforms.upload( _gl, materialProperties.uniformsList, m_uniforms, _this ); 27068 material.uniformsNeedUpdate = false; 27069 27070 } 27071 27072 // common matrices 27073 27074 p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix ); 27075 p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix ); 27076 p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld ); 27077 27078 return program; 27079
27080 } 27081 27082 // Uniforms (refresh uniforms objects) 27083 27084 function refreshUniformsCommon( uniforms, material ) { 27085 27086 uniforms.opacity.value = material.opacity; 27087 27088 if ( material.color ) { 27089 27090 uniforms.diffuse.value = material.color; 27091 27092 } 27093 27094 if ( material.emissive ) { 27095 27096 uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity ); 27097 27098 } 27099 27100 if ( material.map ) { 27101 27102 uniforms.map.value = material.map; 27103 27104 } 27105 27106 if ( material.alphaMap ) { 27107 27108 uniforms.alphaMap.value = material.alphaMap; 27109 27110 } 27111 27112 if ( material.specularMap ) { 27113 27114 uniforms.specularMap.value = material.specularMap; 27115 27116 } 27117 27118 if ( material.envMap ) { 27119 27120 uniforms.envMap.value = material.envMap; 27121 27122 // don't flip CubeTexture envMaps, flip everything else: 27123 // WebGLRenderTargetCube will be flipped for backwards compatibility 27124 // WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture 27125 // this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future 27126 uniforms.flipEnvMap.value = ( ! ( material.envMap && material.envMap.isCubeTexture ) ) ? 1 : - 1; 27127 27128 uniforms.reflectivity.value = material.reflectivity; 27129 uniforms.refractionRatio.value = material.refractionRatio; 27130 27131 uniforms.maxMipLevel.value = properties.get( material.envMap ).__maxMipLevel; 27132 27133 } 27134 27135 if ( material.lightMap ) { 27136 27137 uniforms.lightMap.value = material.lightMap; 27138 uniforms.lightMapIntensity.value = material.lightMapIntensity; 27139 27140 } 27141 27142 if ( material.aoMap ) { 27143 27144 uniforms.aoMap.value = material.aoMap; 27145 uniforms.aoMapIntensity.value = material.aoMapIntensity; 27146 27147 } 27148 27149 // uv repeat and offset setting priorities 27150 // 1. color map 27151 // 2. specular map 27152 // 3. normal map 27153 // 4. bump map 27154 // 5. alpha map 27155 // 6. emissive map 27156 27157 var uvScaleMap; 27158 27159 if ( material.map ) { 27160 27161 uvScaleMap = material.map; 27162 27163 } else if ( material.specularMap ) { 27164 27165 uvScaleMap = material.specularMap; 27166 27167 } else if ( material.displacementMap ) { 27168 27169 uvScaleMap = material.displacementMap; 27170 27171 } else if ( material.normalMap ) { 27172 27173 uvScaleMap = material.normalMap; 27174 27175 } else if ( material.bumpMap ) { 27176 27177 uvScaleMap = material.bumpMap; 27178 27179 } else if ( material.roughnessMap ) { 27180 27181 uvScaleMap = material.roughnessMap; 27182 27183 } else if ( material.metalnessMap ) { 27184 27185 uvScaleMap = material.metalnessMap; 27186 27187 } else if ( material.alphaMap ) { 27188 27189 uvScaleMap = material.alphaMap; 27190 27191 } else if ( material.emissiveMap ) { 27192 27193 uvScaleMap = material.emissiveMap; 27194 27195 } 27196 27197 if ( uvScaleMap !== undefined ) { 27198 27199 // backwards compatibility 27200 if ( uvScaleMap.isWebGLRenderTarget ) { 27201 27202 uvScaleMap = uvScaleMap.texture; 27203 27204 } 27205 27206 if ( uvScaleMap.matrixAutoUpdate === true ) { 27207 27208 uvScaleMap.updateMatrix(); 27209 27210 } 27211 27212 uniforms.uvTransform.value.copy( uvScaleMap.matrix ); 27213 27214 } 27215 27216 } 27217 27218 function refreshUniformsLine( uniforms, material ) { 27219 27220 uniforms.diffuse.value = material.color; 27221 uniforms.opacity.value = material.opacity; 27222 27223 } 27224 27225 function refreshUniformsDash( uniforms, material ) { 27226 27227 uniforms.dashSize.value = material.dashSize; 27228 uniforms.totalSize.value = material.dashSize + material.gapSize; 27229 uniforms.scale.value = material.scale; 27230 27231 } 27232 27233 function refreshUniformsPoints( uniforms, material ) { 27234 27235 uniforms.diffuse.value = material.color; 27236 uniforms.opacity.value = material.opacity; 27237 uniforms.size.value = material.size * _pixelRatio; 27238 uniforms.scale.value = _height * 0.5; 27239 27240 uniforms.map.value = material.map; 27241 27242 if ( material.map !== null ) { 27243 27244 if ( material.map.matrixAutoUpdate === true ) { 27245 27246 material.map.updateMatrix(); 27247 27248 } 27249 27250 uniforms.uvTransform.value.copy( material.map.matrix ); 27251 27252 } 27253 27254 } 27255 27256 function refreshUniformsFog( uniforms, fog ) { 27257 27258 uniforms.fogColor.value = fog.color; 27259 27260 if ( fog.isFog ) { 27261 27262 uniforms.fogNear.value = fog.near; 27263 uniforms.fogFar.value = fog.far; 27264 27265 } else if ( fog.isFogExp2 ) { 27266 27267 uniforms.fogDensity.value = fog.density; 27268 27269 } 27270 27271 } 27272 27273 function refreshUniformsLambert( uniforms, material ) { 27274 27275 if ( material.emissiveMap ) { 27276 27277 uniforms.emissiveMap.value = material.emissiveMap; 27278 27279 } 27280 27281 } 27282 27283 function refreshUniformsPhong( uniforms, material ) { 27284 27285 uniforms.specular.value = material.specular; 27286 uniforms.shininess.value = Math.max( material.shininess, 1e-4 ); // to prevent pow( 0.0, 0.0 ) 27287 27288 if ( material.emissiveMap ) { 27289 27290 uniforms.emissiveMap.value = material.emissiveMap; 27291 27292 } 27293 27294 if ( material.bumpMap ) { 27295 27296 uniforms.bumpMap.value = material.bumpMap; 27297 uniforms.bumpScale.value = material.bumpScale; 27298 if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1; 27299 27300 } 27301 27302 if ( material.normalMap ) { 27303 27304 uniforms.normalMap.value = material.normalMap; 27305 uniforms.normalScale.value.copy( material.normalScale ); 27306 if ( material.side === BackSide ) uniforms.normalScale.value.negate(); 27307 27308 } 27309 27310 if ( material.displacementMap ) { 27311 27312 uniforms.displacementMap.value = material.displacementMap; 27313 uniforms.displacementScale.value = material.displacementScale; 27314 uniforms.displacementBias.value = material.displacementBias; 27315 27316 } 27317 27318 } 27319 27320 function refreshUniformsToon( uniforms, material ) { 27321 27322 refreshUniformsPhong( uniforms, material ); 27323 27324 if ( material.gradientMap ) { 27325 27326 uniforms.gradientMap.value = material.gradientMap; 27327 27328 } 27329 27330 } 27331 27332 function refreshUniformsStandard( uniforms, material ) { 27333 27334 uniforms.roughness.value = material.roughness; 27335 uniforms.metalness.value = material.metalness; 27336 27337 if ( material.roughnessMap ) { 27338 27339 uniforms.roughnessMap.value = material.roughnessMap; 27340 27341 } 27342 27343 if ( material.metalnessMap ) { 27344 27345 uniforms.metalnessMap.value = material.metalnessMap; 27346 27347 } 27348 27349 if ( material.emissiveMap ) { 27350 27351 uniforms.emissiveMap.value = material.emissiveMap; 27352 27353 } 27354 27355 if ( material.bumpMap ) { 27356 27357 uniforms.bumpMap.value = material.bumpMap; 27358 uniforms.bumpScale.value = material.bumpScale; 27359 if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1; 27360 27361 } 27362 27363 if ( material.normalMap ) { 27364 27365 uniforms.normalMap.value = material.normalMap; 27366 uniforms.normalScale.value.copy( material.normalScale ); 27367 if ( material.side === BackSide ) uniforms.normalScale.value.negate(); 27368 27369 } 27370 27371 if ( material.displacementMap ) { 27372 27373 uniforms.displacementMap.value = material.displacementMap; 27374 uniforms.displacementScale.value = material.displacementScale; 27375 uniforms.displacementBias.value = material.displacementBias; 27376 27377 } 27378 27379 if ( material.envMap ) { 27380 27381 //uniforms.envMap.value = material.envMap; // part of uniforms common 27382 uniforms.envMapIntensity.value = material.envMapIntensity; 27383 27384 } 27385 27386 } 27387 27388 function refreshUniformsPhysical( uniforms, material ) { 27389 27390 uniforms.clearCoat.value = material.clearCoat; 27391 uniforms.clearCoatRoughness.value = material.clearCoatRoughness; 27392 27393 refreshUniformsStandard( uniforms, material ); 27394 27395 } 27396 27397 function refreshUniformsDepth( uniforms, material ) { 27398 27399 if ( material.displacementMap ) { 27400 27401 uniforms.displacementMap.value = material.displacementMap; 27402 uniforms.displacementScale.value = material.displacementScale; 27403 uniforms.displacementBias.value = material.displacementBias; 27404 27405 } 27406 27407 } 27408 27409 function refreshUniformsDistance( uniforms, material ) { 27410 27411 if ( material.displacementMap ) { 27412 27413 uniforms.displacementMap.value = material.displacementMap; 27414 uniforms.displacementScale.value = material.displacementScale; 27415 uniforms.displacementBias.value = material.displacementBias; 27416 27417 } 27418 27419 uniforms.referencePosition.value.copy( material.referencePosition ); 27420 uniforms.nearDistance.value = material.nearDistance; 27421 uniforms.farDistance.value = material.farDistance; 27422
27423 } 27424 27425 function refreshUniformsNormal( uniforms, material ) { 27426 27427 if ( material.bumpMap ) { 27428 27429 uniforms.bumpMap.value = material.bumpMap; 27430 uniforms.bumpScale.value = material.bumpScale; 27431 if ( material.side === BackSide ) uniforms.bumpScale.value *= - 1; 27432 27433 } 27434 27435 if ( material.normalMap ) { 27436 27437 uniforms.normalMap.value = material.normalMap; 27438 uniforms.normalScale.value.copy( material.normalScale ); 27439 if ( material.side === BackSide ) uniforms.normalScale.value.negate(); 27440 27441 } 27442 27443 if ( material.displacementMap ) { 27444 27445 uniforms.displacementMap.value = material.displacementMap; 27446 uniforms.displacementScale.value = material.displacementScale; 27447 uniforms.displacementBias.value = material.displacementBias; 27448 27449 } 27450 27451 } 27452 27453 // If uniforms are marked as clean, they don't need to be loaded to the GPU. 27454 27455 function markUniformsLightsNeedsUpdate( uniforms, value ) { 27456 27457 uniforms.ambientLightColor.needsUpdate = value; 27458 27459 uniforms.directionalLights.needsUpdate = value; 27460 uniforms.pointLights.needsUpdate = value; 27461 uniforms.spotLights.needsUpdate = value; 27462 uniforms.rectAreaLights.needsUpdate = value; 27463 uniforms.hemisphereLights.needsUpdate = value; 27464 27465 } 27466 27467 // Textures 27468 27469 function allocTextureUnit() { 27470 27471 var textureUnit = _usedTextureUnits; 27472 27473 if ( textureUnit >= capabilities.maxTextures ) { 27474 27475 console.warn( 'THREE.WebGLRenderer: Trying to use ' + textureUnit + ' texture units while this GPU supports only ' + capabilities.maxTextures ); 27476 27477 } 27478 27479 _usedTextureUnits += 1; 27480 27481 return textureUnit; 27482 27483 } 27484 27485 this.allocTextureUnit = allocTextureUnit; 27486 27487 // this.setTexture2D = setTexture2D; 27488 this.setTexture2D = ( function () { 27489 27490 var warned = false; 27491 27492 // backwards compatibility: peel texture.texture 27493 return function setTexture2D( texture, slot ) { 27494 27495 if ( texture && texture.isWebGLRenderTarget ) { 27496 27497 if ( ! warned ) { 27498 27499 console.warn( "THREE.WebGLRenderer.setTexture2D: don't use render targets as textures. Use their .texture property instead." ); 27500 warned = true; 27501 27502 } 27503 27504 texture = texture.texture; 27505 27506 } 27507 27508 textures.setTexture2D( texture, slot ); 27509 27510 }; 27511 27512 }() ); 27513 27514 this.setTexture = ( function () { 27515 27516 var warned = false; 27517 27518 return function setTexture( texture, slot ) { 27519 27520 if ( ! warned ) { 27521 27522 console.warn( "THREE.WebGLRenderer: .setTexture is deprecated, use setTexture2D instead." ); 27523 warned = true; 27524 27525 } 27526 27527 textures.setTexture2D( texture, slot ); 27528 27529 }; 27530 27531 }() ); 27532 27533 this.setTextureCube = ( function () { 27534 27535 var warned = false; 27536 27537 return function setTextureCube( texture, slot ) { 27538 27539 // backwards compatibility: peel texture.texture 27540 if ( texture && texture.isWebGLRenderTargetCube ) { 27541 27542 if ( ! warned ) { 27543 27544 console.warn( "THREE.WebGLRenderer.setTextureCube: don't use cube render targets as textures. Use their .texture property instead." ); 27545 warned = true; 27546 27547 } 27548 27549 texture = texture.texture; 27550 27551 } 27552 27553 // currently relying on the fact that WebGLRenderTargetCube.texture is a Texture and NOT a CubeTexture 27554 // TODO: unify these code paths 27555 if ( ( texture && texture.isCubeTexture ) || 27556 ( Array.isArray( texture.image ) && texture.image.length === 6 ) ) { 27557 27558 // CompressedTexture can have Array in image :/ 27559 27560 // this function alone should take care of cube textures 27561 textures.setTextureCube( texture, slot ); 27562 27563 } else { 27564 27565 // assumed: texture property of THREE.WebGLRenderTargetCube 27566 27567 textures.setTextureCubeDynamic( texture, slot ); 27568 27569 } 27570 27571 }; 27572 27573 }() ); 27574 27575 // 27576 27577 this.setFramebuffer = function ( value ) { 27578 27579 _framebuffer = value; 27580 27581 }; 27582 27583 this.getRenderTarget = function () { 27584 27585 return _currentRenderTarget; 27586 27587 }; 27588 27589 this.setRenderTarget = function ( renderTarget ) { 27590 27591 _currentRenderTarget = renderTarget; 27592 27593 if ( renderTarget && properties.get( renderTarget ).__webglFramebuffer === undefined ) { 27594 27595 textures.setupRenderTarget( renderTarget ); 27596 27597 } 27598 27599 var framebuffer = _framebuffer; 27600 var isCube = false;
27601 27602 if ( renderTarget ) { 27603 27604 var __webglFramebuffer = properties.get( renderTarget ).__webglFramebuffer; 27605 27606 if ( renderTarget.isWebGLRenderTargetCube ) { 27607 27608 framebuffer = __webglFramebuffer[ renderTarget.activeCubeFace ]; 27609 isCube = true; 27610 27611 } else { 27612 27613 framebuffer = __webglFramebuffer; 27614 27615 } 27616 27617 _currentViewport.copy( renderTarget.viewport ); 27618 _currentScissor.copy( renderTarget.scissor ); 27619 _currentScissorTest = renderTarget.scissorTest; 27620 27621 } else { 27622 27623 _currentViewport.copy( _viewport ).multiplyScalar( _pixelRatio ); 27624 _currentScissor.copy( _scissor ).multiplyScalar( _pixelRatio ); 27625 _currentScissorTest = _scissorTest; 27626 27627 } 27628 27629 if ( _currentFramebuffer !== framebuffer ) { 27630 27631 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 27632 _currentFramebuffer = framebuffer; 27633 27634 } 27635 27636 state.viewport( _currentViewport ); 27637 state.scissor( _currentScissor ); 27638 state.setScissorTest( _currentScissorTest ); 27639 27640 if ( isCube ) { 27641 27642 var textureProperties = properties.get( renderTarget.texture ); 27643 _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + renderTarget.activeCubeFace, textureProperties.__webglTexture, renderTarget.activeMipMapLevel ); 27644 27645 } 27646 27647 }; 27648 27649 this.readRenderTargetPixels = function ( renderTarget, x, y, width, height, buffer ) { 27650 27651 if ( ! ( renderTarget && renderTarget.isWebGLRenderTarget ) ) { 27652 27653 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.' ); 27654 return; 27655 27656 } 27657 27658 var framebuffer = properties.get( renderTarget ).__webglFramebuffer; 27659 27660 if ( framebuffer ) { 27661 27662 var restore = false; 27663 27664 if ( framebuffer !== _currentFramebuffer ) { 27665 27666 _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); 27667 27668 restore = true; 27669 27670 } 27671 27672 try { 27673 27674 var texture = renderTarget.texture; 27675 var textureFormat = texture.format; 27676 var textureType = texture.type; 27677 27678 if ( textureFormat !== RGBAFormat && utils.convert( textureFormat ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_FORMAT ) ) { 27679 27680 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.' ); 27681 return; 27682 27683 } 27684 27685 if ( textureType !== UnsignedByteType && utils.convert( textureType ) !== _gl.getParameter( _gl.IMPLEMENTATION_COLOR_READ_TYPE ) && // IE11, Edge and Chrome Mac < 52 (#9513) 27686 ! ( textureType === FloatType && ( extensions.get( 'OES_texture_float' ) || extensions.get( 'WEBGL_color_buffer_float' ) ) ) && // Chrome Mac >= 52 and Firefox 27687 ! ( textureType === HalfFloatType && extensions.get( 'EXT_color_buffer_half_float' ) ) ) { 27688 27689 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.' ); 27690 return; 27691 27692 } 27693 27694 if ( _gl.checkFramebufferStatus( _gl.FRAMEBUFFER ) === _gl.FRAMEBUFFER_COMPLETE ) { 27695 27696 // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) 27697 27698 if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { 27699 27700 _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), buffer ); 27701 27702 } 27703 27704 } else { 27705 27706 console.error( 'THREE.WebGLRenderer.readRenderTargetPixels: readPixels from renderTarget failed. Framebuffer not complete.' ); 27707 27708 } 27709 27710 } finally { 27711 27712 if ( restore ) { 27713 27714 _gl.bindFramebuffer( _gl.FRAMEBUFFER, _currentFramebuffer ); 27715 27716 } 27717 27718 } 27719 27720 } 27721 27722 }; 27723 27724 this.copyFramebufferToTexture = function ( position, texture, level ) { 27725 27726 var width = texture.image.width; 27727 var height = texture.image.height; 27728 var glFormat = utils.convert( texture.format ); 27729 27730 this.setTexture2D( texture, 0 ); 27731 27732 _gl.copyTexImage2D( _gl.TEXTURE_2D, level || 0, glFormat, position.x, position.y, width, height, 0 ); 27733 27734 }; 27735 27736 this.copyTextureToTexture = function ( position, srcTexture, dstTexture, level ) { 27737 27738 var width = srcTexture.image.width; 27739 var height = srcTexture.image.height; 27740 var glFormat = utils.convert( dstTexture.format ); 27741 var glType = utils.convert( dstTexture.type ); 27742 27743 this.setTexture2D( dstTexture, 0 ); 27744 27745 if ( srcTexture.isDataTexture ) { 27746 27747 _gl.texSubImage2D( _gl.TEXTURE_2D, level || 0, position.x, position.y, width, height, glFormat, glType, srcTexture.image.data ); 27748 27749 } else { 27750
27751 _gl.texSubImage2D( _gl.TEXTURE_2D, level || 0, position.x, position.y, glFormat, glType, srcTexture.image ); 27752 27753 } 27754 27755 }; 27756 27757 } 27758 27759 /** 27760 * @author mrdoob / http://mrdoob.com/ 27761 * @author alteredq / http://alteredqualia.com/ 27762 */ 27763 27764 function FogExp2( color, density ) { 27765 27766 this.name = ''; 27767 27768 this.color = new Color( color ); 27769 this.density = ( density !== undefined ) ? density : 0.00025; 27770 27771 } 27772 27773 FogExp2.prototype.isFogExp2 = true; 27774 27775 FogExp2.prototype.clone = function () { 27776 27777 return new FogExp2( this.color, this.density ); 27778 27779 }; 27780 27781 FogExp2.prototype.toJSON = function ( /* meta */ ) { 27782 27783 return { 27784 type: 'FogExp2', 27785 color: this.color.getHex(), 27786 density: this.density 27787 }; 27788 27789 }; 27790 27791 /** 27792 * @author mrdoob / http://mrdoob.com/ 27793 * @author alteredq / http://alteredqualia.com/ 27794 */ 27795 27796 function Fog( color, near, far ) { 27797 27798 this.name = ''; 27799 27800 this.color = new Color( color ); 27801 27802 this.near = ( near !== undefined ) ? near : 1; 27803 this.far = ( far !== undefined ) ? far : 1000; 27804 27805 } 27806 27807 Fog.prototype.isFog = true; 27808 27809 Fog.prototype.clone = function () { 27810 27811 return new Fog( this.color, this.near, this.far ); 27812 27813 }; 27814 27815 Fog.prototype.toJSON = function ( /* meta */ ) { 27816 27817 return { 27818 type: 'Fog', 27819 color: this.color.getHex(), 27820 near: this.near, 27821 far: this.far 27822 }; 27823 27824 }; 27825 27826 /** 27827 * @author mrdoob / http://mrdoob.com/ 27828 */ 27829 27830 function Scene() { 27831 27832 Object3D.call( this ); 27833 27834 this.type = 'Scene'; 27835 27836 this.background = null; 27837 this.fog = null; 27838 this.overrideMaterial = null; 27839 27840 this.autoUpdate = true; // checked by the renderer 27841 27842 } 27843 27844 Scene.prototype = Object.assign( Object.create( Object3D.prototype ), { 27845 27846 constructor: Scene, 27847 27848 copy: function ( source, recursive ) { 27849 27850 Object3D.prototype.copy.call( this, source, recursive ); 27851 27852 if ( source.background !== null ) this.background = source.background.clone(); 27853 if ( source.fog !== null ) this.fog = source.fog.clone(); 27854 if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); 27855 27856 this.autoUpdate = source.autoUpdate; 27857 this.matrixAutoUpdate = source.matrixAutoUpdate; 27858 27859 return this; 27860 27861 }, 27862 27863 toJSON: function ( meta ) { 27864 27865 var data = Object3D.prototype.toJSON.call( this, meta ); 27866 27867 if ( this.background !== null ) data.object.background = this.background.toJSON( meta ); 27868 if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); 27869 27870 return data; 27871 27872 } 27873 27874 } ); 27875 27876 /** 27877 * @author alteredq / http://alteredqualia.com/ 27878 * 27879 * parameters = { 27880 * color: <hex>, 27881 * opacity: <float>, 27882 * map: new THREE.Texture( <Image> ), 27883 * 27884 * uvOffset: new THREE.Vector2(), 27885 * uvScale: new THREE.Vector2() 27886 * } 27887 */ 27888 27889 function SpriteMaterial( parameters ) { 27890 27891 Material.call( this ); 27892 27893 this.type = 'SpriteMaterial'; 27894 27895 this.color = new Color( 0xffffff ); 27896 this.map = null; 27897 27898 this.rotation = 0; 27899 27900 this.fog = false; 27901 this.lights = false; 27902 27903 this.setValues( parameters ); 27904 27905 } 27906 27907 SpriteMaterial.prototype = Object.create( Material.prototype ); 27908 SpriteMaterial.prototype.constructor = SpriteMaterial; 27909 SpriteMaterial.prototype.isSpriteMaterial = true; 27910 27911 SpriteMaterial.prototype.copy = function ( source ) { 27912 27913 Material.prototype.copy.call( this, source ); 27914 27915 this.color.copy( source.color ); 27916 this.map = source.map; 27917 27918 this.rotation = source.rotation; 27919 27920 return this; 27921 27922 }; 27923 27924 /** 27925 * @author mikael emtinger / http://gomo.se/ 27926 * @author alteredq / http://alteredqualia.com/ 27927 */ 27928 27929 function Sprite( material ) { 27930 27931 Object3D.call( this ); 27932 27933 this.type = 'Sprite'; 27934 27935 this.material = ( material !== undefined ) ? material : new SpriteMaterial(); 27936 27937 this.center = new Vector2( 0.5, 0.5 ); 27938 27939 } 27940 27941 Sprite.prototype = Object.assign( Object.create( Object3D.prototype ), { 27942 27943 constructor: Sprite, 27944 27945 isSprite: true, 27946 27947 raycast: ( function () { 27948 27949 var intersectPoint = new Vector3(); 27950 var worldPosition = new Vector3(); 27951 var worldScale = new Vector3(); 27952 27953 return function raycast( raycaster, intersects ) { 27954 27955 worldPosition.setFromMatrixPosition( this.matrixWorld ); 27956 raycaster.ray.closestPointToPoint( worldPosition, intersectPoint ); 27957 27958 worldScale.setFromMatrixScale( this.matrixWorld ); 27959 var guessSizeSq = worldScale.x * worldScale.y / 4; 27960 27961 if ( worldPosition.distanceToSquared( intersectPoint ) > guessSizeSq ) return; 27962 27963 var distance = raycaster.ray.origin.distanceTo( intersectPoint ); 27964 27965 if ( distance < raycaster.near || distance > raycaster.far ) return; 27966 27967 intersects.push( { 27968 27969 distance: distance, 27970 point: intersectPoint.clone(), 27971 face: null, 27972 object: this 27973 27974 } ); 27975 27976 }; 27977 27978 }() ), 27979 27980 clone: function () { 27981 27982 return new this.constructor( this.material ).copy( this ); 27983 27984 }, 27985
vendor: 4,101 bytes, lines 27986-28217
27986 copy: function ( source ) { 27987 27988 Object3D.prototype.copy.call( this, source ); 27989 27990 if ( source.center !== undefined ) this.center.copy( source.center ); 27991 27992 return this; 27993 27994 } 27995 27996 27997 } ); 27998 27999 /** 28000 * @author mikael emtinger / http://gomo.se/ 28001 * @author alteredq / http://alteredqualia.com/ 28002 * @author mrdoob / http://mrdoob.com/ 28003 */ 28004 28005 function LOD() { 28006 28007 Object3D.call( this ); 28008 28009 this.type = 'LOD'; 28010 28011 Object.defineProperties( this, { 28012 levels: { 28013 enumerable: true, 28014 value: [] 28015 } 28016 } ); 28017 28018 } 28019 28020 LOD.prototype = Object.assign( Object.create( Object3D.prototype ), { 28021 28022 constructor: LOD, 28023 28024 copy: function ( source ) { 28025 28026 Object3D.prototype.copy.call( this, source, false ); 28027 28028 var levels = source.levels; 28029 28030 for ( var i = 0, l = levels.length; i < l; i ++ ) { 28031 28032 var level = levels[ i ]; 28033 28034 this.addLevel( level.object.clone(), level.distance ); 28035 28036 } 28037 28038 return this; 28039 28040 }, 28041 28042 addLevel: function ( object, distance ) { 28043 28044 if ( distance === undefined ) distance = 0; 28045 28046 distance = Math.abs( distance ); 28047 28048 var levels = this.levels; 28049 28050 for ( var l = 0; l < levels.length; l ++ ) { 28051 28052 if ( distance < levels[ l ].distance ) { 28053 28054 break; 28055 28056 } 28057 28058 } 28059 28060 levels.splice( l, 0, { distance: distance, object: object } ); 28061 28062 this.add( object ); 28063 28064 }, 28065 28066 getObjectForDistance: function ( distance ) { 28067 28068 var levels = this.levels; 28069 28070 for ( var i = 1, l = levels.length; i < l; i ++ ) { 28071 28072 if ( distance < levels[ i ].distance ) { 28073 28074 break; 28075 28076 } 28077 28078 } 28079 28080 return levels[ i - 1 ].object; 28081 28082 }, 28083 28084 raycast: ( function () { 28085 28086 var matrixPosition = new Vector3(); 28087 28088 return function raycast( raycaster, intersects ) { 28089 28090 matrixPosition.setFromMatrixPosition( this.matrixWorld ); 28091 28092 var distance = raycaster.ray.origin.distanceTo( matrixPosition ); 28093 28094 this.getObjectForDistance( distance ).raycast( raycaster, intersects ); 28095 28096 }; 28097 28098 }() ), 28099 28100 update: function () { 28101 28102 var v1 = new Vector3(); 28103 var v2 = new Vector3(); 28104 28105 return function update( camera ) { 28106 28107 var levels = this.levels; 28108 28109 if ( levels.length > 1 ) { 28110 28111 v1.setFromMatrixPosition( camera.matrixWorld ); 28112 v2.setFromMatrixPosition( this.matrixWorld ); 28113 28114 var distance = v1.distanceTo( v2 ); 28115 28116 levels[ 0 ].object.visible = true; 28117 28118 for ( var i = 1, l = levels.length; i < l; i ++ ) { 28119 28120 if ( distance >= levels[ i ].distance ) { 28121 28122 levels[ i - 1 ].object.visible = false; 28123 levels[ i ].object.visible = true; 28124 28125 } else { 28126 28127 break; 28128 28129 } 28130 28131 } 28132 28133 for ( ; i < l; i ++ ) { 28134 28135 levels[ i ].object.visible = false; 28136 28137 } 28138 28139 } 28140 28141 }; 28142 28143 }(), 28144 28145 toJSON: function ( meta ) { 28146 28147 var data = Object3D.prototype.toJSON.call( this, meta ); 28148 28149 data.object.levels = []; 28150 28151 var levels = this.levels; 28152 28153 for ( var i = 0, l = levels.length; i < l; i ++ ) { 28154 28155 var level = levels[ i ]; 28156 28157 data.object.levels.push( { 28158 object: level.object.uuid, 28159 distance: level.distance 28160 } ); 28161 28162 } 28163 28164 return data; 28165 28166 } 28167 28168 } ); 28169 28170 /** 28171 * @author mikael emtinger / http://gomo.se/ 28172 * @author alteredq / http://alteredqualia.com/ 28173 * @author michael guerrero / http://realitymeltdown.com 28174 * @author ikerr / http://verold.com 28175 */ 28176 28177 function Skeleton( bones, boneInverses ) { 28178 28179 // copy the bone array 28180 28181 bones = bones || []; 28182 28183 this.bones = bones.slice( 0 ); 28184 this.boneMatrices = new Float32Array( this.bones.length * 16 ); 28185 28186 // use the supplied bone inverses or calculate the inverses 28187 28188 if ( boneInverses === undefined ) { 28189 28190 this.calculateInverses(); 28191 28192 } else { 28193 28194 if ( this.bones.length === boneInverses.length ) { 28195 28196 this.boneInverses = boneInverses.slice( 0 ); 28197 28198 } else { 28199 28200 console.warn( 'THREE.Skeleton boneInverses is the wrong length.' ); 28201 28202 this.boneInverses = []; 28203 28204 for ( var i = 0, il = this.bones.length; i < il; i ++ ) { 28205 28206 this.boneInverses.push( new Matrix4() ); 28207 28208 } 28209 28210 } 28211 28212 } 28213 28214 } 28215 28216 Object.assign( Skeleton.prototype, { 28217
28218 calculateInverses: function () { 28219 28220 this.boneInverses = []; 28221 28222 for ( var i = 0, il = this.bones.length; i < il; i ++ ) { 28223 28224 var inverse = new Matrix4(); 28225 28226 if ( this.bones[ i ] ) { 28227 28228 inverse.getInverse( this.bones[ i ].matrixWorld ); 28229 28230 } 28231 28232 this.boneInverses.push( inverse ); 28233 28234 } 28235 28236 }, 28237 28238 pose: function () { 28239 28240 var bone, i, il; 28241 28242 // recover the bind-time world matrices 28243 28244 for ( i = 0, il = this.bones.length; i < il; i ++ ) { 28245 28246 bone = this.bones[ i ]; 28247 28248 if ( bone ) { 28249 28250 bone.matrixWorld.getInverse( this.boneInverses[ i ] ); 28251 28252 } 28253 28254 } 28255 28256 // compute the local matrices, positions, rotations and scales 28257 28258 for ( i = 0, il = this.bones.length; i < il; i ++ ) { 28259 28260 bone = this.bones[ i ]; 28261 28262 if ( bone ) { 28263 28264 if ( bone.parent && bone.parent.isBone ) { 28265 28266 bone.matrix.getInverse( bone.parent.matrixWorld ); 28267 bone.matrix.multiply( bone.matrixWorld ); 28268 28269 } else { 28270 28271 bone.matrix.copy( bone.matrixWorld ); 28272 28273 } 28274 28275 bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); 28276 28277 } 28278 28279 } 28280 28281 }, 28282 28283 update: ( function () { 28284 28285 var offsetMatrix = new Matrix4(); 28286 var identityMatrix = new Matrix4(); 28287 28288 return function update() { 28289 28290 var bones = this.bones; 28291 var boneInverses = this.boneInverses; 28292 var boneMatrices = this.boneMatrices; 28293 var boneTexture = this.boneTexture; 28294 28295 // flatten bone matrices to array 28296 28297 for ( var i = 0, il = bones.length; i < il; i ++ ) { 28298 28299 // compute the offset between the current and the original transform 28300 28301 var matrix = bones[ i ] ? bones[ i ].matrixWorld : identityMatrix; 28302 28303 offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); 28304 offsetMatrix.toArray( boneMatrices, i * 16 ); 28305 28306 } 28307 28308 if ( boneTexture !== undefined ) { 28309 28310 boneTexture.needsUpdate = true; 28311 28312 } 28313 28314 }; 28315 28316 } )(), 28317 28318 clone: function () { 28319 28320 return new Skeleton( this.bones, this.boneInverses ); 28321 28322 }, 28323 28324 getBoneByName: function ( name ) { 28325 28326 for ( var i = 0, il = this.bones.length; i < il; i ++ ) { 28327 28328 var bone = this.bones[ i ]; 28329 28330 if ( bone.name === name ) { 28331 28332 return bone; 28333 28334 } 28335 28336 } 28337 28338 return undefined; 28339 28340 } 28341 28342 } ); 28343 28344 /** 28345 * @author mikael emtinger / http://gomo.se/ 28346 * @author alteredq / http://alteredqualia.com/ 28347 * @author ikerr / http://verold.com 28348 */ 28349 28350 function Bone() { 28351 28352 Object3D.call( this ); 28353 28354 this.type = 'Bone'; 28355 28356 } 28357 28358 Bone.prototype = Object.assign( Object.create( Object3D.prototype ), { 28359 28360 constructor: Bone, 28361 28362 isBone: true 28363 28364 } ); 28365 28366 /** 28367 * @author mikael emtinger / http://gomo.se/ 28368 * @author alteredq / http://alteredqualia.com/ 28369 * @author ikerr / http://verold.com 28370 */ 28371 28372 function SkinnedMesh( geometry, material ) { 28373 28374 Mesh.call( this, geometry, material ); 28375 28376 this.type = 'SkinnedMesh'; 28377 28378 this.bindMode = 'attached'; 28379 this.bindMatrix = new Matrix4(); 28380 this.bindMatrixInverse = new Matrix4(); 28381 28382 var bones = this.initBones(); 28383 var skeleton = new Skeleton( bones ); 28384 28385 this.bind( skeleton, this.matrixWorld ); 28386 28387 this.normalizeSkinWeights(); 28388 28389 } 28390 28391 SkinnedMesh.prototype = Object.assign( Object.create( Mesh.prototype ), { 28392 28393 constructor: SkinnedMesh, 28394 28395 isSkinnedMesh: true, 28396 28397 initBones: function () { 28398 28399 var bones = [], bone, gbone; 28400 var i, il; 28401 28402 if ( this.geometry && this.geometry.bones !== undefined ) { 28403 28404 // first, create array of 'Bone' objects from geometry data 28405 28406 for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { 28407 28408 gbone = this.geometry.bones[ i ]; 28409 28410 // create new 'Bone' object 28411 28412 bone = new Bone(); 28413 bones.push( bone ); 28414 28415 // apply values 28416 28417 bone.name = gbone.name; 28418 bone.position.fromArray( gbone.pos ); 28419 bone.quaternion.fromArray( gbone.rotq ); 28420 if ( gbone.scl !== undefined ) bone.scale.fromArray( gbone.scl ); 28421 28422 } 28423 28424 // second, create bone hierarchy 28425 28426 for ( i = 0, il = this.geometry.bones.length; i < il; i ++ ) { 28427 28428 gbone = this.geometry.bones[ i ]; 28429 28430 if ( ( gbone.parent !== - 1 ) && ( gbone.parent !== null ) && ( bones[ gbone.parent ] !== undefined ) ) { 28431 28432 // subsequent bones in the hierarchy 28433 28434 bones[ gbone.parent ].add( bones[ i ] ); 28435 28436 } else { 28437
28438 // topmost bone, immediate child of the skinned mesh 28439 28440 this.add( bones[ i ] ); 28441 28442 } 28443 28444 } 28445 28446 } 28447 28448 // now the bones are part of the scene graph and children of the skinned mesh. 28449 // let's update the corresponding matrices 28450 28451 this.updateMatrixWorld( true ); 28452 28453 return bones; 28454 28455 }, 28456 28457 bind: function ( skeleton, bindMatrix ) { 28458 28459 this.skeleton = skeleton; 28460 28461 if ( bindMatrix === undefined ) { 28462 28463 this.updateMatrixWorld( true ); 28464 28465 this.skeleton.calculateInverses(); 28466 28467 bindMatrix = this.matrixWorld; 28468 28469 } 28470 28471 this.bindMatrix.copy( bindMatrix ); 28472 this.bindMatrixInverse.getInverse( bindMatrix ); 28473 28474 }, 28475 28476 pose: function () { 28477 28478 this.skeleton.pose(); 28479 28480 }, 28481 28482 normalizeSkinWeights: function () { 28483 28484 var scale, i; 28485 28486 if ( this.geometry && this.geometry.isGeometry ) { 28487 28488 for ( i = 0; i < this.geometry.skinWeights.length; i ++ ) { 28489 28490 var sw = this.geometry.skinWeights[ i ]; 28491 28492 scale = 1.0 / sw.manhattanLength(); 28493 28494 if ( scale !== Infinity ) { 28495 28496 sw.multiplyScalar( scale ); 28497 28498 } else { 28499 28500 sw.set( 1, 0, 0, 0 );
vendor: 52,515 bytes, lines 28500-30782
28500 // do something reasonable 28501 28502 } 28503 28504 } 28505 28506 } else if ( this.geometry && this.geometry.isBufferGeometry ) { 28507 28508 var vec = new Vector4(); 28509 28510 var skinWeight = this.geometry.attributes.skinWeight; 28511 28512 for ( i = 0; i < skinWeight.count; i ++ ) { 28513 28514 vec.x = skinWeight.getX( i ); 28515 vec.y = skinWeight.getY( i ); 28516 vec.z = skinWeight.getZ( i ); 28517 vec.w = skinWeight.getW( i ); 28518 28519 scale = 1.0 / vec.manhattanLength(); 28520 28521 if ( scale !== Infinity ) { 28522 28523 vec.multiplyScalar( scale ); 28524 28525 } else { 28526 28527 vec.set( 1, 0, 0, 0 ); // do something reasonable 28528 28529 } 28530 28531 skinWeight.setXYZW( i, vec.x, vec.y, vec.z, vec.w ); 28532 28533 } 28534 28535 } 28536 28537 }, 28538 28539 updateMatrixWorld: function ( force ) { 28540 28541 Mesh.prototype.updateMatrixWorld.call( this, force ); 28542 28543 if ( this.bindMode === 'attached' ) { 28544 28545 this.bindMatrixInverse.getInverse( this.matrixWorld ); 28546 28547 } else if ( this.bindMode === 'detached' ) { 28548 28549 this.bindMatrixInverse.getInverse( this.bindMatrix ); 28550 28551 } else { 28552 28553 console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); 28554 28555 } 28556 28557 }, 28558 28559 clone: function () { 28560 28561 return new this.constructor( this.geometry, this.material ).copy( this ); 28562 28563 } 28564 28565 } ); 28566 28567 /** 28568 * @author mrdoob / http://mrdoob.com/ 28569 * @author alteredq / http://alteredqualia.com/ 28570 * 28571 * parameters = { 28572 * color: <hex>, 28573 * opacity: <float>, 28574 * 28575 * linewidth: <float>, 28576 * linecap: "round", 28577 * linejoin: "round" 28578 * } 28579 */ 28580 28581 function LineBasicMaterial( parameters ) { 28582 28583 Material.call( this ); 28584 28585 this.type = 'LineBasicMaterial'; 28586 28587 this.color = new Color( 0xffffff ); 28588 28589 this.linewidth = 1; 28590 this.linecap = 'round'; 28591 this.linejoin = 'round'; 28592 28593 this.lights = false; 28594 28595 this.setValues( parameters ); 28596 28597 } 28598 28599 LineBasicMaterial.prototype = Object.create( Material.prototype ); 28600 LineBasicMaterial.prototype.constructor = LineBasicMaterial; 28601 28602 LineBasicMaterial.prototype.isLineBasicMaterial = true; 28603 28604 LineBasicMaterial.prototype.copy = function ( source ) { 28605 28606 Material.prototype.copy.call( this, source ); 28607 28608 this.color.copy( source.color ); 28609 28610 this.linewidth = source.linewidth; 28611 this.linecap = source.linecap; 28612 this.linejoin = source.linejoin; 28613 28614 return this; 28615 28616 }; 28617 28618 /** 28619 * @author mrdoob / http://mrdoob.com/ 28620 */ 28621 28622 function Line( geometry, material, mode ) { 28623 28624 if ( mode === 1 ) { 28625 28626 console.warn( 'THREE.Line: parameter THREE.LinePieces no longer supported. Created THREE.LineSegments instead.' ); 28627 return new LineSegments( geometry, material ); 28628 28629 } 28630 28631 Object3D.call( this ); 28632 28633 this.type = 'Line'; 28634 28635 this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); 28636 this.material = material !== undefined ? material : new LineBasicMaterial( { color: Math.random() * 0xffffff } ); 28637 28638 } 28639 28640 Line.prototype = Object.assign( Object.create( Object3D.prototype ), { 28641 28642 constructor: Line, 28643 28644 isLine: true, 28645 28646 computeLineDistances: ( function () { 28647 28648 var start = new Vector3(); 28649 var end = new Vector3(); 28650 28651 return function computeLineDistances() { 28652 28653 var geometry = this.geometry; 28654 28655 if ( geometry.isBufferGeometry ) { 28656 28657 // we assume non-indexed geometry 28658 28659 if ( geometry.index === null ) { 28660 28661 var positionAttribute = geometry.attributes.position; 28662 var lineDistances = [ 0 ]; 28663 28664 for ( var i = 1, l = positionAttribute.count; i < l; i ++ ) { 28665 28666 start.fromBufferAttribute( positionAttribute, i - 1 ); 28667 end.fromBufferAttribute( positionAttribute, i ); 28668 28669 lineDistances[ i ] = lineDistances[ i - 1 ]; 28670 lineDistances[ i ] += start.distanceTo( end ); 28671 28672 } 28673 28674 geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 28675 28676 } else { 28677 28678 console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 28679 28680 } 28681 28682 } else if ( geometry.isGeometry ) { 28683 28684 var vertices = geometry.vertices; 28685 var lineDistances = geometry.lineDistances; 28686 28687 lineDistances[ 0 ] = 0; 28688 28689 for ( var i = 1, l = vertices.length; i < l; i ++ ) { 28690 28691 lineDistances[ i ] = lineDistances[ i - 1 ]; 28692 lineDistances[ i ] += vertices[ i - 1 ].distanceTo( vertices[ i ] ); 28693 28694 } 28695 28696 } 28697 28698 return this; 28699 28700 }; 28701 28702 }() ), 28703 28704 raycast: ( function () { 28705 28706 var inverseMatrix = new Matrix4(); 28707 var ray = new Ray(); 28708 var sphere = new Sphere(); 28709 28710 return function raycast( raycaster, intersects ) { 28711 28712 var precision = raycaster.linePrecision; 28713 var precisionSq = precision * precision; 28714 28715 var geometry = this.geometry; 28716 var matrixWorld = this.matrixWorld; 28717 28718 // Checking boundingSphere distance to ray 28719 28720 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 28721 28722 sphere.copy( geometry.boundingSphere ); 28723 sphere.applyMatrix4( matrixWorld ); 28724 28725 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; 28726 28727 // 28728 28729 inverseMatrix.getInverse( matrixWorld ); 28730 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); 28731 28732 var vStart = new Vector3(); 28733 var vEnd = new Vector3(); 28734 var interSegment = new Vector3(); 28735 var interRay = new Vector3(); 28736 var step = ( this && this.isLineSegments ) ? 2 : 1; 28737 28738 if ( geometry.isBufferGeometry ) { 28739 28740 var index = geometry.index; 28741 var attributes = geometry.attributes; 28742 var positions = attributes.position.array; 28743 28744 if ( index !== null ) { 28745 28746 var indices = index.array; 28747 28748 for ( var i = 0, l = indices.length - 1; i < l; i += step ) { 28749 28750 var a = indices[ i ]; 28751 var b = indices[ i + 1 ]; 28752 28753 vStart.fromArray( positions, a * 3 ); 28754 vEnd.fromArray( positions, b * 3 ); 28755 28756 var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); 28757 28758 if ( distSq > precisionSq ) continue; 28759 28760 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation 28761 28762 var distance = raycaster.ray.origin.distanceTo( interRay ); 28763 28764 if ( distance < raycaster.near || distance > raycaster.far ) continue; 28765 28766 intersects.push( { 28767 28768 distance: distance, 28769 // What do we want? intersection point on the ray or on the segment?? 28770 // point: raycaster.ray.at( distance ), 28771 point: interSegment.clone().applyMatrix4( this.matrixWorld ), 28772 index: i, 28773 face: null, 28774 faceIndex: null, 28775 object: this 28776 28777 } ); 28778 28779 } 28780 28781 } else { 28782 28783 for ( var i = 0, l = positions.length / 3 - 1; i < l; i += step ) { 28784 28785 vStart.fromArray( positions, 3 * i ); 28786 vEnd.fromArray( positions, 3 * i + 3 ); 28787 28788 var distSq = ray.distanceSqToSegment( vStart, vEnd, interRay, interSegment ); 28789 28790 if ( distSq > precisionSq ) continue; 28791 28792 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation 28793 28794 var distance = raycaster.ray.origin.distanceTo( interRay ); 28795 28796 if ( distance < raycaster.near || distance > raycaster.far ) continue; 28797 28798 intersects.push( { 28799 28800 distance: distance, 28801 // What do we want? intersection point on the ray or on the segment?? 28802 // point: raycaster.ray.at( distance ), 28803 point: interSegment.clone().applyMatrix4( this.matrixWorld ), 28804 index: i, 28805 face: null, 28806 faceIndex: null, 28807 object: this 28808 28809 } ); 28810 28811 } 28812 28813 } 28814 28815 } else if ( geometry.isGeometry ) { 28816 28817 var vertices = geometry.vertices; 28818 var nbVertices = vertices.length; 28819 28820 for ( var i = 0; i < nbVertices - 1; i += step ) { 28821 28822 var distSq = ray.distanceSqToSegment( vertices[ i ], vertices[ i + 1 ], interRay, interSegment ); 28823 28824 if ( distSq > precisionSq ) continue; 28825 28826 interRay.applyMatrix4( this.matrixWorld ); //Move back to world space for distance calculation 28827 28828 var distance = raycaster.ray.origin.distanceTo( interRay ); 28829 28830 if ( distance < raycaster.near || distance > raycaster.far ) continue; 28831 28832 intersects.push( { 28833 28834 distance: distance, 28835 // What do we want? intersection point on the ray or on the segment?? 28836 // point: raycaster.ray.at( distance ), 28837 point: interSegment.clone().applyMatrix4( this.matrixWorld ), 28838 index: i, 28839 face: null, 28840 faceIndex: null, 28841 object: this 28842 28843 } ); 28844 28845 } 28846 28847 } 28848 28849 }; 28850 28851 }() ), 28852 28853 clone: function () { 28854 28855 return new this.constructor( this.geometry, this.material ).copy( this ); 28856 28857 } 28858 28859 } ); 28860 28861 /** 28862 * @author mrdoob / http://mrdoob.com/ 28863 */ 28864 28865 function LineSegments( geometry, material ) { 28866 28867 Line.call( this, geometry, material ); 28868 28869 this.type = 'LineSegments'; 28870 28871 } 28872 28873 LineSegments.prototype = Object.assign( Object.create( Line.prototype ), { 28874 28875 constructor: LineSegments, 28876 28877 isLineSegments: true, 28878 28879 computeLineDistances: ( function () { 28880 28881 var start = new Vector3(); 28882 var end = new Vector3(); 28883 28884 return function computeLineDistances() { 28885 28886 var geometry = this.geometry; 28887 28888 if ( geometry.isBufferGeometry ) { 28889 28890 // we assume non-indexed geometry 28891 28892 if ( geometry.index === null ) { 28893 28894 var positionAttribute = geometry.attributes.position; 28895 var lineDistances = []; 28896 28897 for ( var i = 0, l = positionAttribute.count; i < l; i += 2 ) { 28898 28899 start.fromBufferAttribute( positionAttribute, i ); 28900 end.fromBufferAttribute( positionAttribute, i + 1 ); 28901 28902 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; 28903 lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end ); 28904 28905 } 28906 28907 geometry.addAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); 28908 28909 } else { 28910 28911 console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); 28912 28913 } 28914 28915 } else if ( geometry.isGeometry ) { 28916 28917 var vertices = geometry.vertices; 28918 var lineDistances = geometry.lineDistances; 28919 28920 for ( var i = 0, l = vertices.length; i < l; i += 2 ) { 28921 28922 start.copy( vertices[ i ] ); 28923 end.copy( vertices[ i + 1 ] ); 28924 28925 lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; 28926 lineDistances[ i + 1 ] = lineDistances[ i ] + start.distanceTo( end ); 28927 28928 } 28929 28930 } 28931 28932 return this; 28933 28934 }; 28935 28936 }() ) 28937 28938 } ); 28939 28940 /** 28941 * @author mgreter / http://github.com/mgreter 28942 */ 28943 28944 function LineLoop( geometry, material ) { 28945 28946 Line.call( this, geometry, material ); 28947 28948 this.type = 'LineLoop'; 28949 28950 } 28951 28952 LineLoop.prototype = Object.assign( Object.create( Line.prototype ), { 28953 28954 constructor: LineLoop, 28955 28956 isLineLoop: true, 28957 28958 } ); 28959 28960 /** 28961 * @author mrdoob / http://mrdoob.com/ 28962 * @author alteredq / http://alteredqualia.com/ 28963 * 28964 * parameters = { 28965 * color: <hex>, 28966 * opacity: <float>, 28967 * map: new THREE.Texture( <Image> ), 28968 * 28969 * size: <float>, 28970 * sizeAttenuation: <bool> 28971 * 28972 * morphTargets: <bool> 28973 * } 28974 */ 28975 28976 function PointsMaterial( parameters ) { 28977 28978 Material.call( this ); 28979 28980 this.type = 'PointsMaterial'; 28981 28982 this.color = new Color( 0xffffff ); 28983 28984 this.map = null; 28985 28986 this.size = 1; 28987 this.sizeAttenuation = true; 28988 28989 this.morphTargets = false; 28990 28991 this.lights = false; 28992 28993 this.setValues( parameters ); 28994 28995 } 28996 28997 PointsMaterial.prototype = Object.create( Material.prototype ); 28998 PointsMaterial.prototype.constructor = PointsMaterial; 28999 29000 PointsMaterial.prototype.isPointsMaterial = true; 29001 29002 PointsMaterial.prototype.copy = function ( source ) { 29003 29004 Material.prototype.copy.call( this, source ); 29005 29006 this.color.copy( source.color ); 29007 29008 this.map = source.map; 29009 29010 this.size = source.size; 29011 this.sizeAttenuation = source.sizeAttenuation; 29012 29013 this.morphTargets = source.morphTargets; 29014 29015 return this; 29016 29017 }; 29018 29019 /** 29020 * @author alteredq / http://alteredqualia.com/ 29021 */ 29022 29023 function Points( geometry, material ) { 29024 29025 Object3D.call( this ); 29026 29027 this.type = 'Points'; 29028 29029 this.geometry = geometry !== undefined ? geometry : new BufferGeometry(); 29030 this.material = material !== undefined ? material : new PointsMaterial( { color: Math.random() * 0xffffff } ); 29031 29032 } 29033 29034 Points.prototype = Object.assign( Object.create( Object3D.prototype ), { 29035 29036 constructor: Points, 29037 29038 isPoints: true, 29039 29040 raycast: ( function () { 29041 29042 var inverseMatrix = new Matrix4(); 29043 var ray = new Ray(); 29044 var sphere = new Sphere(); 29045 29046 return function raycast( raycaster, intersects ) { 29047 29048 var object = this; 29049 var geometry = this.geometry; 29050 var matrixWorld = this.matrixWorld; 29051 var threshold = raycaster.params.Points.threshold; 29052 29053 // Checking boundingSphere distance to ray 29054 29055 if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); 29056 29057 sphere.copy( geometry.boundingSphere ); 29058 sphere.applyMatrix4( matrixWorld ); 29059 sphere.radius += threshold; 29060 29061 if ( raycaster.ray.intersectsSphere( sphere ) === false ) return; 29062 29063 // 29064 29065 inverseMatrix.getInverse( matrixWorld ); 29066 ray.copy( raycaster.ray ).applyMatrix4( inverseMatrix ); 29067 29068 var localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); 29069 var localThresholdSq = localThreshold * localThreshold; 29070 var position = new Vector3(); 29071 var intersectPoint = new Vector3(); 29072 29073 function testPoint( point, index ) { 29074 29075 var rayPointDistanceSq = ray.distanceSqToPoint( point ); 29076 29077 if ( rayPointDistanceSq < localThresholdSq ) { 29078 29079 ray.closestPointToPoint( point, intersectPoint ); 29080 intersectPoint.applyMatrix4( matrixWorld ); 29081 29082 var distance = raycaster.ray.origin.distanceTo( intersectPoint ); 29083 29084 if ( distance < raycaster.near || distance > raycaster.far ) return; 29085 29086 intersects.push( { 29087 29088 distance: distance, 29089 distanceToRay: Math.sqrt( rayPointDistanceSq ), 29090 point: intersectPoint.clone(), 29091 index: index, 29092 face: null, 29093 object: object 29094 29095 } ); 29096 29097 } 29098 29099 } 29100 29101 if ( geometry.isBufferGeometry ) { 29102 29103 var index = geometry.index; 29104 var attributes = geometry.attributes; 29105 var positions = attributes.position.array; 29106 29107 if ( index !== null ) { 29108 29109 var indices = index.array; 29110 29111 for ( var i = 0, il = indices.length; i < il; i ++ ) { 29112 29113 var a = indices[ i ]; 29114 29115 position.fromArray( positions, a * 3 ); 29116 29117 testPoint( position, a ); 29118 29119 } 29120 29121 } else { 29122 29123 for ( var i = 0, l = positions.length / 3; i < l; i ++ ) { 29124 29125 position.fromArray( positions, i * 3 ); 29126 29127 testPoint( position, i ); 29128 29129 } 29130 29131 } 29132 29133 } else { 29134 29135 var vertices = geometry.vertices; 29136 29137 for ( var i = 0, l = vertices.length; i < l; i ++ ) { 29138 29139 testPoint( vertices[ i ], i ); 29140 29141 } 29142 29143 } 29144 29145 }; 29146 29147 }() ), 29148 29149 clone: function () { 29150 29151 return new this.constructor( this.geometry, this.material ).copy( this ); 29152 29153 } 29154 29155 } ); 29156 29157 /** 29158 * @author mrdoob / http://mrdoob.com/ 29159 */ 29160 29161 function Group() { 29162 29163 Object3D.call( this ); 29164 29165 this.type = 'Group'; 29166 29167 } 29168 29169 Group.prototype = Object.assign( Object.create( Object3D.prototype ), { 29170 29171 constructor: Group, 29172 29173 isGroup: true 29174 29175 } ); 29176 29177 /** 29178 * @author mrdoob / http://mrdoob.com/ 29179 */ 29180 29181 function VideoTexture( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { 29182 29183 Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 29184 29185 this.generateMipmaps = false; 29186 29187 } 29188 29189 VideoTexture.prototype = Object.assign( Object.create( Texture.prototype ), { 29190 29191 constructor: VideoTexture, 29192 29193 isVideoTexture: true, 29194 29195 update: function () { 29196 29197 var video = this.image; 29198 29199 if ( video.readyState >= video.HAVE_CURRENT_DATA ) { 29200 29201 this.needsUpdate = true; 29202 29203 } 29204 29205 } 29206 29207 } ); 29208 29209 /** 29210 * @author alteredq / http://alteredqualia.com/ 29211 */ 29212 29213 function CompressedTexture( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, encoding ) { 29214 29215 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, encoding ); 29216 29217 this.image = { width: width, height: height }; 29218 this.mipmaps = mipmaps; 29219 29220 // no flipping for cube textures 29221 // (also flipping doesn't work for compressed textures ) 29222 29223 this.flipY = false; 29224 29225 // can't generate mipmaps for compressed textures 29226 // mips must be embedded in DDS files 29227 29228 this.generateMipmaps = false; 29229 29230 } 29231 29232 CompressedTexture.prototype = Object.create( Texture.prototype ); 29233 CompressedTexture.prototype.constructor = CompressedTexture; 29234 29235 CompressedTexture.prototype.isCompressedTexture = true; 29236 29237 /** 29238 * @author Matt DesLauriers / @mattdesl 29239 * @author atix / arthursilber.de 29240 */ 29241 29242 function DepthTexture( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format ) { 29243 29244 format = format !== undefined ? format : DepthFormat; 29245 29246 if ( format !== DepthFormat && format !== DepthStencilFormat ) { 29247 29248 throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); 29249 29250 } 29251 29252 if ( type === undefined && format === DepthFormat ) type = UnsignedShortType; 29253 if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; 29254 29255 Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); 29256 29257 this.image = { width: width, height: height }; 29258 29259 this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; 29260 this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; 29261 29262 this.flipY = false; 29263 this.generateMipmaps = false; 29264 29265 } 29266 29267 DepthTexture.prototype = Object.create( Texture.prototype ); 29268 DepthTexture.prototype.constructor = DepthTexture; 29269 DepthTexture.prototype.isDepthTexture = true; 29270 29271 /** 29272 * @author mrdoob / http://mrdoob.com/ 29273 * @author Mugen87 / https://github.com/Mugen87 29274 */ 29275 29276 function WireframeGeometry( geometry ) { 29277 29278 BufferGeometry.call( this ); 29279 29280 this.type = 'WireframeGeometry'; 29281 29282 // buffer 29283 29284 var vertices = []; 29285 29286 // helper variables 29287 29288 var i, j, l, o, ol; 29289 var edge = [ 0, 0 ], edges = {}, e, edge1, edge2; 29290 var key, keys = [ 'a', 'b', 'c' ]; 29291 var vertex; 29292 29293 // different logic for Geometry and BufferGeometry 29294 29295 if ( geometry && geometry.isGeometry ) { 29296 29297 // create a data structure that contains all edges without duplicates 29298 29299 var faces = geometry.faces; 29300 29301 for ( i = 0, l = faces.length; i < l; i ++ ) { 29302 29303 var face = faces[ i ]; 29304 29305 for ( j = 0; j < 3; j ++ ) { 29306 29307 edge1 = face[ keys[ j ] ]; 29308 edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; 29309 edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates 29310 edge[ 1 ] = Math.max( edge1, edge2 ); 29311 29312 key = edge[ 0 ] + ',' + edge[ 1 ]; 29313 29314 if ( edges[ key ] === undefined ) { 29315 29316 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; 29317 29318 } 29319 29320 } 29321 29322 } 29323 29324 // generate vertices 29325 29326 for ( key in edges ) { 29327 29328 e = edges[ key ]; 29329 29330 vertex = geometry.vertices[ e.index1 ]; 29331 vertices.push( vertex.x, vertex.y, vertex.z ); 29332 29333 vertex = geometry.vertices[ e.index2 ]; 29334 vertices.push( vertex.x, vertex.y, vertex.z ); 29335 29336 } 29337 29338 } else if ( geometry && geometry.isBufferGeometry ) { 29339 29340 var position, indices, groups; 29341 var group, start, count; 29342 var index1, index2; 29343 29344 vertex = new Vector3(); 29345 29346 if ( geometry.index !== null ) { 29347 29348 // indexed BufferGeometry 29349 29350 position = geometry.attributes.position; 29351 indices = geometry.index; 29352 groups = geometry.groups; 29353 29354 if ( groups.length === 0 ) { 29355 29356 groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; 29357 29358 } 29359 29360 // create a data structure that contains all eges without duplicates 29361 29362 for ( o = 0, ol = groups.length; o < ol; ++ o ) { 29363 29364 group = groups[ o ]; 29365 29366 start = group.start; 29367 count = group.count; 29368 29369 for ( i = start, l = ( start + count ); i < l; i += 3 ) { 29370 29371 for ( j = 0; j < 3; j ++ ) { 29372 29373 edge1 = indices.getX( i + j ); 29374 edge2 = indices.getX( i + ( j + 1 ) % 3 ); 29375 edge[ 0 ] = Math.min( edge1, edge2 ); // sorting prevents duplicates 29376 edge[ 1 ] = Math.max( edge1, edge2 ); 29377 29378 key = edge[ 0 ] + ',' + edge[ 1 ]; 29379 29380 if ( edges[ key ] === undefined ) { 29381 29382 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ] }; 29383 29384 } 29385 29386 } 29387 29388 } 29389 29390 } 29391 29392 // generate vertices 29393 29394 for ( key in edges ) { 29395 29396 e = edges[ key ]; 29397 29398 vertex.fromBufferAttribute( position, e.index1 ); 29399 vertices.push( vertex.x, vertex.y, vertex.z ); 29400 29401 vertex.fromBufferAttribute( position, e.index2 ); 29402 vertices.push( vertex.x, vertex.y, vertex.z ); 29403 29404 } 29405 29406 } else { 29407 29408 // non-indexed BufferGeometry 29409 29410 position = geometry.attributes.position; 29411 29412 for ( i = 0, l = ( position.count / 3 ); i < l; i ++ ) { 29413 29414 for ( j = 0; j < 3; j ++ ) { 29415 29416 // three edges per triangle, an edge is represented as (index1, index2) 29417 // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) 29418 29419 index1 = 3 * i + j; 29420 vertex.fromBufferAttribute( position, index1 ); 29421 vertices.push( vertex.x, vertex.y, vertex.z ); 29422 29423 index2 = 3 * i + ( ( j + 1 ) % 3 ); 29424 vertex.fromBufferAttribute( position, index2 ); 29425 vertices.push( vertex.x, vertex.y, vertex.z ); 29426 29427 } 29428 29429 } 29430 29431 } 29432 29433 } 29434 29435 // build geometry 29436 29437 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 29438 29439 } 29440 29441 WireframeGeometry.prototype = Object.create( BufferGeometry.prototype ); 29442 WireframeGeometry.prototype.constructor = WireframeGeometry; 29443 29444 /** 29445 * @author zz85 / https://github.com/zz85 29446 * @author Mugen87 / https://github.com/Mugen87 29447 * 29448 * Parametric Surfaces Geometry 29449 * based on the brilliant article by @prideout http://prideout.net/blog/?p=44 29450 */ 29451 29452 // ParametricGeometry 29453 29454 function ParametricGeometry( func, slices, stacks ) { 29455 29456 Geometry.call( this ); 29457 29458 this.type = 'ParametricGeometry'; 29459 29460 this.parameters = { 29461 func: func, 29462 slices: slices, 29463 stacks: stacks 29464 }; 29465 29466 this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) ); 29467 this.mergeVertices(); 29468 29469 } 29470 29471 ParametricGeometry.prototype = Object.create( Geometry.prototype ); 29472 ParametricGeometry.prototype.constructor = ParametricGeometry; 29473 29474 // ParametricBufferGeometry 29475 29476 function ParametricBufferGeometry( func, slices, stacks ) { 29477 29478 BufferGeometry.call( this ); 29479 29480 this.type = 'ParametricBufferGeometry'; 29481 29482 this.parameters = { 29483 func: func, 29484 slices: slices, 29485 stacks: stacks 29486 }; 29487 29488 // buffers 29489 29490 var indices = []; 29491 var vertices = []; 29492 var normals = []; 29493 var uvs = []; 29494 29495 var EPS = 0.00001; 29496 29497 var normal = new Vector3(); 29498 29499 var p0 = new Vector3(), p1 = new Vector3(); 29500 var pu = new Vector3(), pv = new Vector3(); 29501 29502 var i, j; 29503 29504 if ( func.length < 3 ) { 29505 29506 console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' ); 29507 29508 } 29509 29510 // generate vertices, normals and uvs 29511 29512 var sliceCount = slices + 1; 29513 29514 for ( i = 0; i <= stacks; i ++ ) { 29515 29516 var v = i / stacks; 29517 29518 for ( j = 0; j <= slices; j ++ ) { 29519 29520 var u = j / slices; 29521 29522 // vertex 29523 29524 func( u, v, p0 ); 29525 vertices.push( p0.x, p0.y, p0.z ); 29526 29527 // normal 29528 29529 // approximate tangent vectors via finite differences 29530 29531 if ( u - EPS >= 0 ) { 29532 29533 func( u - EPS, v, p1 ); 29534 pu.subVectors( p0, p1 ); 29535 29536 } else { 29537 29538 func( u + EPS, v, p1 ); 29539 pu.subVectors( p1, p0 ); 29540 29541 } 29542 29543 if ( v - EPS >= 0 ) { 29544 29545 func( u, v - EPS, p1 ); 29546 pv.subVectors( p0, p1 ); 29547 29548 } else { 29549 29550 func( u, v + EPS, p1 ); 29551 pv.subVectors( p1, p0 ); 29552 29553 } 29554 29555 // cross product of tangent vectors returns surface normal 29556 29557 normal.crossVectors( pu, pv ).normalize(); 29558 normals.push( normal.x, normal.y, normal.z ); 29559 29560 // uv 29561 29562 uvs.push( u, v ); 29563 29564 } 29565 29566 } 29567 29568 // generate indices 29569 29570 for ( i = 0; i < stacks; i ++ ) { 29571 29572 for ( j = 0; j < slices; j ++ ) { 29573 29574 var a = i * sliceCount + j; 29575 var b = i * sliceCount + j + 1; 29576 var c = ( i + 1 ) * sliceCount + j + 1; 29577 var d = ( i + 1 ) * sliceCount + j; 29578 29579 // faces one and two 29580 29581 indices.push( a, b, d ); 29582 indices.push( b, c, d ); 29583 29584 } 29585 29586 } 29587 29588 // build geometry 29589 29590 this.setIndex( indices ); 29591 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 29592 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 29593 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 29594 29595 } 29596 29597 ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 29598 ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry; 29599 29600 /** 29601 * @author clockworkgeek / https://github.com/clockworkgeek 29602 * @author timothypratley / https://github.com/timothypratley 29603 * @author WestLangley / http://github.com/WestLangley 29604 * @author Mugen87 / https://github.com/Mugen87 29605 */ 29606 29607 // PolyhedronGeometry 29608 29609 function PolyhedronGeometry( vertices, indices, radius, detail ) { 29610 29611 Geometry.call( this ); 29612 29613 this.type = 'PolyhedronGeometry'; 29614 29615 this.parameters = { 29616 vertices: vertices, 29617 indices: indices, 29618 radius: radius, 29619 detail: detail 29620 }; 29621 29622 this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) ); 29623 this.mergeVertices(); 29624 29625 } 29626 29627 PolyhedronGeometry.prototype = Object.create( Geometry.prototype ); 29628 PolyhedronGeometry.prototype.constructor = PolyhedronGeometry; 29629 29630 // PolyhedronBufferGeometry 29631 29632 function PolyhedronBufferGeometry( vertices, indices, radius, detail ) { 29633 29634 BufferGeometry.call( this ); 29635 29636 this.type = 'PolyhedronBufferGeometry'; 29637 29638 this.parameters = { 29639 vertices: vertices, 29640 indices: indices, 29641 radius: radius, 29642 detail: detail 29643 }; 29644 29645 radius = radius || 1; 29646 detail = detail || 0; 29647 29648 // default buffer data 29649 29650 var vertexBuffer = []; 29651 var uvBuffer = []; 29652 29653 // the subdivision creates the vertex buffer data 29654 29655 subdivide( detail ); 29656 29657 // all vertices should lie on a conceptual sphere with a given radius 29658 29659 appplyRadius( radius ); 29660 29661 // finally, create the uv data 29662 29663 generateUVs(); 29664 29665 // build non-indexed geometry 29666 29667 this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); 29668 this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); 29669 this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); 29670 29671 if ( detail === 0 ) { 29672 29673 this.computeVertexNormals(); // flat normals 29674 29675 } else { 29676 29677 this.normalizeNormals(); // smooth normals 29678 29679 } 29680 29681 // helper functions 29682 29683 function subdivide( detail ) { 29684 29685 var a = new Vector3(); 29686 var b = new Vector3(); 29687 var c = new Vector3(); 29688 29689 // iterate over all faces and apply a subdivison with the given detail value 29690 29691 for ( var i = 0; i < indices.length; i += 3 ) { 29692 29693 // get the vertices of the face 29694 29695 getVertexByIndex( indices[ i + 0 ], a ); 29696 getVertexByIndex( indices[ i + 1 ], b ); 29697 getVertexByIndex( indices[ i + 2 ], c ); 29698 29699 // perform subdivision 29700 29701 subdivideFace( a, b, c, detail ); 29702 29703 } 29704 29705 } 29706 29707 function subdivideFace( a, b, c, detail ) { 29708 29709 var cols = Math.pow( 2, detail ); 29710 29711 // we use this multidimensional array as a data structure for creating the subdivision 29712 29713 var v = []; 29714 29715 var i, j; 29716 29717 // construct all of the vertices for this subdivision 29718 29719 for ( i = 0; i <= cols; i ++ ) { 29720 29721 v[ i ] = []; 29722 29723 var aj = a.clone().lerp( c, i / cols ); 29724 var bj = b.clone().lerp( c, i / cols ); 29725 29726 var rows = cols - i; 29727 29728 for ( j = 0; j <= rows; j ++ ) { 29729 29730 if ( j === 0 && i === cols ) { 29731 29732 v[ i ][ j ] = aj; 29733 29734 } else { 29735 29736 v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); 29737 29738 } 29739 29740 } 29741 29742 } 29743 29744 // construct all of the faces 29745 29746 for ( i = 0; i < cols; i ++ ) { 29747 29748 for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { 29749 29750 var k = Math.floor( j / 2 ); 29751 29752 if ( j % 2 === 0 ) { 29753 29754 pushVertex( v[ i ][ k + 1 ] ); 29755 pushVertex( v[ i + 1 ][ k ] ); 29756 pushVertex( v[ i ][ k ] ); 29757 29758 } else { 29759 29760 pushVertex( v[ i ][ k + 1 ] ); 29761 pushVertex( v[ i + 1 ][ k + 1 ] ); 29762 pushVertex( v[ i + 1 ][ k ] ); 29763 29764 } 29765 29766 } 29767 29768 } 29769 29770 } 29771 29772 function appplyRadius( radius ) { 29773 29774 var vertex = new Vector3(); 29775 29776 // iterate over the entire buffer and apply the radius to each vertex 29777 29778 for ( var i = 0; i < vertexBuffer.length; i += 3 ) { 29779 29780 vertex.x = vertexBuffer[ i + 0 ]; 29781 vertex.y = vertexBuffer[ i + 1 ]; 29782 vertex.z = vertexBuffer[ i + 2 ]; 29783 29784 vertex.normalize().multiplyScalar( radius ); 29785 29786 vertexBuffer[ i + 0 ] = vertex.x; 29787 vertexBuffer[ i + 1 ] = vertex.y; 29788 vertexBuffer[ i + 2 ] = vertex.z; 29789 29790 } 29791 29792 } 29793 29794 function generateUVs() { 29795 29796 var vertex = new Vector3(); 29797 29798 for ( var i = 0; i < vertexBuffer.length; i += 3 ) { 29799 29800 vertex.x = vertexBuffer[ i + 0 ]; 29801 vertex.y = vertexBuffer[ i + 1 ]; 29802 vertex.z = vertexBuffer[ i + 2 ]; 29803 29804 var u = azimuth( vertex ) / 2 / Math.PI + 0.5; 29805 var v = inclination( vertex ) / Math.PI + 0.5; 29806 uvBuffer.push( u, 1 - v ); 29807 29808 } 29809 29810 correctUVs(); 29811 29812 correctSeam(); 29813 29814 } 29815 29816 function correctSeam() { 29817 29818 // handle case when face straddles the seam, see #3269 29819 29820 for ( var i = 0; i < uvBuffer.length; i += 6 ) { 29821 29822 // uv data of a single face 29823 29824 var x0 = uvBuffer[ i + 0 ]; 29825 var x1 = uvBuffer[ i + 2 ]; 29826 var x2 = uvBuffer[ i + 4 ]; 29827 29828 var max = Math.max( x0, x1, x2 ); 29829 var min = Math.min( x0, x1, x2 ); 29830 29831 // 0.9 is somewhat arbitrary 29832 29833 if ( max > 0.9 && min < 0.1 ) { 29834 29835 if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1; 29836 if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1; 29837 if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1; 29838 29839 } 29840 29841 } 29842 29843 } 29844 29845 function pushVertex( vertex ) { 29846 29847 vertexBuffer.push( vertex.x, vertex.y, vertex.z ); 29848 29849 } 29850 29851 function getVertexByIndex( index, vertex ) { 29852 29853 var stride = index * 3; 29854 29855 vertex.x = vertices[ stride + 0 ]; 29856 vertex.y = vertices[ stride + 1 ]; 29857 vertex.z = vertices[ stride + 2 ]; 29858 29859 } 29860 29861 function correctUVs() { 29862 29863 var a = new Vector3(); 29864 var b = new Vector3(); 29865 var c = new Vector3(); 29866 29867 var centroid = new Vector3(); 29868 29869 var uvA = new Vector2(); 29870 var uvB = new Vector2(); 29871 var uvC = new Vector2(); 29872 29873 for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { 29874 29875 a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); 29876 b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); 29877 c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); 29878 29879 uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] ); 29880 uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] ); 29881 uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] ); 29882 29883 centroid.copy( a ).add( b ).add( c ).divideScalar( 3 ); 29884 29885 var azi = azimuth( centroid ); 29886 29887 correctUV( uvA, j + 0, a, azi ); 29888 correctUV( uvB, j + 2, b, azi ); 29889 correctUV( uvC, j + 4, c, azi ); 29890 29891 } 29892 29893 } 29894 29895 function correctUV( uv, stride, vector, azimuth ) { 29896 29897 if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { 29898 29899 uvBuffer[ stride ] = uv.x - 1; 29900 29901 } 29902 29903 if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { 29904 29905 uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; 29906 29907 } 29908 29909 } 29910 29911 // Angle around the Y axis, counter-clockwise when looking from above. 29912 29913 function azimuth( vector ) { 29914 29915 return Math.atan2( vector.z, - vector.x ); 29916 29917 } 29918 29919 29920 // Angle above the XZ plane. 29921 29922 function inclination( vector ) { 29923 29924 return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); 29925 29926 } 29927 29928 } 29929 29930 PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 29931 PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry; 29932 29933 /** 29934 * @author timothypratley / https://github.com/timothypratley 29935 * @author Mugen87 / https://github.com/Mugen87 29936 */ 29937 29938 // TetrahedronGeometry 29939 29940 function TetrahedronGeometry( radius, detail ) { 29941 29942 Geometry.call( this ); 29943 29944 this.type = 'TetrahedronGeometry'; 29945 29946 this.parameters = { 29947 radius: radius, 29948 detail: detail 29949 }; 29950 29951 this.fromBufferGeometry( new TetrahedronBufferGeometry( radius, detail ) ); 29952 this.mergeVertices(); 29953 29954 } 29955 29956 TetrahedronGeometry.prototype = Object.create( Geometry.prototype ); 29957 TetrahedronGeometry.prototype.constructor = TetrahedronGeometry; 29958 29959 // TetrahedronBufferGeometry 29960 29961 function TetrahedronBufferGeometry( radius, detail ) { 29962 29963 var vertices = [ 29964 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 29965 ]; 29966 29967 var indices = [ 29968 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 29969 ]; 29970 29971 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); 29972 29973 this.type = 'TetrahedronBufferGeometry'; 29974 29975 this.parameters = { 29976 radius: radius, 29977 detail: detail 29978 }; 29979 29980 } 29981 29982 TetrahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); 29983 TetrahedronBufferGeometry.prototype.constructor = TetrahedronBufferGeometry; 29984 29985 /** 29986 * @author timothypratley / https://github.com/timothypratley 29987 * @author Mugen87 / https://github.com/Mugen87 29988 */ 29989 29990 // OctahedronGeometry 29991 29992 function OctahedronGeometry( radius, detail ) { 29993 29994 Geometry.call( this ); 29995 29996 this.type = 'OctahedronGeometry'; 29997 29998 this.parameters = { 29999 radius: radius, 30000 detail: detail 30001 }; 30002 30003 this.fromBufferGeometry( new OctahedronBufferGeometry( radius, detail ) ); 30004 this.mergeVertices(); 30005 30006 } 30007 30008 OctahedronGeometry.prototype = Object.create( Geometry.prototype ); 30009 OctahedronGeometry.prototype.constructor = OctahedronGeometry; 30010 30011 // OctahedronBufferGeometry 30012 30013 function OctahedronBufferGeometry( radius, detail ) { 30014 30015 var vertices = [ 30016 1, 0, 0, - 1, 0, 0, 0, 1, 0, 30017 0, - 1, 0, 0, 0, 1, 0, 0, - 1 30018 ]; 30019 30020 var indices = [ 30021 0, 2, 4, 0, 4, 3, 0, 3, 5, 30022 0, 5, 2, 1, 2, 5, 1, 5, 3, 30023 1, 3, 4, 1, 4, 2 30024 ]; 30025 30026 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); 30027 30028 this.type = 'OctahedronBufferGeometry'; 30029 30030 this.parameters = { 30031 radius: radius, 30032 detail: detail 30033 }; 30034 30035 } 30036 30037 OctahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); 30038 OctahedronBufferGeometry.prototype.constructor = OctahedronBufferGeometry; 30039 30040 /** 30041 * @author timothypratley / https://github.com/timothypratley 30042 * @author Mugen87 / https://github.com/Mugen87 30043 */ 30044 30045 // IcosahedronGeometry 30046 30047 function IcosahedronGeometry( radius, detail ) { 30048 30049 Geometry.call( this ); 30050 30051 this.type = 'IcosahedronGeometry'; 30052 30053 this.parameters = { 30054 radius: radius, 30055 detail: detail 30056 }; 30057 30058 this.fromBufferGeometry( new IcosahedronBufferGeometry( radius, detail ) ); 30059 this.mergeVertices(); 30060 30061 } 30062 30063 IcosahedronGeometry.prototype = Object.create( Geometry.prototype ); 30064 IcosahedronGeometry.prototype.constructor = IcosahedronGeometry; 30065 30066 // IcosahedronBufferGeometry 30067 30068 function IcosahedronBufferGeometry( radius, detail ) { 30069 30070 var t = ( 1 + Math.sqrt( 5 ) ) / 2; 30071 30072 var vertices = [ 30073 - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0, 30074 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 30075 t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1 30076 ]; 30077 30078 var indices = [ 30079 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, 30080 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, 30081 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, 30082 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 30083 ]; 30084 30085 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); 30086 30087 this.type = 'IcosahedronBufferGeometry'; 30088 30089 this.parameters = { 30090 radius: radius, 30091 detail: detail 30092 }; 30093 30094 } 30095 30096 IcosahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); 30097 IcosahedronBufferGeometry.prototype.constructor = IcosahedronBufferGeometry; 30098 30099 /** 30100 * @author Abe Pazos / https://hamoid.com 30101 * @author Mugen87 / https://github.com/Mugen87 30102 */ 30103 30104 // DodecahedronGeometry 30105 30106 function DodecahedronGeometry( radius, detail ) { 30107 30108 Geometry.call( this ); 30109 30110 this.type = 'DodecahedronGeometry'; 30111 30112 this.parameters = { 30113 radius: radius, 30114 detail: detail 30115 }; 30116 30117 this.fromBufferGeometry( new DodecahedronBufferGeometry( radius, detail ) ); 30118 this.mergeVertices(); 30119 30120 } 30121 30122 DodecahedronGeometry.prototype = Object.create( Geometry.prototype ); 30123 DodecahedronGeometry.prototype.constructor = DodecahedronGeometry; 30124 30125 // DodecahedronBufferGeometry 30126 30127 function DodecahedronBufferGeometry( radius, detail ) { 30128 30129 var t = ( 1 + Math.sqrt( 5 ) ) / 2; 30130 var r = 1 / t; 30131 30132 var vertices = [ 30133 30134 // (±1, ±1, ±1) 30135 - 1, - 1, - 1, - 1, - 1, 1, 30136 - 1, 1, - 1, - 1, 1, 1, 30137 1, - 1, - 1, 1, - 1, 1, 30138 1, 1, - 1, 1, 1, 1, 30139 30140 // (0, ±1/Ï, ±Ï) 30141 0, - r, - t, 0, - r, t, 30142 0, r, - t, 0, r, t, 30143 30144 // (±1/Ï, ±Ï, 0) 30145 - r, - t, 0, - r, t, 0, 30146 r, - t, 0, r, t, 0, 30147 30148 // (±Ï, 0, ±1/Ï) 30149 - t, 0, - r, t, 0, - r, 30150 - t, 0, r, t, 0, r 30151 ]; 30152 30153 var indices = [ 30154 3, 11, 7, 3, 7, 15, 3, 15, 13, 30155 7, 19, 17, 7, 17, 6, 7, 6, 15, 30156 17, 4, 8, 17, 8, 10, 17, 10, 6, 30157 8, 0, 16, 8, 16, 2, 8, 2, 10, 30158 0, 12, 1, 0, 1, 18, 0, 18, 16, 30159 6, 10, 2, 6, 2, 13, 6, 13, 15, 30160 2, 16, 18, 2, 18, 3, 2, 3, 13, 30161 18, 1, 9, 18, 9, 11, 18, 11, 3, 30162 4, 14, 12, 4, 12, 0, 4, 0, 8, 30163 11, 9, 5, 11, 5, 19, 11, 19, 7, 30164 19, 5, 14, 19, 14, 4, 19, 4, 17, 30165 1, 12, 14, 1, 14, 5, 1, 5, 9 30166 ]; 30167 30168 PolyhedronBufferGeometry.call( this, vertices, indices, radius, detail ); 30169 30170 this.type = 'DodecahedronBufferGeometry'; 30171 30172 this.parameters = { 30173 radius: radius, 30174 detail: detail 30175 }; 30176 30177 } 30178 30179 DodecahedronBufferGeometry.prototype = Object.create( PolyhedronBufferGeometry.prototype ); 30180 DodecahedronBufferGeometry.prototype.constructor = DodecahedronBufferGeometry; 30181 30182 /** 30183 * @author oosmoxiecode / https://github.com/oosmoxiecode 30184 * @author WestLangley / https://github.com/WestLangley 30185 * @author zz85 / https://github.com/zz85 30186 * @author miningold / https://github.com/miningold 30187 * @author jonobr1 / https://github.com/jonobr1 30188 * @author Mugen87 / https://github.com/Mugen87 30189 * 30190 */ 30191 30192 // TubeGeometry 30193 30194 function TubeGeometry( path, tubularSegments, radius, radialSegments, closed, taper ) { 30195 30196 Geometry.call( this ); 30197 30198 this.type = 'TubeGeometry'; 30199 30200 this.parameters = { 30201 path: path, 30202 tubularSegments: tubularSegments, 30203 radius: radius, 30204 radialSegments: radialSegments, 30205 closed: closed 30206 }; 30207 30208 if ( taper !== undefined ) console.warn( 'THREE.TubeGeometry: taper has been removed.' ); 30209 30210 var bufferGeometry = new TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ); 30211 30212 // expose internals 30213 30214 this.tangents = bufferGeometry.tangents; 30215 this.normals = bufferGeometry.normals; 30216 this.binormals = bufferGeometry.binormals; 30217 30218 // create geometry 30219 30220 this.fromBufferGeometry( bufferGeometry ); 30221 this.mergeVertices(); 30222 30223 } 30224 30225 TubeGeometry.prototype = Object.create( Geometry.prototype ); 30226 TubeGeometry.prototype.constructor = TubeGeometry; 30227 30228 // TubeBufferGeometry 30229 30230 function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) { 30231 30232 BufferGeometry.call( this ); 30233 30234 this.type = 'TubeBufferGeometry'; 30235 30236 this.parameters = { 30237 path: path, 30238 tubularSegments: tubularSegments, 30239 radius: radius, 30240 radialSegments: radialSegments, 30241 closed: closed 30242 }; 30243 30244 tubularSegments = tubularSegments || 64; 30245 radius = radius || 1; 30246 radialSegments = radialSegments || 8; 30247 closed = closed || false; 30248 30249 var frames = path.computeFrenetFrames( tubularSegments, closed ); 30250 30251 // expose internals 30252 30253 this.tangents = frames.tangents; 30254 this.normals = frames.normals; 30255 this.binormals = frames.binormals; 30256 30257 // helper variables 30258 30259 var vertex = new Vector3(); 30260 var normal = new Vector3(); 30261 var uv = new Vector2(); 30262 var P = new Vector3(); 30263 30264 var i, j; 30265 30266 // buffer 30267 30268 var vertices = []; 30269 var normals = []; 30270 var uvs = []; 30271 var indices = []; 30272 30273 // create buffer data 30274 30275 generateBufferData(); 30276 30277 // build geometry 30278 30279 this.setIndex( indices ); 30280 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 30281 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 30282 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 30283 30284 // functions 30285 30286 function generateBufferData() { 30287 30288 for ( i = 0; i < tubularSegments; i ++ ) { 30289 30290 generateSegment( i ); 30291 30292 } 30293 30294 // if the geometry is not closed, generate the last row of vertices and normals 30295 // at the regular position on the given path 30296 // 30297 // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) 30298 30299 generateSegment( ( closed === false ) ? tubularSegments : 0 ); 30300 30301 // uvs are generated in a separate function. 30302 // this makes it easy compute correct values for closed geometries 30303 30304 generateUVs(); 30305 30306 // finally create faces 30307 30308 generateIndices(); 30309 30310 } 30311 30312 function generateSegment( i ) { 30313 30314 // we use getPointAt to sample evenly distributed points from the given path 30315 30316 P = path.getPointAt( i / tubularSegments, P ); 30317 30318 // retrieve corresponding normal and binormal 30319 30320 var N = frames.normals[ i ]; 30321 var B = frames.binormals[ i ]; 30322 30323 // generate normals and vertices for the current segment 30324 30325 for ( j = 0; j <= radialSegments; j ++ ) { 30326 30327 var v = j / radialSegments * Math.PI * 2; 30328 30329 var sin = Math.sin( v ); 30330 var cos = - Math.cos( v ); 30331 30332 // normal 30333 30334 normal.x = ( cos * N.x + sin * B.x ); 30335 normal.y = ( cos * N.y + sin * B.y ); 30336 normal.z = ( cos * N.z + sin * B.z ); 30337 normal.normalize(); 30338 30339 normals.push( normal.x, normal.y, normal.z ); 30340 30341 // vertex 30342 30343 vertex.x = P.x + radius * normal.x; 30344 vertex.y = P.y + radius * normal.y; 30345 vertex.z = P.z + radius * normal.z; 30346 30347 vertices.push( vertex.x, vertex.y, vertex.z ); 30348 30349 } 30350 30351 } 30352 30353 function generateIndices() { 30354 30355 for ( j = 1; j <= tubularSegments; j ++ ) { 30356 30357 for ( i = 1; i <= radialSegments; i ++ ) { 30358 30359 var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 30360 var b = ( radialSegments + 1 ) * j + ( i - 1 ); 30361 var c = ( radialSegments + 1 ) * j + i; 30362 var d = ( radialSegments + 1 ) * ( j - 1 ) + i; 30363 30364 // faces 30365 30366 indices.push( a, b, d ); 30367 indices.push( b, c, d ); 30368 30369 } 30370 30371 } 30372 30373 } 30374 30375 function generateUVs() { 30376 30377 for ( i = 0; i <= tubularSegments; i ++ ) { 30378 30379 for ( j = 0; j <= radialSegments; j ++ ) { 30380 30381 uv.x = i / tubularSegments; 30382 uv.y = j / radialSegments; 30383 30384 uvs.push( uv.x, uv.y ); 30385 30386 } 30387 30388 } 30389 30390 } 30391 30392 } 30393 30394 TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 30395 TubeBufferGeometry.prototype.constructor = TubeBufferGeometry; 30396 30397 /** 30398 * @author oosmoxiecode 30399 * @author Mugen87 / https://github.com/Mugen87 30400 * 30401 * based on http://www.blackpawn.com/texts/pqtorus/ 30402 */ 30403 30404 // TorusKnotGeometry 30405 30406 function TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) { 30407 30408 Geometry.call( this ); 30409 30410 this.type = 'TorusKnotGeometry'; 30411 30412 this.parameters = { 30413 radius: radius, 30414 tube: tube, 30415 tubularSegments: tubularSegments, 30416 radialSegments: radialSegments, 30417 p: p, 30418 q: q 30419 }; 30420 30421 if ( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' ); 30422 30423 this.fromBufferGeometry( new TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) ); 30424 this.mergeVertices(); 30425 30426 } 30427 30428 TorusKnotGeometry.prototype = Object.create( Geometry.prototype ); 30429 TorusKnotGeometry.prototype.constructor = TorusKnotGeometry; 30430 30431 // TorusKnotBufferGeometry 30432 30433 function TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) { 30434 30435 BufferGeometry.call( this ); 30436 30437 this.type = 'TorusKnotBufferGeometry'; 30438 30439 this.parameters = { 30440 radius: radius, 30441 tube: tube, 30442 tubularSegments: tubularSegments, 30443 radialSegments: radialSegments, 30444 p: p, 30445 q: q 30446 }; 30447 30448 radius = radius || 1; 30449 tube = tube || 0.4; 30450 tubularSegments = Math.floor( tubularSegments ) || 64; 30451 radialSegments = Math.floor( radialSegments ) || 8; 30452 p = p || 2; 30453 q = q || 3; 30454 30455 // buffers 30456 30457 var indices = []; 30458 var vertices = []; 30459 var normals = []; 30460 var uvs = []; 30461 30462 // helper variables 30463 30464 var i, j; 30465 30466 var vertex = new Vector3(); 30467 var normal = new Vector3(); 30468 30469 var P1 = new Vector3(); 30470 var P2 = new Vector3(); 30471 30472 var B = new Vector3(); 30473 var T = new Vector3(); 30474 var N = new Vector3(); 30475 30476 // generate vertices, normals and uvs 30477 30478 for ( i = 0; i <= tubularSegments; ++ i ) { 30479 30480 // the radian "u" is used to calculate the position on the torus curve of the current tubular segement 30481 30482 var u = i / tubularSegments * p * Math.PI * 2; 30483 30484 // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. 30485 // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions 30486 30487 calculatePositionOnCurve( u, p, q, radius, P1 ); 30488 calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); 30489 30490 // calculate orthonormal basis 30491 30492 T.subVectors( P2, P1 ); 30493 N.addVectors( P2, P1 ); 30494 B.crossVectors( T, N ); 30495 N.crossVectors( B, T ); 30496 30497 // normalize B, N. T can be ignored, we don't use it 30498 30499 B.normalize(); 30500 N.normalize(); 30501 30502 for ( j = 0; j <= radialSegments; ++ j ) { 30503 30504 // now calculate the vertices. they are nothing more than an extrusion of the torus curve. 30505 // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. 30506 30507 var v = j / radialSegments * Math.PI * 2; 30508 var cx = - tube * Math.cos( v ); 30509 var cy = tube * Math.sin( v ); 30510 30511 // now calculate the final vertex position. 30512 // first we orient the extrusion with our basis vectos, then we add it to the current position on the curve 30513 30514 vertex.x = P1.x + ( cx * N.x + cy * B.x ); 30515 vertex.y = P1.y + ( cx * N.y + cy * B.y ); 30516 vertex.z = P1.z + ( cx * N.z + cy * B.z ); 30517 30518 vertices.push( vertex.x, vertex.y, vertex.z ); 30519 30520 // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) 30521 30522 normal.subVectors( vertex, P1 ).normalize(); 30523 30524 normals.push( normal.x, normal.y, normal.z ); 30525 30526 // uv 30527 30528 uvs.push( i / tubularSegments ); 30529 uvs.push( j / radialSegments ); 30530 30531 } 30532 30533 } 30534 30535 // generate indices 30536 30537 for ( j = 1; j <= tubularSegments; j ++ ) { 30538 30539 for ( i = 1; i <= radialSegments; i ++ ) { 30540 30541 // indices 30542 30543 var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); 30544 var b = ( radialSegments + 1 ) * j + ( i - 1 ); 30545 var c = ( radialSegments + 1 ) * j + i; 30546 var d = ( radialSegments + 1 ) * ( j - 1 ) + i; 30547 30548 // faces 30549 30550 indices.push( a, b, d ); 30551 indices.push( b, c, d ); 30552 30553 } 30554 30555 } 30556 30557 // build geometry 30558 30559 this.setIndex( indices ); 30560 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 30561 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 30562 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 30563 30564 // this function calculates the current position on the torus curve 30565 30566 function calculatePositionOnCurve( u, p, q, radius, position ) { 30567 30568 var cu = Math.cos( u ); 30569 var su = Math.sin( u ); 30570 var quOverP = q / p * u; 30571 var cs = Math.cos( quOverP ); 30572 30573 position.x = radius * ( 2 + cs ) * 0.5 * cu; 30574 position.y = radius * ( 2 + cs ) * su * 0.5; 30575 position.z = radius * Math.sin( quOverP ) * 0.5; 30576 30577 } 30578 30579 } 30580 30581 TorusKnotBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 30582 TorusKnotBufferGeometry.prototype.constructor = TorusKnotBufferGeometry; 30583 30584 /** 30585 * @author oosmoxiecode 30586 * @author mrdoob / http://mrdoob.com/ 30587 * @author Mugen87 / https://github.com/Mugen87 30588 */ 30589 30590 // TorusGeometry 30591 30592 function TorusGeometry( radius, tube, radialSegments, tubularSegments, arc ) { 30593 30594 Geometry.call( this ); 30595 30596 this.type = 'TorusGeometry'; 30597 30598 this.parameters = { 30599 radius: radius, 30600 tube: tube, 30601 radialSegments: radialSegments, 30602 tubularSegments: tubularSegments, 30603 arc: arc 30604 }; 30605 30606 this.fromBufferGeometry( new TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) ); 30607 this.mergeVertices(); 30608 30609 } 30610 30611 TorusGeometry.prototype = Object.create( Geometry.prototype ); 30612 TorusGeometry.prototype.constructor = TorusGeometry; 30613 30614 // TorusBufferGeometry 30615 30616 function TorusBufferGeometry( radius, tube, radialSegments, tubularSegments, arc ) { 30617 30618 BufferGeometry.call( this ); 30619 30620 this.type = 'TorusBufferGeometry'; 30621 30622 this.parameters = { 30623 radius: radius, 30624 tube: tube, 30625 radialSegments: radialSegments, 30626 tubularSegments: tubularSegments, 30627 arc: arc 30628 }; 30629 30630 radius = radius || 1; 30631 tube = tube || 0.4; 30632 radialSegments = Math.floor( radialSegments ) || 8; 30633 tubularSegments = Math.floor( tubularSegments ) || 6; 30634 arc = arc || Math.PI * 2; 30635 30636 // buffers 30637 30638 var indices = []; 30639 var vertices = []; 30640 var normals = []; 30641 var uvs = []; 30642 30643 // helper variables 30644 30645 var center = new Vector3(); 30646 var vertex = new Vector3(); 30647 var normal = new Vector3(); 30648 30649 var j, i; 30650 30651 // generate vertices, normals and uvs 30652 30653 for ( j = 0; j <= radialSegments; j ++ ) { 30654 30655 for ( i = 0; i <= tubularSegments; i ++ ) { 30656 30657 var u = i / tubularSegments * arc; 30658 var v = j / radialSegments * Math.PI * 2; 30659 30660 // vertex 30661 30662 vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); 30663 vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); 30664 vertex.z = tube * Math.sin( v ); 30665 30666 vertices.push( vertex.x, vertex.y, vertex.z ); 30667 30668 // normal 30669 30670 center.x = radius * Math.cos( u ); 30671 center.y = radius * Math.sin( u ); 30672 normal.subVectors( vertex, center ).normalize(); 30673 30674 normals.push( normal.x, normal.y, normal.z ); 30675 30676 // uv 30677 30678 uvs.push( i / tubularSegments ); 30679 uvs.push( j / radialSegments ); 30680 30681 } 30682 30683 } 30684 30685 // generate indices 30686 30687 for ( j = 1; j <= radialSegments; j ++ ) { 30688 30689 for ( i = 1; i <= tubularSegments; i ++ ) { 30690 30691 // indices 30692 30693 var a = ( tubularSegments + 1 ) * j + i - 1; 30694 var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; 30695 var c = ( tubularSegments + 1 ) * ( j - 1 ) + i; 30696 var d = ( tubularSegments + 1 ) * j + i; 30697 30698 // faces 30699 30700 indices.push( a, b, d ); 30701 indices.push( b, c, d ); 30702 30703 } 30704 30705 } 30706 30707 // build geometry 30708 30709 this.setIndex( indices ); 30710 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 30711 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 30712 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 30713 30714 } 30715 30716 TorusBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 30717 TorusBufferGeometry.prototype.constructor = TorusBufferGeometry; 30718 30719 /** 30720 * @author Mugen87 / https://github.com/Mugen87 30721 * Port from https://github.com/mapbox/earcut (v2.1.2) 30722 */ 30723 30724 var Earcut = { 30725 30726 triangulate: function ( data, holeIndices, dim ) { 30727 30728 dim = dim || 2; 30729 30730 var hasHoles = holeIndices && holeIndices.length, 30731 outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length, 30732 outerNode = linkedList( data, 0, outerLen, dim, true ), 30733 triangles = []; 30734 30735 if ( ! outerNode ) return triangles; 30736 30737 var minX, minY, maxX, maxY, x, y, invSize; 30738 30739 if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); 30740 30741 // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox 30742 30743 if ( data.length > 80 * dim ) { 30744 30745 minX = maxX = data[ 0 ]; 30746 minY = maxY = data[ 1 ]; 30747 30748 for ( var i = dim; i < outerLen; i += dim ) { 30749 30750 x = data[ i ]; 30751 y = data[ i + 1 ]; 30752 if ( x < minX ) minX = x; 30753 if ( y < minY ) minY = y; 30754 if ( x > maxX ) maxX = x; 30755 if ( y > maxY ) maxY = y; 30756 30757 } 30758 30759 // minX, minY and invSize are later used to transform coords into integers for z-order calculation 30760 30761 invSize = Math.max( maxX - minX, maxY - minY ); 30762 invSize = invSize !== 0 ? 1 / invSize : 0; 30763 30764 } 30765 30766 earcutLinked( outerNode, triangles, dim, minX, minY, invSize ); 30767 30768 return triangles; 30769 30770 } 30771 30772 }; 30773 30774 // create a circular doubly linked list from polygon points in the specified winding order 30775 30776 function linkedList( data, start, end, dim, clockwise ) { 30777 30778 var i, last; 30779 30780 if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) { 30781 30782 for ( i = start; i < end;
vendor: 12,853 bytes, lines 30782-31410
30782 i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 30783 30784 } else { 30785 30786 for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); 30787 30788 } 30789 30790 if ( last && equals( last, last.next ) ) { 30791 30792 removeNode( last ); 30793 last = last.next; 30794 30795 } 30796 30797 return last; 30798 30799 } 30800 30801 // eliminate colinear or duplicate points 30802 30803 function filterPoints( start, end ) { 30804 30805 if ( ! start ) return start; 30806 if ( ! end ) end = start; 30807 30808 var p = start, again; 30809 30810 do { 30811 30812 again = false; 30813 30814 if ( ! p.steiner && ( equals( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) { 30815 30816 removeNode( p ); 30817 p = end = p.prev; 30818 if ( p === p.next ) break; 30819 again = true; 30820 30821 } else { 30822 30823 p = p.next; 30824 30825 } 30826 30827 } while ( again || p !== end ); 30828 30829 return end; 30830 30831 } 30832 30833 // main ear slicing loop which triangulates a polygon (given as a linked list) 30834 30835 function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) { 30836 30837 if ( ! ear ) return; 30838 30839 // interlink polygon nodes in z-order 30840 30841 if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize ); 30842 30843 var stop = ear, prev, next; 30844 30845 // iterate through ears, slicing them one by one 30846 30847 while ( ear.prev !== ear.next ) { 30848 30849 prev = ear.prev; 30850 next = ear.next; 30851 30852 if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) { 30853 30854 // cut off the triangle 30855 triangles.push( prev.i / dim ); 30856 triangles.push( ear.i / dim ); 30857 triangles.push( next.i / dim ); 30858 30859 removeNode( ear ); 30860 30861 // skipping the next vertice leads to less sliver triangles 30862 ear = next.next; 30863 stop = next.next; 30864 30865 continue; 30866 30867 } 30868 30869 ear = next; 30870 30871 // if we looped through the whole remaining polygon and can't find any more ears 30872 30873 if ( ear === stop ) { 30874 30875 // try filtering points and slicing again 30876 30877 if ( ! pass ) { 30878 30879 earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 ); 30880 30881 // if this didn't work, try curing all small self-intersections locally 30882 30883 } else if ( pass === 1 ) { 30884 30885 ear = cureLocalIntersections( ear, triangles, dim ); 30886 earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 ); 30887 30888 // as a last resort, try splitting the remaining polygon into two 30889 30890 } else if ( pass === 2 ) { 30891 30892 splitEarcut( ear, triangles, dim, minX, minY, invSize ); 30893 30894 } 30895 30896 break; 30897 30898 } 30899 30900 } 30901 30902 } 30903 30904 // check whether a polygon node forms a valid ear with adjacent nodes 30905 30906 function isEar( ear ) { 30907 30908 var a = ear.prev, 30909 b = ear, 30910 c = ear.next; 30911 30912 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 30913 30914 // now make sure we don't have other points inside the potential ear 30915 var p = ear.next.next; 30916 30917 while ( p !== ear.prev ) { 30918 30919 if ( pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) { 30920 30921 return false; 30922 30923 } 30924 30925 p = p.next; 30926 30927 } 30928 30929 return true; 30930 30931 } 30932 30933 function isEarHashed( ear, minX, minY, invSize ) { 30934 30935 var a = ear.prev, 30936 b = ear, 30937 c = ear.next; 30938 30939 if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear 30940 30941 // triangle bbox; min & max are calculated like this for speed 30942 30943 var minTX = a.x < b.x ? ( a.x < c.x ? a.x : c.x ) : ( b.x < c.x ? b.x : c.x ), 30944 minTY = a.y < b.y ? ( a.y < c.y ? a.y : c.y ) : ( b.y < c.y ? b.y : c.y ), 30945 maxTX = a.x > b.x ? ( a.x > c.x ? a.x : c.x ) : ( b.x > c.x ? b.x : c.x ), 30946 maxTY = a.y > b.y ? ( a.y > c.y ? a.y : c.y ) : ( b.y > c.y ? b.y : c.y ); 30947 30948 // z-order range for the current triangle bbox; 30949 30950 var minZ = zOrder( minTX, minTY, minX, minY, invSize ), 30951 maxZ = zOrder( maxTX, maxTY, minX, minY, invSize ); 30952 30953 // first look for points inside the triangle in increasing z-order 30954 30955 var p = ear.nextZ; 30956 30957 while ( p && p.z <= maxZ ) { 30958 30959 if ( p !== ear.prev && p !== ear.next && 30960 pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && 30961 area( p.prev, p, p.next ) >= 0 ) return false; 30962 p = p.nextZ; 30963 30964 } 30965 30966 // then look for points in decreasing z-order 30967 30968 p = ear.prevZ; 30969 30970 while ( p && p.z >= minZ ) { 30971 30972 if ( p !== ear.prev && p !== ear.next && 30973 pointInTriangle( a.x, a.y, b.x, b.y, c.x, c.y, p.x, p.y ) && 30974 area( p.prev, p, p.next ) >= 0 ) return false; 30975 30976 p = p.prevZ; 30977 30978 } 30979 30980 return true; 30981 30982 } 30983 30984 // go through all polygon nodes and cure small local self-intersections 30985 30986 function cureLocalIntersections( start, triangles, dim ) { 30987 30988 var p = start; 30989 30990 do { 30991 30992 var a = p.prev, b = p.next.next; 30993 30994 if ( ! equals( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) { 30995 30996 triangles.push( a.i / dim ); 30997 triangles.push( p.i / dim ); 30998 triangles.push( b.i / dim ); 30999 31000 // remove two nodes involved 31001 31002 removeNode( p ); 31003 removeNode( p.next ); 31004 31005 p = start = b; 31006 31007 } 31008 31009 p = p.next; 31010 31011 } while ( p !== start ); 31012 31013 return p; 31014 31015 } 31016 31017 // try splitting polygon into two and triangulate them independently 31018 31019 function splitEarcut( start, triangles, dim, minX, minY, invSize ) { 31020 31021 // look for a valid diagonal that divides the polygon into two 31022 31023 var a = start; 31024 31025 do { 31026 31027 var b = a.next.next; 31028 31029 while ( b !== a.prev ) { 31030 31031 if ( a.i !== b.i && isValidDiagonal( a, b ) ) { 31032 31033 // split the polygon in two by the diagonal 31034 31035 var c = splitPolygon( a, b ); 31036 31037 // filter colinear points around the cuts 31038 31039 a = filterPoints( a, a.next ); 31040 c = filterPoints( c, c.next ); 31041 31042 // run earcut on each half 31043 31044 earcutLinked( a, triangles, dim, minX, minY, invSize ); 31045 earcutLinked( c, triangles, dim, minX, minY, invSize ); 31046 return; 31047 31048 } 31049 31050 b = b.next; 31051 31052 } 31053 31054 a = a.next; 31055 31056 } while ( a !== start ); 31057 31058 } 31059 31060 // link every hole into the outer loop, producing a single-ring polygon without holes 31061 31062 function eliminateHoles( data, holeIndices, outerNode, dim ) { 31063 31064 var queue = [], i, len, start, end, list; 31065 31066 for ( i = 0, len = holeIndices.length; i < len; i ++ ) { 31067 31068 start = holeIndices[ i ] * dim; 31069 end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length; 31070 list = linkedList( data, start, end, dim, false ); 31071 if ( list === list.next ) list.steiner = true; 31072 queue.push( getLeftmost( list ) ); 31073 31074 } 31075 31076 queue.sort( compareX ); 31077 31078 // process holes from left to right 31079 31080 for ( i = 0; i < queue.length; i ++ ) { 31081 31082 eliminateHole( queue[ i ], outerNode ); 31083 outerNode = filterPoints( outerNode, outerNode.next ); 31084 31085 } 31086 31087 return outerNode; 31088 31089 } 31090 31091 function compareX( a, b ) { 31092 31093 return a.x - b.x; 31094 31095 } 31096 31097 // find a bridge between vertices that connects hole with an outer ring and and link it 31098 31099 function eliminateHole( hole, outerNode ) { 31100 31101 outerNode = findHoleBridge( hole, outerNode ); 31102 31103 if ( outerNode ) { 31104 31105 var b = splitPolygon( outerNode, hole ); 31106 31107 filterPoints( b, b.next ); 31108 31109 } 31110 31111 } 31112 31113 // David Eberly's algorithm for finding a bridge between hole and outer polygon 31114 31115 function findHoleBridge( hole, outerNode ) { 31116 31117 var p = outerNode, 31118 hx = hole.x, 31119 hy = hole.y, 31120 qx = - Infinity, 31121 m; 31122 31123 // find a segment intersected by a ray from the hole's leftmost point to the left; 31124 // segment's endpoint with lesser x will be potential connection point 31125 31126 do { 31127 31128 if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) { 31129 31130 var x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y ); 31131 31132 if ( x <= hx && x > qx ) { 31133 31134 qx = x; 31135 31136 if ( x === hx ) { 31137 31138 if ( hy === p.y ) return p; 31139 if ( hy === p.next.y ) return p.next; 31140 31141 } 31142 31143 m = p.x < p.next.x ? p : p.next; 31144 31145 } 31146 31147 } 31148 31149 p = p.next; 31150 31151 } while ( p !== outerNode ); 31152 31153 if ( ! m ) return null; 31154 31155 if ( hx === qx ) return m.prev; // hole touches outer segment; pick lower endpoint 31156 31157 // look for points inside the triangle of hole point, segment intersection and endpoint; 31158 // if there are no points found, we have a valid connection; 31159 // otherwise choose the point of the minimum angle with the ray as connection point 31160 31161 var stop = m, 31162 mx = m.x, 31163 my = m.y, 31164 tanMin = Infinity, 31165 tan; 31166 31167 p = m.next; 31168 31169 while ( p !== stop ) { 31170 31171 if ( hx >= p.x && p.x >= mx && hx !== p.x && 31172 pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) { 31173 31174 tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential 31175 31176 if ( ( tan < tanMin || ( tan === tanMin && p.x > m.x ) ) && locallyInside( p, hole ) ) { 31177 31178 m = p; 31179 tanMin = tan; 31180 31181 } 31182 31183 } 31184 31185 p = p.next; 31186 31187 } 31188 31189 return m; 31190 31191 } 31192 31193 // interlink polygon nodes in z-order 31194 31195 function indexCurve( start, minX, minY, invSize ) { 31196 31197 var p = start; 31198 31199 do { 31200 31201 if ( p.z === null ) p.z = zOrder( p.x, p.y, minX, minY, invSize ); 31202 p.prevZ = p.prev; 31203 p.nextZ = p.next; 31204 p = p.next; 31205 31206 } while ( p !== start ); 31207 31208 p.prevZ.nextZ = null; 31209 p.prevZ = null; 31210 31211 sortLinked( p ); 31212 31213 } 31214 31215 // Simon Tatham's linked list merge sort algorithm 31216 // http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html 31217 31218 function sortLinked( list ) { 31219 31220 var i, p, q, e, tail, numMerges, pSize, qSize, inSize = 1; 31221 31222 do { 31223 31224 p = list; 31225 list = null; 31226 tail = null; 31227 numMerges = 0; 31228 31229 while ( p ) { 31230 31231 numMerges ++; 31232 q = p; 31233 pSize = 0; 31234 31235 for ( i = 0; i < inSize; i ++ ) { 31236 31237 pSize ++; 31238 q = q.nextZ; 31239 if ( ! q ) break; 31240 31241 } 31242 31243 qSize = inSize; 31244 31245 while ( pSize > 0 || ( qSize > 0 && q ) ) { 31246 31247 if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) { 31248 31249 e = p; 31250 p = p.nextZ; 31251 pSize --; 31252 31253 } else { 31254 31255 e = q; 31256 q = q.nextZ; 31257 qSize --; 31258 31259 } 31260 31261 if ( tail ) tail.nextZ = e; 31262 else list = e; 31263 31264 e.prevZ = tail; 31265 tail = e; 31266 31267 } 31268 31269 p = q; 31270 31271 } 31272 31273 tail.nextZ = null; 31274 inSize *= 2; 31275 31276 } while ( numMerges > 1 ); 31277 31278 return list; 31279 31280 } 31281 31282 // z-order of a point given coords and inverse of the longer side of data bbox 31283 31284 function zOrder( x, y, minX, minY, invSize ) { 31285 31286 // coords are transformed into non-negative 15-bit integer range 31287 31288 x = 32767 * ( x - minX ) * invSize; 31289 y = 32767 * ( y - minY ) * invSize; 31290 31291 x = ( x | ( x << 8 ) ) & 0x00FF00FF; 31292 x = ( x | ( x << 4 ) ) & 0x0F0F0F0F; 31293 x = ( x | ( x << 2 ) ) & 0x33333333; 31294 x = ( x | ( x << 1 ) ) & 0x55555555; 31295 31296 y = ( y | ( y << 8 ) ) & 0x00FF00FF; 31297 y = ( y | ( y << 4 ) ) & 0x0F0F0F0F; 31298 y = ( y | ( y << 2 ) ) & 0x33333333; 31299 y = ( y | ( y << 1 ) ) & 0x55555555; 31300 31301 return x | ( y << 1 ); 31302 31303 } 31304 31305 // find the leftmost node of a polygon ring 31306 31307 function getLeftmost( start ) { 31308 31309 var p = start, leftmost = start; 31310 31311 do { 31312 31313 if ( p.x < leftmost.x ) leftmost = p; 31314 p = p.next; 31315 31316 } while ( p !== start ); 31317 31318 return leftmost; 31319 31320 } 31321 31322 // check if a point lies within a convex triangle 31323 31324 function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) { 31325 31326 return ( cx - px ) * ( ay - py ) - ( ax - px ) * ( cy - py ) >= 0 && 31327 ( ax - px ) * ( by - py ) - ( bx - px ) * ( ay - py ) >= 0 && 31328 ( bx - px ) * ( cy - py ) - ( cx - px ) * ( by - py ) >= 0; 31329 31330 } 31331 31332 // check if a diagonal between two polygon nodes is valid (lies in polygon interior) 31333 31334 function isValidDiagonal( a, b ) { 31335 31336 return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && 31337 locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ); 31338 31339 } 31340 31341 // signed area of a triangle 31342 31343 function area( p, q, r ) { 31344 31345 return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y ); 31346 31347 } 31348 31349 // check if two points are equal 31350 31351 function equals( p1, p2 ) { 31352 31353 return p1.x === p2.x && p1.y === p2.y; 31354 31355 } 31356 31357 // check if two segments intersect 31358 31359 function intersects( p1, q1, p2, q2 ) { 31360 31361 if ( ( equals( p1, q1 ) && equals( p2, q2 ) ) || 31362 ( equals( p1, q2 ) && equals( p2, q1 ) ) ) return true; 31363 31364 return area( p1, q1, p2 ) > 0 !== area( p1, q1, q2 ) > 0 && 31365 area( p2, q2, p1 ) > 0 !== area( p2, q2, q1 ) > 0; 31366 31367 } 31368 31369 // check if a polygon diagonal intersects any polygon segments 31370 31371 function intersectsPolygon( a, b ) { 31372 31373 var p = a; 31374 31375 do { 31376 31377 if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && 31378 intersects( p, p.next, a, b ) ) { 31379 31380 return true; 31381 31382 } 31383 31384 p = p.next; 31385 31386 } while ( p !== a ); 31387 31388 return false; 31389 31390 } 31391 31392 // check if a polygon diagonal is locally inside the polygon 31393 31394 function locallyInside( a, b ) { 31395 31396 return area( a.prev, a, a.next ) < 0 ? 31397 area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 : 31398 area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0; 31399 31400 } 31401 31402 // check if the middle point of a polygon diagonal is inside the polygon 31403 31404 function middleInside( a, b ) { 31405 31406 var p = a, 31407 inside = false, 31408 px = ( a.x + b.x ) / 2, 31409 py = ( a.y + b.y ) / 2; 31410
vendor: 56,222 bytes, lines 31411-33904
31411 do { 31412 31413 if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && 31414 ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) { 31415 31416 inside = ! inside; 31417 31418 } 31419 31420 p = p.next; 31421 31422 } while ( p !== a ); 31423 31424 return inside; 31425 31426 } 31427 31428 // link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; 31429 // if one belongs to the outer ring and another to a hole, it merges it into a single ring 31430 31431 function splitPolygon( a, b ) { 31432 31433 var a2 = new Node( a.i, a.x, a.y ), 31434 b2 = new Node( b.i, b.x, b.y ), 31435 an = a.next, 31436 bp = b.prev; 31437 31438 a.next = b; 31439 b.prev = a; 31440 31441 a2.next = an; 31442 an.prev = a2; 31443 31444 b2.next = a2; 31445 a2.prev = b2; 31446 31447 bp.next = b2; 31448 b2.prev = bp; 31449 31450 return b2; 31451 31452 } 31453 31454 // create a node and optionally link it with previous one (in a circular doubly linked list) 31455 31456 function insertNode( i, x, y, last ) { 31457 31458 var p = new Node( i, x, y ); 31459 31460 if ( ! last ) { 31461 31462 p.prev = p; 31463 p.next = p; 31464 31465 } else { 31466 31467 p.next = last.next; 31468 p.prev = last; 31469 last.next.prev = p; 31470 last.next = p; 31471 31472 } 31473 31474 return p; 31475 31476 } 31477 31478 function removeNode( p ) { 31479 31480 p.next.prev = p.prev; 31481 p.prev.next = p.next; 31482 31483 if ( p.prevZ ) p.prevZ.nextZ = p.nextZ; 31484 if ( p.nextZ ) p.nextZ.prevZ = p.prevZ; 31485 31486 } 31487 31488 function Node( i, x, y ) { 31489 31490 // vertice index in coordinates array 31491 this.i = i; 31492 31493 // vertex coordinates 31494 this.x = x; 31495 this.y = y; 31496 31497 // previous and next vertice nodes in a polygon ring 31498 this.prev = null; 31499 this.next = null; 31500 31501 // z-order curve value 31502 this.z = null; 31503 31504 // previous and next nodes in z-order 31505 this.prevZ = null; 31506 this.nextZ = null; 31507 31508 // indicates whether this is a steiner point 31509 this.steiner = false; 31510 31511 } 31512 31513 function signedArea( data, start, end, dim ) { 31514 31515 var sum = 0; 31516 31517 for ( var i = start, j = end - dim; i < end; i += dim ) { 31518 31519 sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] ); 31520 j = i; 31521 31522 } 31523 31524 return sum; 31525 31526 } 31527 31528 /** 31529 * @author zz85 / http://www.lab4games.net/zz85/blog 31530 */ 31531 31532 var ShapeUtils = { 31533 31534 // calculate area of the contour polygon 31535 31536 area: function ( contour ) { 31537 31538 var n = contour.length; 31539 var a = 0.0; 31540 31541 for ( var p = n - 1, q = 0; q < n; p = q ++ ) { 31542 31543 a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; 31544 31545 } 31546 31547 return a * 0.5; 31548 31549 }, 31550 31551 isClockWise: function ( pts ) { 31552 31553 return ShapeUtils.area( pts ) < 0; 31554 31555 }, 31556 31557 triangulateShape: function ( contour, holes ) { 31558 31559 var vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] 31560 var holeIndices = []; // array of hole indices 31561 var faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ] 31562 31563 removeDupEndPts( contour ); 31564 addContour( vertices, contour ); 31565 31566 // 31567 31568 var holeIndex = contour.length; 31569 31570 holes.forEach( removeDupEndPts ); 31571 31572 for ( var i = 0; i < holes.length; i ++ ) { 31573 31574 holeIndices.push( holeIndex ); 31575 holeIndex += holes[ i ].length; 31576 addContour( vertices, holes[ i ] ); 31577 31578 } 31579 31580 // 31581 31582 var triangles = Earcut.triangulate( vertices, holeIndices ); 31583 31584 // 31585 31586 for ( var i = 0; i < triangles.length; i += 3 ) { 31587 31588 faces.push( triangles.slice( i, i + 3 ) ); 31589 31590 } 31591 31592 return faces; 31593 31594 } 31595 31596 }; 31597 31598 function removeDupEndPts( points ) { 31599 31600 var l = points.length; 31601 31602 if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { 31603 31604 points.pop(); 31605 31606 } 31607 31608 } 31609 31610 function addContour( vertices, contour ) { 31611 31612 for ( var i = 0; i < contour.length; i ++ ) { 31613 31614 vertices.push( contour[ i ].x ); 31615 vertices.push( contour[ i ].y ); 31616 31617 } 31618 31619 } 31620 31621 /** 31622 * @author zz85 / http://www.lab4games.net/zz85/blog 31623 * 31624 * Creates extruded geometry from a path shape. 31625 * 31626 * parameters = { 31627 * 31628 * curveSegments: <int>, // number of points on the curves 31629 * steps: <int>, // number of points for z-side extrusions / used for subdividing segments of extrude spline too 31630 * depth: <float>, // Depth to extrude the shape 31631 * 31632 * bevelEnabled: <bool>, // turn on bevel 31633 * bevelThickness: <float>, // how deep into the original shape bevel goes 31634 * bevelSize: <float>, // how far from shape outline is bevel 31635 * bevelSegments: <int>, // number of bevel layers 31636 * 31637 * extrudePath: <THREE.Curve> // curve to extrude shape along 31638 * 31639 * UVGenerator: <Object> // object that provides UV generator functions 31640 * 31641 * } 31642 */ 31643 31644 // ExtrudeGeometry 31645 31646 function ExtrudeGeometry( shapes, options ) { 31647 31648 Geometry.call( this ); 31649 31650 this.type = 'ExtrudeGeometry'; 31651 31652 this.parameters = { 31653 shapes: shapes, 31654 options: options 31655 }; 31656 31657 this.fromBufferGeometry( new ExtrudeBufferGeometry( shapes, options ) ); 31658 this.mergeVertices(); 31659 31660 } 31661 31662 ExtrudeGeometry.prototype = Object.create( Geometry.prototype ); 31663 ExtrudeGeometry.prototype.constructor = ExtrudeGeometry; 31664 31665 ExtrudeGeometry.prototype.toJSON = function () { 31666 31667 var data = Geometry.prototype.toJSON.call( this ); 31668 31669 var shapes = this.parameters.shapes; 31670 var options = this.parameters.options; 31671 31672 return toJSON( shapes, options, data ); 31673 31674 }; 31675 31676 // ExtrudeBufferGeometry 31677 31678 function ExtrudeBufferGeometry( shapes, options ) { 31679 31680 BufferGeometry.call( this ); 31681 31682 this.type = 'ExtrudeBufferGeometry'; 31683 31684 this.parameters = { 31685 shapes: shapes, 31686 options: options 31687 }; 31688 31689 shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; 31690 31691 var scope = this; 31692 31693 var verticesArray = []; 31694 var uvArray = []; 31695 31696 for ( var i = 0, l = shapes.length; i < l; i ++ ) { 31697 31698 var shape = shapes[ i ]; 31699 addShape( shape ); 31700 31701 } 31702 31703 // build geometry 31704 31705 this.addAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); 31706 this.addAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) ); 31707 31708 this.computeVertexNormals(); 31709 31710 // functions 31711 31712 function addShape( shape ) { 31713 31714 var placeholder = []; 31715 31716 // options 31717 31718 var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; 31719 var steps = options.steps !== undefined ? options.steps : 1; 31720 var depth = options.depth !== undefined ? options.depth : 100; 31721 31722 var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; 31723 var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; 31724 var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; 31725 var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; 31726 31727 var extrudePath = options.extrudePath; 31728 31729 var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator; 31730 31731 // deprecated options 31732 31733 if ( options.amount !== undefined ) { 31734 31735 console.warn( 'THREE.ExtrudeBufferGeometry: amount has been renamed to depth.' ); 31736 depth = options.amount; 31737 31738 } 31739 31740 // 31741 31742 var extrudePts, extrudeByPath = false; 31743 var splineTube, binormal, normal, position2; 31744 31745 if ( extrudePath ) { 31746 31747 extrudePts = extrudePath.getSpacedPoints( steps ); 31748 31749 extrudeByPath = true; 31750 bevelEnabled = false; // bevels not supported for path extrusion 31751 31752 // SETUP TNB variables 31753 31754 // TODO1 - have a .isClosed in spline? 31755 31756 splineTube = extrudePath.computeFrenetFrames( steps, false ); 31757 31758 // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); 31759 31760 binormal = new Vector3(); 31761 normal = new Vector3(); 31762 position2 = new Vector3(); 31763 31764 } 31765 31766 // Safeguards if bevels are not enabled 31767 31768 if ( ! bevelEnabled ) { 31769 31770 bevelSegments = 0; 31771 bevelThickness = 0; 31772 bevelSize = 0; 31773 31774 } 31775 31776 // Variables initialization 31777 31778 var ahole, h, hl; // looping of holes 31779 31780 var shapePoints = shape.extractPoints( curveSegments ); 31781 31782 var vertices = shapePoints.shape; 31783 var holes = shapePoints.holes; 31784 31785 var reverse = ! ShapeUtils.isClockWise( vertices ); 31786 31787 if ( reverse ) { 31788 31789 vertices = vertices.reverse(); 31790 31791 // Maybe we should also check if holes are in the opposite direction, just to be safe ... 31792 31793 for ( h = 0, hl = holes.length; h < hl; h ++ ) { 31794 31795 ahole = holes[ h ]; 31796 31797 if ( ShapeUtils.isClockWise( ahole ) ) { 31798 31799 holes[ h ] = ahole.reverse(); 31800 31801 } 31802 31803 } 31804 31805 } 31806 31807 31808 var faces = ShapeUtils.triangulateShape( vertices, holes ); 31809 31810 /* Vertices */ 31811 31812 var contour = vertices; // vertices has all points but contour has only points of circumference 31813 31814 for ( h = 0, hl = holes.length; h < hl; h ++ ) { 31815 31816 ahole = holes[ h ]; 31817 31818 vertices = vertices.concat( ahole ); 31819 31820 } 31821 31822 31823 function scalePt2( pt, vec, size ) { 31824 31825 if ( ! vec ) console.error( "THREE.ExtrudeGeometry: vec does not exist" ); 31826 31827 return vec.clone().multiplyScalar( size ).add( pt ); 31828 31829 } 31830 31831 var b, bs, t, z, 31832 vert, vlen = vertices.length, 31833 face, flen = faces.length; 31834 31835 31836 // Find directions for point movement 31837 31838 31839 function getBevelVec( inPt, inPrev, inNext ) { 31840 31841 // computes for inPt the corresponding point inPt' on a new contour 31842 // shifted by 1 unit (length of normalized vector) to the left 31843 // if we walk along contour clockwise, this new contour is outside the old one 31844 // 31845 // inPt' is the intersection of the two lines parallel to the two 31846 // adjacent edges of inPt at a distance of 1 unit on the left side. 31847 31848 var v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt 31849 31850 // good reading for geometry algorithms (here: line-line intersection) 31851 // http://geomalgorithms.com/a05-_intersect-1.html 31852 31853 var v_prev_x = inPt.x - inPrev.x, 31854 v_prev_y = inPt.y - inPrev.y; 31855 var v_next_x = inNext.x - inPt.x, 31856 v_next_y = inNext.y - inPt.y; 31857 31858 var v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); 31859 31860 // check for collinear edges 31861 var collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 31862 31863 if ( Math.abs( collinear0 ) > Number.EPSILON ) { 31864 31865 // not collinear 31866 31867 // length of vectors for normalizing 31868 31869 var v_prev_len = Math.sqrt( v_prev_lensq ); 31870 var v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); 31871 31872 // shift adjacent points by unit vectors to the left 31873 31874 var ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); 31875 var ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); 31876 31877 var ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); 31878 var ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); 31879 31880 // scaling factor for v_prev to intersection point 31881 31882 var sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y - 31883 ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) / 31884 ( v_prev_x * v_next_y - v_prev_y * v_next_x ); 31885 31886 // vector from inPt to intersection point 31887 31888 v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); 31889 v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); 31890 31891 // Don't normalize!, otherwise sharp corners become ugly 31892 // but prevent crazy spikes 31893 var v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); 31894 if ( v_trans_lensq <= 2 ) { 31895 31896 return new Vector2( v_trans_x, v_trans_y ); 31897 31898 } else { 31899 31900 shrink_by = Math.sqrt( v_trans_lensq / 2 ); 31901 31902 } 31903 31904 } else { 31905 31906 // handle special case of collinear edges 31907 31908 var direction_eq = false; // assumes: opposite 31909 if ( v_prev_x > Number.EPSILON ) { 31910 31911 if ( v_next_x > Number.EPSILON ) { 31912 31913 direction_eq = true; 31914 31915 } 31916 31917 } else { 31918 31919 if ( v_prev_x < - Number.EPSILON ) { 31920 31921 if ( v_next_x < - Number.EPSILON ) { 31922 31923 direction_eq = true; 31924 31925 } 31926 31927 } else { 31928 31929 if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { 31930 31931 direction_eq = true; 31932 31933 } 31934 31935 } 31936 31937 } 31938 31939 if ( direction_eq ) { 31940 31941 // console.log("Warning: lines are a straight sequence"); 31942 v_trans_x = - v_prev_y; 31943 v_trans_y = v_prev_x; 31944 shrink_by = Math.sqrt( v_prev_lensq ); 31945 31946 } else { 31947 31948 // console.log("Warning: lines are a straight spike"); 31949 v_trans_x = v_prev_x; 31950 v_trans_y = v_prev_y; 31951 shrink_by = Math.sqrt( v_prev_lensq / 2 ); 31952 31953 } 31954 31955 } 31956 31957 return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); 31958 31959 } 31960 31961 31962 var contourMovements = []; 31963 31964 for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 31965 31966 if ( j === il ) j = 0; 31967 if ( k === il ) k = 0; 31968 31969 // (j)---(i)---(k) 31970 // console.log('i,j,k', i, j , k) 31971 31972 contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); 31973 31974 } 31975 31976 var holesMovements = [], 31977 oneHoleMovements, verticesMovements = contourMovements.concat(); 31978 31979 for ( h = 0, hl = holes.length; h < hl; h ++ ) { 31980 31981 ahole = holes[ h ]; 31982 31983 oneHoleMovements = []; 31984 31985 for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { 31986 31987 if ( j === il ) j = 0; 31988 if ( k === il ) k = 0; 31989 31990 // (j)---(i)---(k) 31991 oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); 31992 31993 } 31994 31995 holesMovements.push( oneHoleMovements ); 31996 verticesMovements = verticesMovements.concat( oneHoleMovements ); 31997 31998 } 31999 32000 32001 // Loop bevelSegments, 1 for the front, 1 for the back 32002 32003 for ( b = 0; b < bevelSegments; b ++ ) { 32004 32005 //for ( b = bevelSegments; b > 0; b -- ) { 32006 32007 t = b / bevelSegments; 32008 z = bevelThickness * Math.cos( t * Math.PI / 2 ); 32009 bs = bevelSize * Math.sin( t * Math.PI / 2 ); 32010 32011 // contract shape 32012 32013 for ( i = 0, il = contour.length; i < il; i ++ ) { 32014 32015 vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 32016 32017 v( vert.x, vert.y, - z ); 32018 32019 } 32020 32021 // expand holes 32022 32023 for ( h = 0, hl = holes.length; h < hl; h ++ ) { 32024 32025 ahole = holes[ h ]; 32026 oneHoleMovements = holesMovements[ h ]; 32027 32028 for ( i = 0, il = ahole.length; i < il; i ++ ) { 32029 32030 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 32031 32032 v( vert.x, vert.y, - z ); 32033 32034 } 32035 32036 } 32037 32038 } 32039 32040 bs = bevelSize; 32041 32042 // Back facing vertices 32043 32044 for ( i = 0; i < vlen; i ++ ) { 32045 32046 vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 32047 32048 if ( ! extrudeByPath ) { 32049 32050 v( vert.x, vert.y, 0 ); 32051 32052 } else { 32053 32054 // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); 32055 32056 normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); 32057 binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); 32058 32059 position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); 32060 32061 v( position2.x, position2.y, position2.z ); 32062 32063 } 32064 32065 } 32066 32067 // Add stepped vertices... 32068 // Including front facing vertices 32069 32070 var s; 32071 32072 for ( s = 1; s <= steps; s ++ ) { 32073 32074 for ( i = 0; i < vlen; i ++ ) { 32075 32076 vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; 32077 32078 if ( ! extrudeByPath ) { 32079 32080 v( vert.x, vert.y, depth / steps * s ); 32081 32082 } else { 32083 32084 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); 32085 32086 normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); 32087 binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); 32088 32089 position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); 32090 32091 v( position2.x, position2.y, position2.z ); 32092 32093 } 32094 32095 } 32096 32097 } 32098 32099 32100 // Add bevel segments planes 32101 32102 //for ( b = 1; b <= bevelSegments; b ++ ) { 32103 for ( b = bevelSegments - 1; b >= 0; b -- ) { 32104 32105 t = b / bevelSegments; 32106 z = bevelThickness * Math.cos( t * Math.PI / 2 ); 32107 bs = bevelSize * Math.sin( t * Math.PI / 2 ); 32108 32109 // contract shape 32110 32111 for ( i = 0, il = contour.length; i < il; i ++ ) { 32112 32113 vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); 32114 v( vert.x, vert.y, depth + z ); 32115 32116 } 32117 32118 // expand holes 32119 32120 for ( h = 0, hl = holes.length; h < hl; h ++ ) { 32121 32122 ahole = holes[ h ]; 32123 oneHoleMovements = holesMovements[ h ]; 32124 32125 for ( i = 0, il = ahole.length; i < il; i ++ ) { 32126 32127 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); 32128 32129 if ( ! extrudeByPath ) { 32130 32131 v( vert.x, vert.y, depth + z ); 32132 32133 } else { 32134 32135 v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); 32136 32137 } 32138 32139 } 32140 32141 } 32142 32143 } 32144 32145 /* Faces */ 32146 32147 // Top and bottom faces 32148 32149 buildLidFaces(); 32150 32151 // Sides faces 32152 32153 buildSideFaces(); 32154 32155 32156 ///// Internal functions 32157 32158 function buildLidFaces() { 32159 32160 var start = verticesArray.length / 3; 32161 32162 if ( bevelEnabled ) { 32163 32164 var layer = 0; // steps + 1 32165 var offset = vlen * layer; 32166 32167 // Bottom faces 32168 32169 for ( i = 0; i < flen; i ++ ) { 32170 32171 face = faces[ i ]; 32172 f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); 32173 32174 } 32175 32176 layer = steps + bevelSegments * 2; 32177 offset = vlen * layer; 32178 32179 // Top faces 32180 32181 for ( i = 0; i < flen; i ++ ) { 32182 32183 face = faces[ i ]; 32184 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); 32185 32186 } 32187 32188 } else { 32189 32190 // Bottom faces 32191 32192 for ( i = 0; i < flen; i ++ ) { 32193 32194 face = faces[ i ]; 32195 f3( face[ 2 ], face[ 1 ], face[ 0 ] ); 32196 32197 } 32198 32199 // Top faces 32200 32201 for ( i = 0; i < flen; i ++ ) { 32202 32203 face = faces[ i ]; 32204 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); 32205 32206 } 32207 32208 } 32209 32210 scope.addGroup( start, verticesArray.length / 3 - start, 0 ); 32211 32212 } 32213 32214 // Create faces for the z-sides of the shape 32215 32216 function buildSideFaces() { 32217 32218 var start = verticesArray.length / 3; 32219 var layeroffset = 0; 32220 sidewalls( contour, layeroffset ); 32221 layeroffset += contour.length; 32222 32223 for ( h = 0, hl = holes.length; h < hl; h ++ ) { 32224 32225 ahole = holes[ h ]; 32226 sidewalls( ahole, layeroffset ); 32227 32228 //, true 32229 layeroffset += ahole.length; 32230 32231 } 32232 32233 32234 scope.addGroup( start, verticesArray.length / 3 - start, 1 ); 32235 32236 32237 } 32238 32239 function sidewalls( contour, layeroffset ) { 32240 32241 var j, k; 32242 i = contour.length; 32243 32244 while ( -- i >= 0 ) { 32245 32246 j = i; 32247 k = i - 1; 32248 if ( k < 0 ) k = contour.length - 1; 32249 32250 //console.log('b', i,j, i-1, k,vertices.length); 32251 32252 var s = 0, 32253 sl = steps + bevelSegments * 2; 32254 32255 for ( s = 0; s < sl; s ++ ) { 32256 32257 var slen1 = vlen * s; 32258 var slen2 = vlen * ( s + 1 ); 32259 32260 var a = layeroffset + j + slen1, 32261 b = layeroffset + k + slen1, 32262 c = layeroffset + k + slen2, 32263 d = layeroffset + j + slen2; 32264 32265 f4( a, b, c, d ); 32266 32267 } 32268 32269 } 32270 32271 } 32272 32273 function v( x, y, z ) { 32274 32275 placeholder.push( x ); 32276 placeholder.push( y ); 32277 placeholder.push( z ); 32278 32279 } 32280 32281 32282 function f3( a, b, c ) { 32283 32284 addVertex( a ); 32285 addVertex( b ); 32286 addVertex( c ); 32287 32288 var nextIndex = verticesArray.length / 3; 32289 var uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 32290 32291 addUV( uvs[ 0 ] ); 32292 addUV( uvs[ 1 ] ); 32293 addUV( uvs[ 2 ] ); 32294 32295 } 32296 32297 function f4( a, b, c, d ) { 32298 32299 addVertex( a ); 32300 addVertex( b ); 32301 addVertex( d ); 32302 32303 addVertex( b ); 32304 addVertex( c ); 32305 addVertex( d ); 32306 32307 32308 var nextIndex = verticesArray.length / 3; 32309 var uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); 32310 32311 addUV( uvs[ 0 ] ); 32312 addUV( uvs[ 1 ] ); 32313 addUV( uvs[ 3 ] ); 32314 32315 addUV( uvs[ 1 ] ); 32316 addUV( uvs[ 2 ] ); 32317 addUV( uvs[ 3 ] ); 32318 32319 } 32320 32321 function addVertex( index ) { 32322 32323 verticesArray.push( placeholder[ index * 3 + 0 ] ); 32324 verticesArray.push( placeholder[ index * 3 + 1 ] ); 32325 verticesArray.push( placeholder[ index * 3 + 2 ] ); 32326 32327 } 32328 32329 32330 function addUV( vector2 ) { 32331 32332 uvArray.push( vector2.x ); 32333 uvArray.push( vector2.y ); 32334 32335 } 32336 32337 } 32338 32339 } 32340 32341 ExtrudeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 32342 ExtrudeBufferGeometry.prototype.constructor = ExtrudeBufferGeometry; 32343 32344 ExtrudeBufferGeometry.prototype.toJSON = function () { 32345 32346 var data = BufferGeometry.prototype.toJSON.call( this ); 32347 32348 var shapes = this.parameters.shapes; 32349 var options = this.parameters.options; 32350 32351 return toJSON( shapes, options, data ); 32352 32353 }; 32354 32355 // 32356 32357 var WorldUVGenerator = { 32358 32359 generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { 32360 32361 var a_x = vertices[ indexA * 3 ]; 32362 var a_y = vertices[ indexA * 3 + 1 ]; 32363 var b_x = vertices[ indexB * 3 ]; 32364 var b_y = vertices[ indexB * 3 + 1 ]; 32365 var c_x = vertices[ indexC * 3 ]; 32366 var c_y = vertices[ indexC * 3 + 1 ]; 32367 32368 return [ 32369 new Vector2( a_x, a_y ), 32370 new Vector2( b_x, b_y ), 32371 new Vector2( c_x, c_y ) 32372 ]; 32373 32374 }, 32375 32376 generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { 32377 32378 var a_x = vertices[ indexA * 3 ]; 32379 var a_y = vertices[ indexA * 3 + 1 ]; 32380 var a_z = vertices[ indexA * 3 + 2 ]; 32381 var b_x = vertices[ indexB * 3 ]; 32382 var b_y = vertices[ indexB * 3 + 1 ]; 32383 var b_z = vertices[ indexB * 3 + 2 ]; 32384 var c_x = vertices[ indexC * 3 ]; 32385 var c_y = vertices[ indexC * 3 + 1 ]; 32386 var c_z = vertices[ indexC * 3 + 2 ]; 32387 var d_x = vertices[ indexD * 3 ]; 32388 var d_y = vertices[ indexD * 3 + 1 ]; 32389 var d_z = vertices[ indexD * 3 + 2 ]; 32390 32391 if ( Math.abs( a_y - b_y ) < 0.01 ) { 32392 32393 return [ 32394 new Vector2( a_x, 1 - a_z ), 32395 new Vector2( b_x, 1 - b_z ), 32396 new Vector2( c_x, 1 - c_z ), 32397 new Vector2( d_x, 1 - d_z ) 32398 ]; 32399 32400 } else { 32401 32402 return [ 32403 new Vector2( a_y, 1 - a_z ), 32404 new Vector2( b_y, 1 - b_z ), 32405 new Vector2( c_y, 1 - c_z ), 32406 new Vector2( d_y, 1 - d_z ) 32407 ]; 32408 32409 } 32410 32411 } 32412 }; 32413 32414 function toJSON( shapes, options, data ) { 32415 32416 // 32417 32418 data.shapes = []; 32419 32420 if ( Array.isArray( shapes ) ) { 32421 32422 for ( var i = 0, l = shapes.length; i < l; i ++ ) { 32423 32424 var shape = shapes[ i ]; 32425 32426 data.shapes.push( shape.uuid ); 32427 32428 } 32429 32430 } else { 32431 32432 data.shapes.push( shapes.uuid ); 32433 32434 } 32435 32436 // 32437 32438 if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON(); 32439 32440 return data; 32441 32442 } 32443 32444 /** 32445 * @author zz85 / http://www.lab4games.net/zz85/blog 32446 * @author alteredq / http://alteredqualia.com/ 32447 * 32448 * Text = 3D Text 32449 * 32450 * parameters = { 32451 * font: <THREE.Font>, // font 32452 * 32453 * size: <float>, // size of the text 32454 * height: <float>, // thickness to extrude text 32455 * curveSegments: <int>, // number of points on the curves 32456 * 32457 * bevelEnabled: <bool>, // turn on bevel 32458 * bevelThickness: <float>, // how deep into text bevel goes 32459 * bevelSize: <float> // how far from text outline is bevel 32460 * } 32461 */ 32462 32463 // TextGeometry 32464 32465 function TextGeometry( text, parameters ) { 32466 32467 Geometry.call( this ); 32468 32469 this.type = 'TextGeometry'; 32470 32471 this.parameters = { 32472 text: text, 32473 parameters: parameters 32474 }; 32475 32476 this.fromBufferGeometry( new TextBufferGeometry( text, parameters ) ); 32477 this.mergeVertices(); 32478 32479 } 32480 32481 TextGeometry.prototype = Object.create( Geometry.prototype ); 32482 TextGeometry.prototype.constructor = TextGeometry; 32483 32484 // TextBufferGeometry 32485 32486 function TextBufferGeometry( text, parameters ) { 32487 32488 parameters = parameters || {}; 32489 32490 var font = parameters.font; 32491 32492 if ( ! ( font && font.isFont ) ) { 32493 32494 console.error( 'THREE.TextGeometry: font parameter is not an instance of THREE.Font.' ); 32495 return new Geometry(); 32496 32497 } 32498 32499 var shapes = font.generateShapes( text, parameters.size, parameters.curveSegments ); 32500 32501 // translate parameters to ExtrudeGeometry API 32502 32503 parameters.depth = parameters.height !== undefined ? parameters.height : 50; 32504 32505 // defaults 32506 32507 if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10; 32508 if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8; 32509 if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false; 32510 32511 ExtrudeBufferGeometry.call( this, shapes, parameters ); 32512 32513 this.type = 'TextBufferGeometry'; 32514 32515 } 32516 32517 TextBufferGeometry.prototype = Object.create( ExtrudeBufferGeometry.prototype ); 32518 TextBufferGeometry.prototype.constructor = TextBufferGeometry; 32519 32520 /** 32521 * @author mrdoob / http://mrdoob.com/ 32522 * @author benaadams / https://twitter.com/ben_a_adams 32523 * @author Mugen87 / https://github.com/Mugen87 32524 */ 32525 32526 // SphereGeometry 32527 32528 function SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { 32529 32530 Geometry.call( this ); 32531 32532 this.type = 'SphereGeometry'; 32533 32534 this.parameters = { 32535 radius: radius, 32536 widthSegments: widthSegments, 32537 heightSegments: heightSegments, 32538 phiStart: phiStart, 32539 phiLength: phiLength, 32540 thetaStart: thetaStart, 32541 thetaLength: thetaLength 32542 }; 32543 32544 this.fromBufferGeometry( new SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) ); 32545 this.mergeVertices(); 32546 32547 } 32548 32549 SphereGeometry.prototype = Object.create( Geometry.prototype ); 32550 SphereGeometry.prototype.constructor = SphereGeometry; 32551 32552 // SphereBufferGeometry 32553 32554 function SphereBufferGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength ) { 32555 32556 BufferGeometry.call( this ); 32557 32558 this.type = 'SphereBufferGeometry'; 32559 32560 this.parameters = { 32561 radius: radius, 32562 widthSegments: widthSegments, 32563 heightSegments: heightSegments, 32564 phiStart: phiStart, 32565 phiLength: phiLength, 32566 thetaStart: thetaStart, 32567 thetaLength: thetaLength 32568 }; 32569 32570 radius = radius || 1; 32571 32572 widthSegments = Math.max( 3, Math.floor( widthSegments ) || 8 ); 32573 heightSegments = Math.max( 2, Math.floor( heightSegments ) || 6 ); 32574 32575 phiStart = phiStart !== undefined ? phiStart : 0; 32576 phiLength = phiLength !== undefined ? phiLength : Math.PI * 2; 32577 32578 thetaStart = thetaStart !== undefined ? thetaStart : 0; 32579 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI; 32580 32581 var thetaEnd = thetaStart + thetaLength; 32582 32583 var ix, iy; 32584 32585 var index = 0; 32586 var grid = []; 32587 32588 var vertex = new Vector3(); 32589 var normal = new Vector3(); 32590 32591 // buffers 32592 32593 var indices = []; 32594 var vertices = []; 32595 var normals = []; 32596 var uvs = []; 32597 32598 // generate vertices, normals and uvs 32599 32600 for ( iy = 0; iy <= heightSegments; iy ++ ) { 32601 32602 var verticesRow = []; 32603 32604 var v = iy / heightSegments; 32605 32606 for ( ix = 0; ix <= widthSegments; ix ++ ) { 32607 32608 var u = ix / widthSegments; 32609 32610 // vertex 32611 32612 vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 32613 vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); 32614 vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); 32615 32616 vertices.push( vertex.x, vertex.y, vertex.z ); 32617 32618 // normal 32619 32620 normal.set( vertex.x, vertex.y, vertex.z ).normalize(); 32621 normals.push( normal.x, normal.y, normal.z ); 32622 32623 // uv 32624 32625 uvs.push( u, 1 - v ); 32626 32627 verticesRow.push( index ++ ); 32628 32629 } 32630 32631 grid.push( verticesRow ); 32632 32633 } 32634 32635 // indices 32636 32637 for ( iy = 0; iy < heightSegments; iy ++ ) { 32638 32639 for ( ix = 0; ix < widthSegments; ix ++ ) { 32640 32641 var a = grid[ iy ][ ix + 1 ]; 32642 var b = grid[ iy ][ ix ]; 32643 var c = grid[ iy + 1 ][ ix ]; 32644 var d = grid[ iy + 1 ][ ix + 1 ]; 32645 32646 if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); 32647 if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); 32648 32649 } 32650 32651 } 32652 32653 // build geometry 32654 32655 this.setIndex( indices ); 32656 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 32657 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 32658 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 32659 32660 } 32661 32662 SphereBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 32663 SphereBufferGeometry.prototype.constructor = SphereBufferGeometry; 32664 32665 /** 32666 * @author Kaleb Murphy 32667 * @author Mugen87 / https://github.com/Mugen87 32668 */ 32669 32670 // RingGeometry 32671 32672 function RingGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { 32673 32674 Geometry.call( this ); 32675 32676 this.type = 'RingGeometry'; 32677 32678 this.parameters = { 32679 innerRadius: innerRadius, 32680 outerRadius: outerRadius, 32681 thetaSegments: thetaSegments, 32682 phiSegments: phiSegments, 32683 thetaStart: thetaStart, 32684 thetaLength: thetaLength 32685 }; 32686 32687 this.fromBufferGeometry( new RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) ); 32688 this.mergeVertices(); 32689 32690 } 32691 32692 RingGeometry.prototype = Object.create( Geometry.prototype ); 32693 RingGeometry.prototype.constructor = RingGeometry; 32694 32695 // RingBufferGeometry 32696 32697 function RingBufferGeometry( innerRadius, outerRadius, thetaSegments, phiSegments, thetaStart, thetaLength ) { 32698 32699 BufferGeometry.call( this ); 32700 32701 this.type = 'RingBufferGeometry'; 32702 32703 this.parameters = { 32704 innerRadius: innerRadius, 32705 outerRadius: outerRadius, 32706 thetaSegments: thetaSegments, 32707 phiSegments: phiSegments, 32708 thetaStart: thetaStart, 32709 thetaLength: thetaLength 32710 }; 32711 32712 innerRadius = innerRadius || 0.5; 32713 outerRadius = outerRadius || 1; 32714 32715 thetaStart = thetaStart !== undefined ? thetaStart : 0; 32716 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; 32717 32718 thetaSegments = thetaSegments !== undefined ? Math.max( 3, thetaSegments ) : 8; 32719 phiSegments = phiSegments !== undefined ? Math.max( 1, phiSegments ) : 1; 32720 32721 // buffers 32722 32723 var indices = []; 32724 var vertices = []; 32725 var normals = []; 32726 var uvs = []; 32727 32728 // some helper variables 32729 32730 var segment; 32731 var radius = innerRadius; 32732 var radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); 32733 var vertex = new Vector3(); 32734 var uv = new Vector2(); 32735 var j, i; 32736 32737 // generate vertices, normals and uvs 32738 32739 for ( j = 0; j <= phiSegments; j ++ ) { 32740 32741 for ( i = 0; i <= thetaSegments; i ++ ) { 32742 32743 // values are generate from the inside of the ring to the outside 32744 32745 segment = thetaStart + i / thetaSegments * thetaLength; 32746 32747 // vertex 32748 32749 vertex.x = radius * Math.cos( segment ); 32750 vertex.y = radius * Math.sin( segment ); 32751 32752 vertices.push( vertex.x, vertex.y, vertex.z ); 32753 32754 // normal 32755 32756 normals.push( 0, 0, 1 ); 32757 32758 // uv 32759 32760 uv.x = ( vertex.x / outerRadius + 1 ) / 2; 32761 uv.y = ( vertex.y / outerRadius + 1 ) / 2; 32762 32763 uvs.push( uv.x, uv.y ); 32764 32765 } 32766 32767 // increase the radius for next row of vertices 32768 32769 radius += radiusStep; 32770 32771 } 32772 32773 // indices 32774 32775 for ( j = 0; j < phiSegments; j ++ ) { 32776 32777 var thetaSegmentLevel = j * ( thetaSegments + 1 ); 32778 32779 for ( i = 0; i < thetaSegments; i ++ ) { 32780 32781 segment = i + thetaSegmentLevel; 32782 32783 var a = segment; 32784 var b = segment + thetaSegments + 1; 32785 var c = segment + thetaSegments + 2; 32786 var d = segment + 1; 32787 32788 // faces 32789 32790 indices.push( a, b, d ); 32791 indices.push( b, c, d ); 32792 32793 } 32794 32795 } 32796 32797 // build geometry 32798 32799 this.setIndex( indices ); 32800 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 32801 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 32802 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 32803 32804 } 32805 32806 RingBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 32807 RingBufferGeometry.prototype.constructor = RingBufferGeometry; 32808 32809 /** 32810 * @author astrodud / http://astrodud.isgreat.org/ 32811 * @author zz85 / https://github.com/zz85 32812 * @author bhouston / http://clara.io 32813 * @author Mugen87 / https://github.com/Mugen87 32814 */ 32815 32816 // LatheGeometry 32817 32818 function LatheGeometry( points, segments, phiStart, phiLength ) { 32819 32820 Geometry.call( this ); 32821 32822 this.type = 'LatheGeometry'; 32823 32824 this.parameters = { 32825 points: points, 32826 segments: segments, 32827 phiStart: phiStart, 32828 phiLength: phiLength 32829 }; 32830 32831 this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) ); 32832 this.mergeVertices(); 32833 32834 } 32835 32836 LatheGeometry.prototype = Object.create( Geometry.prototype ); 32837 LatheGeometry.prototype.constructor = LatheGeometry; 32838 32839 // LatheBufferGeometry 32840 32841 function LatheBufferGeometry( points, segments, phiStart, phiLength ) { 32842 32843 BufferGeometry.call( this ); 32844 32845 this.type = 'LatheBufferGeometry'; 32846 32847 this.parameters = { 32848 points: points, 32849 segments: segments, 32850 phiStart: phiStart, 32851 phiLength: phiLength 32852 }; 32853 32854 segments = Math.floor( segments ) || 12; 32855 phiStart = phiStart || 0; 32856 phiLength = phiLength || Math.PI * 2; 32857 32858 // clamp phiLength so it's in range of [ 0, 2PI ] 32859 32860 phiLength = _Math.clamp( phiLength, 0, Math.PI * 2 ); 32861 32862 32863 // buffers 32864 32865 var indices = []; 32866 var vertices = []; 32867 var uvs = []; 32868 32869 // helper variables 32870 32871 var base; 32872 var inverseSegments = 1.0 / segments; 32873 var vertex = new Vector3(); 32874 var uv = new Vector2(); 32875 var i, j; 32876 32877 // generate vertices and uvs 32878 32879 for ( i = 0; i <= segments; i ++ ) { 32880 32881 var phi = phiStart + i * inverseSegments * phiLength; 32882 32883 var sin = Math.sin( phi ); 32884 var cos = Math.cos( phi ); 32885 32886 for ( j = 0; j <= ( points.length - 1 ); j ++ ) { 32887 32888 // vertex 32889 32890 vertex.x = points[ j ].x * sin; 32891 vertex.y = points[ j ].y; 32892 vertex.z = points[ j ].x * cos; 32893 32894 vertices.push( vertex.x, vertex.y, vertex.z ); 32895 32896 // uv 32897 32898 uv.x = i / segments; 32899 uv.y = j / ( points.length - 1 ); 32900 32901 uvs.push( uv.x, uv.y ); 32902 32903 32904 } 32905 32906 } 32907 32908 // indices 32909 32910 for ( i = 0; i < segments; i ++ ) { 32911 32912 for ( j = 0; j < ( points.length - 1 ); j ++ ) { 32913 32914 base = j + i * points.length; 32915 32916 var a = base; 32917 var b = base + points.length; 32918 var c = base + points.length + 1; 32919 var d = base + 1; 32920 32921 // faces 32922 32923 indices.push( a, b, d ); 32924 indices.push( b, c, d ); 32925 32926 } 32927 32928 } 32929 32930 // build geometry 32931 32932 this.setIndex( indices ); 32933 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 32934 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 32935 32936 // generate normals 32937 32938 this.computeVertexNormals(); 32939 32940 // if the geometry is closed, we need to average the normals along the seam. 32941 // because the corresponding vertices are identical (but still have different UVs). 32942 32943 if ( phiLength === Math.PI * 2 ) { 32944 32945 var normals = this.attributes.normal.array; 32946 var n1 = new Vector3(); 32947 var n2 = new Vector3(); 32948 var n = new Vector3(); 32949 32950 // this is the buffer offset for the last line of vertices 32951 32952 base = segments * points.length * 3; 32953 32954 for ( i = 0, j = 0; i < points.length; i ++, j += 3 ) { 32955 32956 // select the normal of the vertex in the first line 32957 32958 n1.x = normals[ j + 0 ]; 32959 n1.y = normals[ j + 1 ]; 32960 n1.z = normals[ j + 2 ]; 32961 32962 // select the normal of the vertex in the last line 32963 32964 n2.x = normals[ base + j + 0 ]; 32965 n2.y = normals[ base + j + 1 ]; 32966 n2.z = normals[ base + j + 2 ]; 32967 32968 // average normals 32969 32970 n.addVectors( n1, n2 ).normalize(); 32971 32972 // assign the new values to both normals 32973 32974 normals[ j + 0 ] = normals[ base + j + 0 ] = n.x; 32975 normals[ j + 1 ] = normals[ base + j + 1 ] = n.y; 32976 normals[ j + 2 ] = normals[ base + j + 2 ] = n.z; 32977 32978 } 32979 32980 } 32981 32982 } 32983 32984 LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 32985 LatheBufferGeometry.prototype.constructor = LatheBufferGeometry; 32986 32987 /** 32988 * @author jonobr1 / http://jonobr1.com 32989 * @author Mugen87 / https://github.com/Mugen87 32990 */ 32991 32992 // ShapeGeometry 32993 32994 function ShapeGeometry( shapes, curveSegments ) { 32995 32996 Geometry.call( this ); 32997 32998 this.type = 'ShapeGeometry'; 32999 33000 if ( typeof curveSegments === 'object' ) { 33001 33002 console.warn( 'THREE.ShapeGeometry: Options parameter has been removed.' ); 33003 33004 curveSegments = curveSegments.curveSegments; 33005 33006 } 33007 33008 this.parameters = { 33009 shapes: shapes, 33010 curveSegments: curveSegments 33011 }; 33012 33013 this.fromBufferGeometry( new ShapeBufferGeometry( shapes, curveSegments ) ); 33014 this.mergeVertices(); 33015 33016 } 33017 33018 ShapeGeometry.prototype = Object.create( Geometry.prototype ); 33019 ShapeGeometry.prototype.constructor = ShapeGeometry; 33020 33021 ShapeGeometry.prototype.toJSON = function () { 33022 33023 var data = Geometry.prototype.toJSON.call( this ); 33024 33025 var shapes = this.parameters.shapes; 33026 33027 return toJSON$1( shapes, data ); 33028 33029 }; 33030 33031 // ShapeBufferGeometry 33032 33033 function ShapeBufferGeometry( shapes, curveSegments ) { 33034 33035 BufferGeometry.call( this ); 33036 33037 this.type = 'ShapeBufferGeometry'; 33038 33039 this.parameters = { 33040 shapes: shapes, 33041 curveSegments: curveSegments 33042 }; 33043 33044 curveSegments = curveSegments || 12; 33045 33046 // buffers 33047 33048 var indices = []; 33049 var vertices = []; 33050 var normals = []; 33051 var uvs = []; 33052 33053 // helper variables 33054 33055 var groupStart = 0; 33056 var groupCount = 0; 33057 33058 // allow single and array values for "shapes" parameter 33059 33060 if ( Array.isArray( shapes ) === false ) { 33061 33062 addShape( shapes ); 33063 33064 } else { 33065 33066 for ( var i = 0; i < shapes.length; i ++ ) { 33067 33068 addShape( shapes[ i ] ); 33069 33070 this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support 33071 33072 groupStart += groupCount; 33073 groupCount = 0; 33074 33075 } 33076 33077 } 33078 33079 // build geometry 33080 33081 this.setIndex( indices ); 33082 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 33083 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 33084 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 33085 33086 33087 // helper functions 33088 33089 function addShape( shape ) { 33090 33091 var i, l, shapeHole; 33092 33093 var indexOffset = vertices.length / 3; 33094 var points = shape.extractPoints( curveSegments ); 33095 33096 var shapeVertices = points.shape; 33097 var shapeHoles = points.holes; 33098 33099 // check direction of vertices 33100 33101 if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { 33102 33103 shapeVertices = shapeVertices.reverse(); 33104 33105 // also check if holes are in the opposite direction 33106 33107 for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { 33108 33109 shapeHole = shapeHoles[ i ]; 33110 33111 if ( ShapeUtils.isClockWise( shapeHole ) === true ) { 33112 33113 shapeHoles[ i ] = shapeHole.reverse(); 33114 33115 } 33116 33117 } 33118 33119 } 33120 33121 var faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); 33122 33123 // join vertices of inner and outer paths to a single array 33124 33125 for ( i = 0, l = shapeHoles.length; i < l; i ++ ) { 33126 33127 shapeHole = shapeHoles[ i ]; 33128 shapeVertices = shapeVertices.concat( shapeHole ); 33129 33130 } 33131 33132 // vertices, normals, uvs 33133 33134 for ( i = 0, l = shapeVertices.length; i < l; i ++ ) { 33135 33136 var vertex = shapeVertices[ i ]; 33137 33138 vertices.push( vertex.x, vertex.y, 0 ); 33139 normals.push( 0, 0, 1 ); 33140 uvs.push( vertex.x, vertex.y ); // world uvs 33141 33142 } 33143 33144 // incides 33145 33146 for ( i = 0, l = faces.length; i < l; i ++ ) { 33147 33148 var face = faces[ i ]; 33149 33150 var a = face[ 0 ] + indexOffset; 33151 var b = face[ 1 ] + indexOffset; 33152 var c = face[ 2 ] + indexOffset; 33153 33154 indices.push( a, b, c ); 33155 groupCount += 3; 33156 33157 } 33158 33159 } 33160 33161 } 33162 33163 ShapeBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 33164 ShapeBufferGeometry.prototype.constructor = ShapeBufferGeometry; 33165 33166 ShapeBufferGeometry.prototype.toJSON = function () { 33167 33168 var data = BufferGeometry.prototype.toJSON.call( this ); 33169 33170 var shapes = this.parameters.shapes; 33171 33172 return toJSON$1( shapes, data ); 33173 33174 }; 33175 33176 // 33177 33178 function toJSON$1( shapes, data ) { 33179 33180 data.shapes = []; 33181 33182 if ( Array.isArray( shapes ) ) { 33183 33184 for ( var i = 0, l = shapes.length; i < l; i ++ ) { 33185 33186 var shape = shapes[ i ]; 33187 33188 data.shapes.push( shape.uuid ); 33189 33190 } 33191 33192 } else { 33193 33194 data.shapes.push( shapes.uuid ); 33195 33196 } 33197 33198 return data; 33199 33200 } 33201 33202 /** 33203 * @author WestLangley / http://github.com/WestLangley 33204 * @author Mugen87 / https://github.com/Mugen87 33205 */ 33206 33207 function EdgesGeometry( geometry, thresholdAngle ) { 33208 33209 BufferGeometry.call( this ); 33210 33211 this.type = 'EdgesGeometry'; 33212 33213 this.parameters = { 33214 thresholdAngle: thresholdAngle 33215 }; 33216 33217 thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1; 33218 33219 // buffer 33220 33221 var vertices = []; 33222 33223 // helper variables 33224 33225 var thresholdDot = Math.cos( _Math.DEG2RAD * thresholdAngle ); 33226 var edge = [ 0, 0 ], edges = {}, edge1, edge2; 33227 var key, keys = [ 'a', 'b', 'c' ]; 33228 33229 // prepare source geometry 33230 33231 var geometry2; 33232 33233 if ( geometry.isBufferGeometry ) { 33234 33235 geometry2 = new Geometry(); 33236 geometry2.fromBufferGeometry( geometry ); 33237 33238 } else { 33239 33240 geometry2 = geometry.clone(); 33241 33242 } 33243 33244 geometry2.mergeVertices(); 33245 geometry2.computeFaceNormals(); 33246 33247 var sourceVertices = geometry2.vertices; 33248 var faces = geometry2.faces; 33249 33250 // now create a data structure where each entry represents an edge with its adjoining faces 33251 33252 for ( var i = 0, l = faces.length; i < l; i ++ ) { 33253 33254 var face = faces[ i ]; 33255 33256 for ( var j = 0; j < 3; j ++ ) { 33257 33258 edge1 = face[ keys[ j ] ]; 33259 edge2 = face[ keys[ ( j + 1 ) % 3 ] ]; 33260 edge[ 0 ] = Math.min( edge1, edge2 ); 33261 edge[ 1 ] = Math.max( edge1, edge2 ); 33262 33263 key = edge[ 0 ] + ',' + edge[ 1 ]; 33264 33265 if ( edges[ key ] === undefined ) { 33266 33267 edges[ key ] = { index1: edge[ 0 ], index2: edge[ 1 ], face1: i, face2: undefined }; 33268 33269 } else { 33270 33271 edges[ key ].face2 = i; 33272 33273 } 33274 33275 } 33276 33277 } 33278 33279 // generate vertices 33280 33281 for ( key in edges ) { 33282 33283 var e = edges[ key ]; 33284 33285 // an edge is only rendered if the angle (in degrees) between the face normals of the adjoining faces exceeds this value. default = 1 degree. 33286 33287 if ( e.face2 === undefined || faces[ e.face1 ].normal.dot( faces[ e.face2 ].normal ) <= thresholdDot ) { 33288 33289 var vertex = sourceVertices[ e.index1 ]; 33290 vertices.push( vertex.x, vertex.y, vertex.z ); 33291 33292 vertex = sourceVertices[ e.index2 ]; 33293 vertices.push( vertex.x, vertex.y, vertex.z ); 33294 33295 } 33296 33297 } 33298 33299 // build geometry 33300 33301 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 33302 33303 } 33304 33305 EdgesGeometry.prototype = Object.create( BufferGeometry.prototype ); 33306 EdgesGeometry.prototype.constructor = EdgesGeometry; 33307 33308 /** 33309 * @author mrdoob / http://mrdoob.com/ 33310 * @author Mugen87 / https://github.com/Mugen87 33311 */ 33312 33313 // CylinderGeometry 33314 33315 function CylinderGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { 33316 33317 Geometry.call( this ); 33318 33319 this.type = 'CylinderGeometry'; 33320 33321 this.parameters = { 33322 radiusTop: radiusTop, 33323 radiusBottom: radiusBottom, 33324 height: height, 33325 radialSegments: radialSegments, 33326 heightSegments: heightSegments, 33327 openEnded: openEnded, 33328 thetaStart: thetaStart, 33329 thetaLength: thetaLength 33330 }; 33331 33332 this.fromBufferGeometry( new CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) ); 33333 this.mergeVertices(); 33334 33335 } 33336 33337 CylinderGeometry.prototype = Object.create( Geometry.prototype ); 33338 CylinderGeometry.prototype.constructor = CylinderGeometry; 33339 33340 // CylinderBufferGeometry 33341 33342 function CylinderBufferGeometry( radiusTop, radiusBottom, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { 33343 33344 BufferGeometry.call( this ); 33345 33346 this.type = 'CylinderBufferGeometry'; 33347 33348 this.parameters = { 33349 radiusTop: radiusTop, 33350 radiusBottom: radiusBottom, 33351 height: height, 33352 radialSegments: radialSegments, 33353 heightSegments: heightSegments, 33354 openEnded: openEnded, 33355 thetaStart: thetaStart, 33356 thetaLength: thetaLength 33357 }; 33358 33359 var scope = this; 33360 33361 radiusTop = radiusTop !== undefined ? radiusTop : 1; 33362 radiusBottom = radiusBottom !== undefined ? radiusBottom : 1; 33363 height = height || 1; 33364 33365 radialSegments = Math.floor( radialSegments ) || 8; 33366 heightSegments = Math.floor( heightSegments ) || 1; 33367 33368 openEnded = openEnded !== undefined ? openEnded : false; 33369 thetaStart = thetaStart !== undefined ? thetaStart : 0.0; 33370 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; 33371 33372 // buffers 33373 33374 var indices = []; 33375 var vertices = []; 33376 var normals = []; 33377 var uvs = []; 33378 33379 // helper variables 33380 33381 var index = 0; 33382 var indexArray = []; 33383 var halfHeight = height / 2; 33384 var groupStart = 0; 33385 33386 // generate geometry 33387 33388 generateTorso(); 33389 33390 if ( openEnded === false ) { 33391 33392 if ( radiusTop > 0 ) generateCap( true ); 33393 if ( radiusBottom > 0 ) generateCap( false ); 33394 33395 } 33396 33397 // build geometry 33398 33399 this.setIndex( indices ); 33400 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 33401 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 33402 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 33403 33404 function generateTorso() { 33405 33406 var x, y; 33407 var normal = new Vector3(); 33408 var vertex = new Vector3(); 33409 33410 var groupCount = 0; 33411 33412 // this will be used to calculate the normal 33413 var slope = ( radiusBottom - radiusTop ) / height; 33414 33415 // generate vertices, normals and uvs 33416 33417 for ( y = 0; y <= heightSegments; y ++ ) { 33418 33419 var indexRow = []; 33420 33421 var v = y / heightSegments; 33422 33423 // calculate the radius of the current row 33424 33425 var radius = v * ( radiusBottom - radiusTop ) + radiusTop; 33426 33427 for ( x = 0; x <= radialSegments; x ++ ) { 33428 33429 var u = x / radialSegments; 33430 33431 var theta = u * thetaLength + thetaStart; 33432 33433 var sinTheta = Math.sin( theta ); 33434 var cosTheta = Math.cos( theta ); 33435 33436 // vertex 33437 33438 vertex.x = radius * sinTheta; 33439 vertex.y = - v * height + halfHeight; 33440 vertex.z = radius * cosTheta; 33441 vertices.push( vertex.x, vertex.y, vertex.z ); 33442 33443 // normal 33444 33445 normal.set( sinTheta, slope, cosTheta ).normalize(); 33446 normals.push( normal.x, normal.y, normal.z ); 33447 33448 // uv 33449 33450 uvs.push( u, 1 - v ); 33451 33452 // save index of vertex in respective row 33453 33454 indexRow.push( index ++ ); 33455 33456 } 33457 33458 // now save vertices of the row in our index array 33459 33460 indexArray.push( indexRow ); 33461 33462 } 33463 33464 // generate indices 33465 33466 for ( x = 0; x < radialSegments; x ++ ) { 33467 33468 for ( y = 0; y < heightSegments; y ++ ) { 33469 33470 // we use the index array to access the correct indices 33471 33472 var a = indexArray[ y ][ x ]; 33473 var b = indexArray[ y + 1 ][ x ]; 33474 var c = indexArray[ y + 1 ][ x + 1 ]; 33475 var d = indexArray[ y ][ x + 1 ]; 33476 33477 // faces 33478 33479 indices.push( a, b, d ); 33480 indices.push( b, c, d ); 33481 33482 // update group counter 33483 33484 groupCount += 6; 33485 33486 } 33487 33488 } 33489 33490 // add a group to the geometry. this will ensure multi material support 33491 33492 scope.addGroup( groupStart, groupCount, 0 ); 33493 33494 // calculate new start value for groups 33495 33496 groupStart += groupCount; 33497 33498 } 33499 33500 function generateCap( top ) { 33501 33502 var x, centerIndexStart, centerIndexEnd; 33503 33504 var uv = new Vector2(); 33505 var vertex = new Vector3(); 33506 33507 var groupCount = 0; 33508 33509 var radius = ( top === true ) ? radiusTop : radiusBottom; 33510 var sign = ( top === true ) ? 1 : - 1; 33511 33512 // save the index of the first center vertex 33513 centerIndexStart = index; 33514 33515 // first we generate the center vertex data of the cap. 33516 // because the geometry needs one set of uvs per face, 33517 // we must generate a center vertex per face/segment 33518 33519 for ( x = 1; x <= radialSegments; x ++ ) { 33520 33521 // vertex 33522 33523 vertices.push( 0, halfHeight * sign, 0 ); 33524 33525 // normal 33526 33527 normals.push( 0, sign, 0 ); 33528 33529 // uv 33530 33531 uvs.push( 0.5, 0.5 ); 33532 33533 // increase index 33534 33535 index ++; 33536 33537 } 33538 33539 // save the index of the last center vertex 33540 33541 centerIndexEnd = index; 33542 33543 // now we generate the surrounding vertices, normals and uvs 33544 33545 for ( x = 0; x <= radialSegments; x ++ ) { 33546 33547 var u = x / radialSegments; 33548 var theta = u * thetaLength + thetaStart; 33549 33550 var cosTheta = Math.cos( theta ); 33551 var sinTheta = Math.sin( theta ); 33552 33553 // vertex 33554 33555 vertex.x = radius * sinTheta; 33556 vertex.y = halfHeight * sign; 33557 vertex.z = radius * cosTheta; 33558 vertices.push( vertex.x, vertex.y, vertex.z ); 33559 33560 // normal 33561 33562 normals.push( 0, sign, 0 ); 33563 33564 // uv 33565 33566 uv.x = ( cosTheta * 0.5 ) + 0.5; 33567 uv.y = ( sinTheta * 0.5 * sign ) + 0.5; 33568 uvs.push( uv.x, uv.y ); 33569 33570 // increase index 33571 33572 index ++; 33573 33574 } 33575 33576 // generate indices 33577 33578 for ( x = 0; x < radialSegments; x ++ ) { 33579 33580 var c = centerIndexStart + x; 33581 var i = centerIndexEnd + x; 33582 33583 if ( top === true ) { 33584 33585 // face top 33586 33587 indices.push( i, i + 1, c ); 33588 33589 } else { 33590 33591 // face bottom 33592 33593 indices.push( i + 1, i, c ); 33594 33595 } 33596 33597 groupCount += 3; 33598 33599 } 33600 33601 // add a group to the geometry. this will ensure multi material support 33602 33603 scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); 33604 33605 // calculate new start value for groups 33606 33607 groupStart += groupCount; 33608 33609 } 33610 33611 } 33612 33613 CylinderBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 33614 CylinderBufferGeometry.prototype.constructor = CylinderBufferGeometry; 33615 33616 /** 33617 * @author abelnation / http://github.com/abelnation 33618 */ 33619 33620 // ConeGeometry 33621 33622 function ConeGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { 33623 33624 CylinderGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); 33625 33626 this.type = 'ConeGeometry'; 33627 33628 this.parameters = { 33629 radius: radius, 33630 height: height, 33631 radialSegments: radialSegments, 33632 heightSegments: heightSegments, 33633 openEnded: openEnded, 33634 thetaStart: thetaStart, 33635 thetaLength: thetaLength 33636 }; 33637 33638 } 33639 33640 ConeGeometry.prototype = Object.create( CylinderGeometry.prototype ); 33641 ConeGeometry.prototype.constructor = ConeGeometry; 33642 33643 // ConeBufferGeometry 33644 33645 function ConeBufferGeometry( radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ) { 33646 33647 CylinderBufferGeometry.call( this, 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); 33648 33649 this.type = 'ConeBufferGeometry'; 33650 33651 this.parameters = { 33652 radius: radius, 33653 height: height, 33654 radialSegments: radialSegments, 33655 heightSegments: heightSegments, 33656 openEnded: openEnded, 33657 thetaStart: thetaStart, 33658 thetaLength: thetaLength 33659 }; 33660 33661 } 33662 33663 ConeBufferGeometry.prototype = Object.create( CylinderBufferGeometry.prototype ); 33664 ConeBufferGeometry.prototype.constructor = ConeBufferGeometry; 33665 33666 /** 33667 * @author benaadams / https://twitter.com/ben_a_adams 33668 * @author Mugen87 / https://github.com/Mugen87 33669 * @author hughes 33670 */ 33671 33672 // CircleGeometry 33673 33674 function CircleGeometry( radius, segments, thetaStart, thetaLength ) { 33675 33676 Geometry.call( this ); 33677 33678 this.type = 'CircleGeometry'; 33679 33680 this.parameters = { 33681 radius: radius, 33682 segments: segments, 33683 thetaStart: thetaStart, 33684 thetaLength: thetaLength 33685 }; 33686 33687 this.fromBufferGeometry( new CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) ); 33688 this.mergeVertices(); 33689 33690 } 33691 33692 CircleGeometry.prototype = Object.create( Geometry.prototype ); 33693 CircleGeometry.prototype.constructor = CircleGeometry; 33694 33695 // CircleBufferGeometry 33696 33697 function CircleBufferGeometry( radius, segments, thetaStart, thetaLength ) { 33698 33699 BufferGeometry.call( this ); 33700 33701 this.type = 'CircleBufferGeometry'; 33702 33703 this.parameters = { 33704 radius: radius, 33705 segments: segments, 33706 thetaStart: thetaStart, 33707 thetaLength: thetaLength 33708 }; 33709 33710 radius = radius || 1; 33711 segments = segments !== undefined ? Math.max( 3, segments ) : 8; 33712 33713 thetaStart = thetaStart !== undefined ? thetaStart : 0; 33714 thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2; 33715 33716 // buffers 33717 33718 var indices = []; 33719 var vertices = []; 33720 var normals = []; 33721 var uvs = []; 33722 33723 // helper variables 33724 33725 var i, s; 33726 var vertex = new Vector3(); 33727 var uv = new Vector2(); 33728 33729 // center point 33730 33731 vertices.push( 0, 0, 0 ); 33732 normals.push( 0, 0, 1 ); 33733 uvs.push( 0.5, 0.5 ); 33734 33735 for ( s = 0, i = 3; s <= segments; s ++, i += 3 ) { 33736 33737 var segment = thetaStart + s / segments * thetaLength; 33738 33739 // vertex 33740 33741 vertex.x = radius * Math.cos( segment ); 33742 vertex.y = radius * Math.sin( segment ); 33743 33744 vertices.push( vertex.x, vertex.y, vertex.z ); 33745 33746 // normal 33747 33748 normals.push( 0, 0, 1 ); 33749 33750 // uvs 33751 33752 uv.x = ( vertices[ i ] / radius + 1 ) / 2; 33753 uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; 33754 33755 uvs.push( uv.x, uv.y ); 33756 33757 } 33758 33759 // indices 33760 33761 for ( i = 1; i <= segments; i ++ ) { 33762 33763 indices.push( i, i + 1, 0 ); 33764 33765 } 33766 33767 // build geometry 33768 33769 this.setIndex( indices ); 33770 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 33771 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); 33772 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 33773 33774 } 33775 33776 CircleBufferGeometry.prototype = Object.create( BufferGeometry.prototype ); 33777 CircleBufferGeometry.prototype.constructor = CircleBufferGeometry; 33778 33779 33780 33781 var Geometries = /*#__PURE__*/Object.freeze({ 33782 WireframeGeometry: WireframeGeometry, 33783 ParametricGeometry: ParametricGeometry, 33784 ParametricBufferGeometry: ParametricBufferGeometry, 33785 TetrahedronGeometry: TetrahedronGeometry, 33786 TetrahedronBufferGeometry: TetrahedronBufferGeometry, 33787 OctahedronGeometry: OctahedronGeometry, 33788 OctahedronBufferGeometry: OctahedronBufferGeometry, 33789 IcosahedronGeometry: IcosahedronGeometry, 33790 IcosahedronBufferGeometry: IcosahedronBufferGeometry, 33791 DodecahedronGeometry: DodecahedronGeometry, 33792 DodecahedronBufferGeometry: DodecahedronBufferGeometry, 33793 PolyhedronGeometry: PolyhedronGeometry, 33794 PolyhedronBufferGeometry: PolyhedronBufferGeometry, 33795 TubeGeometry: TubeGeometry, 33796 TubeBufferGeometry: TubeBufferGeometry, 33797 TorusKnotGeometry: TorusKnotGeometry, 33798 TorusKnotBufferGeometry: TorusKnotBufferGeometry, 33799 TorusGeometry: TorusGeometry, 33800 TorusBufferGeometry: TorusBufferGeometry, 33801 TextGeometry: TextGeometry, 33802 TextBufferGeometry: TextBufferGeometry, 33803 SphereGeometry: SphereGeometry, 33804 SphereBufferGeometry: SphereBufferGeometry, 33805 RingGeometry: RingGeometry, 33806 RingBufferGeometry: RingBufferGeometry, 33807 PlaneGeometry: PlaneGeometry, 33808 PlaneBufferGeometry: PlaneBufferGeometry, 33809 LatheGeometry: LatheGeometry, 33810 LatheBufferGeometry: LatheBufferGeometry, 33811 ShapeGeometry: ShapeGeometry, 33812 ShapeBufferGeometry: ShapeBufferGeometry, 33813 ExtrudeGeometry: ExtrudeGeometry, 33814 ExtrudeBufferGeometry: ExtrudeBufferGeometry, 33815 EdgesGeometry: EdgesGeometry, 33816 ConeGeometry: ConeGeometry, 33817 ConeBufferGeometry: ConeBufferGeometry, 33818 CylinderGeometry: CylinderGeometry, 33819 CylinderBufferGeometry: CylinderBufferGeometry, 33820 CircleGeometry: CircleGeometry, 33821 CircleBufferGeometry: CircleBufferGeometry, 33822 BoxGeometry: BoxGeometry, 33823 BoxBufferGeometry: BoxBufferGeometry 33824 }); 33825 33826 /** 33827 * @author mrdoob / http://mrdoob.com/ 33828 * 33829 * parameters = { 33830 * color: <THREE.Color> 33831 * } 33832 */ 33833 33834 function ShadowMaterial( parameters ) { 33835 33836 Material.call( this ); 33837 33838 this.type = 'ShadowMaterial'; 33839 33840 this.color = new Color( 0x000000 ); 33841 this.transparent = true; 33842 33843 this.setValues( parameters ); 33844 33845 } 33846 33847 ShadowMaterial.prototype = Object.create( Material.prototype ); 33848 ShadowMaterial.prototype.constructor = ShadowMaterial; 33849 33850 ShadowMaterial.prototype.isShadowMaterial = true; 33851 33852 ShadowMaterial.prototype.copy = function ( source ) { 33853 33854 Material.prototype.copy.call( this, source ); 33855 33856 this.color.copy( source.color ); 33857 33858 return this; 33859 33860 }; 33861 33862 /** 33863 * @author mrdoob / http://mrdoob.com/ 33864 */ 33865 33866 function RawShaderMaterial( parameters ) { 33867 33868 ShaderMaterial.call( this, parameters ); 33869 33870 this.type = 'RawShaderMaterial'; 33871 33872 } 33873 33874 RawShaderMaterial.prototype = Object.create( ShaderMaterial.prototype ); 33875 RawShaderMaterial.prototype.constructor = RawShaderMaterial; 33876 33877 RawShaderMaterial.prototype.isRawShaderMaterial = true; 33878 33879 /** 33880 * @author WestLangley / http://github.com/WestLangley 33881 * 33882 * parameters = { 33883 * color: <hex>, 33884 * roughness: <float>, 33885 * metalness: <float>, 33886 * opacity: <float>, 33887 * 33888 * map: new THREE.Texture( <Image> ), 33889 * 33890 * lightMap: new THREE.Texture( <Image> ), 33891 * lightMapIntensity: <float> 33892 * 33893 * aoMap: new THREE.Texture( <Image> ), 33894 * aoMapIntensity: <float> 33895 * 33896 * emissive: <hex>, 33897 * emissiveIntensity: <float> 33898 * emissiveMap: new THREE.Texture( <Image> ), 33899 * 33900 * bumpMap: new THREE.Texture( <Image> ), 33901 * bumpScale: <float>, 33902 * 33903 * normalMap: new THREE.Texture( <Image> ), 33904 * normalScale: <Vector2>,
33905 * 33906 * displacementMap: new THREE.Texture( <Image> ), 33907 * displacementScale: <float>, 33908 * displacementBias: <float>, 33909 * 33910 * roughnessMap: new THREE.Texture( <Image> ), 33911 * 33912 * metalnessMap: new THREE.Texture( <Image> ), 33913 * 33914 * alphaMap: new THREE.Texture( <Image> ), 33915 * 33916 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ), 33917 * envMapIntensity: <float> 33918 * 33919 * refractionRatio: <float>, 33920 * 33921 * wireframe: <boolean>, 33922 * wireframeLinewidth: <float>, 33923 * 33924 * skinning: <bool>, 33925 * morphTargets: <bool>, 33926 * morphNormals: <bool> 33927 * } 33928 */ 33929 33930 function MeshStandardMaterial( parameters ) { 33931 33932 Material.call( this ); 33933 33934 this.defines = { 'STANDARD': '' }; 33935 33936 this.type = 'MeshStandardMaterial'; 33937 33938 this.color = new Color( 0xffffff ); // diffuse 33939 this.roughness = 0.5; 33940 this.metalness = 0.5; 33941 33942 this.map = null; 33943 33944 this.lightMap = null; 33945 this.lightMapIntensity = 1.0; 33946 33947 this.aoMap = null; 33948 this.aoMapIntensity = 1.0; 33949 33950 this.emissive = new Color( 0x000000 ); 33951 this.emissiveIntensity = 1.0; 33952 this.emissiveMap = null; 33953 33954 this.bumpMap = null; 33955 this.bumpScale = 1; 33956 33957 this.normalMap = null; 33958 this.normalScale = new Vector2( 1, 1 ); 33959 33960 this.displacementMap = null; 33961 this.displacementScale = 1; 33962 this.displacementBias = 0; 33963 33964 this.roughnessMap = null; 33965 33966 this.metalnessMap = null; 33967 33968 this.alphaMap = null; 33969 33970 this.envMap = null; 33971 this.envMapIntensity = 1.0; 33972 33973 this.refractionRatio = 0.98; 33974 33975 this.wireframe = false; 33976 this.wireframeLinewidth = 1; 33977 this.wireframeLinecap = 'round'; 33978 this.wireframeLinejoin = 'round'; 33979 33980 this.skinning = false; 33981 this.morphTargets = false; 33982 this.morphNormals = false; 33983 33984 this.setValues( parameters ); 33985 33986 } 33987 33988 MeshStandardMaterial.prototype = Object.create( Material.prototype ); 33989 MeshStandardMaterial.prototype.constructor = MeshStandardMaterial; 33990 33991 MeshStandardMaterial.prototype.isMeshStandardMaterial = true; 33992 33993 MeshStandardMaterial.prototype.copy = function ( source ) { 33994 33995 Material.prototype.copy.call( this, source ); 33996 33997 this.defines = { 'STANDARD': '' }; 33998 33999 this.color.copy( source.color ); 34000 this.roughness = source.roughness; 34001 this.metalness = source.metalness; 34002 34003 this.map = source.map; 34004 34005 this.lightMap = source.lightMap; 34006 this.lightMapIntensity = source.lightMapIntensity; 34007 34008 this.aoMap = source.aoMap; 34009 this.aoMapIntensity = source.aoMapIntensity; 34010 34011 this.emissive.copy( source.emissive ); 34012 this.emissiveMap = source.emissiveMap; 34013 this.emissiveIntensity = source.emissiveIntensity; 34014 34015 this.bumpMap = source.bumpMap; 34016 this.bumpScale = source.bumpScale; 34017 34018 this.normalMap = source.normalMap; 34019 this.normalScale.copy( source.normalScale ); 34020 34021 this.displacementMap = source.displacementMap; 34022 this.displacementScale = source.displacementScale; 34023 this.displacementBias = source.displacementBias; 34024 34025 this.roughnessMap = source.roughnessMap; 34026 34027 this.metalnessMap = source.metalnessMap; 34028 34029 this.alphaMap = source.alphaMap; 34030 34031 this.envMap = source.envMap; 34032 this.envMapIntensity = source.envMapIntensity; 34033 34034 this.refractionRatio = source.refractionRatio; 34035 34036 this.wireframe = source.wireframe; 34037 this.wireframeLinewidth = source.wireframeLinewidth; 34038 this.wireframeLinecap = source.wireframeLinecap; 34039 this.wireframeLinejoin = source.wireframeLinejoin; 34040 34041 this.skinning = source.skinning; 34042 this.morphTargets = source.morphTargets; 34043 this.morphNormals = source.morphNormals; 34044 34045 return this; 34046 34047 }; 34048 34049 /** 34050 * @author WestLangley / http://github.com/WestLangley 34051 * 34052 * parameters = { 34053 * reflectivity: <float> 34054 * } 34055 */ 34056 34057 function MeshPhysicalMaterial( parameters ) { 34058 34059 MeshStandardMaterial.call( this ); 34060 34061 this.defines = { 'PHYSICAL': '' }; 34062 34063 this.type = 'MeshPhysicalMaterial'; 34064 34065 this.reflectivity = 0.5; // maps to F0 = 0.04 34066 34067 this.clearCoat = 0.0; 34068 this.clearCoatRoughness = 0.0; 34069 34070 this.setValues( parameters ); 34071 34072 } 34073 34074 MeshPhysicalMaterial.prototype = Object.create( MeshStandardMaterial.prototype ); 34075 MeshPhysicalMaterial.prototype.constructor = MeshPhysicalMaterial; 34076 34077 MeshPhysicalMaterial.prototype.isMeshPhysicalMaterial = true; 34078 34079 MeshPhysicalMaterial.prototype.copy = function ( source ) { 34080 34081 MeshStandardMaterial.prototype.copy.call( this, source ); 34082 34083 this.defines = { 'PHYSICAL': '' }; 34084 34085 this.reflectivity = source.reflectivity; 34086 34087 this.clearCoat = source.clearCoat; 34088 this.clearCoatRoughness = source.clearCoatRoughness; 34089 34090 return this; 34091 34092 }; 34093 34094 /** 34095 * @author mrdoob / http://mrdoob.com/ 34096 * @author alteredq / http://alteredqualia.com/ 34097 * 34098 * parameters = { 34099 * color: <hex>, 34100 * specular: <hex>, 34101 * shininess: <float>, 34102 * opacity: <float>, 34103 * 34104 * map: new THREE.Texture( <Image> ), 34105 * 34106 * lightMap: new THREE.Texture( <Image> ), 34107 * lightMapIntensity: <float> 34108 * 34109 * aoMap: new THREE.Texture( <Image> ), 34110 * aoMapIntensity: <float> 34111 * 34112 * emissive: <hex>, 34113 * emissiveIntensity: <float> 34114 * emissiveMap: new THREE.Texture( <Image> ), 34115 * 34116 * bumpMap: new THREE.Texture( <Image> ), 34117 * bumpScale: <float>, 34118 * 34119 * normalMap: new THREE.Texture( <Image> ), 34120 * normalScale: <Vector2>,
34121 * 34122 * displacementMap: new THREE.Texture( <Image> ), 34123 * displacementScale: <float>, 34124 * displacementBias: <float>, 34125 * 34126 * specularMap: new THREE.Texture( <Image> ), 34127 * 34128 * alphaMap: new THREE.Texture( <Image> ), 34129 * 34130 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ), 34131 * combine: THREE.Multiply, 34132 * reflectivity: <float>, 34133 * refractionRatio: <float>, 34134 * 34135 * wireframe: <boolean>, 34136 * wireframeLinewidth: <float>, 34137 * 34138 * skinning: <bool>, 34139 * morphTargets: <bool>, 34140 * morphNormals: <bool> 34141 * } 34142 */ 34143 34144 function MeshPhongMaterial( parameters ) { 34145 34146 Material.call( this ); 34147 34148 this.type = 'MeshPhongMaterial'; 34149 34150 this.color = new Color( 0xffffff ); // diffuse 34151 this.specular = new Color( 0x111111 ); 34152 this.shininess = 30; 34153 34154 this.map = null; 34155 34156 this.lightMap = null; 34157 this.lightMapIntensity = 1.0; 34158 34159 this.aoMap = null; 34160 this.aoMapIntensity = 1.0; 34161 34162 this.emissive = new Color( 0x000000 ); 34163 this.emissiveIntensity = 1.0; 34164 this.emissiveMap = null; 34165 34166 this.bumpMap = null; 34167 this.bumpScale = 1; 34168 34169 this.normalMap = null; 34170 this.normalScale = new Vector2( 1, 1 ); 34171 34172 this.displacementMap = null; 34173 this.displacementScale = 1; 34174 this.displacementBias = 0; 34175 34176 this.specularMap = null; 34177 34178 this.alphaMap = null; 34179 34180 this.envMap = null; 34181 this.combine = MultiplyOperation; 34182 this.reflectivity = 1; 34183 this.refractionRatio = 0.98; 34184 34185 this.wireframe = false; 34186 this.wireframeLinewidth = 1; 34187 this.wireframeLinecap = 'round'; 34188 this.wireframeLinejoin = 'round'; 34189 34190 this.skinning = false; 34191 this.morphTargets = false; 34192 this.morphNormals = false; 34193 34194 this.setValues( parameters ); 34195 34196 } 34197 34198 MeshPhongMaterial.prototype = Object.create( Material.prototype ); 34199 MeshPhongMaterial.prototype.constructor = MeshPhongMaterial; 34200 34201 MeshPhongMaterial.prototype.isMeshPhongMaterial = true; 34202 34203 MeshPhongMaterial.prototype.copy = function ( source ) { 34204 34205 Material.prototype.copy.call( this, source ); 34206 34207 this.color.copy( source.color ); 34208 this.specular.copy( source.specular ); 34209 this.shininess = source.shininess; 34210 34211 this.map = source.map; 34212 34213 this.lightMap = source.lightMap; 34214 this.lightMapIntensity = source.lightMapIntensity; 34215 34216 this.aoMap = source.aoMap; 34217 this.aoMapIntensity = source.aoMapIntensity; 34218 34219 this.emissive.copy( source.emissive ); 34220 this.emissiveMap = source.emissiveMap; 34221 this.emissiveIntensity = source.emissiveIntensity; 34222 34223 this.bumpMap = source.bumpMap; 34224 this.bumpScale = source.bumpScale; 34225 34226 this.normalMap = source.normalMap; 34227 this.normalScale.copy( source.normalScale ); 34228 34229 this.displacementMap = source.displacementMap; 34230 this.displacementScale = source.displacementScale; 34231 this.displacementBias = source.displacementBias; 34232 34233 this.specularMap = source.specularMap; 34234 34235 this.alphaMap = source.alphaMap; 34236 34237 this.envMap = source.envMap; 34238 this.combine = source.combine; 34239 this.reflectivity = source.reflectivity; 34240 this.refractionRatio = source.refractionRatio; 34241 34242 this.wireframe = source.wireframe; 34243 this.wireframeLinewidth = source.wireframeLinewidth; 34244 this.wireframeLinecap = source.wireframeLinecap; 34245 this.wireframeLinejoin = source.wireframeLinejoin; 34246 34247 this.skinning = source.skinning; 34248 this.morphTargets = source.morphTargets; 34249 this.morphNormals = source.morphNormals; 34250 34251 return this; 34252 34253 }; 34254 34255 /** 34256 * @author takahirox / http://github.com/takahirox 34257 * 34258 * parameters = { 34259 * gradientMap: new THREE.Texture( <Image> ) 34260 * } 34261 */ 34262 34263 function MeshToonMaterial( parameters ) { 34264 34265 MeshPhongMaterial.call( this ); 34266 34267 this.defines = { 'TOON': '' }; 34268 34269 this.type = 'MeshToonMaterial'; 34270 34271 this.gradientMap = null; 34272 34273 this.setValues( parameters ); 34274 34275 } 34276 34277 MeshToonMaterial.prototype = Object.create( MeshPhongMaterial.prototype ); 34278 MeshToonMaterial.prototype.constructor = MeshToonMaterial; 34279 34280 MeshToonMaterial.prototype.isMeshToonMaterial = true; 34281 34282 MeshToonMaterial.prototype.copy = function ( source ) { 34283 34284 MeshPhongMaterial.prototype.copy.call( this, source ); 34285 34286 this.gradientMap = source.gradientMap; 34287 34288 return this; 34289 34290 }; 34291 34292 /** 34293 * @author mrdoob / http://mrdoob.com/ 34294 * @author WestLangley / http://github.com/WestLangley 34295 * 34296 * parameters = { 34297 * opacity: <float>, 34298 * 34299 * bumpMap: new THREE.Texture( <Image> ), 34300 * bumpScale: <float>, 34301 * 34302 * normalMap: new THREE.Texture( <Image> ), 34303 * normalScale: <Vector2>,
34304 * 34305 * displacementMap: new THREE.Texture( <Image> ), 34306 * displacementScale: <float>, 34307 * displacementBias: <float>, 34308 * 34309 * wireframe: <boolean>, 34310 * wireframeLinewidth: <float> 34311 * 34312 * skinning: <bool>, 34313 * morphTargets: <bool>, 34314 * morphNormals: <bool> 34315 * } 34316 */ 34317 34318 function MeshNormalMaterial( parameters ) { 34319 34320 Material.call( this ); 34321 34322 this.type = 'MeshNormalMaterial'; 34323 34324 this.bumpMap = null; 34325 this.bumpScale = 1; 34326 34327 this.normalMap = null; 34328 this.normalScale = new Vector2( 1, 1 ); 34329 34330 this.displacementMap = null; 34331 this.displacementScale = 1; 34332 this.displacementBias = 0; 34333 34334 this.wireframe = false; 34335 this.wireframeLinewidth = 1; 34336 34337 this.fog = false; 34338 this.lights = false; 34339 34340 this.skinning = false; 34341 this.morphTargets = false; 34342 this.morphNormals = false; 34343 34344 this.setValues( parameters ); 34345 34346 } 34347 34348 MeshNormalMaterial.prototype = Object.create( Material.prototype ); 34349 MeshNormalMaterial.prototype.constructor = MeshNormalMaterial; 34350 34351 MeshNormalMaterial.prototype.isMeshNormalMaterial = true; 34352 34353 MeshNormalMaterial.prototype.copy = function ( source ) { 34354 34355 Material.prototype.copy.call( this, source ); 34356 34357 this.bumpMap = source.bumpMap; 34358 this.bumpScale = source.bumpScale; 34359 34360 this.normalMap = source.normalMap; 34361 this.normalScale.copy( source.normalScale ); 34362 34363 this.displacementMap = source.displacementMap; 34364 this.displacementScale = source.displacementScale; 34365 this.displacementBias = source.displacementBias; 34366 34367 this.wireframe = source.wireframe; 34368 this.wireframeLinewidth = source.wireframeLinewidth; 34369 34370 this.skinning = source.skinning; 34371 this.morphTargets = source.morphTargets; 34372 this.morphNormals = source.morphNormals; 34373 34374 return this; 34375 34376 }; 34377 34378 /** 34379 * @author mrdoob / http://mrdoob.com/ 34380 * @author alteredq / http://alteredqualia.com/ 34381 * 34382 * parameters = { 34383 * color: <hex>, 34384 * opacity: <float>, 34385 * 34386 * map: new THREE.Texture( <Image> ), 34387 * 34388 * lightMap: new THREE.Texture( <Image> ), 34389 * lightMapIntensity: <float> 34390 * 34391 * aoMap: new THREE.Texture( <Image> ), 34392 * aoMapIntensity: <float> 34393 * 34394 * emissive: <hex>, 34395 * emissiveIntensity: <float> 34396 * emissiveMap: new THREE.Texture( <Image> ), 34397 * 34398 * specularMap: new THREE.Texture( <Image> ), 34399 * 34400 * alphaMap: new THREE.Texture( <Image> ), 34401 * 34402 * envMap: new THREE.CubeTexture( [posx, negx, posy, negy, posz, negz] ), 34403 * combine: THREE.Multiply, 34404 * reflectivity: <float>, 34405 * refractionRatio: <float>, 34406 * 34407 * wireframe: <boolean>, 34408 * wireframeLinewidth: <float>, 34409 * 34410 * skinning: <bool>, 34411 * morphTargets: <bool>, 34412 * morphNormals: <bool> 34413 * } 34414 */ 34415 34416 function MeshLambertMaterial( parameters ) { 34417 34418 Material.call( this ); 34419 34420 this.type = 'MeshLambertMaterial'; 34421 34422 this.color = new Color( 0xffffff ); // diffuse 34423 34424 this.map = null; 34425 34426 this.lightMap = null; 34427 this.lightMapIntensity = 1.0; 34428 34429 this.aoMap = null; 34430 this.aoMapIntensity = 1.0; 34431 34432 this.emissive = new Color( 0x000000 ); 34433 this.emissiveIntensity = 1.0; 34434 this.emissiveMap = null; 34435 34436 this.specularMap = null; 34437 34438 this.alphaMap = null; 34439 34440 this.envMap = null; 34441 this.combine = MultiplyOperation; 34442 this.reflectivity = 1; 34443 this.refractionRatio = 0.98; 34444 34445 this.wireframe = false; 34446 this.wireframeLinewidth = 1; 34447 this.wireframeLinecap = 'round'; 34448 this.wireframeLinejoin = 'round'; 34449 34450 this.skinning = false; 34451 this.morphTargets = false; 34452 this.morphNormals = false; 34453 34454 this.setValues( parameters ); 34455 34456 } 34457 34458 MeshLambertMaterial.prototype = Object.create( Material.prototype ); 34459 MeshLambertMaterial.prototype.constructor = MeshLambertMaterial; 34460 34461 MeshLambertMaterial.prototype.isMeshLambertMaterial = true; 34462 34463 MeshLambertMaterial.prototype.copy = function ( source ) { 34464 34465 Material.prototype.copy.call( this, source ); 34466 34467 this.color.copy( source.color ); 34468 34469 this.map = source.map; 34470 34471 this.lightMap = source.lightMap; 34472 this.lightMapIntensity = source.lightMapIntensity; 34473 34474 this.aoMap = source.aoMap; 34475 this.aoMapIntensity = source.aoMapIntensity; 34476 34477 this.emissive.copy( source.emissive ); 34478 this.emissiveMap = source.emissiveMap; 34479 this.emissiveIntensity = source.emissiveIntensity; 34480 34481 this.specularMap = source.specularMap; 34482 34483 this.alphaMap = source.alphaMap; 34484 34485 this.envMap = source.envMap; 34486 this.combine = source.combine; 34487 this.reflectivity = source.reflectivity; 34488 this.refractionRatio = source.refractionRatio; 34489 34490 this.wireframe = source.wireframe; 34491 this.wireframeLinewidth = source.wireframeLinewidth; 34492 this.wireframeLinecap = source.wireframeLinecap; 34493 this.wireframeLinejoin = source.wireframeLinejoin; 34494 34495 this.skinning = source.skinning; 34496 this.morphTargets = source.morphTargets; 34497 this.morphNormals = source.morphNormals; 34498 34499 return this; 34500 34501 }; 34502 34503 /** 34504 * @author alteredq / http://alteredqualia.com/ 34505 * 34506 * parameters = { 34507 * color: <hex>, 34508 * opacity: <float>, 34509 * 34510 * linewidth: <float>, 34511 * 34512 * scale: <float>, 34513 * dashSize: <float>, 34514 * gapSize: <float> 34515 * } 34516 */ 34517 34518 function LineDashedMaterial( parameters ) { 34519 34520 LineBasicMaterial.call( this ); 34521 34522 this.type = 'LineDashedMaterial'; 34523 34524 this.scale = 1; 34525 this.dashSize = 3; 34526 this.gapSize = 1; 34527 34528 this.setValues( parameters ); 34529 34530 } 34531 34532 LineDashedMaterial.prototype = Object.create( LineBasicMaterial.prototype ); 34533 LineDashedMaterial.prototype.constructor = LineDashedMaterial; 34534 34535 LineDashedMaterial.prototype.isLineDashedMaterial = true; 34536 34537 LineDashedMaterial.prototype.copy = function ( source ) { 34538 34539 LineBasicMaterial.prototype.copy.call( this, source ); 34540 34541 this.scale = source.scale; 34542 this.dashSize = source.dashSize; 34543 this.gapSize = source.gapSize; 34544 34545 return this; 34546 34547 }; 34548 34549 34550 34551 var Materials = /*#__PURE__*/Object.freeze({ 34552 ShadowMaterial: ShadowMaterial, 34553 SpriteMaterial: SpriteMaterial, 34554 RawShaderMaterial: RawShaderMaterial, 34555 ShaderMaterial: ShaderMaterial, 34556 PointsMaterial: PointsMaterial, 34557 MeshPhysicalMaterial: MeshPhysicalMaterial, 34558 MeshStandardMaterial: MeshStandardMaterial, 34559 MeshPhongMaterial: MeshPhongMaterial, 34560 MeshToonMaterial: MeshToonMaterial, 34561 MeshNormalMaterial: MeshNormalMaterial, 34562 MeshLambertMaterial: MeshLambertMaterial, 34563 MeshDepthMaterial: MeshDepthMaterial, 34564 MeshDistanceMaterial: MeshDistanceMaterial, 34565 MeshBasicMaterial: MeshBasicMaterial, 34566 LineDashedMaterial: LineDashedMaterial, 34567 LineBasicMaterial: LineBasicMaterial, 34568 Material: Material 34569 }); 34570 34571 /** 34572 * @author mrdoob / http://mrdoob.com/ 34573 */ 34574 34575 var Cache = { 34576 34577 enabled: false, 34578 34579 files: {}, 34580 34581 add: function ( key, file ) { 34582 34583 if ( this.enabled === false ) return; 34584
vendor: 10,683 bytes, lines 34585-35154
34585 // console.log( 'THREE.Cache', 'Adding key:', key ); 34586 34587 this.files[ key ] = file; 34588 34589 }, 34590 34591 get: function ( key ) { 34592 34593 if ( this.enabled === false ) return; 34594 34595 // console.log( 'THREE.Cache', 'Checking key:', key ); 34596 34597 return this.files[ key ]; 34598 34599 }, 34600 34601 remove: function ( key ) { 34602 34603 delete this.files[ key ]; 34604 34605 }, 34606 34607 clear: function () { 34608 34609 this.files = {}; 34610 34611 } 34612 34613 }; 34614 34615 /** 34616 * @author mrdoob / http://mrdoob.com/ 34617 */ 34618 34619 function LoadingManager( onLoad, onProgress, onError ) { 34620 34621 var scope = this; 34622 34623 var isLoading = false; 34624 var itemsLoaded = 0; 34625 var itemsTotal = 0; 34626 var urlModifier = undefined; 34627 34628 this.onStart = undefined; 34629 this.onLoad = onLoad; 34630 this.onProgress = onProgress; 34631 this.onError = onError; 34632 34633 this.itemStart = function ( url ) { 34634 34635 itemsTotal ++; 34636 34637 if ( isLoading === false ) { 34638 34639 if ( scope.onStart !== undefined ) { 34640 34641 scope.onStart( url, itemsLoaded, itemsTotal ); 34642 34643 } 34644 34645 } 34646 34647 isLoading = true; 34648 34649 }; 34650 34651 this.itemEnd = function ( url ) { 34652 34653 itemsLoaded ++; 34654 34655 if ( scope.onProgress !== undefined ) { 34656 34657 scope.onProgress( url, itemsLoaded, itemsTotal ); 34658 34659 } 34660 34661 if ( itemsLoaded === itemsTotal ) { 34662 34663 isLoading = false; 34664 34665 if ( scope.onLoad !== undefined ) { 34666 34667 scope.onLoad(); 34668 34669 } 34670 34671 } 34672 34673 }; 34674 34675 this.itemError = function ( url ) { 34676 34677 if ( scope.onError !== undefined ) { 34678 34679 scope.onError( url ); 34680 34681 } 34682 34683 }; 34684 34685 this.resolveURL = function ( url ) { 34686 34687 if ( urlModifier ) { 34688 34689 return urlModifier( url ); 34690 34691 } 34692 34693 return url; 34694 34695 }; 34696 34697 this.setURLModifier = function ( transform ) { 34698 34699 urlModifier = transform; 34700 return this; 34701 34702 }; 34703 34704 } 34705 34706 var DefaultLoadingManager = new LoadingManager(); 34707 34708 /** 34709 * @author mrdoob / http://mrdoob.com/ 34710 */ 34711 34712 var loading = {}; 34713 34714 function FileLoader( manager ) { 34715 34716 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 34717 34718 } 34719 34720 Object.assign( FileLoader.prototype, { 34721 34722 load: function ( url, onLoad, onProgress, onError ) { 34723 34724 if ( url === undefined ) url = ''; 34725 34726 if ( this.path !== undefined ) url = this.path + url; 34727 34728 url = this.manager.resolveURL( url ); 34729 34730 var scope = this; 34731 34732 var cached = Cache.get( url ); 34733 34734 if ( cached !== undefined ) { 34735 34736 scope.manager.itemStart( url ); 34737 34738 setTimeout( function () { 34739 34740 if ( onLoad ) onLoad( cached ); 34741 34742 scope.manager.itemEnd( url ); 34743 34744 }, 0 ); 34745 34746 return cached; 34747 34748 } 34749 34750 // Check if request is duplicate 34751 34752 if ( loading[ url ] !== undefined ) { 34753 34754 loading[ url ].push( { 34755 34756 onLoad: onLoad, 34757 onProgress: onProgress, 34758 onError: onError 34759 34760 } ); 34761 34762 return; 34763 34764 } 34765 34766 // Check for data: URI 34767 var dataUriRegex = /^data:(.*?)(;base64)?,(.*)$/; 34768 var dataUriRegexResult = url.match( dataUriRegex ); 34769 34770 // Safari can not handle Data URIs through XMLHttpRequest so process manually 34771 if ( dataUriRegexResult ) { 34772 34773 var mimeType = dataUriRegexResult[ 1 ]; 34774 var isBase64 = !! dataUriRegexResult[ 2 ]; 34775 var data = dataUriRegexResult[ 3 ]; 34776 34777 data = window.decodeURIComponent( data ); 34778 34779 if ( isBase64 ) data = window.atob( data ); 34780 34781 try { 34782 34783 var response; 34784 var responseType = ( this.responseType || '' ).toLowerCase(); 34785 34786 switch ( responseType ) { 34787 34788 case 'arraybuffer': 34789 case 'blob': 34790 34791 var view = new Uint8Array( data.length ); 34792 34793 for ( var i = 0; i < data.length; i ++ ) { 34794 34795 view[ i ] = data.charCodeAt( i ); 34796 34797 } 34798 34799 if ( responseType === 'blob' ) { 34800 34801 response = new Blob( [ view.buffer ], { type: mimeType } ); 34802 34803 } else { 34804 34805 response = view.buffer; 34806 34807 } 34808 34809 break; 34810 34811 case 'document': 34812 34813 var parser = new DOMParser(); 34814 response = parser.parseFromString( data, mimeType ); 34815 34816 break; 34817 34818 case 'json': 34819 34820 response = JSON.parse( data ); 34821 34822 break; 34823 34824 default: // 'text' or other 34825 34826 response = data; 34827 34828 break; 34829 34830 } 34831 34832 // Wait for next browser tick like standard XMLHttpRequest event dispatching does 34833 window.setTimeout( function () { 34834 34835 if ( onLoad ) onLoad( response ); 34836 34837 scope.manager.itemEnd( url ); 34838 34839 }, 0 ); 34840 34841 } catch ( error ) { 34842 34843 // Wait for next browser tick like standard XMLHttpRequest event dispatching does 34844 window.setTimeout( function () { 34845 34846 if ( onError ) onError( error ); 34847 34848 scope.manager.itemEnd( url ); 34849 scope.manager.itemError( url ); 34850 34851 }, 0 ); 34852 34853 } 34854 34855 } else { 34856 34857 // Initialise array for duplicate requests 34858 34859 loading[ url ] = []; 34860 34861 loading[ url ].push( { 34862 34863 onLoad: onLoad, 34864 onProgress: onProgress, 34865 onError: onError 34866 34867 } ); 34868 34869 var request = new XMLHttpRequest(); 34870 34871 request.open( 'GET', url, true ); 34872 34873 request.addEventListener( 'load', function ( event ) { 34874 34875 var response = this.response; 34876 34877 Cache.add( url, response ); 34878 34879 var callbacks = loading[ url ]; 34880 34881 delete loading[ url ]; 34882 34883 if ( this.status === 200 || this.status === 0 ) { 34884 34885 // Some browsers return HTTP Status 0 when using non-http protocol 34886 // e.g. 'file://' or 'data://'. Handle as success. 34887 34888 if ( this.status === 0 ) console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); 34889 34890 for ( var i = 0, il = callbacks.length; i < il; i ++ ) { 34891 34892 var callback = callbacks[ i ]; 34893 if ( callback.onLoad ) callback.onLoad( response ); 34894 34895 } 34896 34897 scope.manager.itemEnd( url ); 34898 34899 } else { 34900 34901 for ( var i = 0, il = callbacks.length; i < il; i ++ ) { 34902 34903 var callback = callbacks[ i ]; 34904 if ( callback.onError ) callback.onError( event ); 34905 34906 } 34907 34908 scope.manager.itemEnd( url ); 34909 scope.manager.itemError( url ); 34910 34911 } 34912 34913 }, false ); 34914 34915 request.addEventListener( 'progress', function ( event ) { 34916 34917 var callbacks = loading[ url ]; 34918 34919 for ( var i = 0, il = callbacks.length; i < il; i ++ ) { 34920 34921 var callback = callbacks[ i ]; 34922 if ( callback.onProgress ) callback.onProgress( event ); 34923 34924 } 34925 34926 }, false ); 34927 34928 request.addEventListener( 'error', function ( event ) { 34929 34930 var callbacks = loading[ url ]; 34931 34932 delete loading[ url ]; 34933 34934 for ( var i = 0, il = callbacks.length; i < il; i ++ ) { 34935 34936 var callback = callbacks[ i ]; 34937 if ( callback.onError ) callback.onError( event ); 34938 34939 } 34940 34941 scope.manager.itemEnd( url ); 34942 scope.manager.itemError( url ); 34943 34944 }, false ); 34945 34946 if ( this.responseType !== undefined ) request.responseType = this.responseType; 34947 if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials; 34948 34949 if ( request.overrideMimeType ) request.overrideMimeType( this.mimeType !== undefined ? this.mimeType : 'text/plain' ); 34950 34951 for ( var header in this.requestHeader ) { 34952 34953 request.setRequestHeader( header, this.requestHeader[ header ] ); 34954 34955 } 34956 34957 request.send( null ); 34958 34959 } 34960 34961 scope.manager.itemStart( url ); 34962 34963 return request; 34964 34965 }, 34966 34967 setPath: function ( value ) { 34968 34969 this.path = value; 34970 return this; 34971 34972 }, 34973 34974 setResponseType: function ( value ) { 34975 34976 this.responseType = value; 34977 return this; 34978 34979 }, 34980 34981 setWithCredentials: function ( value ) { 34982 34983 this.withCredentials = value; 34984 return this; 34985 34986 }, 34987 34988 setMimeType: function ( value ) { 34989 34990 this.mimeType = value; 34991 return this; 34992 34993 }, 34994 34995 setRequestHeader: function ( value ) { 34996 34997 this.requestHeader = value; 34998 return this; 34999 35000 } 35001 35002 } ); 35003 35004 /** 35005 * @author mrdoob / http://mrdoob.com/ 35006 * 35007 * Abstract Base class to block based textures loader (dds, pvr, ...) 35008 */ 35009 35010 function CompressedTextureLoader( manager ) { 35011 35012 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 35013 35014 // override in sub classes 35015 this._parser = null; 35016 35017 } 35018 35019 Object.assign( CompressedTextureLoader.prototype, { 35020 35021 load: function ( url, onLoad, onProgress, onError ) { 35022 35023 var scope = this; 35024 35025 var images = []; 35026 35027 var texture = new CompressedTexture(); 35028 texture.image = images; 35029 35030 var loader = new FileLoader( this.manager ); 35031 loader.setPath( this.path ); 35032 loader.setResponseType( 'arraybuffer' ); 35033 35034 function loadTexture( i ) { 35035 35036 loader.load( url[ i ], function ( buffer ) { 35037 35038 var texDatas = scope._parser( buffer, true ); 35039 35040 images[ i ] = { 35041 width: texDatas.width, 35042 height: texDatas.height, 35043 format: texDatas.format, 35044 mipmaps: texDatas.mipmaps 35045 }; 35046 35047 loaded += 1; 35048 35049 if ( loaded === 6 ) { 35050 35051 if ( texDatas.mipmapCount === 1 ) 35052 texture.minFilter = LinearFilter; 35053 35054 texture.format = texDatas.format; 35055 texture.needsUpdate = true; 35056 35057 if ( onLoad ) onLoad( texture ); 35058 35059 } 35060 35061 }, onProgress, onError ); 35062 35063 } 35064 35065 if ( Array.isArray( url ) ) { 35066 35067 var loaded = 0; 35068 35069 for ( var i = 0, il = url.length; i < il; ++ i ) { 35070 35071 loadTexture( i ); 35072 35073 } 35074 35075 } else { 35076 35077 // compressed cubemap texture stored in a single DDS file 35078 35079 loader.load( url, function ( buffer ) { 35080 35081 var texDatas = scope._parser( buffer, true ); 35082 35083 if ( texDatas.isCubemap ) { 35084 35085 var faces = texDatas.mipmaps.length / texDatas.mipmapCount; 35086 35087 for ( var f = 0; f < faces; f ++ ) { 35088 35089 images[ f ] = { mipmaps: [] }; 35090 35091 for ( var i = 0; i < texDatas.mipmapCount; i ++ ) { 35092 35093 images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] ); 35094 images[ f ].format = texDatas.format; 35095 images[ f ].width = texDatas.width; 35096 images[ f ].height = texDatas.height; 35097 35098 } 35099 35100 } 35101 35102 } else { 35103 35104 texture.image.width = texDatas.width; 35105 texture.image.height = texDatas.height; 35106 texture.mipmaps = texDatas.mipmaps; 35107 35108 } 35109 35110 if ( texDatas.mipmapCount === 1 ) { 35111 35112 texture.minFilter = LinearFilter; 35113 35114 } 35115 35116 texture.format = texDatas.format; 35117 texture.needsUpdate = true; 35118 35119 if ( onLoad ) onLoad( texture ); 35120 35121 }, onProgress, onError ); 35122 35123 } 35124 35125 return texture; 35126 35127 }, 35128 35129 setPath: function ( value ) { 35130 35131 this.path = value; 35132 return this; 35133 35134 } 35135 35136 } ); 35137 35138 /** 35139 * @author Nikos M. / https://github.com/foo123/ 35140 * 35141 * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) 35142 */ 35143 35144 function DataTextureLoader( manager ) { 35145 35146 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 35147 35148 // override in sub classes 35149 this._parser = null; 35150 35151 } 35152 35153 Object.assign( DataTextureLoader.prototype, { 35154
35155 load: function ( url, onLoad, onProgress, onError ) { 35156 35157 var scope = this; 35158 35159 var texture = new DataTexture(); 35160 35161 var loader = new FileLoader( this.manager ); 35162 loader.setResponseType( 'arraybuffer' ); 35163 35164 loader.load( url, function ( buffer ) { 35165 35166 var texData = scope._parser( buffer ); 35167 35168 if ( ! texData ) return; 35169 35170 if ( undefined !== texData.image ) { 35171 35172 texture.image = texData.image; 35173 35174 } else if ( undefined !== texData.data ) { 35175 35176 texture.image.width = texData.width; 35177 texture.image.height = texData.height; 35178 texture.image.data = texData.data; 35179 35180 } 35181 35182 texture.wrapS = undefined !== texData.wrapS ? texData.wrapS : ClampToEdgeWrapping; 35183 texture.wrapT = undefined !== texData.wrapT ? texData.wrapT : ClampToEdgeWrapping; 35184 35185 texture.magFilter = undefined !== texData.magFilter ? texData.magFilter : LinearFilter; 35186 texture.minFilter = undefined !== texData.minFilter ? texData.minFilter : LinearMipMapLinearFilter; 35187 35188 texture.anisotropy = undefined !== texData.anisotropy ? texData.anisotropy : 1; 35189 35190 if ( undefined !== texData.format ) { 35191 35192 texture.format = texData.format; 35193 35194 } 35195 if ( undefined !== texData.type ) { 35196 35197 texture.type = texData.type; 35198 35199 } 35200 35201 if ( undefined !== texData.mipmaps ) { 35202 35203 texture.mipmaps = texData.mipmaps; 35204 35205 } 35206 35207 if ( 1 === texData.mipmapCount ) { 35208 35209 texture.minFilter = LinearFilter; 35210 35211 } 35212 35213 texture.needsUpdate = true; 35214 35215 if ( onLoad ) onLoad( texture, texData ); 35216 35217 }, onProgress, onError ); 35218 35219 35220 return texture; 35221 35222 } 35223 35224 } ); 35225 35226 /** 35227 * @author mrdoob / http://mrdoob.com/ 35228 */ 35229 35230 35231 function ImageLoader( manager ) { 35232 35233 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 35234 35235 } 35236 35237 Object.assign( ImageLoader.prototype, { 35238
vendor: 100,403 bytes, lines 35239-39931
35239 crossOrigin: 'Anonymous', 35240 35241 load: function ( url, onLoad, onProgress, onError ) { 35242 35243 if ( url === undefined ) url = ''; 35244 35245 if ( this.path !== undefined ) url = this.path + url; 35246 35247 url = this.manager.resolveURL( url ); 35248 35249 var scope = this; 35250 35251 var cached = Cache.get( url ); 35252 35253 if ( cached !== undefined ) { 35254 35255 scope.manager.itemStart( url ); 35256 35257 setTimeout( function () { 35258 35259 if ( onLoad ) onLoad( cached ); 35260 35261 scope.manager.itemEnd( url ); 35262 35263 }, 0 ); 35264 35265 return cached; 35266 35267 } 35268 35269 var image = document.createElementNS( 'http://www.w3.org/1999/xhtml', 'img' ); 35270 35271 function onImageLoad() { 35272 35273 image.removeEventListener( 'load', onImageLoad, false ); 35274 image.removeEventListener( 'error', onImageError, false ); 35275 35276 Cache.add( url, this ); 35277 35278 if ( onLoad ) onLoad( this ); 35279 35280 scope.manager.itemEnd( url ); 35281 35282 } 35283 35284 function onImageError( event ) { 35285 35286 image.removeEventListener( 'load', onImageLoad, false ); 35287 image.removeEventListener( 'error', onImageError, false ); 35288 35289 if ( onError ) onError( event ); 35290 35291 scope.manager.itemEnd( url ); 35292 scope.manager.itemError( url ); 35293 35294 } 35295 35296 image.addEventListener( 'load', onImageLoad, false ); 35297 image.addEventListener( 'error', onImageError, false ); 35298 35299 if ( url.substr( 0, 5 ) !== 'data:' ) { 35300 35301 if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; 35302 35303 } 35304 35305 scope.manager.itemStart( url ); 35306 35307 image.src = url; 35308 35309 return image; 35310 35311 }, 35312 35313 setCrossOrigin: function ( value ) { 35314 35315 this.crossOrigin = value; 35316 return this; 35317 35318 }, 35319 35320 setPath: function ( value ) { 35321 35322 this.path = value; 35323 return this; 35324 35325 } 35326 35327 } ); 35328 35329 /** 35330 * @author mrdoob / http://mrdoob.com/ 35331 */ 35332 35333 35334 function CubeTextureLoader( manager ) { 35335 35336 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 35337 35338 } 35339 35340 Object.assign( CubeTextureLoader.prototype, { 35341 35342 crossOrigin: 'Anonymous', 35343 35344 load: function ( urls, onLoad, onProgress, onError ) { 35345 35346 var texture = new CubeTexture(); 35347 35348 var loader = new ImageLoader( this.manager ); 35349 loader.setCrossOrigin( this.crossOrigin ); 35350 loader.setPath( this.path ); 35351 35352 var loaded = 0; 35353 35354 function loadTexture( i ) { 35355 35356 loader.load( urls[ i ], function ( image ) { 35357 35358 texture.images[ i ] = image; 35359 35360 loaded ++; 35361 35362 if ( loaded === 6 ) { 35363 35364 texture.needsUpdate = true; 35365 35366 if ( onLoad ) onLoad( texture ); 35367 35368 } 35369 35370 }, undefined, onError ); 35371 35372 } 35373 35374 for ( var i = 0; i < urls.length; ++ i ) { 35375 35376 loadTexture( i ); 35377 35378 } 35379 35380 return texture; 35381 35382 }, 35383 35384 setCrossOrigin: function ( value ) { 35385 35386 this.crossOrigin = value; 35387 return this; 35388 35389 }, 35390 35391 setPath: function ( value ) { 35392 35393 this.path = value; 35394 return this; 35395 35396 } 35397 35398 } ); 35399 35400 /** 35401 * @author mrdoob / http://mrdoob.com/ 35402 */ 35403 35404 35405 function TextureLoader( manager ) { 35406 35407 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 35408 35409 } 35410 35411 Object.assign( TextureLoader.prototype, { 35412 35413 crossOrigin: 'Anonymous', 35414 35415 load: function ( url, onLoad, onProgress, onError ) { 35416 35417 var texture = new Texture(); 35418 35419 var loader = new ImageLoader( this.manager ); 35420 loader.setCrossOrigin( this.crossOrigin ); 35421 loader.setPath( this.path ); 35422 35423 loader.load( url, function ( image ) { 35424 35425 texture.image = image; 35426 35427 // JPEGs can't have an alpha channel, so memory can be saved by storing them as RGB. 35428 var isJPEG = url.search( /\.(jpg|jpeg)$/ ) > 0 || url.search( /^data\:image\/jpeg/ ) === 0; 35429 35430 texture.format = isJPEG ? RGBFormat : RGBAFormat; 35431 texture.needsUpdate = true; 35432 35433 if ( onLoad !== undefined ) { 35434 35435 onLoad( texture ); 35436 35437 } 35438 35439 }, onProgress, onError ); 35440 35441 return texture; 35442 35443 }, 35444 35445 setCrossOrigin: function ( value ) { 35446 35447 this.crossOrigin = value; 35448 return this; 35449 35450 }, 35451 35452 setPath: function ( value ) { 35453 35454 this.path = value; 35455 return this; 35456 35457 } 35458 35459 } ); 35460 35461 /** 35462 * @author zz85 / http://www.lab4games.net/zz85/blog 35463 * Extensible curve object 35464 * 35465 * Some common of curve methods: 35466 * .getPoint( t, optionalTarget ), .getTangent( t ) 35467 * .getPointAt( u, optionalTarget ), .getTangentAt( u ) 35468 * .getPoints(), .getSpacedPoints() 35469 * .getLength() 35470 * .updateArcLengths() 35471 * 35472 * This following curves inherit from THREE.Curve: 35473 * 35474 * -- 2D curves -- 35475 * THREE.ArcCurve 35476 * THREE.CubicBezierCurve 35477 * THREE.EllipseCurve 35478 * THREE.LineCurve 35479 * THREE.QuadraticBezierCurve 35480 * THREE.SplineCurve 35481 * 35482 * -- 3D curves -- 35483 * THREE.CatmullRomCurve3 35484 * THREE.CubicBezierCurve3 35485 * THREE.LineCurve3 35486 * THREE.QuadraticBezierCurve3 35487 * 35488 * A series of curves can be represented as a THREE.CurvePath. 35489 * 35490 **/ 35491 35492 /************************************************************** 35493 * Abstract Curve base class 35494 **************************************************************/ 35495 35496 function Curve() { 35497 35498 this.type = 'Curve'; 35499 35500 this.arcLengthDivisions = 200; 35501 35502 } 35503 35504 Object.assign( Curve.prototype, { 35505 35506 // Virtual base class method to overwrite and implement in subclasses 35507 // - t [0 .. 1] 35508 35509 getPoint: function ( /* t, optionalTarget */ ) { 35510 35511 console.warn( 'THREE.Curve: .getPoint() not implemented.' ); 35512 return null; 35513 35514 }, 35515 35516 // Get point at relative position in curve according to arc length 35517 // - u [0 .. 1] 35518 35519 getPointAt: function ( u, optionalTarget ) { 35520 35521 var t = this.getUtoTmapping( u ); 35522 return this.getPoint( t, optionalTarget ); 35523 35524 }, 35525 35526 // Get sequence of points using getPoint( t ) 35527 35528 getPoints: function ( divisions ) { 35529 35530 if ( divisions === undefined ) divisions = 5; 35531 35532 var points = []; 35533 35534 for ( var d = 0; d <= divisions; d ++ ) { 35535 35536 points.push( this.getPoint( d / divisions ) ); 35537 35538 } 35539 35540 return points; 35541 35542 }, 35543 35544 // Get sequence of points using getPointAt( u ) 35545 35546 getSpacedPoints: function ( divisions ) { 35547 35548 if ( divisions === undefined ) divisions = 5; 35549 35550 var points = []; 35551 35552 for ( var d = 0; d <= divisions; d ++ ) { 35553 35554 points.push( this.getPointAt( d / divisions ) ); 35555 35556 } 35557 35558 return points; 35559 35560 }, 35561 35562 // Get total curve arc length 35563 35564 getLength: function () { 35565 35566 var lengths = this.getLengths(); 35567 return lengths[ lengths.length - 1 ]; 35568 35569 }, 35570 35571 // Get list of cumulative segment lengths 35572 35573 getLengths: function ( divisions ) { 35574 35575 if ( divisions === undefined ) divisions = this.arcLengthDivisions; 35576 35577 if ( this.cacheArcLengths && 35578 ( this.cacheArcLengths.length === divisions + 1 ) && 35579 ! this.needsUpdate ) { 35580 35581 return this.cacheArcLengths; 35582 35583 } 35584 35585 this.needsUpdate = false; 35586 35587 var cache = []; 35588 var current, last = this.getPoint( 0 ); 35589 var p, sum = 0; 35590 35591 cache.push( 0 ); 35592 35593 for ( p = 1; p <= divisions; p ++ ) { 35594 35595 current = this.getPoint( p / divisions ); 35596 sum += current.distanceTo( last ); 35597 cache.push( sum ); 35598 last = current; 35599 35600 } 35601 35602 this.cacheArcLengths = cache; 35603 35604 return cache; // { sums: cache, sum: sum }; Sum is in the last element. 35605 35606 }, 35607 35608 updateArcLengths: function () { 35609 35610 this.needsUpdate = true; 35611 this.getLengths(); 35612 35613 }, 35614 35615 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant 35616 35617 getUtoTmapping: function ( u, distance ) { 35618 35619 var arcLengths = this.getLengths(); 35620 35621 var i = 0, il = arcLengths.length; 35622 35623 var targetArcLength; // The targeted u distance value to get 35624 35625 if ( distance ) { 35626 35627 targetArcLength = distance; 35628 35629 } else { 35630 35631 targetArcLength = u * arcLengths[ il - 1 ]; 35632 35633 } 35634 35635 // binary search for the index with largest value smaller than target u distance 35636 35637 var low = 0, high = il - 1, comparison; 35638 35639 while ( low <= high ) { 35640 35641 i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats 35642 35643 comparison = arcLengths[ i ] - targetArcLength; 35644 35645 if ( comparison < 0 ) { 35646 35647 low = i + 1; 35648 35649 } else if ( comparison > 0 ) { 35650 35651 high = i - 1; 35652 35653 } else { 35654 35655 high = i; 35656 break; 35657 35658 // DONE 35659 35660 } 35661 35662 } 35663 35664 i = high; 35665 35666 if ( arcLengths[ i ] === targetArcLength ) { 35667 35668 return i / ( il - 1 ); 35669 35670 } 35671 35672 // we could get finer grain at lengths, or use simple interpolation between two points 35673 35674 var lengthBefore = arcLengths[ i ]; 35675 var lengthAfter = arcLengths[ i + 1 ]; 35676 35677 var segmentLength = lengthAfter - lengthBefore; 35678 35679 // determine where we are between the 'before' and 'after' points 35680 35681 var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; 35682 35683 // add that fractional amount to t 35684 35685 var t = ( i + segmentFraction ) / ( il - 1 ); 35686 35687 return t; 35688 35689 }, 35690 35691 // Returns a unit vector tangent at t 35692 // In case any sub curve does not implement its tangent derivation, 35693 // 2 points a small delta apart will be used to find its gradient 35694 // which seems to give a reasonable approximation 35695 35696 getTangent: function ( t ) { 35697 35698 var delta = 0.0001; 35699 var t1 = t - delta; 35700 var t2 = t + delta; 35701 35702 // Capping in case of danger 35703 35704 if ( t1 < 0 ) t1 = 0; 35705 if ( t2 > 1 ) t2 = 1; 35706 35707 var pt1 = this.getPoint( t1 ); 35708 var pt2 = this.getPoint( t2 ); 35709 35710 var vec = pt2.clone().sub( pt1 ); 35711 return vec.normalize(); 35712 35713 }, 35714 35715 getTangentAt: function ( u ) { 35716 35717 var t = this.getUtoTmapping( u ); 35718 return this.getTangent( t ); 35719 35720 }, 35721 35722 computeFrenetFrames: function ( segments, closed ) { 35723 35724 // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf 35725 35726 var normal = new Vector3(); 35727 35728 var tangents = []; 35729 var normals = []; 35730 var binormals = []; 35731 35732 var vec = new Vector3(); 35733 var mat = new Matrix4(); 35734 35735 var i, u, theta; 35736 35737 // compute the tangent vectors for each segment on the curve 35738 35739 for ( i = 0; i <= segments; i ++ ) { 35740 35741 u = i / segments; 35742 35743 tangents[ i ] = this.getTangentAt( u ); 35744 tangents[ i ].normalize(); 35745 35746 } 35747 35748 // select an initial normal vector perpendicular to the first tangent vector, 35749 // and in the direction of the minimum tangent xyz component 35750 35751 normals[ 0 ] = new Vector3(); 35752 binormals[ 0 ] = new Vector3(); 35753 var min = Number.MAX_VALUE; 35754 var tx = Math.abs( tangents[ 0 ].x ); 35755 var ty = Math.abs( tangents[ 0 ].y ); 35756 var tz = Math.abs( tangents[ 0 ].z ); 35757 35758 if ( tx <= min ) { 35759 35760 min = tx; 35761 normal.set( 1, 0, 0 ); 35762 35763 } 35764 35765 if ( ty <= min ) { 35766 35767 min = ty; 35768 normal.set( 0, 1, 0 ); 35769 35770 } 35771 35772 if ( tz <= min ) { 35773 35774 normal.set( 0, 0, 1 ); 35775 35776 } 35777 35778 vec.crossVectors( tangents[ 0 ], normal ).normalize(); 35779 35780 normals[ 0 ].crossVectors( tangents[ 0 ], vec ); 35781 binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); 35782 35783 35784 // compute the slowly-varying normal and binormal vectors for each segment on the curve 35785 35786 for ( i = 1; i <= segments; i ++ ) { 35787 35788 normals[ i ] = normals[ i - 1 ].clone(); 35789 35790 binormals[ i ] = binormals[ i - 1 ].clone(); 35791 35792 vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); 35793 35794 if ( vec.length() > Number.EPSILON ) { 35795 35796 vec.normalize(); 35797 35798 theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors 35799 35800 normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); 35801 35802 } 35803 35804 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 35805 35806 } 35807 35808 // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same 35809 35810 if ( closed === true ) { 35811 35812 theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); 35813 theta /= segments; 35814 35815 if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { 35816 35817 theta = - theta; 35818 35819 } 35820 35821 for ( i = 1; i <= segments; i ++ ) { 35822 35823 // twist a little... 35824 normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); 35825 binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); 35826 35827 } 35828 35829 } 35830 35831 return { 35832 tangents: tangents, 35833 normals: normals, 35834 binormals: binormals 35835 }; 35836 35837 }, 35838 35839 clone: function () { 35840 35841 return new this.constructor().copy( this ); 35842 35843 }, 35844 35845 copy: function ( source ) { 35846 35847 this.arcLengthDivisions = source.arcLengthDivisions; 35848 35849 return this; 35850 35851 }, 35852 35853 toJSON: function () { 35854 35855 var data = { 35856 metadata: { 35857 version: 4.5, 35858 type: 'Curve', 35859 generator: 'Curve.toJSON' 35860 } 35861 }; 35862 35863 data.arcLengthDivisions = this.arcLengthDivisions; 35864 data.type = this.type; 35865 35866 return data; 35867 35868 }, 35869 35870 fromJSON: function ( json ) { 35871 35872 this.arcLengthDivisions = json.arcLengthDivisions; 35873 35874 return this; 35875 35876 } 35877 35878 } ); 35879 35880 function EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 35881 35882 Curve.call( this ); 35883 35884 this.type = 'EllipseCurve'; 35885 35886 this.aX = aX || 0; 35887 this.aY = aY || 0; 35888 35889 this.xRadius = xRadius || 1; 35890 this.yRadius = yRadius || 1; 35891 35892 this.aStartAngle = aStartAngle || 0; 35893 this.aEndAngle = aEndAngle || 2 * Math.PI; 35894 35895 this.aClockwise = aClockwise || false; 35896 35897 this.aRotation = aRotation || 0; 35898 35899 } 35900 35901 EllipseCurve.prototype = Object.create( Curve.prototype ); 35902 EllipseCurve.prototype.constructor = EllipseCurve; 35903 35904 EllipseCurve.prototype.isEllipseCurve = true; 35905 35906 EllipseCurve.prototype.getPoint = function ( t, optionalTarget ) { 35907 35908 var point = optionalTarget || new Vector2(); 35909 35910 var twoPi = Math.PI * 2; 35911 var deltaAngle = this.aEndAngle - this.aStartAngle; 35912 var samePoints = Math.abs( deltaAngle ) < Number.EPSILON; 35913 35914 // ensures that deltaAngle is 0 .. 2 PI 35915 while ( deltaAngle < 0 ) deltaAngle += twoPi; 35916 while ( deltaAngle > twoPi ) deltaAngle -= twoPi; 35917 35918 if ( deltaAngle < Number.EPSILON ) { 35919 35920 if ( samePoints ) { 35921 35922 deltaAngle = 0; 35923 35924 } else { 35925 35926 deltaAngle = twoPi; 35927 35928 } 35929 35930 } 35931 35932 if ( this.aClockwise === true && ! samePoints ) { 35933 35934 if ( deltaAngle === twoPi ) { 35935 35936 deltaAngle = - twoPi; 35937 35938 } else { 35939 35940 deltaAngle = deltaAngle - twoPi; 35941 35942 } 35943 35944 } 35945 35946 var angle = this.aStartAngle + t * deltaAngle; 35947 var x = this.aX + this.xRadius * Math.cos( angle ); 35948 var y = this.aY + this.yRadius * Math.sin( angle ); 35949 35950 if ( this.aRotation !== 0 ) { 35951 35952 var cos = Math.cos( this.aRotation ); 35953 var sin = Math.sin( this.aRotation ); 35954 35955 var tx = x - this.aX; 35956 var ty = y - this.aY; 35957 35958 // Rotate the point about the center of the ellipse. 35959 x = tx * cos - ty * sin + this.aX; 35960 y = tx * sin + ty * cos + this.aY; 35961 35962 } 35963 35964 return point.set( x, y ); 35965 35966 }; 35967 35968 EllipseCurve.prototype.copy = function ( source ) { 35969 35970 Curve.prototype.copy.call( this, source ); 35971 35972 this.aX = source.aX; 35973 this.aY = source.aY; 35974 35975 this.xRadius = source.xRadius; 35976 this.yRadius = source.yRadius; 35977 35978 this.aStartAngle = source.aStartAngle; 35979 this.aEndAngle = source.aEndAngle; 35980 35981 this.aClockwise = source.aClockwise; 35982 35983 this.aRotation = source.aRotation; 35984 35985 return this; 35986 35987 }; 35988 35989 35990 EllipseCurve.prototype.toJSON = function () { 35991 35992 var data = Curve.prototype.toJSON.call( this ); 35993 35994 data.aX = this.aX; 35995 data.aY = this.aY; 35996 35997 data.xRadius = this.xRadius; 35998 data.yRadius = this.yRadius; 35999 36000 data.aStartAngle = this.aStartAngle; 36001 data.aEndAngle = this.aEndAngle; 36002 36003 data.aClockwise = this.aClockwise; 36004 36005 data.aRotation = this.aRotation; 36006 36007 return data; 36008 36009 }; 36010 36011 EllipseCurve.prototype.fromJSON = function ( json ) { 36012 36013 Curve.prototype.fromJSON.call( this, json ); 36014 36015 this.aX = json.aX; 36016 this.aY = json.aY; 36017 36018 this.xRadius = json.xRadius; 36019 this.yRadius = json.yRadius; 36020 36021 this.aStartAngle = json.aStartAngle; 36022 this.aEndAngle = json.aEndAngle; 36023 36024 this.aClockwise = json.aClockwise; 36025 36026 this.aRotation = json.aRotation; 36027 36028 return this; 36029 36030 }; 36031 36032 function ArcCurve( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 36033 36034 EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 36035 36036 this.type = 'ArcCurve'; 36037 36038 } 36039 36040 ArcCurve.prototype = Object.create( EllipseCurve.prototype ); 36041 ArcCurve.prototype.constructor = ArcCurve; 36042 36043 ArcCurve.prototype.isArcCurve = true; 36044 36045 /** 36046 * @author zz85 https://github.com/zz85 36047 * 36048 * Centripetal CatmullRom Curve - which is useful for avoiding 36049 * cusps and self-intersections in non-uniform catmull rom curves. 36050 * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf 36051 * 36052 * curve.type accepts centripetal(default), chordal and catmullrom 36053 * curve.tension is used for catmullrom which defaults to 0.5 36054 */ 36055 36056 36057 /* 36058 Based on an optimized c++ solution in 36059 - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ 36060 - http://ideone.com/NoEbVM 36061 36062 This CubicPoly class could be used for reusing some variables and calculations, 36063 but for three.js curve use, it could be possible inlined and flatten into a single function call 36064 which can be placed in CurveUtils. 36065 */ 36066 36067 function CubicPoly() { 36068 36069 var c0 = 0, c1 = 0, c2 = 0, c3 = 0; 36070 36071 /* 36072 * Compute coefficients for a cubic polynomial 36073 * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 36074 * such that 36075 * p(0) = x0, p(1) = x1 36076 * and 36077 * p'(0) = t0, p'(1) = t1. 36078 */ 36079 function init( x0, x1, t0, t1 ) { 36080 36081 c0 = x0; 36082 c1 = t0; 36083 c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; 36084 c3 = 2 * x0 - 2 * x1 + t0 + t1; 36085 36086 } 36087 36088 return { 36089 36090 initCatmullRom: function ( x0, x1, x2, x3, tension ) { 36091 36092 init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); 36093 36094 }, 36095 36096 initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { 36097 36098 // compute tangents when parameterized in [t1,t2] 36099 var t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; 36100 var t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; 36101 36102 // rescale tangents for parametrization in [0,1] 36103 t1 *= dt1; 36104 t2 *= dt1; 36105 36106 init( x1, x2, t1, t2 ); 36107 36108 }, 36109 36110 calc: function ( t ) { 36111 36112 var t2 = t * t; 36113 var t3 = t2 * t; 36114 return c0 + c1 * t + c2 * t2 + c3 * t3; 36115 36116 } 36117 36118 }; 36119 36120 } 36121 36122 // 36123 36124 var tmp = new Vector3(); 36125 var px = new CubicPoly(), py = new CubicPoly(), pz = new CubicPoly(); 36126 36127 function CatmullRomCurve3( points, closed, curveType, tension ) { 36128 36129 Curve.call( this ); 36130 36131 this.type = 'CatmullRomCurve3'; 36132 36133 this.points = points || []; 36134 this.closed = closed || false; 36135 this.curveType = curveType || 'centripetal'; 36136 this.tension = tension || 0.5; 36137 36138 } 36139 36140 CatmullRomCurve3.prototype = Object.create( Curve.prototype ); 36141 CatmullRomCurve3.prototype.constructor = CatmullRomCurve3; 36142 36143 CatmullRomCurve3.prototype.isCatmullRomCurve3 = true; 36144 36145 CatmullRomCurve3.prototype.getPoint = function ( t, optionalTarget ) { 36146 36147 var point = optionalTarget || new Vector3(); 36148 36149 var points = this.points; 36150 var l = points.length; 36151 36152 var p = ( l - ( this.closed ? 0 : 1 ) ) * t; 36153 var intPoint = Math.floor( p ); 36154 var weight = p - intPoint; 36155 36156 if ( this.closed ) { 36157 36158 intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l; 36159 36160 } else if ( weight === 0 && intPoint === l - 1 ) { 36161 36162 intPoint = l - 2; 36163 weight = 1; 36164 36165 } 36166 36167 var p0, p1, p2, p3; // 4 points 36168 36169 if ( this.closed || intPoint > 0 ) { 36170 36171 p0 = points[ ( intPoint - 1 ) % l ]; 36172 36173 } else { 36174 36175 // extrapolate first point 36176 tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); 36177 p0 = tmp; 36178 36179 } 36180 36181 p1 = points[ intPoint % l ]; 36182 p2 = points[ ( intPoint + 1 ) % l ]; 36183 36184 if ( this.closed || intPoint + 2 < l ) { 36185 36186 p3 = points[ ( intPoint + 2 ) % l ]; 36187 36188 } else { 36189 36190 // extrapolate last point 36191 tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); 36192 p3 = tmp; 36193 36194 } 36195 36196 if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { 36197 36198 // init Centripetal / Chordal Catmull-Rom 36199 var pow = this.curveType === 'chordal' ? 0.5 : 0.25; 36200 var dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); 36201 var dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); 36202 var dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); 36203 36204 // safety check for repeated points 36205 if ( dt1 < 1e-4 ) dt1 = 1.0; 36206 if ( dt0 < 1e-4 ) dt0 = dt1; 36207 if ( dt2 < 1e-4 ) dt2 = dt1; 36208 36209 px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 ); 36210 py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 ); 36211 pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 ); 36212 36213 } else if ( this.curveType === 'catmullrom' ) { 36214 36215 px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension ); 36216 py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension ); 36217 pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension ); 36218 36219 } 36220 36221 point.set( 36222 px.calc( weight ), 36223 py.calc( weight ), 36224 pz.calc( weight ) 36225 ); 36226 36227 return point; 36228 36229 }; 36230 36231 CatmullRomCurve3.prototype.copy = function ( source ) { 36232 36233 Curve.prototype.copy.call( this, source ); 36234 36235 this.points = []; 36236 36237 for ( var i = 0, l = source.points.length; i < l; i ++ ) { 36238 36239 var point = source.points[ i ]; 36240 36241 this.points.push( point.clone() ); 36242 36243 } 36244 36245 this.closed = source.closed; 36246 this.curveType = source.curveType; 36247 this.tension = source.tension; 36248 36249 return this; 36250 36251 }; 36252 36253 CatmullRomCurve3.prototype.toJSON = function () { 36254 36255 var data = Curve.prototype.toJSON.call( this ); 36256 36257 data.points = []; 36258 36259 for ( var i = 0, l = this.points.length; i < l; i ++ ) { 36260 36261 var point = this.points[ i ]; 36262 data.points.push( point.toArray() ); 36263 36264 } 36265 36266 data.closed = this.closed; 36267 data.curveType = this.curveType; 36268 data.tension = this.tension; 36269 36270 return data; 36271 36272 }; 36273 36274 CatmullRomCurve3.prototype.fromJSON = function ( json ) { 36275 36276 Curve.prototype.fromJSON.call( this, json ); 36277 36278 this.points = []; 36279 36280 for ( var i = 0, l = json.points.length; i < l; i ++ ) { 36281 36282 var point = json.points[ i ]; 36283 this.points.push( new Vector3().fromArray( point ) ); 36284 36285 } 36286 36287 this.closed = json.closed; 36288 this.curveType = json.curveType; 36289 this.tension = json.tension; 36290 36291 return this; 36292 36293 }; 36294 36295 /** 36296 * @author zz85 / http://www.lab4games.net/zz85/blog 36297 * 36298 * Bezier Curves formulas obtained from 36299 * http://en.wikipedia.org/wiki/Bézier_curve 36300 */ 36301 36302 function CatmullRom( t, p0, p1, p2, p3 ) { 36303 36304 var v0 = ( p2 - p0 ) * 0.5; 36305 var v1 = ( p3 - p1 ) * 0.5; 36306 var t2 = t * t; 36307 var t3 = t * t2; 36308 return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; 36309 36310 } 36311 36312 // 36313 36314 function QuadraticBezierP0( t, p ) { 36315 36316 var k = 1 - t; 36317 return k * k * p; 36318 36319 } 36320 36321 function QuadraticBezierP1( t, p ) { 36322 36323 return 2 * ( 1 - t ) * t * p; 36324 36325 } 36326 36327 function QuadraticBezierP2( t, p ) { 36328 36329 return t * t * p; 36330 36331 } 36332 36333 function QuadraticBezier( t, p0, p1, p2 ) { 36334 36335 return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + 36336 QuadraticBezierP2( t, p2 ); 36337 36338 } 36339 36340 // 36341 36342 function CubicBezierP0( t, p ) { 36343 36344 var k = 1 - t; 36345 return k * k * k * p; 36346 36347 } 36348 36349 function CubicBezierP1( t, p ) { 36350 36351 var k = 1 - t; 36352 return 3 * k * k * t * p; 36353 36354 } 36355 36356 function CubicBezierP2( t, p ) { 36357 36358 return 3 * ( 1 - t ) * t * t * p; 36359 36360 } 36361 36362 function CubicBezierP3( t, p ) { 36363 36364 return t * t * t * p; 36365 36366 } 36367 36368 function CubicBezier( t, p0, p1, p2, p3 ) { 36369 36370 return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + 36371 CubicBezierP3( t, p3 ); 36372 36373 } 36374 36375 function CubicBezierCurve( v0, v1, v2, v3 ) { 36376 36377 Curve.call( this ); 36378 36379 this.type = 'CubicBezierCurve'; 36380 36381 this.v0 = v0 || new Vector2(); 36382 this.v1 = v1 || new Vector2(); 36383 this.v2 = v2 || new Vector2(); 36384 this.v3 = v3 || new Vector2(); 36385 36386 } 36387 36388 CubicBezierCurve.prototype = Object.create( Curve.prototype ); 36389 CubicBezierCurve.prototype.constructor = CubicBezierCurve; 36390 36391 CubicBezierCurve.prototype.isCubicBezierCurve = true; 36392 36393 CubicBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { 36394 36395 var point = optionalTarget || new Vector2(); 36396 36397 var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 36398 36399 point.set( 36400 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 36401 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) 36402 ); 36403 36404 return point; 36405 36406 }; 36407 36408 CubicBezierCurve.prototype.copy = function ( source ) { 36409 36410 Curve.prototype.copy.call( this, source ); 36411 36412 this.v0.copy( source.v0 ); 36413 this.v1.copy( source.v1 ); 36414 this.v2.copy( source.v2 ); 36415 this.v3.copy( source.v3 ); 36416 36417 return this; 36418 36419 }; 36420 36421 CubicBezierCurve.prototype.toJSON = function () { 36422 36423 var data = Curve.prototype.toJSON.call( this ); 36424 36425 data.v0 = this.v0.toArray(); 36426 data.v1 = this.v1.toArray(); 36427 data.v2 = this.v2.toArray(); 36428 data.v3 = this.v3.toArray(); 36429 36430 return data; 36431 36432 }; 36433 36434 CubicBezierCurve.prototype.fromJSON = function ( json ) { 36435 36436 Curve.prototype.fromJSON.call( this, json ); 36437 36438 this.v0.fromArray( json.v0 ); 36439 this.v1.fromArray( json.v1 ); 36440 this.v2.fromArray( json.v2 ); 36441 this.v3.fromArray( json.v3 ); 36442 36443 return this; 36444 36445 }; 36446 36447 function CubicBezierCurve3( v0, v1, v2, v3 ) { 36448 36449 Curve.call( this ); 36450 36451 this.type = 'CubicBezierCurve3'; 36452 36453 this.v0 = v0 || new Vector3(); 36454 this.v1 = v1 || new Vector3(); 36455 this.v2 = v2 || new Vector3(); 36456 this.v3 = v3 || new Vector3(); 36457 36458 } 36459 36460 CubicBezierCurve3.prototype = Object.create( Curve.prototype ); 36461 CubicBezierCurve3.prototype.constructor = CubicBezierCurve3; 36462 36463 CubicBezierCurve3.prototype.isCubicBezierCurve3 = true; 36464 36465 CubicBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { 36466 36467 var point = optionalTarget || new Vector3(); 36468 36469 var v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; 36470 36471 point.set( 36472 CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), 36473 CubicBezier( t, v0.y, v1.y, v2.y, v3.y ), 36474 CubicBezier( t, v0.z, v1.z, v2.z, v3.z ) 36475 ); 36476 36477 return point; 36478 36479 }; 36480 36481 CubicBezierCurve3.prototype.copy = function ( source ) { 36482 36483 Curve.prototype.copy.call( this, source ); 36484 36485 this.v0.copy( source.v0 ); 36486 this.v1.copy( source.v1 ); 36487 this.v2.copy( source.v2 ); 36488 this.v3.copy( source.v3 ); 36489 36490 return this; 36491 36492 }; 36493 36494 CubicBezierCurve3.prototype.toJSON = function () { 36495 36496 var data = Curve.prototype.toJSON.call( this ); 36497 36498 data.v0 = this.v0.toArray(); 36499 data.v1 = this.v1.toArray(); 36500 data.v2 = this.v2.toArray(); 36501 data.v3 = this.v3.toArray(); 36502 36503 return data; 36504 36505 }; 36506 36507 CubicBezierCurve3.prototype.fromJSON = function ( json ) { 36508 36509 Curve.prototype.fromJSON.call( this, json ); 36510 36511 this.v0.fromArray( json.v0 ); 36512 this.v1.fromArray( json.v1 ); 36513 this.v2.fromArray( json.v2 ); 36514 this.v3.fromArray( json.v3 ); 36515 36516 return this; 36517 36518 }; 36519 36520 function LineCurve( v1, v2 ) { 36521 36522 Curve.call( this ); 36523 36524 this.type = 'LineCurve'; 36525 36526 this.v1 = v1 || new Vector2(); 36527 this.v2 = v2 || new Vector2(); 36528 36529 } 36530 36531 LineCurve.prototype = Object.create( Curve.prototype ); 36532 LineCurve.prototype.constructor = LineCurve; 36533 36534 LineCurve.prototype.isLineCurve = true; 36535 36536 LineCurve.prototype.getPoint = function ( t, optionalTarget ) { 36537 36538 var point = optionalTarget || new Vector2(); 36539 36540 if ( t === 1 ) { 36541 36542 point.copy( this.v2 ); 36543 36544 } else { 36545 36546 point.copy( this.v2 ).sub( this.v1 ); 36547 point.multiplyScalar( t ).add( this.v1 ); 36548 36549 } 36550 36551 return point; 36552 36553 }; 36554 36555 // Line curve is linear, so we can overwrite default getPointAt 36556 36557 LineCurve.prototype.getPointAt = function ( u, optionalTarget ) { 36558 36559 return this.getPoint( u, optionalTarget ); 36560 36561 }; 36562 36563 LineCurve.prototype.getTangent = function ( /* t */ ) { 36564 36565 var tangent = this.v2.clone().sub( this.v1 ); 36566 36567 return tangent.normalize(); 36568 36569 }; 36570 36571 LineCurve.prototype.copy = function ( source ) { 36572 36573 Curve.prototype.copy.call( this, source ); 36574 36575 this.v1.copy( source.v1 ); 36576 this.v2.copy( source.v2 ); 36577 36578 return this; 36579 36580 }; 36581 36582 LineCurve.prototype.toJSON = function () { 36583 36584 var data = Curve.prototype.toJSON.call( this ); 36585 36586 data.v1 = this.v1.toArray(); 36587 data.v2 = this.v2.toArray(); 36588 36589 return data; 36590 36591 }; 36592 36593 LineCurve.prototype.fromJSON = function ( json ) { 36594 36595 Curve.prototype.fromJSON.call( this, json ); 36596 36597 this.v1.fromArray( json.v1 ); 36598 this.v2.fromArray( json.v2 ); 36599 36600 return this; 36601 36602 }; 36603 36604 function LineCurve3( v1, v2 ) { 36605 36606 Curve.call( this ); 36607 36608 this.type = 'LineCurve3'; 36609 36610 this.v1 = v1 || new Vector3(); 36611 this.v2 = v2 || new Vector3(); 36612 36613 } 36614 36615 LineCurve3.prototype = Object.create( Curve.prototype ); 36616 LineCurve3.prototype.constructor = LineCurve3; 36617 36618 LineCurve3.prototype.isLineCurve3 = true; 36619 36620 LineCurve3.prototype.getPoint = function ( t, optionalTarget ) { 36621 36622 var point = optionalTarget || new Vector3(); 36623 36624 if ( t === 1 ) { 36625 36626 point.copy( this.v2 ); 36627 36628 } else { 36629 36630 point.copy( this.v2 ).sub( this.v1 ); 36631 point.multiplyScalar( t ).add( this.v1 ); 36632 36633 } 36634 36635 return point; 36636 36637 }; 36638 36639 // Line curve is linear, so we can overwrite default getPointAt 36640 36641 LineCurve3.prototype.getPointAt = function ( u, optionalTarget ) { 36642 36643 return this.getPoint( u, optionalTarget ); 36644 36645 }; 36646 36647 LineCurve3.prototype.copy = function ( source ) { 36648 36649 Curve.prototype.copy.call( this, source ); 36650 36651 this.v1.copy( source.v1 ); 36652 this.v2.copy( source.v2 ); 36653 36654 return this; 36655 36656 }; 36657 36658 LineCurve3.prototype.toJSON = function () { 36659 36660 var data = Curve.prototype.toJSON.call( this ); 36661 36662 data.v1 = this.v1.toArray(); 36663 data.v2 = this.v2.toArray(); 36664 36665 return data; 36666 36667 }; 36668 36669 LineCurve3.prototype.fromJSON = function ( json ) { 36670 36671 Curve.prototype.fromJSON.call( this, json ); 36672 36673 this.v1.fromArray( json.v1 ); 36674 this.v2.fromArray( json.v2 ); 36675 36676 return this; 36677 36678 }; 36679 36680 function QuadraticBezierCurve( v0, v1, v2 ) { 36681 36682 Curve.call( this ); 36683 36684 this.type = 'QuadraticBezierCurve'; 36685 36686 this.v0 = v0 || new Vector2(); 36687 this.v1 = v1 || new Vector2(); 36688 this.v2 = v2 || new Vector2(); 36689 36690 } 36691 36692 QuadraticBezierCurve.prototype = Object.create( Curve.prototype ); 36693 QuadraticBezierCurve.prototype.constructor = QuadraticBezierCurve; 36694 36695 QuadraticBezierCurve.prototype.isQuadraticBezierCurve = true; 36696 36697 QuadraticBezierCurve.prototype.getPoint = function ( t, optionalTarget ) { 36698 36699 var point = optionalTarget || new Vector2(); 36700 36701 var v0 = this.v0, v1 = this.v1, v2 = this.v2; 36702 36703 point.set( 36704 QuadraticBezier( t, v0.x, v1.x, v2.x ), 36705 QuadraticBezier( t, v0.y, v1.y, v2.y ) 36706 ); 36707 36708 return point; 36709 36710 }; 36711 36712 QuadraticBezierCurve.prototype.copy = function ( source ) { 36713 36714 Curve.prototype.copy.call( this, source ); 36715 36716 this.v0.copy( source.v0 ); 36717 this.v1.copy( source.v1 ); 36718 this.v2.copy( source.v2 ); 36719 36720 return this; 36721 36722 }; 36723 36724 QuadraticBezierCurve.prototype.toJSON = function () { 36725 36726 var data = Curve.prototype.toJSON.call( this ); 36727 36728 data.v0 = this.v0.toArray(); 36729 data.v1 = this.v1.toArray(); 36730 data.v2 = this.v2.toArray(); 36731 36732 return data; 36733 36734 }; 36735 36736 QuadraticBezierCurve.prototype.fromJSON = function ( json ) { 36737 36738 Curve.prototype.fromJSON.call( this, json ); 36739 36740 this.v0.fromArray( json.v0 ); 36741 this.v1.fromArray( json.v1 ); 36742 this.v2.fromArray( json.v2 ); 36743 36744 return this; 36745 36746 }; 36747 36748 function QuadraticBezierCurve3( v0, v1, v2 ) { 36749 36750 Curve.call( this ); 36751 36752 this.type = 'QuadraticBezierCurve3'; 36753 36754 this.v0 = v0 || new Vector3(); 36755 this.v1 = v1 || new Vector3(); 36756 this.v2 = v2 || new Vector3(); 36757 36758 } 36759 36760 QuadraticBezierCurve3.prototype = Object.create( Curve.prototype ); 36761 QuadraticBezierCurve3.prototype.constructor = QuadraticBezierCurve3; 36762 36763 QuadraticBezierCurve3.prototype.isQuadraticBezierCurve3 = true; 36764 36765 QuadraticBezierCurve3.prototype.getPoint = function ( t, optionalTarget ) { 36766 36767 var point = optionalTarget || new Vector3(); 36768 36769 var v0 = this.v0, v1 = this.v1, v2 = this.v2; 36770 36771 point.set( 36772 QuadraticBezier( t, v0.x, v1.x, v2.x ), 36773 QuadraticBezier( t, v0.y, v1.y, v2.y ), 36774 QuadraticBezier( t, v0.z, v1.z, v2.z ) 36775 ); 36776 36777 return point; 36778 36779 }; 36780 36781 QuadraticBezierCurve3.prototype.copy = function ( source ) { 36782 36783 Curve.prototype.copy.call( this, source ); 36784 36785 this.v0.copy( source.v0 ); 36786 this.v1.copy( source.v1 ); 36787 this.v2.copy( source.v2 ); 36788 36789 return this; 36790 36791 }; 36792 36793 QuadraticBezierCurve3.prototype.toJSON = function () { 36794 36795 var data = Curve.prototype.toJSON.call( this ); 36796 36797 data.v0 = this.v0.toArray(); 36798 data.v1 = this.v1.toArray(); 36799 data.v2 = this.v2.toArray(); 36800 36801 return data; 36802 36803 }; 36804 36805 QuadraticBezierCurve3.prototype.fromJSON = function ( json ) { 36806 36807 Curve.prototype.fromJSON.call( this, json ); 36808 36809 this.v0.fromArray( json.v0 ); 36810 this.v1.fromArray( json.v1 ); 36811 this.v2.fromArray( json.v2 ); 36812 36813 return this; 36814 36815 }; 36816 36817 function SplineCurve( points /* array of Vector2 */ ) { 36818 36819 Curve.call( this ); 36820 36821 this.type = 'SplineCurve'; 36822 36823 this.points = points || []; 36824 36825 } 36826 36827 SplineCurve.prototype = Object.create( Curve.prototype ); 36828 SplineCurve.prototype.constructor = SplineCurve; 36829 36830 SplineCurve.prototype.isSplineCurve = true; 36831 36832 SplineCurve.prototype.getPoint = function ( t, optionalTarget ) { 36833 36834 var point = optionalTarget || new Vector2(); 36835 36836 var points = this.points; 36837 var p = ( points.length - 1 ) * t; 36838 36839 var intPoint = Math.floor( p ); 36840 var weight = p - intPoint; 36841 36842 var p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; 36843 var p1 = points[ intPoint ]; 36844 var p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; 36845 var p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ]; 36846 36847 point.set( 36848 CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ), 36849 CatmullRom( weight, p0.y, p1.y, p2.y, p3.y ) 36850 ); 36851 36852 return point; 36853 36854 }; 36855 36856 SplineCurve.prototype.copy = function ( source ) { 36857 36858 Curve.prototype.copy.call( this, source ); 36859 36860 this.points = []; 36861 36862 for ( var i = 0, l = source.points.length; i < l; i ++ ) { 36863 36864 var point = source.points[ i ]; 36865 36866 this.points.push( point.clone() ); 36867 36868 } 36869 36870 return this; 36871 36872 }; 36873 36874 SplineCurve.prototype.toJSON = function () { 36875 36876 var data = Curve.prototype.toJSON.call( this ); 36877 36878 data.points = []; 36879 36880 for ( var i = 0, l = this.points.length; i < l; i ++ ) { 36881 36882 var point = this.points[ i ]; 36883 data.points.push( point.toArray() ); 36884 36885 } 36886 36887 return data; 36888 36889 }; 36890 36891 SplineCurve.prototype.fromJSON = function ( json ) { 36892 36893 Curve.prototype.fromJSON.call( this, json ); 36894 36895 this.points = []; 36896 36897 for ( var i = 0, l = json.points.length; i < l; i ++ ) { 36898 36899 var point = json.points[ i ]; 36900 this.points.push( new Vector2().fromArray( point ) ); 36901 36902 } 36903 36904 return this; 36905 36906 }; 36907 36908 36909 36910 var Curves = /*#__PURE__*/Object.freeze({ 36911 ArcCurve: ArcCurve, 36912 CatmullRomCurve3: CatmullRomCurve3, 36913 CubicBezierCurve: CubicBezierCurve, 36914 CubicBezierCurve3: CubicBezierCurve3, 36915 EllipseCurve: EllipseCurve, 36916 LineCurve: LineCurve, 36917 LineCurve3: LineCurve3, 36918 QuadraticBezierCurve: QuadraticBezierCurve, 36919 QuadraticBezierCurve3: QuadraticBezierCurve3, 36920 SplineCurve: SplineCurve 36921 }); 36922 36923 /** 36924 * @author zz85 / http://www.lab4games.net/zz85/blog 36925 * 36926 **/ 36927 36928 /************************************************************** 36929 * Curved Path - a curve path is simply a array of connected 36930 * curves, but retains the api of a curve 36931 **************************************************************/ 36932 36933 function CurvePath() { 36934 36935 Curve.call( this ); 36936 36937 this.type = 'CurvePath'; 36938 36939 this.curves = []; 36940 this.autoClose = false; // Automatically closes the path 36941 36942 } 36943 36944 CurvePath.prototype = Object.assign( Object.create( Curve.prototype ), { 36945 36946 constructor: CurvePath, 36947 36948 add: function ( curve ) { 36949 36950 this.curves.push( curve ); 36951 36952 }, 36953 36954 closePath: function () { 36955 36956 // Add a line curve if start and end of lines are not connected 36957 var startPoint = this.curves[ 0 ].getPoint( 0 ); 36958 var endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); 36959 36960 if ( ! startPoint.equals( endPoint ) ) { 36961 36962 this.curves.push( new LineCurve( endPoint, startPoint ) ); 36963 36964 } 36965 36966 }, 36967 36968 // To get accurate point with reference to 36969 // entire path distance at time t, 36970 // following has to be done: 36971 36972 // 1. Length of each sub path have to be known 36973 // 2. Locate and identify type of curve 36974 // 3. Get t for the curve 36975 // 4. Return curve.getPointAt(t') 36976 36977 getPoint: function ( t ) { 36978 36979 var d = t * this.getLength(); 36980 var curveLengths = this.getCurveLengths(); 36981 var i = 0; 36982 36983 // To think about boundaries points. 36984 36985 while ( i < curveLengths.length ) { 36986 36987 if ( curveLengths[ i ] >= d ) { 36988 36989 var diff = curveLengths[ i ] - d; 36990 var curve = this.curves[ i ]; 36991 36992 var segmentLength = curve.getLength(); 36993 var u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; 36994 36995 return curve.getPointAt( u ); 36996 36997 } 36998 36999 i ++; 37000 37001 } 37002 37003 return null; 37004 37005 // loop where sum != 0, sum > d , sum+1 <d 37006 37007 }, 37008 37009 // We cannot use the default THREE.Curve getPoint() with getLength() because in 37010 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath 37011 // getPoint() depends on getLength 37012 37013 getLength: function () { 37014 37015 var lens = this.getCurveLengths(); 37016 return lens[ lens.length - 1 ]; 37017 37018 }, 37019 37020 // cacheLengths must be recalculated. 37021 updateArcLengths: function () { 37022 37023 this.needsUpdate = true; 37024 this.cacheLengths = null; 37025 this.getCurveLengths(); 37026 37027 }, 37028 37029 // Compute lengths and cache them 37030 // We cannot overwrite getLengths() because UtoT mapping uses it. 37031 37032 getCurveLengths: function () { 37033 37034 // We use cache values if curves and cache array are same length 37035 37036 if ( this.cacheLengths && this.cacheLengths.length === this.curves.length ) { 37037 37038 return this.cacheLengths; 37039 37040 } 37041 37042 // Get length of sub-curve 37043 // Push sums into cached array 37044 37045 var lengths = [], sums = 0; 37046 37047 for ( var i = 0, l = this.curves.length; i < l; i ++ ) { 37048 37049 sums += this.curves[ i ].getLength(); 37050 lengths.push( sums ); 37051 37052 } 37053 37054 this.cacheLengths = lengths; 37055 37056 return lengths; 37057 37058 }, 37059 37060 getSpacedPoints: function ( divisions ) { 37061 37062 if ( divisions === undefined ) divisions = 40; 37063 37064 var points = []; 37065 37066 for ( var i = 0; i <= divisions; i ++ ) { 37067 37068 points.push( this.getPoint( i / divisions ) ); 37069 37070 } 37071 37072 if ( this.autoClose ) { 37073 37074 points.push( points[ 0 ] ); 37075 37076 } 37077 37078 return points; 37079 37080 }, 37081 37082 getPoints: function ( divisions ) { 37083 37084 divisions = divisions || 12; 37085 37086 var points = [], last; 37087 37088 for ( var i = 0, curves = this.curves; i < curves.length; i ++ ) { 37089 37090 var curve = curves[ i ]; 37091 var resolution = ( curve && curve.isEllipseCurve ) ? divisions * 2 37092 : ( curve && curve.isLineCurve ) ? 1 37093 : ( curve && curve.isSplineCurve ) ? divisions * curve.points.length 37094 : divisions; 37095 37096 var pts = curve.getPoints( resolution ); 37097 37098 for ( var j = 0; j < pts.length; j ++ ) { 37099 37100 var point = pts[ j ]; 37101 37102 if ( last && last.equals( point ) ) continue; // ensures no consecutive points are duplicates 37103 37104 points.push( point ); 37105 last = point; 37106 37107 } 37108 37109 } 37110 37111 if ( this.autoClose && points.length > 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { 37112 37113 points.push( points[ 0 ] ); 37114 37115 } 37116 37117 return points; 37118 37119 }, 37120 37121 copy: function ( source ) { 37122 37123 Curve.prototype.copy.call( this, source ); 37124 37125 this.curves = []; 37126 37127 for ( var i = 0, l = source.curves.length; i < l; i ++ ) { 37128 37129 var curve = source.curves[ i ]; 37130 37131 this.curves.push( curve.clone() ); 37132 37133 } 37134 37135 this.autoClose = source.autoClose; 37136 37137 return this; 37138 37139 }, 37140 37141 toJSON: function () { 37142 37143 var data = Curve.prototype.toJSON.call( this ); 37144 37145 data.autoClose = this.autoClose; 37146 data.curves = []; 37147 37148 for ( var i = 0, l = this.curves.length; i < l; i ++ ) { 37149 37150 var curve = this.curves[ i ]; 37151 data.curves.push( curve.toJSON() ); 37152 37153 } 37154 37155 return data; 37156 37157 }, 37158 37159 fromJSON: function ( json ) { 37160 37161 Curve.prototype.fromJSON.call( this, json ); 37162 37163 this.autoClose = json.autoClose; 37164 this.curves = []; 37165 37166 for ( var i = 0, l = json.curves.length; i < l; i ++ ) { 37167 37168 var curve = json.curves[ i ]; 37169 this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) ); 37170 37171 } 37172 37173 return this; 37174 37175 } 37176 37177 } ); 37178 37179 /** 37180 * @author zz85 / http://www.lab4games.net/zz85/blog 37181 * Creates free form 2d path using series of points, lines or curves. 37182 **/ 37183 37184 function Path( points ) { 37185 37186 CurvePath.call( this ); 37187 37188 this.type = 'Path'; 37189 37190 this.currentPoint = new Vector2(); 37191 37192 if ( points ) { 37193 37194 this.setFromPoints( points ); 37195 37196 } 37197 37198 } 37199 37200 Path.prototype = Object.assign( Object.create( CurvePath.prototype ), { 37201 37202 constructor: Path, 37203 37204 setFromPoints: function ( points ) { 37205 37206 this.moveTo( points[ 0 ].x, points[ 0 ].y ); 37207 37208 for ( var i = 1, l = points.length; i < l; i ++ ) { 37209 37210 this.lineTo( points[ i ].x, points[ i ].y ); 37211 37212 } 37213 37214 }, 37215 37216 moveTo: function ( x, y ) { 37217 37218 this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? 37219 37220 }, 37221 37222 lineTo: function ( x, y ) { 37223 37224 var curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); 37225 this.curves.push( curve ); 37226 37227 this.currentPoint.set( x, y ); 37228 37229 }, 37230 37231 quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { 37232 37233 var curve = new QuadraticBezierCurve( 37234 this.currentPoint.clone(), 37235 new Vector2( aCPx, aCPy ), 37236 new Vector2( aX, aY ) 37237 ); 37238 37239 this.curves.push( curve ); 37240 37241 this.currentPoint.set( aX, aY ); 37242 37243 }, 37244 37245 bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 37246 37247 var curve = new CubicBezierCurve( 37248 this.currentPoint.clone(), 37249 new Vector2( aCP1x, aCP1y ), 37250 new Vector2( aCP2x, aCP2y ), 37251 new Vector2( aX, aY ) 37252 ); 37253 37254 this.curves.push( curve ); 37255 37256 this.currentPoint.set( aX, aY ); 37257 37258 }, 37259 37260 splineThru: function ( pts /*Array of Vector*/ ) { 37261 37262 var npts = [ this.currentPoint.clone() ].concat( pts ); 37263 37264 var curve = new SplineCurve( npts ); 37265 this.curves.push( curve ); 37266 37267 this.currentPoint.copy( pts[ pts.length - 1 ] ); 37268 37269 }, 37270 37271 arc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 37272 37273 var x0 = this.currentPoint.x; 37274 var y0 = this.currentPoint.y; 37275 37276 this.absarc( aX + x0, aY + y0, aRadius, 37277 aStartAngle, aEndAngle, aClockwise ); 37278 37279 }, 37280 37281 absarc: function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { 37282 37283 this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); 37284 37285 }, 37286 37287 ellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 37288 37289 var x0 = this.currentPoint.x; 37290 var y0 = this.currentPoint.y; 37291 37292 this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 37293 37294 }, 37295 37296 absellipse: function ( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { 37297 37298 var curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); 37299 37300 if ( this.curves.length > 0 ) { 37301 37302 // if a previous curve is present, attempt to join 37303 var firstPoint = curve.getPoint( 0 ); 37304 37305 if ( ! firstPoint.equals( this.currentPoint ) ) { 37306 37307 this.lineTo( firstPoint.x, firstPoint.y ); 37308 37309 } 37310 37311 } 37312 37313 this.curves.push( curve ); 37314 37315 var lastPoint = curve.getPoint( 1 ); 37316 this.currentPoint.copy( lastPoint ); 37317 37318 }, 37319 37320 copy: function ( source ) { 37321 37322 CurvePath.prototype.copy.call( this, source ); 37323 37324 this.currentPoint.copy( source.currentPoint ); 37325 37326 return this; 37327 37328 }, 37329 37330 toJSON: function () { 37331 37332 var data = CurvePath.prototype.toJSON.call( this ); 37333 37334 data.currentPoint = this.currentPoint.toArray(); 37335 37336 return data; 37337 37338 }, 37339 37340 fromJSON: function ( json ) { 37341 37342 CurvePath.prototype.fromJSON.call( this, json ); 37343 37344 this.currentPoint.fromArray( json.currentPoint ); 37345 37346 return this; 37347 37348 } 37349 37350 } ); 37351 37352 /** 37353 * @author zz85 / http://www.lab4games.net/zz85/blog 37354 * Defines a 2d shape plane using paths. 37355 **/ 37356 37357 // STEP 1 Create a path. 37358 // STEP 2 Turn path into shape. 37359 // STEP 3 ExtrudeGeometry takes in Shape/Shapes 37360 // STEP 3a - Extract points from each shape, turn to vertices 37361 // STEP 3b - Triangulate each shape, add faces. 37362 37363 function Shape( points ) { 37364 37365 Path.call( this, points ); 37366 37367 this.uuid = _Math.generateUUID(); 37368 37369 this.type = 'Shape'; 37370 37371 this.holes = []; 37372 37373 } 37374 37375 Shape.prototype = Object.assign( Object.create( Path.prototype ), { 37376 37377 constructor: Shape, 37378 37379 getPointsHoles: function ( divisions ) { 37380 37381 var holesPts = []; 37382 37383 for ( var i = 0, l = this.holes.length; i < l; i ++ ) { 37384 37385 holesPts[ i ] = this.holes[ i ].getPoints( divisions ); 37386 37387 } 37388 37389 return holesPts; 37390 37391 }, 37392 37393 // get points of shape and holes (keypoints based on segments parameter) 37394 37395 extractPoints: function ( divisions ) { 37396 37397 return { 37398 37399 shape: this.getPoints( divisions ), 37400 holes: this.getPointsHoles( divisions ) 37401 37402 }; 37403 37404 }, 37405 37406 copy: function ( source ) { 37407 37408 Path.prototype.copy.call( this, source ); 37409 37410 this.holes = []; 37411 37412 for ( var i = 0, l = source.holes.length; i < l; i ++ ) { 37413 37414 var hole = source.holes[ i ]; 37415 37416 this.holes.push( hole.clone() ); 37417 37418 } 37419 37420 return this; 37421 37422 }, 37423 37424 toJSON: function () { 37425 37426 var data = Path.prototype.toJSON.call( this ); 37427 37428 data.uuid = this.uuid; 37429 data.holes = []; 37430 37431 for ( var i = 0, l = this.holes.length; i < l; i ++ ) { 37432 37433 var hole = this.holes[ i ]; 37434 data.holes.push( hole.toJSON() ); 37435 37436 } 37437 37438 return data; 37439 37440 }, 37441 37442 fromJSON: function ( json ) { 37443 37444 Path.prototype.fromJSON.call( this, json ); 37445 37446 this.uuid = json.uuid; 37447 this.holes = []; 37448 37449 for ( var i = 0, l = json.holes.length; i < l; i ++ ) { 37450 37451 var hole = json.holes[ i ]; 37452 this.holes.push( new Path().fromJSON( hole ) ); 37453 37454 } 37455 37456 return this; 37457 37458 } 37459 37460 } ); 37461 37462 /** 37463 * @author mrdoob / http://mrdoob.com/ 37464 * @author alteredq / http://alteredqualia.com/ 37465 */ 37466 37467 function Light( color, intensity ) { 37468 37469 Object3D.call( this ); 37470 37471 this.type = 'Light'; 37472 37473 this.color = new Color( color ); 37474 this.intensity = intensity !== undefined ? intensity : 1; 37475 37476 this.receiveShadow = undefined; 37477 37478 } 37479 37480 Light.prototype = Object.assign( Object.create( Object3D.prototype ), { 37481 37482 constructor: Light, 37483 37484 isLight: true, 37485 37486 copy: function ( source ) { 37487 37488 Object3D.prototype.copy.call( this, source ); 37489 37490 this.color.copy( source.color ); 37491 this.intensity = source.intensity; 37492 37493 return this; 37494 37495 }, 37496 37497 toJSON: function ( meta ) { 37498 37499 var data = Object3D.prototype.toJSON.call( this, meta ); 37500 37501 data.object.color = this.color.getHex(); 37502 data.object.intensity = this.intensity; 37503 37504 if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); 37505 37506 if ( this.distance !== undefined ) data.object.distance = this.distance; 37507 if ( this.angle !== undefined ) data.object.angle = this.angle; 37508 if ( this.decay !== undefined ) data.object.decay = this.decay; 37509 if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; 37510 37511 if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); 37512 37513 return data; 37514 37515 } 37516 37517 } ); 37518 37519 /** 37520 * @author alteredq / http://alteredqualia.com/ 37521 */ 37522 37523 function HemisphereLight( skyColor, groundColor, intensity ) { 37524 37525 Light.call( this, skyColor, intensity ); 37526 37527 this.type = 'HemisphereLight'; 37528 37529 this.castShadow = undefined; 37530 37531 this.position.copy( Object3D.DefaultUp ); 37532 this.updateMatrix(); 37533 37534 this.groundColor = new Color( groundColor ); 37535 37536 } 37537 37538 HemisphereLight.prototype = Object.assign( Object.create( Light.prototype ), { 37539 37540 constructor: HemisphereLight, 37541 37542 isHemisphereLight: true, 37543 37544 copy: function ( source ) { 37545 37546 Light.prototype.copy.call( this, source ); 37547 37548 this.groundColor.copy( source.groundColor ); 37549 37550 return this; 37551 37552 } 37553 37554 } ); 37555 37556 /** 37557 * @author mrdoob / http://mrdoob.com/ 37558 */ 37559 37560 function LightShadow( camera ) { 37561 37562 this.camera = camera; 37563 37564 this.bias = 0; 37565 this.radius = 1; 37566 37567 this.mapSize = new Vector2( 512, 512 ); 37568 37569 this.map = null; 37570 this.matrix = new Matrix4(); 37571 37572 } 37573 37574 Object.assign( LightShadow.prototype, { 37575 37576 copy: function ( source ) { 37577 37578 this.camera = source.camera.clone(); 37579 37580 this.bias = source.bias; 37581 this.radius = source.radius; 37582 37583 this.mapSize.copy( source.mapSize ); 37584 37585 return this; 37586 37587 }, 37588 37589 clone: function () { 37590 37591 return new this.constructor().copy( this ); 37592 37593 }, 37594 37595 toJSON: function () { 37596 37597 var object = {}; 37598 37599 if ( this.bias !== 0 ) object.bias = this.bias; 37600 if ( this.radius !== 1 ) object.radius = this.radius; 37601 if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); 37602 37603 object.camera = this.camera.toJSON( false ).object; 37604 delete object.camera.matrix; 37605 37606 return object; 37607 37608 } 37609 37610 } ); 37611 37612 /** 37613 * @author mrdoob / http://mrdoob.com/ 37614 */ 37615 37616 function SpotLightShadow() { 37617 37618 LightShadow.call( this, new PerspectiveCamera( 50, 1, 0.5, 500 ) ); 37619 37620 } 37621 37622 SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { 37623 37624 constructor: SpotLightShadow, 37625 37626 isSpotLightShadow: true, 37627 37628 update: function ( light ) { 37629 37630 var camera = this.camera; 37631 37632 var fov = _Math.RAD2DEG * 2 * light.angle; 37633 var aspect = this.mapSize.width / this.mapSize.height; 37634 var far = light.distance || camera.far; 37635 37636 if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { 37637 37638 camera.fov = fov; 37639 camera.aspect = aspect; 37640 camera.far = far; 37641 camera.updateProjectionMatrix(); 37642 37643 } 37644 37645 } 37646 37647 } ); 37648 37649 /** 37650 * @author alteredq / http://alteredqualia.com/ 37651 */ 37652 37653 function SpotLight( color, intensity, distance, angle, penumbra, decay ) { 37654 37655 Light.call( this, color, intensity ); 37656 37657 this.type = 'SpotLight'; 37658 37659 this.position.copy( Object3D.DefaultUp ); 37660 this.updateMatrix(); 37661 37662 this.target = new Object3D(); 37663 37664 Object.defineProperty( this, 'power', { 37665 get: function () { 37666 37667 // intensity = power per solid angle. 37668 // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf 37669 return this.intensity * Math.PI; 37670 37671 }, 37672 set: function ( power ) { 37673 37674 // intensity = power per solid angle. 37675 // ref: equation (17) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf 37676 this.intensity = power / Math.PI; 37677 37678 } 37679 } ); 37680 37681 this.distance = ( distance !== undefined ) ? distance : 0; 37682 this.angle = ( angle !== undefined ) ? angle : Math.PI / 3; 37683 this.penumbra = ( penumbra !== undefined ) ? penumbra : 0; 37684 this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. 37685 37686 this.shadow = new SpotLightShadow(); 37687 37688 } 37689 37690 SpotLight.prototype = Object.assign( Object.create( Light.prototype ), { 37691 37692 constructor: SpotLight, 37693 37694 isSpotLight: true, 37695 37696 copy: function ( source ) { 37697 37698 Light.prototype.copy.call( this, source ); 37699 37700 this.distance = source.distance; 37701 this.angle = source.angle; 37702 this.penumbra = source.penumbra; 37703 this.decay = source.decay; 37704 37705 this.target = source.target.clone(); 37706 37707 this.shadow = source.shadow.clone(); 37708 37709 return this; 37710 37711 } 37712 37713 } ); 37714 37715 /** 37716 * @author mrdoob / http://mrdoob.com/ 37717 */ 37718 37719 37720 function PointLight( color, intensity, distance, decay ) { 37721 37722 Light.call( this, color, intensity ); 37723 37724 this.type = 'PointLight'; 37725 37726 Object.defineProperty( this, 'power', { 37727 get: function () { 37728 37729 // intensity = power per solid angle. 37730 // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf 37731 return this.intensity * 4 * Math.PI; 37732 37733 }, 37734 set: function ( power ) { 37735 37736 // intensity = power per solid angle. 37737 // ref: equation (15) from https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf 37738 this.intensity = power / ( 4 * Math.PI ); 37739 37740 } 37741 } ); 37742 37743 this.distance = ( distance !== undefined ) ? distance : 0; 37744 this.decay = ( decay !== undefined ) ? decay : 1; // for physically correct lights, should be 2. 37745 37746 this.shadow = new LightShadow( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); 37747 37748 } 37749 37750 PointLight.prototype = Object.assign( Object.create( Light.prototype ), { 37751 37752 constructor: PointLight, 37753 37754 isPointLight: true, 37755 37756 copy: function ( source ) { 37757 37758 Light.prototype.copy.call( this, source ); 37759 37760 this.distance = source.distance; 37761 this.decay = source.decay; 37762 37763 this.shadow = source.shadow.clone(); 37764 37765 return this; 37766 37767 } 37768 37769 } ); 37770 37771 /** 37772 * @author mrdoob / http://mrdoob.com/ 37773 */ 37774 37775 function DirectionalLightShadow( ) { 37776 37777 LightShadow.call( this, new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); 37778 37779 } 37780 37781 DirectionalLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype ), { 37782 37783 constructor: DirectionalLightShadow 37784 37785 } ); 37786 37787 /** 37788 * @author mrdoob / http://mrdoob.com/ 37789 * @author alteredq / http://alteredqualia.com/ 37790 */ 37791 37792 function DirectionalLight( color, intensity ) { 37793 37794 Light.call( this, color, intensity ); 37795 37796 this.type = 'DirectionalLight'; 37797 37798 this.position.copy( Object3D.DefaultUp ); 37799 this.updateMatrix(); 37800 37801 this.target = new Object3D(); 37802 37803 this.shadow = new DirectionalLightShadow(); 37804 37805 } 37806 37807 DirectionalLight.prototype = Object.assign( Object.create( Light.prototype ), { 37808 37809 constructor: DirectionalLight, 37810 37811 isDirectionalLight: true, 37812 37813 copy: function ( source ) { 37814 37815 Light.prototype.copy.call( this, source ); 37816 37817 this.target = source.target.clone(); 37818 37819 this.shadow = source.shadow.clone(); 37820 37821 return this; 37822 37823 } 37824 37825 } ); 37826 37827 /** 37828 * @author mrdoob / http://mrdoob.com/ 37829 */ 37830 37831 function AmbientLight( color, intensity ) { 37832 37833 Light.call( this, color, intensity ); 37834 37835 this.type = 'AmbientLight'; 37836 37837 this.castShadow = undefined; 37838 37839 } 37840 37841 AmbientLight.prototype = Object.assign( Object.create( Light.prototype ), { 37842 37843 constructor: AmbientLight, 37844 37845 isAmbientLight: true 37846 37847 } ); 37848 37849 /** 37850 * @author abelnation / http://github.com/abelnation 37851 */ 37852 37853 function RectAreaLight( color, intensity, width, height ) { 37854 37855 Light.call( this, color, intensity ); 37856 37857 this.type = 'RectAreaLight'; 37858 37859 this.width = ( width !== undefined ) ? width : 10; 37860 this.height = ( height !== undefined ) ? height : 10; 37861 37862 } 37863 37864 RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), { 37865 37866 constructor: RectAreaLight, 37867 37868 isRectAreaLight: true, 37869 37870 copy: function ( source ) { 37871 37872 Light.prototype.copy.call( this, source ); 37873 37874 this.width = source.width; 37875 this.height = source.height; 37876 37877 return this; 37878 37879 }, 37880 37881 toJSON: function ( meta ) { 37882 37883 var data = Light.prototype.toJSON.call( this, meta ); 37884 37885 data.object.width = this.width; 37886 data.object.height = this.height; 37887 37888 return data; 37889 37890 } 37891 37892 } ); 37893 37894 /** 37895 * 37896 * A Track that interpolates Strings 37897 * 37898 * 37899 * @author Ben Houston / http://clara.io/ 37900 * @author David Sarno / http://lighthaus.us/ 37901 * @author tschw 37902 */ 37903 37904 function StringKeyframeTrack( name, times, values, interpolation ) { 37905 37906 KeyframeTrack.call( this, name, times, values, interpolation ); 37907 37908 } 37909 37910 StringKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { 37911 37912 constructor: StringKeyframeTrack, 37913 37914 ValueTypeName: 'string', 37915 ValueBufferType: Array, 37916 37917 DefaultInterpolation: InterpolateDiscrete, 37918 37919 InterpolantFactoryMethodLinear: undefined, 37920 37921 InterpolantFactoryMethodSmooth: undefined 37922 37923 } ); 37924 37925 /** 37926 * 37927 * A Track of Boolean keyframe values. 37928 * 37929 * 37930 * @author Ben Houston / http://clara.io/ 37931 * @author David Sarno / http://lighthaus.us/ 37932 * @author tschw 37933 */ 37934 37935 function BooleanKeyframeTrack( name, times, values ) { 37936 37937 KeyframeTrack.call( this, name, times, values ); 37938 37939 } 37940 37941 BooleanKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { 37942 37943 constructor: BooleanKeyframeTrack, 37944 37945 ValueTypeName: 'bool', 37946 ValueBufferType: Array, 37947 37948 DefaultInterpolation: InterpolateDiscrete, 37949 37950 InterpolantFactoryMethodLinear: undefined, 37951 InterpolantFactoryMethodSmooth: undefined 37952 37953 // Note: Actually this track could have a optimized / compressed 37954 // representation of a single value and a custom interpolant that 37955 // computes "firstValue ^ isOdd( index )". 37956 37957 } ); 37958 37959 /** 37960 * Abstract base class of interpolants over parametric samples. 37961 * 37962 * The parameter domain is one dimensional, typically the time or a path 37963 * along a curve defined by the data. 37964 * 37965 * The sample values can have any dimensionality and derived classes may 37966 * apply special interpretations to the data. 37967 * 37968 * This class provides the interval seek in a Template Method, deferring 37969 * the actual interpolation to derived classes. 37970 * 37971 * Time complexity is O(1) for linear access crossing at most two points 37972 * and O(log N) for random access, where N is the number of positions. 37973 * 37974 * References: 37975 * 37976 * http://www.oodesign.com/template-method-pattern.html 37977 * 37978 * @author tschw 37979 */ 37980 37981 function Interpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 37982 37983 this.parameterPositions = parameterPositions; 37984 this._cachedIndex = 0; 37985 37986 this.resultBuffer = resultBuffer !== undefined ? 37987 resultBuffer : new sampleValues.constructor( sampleSize ); 37988 this.sampleValues = sampleValues; 37989 this.valueSize = sampleSize; 37990 37991 } 37992 37993 Object.assign( Interpolant.prototype, { 37994 37995 evaluate: function ( t ) { 37996 37997 var pp = this.parameterPositions, 37998 i1 = this._cachedIndex, 37999 38000 t1 = pp[ i1 ], 38001 t0 = pp[ i1 - 1 ]; 38002 38003 validate_interval: { 38004 38005 seek: { 38006 38007 var right; 38008 38009 linear_scan: { 38010 38011 //- See http://jsperf.com/comparison-to-undefined/3 38012 //- slower code: 38013 //- 38014 //- if ( t >= t1 || t1 === undefined ) { 38015 forward_scan: if ( ! ( t < t1 ) ) { 38016 38017 for ( var giveUpAt = i1 + 2; ; ) { 38018 38019 if ( t1 === undefined ) { 38020 38021 if ( t < t0 ) break forward_scan; 38022 38023 // after end 38024 38025 i1 = pp.length; 38026 this._cachedIndex = i1; 38027 return this.afterEnd_( i1 - 1, t, t0 ); 38028 38029 } 38030 38031 if ( i1 === giveUpAt ) break; // this loop 38032 38033 t0 = t1; 38034 t1 = pp[ ++ i1 ]; 38035 38036 if ( t < t1 ) { 38037 38038 // we have arrived at the sought interval 38039 break seek; 38040 38041 } 38042 38043 } 38044 38045 // prepare binary search on the right side of the index 38046 right = pp.length; 38047 break linear_scan; 38048 38049 } 38050 38051 //- slower code: 38052 //- if ( t < t0 || t0 === undefined ) { 38053 if ( ! ( t >= t0 ) ) { 38054 38055 // looping? 38056 38057 var t1global = pp[ 1 ]; 38058 38059 if ( t < t1global ) { 38060 38061 i1 = 2; // + 1, using the scan for the details 38062 t0 = t1global; 38063 38064 } 38065 38066 // linear reverse scan 38067 38068 for ( var giveUpAt = i1 - 2; ; ) { 38069 38070 if ( t0 === undefined ) { 38071 38072 // before start 38073 38074 this._cachedIndex = 0; 38075 return this.beforeStart_( 0, t, t1 ); 38076 38077 } 38078 38079 if ( i1 === giveUpAt ) break; // this loop 38080 38081 t1 = t0; 38082 t0 = pp[ -- i1 - 1 ]; 38083 38084 if ( t >= t0 ) { 38085 38086 // we have arrived at the sought interval 38087 break seek; 38088 38089 } 38090 38091 } 38092 38093 // prepare binary search on the left side of the index 38094 right = i1; 38095 i1 = 0; 38096 break linear_scan; 38097 38098 } 38099 38100 // the interval is valid 38101 38102 break validate_interval; 38103 38104 } // linear scan 38105 38106 // binary search 38107 38108 while ( i1 < right ) { 38109 38110 var mid = ( i1 + right ) >>> 1; 38111 38112 if ( t < pp[ mid ] ) { 38113 38114 right = mid; 38115 38116 } else { 38117 38118 i1 = mid + 1; 38119 38120 } 38121 38122 } 38123 38124 t1 = pp[ i1 ]; 38125 t0 = pp[ i1 - 1 ]; 38126 38127 // check boundary cases, again 38128 38129 if ( t0 === undefined ) { 38130 38131 this._cachedIndex = 0; 38132 return this.beforeStart_( 0, t, t1 ); 38133 38134 } 38135 38136 if ( t1 === undefined ) { 38137 38138 i1 = pp.length; 38139 this._cachedIndex = i1; 38140 return this.afterEnd_( i1 - 1, t0, t ); 38141 38142 } 38143 38144 } // seek 38145 38146 this._cachedIndex = i1; 38147 38148 this.intervalChanged_( i1, t0, t1 ); 38149 38150 } // validate_interval 38151 38152 return this.interpolate_( i1, t0, t, t1 ); 38153 38154 }, 38155 38156 settings: null, // optional, subclass-specific settings structure 38157 // Note: The indirection allows central control of many interpolants. 38158 38159 // --- Protected interface 38160 38161 DefaultSettings_: {}, 38162 38163 getSettings_: function () { 38164 38165 return this.settings || this.DefaultSettings_; 38166 38167 }, 38168 38169 copySampleValue_: function ( index ) { 38170 38171 // copies a sample value to the result buffer 38172 38173 var result = this.resultBuffer, 38174 values = this.sampleValues, 38175 stride = this.valueSize, 38176 offset = index * stride; 38177 38178 for ( var i = 0; i !== stride; ++ i ) { 38179 38180 result[ i ] = values[ offset + i ]; 38181 38182 } 38183 38184 return result; 38185 38186 }, 38187 38188 // Template methods for derived classes: 38189 38190 interpolate_: function ( /* i1, t0, t, t1 */ ) { 38191 38192 throw new Error( 'call to abstract method' ); 38193 // implementations shall return this.resultBuffer 38194 38195 }, 38196 38197 intervalChanged_: function ( /* i1, t0, t1 */ ) { 38198 38199 // empty 38200 38201 } 38202 38203 } ); 38204 38205 //!\ DECLARE ALIAS AFTER assign prototype ! 38206 Object.assign( Interpolant.prototype, { 38207 38208 //( 0, t, t0 ), returns this.resultBuffer 38209 beforeStart_: Interpolant.prototype.copySampleValue_, 38210 38211 //( N-1, tN-1, t ), returns this.resultBuffer 38212 afterEnd_: Interpolant.prototype.copySampleValue_, 38213 38214 } ); 38215 38216 /** 38217 * Spherical linear unit quaternion interpolant. 38218 * 38219 * @author tschw 38220 */ 38221 38222 function QuaternionLinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 38223 38224 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); 38225 38226 } 38227 38228 QuaternionLinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { 38229 38230 constructor: QuaternionLinearInterpolant, 38231 38232 interpolate_: function ( i1, t0, t, t1 ) { 38233 38234 var result = this.resultBuffer, 38235 values = this.sampleValues, 38236 stride = this.valueSize, 38237 38238 offset = i1 * stride, 38239 38240 alpha = ( t - t0 ) / ( t1 - t0 ); 38241 38242 for ( var end = offset + stride; offset !== end; offset += 4 ) { 38243 38244 Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); 38245 38246 } 38247 38248 return result; 38249 38250 } 38251 38252 } ); 38253 38254 /** 38255 * 38256 * A Track of quaternion keyframe values. 38257 * 38258 * @author Ben Houston / http://clara.io/ 38259 * @author David Sarno / http://lighthaus.us/ 38260 * @author tschw 38261 */ 38262 38263 function QuaternionKeyframeTrack( name, times, values, interpolation ) { 38264 38265 KeyframeTrack.call( this, name, times, values, interpolation ); 38266 38267 } 38268 38269 QuaternionKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { 38270 38271 constructor: QuaternionKeyframeTrack, 38272 38273 ValueTypeName: 'quaternion', 38274 38275 // ValueBufferType is inherited 38276 38277 DefaultInterpolation: InterpolateLinear, 38278 38279 InterpolantFactoryMethodLinear: function ( result ) { 38280 38281 return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); 38282 38283 }, 38284 38285 InterpolantFactoryMethodSmooth: undefined // not yet implemented 38286 38287 } ); 38288 38289 /** 38290 * 38291 * A Track of keyframe values that represent color. 38292 * 38293 * 38294 * @author Ben Houston / http://clara.io/ 38295 * @author David Sarno / http://lighthaus.us/ 38296 * @author tschw 38297 */ 38298 38299 function ColorKeyframeTrack( name, times, values, interpolation ) { 38300 38301 KeyframeTrack.call( this, name, times, values, interpolation ); 38302 38303 } 38304 38305 ColorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { 38306 38307 constructor: ColorKeyframeTrack, 38308 38309 ValueTypeName: 'color' 38310 38311 // ValueBufferType is inherited 38312 38313 // DefaultInterpolation is inherited 38314 38315 // Note: Very basic implementation and nothing special yet. 38316 // However, this is the place for color space parameterization. 38317 38318 } ); 38319 38320 /** 38321 * 38322 * A Track of numeric keyframe values. 38323 * 38324 * @author Ben Houston / http://clara.io/ 38325 * @author David Sarno / http://lighthaus.us/ 38326 * @author tschw 38327 */ 38328 38329 function NumberKeyframeTrack( name, times, values, interpolation ) { 38330 38331 KeyframeTrack.call( this, name, times, values, interpolation ); 38332 38333 } 38334 38335 NumberKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { 38336 38337 constructor: NumberKeyframeTrack, 38338 38339 ValueTypeName: 'number' 38340 38341 // ValueBufferType is inherited 38342 38343 // DefaultInterpolation is inherited 38344 38345 } ); 38346 38347 /** 38348 * Fast and simple cubic spline interpolant. 38349 * 38350 * It was derived from a Hermitian construction setting the first derivative 38351 * at each sample position to the linear slope between neighboring positions 38352 * over their parameter interval. 38353 * 38354 * @author tschw 38355 */ 38356 38357 function CubicInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 38358 38359 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); 38360 38361 this._weightPrev = - 0; 38362 this._offsetPrev = - 0; 38363 this._weightNext = - 0; 38364 this._offsetNext = - 0; 38365 38366 } 38367 38368 CubicInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { 38369 38370 constructor: CubicInterpolant, 38371 38372 DefaultSettings_: { 38373 38374 endingStart: ZeroCurvatureEnding, 38375 endingEnd: ZeroCurvatureEnding 38376 38377 }, 38378 38379 intervalChanged_: function ( i1, t0, t1 ) { 38380 38381 var pp = this.parameterPositions, 38382 iPrev = i1 - 2, 38383 iNext = i1 + 1, 38384 38385 tPrev = pp[ iPrev ], 38386 tNext = pp[ iNext ]; 38387 38388 if ( tPrev === undefined ) { 38389 38390 switch ( this.getSettings_().endingStart ) { 38391 38392 case ZeroSlopeEnding: 38393 38394 // f'(t0) = 0 38395 iPrev = i1; 38396 tPrev = 2 * t0 - t1; 38397 38398 break; 38399 38400 case WrapAroundEnding: 38401 38402 // use the other end of the curve 38403 iPrev = pp.length - 2; 38404 tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; 38405 38406 break; 38407 38408 default: // ZeroCurvatureEnding 38409 38410 // f''(t0) = 0 a.k.a. Natural Spline 38411 iPrev = i1; 38412 tPrev = t1; 38413 38414 } 38415 38416 } 38417 38418 if ( tNext === undefined ) { 38419 38420 switch ( this.getSettings_().endingEnd ) { 38421 38422 case ZeroSlopeEnding: 38423 38424 // f'(tN) = 0 38425 iNext = i1; 38426 tNext = 2 * t1 - t0; 38427 38428 break; 38429 38430 case WrapAroundEnding: 38431 38432 // use the other end of the curve 38433 iNext = 1; 38434 tNext = t1 + pp[ 1 ] - pp[ 0 ]; 38435 38436 break; 38437 38438 default: // ZeroCurvatureEnding 38439 38440 // f''(tN) = 0, a.k.a. Natural Spline 38441 iNext = i1 - 1; 38442 tNext = t0; 38443 38444 } 38445 38446 } 38447 38448 var halfDt = ( t1 - t0 ) * 0.5, 38449 stride = this.valueSize; 38450 38451 this._weightPrev = halfDt / ( t0 - tPrev ); 38452 this._weightNext = halfDt / ( tNext - t1 ); 38453 this._offsetPrev = iPrev * stride; 38454 this._offsetNext = iNext * stride; 38455 38456 }, 38457 38458 interpolate_: function ( i1, t0, t, t1 ) { 38459 38460 var result = this.resultBuffer, 38461 values = this.sampleValues, 38462 stride = this.valueSize, 38463 38464 o1 = i1 * stride, o0 = o1 - stride, 38465 oP = this._offsetPrev, oN = this._offsetNext, 38466 wP = this._weightPrev, wN = this._weightNext, 38467 38468 p = ( t - t0 ) / ( t1 - t0 ), 38469 pp = p * p, 38470 ppp = pp * p; 38471 38472 // evaluate polynomials 38473 38474 var sP = - wP * ppp + 2 * wP * pp - wP * p; 38475 var s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; 38476 var s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; 38477 var sN = wN * ppp - wN * pp; 38478 38479 // combine data linearly 38480 38481 for ( var i = 0; i !== stride; ++ i ) { 38482 38483 result[ i ] = 38484 sP * values[ oP + i ] + 38485 s0 * values[ o0 + i ] + 38486 s1 * values[ o1 + i ] + 38487 sN * values[ oN + i ]; 38488 38489 } 38490 38491 return result; 38492 38493 } 38494 38495 } ); 38496 38497 /** 38498 * @author tschw 38499 */ 38500 38501 function LinearInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 38502 38503 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); 38504 38505 } 38506 38507 LinearInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { 38508 38509 constructor: LinearInterpolant, 38510 38511 interpolate_: function ( i1, t0, t, t1 ) { 38512 38513 var result = this.resultBuffer, 38514 values = this.sampleValues, 38515 stride = this.valueSize, 38516 38517 offset1 = i1 * stride, 38518 offset0 = offset1 - stride, 38519 38520 weight1 = ( t - t0 ) / ( t1 - t0 ), 38521 weight0 = 1 - weight1; 38522 38523 for ( var i = 0; i !== stride; ++ i ) { 38524 38525 result[ i ] = 38526 values[ offset0 + i ] * weight0 + 38527 values[ offset1 + i ] * weight1; 38528 38529 } 38530 38531 return result; 38532 38533 } 38534 38535 } ); 38536 38537 /** 38538 * 38539 * Interpolant that evaluates to the sample value at the position preceeding 38540 * the parameter. 38541 * 38542 * @author tschw 38543 */ 38544 38545 function DiscreteInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) { 38546 38547 Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer ); 38548 38549 } 38550 38551 DiscreteInterpolant.prototype = Object.assign( Object.create( Interpolant.prototype ), { 38552 38553 constructor: DiscreteInterpolant, 38554 38555 interpolate_: function ( i1 /*, t0, t, t1 */ ) { 38556 38557 return this.copySampleValue_( i1 - 1 ); 38558 38559 } 38560 38561 } ); 38562 38563 /** 38564 * @author tschw 38565 * @author Ben Houston / http://clara.io/ 38566 * @author David Sarno / http://lighthaus.us/ 38567 */ 38568 38569 var AnimationUtils = { 38570 38571 // same as Array.prototype.slice, but also works on typed arrays 38572 arraySlice: function ( array, from, to ) { 38573 38574 if ( AnimationUtils.isTypedArray( array ) ) { 38575 38576 // in ios9 array.subarray(from, undefined) will return empty array 38577 // but array.subarray(from) or array.subarray(from, len) is correct 38578 return new array.constructor( array.subarray( from, to !== undefined ? to : array.length ) ); 38579 38580 } 38581 38582 return array.slice( from, to ); 38583 38584 }, 38585 38586 // converts an array to a specific type 38587 convertArray: function ( array, type, forceClone ) { 38588 38589 if ( ! array || // let 'undefined' and 'null' pass 38590 ! forceClone && array.constructor === type ) return array; 38591 38592 if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { 38593 38594 return new type( array ); // create typed array 38595 38596 } 38597 38598 return Array.prototype.slice.call( array ); // create Array 38599 38600 }, 38601 38602 isTypedArray: function ( object ) { 38603 38604 return ArrayBuffer.isView( object ) && 38605 ! ( object instanceof DataView ); 38606 38607 }, 38608 38609 // returns an array by which times and values can be sorted 38610 getKeyframeOrder: function ( times ) { 38611 38612 function compareTime( i, j ) { 38613 38614 return times[ i ] - times[ j ]; 38615 38616 } 38617 38618 var n = times.length; 38619 var result = new Array( n ); 38620 for ( var i = 0; i !== n; ++ i ) result[ i ] = i; 38621 38622 result.sort( compareTime ); 38623 38624 return result; 38625 38626 }, 38627 38628 // uses the array previously returned by 'getKeyframeOrder' to sort data 38629 sortedArray: function ( values, stride, order ) { 38630 38631 var nValues = values.length; 38632 var result = new values.constructor( nValues ); 38633 38634 for ( var i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { 38635 38636 var srcOffset = order[ i ] * stride; 38637 38638 for ( var j = 0; j !== stride; ++ j ) { 38639 38640 result[ dstOffset ++ ] = values[ srcOffset + j ]; 38641 38642 } 38643 38644 } 38645 38646 return result; 38647 38648 }, 38649 38650 // function for parsing AOS keyframe formats 38651 flattenJSON: function ( jsonKeys, times, values, valuePropertyName ) { 38652 38653 var i = 1, key = jsonKeys[ 0 ]; 38654 38655 while ( key !== undefined && key[ valuePropertyName ] === undefined ) { 38656 38657 key = jsonKeys[ i ++ ]; 38658 38659 } 38660 38661 if ( key === undefined ) return; // no data 38662 38663 var value = key[ valuePropertyName ]; 38664 if ( value === undefined ) return; // no data 38665 38666 if ( Array.isArray( value ) ) { 38667 38668 do { 38669 38670 value = key[ valuePropertyName ]; 38671 38672 if ( value !== undefined ) { 38673 38674 times.push( key.time ); 38675 values.push.apply( values, value ); // push all elements 38676 38677 } 38678 38679 key = jsonKeys[ i ++ ]; 38680 38681 } while ( key !== undefined ); 38682 38683 } else if ( value.toArray !== undefined ) { 38684 38685 // ...assume THREE.Math-ish 38686 38687 do { 38688 38689 value = key[ valuePropertyName ]; 38690 38691 if ( value !== undefined ) { 38692 38693 times.push( key.time ); 38694 value.toArray( values, values.length ); 38695 38696 } 38697 38698 key = jsonKeys[ i ++ ]; 38699 38700 } while ( key !== undefined ); 38701 38702 } else { 38703 38704 // otherwise push as-is 38705 38706 do { 38707 38708 value = key[ valuePropertyName ]; 38709 38710 if ( value !== undefined ) { 38711 38712 times.push( key.time ); 38713 values.push( value ); 38714 38715 } 38716 38717 key = jsonKeys[ i ++ ]; 38718 38719 } while ( key !== undefined ); 38720 38721 } 38722 38723 } 38724 38725 }; 38726 38727 /** 38728 * 38729 * A timed sequence of keyframes for a specific property. 38730 * 38731 * 38732 * @author Ben Houston / http://clara.io/ 38733 * @author David Sarno / http://lighthaus.us/ 38734 * @author tschw 38735 */ 38736 38737 function KeyframeTrack( name, times, values, interpolation ) { 38738 38739 if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); 38740 if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); 38741 38742 this.name = name; 38743 38744 this.times = AnimationUtils.convertArray( times, this.TimeBufferType ); 38745 this.values = AnimationUtils.convertArray( values, this.ValueBufferType ); 38746 38747 this.setInterpolation( interpolation || this.DefaultInterpolation ); 38748 38749 this.validate(); 38750 this.optimize(); 38751 38752 } 38753 38754 // Static methods: 38755 38756 Object.assign( KeyframeTrack, { 38757 38758 // Serialization (in static context, because of constructor invocation 38759 // and automatic invocation of .toJSON): 38760 38761 parse: function ( json ) { 38762 38763 if ( json.type === undefined ) { 38764 38765 throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); 38766 38767 } 38768 38769 var trackType = KeyframeTrack._getTrackTypeForValueTypeName( json.type ); 38770 38771 if ( json.times === undefined ) { 38772 38773 var times = [], values = []; 38774 38775 AnimationUtils.flattenJSON( json.keys, times, values, 'value' ); 38776 38777 json.times = times; 38778 json.values = values; 38779 38780 } 38781 38782 // derived classes can define a static parse method 38783 if ( trackType.parse !== undefined ) { 38784 38785 return trackType.parse( json ); 38786 38787 } else { 38788 38789 // by default, we assume a constructor compatible with the base 38790 return new trackType( json.name, json.times, json.values, json.interpolation ); 38791 38792 } 38793 38794 }, 38795 38796 toJSON: function ( track ) { 38797 38798 var trackType = track.constructor; 38799 38800 var json; 38801 38802 // derived classes can define a static toJSON method 38803 if ( trackType.toJSON !== undefined ) { 38804 38805 json = trackType.toJSON( track ); 38806 38807 } else { 38808 38809 // by default, we assume the data can be serialized as-is 38810 json = { 38811 38812 'name': track.name, 38813 'times': AnimationUtils.convertArray( track.times, Array ), 38814 'values': AnimationUtils.convertArray( track.values, Array ) 38815 38816 }; 38817 38818 var interpolation = track.getInterpolation(); 38819 38820 if ( interpolation !== track.DefaultInterpolation ) { 38821 38822 json.interpolation = interpolation; 38823 38824 } 38825 38826 } 38827 38828 json.type = track.ValueTypeName; // mandatory 38829 38830 return json; 38831 38832 }, 38833 38834 _getTrackTypeForValueTypeName: function ( typeName ) { 38835 38836 switch ( typeName.toLowerCase() ) { 38837 38838 case 'scalar': 38839 case 'double': 38840 case 'float': 38841 case 'number': 38842 case 'integer': 38843 38844 return NumberKeyframeTrack; 38845 38846 case 'vector': 38847 case 'vector2': 38848 case 'vector3': 38849 case 'vector4': 38850 38851 return VectorKeyframeTrack; 38852 38853 case 'color': 38854 38855 return ColorKeyframeTrack; 38856 38857 case 'quaternion': 38858 38859 return QuaternionKeyframeTrack; 38860 38861 case 'bool': 38862 case 'boolean': 38863 38864 return BooleanKeyframeTrack; 38865 38866 case 'string': 38867 38868 return StringKeyframeTrack; 38869 38870 } 38871 38872 throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); 38873 38874 } 38875 38876 } ); 38877 38878 Object.assign( KeyframeTrack.prototype, { 38879 38880 constructor: KeyframeTrack, 38881 38882 TimeBufferType: Float32Array, 38883 38884 ValueBufferType: Float32Array, 38885 38886 DefaultInterpolation: InterpolateLinear, 38887 38888 InterpolantFactoryMethodDiscrete: function ( result ) { 38889 38890 return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); 38891 38892 }, 38893 38894 InterpolantFactoryMethodLinear: function ( result ) { 38895 38896 return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); 38897 38898 }, 38899 38900 InterpolantFactoryMethodSmooth: function ( result ) { 38901 38902 return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); 38903 38904 }, 38905 38906 setInterpolation: function ( interpolation ) { 38907 38908 var factoryMethod; 38909 38910 switch ( interpolation ) { 38911 38912 case InterpolateDiscrete: 38913 38914 factoryMethod = this.InterpolantFactoryMethodDiscrete; 38915 38916 break; 38917 38918 case InterpolateLinear: 38919 38920 factoryMethod = this.InterpolantFactoryMethodLinear; 38921 38922 break; 38923 38924 case InterpolateSmooth: 38925 38926 factoryMethod = this.InterpolantFactoryMethodSmooth; 38927 38928 break; 38929 38930 } 38931 38932 if ( factoryMethod === undefined ) { 38933 38934 var message = "unsupported interpolation for " + 38935 this.ValueTypeName + " keyframe track named " + this.name; 38936 38937 if ( this.createInterpolant === undefined ) { 38938 38939 // fall back to default, unless the default itself is messed up 38940 if ( interpolation !== this.DefaultInterpolation ) { 38941 38942 this.setInterpolation( this.DefaultInterpolation ); 38943 38944 } else { 38945 38946 throw new Error( message ); // fatal, in this case 38947 38948 } 38949 38950 } 38951 38952 console.warn( 'THREE.KeyframeTrack:', message ); 38953 return; 38954 38955 } 38956 38957 this.createInterpolant = factoryMethod; 38958 38959 }, 38960 38961 getInterpolation: function () { 38962 38963 switch ( this.createInterpolant ) { 38964 38965 case this.InterpolantFactoryMethodDiscrete: 38966 38967 return InterpolateDiscrete; 38968 38969 case this.InterpolantFactoryMethodLinear: 38970 38971 return InterpolateLinear; 38972 38973 case this.InterpolantFactoryMethodSmooth: 38974 38975 return InterpolateSmooth; 38976 38977 } 38978 38979 }, 38980 38981 getValueSize: function () { 38982 38983 return this.values.length / this.times.length; 38984 38985 }, 38986 38987 // move all keyframes either forwards or backwards in time 38988 shift: function ( timeOffset ) { 38989 38990 if ( timeOffset !== 0.0 ) { 38991 38992 var times = this.times; 38993 38994 for ( var i = 0, n = times.length; i !== n; ++ i ) { 38995 38996 times[ i ] += timeOffset; 38997 38998 } 38999 39000 } 39001 39002 return this; 39003 39004 }, 39005 39006 // scale all keyframe times by a factor (useful for frame <-> seconds conversions) 39007 scale: function ( timeScale ) { 39008 39009 if ( timeScale !== 1.0 ) { 39010 39011 var times = this.times; 39012 39013 for ( var i = 0, n = times.length; i !== n; ++ i ) { 39014 39015 times[ i ] *= timeScale; 39016 39017 } 39018 39019 } 39020 39021 return this; 39022 39023 }, 39024 39025 // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. 39026 // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values 39027 trim: function ( startTime, endTime ) { 39028 39029 var times = this.times, 39030 nKeys = times.length, 39031 from = 0, 39032 to = nKeys - 1; 39033 39034 while ( from !== nKeys && times[ from ] < startTime ) { 39035 39036 ++ from; 39037 39038 } 39039 39040 while ( to !== - 1 && times[ to ] > endTime ) { 39041 39042 -- to; 39043 39044 } 39045 39046 ++ to; // inclusive -> exclusive bound 39047 39048 if ( from !== 0 || to !== nKeys ) { 39049 39050 // empty tracks are forbidden, so keep at least one keyframe 39051 if ( from >= to ) to = Math.max( to, 1 ), from = to - 1; 39052 39053 var stride = this.getValueSize(); 39054 this.times = AnimationUtils.arraySlice( times, from, to ); 39055 this.values = AnimationUtils.arraySlice( this.values, from * stride, to * stride ); 39056 39057 } 39058 39059 return this; 39060 39061 }, 39062 39063 // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable 39064 validate: function () { 39065 39066 var valid = true; 39067 39068 var valueSize = this.getValueSize(); 39069 if ( valueSize - Math.floor( valueSize ) !== 0 ) { 39070 39071 console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); 39072 valid = false; 39073 39074 } 39075 39076 var times = this.times, 39077 values = this.values, 39078 39079 nKeys = times.length; 39080 39081 if ( nKeys === 0 ) { 39082 39083 console.error( 'THREE.KeyframeTrack: Track is empty.', this ); 39084 valid = false; 39085 39086 } 39087 39088 var prevTime = null; 39089 39090 for ( var i = 0; i !== nKeys; i ++ ) { 39091 39092 var currTime = times[ i ]; 39093 39094 if ( typeof currTime === 'number' && isNaN( currTime ) ) { 39095 39096 console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); 39097 valid = false; 39098 break; 39099 39100 } 39101 39102 if ( prevTime !== null && prevTime > currTime ) { 39103 39104 console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); 39105 valid = false; 39106 break; 39107 39108 } 39109 39110 prevTime = currTime; 39111 39112 } 39113 39114 if ( values !== undefined ) { 39115 39116 if ( AnimationUtils.isTypedArray( values ) ) { 39117 39118 for ( var i = 0, n = values.length; i !== n; ++ i ) { 39119 39120 var value = values[ i ]; 39121 39122 if ( isNaN( value ) ) { 39123 39124 console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); 39125 valid = false; 39126 break; 39127 39128 } 39129 39130 } 39131 39132 } 39133 39134 } 39135 39136 return valid; 39137 39138 }, 39139 39140 // removes equivalent sequential keys as common in morph target sequences 39141 // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) 39142 optimize: function () { 39143 39144 var times = this.times, 39145 values = this.values, 39146 stride = this.getValueSize(), 39147 39148 smoothInterpolation = this.getInterpolation() === InterpolateSmooth, 39149 39150 writeIndex = 1, 39151 lastIndex = times.length - 1; 39152 39153 for ( var i = 1; i < lastIndex; ++ i ) { 39154 39155 var keep = false; 39156 39157 var time = times[ i ]; 39158 var timeNext = times[ i + 1 ]; 39159 39160 // remove adjacent keyframes scheduled at the same time 39161 39162 if ( time !== timeNext && ( i !== 1 || time !== time[ 0 ] ) ) { 39163 39164 if ( ! smoothInterpolation ) { 39165 39166 // remove unnecessary keyframes same as their neighbors 39167 39168 var offset = i * stride, 39169 offsetP = offset - stride, 39170 offsetN = offset + stride; 39171 39172 for ( var j = 0; j !== stride; ++ j ) { 39173 39174 var value = values[ offset + j ]; 39175 39176 if ( value !== values[ offsetP + j ] || 39177 value !== values[ offsetN + j ] ) { 39178 39179 keep = true; 39180 break; 39181 39182 } 39183 39184 } 39185 39186 } else { 39187 39188 keep = true; 39189 39190 } 39191 39192 } 39193 39194 // in-place compaction 39195 39196 if ( keep ) { 39197 39198 if ( i !== writeIndex ) { 39199 39200 times[ writeIndex ] = times[ i ]; 39201 39202 var readOffset = i * stride, 39203 writeOffset = writeIndex * stride; 39204 39205 for ( var j = 0; j !== stride; ++ j ) { 39206 39207 values[ writeOffset + j ] = values[ readOffset + j ]; 39208 39209 } 39210 39211 } 39212 39213 ++ writeIndex; 39214 39215 } 39216 39217 } 39218 39219 // flush last keyframe (compaction looks ahead) 39220 39221 if ( lastIndex > 0 ) { 39222 39223 times[ writeIndex ] = times[ lastIndex ]; 39224 39225 for ( var readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { 39226 39227 values[ writeOffset + j ] = values[ readOffset + j ]; 39228 39229 } 39230 39231 ++ writeIndex; 39232 39233 } 39234 39235 if ( writeIndex !== times.length ) { 39236 39237 this.times = AnimationUtils.arraySlice( times, 0, writeIndex ); 39238 this.values = AnimationUtils.arraySlice( values, 0, writeIndex * stride ); 39239 39240 } 39241 39242 return this; 39243 39244 } 39245 39246 } ); 39247 39248 /** 39249 * 39250 * A Track of vectored keyframe values. 39251 * 39252 * 39253 * @author Ben Houston / http://clara.io/ 39254 * @author David Sarno / http://lighthaus.us/ 39255 * @author tschw 39256 */ 39257 39258 function VectorKeyframeTrack( name, times, values, interpolation ) { 39259 39260 KeyframeTrack.call( this, name, times, values, interpolation ); 39261 39262 } 39263 39264 VectorKeyframeTrack.prototype = Object.assign( Object.create( KeyframeTrack.prototype ), { 39265 39266 constructor: VectorKeyframeTrack, 39267 39268 ValueTypeName: 'vector' 39269 39270 // ValueBufferType is inherited 39271 39272 // DefaultInterpolation is inherited 39273 39274 } ); 39275 39276 /** 39277 * 39278 * Reusable set of Tracks that represent an animation. 39279 * 39280 * @author Ben Houston / http://clara.io/ 39281 * @author David Sarno / http://lighthaus.us/ 39282 */ 39283 39284 function AnimationClip( name, duration, tracks ) { 39285 39286 this.name = name; 39287 this.tracks = tracks; 39288 this.duration = ( duration !== undefined ) ? duration : - 1; 39289 39290 this.uuid = _Math.generateUUID(); 39291 39292 // this means it should figure out its duration by scanning the tracks 39293 if ( this.duration < 0 ) { 39294 39295 this.resetDuration(); 39296 39297 } 39298 39299 this.optimize(); 39300 39301 } 39302 39303 Object.assign( AnimationClip, { 39304 39305 parse: function ( json ) { 39306 39307 var tracks = [], 39308 jsonTracks = json.tracks, 39309 frameTime = 1.0 / ( json.fps || 1.0 ); 39310 39311 for ( var i = 0, n = jsonTracks.length; i !== n; ++ i ) { 39312 39313 tracks.push( KeyframeTrack.parse( jsonTracks[ i ] ).scale( frameTime ) ); 39314 39315 } 39316 39317 return new AnimationClip( json.name, json.duration, tracks ); 39318 39319 }, 39320 39321 toJSON: function ( clip ) { 39322 39323 var tracks = [], 39324 clipTracks = clip.tracks; 39325 39326 var json = { 39327 39328 'name': clip.name, 39329 'duration': clip.duration, 39330 'tracks': tracks, 39331 'uuid': clip.uuid 39332 39333 }; 39334 39335 for ( var i = 0, n = clipTracks.length; i !== n; ++ i ) { 39336 39337 tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); 39338 39339 } 39340 39341 return json; 39342 39343 }, 39344 39345 CreateFromMorphTargetSequence: function ( name, morphTargetSequence, fps, noLoop ) { 39346 39347 var numMorphTargets = morphTargetSequence.length; 39348 var tracks = []; 39349 39350 for ( var i = 0; i < numMorphTargets; i ++ ) { 39351 39352 var times = []; 39353 var values = []; 39354 39355 times.push( 39356 ( i + numMorphTargets - 1 ) % numMorphTargets, 39357 i, 39358 ( i + 1 ) % numMorphTargets ); 39359 39360 values.push( 0, 1, 0 ); 39361 39362 var order = AnimationUtils.getKeyframeOrder( times ); 39363 times = AnimationUtils.sortedArray( times, 1, order ); 39364 values = AnimationUtils.sortedArray( values, 1, order ); 39365 39366 // if there is a key at the first frame, duplicate it as the 39367 // last frame as well for perfect loop. 39368 if ( ! noLoop && times[ 0 ] === 0 ) { 39369 39370 times.push( numMorphTargets ); 39371 values.push( values[ 0 ] ); 39372 39373 } 39374 39375 tracks.push( 39376 new NumberKeyframeTrack( 39377 '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', 39378 times, values 39379 ).scale( 1.0 / fps ) ); 39380 39381 } 39382 39383 return new AnimationClip( name, - 1, tracks ); 39384 39385 }, 39386 39387 findByName: function ( objectOrClipArray, name ) { 39388 39389 var clipArray = objectOrClipArray; 39390 39391 if ( ! Array.isArray( objectOrClipArray ) ) { 39392 39393 var o = objectOrClipArray; 39394 clipArray = o.geometry && o.geometry.animations || o.animations; 39395 39396 } 39397 39398 for ( var i = 0; i < clipArray.length; i ++ ) { 39399 39400 if ( clipArray[ i ].name === name ) { 39401 39402 return clipArray[ i ]; 39403 39404 } 39405 39406 } 39407 39408 return null; 39409 39410 }, 39411 39412 CreateClipsFromMorphTargetSequences: function ( morphTargets, fps, noLoop ) { 39413 39414 var animationToMorphTargets = {}; 39415 39416 // tested with https://regex101.com/ on trick sequences 39417 // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 39418 var pattern = /^([\w-]*?)([\d]+)$/; 39419 39420 // sort morph target names into animation groups based 39421 // patterns like Walk_001, Walk_002, Run_001, Run_002 39422 for ( var i = 0, il = morphTargets.length; i < il; i ++ ) { 39423 39424 var morphTarget = morphTargets[ i ]; 39425 var parts = morphTarget.name.match( pattern ); 39426 39427 if ( parts && parts.length > 1 ) { 39428 39429 var name = parts[ 1 ]; 39430 39431 var animationMorphTargets = animationToMorphTargets[ name ]; 39432 if ( ! animationMorphTargets ) { 39433 39434 animationToMorphTargets[ name ] = animationMorphTargets = []; 39435 39436 } 39437 39438 animationMorphTargets.push( morphTarget ); 39439 39440 } 39441 39442 } 39443 39444 var clips = []; 39445 39446 for ( var name in animationToMorphTargets ) { 39447 39448 clips.push( AnimationClip.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); 39449 39450 } 39451 39452 return clips; 39453 39454 }, 39455 39456 // parse the animation.hierarchy format 39457 parseAnimation: function ( animation, bones ) { 39458 39459 if ( ! animation ) { 39460 39461 console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); 39462 return null; 39463 39464 } 39465 39466 var addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { 39467 39468 // only return track if there are actually keys. 39469 if ( animationKeys.length !== 0 ) { 39470 39471 var times = []; 39472 var values = []; 39473 39474 AnimationUtils.flattenJSON( animationKeys, times, values, propertyName ); 39475 39476 // empty keys are filtered out, so check again 39477 if ( times.length !== 0 ) { 39478 39479 destTracks.push( new trackType( trackName, times, values ) ); 39480 39481 } 39482 39483 } 39484 39485 }; 39486 39487 var tracks = []; 39488 39489 var clipName = animation.name || 'default'; 39490 // automatic length determination in AnimationClip. 39491 var duration = animation.length || - 1; 39492 var fps = animation.fps || 30; 39493 39494 var hierarchyTracks = animation.hierarchy || []; 39495 39496 for ( var h = 0; h < hierarchyTracks.length; h ++ ) { 39497 39498 var animationKeys = hierarchyTracks[ h ].keys; 39499 39500 // skip empty tracks 39501 if ( ! animationKeys || animationKeys.length === 0 ) continue; 39502 39503 // process morph targets 39504 if ( animationKeys[ 0 ].morphTargets ) { 39505 39506 // figure out all morph targets used in this track 39507 var morphTargetNames = {}; 39508 39509 for ( var k = 0; k < animationKeys.length; k ++ ) { 39510 39511 if ( animationKeys[ k ].morphTargets ) { 39512 39513 for ( var m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { 39514 39515 morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; 39516 39517 } 39518 39519 } 39520 39521 } 39522 39523 // create a track for each morph target with all zero 39524 // morphTargetInfluences except for the keys in which 39525 // the morphTarget is named. 39526 for ( var morphTargetName in morphTargetNames ) { 39527 39528 var times = []; 39529 var values = []; 39530 39531 for ( var m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { 39532 39533 var animationKey = animationKeys[ k ]; 39534 39535 times.push( animationKey.time ); 39536 values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); 39537 39538 } 39539 39540 tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); 39541 39542 } 39543 39544 duration = morphTargetNames.length * ( fps || 1.0 ); 39545 39546 } else { 39547 39548 // ...assume skeletal animation 39549 39550 var boneName = '.bones[' + bones[ h ].name + ']'; 39551 39552 addNonemptyTrack( 39553 VectorKeyframeTrack, boneName + '.position', 39554 animationKeys, 'pos', tracks ); 39555 39556 addNonemptyTrack( 39557 QuaternionKeyframeTrack, boneName + '.quaternion', 39558 animationKeys, 'rot', tracks ); 39559 39560 addNonemptyTrack( 39561 VectorKeyframeTrack, boneName + '.scale', 39562 animationKeys, 'scl', tracks ); 39563 39564 } 39565 39566 } 39567 39568 if ( tracks.length === 0 ) { 39569 39570 return null; 39571 39572 } 39573 39574 var clip = new AnimationClip( clipName, duration, tracks ); 39575 39576 return clip; 39577 39578 } 39579 39580 } ); 39581 39582 Object.assign( AnimationClip.prototype, { 39583 39584 resetDuration: function () { 39585 39586 var tracks = this.tracks, duration = 0; 39587 39588 for ( var i = 0, n = tracks.length; i !== n; ++ i ) { 39589 39590 var track = this.tracks[ i ]; 39591 39592 duration = Math.max( duration, track.times[ track.times.length - 1 ] ); 39593 39594 } 39595 39596 this.duration = duration; 39597 39598 }, 39599 39600 trim: function () { 39601 39602 for ( var i = 0; i < this.tracks.length; i ++ ) { 39603 39604 this.tracks[ i ].trim( 0, this.duration ); 39605 39606 } 39607 39608 return this; 39609 39610 }, 39611 39612 optimize: function () { 39613 39614 for ( var i = 0; i < this.tracks.length; i ++ ) { 39615 39616 this.tracks[ i ].optimize(); 39617 39618 } 39619 39620 return this; 39621 39622 } 39623 39624 } ); 39625 39626 /** 39627 * @author mrdoob / http://mrdoob.com/ 39628 */ 39629 39630 function MaterialLoader( manager ) { 39631 39632 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 39633 this.textures = {}; 39634 39635 } 39636 39637 Object.assign( MaterialLoader.prototype, { 39638 39639 load: function ( url, onLoad, onProgress, onError ) { 39640 39641 var scope = this; 39642 39643 var loader = new FileLoader( scope.manager ); 39644 loader.load( url, function ( text ) { 39645 39646 onLoad( scope.parse( JSON.parse( text ) ) ); 39647 39648 }, onProgress, onError ); 39649 39650 }, 39651 39652 setTextures: function ( value ) { 39653 39654 this.textures = value; 39655 39656 }, 39657 39658 parse: function ( json ) { 39659 39660 var textures = this.textures; 39661 39662 function getTexture( name ) { 39663 39664 if ( textures[ name ] === undefined ) { 39665 39666 console.warn( 'THREE.MaterialLoader: Undefined texture', name ); 39667 39668 } 39669 39670 return textures[ name ]; 39671 39672 } 39673 39674 var material = new Materials[ json.type ](); 39675 39676 if ( json.uuid !== undefined ) material.uuid = json.uuid; 39677 if ( json.name !== undefined ) material.name = json.name; 39678 if ( json.color !== undefined ) material.color.setHex( json.color ); 39679 if ( json.roughness !== undefined ) material.roughness = json.roughness; 39680 if ( json.metalness !== undefined ) material.metalness = json.metalness; 39681 if ( json.emissive !== undefined ) material.emissive.setHex( json.emissive ); 39682 if ( json.specular !== undefined ) material.specular.setHex( json.specular ); 39683 if ( json.shininess !== undefined ) material.shininess = json.shininess; 39684 if ( json.clearCoat !== undefined ) material.clearCoat = json.clearCoat; 39685 if ( json.clearCoatRoughness !== undefined ) material.clearCoatRoughness = json.clearCoatRoughness; 39686 if ( json.uniforms !== undefined ) material.uniforms = json.uniforms; 39687 if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; 39688 if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; 39689 if ( json.vertexColors !== undefined ) material.vertexColors = json.vertexColors; 39690 if ( json.fog !== undefined ) material.fog = json.fog; 39691 if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; 39692 if ( json.blending !== undefined ) material.blending = json.blending; 39693 if ( json.side !== undefined ) material.side = json.side; 39694 if ( json.opacity !== undefined ) material.opacity = json.opacity; 39695 if ( json.transparent !== undefined ) material.transparent = json.transparent; 39696 if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; 39697 if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; 39698 if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; 39699 if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; 39700 if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; 39701 if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; 39702 if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; 39703 if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; 39704 39705 if ( json.rotation !== undefined ) material.rotation = json.rotation; 39706 39707 if ( json.linewidth !== 1 ) material.linewidth = json.linewidth; 39708 if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; 39709 if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; 39710 if ( json.scale !== undefined ) material.scale = json.scale; 39711 39712 if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset; 39713 if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor; 39714 if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits; 39715 39716 if ( json.skinning !== undefined ) material.skinning = json.skinning; 39717 if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets; 39718 if ( json.dithering !== undefined ) material.dithering = json.dithering; 39719 39720 if ( json.visible !== undefined ) material.visible = json.visible; 39721 if ( json.userData !== undefined ) material.userData = json.userData; 39722 39723 // Deprecated 39724 39725 if ( json.shading !== undefined ) material.flatShading = json.shading === 1; // THREE.FlatShading 39726 39727 // for PointsMaterial 39728 39729 if ( json.size !== undefined ) material.size = json.size; 39730 if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; 39731 39732 // maps 39733 39734 if ( json.map !== undefined ) material.map = getTexture( json.map ); 39735 39736 if ( json.alphaMap !== undefined ) { 39737 39738 material.alphaMap = getTexture( json.alphaMap ); 39739 material.transparent = true; 39740 39741 } 39742 39743 if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); 39744 if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; 39745 39746 if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); 39747 if ( json.normalScale !== undefined ) { 39748 39749 var normalScale = json.normalScale; 39750 39751 if ( Array.isArray( normalScale ) === false ) { 39752 39753 // Blender exporter used to export a scalar. See #7459 39754 39755 normalScale = [ normalScale, normalScale ]; 39756 39757 } 39758 39759 material.normalScale = new Vector2().fromArray( normalScale ); 39760 39761 } 39762 39763 if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); 39764 if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; 39765 if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; 39766 39767 if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); 39768 if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); 39769 39770 if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); 39771 if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; 39772 39773 if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); 39774 39775 if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); 39776 39777 if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; 39778 39779 if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); 39780 if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; 39781 39782 if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); 39783 if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; 39784 39785 if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); 39786 39787 return material; 39788 39789 } 39790 39791 } ); 39792 39793 /** 39794 * @author mrdoob / http://mrdoob.com/ 39795 */ 39796 39797 function BufferGeometryLoader( manager ) { 39798 39799 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 39800 39801 } 39802 39803 Object.assign( BufferGeometryLoader.prototype, { 39804 39805 load: function ( url, onLoad, onProgress, onError ) { 39806 39807 var scope = this; 39808 39809 var loader = new FileLoader( scope.manager ); 39810 loader.load( url, function ( text ) { 39811 39812 onLoad( scope.parse( JSON.parse( text ) ) ); 39813 39814 }, onProgress, onError ); 39815 39816 }, 39817 39818 parse: function ( json ) { 39819 39820 var geometry = new BufferGeometry(); 39821 39822 var index = json.data.index; 39823 39824 if ( index !== undefined ) { 39825 39826 var typedArray = new TYPED_ARRAYS[ index.type ]( index.array ); 39827 geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); 39828 39829 } 39830 39831 var attributes = json.data.attributes; 39832 39833 for ( var key in attributes ) { 39834 39835 var attribute = attributes[ key ]; 39836 var typedArray = new TYPED_ARRAYS[ attribute.type ]( attribute.array ); 39837 39838 geometry.addAttribute( key, new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ) ); 39839 39840 } 39841 39842 var groups = json.data.groups || json.data.drawcalls || json.data.offsets; 39843 39844 if ( groups !== undefined ) { 39845 39846 for ( var i = 0, n = groups.length; i !== n; ++ i ) { 39847 39848 var group = groups[ i ]; 39849 39850 geometry.addGroup( group.start, group.count, group.materialIndex ); 39851 39852 } 39853 39854 } 39855 39856 var boundingSphere = json.data.boundingSphere; 39857 39858 if ( boundingSphere !== undefined ) { 39859 39860 var center = new Vector3(); 39861 39862 if ( boundingSphere.center !== undefined ) { 39863 39864 center.fromArray( boundingSphere.center ); 39865 39866 } 39867 39868 geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); 39869 39870 } 39871 39872 return geometry; 39873 39874 } 39875 39876 } ); 39877 39878 var TYPED_ARRAYS = { 39879 Int8Array: Int8Array, 39880 Uint8Array: Uint8Array, 39881 // Workaround for IE11 pre KB2929437. See #11440 39882 Uint8ClampedArray: typeof Uint8ClampedArray !== 'undefined' ? Uint8ClampedArray : Uint8Array, 39883 Int16Array: Int16Array, 39884 Uint16Array: Uint16Array, 39885 Int32Array: Int32Array, 39886 Uint32Array: Uint32Array, 39887 Float32Array: Float32Array, 39888 Float64Array: Float64Array 39889 }; 39890 39891 /** 39892 * @author alteredq / http://alteredqualia.com/ 39893 */ 39894 39895 function Loader() {} 39896 39897 Loader.Handlers = { 39898 39899 handlers: [], 39900 39901 add: function ( regex, loader ) { 39902 39903 this.handlers.push( regex, loader ); 39904 39905 }, 39906 39907 get: function ( file ) { 39908 39909 var handlers = this.handlers; 39910 39911 for ( var i = 0, l = handlers.length; i < l; i += 2 ) { 39912 39913 var regex = handlers[ i ]; 39914 var loader = handlers[ i + 1 ]; 39915 39916 if ( regex.test( file ) ) { 39917 39918 return loader; 39919 39920 } 39921 39922 } 39923 39924 return null; 39925 39926 } 39927 39928 }; 39929 39930 Object.assign( Loader.prototype, { 39931
vendor: 6,349 bytes, lines 39932-40155
39932 crossOrigin: undefined, 39933 39934 onLoadStart: function () {}, 39935 39936 onLoadProgress: function () {}, 39937 39938 onLoadComplete: function () {}, 39939 39940 initMaterials: function ( materials, texturePath, crossOrigin ) { 39941 39942 var array = []; 39943 39944 for ( var i = 0; i < materials.length; ++ i ) { 39945 39946 array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin ); 39947 39948 } 39949 39950 return array; 39951 39952 }, 39953 39954 createMaterial: ( function () { 39955 39956 var BlendingMode = { 39957 NoBlending: NoBlending, 39958 NormalBlending: NormalBlending, 39959 AdditiveBlending: AdditiveBlending, 39960 SubtractiveBlending: SubtractiveBlending, 39961 MultiplyBlending: MultiplyBlending, 39962 CustomBlending: CustomBlending 39963 }; 39964 39965 var color = new Color(); 39966 var textureLoader = new TextureLoader(); 39967 var materialLoader = new MaterialLoader(); 39968 39969 return function createMaterial( m, texturePath, crossOrigin ) { 39970 39971 // convert from old material format 39972 39973 var textures = {}; 39974 39975 function loadTexture( path, repeat, offset, wrap, anisotropy ) { 39976 39977 var fullPath = texturePath + path; 39978 var loader = Loader.Handlers.get( fullPath ); 39979 39980 var texture; 39981 39982 if ( loader !== null ) { 39983 39984 texture = loader.load( fullPath ); 39985 39986 } else { 39987 39988 textureLoader.setCrossOrigin( crossOrigin ); 39989 texture = textureLoader.load( fullPath ); 39990 39991 } 39992 39993 if ( repeat !== undefined ) { 39994 39995 texture.repeat.fromArray( repeat ); 39996 39997 if ( repeat[ 0 ] !== 1 ) texture.wrapS = RepeatWrapping; 39998 if ( repeat[ 1 ] !== 1 ) texture.wrapT = RepeatWrapping; 39999 40000 } 40001 40002 if ( offset !== undefined ) { 40003 40004 texture.offset.fromArray( offset ); 40005 40006 } 40007 40008 if ( wrap !== undefined ) { 40009 40010 if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = RepeatWrapping; 40011 if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = MirroredRepeatWrapping; 40012 40013 if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = RepeatWrapping; 40014 if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = MirroredRepeatWrapping; 40015 40016 } 40017 40018 if ( anisotropy !== undefined ) { 40019 40020 texture.anisotropy = anisotropy; 40021 40022 } 40023 40024 var uuid = _Math.generateUUID(); 40025 40026 textures[ uuid ] = texture; 40027 40028 return uuid; 40029 40030 } 40031 40032 // 40033 40034 var json = { 40035 uuid: _Math.generateUUID(), 40036 type: 'MeshLambertMaterial' 40037 }; 40038 40039 for ( var name in m ) { 40040 40041 var value = m[ name ]; 40042 40043 switch ( name ) { 40044 40045 case 'DbgColor': 40046 case 'DbgIndex': 40047 case 'opticalDensity': 40048 case 'illumination': 40049 break; 40050 case 'DbgName': 40051 json.name = value; 40052 break; 40053 case 'blending': 40054 json.blending = BlendingMode[ value ]; 40055 break; 40056 case 'colorAmbient': 40057 case 'mapAmbient': 40058 console.warn( 'THREE.Loader.createMaterial:', name, 'is no longer supported.' ); 40059 break; 40060 case 'colorDiffuse': 40061 json.color = color.fromArray( value ).getHex(); 40062 break; 40063 case 'colorSpecular': 40064 json.specular = color.fromArray( value ).getHex(); 40065 break; 40066 case 'colorEmissive': 40067 json.emissive = color.fromArray( value ).getHex(); 40068 break; 40069 case 'specularCoef': 40070 json.shininess = value; 40071 break; 40072 case 'shading': 40073 if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial'; 40074 if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial'; 40075 if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial'; 40076 break; 40077 case 'mapDiffuse': 40078 json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy ); 40079 break; 40080 case 'mapDiffuseRepeat': 40081 case 'mapDiffuseOffset': 40082 case 'mapDiffuseWrap': 40083 case 'mapDiffuseAnisotropy': 40084 break; 40085 case 'mapEmissive': 40086 json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy ); 40087 break; 40088 case 'mapEmissiveRepeat': 40089 case 'mapEmissiveOffset': 40090 case 'mapEmissiveWrap': 40091 case 'mapEmissiveAnisotropy': 40092 break; 40093 case 'mapLight': 40094 json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy ); 40095 break; 40096 case 'mapLightRepeat': 40097 case 'mapLightOffset': 40098 case 'mapLightWrap': 40099 case 'mapLightAnisotropy': 40100 break; 40101 case 'mapAO': 40102 json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy ); 40103 break; 40104 case 'mapAORepeat': 40105 case 'mapAOOffset': 40106 case 'mapAOWrap': 40107 case 'mapAOAnisotropy': 40108 break; 40109 case 'mapBump': 40110 json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy ); 40111 break; 40112 case 'mapBumpScale': 40113 json.bumpScale = value; 40114 break; 40115 case 'mapBumpRepeat': 40116 case 'mapBumpOffset': 40117 case 'mapBumpWrap': 40118 case 'mapBumpAnisotropy': 40119 break; 40120 case 'mapNormal': 40121 json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy ); 40122 break; 40123 case 'mapNormalFactor': 40124 json.normalScale = value; 40125 break; 40126 case 'mapNormalRepeat': 40127 case 'mapNormalOffset': 40128 case 'mapNormalWrap': 40129 case 'mapNormalAnisotropy': 40130 break; 40131 case 'mapSpecular': 40132 json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy ); 40133 break; 40134 case 'mapSpecularRepeat': 40135 case 'mapSpecularOffset': 40136 case 'mapSpecularWrap': 40137 case 'mapSpecularAnisotropy': 40138 break; 40139 case 'mapMetalness': 40140 json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy ); 40141 break; 40142 case 'mapMetalnessRepeat': 40143 case 'mapMetalnessOffset': 40144 case 'mapMetalnessWrap': 40145 case 'mapMetalnessAnisotropy': 40146 break; 40147 case 'mapRoughness': 40148 json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy ); 40149 break; 40150 case 'mapRoughnessRepeat': 40151 case 'mapRoughnessOffset': 40152 case 'mapRoughnessWrap': 40153 case 'mapRoughnessAnisotropy': 40154 break; 40155 case 'mapAlpha':
40156 json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy ); 40157 break; 40158 case 'mapAlphaRepeat': 40159 case 'mapAlphaOffset': 40160 case 'mapAlphaWrap': 40161 case 'mapAlphaAnisotropy': 40162 break; 40163 case 'flipSided': 40164 json.side = BackSide; 40165 break; 40166 case 'doubleSided': 40167 json.side = DoubleSide; 40168 break; 40169 case 'transparency': 40170 console.warn( 'THREE.Loader.createMaterial: transparency has been renamed to opacity' ); 40171 json.opacity = value; 40172 break; 40173 case 'depthTest': 40174 case 'depthWrite': 40175 case 'colorWrite': 40176 case 'opacity': 40177 case 'reflectivity': 40178 case 'transparent': 40179 case 'visible': 40180 case 'wireframe': 40181 json[ name ] = value; 40182 break; 40183 case 'vertexColors': 40184 if ( value === true ) json.vertexColors = VertexColors; 40185 if ( value === 'face' ) json.vertexColors = FaceColors; 40186 break; 40187 default: 40188 console.error( 'THREE.Loader.createMaterial: Unsupported', name, value ); 40189 break; 40190 40191 } 40192 40193 } 40194 40195 if ( json.type === 'MeshBasicMaterial' ) delete json.emissive; 40196 if ( json.type !== 'MeshPhongMaterial' ) delete json.specular; 40197 40198 if ( json.opacity < 1 ) json.transparent = true; 40199 40200 materialLoader.setTextures( textures ); 40201 40202 return materialLoader.parse( json ); 40203 40204 }; 40205 40206 } )() 40207 40208 } ); 40209 40210 /** 40211 * @author Don McCurdy / https://www.donmccurdy.com 40212 */ 40213 40214 var LoaderUtils = { 40215 40216 decodeText: function ( array ) { 40217 40218 if ( typeof TextDecoder !== 'undefined' ) { 40219 40220 return new TextDecoder().decode( array ); 40221 40222 } 40223 40224 // Avoid the String.fromCharCode.apply(null, array) shortcut, which 40225 // throws a "maximum call stack size exceeded" error for large arrays. 40226 40227 var s = ''; 40228 40229 for ( var i = 0, il = array.length; i < il; i ++ ) { 40230 40231 // Implicitly assumes little-endian. 40232 s += String.fromCharCode( array[ i ] ); 40233 40234 } 40235 40236 // Merges multi-byte utf-8 characters. 40237 return decodeURIComponent( escape( s ) ); 40238 40239 }, 40240 40241 extractUrlBase: function ( url ) { 40242 40243 var index = url.lastIndexOf( '/' ); 40244 40245 if ( index === - 1 ) return './'; 40246 40247 return url.substr( 0, index + 1 ); 40248 40249 } 40250 40251 }; 40252 40253 /** 40254 * @author mrdoob / http://mrdoob.com/ 40255 * @author alteredq / http://alteredqualia.com/ 40256 */ 40257 40258 function JSONLoader( manager ) { 40259 40260 if ( typeof manager === 'boolean' ) { 40261 40262 console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' ); 40263 manager = undefined; 40264 40265 } 40266 40267 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 40268 40269 this.withCredentials = false; 40270 40271 } 40272 40273 Object.assign( JSONLoader.prototype, { 40274
vendor: 11,331 bytes, lines 40275-40775
40275 load: function ( url, onLoad, onProgress, onError ) { 40276 40277 var scope = this; 40278 40279 var texturePath = this.texturePath && ( typeof this.texturePath === 'string' ) ? this.texturePath : LoaderUtils.extractUrlBase( url ); 40280 40281 var loader = new FileLoader( this.manager ); 40282 loader.setWithCredentials( this.withCredentials ); 40283 loader.load( url, function ( text ) { 40284 40285 var json = JSON.parse( text ); 40286 var metadata = json.metadata; 40287 40288 if ( metadata !== undefined ) { 40289 40290 var type = metadata.type; 40291 40292 if ( type !== undefined ) { 40293 40294 if ( type.toLowerCase() === 'object' ) { 40295 40296 console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' ); 40297 return; 40298 40299 } 40300 40301 } 40302 40303 } 40304 40305 var object = scope.parse( json, texturePath ); 40306 onLoad( object.geometry, object.materials ); 40307 40308 }, onProgress, onError ); 40309 40310 }, 40311 40312 setTexturePath: function ( value ) { 40313 40314 this.texturePath = value; 40315 40316 }, 40317 40318 parse: ( function () { 40319 40320 function parseModel( json, geometry ) { 40321 40322 function isBitSet( value, position ) { 40323 40324 return value & ( 1 << position ); 40325 40326 } 40327 40328 var i, j, fi, 40329 40330 offset, zLength, 40331 40332 colorIndex, normalIndex, uvIndex, materialIndex, 40333 40334 type, 40335 isQuad, 40336 hasMaterial, 40337 hasFaceVertexUv, 40338 hasFaceNormal, hasFaceVertexNormal, 40339 hasFaceColor, hasFaceVertexColor, 40340 40341 vertex, face, faceA, faceB, hex, normal, 40342 40343 uvLayer, uv, u, v, 40344 40345 faces = json.faces, 40346 vertices = json.vertices, 40347 normals = json.normals, 40348 colors = json.colors, 40349 40350 scale = json.scale, 40351 40352 nUvLayers = 0; 40353 40354 40355 if ( json.uvs !== undefined ) { 40356 40357 // disregard empty arrays 40358 40359 for ( i = 0; i < json.uvs.length; i ++ ) { 40360 40361 if ( json.uvs[ i ].length ) nUvLayers ++; 40362 40363 } 40364 40365 for ( i = 0; i < nUvLayers; i ++ ) { 40366 40367 geometry.faceVertexUvs[ i ] = []; 40368 40369 } 40370 40371 } 40372 40373 offset = 0; 40374 zLength = vertices.length; 40375 40376 while ( offset < zLength ) { 40377 40378 vertex = new Vector3(); 40379 40380 vertex.x = vertices[ offset ++ ] * scale; 40381 vertex.y = vertices[ offset ++ ] * scale; 40382 vertex.z = vertices[ offset ++ ] * scale; 40383 40384 geometry.vertices.push( vertex ); 40385 40386 } 40387 40388 offset = 0; 40389 zLength = faces.length; 40390 40391 while ( offset < zLength ) { 40392 40393 type = faces[ offset ++ ]; 40394 40395 isQuad = isBitSet( type, 0 ); 40396 hasMaterial = isBitSet( type, 1 ); 40397 hasFaceVertexUv = isBitSet( type, 3 ); 40398 hasFaceNormal = isBitSet( type, 4 ); 40399 hasFaceVertexNormal = isBitSet( type, 5 ); 40400 hasFaceColor = isBitSet( type, 6 ); 40401 hasFaceVertexColor = isBitSet( type, 7 ); 40402 40403 // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor); 40404 40405 if ( isQuad ) { 40406 40407 faceA = new Face3(); 40408 faceA.a = faces[ offset ]; 40409 faceA.b = faces[ offset + 1 ]; 40410 faceA.c = faces[ offset + 3 ]; 40411 40412 faceB = new Face3(); 40413 faceB.a = faces[ offset + 1 ]; 40414 faceB.b = faces[ offset + 2 ]; 40415 faceB.c = faces[ offset + 3 ]; 40416 40417 offset += 4; 40418 40419 if ( hasMaterial ) { 40420 40421 materialIndex = faces[ offset ++ ]; 40422 faceA.materialIndex = materialIndex; 40423 faceB.materialIndex = materialIndex; 40424 40425 } 40426 40427 // to get face <=> uv index correspondence 40428 40429 fi = geometry.faces.length; 40430 40431 if ( hasFaceVertexUv ) { 40432 40433 for ( i = 0; i < nUvLayers; i ++ ) { 40434 40435 uvLayer = json.uvs[ i ]; 40436 40437 geometry.faceVertexUvs[ i ][ fi ] = []; 40438 geometry.faceVertexUvs[ i ][ fi + 1 ] = []; 40439 40440 for ( j = 0; j < 4; j ++ ) { 40441 40442 uvIndex = faces[ offset ++ ]; 40443 40444 u = uvLayer[ uvIndex * 2 ]; 40445 v = uvLayer[ uvIndex * 2 + 1 ]; 40446 40447 uv = new Vector2( u, v ); 40448 40449 if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv ); 40450 if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv ); 40451 40452 } 40453 40454 } 40455 40456 } 40457 40458 if ( hasFaceNormal ) { 40459 40460 normalIndex = faces[ offset ++ ] * 3; 40461 40462 faceA.normal.set( 40463 normals[ normalIndex ++ ], 40464 normals[ normalIndex ++ ], 40465 normals[ normalIndex ] 40466 ); 40467 40468 faceB.normal.copy( faceA.normal ); 40469 40470 } 40471 40472 if ( hasFaceVertexNormal ) { 40473 40474 for ( i = 0; i < 4; i ++ ) { 40475 40476 normalIndex = faces[ offset ++ ] * 3; 40477 40478 normal = new Vector3( 40479 normals[ normalIndex ++ ], 40480 normals[ normalIndex ++ ], 40481 normals[ normalIndex ] 40482 ); 40483 40484 40485 if ( i !== 2 ) faceA.vertexNormals.push( normal ); 40486 if ( i !== 0 ) faceB.vertexNormals.push( normal ); 40487 40488 } 40489 40490 } 40491 40492 40493 if ( hasFaceColor ) { 40494 40495 colorIndex = faces[ offset ++ ]; 40496 hex = colors[ colorIndex ]; 40497 40498 faceA.color.setHex( hex ); 40499 faceB.color.setHex( hex ); 40500 40501 } 40502 40503 40504 if ( hasFaceVertexColor ) { 40505 40506 for ( i = 0; i < 4; i ++ ) { 40507 40508 colorIndex = faces[ offset ++ ]; 40509 hex = colors[ colorIndex ]; 40510 40511 if ( i !== 2 ) faceA.vertexColors.push( new Color( hex ) ); 40512 if ( i !== 0 ) faceB.vertexColors.push( new Color( hex ) ); 40513 40514 } 40515 40516 } 40517 40518 geometry.faces.push( faceA ); 40519 geometry.faces.push( faceB ); 40520 40521 } else { 40522 40523 face = new Face3(); 40524 face.a = faces[ offset ++ ]; 40525 face.b = faces[ offset ++ ]; 40526 face.c = faces[ offset ++ ]; 40527 40528 if ( hasMaterial ) { 40529 40530 materialIndex = faces[ offset ++ ]; 40531 face.materialIndex = materialIndex; 40532 40533 } 40534 40535 // to get face <=> uv index correspondence 40536 40537 fi = geometry.faces.length; 40538 40539 if ( hasFaceVertexUv ) { 40540 40541 for ( i = 0; i < nUvLayers; i ++ ) { 40542 40543 uvLayer = json.uvs[ i ]; 40544 40545 geometry.faceVertexUvs[ i ][ fi ] = []; 40546 40547 for ( j = 0; j < 3; j ++ ) { 40548 40549 uvIndex = faces[ offset ++ ]; 40550 40551 u = uvLayer[ uvIndex * 2 ]; 40552 v = uvLayer[ uvIndex * 2 + 1 ]; 40553 40554 uv = new Vector2( u, v ); 40555 40556 geometry.faceVertexUvs[ i ][ fi ].push( uv ); 40557 40558 } 40559 40560 } 40561 40562 } 40563 40564 if ( hasFaceNormal ) { 40565 40566 normalIndex = faces[ offset ++ ] * 3; 40567 40568 face.normal.set( 40569 normals[ normalIndex ++ ], 40570 normals[ normalIndex ++ ], 40571 normals[ normalIndex ] 40572 ); 40573 40574 } 40575 40576 if ( hasFaceVertexNormal ) { 40577 40578 for ( i = 0; i < 3; i ++ ) { 40579 40580 normalIndex = faces[ offset ++ ] * 3; 40581 40582 normal = new Vector3( 40583 normals[ normalIndex ++ ], 40584 normals[ normalIndex ++ ], 40585 normals[ normalIndex ] 40586 ); 40587 40588 face.vertexNormals.push( normal ); 40589 40590 } 40591 40592 } 40593 40594 40595 if ( hasFaceColor ) { 40596 40597 colorIndex = faces[ offset ++ ]; 40598 face.color.setHex( colors[ colorIndex ] ); 40599 40600 } 40601 40602 40603 if ( hasFaceVertexColor ) { 40604 40605 for ( i = 0; i < 3; i ++ ) { 40606 40607 colorIndex = faces[ offset ++ ]; 40608 face.vertexColors.push( new Color( colors[ colorIndex ] ) ); 40609 40610 } 40611 40612 } 40613 40614 geometry.faces.push( face ); 40615 40616 } 40617 40618 } 40619 40620 } 40621 40622 function parseSkin( json, geometry ) { 40623 40624 var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2; 40625 40626 if ( json.skinWeights ) { 40627 40628 for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) { 40629 40630 var x = json.skinWeights[ i ]; 40631 var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0; 40632 var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0; 40633 var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0; 40634 40635 geometry.skinWeights.push( new Vector4( x, y, z, w ) ); 40636 40637 } 40638 40639 } 40640 40641 if ( json.skinIndices ) { 40642 40643 for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) { 40644 40645 var a = json.skinIndices[ i ]; 40646 var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0; 40647 var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0; 40648 var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0; 40649 40650 geometry.skinIndices.push( new Vector4( a, b, c, d ) ); 40651 40652 } 40653 40654 } 40655 40656 geometry.bones = json.bones; 40657 40658 if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) { 40659 40660 console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' + 40661 geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' ); 40662 40663 } 40664 40665 } 40666 40667 function parseMorphing( json, geometry ) { 40668 40669 var scale = json.scale; 40670 40671 if ( json.morphTargets !== undefined ) { 40672 40673 for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) { 40674 40675 geometry.morphTargets[ i ] = {}; 40676 geometry.morphTargets[ i ].name = json.morphTargets[ i ].name; 40677 geometry.morphTargets[ i ].vertices = []; 40678 40679 var dstVertices = geometry.morphTargets[ i ].vertices; 40680 var srcVertices = json.morphTargets[ i ].vertices; 40681 40682 for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) { 40683 40684 var vertex = new Vector3(); 40685 vertex.x = srcVertices[ v ] * scale; 40686 vertex.y = srcVertices[ v + 1 ] * scale; 40687 vertex.z = srcVertices[ v + 2 ] * scale; 40688 40689 dstVertices.push( vertex ); 40690 40691 } 40692 40693 } 40694 40695 } 40696 40697 if ( json.morphColors !== undefined && json.morphColors.length > 0 ) { 40698 40699 console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' ); 40700 40701 var faces = geometry.faces; 40702 var morphColors = json.morphColors[ 0 ].colors; 40703 40704 for ( var i = 0, l = faces.length; i < l; i ++ ) { 40705 40706 faces[ i ].color.fromArray( morphColors, i * 3 ); 40707 40708 } 40709 40710 } 40711 40712 } 40713 40714 function parseAnimations( json, geometry ) { 40715 40716 var outputAnimations = []; 40717 40718 // parse old style Bone/Hierarchy animations 40719 var animations = []; 40720 40721 if ( json.animation !== undefined ) { 40722 40723 animations.push( json.animation ); 40724 40725 } 40726 40727 if ( json.animations !== undefined ) { 40728 40729 if ( json.animations.length ) { 40730 40731 animations = animations.concat( json.animations ); 40732 40733 } else { 40734 40735 animations.push( json.animations ); 40736 40737 } 40738 40739 } 40740 40741 for ( var i = 0; i < animations.length; i ++ ) { 40742 40743 var clip = AnimationClip.parseAnimation( animations[ i ], geometry.bones ); 40744 if ( clip ) outputAnimations.push( clip ); 40745 40746 } 40747 40748 // parse implicit morph animations 40749 if ( geometry.morphTargets ) { 40750 40751 // TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary. 40752 var morphAnimationClips = AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 ); 40753 outputAnimations = outputAnimations.concat( morphAnimationClips ); 40754 40755 } 40756 40757 if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations; 40758 40759 } 40760 40761 return function parse( json, texturePath ) { 40762 40763 if ( json.data !== undefined ) { 40764 40765 // Geometry 4.0 spec 40766 json = json.data; 40767 40768 } 40769 40770 if ( json.scale !== undefined ) { 40771 40772 json.scale = 1.0 / json.scale; 40773 40774 } else { 40775
vendor: 20,413 bytes, lines 40776-41701
40776 json.scale = 1.0; 40777 40778 } 40779 40780 var geometry = new Geometry(); 40781 40782 parseModel( json, geometry ); 40783 parseSkin( json, geometry ); 40784 parseMorphing( json, geometry ); 40785 parseAnimations( json, geometry ); 40786 40787 geometry.computeFaceNormals(); 40788 geometry.computeBoundingSphere(); 40789 40790 if ( json.materials === undefined || json.materials.length === 0 ) { 40791 40792 return { geometry: geometry }; 40793 40794 } else { 40795 40796 var materials = Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin ); 40797 40798 return { geometry: geometry, materials: materials }; 40799 40800 } 40801 40802 }; 40803 40804 } )() 40805 40806 } ); 40807 40808 /** 40809 * @author mrdoob / http://mrdoob.com/ 40810 */ 40811 40812 function ObjectLoader( manager ) { 40813 40814 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 40815 this.texturePath = ''; 40816 40817 } 40818 40819 Object.assign( ObjectLoader.prototype, { 40820 40821 load: function ( url, onLoad, onProgress, onError ) { 40822 40823 if ( this.texturePath === '' ) { 40824 40825 this.texturePath = url.substring( 0, url.lastIndexOf( '/' ) + 1 ); 40826 40827 } 40828 40829 var scope = this; 40830 40831 var loader = new FileLoader( scope.manager ); 40832 loader.load( url, function ( text ) { 40833 40834 var json = null; 40835 40836 try { 40837 40838 json = JSON.parse( text ); 40839 40840 } catch ( error ) { 40841 40842 if ( onError !== undefined ) onError( error ); 40843 40844 console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); 40845 40846 return; 40847 40848 } 40849 40850 var metadata = json.metadata; 40851 40852 if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { 40853 40854 console.error( 'THREE.ObjectLoader: Can\'t load ' + url + '. Use THREE.JSONLoader instead.' ); 40855 return; 40856 40857 } 40858 40859 scope.parse( json, onLoad ); 40860 40861 }, onProgress, onError ); 40862 40863 }, 40864 40865 setTexturePath: function ( value ) { 40866 40867 this.texturePath = value; 40868 return this; 40869 40870 }, 40871 40872 setCrossOrigin: function ( value ) { 40873 40874 this.crossOrigin = value; 40875 return this; 40876 40877 }, 40878 40879 parse: function ( json, onLoad ) { 40880 40881 var shapes = this.parseShape( json.shapes ); 40882 var geometries = this.parseGeometries( json.geometries, shapes ); 40883 40884 var images = this.parseImages( json.images, function () { 40885 40886 if ( onLoad !== undefined ) onLoad( object ); 40887 40888 } ); 40889 40890 var textures = this.parseTextures( json.textures, images ); 40891 var materials = this.parseMaterials( json.materials, textures ); 40892 40893 var object = this.parseObject( json.object, geometries, materials ); 40894 40895 if ( json.animations ) { 40896 40897 object.animations = this.parseAnimations( json.animations ); 40898 40899 } 40900 40901 if ( json.images === undefined || json.images.length === 0 ) { 40902 40903 if ( onLoad !== undefined ) onLoad( object ); 40904 40905 } 40906 40907 return object; 40908 40909 }, 40910 40911 parseShape: function ( json ) { 40912 40913 var shapes = {}; 40914 40915 if ( json !== undefined ) { 40916 40917 for ( var i = 0, l = json.length; i < l; i ++ ) { 40918 40919 var shape = new Shape().fromJSON( json[ i ] ); 40920 40921 shapes[ shape.uuid ] = shape; 40922 40923 } 40924 40925 } 40926 40927 return shapes; 40928 40929 }, 40930 40931 parseGeometries: function ( json, shapes ) { 40932 40933 var geometries = {}; 40934 40935 if ( json !== undefined ) { 40936 40937 var geometryLoader = new JSONLoader(); 40938 var bufferGeometryLoader = new BufferGeometryLoader(); 40939 40940 for ( var i = 0, l = json.length; i < l; i ++ ) { 40941 40942 var geometry; 40943 var data = json[ i ]; 40944 40945 switch ( data.type ) { 40946 40947 case 'PlaneGeometry': 40948 case 'PlaneBufferGeometry': 40949 40950 geometry = new Geometries[ data.type ]( 40951 data.width, 40952 data.height, 40953 data.widthSegments, 40954 data.heightSegments 40955 ); 40956 40957 break; 40958 40959 case 'BoxGeometry': 40960 case 'BoxBufferGeometry': 40961 case 'CubeGeometry': // backwards compatible 40962 40963 geometry = new Geometries[ data.type ]( 40964 data.width, 40965 data.height, 40966 data.depth, 40967 data.widthSegments, 40968 data.heightSegments, 40969 data.depthSegments 40970 ); 40971 40972 break; 40973 40974 case 'CircleGeometry': 40975 case 'CircleBufferGeometry': 40976 40977 geometry = new Geometries[ data.type ]( 40978 data.radius, 40979 data.segments, 40980 data.thetaStart, 40981 data.thetaLength 40982 ); 40983 40984 break; 40985 40986 case 'CylinderGeometry': 40987 case 'CylinderBufferGeometry': 40988 40989 geometry = new Geometries[ data.type ]( 40990 data.radiusTop, 40991 data.radiusBottom, 40992 data.height, 40993 data.radialSegments, 40994 data.heightSegments, 40995 data.openEnded, 40996 data.thetaStart, 40997 data.thetaLength 40998 ); 40999 41000 break; 41001 41002 case 'ConeGeometry': 41003 case 'ConeBufferGeometry': 41004 41005 geometry = new Geometries[ data.type ]( 41006 data.radius, 41007 data.height, 41008 data.radialSegments, 41009 data.heightSegments, 41010 data.openEnded, 41011 data.thetaStart, 41012 data.thetaLength 41013 ); 41014 41015 break; 41016 41017 case 'SphereGeometry': 41018 case 'SphereBufferGeometry': 41019 41020 geometry = new Geometries[ data.type ]( 41021 data.radius, 41022 data.widthSegments, 41023 data.heightSegments, 41024 data.phiStart, 41025 data.phiLength, 41026 data.thetaStart, 41027 data.thetaLength 41028 ); 41029 41030 break; 41031 41032 case 'DodecahedronGeometry': 41033 case 'DodecahedronBufferGeometry': 41034 case 'IcosahedronGeometry': 41035 case 'IcosahedronBufferGeometry': 41036 case 'OctahedronGeometry': 41037 case 'OctahedronBufferGeometry': 41038 case 'TetrahedronGeometry': 41039 case 'TetrahedronBufferGeometry': 41040 41041 geometry = new Geometries[ data.type ]( 41042 data.radius, 41043 data.detail 41044 ); 41045 41046 break; 41047 41048 case 'RingGeometry': 41049 case 'RingBufferGeometry': 41050 41051 geometry = new Geometries[ data.type ]( 41052 data.innerRadius, 41053 data.outerRadius, 41054 data.thetaSegments, 41055 data.phiSegments, 41056 data.thetaStart, 41057 data.thetaLength 41058 ); 41059 41060 break; 41061 41062 case 'TorusGeometry': 41063 case 'TorusBufferGeometry': 41064 41065 geometry = new Geometries[ data.type ]( 41066 data.radius, 41067 data.tube, 41068 data.radialSegments, 41069 data.tubularSegments, 41070 data.arc 41071 ); 41072 41073 break; 41074 41075 case 'TorusKnotGeometry': 41076 case 'TorusKnotBufferGeometry': 41077 41078 geometry = new Geometries[ data.type ]( 41079 data.radius, 41080 data.tube, 41081 data.tubularSegments, 41082 data.radialSegments, 41083 data.p, 41084 data.q 41085 ); 41086 41087 break; 41088 41089 case 'LatheGeometry': 41090 case 'LatheBufferGeometry': 41091 41092 geometry = new Geometries[ data.type ]( 41093 data.points, 41094 data.segments, 41095 data.phiStart, 41096 data.phiLength 41097 ); 41098 41099 break; 41100 41101 case 'PolyhedronGeometry': 41102 case 'PolyhedronBufferGeometry': 41103 41104 geometry = new Geometries[ data.type ]( 41105 data.vertices, 41106 data.indices, 41107 data.radius, 41108 data.details 41109 ); 41110 41111 break; 41112 41113 case 'ShapeGeometry': 41114 case 'ShapeBufferGeometry': 41115 41116 var geometryShapes = []; 41117 41118 for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) { 41119 41120 var shape = shapes[ data.shapes[ j ] ]; 41121 41122 geometryShapes.push( shape ); 41123 41124 } 41125 41126 geometry = new Geometries[ data.type ]( 41127 geometryShapes, 41128 data.curveSegments 41129 ); 41130 41131 break; 41132 41133 41134 case 'ExtrudeGeometry': 41135 case 'ExtrudeBufferGeometry': 41136 41137 var geometryShapes = []; 41138 41139 for ( var j = 0, jl = data.shapes.length; j < jl; j ++ ) { 41140 41141 var shape = shapes[ data.shapes[ j ] ]; 41142 41143 geometryShapes.push( shape ); 41144 41145 } 41146 41147 var extrudePath = data.options.extrudePath; 41148 41149 if ( extrudePath !== undefined ) { 41150 41151 data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath ); 41152 41153 } 41154 41155 geometry = new Geometries[ data.type ]( 41156 geometryShapes, 41157 data.options 41158 ); 41159 41160 break; 41161 41162 case 'BufferGeometry': 41163 41164 geometry = bufferGeometryLoader.parse( data ); 41165 41166 break; 41167 41168 case 'Geometry': 41169 41170 geometry = geometryLoader.parse( data, this.texturePath ).geometry; 41171 41172 break; 41173 41174 default: 41175 41176 console.warn( 'THREE.ObjectLoader: Unsupported geometry type "' + data.type + '"' ); 41177 41178 continue; 41179 41180 } 41181 41182 geometry.uuid = data.uuid; 41183 41184 if ( data.name !== undefined ) geometry.name = data.name; 41185 if ( geometry.isBufferGeometry === true && data.userData !== undefined ) geometry.userData = data.userData; 41186 41187 geometries[ data.uuid ] = geometry; 41188 41189 } 41190 41191 } 41192 41193 return geometries; 41194 41195 }, 41196 41197 parseMaterials: function ( json, textures ) { 41198 41199 var materials = {}; 41200 41201 if ( json !== undefined ) { 41202 41203 var loader = new MaterialLoader(); 41204 loader.setTextures( textures ); 41205 41206 for ( var i = 0, l = json.length; i < l; i ++ ) { 41207 41208 var data = json[ i ]; 41209 41210 if ( data.type === 'MultiMaterial' ) { 41211 41212 // Deprecated 41213 41214 var array = []; 41215 41216 for ( var j = 0; j < data.materials.length; j ++ ) { 41217 41218 array.push( loader.parse( data.materials[ j ] ) ); 41219 41220 } 41221 41222 materials[ data.uuid ] = array; 41223 41224 } else { 41225 41226 materials[ data.uuid ] = loader.parse( data ); 41227 41228 } 41229 41230 } 41231 41232 } 41233 41234 return materials; 41235 41236 }, 41237 41238 parseAnimations: function ( json ) { 41239 41240 var animations = []; 41241 41242 for ( var i = 0; i < json.length; i ++ ) { 41243 41244 var data = json[ i ]; 41245 41246 var clip = AnimationClip.parse( data ); 41247 41248 if ( data.uuid !== undefined ) clip.uuid = data.uuid; 41249 41250 animations.push( clip ); 41251 41252 } 41253 41254 return animations; 41255 41256 }, 41257 41258 parseImages: function ( json, onLoad ) { 41259 41260 var scope = this; 41261 var images = {}; 41262 41263 function loadImage( url ) { 41264 41265 scope.manager.itemStart( url ); 41266 41267 return loader.load( url, function () { 41268 41269 scope.manager.itemEnd( url ); 41270 41271 }, undefined, function () { 41272 41273 scope.manager.itemEnd( url ); 41274 scope.manager.itemError( url ); 41275 41276 } ); 41277 41278 } 41279 41280 if ( json !== undefined && json.length > 0 ) { 41281 41282 var manager = new LoadingManager( onLoad ); 41283 41284 var loader = new ImageLoader( manager ); 41285 loader.setCrossOrigin( this.crossOrigin ); 41286 41287 for ( var i = 0, l = json.length; i < l; i ++ ) { 41288 41289 var image = json[ i ]; 41290 var path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( image.url ) ? image.url : scope.texturePath + image.url; 41291 41292 images[ image.uuid ] = loadImage( path ); 41293 41294 } 41295 41296 } 41297 41298 return images; 41299 41300 }, 41301 41302 parseTextures: function ( json, images ) { 41303 41304 function parseConstant( value, type ) { 41305 41306 if ( typeof value === 'number' ) return value; 41307 41308 console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); 41309 41310 return type[ value ]; 41311 41312 } 41313 41314 var textures = {}; 41315 41316 if ( json !== undefined ) { 41317 41318 for ( var i = 0, l = json.length; i < l; i ++ ) { 41319 41320 var data = json[ i ]; 41321 41322 if ( data.image === undefined ) { 41323 41324 console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); 41325 41326 } 41327 41328 if ( images[ data.image ] === undefined ) { 41329 41330 console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); 41331 41332 } 41333 41334 var texture = new Texture( images[ data.image ] ); 41335 texture.needsUpdate = true; 41336 41337 texture.uuid = data.uuid; 41338 41339 if ( data.name !== undefined ) texture.name = data.name; 41340 41341 if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); 41342 41343 if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); 41344 if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); 41345 if ( data.center !== undefined ) texture.center.fromArray( data.center ); 41346 if ( data.rotation !== undefined ) texture.rotation = data.rotation; 41347 41348 if ( data.wrap !== undefined ) { 41349 41350 texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); 41351 texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); 41352 41353 } 41354 41355 if ( data.format !== undefined ) texture.format = data.format; 41356 41357 if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); 41358 if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); 41359 if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; 41360 41361 if ( data.flipY !== undefined ) texture.flipY = data.flipY; 41362 41363 textures[ data.uuid ] = texture; 41364 41365 } 41366 41367 } 41368 41369 return textures; 41370 41371 }, 41372 41373 parseObject: function ( data, geometries, materials ) { 41374 41375 var object; 41376 41377 function getGeometry( name ) { 41378 41379 if ( geometries[ name ] === undefined ) { 41380 41381 console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); 41382 41383 } 41384 41385 return geometries[ name ]; 41386 41387 } 41388 41389 function getMaterial( name ) { 41390 41391 if ( name === undefined ) return undefined; 41392 41393 if ( Array.isArray( name ) ) { 41394 41395 var array = []; 41396 41397 for ( var i = 0, l = name.length; i < l; i ++ ) { 41398 41399 var uuid = name[ i ]; 41400 41401 if ( materials[ uuid ] === undefined ) { 41402 41403 console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); 41404 41405 } 41406 41407 array.push( materials[ uuid ] ); 41408 41409 } 41410 41411 return array; 41412 41413 } 41414 41415 if ( materials[ name ] === undefined ) { 41416 41417 console.warn( 'THREE.ObjectLoader: Undefined material', name ); 41418 41419 } 41420 41421 return materials[ name ]; 41422 41423 } 41424 41425 switch ( data.type ) { 41426 41427 case 'Scene': 41428 41429 object = new Scene(); 41430 41431 if ( data.background !== undefined ) { 41432 41433 if ( Number.isInteger( data.background ) ) { 41434 41435 object.background = new Color( data.background ); 41436 41437 } 41438 41439 } 41440 41441 if ( data.fog !== undefined ) { 41442 41443 if ( data.fog.type === 'Fog' ) { 41444 41445 object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); 41446 41447 } else if ( data.fog.type === 'FogExp2' ) { 41448 41449 object.fog = new FogExp2( data.fog.color, data.fog.density ); 41450 41451 } 41452 41453 } 41454 41455 break; 41456 41457 case 'PerspectiveCamera': 41458 41459 object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); 41460 41461 if ( data.focus !== undefined ) object.focus = data.focus; 41462 if ( data.zoom !== undefined ) object.zoom = data.zoom; 41463 if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; 41464 if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; 41465 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 41466 41467 break; 41468 41469 case 'OrthographicCamera': 41470 41471 object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); 41472 41473 if ( data.zoom !== undefined ) object.zoom = data.zoom; 41474 if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); 41475 41476 break; 41477 41478 case 'AmbientLight': 41479 41480 object = new AmbientLight( data.color, data.intensity ); 41481 41482 break; 41483 41484 case 'DirectionalLight': 41485 41486 object = new DirectionalLight( data.color, data.intensity ); 41487 41488 break; 41489 41490 case 'PointLight': 41491 41492 object = new PointLight( data.color, data.intensity, data.distance, data.decay ); 41493 41494 break; 41495 41496 case 'RectAreaLight': 41497 41498 object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); 41499 41500 break; 41501 41502 case 'SpotLight': 41503 41504 object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); 41505 41506 break; 41507 41508 case 'HemisphereLight': 41509 41510 object = new HemisphereLight( data.color, data.groundColor, data.intensity ); 41511 41512 break; 41513 41514 case 'SkinnedMesh': 41515 41516 console.warn( 'THREE.ObjectLoader.parseObject() does not support SkinnedMesh yet.' ); 41517 41518 case 'Mesh': 41519 41520 var geometry = getGeometry( data.geometry ); 41521 var material = getMaterial( data.material ); 41522 41523 if ( geometry.bones && geometry.bones.length > 0 ) { 41524 41525 object = new SkinnedMesh( geometry, material ); 41526 41527 } else { 41528 41529 object = new Mesh( geometry, material ); 41530 41531 } 41532 41533 break; 41534 41535 case 'LOD': 41536 41537 object = new LOD(); 41538 41539 break; 41540 41541 case 'Line': 41542 41543 object = new Line( getGeometry( data.geometry ), getMaterial( data.material ), data.mode ); 41544 41545 break; 41546 41547 case 'LineLoop': 41548 41549 object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); 41550 41551 break; 41552 41553 case 'LineSegments': 41554 41555 object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); 41556 41557 break; 41558 41559 case 'PointCloud': 41560 case 'Points': 41561 41562 object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) ); 41563 41564 break; 41565 41566 case 'Sprite': 41567 41568 object = new Sprite( getMaterial( data.material ) ); 41569 41570 break; 41571 41572 case 'Group': 41573 41574 object = new Group(); 41575 41576 break; 41577 41578 default: 41579 41580 object = new Object3D(); 41581 41582 } 41583 41584 object.uuid = data.uuid; 41585 41586 if ( data.name !== undefined ) object.name = data.name; 41587 41588 if ( data.matrix !== undefined ) { 41589 41590 object.matrix.fromArray( data.matrix ); 41591 41592 if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate; 41593 if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale ); 41594 41595 } else { 41596 41597 if ( data.position !== undefined ) object.position.fromArray( data.position ); 41598 if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); 41599 if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); 41600 if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); 41601 41602 } 41603 41604 if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; 41605 if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; 41606 41607 if ( data.shadow ) { 41608 41609 if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; 41610 if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; 41611 if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); 41612 if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); 41613 41614 } 41615 41616 if ( data.visible !== undefined ) object.visible = data.visible; 41617 if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled; 41618 if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder; 41619 if ( data.userData !== undefined ) object.userData = data.userData; 41620 41621 if ( data.children !== undefined ) { 41622 41623 var children = data.children; 41624 41625 for ( var i = 0; i < children.length; i ++ ) { 41626 41627 object.add( this.parseObject( children[ i ], geometries, materials ) ); 41628 41629 } 41630 41631 } 41632 41633 if ( data.type === 'LOD' ) { 41634 41635 var levels = data.levels; 41636 41637 for ( var l = 0; l < levels.length; l ++ ) { 41638 41639 var level = levels[ l ]; 41640 var child = object.getObjectByProperty( 'uuid', level.object ); 41641 41642 if ( child !== undefined ) { 41643 41644 object.addLevel( child, level.distance ); 41645 41646 } 41647 41648 } 41649 41650 } 41651 41652 return object; 41653 41654 } 41655 41656 } ); 41657 41658 var TEXTURE_MAPPING = { 41659 UVMapping: UVMapping, 41660 CubeReflectionMapping: CubeReflectionMapping, 41661 CubeRefractionMapping: CubeRefractionMapping, 41662 EquirectangularReflectionMapping: EquirectangularReflectionMapping, 41663 EquirectangularRefractionMapping: EquirectangularRefractionMapping, 41664 SphericalReflectionMapping: SphericalReflectionMapping, 41665 CubeUVReflectionMapping: CubeUVReflectionMapping, 41666 CubeUVRefractionMapping: CubeUVRefractionMapping 41667 }; 41668 41669 var TEXTURE_WRAPPING = { 41670 RepeatWrapping: RepeatWrapping, 41671 ClampToEdgeWrapping: ClampToEdgeWrapping, 41672 MirroredRepeatWrapping: MirroredRepeatWrapping 41673 }; 41674 41675 var TEXTURE_FILTER = { 41676 NearestFilter: NearestFilter, 41677 NearestMipMapNearestFilter: NearestMipMapNearestFilter, 41678 NearestMipMapLinearFilter: NearestMipMapLinearFilter, 41679 LinearFilter: LinearFilter, 41680 LinearMipMapNearestFilter: LinearMipMapNearestFilter, 41681 LinearMipMapLinearFilter: LinearMipMapLinearFilter 41682 }; 41683 41684 /** 41685 * @author zz85 / http://www.lab4games.net/zz85/blog 41686 * minimal class for proxing functions to Path. Replaces old "extractSubpaths()" 41687 **/ 41688 41689 function ShapePath() { 41690 41691 this.type = 'ShapePath'; 41692 41693 this.color = new Color(); 41694 41695 this.subPaths = []; 41696 this.currentPath = null; 41697 41698 } 41699 41700 Object.assign( ShapePath.prototype, { 41701
41702 moveTo: function ( x, y ) { 41703 41704 this.currentPath = new Path(); 41705 this.subPaths.push( this.currentPath ); 41706 this.currentPath.moveTo( x, y ); 41707 41708 }, 41709 41710 lineTo: function ( x, y ) { 41711 41712 this.currentPath.lineTo( x, y ); 41713 41714 }, 41715 41716 quadraticCurveTo: function ( aCPx, aCPy, aX, aY ) { 41717 41718 this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); 41719 41720 }, 41721 41722 bezierCurveTo: function ( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { 41723 41724 this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); 41725 41726 }, 41727 41728 splineThru: function ( pts ) { 41729 41730 this.currentPath.splineThru( pts ); 41731 41732 }, 41733 41734 toShapes: function ( isCCW, noHoles ) { 41735 41736 function toShapesNoHoles( inSubpaths ) { 41737 41738 var shapes = []; 41739 41740 for ( var i = 0, l = inSubpaths.length; i < l; i ++ ) { 41741 41742 var tmpPath = inSubpaths[ i ]; 41743 41744 var tmpShape = new Shape(); 41745 tmpShape.curves = tmpPath.curves; 41746 41747 shapes.push( tmpShape ); 41748 41749 } 41750 41751 return shapes; 41752 41753 } 41754 41755 function isPointInsidePolygon( inPt, inPolygon ) { 41756 41757 var polyLen = inPolygon.length; 41758 41759 // inPt on polygon contour => immediate success or 41760 // toggling of inside/outside at every single! intersection point of an edge 41761 // with the horizontal line through inPt, left of inPt 41762 // not counting lowerY endpoints of edges and whole edges on that line 41763 var inside = false;
vendor: 9,176 bytes, lines 41764-42201
41764 for ( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { 41765 41766 var edgeLowPt = inPolygon[ p ]; 41767 var edgeHighPt = inPolygon[ q ]; 41768 41769 var edgeDx = edgeHighPt.x - edgeLowPt.x; 41770 var edgeDy = edgeHighPt.y - edgeLowPt.y; 41771 41772 if ( Math.abs( edgeDy ) > Number.EPSILON ) { 41773 41774 // not parallel 41775 if ( edgeDy < 0 ) { 41776 41777 edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; 41778 edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; 41779 41780 } 41781 if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; 41782 41783 if ( inPt.y === edgeLowPt.y ) { 41784 41785 if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? 41786 // continue; // no intersection or edgeLowPt => doesn't count !!! 41787 41788 } else { 41789 41790 var perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); 41791 if ( perpEdge === 0 ) return true; // inPt is on contour ? 41792 if ( perpEdge < 0 ) continue; 41793 inside = ! inside; // true intersection left of inPt 41794 41795 } 41796 41797 } else { 41798 41799 // parallel or collinear 41800 if ( inPt.y !== edgeLowPt.y ) continue; // parallel 41801 // edge lies on the same horizontal line as inPt 41802 if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || 41803 ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! 41804 // continue; 41805 41806 } 41807 41808 } 41809 41810 return inside; 41811 41812 } 41813 41814 var isClockWise = ShapeUtils.isClockWise; 41815 41816 var subPaths = this.subPaths; 41817 if ( subPaths.length === 0 ) return []; 41818 41819 if ( noHoles === true ) return toShapesNoHoles( subPaths ); 41820 41821 41822 var solid, tmpPath, tmpShape, shapes = []; 41823 41824 if ( subPaths.length === 1 ) { 41825 41826 tmpPath = subPaths[ 0 ]; 41827 tmpShape = new Shape(); 41828 tmpShape.curves = tmpPath.curves; 41829 shapes.push( tmpShape ); 41830 return shapes; 41831 41832 } 41833 41834 var holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); 41835 holesFirst = isCCW ? ! holesFirst : holesFirst; 41836 41837 // console.log("Holes first", holesFirst); 41838 41839 var betterShapeHoles = []; 41840 var newShapes = []; 41841 var newShapeHoles = []; 41842 var mainIdx = 0; 41843 var tmpPoints; 41844 41845 newShapes[ mainIdx ] = undefined; 41846 newShapeHoles[ mainIdx ] = []; 41847 41848 for ( var i = 0, l = subPaths.length; i < l; i ++ ) { 41849 41850 tmpPath = subPaths[ i ]; 41851 tmpPoints = tmpPath.getPoints(); 41852 solid = isClockWise( tmpPoints ); 41853 solid = isCCW ? ! solid : solid; 41854 41855 if ( solid ) { 41856 41857 if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; 41858 41859 newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; 41860 newShapes[ mainIdx ].s.curves = tmpPath.curves; 41861 41862 if ( holesFirst ) mainIdx ++; 41863 newShapeHoles[ mainIdx ] = []; 41864 41865 //console.log('cw', i); 41866 41867 } else { 41868 41869 newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); 41870 41871 //console.log('ccw', i); 41872 41873 } 41874 41875 } 41876 41877 // only Holes? -> probably all Shapes with wrong orientation 41878 if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); 41879 41880 41881 if ( newShapes.length > 1 ) { 41882 41883 var ambiguous = false; 41884 var toChange = []; 41885 41886 for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 41887 41888 betterShapeHoles[ sIdx ] = []; 41889 41890 } 41891 41892 for ( var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { 41893 41894 var sho = newShapeHoles[ sIdx ]; 41895 41896 for ( var hIdx = 0; hIdx < sho.length; hIdx ++ ) { 41897 41898 var ho = sho[ hIdx ]; 41899 var hole_unassigned = true; 41900 41901 for ( var s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { 41902 41903 if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { 41904 41905 if ( sIdx !== s2Idx ) toChange.push( { froms: sIdx, tos: s2Idx, hole: hIdx } ); 41906 if ( hole_unassigned ) { 41907 41908 hole_unassigned = false; 41909 betterShapeHoles[ s2Idx ].push( ho ); 41910 41911 } else { 41912 41913 ambiguous = true; 41914 41915 } 41916 41917 } 41918 41919 } 41920 if ( hole_unassigned ) { 41921 41922 betterShapeHoles[ sIdx ].push( ho ); 41923 41924 } 41925 41926 } 41927 41928 } 41929 // console.log("ambiguous: ", ambiguous); 41930 if ( toChange.length > 0 ) { 41931 41932 // console.log("to change: ", toChange); 41933 if ( ! ambiguous ) newShapeHoles = betterShapeHoles; 41934 41935 } 41936 41937 } 41938 41939 var tmpHoles; 41940 41941 for ( var i = 0, il = newShapes.length; i < il; i ++ ) { 41942 41943 tmpShape = newShapes[ i ].s; 41944 shapes.push( tmpShape ); 41945 tmpHoles = newShapeHoles[ i ]; 41946 41947 for ( var j = 0, jl = tmpHoles.length; j < jl; j ++ ) { 41948 41949 tmpShape.holes.push( tmpHoles[ j ].h ); 41950 41951 } 41952 41953 } 41954 41955 //console.log("shape", shapes); 41956 41957 return shapes; 41958 41959 } 41960 41961 } ); 41962 41963 /** 41964 * @author zz85 / http://www.lab4games.net/zz85/blog 41965 * @author mrdoob / http://mrdoob.com/ 41966 */ 41967 41968 41969 function Font( data ) { 41970 41971 this.type = 'Font'; 41972 41973 this.data = data; 41974 41975 } 41976 41977 Object.assign( Font.prototype, { 41978 41979 isFont: true, 41980 41981 generateShapes: function ( text, size, divisions ) { 41982 41983 if ( size === undefined ) size = 100; 41984 if ( divisions === undefined ) divisions = 4; 41985 41986 var shapes = []; 41987 var paths = createPaths( text, size, divisions, this.data ); 41988 41989 for ( var p = 0, pl = paths.length; p < pl; p ++ ) { 41990 41991 Array.prototype.push.apply( shapes, paths[ p ].toShapes() ); 41992 41993 } 41994 41995 return shapes; 41996 41997 } 41998 41999 } ); 42000 42001 function createPaths( text, size, divisions, data ) { 42002 42003 var chars = Array.from ? Array.from( text ) : String( text ).split( '' ); // see #13988 42004 var scale = size / data.resolution; 42005 var line_height = ( data.boundingBox.yMax - data.boundingBox.yMin + data.underlineThickness ) * scale; 42006 42007 var paths = []; 42008 42009 var offsetX = 0, offsetY = 0; 42010 42011 for ( var i = 0; i < chars.length; i ++ ) { 42012 42013 var char = chars[ i ]; 42014 42015 if ( char === '\n' ) { 42016 42017 offsetX = 0; 42018 offsetY -= line_height; 42019 42020 } else { 42021 42022 var ret = createPath( char, divisions, scale, offsetX, offsetY, data ); 42023 offsetX += ret.offsetX; 42024 paths.push( ret.path ); 42025 42026 } 42027 42028 } 42029 42030 return paths; 42031 42032 } 42033 42034 function createPath( char, divisions, scale, offsetX, offsetY, data ) { 42035 42036 var glyph = data.glyphs[ char ] || data.glyphs[ '?' ]; 42037 42038 if ( ! glyph ) return; 42039 42040 var path = new ShapePath(); 42041 42042 var x, y, cpx, cpy, cpx1, cpy1, cpx2, cpy2; 42043 42044 if ( glyph.o ) { 42045 42046 var outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) ); 42047 42048 for ( var i = 0, l = outline.length; i < l; ) { 42049 42050 var action = outline[ i ++ ]; 42051 42052 switch ( action ) { 42053 42054 case 'm': // moveTo 42055 42056 x = outline[ i ++ ] * scale + offsetX; 42057 y = outline[ i ++ ] * scale + offsetY; 42058 42059 path.moveTo( x, y ); 42060 42061 break; 42062 42063 case 'l': // lineTo 42064 42065 x = outline[ i ++ ] * scale + offsetX; 42066 y = outline[ i ++ ] * scale + offsetY; 42067 42068 path.lineTo( x, y ); 42069 42070 break; 42071 42072 case 'q': // quadraticCurveTo 42073 42074 cpx = outline[ i ++ ] * scale + offsetX; 42075 cpy = outline[ i ++ ] * scale + offsetY; 42076 cpx1 = outline[ i ++ ] * scale + offsetX; 42077 cpy1 = outline[ i ++ ] * scale + offsetY; 42078 42079 path.quadraticCurveTo( cpx1, cpy1, cpx, cpy ); 42080 42081 break; 42082 42083 case 'b': // bezierCurveTo 42084 42085 cpx = outline[ i ++ ] * scale + offsetX; 42086 cpy = outline[ i ++ ] * scale + offsetY; 42087 cpx1 = outline[ i ++ ] * scale + offsetX; 42088 cpy1 = outline[ i ++ ] * scale + offsetY; 42089 cpx2 = outline[ i ++ ] * scale + offsetX; 42090 cpy2 = outline[ i ++ ] * scale + offsetY; 42091 42092 path.bezierCurveTo( cpx1, cpy1, cpx2, cpy2, cpx, cpy ); 42093 42094 break; 42095 42096 } 42097 42098 } 42099 42100 } 42101 42102 return { offsetX: glyph.ha * scale, path: path }; 42103 42104 } 42105 42106 /** 42107 * @author mrdoob / http://mrdoob.com/ 42108 */ 42109 42110 function FontLoader( manager ) { 42111 42112 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 42113 42114 } 42115 42116 Object.assign( FontLoader.prototype, { 42117 42118 load: function ( url, onLoad, onProgress, onError ) { 42119 42120 var scope = this; 42121 42122 var loader = new FileLoader( this.manager ); 42123 loader.setPath( this.path ); 42124 loader.load( url, function ( text ) { 42125 42126 var json; 42127 42128 try { 42129 42130 json = JSON.parse( text ); 42131 42132 } catch ( e ) { 42133 42134 console.warn( 'THREE.FontLoader: typeface.js support is being deprecated. Use typeface.json instead.' ); 42135 json = JSON.parse( text.substring( 65, text.length - 2 ) ); 42136 42137 } 42138 42139 var font = scope.parse( json ); 42140 42141 if ( onLoad ) onLoad( font ); 42142 42143 }, onProgress, onError ); 42144 42145 }, 42146 42147 parse: function ( json ) { 42148 42149 return new Font( json ); 42150 42151 }, 42152 42153 setPath: function ( value ) { 42154 42155 this.path = value; 42156 return this; 42157 42158 } 42159 42160 } ); 42161 42162 /** 42163 * @author mrdoob / http://mrdoob.com/ 42164 */ 42165 42166 var context; 42167 42168 var AudioContext = { 42169 42170 getContext: function () { 42171 42172 if ( context === undefined ) { 42173 42174 context = new ( window.AudioContext || window.webkitAudioContext )(); 42175 42176 } 42177 42178 return context; 42179 42180 }, 42181 42182 setContext: function ( value ) { 42183 42184 context = value; 42185 42186 } 42187 42188 }; 42189 42190 /** 42191 * @author Reece Aaron Lecrivain / http://reecenotes.com/ 42192 */ 42193 42194 function AudioLoader( manager ) { 42195 42196 this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 42197 42198 } 42199 42200 Object.assign( AudioLoader.prototype, { 42201
42202 load: function ( url, onLoad, onProgress, onError ) { 42203 42204 var loader = new FileLoader( this.manager ); 42205 loader.setResponseType( 'arraybuffer' ); 42206 loader.load( url, function ( buffer ) { 42207 42208 var context = AudioContext.getContext(); 42209 42210 context.decodeAudioData( buffer, function ( audioBuffer ) { 42211 42212 onLoad( audioBuffer ); 42213 42214 } ); 42215 42216 }, onProgress, onError ); 42217 42218 } 42219 42220 } ); 42221 42222 /** 42223 * @author mrdoob / http://mrdoob.com/ 42224 */ 42225 42226 function StereoCamera() { 42227 42228 this.type = 'StereoCamera'; 42229 42230 this.aspect = 1; 42231 42232 this.eyeSep = 0.064; 42233 42234 this.cameraL = new PerspectiveCamera(); 42235 this.cameraL.layers.enable( 1 ); 42236 this.cameraL.matrixAutoUpdate = false; 42237 42238 this.cameraR = new PerspectiveCamera(); 42239 this.cameraR.layers.enable( 2 ); 42240 this.cameraR.matrixAutoUpdate = false; 42241 42242 } 42243 42244 Object.assign( StereoCamera.prototype, { 42245 42246 update: ( function () { 42247 42248 var instance, focus, fov, aspect, near, far, zoom, eyeSep; 42249 42250 var eyeRight = new Matrix4(); 42251 var eyeLeft = new Matrix4(); 42252 42253 return function update( camera ) { 42254 42255 var needsUpdate = instance !== this || focus !== camera.focus || fov !== camera.fov || 42256 aspect !== camera.aspect * this.aspect || near !== camera.near || 42257 far !== camera.far || zoom !== camera.zoom || eyeSep !== this.eyeSep; 42258 42259 if ( needsUpdate ) { 42260 42261 instance = this; 42262 focus = camera.focus; 42263 fov = camera.fov; 42264 aspect = camera.aspect * this.aspect; 42265 near = camera.near; 42266 far = camera.far; 42267 zoom = camera.zoom; 42268 42269 // Off-axis stereoscopic effect based on 42270 // http://paulbourke.net/stereographics/stereorender/ 42271 42272 var projectionMatrix = camera.projectionMatrix.clone(); 42273 eyeSep = this.eyeSep / 2; 42274 var eyeSepOnProjection = eyeSep * near / focus; 42275 var ymax = ( near * Math.tan( _Math.DEG2RAD * fov * 0.5 ) ) / zoom; 42276 var xmin, xmax; 42277 42278 // translate xOffset 42279 42280 eyeLeft.elements[ 12 ] = - eyeSep; 42281 eyeRight.elements[ 12 ] = eyeSep; 42282 42283 // for left eye 42284 42285 xmin = - ymax * aspect + eyeSepOnProjection; 42286 xmax = ymax * aspect + eyeSepOnProjection; 42287 42288 projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin ); 42289 projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 42290 42291 this.cameraL.projectionMatrix.copy( projectionMatrix ); 42292 42293 // for right eye 42294 42295 xmin = - ymax * aspect - eyeSepOnProjection; 42296 xmax = ymax * aspect - eyeSepOnProjection; 42297 42298 projectionMatrix.elements[ 0 ] = 2 * near / ( xmax - xmin ); 42299 projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); 42300 42301 this.cameraR.projectionMatrix.copy( projectionMatrix ); 42302 42303 } 42304 42305 this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( eyeLeft ); 42306 this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( eyeRight ); 42307 42308 }; 42309 42310 } )() 42311 42312 } ); 42313 42314 /** 42315 * Camera for rendering cube maps 42316 * - renders scene into axis-aligned cube 42317 * 42318 * @author alteredq / http://alteredqualia.com/ 42319 */ 42320 42321 function CubeCamera( near, far, cubeResolution ) { 42322 42323 Object3D.call( this ); 42324 42325 this.type = 'CubeCamera'; 42326 42327 var fov = 90, aspect = 1; 42328 42329 var cameraPX = new PerspectiveCamera( fov, aspect, near, far ); 42330 cameraPX.up.set( 0, - 1, 0 ); 42331 cameraPX.lookAt( new Vector3( 1, 0, 0 ) ); 42332 this.add( cameraPX ); 42333 42334 var cameraNX = new PerspectiveCamera( fov, aspect, near, far ); 42335 cameraNX.up.set( 0, - 1, 0 ); 42336 cameraNX.lookAt( new Vector3( - 1, 0, 0 ) ); 42337 this.add( cameraNX ); 42338 42339 var cameraPY = new PerspectiveCamera( fov, aspect, near, far ); 42340 cameraPY.up.set( 0, 0, 1 ); 42341 cameraPY.lookAt( new Vector3( 0, 1, 0 ) ); 42342 this.add( cameraPY ); 42343 42344 var cameraNY = new PerspectiveCamera( fov, aspect, near, far ); 42345 cameraNY.up.set( 0, 0, - 1 ); 42346 cameraNY.lookAt( new Vector3( 0, - 1, 0 ) ); 42347 this.add( cameraNY ); 42348 42349 var cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); 42350 cameraPZ.up.set( 0, - 1, 0 ); 42351 cameraPZ.lookAt( new Vector3( 0, 0, 1 ) ); 42352 this.add( cameraPZ ); 42353 42354 var cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); 42355 cameraNZ.up.set( 0, - 1, 0 ); 42356 cameraNZ.lookAt( new Vector3( 0, 0, - 1 ) ); 42357 this.add( cameraNZ ); 42358 42359 var options = { format: RGBFormat, magFilter: LinearFilter, minFilter: LinearFilter }; 42360 42361 this.renderTarget = new WebGLRenderTargetCube( cubeResolution, cubeResolution, options ); 42362 this.renderTarget.texture.name = "CubeCamera"; 42363 42364 this.update = function ( renderer, scene ) { 42365 42366 if ( this.parent === null ) this.updateMatrixWorld(); 42367 42368 var renderTarget = this.renderTarget; 42369 var generateMipmaps = renderTarget.texture.generateMipmaps; 42370 42371 renderTarget.texture.generateMipmaps = false;
42372 42373 renderTarget.activeCubeFace = 0; 42374 renderer.render( scene, cameraPX, renderTarget ); 42375 42376 renderTarget.activeCubeFace = 1; 42377 renderer.render( scene, cameraNX, renderTarget ); 42378 42379 renderTarget.activeCubeFace = 2; 42380 renderer.render( scene, cameraPY, renderTarget ); 42381 42382 renderTarget.activeCubeFace = 3; 42383 renderer.render( scene, cameraNY, renderTarget ); 42384 42385 renderTarget.activeCubeFace = 4; 42386 renderer.render( scene, cameraPZ, renderTarget ); 42387 42388 renderTarget.texture.generateMipmaps = generateMipmaps; 42389 42390 renderTarget.activeCubeFace = 5; 42391 renderer.render( scene, cameraNZ, renderTarget ); 42392 42393 renderer.setRenderTarget( null ); 42394 42395 }; 42396 42397 this.clear = function ( renderer, color, depth, stencil ) { 42398 42399 var renderTarget = this.renderTarget; 42400 42401 for ( var i = 0; i < 6; i ++ ) { 42402 42403 renderTarget.activeCubeFace = i; 42404 renderer.setRenderTarget( renderTarget ); 42405 42406 renderer.clear( color, depth, stencil ); 42407 42408 } 42409 42410 renderer.setRenderTarget( null ); 42411 42412 }; 42413 42414 } 42415 42416 CubeCamera.prototype = Object.create( Object3D.prototype ); 42417 CubeCamera.prototype.constructor = CubeCamera; 42418 42419 /** 42420 * @author mrdoob / http://mrdoob.com/ 42421 */ 42422 42423 function AudioListener() { 42424 42425 Object3D.call( this ); 42426 42427 this.type = 'AudioListener'; 42428 42429 this.context = AudioContext.getContext(); 42430 42431 this.gain = this.context.createGain(); 42432 this.gain.connect( this.context.destination ); 42433 42434 this.filter = null; 42435 42436 } 42437 42438 AudioListener.prototype = Object.assign( Object.create( Object3D.prototype ), { 42439 42440 constructor: AudioListener, 42441 42442 getInput: function () { 42443 42444 return this.gain; 42445 42446 }, 42447 42448 removeFilter: function ( ) { 42449 42450 if ( this.filter !== null ) { 42451 42452 this.gain.disconnect( this.filter ); 42453 this.filter.disconnect( this.context.destination ); 42454 this.gain.connect( this.context.destination ); 42455 this.filter = null; 42456 42457 } 42458 42459 }, 42460 42461 getFilter: function () { 42462 42463 return this.filter; 42464 42465 }, 42466 42467 setFilter: function ( value ) { 42468 42469 if ( this.filter !== null ) { 42470 42471 this.gain.disconnect( this.filter ); 42472 this.filter.disconnect( this.context.destination ); 42473 42474 } else { 42475 42476 this.gain.disconnect( this.context.destination ); 42477 42478 } 42479 42480 this.filter = value; 42481 this.gain.connect( this.filter ); 42482 this.filter.connect( this.context.destination ); 42483 42484 }, 42485 42486 getMasterVolume: function () { 42487 42488 return this.gain.gain.value; 42489 42490 }, 42491 42492 setMasterVolume: function ( value ) { 42493 42494 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 42495 42496 }, 42497 42498 updateMatrixWorld: ( function () { 42499 42500 var position = new Vector3(); 42501 var quaternion = new Quaternion(); 42502 var scale = new Vector3(); 42503 42504 var orientation = new Vector3(); 42505 42506 return function updateMatrixWorld( force ) { 42507 42508 Object3D.prototype.updateMatrixWorld.call( this, force ); 42509 42510 var listener = this.context.listener; 42511 var up = this.up; 42512 42513 this.matrixWorld.decompose( position, quaternion, scale ); 42514 42515 orientation.set( 0, 0, - 1 ).applyQuaternion( quaternion ); 42516 42517 if ( listener.positionX ) { 42518 42519 listener.positionX.setValueAtTime( position.x, this.context.currentTime ); 42520 listener.positionY.setValueAtTime( position.y, this.context.currentTime ); 42521 listener.positionZ.setValueAtTime( position.z, this.context.currentTime ); 42522 listener.forwardX.setValueAtTime( orientation.x, this.context.currentTime ); 42523 listener.forwardY.setValueAtTime( orientation.y, this.context.currentTime ); 42524 listener.forwardZ.setValueAtTime( orientation.z, this.context.currentTime ); 42525 listener.upX.setValueAtTime( up.x, this.context.currentTime ); 42526 listener.upY.setValueAtTime( up.y, this.context.currentTime ); 42527 listener.upZ.setValueAtTime( up.z, this.context.currentTime ); 42528 42529 } else { 42530 42531 listener.setPosition( position.x, position.y, position.z ); 42532 listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z ); 42533 42534 } 42535 42536 }; 42537 42538 } )() 42539 42540 } ); 42541 42542 /** 42543 * @author mrdoob / http://mrdoob.com/ 42544 * @author Reece Aaron Lecrivain / http://reecenotes.com/ 42545 */ 42546 42547 function Audio( listener ) { 42548 42549 Object3D.call( this ); 42550 42551 this.type = 'Audio'; 42552 42553 this.context = listener.context; 42554 42555 this.gain = this.context.createGain(); 42556 this.gain.connect( listener.getInput() ); 42557 42558 this.autoplay = false;
vendor: 4,143 bytes, lines 42559-42793
42559 42560 this.buffer = null; 42561 this.loop = false; 42562 this.startTime = 0; 42563 this.offset = 0; 42564 this.playbackRate = 1; 42565 this.isPlaying = false; 42566 this.hasPlaybackControl = true; 42567 this.sourceType = 'empty'; 42568 42569 this.filters = []; 42570 42571 } 42572 42573 Audio.prototype = Object.assign( Object.create( Object3D.prototype ), { 42574 42575 constructor: Audio, 42576 42577 getOutput: function () { 42578 42579 return this.gain; 42580 42581 }, 42582 42583 setNodeSource: function ( audioNode ) { 42584 42585 this.hasPlaybackControl = false; 42586 this.sourceType = 'audioNode'; 42587 this.source = audioNode; 42588 this.connect(); 42589 42590 return this; 42591 42592 }, 42593 42594 setMediaElementSource: function ( mediaElement ) { 42595 42596 this.hasPlaybackControl = false; 42597 this.sourceType = 'mediaNode'; 42598 this.source = this.context.createMediaElementSource( mediaElement ); 42599 this.connect(); 42600 42601 return this; 42602 42603 }, 42604 42605 setBuffer: function ( audioBuffer ) { 42606 42607 this.buffer = audioBuffer; 42608 this.sourceType = 'buffer'; 42609 42610 if ( this.autoplay ) this.play(); 42611 42612 return this; 42613 42614 }, 42615 42616 play: function () { 42617 42618 if ( this.isPlaying === true ) { 42619 42620 console.warn( 'THREE.Audio: Audio is already playing.' ); 42621 return; 42622 42623 } 42624 42625 if ( this.hasPlaybackControl === false ) { 42626 42627 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 42628 return; 42629 42630 } 42631 42632 var source = this.context.createBufferSource(); 42633 42634 source.buffer = this.buffer; 42635 source.loop = this.loop; 42636 source.onended = this.onEnded.bind( this ); 42637 source.playbackRate.setValueAtTime( this.playbackRate, this.startTime ); 42638 this.startTime = this.context.currentTime; 42639 source.start( this.startTime, this.offset ); 42640 42641 this.isPlaying = true; 42642 42643 this.source = source; 42644 42645 return this.connect(); 42646 42647 }, 42648 42649 pause: function () { 42650 42651 if ( this.hasPlaybackControl === false ) { 42652 42653 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 42654 return; 42655 42656 } 42657 42658 if ( this.isPlaying === true ) { 42659 42660 this.source.stop(); 42661 this.offset += ( this.context.currentTime - this.startTime ) * this.playbackRate; 42662 this.isPlaying = false; 42663 42664 } 42665 42666 return this; 42667 42668 }, 42669 42670 stop: function () { 42671 42672 if ( this.hasPlaybackControl === false ) { 42673 42674 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 42675 return; 42676 42677 } 42678 42679 this.source.stop(); 42680 this.offset = 0; 42681 this.isPlaying = false; 42682 42683 return this; 42684 42685 }, 42686 42687 connect: function () { 42688 42689 if ( this.filters.length > 0 ) { 42690 42691 this.source.connect( this.filters[ 0 ] ); 42692 42693 for ( var i = 1, l = this.filters.length; i < l; i ++ ) { 42694 42695 this.filters[ i - 1 ].connect( this.filters[ i ] ); 42696 42697 } 42698 42699 this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); 42700 42701 } else { 42702 42703 this.source.connect( this.getOutput() ); 42704 42705 } 42706 42707 return this; 42708 42709 }, 42710 42711 disconnect: function () { 42712 42713 if ( this.filters.length > 0 ) { 42714 42715 this.source.disconnect( this.filters[ 0 ] ); 42716 42717 for ( var i = 1, l = this.filters.length; i < l; i ++ ) { 42718 42719 this.filters[ i - 1 ].disconnect( this.filters[ i ] ); 42720 42721 } 42722 42723 this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); 42724 42725 } else { 42726 42727 this.source.disconnect( this.getOutput() ); 42728 42729 } 42730 42731 return this; 42732 42733 }, 42734 42735 getFilters: function () { 42736 42737 return this.filters; 42738 42739 }, 42740 42741 setFilters: function ( value ) { 42742 42743 if ( ! value ) value = []; 42744 42745 if ( this.isPlaying === true ) { 42746 42747 this.disconnect(); 42748 this.filters = value; 42749 this.connect(); 42750 42751 } else { 42752 42753 this.filters = value; 42754 42755 } 42756 42757 return this; 42758 42759 }, 42760 42761 getFilter: function () { 42762 42763 return this.getFilters()[ 0 ]; 42764 42765 }, 42766 42767 setFilter: function ( filter ) { 42768 42769 return this.setFilters( filter ? [ filter ] : [] ); 42770 42771 }, 42772 42773 setPlaybackRate: function ( value ) { 42774 42775 if ( this.hasPlaybackControl === false ) { 42776 42777 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 42778 return; 42779 42780 } 42781 42782 this.playbackRate = value; 42783 42784 if ( this.isPlaying === true ) { 42785 42786 this.source.playbackRate.setValueAtTime( this.playbackRate, this.context.currentTime ); 42787 42788 } 42789 42790 return this; 42791 42792 }, 42793
vendor: 40,587 bytes, lines 42794-44581
42794 getPlaybackRate: function () { 42795 42796 return this.playbackRate; 42797 42798 }, 42799 42800 onEnded: function () { 42801 42802 this.isPlaying = false; 42803 42804 }, 42805 42806 getLoop: function () { 42807 42808 if ( this.hasPlaybackControl === false ) { 42809 42810 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 42811 return false; 42812 42813 } 42814 42815 return this.loop; 42816 42817 }, 42818 42819 setLoop: function ( value ) { 42820 42821 if ( this.hasPlaybackControl === false ) { 42822 42823 console.warn( 'THREE.Audio: this Audio has no playback control.' ); 42824 return; 42825 42826 } 42827 42828 this.loop = value; 42829 42830 if ( this.isPlaying === true ) { 42831 42832 this.source.loop = this.loop; 42833 42834 } 42835 42836 return this; 42837 42838 }, 42839 42840 getVolume: function () { 42841 42842 return this.gain.gain.value; 42843 42844 }, 42845 42846 setVolume: function ( value ) { 42847 42848 this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); 42849 42850 return this; 42851 42852 } 42853 42854 } ); 42855 42856 /** 42857 * @author mrdoob / http://mrdoob.com/ 42858 */ 42859 42860 function PositionalAudio( listener ) { 42861 42862 Audio.call( this, listener ); 42863 42864 this.panner = this.context.createPanner(); 42865 this.panner.connect( this.gain ); 42866 42867 } 42868 42869 PositionalAudio.prototype = Object.assign( Object.create( Audio.prototype ), { 42870 42871 constructor: PositionalAudio, 42872 42873 getOutput: function () { 42874 42875 return this.panner; 42876 42877 }, 42878 42879 getRefDistance: function () { 42880 42881 return this.panner.refDistance; 42882 42883 }, 42884 42885 setRefDistance: function ( value ) { 42886 42887 this.panner.refDistance = value; 42888 42889 }, 42890 42891 getRolloffFactor: function () { 42892 42893 return this.panner.rolloffFactor; 42894 42895 }, 42896 42897 setRolloffFactor: function ( value ) { 42898 42899 this.panner.rolloffFactor = value; 42900 42901 }, 42902 42903 getDistanceModel: function () { 42904 42905 return this.panner.distanceModel; 42906 42907 }, 42908 42909 setDistanceModel: function ( value ) { 42910 42911 this.panner.distanceModel = value; 42912 42913 }, 42914 42915 getMaxDistance: function () { 42916 42917 return this.panner.maxDistance; 42918 42919 }, 42920 42921 setMaxDistance: function ( value ) { 42922 42923 this.panner.maxDistance = value; 42924 42925 }, 42926 42927 updateMatrixWorld: ( function () { 42928 42929 var position = new Vector3(); 42930 42931 return function updateMatrixWorld( force ) { 42932 42933 Object3D.prototype.updateMatrixWorld.call( this, force ); 42934 42935 position.setFromMatrixPosition( this.matrixWorld ); 42936 42937 this.panner.setPosition( position.x, position.y, position.z ); 42938 42939 }; 42940 42941 } )() 42942 42943 42944 } ); 42945 42946 /** 42947 * @author mrdoob / http://mrdoob.com/ 42948 */ 42949 42950 function AudioAnalyser( audio, fftSize ) { 42951 42952 this.analyser = audio.context.createAnalyser(); 42953 this.analyser.fftSize = fftSize !== undefined ? fftSize : 2048; 42954 42955 this.data = new Uint8Array( this.analyser.frequencyBinCount ); 42956 42957 audio.getOutput().connect( this.analyser ); 42958 42959 } 42960 42961 Object.assign( AudioAnalyser.prototype, { 42962 42963 getFrequencyData: function () { 42964 42965 this.analyser.getByteFrequencyData( this.data ); 42966 42967 return this.data; 42968 42969 }, 42970 42971 getAverageFrequency: function () { 42972 42973 var value = 0, data = this.getFrequencyData(); 42974 42975 for ( var i = 0; i < data.length; i ++ ) { 42976 42977 value += data[ i ]; 42978 42979 } 42980 42981 return value / data.length; 42982 42983 } 42984 42985 } ); 42986 42987 /** 42988 * 42989 * Buffered scene graph property that allows weighted accumulation. 42990 * 42991 * 42992 * @author Ben Houston / http://clara.io/ 42993 * @author David Sarno / http://lighthaus.us/ 42994 * @author tschw 42995 */ 42996 42997 function PropertyMixer( binding, typeName, valueSize ) { 42998 42999 this.binding = binding; 43000 this.valueSize = valueSize; 43001 43002 var bufferType = Float64Array, 43003 mixFunction; 43004 43005 switch ( typeName ) { 43006 43007 case 'quaternion': 43008 mixFunction = this._slerp; 43009 break; 43010 43011 case 'string': 43012 case 'bool': 43013 bufferType = Array; 43014 mixFunction = this._select; 43015 break; 43016 43017 default: 43018 mixFunction = this._lerp; 43019 43020 } 43021 43022 this.buffer = new bufferType( valueSize * 4 ); 43023 // layout: [ incoming | accu0 | accu1 | orig ] 43024 // 43025 // interpolators can use .buffer as their .result 43026 // the data then goes to 'incoming' 43027 // 43028 // 'accu0' and 'accu1' are used frame-interleaved for 43029 // the cumulative result and are compared to detect 43030 // changes 43031 // 43032 // 'orig' stores the original state of the property 43033 43034 this._mixBufferRegion = mixFunction; 43035 43036 this.cumulativeWeight = 0; 43037 43038 this.useCount = 0; 43039 this.referenceCount = 0; 43040 43041 } 43042 43043 Object.assign( PropertyMixer.prototype, { 43044 43045 // accumulate data in the 'incoming' region into 'accu<i>' 43046 accumulate: function ( accuIndex, weight ) { 43047 43048 // note: happily accumulating nothing when weight = 0, the caller knows 43049 // the weight and shouldn't have made the call in the first place 43050 43051 var buffer = this.buffer, 43052 stride = this.valueSize, 43053 offset = accuIndex * stride + stride, 43054 43055 currentWeight = this.cumulativeWeight; 43056 43057 if ( currentWeight === 0 ) { 43058 43059 // accuN := incoming * weight 43060 43061 for ( var i = 0; i !== stride; ++ i ) { 43062 43063 buffer[ offset + i ] = buffer[ i ]; 43064 43065 } 43066 43067 currentWeight = weight; 43068 43069 } else { 43070 43071 // accuN := accuN + incoming * weight 43072 43073 currentWeight += weight; 43074 var mix = weight / currentWeight; 43075 this._mixBufferRegion( buffer, offset, 0, mix, stride ); 43076 43077 } 43078 43079 this.cumulativeWeight = currentWeight; 43080 43081 }, 43082 43083 // apply the state of 'accu<i>' to the binding when accus differ 43084 apply: function ( accuIndex ) { 43085 43086 var stride = this.valueSize, 43087 buffer = this.buffer, 43088 offset = accuIndex * stride + stride, 43089 43090 weight = this.cumulativeWeight, 43091 43092 binding = this.binding; 43093 43094 this.cumulativeWeight = 0; 43095 43096 if ( weight < 1 ) { 43097 43098 // accuN := accuN + original * ( 1 - cumulativeWeight ) 43099 43100 var originalValueOffset = stride * 3; 43101 43102 this._mixBufferRegion( 43103 buffer, offset, originalValueOffset, 1 - weight, stride ); 43104 43105 } 43106 43107 for ( var i = stride, e = stride + stride; i !== e; ++ i ) { 43108 43109 if ( buffer[ i ] !== buffer[ i + stride ] ) { 43110 43111 // value has changed -> update scene graph 43112 43113 binding.setValue( buffer, offset ); 43114 break; 43115 43116 } 43117 43118 } 43119 43120 }, 43121 43122 // remember the state of the bound property and copy it to both accus 43123 saveOriginalState: function () { 43124 43125 var binding = this.binding; 43126 43127 var buffer = this.buffer, 43128 stride = this.valueSize, 43129 43130 originalValueOffset = stride * 3; 43131 43132 binding.getValue( buffer, originalValueOffset ); 43133 43134 // accu[0..1] := orig -- initially detect changes against the original 43135 for ( var i = stride, e = originalValueOffset; i !== e; ++ i ) { 43136 43137 buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; 43138 43139 } 43140 43141 this.cumulativeWeight = 0; 43142 43143 }, 43144 43145 // apply the state previously taken via 'saveOriginalState' to the binding 43146 restoreOriginalState: function () { 43147 43148 var originalValueOffset = this.valueSize * 3; 43149 this.binding.setValue( this.buffer, originalValueOffset ); 43150 43151 }, 43152 43153 43154 // mix functions 43155 43156 _select: function ( buffer, dstOffset, srcOffset, t, stride ) { 43157 43158 if ( t >= 0.5 ) { 43159 43160 for ( var i = 0; i !== stride; ++ i ) { 43161 43162 buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; 43163 43164 } 43165 43166 } 43167 43168 }, 43169 43170 _slerp: function ( buffer, dstOffset, srcOffset, t ) { 43171 43172 Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); 43173 43174 }, 43175 43176 _lerp: function ( buffer, dstOffset, srcOffset, t, stride ) { 43177 43178 var s = 1 - t; 43179 43180 for ( var i = 0; i !== stride; ++ i ) { 43181 43182 var j = dstOffset + i; 43183 43184 buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; 43185 43186 } 43187 43188 } 43189 43190 } ); 43191 43192 /** 43193 * 43194 * A reference to a real property in the scene graph. 43195 * 43196 * 43197 * @author Ben Houston / http://clara.io/ 43198 * @author David Sarno / http://lighthaus.us/ 43199 * @author tschw 43200 */ 43201 43202 // Characters [].:/ are reserved for track binding syntax. 43203 var RESERVED_CHARS_RE = '\\[\\]\\.:\\/'; 43204 43205 function Composite( targetGroup, path, optionalParsedPath ) { 43206 43207 var parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); 43208 43209 this._targetGroup = targetGroup; 43210 this._bindings = targetGroup.subscribe_( path, parsedPath ); 43211 43212 } 43213 43214 Object.assign( Composite.prototype, { 43215 43216 getValue: function ( array, offset ) { 43217 43218 this.bind(); // bind all binding 43219 43220 var firstValidIndex = this._targetGroup.nCachedObjects_, 43221 binding = this._bindings[ firstValidIndex ]; 43222 43223 // and only call .getValue on the first 43224 if ( binding !== undefined ) binding.getValue( array, offset ); 43225 43226 }, 43227 43228 setValue: function ( array, offset ) { 43229 43230 var bindings = this._bindings; 43231 43232 for ( var i = this._targetGroup.nCachedObjects_, 43233 n = bindings.length; i !== n; ++ i ) { 43234 43235 bindings[ i ].setValue( array, offset ); 43236 43237 } 43238 43239 }, 43240 43241 bind: function () { 43242 43243 var bindings = this._bindings; 43244 43245 for ( var i = this._targetGroup.nCachedObjects_, 43246 n = bindings.length; i !== n; ++ i ) { 43247 43248 bindings[ i ].bind(); 43249 43250 } 43251 43252 }, 43253 43254 unbind: function () { 43255 43256 var bindings = this._bindings; 43257 43258 for ( var i = this._targetGroup.nCachedObjects_, 43259 n = bindings.length; i !== n; ++ i ) { 43260 43261 bindings[ i ].unbind(); 43262 43263 } 43264 43265 } 43266 43267 } ); 43268 43269 43270 function PropertyBinding( rootNode, path, parsedPath ) { 43271 43272 this.path = path; 43273 this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); 43274 43275 this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ) || rootNode; 43276 43277 this.rootNode = rootNode; 43278 43279 } 43280 43281 Object.assign( PropertyBinding, { 43282 43283 Composite: Composite, 43284 43285 create: function ( root, path, parsedPath ) { 43286 43287 if ( ! ( root && root.isAnimationObjectGroup ) ) { 43288 43289 return new PropertyBinding( root, path, parsedPath ); 43290 43291 } else { 43292 43293 return new PropertyBinding.Composite( root, path, parsedPath ); 43294 43295 } 43296 43297 }, 43298 43299 /** 43300 * Replaces spaces with underscores and removes unsupported characters from 43301 * node names, to ensure compatibility with parseTrackName(). 43302 * 43303 * @param {string} name Node name to be sanitized. 43304 * @return {string} 43305 */ 43306 sanitizeNodeName: ( function () { 43307 43308 var reservedRe = new RegExp( '[' + RESERVED_CHARS_RE + ']', 'g' ); 43309 43310 return function sanitizeNodeName( name ) { 43311 43312 return name.replace( /\s/g, '_' ).replace( reservedRe, '' ); 43313 43314 }; 43315 43316 }() ), 43317 43318 parseTrackName: function () { 43319 43320 // Attempts to allow node names from any language. ES5's `\w` regexp matches 43321 // only latin characters, and the unicode \p{L} is not yet supported. So 43322 // instead, we exclude reserved characters and match everything else. 43323 var wordChar = '[^' + RESERVED_CHARS_RE + ']'; 43324 var wordCharOrDot = '[^' + RESERVED_CHARS_RE.replace( '\\.', '' ) + ']'; 43325 43326 // Parent directories, delimited by '/' or ':'. Currently unused, but must 43327 // be matched to parse the rest of the track name. 43328 var directoryRe = /((?:WC+[\/:])*)/.source.replace( 'WC', wordChar ); 43329 43330 // Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. 43331 var nodeRe = /(WCOD+)?/.source.replace( 'WCOD', wordCharOrDot ); 43332 43333 // Object on target node, and accessor. May not contain reserved 43334 // characters. Accessor may contain any character except closing bracket. 43335 var objectRe = /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', wordChar ); 43336 43337 // Property and accessor. May not contain reserved characters. Accessor may 43338 // contain any non-bracket characters. 43339 var propertyRe = /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', wordChar ); 43340 43341 var trackRe = new RegExp( '' 43342 + '^' 43343 + directoryRe 43344 + nodeRe 43345 + objectRe 43346 + propertyRe 43347 + '$' 43348 ); 43349 43350 var supportedObjectNames = [ 'material', 'materials', 'bones' ]; 43351 43352 return function parseTrackName( trackName ) { 43353 43354 var matches = trackRe.exec( trackName ); 43355 43356 if ( ! matches ) { 43357 43358 throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); 43359 43360 } 43361 43362 var results = { 43363 // directoryName: matches[ 1 ], // (tschw) currently unused 43364 nodeName: matches[ 2 ], 43365 objectName: matches[ 3 ], 43366 objectIndex: matches[ 4 ], 43367 propertyName: matches[ 5 ], // required 43368 propertyIndex: matches[ 6 ] 43369 }; 43370 43371 var lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); 43372 43373 if ( lastDot !== undefined && lastDot !== - 1 ) { 43374 43375 var objectName = results.nodeName.substring( lastDot + 1 ); 43376 43377 // Object names must be checked against a whitelist. Otherwise, there 43378 // is no way to parse 'foo.bar.baz': 'baz' must be a property, but 43379 // 'bar' could be the objectName, or part of a nodeName (which can 43380 // include '.' characters). 43381 if ( supportedObjectNames.indexOf( objectName ) !== - 1 ) { 43382 43383 results.nodeName = results.nodeName.substring( 0, lastDot ); 43384 results.objectName = objectName; 43385 43386 } 43387 43388 } 43389 43390 if ( results.propertyName === null || results.propertyName.length === 0 ) { 43391 43392 throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); 43393 43394 } 43395 43396 return results; 43397 43398 }; 43399 43400 }(), 43401 43402 findNode: function ( root, nodeName ) { 43403 43404 if ( ! nodeName || nodeName === "" || nodeName === "root" || nodeName === "." || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { 43405 43406 return root; 43407 43408 } 43409 43410 // search into skeleton bones. 43411 if ( root.skeleton ) { 43412 43413 var bone = root.skeleton.getBoneByName( nodeName ); 43414 43415 if ( bone !== undefined ) { 43416 43417 return bone; 43418 43419 } 43420 43421 } 43422 43423 // search into node subtree. 43424 if ( root.children ) { 43425 43426 var searchNodeSubtree = function ( children ) { 43427 43428 for ( var i = 0; i < children.length; i ++ ) { 43429 43430 var childNode = children[ i ]; 43431 43432 if ( childNode.name === nodeName || childNode.uuid === nodeName ) { 43433 43434 return childNode; 43435 43436 } 43437 43438 var result = searchNodeSubtree( childNode.children ); 43439 43440 if ( result ) return result; 43441 43442 } 43443 43444 return null; 43445 43446 }; 43447 43448 var subTreeNode = searchNodeSubtree( root.children ); 43449 43450 if ( subTreeNode ) { 43451 43452 return subTreeNode; 43453 43454 } 43455 43456 } 43457 43458 return null; 43459 43460 } 43461 43462 } ); 43463 43464 Object.assign( PropertyBinding.prototype, { // prototype, continued 43465 43466 // these are used to "bind" a nonexistent property 43467 _getValue_unavailable: function () {}, 43468 _setValue_unavailable: function () {}, 43469 43470 BindingType: { 43471 Direct: 0, 43472 EntireArray: 1, 43473 ArrayElement: 2, 43474 HasFromToArray: 3 43475 }, 43476 43477 Versioning: { 43478 None: 0, 43479 NeedsUpdate: 1, 43480 MatrixWorldNeedsUpdate: 2 43481 }, 43482 43483 GetterByBindingType: [ 43484 43485 function getValue_direct( buffer, offset ) { 43486 43487 buffer[ offset ] = this.node[ this.propertyName ]; 43488 43489 }, 43490 43491 function getValue_array( buffer, offset ) { 43492 43493 var source = this.resolvedProperty; 43494 43495 for ( var i = 0, n = source.length; i !== n; ++ i ) { 43496 43497 buffer[ offset ++ ] = source[ i ]; 43498 43499 } 43500 43501 }, 43502 43503 function getValue_arrayElement( buffer, offset ) { 43504 43505 buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; 43506 43507 }, 43508 43509 function getValue_toArray( buffer, offset ) { 43510 43511 this.resolvedProperty.toArray( buffer, offset ); 43512 43513 } 43514 43515 ], 43516 43517 SetterByBindingTypeAndVersioning: [ 43518 43519 [ 43520 // Direct 43521 43522 function setValue_direct( buffer, offset ) { 43523 43524 this.targetObject[ this.propertyName ] = buffer[ offset ]; 43525 43526 }, 43527 43528 function setValue_direct_setNeedsUpdate( buffer, offset ) { 43529 43530 this.targetObject[ this.propertyName ] = buffer[ offset ]; 43531 this.targetObject.needsUpdate = true; 43532 43533 }, 43534 43535 function setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { 43536 43537 this.targetObject[ this.propertyName ] = buffer[ offset ]; 43538 this.targetObject.matrixWorldNeedsUpdate = true; 43539 43540 } 43541 43542 ], [ 43543 43544 // EntireArray 43545 43546 function setValue_array( buffer, offset ) { 43547 43548 var dest = this.resolvedProperty; 43549 43550 for ( var i = 0, n = dest.length; i !== n; ++ i ) { 43551 43552 dest[ i ] = buffer[ offset ++ ]; 43553 43554 } 43555 43556 }, 43557 43558 function setValue_array_setNeedsUpdate( buffer, offset ) { 43559 43560 var dest = this.resolvedProperty; 43561 43562 for ( var i = 0, n = dest.length; i !== n; ++ i ) { 43563 43564 dest[ i ] = buffer[ offset ++ ]; 43565 43566 } 43567 43568 this.targetObject.needsUpdate = true; 43569 43570 }, 43571 43572 function setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { 43573 43574 var dest = this.resolvedProperty; 43575 43576 for ( var i = 0, n = dest.length; i !== n; ++ i ) { 43577 43578 dest[ i ] = buffer[ offset ++ ]; 43579 43580 } 43581 43582 this.targetObject.matrixWorldNeedsUpdate = true; 43583 43584 } 43585 43586 ], [ 43587 43588 // ArrayElement 43589 43590 function setValue_arrayElement( buffer, offset ) { 43591 43592 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 43593 43594 }, 43595 43596 function setValue_arrayElement_setNeedsUpdate( buffer, offset ) { 43597 43598 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 43599 this.targetObject.needsUpdate = true; 43600 43601 }, 43602 43603 function setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { 43604 43605 this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; 43606 this.targetObject.matrixWorldNeedsUpdate = true; 43607 43608 } 43609 43610 ], [ 43611 43612 // HasToFromArray 43613 43614 function setValue_fromArray( buffer, offset ) { 43615 43616 this.resolvedProperty.fromArray( buffer, offset ); 43617 43618 }, 43619 43620 function setValue_fromArray_setNeedsUpdate( buffer, offset ) { 43621 43622 this.resolvedProperty.fromArray( buffer, offset ); 43623 this.targetObject.needsUpdate = true; 43624 43625 }, 43626 43627 function setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { 43628 43629 this.resolvedProperty.fromArray( buffer, offset ); 43630 this.targetObject.matrixWorldNeedsUpdate = true; 43631 43632 } 43633 43634 ] 43635 43636 ], 43637 43638 getValue: function getValue_unbound( targetArray, offset ) { 43639 43640 this.bind(); 43641 this.getValue( targetArray, offset ); 43642 43643 // Note: This class uses a State pattern on a per-method basis: 43644 // 'bind' sets 'this.getValue' / 'setValue' and shadows the 43645 // prototype version of these methods with one that represents 43646 // the bound state. When the property is not found, the methods 43647 // become no-ops. 43648 43649 }, 43650 43651 setValue: function getValue_unbound( sourceArray, offset ) { 43652 43653 this.bind(); 43654 this.setValue( sourceArray, offset ); 43655 43656 }, 43657 43658 // create getter / setter pair for a property in the scene graph 43659 bind: function () { 43660 43661 var targetObject = this.node, 43662 parsedPath = this.parsedPath, 43663 43664 objectName = parsedPath.objectName, 43665 propertyName = parsedPath.propertyName, 43666 propertyIndex = parsedPath.propertyIndex; 43667 43668 if ( ! targetObject ) { 43669 43670 targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ) || this.rootNode; 43671 43672 this.node = targetObject; 43673 43674 } 43675 43676 // set fail state so we can just 'return' on error 43677 this.getValue = this._getValue_unavailable; 43678 this.setValue = this._setValue_unavailable; 43679 43680 // ensure there is a value node 43681 if ( ! targetObject ) { 43682 43683 console.error( 'THREE.PropertyBinding: Trying to update node for track: ' + this.path + ' but it wasn\'t found.' ); 43684 return; 43685 43686 } 43687 43688 if ( objectName ) { 43689 43690 var objectIndex = parsedPath.objectIndex; 43691 43692 // special cases were we need to reach deeper into the hierarchy to get the face materials.... 43693 switch ( objectName ) { 43694 43695 case 'materials': 43696 43697 if ( ! targetObject.material ) { 43698 43699 console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); 43700 return; 43701 43702 } 43703 43704 if ( ! targetObject.material.materials ) { 43705 43706 console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); 43707 return; 43708 43709 } 43710 43711 targetObject = targetObject.material.materials; 43712 43713 break; 43714 43715 case 'bones': 43716 43717 if ( ! targetObject.skeleton ) { 43718 43719 console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); 43720 return; 43721 43722 } 43723 43724 // potential future optimization: skip this if propertyIndex is already an integer 43725 // and convert the integer string to a true integer. 43726 43727 targetObject = targetObject.skeleton.bones; 43728 43729 // support resolving morphTarget names into indices. 43730 for ( var i = 0; i < targetObject.length; i ++ ) { 43731 43732 if ( targetObject[ i ].name === objectIndex ) { 43733 43734 objectIndex = i; 43735 break; 43736 43737 } 43738 43739 } 43740 43741 break; 43742 43743 default: 43744 43745 if ( targetObject[ objectName ] === undefined ) { 43746 43747 console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); 43748 return; 43749 43750 } 43751 43752 targetObject = targetObject[ objectName ]; 43753 43754 } 43755 43756 43757 if ( objectIndex !== undefined ) { 43758 43759 if ( targetObject[ objectIndex ] === undefined ) { 43760 43761 console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); 43762 return; 43763 43764 } 43765 43766 targetObject = targetObject[ objectIndex ]; 43767 43768 } 43769 43770 } 43771 43772 // resolve property 43773 var nodeProperty = targetObject[ propertyName ]; 43774 43775 if ( nodeProperty === undefined ) { 43776 43777 var nodeName = parsedPath.nodeName; 43778 43779 console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + 43780 '.' + propertyName + ' but it wasn\'t found.', targetObject ); 43781 return; 43782 43783 } 43784 43785 // determine versioning scheme 43786 var versioning = this.Versioning.None; 43787 43788 if ( targetObject.needsUpdate !== undefined ) { // material 43789 43790 versioning = this.Versioning.NeedsUpdate; 43791 this.targetObject = targetObject; 43792 43793 } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform 43794 43795 versioning = this.Versioning.MatrixWorldNeedsUpdate; 43796 this.targetObject = targetObject; 43797 43798 } 43799 43800 // determine how the property gets bound 43801 var bindingType = this.BindingType.Direct; 43802 43803 if ( propertyIndex !== undefined ) { 43804 43805 // access a sub element of the property array (only primitives are supported right now) 43806 43807 if ( propertyName === "morphTargetInfluences" ) { 43808 43809 // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. 43810 43811 // support resolving morphTarget names into indices. 43812 if ( ! targetObject.geometry ) { 43813 43814 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); 43815 return; 43816 43817 } 43818 43819 if ( targetObject.geometry.isBufferGeometry ) { 43820 43821 if ( ! targetObject.geometry.morphAttributes ) { 43822 43823 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); 43824 return; 43825 43826 } 43827 43828 for ( var i = 0; i < this.node.geometry.morphAttributes.position.length; i ++ ) { 43829 43830 if ( targetObject.geometry.morphAttributes.position[ i ].name === propertyIndex ) { 43831 43832 propertyIndex = i; 43833 break; 43834 43835 } 43836 43837 } 43838 43839 43840 } else { 43841 43842 if ( ! targetObject.geometry.morphTargets ) { 43843 43844 console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphTargets.', this ); 43845 return; 43846 43847 } 43848 43849 for ( var i = 0; i < this.node.geometry.morphTargets.length; i ++ ) { 43850 43851 if ( targetObject.geometry.morphTargets[ i ].name === propertyIndex ) { 43852 43853 propertyIndex = i; 43854 break; 43855 43856 } 43857 43858 } 43859 43860 } 43861 43862 } 43863 43864 bindingType = this.BindingType.ArrayElement; 43865 43866 this.resolvedProperty = nodeProperty; 43867 this.propertyIndex = propertyIndex; 43868 43869 } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { 43870 43871 // must use copy for Object3D.Euler/Quaternion 43872 43873 bindingType = this.BindingType.HasFromToArray; 43874 43875 this.resolvedProperty = nodeProperty; 43876 43877 } else if ( Array.isArray( nodeProperty ) ) { 43878 43879 bindingType = this.BindingType.EntireArray; 43880 43881 this.resolvedProperty = nodeProperty; 43882 43883 } else { 43884 43885 this.propertyName = propertyName; 43886 43887 } 43888 43889 // select getter / setter 43890 this.getValue = this.GetterByBindingType[ bindingType ]; 43891 this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; 43892 43893 }, 43894 43895 unbind: function () { 43896 43897 this.node = null; 43898 43899 // back to the prototype version of getValue / setValue 43900 // note: avoiding to mutate the shape of 'this' via 'delete' 43901 this.getValue = this._getValue_unbound; 43902 this.setValue = this._setValue_unbound; 43903 43904 } 43905 43906 } ); 43907 43908 //!\ DECLARE ALIAS AFTER assign prototype ! 43909 Object.assign( PropertyBinding.prototype, { 43910 43911 // initial state of these methods that calls 'bind' 43912 _getValue_unbound: PropertyBinding.prototype.getValue, 43913 _setValue_unbound: PropertyBinding.prototype.setValue, 43914 43915 } ); 43916 43917 /** 43918 * 43919 * A group of objects that receives a shared animation state. 43920 * 43921 * Usage: 43922 * 43923 * - Add objects you would otherwise pass as 'root' to the 43924 * constructor or the .clipAction method of AnimationMixer. 43925 * 43926 * - Instead pass this object as 'root'. 43927 * 43928 * - You can also add and remove objects later when the mixer 43929 * is running. 43930 * 43931 * Note: 43932 * 43933 * Objects of this class appear as one object to the mixer, 43934 * so cache control of the individual objects must be done 43935 * on the group. 43936 * 43937 * Limitation: 43938 * 43939 * - The animated properties must be compatible among the 43940 * all objects in the group. 43941 * 43942 * - A single property can either be controlled through a 43943 * target group or directly, but not both. 43944 * 43945 * @author tschw 43946 */ 43947 43948 function AnimationObjectGroup() { 43949 43950 this.uuid = _Math.generateUUID(); 43951 43952 // cached objects followed by the active ones 43953 this._objects = Array.prototype.slice.call( arguments ); 43954 43955 this.nCachedObjects_ = 0; // threshold 43956 // note: read by PropertyBinding.Composite 43957 43958 var indices = {}; 43959 this._indicesByUUID = indices; // for bookkeeping 43960 43961 for ( var i = 0, n = arguments.length; i !== n; ++ i ) { 43962 43963 indices[ arguments[ i ].uuid ] = i; 43964 43965 } 43966 43967 this._paths = []; // inside: string 43968 this._parsedPaths = []; // inside: { we don't care, here } 43969 this._bindings = []; // inside: Array< PropertyBinding > 43970 this._bindingsIndicesByPath = {}; // inside: indices in these arrays 43971 43972 var scope = this; 43973 43974 this.stats = { 43975 43976 objects: { 43977 get total() { 43978 43979 return scope._objects.length; 43980 43981 }, 43982 get inUse() { 43983 43984 return this.total - scope.nCachedObjects_; 43985 43986 } 43987 }, 43988 get bindingsPerObject() { 43989 43990 return scope._bindings.length; 43991 43992 } 43993 43994 }; 43995 43996 } 43997 43998 Object.assign( AnimationObjectGroup.prototype, { 43999 44000 isAnimationObjectGroup: true, 44001 44002 add: function () { 44003 44004 var objects = this._objects, 44005 nObjects = objects.length, 44006 nCachedObjects = this.nCachedObjects_, 44007 indicesByUUID = this._indicesByUUID, 44008 paths = this._paths, 44009 parsedPaths = this._parsedPaths, 44010 bindings = this._bindings, 44011 nBindings = bindings.length, 44012 knownObject = undefined; 44013 44014 for ( var i = 0, n = arguments.length; i !== n; ++ i ) { 44015 44016 var object = arguments[ i ], 44017 uuid = object.uuid, 44018 index = indicesByUUID[ uuid ]; 44019 44020 if ( index === undefined ) { 44021 44022 // unknown object -> add it to the ACTIVE region 44023 44024 index = nObjects ++; 44025 indicesByUUID[ uuid ] = index; 44026 objects.push( object ); 44027 44028 // accounting is done, now do the same for all bindings 44029 44030 for ( var j = 0, m = nBindings; j !== m; ++ j ) { 44031 44032 bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); 44033 44034 } 44035 44036 } else if ( index < nCachedObjects ) { 44037 44038 knownObject = objects[ index ]; 44039 44040 // move existing object to the ACTIVE region 44041 44042 var firstActiveIndex = -- nCachedObjects, 44043 lastCachedObject = objects[ firstActiveIndex ]; 44044 44045 indicesByUUID[ lastCachedObject.uuid ] = index; 44046 objects[ index ] = lastCachedObject; 44047 44048 indicesByUUID[ uuid ] = firstActiveIndex; 44049 objects[ firstActiveIndex ] = object; 44050 44051 // accounting is done, now do the same for all bindings 44052 44053 for ( var j = 0, m = nBindings; j !== m; ++ j ) { 44054 44055 var bindingsForPath = bindings[ j ], 44056 lastCached = bindingsForPath[ firstActiveIndex ], 44057 binding = bindingsForPath[ index ]; 44058 44059 bindingsForPath[ index ] = lastCached; 44060 44061 if ( binding === undefined ) { 44062 44063 // since we do not bother to create new bindings 44064 // for objects that are cached, the binding may 44065 // or may not exist 44066 44067 binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); 44068 44069 } 44070 44071 bindingsForPath[ firstActiveIndex ] = binding; 44072 44073 } 44074 44075 } else if ( objects[ index ] !== knownObject ) { 44076 44077 console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' + 44078 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); 44079 44080 } // else the object is already where we want it to be 44081 44082 } // for arguments 44083 44084 this.nCachedObjects_ = nCachedObjects; 44085 44086 }, 44087 44088 remove: function () { 44089 44090 var objects = this._objects, 44091 nCachedObjects = this.nCachedObjects_, 44092 indicesByUUID = this._indicesByUUID, 44093 bindings = this._bindings, 44094 nBindings = bindings.length; 44095 44096 for ( var i = 0, n = arguments.length; i !== n; ++ i ) { 44097 44098 var object = arguments[ i ], 44099 uuid = object.uuid, 44100 index = indicesByUUID[ uuid ]; 44101 44102 if ( index !== undefined && index >= nCachedObjects ) { 44103 44104 // move existing object into the CACHED region 44105 44106 var lastCachedIndex = nCachedObjects ++, 44107 firstActiveObject = objects[ lastCachedIndex ]; 44108 44109 indicesByUUID[ firstActiveObject.uuid ] = index; 44110 objects[ index ] = firstActiveObject; 44111 44112 indicesByUUID[ uuid ] = lastCachedIndex; 44113 objects[ lastCachedIndex ] = object; 44114 44115 // accounting is done, now do the same for all bindings 44116 44117 for ( var j = 0, m = nBindings; j !== m; ++ j ) { 44118 44119 var bindingsForPath = bindings[ j ], 44120 firstActive = bindingsForPath[ lastCachedIndex ], 44121 binding = bindingsForPath[ index ]; 44122 44123 bindingsForPath[ index ] = firstActive; 44124 bindingsForPath[ lastCachedIndex ] = binding; 44125 44126 } 44127 44128 } 44129 44130 } // for arguments 44131 44132 this.nCachedObjects_ = nCachedObjects; 44133 44134 }, 44135 44136 // remove & forget 44137 uncache: function () { 44138 44139 var objects = this._objects, 44140 nObjects = objects.length, 44141 nCachedObjects = this.nCachedObjects_, 44142 indicesByUUID = this._indicesByUUID, 44143 bindings = this._bindings, 44144 nBindings = bindings.length; 44145 44146 for ( var i = 0, n = arguments.length; i !== n; ++ i ) { 44147 44148 var object = arguments[ i ], 44149 uuid = object.uuid, 44150 index = indicesByUUID[ uuid ]; 44151 44152 if ( index !== undefined ) { 44153 44154 delete indicesByUUID[ uuid ]; 44155 44156 if ( index < nCachedObjects ) { 44157 44158 // object is cached, shrink the CACHED region 44159 44160 var firstActiveIndex = -- nCachedObjects, 44161 lastCachedObject = objects[ firstActiveIndex ], 44162 lastIndex = -- nObjects, 44163 lastObject = objects[ lastIndex ]; 44164 44165 // last cached object takes this object's place 44166 indicesByUUID[ lastCachedObject.uuid ] = index; 44167 objects[ index ] = lastCachedObject; 44168 44169 // last object goes to the activated slot and pop 44170 indicesByUUID[ lastObject.uuid ] = firstActiveIndex; 44171 objects[ firstActiveIndex ] = lastObject; 44172 objects.pop(); 44173 44174 // accounting is done, now do the same for all bindings 44175 44176 for ( var j = 0, m = nBindings; j !== m; ++ j ) { 44177 44178 var bindingsForPath = bindings[ j ], 44179 lastCached = bindingsForPath[ firstActiveIndex ], 44180 last = bindingsForPath[ lastIndex ]; 44181 44182 bindingsForPath[ index ] = lastCached; 44183 bindingsForPath[ firstActiveIndex ] = last; 44184 bindingsForPath.pop(); 44185 44186 } 44187 44188 } else { 44189 44190 // object is active, just swap with the last and pop 44191 44192 var lastIndex = -- nObjects, 44193 lastObject = objects[ lastIndex ]; 44194 44195 indicesByUUID[ lastObject.uuid ] = index; 44196 objects[ index ] = lastObject; 44197 objects.pop(); 44198 44199 // accounting is done, now do the same for all bindings 44200 44201 for ( var j = 0, m = nBindings; j !== m; ++ j ) { 44202 44203 var bindingsForPath = bindings[ j ]; 44204 44205 bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; 44206 bindingsForPath.pop(); 44207 44208 } 44209 44210 } // cached or active 44211 44212 } // if object is known 44213 44214 } // for arguments 44215 44216 this.nCachedObjects_ = nCachedObjects; 44217 44218 }, 44219 44220 // Internal interface used by befriended PropertyBinding.Composite: 44221 44222 subscribe_: function ( path, parsedPath ) { 44223 44224 // returns an array of bindings for the given path that is changed 44225 // according to the contained objects in the group 44226 44227 var indicesByPath = this._bindingsIndicesByPath, 44228 index = indicesByPath[ path ], 44229 bindings = this._bindings; 44230 44231 if ( index !== undefined ) return bindings[ index ]; 44232 44233 var paths = this._paths, 44234 parsedPaths = this._parsedPaths, 44235 objects = this._objects, 44236 nObjects = objects.length, 44237 nCachedObjects = this.nCachedObjects_, 44238 bindingsForPath = new Array( nObjects ); 44239 44240 index = bindings.length; 44241 44242 indicesByPath[ path ] = index; 44243 44244 paths.push( path ); 44245 parsedPaths.push( parsedPath ); 44246 bindings.push( bindingsForPath ); 44247 44248 for ( var i = nCachedObjects, n = objects.length; i !== n; ++ i ) { 44249 44250 var object = objects[ i ]; 44251 bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); 44252 44253 } 44254 44255 return bindingsForPath; 44256 44257 }, 44258 44259 unsubscribe_: function ( path ) { 44260 44261 // tells the group to forget about a property path and no longer 44262 // update the array previously obtained with 'subscribe_' 44263 44264 var indicesByPath = this._bindingsIndicesByPath, 44265 index = indicesByPath[ path ]; 44266 44267 if ( index !== undefined ) { 44268 44269 var paths = this._paths, 44270 parsedPaths = this._parsedPaths, 44271 bindings = this._bindings, 44272 lastBindingsIndex = bindings.length - 1, 44273 lastBindings = bindings[ lastBindingsIndex ], 44274 lastBindingsPath = path[ lastBindingsIndex ]; 44275 44276 indicesByPath[ lastBindingsPath ] = index; 44277 44278 bindings[ index ] = lastBindings; 44279 bindings.pop(); 44280 44281 parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; 44282 parsedPaths.pop(); 44283 44284 paths[ index ] = paths[ lastBindingsIndex ]; 44285 paths.pop(); 44286 44287 } 44288 44289 } 44290 44291 } ); 44292 44293 /** 44294 * 44295 * Action provided by AnimationMixer for scheduling clip playback on specific 44296 * objects. 44297 * 44298 * @author Ben Houston / http://clara.io/ 44299 * @author David Sarno / http://lighthaus.us/ 44300 * @author tschw 44301 * 44302 */ 44303 44304 function AnimationAction( mixer, clip, localRoot ) { 44305 44306 this._mixer = mixer; 44307 this._clip = clip; 44308 this._localRoot = localRoot || null; 44309 44310 var tracks = clip.tracks, 44311 nTracks = tracks.length, 44312 interpolants = new Array( nTracks ); 44313 44314 var interpolantSettings = { 44315 endingStart: ZeroCurvatureEnding, 44316 endingEnd: ZeroCurvatureEnding 44317 }; 44318 44319 for ( var i = 0; i !== nTracks; ++ i ) { 44320 44321 var interpolant = tracks[ i ].createInterpolant( null ); 44322 interpolants[ i ] = interpolant; 44323 interpolant.settings = interpolantSettings; 44324 44325 } 44326 44327 this._interpolantSettings = interpolantSettings; 44328 44329 this._interpolants = interpolants; // bound by the mixer 44330 44331 // inside: PropertyMixer (managed by the mixer) 44332 this._propertyBindings = new Array( nTracks ); 44333 44334 this._cacheIndex = null; // for the memory manager 44335 this._byClipCacheIndex = null; // for the memory manager 44336 44337 this._timeScaleInterpolant = null; 44338 this._weightInterpolant = null; 44339 44340 this.loop = LoopRepeat; 44341 this._loopCount = - 1; 44342 44343 // global mixer time when the action is to be started 44344 // it's set back to 'null' upon start of the action 44345 this._startTime = null; 44346 44347 // scaled local time of the action 44348 // gets clamped or wrapped to 0..clip.duration according to loop 44349 this.time = 0; 44350 44351 this.timeScale = 1; 44352 this._effectiveTimeScale = 1; 44353 44354 this.weight = 1; 44355 this._effectiveWeight = 1; 44356 44357 this.repetitions = Infinity; // no. of repetitions when looping 44358 44359 this.paused = false; // true -> zero effective time scale 44360 this.enabled = true; // false -> zero effective weight 44361 44362 this.clampWhenFinished = false; // keep feeding the last frame? 44363 44364 this.zeroSlopeAtStart = true; // for smooth interpolation w/o separate 44365 this.zeroSlopeAtEnd = true; // clips for start, loop and end 44366 44367 } 44368 44369 Object.assign( AnimationAction.prototype, { 44370 44371 // State & Scheduling 44372 44373 play: function () { 44374 44375 this._mixer._activateAction( this ); 44376 44377 return this; 44378 44379 }, 44380 44381 stop: function () { 44382 44383 this._mixer._deactivateAction( this ); 44384 44385 return this.reset(); 44386 44387 }, 44388 44389 reset: function () { 44390 44391 this.paused = false; 44392 this.enabled = true; 44393 44394 this.time = 0; // restart clip 44395 this._loopCount = - 1; // forget previous loops 44396 this._startTime = null; // forget scheduling 44397 44398 return this.stopFading().stopWarping(); 44399 44400 }, 44401 44402 isRunning: function () { 44403 44404 return this.enabled && ! this.paused && this.timeScale !== 0 && 44405 this._startTime === null && this._mixer._isActiveAction( this ); 44406 44407 }, 44408 44409 // return true when play has been called 44410 isScheduled: function () { 44411 44412 return this._mixer._isActiveAction( this ); 44413 44414 }, 44415 44416 startAt: function ( time ) { 44417 44418 this._startTime = time; 44419 44420 return this; 44421 44422 }, 44423 44424 setLoop: function ( mode, repetitions ) { 44425 44426 this.loop = mode; 44427 this.repetitions = repetitions; 44428 44429 return this; 44430 44431 }, 44432 44433 // Weight 44434 44435 // set the weight stopping any scheduled fading 44436 // although .enabled = false yields an effective weight of zero, this 44437 // method does *not* change .enabled, because it would be confusing 44438 setEffectiveWeight: function ( weight ) { 44439 44440 this.weight = weight; 44441 44442 // note: same logic as when updated at runtime 44443 this._effectiveWeight = this.enabled ? weight : 0; 44444 44445 return this.stopFading(); 44446 44447 }, 44448 44449 // return the weight considering fading and .enabled 44450 getEffectiveWeight: function () { 44451 44452 return this._effectiveWeight; 44453 44454 }, 44455 44456 fadeIn: function ( duration ) { 44457 44458 return this._scheduleFading( duration, 0, 1 ); 44459 44460 }, 44461 44462 fadeOut: function ( duration ) { 44463 44464 return this._scheduleFading( duration, 1, 0 ); 44465 44466 }, 44467 44468 crossFadeFrom: function ( fadeOutAction, duration, warp ) { 44469 44470 fadeOutAction.fadeOut( duration ); 44471 this.fadeIn( duration ); 44472 44473 if ( warp ) { 44474 44475 var fadeInDuration = this._clip.duration, 44476 fadeOutDuration = fadeOutAction._clip.duration, 44477 44478 startEndRatio = fadeOutDuration / fadeInDuration, 44479 endStartRatio = fadeInDuration / fadeOutDuration; 44480 44481 fadeOutAction.warp( 1.0, startEndRatio, duration ); 44482 this.warp( endStartRatio, 1.0, duration ); 44483 44484 } 44485 44486 return this; 44487 44488 }, 44489 44490 crossFadeTo: function ( fadeInAction, duration, warp ) { 44491 44492 return fadeInAction.crossFadeFrom( this, duration, warp ); 44493 44494 }, 44495 44496 stopFading: function () { 44497 44498 var weightInterpolant = this._weightInterpolant; 44499 44500 if ( weightInterpolant !== null ) { 44501 44502 this._weightInterpolant = null; 44503 this._mixer._takeBackControlInterpolant( weightInterpolant ); 44504 44505 } 44506 44507 return this; 44508 44509 }, 44510 44511 // Time Scale Control 44512 44513 // set the time scale stopping any scheduled warping 44514 // although .paused = true yields an effective time scale of zero, this 44515 // method does *not* change .paused, because it would be confusing 44516 setEffectiveTimeScale: function ( timeScale ) { 44517 44518 this.timeScale = timeScale; 44519 this._effectiveTimeScale = this.paused ? 0 : timeScale; 44520 44521 return this.stopWarping(); 44522 44523 }, 44524 44525 // return the time scale considering warping and .paused 44526 getEffectiveTimeScale: function () { 44527 44528 return this._effectiveTimeScale; 44529 44530 }, 44531 44532 setDuration: function ( duration ) { 44533 44534 this.timeScale = this._clip.duration / duration; 44535 44536 return this.stopWarping(); 44537 44538 }, 44539 44540 syncWith: function ( action ) { 44541 44542 this.time = action.time; 44543 this.timeScale = action.timeScale; 44544 44545 return this.stopWarping(); 44546 44547 }, 44548 44549 halt: function ( duration ) { 44550 44551 return this.warp( this._effectiveTimeScale, 0, duration ); 44552 44553 }, 44554 44555 warp: function ( startTimeScale, endTimeScale, duration ) { 44556 44557 var mixer = this._mixer, now = mixer.time, 44558 interpolant = this._timeScaleInterpolant, 44559 44560 timeScale = this.timeScale; 44561 44562 if ( interpolant === null ) { 44563 44564 interpolant = mixer._lendControlInterpolant(); 44565 this._timeScaleInterpolant = interpolant; 44566 44567 } 44568 44569 var times = interpolant.parameterPositions, 44570 values = interpolant.sampleValues; 44571 44572 times[ 0 ] = now; 44573 times[ 1 ] = now + duration; 44574 44575 values[ 0 ] = startTimeScale / timeScale; 44576 values[ 1 ] = endTimeScale / timeScale; 44577 44578 return this; 44579 44580 }, 44581
vendor: 4,213 bytes, lines 44582-44817
44582 stopWarping: function () { 44583 44584 var timeScaleInterpolant = this._timeScaleInterpolant; 44585 44586 if ( timeScaleInterpolant !== null ) { 44587 44588 this._timeScaleInterpolant = null; 44589 this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); 44590 44591 } 44592 44593 return this; 44594 44595 }, 44596 44597 // Object Accessors 44598 44599 getMixer: function () { 44600 44601 return this._mixer; 44602 44603 }, 44604 44605 getClip: function () { 44606 44607 return this._clip; 44608 44609 }, 44610 44611 getRoot: function () { 44612 44613 return this._localRoot || this._mixer._root; 44614 44615 }, 44616 44617 // Interna 44618 44619 _update: function ( time, deltaTime, timeDirection, accuIndex ) { 44620 44621 // called by the mixer 44622 44623 if ( ! this.enabled ) { 44624 44625 // call ._updateWeight() to update ._effectiveWeight 44626 44627 this._updateWeight( time ); 44628 return; 44629 44630 } 44631 44632 var startTime = this._startTime; 44633 44634 if ( startTime !== null ) { 44635 44636 // check for scheduled start of action 44637 44638 var timeRunning = ( time - startTime ) * timeDirection; 44639 if ( timeRunning < 0 || timeDirection === 0 ) { 44640 44641 return; // yet to come / don't decide when delta = 0 44642 44643 } 44644 44645 // start 44646 44647 this._startTime = null; // unschedule 44648 deltaTime = timeDirection * timeRunning; 44649 44650 } 44651 44652 // apply time scale and advance time 44653 44654 deltaTime *= this._updateTimeScale( time ); 44655 var clipTime = this._updateTime( deltaTime ); 44656 44657 // note: _updateTime may disable the action resulting in 44658 // an effective weight of 0 44659 44660 var weight = this._updateWeight( time ); 44661 44662 if ( weight > 0 ) { 44663 44664 var interpolants = this._interpolants; 44665 var propertyMixers = this._propertyBindings; 44666 44667 for ( var j = 0, m = interpolants.length; j !== m; ++ j ) { 44668 44669 interpolants[ j ].evaluate( clipTime ); 44670 propertyMixers[ j ].accumulate( accuIndex, weight ); 44671 44672 } 44673 44674 } 44675 44676 }, 44677 44678 _updateWeight: function ( time ) { 44679 44680 var weight = 0; 44681 44682 if ( this.enabled ) { 44683 44684 weight = this.weight; 44685 var interpolant = this._weightInterpolant; 44686 44687 if ( interpolant !== null ) { 44688 44689 var interpolantValue = interpolant.evaluate( time )[ 0 ]; 44690 44691 weight *= interpolantValue; 44692 44693 if ( time > interpolant.parameterPositions[ 1 ] ) { 44694 44695 this.stopFading(); 44696 44697 if ( interpolantValue === 0 ) { 44698 44699 // faded out, disable 44700 this.enabled = false; 44701 44702 } 44703 44704 } 44705 44706 } 44707 44708 } 44709 44710 this._effectiveWeight = weight; 44711 return weight; 44712 44713 }, 44714 44715 _updateTimeScale: function ( time ) { 44716 44717 var timeScale = 0; 44718 44719 if ( ! this.paused ) { 44720 44721 timeScale = this.timeScale; 44722 44723 var interpolant = this._timeScaleInterpolant; 44724 44725 if ( interpolant !== null ) { 44726 44727 var interpolantValue = interpolant.evaluate( time )[ 0 ]; 44728 44729 timeScale *= interpolantValue; 44730 44731 if ( time > interpolant.parameterPositions[ 1 ] ) { 44732 44733 this.stopWarping(); 44734 44735 if ( timeScale === 0 ) { 44736 44737 // motion has halted, pause 44738 this.paused = true; 44739 44740 } else { 44741 44742 // warp done - apply final time scale 44743 this.timeScale = timeScale; 44744 44745 } 44746 44747 } 44748 44749 } 44750 44751 } 44752 44753 this._effectiveTimeScale = timeScale; 44754 return timeScale; 44755 44756 }, 44757 44758 _updateTime: function ( deltaTime ) { 44759 44760 var time = this.time + deltaTime; 44761 44762 if ( deltaTime === 0 ) return time; 44763 44764 var duration = this._clip.duration, 44765 44766 loop = this.loop, 44767 loopCount = this._loopCount; 44768 44769 if ( loop === LoopOnce ) { 44770 44771 if ( loopCount === - 1 ) { 44772 44773 // just started 44774 44775 this._loopCount = 0; 44776 this._setEndings( true, true, false ); 44777 44778 } 44779 44780 handle_stop: { 44781 44782 if ( time >= duration ) { 44783 44784 time = duration; 44785 44786 } else if ( time < 0 ) { 44787 44788 time = 0; 44789 44790 } else break handle_stop; 44791 44792 if ( this.clampWhenFinished ) this.paused = true; 44793 else this.enabled = false; 44794 44795 this._mixer.dispatchEvent( { 44796 type: 'finished', action: this, 44797 direction: deltaTime < 0 ? - 1 : 1 44798 } ); 44799 44800 } 44801 44802 } else { // repetitive Repeat or PingPong 44803 44804 var pingPong = ( loop === LoopPingPong ); 44805 44806 if ( loopCount === - 1 ) { 44807 44808 // just started 44809 44810 if ( deltaTime >= 0 ) { 44811 44812 loopCount = 0; 44813 44814 this._setEndings( true, this.repetitions === 0, pingPong ); 44815 44816 } else { 44817
vendor: 8,768 bytes, lines 44818-45246
44818 // when looping in reverse direction, the initial 44819 // transition through zero counts as a repetition, 44820 // so leave loopCount at -1 44821 44822 this._setEndings( this.repetitions === 0, true, pingPong ); 44823 44824 } 44825 44826 } 44827 44828 if ( time >= duration || time < 0 ) { 44829 44830 // wrap around 44831 44832 var loopDelta = Math.floor( time / duration ); // signed 44833 time -= duration * loopDelta; 44834 44835 loopCount += Math.abs( loopDelta ); 44836 44837 var pending = this.repetitions - loopCount; 44838 44839 if ( pending <= 0 ) { 44840 44841 // have to stop (switch state, clamp time, fire event) 44842 44843 if ( this.clampWhenFinished ) this.paused = true; 44844 else this.enabled = false; 44845 44846 time = deltaTime > 0 ? duration : 0; 44847 44848 this._mixer.dispatchEvent( { 44849 type: 'finished', action: this, 44850 direction: deltaTime > 0 ? 1 : - 1 44851 } ); 44852 44853 } else { 44854 44855 // keep running 44856 44857 if ( pending === 1 ) { 44858 44859 // entering the last round 44860 44861 var atStart = deltaTime < 0; 44862 this._setEndings( atStart, ! atStart, pingPong ); 44863 44864 } else { 44865 44866 this._setEndings( false, false, pingPong ); 44867 44868 } 44869 44870 this._loopCount = loopCount; 44871 44872 this._mixer.dispatchEvent( { 44873 type: 'loop', action: this, loopDelta: loopDelta 44874 } ); 44875 44876 } 44877 44878 } 44879 44880 if ( pingPong && ( loopCount & 1 ) === 1 ) { 44881 44882 // invert time for the "pong round" 44883 44884 this.time = time; 44885 return duration - time; 44886 44887 } 44888 44889 } 44890 44891 this.time = time; 44892 return time; 44893 44894 }, 44895 44896 _setEndings: function ( atStart, atEnd, pingPong ) { 44897 44898 var settings = this._interpolantSettings; 44899 44900 if ( pingPong ) { 44901 44902 settings.endingStart = ZeroSlopeEnding; 44903 settings.endingEnd = ZeroSlopeEnding; 44904 44905 } else { 44906 44907 // assuming for LoopOnce atStart == atEnd == true 44908 44909 if ( atStart ) { 44910 44911 settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; 44912 44913 } else { 44914 44915 settings.endingStart = WrapAroundEnding; 44916 44917 } 44918 44919 if ( atEnd ) { 44920 44921 settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; 44922 44923 } else { 44924 44925 settings.endingEnd = WrapAroundEnding; 44926 44927 } 44928 44929 } 44930 44931 }, 44932 44933 _scheduleFading: function ( duration, weightNow, weightThen ) { 44934 44935 var mixer = this._mixer, now = mixer.time, 44936 interpolant = this._weightInterpolant; 44937 44938 if ( interpolant === null ) { 44939 44940 interpolant = mixer._lendControlInterpolant(); 44941 this._weightInterpolant = interpolant; 44942 44943 } 44944 44945 var times = interpolant.parameterPositions, 44946 values = interpolant.sampleValues; 44947 44948 times[ 0 ] = now; values[ 0 ] = weightNow; 44949 times[ 1 ] = now + duration; values[ 1 ] = weightThen; 44950 44951 return this; 44952 44953 } 44954 44955 } ); 44956 44957 /** 44958 * 44959 * Player for AnimationClips. 44960 * 44961 * 44962 * @author Ben Houston / http://clara.io/ 44963 * @author David Sarno / http://lighthaus.us/ 44964 * @author tschw 44965 */ 44966 44967 function AnimationMixer( root ) { 44968 44969 this._root = root; 44970 this._initMemoryManager(); 44971 this._accuIndex = 0; 44972 44973 this.time = 0; 44974 44975 this.timeScale = 1.0; 44976 44977 } 44978 44979 AnimationMixer.prototype = Object.assign( Object.create( EventDispatcher.prototype ), { 44980 44981 constructor: AnimationMixer, 44982 44983 _bindAction: function ( action, prototypeAction ) { 44984 44985 var root = action._localRoot || this._root, 44986 tracks = action._clip.tracks, 44987 nTracks = tracks.length, 44988 bindings = action._propertyBindings, 44989 interpolants = action._interpolants, 44990 rootUuid = root.uuid, 44991 bindingsByRoot = this._bindingsByRootAndName, 44992 bindingsByName = bindingsByRoot[ rootUuid ]; 44993 44994 if ( bindingsByName === undefined ) { 44995 44996 bindingsByName = {}; 44997 bindingsByRoot[ rootUuid ] = bindingsByName; 44998 44999 } 45000 45001 for ( var i = 0; i !== nTracks; ++ i ) { 45002 45003 var track = tracks[ i ], 45004 trackName = track.name, 45005 binding = bindingsByName[ trackName ]; 45006 45007 if ( binding !== undefined ) { 45008 45009 bindings[ i ] = binding; 45010 45011 } else { 45012 45013 binding = bindings[ i ]; 45014 45015 if ( binding !== undefined ) { 45016 45017 // existing binding, make sure the cache knows 45018 45019 if ( binding._cacheIndex === null ) { 45020 45021 ++ binding.referenceCount; 45022 this._addInactiveBinding( binding, rootUuid, trackName ); 45023 45024 } 45025 45026 continue; 45027 45028 } 45029 45030 var path = prototypeAction && prototypeAction. 45031 _propertyBindings[ i ].binding.parsedPath; 45032 45033 binding = new PropertyMixer( 45034 PropertyBinding.create( root, trackName, path ), 45035 track.ValueTypeName, track.getValueSize() ); 45036 45037 ++ binding.referenceCount; 45038 this._addInactiveBinding( binding, rootUuid, trackName ); 45039 45040 bindings[ i ] = binding; 45041 45042 } 45043 45044 interpolants[ i ].resultBuffer = binding.buffer; 45045 45046 } 45047 45048 }, 45049 45050 _activateAction: function ( action ) { 45051 45052 if ( ! this._isActiveAction( action ) ) { 45053 45054 if ( action._cacheIndex === null ) { 45055 45056 // this action has been forgotten by the cache, but the user 45057 // appears to be still using it -> rebind 45058 45059 var rootUuid = ( action._localRoot || this._root ).uuid, 45060 clipUuid = action._clip.uuid, 45061 actionsForClip = this._actionsByClip[ clipUuid ]; 45062 45063 this._bindAction( action, 45064 actionsForClip && actionsForClip.knownActions[ 0 ] ); 45065 45066 this._addInactiveAction( action, clipUuid, rootUuid ); 45067 45068 } 45069 45070 var bindings = action._propertyBindings; 45071 45072 // increment reference counts / sort out state 45073 for ( var i = 0, n = bindings.length; i !== n; ++ i ) { 45074 45075 var binding = bindings[ i ]; 45076 45077 if ( binding.useCount ++ === 0 ) { 45078 45079 this._lendBinding( binding ); 45080 binding.saveOriginalState(); 45081 45082 } 45083 45084 } 45085 45086 this._lendAction( action ); 45087 45088 } 45089 45090 }, 45091 45092 _deactivateAction: function ( action ) { 45093 45094 if ( this._isActiveAction( action ) ) { 45095 45096 var bindings = action._propertyBindings; 45097 45098 // decrement reference counts / sort out state 45099 for ( var i = 0, n = bindings.length; i !== n; ++ i ) { 45100 45101 var binding = bindings[ i ]; 45102 45103 if ( -- binding.useCount === 0 ) { 45104 45105 binding.restoreOriginalState(); 45106 this._takeBackBinding( binding ); 45107 45108 } 45109 45110 } 45111 45112 this._takeBackAction( action ); 45113 45114 } 45115 45116 }, 45117 45118 // Memory manager 45119 45120 _initMemoryManager: function () { 45121 45122 this._actions = []; // 'nActiveActions' followed by inactive ones 45123 this._nActiveActions = 0; 45124 45125 this._actionsByClip = {}; 45126 // inside: 45127 // { 45128 // knownActions: Array< AnimationAction > - used as prototypes 45129 // actionByRoot: AnimationAction - lookup 45130 // } 45131 45132 45133 this._bindings = []; // 'nActiveBindings' followed by inactive ones 45134 this._nActiveBindings = 0; 45135 45136 this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > 45137 45138 45139 this._controlInterpolants = []; // same game as above 45140 this._nActiveControlInterpolants = 0; 45141 45142 var scope = this; 45143 45144 this.stats = { 45145 45146 actions: { 45147 get total() { 45148 45149 return scope._actions.length; 45150 45151 }, 45152 get inUse() { 45153 45154 return scope._nActiveActions; 45155 45156 } 45157 }, 45158 bindings: { 45159 get total() { 45160 45161 return scope._bindings.length; 45162 45163 }, 45164 get inUse() { 45165 45166 return scope._nActiveBindings; 45167 45168 } 45169 }, 45170 controlInterpolants: { 45171 get total() { 45172 45173 return scope._controlInterpolants.length; 45174 45175 }, 45176 get inUse() { 45177 45178 return scope._nActiveControlInterpolants; 45179 45180 } 45181 } 45182 45183 }; 45184 45185 }, 45186 45187 // Memory management for AnimationAction objects 45188 45189 _isActiveAction: function ( action ) { 45190 45191 var index = action._cacheIndex; 45192 return index !== null && index < this._nActiveActions; 45193 45194 }, 45195 45196 _addInactiveAction: function ( action, clipUuid, rootUuid ) { 45197 45198 var actions = this._actions, 45199 actionsByClip = this._actionsByClip, 45200 actionsForClip = actionsByClip[ clipUuid ]; 45201 45202 if ( actionsForClip === undefined ) { 45203 45204 actionsForClip = { 45205 45206 knownActions: [ action ], 45207 actionByRoot: {} 45208 45209 }; 45210 45211 action._byClipCacheIndex = 0; 45212 45213 actionsByClip[ clipUuid ] = actionsForClip; 45214 45215 } else { 45216 45217 var knownActions = actionsForClip.knownActions; 45218 45219 action._byClipCacheIndex = knownActions.length; 45220 knownActions.push( action ); 45221 45222 } 45223 45224 action._cacheIndex = actions.length; 45225 actions.push( action ); 45226 45227 actionsForClip.actionByRoot[ rootUuid ] = action; 45228 45229 }, 45230 45231 _removeInactiveAction: function ( action ) { 45232 45233 var actions = this._actions, 45234 lastInactiveAction = actions[ actions.length - 1 ], 45235 cacheIndex = action._cacheIndex; 45236 45237 lastInactiveAction._cacheIndex = cacheIndex; 45238 actions[ cacheIndex ] = lastInactiveAction; 45239 actions.pop(); 45240 45241 action._cacheIndex = null; 45242 45243 45244 var clipUuid = action._clip.uuid, 45245 actionsByClip = this._actionsByClip, 45246 actionsForClip = actionsByClip[ clipUuid ],
vendor: 4,311 bytes, lines 45247-45423
45247 knownActionsForClip = actionsForClip.knownActions, 45248 45249 lastKnownAction = 45250 knownActionsForClip[ knownActionsForClip.length - 1 ], 45251 45252 byClipCacheIndex = action._byClipCacheIndex; 45253 45254 lastKnownAction._byClipCacheIndex = byClipCacheIndex; 45255 knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; 45256 knownActionsForClip.pop(); 45257 45258 action._byClipCacheIndex = null; 45259 45260 45261 var actionByRoot = actionsForClip.actionByRoot, 45262 rootUuid = ( action._localRoot || this._root ).uuid; 45263 45264 delete actionByRoot[ rootUuid ]; 45265 45266 if ( knownActionsForClip.length === 0 ) { 45267 45268 delete actionsByClip[ clipUuid ]; 45269 45270 } 45271 45272 this._removeInactiveBindingsForAction( action ); 45273 45274 }, 45275 45276 _removeInactiveBindingsForAction: function ( action ) { 45277 45278 var bindings = action._propertyBindings; 45279 for ( var i = 0, n = bindings.length; i !== n; ++ i ) { 45280 45281 var binding = bindings[ i ]; 45282 45283 if ( -- binding.referenceCount === 0 ) { 45284 45285 this._removeInactiveBinding( binding ); 45286 45287 } 45288 45289 } 45290 45291 }, 45292 45293 _lendAction: function ( action ) { 45294 45295 // [ active actions | inactive actions ] 45296 // [ active actions >| inactive actions ] 45297 // s a 45298 // <-swap-> 45299 // a s 45300 45301 var actions = this._actions, 45302 prevIndex = action._cacheIndex, 45303 45304 lastActiveIndex = this._nActiveActions ++, 45305 45306 firstInactiveAction = actions[ lastActiveIndex ]; 45307 45308 action._cacheIndex = lastActiveIndex; 45309 actions[ lastActiveIndex ] = action; 45310 45311 firstInactiveAction._cacheIndex = prevIndex; 45312 actions[ prevIndex ] = firstInactiveAction; 45313 45314 }, 45315 45316 _takeBackAction: function ( action ) { 45317 45318 // [ active actions | inactive actions ] 45319 // [ active actions |< inactive actions ] 45320 // a s 45321 // <-swap-> 45322 // s a 45323 45324 var actions = this._actions, 45325 prevIndex = action._cacheIndex, 45326 45327 firstInactiveIndex = -- this._nActiveActions, 45328 45329 lastActiveAction = actions[ firstInactiveIndex ]; 45330 45331 action._cacheIndex = firstInactiveIndex; 45332 actions[ firstInactiveIndex ] = action; 45333 45334 lastActiveAction._cacheIndex = prevIndex; 45335 actions[ prevIndex ] = lastActiveAction; 45336 45337 }, 45338 45339 // Memory management for PropertyMixer objects 45340 45341 _addInactiveBinding: function ( binding, rootUuid, trackName ) { 45342 45343 var bindingsByRoot = this._bindingsByRootAndName, 45344 bindingByName = bindingsByRoot[ rootUuid ], 45345 45346 bindings = this._bindings; 45347 45348 if ( bindingByName === undefined ) { 45349 45350 bindingByName = {}; 45351 bindingsByRoot[ rootUuid ] = bindingByName; 45352 45353 } 45354 45355 bindingByName[ trackName ] = binding; 45356 45357 binding._cacheIndex = bindings.length; 45358 bindings.push( binding ); 45359 45360 }, 45361 45362 _removeInactiveBinding: function ( binding ) { 45363 45364 var bindings = this._bindings, 45365 propBinding = binding.binding, 45366 rootUuid = propBinding.rootNode.uuid, 45367 trackName = propBinding.path, 45368 bindingsByRoot = this._bindingsByRootAndName, 45369 bindingByName = bindingsByRoot[ rootUuid ], 45370 45371 lastInactiveBinding = bindings[ bindings.length - 1 ], 45372 cacheIndex = binding._cacheIndex; 45373 45374 lastInactiveBinding._cacheIndex = cacheIndex; 45375 bindings[ cacheIndex ] = lastInactiveBinding; 45376 bindings.pop(); 45377 45378 delete bindingByName[ trackName ]; 45379 45380 remove_empty_map: { 45381 45382 for ( var _ in bindingByName ) break remove_empty_map; // eslint-disable-line no-unused-vars 45383 45384 delete bindingsByRoot[ rootUuid ]; 45385 45386 } 45387 45388 }, 45389 45390 _lendBinding: function ( binding ) { 45391 45392 var bindings = this._bindings, 45393 prevIndex = binding._cacheIndex, 45394 45395 lastActiveIndex = this._nActiveBindings ++, 45396 45397 firstInactiveBinding = bindings[ lastActiveIndex ]; 45398 45399 binding._cacheIndex = lastActiveIndex; 45400 bindings[ lastActiveIndex ] = binding; 45401 45402 firstInactiveBinding._cacheIndex = prevIndex; 45403 bindings[ prevIndex ] = firstInactiveBinding; 45404 45405 }, 45406 45407 _takeBackBinding: function ( binding ) { 45408 45409 var bindings = this._bindings, 45410 prevIndex = binding._cacheIndex, 45411 45412 firstInactiveIndex = -- this._nActiveBindings, 45413 45414 lastActiveBinding = bindings[ firstInactiveIndex ]; 45415 45416 binding._cacheIndex = firstInactiveIndex; 45417 bindings[ firstInactiveIndex ] = binding; 45418 45419 lastActiveBinding._cacheIndex = prevIndex; 45420 bindings[ prevIndex ] = lastActiveBinding; 45421 45422 }, 45423
vendor: 17,907 bytes, lines 45424-46295
45424 45425 // Memory management of Interpolants for weight and time scale 45426 45427 _lendControlInterpolant: function () { 45428 45429 var interpolants = this._controlInterpolants, 45430 lastActiveIndex = this._nActiveControlInterpolants ++, 45431 interpolant = interpolants[ lastActiveIndex ]; 45432 45433 if ( interpolant === undefined ) { 45434 45435 interpolant = new LinearInterpolant( 45436 new Float32Array( 2 ), new Float32Array( 2 ), 45437 1, this._controlInterpolantsResultBuffer ); 45438 45439 interpolant.__cacheIndex = lastActiveIndex; 45440 interpolants[ lastActiveIndex ] = interpolant; 45441 45442 } 45443 45444 return interpolant; 45445 45446 }, 45447 45448 _takeBackControlInterpolant: function ( interpolant ) { 45449 45450 var interpolants = this._controlInterpolants, 45451 prevIndex = interpolant.__cacheIndex, 45452 45453 firstInactiveIndex = -- this._nActiveControlInterpolants, 45454 45455 lastActiveInterpolant = interpolants[ firstInactiveIndex ]; 45456 45457 interpolant.__cacheIndex = firstInactiveIndex; 45458 interpolants[ firstInactiveIndex ] = interpolant; 45459 45460 lastActiveInterpolant.__cacheIndex = prevIndex; 45461 interpolants[ prevIndex ] = lastActiveInterpolant; 45462 45463 }, 45464 45465 _controlInterpolantsResultBuffer: new Float32Array( 1 ), 45466 45467 // return an action for a clip optionally using a custom root target 45468 // object (this method allocates a lot of dynamic memory in case a 45469 // previously unknown clip/root combination is specified) 45470 clipAction: function ( clip, optionalRoot ) { 45471 45472 var root = optionalRoot || this._root, 45473 rootUuid = root.uuid, 45474 45475 clipObject = typeof clip === 'string' ? 45476 AnimationClip.findByName( root, clip ) : clip, 45477 45478 clipUuid = clipObject !== null ? clipObject.uuid : clip, 45479 45480 actionsForClip = this._actionsByClip[ clipUuid ], 45481 prototypeAction = null; 45482 45483 if ( actionsForClip !== undefined ) { 45484 45485 var existingAction = 45486 actionsForClip.actionByRoot[ rootUuid ]; 45487 45488 if ( existingAction !== undefined ) { 45489 45490 return existingAction; 45491 45492 } 45493 45494 // we know the clip, so we don't have to parse all 45495 // the bindings again but can just copy 45496 prototypeAction = actionsForClip.knownActions[ 0 ]; 45497 45498 // also, take the clip from the prototype action 45499 if ( clipObject === null ) 45500 clipObject = prototypeAction._clip; 45501 45502 } 45503 45504 // clip must be known when specified via string 45505 if ( clipObject === null ) return null; 45506 45507 // allocate all resources required to run it 45508 var newAction = new AnimationAction( this, clipObject, optionalRoot ); 45509 45510 this._bindAction( newAction, prototypeAction ); 45511 45512 // and make the action known to the memory manager 45513 this._addInactiveAction( newAction, clipUuid, rootUuid ); 45514 45515 return newAction; 45516 45517 }, 45518 45519 // get an existing action 45520 existingAction: function ( clip, optionalRoot ) { 45521 45522 var root = optionalRoot || this._root, 45523 rootUuid = root.uuid, 45524 45525 clipObject = typeof clip === 'string' ? 45526 AnimationClip.findByName( root, clip ) : clip, 45527 45528 clipUuid = clipObject ? clipObject.uuid : clip, 45529 45530 actionsForClip = this._actionsByClip[ clipUuid ]; 45531 45532 if ( actionsForClip !== undefined ) { 45533 45534 return actionsForClip.actionByRoot[ rootUuid ] || null; 45535 45536 } 45537 45538 return null; 45539 45540 }, 45541 45542 // deactivates all previously scheduled actions 45543 stopAllAction: function () { 45544 45545 var actions = this._actions, 45546 nActions = this._nActiveActions, 45547 bindings = this._bindings, 45548 nBindings = this._nActiveBindings; 45549 45550 this._nActiveActions = 0; 45551 this._nActiveBindings = 0; 45552 45553 for ( var i = 0; i !== nActions; ++ i ) { 45554 45555 actions[ i ].reset(); 45556 45557 } 45558 45559 for ( var i = 0; i !== nBindings; ++ i ) { 45560 45561 bindings[ i ].useCount = 0; 45562 45563 } 45564 45565 return this; 45566 45567 }, 45568 45569 // advance the time and update apply the animation 45570 update: function ( deltaTime ) { 45571 45572 deltaTime *= this.timeScale; 45573 45574 var actions = this._actions, 45575 nActions = this._nActiveActions, 45576 45577 time = this.time += deltaTime, 45578 timeDirection = Math.sign( deltaTime ), 45579 45580 accuIndex = this._accuIndex ^= 1; 45581 45582 // run active actions 45583 45584 for ( var i = 0; i !== nActions; ++ i ) { 45585 45586 var action = actions[ i ]; 45587 45588 action._update( time, deltaTime, timeDirection, accuIndex ); 45589 45590 } 45591 45592 // update scene graph 45593 45594 var bindings = this._bindings, 45595 nBindings = this._nActiveBindings; 45596 45597 for ( var i = 0; i !== nBindings; ++ i ) { 45598 45599 bindings[ i ].apply( accuIndex ); 45600 45601 } 45602 45603 return this; 45604 45605 }, 45606 45607 // return this mixer's root target object 45608 getRoot: function () { 45609 45610 return this._root; 45611 45612 }, 45613 45614 // free all resources specific to a particular clip 45615 uncacheClip: function ( clip ) { 45616 45617 var actions = this._actions, 45618 clipUuid = clip.uuid, 45619 actionsByClip = this._actionsByClip, 45620 actionsForClip = actionsByClip[ clipUuid ]; 45621 45622 if ( actionsForClip !== undefined ) { 45623 45624 // note: just calling _removeInactiveAction would mess up the 45625 // iteration state and also require updating the state we can 45626 // just throw away 45627 45628 var actionsToRemove = actionsForClip.knownActions; 45629 45630 for ( var i = 0, n = actionsToRemove.length; i !== n; ++ i ) { 45631 45632 var action = actionsToRemove[ i ]; 45633 45634 this._deactivateAction( action ); 45635 45636 var cacheIndex = action._cacheIndex, 45637 lastInactiveAction = actions[ actions.length - 1 ]; 45638 45639 action._cacheIndex = null; 45640 action._byClipCacheIndex = null; 45641 45642 lastInactiveAction._cacheIndex = cacheIndex; 45643 actions[ cacheIndex ] = lastInactiveAction; 45644 actions.pop(); 45645 45646 this._removeInactiveBindingsForAction( action ); 45647 45648 } 45649 45650 delete actionsByClip[ clipUuid ]; 45651 45652 } 45653 45654 }, 45655 45656 // free all resources specific to a particular root target object 45657 uncacheRoot: function ( root ) { 45658 45659 var rootUuid = root.uuid, 45660 actionsByClip = this._actionsByClip; 45661 45662 for ( var clipUuid in actionsByClip ) { 45663 45664 var actionByRoot = actionsByClip[ clipUuid ].actionByRoot, 45665 action = actionByRoot[ rootUuid ]; 45666 45667 if ( action !== undefined ) { 45668 45669 this._deactivateAction( action ); 45670 this._removeInactiveAction( action ); 45671 45672 } 45673 45674 } 45675 45676 var bindingsByRoot = this._bindingsByRootAndName, 45677 bindingByName = bindingsByRoot[ rootUuid ]; 45678 45679 if ( bindingByName !== undefined ) { 45680 45681 for ( var trackName in bindingByName ) { 45682 45683 var binding = bindingByName[ trackName ]; 45684 binding.restoreOriginalState(); 45685 this._removeInactiveBinding( binding ); 45686 45687 } 45688 45689 } 45690 45691 }, 45692 45693 // remove a targeted clip from the cache 45694 uncacheAction: function ( clip, optionalRoot ) { 45695 45696 var action = this.existingAction( clip, optionalRoot ); 45697 45698 if ( action !== null ) { 45699 45700 this._deactivateAction( action ); 45701 this._removeInactiveAction( action ); 45702 45703 } 45704 45705 } 45706 45707 } ); 45708 45709 /** 45710 * @author mrdoob / http://mrdoob.com/ 45711 */ 45712 45713 function Uniform( value ) { 45714 45715 if ( typeof value === 'string' ) { 45716 45717 console.warn( 'THREE.Uniform: Type parameter is no longer needed.' ); 45718 value = arguments[ 1 ]; 45719 45720 } 45721 45722 this.value = value; 45723 45724 } 45725 45726 Uniform.prototype.clone = function () { 45727 45728 return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); 45729 45730 }; 45731 45732 /** 45733 * @author benaadams / https://twitter.com/ben_a_adams 45734 */ 45735 45736 function InstancedBufferGeometry() { 45737 45738 BufferGeometry.call( this ); 45739 45740 this.type = 'InstancedBufferGeometry'; 45741 this.maxInstancedCount = undefined; 45742 45743 } 45744 45745 InstancedBufferGeometry.prototype = Object.assign( Object.create( BufferGeometry.prototype ), { 45746 45747 constructor: InstancedBufferGeometry, 45748 45749 isInstancedBufferGeometry: true, 45750 45751 copy: function ( source ) { 45752 45753 BufferGeometry.prototype.copy.call( this, source ); 45754 45755 this.maxInstancedCount = source.maxInstancedCount; 45756 45757 return this; 45758 45759 }, 45760 45761 clone: function () { 45762 45763 return new this.constructor().copy( this ); 45764 45765 } 45766 45767 } ); 45768 45769 /** 45770 * @author benaadams / https://twitter.com/ben_a_adams 45771 */ 45772 45773 function InterleavedBufferAttribute( interleavedBuffer, itemSize, offset, normalized ) { 45774 45775 this.data = interleavedBuffer; 45776 this.itemSize = itemSize; 45777 this.offset = offset; 45778 45779 this.normalized = normalized === true; 45780 45781 } 45782 45783 Object.defineProperties( InterleavedBufferAttribute.prototype, { 45784 45785 count: { 45786 45787 get: function () { 45788 45789 return this.data.count; 45790 45791 } 45792 45793 }, 45794 45795 array: { 45796 45797 get: function () { 45798 45799 return this.data.array; 45800 45801 } 45802 45803 } 45804 45805 } ); 45806 45807 Object.assign( InterleavedBufferAttribute.prototype, { 45808 45809 isInterleavedBufferAttribute: true, 45810 45811 setX: function ( index, x ) { 45812 45813 this.data.array[ index * this.data.stride + this.offset ] = x; 45814 45815 return this; 45816 45817 }, 45818 45819 setY: function ( index, y ) { 45820 45821 this.data.array[ index * this.data.stride + this.offset + 1 ] = y; 45822 45823 return this; 45824 45825 }, 45826 45827 setZ: function ( index, z ) { 45828 45829 this.data.array[ index * this.data.stride + this.offset + 2 ] = z; 45830 45831 return this; 45832 45833 }, 45834 45835 setW: function ( index, w ) { 45836 45837 this.data.array[ index * this.data.stride + this.offset + 3 ] = w; 45838 45839 return this; 45840 45841 }, 45842 45843 getX: function ( index ) { 45844 45845 return this.data.array[ index * this.data.stride + this.offset ]; 45846 45847 }, 45848 45849 getY: function ( index ) { 45850 45851 return this.data.array[ index * this.data.stride + this.offset + 1 ]; 45852 45853 }, 45854 45855 getZ: function ( index ) { 45856 45857 return this.data.array[ index * this.data.stride + this.offset + 2 ]; 45858 45859 }, 45860 45861 getW: function ( index ) { 45862 45863 return this.data.array[ index * this.data.stride + this.offset + 3 ]; 45864 45865 }, 45866 45867 setXY: function ( index, x, y ) { 45868 45869 index = index * this.data.stride + this.offset; 45870 45871 this.data.array[ index + 0 ] = x; 45872 this.data.array[ index + 1 ] = y; 45873 45874 return this; 45875 45876 }, 45877 45878 setXYZ: function ( index, x, y, z ) { 45879 45880 index = index * this.data.stride + this.offset; 45881 45882 this.data.array[ index + 0 ] = x; 45883 this.data.array[ index + 1 ] = y; 45884 this.data.array[ index + 2 ] = z; 45885 45886 return this; 45887 45888 }, 45889 45890 setXYZW: function ( index, x, y, z, w ) { 45891 45892 index = index * this.data.stride + this.offset; 45893 45894 this.data.array[ index + 0 ] = x; 45895 this.data.array[ index + 1 ] = y; 45896 this.data.array[ index + 2 ] = z; 45897 this.data.array[ index + 3 ] = w; 45898 45899 return this; 45900 45901 } 45902 45903 } ); 45904 45905 /** 45906 * @author benaadams / https://twitter.com/ben_a_adams 45907 */ 45908 45909 function InterleavedBuffer( array, stride ) { 45910 45911 this.array = array; 45912 this.stride = stride; 45913 this.count = array !== undefined ? array.length / stride : 0; 45914 45915 this.dynamic = false; 45916 this.updateRange = { offset: 0, count: - 1 }; 45917 45918 this.version = 0; 45919 45920 } 45921 45922 Object.defineProperty( InterleavedBuffer.prototype, 'needsUpdate', { 45923 45924 set: function ( value ) { 45925 45926 if ( value === true ) this.version ++; 45927 45928 } 45929 45930 } ); 45931 45932 Object.assign( InterleavedBuffer.prototype, { 45933 45934 isInterleavedBuffer: true, 45935 45936 onUploadCallback: function () {}, 45937 45938 setArray: function ( array ) { 45939 45940 if ( Array.isArray( array ) ) { 45941 45942 throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); 45943 45944 } 45945 45946 this.count = array !== undefined ? array.length / this.stride : 0; 45947 this.array = array; 45948 45949 return this; 45950 45951 }, 45952 45953 setDynamic: function ( value ) { 45954 45955 this.dynamic = value; 45956 45957 return this; 45958 45959 }, 45960 45961 copy: function ( source ) { 45962 45963 this.array = new source.array.constructor( source.array ); 45964 this.count = source.count; 45965 this.stride = source.stride; 45966 this.dynamic = source.dynamic; 45967 45968 return this; 45969 45970 }, 45971 45972 copyAt: function ( index1, attribute, index2 ) { 45973 45974 index1 *= this.stride; 45975 index2 *= attribute.stride; 45976 45977 for ( var i = 0, l = this.stride; i < l; i ++ ) { 45978 45979 this.array[ index1 + i ] = attribute.array[ index2 + i ]; 45980 45981 } 45982 45983 return this; 45984 45985 }, 45986 45987 set: function ( value, offset ) { 45988 45989 if ( offset === undefined ) offset = 0; 45990 45991 this.array.set( value, offset ); 45992 45993 return this; 45994 45995 }, 45996 45997 clone: function () { 45998 45999 return new this.constructor().copy( this ); 46000 46001 }, 46002 46003 onUpload: function ( callback ) { 46004 46005 this.onUploadCallback = callback; 46006 46007 return this; 46008 46009 } 46010 46011 } ); 46012 46013 /** 46014 * @author benaadams / https://twitter.com/ben_a_adams 46015 */ 46016 46017 function InstancedInterleavedBuffer( array, stride, meshPerAttribute ) { 46018 46019 InterleavedBuffer.call( this, array, stride ); 46020 46021 this.meshPerAttribute = meshPerAttribute || 1; 46022 46023 } 46024 46025 InstancedInterleavedBuffer.prototype = Object.assign( Object.create( InterleavedBuffer.prototype ), { 46026 46027 constructor: InstancedInterleavedBuffer, 46028 46029 isInstancedInterleavedBuffer: true, 46030 46031 copy: function ( source ) { 46032 46033 InterleavedBuffer.prototype.copy.call( this, source ); 46034 46035 this.meshPerAttribute = source.meshPerAttribute; 46036 46037 return this; 46038 46039 } 46040 46041 } ); 46042 46043 /** 46044 * @author benaadams / https://twitter.com/ben_a_adams 46045 */ 46046 46047 function InstancedBufferAttribute( array, itemSize, meshPerAttribute ) { 46048 46049 BufferAttribute.call( this, array, itemSize ); 46050 46051 this.meshPerAttribute = meshPerAttribute || 1; 46052 46053 } 46054 46055 InstancedBufferAttribute.prototype = Object.assign( Object.create( BufferAttribute.prototype ), { 46056 46057 constructor: InstancedBufferAttribute, 46058 46059 isInstancedBufferAttribute: true, 46060 46061 copy: function ( source ) { 46062 46063 BufferAttribute.prototype.copy.call( this, source ); 46064 46065 this.meshPerAttribute = source.meshPerAttribute; 46066 46067 return this; 46068 46069 } 46070 46071 } ); 46072 46073 /** 46074 * @author mrdoob / http://mrdoob.com/ 46075 * @author bhouston / http://clara.io/ 46076 * @author stephomi / http://stephaneginier.com/ 46077 */ 46078 46079 function Raycaster( origin, direction, near, far ) { 46080 46081 this.ray = new Ray( origin, direction ); 46082 // direction is assumed to be normalized (for accurate distance calculations) 46083 46084 this.near = near || 0; 46085 this.far = far || Infinity; 46086 46087 this.params = { 46088 Mesh: {}, 46089 Line: {}, 46090 LOD: {}, 46091 Points: { threshold: 1 }, 46092 Sprite: {} 46093 }; 46094 46095 Object.defineProperties( this.params, { 46096 PointCloud: { 46097 get: function () { 46098 46099 console.warn( 'THREE.Raycaster: params.PointCloud has been renamed to params.Points.' ); 46100 return this.Points; 46101 46102 } 46103 } 46104 } ); 46105 46106 } 46107 46108 function ascSort( a, b ) { 46109 46110 return a.distance - b.distance; 46111 46112 } 46113 46114 function intersectObject( object, raycaster, intersects, recursive ) { 46115 46116 if ( object.visible === false ) return; 46117 46118 object.raycast( raycaster, intersects ); 46119 46120 if ( recursive === true ) { 46121 46122 var children = object.children; 46123 46124 for ( var i = 0, l = children.length; i < l; i ++ ) { 46125 46126 intersectObject( children[ i ], raycaster, intersects, true ); 46127 46128 } 46129 46130 } 46131 46132 } 46133 46134 Object.assign( Raycaster.prototype, { 46135 46136 linePrecision: 1, 46137 46138 set: function ( origin, direction ) { 46139 46140 // direction is assumed to be normalized (for accurate distance calculations) 46141 46142 this.ray.set( origin, direction ); 46143 46144 }, 46145 46146 setFromCamera: function ( coords, camera ) { 46147 46148 if ( ( camera && camera.isPerspectiveCamera ) ) { 46149 46150 this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); 46151 this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); 46152 46153 } else if ( ( camera && camera.isOrthographicCamera ) ) { 46154 46155 this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera 46156 this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); 46157 46158 } else { 46159 46160 console.error( 'THREE.Raycaster: Unsupported camera type.' ); 46161 46162 } 46163 46164 }, 46165 46166 intersectObject: function ( object, recursive, optionalTarget ) { 46167 46168 var intersects = optionalTarget || []; 46169 46170 intersectObject( object, this, intersects, recursive ); 46171 46172 intersects.sort( ascSort ); 46173 46174 return intersects; 46175 46176 }, 46177 46178 intersectObjects: function ( objects, recursive, optionalTarget ) { 46179 46180 var intersects = optionalTarget || []; 46181 46182 if ( Array.isArray( objects ) === false ) { 46183 46184 console.warn( 'THREE.Raycaster.intersectObjects: objects is not an Array.' ); 46185 return intersects; 46186 46187 } 46188 46189 for ( var i = 0, l = objects.length; i < l; i ++ ) { 46190 46191 intersectObject( objects[ i ], this, intersects, recursive ); 46192 46193 } 46194 46195 intersects.sort( ascSort ); 46196 46197 return intersects; 46198 46199 } 46200 46201 } ); 46202 46203 /** 46204 * @author alteredq / http://alteredqualia.com/ 46205 */ 46206 46207 function Clock( autoStart ) { 46208 46209 this.autoStart = ( autoStart !== undefined ) ? autoStart : true; 46210 46211 this.startTime = 0; 46212 this.oldTime = 0; 46213 this.elapsedTime = 0; 46214 46215 this.running = false; 46216 46217 } 46218 46219 Object.assign( Clock.prototype, { 46220 46221 start: function () { 46222 46223 this.startTime = ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 46224 46225 this.oldTime = this.startTime; 46226 this.elapsedTime = 0; 46227 this.running = true; 46228 46229 }, 46230 46231 stop: function () { 46232 46233 this.getElapsedTime(); 46234 this.running = false; 46235 this.autoStart = false; 46236 46237 }, 46238 46239 getElapsedTime: function () { 46240 46241 this.getDelta(); 46242 return this.elapsedTime; 46243 46244 }, 46245 46246 getDelta: function () { 46247 46248 var diff = 0; 46249 46250 if ( this.autoStart && ! this.running ) { 46251 46252 this.start(); 46253 return 0; 46254 46255 } 46256 46257 if ( this.running ) { 46258 46259 var newTime = ( typeof performance === 'undefined' ? Date : performance ).now(); 46260 46261 diff = ( newTime - this.oldTime ) / 1000; 46262 this.oldTime = newTime; 46263 46264 this.elapsedTime += diff; 46265 46266 } 46267 46268 return diff; 46269 46270 } 46271 46272 } ); 46273 46274 /** 46275 * @author bhouston / http://clara.io 46276 * @author WestLangley / http://github.com/WestLangley 46277 * 46278 * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system 46279 * 46280 * The poles (phi) are at the positive and negative y axis. 46281 * The equator starts at positive z. 46282 */ 46283 46284 function Spherical( radius, phi, theta ) { 46285 46286 this.radius = ( radius !== undefined ) ? radius : 1.0; 46287 this.phi = ( phi !== undefined ) ? phi : 0; // up / down towards top and bottom pole 46288 this.theta = ( theta !== undefined ) ? theta : 0; // around the equator of the sphere 46289 46290 return this; 46291 46292 } 46293 46294 Object.assign( Spherical.prototype, { 46295
vendor: 1,528 bytes, lines 46296-46372
46296 set: function ( radius, phi, theta ) { 46297 46298 this.radius = radius; 46299 this.phi = phi; 46300 this.theta = theta; 46301 46302 return this; 46303 46304 }, 46305 46306 clone: function () { 46307 46308 return new this.constructor().copy( this ); 46309 46310 }, 46311 46312 copy: function ( other ) { 46313 46314 this.radius = other.radius; 46315 this.phi = other.phi; 46316 this.theta = other.theta; 46317 46318 return this; 46319 46320 }, 46321 46322 // restrict phi to be betwee EPS and PI-EPS 46323 makeSafe: function () { 46324 46325 var EPS = 0.000001; 46326 this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); 46327 46328 return this; 46329 46330 }, 46331 46332 setFromVector3: function ( vec3 ) { 46333 46334 this.radius = vec3.length(); 46335 46336 if ( this.radius === 0 ) { 46337 46338 this.theta = 0; 46339 this.phi = 0; 46340 46341 } else { 46342 46343 this.theta = Math.atan2( vec3.x, vec3.z ); // equator angle around y-up axis 46344 this.phi = Math.acos( _Math.clamp( vec3.y / this.radius, - 1, 1 ) ); // polar angle 46345 46346 } 46347 46348 return this; 46349 46350 } 46351 46352 } ); 46353 46354 /** 46355 * @author Mugen87 / https://github.com/Mugen87 46356 * 46357 * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system 46358 * 46359 */ 46360 46361 function Cylindrical( radius, theta, y ) { 46362 46363 this.radius = ( radius !== undefined ) ? radius : 1.0; // distance from the origin to a point in the x-z plane 46364 this.theta = ( theta !== undefined ) ? theta : 0; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis 46365 this.y = ( y !== undefined ) ? y : 0; // height above the x-z plane 46366 46367 return this; 46368 46369 } 46370 46371 Object.assign( Cylindrical.prototype, { 46372
vendor: 4,357 bytes, lines 46373-46602
46373 set: function ( radius, theta, y ) { 46374 46375 this.radius = radius; 46376 this.theta = theta; 46377 this.y = y; 46378 46379 return this; 46380 46381 }, 46382 46383 clone: function () { 46384 46385 return new this.constructor().copy( this ); 46386 46387 }, 46388 46389 copy: function ( other ) { 46390 46391 this.radius = other.radius; 46392 this.theta = other.theta; 46393 this.y = other.y; 46394 46395 return this; 46396 46397 }, 46398 46399 setFromVector3: function ( vec3 ) { 46400 46401 this.radius = Math.sqrt( vec3.x * vec3.x + vec3.z * vec3.z ); 46402 this.theta = Math.atan2( vec3.x, vec3.z ); 46403 this.y = vec3.y; 46404 46405 return this; 46406 46407 } 46408 46409 } ); 46410 46411 /** 46412 * @author bhouston / http://clara.io 46413 */ 46414 46415 function Box2( min, max ) { 46416 46417 this.min = ( min !== undefined ) ? min : new Vector2( + Infinity, + Infinity ); 46418 this.max = ( max !== undefined ) ? max : new Vector2( - Infinity, - Infinity ); 46419 46420 } 46421 46422 Object.assign( Box2.prototype, { 46423 46424 set: function ( min, max ) { 46425 46426 this.min.copy( min ); 46427 this.max.copy( max ); 46428 46429 return this; 46430 46431 }, 46432 46433 setFromPoints: function ( points ) { 46434 46435 this.makeEmpty(); 46436 46437 for ( var i = 0, il = points.length; i < il; i ++ ) { 46438 46439 this.expandByPoint( points[ i ] ); 46440 46441 } 46442 46443 return this; 46444 46445 }, 46446 46447 setFromCenterAndSize: function () { 46448 46449 var v1 = new Vector2(); 46450 46451 return function setFromCenterAndSize( center, size ) { 46452 46453 var halfSize = v1.copy( size ).multiplyScalar( 0.5 ); 46454 this.min.copy( center ).sub( halfSize ); 46455 this.max.copy( center ).add( halfSize ); 46456 46457 return this; 46458 46459 }; 46460 46461 }(), 46462 46463 clone: function () { 46464 46465 return new this.constructor().copy( this ); 46466 46467 }, 46468 46469 copy: function ( box ) { 46470 46471 this.min.copy( box.min ); 46472 this.max.copy( box.max ); 46473 46474 return this; 46475 46476 }, 46477 46478 makeEmpty: function () { 46479 46480 this.min.x = this.min.y = + Infinity; 46481 this.max.x = this.max.y = - Infinity; 46482 46483 return this; 46484 46485 }, 46486 46487 isEmpty: function () { 46488 46489 // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes 46490 46491 return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); 46492 46493 }, 46494 46495 getCenter: function ( target ) { 46496 46497 if ( target === undefined ) { 46498 46499 console.warn( 'THREE.Box2: .getCenter() target is now required' ); 46500 target = new Vector2(); 46501 46502 } 46503 46504 return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); 46505 46506 }, 46507 46508 getSize: function ( target ) { 46509 46510 if ( target === undefined ) { 46511 46512 console.warn( 'THREE.Box2: .getSize() target is now required' ); 46513 target = new Vector2(); 46514 46515 } 46516 46517 return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min ); 46518 46519 }, 46520 46521 expandByPoint: function ( point ) { 46522 46523 this.min.min( point ); 46524 this.max.max( point ); 46525 46526 return this; 46527 46528 }, 46529 46530 expandByVector: function ( vector ) { 46531 46532 this.min.sub( vector ); 46533 this.max.add( vector ); 46534 46535 return this; 46536 46537 }, 46538 46539 expandByScalar: function ( scalar ) { 46540 46541 this.min.addScalar( - scalar ); 46542 this.max.addScalar( scalar ); 46543 46544 return this; 46545 46546 }, 46547 46548 containsPoint: function ( point ) { 46549 46550 return point.x < this.min.x || point.x > this.max.x || 46551 point.y < this.min.y || point.y > this.max.y ? false : true; 46552 46553 }, 46554 46555 containsBox: function ( box ) { 46556 46557 return this.min.x <= box.min.x && box.max.x <= this.max.x && 46558 this.min.y <= box.min.y && box.max.y <= this.max.y; 46559 46560 }, 46561 46562 getParameter: function ( point, target ) { 46563 46564 // This can potentially have a divide by zero if the box 46565 // has a size dimension of 0. 46566 46567 if ( target === undefined ) { 46568 46569 console.warn( 'THREE.Box2: .getParameter() target is now required' ); 46570 target = new Vector2(); 46571 46572 } 46573 46574 return target.set( 46575 ( point.x - this.min.x ) / ( this.max.x - this.min.x ), 46576 ( point.y - this.min.y ) / ( this.max.y - this.min.y ) 46577 ); 46578 46579 }, 46580 46581 intersectsBox: function ( box ) { 46582 46583 // using 4 splitting planes to rule out intersections 46584 46585 return box.max.x < this.min.x || box.min.x > this.max.x || 46586 box.max.y < this.min.y || box.min.y > this.max.y ? false : true; 46587 46588 }, 46589 46590 clampPoint: function ( point, target ) { 46591 46592 if ( target === undefined ) { 46593 46594 console.warn( 'THREE.Box2: .clampPoint() target is now required' ); 46595 target = new Vector2(); 46596 46597 } 46598 46599 return target.copy( point ).clamp( this.min, this.max ); 46600 46601 }, 46602
46603 distanceToPoint: function () { 46604 46605 var v1 = new Vector2(); 46606 46607 return function distanceToPoint( point ) { 46608 46609 var clampedPoint = v1.copy( point ).clamp( this.min, this.max ); 46610 return clampedPoint.sub( point ).length(); 46611 46612 }; 46613 46614 }(), 46615 46616 intersect: function ( box ) { 46617 46618 this.min.max( box.min ); 46619 this.max.min( box.max ); 46620 46621 return this; 46622 46623 }, 46624 46625 union: function ( box ) { 46626 46627 this.min.min( box.min ); 46628 this.max.max( box.max ); 46629 46630 return this; 46631 46632 }, 46633 46634 translate: function ( offset ) { 46635 46636 this.min.add( offset ); 46637 this.max.add( offset ); 46638 46639 return this; 46640 46641 }, 46642 46643 equals: function ( box ) { 46644 46645 return box.min.equals( this.min ) && box.max.equals( this.max ); 46646 46647 } 46648 46649 } ); 46650 46651 /** 46652 * @author alteredq / http://alteredqualia.com/ 46653 */ 46654 46655 function ImmediateRenderObject( material ) { 46656 46657 Object3D.call( this ); 46658 46659 this.material = material; 46660 this.render = function ( /* renderCallback */ ) {}; 46661 46662 } 46663 46664 ImmediateRenderObject.prototype = Object.create( Object3D.prototype ); 46665 ImmediateRenderObject.prototype.constructor = ImmediateRenderObject; 46666 46667 ImmediateRenderObject.prototype.isImmediateRenderObject = true; 46668 46669 /** 46670 * @author mrdoob / http://mrdoob.com/ 46671 * @author WestLangley / http://github.com/WestLangley 46672 */ 46673 46674 function VertexNormalsHelper( object, size, hex, linewidth ) { 46675 46676 this.object = object; 46677 46678 this.size = ( size !== undefined ) ? size : 1; 46679 46680 var color = ( hex !== undefined ) ? hex : 0xff0000; 46681 46682 var width = ( linewidth !== undefined ) ? linewidth : 1; 46683 46684 // 46685 46686 var nNormals = 0; 46687 46688 var objGeometry = this.object.geometry; 46689 46690 if ( objGeometry && objGeometry.isGeometry ) { 46691 46692 nNormals = objGeometry.faces.length * 3; 46693 46694 } else if ( objGeometry && objGeometry.isBufferGeometry ) { 46695 46696 nNormals = objGeometry.attributes.normal.count; 46697 46698 } 46699 46700 // 46701 46702 var geometry = new BufferGeometry(); 46703 46704 var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); 46705 46706 geometry.addAttribute( 'position', positions ); 46707 46708 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); 46709 46710 // 46711 46712 this.matrixAutoUpdate = false; 46713 46714 this.update(); 46715 46716 } 46717 46718 VertexNormalsHelper.prototype = Object.create( LineSegments.prototype ); 46719 VertexNormalsHelper.prototype.constructor = VertexNormalsHelper; 46720 46721 VertexNormalsHelper.prototype.update = ( function () { 46722 46723 var v1 = new Vector3(); 46724 var v2 = new Vector3(); 46725 var normalMatrix = new Matrix3(); 46726 46727 return function update() { 46728 46729 var keys = [ 'a', 'b', 'c' ]; 46730 46731 this.object.updateMatrixWorld( true ); 46732 46733 normalMatrix.getNormalMatrix( this.object.matrixWorld ); 46734 46735 var matrixWorld = this.object.matrixWorld; 46736 46737 var position = this.geometry.attributes.position; 46738 46739 // 46740 46741 var objGeometry = this.object.geometry; 46742 46743 if ( objGeometry && objGeometry.isGeometry ) { 46744 46745 var vertices = objGeometry.vertices; 46746 46747 var faces = objGeometry.faces; 46748 46749 var idx = 0; 46750 46751 for ( var i = 0, l = faces.length; i < l; i ++ ) { 46752 46753 var face = faces[ i ]; 46754 46755 for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) { 46756 46757 var vertex = vertices[ face[ keys[ j ] ] ]; 46758 46759 var normal = face.vertexNormals[ j ]; 46760 46761 v1.copy( vertex ).applyMatrix4( matrixWorld ); 46762 46763 v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); 46764 46765 position.setXYZ( idx, v1.x, v1.y, v1.z ); 46766 46767 idx = idx + 1; 46768 46769 position.setXYZ( idx, v2.x, v2.y, v2.z ); 46770 46771 idx = idx + 1; 46772 46773 } 46774 46775 } 46776 46777 } else if ( objGeometry && objGeometry.isBufferGeometry ) { 46778 46779 var objPos = objGeometry.attributes.position; 46780 46781 var objNorm = objGeometry.attributes.normal; 46782 46783 var idx = 0; 46784 46785 // for simplicity, ignore index and drawcalls, and render every normal 46786 46787 for ( var j = 0, jl = objPos.count; j < jl; j ++ ) { 46788 46789 v1.set( objPos.getX( j ), objPos.getY( j ), objPos.getZ( j ) ).applyMatrix4( matrixWorld ); 46790 46791 v2.set( objNorm.getX( j ), objNorm.getY( j ), objNorm.getZ( j ) ); 46792 46793 v2.applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); 46794 46795 position.setXYZ( idx, v1.x, v1.y, v1.z ); 46796 46797 idx = idx + 1; 46798 46799 position.setXYZ( idx, v2.x, v2.y, v2.z ); 46800 46801 idx = idx + 1; 46802 46803 } 46804 46805 } 46806 46807 position.needsUpdate = true; 46808 46809 }; 46810 46811 }() ); 46812 46813 /** 46814 * @author alteredq / http://alteredqualia.com/ 46815 * @author mrdoob / http://mrdoob.com/ 46816 * @author WestLangley / http://github.com/WestLangley 46817 */ 46818 46819 function SpotLightHelper( light, color ) { 46820 46821 Object3D.call( this ); 46822 46823 this.light = light; 46824 this.light.updateMatrixWorld(); 46825 46826 this.matrix = light.matrixWorld; 46827 this.matrixAutoUpdate = false;
vendor: 5,008 bytes, lines 46828-47042
46828 46829 this.color = color; 46830 46831 var geometry = new BufferGeometry(); 46832 46833 var positions = [ 46834 0, 0, 0, 0, 0, 1, 46835 0, 0, 0, 1, 0, 1, 46836 0, 0, 0, - 1, 0, 1, 46837 0, 0, 0, 0, 1, 1, 46838 0, 0, 0, 0, - 1, 1 46839 ]; 46840 46841 for ( var i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { 46842 46843 var p1 = ( i / l ) * Math.PI * 2; 46844 var p2 = ( j / l ) * Math.PI * 2; 46845 46846 positions.push( 46847 Math.cos( p1 ), Math.sin( p1 ), 1, 46848 Math.cos( p2 ), Math.sin( p2 ), 1 46849 ); 46850 46851 } 46852 46853 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 46854 46855 var material = new LineBasicMaterial( { fog: false } ); 46856 46857 this.cone = new LineSegments( geometry, material ); 46858 this.add( this.cone ); 46859 46860 this.update(); 46861 46862 } 46863 46864 SpotLightHelper.prototype = Object.create( Object3D.prototype ); 46865 SpotLightHelper.prototype.constructor = SpotLightHelper; 46866 46867 SpotLightHelper.prototype.dispose = function () { 46868 46869 this.cone.geometry.dispose(); 46870 this.cone.material.dispose(); 46871 46872 }; 46873 46874 SpotLightHelper.prototype.update = function () { 46875 46876 var vector = new Vector3(); 46877 var vector2 = new Vector3(); 46878 46879 return function update() { 46880 46881 this.light.updateMatrixWorld(); 46882 46883 var coneLength = this.light.distance ? this.light.distance : 1000; 46884 var coneWidth = coneLength * Math.tan( this.light.angle ); 46885 46886 this.cone.scale.set( coneWidth, coneWidth, coneLength ); 46887 46888 vector.setFromMatrixPosition( this.light.matrixWorld ); 46889 vector2.setFromMatrixPosition( this.light.target.matrixWorld ); 46890 46891 this.cone.lookAt( vector2.sub( vector ) ); 46892 46893 if ( this.color !== undefined ) { 46894 46895 this.cone.material.color.set( this.color ); 46896 46897 } else { 46898 46899 this.cone.material.color.copy( this.light.color ); 46900 46901 } 46902 46903 }; 46904 46905 }(); 46906 46907 /** 46908 * @author Sean Griffin / http://twitter.com/sgrif 46909 * @author Michael Guerrero / http://realitymeltdown.com 46910 * @author mrdoob / http://mrdoob.com/ 46911 * @author ikerr / http://verold.com 46912 * @author Mugen87 / https://github.com/Mugen87 46913 */ 46914 46915 function getBoneList( object ) { 46916 46917 var boneList = []; 46918 46919 if ( object && object.isBone ) { 46920 46921 boneList.push( object ); 46922 46923 } 46924 46925 for ( var i = 0; i < object.children.length; i ++ ) { 46926 46927 boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); 46928 46929 } 46930 46931 return boneList; 46932 46933 } 46934 46935 function SkeletonHelper( object ) { 46936 46937 var bones = getBoneList( object ); 46938 46939 var geometry = new BufferGeometry(); 46940 46941 var vertices = []; 46942 var colors = []; 46943 46944 var color1 = new Color( 0, 0, 1 ); 46945 var color2 = new Color( 0, 1, 0 ); 46946 46947 for ( var i = 0; i < bones.length; i ++ ) { 46948 46949 var bone = bones[ i ]; 46950 46951 if ( bone.parent && bone.parent.isBone ) { 46952 46953 vertices.push( 0, 0, 0 ); 46954 vertices.push( 0, 0, 0 ); 46955 colors.push( color1.r, color1.g, color1.b ); 46956 colors.push( color2.r, color2.g, color2.b ); 46957 46958 } 46959 46960 } 46961 46962 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 46963 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 46964 46965 var material = new LineBasicMaterial( { vertexColors: VertexColors, depthTest: false, depthWrite: false, transparent: true } ); 46966 46967 LineSegments.call( this, geometry, material ); 46968 46969 this.root = object; 46970 this.bones = bones; 46971 46972 this.matrix = object.matrixWorld; 46973 this.matrixAutoUpdate = false; 46974 46975 } 46976 46977 SkeletonHelper.prototype = Object.create( LineSegments.prototype ); 46978 SkeletonHelper.prototype.constructor = SkeletonHelper; 46979 46980 SkeletonHelper.prototype.updateMatrixWorld = function () { 46981 46982 var vector = new Vector3(); 46983 46984 var boneMatrix = new Matrix4(); 46985 var matrixWorldInv = new Matrix4(); 46986 46987 return function updateMatrixWorld( force ) { 46988 46989 var bones = this.bones; 46990 46991 var geometry = this.geometry; 46992 var position = geometry.getAttribute( 'position' ); 46993 46994 matrixWorldInv.getInverse( this.root.matrixWorld ); 46995 46996 for ( var i = 0, j = 0; i < bones.length; i ++ ) { 46997 46998 var bone = bones[ i ]; 46999 47000 if ( bone.parent && bone.parent.isBone ) { 47001 47002 boneMatrix.multiplyMatrices( matrixWorldInv, bone.matrixWorld ); 47003 vector.setFromMatrixPosition( boneMatrix ); 47004 position.setXYZ( j, vector.x, vector.y, vector.z ); 47005 47006 boneMatrix.multiplyMatrices( matrixWorldInv, bone.parent.matrixWorld ); 47007 vector.setFromMatrixPosition( boneMatrix ); 47008 position.setXYZ( j + 1, vector.x, vector.y, vector.z ); 47009 47010 j += 2; 47011 47012 } 47013 47014 } 47015 47016 geometry.getAttribute( 'position' ).needsUpdate = true; 47017 47018 Object3D.prototype.updateMatrixWorld.call( this, force ); 47019 47020 }; 47021 47022 }(); 47023 47024 /** 47025 * @author alteredq / http://alteredqualia.com/ 47026 * @author mrdoob / http://mrdoob.com/ 47027 */ 47028 47029 function PointLightHelper( light, sphereSize, color ) { 47030 47031 this.light = light; 47032 this.light.updateMatrixWorld(); 47033 47034 this.color = color; 47035 47036 var geometry = new SphereBufferGeometry( sphereSize, 4, 2 ); 47037 var material = new MeshBasicMaterial( { wireframe: true, fog: false } ); 47038 47039 Mesh.call( this, geometry, material ); 47040 47041 this.matrix = this.light.matrixWorld; 47042 this.matrixAutoUpdate = false;
47043 47044 this.update(); 47045 47046 47047 /* 47048 var distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); 47049 var distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); 47050 47051 this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); 47052 this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); 47053 47054 var d = light.distance; 47055 47056 if ( d === 0.0 ) { 47057 47058 this.lightDistance.visible = false; 47059 47060 } else { 47061 47062 this.lightDistance.scale.set( d, d, d ); 47063 47064 } 47065 47066 this.add( this.lightDistance ); 47067 */ 47068 47069 } 47070 47071 PointLightHelper.prototype = Object.create( Mesh.prototype ); 47072 PointLightHelper.prototype.constructor = PointLightHelper; 47073 47074 PointLightHelper.prototype.dispose = function () { 47075 47076 this.geometry.dispose(); 47077 this.material.dispose(); 47078 47079 }; 47080 47081 PointLightHelper.prototype.update = function () { 47082 47083 if ( this.color !== undefined ) { 47084 47085 this.material.color.set( this.color ); 47086 47087 } else { 47088 47089 this.material.color.copy( this.light.color ); 47090 47091 } 47092 47093 /* 47094 var d = this.light.distance; 47095 47096 if ( d === 0.0 ) { 47097 47098 this.lightDistance.visible = false; 47099 47100 } else { 47101 47102 this.lightDistance.visible = true; 47103 this.lightDistance.scale.set( d, d, d ); 47104 47105 } 47106 */ 47107 47108 }; 47109 47110 /** 47111 * @author abelnation / http://github.com/abelnation 47112 * @author Mugen87 / http://github.com/Mugen87 47113 * @author WestLangley / http://github.com/WestLangley 47114 */ 47115 47116 function RectAreaLightHelper( light, color ) { 47117 47118 Object3D.call( this ); 47119 47120 this.light = light; 47121 this.light.updateMatrixWorld(); 47122 47123 this.matrix = light.matrixWorld; 47124 this.matrixAutoUpdate = false; 47125 47126 this.color = color; 47127 47128 var material = new LineBasicMaterial( { fog: false } ); 47129 47130 var geometry = new BufferGeometry(); 47131 47132 geometry.addAttribute( 'position', new BufferAttribute( new Float32Array( 5 * 3 ), 3 ) ); 47133 47134 this.line = new Line( geometry, material ); 47135 this.add( this.line ); 47136 47137 47138 this.update(); 47139 47140 } 47141 47142 RectAreaLightHelper.prototype = Object.create( Object3D.prototype ); 47143 RectAreaLightHelper.prototype.constructor = RectAreaLightHelper; 47144 47145 RectAreaLightHelper.prototype.dispose = function () { 47146 47147 this.children[ 0 ].geometry.dispose(); 47148 this.children[ 0 ].material.dispose(); 47149 47150 }; 47151 47152 RectAreaLightHelper.prototype.update = function () { 47153 47154 // calculate new dimensions of the helper 47155 47156 var hx = this.light.width * 0.5; 47157 var hy = this.light.height * 0.5; 47158 47159 var position = this.line.geometry.attributes.position; 47160 var array = position.array; 47161 47162 // update vertices 47163 47164 array[ 0 ] = hx; array[ 1 ] = - hy; array[ 2 ] = 0; 47165 array[ 3 ] = hx; array[ 4 ] = hy; array[ 5 ] = 0; 47166 array[ 6 ] = - hx; array[ 7 ] = hy; array[ 8 ] = 0; 47167 array[ 9 ] = - hx; array[ 10 ] = - hy; array[ 11 ] = 0; 47168 array[ 12 ] = hx; array[ 13 ] = - hy; array[ 14 ] = 0; 47169 47170 position.needsUpdate = true; 47171 47172 if ( this.color !== undefined ) { 47173 47174 this.line.material.color.set( this.color ); 47175 47176 } else { 47177 47178 this.line.material.color.copy( this.light.color ); 47179 47180 } 47181 47182 }; 47183 47184 /** 47185 * @author alteredq / http://alteredqualia.com/ 47186 * @author mrdoob / http://mrdoob.com/ 47187 * @author Mugen87 / https://github.com/Mugen87 47188 */ 47189 47190 function HemisphereLightHelper( light, size, color ) { 47191 47192 Object3D.call( this ); 47193 47194 this.light = light; 47195 this.light.updateMatrixWorld(); 47196 47197 this.matrix = light.matrixWorld; 47198 this.matrixAutoUpdate = false; 47199 47200 this.color = color; 47201 47202 var geometry = new OctahedronBufferGeometry( size ); 47203 geometry.rotateY( Math.PI * 0.5 ); 47204 47205 this.material = new MeshBasicMaterial( { wireframe: true, fog: false } ); 47206 if ( this.color === undefined ) this.material.vertexColors = VertexColors; 47207 47208 var position = geometry.getAttribute( 'position' ); 47209 var colors = new Float32Array( position.count * 3 ); 47210 47211 geometry.addAttribute( 'color', new BufferAttribute( colors, 3 ) ); 47212 47213 this.add( new Mesh( geometry, this.material ) ); 47214 47215 this.update(); 47216 47217 } 47218 47219 HemisphereLightHelper.prototype = Object.create( Object3D.prototype ); 47220 HemisphereLightHelper.prototype.constructor = HemisphereLightHelper; 47221 47222 HemisphereLightHelper.prototype.dispose = function () { 47223 47224 this.children[ 0 ].geometry.dispose(); 47225 this.children[ 0 ].material.dispose(); 47226 47227 }; 47228 47229 HemisphereLightHelper.prototype.update = function () { 47230 47231 var vector = new Vector3(); 47232 47233 var color1 = new Color(); 47234 var color2 = new Color(); 47235
vendor: 4,151 bytes, lines 47236-47406
47236 return function update() { 47237 47238 var mesh = this.children[ 0 ]; 47239 47240 if ( this.color !== undefined ) { 47241 47242 this.material.color.set( this.color ); 47243 47244 } else { 47245 47246 var colors = mesh.geometry.getAttribute( 'color' ); 47247 47248 color1.copy( this.light.color ); 47249 color2.copy( this.light.groundColor ); 47250 47251 for ( var i = 0, l = colors.count; i < l; i ++ ) { 47252 47253 var color = ( i < ( l / 2 ) ) ? color1 : color2; 47254 47255 colors.setXYZ( i, color.r, color.g, color.b ); 47256 47257 } 47258 47259 colors.needsUpdate = true; 47260 47261 } 47262 47263 mesh.lookAt( vector.setFromMatrixPosition( this.light.matrixWorld ).negate() ); 47264 47265 }; 47266 47267 }(); 47268 47269 /** 47270 * @author mrdoob / http://mrdoob.com/ 47271 */ 47272 47273 function GridHelper( size, divisions, color1, color2 ) { 47274 47275 size = size || 10; 47276 divisions = divisions || 10; 47277 color1 = new Color( color1 !== undefined ? color1 : 0x444444 ); 47278 color2 = new Color( color2 !== undefined ? color2 : 0x888888 ); 47279 47280 var center = divisions / 2; 47281 var step = size / divisions; 47282 var halfSize = size / 2; 47283 47284 var vertices = [], colors = []; 47285 47286 for ( var i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { 47287 47288 vertices.push( - halfSize, 0, k, halfSize, 0, k ); 47289 vertices.push( k, 0, - halfSize, k, 0, halfSize ); 47290 47291 var color = i === center ? color1 : color2; 47292 47293 color.toArray( colors, j ); j += 3; 47294 color.toArray( colors, j ); j += 3; 47295 color.toArray( colors, j ); j += 3; 47296 color.toArray( colors, j ); j += 3; 47297 47298 } 47299 47300 var geometry = new BufferGeometry(); 47301 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 47302 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 47303 47304 var material = new LineBasicMaterial( { vertexColors: VertexColors } ); 47305 47306 LineSegments.call( this, geometry, material ); 47307 47308 } 47309 47310 GridHelper.prototype = Object.create( LineSegments.prototype ); 47311 GridHelper.prototype.constructor = GridHelper; 47312 47313 /** 47314 * @author mrdoob / http://mrdoob.com/ 47315 * @author Mugen87 / http://github.com/Mugen87 47316 * @author Hectate / http://www.github.com/Hectate 47317 */ 47318 47319 function PolarGridHelper( radius, radials, circles, divisions, color1, color2 ) { 47320 47321 radius = radius || 10; 47322 radials = radials || 16; 47323 circles = circles || 8; 47324 divisions = divisions || 64; 47325 color1 = new Color( color1 !== undefined ? color1 : 0x444444 ); 47326 color2 = new Color( color2 !== undefined ? color2 : 0x888888 ); 47327 47328 var vertices = []; 47329 var colors = []; 47330 47331 var x, z; 47332 var v, i, j, r, color; 47333 47334 // create the radials 47335 47336 for ( i = 0; i <= radials; i ++ ) { 47337 47338 v = ( i / radials ) * ( Math.PI * 2 ); 47339 47340 x = Math.sin( v ) * radius; 47341 z = Math.cos( v ) * radius; 47342 47343 vertices.push( 0, 0, 0 ); 47344 vertices.push( x, 0, z ); 47345 47346 color = ( i & 1 ) ? color1 : color2; 47347 47348 colors.push( color.r, color.g, color.b ); 47349 colors.push( color.r, color.g, color.b ); 47350 47351 } 47352 47353 // create the circles 47354 47355 for ( i = 0; i <= circles; i ++ ) { 47356 47357 color = ( i & 1 ) ? color1 : color2; 47358 47359 r = radius - ( radius / circles * i ); 47360 47361 for ( j = 0; j < divisions; j ++ ) { 47362 47363 // first vertex 47364 47365 v = ( j / divisions ) * ( Math.PI * 2 ); 47366 47367 x = Math.sin( v ) * r; 47368 z = Math.cos( v ) * r; 47369 47370 vertices.push( x, 0, z ); 47371 colors.push( color.r, color.g, color.b ); 47372 47373 // second vertex 47374 47375 v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); 47376 47377 x = Math.sin( v ) * r; 47378 z = Math.cos( v ) * r; 47379 47380 vertices.push( x, 0, z ); 47381 colors.push( color.r, color.g, color.b ); 47382 47383 } 47384 47385 } 47386 47387 var geometry = new BufferGeometry(); 47388 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 47389 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 47390 47391 var material = new LineBasicMaterial( { vertexColors: VertexColors } ); 47392 47393 LineSegments.call( this, geometry, material ); 47394 47395 } 47396 47397 PolarGridHelper.prototype = Object.create( LineSegments.prototype ); 47398 PolarGridHelper.prototype.constructor = PolarGridHelper; 47399 47400 /** 47401 * @author mrdoob / http://mrdoob.com/ 47402 * @author WestLangley / http://github.com/WestLangley 47403 */ 47404 47405 function FaceNormalsHelper( object, size, hex, linewidth ) { 47406
47407 // FaceNormalsHelper only supports THREE.Geometry 47408 47409 this.object = object; 47410 47411 this.size = ( size !== undefined ) ? size : 1; 47412 47413 var color = ( hex !== undefined ) ? hex : 0xffff00; 47414 47415 var width = ( linewidth !== undefined ) ? linewidth : 1; 47416 47417 // 47418 47419 var nNormals = 0; 47420 47421 var objGeometry = this.object.geometry; 47422 47423 if ( objGeometry && objGeometry.isGeometry ) { 47424 47425 nNormals = objGeometry.faces.length; 47426 47427 } else { 47428 47429 console.warn( 'THREE.FaceNormalsHelper: only THREE.Geometry is supported. Use THREE.VertexNormalsHelper, instead.' ); 47430 47431 } 47432 47433 // 47434 47435 var geometry = new BufferGeometry(); 47436 47437 var positions = new Float32BufferAttribute( nNormals * 2 * 3, 3 ); 47438 47439 geometry.addAttribute( 'position', positions ); 47440 47441 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color, linewidth: width } ) ); 47442 47443 // 47444 47445 this.matrixAutoUpdate = false; 47446 this.update(); 47447 47448 } 47449 47450 FaceNormalsHelper.prototype = Object.create( LineSegments.prototype ); 47451 FaceNormalsHelper.prototype.constructor = FaceNormalsHelper; 47452 47453 FaceNormalsHelper.prototype.update = ( function () { 47454 47455 var v1 = new Vector3(); 47456 var v2 = new Vector3(); 47457 var normalMatrix = new Matrix3(); 47458 47459 return function update() { 47460 47461 this.object.updateMatrixWorld( true ); 47462 47463 normalMatrix.getNormalMatrix( this.object.matrixWorld ); 47464 47465 var matrixWorld = this.object.matrixWorld; 47466 47467 var position = this.geometry.attributes.position; 47468 47469 // 47470 47471 var objGeometry = this.object.geometry; 47472 47473 var vertices = objGeometry.vertices; 47474 47475 var faces = objGeometry.faces; 47476 47477 var idx = 0; 47478 47479 for ( var i = 0, l = faces.length; i < l; i ++ ) { 47480 47481 var face = faces[ i ]; 47482 47483 var normal = face.normal; 47484 47485 v1.copy( vertices[ face.a ] ) 47486 .add( vertices[ face.b ] ) 47487 .add( vertices[ face.c ] ) 47488 .divideScalar( 3 ) 47489 .applyMatrix4( matrixWorld ); 47490 47491 v2.copy( normal ).applyMatrix3( normalMatrix ).normalize().multiplyScalar( this.size ).add( v1 ); 47492 47493 position.setXYZ( idx, v1.x, v1.y, v1.z ); 47494 47495 idx = idx + 1; 47496 47497 position.setXYZ( idx, v2.x, v2.y, v2.z ); 47498 47499 idx = idx + 1; 47500 47501 } 47502 47503 position.needsUpdate = true; 47504 47505 }; 47506 47507 }() ); 47508 47509 /** 47510 * @author alteredq / http://alteredqualia.com/ 47511 * @author mrdoob / http://mrdoob.com/ 47512 * @author WestLangley / http://github.com/WestLangley 47513 */ 47514 47515 function DirectionalLightHelper( light, size, color ) { 47516 47517 Object3D.call( this ); 47518 47519 this.light = light; 47520 this.light.updateMatrixWorld(); 47521 47522 this.matrix = light.matrixWorld; 47523 this.matrixAutoUpdate = false; 47524 47525 this.color = color; 47526 47527 if ( size === undefined ) size = 1; 47528 47529 var geometry = new BufferGeometry(); 47530 geometry.addAttribute( 'position', new Float32BufferAttribute( [ 47531 - size, size, 0, 47532 size, size, 0, 47533 size, - size, 0, 47534 - size, - size, 0, 47535 - size, size, 0 47536 ], 3 ) ); 47537 47538 var material = new LineBasicMaterial( { fog: false } ); 47539 47540 this.lightPlane = new Line( geometry, material ); 47541 this.add( this.lightPlane ); 47542 47543 geometry = new BufferGeometry(); 47544 geometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); 47545 47546 this.targetLine = new Line( geometry, material ); 47547 this.add( this.targetLine ); 47548 47549 this.update(); 47550 47551 } 47552 47553 DirectionalLightHelper.prototype = Object.create( Object3D.prototype ); 47554 DirectionalLightHelper.prototype.constructor = DirectionalLightHelper; 47555 47556 DirectionalLightHelper.prototype.dispose = function () { 47557 47558 this.lightPlane.geometry.dispose(); 47559 this.lightPlane.material.dispose(); 47560 this.targetLine.geometry.dispose(); 47561 this.targetLine.material.dispose(); 47562 47563 }; 47564 47565 DirectionalLightHelper.prototype.update = function () { 47566 47567 var v1 = new Vector3(); 47568 var v2 = new Vector3(); 47569 var v3 = new Vector3(); 47570 47571 return function update() { 47572 47573 v1.setFromMatrixPosition( this.light.matrixWorld ); 47574 v2.setFromMatrixPosition( this.light.target.matrixWorld ); 47575 v3.subVectors( v2, v1 ); 47576 47577 this.lightPlane.lookAt( v3 ); 47578 47579 if ( this.color !== undefined ) { 47580 47581 this.lightPlane.material.color.set( this.color ); 47582 this.targetLine.material.color.set( this.color ); 47583 47584 } else { 47585
47586 this.lightPlane.material.color.copy( this.light.color ); 47587 this.targetLine.material.color.copy( this.light.color ); 47588 47589 } 47590 47591 this.targetLine.lookAt( v3 ); 47592 this.targetLine.scale.z = v3.length(); 47593 47594 }; 47595 47596 }(); 47597 47598 /** 47599 * @author alteredq / http://alteredqualia.com/ 47600 * @author Mugen87 / https://github.com/Mugen87 47601 * 47602 * - shows frustum, line of sight and up of the camera 47603 * - suitable for fast updates 47604 * - based on frustum visualization in lightgl.js shadowmap example 47605 * http://evanw.github.com/lightgl.js/tests/shadowmap.html 47606 */ 47607 47608 function CameraHelper( camera ) { 47609 47610 var geometry = new BufferGeometry(); 47611 var material = new LineBasicMaterial( { color: 0xffffff, vertexColors: FaceColors } ); 47612 47613 var vertices = []; 47614 var colors = []; 47615 47616 var pointMap = {}; 47617 47618 // colors 47619 47620 var colorFrustum = new Color( 0xffaa00 ); 47621 var colorCone = new Color( 0xff0000 ); 47622 var colorUp = new Color( 0x00aaff ); 47623 var colorTarget = new Color( 0xffffff ); 47624 var colorCross = new Color( 0x333333 ); 47625 47626 // near 47627 47628 addLine( 'n1', 'n2', colorFrustum ); 47629 addLine( 'n2', 'n4', colorFrustum ); 47630 addLine( 'n4', 'n3', colorFrustum ); 47631 addLine( 'n3', 'n1', colorFrustum ); 47632 47633 // far 47634 47635 addLine( 'f1', 'f2', colorFrustum ); 47636 addLine( 'f2', 'f4', colorFrustum ); 47637 addLine( 'f4', 'f3', colorFrustum ); 47638 addLine( 'f3', 'f1', colorFrustum ); 47639 47640 // sides 47641 47642 addLine( 'n1', 'f1', colorFrustum ); 47643 addLine( 'n2', 'f2', colorFrustum ); 47644 addLine( 'n3', 'f3', colorFrustum ); 47645 addLine( 'n4', 'f4', colorFrustum ); 47646 47647 // cone 47648 47649 addLine( 'p', 'n1', colorCone ); 47650 addLine( 'p', 'n2', colorCone ); 47651 addLine( 'p', 'n3', colorCone ); 47652 addLine( 'p', 'n4', colorCone ); 47653 47654 // up 47655 47656 addLine( 'u1', 'u2', colorUp ); 47657 addLine( 'u2', 'u3', colorUp ); 47658 addLine( 'u3', 'u1', colorUp ); 47659 47660 // target 47661 47662 addLine( 'c', 't', colorTarget ); 47663 addLine( 'p', 'c', colorCross ); 47664 47665 // cross 47666 47667 addLine( 'cn1', 'cn2', colorCross ); 47668 addLine( 'cn3', 'cn4', colorCross ); 47669 47670 addLine( 'cf1', 'cf2', colorCross ); 47671 addLine( 'cf3', 'cf4', colorCross ); 47672 47673 function addLine( a, b, color ) { 47674 47675 addPoint( a, color ); 47676 addPoint( b, color ); 47677 47678 } 47679 47680 function addPoint( id, color ) { 47681 47682 vertices.push( 0, 0, 0 ); 47683 colors.push( color.r, color.g, color.b ); 47684 47685 if ( pointMap[ id ] === undefined ) { 47686 47687 pointMap[ id ] = []; 47688 47689 } 47690 47691 pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); 47692 47693 } 47694 47695 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 47696 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 47697 47698 LineSegments.call( this, geometry, material ); 47699 47700 this.camera = camera; 47701 if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); 47702 47703 this.matrix = camera.matrixWorld; 47704 this.matrixAutoUpdate = false; 47705 47706 this.pointMap = pointMap; 47707 47708 this.update(); 47709 47710 } 47711 47712 CameraHelper.prototype = Object.create( LineSegments.prototype ); 47713 CameraHelper.prototype.constructor = CameraHelper; 47714 47715 CameraHelper.prototype.update = function () { 47716 47717 var geometry, pointMap; 47718 47719 var vector = new Vector3(); 47720 var camera = new Camera(); 47721 47722 function setPoint( point, x, y, z ) { 47723 47724 vector.set( x, y, z ).unproject( camera ); 47725 47726 var points = pointMap[ point ]; 47727 47728 if ( points !== undefined ) { 47729 47730 var position = geometry.getAttribute( 'position' ); 47731 47732 for ( var i = 0, l = points.length; i < l; i ++ ) { 47733 47734 position.setXYZ( points[ i ], vector.x, vector.y, vector.z ); 47735 47736 } 47737 47738 } 47739 47740 } 47741 47742 return function update() { 47743 47744 geometry = this.geometry; 47745 pointMap = this.pointMap; 47746 47747 var w = 1, h = 1; 47748 47749 // we need just camera projection matrix 47750 // world matrix must be identity 47751 47752 camera.projectionMatrix.copy( this.camera.projectionMatrix ); 47753 47754 // center / target 47755 47756 setPoint( 'c', 0, 0, - 1 ); 47757 setPoint( 't', 0, 0, 1 ); 47758 47759 // near 47760 47761 setPoint( 'n1', - w, - h, - 1 ); 47762 setPoint( 'n2', w, - h, - 1 ); 47763 setPoint( 'n3', - w, h, - 1 ); 47764 setPoint( 'n4', w, h, - 1 ); 47765 47766 // far 47767 47768 setPoint( 'f1', - w, - h, 1 ); 47769 setPoint( 'f2', w, - h, 1 ); 47770 setPoint( 'f3', - w, h, 1 ); 47771 setPoint( 'f4', w, h, 1 ); 47772 47773 // up 47774 47775 setPoint( 'u1', w * 0.7, h * 1.1, - 1 ); 47776 setPoint( 'u2', - w * 0.7, h * 1.1, - 1 ); 47777 setPoint( 'u3', 0, h * 2, - 1 ); 47778 47779 // cross 47780 47781 setPoint( 'cf1', - w, 0, 1 ); 47782 setPoint( 'cf2', w, 0, 1 ); 47783 setPoint( 'cf3', 0, - h, 1 ); 47784 setPoint( 'cf4', 0, h, 1 ); 47785 47786 setPoint( 'cn1', - w, 0, - 1 ); 47787 setPoint( 'cn2', w, 0, - 1 ); 47788 setPoint( 'cn3', 0, - h, - 1 ); 47789 setPoint( 'cn4', 0, h, - 1 ); 47790 47791 geometry.getAttribute( 'position' ).needsUpdate = true; 47792 47793 }; 47794 47795 }(); 47796 47797 /** 47798 * @author mrdoob / http://mrdoob.com/ 47799 * @author Mugen87 / http://github.com/Mugen87 47800 */ 47801 47802 function BoxHelper( object, color ) { 47803 47804 this.object = object; 47805 47806 if ( color === undefined ) color = 0xffff00; 47807 47808 var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] ); 47809 var positions = new Float32Array( 8 * 3 ); 47810 47811 var geometry = new BufferGeometry(); 47812 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 47813 geometry.addAttribute( 'position', new BufferAttribute( positions, 3 ) ); 47814 47815 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); 47816 47817 this.matrixAutoUpdate = false;
vendor: 8,404 bytes, lines 47818-48154
47818 47819 this.update(); 47820 47821 } 47822 47823 BoxHelper.prototype = Object.create( LineSegments.prototype ); 47824 BoxHelper.prototype.constructor = BoxHelper; 47825 47826 BoxHelper.prototype.update = ( function () { 47827 47828 var box = new Box3(); 47829 47830 return function update( object ) { 47831 47832 if ( object !== undefined ) { 47833 47834 console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); 47835 47836 } 47837 47838 if ( this.object !== undefined ) { 47839 47840 box.setFromObject( this.object ); 47841 47842 } 47843 47844 if ( box.isEmpty() ) return; 47845 47846 var min = box.min; 47847 var max = box.max; 47848 47849 /* 47850 5____4 47851 1/___0/| 47852 | 6__|_7 47853 2/___3/ 47854 47855 0: max.x, max.y, max.z 47856 1: min.x, max.y, max.z 47857 2: min.x, min.y, max.z 47858 3: max.x, min.y, max.z 47859 4: max.x, max.y, min.z 47860 5: min.x, max.y, min.z 47861 6: min.x, min.y, min.z 47862 7: max.x, min.y, min.z 47863 */ 47864 47865 var position = this.geometry.attributes.position; 47866 var array = position.array; 47867 47868 array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; 47869 array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; 47870 array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; 47871 array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; 47872 array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; 47873 array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; 47874 array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; 47875 array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; 47876 47877 position.needsUpdate = true; 47878 47879 this.geometry.computeBoundingSphere(); 47880 47881 }; 47882 47883 } )(); 47884 47885 BoxHelper.prototype.setFromObject = function ( object ) { 47886 47887 this.object = object; 47888 this.update(); 47889 47890 return this; 47891 47892 }; 47893 47894 /** 47895 * @author WestLangley / http://github.com/WestLangley 47896 */ 47897 47898 function Box3Helper( box, hex ) { 47899 47900 this.type = 'Box3Helper'; 47901 47902 this.box = box; 47903 47904 var color = ( hex !== undefined ) ? hex : 0xffff00; 47905 47906 var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] ); 47907 47908 var positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ]; 47909 47910 var geometry = new BufferGeometry(); 47911 47912 geometry.setIndex( new BufferAttribute( indices, 1 ) ); 47913 47914 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 47915 47916 LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) ); 47917 47918 this.geometry.computeBoundingSphere(); 47919 47920 } 47921 47922 Box3Helper.prototype = Object.create( LineSegments.prototype ); 47923 Box3Helper.prototype.constructor = Box3Helper; 47924 47925 Box3Helper.prototype.updateMatrixWorld = function ( force ) { 47926 47927 var box = this.box; 47928 47929 if ( box.isEmpty() ) return; 47930 47931 box.getCenter( this.position ); 47932 47933 box.getSize( this.scale ); 47934 47935 this.scale.multiplyScalar( 0.5 ); 47936 47937 Object3D.prototype.updateMatrixWorld.call( this, force ); 47938 47939 }; 47940 47941 /** 47942 * @author WestLangley / http://github.com/WestLangley 47943 */ 47944 47945 function PlaneHelper( plane, size, hex ) { 47946 47947 this.type = 'PlaneHelper'; 47948 47949 this.plane = plane; 47950 47951 this.size = ( size === undefined ) ? 1 : size; 47952 47953 var color = ( hex !== undefined ) ? hex : 0xffff00; 47954 47955 var positions = [ 1, - 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0 ]; 47956 47957 var geometry = new BufferGeometry(); 47958 geometry.addAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 47959 geometry.computeBoundingSphere(); 47960 47961 Line.call( this, geometry, new LineBasicMaterial( { color: color } ) ); 47962 47963 // 47964 47965 var positions2 = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, 1, 1, - 1, - 1, 1, 1, - 1, 1 ]; 47966 47967 var geometry2 = new BufferGeometry(); 47968 geometry2.addAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); 47969 geometry2.computeBoundingSphere(); 47970 47971 this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false } ) ) ); 47972 47973 } 47974 47975 PlaneHelper.prototype = Object.create( Line.prototype ); 47976 PlaneHelper.prototype.constructor = PlaneHelper; 47977 47978 PlaneHelper.prototype.updateMatrixWorld = function ( force ) { 47979 47980 var scale = - this.plane.constant; 47981 47982 if ( Math.abs( scale ) < 1e-8 ) scale = 1e-8; // sign does not matter 47983 47984 this.scale.set( 0.5 * this.size, 0.5 * this.size, scale ); 47985 47986 this.children[ 0 ].material.side = ( scale < 0 ) ? BackSide : FrontSide; // renderer flips side when determinant < 0; flipping not wanted here 47987 47988 this.lookAt( this.plane.normal ); 47989 47990 Object3D.prototype.updateMatrixWorld.call( this, force ); 47991 47992 }; 47993 47994 /** 47995 * @author WestLangley / http://github.com/WestLangley 47996 * @author zz85 / http://github.com/zz85 47997 * @author bhouston / http://clara.io 47998 * 47999 * Creates an arrow for visualizing directions 48000 * 48001 * Parameters: 48002 * dir - Vector3 48003 * origin - Vector3 48004 * length - Number 48005 * color - color in hex value 48006 * headLength - Number 48007 * headWidth - Number 48008 */ 48009 48010 var lineGeometry, coneGeometry; 48011 48012 function ArrowHelper( dir, origin, length, color, headLength, headWidth ) { 48013 48014 // dir is assumed to be normalized 48015 48016 Object3D.call( this ); 48017 48018 if ( color === undefined ) color = 0xffff00; 48019 if ( length === undefined ) length = 1; 48020 if ( headLength === undefined ) headLength = 0.2 * length; 48021 if ( headWidth === undefined ) headWidth = 0.2 * headLength; 48022 48023 if ( lineGeometry === undefined ) { 48024 48025 lineGeometry = new BufferGeometry(); 48026 lineGeometry.addAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); 48027 48028 coneGeometry = new CylinderBufferGeometry( 0, 0.5, 1, 5, 1 ); 48029 coneGeometry.translate( 0, - 0.5, 0 ); 48030 48031 } 48032 48033 this.position.copy( origin ); 48034 48035 this.line = new Line( lineGeometry, new LineBasicMaterial( { color: color } ) ); 48036 this.line.matrixAutoUpdate = false; 48037 this.add( this.line ); 48038 48039 this.cone = new Mesh( coneGeometry, new MeshBasicMaterial( { color: color } ) ); 48040 this.cone.matrixAutoUpdate = false; 48041 this.add( this.cone ); 48042 48043 this.setDirection( dir ); 48044 this.setLength( length, headLength, headWidth ); 48045 48046 } 48047 48048 ArrowHelper.prototype = Object.create( Object3D.prototype ); 48049 ArrowHelper.prototype.constructor = ArrowHelper; 48050 48051 ArrowHelper.prototype.setDirection = ( function () { 48052 48053 var axis = new Vector3(); 48054 var radians; 48055 48056 return function setDirection( dir ) { 48057 48058 // dir is assumed to be normalized 48059 48060 if ( dir.y > 0.99999 ) { 48061 48062 this.quaternion.set( 0, 0, 0, 1 ); 48063 48064 } else if ( dir.y < - 0.99999 ) { 48065 48066 this.quaternion.set( 1, 0, 0, 0 ); 48067 48068 } else { 48069 48070 axis.set( dir.z, 0, - dir.x ).normalize(); 48071 48072 radians = Math.acos( dir.y ); 48073 48074 this.quaternion.setFromAxisAngle( axis, radians ); 48075 48076 } 48077 48078 }; 48079 48080 }() ); 48081 48082 ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) { 48083 48084 if ( headLength === undefined ) headLength = 0.2 * length; 48085 if ( headWidth === undefined ) headWidth = 0.2 * headLength; 48086 48087 this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 ); 48088 this.line.updateMatrix(); 48089 48090 this.cone.scale.set( headWidth, headLength, headWidth ); 48091 this.cone.position.y = length; 48092 this.cone.updateMatrix(); 48093 48094 }; 48095 48096 ArrowHelper.prototype.setColor = function ( color ) { 48097 48098 this.line.material.color.copy( color ); 48099 this.cone.material.color.copy( color ); 48100 48101 }; 48102 48103 /** 48104 * @author sroucheray / http://sroucheray.org/ 48105 * @author mrdoob / http://mrdoob.com/ 48106 */ 48107 48108 function AxesHelper( size ) { 48109 48110 size = size || 1; 48111 48112 var vertices = [ 48113 0, 0, 0, size, 0, 0, 48114 0, 0, 0, 0, size, 0, 48115 0, 0, 0, 0, 0, size 48116 ]; 48117 48118 var colors = [ 48119 1, 0, 0, 1, 0.6, 0, 48120 0, 1, 0, 0.6, 1, 0, 48121 0, 0, 1, 0, 0.6, 1 48122 ]; 48123 48124 var geometry = new BufferGeometry(); 48125 geometry.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 48126 geometry.addAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 48127 48128 var material = new LineBasicMaterial( { vertexColors: VertexColors } ); 48129 48130 LineSegments.call( this, geometry, material ); 48131 48132 } 48133 48134 AxesHelper.prototype = Object.create( LineSegments.prototype ); 48135 AxesHelper.prototype.constructor = AxesHelper; 48136 48137 // 48138 48139 Curve.create = function ( construct, getPoint ) { 48140 48141 console.log( 'THREE.Curve.create() has been deprecated' ); 48142 48143 construct.prototype = Object.create( Curve.prototype ); 48144 construct.prototype.constructor = construct; 48145 construct.prototype.getPoint = getPoint; 48146 48147 return construct; 48148 48149 }; 48150 48151 // 48152 48153 Object.assign( CurvePath.prototype, { 48154
48155 createPointsGeometry: function ( divisions ) { 48156 48157 console.warn( 'THREE.CurvePath: .createPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); 48158 48159 // generate geometry from path points (for Line or Points objects) 48160 48161 var pts = this.getPoints( divisions ); 48162 return this.createGeometry( pts ); 48163 48164 }, 48165 48166 createSpacedPointsGeometry: function ( divisions ) { 48167 48168 console.warn( 'THREE.CurvePath: .createSpacedPointsGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); 48169 48170 // generate geometry from equidistant sampling along the path 48171 48172 var pts = this.getSpacedPoints( divisions ); 48173 return this.createGeometry( pts ); 48174 48175 }, 48176 48177 createGeometry: function ( points ) { 48178 48179 console.warn( 'THREE.CurvePath: .createGeometry() has been removed. Use new THREE.Geometry().setFromPoints( points ) instead.' ); 48180 48181 var geometry = new Geometry(); 48182 48183 for ( var i = 0, l = points.length; i < l; i ++ ) { 48184 48185 var point = points[ i ]; 48186 geometry.vertices.push( new Vector3( point.x, point.y, point.z || 0 ) ); 48187 48188 } 48189 48190 return geometry; 48191 48192 } 48193 48194 } ); 48195 48196 // 48197 48198 Object.assign( Path.prototype, { 48199
48200 fromPoints: function ( points ) { 48201 48202 console.warn( 'THREE.Path: .fromPoints() has been renamed to .setFromPoints().' ); 48203 this.setFromPoints( points ); 48204 48205 } 48206 48207 } ); 48208 48209 // 48210 48211 function Spline( points ) { 48212 48213 console.warn( 'THREE.Spline has been removed. Use THREE.CatmullRomCurve3 instead.' ); 48214 48215 CatmullRomCurve3.call( this, points ); 48216 this.type = 'catmullrom'; 48217 48218 } 48219 48220 Spline.prototype = Object.create( CatmullRomCurve3.prototype ); 48221 48222 Object.assign( Spline.prototype, { 48223 48224 initFromArray: function ( /* a */ ) { 48225 48226 console.error( 'THREE.Spline: .initFromArray() has been removed.' ); 48227 48228 }, 48229 getControlPointsArray: function ( /* optionalTarget */ ) { 48230 48231 console.error( 'THREE.Spline: .getControlPointsArray() has been removed.' ); 48232 48233 }, 48234 reparametrizeByArcLength: function ( /* samplingCoef */ ) { 48235 48236 console.error( 'THREE.Spline: .reparametrizeByArcLength() has been removed.' ); 48237 48238 } 48239 48240 } ); 48241 48242 GridHelper.prototype.setColors = function () { 48243 48244 console.error( 'THREE.GridHelper: setColors() has been deprecated, pass them in the constructor instead.' ); 48245 48246 }; 48247 48248 SkeletonHelper.prototype.update = function () { 48249 48250 console.error( 'THREE.SkeletonHelper: update() no longer needs to be called.' ); 48251 48252 }; 48253 48254 // 48255 48256 Object.assign( Loader.prototype, { 48257
48258 extractUrlBase: function ( url ) { 48259 48260 console.warn( 'THREE.Loader: .extractUrlBase() has been deprecated. Use THREE.LoaderUtils.extractUrlBase() instead.' ); 48261 return LoaderUtils.extractUrlBase( url ); 48262 48263 } 48264 48265 } ); 48266 48267 // 48268 48269 Object.assign( Box2.prototype, { 48270 48271 center: function ( optionalTarget ) { 48272 48273 console.warn( 'THREE.Box2: .center() has been renamed to .getCenter().' ); 48274 return this.getCenter( optionalTarget ); 48275 48276 }, 48277 empty: function () { 48278 48279 console.warn( 'THREE.Box2: .empty() has been renamed to .isEmpty().' ); 48280 return this.isEmpty(); 48281 48282 }, 48283 isIntersectionBox: function ( box ) { 48284 48285 console.warn( 'THREE.Box2: .isIntersectionBox() has been renamed to .intersectsBox().' ); 48286 return this.intersectsBox( box ); 48287 48288 }, 48289 size: function ( optionalTarget ) { 48290 48291 console.warn( 'THREE.Box2: .size() has been renamed to .getSize().' ); 48292 return this.getSize( optionalTarget ); 48293 48294 } 48295 } ); 48296 48297 Object.assign( Box3.prototype, { 48298 48299 center: function ( optionalTarget ) { 48300 48301 console.warn( 'THREE.Box3: .center() has been renamed to .getCenter().' ); 48302 return this.getCenter( optionalTarget ); 48303 48304 }, 48305 empty: function () { 48306 48307 console.warn( 'THREE.Box3: .empty() has been renamed to .isEmpty().' ); 48308 return this.isEmpty(); 48309 48310 }, 48311 isIntersectionBox: function ( box ) { 48312 48313 console.warn( 'THREE.Box3: .isIntersectionBox() has been renamed to .intersectsBox().' ); 48314 return this.intersectsBox( box ); 48315 48316 }, 48317 isIntersectionSphere: function ( sphere ) { 48318 48319 console.warn( 'THREE.Box3: .isIntersectionSphere() has been renamed to .intersectsSphere().' ); 48320 return this.intersectsSphere( sphere ); 48321 48322 }, 48323 size: function ( optionalTarget ) { 48324 48325 console.warn( 'THREE.Box3: .size() has been renamed to .getSize().' ); 48326 return this.getSize( optionalTarget ); 48327 48328 } 48329 } ); 48330 48331 Line3.prototype.center = function ( optionalTarget ) { 48332 48333 console.warn( 'THREE.Line3: .center() has been renamed to .getCenter().' ); 48334 return this.getCenter( optionalTarget ); 48335 48336 }; 48337 48338 Object.assign( _Math, { 48339 48340 random16: function () { 48341 48342 console.warn( 'THREE.Math: .random16() has been deprecated. Use Math.random() instead.' ); 48343 return Math.random(); 48344 48345 }, 48346 48347 nearestPowerOfTwo: function ( value ) { 48348 48349 console.warn( 'THREE.Math: .nearestPowerOfTwo() has been renamed to .floorPowerOfTwo().' ); 48350 return _Math.floorPowerOfTwo( value ); 48351 48352 }, 48353 48354 nextPowerOfTwo: function ( value ) { 48355 48356 console.warn( 'THREE.Math: .nextPowerOfTwo() has been renamed to .ceilPowerOfTwo().' ); 48357 return _Math.ceilPowerOfTwo( value ); 48358 48359 } 48360 48361 } ); 48362 48363 Object.assign( Matrix3.prototype, { 48364
48365 flattenToArrayOffset: function ( array, offset ) { 48366 48367 console.warn( "THREE.Matrix3: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." ); 48368 return this.toArray( array, offset ); 48369 48370 }, 48371 multiplyVector3: function ( vector ) { 48372 48373 console.warn( 'THREE.Matrix3: .multiplyVector3() has been removed. Use vector.applyMatrix3( matrix ) instead.' ); 48374 return vector.applyMatrix3( this ); 48375 48376 }, 48377 multiplyVector3Array: function ( /* a */ ) { 48378 48379 console.error( 'THREE.Matrix3: .multiplyVector3Array() has been removed.' ); 48380 48381 }, 48382 applyToBuffer: function ( buffer /*, offset, length */ ) { 48383 48384 console.warn( 'THREE.Matrix3: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' ); 48385 return this.applyToBufferAttribute( buffer ); 48386 48387 }, 48388 applyToVector3Array: function ( /* array, offset, length */ ) { 48389 48390 console.error( 'THREE.Matrix3: .applyToVector3Array() has been removed.' ); 48391 48392 } 48393 48394 } ); 48395 48396 Object.assign( Matrix4.prototype, { 48397 48398 extractPosition: function ( m ) { 48399 48400 console.warn( 'THREE.Matrix4: .extractPosition() has been renamed to .copyPosition().' ); 48401 return this.copyPosition( m ); 48402 48403 }, 48404 flattenToArrayOffset: function ( array, offset ) { 48405 48406 console.warn( "THREE.Matrix4: .flattenToArrayOffset() has been deprecated. Use .toArray() instead." ); 48407 return this.toArray( array, offset ); 48408 48409 }, 48410 getPosition: function () { 48411 48412 var v1; 48413 48414 return function getPosition() { 48415 48416 if ( v1 === undefined ) v1 = new Vector3(); 48417 console.warn( 'THREE.Matrix4: .getPosition() has been removed. Use Vector3.setFromMatrixPosition( matrix ) instead.' ); 48418 return v1.setFromMatrixColumn( this, 3 ); 48419 48420 }; 48421 48422 }(), 48423 setRotationFromQuaternion: function ( q ) { 48424 48425 console.warn( 'THREE.Matrix4: .setRotationFromQuaternion() has been renamed to .makeRotationFromQuaternion().' ); 48426 return this.makeRotationFromQuaternion( q ); 48427 48428 }, 48429 multiplyToArray: function () { 48430 48431 console.warn( 'THREE.Matrix4: .multiplyToArray() has been removed.' ); 48432 48433 }, 48434 multiplyVector3: function ( vector ) { 48435
48436 console.warn( 'THREE.Matrix4: .multiplyVector3() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); 48437 return vector.applyMatrix4( this ); 48438 48439 }, 48440 multiplyVector4: function ( vector ) { 48441 48442 console.warn( 'THREE.Matrix4: .multiplyVector4() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); 48443 return vector.applyMatrix4( this ); 48444 48445 }, 48446 multiplyVector3Array: function ( /* a */ ) { 48447 48448 console.error( 'THREE.Matrix4: .multiplyVector3Array() has been removed.' ); 48449 48450 }, 48451 rotateAxis: function ( v ) { 48452 48453 console.warn( 'THREE.Matrix4: .rotateAxis() has been removed. Use Vector3.transformDirection( matrix ) instead.' ); 48454 v.transformDirection( this ); 48455 48456 }, 48457 crossVector: function ( vector ) { 48458 48459 console.warn( 'THREE.Matrix4: .crossVector() has been removed. Use vector.applyMatrix4( matrix ) instead.' ); 48460 return vector.applyMatrix4( this ); 48461 48462 }, 48463 translate: function () { 48464 48465 console.error( 'THREE.Matrix4: .translate() has been removed.' ); 48466 48467 }, 48468 rotateX: function () { 48469 48470 console.error( 'THREE.Matrix4: .rotateX() has been removed.' ); 48471 48472 }, 48473 rotateY: function () { 48474 48475 console.error( 'THREE.Matrix4: .rotateY() has been removed.' ); 48476 48477 }, 48478 rotateZ: function () { 48479 48480 console.error( 'THREE.Matrix4: .rotateZ() has been removed.' ); 48481 48482 }, 48483 rotateByAxis: function () { 48484 48485 console.error( 'THREE.Matrix4: .rotateByAxis() has been removed.' ); 48486 48487 }, 48488 applyToBuffer: function ( buffer /*, offset, length */ ) { 48489 48490 console.warn( 'THREE.Matrix4: .applyToBuffer() has been removed. Use matrix.applyToBufferAttribute( attribute ) instead.' ); 48491 return this.applyToBufferAttribute( buffer ); 48492 48493 }, 48494 applyToVector3Array: function ( /* array, offset, length */ ) { 48495 48496 console.error( 'THREE.Matrix4: .applyToVector3Array() has been removed.' ); 48497 48498 }, 48499 makeFrustum: function ( left, right, bottom, top, near, far ) { 48500 48501 console.warn( 'THREE.Matrix4: .makeFrustum() has been removed. Use .makePerspective( left, right, top, bottom, near, far ) instead.' ); 48502 return this.makePerspective( left, right, top, bottom, near, far ); 48503 48504 } 48505 48506 } ); 48507 48508 Plane.prototype.isIntersectionLine = function ( line ) { 48509 48510 console.warn( 'THREE.Plane: .isIntersectionLine() has been renamed to .intersectsLine().' ); 48511 return this.intersectsLine( line ); 48512 48513 }; 48514 48515 Quaternion.prototype.multiplyVector3 = function ( vector ) { 48516
48517 console.warn( 'THREE.Quaternion: .multiplyVector3() has been removed. Use is now vector.applyQuaternion( quaternion ) instead.' ); 48518 return vector.applyQuaternion( this ); 48519 48520 }; 48521 48522 Object.assign( Ray.prototype, { 48523 48524 isIntersectionBox: function ( box ) { 48525 48526 console.warn( 'THREE.Ray: .isIntersectionBox() has been renamed to .intersectsBox().' ); 48527 return this.intersectsBox( box ); 48528 48529 }, 48530 isIntersectionPlane: function ( plane ) { 48531 48532 console.warn( 'THREE.Ray: .isIntersectionPlane() has been renamed to .intersectsPlane().' ); 48533 return this.intersectsPlane( plane ); 48534 48535 }, 48536 isIntersectionSphere: function ( sphere ) { 48537 48538 console.warn( 'THREE.Ray: .isIntersectionSphere() has been renamed to .intersectsSphere().' ); 48539 return this.intersectsSphere( sphere ); 48540 48541 } 48542 48543 } ); 48544 48545 Object.assign( Triangle.prototype, { 48546 48547 area: function () { 48548 48549 console.warn( 'THREE.Triangle: .area() has been renamed to .getArea().' ); 48550 return this.getArea(); 48551 48552 }, 48553 barycoordFromPoint: function ( point, target ) { 48554 48555 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' ); 48556 return this.getBarycoord( point, target ); 48557 48558 }, 48559 midpoint: function ( target ) { 48560 48561 console.warn( 'THREE.Triangle: .midpoint() has been renamed to .getMidpoint().' ); 48562 return this.getMidpoint( target ); 48563 48564 }, 48565 normal: function ( target ) { 48566 48567 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' ); 48568 return this.getNormal( target ); 48569 48570 }, 48571 plane: function ( target ) { 48572 48573 console.warn( 'THREE.Triangle: .plane() has been renamed to .getPlane().' ); 48574 return this.getPlane( target ); 48575 48576 } 48577 48578 } ); 48579 48580 Object.assign( Triangle, { 48581 48582 barycoordFromPoint: function ( point, a, b, c, target ) { 48583 48584 console.warn( 'THREE.Triangle: .barycoordFromPoint() has been renamed to .getBarycoord().' ); 48585 return Triangle.getBarycoord( point, a, b, c, target ); 48586 48587 }, 48588 normal: function ( a, b, c, target ) { 48589 48590 console.warn( 'THREE.Triangle: .normal() has been renamed to .getNormal().' ); 48591 return Triangle.getNormal( a, b, c, target ); 48592 48593 } 48594 48595 } ); 48596 48597 Object.assign( Shape.prototype, { 48598
48599 extractAllPoints: function ( divisions ) { 48600 48601 console.warn( 'THREE.Shape: .extractAllPoints() has been removed. Use .extractPoints() instead.' ); 48602 return this.extractPoints( divisions ); 48603 48604 }, 48605 extrude: function ( options ) { 48606 48607 console.warn( 'THREE.Shape: .extrude() has been removed. Use ExtrudeGeometry() instead.' ); 48608 return new ExtrudeGeometry( this, options ); 48609 48610 }, 48611 makeGeometry: function ( options ) { 48612 48613 console.warn( 'THREE.Shape: .makeGeometry() has been removed. Use ShapeGeometry() instead.' ); 48614 return new ShapeGeometry( this, options ); 48615 48616 } 48617 48618 } ); 48619 48620 Object.assign( Vector2.prototype, { 48621 48622 fromAttribute: function ( attribute, index, offset ) { 48623 48624 console.warn( 'THREE.Vector2: .fromAttribute() has been renamed to .fromBufferAttribute().' ); 48625 return this.fromBufferAttribute( attribute, index, offset ); 48626 48627 }, 48628 distanceToManhattan: function ( v ) { 48629 48630 console.warn( 'THREE.Vector2: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' ); 48631 return this.manhattanDistanceTo( v ); 48632 48633 }, 48634 lengthManhattan: function () { 48635 48636 console.warn( 'THREE.Vector2: .lengthManhattan() has been renamed to .manhattanLength().' ); 48637 return this.manhattanLength(); 48638 48639 } 48640 48641 } ); 48642 48643 Object.assign( Vector3.prototype, { 48644
48645 setEulerFromRotationMatrix: function () { 48646 48647 console.error( 'THREE.Vector3: .setEulerFromRotationMatrix() has been removed. Use Euler.setFromRotationMatrix() instead.' ); 48648 48649 }, 48650 setEulerFromQuaternion: function () { 48651 48652 console.error( 'THREE.Vector3: .setEulerFromQuaternion() has been removed. Use Euler.setFromQuaternion() instead.' ); 48653 48654 }, 48655 getPositionFromMatrix: function ( m ) { 48656 48657 console.warn( 'THREE.Vector3: .getPositionFromMatrix() has been renamed to .setFromMatrixPosition().' ); 48658 return this.setFromMatrixPosition( m ); 48659 48660 }, 48661 getScaleFromMatrix: function ( m ) { 48662 48663 console.warn( 'THREE.Vector3: .getScaleFromMatrix() has been renamed to .setFromMatrixScale().' ); 48664 return this.setFromMatrixScale( m ); 48665 48666 }, 48667 getColumnFromMatrix: function ( index, matrix ) { 48668 48669 console.warn( 'THREE.Vector3: .getColumnFromMatrix() has been renamed to .setFromMatrixColumn().' ); 48670 return this.setFromMatrixColumn( matrix, index ); 48671 48672 }, 48673 applyProjection: function ( m ) { 48674 48675 console.warn( 'THREE.Vector3: .applyProjection() has been removed. Use .applyMatrix4( m ) instead.' ); 48676 return this.applyMatrix4( m ); 48677 48678 }, 48679 fromAttribute: function ( attribute, index, offset ) { 48680 48681 console.warn( 'THREE.Vector3: .fromAttribute() has been renamed to .fromBufferAttribute().' ); 48682 return this.fromBufferAttribute( attribute, index, offset ); 48683 48684 }, 48685 distanceToManhattan: function ( v ) { 48686 48687 console.warn( 'THREE.Vector3: .distanceToManhattan() has been renamed to .manhattanDistanceTo().' ); 48688 return this.manhattanDistanceTo( v ); 48689 48690 }, 48691 lengthManhattan: function () { 48692 48693 console.warn( 'THREE.Vector3: .lengthManhattan() has been renamed to .manhattanLength().' ); 48694 return this.manhattanLength(); 48695 48696 } 48697 48698 } ); 48699 48700 Object.assign( Vector4.prototype, { 48701
48702 fromAttribute: function ( attribute, index, offset ) { 48703 48704 console.warn( 'THREE.Vector4: .fromAttribute() has been renamed to .fromBufferAttribute().' ); 48705 return this.fromBufferAttribute( attribute, index, offset ); 48706 48707 }, 48708 lengthManhattan: function () { 48709 48710 console.warn( 'THREE.Vector4: .lengthManhattan() has been renamed to .manhattanLength().' ); 48711 return this.manhattanLength(); 48712 48713 } 48714 48715 } ); 48716 48717 // 48718 48719 Object.assign( Geometry.prototype, { 48720 48721 computeTangents: function () { 48722 48723 console.error( 'THREE.Geometry: .computeTangents() has been removed.' ); 48724 48725 }, 48726 computeLineDistances: function () { 48727 48728 console.error( 'THREE.Geometry: .computeLineDistances() has been removed. Use THREE.Line.computeLineDistances() instead.' ); 48729 48730 } 48731 48732 } ); 48733 48734 Object.assign( Object3D.prototype, { 48735 48736 getChildByName: function ( name ) { 48737 48738 console.warn( 'THREE.Object3D: .getChildByName() has been renamed to .getObjectByName().' ); 48739 return this.getObjectByName( name ); 48740 48741 }, 48742 renderDepth: function () { 48743 48744 console.warn( 'THREE.Object3D: .renderDepth has been removed. Use .renderOrder, instead.' ); 48745 48746 }, 48747 translate: function ( distance, axis ) { 48748 48749 console.warn( 'THREE.Object3D: .translate() has been removed. Use .translateOnAxis( axis, distance ) instead.' ); 48750 return this.translateOnAxis( axis, distance ); 48751 48752 }, 48753 getWorldRotation: function () { 48754 48755 console.error( 'THREE.Object3D: .getWorldRotation() has been removed. Use THREE.Object3D.getWorldQuaternion( target ) instead.' ); 48756 48757 } 48758 48759 } ); 48760 48761 Object.defineProperties( Object3D.prototype, { 48762
vendor: 4,278 bytes, lines 48763-48958
48763 eulerOrder: { 48764 get: function () { 48765 48766 console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' ); 48767 return this.rotation.order; 48768 48769 }, 48770 set: function ( value ) { 48771 48772 console.warn( 'THREE.Object3D: .eulerOrder is now .rotation.order.' ); 48773 this.rotation.order = value; 48774 48775 } 48776 }, 48777 useQuaternion: { 48778 get: function () { 48779 48780 console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); 48781 48782 }, 48783 set: function () { 48784 48785 console.warn( 'THREE.Object3D: .useQuaternion has been removed. The library now uses quaternions by default.' ); 48786 48787 } 48788 } 48789 48790 } ); 48791 48792 Object.defineProperties( LOD.prototype, { 48793 48794 objects: { 48795 get: function () { 48796 48797 console.warn( 'THREE.LOD: .objects has been renamed to .levels.' ); 48798 return this.levels; 48799 48800 } 48801 } 48802 48803 } ); 48804 48805 Object.defineProperty( Skeleton.prototype, 'useVertexTexture', { 48806 48807 get: function () { 48808 48809 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' ); 48810 48811 }, 48812 set: function () { 48813 48814 console.warn( 'THREE.Skeleton: useVertexTexture has been removed.' ); 48815 48816 } 48817 48818 } ); 48819 48820 Object.defineProperty( Curve.prototype, '__arcLengthDivisions', { 48821 48822 get: function () { 48823 48824 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); 48825 return this.arcLengthDivisions; 48826 48827 }, 48828 set: function ( value ) { 48829 48830 console.warn( 'THREE.Curve: .__arcLengthDivisions is now .arcLengthDivisions.' ); 48831 this.arcLengthDivisions = value; 48832 48833 } 48834 48835 } ); 48836 48837 // 48838 48839 PerspectiveCamera.prototype.setLens = function ( focalLength, filmGauge ) { 48840 48841 console.warn( "THREE.PerspectiveCamera.setLens is deprecated. " + 48842 "Use .setFocalLength and .filmGauge for a photographic setup." ); 48843 48844 if ( filmGauge !== undefined ) this.filmGauge = filmGauge; 48845 this.setFocalLength( focalLength ); 48846 48847 }; 48848 48849 // 48850 48851 Object.defineProperties( Light.prototype, { 48852 onlyShadow: { 48853 set: function () { 48854 48855 console.warn( 'THREE.Light: .onlyShadow has been removed.' ); 48856 48857 } 48858 }, 48859 shadowCameraFov: { 48860 set: function ( value ) { 48861 48862 console.warn( 'THREE.Light: .shadowCameraFov is now .shadow.camera.fov.' ); 48863 this.shadow.camera.fov = value; 48864 48865 } 48866 }, 48867 shadowCameraLeft: { 48868 set: function ( value ) { 48869 48870 console.warn( 'THREE.Light: .shadowCameraLeft is now .shadow.camera.left.' ); 48871 this.shadow.camera.left = value; 48872 48873 } 48874 }, 48875 shadowCameraRight: { 48876 set: function ( value ) { 48877 48878 console.warn( 'THREE.Light: .shadowCameraRight is now .shadow.camera.right.' ); 48879 this.shadow.camera.right = value; 48880 48881 } 48882 }, 48883 shadowCameraTop: { 48884 set: function ( value ) { 48885 48886 console.warn( 'THREE.Light: .shadowCameraTop is now .shadow.camera.top.' ); 48887 this.shadow.camera.top = value; 48888 48889 } 48890 }, 48891 shadowCameraBottom: { 48892 set: function ( value ) { 48893 48894 console.warn( 'THREE.Light: .shadowCameraBottom is now .shadow.camera.bottom.' ); 48895 this.shadow.camera.bottom = value; 48896 48897 } 48898 }, 48899 shadowCameraNear: { 48900 set: function ( value ) { 48901 48902 console.warn( 'THREE.Light: .shadowCameraNear is now .shadow.camera.near.' ); 48903 this.shadow.camera.near = value; 48904 48905 } 48906 }, 48907 shadowCameraFar: { 48908 set: function ( value ) { 48909 48910 console.warn( 'THREE.Light: .shadowCameraFar is now .shadow.camera.far.' ); 48911 this.shadow.camera.far = value; 48912 48913 } 48914 }, 48915 shadowCameraVisible: { 48916 set: function () { 48917 48918 console.warn( 'THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.' ); 48919 48920 } 48921 }, 48922 shadowBias: { 48923 set: function ( value ) { 48924 48925 console.warn( 'THREE.Light: .shadowBias is now .shadow.bias.' ); 48926 this.shadow.bias = value; 48927 48928 } 48929 }, 48930 shadowDarkness: { 48931 set: function () { 48932 48933 console.warn( 'THREE.Light: .shadowDarkness has been removed.' ); 48934 48935 } 48936 }, 48937 shadowMapWidth: { 48938 set: function ( value ) { 48939 48940 console.warn( 'THREE.Light: .shadowMapWidth is now .shadow.mapSize.width.' ); 48941 this.shadow.mapSize.width = value; 48942 48943 } 48944 }, 48945 shadowMapHeight: { 48946 set: function ( value ) { 48947 48948 console.warn( 'THREE.Light: .shadowMapHeight is now .shadow.mapSize.height.' ); 48949 this.shadow.mapSize.height = value; 48950 48951 } 48952 } 48953 } ); 48954 48955 // 48956 48957 Object.defineProperties( BufferAttribute.prototype, { 48958
vendor: 1,325 bytes, lines 48959-49014
48959 length: { 48960 get: function () { 48961 48962 console.warn( 'THREE.BufferAttribute: .length has been deprecated. Use .count instead.' ); 48963 return this.array.length; 48964 48965 } 48966 }, 48967 copyIndicesArray: function ( /* indices */ ) { 48968 48969 console.error( 'THREE.BufferAttribute: .copyIndicesArray() has been removed.' ); 48970 48971 } 48972 48973 } ); 48974 48975 Object.assign( BufferGeometry.prototype, { 48976 48977 addIndex: function ( index ) { 48978 48979 console.warn( 'THREE.BufferGeometry: .addIndex() has been renamed to .setIndex().' ); 48980 this.setIndex( index ); 48981 48982 }, 48983 addDrawCall: function ( start, count, indexOffset ) { 48984 48985 if ( indexOffset !== undefined ) { 48986 48987 console.warn( 'THREE.BufferGeometry: .addDrawCall() no longer supports indexOffset.' ); 48988 48989 } 48990 console.warn( 'THREE.BufferGeometry: .addDrawCall() is now .addGroup().' ); 48991 this.addGroup( start, count ); 48992 48993 }, 48994 clearDrawCalls: function () { 48995 48996 console.warn( 'THREE.BufferGeometry: .clearDrawCalls() is now .clearGroups().' ); 48997 this.clearGroups(); 48998 48999 }, 49000 computeTangents: function () { 49001 49002 console.warn( 'THREE.BufferGeometry: .computeTangents() has been removed.' ); 49003 49004 }, 49005 computeOffsets: function () { 49006 49007 console.warn( 'THREE.BufferGeometry: .computeOffsets() has been removed.' ); 49008 49009 } 49010 49011 } ); 49012 49013 Object.defineProperties( BufferGeometry.prototype, { 49014
vendor: 1,232 bytes, lines 49015-49083
49015 drawcalls: { 49016 get: function () { 49017 49018 console.error( 'THREE.BufferGeometry: .drawcalls has been renamed to .groups.' ); 49019 return this.groups; 49020 49021 } 49022 }, 49023 offsets: { 49024 get: function () { 49025 49026 console.warn( 'THREE.BufferGeometry: .offsets has been renamed to .groups.' ); 49027 return this.groups; 49028 49029 } 49030 } 49031 49032 } ); 49033 49034 // 49035 49036 Object.assign( ExtrudeBufferGeometry.prototype, { 49037 49038 getArrays: function () { 49039 49040 console.error( 'THREE.ExtrudeBufferGeometry: .getArrays() has been removed.' ); 49041 49042 }, 49043 49044 addShapeList: function () { 49045 49046 console.error( 'THREE.ExtrudeBufferGeometry: .addShapeList() has been removed.' ); 49047 49048 }, 49049 49050 addShape: function () { 49051 49052 console.error( 'THREE.ExtrudeBufferGeometry: .addShape() has been removed.' ); 49053 49054 } 49055 49056 } ); 49057 49058 // 49059 49060 Object.defineProperties( Uniform.prototype, { 49061 49062 dynamic: { 49063 set: function () { 49064 49065 console.warn( 'THREE.Uniform: .dynamic has been removed. Use object.onBeforeRender() instead.' ); 49066 49067 } 49068 }, 49069 onUpdate: { 49070 value: function () { 49071 49072 console.warn( 'THREE.Uniform: .onUpdate() has been removed. Use object.onBeforeRender() instead.' ); 49073 return this; 49074 49075 } 49076 } 49077 49078 } ); 49079 49080 // 49081 49082 Object.defineProperties( Material.prototype, { 49083
vendor: 1,204 bytes, lines 49084-49140
49084 wrapAround: { 49085 get: function () { 49086 49087 console.warn( 'THREE.Material: .wrapAround has been removed.' ); 49088 49089 }, 49090 set: function () { 49091 49092 console.warn( 'THREE.Material: .wrapAround has been removed.' ); 49093 49094 } 49095 }, 49096 wrapRGB: { 49097 get: function () { 49098 49099 console.warn( 'THREE.Material: .wrapRGB has been removed.' ); 49100 return new Color(); 49101 49102 } 49103 }, 49104 49105 shading: { 49106 get: function () { 49107 49108 console.error( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); 49109 49110 }, 49111 set: function ( value ) { 49112 49113 console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' ); 49114 this.flatShading = ( value === FlatShading ); 49115 49116 } 49117 } 49118 49119 } ); 49120 49121 Object.defineProperties( MeshPhongMaterial.prototype, { 49122 49123 metal: { 49124 get: function () { 49125 49126 console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead.' ); 49127 return false; 49128 49129 }, 49130 set: function () { 49131 49132 console.warn( 'THREE.MeshPhongMaterial: .metal has been removed. Use THREE.MeshStandardMaterial instead' ); 49133 49134 } 49135 } 49136 49137 } ); 49138 49139 Object.defineProperties( ShaderMaterial.prototype, { 49140
vendor: 4,060 bytes, lines 49141-49280
49141 derivatives: { 49142 get: function () { 49143 49144 console.warn( 'THREE.ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' ); 49145 return this.extensions.derivatives; 49146 49147 }, 49148 set: function ( value ) { 49149 49150 console.warn( 'THREE. ShaderMaterial: .derivatives has been moved to .extensions.derivatives.' ); 49151 this.extensions.derivatives = value; 49152 49153 } 49154 } 49155 49156 } ); 49157 49158 // 49159 49160 Object.assign( WebGLRenderer.prototype, { 49161 49162 animate: function ( callback ) { 49163 49164 console.warn( 'THREE.WebGLRenderer: .animate() is now .setAnimationLoop().' ); 49165 this.setAnimationLoop( callback ); 49166 49167 }, 49168 49169 getCurrentRenderTarget: function () { 49170 49171 console.warn( 'THREE.WebGLRenderer: .getCurrentRenderTarget() is now .getRenderTarget().' ); 49172 return this.getRenderTarget(); 49173 49174 }, 49175 49176 getMaxAnisotropy: function () { 49177 49178 console.warn( 'THREE.WebGLRenderer: .getMaxAnisotropy() is now .capabilities.getMaxAnisotropy().' ); 49179 return this.capabilities.getMaxAnisotropy(); 49180 49181 }, 49182 49183 getPrecision: function () { 49184 49185 console.warn( 'THREE.WebGLRenderer: .getPrecision() is now .capabilities.precision.' ); 49186 return this.capabilities.precision; 49187 49188 }, 49189 49190 resetGLState: function () { 49191 49192 console.warn( 'THREE.WebGLRenderer: .resetGLState() is now .state.reset().' ); 49193 return this.state.reset(); 49194 49195 }, 49196 49197 supportsFloatTextures: function () { 49198 49199 console.warn( 'THREE.WebGLRenderer: .supportsFloatTextures() is now .extensions.get( \'OES_texture_float\' ).' ); 49200 return this.extensions.get( 'OES_texture_float' ); 49201 49202 }, 49203 supportsHalfFloatTextures: function () { 49204 49205 console.warn( 'THREE.WebGLRenderer: .supportsHalfFloatTextures() is now .extensions.get( \'OES_texture_half_float\' ).' ); 49206 return this.extensions.get( 'OES_texture_half_float' ); 49207 49208 }, 49209 supportsStandardDerivatives: function () { 49210 49211 console.warn( 'THREE.WebGLRenderer: .supportsStandardDerivatives() is now .extensions.get( \'OES_standard_derivatives\' ).' ); 49212 return this.extensions.get( 'OES_standard_derivatives' ); 49213 49214 }, 49215 supportsCompressedTextureS3TC: function () { 49216 49217 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTextureS3TC() is now .extensions.get( \'WEBGL_compressed_texture_s3tc\' ).' ); 49218 return this.extensions.get( 'WEBGL_compressed_texture_s3tc' ); 49219 49220 }, 49221 supportsCompressedTexturePVRTC: function () { 49222 49223 console.warn( 'THREE.WebGLRenderer: .supportsCompressedTexturePVRTC() is now .extensions.get( \'WEBGL_compressed_texture_pvrtc\' ).' ); 49224 return this.extensions.get( 'WEBGL_compressed_texture_pvrtc' ); 49225 49226 }, 49227 supportsBlendMinMax: function () { 49228 49229 console.warn( 'THREE.WebGLRenderer: .supportsBlendMinMax() is now .extensions.get( \'EXT_blend_minmax\' ).' ); 49230 return this.extensions.get( 'EXT_blend_minmax' ); 49231 49232 }, 49233 supportsVertexTextures: function () { 49234 49235 console.warn( 'THREE.WebGLRenderer: .supportsVertexTextures() is now .capabilities.vertexTextures.' ); 49236 return this.capabilities.vertexTextures; 49237 49238 }, 49239 supportsInstancedArrays: function () { 49240 49241 console.warn( 'THREE.WebGLRenderer: .supportsInstancedArrays() is now .extensions.get( \'ANGLE_instanced_arrays\' ).' ); 49242 return this.extensions.get( 'ANGLE_instanced_arrays' ); 49243 49244 }, 49245 enableScissorTest: function ( boolean ) { 49246 49247 console.warn( 'THREE.WebGLRenderer: .enableScissorTest() is now .setScissorTest().' ); 49248 this.setScissorTest( boolean ); 49249 49250 }, 49251 initMaterial: function () { 49252 49253 console.warn( 'THREE.WebGLRenderer: .initMaterial() has been removed.' ); 49254 49255 }, 49256 addPrePlugin: function () { 49257 49258 console.warn( 'THREE.WebGLRenderer: .addPrePlugin() has been removed.' ); 49259 49260 }, 49261 addPostPlugin: function () { 49262 49263 console.warn( 'THREE.WebGLRenderer: .addPostPlugin() has been removed.' ); 49264 49265 }, 49266 updateShadowMap: function () { 49267 49268 console.warn( 'THREE.WebGLRenderer: .updateShadowMap() has been removed.' ); 49269 49270 }, 49271 setFaceCulling: function () { 49272 49273 console.warn( 'THREE.WebGLRenderer: .setFaceCulling() has been removed.' ); 49274 49275 } 49276 49277 } ); 49278 49279 Object.defineProperties( WebGLRenderer.prototype, { 49280
49281 shadowMapEnabled: { 49282 get: function () { 49283 49284 return this.shadowMap.enabled; 49285 49286 }, 49287 set: function ( value ) { 49288 49289 console.warn( 'THREE.WebGLRenderer: .shadowMapEnabled is now .shadowMap.enabled.' ); 49290 this.shadowMap.enabled = value; 49291 49292 } 49293 }, 49294 shadowMapType: { 49295 get: function () { 49296 49297 return this.shadowMap.type; 49298 49299 }, 49300 set: function ( value ) { 49301 49302 console.warn( 'THREE.WebGLRenderer: .shadowMapType is now .shadowMap.type.' ); 49303 this.shadowMap.type = value; 49304 49305 } 49306 }, 49307 shadowMapCullFace: { 49308 get: function () { 49309 49310 console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' ); 49311 return undefined; 49312 49313 }, 49314 set: function ( /* value */ ) { 49315 49316 console.warn( 'THREE.WebGLRenderer: .shadowMapCullFace has been removed. Set Material.shadowSide instead.' ); 49317 49318 } 49319 } 49320 } ); 49321 49322 Object.defineProperties( WebGLShadowMap.prototype, { 49323 49324 cullFace: { 49325 get: function () { 49326 49327 console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' ); 49328 return undefined; 49329 49330 }, 49331 set: function ( /* cullFace */ ) { 49332 49333 console.warn( 'THREE.WebGLRenderer: .shadowMap.cullFace has been removed. Set Material.shadowSide instead.' ); 49334 49335 } 49336 }, 49337 renderReverseSided: { 49338 get: function () { 49339 49340 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' ); 49341 return undefined; 49342 49343 }, 49344 set: function () { 49345 49346 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderReverseSided has been removed. Set Material.shadowSide instead.' ); 49347 49348 } 49349 }, 49350 renderSingleSided: { 49351 get: function () { 49352 49353 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' ); 49354 return undefined; 49355 49356 }, 49357 set: function () { 49358 49359 console.warn( 'THREE.WebGLRenderer: .shadowMap.renderSingleSided has been removed. Set Material.shadowSide instead.' ); 49360 49361 } 49362 } 49363 49364 } ); 49365 49366 // 49367 49368 Object.defineProperties( WebGLRenderTarget.prototype, { 49369
49370 wrapS: { 49371 get: function () { 49372 49373 console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' ); 49374 return this.texture.wrapS; 49375 49376 }, 49377 set: function ( value ) { 49378 49379 console.warn( 'THREE.WebGLRenderTarget: .wrapS is now .texture.wrapS.' ); 49380 this.texture.wrapS = value; 49381 49382 } 49383 }, 49384 wrapT: { 49385 get: function () { 49386 49387 console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' ); 49388 return this.texture.wrapT; 49389 49390 }, 49391 set: function ( value ) { 49392 49393 console.warn( 'THREE.WebGLRenderTarget: .wrapT is now .texture.wrapT.' ); 49394 this.texture.wrapT = value; 49395 49396 } 49397 }, 49398 magFilter: { 49399 get: function () { 49400 49401 console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' ); 49402 return this.texture.magFilter; 49403 49404 }, 49405 set: function ( value ) { 49406 49407 console.warn( 'THREE.WebGLRenderTarget: .magFilter is now .texture.magFilter.' ); 49408 this.texture.magFilter = value; 49409 49410 } 49411 }, 49412 minFilter: { 49413 get: function () { 49414 49415 console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' ); 49416 return this.texture.minFilter; 49417 49418 }, 49419 set: function ( value ) { 49420 49421 console.warn( 'THREE.WebGLRenderTarget: .minFilter is now .texture.minFilter.' ); 49422 this.texture.minFilter = value; 49423 49424 } 49425 }, 49426 anisotropy: { 49427 get: function () { 49428 49429 console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' ); 49430 return this.texture.anisotropy; 49431 49432 }, 49433 set: function ( value ) { 49434 49435 console.warn( 'THREE.WebGLRenderTarget: .anisotropy is now .texture.anisotropy.' ); 49436 this.texture.anisotropy = value; 49437 49438 } 49439 }, 49440 offset: { 49441 get: function () { 49442 49443 console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' ); 49444 return this.texture.offset; 49445 49446 }, 49447 set: function ( value ) { 49448 49449 console.warn( 'THREE.WebGLRenderTarget: .offset is now .texture.offset.' ); 49450 this.texture.offset = value; 49451 49452 } 49453 }, 49454 repeat: { 49455 get: function () { 49456 49457 console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' ); 49458 return this.texture.repeat; 49459 49460 }, 49461 set: function ( value ) { 49462 49463 console.warn( 'THREE.WebGLRenderTarget: .repeat is now .texture.repeat.' ); 49464 this.texture.repeat = value; 49465 49466 } 49467 }, 49468 format: { 49469 get: function () { 49470 49471 console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' ); 49472 return this.texture.format; 49473 49474 }, 49475 set: function ( value ) { 49476 49477 console.warn( 'THREE.WebGLRenderTarget: .format is now .texture.format.' ); 49478 this.texture.format = value; 49479 49480 } 49481 }, 49482 type: { 49483 get: function () { 49484 49485 console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' ); 49486 return this.texture.type; 49487 49488 }, 49489 set: function ( value ) { 49490 49491 console.warn( 'THREE.WebGLRenderTarget: .type is now .texture.type.' ); 49492 this.texture.type = value; 49493 49494 } 49495 }, 49496 generateMipmaps: { 49497 get: function () { 49498 49499 console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' ); 49500 return this.texture.generateMipmaps; 49501 49502 }, 49503 set: function ( value ) { 49504 49505 console.warn( 'THREE.WebGLRenderTarget: .generateMipmaps is now .texture.generateMipmaps.' ); 49506 this.texture.generateMipmaps = value; 49507 49508 } 49509 } 49510 49511 } ); 49512 49513 // 49514 49515 Object.defineProperties( WebVRManager.prototype, { 49516
vendor: 4,336 bytes, lines 49517-49744
49517 standing: { 49518 set: function ( /* value */ ) { 49519 49520 console.warn( 'THREE.WebVRManager: .standing has been removed.' ); 49521 49522 } 49523 } 49524 49525 } ); 49526 49527 // 49528 49529 Audio.prototype.load = function ( file ) { 49530 49531 console.warn( 'THREE.Audio: .load has been deprecated. Use THREE.AudioLoader instead.' ); 49532 var scope = this; 49533 var audioLoader = new AudioLoader(); 49534 audioLoader.load( file, function ( buffer ) { 49535 49536 scope.setBuffer( buffer ); 49537 49538 } ); 49539 return this; 49540 49541 }; 49542 49543 AudioAnalyser.prototype.getData = function () { 49544 49545 console.warn( 'THREE.AudioAnalyser: .getData() is now .getFrequencyData().' ); 49546 return this.getFrequencyData(); 49547 49548 }; 49549 49550 // 49551 49552 CubeCamera.prototype.updateCubeMap = function ( renderer, scene ) { 49553 49554 console.warn( 'THREE.CubeCamera: .updateCubeMap() is now .update().' ); 49555 return this.update( renderer, scene ); 49556 49557 }; 49558 49559 /** 49560 * @author dmarcos / https://github.com/dmarcos 49561 * @author mrdoob / http://mrdoob.com 49562 */ 49563 var VRControls = function ( object, onError ) { 49564 49565 var scope = this; 49566 49567 var vrDisplay, vrDisplays; 49568 49569 var standingMatrix = new Matrix4(); 49570 49571 var frameData = null; 49572 49573 if ( 'VRFrameData' in window ) { 49574 49575 frameData = new VRFrameData(); 49576 49577 } 49578 49579 function gotVRDisplays( displays ) { 49580 49581 vrDisplays = displays; 49582 49583 if ( displays.length > 0 ) { 49584 49585 vrDisplay = displays[ 0 ]; 49586 49587 } else { 49588 49589 if ( onError ) onError( 'VR input not available.' ); 49590 49591 } 49592 49593 } 49594 49595 if ( navigator.getVRDisplays ) { 49596 49597 navigator.getVRDisplays().then( gotVRDisplays ).catch( function () { 49598 49599 console.warn( 'VRControls: Unable to get VR Displays' ); 49600 49601 } ); 49602 49603 } 49604 49605 // the Rift SDK returns the position in meters 49606 // this scale factor allows the user to define how meters 49607 // are converted to scene units. 49608 49609 this.scale = 1; 49610 49611 // If true will use "standing space" coordinate system where y=0 is the 49612 // floor and x=0, z=0 is the center of the room. 49613 this.standing = false; 49614 49615 // Distance from the users eyes to the floor in meters. Used when 49616 // standing=true but the VRDisplay doesn't provide stageParameters. 49617 this.userHeight = 1.6; 49618 49619 this.getVRDisplay = function () { 49620 49621 return vrDisplay; 49622 49623 }; 49624 49625 this.setVRDisplay = function ( value ) { 49626 49627 vrDisplay = value; 49628 49629 }; 49630 49631 this.getVRDisplays = function () { 49632 49633 console.warn( 'VRControls: getVRDisplays() is being deprecated.' ); 49634 return vrDisplays; 49635 49636 }; 49637 49638 this.getStandingMatrix = function () { 49639 49640 return standingMatrix; 49641 49642 }; 49643 49644 this.update = function () { 49645 49646 if ( vrDisplay ) { 49647 49648 var pose; 49649 49650 if ( vrDisplay.getFrameData ) { 49651 49652 vrDisplay.getFrameData( frameData ); 49653 pose = frameData.pose; 49654 49655 } else if ( vrDisplay.getPose ) { 49656 49657 pose = vrDisplay.getPose(); 49658 49659 } 49660 49661 if ( pose.orientation !== null ) { 49662 49663 object.quaternion.fromArray( pose.orientation ); 49664 49665 } 49666 49667 if ( pose.position !== null ) { 49668 49669 object.position.fromArray( pose.position ); 49670 49671 } else { 49672 49673 object.position.set( 0, 0, 0 ); 49674 49675 } 49676 49677 if ( this.standing ) { 49678 49679 if ( vrDisplay.stageParameters ) { 49680 49681 object.updateMatrix(); 49682 49683 standingMatrix.fromArray( vrDisplay.stageParameters.sittingToStandingTransform ); 49684 object.applyMatrix( standingMatrix ); 49685 49686 } else { 49687 49688 object.position.setY( object.position.y + this.userHeight ); 49689 49690 } 49691 49692 } 49693 49694 object.position.multiplyScalar( scope.scale ); 49695 49696 } 49697 49698 }; 49699 49700 this.dispose = function () { 49701 49702 vrDisplay = null; 49703 49704 }; 49705 49706 }; 49707 49708 /** 49709 * @author dmarcos / https://github.com/dmarcos 49710 * @author mrdoob / http://mrdoob.com 49711 * 49712 * WebVR Spec: http://mozvr.github.io/webvr-spec/webvr.html 49713 * 49714 * Firefox: http://mozvr.com/downloads/ 49715 * Chromium: https://webvr.info/get-chrome 49716 */ 49717 var VREffect = function ( renderer, onError ) { 49718 49719 var vrDisplay, vrDisplays; 49720 var eyeTranslationL = new Vector3(); 49721 var eyeTranslationR = new Vector3(); 49722 var renderRectL, renderRectR; 49723 var headMatrix = new Matrix4(); 49724 var eyeMatrixL = new Matrix4(); 49725 var eyeMatrixR = new Matrix4(); 49726 49727 var frameData = null; 49728 49729 if ( 'VRFrameData' in window ) { 49730 49731 frameData = new window.VRFrameData(); 49732 49733 } 49734 49735 function gotVRDisplays( displays ) { 49736 49737 vrDisplays = displays; 49738 49739 if ( displays.length > 0 ) { 49740 49741 vrDisplay = displays[ 0 ]; 49742 49743 } else { 49744
vendor: 22,864 bytes, lines 49745-50608
49745 if ( onError ) onError( 'HMD not available' ); 49746 49747 } 49748 49749 } 49750 49751 if ( navigator.getVRDisplays ) { 49752 49753 navigator.getVRDisplays().then( gotVRDisplays ).catch( function () { 49754 49755 console.warn( 'VREffect: Unable to get VR Displays' ); 49756 49757 } ); 49758 49759 } 49760 49761 // 49762 49763 this.isPresenting = false; 49764 49765 var scope = this; 49766 49767 var rendererSize = renderer.getSize(); 49768 var rendererUpdateStyle = false; 49769 var rendererPixelRatio = renderer.getPixelRatio(); 49770 49771 this.getVRDisplay = function () { 49772 49773 return vrDisplay; 49774 49775 }; 49776 49777 this.setVRDisplay = function ( value ) { 49778 49779 vrDisplay = value; 49780 49781 }; 49782 49783 this.getVRDisplays = function () { 49784 49785 console.warn( 'VREffect: getVRDisplays() is being deprecated.' ); 49786 return vrDisplays; 49787 49788 }; 49789 49790 this.setSize = function ( width, height, updateStyle ) { 49791 49792 rendererSize = { width: width, height: height }; 49793 rendererUpdateStyle = updateStyle; 49794 49795 if ( scope.isPresenting ) { 49796 49797 var eyeParamsL = vrDisplay.getEyeParameters( 'left' ); 49798 renderer.setPixelRatio( 1 ); 49799 renderer.setSize( eyeParamsL.renderWidth * 2, eyeParamsL.renderHeight, false ); 49800 49801 } else { 49802 49803 renderer.setPixelRatio( rendererPixelRatio ); 49804 renderer.setSize( width, height, updateStyle ); 49805 49806 } 49807 49808 }; 49809 49810 // VR presentation 49811 49812 var canvas = renderer.domElement; 49813 var defaultLeftBounds = [ 0.0, 0.0, 0.5, 1.0 ]; 49814 var defaultRightBounds = [ 0.5, 0.0, 0.5, 1.0 ]; 49815 49816 function onVRDisplayPresentChange() { 49817 49818 var wasPresenting = scope.isPresenting; 49819 scope.isPresenting = vrDisplay !== undefined && vrDisplay.isPresenting; 49820 49821 if ( scope.isPresenting ) { 49822 49823 var eyeParamsL = vrDisplay.getEyeParameters( 'left' ); 49824 var eyeWidth = eyeParamsL.renderWidth; 49825 var eyeHeight = eyeParamsL.renderHeight; 49826 49827 if ( ! wasPresenting ) { 49828 49829 rendererPixelRatio = renderer.getPixelRatio(); 49830 rendererSize = renderer.getSize(); 49831 49832 renderer.setPixelRatio( 1 ); 49833 renderer.setSize( eyeWidth * 2, eyeHeight, false ); 49834 49835 } 49836 49837 } else if ( wasPresenting ) { 49838 49839 renderer.setPixelRatio( rendererPixelRatio ); 49840 renderer.setSize( rendererSize.width, rendererSize.height, rendererUpdateStyle ); 49841 49842 } 49843 49844 } 49845 49846 window.addEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false ); 49847 49848 this.setFullScreen = function ( boolean ) { 49849 49850 return new Promise( function ( resolve, reject ) { 49851 49852 if ( vrDisplay === undefined ) { 49853 49854 reject( new Error( 'No VR hardware found.' ) ); 49855 return; 49856 49857 } 49858 49859 if ( scope.isPresenting === boolean ) { 49860 49861 resolve(); 49862 return; 49863 49864 } 49865 49866 if ( boolean ) { 49867 49868 resolve( vrDisplay.requestPresent( [ { source: canvas } ] ) ); 49869 49870 } else { 49871 49872 resolve( vrDisplay.exitPresent() ); 49873 49874 } 49875 49876 } ); 49877 49878 }; 49879 49880 this.requestPresent = function () { 49881 49882 return this.setFullScreen( true ); 49883 49884 }; 49885 49886 this.exitPresent = function () { 49887 49888 return this.setFullScreen( false ); 49889 49890 }; 49891 49892 this.requestAnimationFrame = function ( f ) { 49893 49894 if ( vrDisplay !== undefined ) { 49895 49896 return vrDisplay.requestAnimationFrame( f ); 49897 49898 } else { 49899 49900 return window.requestAnimationFrame( f ); 49901 49902 } 49903 49904 }; 49905 49906 this.cancelAnimationFrame = function ( h ) { 49907 49908 if ( vrDisplay !== undefined ) { 49909 49910 vrDisplay.cancelAnimationFrame( h ); 49911 49912 } else { 49913 49914 window.cancelAnimationFrame( h ); 49915 49916 } 49917 49918 }; 49919 49920 this.submitFrame = function () { 49921 49922 if ( vrDisplay !== undefined && scope.isPresenting ) { 49923 49924 vrDisplay.submitFrame(); 49925 49926 } 49927 49928 }; 49929 49930 this.autoSubmitFrame = true; 49931 49932 // render 49933 49934 var cameraL = new PerspectiveCamera(); 49935 cameraL.layers.enable( 1 ); 49936 49937 var cameraR = new PerspectiveCamera(); 49938 cameraR.layers.enable( 2 ); 49939 49940 this.render = function ( scene, camera, renderTarget, forceClear ) { 49941 49942 if ( vrDisplay && scope.isPresenting ) { 49943 49944 var autoUpdate = scene.autoUpdate; 49945 49946 if ( autoUpdate ) { 49947 49948 scene.updateMatrixWorld(); 49949 scene.autoUpdate = false; 49950 49951 } 49952 49953 if ( Array.isArray( scene ) ) { 49954 49955 console.warn( 'VREffect.render() no longer supports arrays. Use object.layers instead.' ); 49956 scene = scene[ 0 ]; 49957 49958 } 49959 49960 // When rendering we don't care what the recommended size is, only what the actual size 49961 // of the backbuffer is. 49962 var size = renderer.getSize(); 49963 var layers = vrDisplay.getLayers(); 49964 var leftBounds; 49965 var rightBounds; 49966 49967 if ( layers.length ) { 49968 49969 var layer = layers[ 0 ]; 49970 49971 leftBounds = layer.leftBounds !== null && layer.leftBounds.length === 4 ? layer.leftBounds : defaultLeftBounds; 49972 rightBounds = layer.rightBounds !== null && layer.rightBounds.length === 4 ? layer.rightBounds : defaultRightBounds; 49973 49974 } else { 49975 49976 leftBounds = defaultLeftBounds; 49977 rightBounds = defaultRightBounds; 49978 49979 } 49980 49981 renderRectL = { 49982 x: Math.round( size.width * leftBounds[ 0 ] ), 49983 y: Math.round( size.height * leftBounds[ 1 ] ), 49984 width: Math.round( size.width * leftBounds[ 2 ] ), 49985 height: Math.round( size.height * leftBounds[ 3 ] ) 49986 }; 49987 renderRectR = { 49988 x: Math.round( size.width * rightBounds[ 0 ] ), 49989 y: Math.round( size.height * rightBounds[ 1 ] ), 49990 width: Math.round( size.width * rightBounds[ 2 ] ), 49991 height: Math.round( size.height * rightBounds[ 3 ] ) 49992 }; 49993 49994 if ( renderTarget ) { 49995 49996 renderer.setRenderTarget( renderTarget ); 49997 renderTarget.scissorTest = true; 49998 49999 } else { 50000 50001 renderer.setRenderTarget( null ); 50002 renderer.setScissorTest( true ); 50003 50004 } 50005 50006 if ( renderer.autoClear || forceClear ) renderer.clear(); 50007 50008 if ( camera.parent === null ) camera.updateMatrixWorld(); 50009 50010 camera.matrixWorld.decompose( cameraL.position, cameraL.quaternion, cameraL.scale ); 50011 50012 cameraR.position.copy( cameraL.position ); 50013 cameraR.quaternion.copy( cameraL.quaternion ); 50014 cameraR.scale.copy( cameraL.scale ); 50015 50016 if ( vrDisplay.getFrameData ) { 50017 50018 vrDisplay.depthNear = camera.near; 50019 vrDisplay.depthFar = camera.far; 50020 50021 vrDisplay.getFrameData( frameData ); 50022 50023 cameraL.projectionMatrix.elements = frameData.leftProjectionMatrix; 50024 cameraR.projectionMatrix.elements = frameData.rightProjectionMatrix; 50025 50026 getEyeMatrices( frameData ); 50027 50028 cameraL.updateMatrix(); 50029 cameraL.matrix.multiply( eyeMatrixL ); 50030 cameraL.matrix.decompose( cameraL.position, cameraL.quaternion, cameraL.scale ); 50031 50032 cameraR.updateMatrix(); 50033 cameraR.matrix.multiply( eyeMatrixR ); 50034 cameraR.matrix.decompose( cameraR.position, cameraR.quaternion, cameraR.scale ); 50035 50036 } else { 50037 50038 var eyeParamsL = vrDisplay.getEyeParameters( 'left' ); 50039 var eyeParamsR = vrDisplay.getEyeParameters( 'right' ); 50040 50041 cameraL.projectionMatrix = fovToProjection( eyeParamsL.fieldOfView, true, camera.near, camera.far ); 50042 cameraR.projectionMatrix = fovToProjection( eyeParamsR.fieldOfView, true, camera.near, camera.far ); 50043 50044 eyeTranslationL.fromArray( eyeParamsL.offset ); 50045 eyeTranslationR.fromArray( eyeParamsR.offset ); 50046 50047 cameraL.translateOnAxis( eyeTranslationL, cameraL.scale.x ); 50048 cameraR.translateOnAxis( eyeTranslationR, cameraR.scale.x ); 50049 50050 } 50051 50052 // render left eye 50053 if ( renderTarget ) { 50054 50055 renderTarget.viewport.set( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height ); 50056 renderTarget.scissor.set( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height ); 50057 50058 } else { 50059 50060 renderer.setViewport( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height ); 50061 renderer.setScissor( renderRectL.x, renderRectL.y, renderRectL.width, renderRectL.height ); 50062 50063 } 50064 renderer.render( scene, cameraL, renderTarget, forceClear ); 50065 50066 // render right eye 50067 if ( renderTarget ) { 50068 50069 renderTarget.viewport.set( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height ); 50070 renderTarget.scissor.set( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height ); 50071 50072 } else { 50073 50074 renderer.setViewport( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height ); 50075 renderer.setScissor( renderRectR.x, renderRectR.y, renderRectR.width, renderRectR.height ); 50076 50077 } 50078 renderer.render( scene, cameraR, renderTarget, forceClear ); 50079 50080 if ( renderTarget ) { 50081 50082 renderTarget.viewport.set( 0, 0, size.width, size.height ); 50083 renderTarget.scissor.set( 0, 0, size.width, size.height ); 50084 renderTarget.scissorTest = false; 50085 renderer.setRenderTarget( null ); 50086 50087 } else { 50088 50089 renderer.setViewport( 0, 0, size.width, size.height ); 50090 renderer.setScissorTest( false ); 50091 50092 } 50093 50094 if ( autoUpdate ) { 50095 50096 scene.autoUpdate = true; 50097 50098 } 50099 50100 if ( scope.autoSubmitFrame ) { 50101 50102 scope.submitFrame(); 50103 50104 } 50105 50106 return; 50107 50108 } 50109 50110 // Regular render mode if not HMD 50111 50112 renderer.render( scene, camera, renderTarget, forceClear ); 50113 50114 }; 50115 50116 this.dispose = function () { 50117 50118 window.removeEventListener( 'vrdisplaypresentchange', onVRDisplayPresentChange, false ); 50119 50120 }; 50121 50122 // 50123 50124 var poseOrientation = new Quaternion(); 50125 var posePosition = new Vector3(); 50126 50127 // Compute model matrices of the eyes with respect to the head. 50128 function getEyeMatrices( frameData ) { 50129 50130 // Compute the matrix for the position of the head based on the pose 50131 if ( frameData.pose.orientation ) { 50132 50133 poseOrientation.fromArray( frameData.pose.orientation ); 50134 headMatrix.makeRotationFromQuaternion( poseOrientation ); 50135 50136 } else { 50137 50138 headMatrix.identity(); 50139 50140 } 50141 50142 if ( frameData.pose.position ) { 50143 50144 posePosition.fromArray( frameData.pose.position ); 50145 headMatrix.setPosition( posePosition ); 50146 50147 } 50148 50149 // The view matrix transforms vertices from sitting space to eye space. As such, the view matrix can be thought of as a product of two matrices: 50150 // headToEyeMatrix * sittingToHeadMatrix 50151 50152 // The headMatrix that we've calculated above is the model matrix of the head in sitting space, which is the inverse of sittingToHeadMatrix. 50153 // So when we multiply the view matrix with headMatrix, we're left with headToEyeMatrix: 50154 // viewMatrix * headMatrix = headToEyeMatrix * sittingToHeadMatrix * headMatrix = headToEyeMatrix 50155 50156 eyeMatrixL.fromArray( frameData.leftViewMatrix ); 50157 eyeMatrixL.multiply( headMatrix ); 50158 eyeMatrixR.fromArray( frameData.rightViewMatrix ); 50159 eyeMatrixR.multiply( headMatrix ); 50160 50161 // The eye's model matrix in head space is the inverse of headToEyeMatrix we calculated above. 50162 50163 eyeMatrixL.getInverse( eyeMatrixL ); 50164 eyeMatrixR.getInverse( eyeMatrixR ); 50165 50166 } 50167 50168 function fovToNDCScaleOffset( fov ) { 50169 50170 var pxscale = 2.0 / ( fov.leftTan + fov.rightTan ); 50171 var pxoffset = ( fov.leftTan - fov.rightTan ) * pxscale * 0.5; 50172 var pyscale = 2.0 / ( fov.upTan + fov.downTan ); 50173 var pyoffset = ( fov.upTan - fov.downTan ) * pyscale * 0.5; 50174 return { scale: [ pxscale, pyscale ], offset: [ pxoffset, pyoffset ] }; 50175 50176 } 50177 50178 function fovPortToProjection( fov, rightHanded, zNear, zFar ) { 50179 50180 rightHanded = rightHanded === undefined ? true : rightHanded; 50181 zNear = zNear === undefined ? 0.01 : zNear; 50182 zFar = zFar === undefined ? 10000.0 : zFar; 50183 50184 var handednessScale = rightHanded ? - 1.0 : 1.0; 50185 50186 // start with an identity matrix 50187 var mobj = new Matrix4(); 50188 var m = mobj.elements; 50189 50190 // and with scale/offset info for normalized device coords 50191 var scaleAndOffset = fovToNDCScaleOffset( fov ); 50192 50193 // X result, map clip edges to [-w,+w] 50194 m[ 0 * 4 + 0 ] = scaleAndOffset.scale[ 0 ]; 50195 m[ 0 * 4 + 1 ] = 0.0; 50196 m[ 0 * 4 + 2 ] = scaleAndOffset.offset[ 0 ] * handednessScale; 50197 m[ 0 * 4 + 3 ] = 0.0; 50198 50199 // Y result, map clip edges to [-w,+w] 50200 // Y offset is negated because this proj matrix transforms from world coords with Y=up, 50201 // but the NDC scaling has Y=down (thanks D3D?) 50202 m[ 1 * 4 + 0 ] = 0.0; 50203 m[ 1 * 4 + 1 ] = scaleAndOffset.scale[ 1 ]; 50204 m[ 1 * 4 + 2 ] = - scaleAndOffset.offset[ 1 ] * handednessScale; 50205 m[ 1 * 4 + 3 ] = 0.0; 50206 50207 // Z result (up to the app) 50208 m[ 2 * 4 + 0 ] = 0.0; 50209 m[ 2 * 4 + 1 ] = 0.0; 50210 m[ 2 * 4 + 2 ] = zFar / ( zNear - zFar ) * - handednessScale; 50211 m[ 2 * 4 + 3 ] = ( zFar * zNear ) / ( zNear - zFar ); 50212 50213 // W result (= Z in) 50214 m[ 3 * 4 + 0 ] = 0.0; 50215 m[ 3 * 4 + 1 ] = 0.0; 50216 m[ 3 * 4 + 2 ] = handednessScale; 50217 m[ 3 * 4 + 3 ] = 0.0; 50218 50219 mobj.transpose(); 50220 return mobj; 50221 50222 } 50223 50224 function fovToProjection( fov, rightHanded, zNear, zFar ) { 50225 50226 var DEG2RAD = Math.PI / 180.0; 50227 50228 var fovPort = { 50229 upTan: Math.tan( fov.upDegrees * DEG2RAD ), 50230 downTan: Math.tan( fov.downDegrees * DEG2RAD ), 50231 leftTan: Math.tan( fov.leftDegrees * DEG2RAD ), 50232 rightTan: Math.tan( fov.rightDegrees * DEG2RAD ) 50233 }; 50234 50235 return fovPortToProjection( fovPort, rightHanded, zNear, zFar ); 50236 50237 } 50238 50239 }; 50240 50241 /** 50242 * @author qiao / https://github.com/qiao 50243 * @author mrdoob / http://mrdoob.com 50244 * @author alteredq / http://alteredqualia.com/ 50245 * @author WestLangley / http://github.com/WestLangley 50246 * @author erich666 / http://erichaines.com 50247 */ 50248 var OrbitControls = function ( object, domElement ) { 50249 50250 this.object = object; 50251 50252 this.domElement = ( domElement !== undefined ) ? domElement : document; 50253 50254 // Set to false to disable this control 50255 this.enabled = true; 50256 50257 // "target" sets the location of focus, where the object orbits around 50258 this.target = new Vector3(); 50259 50260 // How far you can dolly in and out ( PerspectiveCamera only ) 50261 this.minDistance = 0; 50262 this.maxDistance = Infinity; 50263 50264 // How far you can zoom in and out ( OrthographicCamera only ) 50265 this.minZoom = 0; 50266 this.maxZoom = Infinity; 50267 50268 // How far you can orbit vertically, upper and lower limits. 50269 // Range is 0 to Math.PI radians. 50270 this.minPolarAngle = 0; // radians 50271 this.maxPolarAngle = Math.PI; // radians 50272 50273 // How far you can orbit horizontally, upper and lower limits. 50274 // If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ]. 50275 this.minAzimuthAngle = - Infinity; // radians 50276 this.maxAzimuthAngle = Infinity; // radians 50277 50278 // Set to true to enable damping (inertia) 50279 // If damping is enabled, you must call controls.update() in your animation loop 50280 this.enableDamping = false; 50281 this.dampingFactor = 0.25; 50282 50283 // This option actually enables dollying in and out; left as "zoom" for backwards compatibility. 50284 // Set to false to disable zooming 50285 this.enableZoom = true; 50286 this.zoomSpeed = 1.0; 50287 50288 // Set to false to disable rotating 50289 this.enableRotate = true; 50290 this.rotateSpeed = 1.0; 50291 50292 // Set to false to disable panning 50293 this.enablePan = true; 50294 this.panSpeed = 1.0; 50295 this.screenSpacePanning = false; // if true, pan in screen-space 50296 this.keyPanSpeed = 7.0; // pixels moved per arrow key push 50297 50298 // Set to true to automatically rotate around the target 50299 // If auto-rotate is enabled, you must call controls.update() in your animation loop 50300 this.autoRotate = false; 50301 this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60 50302 50303 // Set to false to disable use of the keys 50304 this.enableKeys = true; 50305 50306 // The four arrow keys 50307 this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 }; 50308 50309 // Mouse buttons 50310 this.mouseButtons = { ORBIT: MOUSE.LEFT, ZOOM: MOUSE.MIDDLE, PAN: MOUSE.RIGHT }; 50311 50312 // for reset 50313 this.target0 = this.target.clone(); 50314 this.position0 = this.object.position.clone(); 50315 this.zoom0 = this.object.zoom; 50316 50317 // 50318 // public methods 50319 // 50320 50321 this.getPolarAngle = function () { 50322 50323 return spherical.phi; 50324 50325 }; 50326 50327 this.getAzimuthalAngle = function () { 50328 50329 return spherical.theta; 50330 50331 }; 50332 50333 this.saveState = function () { 50334 50335 scope.target0.copy( scope.target ); 50336 scope.position0.copy( scope.object.position ); 50337 scope.zoom0 = scope.object.zoom; 50338 50339 }; 50340 50341 this.reset = function () { 50342 50343 scope.target.copy( scope.target0 ); 50344 scope.object.position.copy( scope.position0 ); 50345 scope.object.zoom = scope.zoom0; 50346 50347 scope.object.updateProjectionMatrix(); 50348 scope.dispatchEvent( changeEvent ); 50349 50350 scope.update(); 50351 50352 state = STATE.NONE; 50353 50354 }; 50355 50356 // this method is exposed, but perhaps it would be better if we can make it private... 50357 this.update = function () { 50358 50359 var offset = new Vector3(); 50360 50361 // so camera.up is the orbit axis 50362 var quat = new Quaternion().setFromUnitVectors( object.up, new Vector3( 0, 1, 0 ) ); 50363 var quatInverse = quat.clone().inverse(); 50364 50365 var lastPosition = new Vector3(); 50366 var lastQuaternion = new Quaternion(); 50367 50368 return function update() { 50369 50370 var position = scope.object.position; 50371 50372 offset.copy( position ).sub( scope.target ); 50373 50374 // rotate offset to "y-axis-is-up" space 50375 offset.applyQuaternion( quat ); 50376 50377 // angle from z-axis around y-axis 50378 spherical.setFromVector3( offset ); 50379 50380 if ( scope.autoRotate && state === STATE.NONE ) { 50381 50382 scope.rotateLeft( getAutoRotationAngle() ); 50383 50384 } 50385 50386 spherical.theta += sphericalDelta.theta; 50387 spherical.phi += sphericalDelta.phi; 50388 50389 // restrict theta to be between desired limits 50390 spherical.theta = Math.max( scope.minAzimuthAngle, Math.min( scope.maxAzimuthAngle, spherical.theta ) ); 50391 50392 // restrict phi to be between desired limits 50393 spherical.phi = Math.max( scope.minPolarAngle, Math.min( scope.maxPolarAngle, spherical.phi ) ); 50394 50395 spherical.makeSafe(); 50396 50397 50398 spherical.radius *= scale; 50399 50400 // restrict radius to be between desired limits 50401 spherical.radius = Math.max( scope.minDistance, Math.min( scope.maxDistance, spherical.radius ) ); 50402 50403 // move target to panned location 50404 scope.target.add( panOffset ); 50405 50406 offset.setFromSpherical( spherical ); 50407 50408 // rotate offset back to "camera-up-vector-is-up" space 50409 offset.applyQuaternion( quatInverse ); 50410 50411 position.copy( scope.target ).add( offset ); 50412 50413 scope.object.lookAt( scope.target ); 50414 50415 if ( scope.enableDamping === true ) { 50416 50417 sphericalDelta.theta *= ( 1 - scope.dampingFactor ); 50418 sphericalDelta.phi *= ( 1 - scope.dampingFactor ); 50419 50420 panOffset.multiplyScalar( 1 - scope.dampingFactor ); 50421 50422 } else { 50423 50424 sphericalDelta.set( 0, 0, 0 ); 50425 50426 panOffset.set( 0, 0, 0 ); 50427 50428 } 50429 50430 scale = 1; 50431 50432 // update condition is: 50433 // min(camera displacement, camera rotation in radians)^2 > EPS 50434 // using small-angle approximation cos(x/2) = 1 - x^2 / 8 50435 50436 if ( zoomChanged || 50437 lastPosition.distanceToSquared( scope.object.position ) > EPS || 50438 8 * ( 1 - lastQuaternion.dot( scope.object.quaternion ) ) > EPS ) { 50439 50440 scope.dispatchEvent( changeEvent ); 50441 50442 lastPosition.copy( scope.object.position ); 50443 lastQuaternion.copy( scope.object.quaternion ); 50444 zoomChanged = false; 50445 50446 return true; 50447 50448 } 50449 50450 return false; 50451 50452 }; 50453 50454 }(); 50455 50456 this.dispose = function () { 50457 50458 scope.domElement.removeEventListener( 'contextmenu', onContextMenu, false ); 50459 scope.domElement.removeEventListener( 'mousedown', onMouseDown, false ); 50460 scope.domElement.removeEventListener( 'wheel', onMouseWheel, false ); 50461 50462 scope.domElement.removeEventListener( 'touchstart', onTouchStart, false ); 50463 scope.domElement.removeEventListener( 'touchend', onTouchEnd, false ); 50464 scope.domElement.removeEventListener( 'touchmove', onTouchMove, false ); 50465 50466 document.removeEventListener( 'mousemove', onMouseMove, false ); 50467 document.removeEventListener( 'mouseup', onMouseUp, false ); 50468 50469 window.removeEventListener( 'keydown', onKeyDown, false ); 50470 50471 //scope.dispatchEvent( { type: 'dispose' } ); // should this be added here? 50472 50473 }; 50474 50475 // 50476 // internals 50477 // 50478 50479 var scope = this; 50480 50481 var changeEvent = { type: 'change' }; 50482 var startEvent = { type: 'start' }; 50483 var endEvent = { type: 'end' }; 50484 50485 var STATE = { NONE: - 1, ROTATE: 0, DOLLY: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_DOLLY_PAN: 4 }; 50486 50487 var state = STATE.NONE; 50488 50489 var EPS = 0.000001; 50490 50491 // current position in spherical coordinates 50492 var spherical = new Spherical(); 50493 var sphericalDelta = new Spherical(); 50494 50495 var scale = 1; 50496 var panOffset = new Vector3(); 50497 var zoomChanged = false; 50498 50499 var rotateStart = new Vector2(); 50500 var rotateEnd = new Vector2(); 50501 var rotateDelta = new Vector2(); 50502 50503 var panStart = new Vector2(); 50504 var panEnd = new Vector2(); 50505 var panDelta = new Vector2(); 50506 50507 var dollyStart = new Vector2(); 50508 var dollyEnd = new Vector2(); 50509 var dollyDelta = new Vector2(); 50510 50511 function getAutoRotationAngle() { 50512 50513 return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed; 50514 50515 } 50516 50517 function getZoomScale() { 50518 50519 return Math.pow( 0.95, scope.zoomSpeed ); 50520 50521 } 50522 50523 scope.rotateLeft = function( angle ) { 50524 50525 sphericalDelta.theta -= angle; 50526 50527 }; 50528 50529 scope.rotateUp = function( angle ) { 50530 50531 sphericalDelta.phi -= angle; 50532 50533 }; 50534 50535 var panLeft = function () { 50536 50537 var v = new Vector3(); 50538 50539 return function panLeft( distance, objectMatrix ) { 50540 50541 v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix 50542 v.multiplyScalar( - distance ); 50543 50544 panOffset.add( v ); 50545 50546 }; 50547 50548 }(); 50549 50550 var panUp = function () { 50551 50552 var v = new Vector3(); 50553 50554 return function panUp( distance, objectMatrix ) { 50555 50556 if ( scope.screenSpacePanning === true ) { 50557 50558 v.setFromMatrixColumn( objectMatrix, 1 ); 50559 50560 } else { 50561 50562 v.setFromMatrixColumn( objectMatrix, 0 ); 50563 v.crossVectors( scope.object.up, v ); 50564 50565 } 50566 50567 v.multiplyScalar( distance ); 50568 50569 panOffset.add( v ); 50570 50571 }; 50572 50573 }(); 50574 50575 // deltaX and deltaY are in pixels; right and down are positive 50576 var pan = function () { 50577 50578 var offset = new Vector3(); 50579 50580 return function pan( deltaX, deltaY ) { 50581 50582 var element = scope.domElement === document ? scope.domElement.body : scope.domElement; 50583 50584 if ( scope.object.isPerspectiveCamera ) { 50585 50586 // perspective 50587 var position = scope.object.position; 50588 offset.copy( position ).sub( scope.target ); 50589 var targetDistance = offset.length(); 50590 50591 // half of the fov is center to top of screen 50592 targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 ); 50593 50594 // we use only clientHeight here so aspect ratio does not distort speed 50595 panLeft( 2 * deltaX * targetDistance / element.clientHeight, scope.object.matrix ); 50596 panUp( 2 * deltaY * targetDistance / element.clientHeight, scope.object.matrix ); 50597 50598 } else if ( scope.object.isOrthographicCamera ) { 50599 50600 // orthographic 50601 panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix ); 50602 panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix ); 50603 50604 } else { 50605 50606 // camera neither orthographic nor perspective 50607 console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' ); 50608 scope.enablePan = false;
50609 50610 } 50611 50612 }; 50613 50614 }(); 50615 50616 function dollyIn( dollyScale ) { 50617 50618 if ( scope.object.isPerspectiveCamera ) { 50619 50620 scale /= dollyScale; 50621 50622 } else if ( scope.object.isOrthographicCamera ) { 50623 50624 scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom * dollyScale ) ); 50625 scope.object.updateProjectionMatrix(); 50626 zoomChanged = true; 50627 50628 } else { 50629 50630 console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); 50631 scope.enableZoom = false; 50632 50633 } 50634 50635 } 50636 50637 function dollyOut( dollyScale ) { 50638 50639 if ( scope.object.isPerspectiveCamera ) { 50640 50641 scale *= dollyScale; 50642 50643 } else if ( scope.object.isOrthographicCamera ) { 50644 50645 scope.object.zoom = Math.max( scope.minZoom, Math.min( scope.maxZoom, scope.object.zoom / dollyScale ) ); 50646 scope.object.updateProjectionMatrix(); 50647 zoomChanged = true; 50648 50649 } else { 50650 50651 console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' ); 50652 scope.enableZoom = false;
vendor: 14,089 bytes, lines 50653-51331
50653 50654 } 50655 50656 } 50657 50658 // 50659 // event callbacks - update the object state 50660 // 50661 50662 function handleMouseDownRotate( event ) { 50663 50664 //console.log( 'handleMouseDownRotate' ); 50665 50666 rotateStart.set( event.clientX, event.clientY ); 50667 50668 } 50669 50670 function handleMouseDownDolly( event ) { 50671 50672 //console.log( 'handleMouseDownDolly' ); 50673 50674 dollyStart.set( event.clientX, event.clientY ); 50675 50676 } 50677 50678 function handleMouseDownPan( event ) { 50679 50680 //console.log( 'handleMouseDownPan' ); 50681 50682 panStart.set( event.clientX, event.clientY ); 50683 50684 } 50685 50686 function handleMouseMoveRotate( event ) { 50687 50688 //console.log( 'handleMouseMoveRotate' ); 50689 50690 rotateEnd.set( event.clientX, event.clientY ); 50691 50692 rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); 50693 50694 var element = scope.domElement === document ? scope.domElement.body : scope.domElement; 50695 50696 scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height 50697 50698 scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); 50699 50700 rotateStart.copy( rotateEnd ); 50701 50702 scope.update(); 50703 50704 } 50705 50706 function handleMouseMoveDolly( event ) { 50707 50708 //console.log( 'handleMouseMoveDolly' ); 50709 50710 dollyEnd.set( event.clientX, event.clientY ); 50711 50712 dollyDelta.subVectors( dollyEnd, dollyStart ); 50713 50714 if ( dollyDelta.y > 0 ) { 50715 50716 dollyIn( getZoomScale() ); 50717 50718 } else if ( dollyDelta.y < 0 ) { 50719 50720 dollyOut( getZoomScale() ); 50721 50722 } 50723 50724 dollyStart.copy( dollyEnd ); 50725 50726 scope.update(); 50727 50728 } 50729 50730 function handleMouseMovePan( event ) { 50731 50732 //console.log( 'handleMouseMovePan' ); 50733 50734 panEnd.set( event.clientX, event.clientY ); 50735 50736 panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); 50737 50738 pan( panDelta.x, panDelta.y ); 50739 50740 panStart.copy( panEnd ); 50741 50742 scope.update(); 50743 50744 } 50745 50746 function handleMouseWheel( event ) { 50747 50748 // console.log( 'handleMouseWheel' ); 50749 50750 if ( event.deltaY < 0 ) { 50751 50752 dollyOut( getZoomScale() ); 50753 50754 } else if ( event.deltaY > 0 ) { 50755 50756 dollyIn( getZoomScale() ); 50757 50758 } 50759 50760 scope.update(); 50761 50762 } 50763 50764 function handleKeyDown( event ) { 50765 50766 //console.log( 'handleKeyDown' ); 50767 50768 switch ( event.keyCode ) { 50769 50770 case scope.keys.UP: 50771 pan( 0, scope.keyPanSpeed ); 50772 scope.update(); 50773 break; 50774 50775 case scope.keys.BOTTOM: 50776 pan( 0, - scope.keyPanSpeed ); 50777 scope.update(); 50778 break; 50779 50780 case scope.keys.LEFT: 50781 pan( scope.keyPanSpeed, 0 ); 50782 scope.update(); 50783 break; 50784 50785 case scope.keys.RIGHT: 50786 pan( - scope.keyPanSpeed, 0 ); 50787 scope.update(); 50788 break; 50789 50790 } 50791 50792 } 50793 50794 function handleTouchStartRotate( event ) { 50795 50796 //console.log( 'handleTouchStartRotate' ); 50797 50798 rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 50799 50800 } 50801 50802 function handleTouchStartDollyPan( event ) { 50803 50804 //console.log( 'handleTouchStartDollyPan' ); 50805 50806 if ( scope.enableZoom ) { 50807 50808 var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 50809 var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 50810 50811 var distance = Math.sqrt( dx * dx + dy * dy ); 50812 50813 dollyStart.set( 0, distance ); 50814 50815 } 50816 50817 if ( scope.enablePan ) { 50818 50819 var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); 50820 var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); 50821 50822 panStart.set( x, y ); 50823 50824 } 50825 50826 } 50827 50828 function handleTouchMoveRotate( event ) { 50829 50830 //console.log( 'handleTouchMoveRotate' ); 50831 50832 rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ); 50833 50834 rotateDelta.subVectors( rotateEnd, rotateStart ).multiplyScalar( scope.rotateSpeed ); 50835 50836 var element = scope.domElement === document ? scope.domElement.body : scope.domElement; 50837 50838 scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientHeight ); // yes, height 50839 50840 scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight ); 50841 50842 rotateStart.copy( rotateEnd ); 50843 50844 scope.update(); 50845 50846 } 50847 50848 function handleTouchMoveDollyPan( event ) { 50849 50850 //console.log( 'handleTouchMoveDollyPan' ); 50851 50852 if ( scope.enableZoom ) { 50853 50854 var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX; 50855 var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY; 50856 50857 var distance = Math.sqrt( dx * dx + dy * dy ); 50858 50859 dollyEnd.set( 0, distance ); 50860 50861 dollyDelta.set( 0, Math.pow( dollyEnd.y / dollyStart.y, scope.zoomSpeed ) ); 50862 50863 dollyIn( dollyDelta.y ); 50864 50865 dollyStart.copy( dollyEnd ); 50866 50867 } 50868 50869 if ( scope.enablePan ) { 50870 50871 var x = 0.5 * ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ); 50872 var y = 0.5 * ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ); 50873 50874 panEnd.set( x, y ); 50875 50876 panDelta.subVectors( panEnd, panStart ).multiplyScalar( scope.panSpeed ); 50877 50878 pan( panDelta.x, panDelta.y ); 50879 50880 panStart.copy( panEnd ); 50881 50882 } 50883 50884 scope.update(); 50885 50886 } 50887 50888 // 50889 // event handlers - FSM: listen for events and reset state 50890 // 50891 50892 function onMouseDown( event ) { 50893 50894 if ( scope.enabled === false ) return; 50895 50896 event.preventDefault(); 50897 50898 switch ( event.button ) { 50899 50900 case scope.mouseButtons.ORBIT: 50901 50902 if ( scope.enableRotate === false ) return; 50903 50904 handleMouseDownRotate( event ); 50905 50906 state = STATE.ROTATE; 50907 50908 break; 50909 50910 case scope.mouseButtons.ZOOM: 50911 50912 if ( scope.enableZoom === false ) return; 50913 50914 handleMouseDownDolly( event ); 50915 50916 state = STATE.DOLLY; 50917 50918 break; 50919 50920 case scope.mouseButtons.PAN: 50921 50922 if ( scope.enablePan === false ) return; 50923 50924 handleMouseDownPan( event ); 50925 50926 state = STATE.PAN; 50927 50928 break; 50929 50930 } 50931 50932 if ( state !== STATE.NONE ) { 50933 50934 document.addEventListener( 'mousemove', onMouseMove, false ); 50935 document.addEventListener( 'mouseup', onMouseUp, false ); 50936 50937 scope.dispatchEvent( startEvent ); 50938 50939 } 50940 50941 } 50942 50943 function onMouseMove( event ) { 50944 50945 if ( scope.enabled === false ) return; 50946 50947 event.preventDefault(); 50948 50949 switch ( state ) { 50950 50951 case STATE.ROTATE: 50952 50953 if ( scope.enableRotate === false ) return; 50954 50955 handleMouseMoveRotate( event ); 50956 50957 break; 50958 50959 case STATE.DOLLY: 50960 50961 if ( scope.enableZoom === false ) return; 50962 50963 handleMouseMoveDolly( event ); 50964 50965 break; 50966 50967 case STATE.PAN: 50968 50969 if ( scope.enablePan === false ) return; 50970 50971 handleMouseMovePan( event ); 50972 50973 break; 50974 50975 } 50976 50977 } 50978 50979 function onMouseUp( event ) { 50980 50981 if ( scope.enabled === false ) return; 50982 50983 document.removeEventListener( 'mousemove', onMouseMove, false ); 50984 document.removeEventListener( 'mouseup', onMouseUp, false ); 50985 50986 scope.dispatchEvent( endEvent ); 50987 50988 state = STATE.NONE; 50989 50990 } 50991 50992 function onMouseWheel( event ) { 50993 50994 if ( scope.enabled === false || scope.enableZoom === false || ( state !== STATE.NONE && state !== STATE.ROTATE ) ) return; 50995 50996 event.preventDefault(); 50997 event.stopPropagation(); 50998 50999 scope.dispatchEvent( startEvent ); 51000 51001 handleMouseWheel( event ); 51002 51003 scope.dispatchEvent( endEvent ); 51004 51005 } 51006 51007 function onKeyDown( event ) { 51008 51009 if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return; 51010 51011 handleKeyDown( event ); 51012 51013 } 51014 51015 function onTouchStart( event ) { 51016 51017 if ( scope.enabled === false ) return; 51018 51019 event.preventDefault(); 51020 51021 switch ( event.touches.length ) { 51022 51023 case 1: // one-fingered touch: rotate 51024 51025 if ( scope.enableRotate === false ) return; 51026 51027 handleTouchStartRotate( event ); 51028 51029 state = STATE.TOUCH_ROTATE; 51030 51031 break; 51032 51033 case 2: // two-fingered touch: dolly-pan 51034 51035 if ( scope.enableZoom === false && scope.enablePan === false ) return; 51036 51037 handleTouchStartDollyPan( event ); 51038 51039 state = STATE.TOUCH_DOLLY_PAN; 51040 51041 break; 51042 51043 default: 51044 51045 state = STATE.NONE; 51046 51047 } 51048 51049 if ( state !== STATE.NONE ) { 51050 51051 scope.dispatchEvent( startEvent ); 51052 51053 } 51054 51055 } 51056 51057 function onTouchMove( event ) { 51058 51059 if ( scope.enabled === false ) return; 51060 51061 event.preventDefault(); 51062 event.stopPropagation(); 51063 51064 switch ( event.touches.length ) { 51065 51066 case 1: // one-fingered touch: rotate 51067 51068 if ( scope.enableRotate === false ) return; 51069 if ( state !== STATE.TOUCH_ROTATE ) return; // is this needed? 51070 51071 handleTouchMoveRotate( event ); 51072 51073 break; 51074 51075 case 2: // two-fingered touch: dolly-pan 51076 51077 if ( scope.enableZoom === false && scope.enablePan === false ) return; 51078 if ( state !== STATE.TOUCH_DOLLY_PAN ) return; // is this needed? 51079 51080 handleTouchMoveDollyPan( event ); 51081 51082 break; 51083 51084 default: 51085 51086 state = STATE.NONE; 51087 51088 } 51089 51090 } 51091 51092 function onTouchEnd( event ) { 51093 51094 if ( scope.enabled === false ) return; 51095 51096 scope.dispatchEvent( endEvent ); 51097 51098 state = STATE.NONE; 51099 51100 } 51101 51102 function onContextMenu( event ) { 51103 51104 if ( scope.enabled === false ) return; 51105 51106 event.preventDefault(); 51107 51108 } 51109 51110 // 51111 51112 //scope.domElement.addEventListener\( 'contextmenu', onContextMenu, false ); 51113 51114 scope.domElement.addEventListener( 'mousedown', onMouseDown, false ); 51115 scope.domElement.addEventListener( 'wheel', onMouseWheel, false ); 51116 51117 scope.domElement.addEventListener( 'touchstart', onTouchStart, false ); 51118 scope.domElement.addEventListener( 'touchend', onTouchEnd, false ); 51119 scope.domElement.addEventListener( 'touchmove', onTouchMove, false ); 51120 51121 window.addEventListener( 'keydown', onKeyDown, false ); 51122 51123 // force an update at start 51124 51125 this.update(); 51126 51127 }; 51128 51129 OrbitControls.prototype = Object.create( EventDispatcher.prototype ); 51130 OrbitControls.prototype.constructor = OrbitControls; 51131 51132 Object.defineProperties( OrbitControls.prototype, { 51133 51134 center: { 51135 51136 get: function () { 51137 51138 console.warn( 'OrbitControls: .center has been renamed to .target' ); 51139 return this.target; 51140 51141 } 51142 51143 }, 51144 51145 // backward compatibility 51146 51147 noZoom: { 51148 51149 get: function () { 51150 51151 console.warn( 'OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' ); 51152 return ! this.enableZoom; 51153 51154 }, 51155 51156 set: function ( value ) { 51157 51158 console.warn( 'OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' ); 51159 this.enableZoom = ! value; 51160 51161 } 51162 51163 }, 51164 51165 noRotate: { 51166 51167 get: function () { 51168 51169 console.warn( 'OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' ); 51170 return ! this.enableRotate; 51171 51172 }, 51173 51174 set: function ( value ) { 51175 51176 console.warn( 'OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' ); 51177 this.enableRotate = ! value; 51178 51179 } 51180 51181 }, 51182 51183 noPan: { 51184 51185 get: function () { 51186 51187 console.warn( 'OrbitControls: .noPan has been deprecated. Use .enablePan instead.' ); 51188 return ! this.enablePan; 51189 51190 }, 51191 51192 set: function ( value ) { 51193 51194 console.warn( 'OrbitControls: .noPan has been deprecated. Use .enablePan instead.' ); 51195 this.enablePan = ! value; 51196 51197 } 51198 51199 }, 51200 51201 noKeys: { 51202 51203 get: function () { 51204 51205 console.warn( 'OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' ); 51206 return ! this.enableKeys; 51207 51208 }, 51209 51210 set: function ( value ) { 51211 51212 console.warn( 'OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' ); 51213 this.enableKeys = ! value; 51214 51215 } 51216 51217 }, 51218 51219 staticMoving: { 51220 51221 get: function () { 51222 51223 console.warn( 'OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' ); 51224 return ! this.enableDamping; 51225 51226 }, 51227 51228 set: function ( value ) { 51229 51230 console.warn( 'OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' ); 51231 this.enableDamping = ! value; 51232 51233 } 51234 51235 }, 51236 51237 dynamicDampingFactor: { 51238 51239 get: function () { 51240 51241 console.warn( 'OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' ); 51242 return this.dampingFactor; 51243 51244 }, 51245 51246 set: function ( value ) { 51247 51248 console.warn( 'OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' ); 51249 this.dampingFactor = value; 51250 51251 } 51252 51253 } 51254 51255 } ); 51256 51257 /** 51258 * @author richt / http://richt.me 51259 * @author WestLangley / http://github.com/WestLangley 51260 * 51261 * W3C Device Orientation control (http://w3c.github.io/deviceorientation/spec-source-orientation.html) 51262 */ 51263 var DeviceOrientationControls = function ( object ) { 51264 51265 var scope = this; 51266 51267 this.object = object; 51268 this.object.rotation.reorder( 'YXZ' ); 51269 51270 this.enabled = true; 51271 51272 this.deviceOrientation = {}; 51273 this.screenOrientation = 0; 51274 51275 this.alphaOffset = 0; // radians 51276 51277 var onDeviceOrientationChangeEvent = function ( event ) { 51278 51279 scope.deviceOrientation = event; 51280 51281 }; 51282 51283 var onScreenOrientationChangeEvent = function () { 51284 51285 scope.screenOrientation = window.orientation || 0; 51286 51287 }; 51288 51289 // The angles alpha, beta and gamma form a set of intrinsic Tait-Bryan angles of type Z-X'-Y'' 51290 51291 var setObjectQuaternion = function () { 51292 51293 var zee = new Vector3( 0, 0, 1 ); 51294 51295 var euler = new Euler(); 51296 51297 var q0 = new Quaternion(); 51298 51299 var q1 = new Quaternion( - Math.sqrt( 0.5 ), 0, 0, Math.sqrt( 0.5 ) ); // - PI/2 around the x-axis 51300 51301 return function ( quaternion, alpha, beta, gamma, orient ) { 51302 51303 euler.set( beta, alpha, - gamma, 'YXZ' ); // 'ZXY' for the device, but 'YXZ' for us 51304 51305 quaternion.setFromEuler( euler ); // orient the device 51306 51307 quaternion.multiply( q1 ); // camera looks out the back of the device, not the top 51308 51309 quaternion.multiply( q0.setFromAxisAngle( zee, - orient ) ); // adjust for screen orientation 51310 51311 }; 51312 51313 }(); 51314 51315 this.connect = function () { 51316 51317 onScreenOrientationChangeEvent(); // run once on load 51318 51319 window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false ); 51320 window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false ); 51321 51322 scope.enabled = true; 51323 51324 }; 51325 51326 this.disconnect = function () { 51327 51328 window.removeEventListener( 'orientationchange', onScreenOrientationChangeEvent, false ); 51329 window.removeEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false ); 51330 51331 scope.enabled = false;
vendor: 1,895 bytes, lines 51332-51415
51332 51333 }; 51334 51335 this.update = function () { 51336 51337 if ( scope.enabled === false ) return; 51338 51339 var device = scope.deviceOrientation; 51340 51341 if ( device ) { 51342 51343 var alpha = device.alpha ? _Math.degToRad( device.alpha ) + scope.alphaOffset : 0; // Z 51344 51345 var beta = device.beta ? _Math.degToRad( device.beta ) : 0; // X' 51346 51347 var gamma = device.gamma ? _Math.degToRad( device.gamma ) : 0; // Y'' 51348 51349 var orient = scope.screenOrientation ? _Math.degToRad( scope.screenOrientation ) : 0; // O 51350 51351 setObjectQuaternion( scope.object.quaternion, alpha, beta, gamma, orient ); 51352 51353 } 51354 51355 51356 }; 51357 51358 this.dispose = function () { 51359 51360 scope.disconnect(); 51361 51362 }; 51363 51364 this.connect(); 51365 51366 }; 51367 51368 /** 51369 * Convert a quaternion to an angle 51370 * 51371 * Taken from https://stackoverflow.com/a/35448946 51372 * Thanks P. Ellul 51373 */ 51374 51375 function Quat2Angle(x, y, z, w) { 51376 var test = x * y + z * w; // singularity at north pole 51377 51378 if (test > 0.499) { 51379 var _yaw = 2 * Math.atan2(x, w); 51380 51381 var _pitch = Math.PI / 2; 51382 51383 var _roll = 0; 51384 return new Vector3(_pitch, _roll, _yaw); 51385 } // singularity at south pole 51386 51387 51388 if (test < -0.499) { 51389 var _yaw2 = -2 * Math.atan2(x, w); 51390 51391 var _pitch2 = -Math.PI / 2; 51392 51393 var _roll2 = 0; 51394 return new Vector3(_pitch2, _roll2, _yaw2); 51395 } 51396 51397 var sqx = x * x; 51398 var sqy = y * y; 51399 var sqz = z * z; 51400 var yaw = Math.atan2(2 * y * w - 2 * x * z, 1 - 2 * sqy - 2 * sqz); 51401 var pitch = Math.asin(2 * test); 51402 var roll = Math.atan2(2 * x * w - 2 * y * z, 1 - 2 * sqx - 2 * sqz); 51403 return new Vector3(pitch, roll, yaw); 51404 } 51405 51406 var OrbitOrientationControls = 51407 /*#__PURE__*/ 51408 function () { 51409 function OrbitOrientationControls(options) { 51410 this.object = options.camera; 51411 this.domElement = options.canvas; 51412 this.orbit = new OrbitControls(this.object, this.domElement); 51413 this.speed = 0.5; 51414 this.orbit.target.set(0, 0, -1); 51415 this.orbit.enableZoom = false;
51416 this.orbit.enablePan = false; 51417 this.orbit.rotateSpeed = -this.speed; // if orientation is supported 51418 51419 if (options.orientation) { 51420 this.orientation = new DeviceOrientationControls(this.object); 51421 } // if projection is not full view 51422 // limit the rotation angle in order to not display back half view 51423 51424 51425 if (options.halfView) { 51426 this.orbit.minAzimuthAngle = -Math.PI / 4; 51427 this.orbit.maxAzimuthAngle = Math.PI / 4; 51428 } 51429 } 51430 51431 var _proto = OrbitOrientationControls.prototype; 51432 51433 _proto.update = function update() { 51434 // orientation updates the camera using quaternions and 51435 // orbit updates the camera using angles. They are incompatible 51436 // and one update overrides the other. So before 51437 // orbit overrides orientation we convert our quaternion changes to 51438 // an angle change. Then save the angle into orbit so that 51439 // it will take those into account when it updates the camera and overrides 51440 // our changes 51441 if (this.orientation) { 51442 this.orientation.update(); 51443 var quat = this.orientation.object.quaternion; 51444 var currentAngle = Quat2Angle(quat.x, quat.y, quat.z, quat.w); // we also have to store the last angle since quaternions are b 51445 51446 if (typeof this.lastAngle_ === 'undefined') { 51447 this.lastAngle_ = currentAngle; 51448 } 51449 51450 this.orbit.rotateLeft((this.lastAngle_.z - currentAngle.z) * (1 + this.speed)); 51451 this.orbit.rotateUp((this.lastAngle_.y - currentAngle.y) * (1 + this.speed)); 51452 this.lastAngle_ = currentAngle; 51453 } 51454 51455 this.orbit.update(); 51456 }; 51457 51458 _proto.dispose = function dispose() { 51459 this.orbit.dispose(); 51460 51461 if (this.orientation) { 51462 this.orientation.dispose(); 51463 } 51464 }; 51465 51466 return OrbitOrientationControls; 51467 }(); 51468 51469 var corsSupport = function () { 51470 var video = document$1.createElement('video'); 51471 video.crossOrigin = 'anonymous'; 51472 return video.hasAttribute('crossorigin'); 51473 }(); 51474 var validProjections = ['360', '360_LR', '360_TB', '360_CUBE', 'EAC', 'EAC_LR', 'NONE', 'AUTO', 'Sphere', 'Cube', 'equirectangular', '180', '180_LR', '180_MONO']; 51475 var getInternalProjectionName = function getInternalProjectionName(projection) { 51476 if (!projection) { 51477 return; 51478 } 51479 51480 projection = projection.toString().trim(); 51481 51482 if (/sphere/i.test(projection)) { 51483 return '360'; 51484 } 51485 51486 if (/cube/i.test(projection)) { 51487 return '360_CUBE'; 51488 } 51489 51490 if (/equirectangular/i.test(projection)) { 51491 return '360'; 51492 } 51493 51494 for (var i = 0; i < validProjections.length; i++) { 51495 if (new RegExp('^' + validProjections[i] + '$', 'i').test(projection)) { 51496 return validProjections[i]; 51497 } 51498 } 51499 }; 51500 51501 /** 51502 * This class reacts to interactions with the canvas and 51503 * triggers appropriate functionality on the player. Right now 51504 * it does two things: 51505 * 51506 * 1. A `mousedown`/`touchstart` followed by `touchend`/`mouseup` without any 51507 * `touchmove` or `mousemove` toggles play/pause on the player 51508 * 2. Only moving on/clicking the control bar or toggling play/pause should 51509 * show the control bar. Moving around the scene in the canvas should not. 51510 */ 51511 51512 var CanvasPlayerControls = 51513 /*#__PURE__*/ 51514 function (_videojs$EventTarget) { 51515 inheritsLoose(CanvasPlayerControls, _videojs$EventTarget); 51516 51517 function CanvasPlayerControls(player, canvas) { 51518 var _this; 51519 51520 _this = _videojs$EventTarget.call(this) || this; 51521 _this.player = player; 51522 _this.canvas = canvas; 51523 _this.onMoveEnd = videojs.bind(assertThisInitialized(_this), _this.onMoveEnd); 51524 _this.onMoveStart = videojs.bind(assertThisInitialized(_this), _this.onMoveStart); 51525 _this.onMove = videojs.bind(assertThisInitialized(_this), _this.onMove); 51526 _this.onControlBarMove = videojs.bind(assertThisInitialized(_this), _this.onControlBarMove); 51527 51528 _this.player.controlBar.on(['mousedown', 'mousemove', 'mouseup', 'touchstart', 'touchmove', 'touchend'], _this.onControlBarMove); // we have to override these here because 51529 // video.js listens for user activity on the video element 51530 // and makes the user active when the mouse moves. 51531 // We don't want that for 3d videos 51532 51533 51534 _this.oldReportUserActivity = _this.player.reportUserActivity; 51535 51536 _this.player.reportUserActivity = function () {}; // canvas movements 51537 51538 51539 _this.canvas.addEventListener('mousedown', _this.onMoveStart); 51540 51541 _this.canvas.addEventListener('touchstart', _this.onMoveStart); 51542 51543 _this.canvas.addEventListener('mousemove', _this.onMove); 51544 51545 _this.canvas.addEventListener('touchmove', _this.onMove); 51546 51547 _this.canvas.addEventListener('mouseup', _this.onMoveEnd); 51548 51549 _this.canvas.addEventListener('touchend', _this.onMoveEnd); 51550 51551 _this.shouldTogglePlay = false;
51552 return _this; 51553 } 51554 51555 var _proto = CanvasPlayerControls.prototype; 51556 51557 _proto.togglePlay = function togglePlay() { 51558 if (this.player.paused()) { 51559 this.player.play(); 51560 } else { 51561 this.player.pause(); 51562 } 51563 }; 51564 51565 _proto.onMoveStart = function onMoveStart(e) { 51566 // if the player does not have a controlbar or 51567 // the move was a mouse click but not left click do not 51568 // toggle play. 51569 if (!this.player.controls() || e.type === 'mousedown' && !videojs.dom.isSingleLeftClick(e)) { 51570 this.shouldTogglePlay = false; 51571 return; 51572 } 51573 51574 this.shouldTogglePlay = true; 51575 this.touchMoveCount_ = 0; 51576 }; 51577 51578 _proto.onMoveEnd = function onMoveEnd(e) { 51579 // We want to have the same behavior in VR360 Player and standard player. 51580 // in touchend we want to know if was a touch click, for a click we show the bar, 51581 // otherwise continue with the mouse logic. 51582 // 51583 // Maximum movement allowed during a touch event to still be considered a tap 51584 // Other popular libs use anywhere from 2 (hammer.js) to 15, 51585 // so 10 seems like a nice, round number. 51586 if (e.type === 'touchend' && this.touchMoveCount_ < 10) { 51587 if (this.player.userActive() === false) { 51588 this.player.userActive(true); 51589 return; 51590 } 51591 51592 this.player.userActive(false); 51593 return; 51594 } 51595 51596 if (!this.shouldTogglePlay) { 51597 return; 51598 } // We want the same behavior in Desktop for VR360 and standard player 51599 51600 51601 if (e.type == 'mouseup') { 51602 this.togglePlay(); 51603 } 51604 }; 51605 51606 _proto.onMove = function onMove(e) { 51607 // Increase touchMoveCount_ since Android detects 1 - 6 touches when user click normally 51608 this.touchMoveCount_++; 51609 this.shouldTogglePlay = false; 51610 }; 51611 51612 _proto.onControlBarMove = function onControlBarMove(e) { 51613 this.player.userActive(true); 51614 }; 51615 51616 _proto.dispose = function dispose() { 51617 this.canvas.removeEventListener('mousedown', this.onMoveStart); 51618 this.canvas.removeEventListener('touchstart', this.onMoveStart); 51619 this.canvas.removeEventListener('mousemove', this.onMove); 51620 this.canvas.removeEventListener('touchmove', this.onMove); 51621 this.canvas.removeEventListener('mouseup', this.onMoveEnd); 51622 this.canvas.removeEventListener('touchend', this.onMoveEnd); 51623 this.player.controlBar.off(['mousedown', 'mousemove', 'mouseup', 'touchstart', 'touchmove', 'touchend'], this.onControlBarMove); 51624 this.player.reportUserActivity = this.oldReportUserActivity; 51625 }; 51626 51627 return CanvasPlayerControls; 51628 }(videojs.EventTarget); 51629 51630 /** 51631 * This class manages ambisonic decoding and binaural rendering via Omnitone library. 51632 */ 51633 51634 var OmnitoneController = 51635 /*#__PURE__*/ 51636 function (_videojs$EventTarget) { 51637 inheritsLoose(OmnitoneController, _videojs$EventTarget); 51638 51639 /** 51640 * Omnitone controller class. 51641 * 51642 * @class 51643 * @param {AudioContext} audioContext - associated AudioContext. 51644 * @param {Omnitone library} omnitone - Omnitone library element. 51645 * @param {HTMLVideoElement} video - vidoe tag element. 51646 * @param {Object} options - omnitone options. 51647 */ 51648 function OmnitoneController(audioContext, omnitone, video, options) { 51649 var _this; 51650 51651 _this = _videojs$EventTarget.call(this) || this; 51652 var settings = videojs.mergeOptions({ 51653 // Safari uses the different AAC decoder than FFMPEG. The channel order is 51654 // The default 4ch AAC channel layout for FFMPEG AAC channel ordering. 51655 channelMap: videojs.browser.IS_SAFARI ? [2, 0, 1, 3] : [0, 1, 2, 3], 51656 ambisonicOrder: 1 51657 }, options); 51658 _this.videoElementSource = audioContext.createMediaElementSource(video); 51659 _this.foaRenderer = omnitone.createFOARenderer(audioContext, settings); 51660 51661 _this.foaRenderer.initialize().then(function () { 51662 if (audioContext.state === 'suspended') { 51663 _this.trigger({ 51664 type: 'audiocontext-suspended' 51665 }); 51666 } 51667 51668 _this.videoElementSource.connect(_this.foaRenderer.input); 51669 51670 _this.foaRenderer.output.connect(audioContext.destination); 51671 51672 _this.initialized = true; 51673 51674 _this.trigger({ 51675 type: 'omnitone-ready' 51676 }); 51677 }, function (error) { 51678 videojs.log.warn("videojs-vr: Omnitone initializes failed with the following error: " + error + ")"); 51679 }); 51680 51681 return _this; 51682 } 51683 /** 51684 * Updates the rotation of the Omnitone decoder based on three.js camera matrix. 51685 * 51686 * @param {Camera} camera Three.js camera object 51687 */ 51688 51689 51690 var _proto = OmnitoneController.prototype; 51691 51692 _proto.update = function update(camera) { 51693 if (!this.initialized) { 51694 return; 51695 } 51696
51697 this.foaRenderer.setRotationMatrixFromCamera(camera.matrix); 51698 } 51699 /** 51700 * Destroys the controller and does any necessary cleanup. 51701 */ 51702 ; 51703 51704 _proto.dispose = function dispose() { 51705 this.initialized = false; 51706 this.foaRenderer.setRenderingMode('bypass'); 51707 this.foaRenderer = null; 51708 }; 51709 51710 return OmnitoneController; 51711 }(videojs.EventTarget); 51712 51713 var Button = videojs.getComponent('Button'); 51714 51715 var CardboardButton = 51716 /*#__PURE__*/ 51717 function (_Button) { 51718 inheritsLoose(CardboardButton, _Button); 51719 51720 function CardboardButton(player, options) { 51721 var _this; 51722 51723 _this = _Button.call(this, player, options) || this; 51724 _this.handleVrDisplayActivate_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayActivate_); 51725 _this.handleVrDisplayDeactivate_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayDeactivate_); 51726 _this.handleVrDisplayPresentChange_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayPresentChange_); 51727 _this.handleOrientationChange_ = videojs.bind(assertThisInitialized(_this), _this.handleOrientationChange_); 51728 window$1.addEventListener('orientationchange', _this.handleOrientationChange_); 51729 window$1.addEventListener('vrdisplayactivate', _this.handleVrDisplayActivate_); 51730 window$1.addEventListener('vrdisplaydeactivate', _this.handleVrDisplayDeactivate_); // vrdisplaypresentchange does not fire activate or deactivate 51731 // and happens when hitting the back button during cardboard mode 51732 // so we need to make sure we stay in the correct state by 51733 // listening to it and checking if we are presenting it or not 51734 51735 window$1.addEventListener('vrdisplaypresentchange', _this.handleVrDisplayPresentChange_); // we cannot show the cardboard button in fullscreen on 51736 // android as it breaks the controls, and makes it impossible 51737 // to exit cardboard mode 51738 51739 if (videojs.browser.IS_ANDROID) { 51740 _this.on(player, 'fullscreenchange', function () { 51741 if (player.isFullscreen()) { 51742 _this.hide(); 51743 } else { 51744 _this.show(); 51745 } 51746 }); 51747 } 51748 51749 return _this; 51750 } 51751 51752 var _proto = CardboardButton.prototype; 51753 51754 _proto.buildCSSClass = function buildCSSClass() { 51755 return "vjs-button-vr " + _Button.prototype.buildCSSClass.call(this); 51756 }; 51757 51758 _proto.handleVrDisplayPresentChange_ = function handleVrDisplayPresentChange_() { 51759 if (!this.player_.vr().vrDisplay.isPresenting && this.active_) { 51760 this.handleVrDisplayDeactivate_(); 51761 } 51762 51763 if (this.player_.vr().vrDisplay.isPresenting && !this.active_) { 51764 this.handleVrDisplayActivate_(); 51765 } 51766 }; 51767 51768 _proto.handleOrientationChange_ = function handleOrientationChange_() { 51769 if (this.active_ && videojs.browser.IS_IOS) { 51770 this.changeSize_(); 51771 } 51772 }; 51773 51774 _proto.changeSize_ = function changeSize_() { 51775 this.player_.width(window$1.innerWidth); 51776 this.player_.height(window$1.innerHeight); 51777 window$1.dispatchEvent(new window$1.Event('resize')); 51778 }; 51779 51780 _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { 51781 // we mimic fullscreen on IOS 51782 if (videojs.browser.IS_IOS) { 51783 this.oldWidth_ = this.player_.currentWidth(); 51784 this.oldHeight_ = this.player_.currentHeight(); 51785 this.player_.enterFullWindow(); 51786 this.changeSize_(); 51787 } 51788 51789 this.active_ = true; 51790 }; 51791 51792 _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() { 51793 // un-mimic fullscreen on iOS 51794 if (videojs.browser.IS_IOS) { 51795 if (this.oldWidth_) { 51796 this.player_.width(this.oldWidth_); 51797 } 51798 51799 if (this.oldHeight_) { 51800 this.player_.height(this.oldHeight_); 51801 } 51802 51803 this.player_.exitFullWindow(); 51804 } 51805 51806 this.active_ = false; 51807 }; 51808 51809 _proto.handleClick = function handleClick(event) { 51810 // if cardboard mode display is not active, activate it 51811 // otherwise deactivate it 51812 if (!this.active_) { 51813 // This starts playback mode when the cardboard button 51814 // is clicked on Android. We need to do this as the controls 51815 // disappear 51816 if (!this.player_.hasStarted() && videojs.browser.IS_ANDROID) { 51817 this.player_.play(); 51818 } 51819 51820 window$1.dispatchEvent(new window$1.Event('vrdisplayactivate')); 51821 } else { 51822 window$1.dispatchEvent(new window$1.Event('vrdisplaydeactivate')); 51823 } 51824 }; 51825 51826 _proto.dispose = function dispose() { 51827 _Button.prototype.dispose.call(this); 51828 51829 window$1.removeEventListener('vrdisplayactivate', this.handleVrDisplayActivate_); 51830 window$1.removeEventListener('vrdisplaydeactivate', this.handleVrDisplayDeactivate_); 51831 window$1.removeEventListener('vrdisplaypresentchange', this.handleVrDisplayPresentChange_); 51832 }; 51833 51834 return CardboardButton; 51835 }(Button); 51836 51837 videojs.registerComponent('CardboardButton', CardboardButton); 51838 51839 var BigPlayButton = videojs.getComponent('BigPlayButton'); 51840 51841 var BigVrPlayButton = 51842 /*#__PURE__*/ 51843 function (_BigPlayButton) { 51844 inheritsLoose(BigVrPlayButton, _BigPlayButton); 51845 51846 function BigVrPlayButton() { 51847 return _BigPlayButton.apply(this, arguments) || this; 51848 } 51849 51850 var _proto = BigVrPlayButton.prototype; 51851 51852 _proto.buildCSSClass = function buildCSSClass() { 51853 return "vjs-big-vr-play-button " + _BigPlayButton.prototype.buildCSSClass.call(this); 51854 }; 51855 51856 return BigVrPlayButton; 51857 }(BigPlayButton); 51858 51859 videojs.registerComponent('BigVrPlayButton', BigVrPlayButton); 51860 51861 var defaults = { 51862 debug: false, 51863 omnitone: false, 51864 forceCardboard: false, 51865 omnitoneOptions: {}, 51866 projection: 'AUTO', 51867 sphereDetail: 32 51868 }; 51869 var errors = { 51870 'web-vr-out-of-date': { 51871 headline: '360 is out of date', 51872 type: '360_OUT_OF_DATE', 51873 message: "Your browser supports 360 but not the latest version. See <a href='http://webvr.info'>http://webvr.info</a> for more info." 51874 }, 51875 'web-vr-not-supported': { 51876 headline: '360 not supported on this device', 51877 type: '360_NOT_SUPPORTED', 51878 message: "Your browser does not support 360. See <a href='http://webvr.info'>http://webvr.info</a> for assistance." 51879 }, 51880 'web-vr-hls-cors-not-supported': { 51881 headline: '360 HLS video not supported on this device', 51882 type: '360_NOT_SUPPORTED', 51883 message: "Your browser/device does not support HLS 360 video. See <a href='http://webvr.info'>http://webvr.info</a> for assistance." 51884 } 51885 }; 51886 var Plugin = videojs.getPlugin('plugin'); 51887 var Component = videojs.getComponent('Component'); 51888 51889 var VR = 51890 /*#__PURE__*/ 51891 function (_Plugin) { 51892 inheritsLoose(VR, _Plugin); 51893 51894 function VR(player, options) { 51895 var _this; 51896 51897 var settings = videojs.mergeOptions(defaults, options); 51898 _this = _Plugin.call(this, player, settings) || this; 51899 _this.options_ = settings; 51900 _this.player_ = player; 51901 _this.bigPlayButtonIndex_ = player.children().indexOf(player.getChild('BigPlayButton')) || 0; // custom videojs-errors integration boolean 51902 51903 _this.videojsErrorsSupport_ = !!videojs.errors; 51904 51905 if (_this.videojsErrorsSupport_) { 51906 player.errors({ 51907 errors: errors 51908 }); 51909 } // IE 11 does not support enough webgl to be supported 51910 // older safari does not support cors, so it wont work 51911 51912 51913 if (videojs.browser.IE_VERSION || !corsSupport) { 51914 // if a player triggers error before 'loadstart' is fired 51915 // video.js will reset the error overlay 51916 _this.player_.on('loadstart', function () { 51917 _this.triggerError_({ 51918 code: 'web-vr-not-supported',
51919 dismiss: false 51920 }); 51921 }); 51922 51923 return assertThisInitialized(_this); 51924 } 51925 51926 _this.polyfill_ = new WebVRPolyfill({ 51927 // do not show rotate instructions 51928 ROTATE_INSTRUCTIONS_DISABLED: true 51929 }); 51930 _this.polyfill_ = new WebVRPolyfill(); 51931 _this.handleVrDisplayActivate_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayActivate_); 51932 _this.handleVrDisplayDeactivate_ = videojs.bind(assertThisInitialized(_this), _this.handleVrDisplayDeactivate_); 51933 _this.handleResize_ = videojs.bind(assertThisInitialized(_this), _this.handleResize_); 51934 _this.animate_ = videojs.bind(assertThisInitialized(_this), _this.animate_); 51935 51936 _this.setProjection(_this.options_.projection); // any time the video element is recycled for ads 51937 // we have to reset the vr state and re-init after ad 51938 51939 51940 _this.on(player, 'adstart', function () { 51941 return player.setTimeout(function () { 51942 // if the video element was recycled for this ad 51943 if (!player.ads || !player.ads.videoElementRecycled()) { 51944 _this.log('video element not recycled for this ad, no need to reset'); 51945 51946 return; 51947 } 51948 51949 _this.log('video element recycled for this ad, reseting'); 51950 51951 _this.reset(); 51952 51953 _this.one(player, 'playing', _this.init); 51954 }); 51955 }, 1); 51956 51957 _this.on(player, 'loadedmetadata', _this.init); 51958 51959 return _this; 51960 } 51961 51962 var _proto = VR.prototype; 51963 51964 _proto.changeProjection_ = function changeProjection_(projection) { 51965 var _this2 = this; 51966 51967 projection = getInternalProjectionName(projection); // don't change to an invalid projection 51968 51969 if (!projection) { 51970 projection = 'NONE'; 51971 } 51972 51973 var position = { 51974 x: 0, 51975 y: 0, 51976 z: 0 51977 }; 51978 51979 if (this.scene) { 51980 this.scene.remove(this.movieScreen); 51981 } 51982 51983 if (projection === 'AUTO') { 51984 // mediainfo cannot be set to auto or we would infinite loop here 51985 // each source should know whatever they are 360 or not, if using AUTO 51986 if (this.player_.mediainfo && this.player_.mediainfo.projection && this.player_.mediainfo.projection !== 'AUTO') { 51987 var autoProjection = getInternalProjectionName(this.player_.mediainfo.projection); 51988 return this.changeProjection_(autoProjection); 51989 } 51990 51991 return this.changeProjection_('NONE'); 51992 } else if (projection === '360') { 51993 this.movieGeometry = new SphereBufferGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail); 51994 this.movieMaterial = new MeshBasicMaterial({ 51995 map: this.videoTexture, 51996 overdraw: true, 51997 side: BackSide 51998 }); 51999 this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); 52000 this.movieScreen.position.set(position.x, position.y, position.z); 52001 this.movieScreen.scale.x = -1; 52002 this.movieScreen.quaternion.setFromAxisAngle({ 52003 x: 0, 52004 y: 1, 52005 z: 0 52006 }, -Math.PI / 2); 52007 this.scene.add(this.movieScreen); 52008 } else if (projection === '360_LR' || projection === '360_TB') { 52009 // Left eye view 52010 var geometry = new SphereGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail); 52011 var uvs = geometry.faceVertexUvs[0]; 52012 52013 for (var i = 0; i < uvs.length; i++) { 52014 for (var j = 0; j < 3; j++) { 52015 if (projection === '360_LR') { 52016 uvs[i][j].x *= 0.5; 52017 } else { 52018 uvs[i][j].y *= 0.5; 52019 uvs[i][j].y += 0.5; 52020 } 52021 } 52022 } 52023 52024 this.movieGeometry = new BufferGeometry().fromGeometry(geometry); 52025 this.movieMaterial = new MeshBasicMaterial({ 52026 map: this.videoTexture, 52027 overdraw: true, 52028 side: BackSide 52029 }); 52030 this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); 52031 this.movieScreen.scale.x = -1; 52032 this.movieScreen.quaternion.setFromAxisAngle({ 52033 x: 0, 52034 y: 1, 52035 z: 0 52036 }, -Math.PI / 2); // display in left eye only 52037 52038 this.movieScreen.layers.set(1); 52039 this.scene.add(this.movieScreen); // Right eye view 52040 52041 geometry = new SphereGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail); 52042 uvs = geometry.faceVertexUvs[0]; 52043 52044 for (var _i = 0; _i < uvs.length; _i++) { 52045 for (var _j = 0; _j < 3; _j++) { 52046 if (projection === '360_LR') { 52047 uvs[_i][_j].x *= 0.5; 52048 uvs[_i][_j].x += 0.5; 52049 } else { 52050 uvs[_i][_j].y *= 0.5; 52051 } 52052 } 52053 } 52054 52055 this.movieGeometry = new BufferGeometry().fromGeometry(geometry); 52056 this.movieMaterial = new MeshBasicMaterial({ 52057 map: this.videoTexture, 52058 overdraw: true, 52059 side: BackSide 52060 }); 52061 this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); 52062 this.movieScreen.scale.x = -1; 52063 this.movieScreen.quaternion.setFromAxisAngle({ 52064 x: 0, 52065 y: 1, 52066 z: 0 52067 }, -Math.PI / 2); // display in right eye only 52068 52069 this.movieScreen.layers.set(2); 52070 this.scene.add(this.movieScreen); 52071 } else if (projection === '360_CUBE') { 52072 this.movieGeometry = new BoxGeometry(256, 256, 256); 52073 this.movieMaterial = new MeshBasicMaterial({ 52074 map: this.videoTexture, 52075 overdraw: true, 52076 side: BackSide 52077 }); 52078 var left = [new Vector2(0, 0.5), new Vector2(0.333, 0.5), new Vector2(0.333, 1), new Vector2(0, 1)]; 52079 var right = [new Vector2(0.333, 0.5), new Vector2(0.666, 0.5), new Vector2(0.666, 1), new Vector2(0.333, 1)]; 52080 var top = [new Vector2(0.666, 0.5), new Vector2(1, 0.5), new Vector2(1, 1), new Vector2(0.666, 1)]; 52081 var bottom = [new Vector2(0, 0), new Vector2(0.333, 0), new Vector2(0.333, 0.5), new Vector2(0, 0.5)]; 52082 var front = [new Vector2(0.333, 0), new Vector2(0.666, 0), new Vector2(0.666, 0.5), new Vector2(0.333, 0.5)]; 52083 var back = [new Vector2(0.666, 0), new Vector2(1, 0), new Vector2(1, 0.5), new Vector2(0.666, 0.5)]; 52084 this.movieGeometry.faceVertexUvs[0] = []; 52085 this.movieGeometry.faceVertexUvs[0][0] = [right[2], right[1], right[3]]; 52086 this.movieGeometry.faceVertexUvs[0][1] = [right[1], right[0], right[3]]; 52087 this.movieGeometry.faceVertexUvs[0][2] = [left[2], left[1], left[3]]; 52088 this.movieGeometry.faceVertexUvs[0][3] = [left[1], left[0], left[3]]; 52089 this.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]]; 52090 this.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]]; 52091 this.movieGeometry.faceVertexUvs[0][6] = [bottom[2], bottom[1], bottom[3]]; 52092 this.movieGeometry.faceVertexUvs[0][7] = [bottom[1], bottom[0], bottom[3]]; 52093 this.movieGeometry.faceVertexUvs[0][8] = [front[2], front[1], front[3]]; 52094 this.movieGeometry.faceVertexUvs[0][9] = [front[1], front[0], front[3]]; 52095 this.movieGeometry.faceVertexUvs[0][10] = [back[2], back[1], back[3]]; 52096 this.movieGeometry.faceVertexUvs[0][11] = [back[1], back[0], back[3]]; 52097 this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); 52098 this.movieScreen.position.set(position.x, position.y, position.z); 52099 this.movieScreen.rotation.y = -Math.PI; 52100 this.scene.add(this.movieScreen); 52101 } else if (projection === '180' || projection === '180_LR' || projection === '180_MONO') { 52102 var _geometry = new SphereGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail, Math.PI, Math.PI); // Left eye view 52103 52104 52105 _geometry.scale(-1, 1, 1); 52106 52107 var _uvs = _geometry.faceVertexUvs[0]; 52108 52109 if (projection !== '180_MONO') { 52110 for (var _i2 = 0; _i2 < _uvs.length; _i2++) { 52111 for (var _j2 = 0; _j2 < 3; _j2++) { 52112 _uvs[_i2][_j2].x *= 0.5; 52113 } 52114 } 52115 } 52116 52117 this.movieGeometry = new BufferGeometry().fromGeometry(_geometry); 52118 this.movieMaterial = new MeshBasicMaterial({ 52119 map: this.videoTexture, 52120 overdraw: true 52121 }); 52122 this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); // display in left eye only 52123 52124 this.movieScreen.layers.set(1); 52125 this.scene.add(this.movieScreen); // Right eye view 52126 52127 _geometry = new SphereGeometry(256, this.options_.sphereDetail, this.options_.sphereDetail, Math.PI, Math.PI); 52128 52129 _geometry.scale(-1, 1, 1); 52130 52131 _uvs = _geometry.faceVertexUvs[0]; 52132 52133 for (var _i3 = 0; _i3 < _uvs.length; _i3++) { 52134 for (var _j3 = 0; _j3 < 3; _j3++) { 52135 _uvs[_i3][_j3].x *= 0.5; 52136 _uvs[_i3][_j3].x += 0.5; 52137 } 52138 } 52139 52140 this.movieGeometry = new BufferGeometry().fromGeometry(_geometry); 52141 this.movieMaterial = new MeshBasicMaterial({ 52142 map: this.videoTexture, 52143 overdraw: true 52144 }); 52145 this.movieScreen = new Mesh(this.movieGeometry, this.movieMaterial); // display in right eye only 52146 52147 this.movieScreen.layers.set(2); 52148 this.scene.add(this.movieScreen); 52149 } else if (projection === 'EAC' || projection === 'EAC_LR') { 52150 var makeScreen = function makeScreen(mapMatrix, scaleMatrix) { 52151 // "Continuity correction?": because of discontinuous faces and aliasing, 52152 // we truncate the 2-pixel-wide strips on all discontinuous edges, 52153 var contCorrect = 2; 52154 _this2.movieGeometry = new BoxGeometry(256, 256, 256); 52155 _this2.movieMaterial = new ShaderMaterial({ 52156 overdraw: true, 52157 side: BackSide, 52158 uniforms: { 52159 mapped: { 52160 value: _this2.videoTexture 52161 }, 52162 mapMatrix: { 52163 value: mapMatrix 52164 }, 52165 contCorrect: { 52166 value: contCorrect 52167 }, 52168 faceWH: { 52169 value: new Vector2(1 / 3, 1 / 2).applyMatrix3(scaleMatrix) 52170 }, 52171 vidWH: { 52172 value: new Vector2(_this2.videoTexture.image.videoWidth, _this2.videoTexture.image.videoHeight).applyMatrix3(scaleMatrix) 52173 } 52174 }, 52175 vertexShader: "\nvarying vec2 vUv;\nuniform mat3 mapMatrix;\n\nvoid main() {\n vUv = (mapMatrix * vec3(uv, 1.)).xy;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.);\n}", 52176 fragmentShader: "\nvarying vec2 vUv;\nuniform sampler2D mapped;\nuniform vec2 faceWH;\nuniform vec2 vidWH;\nuniform float contCorrect;\n\nconst float PI = 3.1415926535897932384626433832795;\n\nvoid main() {\n vec2 corner = vUv - mod(vUv, faceWH) + vec2(0, c
52176ontCorrect / vidWH.y);\n\n vec2 faceWHadj = faceWH - vec2(0, contCorrect * 2. / vidWH.y);\n\n vec2 p = (vUv - corner) / faceWHadj - .5;\n vec2 q = 2. / PI * atan(2. * p) + .5;\n\n vec2 eUv = corner + q * faceWHadj;\n\n gl_FragColor = texture2D(mapped, eUv);\n}" 52177 }); 52178 var right = [new Vector2(0, 1 / 2), new Vector2(1 / 3, 1 / 2), new Vector2(1 / 3, 1), new Vector2(0, 1)]; 52179 var front = [new Vector2(1 / 3, 1 / 2), new Vector2(2 / 3, 1 / 2), new Vector2(2 / 3, 1), new Vector2(1 / 3, 1)]; 52180 var left = [new Vector2(2 / 3, 1 / 2), new Vector2(1, 1 / 2), new Vector2(1, 1), new Vector2(2 / 3, 1)]; 52181 var bottom = [new Vector2(1 / 3, 0), new Vector2(1 / 3, 1 / 2), new Vector2(0, 1 / 2), new Vector2(0, 0)]; 52182 var back = [new Vector2(1 / 3, 1 / 2), new Vector2(1 / 3, 0), new Vector2(2 / 3, 0), new Vector2(2 / 3, 1 / 2)]; 52183 var top = [new Vector2(1, 0), new Vector2(1, 1 / 2), new Vector2(2 / 3, 1 / 2), new Vector2(2 / 3, 0)]; 52184 52185 for (var _i4 = 0, _arr = [right, front, left, bottom, back, top]; _i4 < _arr.length; _i4++) { 52186 var face = _arr[_i4]; 52187 var height = _this2.videoTexture.image.videoHeight; 52188 var lowY = 1; 52189 var highY = 0; 52190 52191 for (var _iterator = face, _isArray = Array.isArray(_iterator), _i5 = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { 52192 var _ref; 52193 52194 if (_isArray) { 52195 if (_i5 >= _iterator.length) break; 52196 _ref = _iterator[_i5++]; 52197 } else { 52198 _i5 = _iterator.next(); 52199 if (_i5.done) break; 52200 _ref = _i5.value; 52201 } 52202 52203 var vector = _ref; 52204 52205 if (vector.y < lowY) { 52206 lowY = vector.y; 52207 } 52208 52209 if (vector.y > highY) { 52210 highY = vector.y; 52211 } 52212 } 52213 52214 for (var _iterator2 = face, _isArray2 = Array.isArray(_iterator2), _i6 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) { 52215 var _ref2; 52216 52217 if (_isArray2) { 52218 if (_i6 >= _iterator2.length) break; 52219 _ref2 = _iterator2[_i6++]; 52220 } else { 52221 _i6 = _iterator2.next(); 52222 if (_i6.done) break; 52223 _ref2 = _i6.value; 52224 } 52225 52226 var _vector = _ref2; 52227 52228 if (Math.abs(_vector.y - lowY) < Number.EPSILON) { 52229 _vector.y += contCorrect / height; 52230 } 52231 52232 if (Math.abs(_vector.y - highY) < Number.EPSILON) { 52233 _vector.y -= contCorrect / height; 52234 } 52235 52236 _vector.x = _vector.x / height * (height - contCorrect * 2) + contCorrect / height; 52237 } 52238 } 52239 52240 _this2.movieGeometry.faceVertexUvs[0] = []; 52241 _this2.movieGeometry.faceVertexUvs[0][0] = [right[2], right[1], right[3]]; 52242 _this2.movieGeometry.faceVertexUvs[0][1] = [right[1], right[0], right[3]]; 52243 _this2.movieGeometry.faceVertexUvs[0][2] = [left[2], left[1], left[3]]; 52244 _this2.movieGeometry.faceVertexUvs[0][3] = [left[1], left[0], left[3]]; 52245 _this2.movieGeometry.faceVertexUvs[0][4] = [top[2], top[1], top[3]]; 52246 _this2.movieGeometry.faceVertexUvs[0][5] = [top[1], top[0], top[3]]; 52247 _this2.movieGeometry.faceVertexUvs[0][6] = [bottom[2], bottom[1], bottom[3]]; 52248 _this2.movieGeometry.faceVertexUvs[0][7] = [bottom[1], bottom[0], bottom[3]]; 52249 _this2.movieGeometry.faceVertexUvs[0][8] = [front[2], front[1], front[3]]; 52250 _this2.movieGeometry.faceVertexUvs[0][9] = [front[1], front[0], front[3]]; 52251 _this2.movieGeometry.faceVertexUvs[0][10] = [back[2], back[1], back[3]]; 52252 _this2.movieGeometry.faceVertexUvs[0][11] = [back[1], back[0], back[3]]; 52253 _this2.movieScreen = new Mesh(_this2.movieGeometry, _this2.movieMaterial); 52254 52255 _this2.movieScreen.position.set(position.x, position.y, position.z); 52256 52257 _this2.movieScreen.rotation.y = -Math.PI; 52258 return _this2.movieScreen; 52259 }; 52260 52261 if (projection === 'EAC') { 52262 this.scene.add(makeScreen(new Matrix3(), new Matrix3())); 52263 } else { 52264 var scaleMatrix = new Matrix3().set(0, 0.5, 0, 1, 0, 0, 0, 0, 1); 52265 makeScreen(new Matrix3().set(0, -0.5, 0.5, 1, 0, 0, 0, 0, 1), scaleMatrix); // display in left eye only 52266 52267 this.movieScreen.layers.set(1); 52268 this.scene.add(this.movieScreen); 52269 makeScreen(new Matrix3().set(0, -0.5, 1, 1, 0, 0, 0, 0, 1), scaleMatrix); // display in right eye only 52270 52271 this.movieScreen.layers.set(2); 52272 this.scene.add(this.movieScreen); 52273 } 52274 } 52275 52276 this.currentProjection_ = projection; 52277 }; 52278 52279 _proto.triggerError_ = function triggerError_(errorObj) { 52280 // if we have videojs-errors use it 52281 if (this.videojsErrorsSupport_) { 52282 this.player_.error(errorObj); // if we don't have videojs-errors just use a normal player error 52283 } else { 52284 // strip any html content from the error message 52285 // as it is not supported outside of videojs-errors 52286 var div = document$1.createElement('div'); 52287 div.innerHTML = errors[errorObj.code].message; 52288 var message = div.textContent || div.innerText || ''; 52289 this.player_.error({ 52290 code: errorObj.code, 52291 message: message 52292 }); 52293 } 52294 }; 52295 52296 _proto.log = function log() { 52297 if (!this.options_.debug) { 52298 return; 52299 } 52300 52301 for (var _len = arguments.length, msgs = new Array(_len), _key = 0; _key < _len; _key++) { 52302 msgs[_key] = arguments[_key]; 52303 } 52304
52305 msgs.forEach(function (msg) { 52306 videojs.log('VR: ', msg); 52307 }); 52308 }; 52309 52310 _proto.handleVrDisplayActivate_ = function handleVrDisplayActivate_() { 52311 var _this3 = this; 52312 52313 if (!this.vrDisplay) { 52314 return; 52315 } 52316 52317 this.vrDisplay.requestPresent([{ 52318 source: this.renderedCanvas 52319 }]).then(function () { 52320 if (!_this3.vrDisplay.cardboardUI_ || !videojs.browser.IS_IOS) { 52321 return; 52322 } // webvr-polyfill/cardboard ui only watches for click events 52323 // to tell that the back arrow button is pressed during cardboard vr. 52324 // but somewhere along the line these events are silenced with preventDefault 52325 // but only on iOS, so we translate them ourselves here 52326 52327 52328 var touches = []; 52329 52330 var iosCardboardTouchStart_ = function iosCardboardTouchStart_(e) { 52331 for (var i = 0; i < e.touches.length; i++) { 52332 touches.push(e.touches[i]); 52333 } 52334 }; 52335 52336 var iosCardboardTouchEnd_ = function iosCardboardTouchEnd_(e) { 52337 if (!touches.length) { 52338 return; 52339 } 52340 52341 touches.forEach(function (t) { 52342 var simulatedClick = new window$1.MouseEvent('click', { 52343 screenX: t.screenX, 52344 screenY: t.screenY, 52345 clientX: t.clientX, 52346 clientY: t.clientY 52347 }); 52348 52349 _this3.renderedCanvas.dispatchEvent(simulatedClick); 52350 }); 52351 touches = []; 52352 }; 52353 52354 _this3.renderedCanvas.addEventListener('touchstart', iosCardboardTouchStart_); 52355 52356 _this3.renderedCanvas.addEventListener('touchend', iosCardboardTouchEnd_); 52357 52358 _this3.iosRevertTouchToClick_ = function () { 52359 _this3.renderedCanvas.removeEventListener('touchstart', iosCardboardTouchStart_); 52360 52361 _this3.renderedCanvas.removeEventListener('touchend', iosCardboardTouchEnd_); 52362 52363 _this3.iosRevertTouchToClick_ = null; 52364 }; 52365 }); 52366 }; 52367 52368 _proto.handleVrDisplayDeactivate_ = function handleVrDisplayDeactivate_() { 52369 if (!this.vrDisplay || !this.vrDisplay.isPresenting) { 52370 return; 52371 } 52372 52373 if (this.iosRevertTouchToClick_) { 52374 this.iosRevertTouchToClick_(); 52375 } 52376 52377 this.vrDisplay.exitPresent(); 52378 }; 52379 52380 _proto.requestAnimationFrame = function requestAnimationFrame(fn) { 52381 if (this.vrDisplay) { 52382 return this.vrDisplay.requestAnimationFrame(fn); 52383 } 52384 52385 return this.player_.requestAnimationFrame(fn); 52386 }; 52387 52388 _proto.cancelAnimationFrame = function cancelAnimationFrame(id) { 52389 if (this.vrDisplay) { 52390 return this.vrDisplay.cancelAnimationFrame(id); 52391 } 52392 52393 return this.player_.cancelAnimationFrame(id); 52394 }; 52395 52396 _proto.togglePlay_ = function togglePlay_() { 52397 if (this.player_.paused()) { 52398 this.player_.play(); 52399 } else { 52400 this.player_.pause(); 52401 } 52402 }; 52403 52404 _proto.animate_ = function animate_() { 52405 if (!this.initialized_) { 52406 return; 52407 } 52408 52409 if (this.getVideoEl_().readyState === this.getVideoEl_().HAVE_ENOUGH_DATA) { 52410 if (this.videoTexture) { 52411 this.videoTexture.needsUpdate = true; 52412 } 52413 } 52414 52415 this.controls3d.update(); 52416 52417 if (this.omniController) { 52418 this.omniController.update(this.camera); 52419 } 52420 52421 this.effect.render(this.scene, this.camera); 52422 52423 if (window$1.navigator.getGamepads) { 52424 // Grab all gamepads 52425 var gamepads = window$1.navigator.getGamepads(); 52426 52427 for (var i = 0; i < gamepads.length; ++i) { 52428 var gamepad = gamepads[i]; // Make sure gamepad is defined 52429 // Only take input if state has changed since we checked last 52430 52431 if (!gamepad || !gamepad.timestamp || gamepad.timestamp === this.prevTimestamps_[i]) { 52432 continue; 52433 } 52434 52435 for (var j = 0; j < gamepad.buttons.length; ++j) { 52436 if (gamepad.buttons[j].pressed) { 52437 this.togglePlay_(); 52438 this.prevTimestamps_[i] = gamepad.timestamp; 52439 break; 52440 } 52441 } 52442 } 52443 } 52444 52445 this.camera.getWorldDirection(this.cameraVector); 52446 this.animationFrameId_ = this.requestAnimationFrame(this.animate_); 52447 }; 52448 52449 _proto.handleResize_ = function handleResize_() { 52450 var width = this.player_.currentWidth(); 52451 var height = this.player_.currentHeight(); 52452 this.effect.setSize(width, height, false); 52453 this.camera.aspect = width / height; 52454 this.camera.updateProjectionMatrix(); 52455 }; 52456 52457 _proto.setProjection = function setProjection(projection) { 52458 if (!getInternalProjectionName(projection)) { 52459 videojs.log.error('videojs-vr: please pass a valid projection ' + validProjections.join(', ')); 52460 return; 52461 } 52462 52463 this.currentProjection_ = projection; 52464 this.defaultProjection_ = projection; 52465 }; 52466
52467 _proto.init = function init() { 52468 var _this4 = this; 52469 52470 this.reset(); 52471 this.camera = new PerspectiveCamera(75, this.player_.currentWidth() / this.player_.currentHeight(), 1, 1000); // Store vector representing the direction in which the camera is looking, in world space. 52472 52473 this.cameraVector = new Vector3(); 52474 52475 if (this.currentProjection_ === '360_LR' || this.currentProjection_ === '360_TB' || this.currentProjection_ === '180' || this.currentProjection_ === '180_LR' || this.currentProjection_ === '180_MONO' || this.currentProjection_ === 'EAC_LR') { 52476 // Render left eye when not in VR mode 52477 this.camera.layers.enable(1); 52478 } 52479 52480 this.scene = new Scene(); 52481 this.videoTexture = new VideoTexture(this.getVideoEl_()); // shared regardless of wether VideoTexture is used or 52482 // an image canvas is used 52483 52484 this.videoTexture.generateMipmaps = false; 52485 this.videoTexture.minFilter = LinearFilter; 52486 this.videoTexture.magFilter = LinearFilter; 52487 this.videoTexture.format = RGBFormat; 52488 this.changeProjection_(this.currentProjection_); 52489 52490 if (this.currentProjection_ === 'NONE') { 52491 this.log('Projection is NONE, dont init'); 52492 this.reset(); 52493 return; 52494 } 52495 52496 this.player_.removeChild('BigPlayButton'); 52497 this.player_.addChild('BigVrPlayButton', {}, this.bigPlayButtonIndex_); 52498 this.player_.bigPlayButton = this.player_.getChild('BigVrPlayButton'); // mobile devices, or cardboard forced to on 52499 52500 if (this.options_.forceCardboard || videojs.browser.IS_ANDROID || videojs.browser.IS_IOS) { 52501 this.addCardboardButton_(); 52502 } // if ios remove full screen toggle 52503 52504 52505 if (videojs.browser.IS_IOS && this.player_.controlBar && this.player_.controlBar.fullscreenToggle) { 52506 this.player_.controlBar.fullscreenToggle.hide(); 52507 } 52508 52509 this.camera.position.set(0, 0, 0); 52510 this.renderer = new WebGLRenderer({ 52511 devicePixelRatio: window$1.devicePixelRatio, 52512 alpha: false, 52513 clearColor: 0xffffff, 52514 antialias: true 52515 }); 52516 var webglContext = this.renderer.getContext('webgl'); 52517 var oldTexImage2D = webglContext.texImage2D; 52518 /* this is a workaround since threejs uses try catch */ 52519 52520 webglContext.texImage2D = function () { 52521 try { 52522 for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { 52523 args[_key2] = arguments[_key2]; 52524 } 52525 52526 return oldTexImage2D.apply(webglContext, args); 52527 } catch (e) { 52528 _this4.reset(); 52529 52530 _this4.player_.pause(); 52531 52532 _this4.triggerError_({ 52533 code: 'web-vr-hls-cors-not-supported', 52534 dismiss: false 52535 }); 52536 52537 throw new Error(e); 52538 } 52539 }; 52540 52541 this.renderer.setSize(this.player_.currentWidth(), this.player_.currentHeight(), false); 52542 this.effect = new VREffect(this.renderer); 52543 this.effect.setSize(this.player_.currentWidth(), this.player_.currentHeight(), false); 52544 this.vrDisplay = null; // Previous timestamps for gamepad updates 52545 52546 this.prevTimestamps_ = []; 52547 this.renderedCanvas = this.renderer.domElement; 52548 this.renderedCanvas.setAttribute('style', 'width: 100%; height: 100%; position: absolute; top:0;'); 52549 var videoElStyle = this.getVideoEl_().style; 52550 this.player_.el().insertBefore(this.renderedCanvas, this.player_.el().firstChild); 52551 videoElStyle.zIndex = '-1'; 52552 videoElStyle.opacity = '0'; 52553 52554 if (window$1.navigator.getVRDisplays) { 52555 this.log('is supported, getting vr displays'); 52556 window$1.navigator.getVRDisplays().then(function (displays) { 52557 if (displays.length > 0) { 52558 _this4.log('Displays found', displays); 52559 52560 _this4.vrDisplay = displays[0]; // Native WebVR Head Mounted Displays (HMDs) like the HTC Vive 52561 // also need the cardboard button to enter fully immersive mode 52562 // so, we want to add the button if we're not polyfilled. 52563 52564 if (!_this4.vrDisplay.isPolyfilled) { 52565 _this4.log('Real HMD found using VRControls', _this4.vrDisplay); 52566 52567 _this4.addCardboardButton_(); // We use VRControls here since we are working with an HMD 52568 // and we only want orientation controls. 52569 52570 52571 _this4.controls3d = new VRControls(_this4.camera); 52572 } 52573 } 52574 52575 if (!_this4.controls3d) { 52576 _this4.log('no HMD found Using Orbit & Orientation Controls'); 52577 52578 var options = { 52579 camera: _this4.camera, 52580 canvas: _this4.renderedCanvas, 52581 // check if its a half sphere view projection 52582 halfView: _this4.currentProjection_.indexOf('180') === 0, 52583 orientation: videojs.browser.IS_IOS || videojs.browser.IS_ANDROID || false 52584 }; 52585 52586 if (_this4.options_.motionControls === false) { 52587 options.orientation = false;
52588 } 52589 52590 _this4.controls3d = new OrbitOrientationControls(options); 52591 _this4.canvasPlayerControls = new CanvasPlayerControls(_this4.player_, _this4.renderedCanvas); 52592 } 52593 52594 _this4.animationFrameId_ = _this4.requestAnimationFrame(_this4.animate_); 52595 }); 52596 } else if (window$1.navigator.getVRDevices) { 52597 this.triggerError_({ 52598 code: 'web-vr-out-of-date', 52599 dismiss: false 52600 }); 52601 } else { 52602 this.triggerError_({ 52603 code: 'web-vr-not-supported', 52604 dismiss: false 52605 }); 52606 } 52607 52608 if (this.options_.omnitone) { 52609 var audiocontext = AudioContext.getContext(); 52610 this.omniController = new OmnitoneController(audiocontext, this.options_.omnitone, this.getVideoEl_(), this.options_.omnitoneOptions); 52611 this.omniController.one('audiocontext-suspended', function () { 52612 _this4.player.pause(); 52613 52614 _this4.player.one('playing', function () { 52615 audiocontext.resume(); 52616 }); 52617 }); 52618 } 52619 52620 this.on(this.player_, 'fullscreenchange', this.handleResize_); 52621 window$1.addEventListener('vrdisplaypresentchange', this.handleResize_, true); 52622 window$1.addEventListener('resize', this.handleResize_, true); 52623 window$1.addEventListener('vrdisplayactivate', this.handleVrDisplayActivate_, true); 52624 window$1.addEventListener('vrdisplaydeactivate', this.handleVrDisplayDeactivate_, true); 52625 this.initialized_ = true; 52626 this.trigger('initialized'); 52627 }; 52628 52629 _proto.addCardboardButton_ = function addCardboardButton_() { 52630 if (!this.player_.controlBar.getChild('CardboardButton')) { 52631 this.player_.controlBar.addChild('CardboardButton', {}); 52632 } 52633 }; 52634 52635 _proto.getVideoEl_ = function getVideoEl_() { 52636 return this.player_.el().getElementsByTagName('video')[0]; 52637 }; 52638 52639 _proto.reset = function reset() { 52640 if (!this.initialized_) { 52641 return; 52642 } 52643 52644 if (this.omniController) { 52645 this.omniController.off('audiocontext-suspended'); 52646 this.omniController.dispose(); 52647 this.omniController = undefined; 52648 } 52649 52650 if (this.controls3d) { 52651 this.controls3d.dispose(); 52652 this.controls3d = null; 52653 } 52654 52655 if (this.canvasPlayerControls) { 52656 this.canvasPlayerControls.dispose(); 52657 this.canvasPlayerControls = null; 52658 } 52659 52660 if (this.effect) { 52661 this.effect.dispose(); 52662 this.effect = null; 52663 } 52664 52665 window$1.removeEventListener('resize', this.handleResize_, true); 52666 window$1.removeEventListener('vrdisplaypresentchange', this.handleResize_, true); 52667 window$1.removeEventListener('vrdisplayactivate', this.handleVrDisplayActivate_, true); 52668 window$1.removeEventListener('vrdisplaydeactivate', this.handleVrDisplayDeactivate_, true); // re-add the big play button to player 52669 52670 if (!this.player_.getChild('BigPlayButton')) { 52671 this.player_.addChild('BigPlayButton', {}, this.bigPlayButtonIndex_); 52672 } 52673 52674 if (this.player_.getChild('BigVrPlayButton')) { 52675 this.player_.removeChild('BigVrPlayButton'); 52676 } // remove the cardboard button 52677 52678 52679 if (this.player_.getChild('CardboardButton')) { 52680 this.player_.controlBar.removeChild('CardboardButton'); 52681 } // show the fullscreen again 52682 52683 52684 if (videojs.browser.IS_IOS && this.player_.controlBar && this.player_.controlBar.fullscreenToggle) { 52685 this.player_.controlBar.fullscreenToggle.show(); 52686 } // reset the video element style so that it will be displayed 52687 52688 52689 var videoElStyle = this.getVideoEl_().style; 52690 videoElStyle.zIndex = ''; 52691 videoElStyle.opacity = ''; // set the current projection to the default 52692 52693 this.currentProjection_ = this.defaultProjection_; // reset the ios touch to click workaround 52694 52695 if (this.iosRevertTouchToClick_) { 52696 this.iosRevertTouchToClick_(); 52697 } // remove the old canvas 52698 52699 52700 if (this.renderedCanvas) { 52701 this.renderedCanvas.parentNode.removeChild(this.renderedCanvas); 52702 } 52703 52704 if (this.animationFrameId_) { 52705 this.cancelAnimationFrame(this.animationFrameId_); 52706 } 52707 52708 this.initialized_ = false; 52709 }; 52710 52711 _proto.dispose = function dispose() { 52712 _Plugin.prototype.dispose.call(this); 52713 52714 this.reset(); 52715 }; 52716 52717 _proto.polyfillVersion = function polyfillVersion() { 52718 return WebVRPolyfill.version; 52719 }; 52720 52721 return VR; 52722 }(Plugin); 52723 52724 VR.prototype.setTimeout = Component.prototype.setTimeout; 52725 VR.prototype.clearTimeout = Component.prototype.clearTimeout; 52726 VR.VERSION = version; 52727 videojs.registerPlugin('vr', VR); 52728 52729 return VR; 52730 52731 })));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.