├── .gitignore ├── LICENSE ├── README.md ├── images ├── 1.png ├── chrome_1.png ├── chrome_2.png ├── gon.png ├── ikea.png ├── sem.png ├── sig.png ├── vsc_1.png └── vsc_2.png ├── index.html ├── libs ├── brotli │ ├── BUILD │ ├── LICENSE │ ├── WORKSPACE │ ├── decode.js │ ├── decode.min.js │ ├── decode_test.js │ └── polyfill.js └── three.js │ ├── LICENSE │ ├── README.md │ ├── build │ ├── three.js │ ├── three.min.js │ └── three.module.js │ ├── extra │ ├── GLTFLoader.js │ ├── VRButton.js │ ├── XRControllerModelFactory.js │ ├── lines.js │ └── lines │ │ ├── Line2.js │ │ ├── LineGeometry.js │ │ ├── LineMaterial.js │ │ ├── LineSegments2.js │ │ ├── LineSegmentsGeometry.js │ │ ├── Wireframe.js │ │ └── WireframeGeometry2.js │ ├── libs │ ├── chevrotain.module.min.js │ ├── dat.gui.module.js │ ├── deflate.module.min.js │ ├── gunzip.module.min.js │ ├── inflate.module.min.js │ ├── jszip.module.min.js │ ├── meshopt_decoder.module.js │ ├── mmdparser.module.js │ ├── motion-controllers.module.js │ ├── opentype.module.min.js │ ├── stats.module.js │ ├── tween.module.min.js │ └── zstddec.module.js │ ├── lines │ ├── Line2.js │ ├── LineGeometry.js │ ├── LineMaterial.js │ ├── LineSegments2.js │ ├── LineSegmentsGeometry.js │ ├── Wireframe.js │ └── WireframeGeometry2.js │ ├── loaders │ ├── 3DMLoader.js │ ├── 3MFLoader.js │ ├── AMFLoader.js │ ├── AssimpLoader.js │ ├── BVHLoader.js │ ├── BasisTextureLoader.js │ ├── ColladaLoader.js │ ├── DDSLoader.js │ ├── DRACOLoader.js │ ├── EXRLoader.js │ ├── FBXLoader.js │ ├── GCodeLoader.js │ ├── GLTFLoader.js │ ├── HDRCubeTextureLoader.js │ ├── KMZLoader.js │ ├── KTX2Loader.js │ ├── KTXLoader.js │ ├── LDrawLoader.js │ ├── LUT3dlLoader.js │ ├── LUTCubeLoader.js │ ├── LWOLoader.js │ ├── LottieLoader.js │ ├── MD2Loader.js │ ├── MDDLoader.js │ ├── MMDLoader.js │ ├── MTLLoader.js │ ├── NRRDLoader.js │ ├── NodeMaterialLoader.js │ ├── OBJLoader.js │ ├── OBJLoader2.js │ ├── OBJLoader2Parallel.js │ ├── PCDLoader.js │ ├── PDBLoader.js │ ├── PLYLoader.js │ ├── PRWMLoader.js │ ├── PVRLoader.js │ ├── RGBELoader.js │ ├── STLLoader.js │ ├── SVGLoader.js │ ├── TDSLoader.js │ ├── TGALoader.js │ ├── TTFLoader.js │ ├── TiltLoader.js │ ├── VOXLoader.js │ ├── VRMLLoader.js │ ├── VRMLoader.js │ ├── VTKLoader.js │ ├── XLoader.js │ ├── XYZLoader.js │ ├── lwo │ │ ├── IFFParser.js │ │ ├── LWO2Parser.js │ │ └── LWO3Parser.js │ └── obj2 │ │ ├── OBJLoader2Parser.js │ │ ├── bridge │ │ └── MtlObjBridge.js │ │ ├── shared │ │ ├── MaterialHandler.js │ │ └── MeshReceiver.js │ │ ├── utils │ │ └── CodeSerializer.js │ │ └── worker │ │ ├── main │ │ └── WorkerExecutionSupport.js │ │ └── parallel │ │ ├── OBJLoader2JsmWorker.js │ │ └── WorkerRunner.js │ └── webxr │ ├── ARButton.js │ ├── VRButton.js │ ├── XRControllerModelFactory.js │ ├── XRHandModelFactory.js │ ├── XRHandOculusMeshModel.js │ └── XRHandPrimitiveModel.js ├── small_garage.html └── src ├── gaussian-utils ├── DecoderWorker.js ├── DecoderWorker_brotli.js ├── DecoderWorker_gaussian.js ├── WorkerPool.js ├── gaussian-attributes.js ├── gaussian-octree-loader.js └── gaussian-octree.js ├── gl-matrix-min.js ├── indexedDB.js ├── lil-gui@0.18 ├── localforage.min.js ├── main.js ├── main_old ├── main 0.js ├── main 1.js ├── main 2.js └── main 3.js ├── potree.js └── public.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .vscode/* 3 | model/* 4 | UNUSED/* 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Kevin Kwok 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LOD Web Viewer for LetsGo 2 | 3 | ## LetsGo: Large-Scale Garage Modeling and Rendering via LiDAR-Assisted Gaussian Primitives 4 | 6 | 7 | [Project page](https://zhaofuq.github.io/LetsGo/) | [Paper](https://arxiv.org/pdf/2404.09748) | [Video](https://www.youtube.com/watch?v=fs42UBKvGRw) | [LOD Viewer (SIBR)](https://zhaofuq.github.io/LetsGo/) | [Web Viewer](https://zhaofuq.github.io/LetsGo/)| [GarageWorld Dataset](https://zhaofuq.github.io/LetsGo/)
8 | 9 | We provide a web renderer to allow users to experience a scene with Level of Detail (LOD) Gaussian rendering. For users with a computer, the application can be run directly. However, for users with an iPad (preferably with an M- chip), you need to start the server on a computer and ensure that both the iPad and the computer are on the same local network to access it. 10 | 11 | 12 | 13 | ## Setup 14 | 15 | #### Install requirements (For mainstream computer OSs) 16 | 17 | - [**Chrome**](https://www.google.com/chrome/) 18 | 19 | - [**Visual Studio Code**](https://code.visualstudio.com/download) (to start the server) 20 | - And [**Live Server extension**](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer) 21 | 22 | - Or 23 | - [**Node.js**](https://nodejs.org/en/download/package-manager) and [**NPM**](https://docs.npmjs.com/getting-started) (to start the server) 24 | - And [**Live server**](http://tapiov.net/live-server/) 25 | 26 | 27 | #### Install requirements (For iPadOS) 28 | 29 | - [**Chrome**](https://www.google.com/chrome/) 30 | 31 | #### Clone the repo 32 | 33 | Checkout this repository's main branch: 34 | 35 | ```sh 36 | ## through HTTPS 37 | git clone https://github.com/zhaofuq/LOD-Web-Viewer.git 38 | ## through SSH 39 | git clone git@github.com:zhaofuq/LOD-Web-Viewer.git 40 | ``` 41 | 42 | #### Download the data 43 | Put [small garage sample data](https://drive.google.com/drive/folders/1WWHpzkRPYfVuqx9wP1wMpUM78LK3GlTk?usp=sharing) in `LOD-Web-Viewer`. 44 | 45 | ## To run an example 46 | 47 | #### Start with VSCode 48 | 49 | Use VSCode to open the folder: 50 | 51 | ``` 52 | cd {your-folder}/LOD-web-viewer/ 53 | code . 54 | ``` 55 | 56 | Go Live, 57 | 58 | vsc_1 59 | 60 | vsc_2 61 | 62 | Then, open Chrome on the computer and visit the server, usually at `127.0.0.1:5500`. 63 | 64 | #### Start with NPM 65 | 66 | Run it in the terminal: 67 | 68 | ``` 69 | your-name@your-computer:{your-folder}/LOD-web-viewer$ live-server 70 | Serving "{your-folder}/LOD-web-viewer" at http://127.0.0.1:8080 71 | ... 72 | ``` 73 | 74 | Then, open Chrome on the computer and visit the server at `127.0.0.1:8080`. 75 | 76 | #### Visualization on computer 77 | 78 | chrome_1 79 | 80 | chrome_2 81 | 82 | It is recommended to use the `WASDQEIJKL` keys for moving the view horizontally,vertically, forward, backward, and side to side. Click on the webpage using your mouse or touchpad to refresh the view with more details. 83 | 84 | #### Visualization on iPad 85 | 86 | First, obtain your computer's IP address. 87 | 88 | Then, open Chrome on the iPad and visit the server at `192.168.xxx.xxx:{your-port}`. 89 | 90 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /images/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaofuq/LOD-Web-Viewer/6fedef1df59b808337738f875fdcba06d8ed7125/images/1.png -------------------------------------------------------------------------------- /images/chrome_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaofuq/LOD-Web-Viewer/6fedef1df59b808337738f875fdcba06d8ed7125/images/chrome_1.png -------------------------------------------------------------------------------- /images/chrome_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaofuq/LOD-Web-Viewer/6fedef1df59b808337738f875fdcba06d8ed7125/images/chrome_2.png -------------------------------------------------------------------------------- /images/gon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaofuq/LOD-Web-Viewer/6fedef1df59b808337738f875fdcba06d8ed7125/images/gon.png -------------------------------------------------------------------------------- /images/ikea.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaofuq/LOD-Web-Viewer/6fedef1df59b808337738f875fdcba06d8ed7125/images/ikea.png -------------------------------------------------------------------------------- /images/sem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaofuq/LOD-Web-Viewer/6fedef1df59b808337738f875fdcba06d8ed7125/images/sem.png -------------------------------------------------------------------------------- /images/sig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaofuq/LOD-Web-Viewer/6fedef1df59b808337738f875fdcba06d8ed7125/images/sig.png -------------------------------------------------------------------------------- /images/vsc_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaofuq/LOD-Web-Viewer/6fedef1df59b808337738f875fdcba06d8ed7125/images/vsc_1.png -------------------------------------------------------------------------------- /images/vsc_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zhaofuq/LOD-Web-Viewer/6fedef1df59b808337738f875fdcba06d8ed7125/images/vsc_2.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | LetsGo Viewer 8 | 101 | 102 | 103 | 104 |
105 |

LetsGo Viewer

106 |

Large-Scale Garage Modeling and Rendering via LiDAR-Assisted Gaussian Primitives

107 |
108 | 109 |
110 |

Real-Time Level-of-detail Viewer Demos

111 |
112 | 113 |
114 | 115 |
116 |
117 |
Campus 2
118 |
2990MB
119 |
120 |
121 | 122 | 123 |
124 |
125 | 139 | 140 | 141 | -------------------------------------------------------------------------------- /libs/brotli/BUILD: -------------------------------------------------------------------------------- 1 | package( 2 | default_visibility = ["//visibility:public"], 3 | ) 4 | 5 | licenses(["notice"]) # MIT 6 | 7 | load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library") 8 | 9 | # Not a real polyfill. Do NOT use for anything, but tests. 10 | closure_js_library( 11 | name = "polyfill", 12 | srcs = ["polyfill.js"], 13 | suppress = [ 14 | "JSC_INVALID_OPERAND_TYPE", 15 | "JSC_MISSING_JSDOC", 16 | "JSC_STRICT_INEXISTENT_PROPERTY", 17 | "JSC_TYPE_MISMATCH", 18 | "JSC_UNKNOWN_EXPR_TYPE", 19 | ], 20 | ) 21 | 22 | # Do NOT use this artifact; it is for test purposes only. 23 | closure_js_library( 24 | name = "decode", 25 | srcs = ["decode.js"], 26 | suppress = [ 27 | "JSC_DUP_VAR_DECLARATION", 28 | "JSC_USELESS_BLOCK", 29 | ], 30 | deps = [":polyfill"], 31 | ) 32 | 33 | load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_test") 34 | 35 | closure_js_test( 36 | name = "all_tests", 37 | srcs = ["decode_test.js"], 38 | deps = [ 39 | ":decode", 40 | ":polyfill", 41 | "@io_bazel_rules_closure//closure/library:testing", 42 | ], 43 | ) 44 | -------------------------------------------------------------------------------- /libs/brotli/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009, 2010, 2013-2016 by the Brotli Authors. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /libs/brotli/WORKSPACE: -------------------------------------------------------------------------------- 1 | workspace(name = "org_brotli_js") 2 | 3 | load("@bazel_tools//tools/build_defs/repo:git.bzl", "git_repository") 4 | 5 | git_repository( 6 | name = "io_bazel_rules_closure", 7 | commit = "29ec97e7c85d607ba9e41cab3993fbb13f812c4b", 8 | remote = "https://github.com/bazelbuild/rules_closure.git", 9 | ) 10 | 11 | load("@io_bazel_rules_closure//closure:defs.bzl", "closure_repositories") 12 | closure_repositories() 13 | -------------------------------------------------------------------------------- /libs/brotli/decode_test.js: -------------------------------------------------------------------------------- 1 | goog.require('goog.testing.asserts'); 2 | goog.require('goog.testing.jsunit'); 3 | 4 | /** 5 | * @param {!Int8Array} bytes 6 | * @return {string} 7 | */ 8 | function bytesToString(bytes) { 9 | return String.fromCharCode.apply(null, new Uint16Array(bytes)); 10 | } 11 | 12 | function testMetadata() { 13 | assertEquals("", bytesToString(BrotliDecode(Int8Array.from([1, 11, 0, 42, 3])))); 14 | } 15 | 16 | function testEmpty() { 17 | assertEquals("", bytesToString(BrotliDecode(Int8Array.from([6])))); 18 | assertEquals("", bytesToString(BrotliDecode(Int8Array.from([0x81, 1])))); 19 | } 20 | 21 | function testBaseDictWord() { 22 | var input = Int8Array.from([ 23 | 0x1b, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe3, 0xb4, 0x0d, 0x00, 0x00, 24 | 0x07, 0x5b, 0x26, 0x31, 0x40, 0x02, 0x00, 0xe0, 0x4e, 0x1b, 0x41, 0x02 25 | ]); 26 | /** @type {!Int8Array} */ 27 | var output = BrotliDecode(input); 28 | assertEquals("time", bytesToString(output)); 29 | } 30 | 31 | function testBlockCountMessage() { 32 | var input = Int8Array.from([ 33 | 0x1b, 0x0b, 0x00, 0x11, 0x01, 0x8c, 0xc1, 0xc5, 0x0d, 0x08, 0x00, 0x22, 34 | 0x65, 0xe1, 0xfc, 0xfd, 0x22, 0x2c, 0xc4, 0x00, 0x00, 0x38, 0xd8, 0x32, 35 | 0x89, 0x01, 0x12, 0x00, 0x00, 0x77, 0xda, 0x04, 0x10, 0x42, 0x00, 0x00, 0x00 36 | ]); 37 | /** @type {!Int8Array} */ 38 | var output = BrotliDecode(input); 39 | assertEquals("aabbaaaaabab", bytesToString(output)); 40 | } 41 | 42 | function testCompressedUncompressedShortCompressedSmallWindow() { 43 | var input = Int8Array.from([ 44 | 0x21, 0xf4, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xa7, 0x6d, 0x00, 0x00, 45 | 0x38, 0xd8, 0x32, 0x89, 0x01, 0x12, 0x00, 0x00, 0x77, 0xda, 0x34, 0x7b, 46 | 0xdb, 0x50, 0x80, 0x02, 0x80, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x31, 47 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x4e, 0xdb, 0x00, 0x00, 0x70, 0xb0, 48 | 0x65, 0x12, 0x03, 0x24, 0x00, 0x00, 0xee, 0xb4, 0x11, 0x24, 0x00 49 | ]); 50 | /** @type {!Int8Array} */ 51 | var output = BrotliDecode(input); 52 | assertEquals( 53 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 54 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 55 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 56 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 57 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 58 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 59 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 60 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 61 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 62 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 63 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 64 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 65 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 66 | "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + 67 | "aaaaaaaaaaaaaabbbbbbbbbb", bytesToString(output)); 68 | } 69 | 70 | function testIntactDistanceRingBuffer0() { 71 | var input = Int8Array.from([ 72 | 0x1b, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe3, 0xb4, 0x0d, 0x00, 0x00, 73 | 0x07, 0x5b, 0x26, 0x31, 0x40, 0x02, 0x00, 0xe0, 0x4e, 0x1b, 0xa1, 0x80, 74 | 0x20, 0x00 75 | ]); 76 | /** @type {!Int8Array} */ 77 | var output = BrotliDecode(input); 78 | assertEquals("himselfself", bytesToString(output)); 79 | } 80 | -------------------------------------------------------------------------------- /libs/brotli/polyfill.js: -------------------------------------------------------------------------------- 1 | if (!Int32Array.__proto__.from) { 2 | Object.defineProperty(Int32Array.__proto__, 'from', { 3 | value: function(obj) { 4 | obj = Object(obj); 5 | if (!obj['length']) { 6 | return new this(0); 7 | } 8 | var typed_array = new this(obj.length); 9 | for(var i = 0; i < typed_array.length; i++) { 10 | typed_array[i] = obj[i]; 11 | } 12 | return typed_array; 13 | } 14 | }); 15 | } 16 | 17 | if (!Array.prototype.copyWithin) { 18 | Array.prototype.copyWithin = function(target, start, end) { 19 | var O = Object(this); 20 | var len = O.length >>> 0; 21 | var to = target | 0; 22 | var from = start | 0; 23 | var count = Math.min(Math.min(end | 0, len) - from, len - to); 24 | var direction = 1; 25 | if (from < to && to < (from + count)) { 26 | direction = -1; 27 | from += count - 1; 28 | to += count - 1; 29 | } 30 | while (count > 0) { 31 | O[to] = O[from]; 32 | from += direction; 33 | to += direction; 34 | count--; 35 | } 36 | return O; 37 | }; 38 | } 39 | 40 | if (!Array.prototype.fill) { 41 | Object.defineProperty(Array.prototype, 'fill', { 42 | value: function(value, start, end) { 43 | end = end | 0; 44 | var O = Object(this); 45 | var k = start | 0; 46 | while (k < end) { 47 | O[k] = value; 48 | k++; 49 | } 50 | return O; 51 | } 52 | }); 53 | } 54 | 55 | if (!Int8Array.prototype.copyWithin) { 56 | Int8Array.prototype.copyWithin = Array.prototype.copyWithin; 57 | } 58 | 59 | if (!Int8Array.prototype.fill) { 60 | Int8Array.prototype.fill = Array.prototype.fill; 61 | } 62 | 63 | if (!Int32Array.prototype.fill) { 64 | Int32Array.prototype.fill = Array.prototype.fill; 65 | } 66 | -------------------------------------------------------------------------------- /libs/three.js/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright © 2010-2019 three.js authors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /libs/three.js/README.md: -------------------------------------------------------------------------------- 1 | three.js 2 | ======== 3 | 4 | [![NPM package][npm]][npm-url] 5 | [![Build Size][build-size]][build-size-url] 6 | [![Build Status][build-status]][build-status-url] 7 | [![Dependencies][dependencies]][dependencies-url] 8 | [![Dev Dependencies][dev-dependencies]][dev-dependencies-url] 9 | [![Language Grade][lgtm]][lgtm-url] 10 | 11 | #### JavaScript 3D library #### 12 | 13 | The aim of the project is to create an easy to use, lightweight, 3D library with a default WebGL renderer. The library also provides Canvas 2D, SVG and CSS3D renderers in the examples. 14 | 15 | [Examples](http://threejs.org/examples/) — 16 | [Documentation](http://threejs.org/docs/) — 17 | [Wiki](https://github.com/mrdoob/three.js/wiki) — 18 | [Migrating](https://github.com/mrdoob/three.js/wiki/Migration-Guide) — 19 | [Questions](http://stackoverflow.com/questions/tagged/three.js) — 20 | [Forum](https://discourse.threejs.org/) — 21 | [Gitter](https://gitter.im/mrdoob/three.js) — 22 | [Slack](https://join.slack.com/t/threejs/shared_invite/enQtMzYxMzczODM2OTgxLTQ1YmY4YTQxOTFjNDAzYmQ4NjU2YzRhNzliY2RiNDEyYjU2MjhhODgyYWQ5Y2MyZTU3MWNkOGVmOGRhOTQzYTk) 23 | 24 | ### Usage ### 25 | 26 | Download the [minified library](http://threejs.org/build/three.min.js) and include it in your HTML, or install and import it as a [module](http://threejs.org/docs/#manual/introduction/Import-via-modules), 27 | Alternatively, see [how to build the library yourself](https://github.com/mrdoob/three.js/wiki/Build-instructions). 28 | 29 | ```html 30 | 31 | ``` 32 | 33 | This code creates a scene, a camera, and a geometric cube, and it adds the cube to the scene. It then creates a `WebGL` renderer for the scene and camera, and it adds that viewport to the `document.body` element. Finally, it animates the cube within the scene for the camera. 34 | 35 | ```javascript 36 | var camera, scene, renderer; 37 | var geometry, material, mesh; 38 | 39 | init(); 40 | animate(); 41 | 42 | function init() { 43 | 44 | camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 ); 45 | camera.position.z = 1; 46 | 47 | scene = new THREE.Scene(); 48 | 49 | geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 ); 50 | material = new THREE.MeshNormalMaterial(); 51 | 52 | mesh = new THREE.Mesh( geometry, material ); 53 | scene.add( mesh ); 54 | 55 | renderer = new THREE.WebGLRenderer( { antialias: true } ); 56 | renderer.setSize( window.innerWidth, window.innerHeight ); 57 | document.body.appendChild( renderer.domElement ); 58 | 59 | } 60 | 61 | function animate() { 62 | 63 | requestAnimationFrame( animate ); 64 | 65 | mesh.rotation.x += 0.01; 66 | mesh.rotation.y += 0.02; 67 | 68 | renderer.render( scene, camera ); 69 | 70 | } 71 | ``` 72 | 73 | If everything went well you should see [this](https://jsfiddle.net/f2Lommf5/). 74 | 75 | ### Change log ### 76 | 77 | [Releases](https://github.com/mrdoob/three.js/releases) 78 | 79 | 80 | [npm]: https://img.shields.io/npm/v/three.svg 81 | [npm-url]: https://www.npmjs.com/package/three 82 | [build-size]: https://badgen.net/bundlephobia/minzip/three 83 | [build-size-url]: https://bundlephobia.com/result?p=three 84 | [build-status]: https://travis-ci.org/mrdoob/three.js.svg?branch=dev 85 | [build-status-url]: https://travis-ci.org/mrdoob/three.js 86 | [dependencies]: https://img.shields.io/david/mrdoob/three.js.svg 87 | [dependencies-url]: https://david-dm.org/mrdoob/three.js 88 | [dev-dependencies]: https://img.shields.io/david/dev/mrdoob/three.js.svg 89 | [dev-dependencies-url]: https://david-dm.org/mrdoob/three.js#info=devDependencies 90 | [lgtm]: https://img.shields.io/lgtm/grade/javascript/g/mrdoob/three.js.svg?label=code%20quality 91 | [lgtm-url]: https://lgtm.com/projects/g/mrdoob/three.js/ 92 | -------------------------------------------------------------------------------- /libs/three.js/extra/VRButton.js: -------------------------------------------------------------------------------- 1 | 2 | // Adapted from three.js VRButton 3 | 4 | 5 | class VRButton { 6 | 7 | constructor(){ 8 | this.onStartListeners = []; 9 | this.onEndListeners = []; 10 | this.element = null; 11 | } 12 | 13 | onStart(callback){ 14 | this.onStartListeners.push(callback); 15 | } 16 | 17 | onEnd(callback){ 18 | this.onEndListeners.push(callback); 19 | } 20 | 21 | static async createButton( renderer, options ) { 22 | 23 | if ( options ) { 24 | 25 | console.error( 'THREE.VRButton: The "options" parameter has been removed. Please set the reference space type via renderer.xr.setReferenceSpaceType() instead.' ); 26 | 27 | } 28 | 29 | const button = new VRButton(); 30 | const element = document.createElement( 'button' ); 31 | 32 | button.element = element; 33 | 34 | function setEnter(){ 35 | button.element.innerHTML = ` 36 |
ENTER
37 |
VR
38 | `; 39 | } 40 | 41 | function setExit(){ 42 | button.element.innerHTML = ` 43 |
EXIT
44 |
VR
45 | `; 46 | } 47 | 48 | function showEnterVR( /*device*/ ) { 49 | 50 | let currentSession = null; 51 | 52 | function onSessionStarted( session ) { 53 | 54 | session.addEventListener( 'end', onSessionEnded ); 55 | 56 | for(let listener of button.onStartListeners){ 57 | listener(); 58 | } 59 | 60 | 61 | renderer.xr.setSession( session ); 62 | setExit(); 63 | 64 | currentSession = session; 65 | 66 | } 67 | 68 | function onSessionEnded( /*event*/ ) { 69 | 70 | currentSession.removeEventListener( 'end', onSessionEnded ); 71 | 72 | for(let listener of button.onEndListeners){ 73 | listener(); 74 | } 75 | 76 | setEnter(); 77 | 78 | currentSession = null; 79 | 80 | } 81 | 82 | // 83 | 84 | button.element.style.display = ''; 85 | 86 | button.element.style.cursor = 'pointer'; 87 | 88 | setEnter(); 89 | 90 | button.element.onmouseenter = function () { 91 | 92 | button.element.style.opacity = '1.0'; 93 | 94 | }; 95 | 96 | button.element.onmouseleave = function () { 97 | 98 | button.element.style.opacity = '0.7'; 99 | 100 | }; 101 | 102 | button.element.onclick = function () { 103 | 104 | if ( currentSession === null ) { 105 | 106 | // WebXR's requestReferenceSpace only works if the corresponding feature 107 | // was requested at session creation time. For simplicity, just ask for 108 | // the interesting ones as optional features, but be aware that the 109 | // requestReferenceSpace call will fail if it turns out to be unavailable. 110 | // ('local' is always available for immersive sessions and doesn't need to 111 | // be requested separately.) 112 | 113 | const sessionInit = { optionalFeatures: [ 'local-floor', 'bounded-floor', 'hand-tracking' ] }; 114 | navigator.xr.requestSession( 'immersive-vr', sessionInit ).then( onSessionStarted ); 115 | 116 | } else { 117 | 118 | currentSession.end(); 119 | 120 | } 121 | 122 | }; 123 | 124 | } 125 | 126 | function stylizeElement( element ) { 127 | 128 | element.style.position = 'absolute'; 129 | element.style.bottom = '20px'; 130 | element.style.padding = '12px 6px'; 131 | element.style.border = '1px solid #fff'; 132 | element.style.borderRadius = '4px'; 133 | element.style.background = 'rgba(0,0,0,0.1)'; 134 | element.style.color = '#fff'; 135 | element.style.font = 'normal 13px sans-serif'; 136 | element.style.textAlign = 'center'; 137 | element.style.opacity = '0.7'; 138 | element.style.outline = 'none'; 139 | element.style.zIndex = '999'; 140 | 141 | } 142 | 143 | if ( 'xr' in navigator ) { 144 | 145 | button.element.id = 'VRButton'; 146 | button.element.style.display = 'none'; 147 | 148 | stylizeElement( button.element ); 149 | 150 | let supported = await navigator.xr.isSessionSupported( 'immersive-vr' ); 151 | 152 | if(supported){ 153 | showEnterVR(); 154 | 155 | return button; 156 | }else{ 157 | return null; 158 | } 159 | 160 | } else { 161 | 162 | if ( window.isSecureContext === false ) { 163 | 164 | console.log("WEBXR NEEDS HTTPS"); 165 | 166 | } else { 167 | 168 | console.log("WEBXR not available"); 169 | 170 | } 171 | 172 | return null; 173 | 174 | 175 | 176 | } 177 | 178 | } 179 | 180 | } 181 | 182 | export { VRButton }; 183 | -------------------------------------------------------------------------------- /libs/three.js/extra/lines/Line2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author WestLangley / http://github.com/WestLangley 3 | * 4 | */ 5 | 6 | THREE.Line2 = function ( geometry, material ) { 7 | 8 | THREE.LineSegments2.call( this ); 9 | 10 | this.type = 'Line2'; 11 | 12 | this.geometry = geometry !== undefined ? geometry : new THREE.LineGeometry(); 13 | this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); 14 | 15 | }; 16 | 17 | THREE.Line2.prototype = Object.assign( Object.create( THREE.LineSegments2.prototype ), { 18 | 19 | constructor: THREE.Line2, 20 | 21 | isLine2: true, 22 | 23 | copy: function ( /* source */ ) { 24 | 25 | // todo 26 | 27 | return this; 28 | 29 | } 30 | 31 | } ); 32 | -------------------------------------------------------------------------------- /libs/three.js/extra/lines/LineGeometry.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author WestLangley / http://github.com/WestLangley 3 | * 4 | */ 5 | 6 | THREE.LineGeometry = function () { 7 | 8 | THREE.LineSegmentsGeometry.call( this ); 9 | 10 | this.type = 'LineGeometry'; 11 | 12 | }; 13 | 14 | THREE.LineGeometry.prototype = Object.assign( Object.create( THREE.LineSegmentsGeometry.prototype ), { 15 | 16 | constructor: THREE.LineGeometry, 17 | 18 | isLineGeometry: true, 19 | 20 | setPositions: function ( array ) { 21 | 22 | // converts [ x1, y1, z1, x2, y2, z2, ... ] to pairs format 23 | 24 | var length = array.length - 3; 25 | var points = new Float32Array( 2 * length ); 26 | 27 | for ( var i = 0; i < length; i += 3 ) { 28 | 29 | points[ 2 * i ] = array[ i ]; 30 | points[ 2 * i + 1 ] = array[ i + 1 ]; 31 | points[ 2 * i + 2 ] = array[ i + 2 ]; 32 | 33 | points[ 2 * i + 3 ] = array[ i + 3 ]; 34 | points[ 2 * i + 4 ] = array[ i + 4 ]; 35 | points[ 2 * i + 5 ] = array[ i + 5 ]; 36 | 37 | } 38 | 39 | THREE.LineSegmentsGeometry.prototype.setPositions.call( this, points ); 40 | 41 | return this; 42 | 43 | }, 44 | 45 | setColors: function ( array ) { 46 | 47 | // converts [ r1, g1, b1, r2, g2, b2, ... ] to pairs format 48 | 49 | var length = array.length - 3; 50 | var colors = new Float32Array( 2 * length ); 51 | 52 | for ( var i = 0; i < length; i += 3 ) { 53 | 54 | colors[ 2 * i ] = array[ i ]; 55 | colors[ 2 * i + 1 ] = array[ i + 1 ]; 56 | colors[ 2 * i + 2 ] = array[ i + 2 ]; 57 | 58 | colors[ 2 * i + 3 ] = array[ i + 3 ]; 59 | colors[ 2 * i + 4 ] = array[ i + 4 ]; 60 | colors[ 2 * i + 5 ] = array[ i + 5 ]; 61 | 62 | } 63 | 64 | THREE.LineSegmentsGeometry.prototype.setColors.call( this, colors ); 65 | 66 | return this; 67 | 68 | }, 69 | 70 | fromLine: function ( line ) { 71 | 72 | var geometry = line.geometry; 73 | 74 | if ( geometry.isGeometry ) { 75 | 76 | this.setPositions( geometry.vertices ); 77 | 78 | } else if ( geometry.isBufferGeometry ) { 79 | 80 | this.setPositions( geometry.position.array ); // assumes non-indexed 81 | 82 | } 83 | 84 | // set colors, maybe 85 | 86 | return this; 87 | 88 | }, 89 | 90 | copy: function ( /* source */ ) { 91 | 92 | // todo 93 | 94 | return this; 95 | 96 | } 97 | 98 | } ); 99 | -------------------------------------------------------------------------------- /libs/three.js/extra/lines/LineSegments2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author WestLangley / http://github.com/WestLangley 3 | * 4 | */ 5 | 6 | THREE.LineSegments2 = function ( geometry, material ) { 7 | 8 | THREE.Mesh.call( this ); 9 | 10 | this.type = 'LineSegments2'; 11 | 12 | this.geometry = geometry !== undefined ? geometry : new THREE.LineSegmentsGeometry(); 13 | this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); 14 | 15 | }; 16 | 17 | THREE.LineSegments2.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { 18 | 19 | constructor: THREE.LineSegments2, 20 | 21 | isLineSegments2: true, 22 | 23 | computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... 24 | 25 | var start = new THREE.Vector3(); 26 | var end = new THREE.Vector3(); 27 | 28 | return function computeLineDistances() { 29 | 30 | var geometry = this.geometry; 31 | 32 | var instanceStart = geometry.attributes.instanceStart; 33 | var instanceEnd = geometry.attributes.instanceEnd; 34 | var lineDistances = new Float32Array( 2 * instanceStart.data.count ); 35 | 36 | for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) { 37 | 38 | start.fromBufferAttribute( instanceStart, i ); 39 | end.fromBufferAttribute( instanceEnd, i ); 40 | 41 | lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; 42 | lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); 43 | 44 | } 45 | 46 | var instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1 47 | 48 | geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 49 | geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 50 | 51 | return this; 52 | 53 | }; 54 | 55 | }() ), 56 | 57 | copy: function ( /* source */ ) { 58 | 59 | // todo 60 | 61 | return this; 62 | 63 | } 64 | 65 | } ); 66 | -------------------------------------------------------------------------------- /libs/three.js/extra/lines/LineSegmentsGeometry.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author WestLangley / http://github.com/WestLangley 3 | * 4 | */ 5 | 6 | THREE.LineSegmentsGeometry = function () { 7 | 8 | THREE.InstancedBufferGeometry.call( this ); 9 | 10 | this.type = 'LineSegmentsGeometry'; 11 | 12 | var positions = [ - 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0 ]; 13 | var uvs = [ - 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2 ]; 14 | var index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ]; 15 | 16 | this.setIndex( index ); 17 | this.setAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) ); 18 | this.setAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) ); 19 | 20 | }; 21 | 22 | THREE.LineSegmentsGeometry.prototype = Object.assign( Object.create( THREE.InstancedBufferGeometry.prototype ), { 23 | 24 | constructor: THREE.LineSegmentsGeometry, 25 | 26 | isLineSegmentsGeometry: true, 27 | 28 | applyMatrix: function ( matrix ) { 29 | 30 | var start = this.attributes.instanceStart; 31 | var end = this.attributes.instanceEnd; 32 | 33 | if ( start !== undefined ) { 34 | 35 | matrix.applyToBufferAttribute( start ); 36 | 37 | matrix.applyToBufferAttribute( end ); 38 | 39 | start.data.needsUpdate = true; 40 | 41 | } 42 | 43 | if ( this.boundingBox !== null ) { 44 | 45 | this.computeBoundingBox(); 46 | 47 | } 48 | 49 | if ( this.boundingSphere !== null ) { 50 | 51 | this.computeBoundingSphere(); 52 | 53 | } 54 | 55 | return this; 56 | 57 | }, 58 | 59 | setPositions: function ( array ) { 60 | 61 | var lineSegments; 62 | 63 | if ( array instanceof Float32Array ) { 64 | 65 | lineSegments = array; 66 | 67 | } else if ( Array.isArray( array ) ) { 68 | 69 | lineSegments = new Float32Array( array ); 70 | 71 | } 72 | 73 | var instanceBuffer = new THREE.InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz 74 | 75 | this.setAttribute( 'instanceStart', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz 76 | this.setAttribute( 'instanceEnd', new THREE.InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz 77 | 78 | // 79 | 80 | this.computeBoundingBox(); 81 | this.computeBoundingSphere(); 82 | 83 | return this; 84 | 85 | }, 86 | 87 | setColors: function ( array ) { 88 | 89 | var colors; 90 | 91 | if ( array instanceof Float32Array ) { 92 | 93 | colors = array; 94 | 95 | } else if ( Array.isArray( array ) ) { 96 | 97 | colors = new Float32Array( array ); 98 | 99 | } 100 | 101 | var instanceColorBuffer = new THREE.InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb 102 | 103 | this.setAttribute( 'instanceColorStart', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb 104 | this.setAttribute( 'instanceColorEnd', new THREE.InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb 105 | 106 | return this; 107 | 108 | }, 109 | 110 | fromWireframeGeometry: function ( geometry ) { 111 | 112 | this.setPositions( geometry.attributes.position.array ); 113 | 114 | return this; 115 | 116 | }, 117 | 118 | fromEdgesGeometry: function ( geometry ) { 119 | 120 | this.setPositions( geometry.attributes.position.array ); 121 | 122 | return this; 123 | 124 | }, 125 | 126 | fromMesh: function ( mesh ) { 127 | 128 | this.fromWireframeGeometry( new THREE.WireframeGeometry( mesh.geometry ) ); 129 | 130 | // set colors, maybe 131 | 132 | return this; 133 | 134 | }, 135 | 136 | fromLineSegements: function ( lineSegments ) { 137 | 138 | var geometry = lineSegments.geometry; 139 | 140 | if ( geometry.isGeometry ) { 141 | 142 | this.setPositions( geometry.vertices ); 143 | 144 | } else if ( geometry.isBufferGeometry ) { 145 | 146 | this.setPositions( geometry.position.array ); // assumes non-indexed 147 | 148 | } 149 | 150 | // set colors, maybe 151 | 152 | return this; 153 | 154 | }, 155 | 156 | computeBoundingBox: function () { 157 | 158 | var box = new THREE.Box3(); 159 | 160 | return function computeBoundingBox() { 161 | 162 | if ( this.boundingBox === null ) { 163 | 164 | this.boundingBox = new THREE.Box3(); 165 | 166 | } 167 | 168 | var start = this.attributes.instanceStart; 169 | var end = this.attributes.instanceEnd; 170 | 171 | if ( start !== undefined && end !== undefined ) { 172 | 173 | this.boundingBox.setFromBufferAttribute( start ); 174 | 175 | box.setFromBufferAttribute( end ); 176 | 177 | this.boundingBox.union( box ); 178 | 179 | } 180 | 181 | }; 182 | 183 | }(), 184 | 185 | computeBoundingSphere: function () { 186 | 187 | var vector = new THREE.Vector3(); 188 | 189 | return function computeBoundingSphere() { 190 | 191 | if ( this.boundingSphere === null ) { 192 | 193 | this.boundingSphere = new THREE.Sphere(); 194 | 195 | } 196 | 197 | if ( this.boundingBox === null ) { 198 | 199 | this.computeBoundingBox(); 200 | 201 | } 202 | 203 | var start = this.attributes.instanceStart; 204 | var end = this.attributes.instanceEnd; 205 | 206 | if ( start !== undefined && end !== undefined ) { 207 | 208 | var center = this.boundingSphere.center; 209 | 210 | this.boundingBox.getCenter( center ); 211 | 212 | var maxRadiusSq = 0; 213 | 214 | for ( var i = 0, il = start.count; i < il; i ++ ) { 215 | 216 | vector.fromBufferAttribute( start, i ); 217 | maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); 218 | 219 | vector.fromBufferAttribute( end, i ); 220 | maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); 221 | 222 | } 223 | 224 | this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); 225 | 226 | if ( isNaN( this.boundingSphere.radius ) ) { 227 | 228 | console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this ); 229 | 230 | } 231 | 232 | } 233 | 234 | }; 235 | 236 | }(), 237 | 238 | toJSON: function () { 239 | 240 | // todo 241 | 242 | }, 243 | 244 | clone: function () { 245 | 246 | // todo 247 | 248 | }, 249 | 250 | copy: function ( /* source */ ) { 251 | 252 | // todo 253 | 254 | return this; 255 | 256 | } 257 | 258 | } ); 259 | -------------------------------------------------------------------------------- /libs/three.js/extra/lines/Wireframe.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author WestLangley / http://github.com/WestLangley 3 | * 4 | */ 5 | 6 | THREE.Wireframe = function ( geometry, material ) { 7 | 8 | THREE.Mesh.call( this ); 9 | 10 | this.type = 'Wireframe'; 11 | 12 | this.geometry = geometry !== undefined ? geometry : new THREE.LineSegmentsGeometry(); 13 | this.material = material !== undefined ? material : new THREE.LineMaterial( { color: Math.random() * 0xffffff } ); 14 | 15 | }; 16 | 17 | THREE.Wireframe.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), { 18 | 19 | constructor: THREE.Wireframe, 20 | 21 | isWireframe: true, 22 | 23 | computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... 24 | 25 | var start = new THREE.Vector3(); 26 | var end = new THREE.Vector3(); 27 | 28 | return function computeLineDistances() { 29 | 30 | var geometry = this.geometry; 31 | 32 | var instanceStart = geometry.attributes.instanceStart; 33 | var instanceEnd = geometry.attributes.instanceEnd; 34 | var lineDistances = new Float32Array( 2 * instanceStart.data.count ); 35 | 36 | for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) { 37 | 38 | start.fromBufferAttribute( instanceStart, i ); 39 | end.fromBufferAttribute( instanceEnd, i ); 40 | 41 | lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; 42 | lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); 43 | 44 | } 45 | 46 | var instanceDistanceBuffer = new THREE.InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1 47 | 48 | geometry.setAttribute( 'instanceDistanceStart', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 49 | geometry.setAttribute( 'instanceDistanceEnd', new THREE.InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 50 | 51 | return this; 52 | 53 | }; 54 | 55 | }() ), 56 | 57 | copy: function ( /* source */ ) { 58 | 59 | // todo 60 | 61 | return this; 62 | 63 | } 64 | 65 | } ); 66 | -------------------------------------------------------------------------------- /libs/three.js/extra/lines/WireframeGeometry2.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author WestLangley / http://github.com/WestLangley 3 | * 4 | */ 5 | 6 | THREE.WireframeGeometry2 = function ( geometry ) { 7 | 8 | THREE.LineSegmentsGeometry.call( this ); 9 | 10 | this.type = 'WireframeGeometry2'; 11 | 12 | this.fromWireframeGeometry( new THREE.WireframeGeometry( geometry ) ); 13 | 14 | // set colors, maybe 15 | 16 | }; 17 | 18 | THREE.WireframeGeometry2.prototype = Object.assign( Object.create( THREE.LineSegmentsGeometry.prototype ), { 19 | 20 | constructor: THREE.WireframeGeometry2, 21 | 22 | isWireframeGeometry2: true, 23 | 24 | copy: function ( /* source */ ) { 25 | 26 | // todo 27 | 28 | return this; 29 | 30 | } 31 | 32 | } ); 33 | -------------------------------------------------------------------------------- /libs/three.js/libs/inflate.module.min.js: -------------------------------------------------------------------------------- 1 | /** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */var mod={}, l=void 0,aa=mod;function r(c,d){var a=c.split("."),b=aa;!(a[0]in b)&&b.execScript&&b.execScript("var "+a[0]);for(var e;a.length&&(e=a.shift());)!a.length&&d!==l?b[e]=d:b=b[e]?b[e]:b[e]={}};var t="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function v(c){var d=c.length,a=0,b=Number.POSITIVE_INFINITY,e,f,g,h,k,m,n,p,s,x;for(p=0;pa&&(a=c[p]),c[p]>=1;x=g<<16|p;for(s=m;s>>=1;switch(c){case 0:var d=this.input,a=this.a,b=this.c,e=this.b,f=d.length,g=l,h=l,k=b.length,m=l;this.d=this.f=0;if(a+1>=f)throw Error("invalid uncompressed block header: LEN");g=d[a++]|d[a++]<<8;if(a+1>=f)throw Error("invalid uncompressed block header: NLEN");h=d[a++]|d[a++]<<8;if(g===~h)throw Error("invalid uncompressed block header: length verify");if(a+g>d.length)throw Error("input buffer is broken");switch(this.i){case A:for(;e+ 4 | g>b.length;){m=k-e;g-=m;if(t)b.set(d.subarray(a,a+m),e),e+=m,a+=m;else for(;m--;)b[e++]=d[a++];this.b=e;b=this.e();e=this.b}break;case y:for(;e+g>b.length;)b=this.e({p:2});break;default:throw Error("invalid inflate mode");}if(t)b.set(d.subarray(a,a+g),e),e+=g,a+=g;else for(;g--;)b[e++]=d[a++];this.a=a;this.b=e;this.c=b;break;case 1:this.j(ba,ca);break;case 2:for(var n=C(this,5)+257,p=C(this,5)+1,s=C(this,4)+4,x=new (t?Uint8Array:Array)(D.length),S=l,T=l,U=l,u=l,M=l,F=l,z=l,q=l,V=l,q=0;q=P?8:255>=P?9:279>=P?7:8;var ba=v(O),Q=new (t?Uint8Array:Array)(30),R,ga;R=0;for(ga=Q.length;R=g)throw Error("input buffer is broken");a|=e[f++]<>>d;c.d=b-d;c.a=f;return h} 8 | function E(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h=d[0],k=d[1],m,n;b=g);)a|=e[f++]<>>16;if(n>b)throw Error("invalid code length: "+n);c.f=a>>n;c.d=b-n;c.a=f;return m&65535} 9 | w.prototype.j=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length-258,f,g,h,k;256!==(f=E(this,c));)if(256>f)b>=e&&(this.b=b,a=this.e(),b=this.b),a[b++]=f;else{g=f-257;k=I[g];0=e&&(this.b=b,a=this.e(),b=this.b);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b}; 10 | w.prototype.w=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length,f,g,h,k;256!==(f=E(this,c));)if(256>f)b>=e&&(a=this.e(),e=a.length),a[b++]=f;else{g=f-257;k=I[g];0e&&(a=this.e(),e=a.length);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b}; 11 | w.prototype.e=function(){var c=new (t?Uint8Array:Array)(this.b-32768),d=this.b-32768,a,b,e=this.c;if(t)c.set(e.subarray(32768,c.length));else{a=0;for(b=c.length;aa;++a)e[a]=e[d+a];this.b=32768;return e}; 12 | w.prototype.z=function(c){var d,a=this.input.length/this.a+1|0,b,e,f,g=this.input,h=this.c;c&&("number"===typeof c.p&&(a=c.p),"number"===typeof c.u&&(a+=c.u));2>a?(b=(g.length-this.a)/this.o[2],f=258*(b/2)|0,e=fd&&(this.c.length=d),c=this.c);return this.buffer=c};function W(c,d){var a,b;this.input=c;this.a=0;if(d||!(d={}))d.index&&(this.a=d.index),d.verify&&(this.A=d.verify);a=c[this.a++];b=c[this.a++];switch(a&15){case ha:this.method=ha;break;default:throw Error("unsupported compression method");}if(0!==((a<<8)+b)%31)throw Error("invalid fcheck flag:"+((a<<8)+b)%31);if(b&32)throw Error("fdict flag is not supported");this.q=new w(c,{index:this.a,bufferSize:d.bufferSize,bufferType:d.bufferType,resize:d.resize})} 15 | W.prototype.k=function(){var c=this.input,d,a;d=this.q.k();this.a=this.q.a;if(this.A){a=(c[this.a++]<<24|c[this.a++]<<16|c[this.a++]<<8|c[this.a++])>>>0;var b=d;if("string"===typeof b){var e=b.split(""),f,g;f=0;for(g=e.length;f>>0;b=e}for(var h=1,k=0,m=b.length,n,p=0;0>>0)throw Error("invalid adler-32 checksum");}return d};var ha=8;r("Zlib.Inflate",W);r("Zlib.Inflate.prototype.decompress",W.prototype.k);var X={ADAPTIVE:B.s,BLOCK:B.t},Y,Z,$,ia;if(Object.keys)Y=Object.keys(X);else for(Z in Y=[],$=0,X)Y[$++]=Z;$=0;for(ia=Y.length;$= prevTime + 1000 ) { 74 | 75 | fpsPanel.update( ( frames * 1000 ) / ( time - prevTime ), 100 ); 76 | 77 | prevTime = time; 78 | frames = 0; 79 | 80 | if ( memPanel ) { 81 | 82 | var memory = performance.memory; 83 | memPanel.update( memory.usedJSHeapSize / 1048576, memory.jsHeapSizeLimit / 1048576 ); 84 | 85 | } 86 | 87 | } 88 | 89 | return time; 90 | 91 | }, 92 | 93 | update: function () { 94 | 95 | beginTime = this.end(); 96 | 97 | }, 98 | 99 | // Backwards Compatibility 100 | 101 | domElement: container, 102 | setMode: showPanel 103 | 104 | }; 105 | 106 | }; 107 | 108 | Stats.Panel = function ( name, fg, bg ) { 109 | 110 | var min = Infinity, max = 0, round = Math.round; 111 | var PR = round( window.devicePixelRatio || 1 ); 112 | 113 | var WIDTH = 80 * PR, HEIGHT = 48 * PR, 114 | TEXT_X = 3 * PR, TEXT_Y = 2 * PR, 115 | GRAPH_X = 3 * PR, GRAPH_Y = 15 * PR, 116 | GRAPH_WIDTH = 74 * PR, GRAPH_HEIGHT = 30 * PR; 117 | 118 | var canvas = document.createElement( 'canvas' ); 119 | canvas.width = WIDTH; 120 | canvas.height = HEIGHT; 121 | canvas.style.cssText = 'width:80px;height:48px'; 122 | 123 | var context = canvas.getContext( '2d' ); 124 | context.font = 'bold ' + ( 9 * PR ) + 'px Helvetica,Arial,sans-serif'; 125 | context.textBaseline = 'top'; 126 | 127 | context.fillStyle = bg; 128 | context.fillRect( 0, 0, WIDTH, HEIGHT ); 129 | 130 | context.fillStyle = fg; 131 | context.fillText( name, TEXT_X, TEXT_Y ); 132 | context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT ); 133 | 134 | context.fillStyle = bg; 135 | context.globalAlpha = 0.9; 136 | context.fillRect( GRAPH_X, GRAPH_Y, GRAPH_WIDTH, GRAPH_HEIGHT ); 137 | 138 | return { 139 | 140 | dom: canvas, 141 | 142 | update: function ( value, maxValue ) { 143 | 144 | min = Math.min( min, value ); 145 | max = Math.max( max, value ); 146 | 147 | context.fillStyle = bg; 148 | context.globalAlpha = 1; 149 | context.fillRect( 0, 0, WIDTH, GRAPH_Y ); 150 | context.fillStyle = fg; 151 | context.fillText( round( value ) + ' ' + name + ' (' + round( min ) + '-' + round( max ) + ')', TEXT_X, TEXT_Y ); 152 | 153 | context.drawImage( canvas, GRAPH_X + PR, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT, GRAPH_X, GRAPH_Y, GRAPH_WIDTH - PR, GRAPH_HEIGHT ); 154 | 155 | context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, GRAPH_HEIGHT ); 156 | 157 | context.fillStyle = bg; 158 | context.globalAlpha = 0.9; 159 | context.fillRect( GRAPH_X + GRAPH_WIDTH - PR, GRAPH_Y, PR, round( ( 1 - ( value / maxValue ) ) * GRAPH_HEIGHT ) ); 160 | 161 | } 162 | 163 | }; 164 | 165 | }; 166 | 167 | export default Stats; 168 | -------------------------------------------------------------------------------- /libs/three.js/libs/tween.module.min.js: -------------------------------------------------------------------------------- 1 | // tween.js 17.3.5 - https://github.com/tweenjs/tween.js 2 | var _Group=function(){this._tweens={},this._tweensAddedDuringUpdate={}};_Group.prototype={getAll:function(){return Object.keys(this._tweens).map(function(t){return this._tweens[t]}.bind(this))},removeAll:function(){this._tweens={}},add:function(t){this._tweens[t.getId()]=t,this._tweensAddedDuringUpdate[t.getId()]=t},remove:function(t){delete this._tweens[t.getId()],delete this._tweensAddedDuringUpdate[t.getId()]},update:function(t,n){var e=Object.keys(this._tweens);if(0===e.length)return!1;for(t=void 0!==t?t:TWEEN.now();0 1 && end.z > 1; 142 | if ( isBehindCameraNear || isPastCameraFar ) { 143 | 144 | continue; 145 | 146 | } 147 | 148 | // screen space 149 | start.x *= resolution.x / 2; 150 | start.y *= resolution.y / 2; 151 | 152 | end.x *= resolution.x / 2; 153 | end.y *= resolution.y / 2; 154 | 155 | // create 2d segment 156 | line.start.copy( start ); 157 | line.start.z = 0; 158 | 159 | line.end.copy( end ); 160 | line.end.z = 0; 161 | 162 | // get closest point on ray to segment 163 | var param = line.closestPointToPointParameter( ssOrigin3, true ); 164 | line.at( param, closestPoint ); 165 | 166 | // check if the intersection point is within clip space 167 | var zPos = MathUtils.lerp( start.z, end.z, param ); 168 | var isInClipSpace = zPos >= - 1 && zPos <= 1; 169 | 170 | var isInside = ssOrigin3.distanceTo( closestPoint ) < lineWidth * 0.5; 171 | 172 | if ( isInClipSpace && isInside ) { 173 | 174 | line.start.fromBufferAttribute( instanceStart, i ); 175 | line.end.fromBufferAttribute( instanceEnd, i ); 176 | 177 | line.start.applyMatrix4( matrixWorld ); 178 | line.end.applyMatrix4( matrixWorld ); 179 | 180 | var pointOnLine = new Vector3(); 181 | var point = new Vector3(); 182 | 183 | ray.distanceSqToSegment( line.start, line.end, point, pointOnLine ); 184 | 185 | intersects.push( { 186 | 187 | point: point, 188 | pointOnLine: pointOnLine, 189 | distance: ray.origin.distanceTo( point ), 190 | 191 | object: this, 192 | face: null, 193 | faceIndex: i, 194 | uv: null, 195 | uv2: null, 196 | 197 | } ); 198 | 199 | } 200 | 201 | } 202 | 203 | }; 204 | 205 | }() ) 206 | 207 | } ); 208 | 209 | export { LineSegments2 }; 210 | -------------------------------------------------------------------------------- /libs/three.js/lines/LineSegmentsGeometry.js: -------------------------------------------------------------------------------- 1 | import { 2 | Box3, 3 | Float32BufferAttribute, 4 | InstancedBufferGeometry, 5 | InstancedInterleavedBuffer, 6 | InterleavedBufferAttribute, 7 | Sphere, 8 | Vector3, 9 | WireframeGeometry 10 | } from '../build/three.module.js'; 11 | 12 | var LineSegmentsGeometry = function () { 13 | 14 | InstancedBufferGeometry.call( this ); 15 | 16 | this.type = 'LineSegmentsGeometry'; 17 | 18 | var positions = [ - 1, 2, 0, 1, 2, 0, - 1, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 0, - 1, - 1, 0, 1, - 1, 0 ]; 19 | var uvs = [ - 1, 2, 1, 2, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 2, 1, - 2 ]; 20 | var index = [ 0, 2, 1, 2, 3, 1, 2, 4, 3, 4, 5, 3, 4, 6, 5, 6, 7, 5 ]; 21 | 22 | this.setIndex( index ); 23 | this.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); 24 | this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); 25 | 26 | }; 27 | 28 | LineSegmentsGeometry.prototype = Object.assign( Object.create( InstancedBufferGeometry.prototype ), { 29 | 30 | constructor: LineSegmentsGeometry, 31 | 32 | isLineSegmentsGeometry: true, 33 | 34 | applyMatrix4: function ( matrix ) { 35 | 36 | var start = this.attributes.instanceStart; 37 | var end = this.attributes.instanceEnd; 38 | 39 | if ( start !== undefined ) { 40 | 41 | start.applyMatrix4( matrix ); 42 | 43 | end.applyMatrix4( matrix ); 44 | 45 | start.needsUpdate = true; 46 | 47 | } 48 | 49 | if ( this.boundingBox !== null ) { 50 | 51 | this.computeBoundingBox(); 52 | 53 | } 54 | 55 | if ( this.boundingSphere !== null ) { 56 | 57 | this.computeBoundingSphere(); 58 | 59 | } 60 | 61 | return this; 62 | 63 | }, 64 | 65 | setPositions: function ( array ) { 66 | 67 | var lineSegments; 68 | 69 | if ( array instanceof Float32Array ) { 70 | 71 | lineSegments = array; 72 | 73 | } else if ( Array.isArray( array ) ) { 74 | 75 | lineSegments = new Float32Array( array ); 76 | 77 | } 78 | 79 | var instanceBuffer = new InstancedInterleavedBuffer( lineSegments, 6, 1 ); // xyz, xyz 80 | 81 | this.setAttribute( 'instanceStart', new InterleavedBufferAttribute( instanceBuffer, 3, 0 ) ); // xyz 82 | this.setAttribute( 'instanceEnd', new InterleavedBufferAttribute( instanceBuffer, 3, 3 ) ); // xyz 83 | 84 | // 85 | 86 | this.computeBoundingBox(); 87 | this.computeBoundingSphere(); 88 | 89 | return this; 90 | 91 | }, 92 | 93 | setColors: function ( array ) { 94 | 95 | var colors; 96 | 97 | if ( array instanceof Float32Array ) { 98 | 99 | colors = array; 100 | 101 | } else if ( Array.isArray( array ) ) { 102 | 103 | colors = new Float32Array( array ); 104 | 105 | } 106 | 107 | var instanceColorBuffer = new InstancedInterleavedBuffer( colors, 6, 1 ); // rgb, rgb 108 | 109 | this.setAttribute( 'instanceColorStart', new InterleavedBufferAttribute( instanceColorBuffer, 3, 0 ) ); // rgb 110 | this.setAttribute( 'instanceColorEnd', new InterleavedBufferAttribute( instanceColorBuffer, 3, 3 ) ); // rgb 111 | 112 | return this; 113 | 114 | }, 115 | 116 | fromWireframeGeometry: function ( geometry ) { 117 | 118 | this.setPositions( geometry.attributes.position.array ); 119 | 120 | return this; 121 | 122 | }, 123 | 124 | fromEdgesGeometry: function ( geometry ) { 125 | 126 | this.setPositions( geometry.attributes.position.array ); 127 | 128 | return this; 129 | 130 | }, 131 | 132 | fromMesh: function ( mesh ) { 133 | 134 | this.fromWireframeGeometry( new WireframeGeometry( mesh.geometry ) ); 135 | 136 | // set colors, maybe 137 | 138 | return this; 139 | 140 | }, 141 | 142 | fromLineSegments: function ( lineSegments ) { 143 | 144 | var geometry = lineSegments.geometry; 145 | 146 | if ( geometry.isGeometry ) { 147 | 148 | this.setPositions( geometry.vertices ); 149 | 150 | } else if ( geometry.isBufferGeometry ) { 151 | 152 | this.setPositions( geometry.attributes.position.array ); // assumes non-indexed 153 | 154 | } 155 | 156 | // set colors, maybe 157 | 158 | return this; 159 | 160 | }, 161 | 162 | computeBoundingBox: function () { 163 | 164 | var box = new Box3(); 165 | 166 | return function computeBoundingBox() { 167 | 168 | if ( this.boundingBox === null ) { 169 | 170 | this.boundingBox = new Box3(); 171 | 172 | } 173 | 174 | var start = this.attributes.instanceStart; 175 | var end = this.attributes.instanceEnd; 176 | 177 | if ( start !== undefined && end !== undefined ) { 178 | 179 | this.boundingBox.setFromBufferAttribute( start ); 180 | 181 | box.setFromBufferAttribute( end ); 182 | 183 | this.boundingBox.union( box ); 184 | 185 | } 186 | 187 | }; 188 | 189 | }(), 190 | 191 | computeBoundingSphere: function () { 192 | 193 | var vector = new Vector3(); 194 | 195 | return function computeBoundingSphere() { 196 | 197 | if ( this.boundingSphere === null ) { 198 | 199 | this.boundingSphere = new Sphere(); 200 | 201 | } 202 | 203 | if ( this.boundingBox === null ) { 204 | 205 | this.computeBoundingBox(); 206 | 207 | } 208 | 209 | var start = this.attributes.instanceStart; 210 | var end = this.attributes.instanceEnd; 211 | 212 | if ( start !== undefined && end !== undefined ) { 213 | 214 | var center = this.boundingSphere.center; 215 | 216 | this.boundingBox.getCenter( center ); 217 | 218 | var maxRadiusSq = 0; 219 | 220 | for ( var i = 0, il = start.count; i < il; i ++ ) { 221 | 222 | vector.fromBufferAttribute( start, i ); 223 | maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); 224 | 225 | vector.fromBufferAttribute( end, i ); 226 | maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( vector ) ); 227 | 228 | } 229 | 230 | this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); 231 | 232 | if ( isNaN( this.boundingSphere.radius ) ) { 233 | 234 | console.error( 'THREE.LineSegmentsGeometry.computeBoundingSphere(): Computed radius is NaN. The instanced position data is likely to have NaN values.', this ); 235 | 236 | } 237 | 238 | } 239 | 240 | }; 241 | 242 | }(), 243 | 244 | toJSON: function () { 245 | 246 | // todo 247 | 248 | }, 249 | 250 | applyMatrix: function ( matrix ) { 251 | 252 | console.warn( 'THREE.LineSegmentsGeometry: applyMatrix() has been renamed to applyMatrix4().' ); 253 | 254 | return this.applyMatrix4( matrix ); 255 | 256 | } 257 | 258 | } ); 259 | 260 | export { LineSegmentsGeometry }; 261 | -------------------------------------------------------------------------------- /libs/three.js/lines/Wireframe.js: -------------------------------------------------------------------------------- 1 | import { 2 | InstancedInterleavedBuffer, 3 | InterleavedBufferAttribute, 4 | Mesh, 5 | Vector3 6 | } from '../build/three.module.js'; 7 | import { LineSegmentsGeometry } from '../lines/LineSegmentsGeometry.js'; 8 | import { LineMaterial } from '../lines/LineMaterial.js'; 9 | 10 | var Wireframe = function ( geometry, material ) { 11 | 12 | Mesh.call( this ); 13 | 14 | this.type = 'Wireframe'; 15 | 16 | this.geometry = geometry !== undefined ? geometry : new LineSegmentsGeometry(); 17 | this.material = material !== undefined ? material : new LineMaterial( { color: Math.random() * 0xffffff } ); 18 | 19 | }; 20 | 21 | Wireframe.prototype = Object.assign( Object.create( Mesh.prototype ), { 22 | 23 | constructor: Wireframe, 24 | 25 | isWireframe: true, 26 | 27 | computeLineDistances: ( function () { // for backwards-compatability, but could be a method of LineSegmentsGeometry... 28 | 29 | var start = new Vector3(); 30 | var end = new Vector3(); 31 | 32 | return function computeLineDistances() { 33 | 34 | var geometry = this.geometry; 35 | 36 | var instanceStart = geometry.attributes.instanceStart; 37 | var instanceEnd = geometry.attributes.instanceEnd; 38 | var lineDistances = new Float32Array( 2 * instanceStart.data.count ); 39 | 40 | for ( var i = 0, j = 0, l = instanceStart.data.count; i < l; i ++, j += 2 ) { 41 | 42 | start.fromBufferAttribute( instanceStart, i ); 43 | end.fromBufferAttribute( instanceEnd, i ); 44 | 45 | lineDistances[ j ] = ( j === 0 ) ? 0 : lineDistances[ j - 1 ]; 46 | lineDistances[ j + 1 ] = lineDistances[ j ] + start.distanceTo( end ); 47 | 48 | } 49 | 50 | var instanceDistanceBuffer = new InstancedInterleavedBuffer( lineDistances, 2, 1 ); // d0, d1 51 | 52 | geometry.setAttribute( 'instanceDistanceStart', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 0 ) ); // d0 53 | geometry.setAttribute( 'instanceDistanceEnd', new InterleavedBufferAttribute( instanceDistanceBuffer, 1, 1 ) ); // d1 54 | 55 | return this; 56 | 57 | }; 58 | 59 | }() ) 60 | 61 | } ); 62 | 63 | export { Wireframe }; 64 | -------------------------------------------------------------------------------- /libs/three.js/lines/WireframeGeometry2.js: -------------------------------------------------------------------------------- 1 | import { 2 | WireframeGeometry 3 | } from '../build/three.module.js'; 4 | import { LineSegmentsGeometry } from '../lines/LineSegmentsGeometry.js'; 5 | 6 | var WireframeGeometry2 = function ( geometry ) { 7 | 8 | LineSegmentsGeometry.call( this ); 9 | 10 | this.type = 'WireframeGeometry2'; 11 | 12 | this.fromWireframeGeometry( new WireframeGeometry( geometry ) ); 13 | 14 | // set colors, maybe 15 | 16 | }; 17 | 18 | WireframeGeometry2.prototype = Object.assign( Object.create( LineSegmentsGeometry.prototype ), { 19 | 20 | constructor: WireframeGeometry2, 21 | 22 | isWireframeGeometry2: true 23 | 24 | } ); 25 | 26 | export { WireframeGeometry2 }; 27 | -------------------------------------------------------------------------------- /libs/three.js/loaders/DDSLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | CompressedTextureLoader, 3 | RGBAFormat, 4 | RGBA_S3TC_DXT3_Format, 5 | RGBA_S3TC_DXT5_Format, 6 | RGB_ETC1_Format, 7 | RGB_S3TC_DXT1_Format 8 | } from '../../../build/three.module.js'; 9 | 10 | var DDSLoader = function ( manager ) { 11 | 12 | CompressedTextureLoader.call( this, manager ); 13 | 14 | }; 15 | 16 | DDSLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prototype ), { 17 | 18 | constructor: DDSLoader, 19 | 20 | parse: function ( buffer, loadMipmaps ) { 21 | 22 | var dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 }; 23 | 24 | // Adapted from @toji's DDS utils 25 | // https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js 26 | 27 | // All values and structures referenced from: 28 | // http://msdn.microsoft.com/en-us/library/bb943991.aspx/ 29 | 30 | var DDS_MAGIC = 0x20534444; 31 | 32 | // var DDSD_CAPS = 0x1; 33 | // var DDSD_HEIGHT = 0x2; 34 | // var DDSD_WIDTH = 0x4; 35 | // var DDSD_PITCH = 0x8; 36 | // var DDSD_PIXELFORMAT = 0x1000; 37 | var DDSD_MIPMAPCOUNT = 0x20000; 38 | // var DDSD_LINEARSIZE = 0x80000; 39 | // var DDSD_DEPTH = 0x800000; 40 | 41 | // var DDSCAPS_COMPLEX = 0x8; 42 | // var DDSCAPS_MIPMAP = 0x400000; 43 | // var DDSCAPS_TEXTURE = 0x1000; 44 | 45 | var DDSCAPS2_CUBEMAP = 0x200; 46 | var DDSCAPS2_CUBEMAP_POSITIVEX = 0x400; 47 | var DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800; 48 | var DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000; 49 | var DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000; 50 | var DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000; 51 | var DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000; 52 | // var DDSCAPS2_VOLUME = 0x200000; 53 | 54 | // var DDPF_ALPHAPIXELS = 0x1; 55 | // var DDPF_ALPHA = 0x2; 56 | var DDPF_FOURCC = 0x4; 57 | // var DDPF_RGB = 0x40; 58 | // var DDPF_YUV = 0x200; 59 | // var DDPF_LUMINANCE = 0x20000; 60 | 61 | function fourCCToInt32( value ) { 62 | 63 | return value.charCodeAt( 0 ) + 64 | ( value.charCodeAt( 1 ) << 8 ) + 65 | ( value.charCodeAt( 2 ) << 16 ) + 66 | ( value.charCodeAt( 3 ) << 24 ); 67 | 68 | } 69 | 70 | function int32ToFourCC( value ) { 71 | 72 | return String.fromCharCode( 73 | value & 0xff, 74 | ( value >> 8 ) & 0xff, 75 | ( value >> 16 ) & 0xff, 76 | ( value >> 24 ) & 0xff 77 | ); 78 | 79 | } 80 | 81 | function loadARGBMip( buffer, dataOffset, width, height ) { 82 | 83 | var dataLength = width * height * 4; 84 | var srcBuffer = new Uint8Array( buffer, dataOffset, dataLength ); 85 | var byteArray = new Uint8Array( dataLength ); 86 | var dst = 0; 87 | var src = 0; 88 | for ( var y = 0; y < height; y ++ ) { 89 | 90 | for ( var x = 0; x < width; x ++ ) { 91 | 92 | var b = srcBuffer[ src ]; src ++; 93 | var g = srcBuffer[ src ]; src ++; 94 | var r = srcBuffer[ src ]; src ++; 95 | var a = srcBuffer[ src ]; src ++; 96 | byteArray[ dst ] = r; dst ++; //r 97 | byteArray[ dst ] = g; dst ++; //g 98 | byteArray[ dst ] = b; dst ++; //b 99 | byteArray[ dst ] = a; dst ++; //a 100 | 101 | } 102 | 103 | } 104 | 105 | return byteArray; 106 | 107 | } 108 | 109 | var FOURCC_DXT1 = fourCCToInt32( 'DXT1' ); 110 | var FOURCC_DXT3 = fourCCToInt32( 'DXT3' ); 111 | var FOURCC_DXT5 = fourCCToInt32( 'DXT5' ); 112 | var FOURCC_ETC1 = fourCCToInt32( 'ETC1' ); 113 | 114 | var headerLengthInt = 31; // The header length in 32 bit ints 115 | 116 | // Offsets into the header array 117 | 118 | var off_magic = 0; 119 | 120 | var off_size = 1; 121 | var off_flags = 2; 122 | var off_height = 3; 123 | var off_width = 4; 124 | 125 | var off_mipmapCount = 7; 126 | 127 | var off_pfFlags = 20; 128 | var off_pfFourCC = 21; 129 | var off_RGBBitCount = 22; 130 | var off_RBitMask = 23; 131 | var off_GBitMask = 24; 132 | var off_BBitMask = 25; 133 | var off_ABitMask = 26; 134 | 135 | // var off_caps = 27; 136 | var off_caps2 = 28; 137 | // var off_caps3 = 29; 138 | // var off_caps4 = 30; 139 | 140 | // Parse header 141 | 142 | var header = new Int32Array( buffer, 0, headerLengthInt ); 143 | 144 | if ( header[ off_magic ] !== DDS_MAGIC ) { 145 | 146 | console.error( 'THREE.DDSLoader.parse: Invalid magic number in DDS header.' ); 147 | return dds; 148 | 149 | } 150 | 151 | if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) { 152 | 153 | console.error( 'THREE.DDSLoader.parse: Unsupported format, must contain a FourCC code.' ); 154 | return dds; 155 | 156 | } 157 | 158 | var blockBytes; 159 | 160 | var fourCC = header[ off_pfFourCC ]; 161 | 162 | var isRGBAUncompressed = false; 163 | 164 | switch ( fourCC ) { 165 | 166 | case FOURCC_DXT1: 167 | 168 | blockBytes = 8; 169 | dds.format = RGB_S3TC_DXT1_Format; 170 | break; 171 | 172 | case FOURCC_DXT3: 173 | 174 | blockBytes = 16; 175 | dds.format = RGBA_S3TC_DXT3_Format; 176 | break; 177 | 178 | case FOURCC_DXT5: 179 | 180 | blockBytes = 16; 181 | dds.format = RGBA_S3TC_DXT5_Format; 182 | break; 183 | 184 | case FOURCC_ETC1: 185 | 186 | blockBytes = 8; 187 | dds.format = RGB_ETC1_Format; 188 | break; 189 | 190 | default: 191 | 192 | if ( header[ off_RGBBitCount ] === 32 193 | && header[ off_RBitMask ] & 0xff0000 194 | && header[ off_GBitMask ] & 0xff00 195 | && header[ off_BBitMask ] & 0xff 196 | && header[ off_ABitMask ] & 0xff000000 ) { 197 | 198 | isRGBAUncompressed = true; 199 | blockBytes = 64; 200 | dds.format = RGBAFormat; 201 | 202 | } else { 203 | 204 | console.error( 'THREE.DDSLoader.parse: Unsupported FourCC code ', int32ToFourCC( fourCC ) ); 205 | return dds; 206 | 207 | } 208 | 209 | } 210 | 211 | dds.mipmapCount = 1; 212 | 213 | if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) { 214 | 215 | dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] ); 216 | 217 | } 218 | 219 | var caps2 = header[ off_caps2 ]; 220 | dds.isCubemap = caps2 & DDSCAPS2_CUBEMAP ? true : false; 221 | if ( dds.isCubemap && ( 222 | ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEX ) || 223 | ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEX ) || 224 | ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEY ) || 225 | ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEY ) || 226 | ! ( caps2 & DDSCAPS2_CUBEMAP_POSITIVEZ ) || 227 | ! ( caps2 & DDSCAPS2_CUBEMAP_NEGATIVEZ ) 228 | ) ) { 229 | 230 | console.error( 'THREE.DDSLoader.parse: Incomplete cubemap faces' ); 231 | return dds; 232 | 233 | } 234 | 235 | dds.width = header[ off_width ]; 236 | dds.height = header[ off_height ]; 237 | 238 | var dataOffset = header[ off_size ] + 4; 239 | 240 | // Extract mipmaps buffers 241 | 242 | var faces = dds.isCubemap ? 6 : 1; 243 | 244 | for ( var face = 0; face < faces; face ++ ) { 245 | 246 | var width = dds.width; 247 | var height = dds.height; 248 | 249 | for ( var i = 0; i < dds.mipmapCount; i ++ ) { 250 | 251 | if ( isRGBAUncompressed ) { 252 | 253 | var byteArray = loadARGBMip( buffer, dataOffset, width, height ); 254 | var dataLength = byteArray.length; 255 | 256 | } else { 257 | 258 | var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes; 259 | var byteArray = new Uint8Array( buffer, dataOffset, dataLength ); 260 | 261 | } 262 | 263 | var mipmap = { 'data': byteArray, 'width': width, 'height': height }; 264 | dds.mipmaps.push( mipmap ); 265 | 266 | dataOffset += dataLength; 267 | 268 | width = Math.max( width >> 1, 1 ); 269 | height = Math.max( height >> 1, 1 ); 270 | 271 | } 272 | 273 | } 274 | 275 | return dds; 276 | 277 | } 278 | 279 | } ); 280 | 281 | export { DDSLoader }; 282 | -------------------------------------------------------------------------------- /libs/three.js/loaders/GCodeLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | BufferGeometry, 3 | Euler, 4 | FileLoader, 5 | Float32BufferAttribute, 6 | Group, 7 | LineBasicMaterial, 8 | LineSegments, 9 | Loader 10 | } from '../../../build/three.module.js'; 11 | 12 | /** 13 | * GCodeLoader is used to load gcode files usually used for 3D printing or CNC applications. 14 | * 15 | * Gcode files are composed by commands used by machines to create objects. 16 | * 17 | * @class GCodeLoader 18 | * @param {Manager} manager Loading manager. 19 | */ 20 | 21 | var GCodeLoader = function ( manager ) { 22 | 23 | Loader.call( this, manager ); 24 | 25 | this.splitLayer = false; 26 | 27 | }; 28 | 29 | GCodeLoader.prototype = Object.assign( Object.create( Loader.prototype ), { 30 | 31 | constructor: GCodeLoader, 32 | 33 | load: function ( url, onLoad, onProgress, onError ) { 34 | 35 | var scope = this; 36 | 37 | var loader = new FileLoader( scope.manager ); 38 | loader.setPath( scope.path ); 39 | loader.setRequestHeader( scope.requestHeader ); 40 | loader.setWithCredentials( scope.withCredentials ); 41 | loader.load( url, function ( text ) { 42 | 43 | try { 44 | 45 | onLoad( scope.parse( text ) ); 46 | 47 | } catch ( e ) { 48 | 49 | if ( onError ) { 50 | 51 | onError( e ); 52 | 53 | } else { 54 | 55 | console.error( e ); 56 | 57 | } 58 | 59 | scope.manager.itemError( url ); 60 | 61 | } 62 | 63 | }, onProgress, onError ); 64 | 65 | }, 66 | 67 | parse: function ( data ) { 68 | 69 | var state = { x: 0, y: 0, z: 0, e: 0, f: 0, extruding: false, relative: false }; 70 | var layers = []; 71 | 72 | var currentLayer = undefined; 73 | 74 | var pathMaterial = new LineBasicMaterial( { color: 0xFF0000 } ); 75 | pathMaterial.name = 'path'; 76 | 77 | var extrudingMaterial = new LineBasicMaterial( { color: 0x00FF00 } ); 78 | extrudingMaterial.name = 'extruded'; 79 | 80 | function newLayer( line ) { 81 | 82 | currentLayer = { vertex: [], pathVertex: [], z: line.z }; 83 | layers.push( currentLayer ); 84 | 85 | } 86 | 87 | //Create lie segment between p1 and p2 88 | function addSegment( p1, p2 ) { 89 | 90 | if ( currentLayer === undefined ) { 91 | 92 | newLayer( p1 ); 93 | 94 | } 95 | 96 | if ( line.extruding ) { 97 | 98 | currentLayer.vertex.push( p1.x, p1.y, p1.z ); 99 | currentLayer.vertex.push( p2.x, p2.y, p2.z ); 100 | 101 | } else { 102 | 103 | currentLayer.pathVertex.push( p1.x, p1.y, p1.z ); 104 | currentLayer.pathVertex.push( p2.x, p2.y, p2.z ); 105 | 106 | } 107 | 108 | } 109 | 110 | function delta( v1, v2 ) { 111 | 112 | return state.relative ? v2 : v2 - v1; 113 | 114 | } 115 | 116 | function absolute( v1, v2 ) { 117 | 118 | return state.relative ? v1 + v2 : v2; 119 | 120 | } 121 | 122 | var lines = data.replace( /;.+/g, '' ).split( '\n' ); 123 | 124 | for ( var i = 0; i < lines.length; i ++ ) { 125 | 126 | var tokens = lines[ i ].split( ' ' ); 127 | var cmd = tokens[ 0 ].toUpperCase(); 128 | 129 | //Argumments 130 | var args = {}; 131 | tokens.splice( 1 ).forEach( function ( token ) { 132 | 133 | if ( token[ 0 ] !== undefined ) { 134 | 135 | var key = token[ 0 ].toLowerCase(); 136 | var value = parseFloat( token.substring( 1 ) ); 137 | args[ key ] = value; 138 | 139 | } 140 | 141 | } ); 142 | 143 | //Process commands 144 | //G0/G1 – Linear Movement 145 | if ( cmd === 'G0' || cmd === 'G1' ) { 146 | 147 | var line = { 148 | x: args.x !== undefined ? absolute( state.x, args.x ) : state.x, 149 | y: args.y !== undefined ? absolute( state.y, args.y ) : state.y, 150 | z: args.z !== undefined ? absolute( state.z, args.z ) : state.z, 151 | e: args.e !== undefined ? absolute( state.e, args.e ) : state.e, 152 | f: args.f !== undefined ? absolute( state.f, args.f ) : state.f, 153 | }; 154 | 155 | //Layer change detection is or made by watching Z, it's made by watching when we extrude at a new Z position 156 | if ( delta( state.e, line.e ) > 0 ) { 157 | 158 | line.extruding = delta( state.e, line.e ) > 0; 159 | 160 | if ( currentLayer == undefined || line.z != currentLayer.z ) { 161 | 162 | newLayer( line ); 163 | 164 | } 165 | 166 | } 167 | 168 | addSegment( state, line ); 169 | state = line; 170 | 171 | } else if ( cmd === 'G2' || cmd === 'G3' ) { 172 | 173 | //G2/G3 - Arc Movement ( G2 clock wise and G3 counter clock wise ) 174 | //console.warn( 'THREE.GCodeLoader: Arc command not supported' ); 175 | 176 | } else if ( cmd === 'G90' ) { 177 | 178 | //G90: Set to Absolute Positioning 179 | state.relative = false; 180 | 181 | } else if ( cmd === 'G91' ) { 182 | 183 | //G91: Set to state.relative Positioning 184 | state.relative = true; 185 | 186 | } else if ( cmd === 'G92' ) { 187 | 188 | //G92: Set Position 189 | var line = state; 190 | line.x = args.x !== undefined ? args.x : line.x; 191 | line.y = args.y !== undefined ? args.y : line.y; 192 | line.z = args.z !== undefined ? args.z : line.z; 193 | line.e = args.e !== undefined ? args.e : line.e; 194 | state = line; 195 | 196 | } else { 197 | 198 | //console.warn( 'THREE.GCodeLoader: Command not supported:' + cmd ); 199 | 200 | } 201 | 202 | } 203 | 204 | function addObject( vertex, extruding ) { 205 | 206 | var geometry = new BufferGeometry(); 207 | geometry.setAttribute( 'position', new Float32BufferAttribute( vertex, 3 ) ); 208 | 209 | var segments = new LineSegments( geometry, extruding ? extrudingMaterial : pathMaterial ); 210 | segments.name = 'layer' + i; 211 | object.add( segments ); 212 | 213 | } 214 | 215 | var object = new Group(); 216 | object.name = 'gcode'; 217 | 218 | if ( this.splitLayer ) { 219 | 220 | for ( var i = 0; i < layers.length; i ++ ) { 221 | 222 | var layer = layers[ i ]; 223 | addObject( layer.vertex, true ); 224 | addObject( layer.pathVertex, false ); 225 | 226 | } 227 | 228 | } else { 229 | 230 | var vertex = [], pathVertex = []; 231 | 232 | for ( var i = 0; i < layers.length; i ++ ) { 233 | 234 | var layer = layers[ i ]; 235 | var layerVertex = layer.vertex; 236 | var layerPathVertex = layer.pathVertex; 237 | 238 | for ( var j = 0; j < layerVertex.length; j ++ ) { 239 | 240 | vertex.push( layerVertex[ j ] ); 241 | 242 | } 243 | 244 | for ( var j = 0; j < layerPathVertex.length; j ++ ) { 245 | 246 | pathVertex.push( layerPathVertex[ j ] ); 247 | 248 | } 249 | 250 | } 251 | 252 | addObject( vertex, true ); 253 | addObject( pathVertex, false ); 254 | 255 | } 256 | 257 | object.quaternion.setFromEuler( new Euler( - Math.PI / 2, 0, 0 ) ); 258 | 259 | return object; 260 | 261 | } 262 | 263 | } ); 264 | 265 | export { GCodeLoader }; 266 | -------------------------------------------------------------------------------- /libs/three.js/loaders/HDRCubeTextureLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | CubeTexture, 3 | DataTexture, 4 | FileLoader, 5 | FloatType, 6 | HalfFloatType, 7 | LinearEncoding, 8 | LinearFilter, 9 | Loader, 10 | NearestFilter, 11 | RGBAFormat, 12 | RGBEEncoding, 13 | RGBFormat, 14 | UnsignedByteType 15 | } from '../../../build/three.module.js'; 16 | import { RGBELoader } from '../loaders/RGBELoader.js'; 17 | 18 | var HDRCubeTextureLoader = function ( manager ) { 19 | 20 | Loader.call( this, manager ); 21 | 22 | this.hdrLoader = new RGBELoader(); 23 | this.type = UnsignedByteType; 24 | 25 | }; 26 | 27 | HDRCubeTextureLoader.prototype = Object.assign( Object.create( Loader.prototype ), { 28 | 29 | constructor: HDRCubeTextureLoader, 30 | 31 | load: function ( urls, onLoad, onProgress, onError ) { 32 | 33 | if ( ! Array.isArray( urls ) ) { 34 | 35 | console.warn( 'THREE.HDRCubeTextureLoader signature has changed. Use .setDataType() instead.' ); 36 | 37 | this.setDataType( urls ); 38 | 39 | urls = onLoad; 40 | onLoad = onProgress; 41 | onProgress = onError; 42 | onError = arguments[ 4 ]; 43 | 44 | } 45 | 46 | var texture = new CubeTexture(); 47 | 48 | texture.type = this.type; 49 | 50 | switch ( texture.type ) { 51 | 52 | case UnsignedByteType: 53 | 54 | texture.encoding = RGBEEncoding; 55 | texture.format = RGBAFormat; 56 | texture.minFilter = NearestFilter; 57 | texture.magFilter = NearestFilter; 58 | texture.generateMipmaps = false; 59 | break; 60 | 61 | case FloatType: 62 | 63 | texture.encoding = LinearEncoding; 64 | texture.format = RGBFormat; 65 | texture.minFilter = LinearFilter; 66 | texture.magFilter = LinearFilter; 67 | texture.generateMipmaps = false; 68 | break; 69 | 70 | case HalfFloatType: 71 | 72 | texture.encoding = LinearEncoding; 73 | texture.format = RGBFormat; 74 | texture.minFilter = LinearFilter; 75 | texture.magFilter = LinearFilter; 76 | texture.generateMipmaps = false; 77 | break; 78 | 79 | } 80 | 81 | var scope = this; 82 | 83 | var loaded = 0; 84 | 85 | function loadHDRData( i, onLoad, onProgress, onError ) { 86 | 87 | new FileLoader( scope.manager ) 88 | .setPath( scope.path ) 89 | .setResponseType( 'arraybuffer' ) 90 | .setWithCredentials( scope.withCredentials ) 91 | .load( urls[ i ], function ( buffer ) { 92 | 93 | loaded ++; 94 | 95 | var texData = scope.hdrLoader.parse( buffer ); 96 | 97 | if ( ! texData ) return; 98 | 99 | if ( texData.data !== undefined ) { 100 | 101 | var dataTexture = new DataTexture( texData.data, texData.width, texData.height ); 102 | 103 | dataTexture.type = texture.type; 104 | dataTexture.encoding = texture.encoding; 105 | dataTexture.format = texture.format; 106 | dataTexture.minFilter = texture.minFilter; 107 | dataTexture.magFilter = texture.magFilter; 108 | dataTexture.generateMipmaps = texture.generateMipmaps; 109 | 110 | texture.images[ i ] = dataTexture; 111 | 112 | } 113 | 114 | if ( loaded === 6 ) { 115 | 116 | texture.needsUpdate = true; 117 | if ( onLoad ) onLoad( texture ); 118 | 119 | } 120 | 121 | }, onProgress, onError ); 122 | 123 | } 124 | 125 | for ( var i = 0; i < urls.length; i ++ ) { 126 | 127 | loadHDRData( i, onLoad, onProgress, onError ); 128 | 129 | } 130 | 131 | return texture; 132 | 133 | }, 134 | 135 | setDataType: function ( value ) { 136 | 137 | this.type = value; 138 | this.hdrLoader.setDataType( value ); 139 | 140 | return this; 141 | 142 | } 143 | 144 | } ); 145 | 146 | export { HDRCubeTextureLoader }; 147 | -------------------------------------------------------------------------------- /libs/three.js/loaders/KMZLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | FileLoader, 3 | Group, 4 | Loader, 5 | LoadingManager 6 | } from '../../../build/three.module.js'; 7 | import { ColladaLoader } from '../loaders/ColladaLoader.js'; 8 | import { JSZip } from '../libs/jszip.module.min.js'; 9 | 10 | var KMZLoader = function ( manager ) { 11 | 12 | Loader.call( this, manager ); 13 | 14 | }; 15 | 16 | KMZLoader.prototype = Object.assign( Object.create( Loader.prototype ), { 17 | 18 | constructor: KMZLoader, 19 | 20 | load: function ( url, onLoad, onProgress, onError ) { 21 | 22 | var scope = this; 23 | 24 | var loader = new FileLoader( scope.manager ); 25 | loader.setPath( scope.path ); 26 | loader.setResponseType( 'arraybuffer' ); 27 | loader.setRequestHeader( scope.requestHeader ); 28 | loader.setWithCredentials( scope.withCredentials ); 29 | loader.load( url, function ( text ) { 30 | 31 | try { 32 | 33 | onLoad( scope.parse( text ) ); 34 | 35 | } catch ( e ) { 36 | 37 | if ( onError ) { 38 | 39 | onError( e ); 40 | 41 | } else { 42 | 43 | console.error( e ); 44 | 45 | } 46 | 47 | scope.manager.itemError( url ); 48 | 49 | } 50 | 51 | }, onProgress, onError ); 52 | 53 | }, 54 | 55 | parse: function ( data ) { 56 | 57 | function findFile( url ) { 58 | 59 | for ( var path in zip.files ) { 60 | 61 | if ( path.substr( - url.length ) === url ) { 62 | 63 | return zip.files[ path ]; 64 | 65 | } 66 | 67 | } 68 | 69 | } 70 | 71 | var manager = new LoadingManager(); 72 | manager.setURLModifier( function ( url ) { 73 | 74 | var image = findFile( url ); 75 | 76 | if ( image ) { 77 | 78 | console.log( 'Loading', url ); 79 | 80 | var blob = new Blob( [ image.asArrayBuffer() ], { type: 'application/octet-stream' } ); 81 | return URL.createObjectURL( blob ); 82 | 83 | } 84 | 85 | return url; 86 | 87 | } ); 88 | 89 | // 90 | 91 | var zip = new JSZip( data ); // eslint-disable-line no-undef 92 | 93 | if ( zip.files[ 'doc.kml' ] ) { 94 | 95 | var xml = new DOMParser().parseFromString( zip.files[ 'doc.kml' ].asText(), 'application/xml' ); 96 | 97 | var model = xml.querySelector( 'Placemark Model Link href' ); 98 | 99 | if ( model ) { 100 | 101 | var loader = new ColladaLoader( manager ); 102 | return loader.parse( zip.files[ model.textContent ].asText() ); 103 | 104 | } 105 | 106 | } else { 107 | 108 | console.warn( 'KMZLoader: Missing doc.kml file.' ); 109 | 110 | for ( var path in zip.files ) { 111 | 112 | var extension = path.split( '.' ).pop().toLowerCase(); 113 | 114 | if ( extension === 'dae' ) { 115 | 116 | var loader = new ColladaLoader( manager ); 117 | return loader.parse( zip.files[ path ].asText() ); 118 | 119 | } 120 | 121 | } 122 | 123 | } 124 | 125 | console.error( 'KMZLoader: Couldn\'t find .dae file.' ); 126 | return { scene: new Group() }; 127 | 128 | } 129 | 130 | } ); 131 | 132 | export { KMZLoader }; 133 | -------------------------------------------------------------------------------- /libs/three.js/loaders/KTXLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | CompressedTextureLoader 3 | } from '../../../build/three.module.js'; 4 | 5 | /** 6 | * for description see https://www.khronos.org/opengles/sdk/tools/KTX/ 7 | * for file layout see https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ 8 | * 9 | * ported from https://github.com/BabylonJS/Babylon.js/blob/master/src/Tools/babylon.khronosTextureContainer.ts 10 | */ 11 | 12 | 13 | var KTXLoader = function ( manager ) { 14 | 15 | CompressedTextureLoader.call( this, manager ); 16 | 17 | }; 18 | 19 | KTXLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prototype ), { 20 | 21 | constructor: KTXLoader, 22 | 23 | parse: function ( buffer, loadMipmaps ) { 24 | 25 | var ktx = new KhronosTextureContainer( buffer, 1 ); 26 | 27 | return { 28 | mipmaps: ktx.mipmaps( loadMipmaps ), 29 | width: ktx.pixelWidth, 30 | height: ktx.pixelHeight, 31 | format: ktx.glInternalFormat, 32 | isCubemap: ktx.numberOfFaces === 6, 33 | mipmapCount: ktx.numberOfMipmapLevels 34 | }; 35 | 36 | } 37 | 38 | } ); 39 | 40 | var KhronosTextureContainer = ( function () { 41 | 42 | /** 43 | * @param {ArrayBuffer} arrayBuffer- contents of the KTX container file 44 | * @param {number} facesExpected- should be either 1 or 6, based whether a cube texture or or 45 | * @param {boolean} threeDExpected- provision for indicating that data should be a 3D texture, not implemented 46 | * @param {boolean} textureArrayExpected- provision for indicating that data should be a texture array, not implemented 47 | */ 48 | function KhronosTextureContainer( arrayBuffer, facesExpected /*, threeDExpected, textureArrayExpected */ ) { 49 | 50 | this.arrayBuffer = arrayBuffer; 51 | 52 | // Test that it is a ktx formatted file, based on the first 12 bytes, character representation is: 53 | // '´', 'K', 'T', 'X', ' ', '1', '1', 'ª', '\r', '\n', '\x1A', '\n' 54 | // 0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A 55 | var identifier = new Uint8Array( this.arrayBuffer, 0, 12 ); 56 | if ( identifier[ 0 ] !== 0xAB || 57 | identifier[ 1 ] !== 0x4B || 58 | identifier[ 2 ] !== 0x54 || 59 | identifier[ 3 ] !== 0x58 || 60 | identifier[ 4 ] !== 0x20 || 61 | identifier[ 5 ] !== 0x31 || 62 | identifier[ 6 ] !== 0x31 || 63 | identifier[ 7 ] !== 0xBB || 64 | identifier[ 8 ] !== 0x0D || 65 | identifier[ 9 ] !== 0x0A || 66 | identifier[ 10 ] !== 0x1A || 67 | identifier[ 11 ] !== 0x0A ) { 68 | 69 | console.error( 'texture missing KTX identifier' ); 70 | return; 71 | 72 | } 73 | 74 | // load the reset of the header in native 32 bit uint 75 | var dataSize = Uint32Array.BYTES_PER_ELEMENT; 76 | var headerDataView = new DataView( this.arrayBuffer, 12, 13 * dataSize ); 77 | var endianness = headerDataView.getUint32( 0, true ); 78 | var littleEndian = endianness === 0x04030201; 79 | 80 | this.glType = headerDataView.getUint32( 1 * dataSize, littleEndian ); // must be 0 for compressed textures 81 | this.glTypeSize = headerDataView.getUint32( 2 * dataSize, littleEndian ); // must be 1 for compressed textures 82 | this.glFormat = headerDataView.getUint32( 3 * dataSize, littleEndian ); // must be 0 for compressed textures 83 | this.glInternalFormat = headerDataView.getUint32( 4 * dataSize, littleEndian ); // the value of arg passed to gl.compressedTexImage2D(,,x,,,,) 84 | this.glBaseInternalFormat = headerDataView.getUint32( 5 * dataSize, littleEndian ); // specify GL_RGB, GL_RGBA, GL_ALPHA, etc (un-compressed only) 85 | this.pixelWidth = headerDataView.getUint32( 6 * dataSize, littleEndian ); // level 0 value of arg passed to gl.compressedTexImage2D(,,,x,,,) 86 | this.pixelHeight = headerDataView.getUint32( 7 * dataSize, littleEndian ); // level 0 value of arg passed to gl.compressedTexImage2D(,,,,x,,) 87 | this.pixelDepth = headerDataView.getUint32( 8 * dataSize, littleEndian ); // level 0 value of arg passed to gl.compressedTexImage3D(,,,,,x,,) 88 | this.numberOfArrayElements = headerDataView.getUint32( 9 * dataSize, littleEndian ); // used for texture arrays 89 | this.numberOfFaces = headerDataView.getUint32( 10 * dataSize, littleEndian ); // used for cubemap textures, should either be 1 or 6 90 | this.numberOfMipmapLevels = headerDataView.getUint32( 11 * dataSize, littleEndian ); // number of levels; disregard possibility of 0 for compressed textures 91 | this.bytesOfKeyValueData = headerDataView.getUint32( 12 * dataSize, littleEndian ); // the amount of space after the header for meta-data 92 | 93 | // Make sure we have a compressed type. Not only reduces work, but probably better to let dev know they are not compressing. 94 | if ( this.glType !== 0 ) { 95 | 96 | console.warn( 'only compressed formats currently supported' ); 97 | return; 98 | 99 | } else { 100 | 101 | // value of zero is an indication to generate mipmaps @ runtime. Not usually allowed for compressed, so disregard. 102 | this.numberOfMipmapLevels = Math.max( 1, this.numberOfMipmapLevels ); 103 | 104 | } 105 | 106 | if ( this.pixelHeight === 0 || this.pixelDepth !== 0 ) { 107 | 108 | console.warn( 'only 2D textures currently supported' ); 109 | return; 110 | 111 | } 112 | 113 | if ( this.numberOfArrayElements !== 0 ) { 114 | 115 | console.warn( 'texture arrays not currently supported' ); 116 | return; 117 | 118 | } 119 | 120 | if ( this.numberOfFaces !== facesExpected ) { 121 | 122 | console.warn( 'number of faces expected' + facesExpected + ', but found ' + this.numberOfFaces ); 123 | return; 124 | 125 | } 126 | 127 | // we now have a completely validated file, so could use existence of loadType as success 128 | // would need to make this more elaborate & adjust checks above to support more than one load type 129 | this.loadType = KhronosTextureContainer.COMPRESSED_2D; 130 | 131 | } 132 | 133 | // return mipmaps for js 134 | KhronosTextureContainer.prototype.mipmaps = function ( loadMipmaps ) { 135 | 136 | var mipmaps = []; 137 | 138 | // initialize width & height for level 1 139 | var dataOffset = KhronosTextureContainer.HEADER_LEN + this.bytesOfKeyValueData; 140 | var width = this.pixelWidth; 141 | var height = this.pixelHeight; 142 | var mipmapCount = loadMipmaps ? this.numberOfMipmapLevels : 1; 143 | 144 | for ( var level = 0; level < mipmapCount; level ++ ) { 145 | 146 | var imageSize = new Int32Array( this.arrayBuffer, dataOffset, 1 )[ 0 ]; // size per face, since not supporting array cubemaps 147 | dataOffset += 4; // size of the image + 4 for the imageSize field 148 | 149 | for ( var face = 0; face < this.numberOfFaces; face ++ ) { 150 | 151 | var byteArray = new Uint8Array( this.arrayBuffer, dataOffset, imageSize ); 152 | 153 | mipmaps.push( { 'data': byteArray, 'width': width, 'height': height } ); 154 | 155 | dataOffset += imageSize; 156 | dataOffset += 3 - ( ( imageSize + 3 ) % 4 ); // add padding for odd sized image 157 | 158 | } 159 | 160 | width = Math.max( 1.0, width * 0.5 ); 161 | height = Math.max( 1.0, height * 0.5 ); 162 | 163 | } 164 | 165 | return mipmaps; 166 | 167 | }; 168 | 169 | KhronosTextureContainer.HEADER_LEN = 12 + ( 13 * 4 ); // identifier + header elements (not including key value meta-data pairs) 170 | // load types 171 | KhronosTextureContainer.COMPRESSED_2D = 0; // uses a gl.compressedTexImage2D() 172 | KhronosTextureContainer.COMPRESSED_3D = 1; // uses a gl.compressedTexImage3D() 173 | KhronosTextureContainer.TEX_2D = 2; // uses a gl.texImage2D() 174 | KhronosTextureContainer.TEX_3D = 3; // uses a gl.texImage3D() 175 | 176 | return KhronosTextureContainer; 177 | 178 | }() ); 179 | 180 | export { KTXLoader }; 181 | -------------------------------------------------------------------------------- /libs/three.js/loaders/LUT3dlLoader.js: -------------------------------------------------------------------------------- 1 | // http://download.autodesk.com/us/systemdocs/help/2011/lustre/index.html?url=./files/WSc4e151a45a3b785a24c3d9a411df9298473-7ffd.htm,topicNumber=d0e9492 2 | 3 | import { 4 | Loader, 5 | FileLoader, 6 | DataTexture, 7 | DataTexture3D, 8 | RGBFormat, 9 | UnsignedByteType, 10 | ClampToEdgeWrapping, 11 | LinearFilter, 12 | } from '../../../build/three.module.js'; 13 | 14 | export class LUT3dlLoader extends Loader { 15 | 16 | load( url, onLoad, onProgress, onError ) { 17 | 18 | const loader = new FileLoader( this.manager ); 19 | loader.setPath( this.path ); 20 | loader.setResponseType( 'text' ); 21 | loader.load( url, text => { 22 | 23 | try { 24 | 25 | onLoad( this.parse( text ) ); 26 | 27 | } catch ( e ) { 28 | 29 | if ( onError ) { 30 | 31 | onError( e ); 32 | 33 | } else { 34 | 35 | console.error( e ); 36 | 37 | } 38 | 39 | this.manager.itemError( url ); 40 | 41 | } 42 | 43 | }, onProgress, onError ); 44 | 45 | } 46 | 47 | parse( str ) { 48 | 49 | // remove empty lines and comment lints 50 | str = str 51 | .replace( /^#.*?(\n|\r)/gm, '' ) 52 | .replace( /^\s*?(\n|\r)/gm, '' ) 53 | .trim(); 54 | 55 | const lines = str.split( /[\n\r]+/g ); 56 | 57 | // first line is the positions on the grid that are provided by the LUT 58 | const gridLines = lines[ 0 ].trim().split( /\s+/g ).map( e => parseFloat( e ) ); 59 | const gridStep = gridLines[ 1 ] - gridLines[ 0 ]; 60 | const size = gridLines.length; 61 | 62 | for ( let i = 1, l = gridLines.length; i < l; i ++ ) { 63 | 64 | if ( gridStep !== ( gridLines[ i ] - gridLines[ i - 1 ] ) ) { 65 | 66 | throw new Error( 'LUT3dlLoader: Inconsistent grid size not supported.' ); 67 | 68 | } 69 | 70 | } 71 | 72 | const dataArray = new Array( size * size * size * 3 ); 73 | let index = 0; 74 | let maxOutputValue = 0.0; 75 | for ( let i = 1, l = lines.length; i < l; i ++ ) { 76 | 77 | const line = lines[ i ].trim(); 78 | const split = line.split( /\s/g ); 79 | 80 | const r = parseFloat( split[ 0 ] ); 81 | const g = parseFloat( split[ 1 ] ); 82 | const b = parseFloat( split[ 2 ] ); 83 | maxOutputValue = Math.max( maxOutputValue, r, g, b ); 84 | 85 | const bLayer = index % size; 86 | const gLayer = Math.floor( index / size ) % size; 87 | const rLayer = Math.floor( index / ( size * size ) ) % size; 88 | 89 | // b grows first, then g, then r 90 | const pixelIndex = bLayer * size * size + gLayer * size + rLayer; 91 | dataArray[ 3 * pixelIndex + 0 ] = r; 92 | dataArray[ 3 * pixelIndex + 1 ] = g; 93 | dataArray[ 3 * pixelIndex + 2 ] = b; 94 | index += 1; 95 | 96 | } 97 | 98 | // Find the apparent bit depth of the stored RGB values and scale the 99 | // values to [ 0, 255 ]. 100 | const bits = Math.ceil( Math.log2( maxOutputValue ) ); 101 | const maxBitValue = Math.pow( 2.0, bits ); 102 | for ( let i = 0, l = dataArray.length; i < l; i ++ ) { 103 | 104 | const val = dataArray[ i ]; 105 | dataArray[ i ] = 255 * val / maxBitValue; 106 | 107 | } 108 | 109 | const data = new Uint8Array( dataArray ); 110 | const texture = new DataTexture(); 111 | texture.image.data = data; 112 | texture.image.width = size; 113 | texture.image.height = size * size; 114 | texture.format = RGBFormat; 115 | texture.type = UnsignedByteType; 116 | texture.magFilter = LinearFilter; 117 | texture.wrapS = ClampToEdgeWrapping; 118 | texture.wrapT = ClampToEdgeWrapping; 119 | texture.generateMipmaps = false; 120 | 121 | const texture3D = new DataTexture3D(); 122 | texture3D.image.data = data; 123 | texture3D.image.width = size; 124 | texture3D.image.height = size; 125 | texture3D.image.depth = size; 126 | texture3D.format = RGBFormat; 127 | texture3D.type = UnsignedByteType; 128 | texture3D.magFilter = LinearFilter; 129 | texture3D.wrapS = ClampToEdgeWrapping; 130 | texture3D.wrapT = ClampToEdgeWrapping; 131 | texture3D.wrapR = ClampToEdgeWrapping; 132 | texture3D.generateMipmaps = false; 133 | 134 | return { 135 | size, 136 | texture, 137 | texture3D, 138 | }; 139 | 140 | } 141 | 142 | } 143 | -------------------------------------------------------------------------------- /libs/three.js/loaders/LUTCubeLoader.js: -------------------------------------------------------------------------------- 1 | // https://wwwimages2.adobe.com/content/dam/acom/en/products/speedgrade/cc/pdfs/cube-lut-specification-1.0.pdf 2 | 3 | import { 4 | Loader, 5 | FileLoader, 6 | Vector3, 7 | DataTexture, 8 | DataTexture3D, 9 | RGBFormat, 10 | UnsignedByteType, 11 | ClampToEdgeWrapping, 12 | LinearFilter, 13 | } from '../../../build/three.module.js'; 14 | 15 | export class LUTCubeLoader extends Loader { 16 | 17 | load( url, onLoad, onProgress, onError ) { 18 | 19 | const loader = new FileLoader( this.manager ); 20 | loader.setPath( this.path ); 21 | loader.setResponseType( 'text' ); 22 | loader.load( url, text => { 23 | 24 | try { 25 | 26 | onLoad( this.parse( text ) ); 27 | 28 | } catch ( e ) { 29 | 30 | if ( onError ) { 31 | 32 | onError( e ); 33 | 34 | } else { 35 | 36 | console.error( e ); 37 | 38 | } 39 | 40 | this.manager.itemError( url ); 41 | 42 | } 43 | 44 | }, onProgress, onError ); 45 | 46 | } 47 | 48 | parse( str ) { 49 | 50 | // Remove empty lines and comments 51 | str = str 52 | .replace( /^#.*?(\n|\r)/gm, '' ) 53 | .replace( /^\s*?(\n|\r)/gm, '' ) 54 | .trim(); 55 | 56 | let title = null; 57 | let size = null; 58 | const domainMin = new Vector3( 0, 0, 0 ); 59 | const domainMax = new Vector3( 1, 1, 1 ); 60 | 61 | const lines = str.split( /[\n\r]+/g ); 62 | let data = null; 63 | 64 | let currIndex = 0; 65 | for ( let i = 0, l = lines.length; i < l; i ++ ) { 66 | 67 | const line = lines[ i ].trim(); 68 | const split = line.split( /\s/g ); 69 | 70 | switch ( split[ 0 ] ) { 71 | 72 | case 'TITLE': 73 | title = line.substring( 7, line.length - 1 ); 74 | break; 75 | case 'LUT_3D_SIZE': 76 | // TODO: A .CUBE LUT file specifies floating point values and could be represented with 77 | // more precision than can be captured with Uint8Array. 78 | const sizeToken = split[ 1 ]; 79 | size = parseFloat( sizeToken ); 80 | data = new Uint8Array( size * size * size * 3 ); 81 | break; 82 | case 'DOMAIN_MIN': 83 | domainMin.x = parseFloat( split[ 1 ] ); 84 | domainMin.y = parseFloat( split[ 2 ] ); 85 | domainMin.z = parseFloat( split[ 3 ] ); 86 | break; 87 | case 'DOMAIN_MAX': 88 | domainMax.x = parseFloat( split[ 1 ] ); 89 | domainMax.y = parseFloat( split[ 2 ] ); 90 | domainMax.z = parseFloat( split[ 3 ] ); 91 | break; 92 | default: 93 | const r = parseFloat( split[ 0 ] ); 94 | const g = parseFloat( split[ 1 ] ); 95 | const b = parseFloat( split[ 2 ] ); 96 | 97 | if ( 98 | r > 1.0 || r < 0.0 || 99 | g > 1.0 || g < 0.0 || 100 | b > 1.0 || b < 0.0 101 | ) { 102 | 103 | throw new Error( 'LUTCubeLoader : Non normalized values not supported.' ); 104 | 105 | } 106 | 107 | data[ currIndex + 0 ] = r * 255; 108 | data[ currIndex + 1 ] = g * 255; 109 | data[ currIndex + 2 ] = b * 255; 110 | currIndex += 3; 111 | 112 | } 113 | 114 | } 115 | 116 | const texture = new DataTexture(); 117 | texture.image.data = data; 118 | texture.image.width = size; 119 | texture.image.height = size * size; 120 | texture.format = RGBFormat; 121 | texture.type = UnsignedByteType; 122 | texture.magFilter = LinearFilter; 123 | texture.wrapS = ClampToEdgeWrapping; 124 | texture.wrapT = ClampToEdgeWrapping; 125 | texture.generateMipmaps = false; 126 | 127 | const texture3D = new DataTexture3D(); 128 | texture3D.image.data = data; 129 | texture3D.image.width = size; 130 | texture3D.image.height = size; 131 | texture3D.image.depth = size; 132 | texture3D.format = RGBFormat; 133 | texture3D.type = UnsignedByteType; 134 | texture3D.magFilter = LinearFilter; 135 | texture3D.wrapS = ClampToEdgeWrapping; 136 | texture3D.wrapT = ClampToEdgeWrapping; 137 | texture3D.wrapR = ClampToEdgeWrapping; 138 | texture3D.generateMipmaps = false; 139 | 140 | return { 141 | title, 142 | size, 143 | domainMin, 144 | domainMax, 145 | texture, 146 | texture3D, 147 | }; 148 | 149 | } 150 | 151 | } 152 | -------------------------------------------------------------------------------- /libs/three.js/loaders/LottieLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | FileLoader, 3 | Loader, 4 | CanvasTexture, 5 | NearestFilter 6 | } from '../../../build/three.module.js'; 7 | 8 | class LottieLoader extends Loader { 9 | 10 | setQuality( value ) { 11 | 12 | this._quality = value; 13 | 14 | } 15 | 16 | load( url, onLoad, onProgress, onError ) { 17 | 18 | const quality = this._quality || 1; 19 | 20 | const texture = new CanvasTexture(); 21 | texture.minFilter = NearestFilter; 22 | 23 | const loader = new FileLoader( this.manager ); 24 | loader.setPath( this.path ); 25 | loader.setWithCredentials( this.withCredentials ); 26 | 27 | loader.load( url, function ( text ) { 28 | 29 | const data = JSON.parse( text ); 30 | 31 | // bodymoving uses container.offetWidth and offsetHeight 32 | // to define width/height 33 | 34 | const container = document.createElement( 'div' ); 35 | container.style.width = data.w + 'px'; 36 | container.style.height = data.h + 'px'; 37 | document.body.appendChild( container ); 38 | 39 | // eslint-disable-next-line no-undef 40 | const animation = bodymovin.loadAnimation( { 41 | container: container, 42 | animType: 'canvas', 43 | loop: true, 44 | autoplay: true, 45 | animationData: data, 46 | rendererSettings: { dpr: quality } 47 | } ); 48 | 49 | texture.animation = animation; 50 | texture.image = animation.container; 51 | 52 | animation.addEventListener( 'enterFrame', function () { 53 | 54 | texture.needsUpdate = true; 55 | 56 | } ); 57 | 58 | container.style.display = 'none'; 59 | 60 | if ( onLoad !== undefined ) { 61 | 62 | onLoad( texture ); 63 | 64 | } 65 | 66 | }, onProgress, onError ); 67 | 68 | return texture; 69 | 70 | } 71 | 72 | } 73 | 74 | export { LottieLoader }; 75 | -------------------------------------------------------------------------------- /libs/three.js/loaders/MDDLoader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * MDD is a special format that stores a position for every vertex in a model for every frame in an animation. 3 | * Similar to BVH, it can be used to transfer animation data between different 3D applications or engines. 4 | * 5 | * MDD stores its data in binary format (big endian) in the following way: 6 | * 7 | * number of frames (a single uint32) 8 | * number of vertices (a single uint32) 9 | * time values for each frame (sequence of float32) 10 | * vertex data for each frame (sequence of float32) 11 | */ 12 | 13 | import { 14 | AnimationClip, 15 | BufferAttribute, 16 | FileLoader, 17 | Loader, 18 | NumberKeyframeTrack 19 | } from '../../../build/three.module.js'; 20 | 21 | var MDDLoader = function ( manager ) { 22 | 23 | Loader.call( this, manager ); 24 | 25 | }; 26 | 27 | MDDLoader.prototype = Object.assign( Object.create( Loader.prototype ), { 28 | 29 | constructor: MDDLoader, 30 | 31 | load: function ( url, onLoad, onProgress, onError ) { 32 | 33 | var scope = this; 34 | 35 | var loader = new FileLoader( this.manager ); 36 | loader.setPath( this.path ); 37 | loader.setResponseType( 'arraybuffer' ); 38 | loader.load( url, function ( data ) { 39 | 40 | onLoad( scope.parse( data ) ); 41 | 42 | }, onProgress, onError ); 43 | 44 | }, 45 | 46 | parse: function ( data ) { 47 | 48 | var view = new DataView( data ); 49 | 50 | var totalFrames = view.getUint32( 0 ); 51 | var totalPoints = view.getUint32( 4 ); 52 | 53 | var offset = 8; 54 | 55 | // animation clip 56 | 57 | var times = new Float32Array( totalFrames ); 58 | var values = new Float32Array( totalFrames * totalFrames ).fill( 0 ); 59 | 60 | for ( var i = 0; i < totalFrames; i ++ ) { 61 | 62 | times[ i ] = view.getFloat32( offset ); offset += 4; 63 | values[ ( totalFrames * i ) + i ] = 1; 64 | 65 | } 66 | 67 | var track = new NumberKeyframeTrack( '.morphTargetInfluences', times, values ); 68 | var clip = new AnimationClip( 'default', times[ times.length - 1 ], [ track ] ); 69 | 70 | // morph targets 71 | 72 | var morphTargets = []; 73 | 74 | for ( var i = 0; i < totalFrames; i ++ ) { 75 | 76 | var morphTarget = new Float32Array( totalPoints * 3 ); 77 | 78 | for ( var j = 0; j < totalPoints; j ++ ) { 79 | 80 | var stride = ( j * 3 ); 81 | 82 | morphTarget[ stride + 0 ] = view.getFloat32( offset ); offset += 4; // x 83 | morphTarget[ stride + 1 ] = view.getFloat32( offset ); offset += 4; // y 84 | morphTarget[ stride + 2 ] = view.getFloat32( offset ); offset += 4; // z 85 | 86 | } 87 | 88 | var attribute = new BufferAttribute( morphTarget, 3 ); 89 | attribute.name = 'morph_' + i; 90 | 91 | morphTargets.push( attribute ); 92 | 93 | } 94 | 95 | return { 96 | morphTargets: morphTargets, 97 | clip: clip 98 | }; 99 | 100 | } 101 | 102 | } ); 103 | 104 | export { MDDLoader }; 105 | -------------------------------------------------------------------------------- /libs/three.js/loaders/NodeMaterialLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | DefaultLoadingManager, 3 | FileLoader 4 | } from '../../../build/three.module.js'; 5 | 6 | import * as Nodes from '../nodes/Nodes.js'; 7 | 8 | var NodeMaterialLoader = function ( manager, library ) { 9 | 10 | this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; 11 | 12 | this.nodes = {}; 13 | this.materials = {}; 14 | this.passes = {}; 15 | this.names = {}; 16 | this.library = library || {}; 17 | 18 | }; 19 | 20 | var NodeMaterialLoaderUtils = { 21 | 22 | replaceUUIDObject: function ( object, uuid, value, recursive ) { 23 | 24 | recursive = recursive !== undefined ? recursive : true; 25 | 26 | if ( typeof uuid === 'object' ) uuid = uuid.uuid; 27 | 28 | if ( typeof object === 'object' ) { 29 | 30 | var keys = Object.keys( object ); 31 | 32 | for ( var i = 0; i < keys.length; i ++ ) { 33 | 34 | var key = keys[ i ]; 35 | 36 | if ( recursive ) { 37 | 38 | object[ key ] = this.replaceUUIDObject( object[ key ], uuid, value ); 39 | 40 | } 41 | 42 | if ( key === uuid ) { 43 | 44 | object[ uuid ] = object[ key ]; 45 | 46 | delete object[ key ]; 47 | 48 | } 49 | 50 | } 51 | 52 | } 53 | 54 | return object === uuid ? value : object; 55 | 56 | }, 57 | 58 | replaceUUID: function ( json, uuid, value ) { 59 | 60 | this.replaceUUIDObject( json, uuid, value, false ); 61 | this.replaceUUIDObject( json.nodes, uuid, value ); 62 | this.replaceUUIDObject( json.materials, uuid, value ); 63 | this.replaceUUIDObject( json.passes, uuid, value ); 64 | this.replaceUUIDObject( json.library, uuid, value, false ); 65 | 66 | return json; 67 | 68 | } 69 | 70 | }; 71 | 72 | Object.assign( NodeMaterialLoader.prototype, { 73 | 74 | load: function ( url, onLoad, onProgress, onError ) { 75 | 76 | var scope = this; 77 | 78 | var loader = new FileLoader( scope.manager ); 79 | loader.setPath( scope.path ); 80 | loader.load( url, function ( text ) { 81 | 82 | onLoad( scope.parse( JSON.parse( text ) ) ); 83 | 84 | }, onProgress, onError ); 85 | 86 | return this; 87 | 88 | }, 89 | 90 | setPath: function ( value ) { 91 | 92 | this.path = value; 93 | return this; 94 | 95 | }, 96 | 97 | getObjectByName: function ( uuid ) { 98 | 99 | return this.names[ uuid ]; 100 | 101 | }, 102 | 103 | getObjectById: function ( uuid ) { 104 | 105 | return this.library[ uuid ] || 106 | this.nodes[ uuid ] || 107 | this.materials[ uuid ] || 108 | this.passes[ uuid ] || 109 | this.names[ uuid ]; 110 | 111 | }, 112 | 113 | getNode: function ( uuid ) { 114 | 115 | var object = this.getObjectById( uuid ); 116 | 117 | if ( ! object ) { 118 | 119 | console.warn( 'Node "' + uuid + '" not found.' ); 120 | 121 | } 122 | 123 | return object; 124 | 125 | }, 126 | 127 | resolve: function ( json ) { 128 | 129 | switch ( typeof json ) { 130 | 131 | case 'boolean': 132 | case 'number': 133 | 134 | return json; 135 | 136 | case 'string': 137 | 138 | if ( /^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/i.test( json ) || this.library[ json ] ) { 139 | 140 | return this.getNode( json ); 141 | 142 | } 143 | 144 | return json; 145 | 146 | default: 147 | 148 | if ( Array.isArray( json ) ) { 149 | 150 | for ( var i = 0; i < json.length; i ++ ) { 151 | 152 | json[ i ] = this.resolve( json[ i ] ); 153 | 154 | } 155 | 156 | } else { 157 | 158 | for ( var prop in json ) { 159 | 160 | if ( prop === 'uuid' ) continue; 161 | 162 | json[ prop ] = this.resolve( json[ prop ] ); 163 | 164 | } 165 | 166 | } 167 | 168 | } 169 | 170 | return json; 171 | 172 | }, 173 | 174 | declare: function ( json ) { 175 | 176 | var uuid, node, object; 177 | 178 | for ( uuid in json.nodes ) { 179 | 180 | node = json.nodes[ uuid ]; 181 | 182 | object = new Nodes[ node.nodeType + 'Node' ](); 183 | 184 | if ( node.name ) { 185 | 186 | object.name = node.name; 187 | 188 | this.names[ object.name ] = object; 189 | 190 | } 191 | 192 | this.nodes[ uuid ] = object; 193 | 194 | } 195 | 196 | for ( uuid in json.materials ) { 197 | 198 | node = json.materials[ uuid ]; 199 | 200 | object = new Nodes[ node.type ](); 201 | 202 | if ( node.name ) { 203 | 204 | object.name = node.name; 205 | 206 | this.names[ object.name ] = object; 207 | 208 | } 209 | 210 | this.materials[ uuid ] = object; 211 | 212 | } 213 | 214 | for ( uuid in json.passes ) { 215 | 216 | node = json.passes[ uuid ]; 217 | 218 | object = new Nodes[ node.type ](); 219 | 220 | if ( node.name ) { 221 | 222 | object.name = node.name; 223 | 224 | this.names[ object.name ] = object; 225 | 226 | } 227 | 228 | this.passes[ uuid ] = object; 229 | 230 | } 231 | 232 | if ( json.material ) this.material = this.materials[ json.material ]; 233 | 234 | if ( json.pass ) this.pass = this.passes[ json.pass ]; 235 | 236 | return json; 237 | 238 | }, 239 | 240 | parse: function ( json ) { 241 | 242 | var uuid; 243 | 244 | json = this.resolve( this.declare( json ) ); 245 | 246 | for ( uuid in json.nodes ) { 247 | 248 | this.nodes[ uuid ].copy( json.nodes[ uuid ] ); 249 | 250 | } 251 | 252 | for ( uuid in json.materials ) { 253 | 254 | this.materials[ uuid ].copy( json.materials[ uuid ] ); 255 | 256 | } 257 | 258 | for ( uuid in json.passes ) { 259 | 260 | this.passes[ uuid ].copy( json.passes[ uuid ] ); 261 | 262 | } 263 | 264 | return this.material || this.pass || this; 265 | 266 | } 267 | 268 | } ); 269 | 270 | export { NodeMaterialLoader, NodeMaterialLoaderUtils }; 271 | -------------------------------------------------------------------------------- /libs/three.js/loaders/OBJLoader2Parallel.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Development repository: https://github.com/kaisalmen/WWOBJLoader 3 | */ 4 | 5 | // Imports only related to wrapper 6 | import { 7 | Object3D 8 | } from '../../../build/three.module.js'; 9 | import { 10 | CodeBuilderInstructions, 11 | WorkerExecutionSupport 12 | } from './obj2/worker/main/WorkerExecutionSupport.js'; 13 | import { CodeSerializer } from './obj2/utils/CodeSerializer.js'; 14 | import { OBJLoader2 } from './OBJLoader2.js'; 15 | 16 | // Imports only related to worker (when standard workers (modules aren't supported) are used) 17 | import { OBJLoader2Parser } from './obj2/OBJLoader2Parser.js'; 18 | import { 19 | WorkerRunner, 20 | DefaultWorkerPayloadHandler, 21 | ObjectManipulator 22 | } from './obj2/worker/parallel/WorkerRunner.js'; 23 | 24 | 25 | /** 26 | * Creates a new OBJLoader2Parallel. Use it to load OBJ data from files or to parse OBJ data from arraybuffer. 27 | * It extends {@link OBJLoader2} with the capability to run the parser in a web worker. 28 | * 29 | * @param [LoadingManager] manager The loadingManager for the loader to use. Default is {@link LoadingManager} 30 | * @constructor 31 | */ 32 | const OBJLoader2Parallel = function ( manager ) { 33 | 34 | OBJLoader2.call( this, manager ); 35 | this.preferJsmWorker = false; 36 | this.jsmWorkerUrl = null; 37 | 38 | this.executeParallel = true; 39 | this.workerExecutionSupport = new WorkerExecutionSupport(); 40 | 41 | }; 42 | 43 | OBJLoader2Parallel.OBJLOADER2_PARALLEL_VERSION = '3.2.0'; 44 | console.info( 'Using OBJLoader2Parallel version: ' + OBJLoader2Parallel.OBJLOADER2_PARALLEL_VERSION ); 45 | OBJLoader2Parallel.DEFAULT_JSM_WORKER_PATH = './jsm/loaders/obj2/worker/parallel/OBJLoader2JsmWorker.js'; 46 | 47 | OBJLoader2Parallel.prototype = Object.assign( Object.create( OBJLoader2.prototype ), { 48 | 49 | constructor: OBJLoader2Parallel, 50 | 51 | /** 52 | * Execution of parse in parallel via Worker is default, but normal {OBJLoader2} parsing can be enforced via false here. 53 | * 54 | * @param {boolean} executeParallel True or False 55 | * @return {OBJLoader2Parallel} 56 | */ 57 | setExecuteParallel: function ( executeParallel ) { 58 | 59 | this.executeParallel = executeParallel === true; 60 | return this; 61 | 62 | }, 63 | 64 | /** 65 | * Set whether jsm modules in workers should be used. This requires browser support which is currently only experimental. 66 | * @param {boolean} preferJsmWorker True or False 67 | * @param {URL} jsmWorkerUrl Provide complete jsm worker URL otherwise relative path to this module may not be correct 68 | * @return {OBJLoader2Parallel} 69 | */ 70 | setJsmWorker: function ( preferJsmWorker, jsmWorkerUrl ) { 71 | 72 | this.preferJsmWorker = preferJsmWorker === true; 73 | 74 | if ( jsmWorkerUrl === undefined || jsmWorkerUrl === null ) { 75 | 76 | throw 'The url to the jsm worker is not valid. Aborting...'; 77 | 78 | } 79 | 80 | this.jsmWorkerUrl = jsmWorkerUrl; 81 | 82 | return this; 83 | 84 | }, 85 | 86 | /** 87 | * Allow to get hold of {@link WorkerExecutionSupport} for configuration purposes. 88 | * @return {WorkerExecutionSupport} 89 | */ 90 | getWorkerExecutionSupport: function () { 91 | 92 | return this.workerExecutionSupport; 93 | 94 | }, 95 | 96 | /** 97 | * Provide instructions on what is to be contained in the worker. 98 | * @return {CodeBuilderInstructions} 99 | */ 100 | buildWorkerCode: function () { 101 | 102 | const codeBuilderInstructions = new CodeBuilderInstructions( true, true, this.preferJsmWorker ); 103 | 104 | if ( codeBuilderInstructions.isSupportsJsmWorker() ) { 105 | 106 | codeBuilderInstructions.setJsmWorkerUrl( this.jsmWorkerUrl ); 107 | 108 | } 109 | 110 | if ( codeBuilderInstructions.isSupportsStandardWorker() ) { 111 | 112 | const objectManipulator = new ObjectManipulator(); 113 | const defaultWorkerPayloadHandler = new DefaultWorkerPayloadHandler( this.parser ); 114 | const workerRunner = new WorkerRunner( {} ); 115 | codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( OBJLoader2Parser, this.parser ) ); 116 | codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( ObjectManipulator, objectManipulator ) ); 117 | codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( DefaultWorkerPayloadHandler, defaultWorkerPayloadHandler ) ); 118 | codeBuilderInstructions.addCodeFragment( CodeSerializer.serializeClass( WorkerRunner, workerRunner ) ); 119 | 120 | const startCode = 'new ' + workerRunner.constructor.name + '( new ' + defaultWorkerPayloadHandler.constructor.name + '( new ' + this.parser.constructor.name + '() ) );'; 121 | codeBuilderInstructions.addStartCode( startCode ); 122 | 123 | } 124 | 125 | return codeBuilderInstructions; 126 | 127 | }, 128 | 129 | /** 130 | * See {@link OBJLoader2.load} 131 | */ 132 | load: function ( content, onLoad, onFileLoadProgress, onError, onMeshAlter ) { 133 | 134 | const scope = this; 135 | function interceptOnLoad( object3d, message ) { 136 | 137 | if ( object3d.name === 'OBJLoader2ParallelDummy' ) { 138 | 139 | if ( scope.parser.logging.enabled && scope.parser.logging.debug ) { 140 | 141 | console.debug( 'Received dummy answer from OBJLoader2Parallel#parse' ); 142 | 143 | } 144 | 145 | } else { 146 | 147 | onLoad( object3d, message ); 148 | 149 | } 150 | 151 | } 152 | 153 | OBJLoader2.prototype.load.call( this, content, interceptOnLoad, onFileLoadProgress, onError, onMeshAlter ); 154 | 155 | }, 156 | 157 | /** 158 | * See {@link OBJLoader2.parse} 159 | * The callback onLoad needs to be set to be able to receive the content if used in parallel mode. 160 | * Fallback is possible via {@link OBJLoader2Parallel#setExecuteParallel}. 161 | */ 162 | parse: function ( content ) { 163 | 164 | if ( this.executeParallel ) { 165 | 166 | if ( this.parser.callbacks.onLoad === this.parser._onLoad ) { 167 | 168 | throw 'No callback other than the default callback was provided! Aborting!'; 169 | 170 | } 171 | 172 | // check if worker has been initialize before. If yes, skip init 173 | if ( ! this.workerExecutionSupport.isWorkerLoaded( this.preferJsmWorker ) ) { 174 | 175 | this.workerExecutionSupport.buildWorker( this.buildWorkerCode() ); 176 | 177 | const scope = this; 178 | const scopedOnAssetAvailable = function ( payload ) { 179 | 180 | scope._onAssetAvailable( payload ); 181 | 182 | }; 183 | 184 | function scopedOnLoad( message ) { 185 | 186 | scope.parser.callbacks.onLoad( scope.baseObject3d, message ); 187 | 188 | } 189 | 190 | this.workerExecutionSupport.updateCallbacks( scopedOnAssetAvailable, scopedOnLoad ); 191 | 192 | } 193 | 194 | // Create default materials beforehand, but do not override previously set materials (e.g. during init) 195 | this.materialHandler.createDefaultMaterials( false ); 196 | 197 | this.workerExecutionSupport.executeParallel( 198 | { 199 | params: { 200 | modelName: this.modelName, 201 | instanceNo: this.instanceNo, 202 | useIndices: this.parser.useIndices, 203 | disregardNormals: this.parser.disregardNormals, 204 | materialPerSmoothingGroup: this.parser.materialPerSmoothingGroup, 205 | useOAsMesh: this.parser.useOAsMesh, 206 | materials: this.materialHandler.getMaterialsJSON() 207 | }, 208 | data: { 209 | input: content, 210 | options: null 211 | }, 212 | logging: { 213 | enabled: this.parser.logging.enabled, 214 | debug: this.parser.logging.debug 215 | } 216 | } ); 217 | 218 | const dummy = new Object3D(); 219 | dummy.name = 'OBJLoader2ParallelDummy'; 220 | return dummy; 221 | 222 | } else { 223 | 224 | return OBJLoader2.prototype.parse.call( this, content ); 225 | 226 | } 227 | 228 | }, 229 | 230 | } ); 231 | 232 | export { OBJLoader2Parallel }; 233 | -------------------------------------------------------------------------------- /libs/three.js/loaders/PDBLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | BufferGeometry, 3 | FileLoader, 4 | Float32BufferAttribute, 5 | Loader 6 | } from '../../../build/three.module.js'; 7 | 8 | var PDBLoader = function ( manager ) { 9 | 10 | Loader.call( this, manager ); 11 | 12 | }; 13 | 14 | PDBLoader.prototype = Object.assign( Object.create( Loader.prototype ), { 15 | 16 | constructor: PDBLoader, 17 | 18 | load: function ( url, onLoad, onProgress, onError ) { 19 | 20 | var scope = this; 21 | 22 | var loader = new FileLoader( scope.manager ); 23 | loader.setPath( scope.path ); 24 | loader.setRequestHeader( scope.requestHeader ); 25 | loader.setWithCredentials( scope.withCredentials ); 26 | loader.load( url, function ( text ) { 27 | 28 | try { 29 | 30 | onLoad( scope.parse( text ) ); 31 | 32 | } catch ( e ) { 33 | 34 | if ( onError ) { 35 | 36 | onError( e ); 37 | 38 | } else { 39 | 40 | console.error( e ); 41 | 42 | } 43 | 44 | scope.manager.itemError( url ); 45 | 46 | } 47 | 48 | }, onProgress, onError ); 49 | 50 | }, 51 | 52 | // Based on CanvasMol PDB parser 53 | 54 | parse: function ( text ) { 55 | 56 | function trim( text ) { 57 | 58 | return text.replace( /^\s\s*/, '' ).replace( /\s\s*$/, '' ); 59 | 60 | } 61 | 62 | function capitalize( text ) { 63 | 64 | return text.charAt( 0 ).toUpperCase() + text.substr( 1 ).toLowerCase(); 65 | 66 | } 67 | 68 | function hash( s, e ) { 69 | 70 | return 's' + Math.min( s, e ) + 'e' + Math.max( s, e ); 71 | 72 | } 73 | 74 | function parseBond( start, length ) { 75 | 76 | var eatom = parseInt( lines[ i ].substr( start, length ) ); 77 | 78 | if ( eatom ) { 79 | 80 | var h = hash( satom, eatom ); 81 | 82 | if ( _bhash[ h ] === undefined ) { 83 | 84 | _bonds.push( [ satom - 1, eatom - 1, 1 ] ); 85 | _bhash[ h ] = _bonds.length - 1; 86 | 87 | } else { 88 | 89 | // doesn't really work as almost all PDBs 90 | // have just normal bonds appearing multiple 91 | // times instead of being double/triple bonds 92 | // bonds[bhash[h]][2] += 1; 93 | 94 | } 95 | 96 | } 97 | 98 | } 99 | 100 | function buildGeometry() { 101 | 102 | var build = { 103 | geometryAtoms: new BufferGeometry(), 104 | geometryBonds: new BufferGeometry(), 105 | json: { 106 | atoms: atoms 107 | } 108 | }; 109 | 110 | var geometryAtoms = build.geometryAtoms; 111 | var geometryBonds = build.geometryBonds; 112 | 113 | var i, l; 114 | var x, y, z; 115 | 116 | var verticesAtoms = []; 117 | var colorsAtoms = []; 118 | var verticesBonds = []; 119 | 120 | // atoms 121 | 122 | for ( i = 0, l = atoms.length; i < l; i ++ ) { 123 | 124 | var atom = atoms[ i ]; 125 | 126 | x = atom[ 0 ]; 127 | y = atom[ 1 ]; 128 | z = atom[ 2 ]; 129 | 130 | verticesAtoms.push( x, y, z ); 131 | 132 | var r = atom[ 3 ][ 0 ] / 255; 133 | var g = atom[ 3 ][ 1 ] / 255; 134 | var b = atom[ 3 ][ 2 ] / 255; 135 | 136 | colorsAtoms.push( r, g, b ); 137 | 138 | } 139 | 140 | // bonds 141 | 142 | for ( i = 0, l = _bonds.length; i < l; i ++ ) { 143 | 144 | var bond = _bonds[ i ]; 145 | 146 | var start = bond[ 0 ]; 147 | var end = bond[ 1 ]; 148 | 149 | var startAtom = _atomMap[ start ]; 150 | var endAtom = _atomMap[ end ]; 151 | 152 | x = startAtom[ 0 ]; 153 | y = startAtom[ 1 ]; 154 | z = startAtom[ 2 ]; 155 | 156 | verticesBonds.push( x, y, z ); 157 | 158 | x = endAtom[ 0 ]; 159 | y = endAtom[ 1 ]; 160 | z = endAtom[ 2 ]; 161 | 162 | verticesBonds.push( x, y, z ); 163 | 164 | } 165 | 166 | // build geometry 167 | 168 | geometryAtoms.setAttribute( 'position', new Float32BufferAttribute( verticesAtoms, 3 ) ); 169 | geometryAtoms.setAttribute( 'color', new Float32BufferAttribute( colorsAtoms, 3 ) ); 170 | 171 | geometryBonds.setAttribute( 'position', new Float32BufferAttribute( verticesBonds, 3 ) ); 172 | 173 | return build; 174 | 175 | } 176 | 177 | var CPK = { h: [ 255, 255, 255 ], he: [ 217, 255, 255 ], li: [ 204, 128, 255 ], be: [ 194, 255, 0 ], b: [ 255, 181, 181 ], c: [ 144, 144, 144 ], n: [ 48, 80, 248 ], o: [ 255, 13, 13 ], f: [ 144, 224, 80 ], ne: [ 179, 227, 245 ], na: [ 171, 92, 242 ], mg: [ 138, 255, 0 ], al: [ 191, 166, 166 ], si: [ 240, 200, 160 ], p: [ 255, 128, 0 ], s: [ 255, 255, 48 ], cl: [ 31, 240, 31 ], ar: [ 128, 209, 227 ], k: [ 143, 64, 212 ], ca: [ 61, 255, 0 ], sc: [ 230, 230, 230 ], ti: [ 191, 194, 199 ], v: [ 166, 166, 171 ], cr: [ 138, 153, 199 ], mn: [ 156, 122, 199 ], fe: [ 224, 102, 51 ], co: [ 240, 144, 160 ], ni: [ 80, 208, 80 ], cu: [ 200, 128, 51 ], zn: [ 125, 128, 176 ], ga: [ 194, 143, 143 ], ge: [ 102, 143, 143 ], as: [ 189, 128, 227 ], se: [ 255, 161, 0 ], br: [ 166, 41, 41 ], kr: [ 92, 184, 209 ], rb: [ 112, 46, 176 ], sr: [ 0, 255, 0 ], y: [ 148, 255, 255 ], zr: [ 148, 224, 224 ], nb: [ 115, 194, 201 ], mo: [ 84, 181, 181 ], tc: [ 59, 158, 158 ], ru: [ 36, 143, 143 ], rh: [ 10, 125, 140 ], pd: [ 0, 105, 133 ], ag: [ 192, 192, 192 ], cd: [ 255, 217, 143 ], in: [ 166, 117, 115 ], sn: [ 102, 128, 128 ], sb: [ 158, 99, 181 ], te: [ 212, 122, 0 ], i: [ 148, 0, 148 ], xe: [ 66, 158, 176 ], cs: [ 87, 23, 143 ], ba: [ 0, 201, 0 ], la: [ 112, 212, 255 ], ce: [ 255, 255, 199 ], pr: [ 217, 255, 199 ], nd: [ 199, 255, 199 ], pm: [ 163, 255, 199 ], sm: [ 143, 255, 199 ], eu: [ 97, 255, 199 ], gd: [ 69, 255, 199 ], tb: [ 48, 255, 199 ], dy: [ 31, 255, 199 ], ho: [ 0, 255, 156 ], er: [ 0, 230, 117 ], tm: [ 0, 212, 82 ], yb: [ 0, 191, 56 ], lu: [ 0, 171, 36 ], hf: [ 77, 194, 255 ], ta: [ 77, 166, 255 ], w: [ 33, 148, 214 ], re: [ 38, 125, 171 ], os: [ 38, 102, 150 ], ir: [ 23, 84, 135 ], pt: [ 208, 208, 224 ], au: [ 255, 209, 35 ], hg: [ 184, 184, 208 ], tl: [ 166, 84, 77 ], pb: [ 87, 89, 97 ], bi: [ 158, 79, 181 ], po: [ 171, 92, 0 ], at: [ 117, 79, 69 ], rn: [ 66, 130, 150 ], fr: [ 66, 0, 102 ], ra: [ 0, 125, 0 ], ac: [ 112, 171, 250 ], th: [ 0, 186, 255 ], pa: [ 0, 161, 255 ], u: [ 0, 143, 255 ], np: [ 0, 128, 255 ], pu: [ 0, 107, 255 ], am: [ 84, 92, 242 ], cm: [ 120, 92, 227 ], bk: [ 138, 79, 227 ], cf: [ 161, 54, 212 ], es: [ 179, 31, 212 ], fm: [ 179, 31, 186 ], md: [ 179, 13, 166 ], no: [ 189, 13, 135 ], lr: [ 199, 0, 102 ], rf: [ 204, 0, 89 ], db: [ 209, 0, 79 ], sg: [ 217, 0, 69 ], bh: [ 224, 0, 56 ], hs: [ 230, 0, 46 ], mt: [ 235, 0, 38 ], ds: [ 235, 0, 38 ], rg: [ 235, 0, 38 ], cn: [ 235, 0, 38 ], uut: [ 235, 0, 38 ], uuq: [ 235, 0, 38 ], uup: [ 235, 0, 38 ], uuh: [ 235, 0, 38 ], uus: [ 235, 0, 38 ], uuo: [ 235, 0, 38 ] }; 178 | 179 | var atoms = []; 180 | 181 | var _bonds = []; 182 | var _bhash = {}; 183 | var _atomMap = {}; 184 | 185 | var x, y, z, index, e; 186 | 187 | // parse 188 | 189 | var lines = text.split( '\n' ); 190 | 191 | for ( var i = 0, l = lines.length; i < l; i ++ ) { 192 | 193 | if ( lines[ i ].substr( 0, 4 ) === 'ATOM' || lines[ i ].substr( 0, 6 ) === 'HETATM' ) { 194 | 195 | x = parseFloat( lines[ i ].substr( 30, 7 ) ); 196 | y = parseFloat( lines[ i ].substr( 38, 7 ) ); 197 | z = parseFloat( lines[ i ].substr( 46, 7 ) ); 198 | index = parseInt( lines[ i ].substr( 6, 5 ) ) - 1; 199 | 200 | e = trim( lines[ i ].substr( 76, 2 ) ).toLowerCase(); 201 | 202 | if ( e === '' ) { 203 | 204 | e = trim( lines[ i ].substr( 12, 2 ) ).toLowerCase(); 205 | 206 | } 207 | 208 | var atomData = [ x, y, z, CPK[ e ], capitalize( e ) ]; 209 | 210 | atoms.push( atomData ); 211 | _atomMap[ index ] = atomData; 212 | 213 | } else if ( lines[ i ].substr( 0, 6 ) === 'CONECT' ) { 214 | 215 | var satom = parseInt( lines[ i ].substr( 6, 5 ) ); 216 | 217 | parseBond( 11, 5 ); 218 | parseBond( 16, 5 ); 219 | parseBond( 21, 5 ); 220 | parseBond( 26, 5 ); 221 | 222 | } 223 | 224 | } 225 | 226 | // build and return geometry 227 | 228 | return buildGeometry(); 229 | 230 | } 231 | 232 | } ); 233 | 234 | export { PDBLoader }; 235 | -------------------------------------------------------------------------------- /libs/three.js/loaders/PRWMLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | BufferAttribute, 3 | BufferGeometry, 4 | FileLoader, 5 | Loader 6 | } from '../../../build/three.module.js'; 7 | 8 | /** 9 | * See https://github.com/kchapelier/PRWM for more informations about this file format 10 | */ 11 | 12 | var PRWMLoader = ( function () { 13 | 14 | var bigEndianPlatform = null; 15 | 16 | /** 17 | * Check if the endianness of the platform is big-endian (most significant bit first) 18 | * @returns {boolean} True if big-endian, false if little-endian 19 | */ 20 | function isBigEndianPlatform() { 21 | 22 | if ( bigEndianPlatform === null ) { 23 | 24 | var buffer = new ArrayBuffer( 2 ), 25 | uint8Array = new Uint8Array( buffer ), 26 | uint16Array = new Uint16Array( buffer ); 27 | 28 | uint8Array[ 0 ] = 0xAA; // set first byte 29 | uint8Array[ 1 ] = 0xBB; // set second byte 30 | bigEndianPlatform = ( uint16Array[ 0 ] === 0xAABB ); 31 | 32 | } 33 | 34 | return bigEndianPlatform; 35 | 36 | } 37 | 38 | // match the values defined in the spec to the TypedArray types 39 | var InvertedEncodingTypes = [ 40 | null, 41 | Float32Array, 42 | null, 43 | Int8Array, 44 | Int16Array, 45 | null, 46 | Int32Array, 47 | Uint8Array, 48 | Uint16Array, 49 | null, 50 | Uint32Array 51 | ]; 52 | 53 | // define the method to use on a DataView, corresponding the TypedArray type 54 | var getMethods = { 55 | Uint16Array: 'getUint16', 56 | Uint32Array: 'getUint32', 57 | Int16Array: 'getInt16', 58 | Int32Array: 'getInt32', 59 | Float32Array: 'getFloat32', 60 | Float64Array: 'getFloat64' 61 | }; 62 | 63 | 64 | function copyFromBuffer( sourceArrayBuffer, viewType, position, length, fromBigEndian ) { 65 | 66 | var bytesPerElement = viewType.BYTES_PER_ELEMENT, 67 | result; 68 | 69 | if ( fromBigEndian === isBigEndianPlatform() || bytesPerElement === 1 ) { 70 | 71 | result = new viewType( sourceArrayBuffer, position, length ); 72 | 73 | } else { 74 | 75 | var readView = new DataView( sourceArrayBuffer, position, length * bytesPerElement ), 76 | getMethod = getMethods[ viewType.name ], 77 | littleEndian = ! fromBigEndian, 78 | i = 0; 79 | 80 | result = new viewType( length ); 81 | 82 | for ( ; i < length; i ++ ) { 83 | 84 | result[ i ] = readView[ getMethod ]( i * bytesPerElement, littleEndian ); 85 | 86 | } 87 | 88 | } 89 | 90 | return result; 91 | 92 | } 93 | 94 | 95 | function decodePrwm( buffer ) { 96 | 97 | var array = new Uint8Array( buffer ), 98 | version = array[ 0 ], 99 | flags = array[ 1 ], 100 | indexedGeometry = !! ( flags >> 7 & 0x01 ), 101 | indicesType = flags >> 6 & 0x01, 102 | bigEndian = ( flags >> 5 & 0x01 ) === 1, 103 | attributesNumber = flags & 0x1F, 104 | valuesNumber = 0, 105 | indicesNumber = 0; 106 | 107 | if ( bigEndian ) { 108 | 109 | valuesNumber = ( array[ 2 ] << 16 ) + ( array[ 3 ] << 8 ) + array[ 4 ]; 110 | indicesNumber = ( array[ 5 ] << 16 ) + ( array[ 6 ] << 8 ) + array[ 7 ]; 111 | 112 | } else { 113 | 114 | valuesNumber = array[ 2 ] + ( array[ 3 ] << 8 ) + ( array[ 4 ] << 16 ); 115 | indicesNumber = array[ 5 ] + ( array[ 6 ] << 8 ) + ( array[ 7 ] << 16 ); 116 | 117 | } 118 | 119 | /** PRELIMINARY CHECKS **/ 120 | 121 | if ( version === 0 ) { 122 | 123 | throw new Error( 'PRWM decoder: Invalid format version: 0' ); 124 | 125 | } else if ( version !== 1 ) { 126 | 127 | throw new Error( 'PRWM decoder: Unsupported format version: ' + version ); 128 | 129 | } 130 | 131 | if ( ! indexedGeometry ) { 132 | 133 | if ( indicesType !== 0 ) { 134 | 135 | throw new Error( 'PRWM decoder: Indices type must be set to 0 for non-indexed geometries' ); 136 | 137 | } else if ( indicesNumber !== 0 ) { 138 | 139 | throw new Error( 'PRWM decoder: Number of indices must be set to 0 for non-indexed geometries' ); 140 | 141 | } 142 | 143 | } 144 | 145 | /** PARSING **/ 146 | 147 | var pos = 8; 148 | 149 | var attributes = {}, 150 | attributeName, 151 | char, 152 | attributeType, 153 | cardinality, 154 | encodingType, 155 | arrayType, 156 | values, 157 | indices, 158 | i; 159 | 160 | for ( i = 0; i < attributesNumber; i ++ ) { 161 | 162 | attributeName = ''; 163 | 164 | while ( pos < array.length ) { 165 | 166 | char = array[ pos ]; 167 | pos ++; 168 | 169 | if ( char === 0 ) { 170 | 171 | break; 172 | 173 | } else { 174 | 175 | attributeName += String.fromCharCode( char ); 176 | 177 | } 178 | 179 | } 180 | 181 | flags = array[ pos ]; 182 | 183 | attributeType = flags >> 7 & 0x01; 184 | cardinality = ( flags >> 4 & 0x03 ) + 1; 185 | encodingType = flags & 0x0F; 186 | arrayType = InvertedEncodingTypes[ encodingType ]; 187 | 188 | pos ++; 189 | 190 | // padding to next multiple of 4 191 | pos = Math.ceil( pos / 4 ) * 4; 192 | 193 | values = copyFromBuffer( buffer, arrayType, pos, cardinality * valuesNumber, bigEndian ); 194 | 195 | pos += arrayType.BYTES_PER_ELEMENT * cardinality * valuesNumber; 196 | 197 | attributes[ attributeName ] = { 198 | type: attributeType, 199 | cardinality: cardinality, 200 | values: values 201 | }; 202 | 203 | } 204 | 205 | pos = Math.ceil( pos / 4 ) * 4; 206 | 207 | indices = null; 208 | 209 | if ( indexedGeometry ) { 210 | 211 | indices = copyFromBuffer( 212 | buffer, 213 | indicesType === 1 ? Uint32Array : Uint16Array, 214 | pos, 215 | indicesNumber, 216 | bigEndian 217 | ); 218 | 219 | } 220 | 221 | return { 222 | version: version, 223 | attributes: attributes, 224 | indices: indices 225 | }; 226 | 227 | } 228 | 229 | // Define the public interface 230 | 231 | function PRWMLoader( manager ) { 232 | 233 | Loader.call( this, manager ); 234 | 235 | } 236 | 237 | PRWMLoader.prototype = Object.assign( Object.create( Loader.prototype ), { 238 | 239 | constructor: PRWMLoader, 240 | 241 | load: function ( url, onLoad, onProgress, onError ) { 242 | 243 | var scope = this; 244 | 245 | var loader = new FileLoader( scope.manager ); 246 | loader.setPath( scope.path ); 247 | loader.setResponseType( 'arraybuffer' ); 248 | loader.setRequestHeader( scope.requestHeader ); 249 | loader.setWithCredentials( scope.withCredentials ); 250 | 251 | url = url.replace( /\*/g, isBigEndianPlatform() ? 'be' : 'le' ); 252 | 253 | loader.load( url, function ( arrayBuffer ) { 254 | 255 | try { 256 | 257 | onLoad( scope.parse( arrayBuffer ) ); 258 | 259 | } catch ( e ) { 260 | 261 | if ( onError ) { 262 | 263 | onError( e ); 264 | 265 | } else { 266 | 267 | console.error( e ); 268 | 269 | } 270 | 271 | scope.manager.itemError( url ); 272 | 273 | } 274 | 275 | }, onProgress, onError ); 276 | 277 | }, 278 | 279 | parse: function ( arrayBuffer ) { 280 | 281 | var data = decodePrwm( arrayBuffer ), 282 | attributesKey = Object.keys( data.attributes ), 283 | bufferGeometry = new BufferGeometry(), 284 | attribute, 285 | i; 286 | 287 | for ( i = 0; i < attributesKey.length; i ++ ) { 288 | 289 | attribute = data.attributes[ attributesKey[ i ] ]; 290 | bufferGeometry.setAttribute( attributesKey[ i ], new BufferAttribute( attribute.values, attribute.cardinality, attribute.normalized ) ); 291 | 292 | } 293 | 294 | if ( data.indices !== null ) { 295 | 296 | bufferGeometry.setIndex( new BufferAttribute( data.indices, 1 ) ); 297 | 298 | } 299 | 300 | return bufferGeometry; 301 | 302 | } 303 | 304 | } ); 305 | 306 | PRWMLoader.isBigEndianPlatform = function () { 307 | 308 | return isBigEndianPlatform(); 309 | 310 | }; 311 | 312 | return PRWMLoader; 313 | 314 | } )(); 315 | 316 | export { PRWMLoader }; 317 | -------------------------------------------------------------------------------- /libs/three.js/loaders/PVRLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | CompressedTextureLoader, 3 | RGBA_PVRTC_2BPPV1_Format, 4 | RGBA_PVRTC_4BPPV1_Format, 5 | RGB_PVRTC_2BPPV1_Format, 6 | RGB_PVRTC_4BPPV1_Format 7 | } from '../../../build/three.module.js'; 8 | 9 | /* 10 | * PVR v2 (legacy) parser 11 | * TODO : Add Support for PVR v3 format 12 | * TODO : implement loadMipmaps option 13 | */ 14 | 15 | var PVRLoader = function ( manager ) { 16 | 17 | CompressedTextureLoader.call( this, manager ); 18 | 19 | }; 20 | 21 | PVRLoader.prototype = Object.assign( Object.create( CompressedTextureLoader.prototype ), { 22 | 23 | constructor: PVRLoader, 24 | 25 | parse: function ( buffer, loadMipmaps ) { 26 | 27 | var headerLengthInt = 13; 28 | var header = new Uint32Array( buffer, 0, headerLengthInt ); 29 | 30 | var pvrDatas = { 31 | buffer: buffer, 32 | header: header, 33 | loadMipmaps: loadMipmaps 34 | }; 35 | 36 | if ( header[ 0 ] === 0x03525650 ) { 37 | 38 | // PVR v3 39 | 40 | return PVRLoader._parseV3( pvrDatas ); 41 | 42 | } else if ( header[ 11 ] === 0x21525650 ) { 43 | 44 | // PVR v2 45 | 46 | return PVRLoader._parseV2( pvrDatas ); 47 | 48 | } else { 49 | 50 | console.error( 'THREE.PVRLoader: Unknown PVR format.' ); 51 | 52 | } 53 | 54 | } 55 | 56 | } ); 57 | 58 | PVRLoader._parseV3 = function ( pvrDatas ) { 59 | 60 | var header = pvrDatas.header; 61 | var bpp, format; 62 | 63 | 64 | var metaLen = header[ 12 ], 65 | pixelFormat = header[ 2 ], 66 | height = header[ 6 ], 67 | width = header[ 7 ], 68 | // numSurfs = header[ 9 ], 69 | numFaces = header[ 10 ], 70 | numMipmaps = header[ 11 ]; 71 | 72 | switch ( pixelFormat ) { 73 | 74 | case 0 : // PVRTC 2bpp RGB 75 | bpp = 2; 76 | format = RGB_PVRTC_2BPPV1_Format; 77 | break; 78 | 79 | case 1 : // PVRTC 2bpp RGBA 80 | bpp = 2; 81 | format = RGBA_PVRTC_2BPPV1_Format; 82 | break; 83 | 84 | case 2 : // PVRTC 4bpp RGB 85 | bpp = 4; 86 | format = RGB_PVRTC_4BPPV1_Format; 87 | break; 88 | 89 | case 3 : // PVRTC 4bpp RGBA 90 | bpp = 4; 91 | format = RGBA_PVRTC_4BPPV1_Format; 92 | break; 93 | 94 | default : 95 | console.error( 'THREE.PVRLoader: Unsupported PVR format:', pixelFormat ); 96 | 97 | } 98 | 99 | pvrDatas.dataPtr = 52 + metaLen; 100 | pvrDatas.bpp = bpp; 101 | pvrDatas.format = format; 102 | pvrDatas.width = width; 103 | pvrDatas.height = height; 104 | pvrDatas.numSurfaces = numFaces; 105 | pvrDatas.numMipmaps = numMipmaps; 106 | pvrDatas.isCubemap = ( numFaces === 6 ); 107 | 108 | return PVRLoader._extract( pvrDatas ); 109 | 110 | }; 111 | 112 | PVRLoader._parseV2 = function ( pvrDatas ) { 113 | 114 | var header = pvrDatas.header; 115 | 116 | var headerLength = header[ 0 ], 117 | height = header[ 1 ], 118 | width = header[ 2 ], 119 | numMipmaps = header[ 3 ], 120 | flags = header[ 4 ], 121 | // dataLength = header[ 5 ], 122 | // bpp = header[ 6 ], 123 | // bitmaskRed = header[ 7 ], 124 | // bitmaskGreen = header[ 8 ], 125 | // bitmaskBlue = header[ 9 ], 126 | bitmaskAlpha = header[ 10 ], 127 | // pvrTag = header[ 11 ], 128 | numSurfs = header[ 12 ]; 129 | 130 | 131 | var TYPE_MASK = 0xff; 132 | var PVRTC_2 = 24, 133 | PVRTC_4 = 25; 134 | 135 | var formatFlags = flags & TYPE_MASK; 136 | 137 | var bpp, format; 138 | var _hasAlpha = bitmaskAlpha > 0; 139 | 140 | if ( formatFlags === PVRTC_4 ) { 141 | 142 | format = _hasAlpha ? RGBA_PVRTC_4BPPV1_Format : RGB_PVRTC_4BPPV1_Format; 143 | bpp = 4; 144 | 145 | } else if ( formatFlags === PVRTC_2 ) { 146 | 147 | format = _hasAlpha ? RGBA_PVRTC_2BPPV1_Format : RGB_PVRTC_2BPPV1_Format; 148 | bpp = 2; 149 | 150 | } else { 151 | 152 | console.error( 'THREE.PVRLoader: Unknown PVR format:', formatFlags ); 153 | 154 | } 155 | 156 | pvrDatas.dataPtr = headerLength; 157 | pvrDatas.bpp = bpp; 158 | pvrDatas.format = format; 159 | pvrDatas.width = width; 160 | pvrDatas.height = height; 161 | pvrDatas.numSurfaces = numSurfs; 162 | pvrDatas.numMipmaps = numMipmaps + 1; 163 | 164 | // guess cubemap type seems tricky in v2 165 | // it juste a pvr containing 6 surface (no explicit cubemap type) 166 | pvrDatas.isCubemap = ( numSurfs === 6 ); 167 | 168 | return PVRLoader._extract( pvrDatas ); 169 | 170 | }; 171 | 172 | 173 | PVRLoader._extract = function ( pvrDatas ) { 174 | 175 | var pvr = { 176 | mipmaps: [], 177 | width: pvrDatas.width, 178 | height: pvrDatas.height, 179 | format: pvrDatas.format, 180 | mipmapCount: pvrDatas.numMipmaps, 181 | isCubemap: pvrDatas.isCubemap 182 | }; 183 | 184 | var buffer = pvrDatas.buffer; 185 | 186 | var dataOffset = pvrDatas.dataPtr, 187 | bpp = pvrDatas.bpp, 188 | numSurfs = pvrDatas.numSurfaces, 189 | dataSize = 0, 190 | blockSize = 0, 191 | blockWidth = 0, 192 | blockHeight = 0, 193 | widthBlocks = 0, 194 | heightBlocks = 0; 195 | 196 | if ( bpp === 2 ) { 197 | 198 | blockWidth = 8; 199 | blockHeight = 4; 200 | 201 | } else { 202 | 203 | blockWidth = 4; 204 | blockHeight = 4; 205 | 206 | } 207 | 208 | blockSize = ( blockWidth * blockHeight ) * bpp / 8; 209 | 210 | pvr.mipmaps.length = pvrDatas.numMipmaps * numSurfs; 211 | 212 | var mipLevel = 0; 213 | 214 | while ( mipLevel < pvrDatas.numMipmaps ) { 215 | 216 | var sWidth = pvrDatas.width >> mipLevel, 217 | sHeight = pvrDatas.height >> mipLevel; 218 | 219 | widthBlocks = sWidth / blockWidth; 220 | heightBlocks = sHeight / blockHeight; 221 | 222 | // Clamp to minimum number of blocks 223 | if ( widthBlocks < 2 ) widthBlocks = 2; 224 | if ( heightBlocks < 2 ) heightBlocks = 2; 225 | 226 | dataSize = widthBlocks * heightBlocks * blockSize; 227 | 228 | for ( var surfIndex = 0; surfIndex < numSurfs; surfIndex ++ ) { 229 | 230 | var byteArray = new Uint8Array( buffer, dataOffset, dataSize ); 231 | 232 | var mipmap = { 233 | data: byteArray, 234 | width: sWidth, 235 | height: sHeight 236 | }; 237 | 238 | pvr.mipmaps[ surfIndex * pvrDatas.numMipmaps + mipLevel ] = mipmap; 239 | 240 | dataOffset += dataSize; 241 | 242 | } 243 | 244 | mipLevel ++; 245 | 246 | } 247 | 248 | return pvr; 249 | 250 | }; 251 | 252 | export { PVRLoader }; 253 | -------------------------------------------------------------------------------- /libs/three.js/loaders/TTFLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | FileLoader, 3 | Loader 4 | } from '../../../build/three.module.js'; 5 | import { opentype } from '../libs/opentype.module.min.js'; 6 | 7 | /** 8 | * Requires opentype.js to be included in the project. 9 | * Loads TTF files and converts them into typeface JSON that can be used directly 10 | * to create THREE.Font objects. 11 | */ 12 | 13 | var TTFLoader = function ( manager ) { 14 | 15 | Loader.call( this, manager ); 16 | 17 | this.reversed = false; 18 | 19 | }; 20 | 21 | 22 | TTFLoader.prototype = Object.assign( Object.create( Loader.prototype ), { 23 | 24 | constructor: TTFLoader, 25 | 26 | load: function ( url, onLoad, onProgress, onError ) { 27 | 28 | var scope = this; 29 | 30 | var loader = new FileLoader( this.manager ); 31 | loader.setPath( this.path ); 32 | loader.setResponseType( 'arraybuffer' ); 33 | loader.setRequestHeader( this.requestHeader ); 34 | loader.setWithCredentials( this.withCredentials ); 35 | loader.load( url, function ( buffer ) { 36 | 37 | try { 38 | 39 | onLoad( scope.parse( buffer ) ); 40 | 41 | } catch ( e ) { 42 | 43 | if ( onError ) { 44 | 45 | onError( e ); 46 | 47 | } else { 48 | 49 | console.error( e ); 50 | 51 | } 52 | 53 | scope.manager.itemError( url ); 54 | 55 | } 56 | 57 | }, onProgress, onError ); 58 | 59 | }, 60 | 61 | parse: function ( arraybuffer ) { 62 | 63 | function convert( font, reversed ) { 64 | 65 | var round = Math.round; 66 | 67 | var glyphs = {}; 68 | var scale = ( 100000 ) / ( ( font.unitsPerEm || 2048 ) * 72 ); 69 | 70 | var glyphIndexMap = font.encoding.cmap.glyphIndexMap; 71 | var unicodes = Object.keys( glyphIndexMap ); 72 | 73 | for ( var i = 0; i < unicodes.length; i ++ ) { 74 | 75 | var unicode = unicodes[ i ]; 76 | var glyph = font.glyphs.glyphs[ glyphIndexMap[ unicode ] ]; 77 | 78 | if ( unicode !== undefined ) { 79 | 80 | var token = { 81 | ha: round( glyph.advanceWidth * scale ), 82 | x_min: round( glyph.xMin * scale ), 83 | x_max: round( glyph.xMax * scale ), 84 | o: '' 85 | }; 86 | 87 | if ( reversed ) { 88 | 89 | glyph.path.commands = reverseCommands( glyph.path.commands ); 90 | 91 | } 92 | 93 | glyph.path.commands.forEach( function ( command ) { 94 | 95 | if ( command.type.toLowerCase() === 'c' ) { 96 | 97 | command.type = 'b'; 98 | 99 | } 100 | 101 | token.o += command.type.toLowerCase() + ' '; 102 | 103 | if ( command.x !== undefined && command.y !== undefined ) { 104 | 105 | token.o += round( command.x * scale ) + ' ' + round( command.y * scale ) + ' '; 106 | 107 | } 108 | 109 | if ( command.x1 !== undefined && command.y1 !== undefined ) { 110 | 111 | token.o += round( command.x1 * scale ) + ' ' + round( command.y1 * scale ) + ' '; 112 | 113 | } 114 | 115 | if ( command.x2 !== undefined && command.y2 !== undefined ) { 116 | 117 | token.o += round( command.x2 * scale ) + ' ' + round( command.y2 * scale ) + ' '; 118 | 119 | } 120 | 121 | } ); 122 | 123 | glyphs[ String.fromCodePoint( glyph.unicode ) ] = token; 124 | 125 | } 126 | 127 | } 128 | 129 | return { 130 | glyphs: glyphs, 131 | familyName: font.getEnglishName( 'fullName' ), 132 | ascender: round( font.ascender * scale ), 133 | descender: round( font.descender * scale ), 134 | underlinePosition: font.tables.post.underlinePosition, 135 | underlineThickness: font.tables.post.underlineThickness, 136 | boundingBox: { 137 | xMin: font.tables.head.xMin, 138 | xMax: font.tables.head.xMax, 139 | yMin: font.tables.head.yMin, 140 | yMax: font.tables.head.yMax 141 | }, 142 | resolution: 1000, 143 | original_font_information: font.tables.name 144 | }; 145 | 146 | } 147 | 148 | function reverseCommands( commands ) { 149 | 150 | var paths = []; 151 | var path; 152 | 153 | commands.forEach( function ( c ) { 154 | 155 | if ( c.type.toLowerCase() === 'm' ) { 156 | 157 | path = [ c ]; 158 | paths.push( path ); 159 | 160 | } else if ( c.type.toLowerCase() !== 'z' ) { 161 | 162 | path.push( c ); 163 | 164 | } 165 | 166 | } ); 167 | 168 | var reversed = []; 169 | 170 | paths.forEach( function ( p ) { 171 | 172 | var result = { 173 | type: 'm', 174 | x: p[ p.length - 1 ].x, 175 | y: p[ p.length - 1 ].y 176 | }; 177 | 178 | reversed.push( result ); 179 | 180 | for ( var i = p.length - 1; i > 0; i -- ) { 181 | 182 | var command = p[ i ]; 183 | var result = { type: command.type }; 184 | 185 | if ( command.x2 !== undefined && command.y2 !== undefined ) { 186 | 187 | result.x1 = command.x2; 188 | result.y1 = command.y2; 189 | result.x2 = command.x1; 190 | result.y2 = command.y1; 191 | 192 | } else if ( command.x1 !== undefined && command.y1 !== undefined ) { 193 | 194 | result.x1 = command.x1; 195 | result.y1 = command.y1; 196 | 197 | } 198 | 199 | result.x = p[ i - 1 ].x; 200 | result.y = p[ i - 1 ].y; 201 | reversed.push( result ); 202 | 203 | } 204 | 205 | } ); 206 | 207 | return reversed; 208 | 209 | } 210 | 211 | if ( typeof opentype === 'undefined' ) { 212 | 213 | console.warn( 'THREE.TTFLoader: The loader requires opentype.js. Make sure it\'s included before using the loader.' ); 214 | return null; 215 | 216 | } 217 | 218 | return convert( opentype.parse( arraybuffer ), this.reversed ); // eslint-disable-line no-undef 219 | 220 | } 221 | 222 | } ); 223 | 224 | export { TTFLoader }; 225 | -------------------------------------------------------------------------------- /libs/three.js/loaders/VRMLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | Loader 3 | } from '../../../build/three.module.js'; 4 | import { GLTFLoader } from '../loaders/GLTFLoader.js'; 5 | 6 | // VRM Specification: https://dwango.github.io/vrm/vrm_spec/ 7 | // 8 | // VRM is based on glTF 2.0 and VRM extension is defined 9 | // in top-level json.extensions.VRM 10 | 11 | var VRMLoader = ( function () { 12 | 13 | function VRMLoader( manager ) { 14 | 15 | if ( GLTFLoader === undefined ) { 16 | 17 | throw new Error( 'THREE.VRMLoader: Import GLTFLoader.' ); 18 | 19 | } 20 | 21 | Loader.call( this, manager ); 22 | 23 | this.gltfLoader = new GLTFLoader( this.manager ); 24 | 25 | } 26 | 27 | VRMLoader.prototype = Object.assign( Object.create( Loader.prototype ), { 28 | 29 | constructor: VRMLoader, 30 | 31 | load: function ( url, onLoad, onProgress, onError ) { 32 | 33 | var scope = this; 34 | 35 | this.gltfLoader.load( url, function ( gltf ) { 36 | 37 | try { 38 | 39 | scope.parse( gltf, onLoad ); 40 | 41 | } catch ( e ) { 42 | 43 | if ( onError ) { 44 | 45 | onError( e ); 46 | 47 | } else { 48 | 49 | console.error( e ); 50 | 51 | } 52 | 53 | scope.manager.itemError( url ); 54 | 55 | } 56 | 57 | }, onProgress, onError ); 58 | 59 | }, 60 | 61 | setDRACOLoader: function ( dracoLoader ) { 62 | 63 | this.gltfLoader.setDRACOLoader( dracoLoader ); 64 | return this; 65 | 66 | }, 67 | 68 | parse: function ( gltf, onLoad ) { 69 | 70 | // var gltfParser = gltf.parser; 71 | // var gltfExtensions = gltf.userData.gltfExtensions || {}; 72 | // var vrmExtension = gltfExtensions.VRM || {}; 73 | 74 | // handle VRM Extension here 75 | 76 | onLoad( gltf ); 77 | 78 | } 79 | 80 | } ); 81 | 82 | return VRMLoader; 83 | 84 | } )(); 85 | 86 | export { VRMLoader }; 87 | -------------------------------------------------------------------------------- /libs/three.js/loaders/XYZLoader.js: -------------------------------------------------------------------------------- 1 | import { 2 | BufferGeometry, 3 | FileLoader, 4 | Float32BufferAttribute, 5 | Loader 6 | } from '../../../build/three.module.js'; 7 | 8 | class XYZLoader extends Loader { 9 | 10 | load( url, onLoad, onProgress, onError ) { 11 | 12 | const scope = this; 13 | 14 | const loader = new FileLoader( this.manager ); 15 | loader.setPath( this.path ); 16 | loader.setRequestHeader( this.requestHeader ); 17 | loader.setWithCredentials( this.withCredentials ); 18 | loader.load( url, function ( text ) { 19 | 20 | try { 21 | 22 | onLoad( scope.parse( text ) ); 23 | 24 | } catch ( e ) { 25 | 26 | if ( onError ) { 27 | 28 | onError( e ); 29 | 30 | } else { 31 | 32 | console.error( e ); 33 | 34 | } 35 | 36 | scope.manager.itemError( url ); 37 | 38 | } 39 | 40 | }, onProgress, onError ); 41 | 42 | } 43 | 44 | parse( text ) { 45 | 46 | const lines = text.split( '\n' ); 47 | 48 | const vertices = []; 49 | const colors = []; 50 | 51 | for ( let line of lines ) { 52 | 53 | line = line.trim(); 54 | 55 | if ( line.charAt( 0 ) === '#' ) continue; // skip comments 56 | 57 | const lineValues = line.split( /\s+/ ); 58 | 59 | if ( lineValues.length === 3 ) { 60 | 61 | // XYZ 62 | 63 | vertices.push( parseFloat( lineValues[ 0 ] ) ); 64 | vertices.push( parseFloat( lineValues[ 1 ] ) ); 65 | vertices.push( parseFloat( lineValues[ 2 ] ) ); 66 | 67 | } 68 | 69 | if ( lineValues.length === 6 ) { 70 | 71 | // XYZRGB 72 | 73 | vertices.push( parseFloat( lineValues[ 0 ] ) ); 74 | vertices.push( parseFloat( lineValues[ 1 ] ) ); 75 | vertices.push( parseFloat( lineValues[ 2 ] ) ); 76 | 77 | colors.push( parseFloat( lineValues[ 3 ] ) / 255 ); 78 | colors.push( parseFloat( lineValues[ 4 ] ) / 255 ); 79 | colors.push( parseFloat( lineValues[ 5 ] ) / 255 ); 80 | 81 | } 82 | 83 | } 84 | 85 | const geometry = new BufferGeometry(); 86 | geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); 87 | 88 | if ( colors.length > 0 ) { 89 | 90 | geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); 91 | 92 | } 93 | 94 | return geometry; 95 | 96 | } 97 | 98 | } 99 | 100 | export { XYZLoader }; 101 | -------------------------------------------------------------------------------- /libs/three.js/loaders/obj2/bridge/MtlObjBridge.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Development repository: https://github.com/kaisalmen/WWOBJLoader 3 | */ 4 | 5 | import { MTLLoader } from '../../../../jsm/loaders/MTLLoader.js'; 6 | 7 | 8 | const MtlObjBridge = { 9 | 10 | /** 11 | * 12 | * @param processResult 13 | * @param assetLoader 14 | */ 15 | link: function ( processResult, assetLoader ) { 16 | 17 | if ( typeof assetLoader.addMaterials === 'function' ) { 18 | 19 | assetLoader.addMaterials( this.addMaterialsFromMtlLoader( processResult ), true ); 20 | 21 | } 22 | 23 | }, 24 | 25 | /** 26 | * Returns the array instance of {@link MTLLoader.MaterialCreator}. 27 | * 28 | * @param Instance of {@link MTLLoader.MaterialCreator} 29 | */ 30 | addMaterialsFromMtlLoader: function ( materialCreator ) { 31 | 32 | let newMaterials = {}; 33 | 34 | if ( materialCreator instanceof MTLLoader.MaterialCreator ) { 35 | 36 | materialCreator.preload(); 37 | newMaterials = materialCreator.materials; 38 | 39 | } 40 | 41 | return newMaterials; 42 | 43 | } 44 | }; 45 | 46 | export { MtlObjBridge }; 47 | -------------------------------------------------------------------------------- /libs/three.js/loaders/obj2/shared/MaterialHandler.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Development repository: https://github.com/kaisalmen/WWOBJLoader 3 | */ 4 | 5 | import { 6 | LineBasicMaterial, 7 | MaterialLoader, 8 | MeshStandardMaterial, 9 | PointsMaterial 10 | } from '../../../../../build/three.module.js'; 11 | 12 | 13 | const MaterialHandler = function () { 14 | 15 | this.logging = { 16 | enabled: false, 17 | debug: false 18 | }; 19 | 20 | this.callbacks = { 21 | onLoadMaterials: null 22 | }; 23 | this.materials = {}; 24 | 25 | }; 26 | 27 | MaterialHandler.prototype = { 28 | 29 | constructor: MaterialHandler, 30 | 31 | /** 32 | * Enable or disable logging in general (except warn and error), plus enable or disable debug logging. 33 | * 34 | * @param {boolean} enabled True or false. 35 | * @param {boolean} debug True or false. 36 | */ 37 | setLogging: function ( enabled, debug ) { 38 | 39 | this.logging.enabled = enabled === true; 40 | this.logging.debug = debug === true; 41 | 42 | }, 43 | 44 | _setCallbacks: function ( onLoadMaterials ) { 45 | 46 | if ( onLoadMaterials !== undefined && onLoadMaterials !== null && onLoadMaterials instanceof Function ) { 47 | 48 | this.callbacks.onLoadMaterials = onLoadMaterials; 49 | 50 | } 51 | 52 | }, 53 | 54 | /** 55 | * Creates default materials and adds them to the materials object. 56 | * 57 | * @param overrideExisting boolean Override existing material 58 | */ 59 | createDefaultMaterials: function ( overrideExisting ) { 60 | 61 | const defaultMaterial = new MeshStandardMaterial( { color: 0xDCF1FF } ); 62 | defaultMaterial.name = 'defaultMaterial'; 63 | 64 | const defaultVertexColorMaterial = new MeshStandardMaterial( { color: 0xDCF1FF } ); 65 | defaultVertexColorMaterial.name = 'defaultVertexColorMaterial'; 66 | defaultVertexColorMaterial.vertexColors = true; 67 | 68 | const defaultLineMaterial = new LineBasicMaterial(); 69 | defaultLineMaterial.name = 'defaultLineMaterial'; 70 | 71 | const defaultPointMaterial = new PointsMaterial( { size: 0.1 } ); 72 | defaultPointMaterial.name = 'defaultPointMaterial'; 73 | 74 | const runtimeMaterials = {}; 75 | runtimeMaterials[ defaultMaterial.name ] = defaultMaterial; 76 | runtimeMaterials[ defaultVertexColorMaterial.name ] = defaultVertexColorMaterial; 77 | runtimeMaterials[ defaultLineMaterial.name ] = defaultLineMaterial; 78 | runtimeMaterials[ defaultPointMaterial.name ] = defaultPointMaterial; 79 | 80 | this.addMaterials( runtimeMaterials, overrideExisting ); 81 | 82 | }, 83 | 84 | /** 85 | * Updates the materials with contained material objects (sync) or from alteration instructions (async). 86 | * 87 | * @param {Object} materialPayload Material update instructions 88 | * @returns {Object} Map of {@link Material} 89 | */ 90 | addPayloadMaterials: function ( materialPayload ) { 91 | 92 | let material, materialName; 93 | const materialCloneInstructions = materialPayload.materials.materialCloneInstructions; 94 | let newMaterials = {}; 95 | 96 | if ( materialCloneInstructions !== undefined && materialCloneInstructions !== null ) { 97 | 98 | let materialNameOrg = materialCloneInstructions.materialNameOrg; 99 | materialNameOrg = ( materialNameOrg !== undefined && materialNameOrg !== null ) ? materialNameOrg : ''; 100 | const materialOrg = this.materials[ materialNameOrg ]; 101 | if ( materialOrg ) { 102 | 103 | material = materialOrg.clone(); 104 | 105 | materialName = materialCloneInstructions.materialName; 106 | material.name = materialName; 107 | 108 | Object.assign( material, materialCloneInstructions.materialProperties ); 109 | 110 | this.materials[ materialName ] = material; 111 | newMaterials[ materialName ] = material; 112 | 113 | } else { 114 | 115 | if ( this.logging.enabled ) { 116 | 117 | console.info( 'Requested material "' + materialNameOrg + '" is not available!' ); 118 | 119 | } 120 | 121 | } 122 | 123 | } 124 | 125 | let materials = materialPayload.materials.serializedMaterials; 126 | 127 | if ( materials !== undefined && materials !== null && Object.keys( materials ).length > 0 ) { 128 | 129 | const loader = new MaterialLoader(); 130 | let materialJson; 131 | 132 | for ( materialName in materials ) { 133 | 134 | materialJson = materials[ materialName ]; 135 | 136 | if ( materialJson !== undefined && materialJson !== null ) { 137 | 138 | material = loader.parse( materialJson ); 139 | 140 | if ( this.logging.enabled ) { 141 | 142 | console.info( 'De-serialized material with name "' + materialName + '" will be added.' ); 143 | 144 | } 145 | 146 | this.materials[ materialName ] = material; 147 | newMaterials[ materialName ] = material; 148 | 149 | } 150 | 151 | } 152 | 153 | } 154 | 155 | materials = materialPayload.materials.runtimeMaterials; 156 | newMaterials = this.addMaterials( materials, true, newMaterials ); 157 | 158 | return newMaterials; 159 | 160 | }, 161 | 162 | /** 163 | * Set materials loaded by any supplier of an Array of {@link Material}. 164 | * 165 | * @param materials Object with named {@link Material} 166 | * @param overrideExisting boolean Override existing material 167 | * @param newMaterials [Object] with named {@link Material} 168 | */ 169 | addMaterials: function ( materials, overrideExisting, newMaterials ) { 170 | 171 | if ( newMaterials === undefined || newMaterials === null ) { 172 | 173 | newMaterials = {}; 174 | 175 | } 176 | 177 | if ( materials !== undefined && materials !== null && Object.keys( materials ).length > 0 ) { 178 | 179 | let material; 180 | let existingMaterial; 181 | let add; 182 | 183 | for ( const materialName in materials ) { 184 | 185 | material = materials[ materialName ]; 186 | add = overrideExisting === true; 187 | 188 | if ( ! add ) { 189 | 190 | existingMaterial = this.materials[ materialName ]; 191 | add = ( existingMaterial === null || existingMaterial === undefined ); 192 | 193 | } 194 | 195 | if ( add ) { 196 | 197 | this.materials[ materialName ] = material; 198 | newMaterials[ materialName ] = material; 199 | 200 | } 201 | 202 | if ( this.logging.enabled && this.logging.debug ) { 203 | 204 | console.info( 'Material with name "' + materialName + '" was added.' ); 205 | 206 | } 207 | 208 | } 209 | 210 | } 211 | 212 | if ( this.callbacks.onLoadMaterials ) { 213 | 214 | this.callbacks.onLoadMaterials( newMaterials ); 215 | 216 | } 217 | 218 | return newMaterials; 219 | 220 | }, 221 | 222 | /** 223 | * Returns the mapping object of material name and corresponding material. 224 | * 225 | * @returns {Object} Map of {@link Material} 226 | */ 227 | getMaterials: function () { 228 | 229 | return this.materials; 230 | 231 | }, 232 | 233 | /** 234 | * 235 | * @param {String} materialName 236 | * @returns {Material} 237 | */ 238 | getMaterial: function ( materialName ) { 239 | 240 | return this.materials[ materialName ]; 241 | 242 | }, 243 | 244 | /** 245 | * Returns the mapping object of material name and corresponding jsonified material. 246 | * 247 | * @returns {Object} Map of Materials in JSON representation 248 | */ 249 | getMaterialsJSON: function () { 250 | 251 | const materialsJSON = {}; 252 | let material; 253 | 254 | for ( const materialName in this.materials ) { 255 | 256 | material = this.materials[ materialName ]; 257 | materialsJSON[ materialName ] = material.toJSON(); 258 | 259 | } 260 | 261 | return materialsJSON; 262 | 263 | }, 264 | 265 | /** 266 | * Removes all materials 267 | */ 268 | clearMaterials: function () { 269 | 270 | this.materials = {}; 271 | 272 | } 273 | 274 | }; 275 | 276 | export { MaterialHandler }; 277 | -------------------------------------------------------------------------------- /libs/three.js/loaders/obj2/utils/CodeSerializer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Development repository: https://github.com/kaisalmen/WWOBJLoader 3 | */ 4 | 5 | const CodeSerializer = { 6 | 7 | /** 8 | * Serialize an object with specific prototype definition. 9 | * 10 | * @param {Object} targetPrototype The object that should be serialized 11 | * @param {Object} targetPrototypeInstance An instance of the oriobject that should be serialized 12 | * @param {String} [basePrototypeName] Name of the prototype 13 | * @param {Object} [overrideFunctions} Array of {@Link CodeSerializationInstruction} allows to replace or remove function with provided content 14 | * 15 | * @returns {String} 16 | */ 17 | serializeClass: function ( targetPrototype, targetPrototypeInstance, basePrototypeName, overrideFunctions ) { 18 | 19 | let objectPart, constructorString, i, funcInstructions, funcTemp; 20 | const fullObjectName = targetPrototypeInstance.constructor.name; 21 | const prototypeFunctions = []; 22 | const objectProperties = []; 23 | const objectFunctions = []; 24 | const isExtended = ( basePrototypeName !== null && basePrototypeName !== undefined ); 25 | 26 | if ( ! Array.isArray( overrideFunctions ) ) overrideFunctions = []; 27 | 28 | for ( const name in targetPrototype.prototype ) { 29 | 30 | objectPart = targetPrototype.prototype[ name ]; 31 | funcInstructions = new CodeSerializationInstruction( name, fullObjectName + '.prototype.' + name ); 32 | funcInstructions.setCode( objectPart.toString() ); 33 | 34 | if ( name === 'constructor' ) { 35 | 36 | if ( ! funcInstructions.isRemoveCode() ) { 37 | 38 | constructorString = fullObjectName + ' = ' + funcInstructions.getCode() + ';\n\n'; 39 | 40 | } 41 | 42 | } else if ( typeof objectPart === 'function' ) { 43 | 44 | funcTemp = overrideFunctions[ name ]; 45 | 46 | if ( funcTemp instanceof CodeSerializationInstruction && funcTemp.getName() === funcInstructions.getName() ) { 47 | 48 | funcInstructions = funcTemp; 49 | 50 | } 51 | 52 | if ( ! funcInstructions.isRemoveCode() ) { 53 | 54 | if ( isExtended ) { 55 | 56 | prototypeFunctions.push( funcInstructions.getFullName() + ' = ' + funcInstructions.getCode() + ';\n\n' ); 57 | 58 | } else { 59 | 60 | prototypeFunctions.push( '\t' + funcInstructions.getName() + ': ' + funcInstructions.getCode() + ',\n\n' ); 61 | 62 | } 63 | 64 | } 65 | 66 | } 67 | 68 | } 69 | 70 | for ( const name in targetPrototype ) { 71 | 72 | objectPart = targetPrototype[ name ]; 73 | funcInstructions = new CodeSerializationInstruction( name, fullObjectName + '.' + name ); 74 | 75 | if ( typeof objectPart === 'function' ) { 76 | 77 | funcTemp = overrideFunctions[ name ]; 78 | if ( funcTemp instanceof CodeSerializationInstruction && funcTemp.getName() === funcInstructions.getName() ) { 79 | 80 | funcInstructions = funcTemp; 81 | 82 | } else { 83 | 84 | funcInstructions.setCode( objectPart.toString() ); 85 | 86 | } 87 | 88 | if ( ! funcInstructions.isRemoveCode() ) { 89 | 90 | objectFunctions.push( funcInstructions.getFullName() + ' = ' + funcInstructions.getCode() + ';\n\n' ); 91 | 92 | } 93 | 94 | } else { 95 | 96 | if ( typeof ( objectPart ) === 'string' || objectPart instanceof String ) { 97 | 98 | funcInstructions.setCode( '\"' + objectPart.toString() + '\"' ); 99 | 100 | } else if ( typeof objectPart === 'object' ) { 101 | 102 | console.log( 'Omitting object "' + funcInstructions.getName() + '" and replace it with empty object.' ); 103 | funcInstructions.setCode( '{}' ); 104 | 105 | } else { 106 | 107 | funcInstructions.setCode( objectPart ); 108 | 109 | } 110 | 111 | if ( ! funcInstructions.isRemoveCode() ) { 112 | 113 | objectProperties.push( funcInstructions.getFullName() + ' = ' + funcInstructions.getCode() + ';\n' ); 114 | 115 | } 116 | 117 | } 118 | 119 | } 120 | 121 | let objectString = constructorString + '\n\n'; 122 | 123 | if ( isExtended ) { 124 | 125 | objectString += fullObjectName + '.prototype = Object.create( ' + basePrototypeName + '.prototype );\n'; 126 | 127 | } 128 | 129 | objectString += fullObjectName + '.prototype.constructor = ' + fullObjectName + ';\n'; 130 | objectString += '\n\n'; 131 | 132 | for ( i = 0; i < objectProperties.length; i ++ ) { 133 | 134 | objectString += objectProperties[ i ]; 135 | 136 | } 137 | 138 | objectString += '\n\n'; 139 | 140 | for ( i = 0; i < objectFunctions.length; i ++ ) { 141 | 142 | objectString += objectFunctions[ i ]; 143 | 144 | } 145 | 146 | objectString += '\n\n'; 147 | 148 | if ( isExtended ) { 149 | 150 | for ( i = 0; i < prototypeFunctions.length; i ++ ) { 151 | 152 | objectString += prototypeFunctions[ i ]; 153 | 154 | } 155 | 156 | } else { 157 | 158 | objectString += fullObjectName + '.prototype = {\n\n'; 159 | for ( i = 0; i < prototypeFunctions.length; i ++ ) { 160 | 161 | objectString += prototypeFunctions[ i ]; 162 | 163 | } 164 | 165 | objectString += '\n};'; 166 | 167 | } 168 | 169 | objectString += '\n\n'; 170 | 171 | return objectString; 172 | 173 | }, 174 | }; 175 | 176 | /** 177 | * Allows to define instructions to override or remove 178 | * @param {String} name Usually the name of a function 179 | * @param {String} fullName The name plus full object description 180 | * @constructor 181 | */ 182 | const CodeSerializationInstruction = function ( name, fullName ) { 183 | 184 | this.name = name; 185 | this.fullName = fullName; 186 | this.code = null; 187 | this.removeCode = false; 188 | 189 | }; 190 | 191 | CodeSerializationInstruction.prototype = { 192 | 193 | constructor: CodeSerializationInstruction, 194 | 195 | /** 196 | * Returns the name of the function 197 | * @return {String} 198 | */ 199 | getName: function () { 200 | 201 | return this.name; 202 | 203 | }, 204 | 205 | /** 206 | * Returns the full name of the function 207 | * @return {String} 208 | */ 209 | getFullName: function () { 210 | 211 | return this.fullName; 212 | 213 | }, 214 | 215 | /** 216 | * Set the string containing the serialized function 217 | * @param {String} code 218 | * @return {CodeSerializationInstruction} 219 | */ 220 | setCode: function ( code ) { 221 | 222 | this.code = code; 223 | return this; 224 | 225 | }, 226 | 227 | /** 228 | * Returns the serialized function code 229 | * @return {String} 230 | */ 231 | getCode: function () { 232 | 233 | return this.code; 234 | 235 | }, 236 | 237 | /** 238 | * Set if function should be removed 239 | * @param {boolean} removeCode 240 | * @return {CodeSerializationInstruction} 241 | */ 242 | setRemoveCode: function ( removeCode ) { 243 | 244 | this.removeCode = removeCode; 245 | return this; 246 | 247 | }, 248 | 249 | /** 250 | * If function should be completely removed 251 | * @return {boolean} 252 | */ 253 | isRemoveCode: function () { 254 | 255 | return this.removeCode; 256 | 257 | } 258 | 259 | }; 260 | 261 | export { 262 | CodeSerializer, 263 | CodeSerializationInstruction 264 | }; 265 | -------------------------------------------------------------------------------- /libs/three.js/loaders/obj2/worker/parallel/OBJLoader2JsmWorker.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Development repository: https://github.com/kaisalmen/WWOBJLoader 3 | */ 4 | 5 | import { OBJLoader2Parser } from '../../OBJLoader2Parser.js'; 6 | 7 | import { 8 | WorkerRunner, 9 | DefaultWorkerPayloadHandler 10 | } from './WorkerRunner.js'; 11 | 12 | new WorkerRunner( new DefaultWorkerPayloadHandler( new OBJLoader2Parser() ) ); 13 | -------------------------------------------------------------------------------- /libs/three.js/loaders/obj2/worker/parallel/WorkerRunner.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Development repository: https://github.com/kaisalmen/WWOBJLoader 3 | */ 4 | 5 | const ObjectManipulator = function () { 6 | }; 7 | 8 | ObjectManipulator.prototype = { 9 | 10 | constructor: ObjectManipulator, 11 | 12 | /** 13 | * Applies values from parameter object via set functions or via direct assignment. 14 | * 15 | * @param {Object} objToAlter The objToAlter instance 16 | * @param {Object} params The parameter object 17 | * @param {boolean} forceCreation Force the creation of a property 18 | */ 19 | applyProperties: function ( objToAlter, params, forceCreation ) { 20 | 21 | // fast-fail 22 | if ( objToAlter === undefined || objToAlter === null || params === undefined || params === null ) return; 23 | 24 | let property, funcName, values; 25 | for ( property in params ) { 26 | 27 | funcName = 'set' + property.substring( 0, 1 ).toLocaleUpperCase() + property.substring( 1 ); 28 | values = params[ property ]; 29 | 30 | if ( typeof objToAlter[ funcName ] === 'function' ) { 31 | 32 | objToAlter[ funcName ]( values ); 33 | 34 | } else if ( objToAlter.hasOwnProperty( property ) || forceCreation ) { 35 | 36 | objToAlter[ property ] = values; 37 | 38 | } 39 | 40 | } 41 | 42 | } 43 | }; 44 | 45 | const DefaultWorkerPayloadHandler = function ( parser ) { 46 | 47 | this.parser = parser; 48 | this.logging = { 49 | enabled: false, 50 | debug: false 51 | }; 52 | 53 | }; 54 | 55 | DefaultWorkerPayloadHandler.prototype = { 56 | 57 | constructor: DefaultWorkerPayloadHandler, 58 | 59 | handlePayload: function ( payload ) { 60 | 61 | if ( payload.logging ) { 62 | 63 | this.logging.enabled = payload.logging.enabled === true; 64 | this.logging.debug = payload.logging.debug === true; 65 | 66 | } 67 | 68 | if ( payload.cmd === 'parse' ) { 69 | 70 | const scope = this; 71 | const callbacks = { 72 | callbackOnAssetAvailable: function ( payload ) { 73 | 74 | self.postMessage( payload ); 75 | 76 | }, 77 | callbackOnProgress: function ( text ) { 78 | 79 | if ( scope.logging.enabled && scope.logging.debug ) console.debug( 'WorkerRunner: progress: ' + text ); 80 | 81 | } 82 | }; 83 | 84 | const parser = this.parser; 85 | if ( typeof parser[ 'setLogging' ] === 'function' ) { 86 | 87 | parser.setLogging( this.logging.enabled, this.logging.debug ); 88 | 89 | } 90 | 91 | const objectManipulator = new ObjectManipulator(); 92 | objectManipulator.applyProperties( parser, payload.params, false ); 93 | objectManipulator.applyProperties( parser, callbacks, false ); 94 | 95 | const arraybuffer = payload.data.input; 96 | let executeFunctionName = 'execute'; 97 | if ( typeof parser.getParseFunctionName === 'function' ) executeFunctionName = parser.getParseFunctionName(); 98 | if ( payload.usesMeshDisassembler ) { 99 | 100 | // TODO: Allow to plug and use generic MeshDisassembler 101 | 102 | } else { 103 | 104 | parser[ executeFunctionName ]( arraybuffer, payload.data.options ); 105 | 106 | } 107 | 108 | if ( this.logging.enabled ) console.log( 'WorkerRunner: Run complete!' ); 109 | 110 | self.postMessage( { 111 | cmd: 'completeOverall', 112 | msg: 'WorkerRunner completed run.' 113 | } ); 114 | 115 | } else { 116 | 117 | console.error( 'WorkerRunner: Received unknown command: ' + payload.cmd ); 118 | 119 | } 120 | 121 | } 122 | }; 123 | 124 | 125 | /** 126 | * Default implementation of the WorkerRunner responsible for creation and configuration of the parser within the worker. 127 | * @constructor 128 | */ 129 | const WorkerRunner = function ( payloadHandler ) { 130 | 131 | this.payloadHandler = payloadHandler; 132 | 133 | const scope = this; 134 | const scopedRunner = function ( event ) { 135 | 136 | scope.processMessage( event.data ); 137 | 138 | }; 139 | 140 | self.addEventListener( 'message', scopedRunner, false ); 141 | 142 | }; 143 | 144 | WorkerRunner.prototype = { 145 | 146 | constructor: WorkerRunner, 147 | 148 | /** 149 | * Configures the Parser implementation according the supplied configuration object. 150 | * 151 | * @param {Object} payload Raw mesh description (buffers, params, materials) used to build one to many meshes. 152 | */ 153 | processMessage: function ( payload ) { 154 | 155 | this.payloadHandler.handlePayload( payload ); 156 | 157 | } 158 | 159 | }; 160 | 161 | export { 162 | WorkerRunner, 163 | DefaultWorkerPayloadHandler, 164 | ObjectManipulator 165 | }; 166 | -------------------------------------------------------------------------------- /libs/three.js/webxr/ARButton.js: -------------------------------------------------------------------------------- 1 | class ARButton { 2 | 3 | static createButton( renderer, sessionInit = {} ) { 4 | 5 | const button = document.createElement( 'button' ); 6 | 7 | function showStartAR( /*device*/ ) { 8 | 9 | if ( sessionInit.domOverlay === undefined ) { 10 | 11 | var overlay = document.createElement( 'div' ); 12 | overlay.style.display = 'none'; 13 | document.body.appendChild( overlay ); 14 | 15 | var svg = document.createElementNS( 'http://www.w3.org/2000/svg', 'svg' ); 16 | svg.setAttribute( 'width', 38 ); 17 | svg.setAttribute( 'height', 38 ); 18 | svg.style.position = 'absolute'; 19 | svg.style.right = '20px'; 20 | svg.style.top = '20px'; 21 | svg.addEventListener( 'click', function () { 22 | 23 | currentSession.end(); 24 | 25 | } ); 26 | overlay.appendChild( svg ); 27 | 28 | var path = document.createElementNS( 'http://www.w3.org/2000/svg', 'path' ); 29 | path.setAttribute( 'd', 'M 12,12 L 28,28 M 28,12 12,28' ); 30 | path.setAttribute( 'stroke', '#fff' ); 31 | path.setAttribute( 'stroke-width', 2 ); 32 | svg.appendChild( path ); 33 | 34 | sessionInit.optionalFeatures = [ 'dom-overlay' ]; 35 | sessionInit.domOverlay = { root: overlay }; 36 | 37 | } 38 | 39 | // 40 | 41 | let currentSession = null; 42 | 43 | function onSessionStarted( session ) { 44 | 45 | session.addEventListener( 'end', onSessionEnded ); 46 | 47 | renderer.xr.setReferenceSpaceType( 'local' ); 48 | renderer.xr.setSession( session ); 49 | 50 | button.textContent = 'STOP AR'; 51 | sessionInit.domOverlay.root.style.display = ''; 52 | 53 | currentSession = session; 54 | 55 | } 56 | 57 | function onSessionEnded( /*event*/ ) { 58 | 59 | currentSession.removeEventListener( 'end', onSessionEnded ); 60 | 61 | button.textContent = 'START AR'; 62 | sessionInit.domOverlay.root.style.display = 'none'; 63 | 64 | currentSession = null; 65 | 66 | } 67 | 68 | // 69 | 70 | button.style.display = ''; 71 | 72 | button.style.cursor = 'pointer'; 73 | button.style.left = 'calc(50% - 50px)'; 74 | button.style.width = '100px'; 75 | 76 | button.textContent = 'START AR'; 77 | 78 | button.onmouseenter = function () { 79 | 80 | button.style.opacity = '1.0'; 81 | 82 | }; 83 | 84 | button.onmouseleave = function () { 85 | 86 | button.style.opacity = '0.5'; 87 | 88 | }; 89 | 90 | button.onclick = function () { 91 | 92 | if ( currentSession === null ) { 93 | 94 | navigator.xr.requestSession( 'immersive-ar', sessionInit ).then( onSessionStarted ); 95 | 96 | } else { 97 | 98 | currentSession.end(); 99 | 100 | } 101 | 102 | }; 103 | 104 | } 105 | 106 | function disableButton() { 107 | 108 | button.style.display = ''; 109 | 110 | button.style.cursor = 'auto'; 111 | button.style.left = 'calc(50% - 75px)'; 112 | button.style.width = '150px'; 113 | 114 | button.onmouseenter = null; 115 | button.onmouseleave = null; 116 | 117 | button.onclick = null; 118 | 119 | } 120 | 121 | function showARNotSupported() { 122 | 123 | disableButton(); 124 | 125 | button.textContent = 'AR NOT SUPPORTED'; 126 | 127 | } 128 | 129 | function stylizeElement( element ) { 130 | 131 | element.style.position = 'absolute'; 132 | element.style.bottom = '20px'; 133 | element.style.padding = '12px 6px'; 134 | element.style.border = '1px solid #fff'; 135 | element.style.borderRadius = '4px'; 136 | element.style.background = 'rgba(0,0,0,0.1)'; 137 | element.style.color = '#fff'; 138 | element.style.font = 'normal 13px sans-serif'; 139 | element.style.textAlign = 'center'; 140 | element.style.opacity = '0.5'; 141 | element.style.outline = 'none'; 142 | element.style.zIndex = '999'; 143 | 144 | } 145 | 146 | if ( 'xr' in navigator ) { 147 | 148 | button.id = 'ARButton'; 149 | button.style.display = 'none'; 150 | 151 | stylizeElement( button ); 152 | 153 | navigator.xr.isSessionSupported( 'immersive-ar' ).then( function ( supported ) { 154 | 155 | supported ? showStartAR() : showARNotSupported(); 156 | 157 | } ).catch( showARNotSupported ); 158 | 159 | return button; 160 | 161 | } else { 162 | 163 | const message = document.createElement( 'a' ); 164 | 165 | if ( window.isSecureContext === false ) { 166 | 167 | message.href = document.location.href.replace( /^http:/, 'https:' ); 168 | message.innerHTML = 'WEBXR NEEDS HTTPS'; // TODO Improve message 169 | 170 | } else { 171 | 172 | message.href = 'https://immersiveweb.dev/'; 173 | message.innerHTML = 'WEBXR NOT AVAILABLE'; 174 | 175 | } 176 | 177 | message.style.left = 'calc(50% - 90px)'; 178 | message.style.width = '180px'; 179 | message.style.textDecoration = 'none'; 180 | 181 | stylizeElement( message ); 182 | 183 | return message; 184 | 185 | } 186 | 187 | } 188 | 189 | } 190 | 191 | export { ARButton }; 192 | -------------------------------------------------------------------------------- /libs/three.js/webxr/VRButton.js: -------------------------------------------------------------------------------- 1 | class VRButton { 2 | 3 | static createButton( renderer, options ) { 4 | 5 | if ( options ) { 6 | 7 | console.error( 'THREE.VRButton: The "options" parameter has been removed. Please set the reference space type via renderer.xr.setReferenceSpaceType() instead.' ); 8 | 9 | } 10 | 11 | const button = document.createElement( 'button' ); 12 | 13 | function showEnterVR( /*device*/ ) { 14 | 15 | let currentSession = null; 16 | 17 | function onSessionStarted( session ) { 18 | 19 | session.addEventListener( 'end', onSessionEnded ); 20 | 21 | renderer.xr.setSession( session ); 22 | button.textContent = 'EXIT VR'; 23 | 24 | currentSession = session; 25 | 26 | } 27 | 28 | function onSessionEnded( /*event*/ ) { 29 | 30 | currentSession.removeEventListener( 'end', onSessionEnded ); 31 | 32 | button.textContent = 'ENTER VR'; 33 | 34 | currentSession = null; 35 | 36 | } 37 | 38 | // 39 | 40 | button.style.display = ''; 41 | 42 | button.style.cursor = 'pointer'; 43 | button.style.left = 'calc(50% - 50px)'; 44 | button.style.width = '100px'; 45 | 46 | button.textContent = 'ENTER VR'; 47 | 48 | button.onmouseenter = function () { 49 | 50 | button.style.opacity = '1.0'; 51 | 52 | }; 53 | 54 | button.onmouseleave = function () { 55 | 56 | button.style.opacity = '0.5'; 57 | 58 | }; 59 | 60 | button.onclick = function () { 61 | 62 | if ( currentSession === null ) { 63 | 64 | // WebXR's requestReferenceSpace only works if the corresponding feature 65 | // was requested at session creation time. For simplicity, just ask for 66 | // the interesting ones as optional features, but be aware that the 67 | // requestReferenceSpace call will fail if it turns out to be unavailable. 68 | // ('local' is always available for immersive sessions and doesn't need to 69 | // be requested separately.) 70 | 71 | const sessionInit = { optionalFeatures: [ 'local-floor', 'bounded-floor', 'hand-tracking' ] }; 72 | navigator.xr.requestSession( 'immersive-vr', sessionInit ).then( onSessionStarted ); 73 | 74 | } else { 75 | 76 | currentSession.end(); 77 | 78 | } 79 | 80 | }; 81 | 82 | } 83 | 84 | function disableButton() { 85 | 86 | button.style.display = ''; 87 | 88 | button.style.cursor = 'auto'; 89 | button.style.left = 'calc(50% - 75px)'; 90 | button.style.width = '150px'; 91 | 92 | button.onmouseenter = null; 93 | button.onmouseleave = null; 94 | 95 | button.onclick = null; 96 | 97 | } 98 | 99 | function showWebXRNotFound() { 100 | 101 | disableButton(); 102 | 103 | button.textContent = 'VR NOT SUPPORTED'; 104 | 105 | } 106 | 107 | function stylizeElement( element ) { 108 | 109 | element.style.position = 'absolute'; 110 | element.style.bottom = '20px'; 111 | element.style.padding = '12px 6px'; 112 | element.style.border = '1px solid #fff'; 113 | element.style.borderRadius = '4px'; 114 | element.style.background = 'rgba(0,0,0,0.1)'; 115 | element.style.color = '#fff'; 116 | element.style.font = 'normal 13px sans-serif'; 117 | element.style.textAlign = 'center'; 118 | element.style.opacity = '0.5'; 119 | element.style.outline = 'none'; 120 | element.style.zIndex = '999'; 121 | 122 | } 123 | 124 | if ( 'xr' in navigator ) { 125 | 126 | button.id = 'VRButton'; 127 | button.style.display = 'none'; 128 | 129 | stylizeElement( button ); 130 | 131 | navigator.xr.isSessionSupported( 'immersive-vr' ).then( function ( supported ) { 132 | 133 | supported ? showEnterVR() : showWebXRNotFound(); 134 | 135 | } ); 136 | 137 | return button; 138 | 139 | } else { 140 | 141 | const message = document.createElement( 'a' ); 142 | 143 | if ( window.isSecureContext === false ) { 144 | 145 | message.href = document.location.href.replace( /^http:/, 'https:' ); 146 | message.innerHTML = 'WEBXR NEEDS HTTPS'; // TODO Improve message 147 | 148 | } else { 149 | 150 | message.href = 'https://immersiveweb.dev/'; 151 | message.innerHTML = 'WEBXR NOT AVAILABLE'; 152 | 153 | } 154 | 155 | message.style.left = 'calc(50% - 90px)'; 156 | message.style.width = '180px'; 157 | message.style.textDecoration = 'none'; 158 | 159 | stylizeElement( message ); 160 | 161 | return message; 162 | 163 | } 164 | 165 | } 166 | 167 | } 168 | 169 | export { VRButton }; 170 | -------------------------------------------------------------------------------- /libs/three.js/webxr/XRHandModelFactory.js: -------------------------------------------------------------------------------- 1 | import { 2 | Object3D 3 | } from '../../../build/three.module.js'; 4 | 5 | import { 6 | XRHandPrimitiveModel 7 | } from './XRHandPrimitiveModel.js'; 8 | 9 | import { 10 | XRHandOculusMeshModel 11 | } from './XRHandOculusMeshModel.js'; 12 | 13 | function XRHandModel( controller ) { 14 | 15 | Object3D.call( this ); 16 | 17 | this.controller = controller; 18 | this.motionController = null; 19 | this.envMap = null; 20 | 21 | this.mesh = null; 22 | 23 | } 24 | 25 | XRHandModel.prototype = Object.assign( Object.create( Object3D.prototype ), { 26 | 27 | constructor: XRHandModel, 28 | 29 | updateMatrixWorld: function ( force ) { 30 | 31 | Object3D.prototype.updateMatrixWorld.call( this, force ); 32 | 33 | if ( this.motionController ) { 34 | 35 | this.motionController.updateMesh(); 36 | 37 | } 38 | 39 | }, 40 | } ); 41 | 42 | 43 | const XRHandModelFactory = ( function () { 44 | 45 | function XRHandModelFactory() { 46 | 47 | this.path = ''; 48 | 49 | } 50 | 51 | XRHandModelFactory.prototype = { 52 | 53 | constructor: XRHandModelFactory, 54 | 55 | setPath: function ( path ) { 56 | 57 | this.path = path; 58 | return this; 59 | 60 | }, 61 | 62 | createHandModel: function ( controller, profile, options ) { 63 | 64 | const handModel = new XRHandModel( controller ); 65 | 66 | controller.addEventListener( 'connected', ( event ) => { 67 | 68 | const xrInputSource = event.data; 69 | 70 | if ( xrInputSource.hand && ! handModel.motionController ) { 71 | 72 | handModel.visible = true; 73 | handModel.xrInputSource = xrInputSource; 74 | 75 | // @todo Detect profile if not provided 76 | if ( profile === undefined || profile === 'spheres' ) { 77 | 78 | handModel.motionController = new XRHandPrimitiveModel( handModel, controller, this.path, xrInputSource.handedness, { primitive: 'sphere' } ); 79 | 80 | } else if ( profile === 'boxes' ) { 81 | 82 | handModel.motionController = new XRHandPrimitiveModel( handModel, controller, this.path, xrInputSource.handedness, { primitive: 'box' } ); 83 | 84 | } else if ( profile === 'oculus' ) { 85 | 86 | handModel.motionController = new XRHandOculusMeshModel( handModel, controller, this.path, xrInputSource.handedness, options ); 87 | 88 | } 89 | 90 | } 91 | 92 | } ); 93 | 94 | controller.addEventListener( 'disconnected', () => { 95 | 96 | // handModel.motionController = null; 97 | // handModel.remove( scene ); 98 | // scene = null; 99 | 100 | } ); 101 | 102 | return handModel; 103 | 104 | } 105 | 106 | }; 107 | 108 | return XRHandModelFactory; 109 | 110 | } )(); 111 | 112 | 113 | export { XRHandModelFactory }; 114 | -------------------------------------------------------------------------------- /libs/three.js/webxr/XRHandOculusMeshModel.js: -------------------------------------------------------------------------------- 1 | import { FBXLoader } from '../loaders/FBXLoader.js'; 2 | 3 | class XRHandOculusMeshModel { 4 | 5 | constructor( handModel, controller, path, handedness, options ) { 6 | 7 | this.controller = controller; 8 | this.handModel = handModel; 9 | 10 | this.bones = []; 11 | const loader = new FBXLoader(); 12 | const low = options && options.model === 'lowpoly' ? '_low' : ''; 13 | 14 | loader.setPath( path ); 15 | loader.load( `OculusHand_${handedness === 'right' ? 'R' : 'L'}${low}.fbx`, object => { 16 | 17 | this.handModel.add( object ); 18 | // Hack because of the scale of the skinnedmesh 19 | object.scale.setScalar( 0.01 ); 20 | 21 | const mesh = object.getObjectByProperty( 'type', 'SkinnedMesh' ); 22 | mesh.frustumCulled = false; 23 | mesh.castShadow = true; 24 | mesh.receiveShadow = true; 25 | 26 | const bonesMapping = [ 27 | 'b_%_wrist', // XRHand.WRIST, 28 | 29 | 'b_%_thumb1', // XRHand.THUMB_METACARPAL, 30 | 'b_%_thumb2', // XRHand.THUMB_PHALANX_PROXIMAL, 31 | 'b_%_thumb3', // XRHand.THUMB_PHALANX_DISTAL, 32 | 'b_%_thumb_null', // XRHand.THUMB_PHALANX_TIP, 33 | 34 | null, //'b_%_index1', // XRHand.INDEX_METACARPAL, 35 | 'b_%_index1', // XRHand.INDEX_PHALANX_PROXIMAL, 36 | 'b_%_index2', // XRHand.INDEX_PHALANX_INTERMEDIATE, 37 | 'b_%_index3', // XRHand.INDEX_PHALANX_DISTAL, 38 | 'b_%_index_null', // XRHand.INDEX_PHALANX_TIP, 39 | 40 | null, //'b_%_middle1', // XRHand.MIDDLE_METACARPAL, 41 | 'b_%_middle1', // XRHand.MIDDLE_PHALANX_PROXIMAL, 42 | 'b_%_middle2', // XRHand.MIDDLE_PHALANX_INTERMEDIATE, 43 | 'b_%_middle3', // XRHand.MIDDLE_PHALANX_DISTAL, 44 | 'b_%_middlenull', // XRHand.MIDDLE_PHALANX_TIP, 45 | 46 | null, //'b_%_ring1', // XRHand.RING_METACARPAL, 47 | 'b_%_ring1', // XRHand.RING_PHALANX_PROXIMAL, 48 | 'b_%_ring2', // XRHand.RING_PHALANX_INTERMEDIATE, 49 | 'b_%_ring3', // XRHand.RING_PHALANX_DISTAL, 50 | 'b_%_ring_inull', // XRHand.RING_PHALANX_TIP, 51 | 52 | 'b_%_pinky0', // XRHand.LITTLE_METACARPAL, 53 | 'b_%_pinky1', // XRHand.LITTLE_PHALANX_PROXIMAL, 54 | 'b_%_pinky2', // XRHand.LITTLE_PHALANX_INTERMEDIATE, 55 | 'b_%_pinky3', // XRHand.LITTLE_PHALANX_DISTAL, 56 | 'b_%_pinkynull', // XRHand.LITTLE_PHALANX_TIP 57 | ]; 58 | bonesMapping.forEach( boneName => { 59 | 60 | if ( boneName ) { 61 | 62 | const bone = object.getObjectByName( boneName.replace( /%/g, handedness === 'right' ? 'r' : 'l' ) ); 63 | this.bones.push( bone ); 64 | 65 | } else { 66 | 67 | this.bones.push( null ); 68 | 69 | } 70 | 71 | } ); 72 | 73 | } ); 74 | 75 | } 76 | 77 | updateMesh() { 78 | 79 | // XR Joints 80 | const XRJoints = this.controller.joints; 81 | for ( let i = 0; i < this.bones.length; i ++ ) { 82 | 83 | const bone = this.bones[ i ]; 84 | const XRJoint = XRJoints[ i ]; 85 | 86 | if ( XRJoint ) { 87 | 88 | if ( XRJoint.visible ) { 89 | 90 | const position = XRJoint.position; 91 | 92 | if ( bone ) { 93 | 94 | bone.position.copy( position.clone().multiplyScalar( 100 ) ); 95 | bone.quaternion.copy( XRJoint.quaternion ); 96 | // bone.scale.setScalar( XRJoint.jointRadius || defaultRadius ); 97 | 98 | } 99 | 100 | } 101 | 102 | } 103 | 104 | } 105 | 106 | } 107 | 108 | } 109 | 110 | export { XRHandOculusMeshModel }; 111 | -------------------------------------------------------------------------------- /libs/three.js/webxr/XRHandPrimitiveModel.js: -------------------------------------------------------------------------------- 1 | import { 2 | SphereBufferGeometry, 3 | BoxBufferGeometry, 4 | MeshStandardMaterial, 5 | Mesh, 6 | Group 7 | } from '../../../build/three.module.js'; 8 | 9 | class XRHandPrimitiveModel { 10 | 11 | constructor( handModel, controller, path, handedness, options ) { 12 | 13 | this.controller = controller; 14 | this.handModel = handModel; 15 | 16 | this.envMap = null; 17 | 18 | this.handMesh = new Group(); 19 | this.handModel.add( this.handMesh ); 20 | 21 | if ( window.XRHand ) { 22 | 23 | let geometry; 24 | 25 | if ( ! options || ! options.primitive || options.primitive === 'sphere' ) { 26 | 27 | geometry = new SphereBufferGeometry( 1, 10, 10 ); 28 | 29 | } else if ( options.primitive === 'box' ) { 30 | 31 | geometry = new BoxBufferGeometry( 1, 1, 1 ); 32 | 33 | } 34 | 35 | const jointMaterial = new MeshStandardMaterial( { color: 0xffffff, roughness: 1, metalness: 0 } ); 36 | const tipMaterial = new MeshStandardMaterial( { color: 0x999999, roughness: 1, metalness: 0 } ); 37 | 38 | const tipIndexes = [ 39 | window.XRHand.THUMB_PHALANX_TIP, 40 | window.XRHand.INDEX_PHALANX_TIP, 41 | window.XRHand.MIDDLE_PHALANX_TIP, 42 | window.XRHand.RING_PHALANX_TIP, 43 | window.XRHand.LITTLE_PHALANX_TIP 44 | ]; 45 | for ( let i = 0; i <= window.XRHand.LITTLE_PHALANX_TIP; i ++ ) { 46 | 47 | var cube = new Mesh( geometry, tipIndexes.indexOf( i ) !== - 1 ? tipMaterial : jointMaterial ); 48 | cube.castShadow = true; 49 | cube.receiveShadow = true; 50 | this.handMesh.add( cube ); 51 | 52 | } 53 | 54 | } 55 | 56 | } 57 | 58 | updateMesh() { 59 | 60 | const defaultRadius = 0.008; 61 | const objects = this.handMesh.children; 62 | 63 | // XR Joints 64 | const XRJoints = this.controller.joints; 65 | 66 | for ( let i = 0; i < objects.length; i ++ ) { 67 | 68 | const jointMesh = objects[ i ]; 69 | const XRJoint = XRJoints[ i ]; 70 | 71 | if ( XRJoint.visible ) { 72 | 73 | jointMesh.position.copy( XRJoint.position ); 74 | jointMesh.quaternion.copy( XRJoint.quaternion ); 75 | jointMesh.scale.setScalar( XRJoint.jointRadius || defaultRadius ); 76 | 77 | } 78 | 79 | jointMesh.visible = XRJoint.visible; 80 | 81 | } 82 | 83 | } 84 | 85 | } 86 | 87 | export { XRHandPrimitiveModel }; 88 | -------------------------------------------------------------------------------- /small_garage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LetsGo Viewer 6 | 7 | 9 | 10 | 11 | 151 | 152 | 153 | 154 | 157 |
158 |

LetsGo Viewer

159 |

160 |

161 | 162 |
163 |

164 |
Instructions
165 |
166 | - W/S arrow keys to move forward/back 167 | - A/D arrow keys to move left/right 168 | - space to play the video (if available) 169 | 170 | camera angle (wasd) 171 | - q/e to roll camera counterclockwise/clockwise 172 | 173 | trackpad 174 | - scroll up/down/left/right to orbit 175 | - pinch to move forward/back 176 | - ctrl key + scroll to move forward/back 177 | - shift + scroll to move up/down or strafe 178 | 179 | mouse 180 | - click and drag to orbit 181 | - right click (or ctrl/cmd key) and drag up/down to move 182 | 183 | touch (mobile) 184 | - one finger to orbit 185 | - two finger pinch to move forward/back 186 | - two finger rotate to rotate camera clockwise/counterclockwise 187 | - two finger pan to move side-to-side and up-down 188 | 189 | other 190 | - press p to resume default animation 191 |
192 |

193 | 194 |
195 | 196 |
197 | 198 |
199 | 200 |
201 |
202 |
203 |
204 |
205 | 206 |
207 | Load Resources 0Mb...(0%) 208 |
209 |
210 | 211 | 212 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | -------------------------------------------------------------------------------- /src/gaussian-utils/WorkerPool.js: -------------------------------------------------------------------------------- 1 | 2 | export class WorkerPool{ 3 | constructor(){ 4 | this.workers = {}; 5 | } 6 | 7 | getWorker(url){ 8 | if (!this.workers[url]){ 9 | this.workers[url] = []; 10 | } 11 | 12 | if (this.workers[url].length === 0){ 13 | let worker = new Worker(url); 14 | this.workers[url].push(worker); 15 | } 16 | 17 | let worker = this.workers[url].pop(); 18 | 19 | return worker; 20 | } 21 | 22 | returnWorker(url, worker){ 23 | this.workers[url].push(worker); 24 | } 25 | }; 26 | 27 | //Potree.workerPool = new Potree.WorkerPool(); 28 | -------------------------------------------------------------------------------- /src/gaussian-utils/gaussian-attributes.js: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Some types of possible point attribute data formats 4 | * modified from potree\src\loader\PointAttributes.js 5 | * @class 6 | * update by Fuqiang Zhao 7 | */ 8 | const PointAttributeTypes = { 9 | DATA_TYPE_DOUBLE: {ordinal: 0, name: "double", size: 8}, 10 | DATA_TYPE_FLOAT: {ordinal: 1, name: "float", size: 4}, 11 | DATA_TYPE_INT8: {ordinal: 2, name: "int8", size: 1}, 12 | DATA_TYPE_UINT8: {ordinal: 3, name: "uint8", size: 1}, 13 | DATA_TYPE_INT16: {ordinal: 4, name: "int16", size: 2}, 14 | DATA_TYPE_UINT16: {ordinal: 5, name: "uint16", size: 2}, 15 | DATA_TYPE_INT32: {ordinal: 6, name: "int32", size: 4}, 16 | DATA_TYPE_UINT32: {ordinal: 7, name: "uint32", size: 4}, 17 | DATA_TYPE_INT64: {ordinal: 8, name: "int64", size: 8}, 18 | DATA_TYPE_UINT64: {ordinal: 9, name: "uint64", size: 8} 19 | }; 20 | 21 | let i = 0; 22 | for (let obj in PointAttributeTypes) { 23 | PointAttributeTypes[i] = PointAttributeTypes[obj]; 24 | i++; 25 | } 26 | 27 | export {PointAttributeTypes}; 28 | 29 | 30 | class PointAttribute{ 31 | 32 | constructor(name, type, numElements){ 33 | this.name = name; 34 | this.type = type; 35 | this.numElements = numElements; 36 | this.byteSize = this.numElements * this.type.size; 37 | this.description = ""; 38 | this.range = [Infinity, -Infinity]; 39 | } 40 | 41 | }; 42 | 43 | PointAttribute.POSITION_CARTESIAN = new PointAttribute( 44 | "POSITION_CARTESIAN", PointAttributeTypes.DATA_TYPE_FLOAT, 3); 45 | 46 | PointAttribute.RGBA_PACKED = new PointAttribute( 47 | "COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 4); 48 | 49 | PointAttribute.COLOR_PACKED = PointAttribute.RGBA_PACKED; 50 | 51 | PointAttribute.RGB_PACKED = new PointAttribute( 52 | "COLOR_PACKED", PointAttributeTypes.DATA_TYPE_INT8, 3); 53 | 54 | PointAttribute.NORMAL_FLOATS = new PointAttribute( 55 | "NORMAL_FLOATS", PointAttributeTypes.DATA_TYPE_FLOAT, 3); 56 | 57 | PointAttribute.INTENSITY = new PointAttribute( 58 | "INTENSITY", PointAttributeTypes.DATA_TYPE_UINT16, 1); 59 | 60 | PointAttribute.CLASSIFICATION = new PointAttribute( 61 | "CLASSIFICATION", PointAttributeTypes.DATA_TYPE_UINT8, 1); 62 | 63 | PointAttribute.NORMAL_SPHEREMAPPED = new PointAttribute( 64 | "NORMAL_SPHEREMAPPED", PointAttributeTypes.DATA_TYPE_UINT8, 2); 65 | 66 | PointAttribute.NORMAL_OCT16 = new PointAttribute( 67 | "NORMAL_OCT16", PointAttributeTypes.DATA_TYPE_UINT8, 2); 68 | 69 | PointAttribute.NORMAL = new PointAttribute( 70 | "NORMAL", PointAttributeTypes.DATA_TYPE_FLOAT, 3); 71 | 72 | PointAttribute.RETURN_NUMBER = new PointAttribute( 73 | "RETURN_NUMBER", PointAttributeTypes.DATA_TYPE_UINT8, 1); 74 | 75 | PointAttribute.NUMBER_OF_RETURNS = new PointAttribute( 76 | "NUMBER_OF_RETURNS", PointAttributeTypes.DATA_TYPE_UINT8, 1); 77 | 78 | PointAttribute.SOURCE_ID = new PointAttribute( 79 | "SOURCE_ID", PointAttributeTypes.DATA_TYPE_UINT16, 1); 80 | 81 | PointAttribute.INDICES = new PointAttribute( 82 | "INDICES", PointAttributeTypes.DATA_TYPE_UINT32, 1); 83 | 84 | PointAttribute.SPACING = new PointAttribute( 85 | "SPACING", PointAttributeTypes.DATA_TYPE_FLOAT, 1); 86 | 87 | PointAttribute.GPS_TIME = new PointAttribute( 88 | "GPS_TIME", PointAttributeTypes.DATA_TYPE_DOUBLE, 1); 89 | 90 | export {PointAttribute}; 91 | 92 | export class PointAttributes{ 93 | 94 | constructor(pointAttributes){ 95 | this.attributes = []; 96 | this.byteSize = 0; 97 | this.size = 0; 98 | this.vectors = []; 99 | 100 | if (pointAttributes != null) { 101 | for (let i = 0; i < pointAttributes.length; i++) { 102 | let pointAttributeName = pointAttributes[i]; 103 | let pointAttribute = PointAttribute[pointAttributeName]; 104 | this.attributes.push(pointAttribute); 105 | this.byteSize += pointAttribute.byteSize; 106 | this.size++; 107 | } 108 | } 109 | } 110 | 111 | 112 | add(pointAttribute){ 113 | this.attributes.push(pointAttribute); 114 | this.byteSize += pointAttribute.byteSize; 115 | this.size++; 116 | }; 117 | 118 | addVector(vector){ 119 | this.vectors.push(vector); 120 | } 121 | 122 | hasNormals(){ 123 | for (let name in this.attributes) { 124 | let pointAttribute = this.attributes[name]; 125 | if ( 126 | pointAttribute === PointAttribute.NORMAL_SPHEREMAPPED || 127 | pointAttribute === PointAttribute.NORMAL_FLOATS || 128 | pointAttribute === PointAttribute.NORMAL || 129 | pointAttribute === PointAttribute.NORMAL_OCT16) { 130 | return true; 131 | } 132 | } 133 | 134 | return false; 135 | }; 136 | 137 | } 138 | -------------------------------------------------------------------------------- /src/gaussian-utils/gaussian-octree.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Some types of possible point attribute data formats 3 | * modified from potree\src\modules\loader\2.0\OctreeGeometry.js 4 | * @class 5 | * update by Fuqiang Zhao 6 | */ 7 | import * as THREE from "../../libs/three.js/build/three.module.js"; 8 | import {potree} from "../potree.js"; 9 | export class OctreeGeometry{ 10 | constructor(){ 11 | this.url = null; 12 | this.spacing = 0; 13 | this.boundingBox = null; 14 | this.root = null; 15 | this.pointAttributes = null; 16 | this.loader = null; 17 | } 18 | 19 | }; 20 | 21 | export class OctreeGeometryNode{ 22 | 23 | constructor(name, octreeGeometry, boundingBox){ 24 | this.id = OctreeGeometryNode.IDCount++; 25 | this.name = name; 26 | this.index = parseInt(name.charAt(name.length - 1)); 27 | this.octreeGeometry = octreeGeometry; 28 | this.boundingBox = boundingBox; 29 | this.boundingSphere = boundingBox.getBoundingSphere(new THREE.Sphere()); 30 | this.children = {}; 31 | this.numPoints = 0; 32 | this.level = null; 33 | this.oneTimeDisposeHandlers = []; 34 | } 35 | 36 | isGeometryNode(){ 37 | return true; 38 | } 39 | 40 | getLevel(){ 41 | return this.level; 42 | } 43 | 44 | isTreeNode(){ 45 | return false; 46 | } 47 | 48 | isLoaded(){ 49 | return this.loaded; 50 | } 51 | 52 | getBoundingSphere(){ 53 | return this.boundingSphere; 54 | } 55 | 56 | getBoundingBox(){ 57 | return this.boundingBox; 58 | } 59 | 60 | getChildren(){ 61 | let children = []; 62 | 63 | for (let i = 0; i < 8; i++) { 64 | if (this.children[i]) { 65 | children.push(this.children[i]); 66 | } 67 | } 68 | 69 | return children; 70 | } 71 | 72 | getBoundingBox(){ 73 | return this.boundingBox; 74 | } 75 | 76 | load(){ 77 | 78 | if (potree.numNodesLoading >= potree.maxNodesLoading) { 79 | return; 80 | } 81 | 82 | this.octreeGeometry.loader.load(this); 83 | } 84 | 85 | getNumPoints(){ 86 | return this.numPoints; 87 | } 88 | 89 | dispose(){ 90 | if (this.geometry && this.parent != null) { 91 | this.geometry.dispose(); 92 | this.geometry = null; 93 | this.loaded = false; 94 | 95 | // this.dispatchEvent( { type: 'dispose' } ); 96 | for (let i = 0; i < this.oneTimeDisposeHandlers.length; i++) { 97 | let handler = this.oneTimeDisposeHandlers[i]; 98 | handler(); 99 | } 100 | this.oneTimeDisposeHandlers = []; 101 | } 102 | } 103 | 104 | }; 105 | 106 | OctreeGeometryNode.IDCount = 0; -------------------------------------------------------------------------------- /src/indexedDB.js: -------------------------------------------------------------------------------- 1 | import localforage from "localforage"; 2 | 3 | 4 | export async function canInsetToLocalDB() { 5 | let flag = true; 6 | if (navigator.storage && navigator.storage.estimate) { 7 | const quota = await navigator.storage.estimate(); 8 | const percentageUsed = quota.usage / quota.quota; 9 | console.log('DB使用:', percentageUsed) 10 | if (percentageUsed > 0.8) { 11 | localforage.clear() 12 | flag = false; 13 | } 14 | } 15 | return flag 16 | } 17 | 18 | export async function localforageSetItem(key, value) { 19 | let canInsert = canInsetToLocalDB() 20 | if (!canInsert) { 21 | await localforage.clear() 22 | localforage.setItem(key, value); 23 | } 24 | else { 25 | localforage.setItem(key, value); 26 | } 27 | } 28 | export async function localforageGetItem(key) { 29 | const localData = await localforage.getItem(key); 30 | return localData; 31 | } -------------------------------------------------------------------------------- /src/potree.js: -------------------------------------------------------------------------------- 1 | 2 | import { WorkerPool } from "./gaussian-utils/WorkerPool.js"; 3 | import { OctreeLoader } from "./gaussian-utils/gaussian-octree-loader.js"; 4 | 5 | export const workerPool = new WorkerPool(); 6 | 7 | export const version = { 8 | major: 1, 9 | minor: 8, 10 | suffix: '.0' 11 | }; 12 | 13 | // export let pointBudget = 1 * 1000 * 1000; 14 | // export let framenumber = 0; 15 | // export let numNodesLoading = 0; 16 | // export let maxNodesLoading = 4; 17 | 18 | export const potree = { 19 | pointBudget: 1 * 1000 * 1000, 20 | framenumber: 0, 21 | numNodesLoading: 0, 22 | maxNodesLoading: 4 23 | } 24 | 25 | export async function loadPointCloud(path, name, octreeFileUrl, callback) { 26 | 27 | let loaded = function (e) { 28 | e.geometry.name = name; 29 | callback(e); 30 | }; 31 | 32 | let promise = new Promise(async (resolve, reject) => { 33 | // load pointcloud 34 | if (!path) { 35 | reject(new Error("Path is undefined or empty")); 36 | } else if (path.indexOf('metadata.json') > 0) { 37 | OctreeLoader.load(path, octreeFileUrl).then(e => { 38 | let geometry = e.geometry; 39 | if (!geometry) { 40 | console.error(new Error(`failed to load point cloud from URL: ${path}`)); 41 | } else { 42 | 43 | resolve({ type: 'geometry', geometry: geometry }); 44 | } 45 | }).catch(e => { 46 | console.error(new Error(`failed to load point cloud from URL: ${path}`)); 47 | reject(e); 48 | }); 49 | } else { 50 | //callback({'type': 'loading_failed'}); 51 | reject(new Error(`Invalid path for point cloud: ${path}`)); 52 | } 53 | }); 54 | 55 | if (callback) { 56 | promise.then(pointcloud => { 57 | loaded(pointcloud); 58 | }); 59 | } else { 60 | return promise; 61 | } 62 | } -------------------------------------------------------------------------------- /src/public.js: -------------------------------------------------------------------------------- 1 | var host = window.location.host; 2 | var isLocal = !host.includes('47.120.55.223') 3 | 4 | var instructionsBtn = document.getElementById('instructions_title'); 5 | var flat = true 6 | instructionsBtn.addEventListener('click', function () { 7 | console.log(flat) 8 | document.getElementById('instructions').style.display = flat ? "block" : "none" 9 | flat = !flat 10 | }); --------------------------------------------------------------------------------