├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── basic-sample.html
├── search-sample.html
├── third_party
└── three.js
│ ├── LICENSE
│ ├── METADATA
│ ├── README.md
│ └── js
│ ├── LegacyGLTFLoader.js
│ ├── MTLLoader.js
│ ├── OBJLoader.js
│ └── three.min.js
└── tiltbrush-sample.html
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | This project is not accepting pull requests at the moment.
2 |
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Poly API - Web Sample
2 |
3 | Copyright (c) 2017 Google Inc. All rights reserved.
4 |
5 | This is a sample project showing how to invoke the
6 | [Poly API](https://developers.google.com/poly) from
7 | a web app.
8 |
9 | ## How to run
10 |
11 | First, generate an API Key for the Poly API following the instructions in [the
12 | developer documentation](https://developers.google.com/poly/develop).
13 |
14 | Then, enter your API key in each of the HTML files in this sample, replacing
15 | the value of the `API_KEY` variable:
16 |
17 | const API_KEY = "*** INSERT YOUR API KEY HERE ***";
18 |
19 | When replacing, do not leave the asterisks, replace the entire string by
20 | your API Key.
21 |
22 | Place the sample files at the root directory of your web server.
23 | If you have Python installed, you can use the `SimpleHTTPServer` module
24 | to serve a local directory for testing:
25 |
26 | cd /path/to/sample
27 | python -m SimpleHTTPServer 8000
28 |
29 | These are the available samples:
30 |
31 | * **basic-sample.html**. Shows how to load and display a single asset
32 | with known ID.
33 |
34 | * **search-sample.html**. Shows how to search for assets and display them.
35 |
36 | * **tiltbrush-sample.html**. Shows how to load and display a Tilt Brush sketch.
37 |
38 | ## License
39 |
40 | For license information, refer to the `LICENSE` file.
41 |
42 |
--------------------------------------------------------------------------------
/basic-sample.html:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
24 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | Title
56 | by Author
57 |
58 |
59 |
60 |
61 |
62 |
178 |
179 |
180 |
--------------------------------------------------------------------------------
/search-sample.html:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
24 |
81 |
82 |
83 |
84 |
88 |
89 |
90 |
91 | Title
92 | by Author
93 |
94 |
95 |
96 |
97 |
98 |
277 |
278 |
279 |
--------------------------------------------------------------------------------
/third_party/three.js/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright © 2010-2017 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 |
--------------------------------------------------------------------------------
/third_party/three.js/METADATA:
--------------------------------------------------------------------------------
1 | name: "three.js"
2 | description:
3 | "Lightweight 3D library for WebGL."
4 |
5 | third_party {
6 | url {
7 | type: HOMEPAGE
8 | value: "https://github.com/mrdoob/three.js"
9 | }
10 | url {
11 | type: GIT
12 | value: "https://github.com/mrdoob/three.js"
13 | }
14 | version: "62a32a2db8a78b1b8e752c909a68302e83f42202"
15 | last_upgrade_date { year: 2017 month: 11 day: 15 }
16 | license_type: NOTICE
17 | local_modifications:
18 | "Removed all unneeded files, kept minimal subset of needed files in"
19 | "js/ subdirectory."
20 | }
21 |
--------------------------------------------------------------------------------
/third_party/three.js/README.md:
--------------------------------------------------------------------------------
1 | three.js
2 | ========
3 |
4 | [![Gitter][gitter-badge]][gitter-badge-url]
5 | [![Latest NPM release][npm-badge]][npm-badge-url]
6 | [![License][license-badge]][license-badge-url]
7 | [![Dependencies][dependencies-badge]][dependencies-badge-url]
8 | [![Dev Dependencies][devDependencies-badge]][devDependencies-badge-url]
9 |
10 | #### JavaScript 3D library ####
11 |
12 | The aim of the project is to create an easy to use, lightweight, 3D library. The library provides <canvas>, <svg>, CSS3D and WebGL renderers.
13 |
14 | [Examples](http://threejs.org/examples/) —
15 | [Documentation](http://threejs.org/docs/) —
16 | [Wiki](https://github.com/mrdoob/three.js/wiki) —
17 | [Migrating](https://github.com/mrdoob/three.js/wiki/Migration-Guide) —
18 | [Help](http://stackoverflow.com/questions/tagged/three.js)
19 |
20 | ### Usage ###
21 |
22 | 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),
23 | Alternatively see [how to build the library yourself](https://github.com/mrdoob/three.js/wiki/Build-instructions).
24 |
25 | ```html
26 |
27 | ```
28 |
29 | 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.
30 |
31 | ```javascript
32 | var camera, scene, renderer;
33 | var geometry, material, mesh;
34 |
35 | init();
36 | animate();
37 |
38 | function init() {
39 |
40 | camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
41 | camera.position.z = 1;
42 |
43 | scene = new THREE.Scene();
44 |
45 | geometry = new THREE.BoxGeometry( 0.2, 0.2, 0.2 );
46 | material = new THREE.MeshNormalMaterial();
47 |
48 | mesh = new THREE.Mesh( geometry, material );
49 | scene.add( mesh );
50 |
51 | renderer = new THREE.WebGLRenderer( { antialias: true } );
52 | renderer.setSize( window.innerWidth, window.innerHeight );
53 | document.body.appendChild( renderer.domElement );
54 |
55 | }
56 |
57 | function animate() {
58 |
59 | requestAnimationFrame( animate );
60 |
61 | mesh.rotation.x += 0.01;
62 | mesh.rotation.y += 0.02;
63 |
64 | renderer.render( scene, camera );
65 |
66 | }
67 | ```
68 |
69 | If everything went well you should see [this](https://jsfiddle.net/f2Lommf5/).
70 |
71 | ### Change log ###
72 |
73 | [releases](https://github.com/mrdoob/three.js/releases)
74 |
75 |
76 | [gitter-badge]: https://badges.gitter.im/mrdoob/three.js.svg
77 | [gitter-badge-url]: https://gitter.im/mrdoob/three.js
78 | [npm-badge]: https://img.shields.io/npm/v/three.svg
79 | [npm-badge-url]: https://www.npmjs.com/package/three
80 | [license-badge]: https://img.shields.io/npm/l/three.svg
81 | [license-badge-url]: ./LICENSE
82 | [dependencies-badge]: https://img.shields.io/david/mrdoob/three.js.svg
83 | [dependencies-badge-url]: https://david-dm.org/mrdoob/three.js
84 | [devDependencies-badge]: https://img.shields.io/david/dev/mrdoob/three.js.svg
85 | [devDependencies-badge-url]: https://david-dm.org/mrdoob/three.js#info=devDependencies
86 |
--------------------------------------------------------------------------------
/third_party/three.js/js/LegacyGLTFLoader.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Rich Tibbett / https://github.com/richtr
3 | * @author mrdoob / http://mrdoob.com/
4 | * @author Tony Parisi / http://www.tonyparisi.com/
5 | * @author Takahiro / https://github.com/takahirox
6 | */
7 |
8 | THREE.LegacyGLTFLoader = ( function () {
9 |
10 | function LegacyGLTFLoader( manager ) {
11 |
12 | this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
13 |
14 | }
15 |
16 | LegacyGLTFLoader.prototype = {
17 |
18 | constructor: LegacyGLTFLoader,
19 |
20 | crossOrigin: 'Anonymous',
21 |
22 | load: function ( url, onLoad, onProgress, onError ) {
23 |
24 | var scope = this;
25 |
26 | var path = this.path && ( typeof this.path === "string" ) ? this.path : THREE.Loader.prototype.extractUrlBase( url );
27 |
28 | var loader = new THREE.FileLoader( scope.manager );
29 |
30 | loader.setResponseType( 'arraybuffer' );
31 |
32 | loader.load( url, function ( data ) {
33 |
34 | scope.parse( data, onLoad, path );
35 |
36 | }, onProgress, onError );
37 |
38 | },
39 |
40 | setCrossOrigin: function ( value ) {
41 |
42 | this.crossOrigin = value;
43 |
44 | },
45 |
46 | setPath: function ( value ) {
47 |
48 | this.path = value;
49 |
50 | },
51 |
52 | parse: function ( data, callback, path ) {
53 |
54 | var content;
55 | var extensions = {};
56 |
57 | var magic = convertUint8ArrayToString( new Uint8Array( data, 0, 4 ) );
58 |
59 | if ( magic === BINARY_EXTENSION_HEADER_DEFAULTS.magic ) {
60 |
61 | extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );
62 | content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;
63 |
64 | } else {
65 |
66 | content = convertUint8ArrayToString( new Uint8Array( data ) );
67 |
68 | }
69 |
70 | var json = JSON.parse( content );
71 |
72 | if ( json.extensionsUsed && json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_COMMON ) >= 0 ) {
73 |
74 | extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] = new GLTFMaterialsCommonExtension( json );
75 |
76 | }
77 |
78 | console.time( 'LegacyGLTFLoader' );
79 |
80 | var parser = new GLTFParser( json, extensions, {
81 |
82 | path: path || this.path,
83 | crossOrigin: this.crossOrigin
84 |
85 | } );
86 |
87 | parser.parse( function ( scene, scenes, cameras, animations ) {
88 |
89 | console.timeEnd( 'LegacyGLTFLoader' );
90 |
91 | var glTF = {
92 | "scene": scene,
93 | "scenes": scenes,
94 | "cameras": cameras,
95 | "animations": animations
96 | };
97 |
98 | callback( glTF );
99 |
100 | } );
101 |
102 | }
103 |
104 | };
105 |
106 | /* GLTFREGISTRY */
107 |
108 | function GLTFRegistry() {
109 |
110 | var objects = {};
111 |
112 | return {
113 |
114 | get: function ( key ) {
115 |
116 | return objects[ key ];
117 |
118 | },
119 |
120 | add: function ( key, object ) {
121 |
122 | objects[ key ] = object;
123 |
124 | },
125 |
126 | remove: function ( key ) {
127 |
128 | delete objects[ key ];
129 |
130 | },
131 |
132 | removeAll: function () {
133 |
134 | objects = {};
135 |
136 | },
137 |
138 | update: function ( scene, camera ) {
139 |
140 | for ( var name in objects ) {
141 |
142 | var object = objects[ name ];
143 |
144 | if ( object.update ) {
145 |
146 | object.update( scene, camera );
147 |
148 | }
149 |
150 | }
151 |
152 | }
153 |
154 | };
155 |
156 | }
157 |
158 | /* GLTFSHADERS */
159 |
160 | LegacyGLTFLoader.Shaders = {
161 |
162 | update: function () {
163 |
164 | console.warn( 'THREE.LegacyGLTFLoader.Shaders has been deprecated, and now updates automatically.' );
165 |
166 | }
167 |
168 | };
169 |
170 | /* GLTFSHADER */
171 |
172 | function GLTFShader( targetNode, allNodes ) {
173 |
174 | var boundUniforms = {};
175 |
176 | // bind each uniform to its source node
177 |
178 | var uniforms = targetNode.material.uniforms;
179 |
180 | for ( var uniformId in uniforms ) {
181 |
182 | var uniform = uniforms[ uniformId ];
183 |
184 | if ( uniform.semantic ) {
185 |
186 | var sourceNodeRef = uniform.node;
187 |
188 | var sourceNode = targetNode;
189 |
190 | if ( sourceNodeRef ) {
191 |
192 | sourceNode = allNodes[ sourceNodeRef ];
193 |
194 | }
195 |
196 | boundUniforms[ uniformId ] = {
197 | semantic: uniform.semantic,
198 | sourceNode: sourceNode,
199 | targetNode: targetNode,
200 | uniform: uniform
201 | };
202 |
203 | }
204 |
205 | }
206 |
207 | this.boundUniforms = boundUniforms;
208 | this._m4 = new THREE.Matrix4();
209 |
210 | }
211 |
212 | // Update - update all the uniform values
213 | GLTFShader.prototype.update = function ( scene, camera ) {
214 |
215 | var boundUniforms = this.boundUniforms;
216 |
217 | for ( var name in boundUniforms ) {
218 |
219 | var boundUniform = boundUniforms[ name ];
220 |
221 | switch ( boundUniform.semantic ) {
222 |
223 | case "MODELVIEW":
224 |
225 | var m4 = boundUniform.uniform.value;
226 | m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld );
227 | break;
228 |
229 | case "MODELVIEWINVERSETRANSPOSE":
230 |
231 | var m3 = boundUniform.uniform.value;
232 | this._m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld );
233 | m3.getNormalMatrix( this._m4 );
234 | break;
235 |
236 | case "PROJECTION":
237 |
238 | var m4 = boundUniform.uniform.value;
239 | m4.copy( camera.projectionMatrix );
240 | break;
241 |
242 | case "JOINTMATRIX":
243 |
244 | var m4v = boundUniform.uniform.value;
245 |
246 | for ( var mi = 0; mi < m4v.length; mi ++ ) {
247 |
248 | // So it goes like this:
249 | // SkinnedMesh world matrix is already baked into MODELVIEW;
250 | // transform joints to local space,
251 | // then transform using joint's inverse
252 | m4v[ mi ]
253 | .getInverse( boundUniform.sourceNode.matrixWorld )
254 | .multiply( boundUniform.targetNode.skeleton.bones[ mi ].matrixWorld )
255 | .multiply( boundUniform.targetNode.skeleton.boneInverses[ mi ] )
256 | .multiply( boundUniform.targetNode.bindMatrix );
257 |
258 | }
259 |
260 | break;
261 |
262 | default :
263 |
264 | console.warn( "Unhandled shader semantic: " + boundUniform.semantic );
265 | break;
266 |
267 | }
268 |
269 | }
270 |
271 | };
272 |
273 |
274 | /* ANIMATION */
275 |
276 | LegacyGLTFLoader.Animations = {
277 |
278 | update: function () {
279 |
280 | console.warn( 'THREE.LegacyGLTFLoader.Animation has been deprecated. Use THREE.AnimationMixer instead.' );
281 |
282 | }
283 |
284 | };
285 |
286 | /*********************************/
287 | /********** EXTENSIONS ***********/
288 | /*********************************/
289 |
290 | var EXTENSIONS = {
291 | KHR_BINARY_GLTF: 'KHR_binary_glTF',
292 | KHR_MATERIALS_COMMON: 'KHR_materials_common'
293 | };
294 |
295 | /* MATERIALS COMMON EXTENSION */
296 |
297 | function GLTFMaterialsCommonExtension( json ) {
298 |
299 | this.name = EXTENSIONS.KHR_MATERIALS_COMMON;
300 |
301 | this.lights = {};
302 |
303 | var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) || {};
304 | var lights = extension.lights || {};
305 |
306 | for ( var lightId in lights ) {
307 |
308 | var light = lights[ lightId ];
309 | var lightNode;
310 |
311 | var lightParams = light[ light.type ];
312 | var color = new THREE.Color().fromArray( lightParams.color );
313 |
314 | switch ( light.type ) {
315 |
316 | case "directional":
317 | lightNode = new THREE.DirectionalLight( color );
318 | lightNode.position.set( 0, 0, 1 );
319 | break;
320 |
321 | case "point":
322 | lightNode = new THREE.PointLight( color );
323 | break;
324 |
325 | case "spot":
326 | lightNode = new THREE.SpotLight( color );
327 | lightNode.position.set( 0, 0, 1 );
328 | break;
329 |
330 | case "ambient":
331 | lightNode = new THREE.AmbientLight( color );
332 | break;
333 |
334 | }
335 |
336 | if ( lightNode ) {
337 |
338 | this.lights[ lightId ] = lightNode;
339 |
340 | }
341 |
342 | }
343 |
344 | }
345 |
346 | /* BINARY EXTENSION */
347 |
348 | var BINARY_EXTENSION_BUFFER_NAME = 'binary_glTF';
349 |
350 | var BINARY_EXTENSION_HEADER_DEFAULTS = { magic: 'glTF', version: 1, contentFormat: 0 };
351 |
352 | var BINARY_EXTENSION_HEADER_LENGTH = 20;
353 |
354 | function GLTFBinaryExtension( data ) {
355 |
356 | this.name = EXTENSIONS.KHR_BINARY_GLTF;
357 |
358 | var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );
359 |
360 | var header = {
361 | magic: convertUint8ArrayToString( new Uint8Array( data.slice( 0, 4 ) ) ),
362 | version: headerView.getUint32( 4, true ),
363 | length: headerView.getUint32( 8, true ),
364 | contentLength: headerView.getUint32( 12, true ),
365 | contentFormat: headerView.getUint32( 16, true )
366 | };
367 |
368 | for ( var key in BINARY_EXTENSION_HEADER_DEFAULTS ) {
369 |
370 | var value = BINARY_EXTENSION_HEADER_DEFAULTS[ key ];
371 |
372 | if ( header[ key ] !== value ) {
373 |
374 | throw new Error( 'Unsupported glTF-Binary header: Expected "%s" to be "%s".', key, value );
375 |
376 | }
377 |
378 | }
379 |
380 | var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH, header.contentLength );
381 |
382 | this.header = header;
383 | this.content = convertUint8ArrayToString( contentArray );
384 | this.body = data.slice( BINARY_EXTENSION_HEADER_LENGTH + header.contentLength, header.length );
385 |
386 | }
387 |
388 | GLTFBinaryExtension.prototype.loadShader = function ( shader, bufferViews ) {
389 |
390 | var bufferView = bufferViews[ shader.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].bufferView ];
391 | var array = new Uint8Array( bufferView );
392 |
393 | return convertUint8ArrayToString( array );
394 |
395 | };
396 |
397 | GLTFBinaryExtension.prototype.loadTextureSourceUri = function ( source, bufferViews ) {
398 |
399 | var metadata = source.extensions[ EXTENSIONS.KHR_BINARY_GLTF ];
400 | var bufferView = bufferViews[ metadata.bufferView ];
401 | var stringData = convertUint8ArrayToString( new Uint8Array( bufferView ) );
402 |
403 | return 'data:' + metadata.mimeType + ';base64,' + btoa( stringData );
404 |
405 | };
406 |
407 | /*********************************/
408 | /********** INTERNALS ************/
409 | /*********************************/
410 |
411 | /* CONSTANTS */
412 |
413 | var WEBGL_CONSTANTS = {
414 | FLOAT: 5126,
415 | //FLOAT_MAT2: 35674,
416 | FLOAT_MAT3: 35675,
417 | FLOAT_MAT4: 35676,
418 | FLOAT_VEC2: 35664,
419 | FLOAT_VEC3: 35665,
420 | FLOAT_VEC4: 35666,
421 | LINEAR: 9729,
422 | REPEAT: 10497,
423 | SAMPLER_2D: 35678,
424 | TRIANGLES: 4,
425 | LINES: 1,
426 | UNSIGNED_BYTE: 5121,
427 | UNSIGNED_SHORT: 5123,
428 |
429 | VERTEX_SHADER: 35633,
430 | FRAGMENT_SHADER: 35632
431 | };
432 |
433 | var WEBGL_TYPE = {
434 | 5126: Number,
435 | //35674: THREE.Matrix2,
436 | 35675: THREE.Matrix3,
437 | 35676: THREE.Matrix4,
438 | 35664: THREE.Vector2,
439 | 35665: THREE.Vector3,
440 | 35666: THREE.Vector4,
441 | 35678: THREE.Texture
442 | };
443 |
444 | var WEBGL_COMPONENT_TYPES = {
445 | 5120: Int8Array,
446 | 5121: Uint8Array,
447 | 5122: Int16Array,
448 | 5123: Uint16Array,
449 | 5125: Uint32Array,
450 | 5126: Float32Array
451 | };
452 |
453 | var WEBGL_FILTERS = {
454 | 9728: THREE.NearestFilter,
455 | 9729: THREE.LinearFilter,
456 | 9984: THREE.NearestMipMapNearestFilter,
457 | 9985: THREE.LinearMipMapNearestFilter,
458 | 9986: THREE.NearestMipMapLinearFilter,
459 | 9987: THREE.LinearMipMapLinearFilter
460 | };
461 |
462 | var WEBGL_WRAPPINGS = {
463 | 33071: THREE.ClampToEdgeWrapping,
464 | 33648: THREE.MirroredRepeatWrapping,
465 | 10497: THREE.RepeatWrapping
466 | };
467 |
468 | var WEBGL_TEXTURE_FORMATS = {
469 | 6406: THREE.AlphaFormat,
470 | 6407: THREE.RGBFormat,
471 | 6408: THREE.RGBAFormat,
472 | 6409: THREE.LuminanceFormat,
473 | 6410: THREE.LuminanceAlphaFormat
474 | };
475 |
476 | var WEBGL_TEXTURE_DATATYPES = {
477 | 5121: THREE.UnsignedByteType,
478 | 32819: THREE.UnsignedShort4444Type,
479 | 32820: THREE.UnsignedShort5551Type,
480 | 33635: THREE.UnsignedShort565Type
481 | };
482 |
483 | var WEBGL_SIDES = {
484 | 1028: THREE.BackSide, // Culling front
485 | 1029: THREE.FrontSide // Culling back
486 | //1032: THREE.NoSide // Culling front and back, what to do?
487 | };
488 |
489 | var WEBGL_DEPTH_FUNCS = {
490 | 512: THREE.NeverDepth,
491 | 513: THREE.LessDepth,
492 | 514: THREE.EqualDepth,
493 | 515: THREE.LessEqualDepth,
494 | 516: THREE.GreaterEqualDepth,
495 | 517: THREE.NotEqualDepth,
496 | 518: THREE.GreaterEqualDepth,
497 | 519: THREE.AlwaysDepth
498 | };
499 |
500 | var WEBGL_BLEND_EQUATIONS = {
501 | 32774: THREE.AddEquation,
502 | 32778: THREE.SubtractEquation,
503 | 32779: THREE.ReverseSubtractEquation
504 | };
505 |
506 | var WEBGL_BLEND_FUNCS = {
507 | 0: THREE.ZeroFactor,
508 | 1: THREE.OneFactor,
509 | 768: THREE.SrcColorFactor,
510 | 769: THREE.OneMinusSrcColorFactor,
511 | 770: THREE.SrcAlphaFactor,
512 | 771: THREE.OneMinusSrcAlphaFactor,
513 | 772: THREE.DstAlphaFactor,
514 | 773: THREE.OneMinusDstAlphaFactor,
515 | 774: THREE.DstColorFactor,
516 | 775: THREE.OneMinusDstColorFactor,
517 | 776: THREE.SrcAlphaSaturateFactor
518 | // The followings are not supported by Three.js yet
519 | //32769: CONSTANT_COLOR,
520 | //32770: ONE_MINUS_CONSTANT_COLOR,
521 | //32771: CONSTANT_ALPHA,
522 | //32772: ONE_MINUS_CONSTANT_COLOR
523 | };
524 |
525 | var WEBGL_TYPE_SIZES = {
526 | 'SCALAR': 1,
527 | 'VEC2': 2,
528 | 'VEC3': 3,
529 | 'VEC4': 4,
530 | 'MAT2': 4,
531 | 'MAT3': 9,
532 | 'MAT4': 16
533 | };
534 |
535 | var PATH_PROPERTIES = {
536 | scale: 'scale',
537 | translation: 'position',
538 | rotation: 'quaternion'
539 | };
540 |
541 | var INTERPOLATION = {
542 | LINEAR: THREE.InterpolateLinear,
543 | STEP: THREE.InterpolateDiscrete
544 | };
545 |
546 | var STATES_ENABLES = {
547 | 2884: 'CULL_FACE',
548 | 2929: 'DEPTH_TEST',
549 | 3042: 'BLEND',
550 | 3089: 'SCISSOR_TEST',
551 | 32823: 'POLYGON_OFFSET_FILL',
552 | 32926: 'SAMPLE_ALPHA_TO_COVERAGE'
553 | };
554 |
555 | /* UTILITY FUNCTIONS */
556 |
557 | function _each( object, callback, thisObj ) {
558 |
559 | if ( !object ) {
560 | return Promise.resolve();
561 | }
562 |
563 | var results;
564 | var fns = [];
565 |
566 | if ( Object.prototype.toString.call( object ) === '[object Array]' ) {
567 |
568 | results = [];
569 |
570 | var length = object.length;
571 |
572 | for ( var idx = 0; idx < length; idx ++ ) {
573 |
574 | var value = callback.call( thisObj || this, object[ idx ], idx );
575 |
576 | if ( value ) {
577 |
578 | fns.push( value );
579 |
580 | if ( value instanceof Promise ) {
581 |
582 | value.then( function( key, value ) {
583 |
584 | results[ key ] = value;
585 |
586 | }.bind( this, idx ));
587 |
588 | } else {
589 |
590 | results[ idx ] = value;
591 |
592 | }
593 |
594 | }
595 |
596 | }
597 |
598 | } else {
599 |
600 | results = {};
601 |
602 | for ( var key in object ) {
603 |
604 | if ( object.hasOwnProperty( key ) ) {
605 |
606 | var value = callback.call( thisObj || this, object[ key ], key );
607 |
608 | if ( value ) {
609 |
610 | fns.push( value );
611 |
612 | if ( value instanceof Promise ) {
613 |
614 | value.then( function( key, value ) {
615 |
616 | results[ key ] = value;
617 |
618 | }.bind( this, key ));
619 |
620 | } else {
621 |
622 | results[ key ] = value;
623 |
624 | }
625 |
626 | }
627 |
628 | }
629 |
630 | }
631 |
632 | }
633 |
634 | return Promise.all( fns ).then( function() {
635 |
636 | return results;
637 |
638 | });
639 |
640 | }
641 |
642 | function resolveURL( url, path ) {
643 |
644 | // Invalid URL
645 | if ( typeof url !== 'string' || url === '' )
646 | return '';
647 |
648 | // Absolute URL http://,https://,//
649 | if ( /^(https?:)?\/\//i.test( url ) ) {
650 |
651 | return url;
652 |
653 | }
654 |
655 | // Data URI
656 | if ( /^data:.*,.*$/i.test( url ) ) {
657 |
658 | return url;
659 |
660 | }
661 |
662 | // Relative URL
663 | return ( path || '' ) + url;
664 |
665 | }
666 |
667 | function convertUint8ArrayToString( array ) {
668 |
669 | if ( window.TextDecoder !== undefined ) {
670 |
671 | return new TextDecoder().decode( array );
672 |
673 | }
674 |
675 | // Avoid the String.fromCharCode.apply(null, array) shortcut, which
676 | // throws a "maximum call stack size exceeded" error for large arrays.
677 |
678 | var s = '';
679 |
680 | for ( var i = 0, il = array.length; i < il; i ++ ) {
681 |
682 | s += String.fromCharCode( array[ i ] );
683 |
684 | }
685 |
686 | return s;
687 |
688 | }
689 |
690 | // Three.js seems too dependent on attribute names so globally
691 | // replace those in the shader code
692 | function replaceTHREEShaderAttributes( shaderText, technique ) {
693 |
694 | // Expected technique attributes
695 | var attributes = {};
696 |
697 | for ( var attributeId in technique.attributes ) {
698 |
699 | var pname = technique.attributes[ attributeId ];
700 |
701 | var param = technique.parameters[ pname ];
702 | var atype = param.type;
703 | var semantic = param.semantic;
704 |
705 | attributes[ attributeId ] = {
706 | type: atype,
707 | semantic: semantic
708 | };
709 |
710 | }
711 |
712 | // Figure out which attributes to change in technique
713 |
714 | var shaderParams = technique.parameters;
715 | var shaderAttributes = technique.attributes;
716 | var params = {};
717 |
718 | for ( var attributeId in attributes ) {
719 |
720 | var pname = shaderAttributes[ attributeId ];
721 | var shaderParam = shaderParams[ pname ];
722 | var semantic = shaderParam.semantic;
723 | if ( semantic ) {
724 |
725 | params[ attributeId ] = shaderParam;
726 |
727 | }
728 |
729 | }
730 |
731 | for ( var pname in params ) {
732 |
733 | var param = params[ pname ];
734 | var semantic = param.semantic;
735 |
736 | var regEx = new RegExp( "\\b" + pname + "\\b", "g" );
737 |
738 | switch ( semantic ) {
739 |
740 | case "POSITION":
741 |
742 | shaderText = shaderText.replace( regEx, 'position' );
743 | break;
744 |
745 | case "NORMAL":
746 |
747 | shaderText = shaderText.replace( regEx, 'normal' );
748 | break;
749 |
750 | case 'TEXCOORD_0':
751 | case 'TEXCOORD0':
752 | case 'TEXCOORD':
753 |
754 | shaderText = shaderText.replace( regEx, 'uv' );
755 | break;
756 |
757 | case 'TEXCOORD_1':
758 |
759 | shaderText = shaderText.replace( regEx, 'uv2' );
760 | break;
761 |
762 | case 'COLOR_0':
763 | case 'COLOR0':
764 | case 'COLOR':
765 |
766 | shaderText = shaderText.replace( regEx, 'color' );
767 | break;
768 |
769 | case "WEIGHT":
770 |
771 | shaderText = shaderText.replace( regEx, 'skinWeight' );
772 | break;
773 |
774 | case "JOINT":
775 |
776 | shaderText = shaderText.replace( regEx, 'skinIndex' );
777 | break;
778 |
779 | }
780 |
781 | }
782 |
783 | return shaderText;
784 |
785 | }
786 |
787 | function createDefaultMaterial() {
788 |
789 | return new THREE.MeshPhongMaterial( {
790 | color: 0x00000,
791 | emissive: 0x888888,
792 | specular: 0x000000,
793 | shininess: 0,
794 | transparent: false,
795 | depthTest: true,
796 | side: THREE.FrontSide
797 | } );
798 |
799 | }
800 |
801 | // Deferred constructor for RawShaderMaterial types
802 | function DeferredShaderMaterial( params ) {
803 |
804 | this.isDeferredShaderMaterial = true;
805 |
806 | this.params = params;
807 |
808 | }
809 |
810 | DeferredShaderMaterial.prototype.create = function () {
811 |
812 | var uniforms = THREE.UniformsUtils.clone( this.params.uniforms );
813 |
814 | for ( var uniformId in this.params.uniforms ) {
815 |
816 | var originalUniform = this.params.uniforms[ uniformId ];
817 |
818 | if ( originalUniform.value instanceof THREE.Texture ) {
819 |
820 | uniforms[ uniformId ].value = originalUniform.value;
821 | uniforms[ uniformId ].value.needsUpdate = true;
822 |
823 | }
824 |
825 | uniforms[ uniformId ].semantic = originalUniform.semantic;
826 | uniforms[ uniformId ].node = originalUniform.node;
827 |
828 | }
829 |
830 | this.params.uniforms = uniforms;
831 |
832 | return new THREE.RawShaderMaterial( this.params );
833 |
834 | };
835 |
836 | /* GLTF PARSER */
837 |
838 | function GLTFParser( json, extensions, options ) {
839 |
840 | this.json = json || {};
841 | this.extensions = extensions || {};
842 | this.options = options || {};
843 |
844 | // loader object cache
845 | this.cache = new GLTFRegistry();
846 |
847 | }
848 |
849 | GLTFParser.prototype._withDependencies = function ( dependencies ) {
850 |
851 | var _dependencies = {};
852 |
853 | for ( var i = 0; i < dependencies.length; i ++ ) {
854 |
855 | var dependency = dependencies[ i ];
856 | var fnName = "load" + dependency.charAt( 0 ).toUpperCase() + dependency.slice( 1 );
857 |
858 | var cached = this.cache.get( dependency );
859 |
860 | if ( cached !== undefined ) {
861 |
862 | _dependencies[ dependency ] = cached;
863 |
864 | } else if ( this[ fnName ] ) {
865 |
866 | var fn = this[ fnName ]();
867 | this.cache.add( dependency, fn );
868 |
869 | _dependencies[ dependency ] = fn;
870 |
871 | }
872 |
873 | }
874 |
875 | return _each( _dependencies, function ( dependency ) {
876 |
877 | return dependency;
878 |
879 | } );
880 |
881 | };
882 |
883 | GLTFParser.prototype.parse = function ( callback ) {
884 |
885 | var json = this.json;
886 |
887 | // Clear the loader cache
888 | this.cache.removeAll();
889 |
890 | // Fire the callback on complete
891 | this._withDependencies( [
892 |
893 | "scenes",
894 | "cameras",
895 | "animations"
896 |
897 | ] ).then( function ( dependencies ) {
898 |
899 | var scenes = [];
900 |
901 | for ( var name in dependencies.scenes ) {
902 |
903 | scenes.push( dependencies.scenes[ name ] );
904 |
905 | }
906 |
907 | var scene = json.scene !== undefined ? dependencies.scenes[ json.scene ] : scenes[ 0 ];
908 |
909 | var cameras = [];
910 |
911 | for ( var name in dependencies.cameras ) {
912 |
913 | var camera = dependencies.cameras[ name ];
914 | cameras.push( camera );
915 |
916 | }
917 |
918 | var animations = [];
919 |
920 | for ( var name in dependencies.animations ) {
921 |
922 | animations.push( dependencies.animations[ name ] );
923 |
924 | }
925 |
926 | callback( scene, scenes, cameras, animations );
927 |
928 | } );
929 |
930 | };
931 |
932 | GLTFParser.prototype.loadShaders = function () {
933 |
934 | var json = this.json;
935 | var extensions = this.extensions;
936 | var options = this.options;
937 |
938 | return this._withDependencies( [
939 |
940 | "bufferViews"
941 |
942 | ] ).then( function ( dependencies ) {
943 |
944 | return _each( json.shaders, function ( shader ) {
945 |
946 | if ( shader.extensions && shader.extensions[ EXTENSIONS.KHR_BINARY_GLTF ] ) {
947 |
948 | return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].loadShader( shader, dependencies.bufferViews );
949 |
950 | }
951 |
952 | return new Promise( function ( resolve ) {
953 |
954 | var loader = new THREE.FileLoader();
955 | loader.setResponseType( 'text' );
956 | loader.load( resolveURL( shader.uri, options.path ), function ( shaderText ) {
957 |
958 | resolve( shaderText );
959 |
960 | } );
961 |
962 | } );
963 |
964 | } );
965 |
966 | } );
967 |
968 | };
969 |
970 | GLTFParser.prototype.loadBuffers = function () {
971 |
972 | var json = this.json;
973 | var extensions = this.extensions;
974 | var options = this.options;
975 |
976 | return _each( json.buffers, function ( buffer, name ) {
977 |
978 | if ( name === BINARY_EXTENSION_BUFFER_NAME ) {
979 |
980 | return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body;
981 |
982 | }
983 |
984 | if ( buffer.type === 'arraybuffer' || buffer.type === undefined ) {
985 |
986 | return new Promise( function ( resolve ) {
987 |
988 | var loader = new THREE.FileLoader();
989 | loader.setResponseType( 'arraybuffer' );
990 | loader.load( resolveURL( buffer.uri, options.path ), function ( buffer ) {
991 |
992 | resolve( buffer );
993 |
994 | } );
995 |
996 | } );
997 |
998 | } else {
999 |
1000 | console.warn( 'THREE.LegacyGLTFLoader: ' + buffer.type + ' buffer type is not supported' );
1001 |
1002 | }
1003 |
1004 | } );
1005 |
1006 | };
1007 |
1008 | GLTFParser.prototype.loadBufferViews = function () {
1009 |
1010 | var json = this.json;
1011 |
1012 | return this._withDependencies( [
1013 |
1014 | "buffers"
1015 |
1016 | ] ).then( function ( dependencies ) {
1017 |
1018 | return _each( json.bufferViews, function ( bufferView ) {
1019 |
1020 | var arraybuffer = dependencies.buffers[ bufferView.buffer ];
1021 |
1022 | var byteLength = bufferView.byteLength !== undefined ? bufferView.byteLength : 0;
1023 |
1024 | return arraybuffer.slice( bufferView.byteOffset, bufferView.byteOffset + byteLength );
1025 |
1026 | } );
1027 |
1028 | } );
1029 |
1030 | };
1031 |
1032 | GLTFParser.prototype.loadAccessors = function () {
1033 |
1034 | var json = this.json;
1035 |
1036 | return this._withDependencies( [
1037 |
1038 | "bufferViews"
1039 |
1040 | ] ).then( function ( dependencies ) {
1041 |
1042 | return _each( json.accessors, function ( accessor ) {
1043 |
1044 | var arraybuffer = dependencies.bufferViews[ accessor.bufferView ];
1045 | var itemSize = WEBGL_TYPE_SIZES[ accessor.type ];
1046 | var TypedArray = WEBGL_COMPONENT_TYPES[ accessor.componentType ];
1047 |
1048 | // For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.
1049 | var elementBytes = TypedArray.BYTES_PER_ELEMENT;
1050 | var itemBytes = elementBytes * itemSize;
1051 |
1052 | // The buffer is not interleaved if the stride is the item size in bytes.
1053 | if ( accessor.byteStride && accessor.byteStride !== itemBytes ) {
1054 |
1055 | // Use the full buffer if it's interleaved.
1056 | var array = new TypedArray( arraybuffer );
1057 |
1058 | // Integer parameters to IB/IBA are in array elements, not bytes.
1059 | var ib = new THREE.InterleavedBuffer( array, accessor.byteStride / elementBytes );
1060 |
1061 | return new THREE.InterleavedBufferAttribute( ib, itemSize, accessor.byteOffset / elementBytes );
1062 |
1063 | } else {
1064 |
1065 | array = new TypedArray( arraybuffer, accessor.byteOffset, accessor.count * itemSize );
1066 |
1067 | return new THREE.BufferAttribute( array, itemSize );
1068 |
1069 | }
1070 |
1071 | } );
1072 |
1073 | } );
1074 |
1075 | };
1076 |
1077 | GLTFParser.prototype.loadTextures = function () {
1078 |
1079 | var json = this.json;
1080 | var extensions = this.extensions;
1081 | var options = this.options;
1082 |
1083 | return this._withDependencies( [
1084 |
1085 | "bufferViews"
1086 |
1087 | ] ).then( function ( dependencies ) {
1088 |
1089 | return _each( json.textures, function ( texture ) {
1090 |
1091 | if ( texture.source ) {
1092 |
1093 | return new Promise( function ( resolve ) {
1094 |
1095 | var source = json.images[ texture.source ];
1096 | var sourceUri = source.uri;
1097 |
1098 | if ( source.extensions && source.extensions[ EXTENSIONS.KHR_BINARY_GLTF ] ) {
1099 |
1100 | sourceUri = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].loadTextureSourceUri( source, dependencies.bufferViews );
1101 |
1102 | }
1103 |
1104 | var textureLoader = THREE.Loader.Handlers.get( sourceUri );
1105 |
1106 | if ( textureLoader === null ) {
1107 |
1108 | textureLoader = new THREE.TextureLoader();
1109 |
1110 | }
1111 |
1112 | textureLoader.setCrossOrigin( options.crossOrigin );
1113 |
1114 | textureLoader.load( resolveURL( sourceUri, options.path ), function ( _texture ) {
1115 |
1116 | _texture.flipY = false;
1117 |
1118 | if ( texture.name !== undefined ) _texture.name = texture.name;
1119 |
1120 | _texture.format = texture.format !== undefined ? WEBGL_TEXTURE_FORMATS[ texture.format ] : THREE.RGBAFormat;
1121 |
1122 | if ( texture.internalFormat !== undefined && _texture.format !== WEBGL_TEXTURE_FORMATS[ texture.internalFormat ] ) {
1123 |
1124 | console.warn( 'THREE.LegacyGLTFLoader: Three.js doesn\'t support texture internalFormat which is different from texture format. ' +
1125 | 'internalFormat will be forced to be the same value as format.' );
1126 |
1127 | }
1128 |
1129 | _texture.type = texture.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ texture.type ] : THREE.UnsignedByteType;
1130 |
1131 | if ( texture.sampler ) {
1132 |
1133 | var sampler = json.samplers[ texture.sampler ];
1134 |
1135 | _texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter;
1136 | _texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.NearestMipMapLinearFilter;
1137 | _texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping;
1138 | _texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping;
1139 |
1140 | }
1141 |
1142 | resolve( _texture );
1143 |
1144 | }, undefined, function () {
1145 |
1146 | resolve();
1147 |
1148 | } );
1149 |
1150 | } );
1151 |
1152 | }
1153 |
1154 | } );
1155 |
1156 | } );
1157 |
1158 | };
1159 |
1160 | GLTFParser.prototype.loadMaterials = function () {
1161 |
1162 | var json = this.json;
1163 |
1164 | return this._withDependencies( [
1165 |
1166 | "shaders",
1167 | "textures"
1168 |
1169 | ] ).then( function ( dependencies ) {
1170 |
1171 | return _each( json.materials, function ( material ) {
1172 |
1173 | var materialType;
1174 | var materialValues = {};
1175 | var materialParams = {};
1176 |
1177 | var khr_material;
1178 |
1179 | if ( material.extensions && material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) {
1180 |
1181 | khr_material = material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ];
1182 |
1183 | }
1184 |
1185 | if ( khr_material ) {
1186 |
1187 | // don't copy over unused values to avoid material warning spam
1188 | var keys = [ 'ambient', 'emission', 'transparent', 'transparency', 'doubleSided' ];
1189 |
1190 | switch ( khr_material.technique ) {
1191 |
1192 | case 'BLINN' :
1193 | case 'PHONG' :
1194 | materialType = THREE.MeshPhongMaterial;
1195 | keys.push( 'diffuse', 'specular', 'shininess' );
1196 | break;
1197 |
1198 | case 'LAMBERT' :
1199 | materialType = THREE.MeshLambertMaterial;
1200 | keys.push( 'diffuse' );
1201 | break;
1202 |
1203 | case 'CONSTANT' :
1204 | default :
1205 | materialType = THREE.MeshBasicMaterial;
1206 | break;
1207 |
1208 | }
1209 |
1210 | keys.forEach( function( v ) {
1211 |
1212 | if ( khr_material.values[ v ] !== undefined ) materialValues[ v ] = khr_material.values[ v ];
1213 |
1214 | } );
1215 |
1216 | if ( khr_material.doubleSided || materialValues.doubleSided ) {
1217 |
1218 | materialParams.side = THREE.DoubleSide;
1219 |
1220 | }
1221 |
1222 | if ( khr_material.transparent || materialValues.transparent ) {
1223 |
1224 | materialParams.transparent = true;
1225 | materialParams.opacity = ( materialValues.transparency !== undefined ) ? materialValues.transparency : 1;
1226 |
1227 | }
1228 |
1229 | } else if ( material.technique === undefined ) {
1230 |
1231 | materialType = THREE.MeshPhongMaterial;
1232 |
1233 | Object.assign( materialValues, material.values );
1234 |
1235 | } else {
1236 |
1237 | materialType = DeferredShaderMaterial;
1238 |
1239 | var technique = json.techniques[ material.technique ];
1240 |
1241 | materialParams.uniforms = {};
1242 |
1243 | var program = json.programs[ technique.program ];
1244 |
1245 | if ( program ) {
1246 |
1247 | materialParams.fragmentShader = dependencies.shaders[ program.fragmentShader ];
1248 |
1249 | if ( ! materialParams.fragmentShader ) {
1250 |
1251 | console.warn( "ERROR: Missing fragment shader definition:", program.fragmentShader );
1252 | materialType = THREE.MeshPhongMaterial;
1253 |
1254 | }
1255 |
1256 | var vertexShader = dependencies.shaders[ program.vertexShader ];
1257 |
1258 | if ( ! vertexShader ) {
1259 |
1260 | console.warn( "ERROR: Missing vertex shader definition:", program.vertexShader );
1261 | materialType = THREE.MeshPhongMaterial;
1262 |
1263 | }
1264 |
1265 | // IMPORTANT: FIX VERTEX SHADER ATTRIBUTE DEFINITIONS
1266 | materialParams.vertexShader = replaceTHREEShaderAttributes( vertexShader, technique );
1267 |
1268 | var uniforms = technique.uniforms;
1269 |
1270 | for ( var uniformId in uniforms ) {
1271 |
1272 | var pname = uniforms[ uniformId ];
1273 | var shaderParam = technique.parameters[ pname ];
1274 |
1275 | var ptype = shaderParam.type;
1276 |
1277 | if ( WEBGL_TYPE[ ptype ] ) {
1278 |
1279 | var pcount = shaderParam.count;
1280 | var value;
1281 |
1282 | if ( material.values !== undefined ) value = material.values[ pname ];
1283 |
1284 | var uvalue = new WEBGL_TYPE[ ptype ]();
1285 | var usemantic = shaderParam.semantic;
1286 | var unode = shaderParam.node;
1287 |
1288 | switch ( ptype ) {
1289 |
1290 | case WEBGL_CONSTANTS.FLOAT:
1291 |
1292 | uvalue = shaderParam.value;
1293 |
1294 | if ( pname == "transparency" ) {
1295 |
1296 | materialParams.transparent = true;
1297 |
1298 | }
1299 |
1300 | if ( value !== undefined ) {
1301 |
1302 | uvalue = value;
1303 |
1304 | }
1305 |
1306 | break;
1307 |
1308 | case WEBGL_CONSTANTS.FLOAT_VEC2:
1309 | case WEBGL_CONSTANTS.FLOAT_VEC3:
1310 | case WEBGL_CONSTANTS.FLOAT_VEC4:
1311 | case WEBGL_CONSTANTS.FLOAT_MAT3:
1312 |
1313 | if ( shaderParam && shaderParam.value ) {
1314 |
1315 | uvalue.fromArray( shaderParam.value );
1316 |
1317 | }
1318 |
1319 | if ( value ) {
1320 |
1321 | uvalue.fromArray( value );
1322 |
1323 | }
1324 |
1325 | break;
1326 |
1327 | case WEBGL_CONSTANTS.FLOAT_MAT2:
1328 |
1329 | // what to do?
1330 | console.warn( "FLOAT_MAT2 is not a supported uniform type" );
1331 | break;
1332 |
1333 | case WEBGL_CONSTANTS.FLOAT_MAT4:
1334 |
1335 | if ( pcount ) {
1336 |
1337 | uvalue = new Array( pcount );
1338 |
1339 | for ( var mi = 0; mi < pcount; mi ++ ) {
1340 |
1341 | uvalue[ mi ] = new WEBGL_TYPE[ ptype ]();
1342 |
1343 | }
1344 |
1345 | if ( shaderParam && shaderParam.value ) {
1346 |
1347 | var m4v = shaderParam.value;
1348 | uvalue.fromArray( m4v );
1349 |
1350 | }
1351 |
1352 | if ( value ) {
1353 |
1354 | uvalue.fromArray( value );
1355 |
1356 | }
1357 |
1358 | } else {
1359 |
1360 | if ( shaderParam && shaderParam.value ) {
1361 |
1362 | var m4 = shaderParam.value;
1363 | uvalue.fromArray( m4 );
1364 |
1365 | }
1366 |
1367 | if ( value ) {
1368 |
1369 | uvalue.fromArray( value );
1370 |
1371 | }
1372 |
1373 | }
1374 |
1375 | break;
1376 |
1377 | case WEBGL_CONSTANTS.SAMPLER_2D:
1378 |
1379 | if ( value !== undefined ) {
1380 |
1381 | uvalue = dependencies.textures[ value ];
1382 |
1383 | } else if ( shaderParam.value !== undefined ) {
1384 |
1385 | uvalue = dependencies.textures[ shaderParam.value ];
1386 |
1387 | } else {
1388 |
1389 | uvalue = null;
1390 |
1391 | }
1392 |
1393 | break;
1394 |
1395 | }
1396 |
1397 | materialParams.uniforms[ uniformId ] = {
1398 | value: uvalue,
1399 | semantic: usemantic,
1400 | node: unode
1401 | };
1402 |
1403 | } else {
1404 |
1405 | throw new Error( "Unknown shader uniform param type: " + ptype );
1406 |
1407 | }
1408 |
1409 | }
1410 |
1411 | var states = technique.states || {};
1412 | var enables = states.enable || [];
1413 | var functions = states.functions || {};
1414 |
1415 | var enableCullFace = false;
1416 | var enableDepthTest = false;
1417 | var enableBlend = false;
1418 |
1419 | for ( var i = 0, il = enables.length; i < il; i ++ ) {
1420 |
1421 | var enable = enables[ i ];
1422 |
1423 | switch ( STATES_ENABLES[ enable ] ) {
1424 |
1425 | case 'CULL_FACE':
1426 |
1427 | enableCullFace = true;
1428 |
1429 | break;
1430 |
1431 | case 'DEPTH_TEST':
1432 |
1433 | enableDepthTest = true;
1434 |
1435 | break;
1436 |
1437 | case 'BLEND':
1438 |
1439 | enableBlend = true;
1440 |
1441 | break;
1442 |
1443 | // TODO: implement
1444 | case 'SCISSOR_TEST':
1445 | case 'POLYGON_OFFSET_FILL':
1446 | case 'SAMPLE_ALPHA_TO_COVERAGE':
1447 |
1448 | break;
1449 |
1450 | default:
1451 |
1452 | throw new Error( "Unknown technique.states.enable: " + enable );
1453 |
1454 | }
1455 |
1456 | }
1457 |
1458 | if ( enableCullFace ) {
1459 |
1460 | materialParams.side = functions.cullFace !== undefined ? WEBGL_SIDES[ functions.cullFace ] : THREE.FrontSide;
1461 |
1462 | } else {
1463 |
1464 | materialParams.side = THREE.DoubleSide;
1465 |
1466 | }
1467 |
1468 | materialParams.depthTest = enableDepthTest;
1469 | materialParams.depthFunc = functions.depthFunc !== undefined ? WEBGL_DEPTH_FUNCS[ functions.depthFunc ] : THREE.LessDepth;
1470 | materialParams.depthWrite = functions.depthMask !== undefined ? functions.depthMask[ 0 ] : true;
1471 |
1472 | materialParams.blending = enableBlend ? THREE.CustomBlending : THREE.NoBlending;
1473 | materialParams.transparent = enableBlend;
1474 |
1475 | var blendEquationSeparate = functions.blendEquationSeparate;
1476 |
1477 | if ( blendEquationSeparate !== undefined ) {
1478 |
1479 | materialParams.blendEquation = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 0 ] ];
1480 | materialParams.blendEquationAlpha = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 1 ] ];
1481 |
1482 | } else {
1483 |
1484 | materialParams.blendEquation = THREE.AddEquation;
1485 | materialParams.blendEquationAlpha = THREE.AddEquation;
1486 |
1487 | }
1488 |
1489 | var blendFuncSeparate = functions.blendFuncSeparate;
1490 |
1491 | if ( blendFuncSeparate !== undefined ) {
1492 |
1493 | materialParams.blendSrc = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 0 ] ];
1494 | materialParams.blendDst = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 1 ] ];
1495 | materialParams.blendSrcAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 2 ] ];
1496 | materialParams.blendDstAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 3 ] ];
1497 |
1498 | } else {
1499 |
1500 | materialParams.blendSrc = THREE.OneFactor;
1501 | materialParams.blendDst = THREE.ZeroFactor;
1502 | materialParams.blendSrcAlpha = THREE.OneFactor;
1503 | materialParams.blendDstAlpha = THREE.ZeroFactor;
1504 |
1505 | }
1506 |
1507 | }
1508 |
1509 | }
1510 |
1511 | if ( Array.isArray( materialValues.diffuse ) ) {
1512 |
1513 | materialParams.color = new THREE.Color().fromArray( materialValues.diffuse );
1514 |
1515 | } else if ( typeof( materialValues.diffuse ) === 'string' ) {
1516 |
1517 | materialParams.map = dependencies.textures[ materialValues.diffuse ];
1518 |
1519 | }
1520 |
1521 | delete materialParams.diffuse;
1522 |
1523 | if ( typeof( materialValues.reflective ) === 'string' ) {
1524 |
1525 | materialParams.envMap = dependencies.textures[ materialValues.reflective ];
1526 |
1527 | }
1528 |
1529 | if ( typeof( materialValues.bump ) === 'string' ) {
1530 |
1531 | materialParams.bumpMap = dependencies.textures[ materialValues.bump ];
1532 |
1533 | }
1534 |
1535 | if ( Array.isArray( materialValues.emission ) ) {
1536 |
1537 | if ( materialType === THREE.MeshBasicMaterial ) {
1538 |
1539 | materialParams.color = new THREE.Color().fromArray( materialValues.emission );
1540 |
1541 | } else {
1542 |
1543 | materialParams.emissive = new THREE.Color().fromArray( materialValues.emission );
1544 |
1545 | }
1546 |
1547 | } else if ( typeof( materialValues.emission ) === 'string' ) {
1548 |
1549 | if ( materialType === THREE.MeshBasicMaterial ) {
1550 |
1551 | materialParams.map = dependencies.textures[ materialValues.emission ];
1552 |
1553 | } else {
1554 |
1555 | materialParams.emissiveMap = dependencies.textures[ materialValues.emission ];
1556 |
1557 | }
1558 |
1559 | }
1560 |
1561 | if ( Array.isArray( materialValues.specular ) ) {
1562 |
1563 | materialParams.specular = new THREE.Color().fromArray( materialValues.specular );
1564 |
1565 | } else if ( typeof( materialValues.specular ) === 'string' ) {
1566 |
1567 | materialParams.specularMap = dependencies.textures[ materialValues.specular ];
1568 |
1569 | }
1570 |
1571 | if ( materialValues.shininess !== undefined ) {
1572 |
1573 | materialParams.shininess = materialValues.shininess;
1574 |
1575 | }
1576 |
1577 | var _material = new materialType( materialParams );
1578 | if ( material.name !== undefined ) _material.name = material.name;
1579 |
1580 | return _material;
1581 |
1582 | } );
1583 |
1584 | } );
1585 |
1586 | };
1587 |
1588 | GLTFParser.prototype.loadMeshes = function () {
1589 |
1590 | var json = this.json;
1591 |
1592 | return this._withDependencies( [
1593 |
1594 | "accessors",
1595 | "materials"
1596 |
1597 | ] ).then( function ( dependencies ) {
1598 |
1599 | return _each( json.meshes, function ( mesh ) {
1600 |
1601 | var group = new THREE.Group();
1602 | if ( mesh.name !== undefined ) group.name = mesh.name;
1603 |
1604 | if ( mesh.extras ) group.userData = mesh.extras;
1605 |
1606 | var primitives = mesh.primitives || [];
1607 |
1608 | for ( var name in primitives ) {
1609 |
1610 | var primitive = primitives[ name ];
1611 |
1612 | if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === undefined ) {
1613 |
1614 | var geometry = new THREE.BufferGeometry();
1615 |
1616 | var attributes = primitive.attributes;
1617 |
1618 | for ( var attributeId in attributes ) {
1619 |
1620 | var attributeEntry = attributes[ attributeId ];
1621 |
1622 | if ( ! attributeEntry ) return;
1623 |
1624 | var bufferAttribute = dependencies.accessors[ attributeEntry ];
1625 |
1626 | switch ( attributeId ) {
1627 |
1628 | case 'POSITION':
1629 | geometry.addAttribute( 'position', bufferAttribute );
1630 | break;
1631 |
1632 | case 'NORMAL':
1633 | geometry.addAttribute( 'normal', bufferAttribute );
1634 | break;
1635 |
1636 | case 'TEXCOORD_0':
1637 | case 'TEXCOORD0':
1638 | case 'TEXCOORD':
1639 | geometry.addAttribute( 'uv', bufferAttribute );
1640 | break;
1641 |
1642 | case 'TEXCOORD_1':
1643 | geometry.addAttribute( 'uv2', bufferAttribute );
1644 | break;
1645 |
1646 | case 'COLOR_0':
1647 | case 'COLOR0':
1648 | case 'COLOR':
1649 | geometry.addAttribute( 'color', bufferAttribute );
1650 | break;
1651 |
1652 | case 'WEIGHT':
1653 | geometry.addAttribute( 'skinWeight', bufferAttribute );
1654 | break;
1655 |
1656 | case 'JOINT':
1657 | geometry.addAttribute( 'skinIndex', bufferAttribute );
1658 | break;
1659 |
1660 | }
1661 |
1662 | }
1663 |
1664 | if ( primitive.indices ) {
1665 |
1666 | geometry.setIndex( dependencies.accessors[ primitive.indices ] );
1667 |
1668 | }
1669 |
1670 | var material = dependencies.materials !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial();
1671 |
1672 | var meshNode = new THREE.Mesh( geometry, material );
1673 | meshNode.castShadow = true;
1674 | meshNode.name = ( name === "0" ? group.name : group.name + name );
1675 |
1676 | if ( primitive.extras ) meshNode.userData = primitive.extras;
1677 |
1678 | group.add( meshNode );
1679 |
1680 | } else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
1681 |
1682 | var geometry = new THREE.BufferGeometry();
1683 |
1684 | var attributes = primitive.attributes;
1685 |
1686 | for ( var attributeId in attributes ) {
1687 |
1688 | var attributeEntry = attributes[ attributeId ];
1689 |
1690 | if ( ! attributeEntry ) return;
1691 |
1692 | var bufferAttribute = dependencies.accessors[ attributeEntry ];
1693 |
1694 | switch ( attributeId ) {
1695 |
1696 | case 'POSITION':
1697 | geometry.addAttribute( 'position', bufferAttribute );
1698 | break;
1699 |
1700 | case 'COLOR_0':
1701 | case 'COLOR0':
1702 | case 'COLOR':
1703 | geometry.addAttribute( 'color', bufferAttribute );
1704 | break;
1705 |
1706 | }
1707 |
1708 | }
1709 |
1710 | var material = dependencies.materials[ primitive.material ];
1711 |
1712 | var meshNode;
1713 |
1714 | if ( primitive.indices ) {
1715 |
1716 | geometry.setIndex( dependencies.accessors[ primitive.indices ] );
1717 |
1718 | meshNode = new THREE.LineSegments( geometry, material );
1719 |
1720 | } else {
1721 |
1722 | meshNode = new THREE.Line( geometry, material );
1723 |
1724 | }
1725 |
1726 | meshNode.name = ( name === "0" ? group.name : group.name + name );
1727 |
1728 | if ( primitive.extras ) meshNode.userData = primitive.extras;
1729 |
1730 | group.add( meshNode );
1731 |
1732 | } else {
1733 |
1734 | console.warn( "Only triangular and line primitives are supported" );
1735 |
1736 | }
1737 |
1738 | }
1739 |
1740 | return group;
1741 |
1742 | } );
1743 |
1744 | } );
1745 |
1746 | };
1747 |
1748 | GLTFParser.prototype.loadCameras = function () {
1749 |
1750 | var json = this.json;
1751 |
1752 | return _each( json.cameras, function ( camera ) {
1753 |
1754 | if ( camera.type == "perspective" && camera.perspective ) {
1755 |
1756 | var yfov = camera.perspective.yfov;
1757 | var aspectRatio = camera.perspective.aspectRatio !== undefined ? camera.perspective.aspectRatio : 1;
1758 |
1759 | // According to COLLADA spec...
1760 | // aspectRatio = xfov / yfov
1761 | var xfov = yfov * aspectRatio;
1762 |
1763 | var _camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( xfov ), aspectRatio, camera.perspective.znear || 1, camera.perspective.zfar || 2e6 );
1764 | if ( camera.name !== undefined ) _camera.name = camera.name;
1765 |
1766 | if ( camera.extras ) _camera.userData = camera.extras;
1767 |
1768 | return _camera;
1769 |
1770 | } else if ( camera.type == "orthographic" && camera.orthographic ) {
1771 |
1772 | var _camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, camera.orthographic.znear, camera.orthographic.zfar );
1773 | if ( camera.name !== undefined ) _camera.name = camera.name;
1774 |
1775 | if ( camera.extras ) _camera.userData = camera.extras;
1776 |
1777 | return _camera;
1778 |
1779 | }
1780 |
1781 | } );
1782 |
1783 | };
1784 |
1785 | GLTFParser.prototype.loadSkins = function () {
1786 |
1787 | var json = this.json;
1788 |
1789 | return this._withDependencies( [
1790 |
1791 | "accessors"
1792 |
1793 | ] ).then( function ( dependencies ) {
1794 |
1795 | return _each( json.skins, function ( skin ) {
1796 |
1797 | var bindShapeMatrix = new THREE.Matrix4();
1798 |
1799 | if ( skin.bindShapeMatrix !== undefined ) bindShapeMatrix.fromArray( skin.bindShapeMatrix );
1800 |
1801 | var _skin = {
1802 | bindShapeMatrix: bindShapeMatrix,
1803 | jointNames: skin.jointNames,
1804 | inverseBindMatrices: dependencies.accessors[ skin.inverseBindMatrices ]
1805 | };
1806 |
1807 | return _skin;
1808 |
1809 | } );
1810 |
1811 | } );
1812 |
1813 | };
1814 |
1815 | GLTFParser.prototype.loadAnimations = function () {
1816 |
1817 | var json = this.json;
1818 |
1819 | return this._withDependencies( [
1820 |
1821 | "accessors",
1822 | "nodes"
1823 |
1824 | ] ).then( function ( dependencies ) {
1825 |
1826 | return _each( json.animations, function ( animation, animationId ) {
1827 |
1828 | var tracks = [];
1829 |
1830 | for ( var channelId in animation.channels ) {
1831 |
1832 | var channel = animation.channels[ channelId ];
1833 | var sampler = animation.samplers[ channel.sampler ];
1834 |
1835 | if ( sampler ) {
1836 |
1837 | var target = channel.target;
1838 | var name = target.id;
1839 | var input = animation.parameters !== undefined ? animation.parameters[ sampler.input ] : sampler.input;
1840 | var output = animation.parameters !== undefined ? animation.parameters[ sampler.output ] : sampler.output;
1841 |
1842 | var inputAccessor = dependencies.accessors[ input ];
1843 | var outputAccessor = dependencies.accessors[ output ];
1844 |
1845 | var node = dependencies.nodes[ name ];
1846 |
1847 | if ( node ) {
1848 |
1849 | node.updateMatrix();
1850 | node.matrixAutoUpdate = true;
1851 |
1852 | var TypedKeyframeTrack = PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.rotation
1853 | ? THREE.QuaternionKeyframeTrack
1854 | : THREE.VectorKeyframeTrack;
1855 |
1856 | var targetName = node.name ? node.name : node.uuid;
1857 | var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear;
1858 |
1859 | // KeyframeTrack.optimize() will modify given 'times' and 'values'
1860 | // buffers before creating a truncated copy to keep. Because buffers may
1861 | // be reused by other tracks, make copies here.
1862 | tracks.push( new TypedKeyframeTrack(
1863 | targetName + '.' + PATH_PROPERTIES[ target.path ],
1864 | THREE.AnimationUtils.arraySlice( inputAccessor.array, 0 ),
1865 | THREE.AnimationUtils.arraySlice( outputAccessor.array, 0 ),
1866 | interpolation
1867 | ) );
1868 |
1869 | }
1870 |
1871 | }
1872 |
1873 | }
1874 |
1875 | var name = animation.name !== undefined ? animation.name : "animation_" + animationId;
1876 |
1877 | return new THREE.AnimationClip( name, undefined, tracks );
1878 |
1879 | } );
1880 |
1881 | } );
1882 |
1883 | };
1884 |
1885 | GLTFParser.prototype.loadNodes = function () {
1886 |
1887 | var json = this.json;
1888 | var extensions = this.extensions;
1889 | var scope = this;
1890 |
1891 | return _each( json.nodes, function ( node ) {
1892 |
1893 | var matrix = new THREE.Matrix4();
1894 |
1895 | var _node;
1896 |
1897 | if ( node.jointName ) {
1898 |
1899 | _node = new THREE.Bone();
1900 | _node.name = node.name !== undefined ? node.name : node.jointName;
1901 | _node.jointName = node.jointName;
1902 |
1903 | } else {
1904 |
1905 | _node = new THREE.Object3D();
1906 | if ( node.name !== undefined ) _node.name = node.name;
1907 |
1908 | }
1909 |
1910 | if ( node.extras ) _node.userData = node.extras;
1911 |
1912 | if ( node.matrix !== undefined ) {
1913 |
1914 | matrix.fromArray( node.matrix );
1915 | _node.applyMatrix( matrix );
1916 |
1917 | } else {
1918 |
1919 | if ( node.translation !== undefined ) {
1920 |
1921 | _node.position.fromArray( node.translation );
1922 |
1923 | }
1924 |
1925 | if ( node.rotation !== undefined ) {
1926 |
1927 | _node.quaternion.fromArray( node.rotation );
1928 |
1929 | }
1930 |
1931 | if ( node.scale !== undefined ) {
1932 |
1933 | _node.scale.fromArray( node.scale );
1934 |
1935 | }
1936 |
1937 | }
1938 |
1939 | return _node;
1940 |
1941 | } ).then( function ( __nodes ) {
1942 |
1943 | return scope._withDependencies( [
1944 |
1945 | "meshes",
1946 | "skins",
1947 | "cameras"
1948 |
1949 | ] ).then( function ( dependencies ) {
1950 |
1951 | return _each( __nodes, function ( _node, nodeId ) {
1952 |
1953 | var node = json.nodes[ nodeId ];
1954 |
1955 | if ( node.meshes !== undefined ) {
1956 |
1957 | for ( var meshId in node.meshes ) {
1958 |
1959 | var mesh = node.meshes[ meshId ];
1960 | var group = dependencies.meshes[ mesh ];
1961 |
1962 | if ( group === undefined ) {
1963 |
1964 | console.warn( 'LegacyGLTFLoader: Couldn\'t find node "' + mesh + '".' );
1965 | continue;
1966 |
1967 | }
1968 |
1969 | for ( var childrenId in group.children ) {
1970 |
1971 | var child = group.children[ childrenId ];
1972 |
1973 | // clone Mesh to add to _node
1974 |
1975 | var originalMaterial = child.material;
1976 | var originalGeometry = child.geometry;
1977 | var originalUserData = child.userData;
1978 | var originalName = child.name;
1979 |
1980 | var material;
1981 |
1982 | if ( originalMaterial.isDeferredShaderMaterial ) {
1983 |
1984 | originalMaterial = material = originalMaterial.create();
1985 |
1986 | } else {
1987 |
1988 | material = originalMaterial;
1989 |
1990 | }
1991 |
1992 | switch ( child.type ) {
1993 |
1994 | case 'LineSegments':
1995 | child = new THREE.LineSegments( originalGeometry, material );
1996 | break;
1997 |
1998 | case 'LineLoop':
1999 | child = new THREE.LineLoop( originalGeometry, material );
2000 | break;
2001 |
2002 | case 'Line':
2003 | child = new THREE.Line( originalGeometry, material );
2004 | break;
2005 |
2006 | default:
2007 | child = new THREE.Mesh( originalGeometry, material );
2008 |
2009 | }
2010 |
2011 | child.castShadow = true;
2012 | child.userData = originalUserData;
2013 | child.name = originalName;
2014 |
2015 | var skinEntry;
2016 |
2017 | if ( node.skin ) {
2018 |
2019 | skinEntry = dependencies.skins[ node.skin ];
2020 |
2021 | }
2022 |
2023 | // Replace Mesh with SkinnedMesh in library
2024 | if ( skinEntry ) {
2025 |
2026 | var getJointNode = function ( jointId ) {
2027 |
2028 | var keys = Object.keys( __nodes );
2029 |
2030 | for ( var i = 0, il = keys.length; i < il; i ++ ) {
2031 |
2032 | var n = __nodes[ keys[ i ] ];
2033 |
2034 | if ( n.jointName === jointId ) return n;
2035 |
2036 | }
2037 |
2038 | return null;
2039 |
2040 | };
2041 |
2042 | var geometry = originalGeometry;
2043 | var material = originalMaterial;
2044 | material.skinning = true;
2045 |
2046 | child = new THREE.SkinnedMesh( geometry, material );
2047 | child.castShadow = true;
2048 | child.userData = originalUserData;
2049 | child.name = originalName;
2050 |
2051 | var bones = [];
2052 | var boneInverses = [];
2053 |
2054 | for ( var i = 0, l = skinEntry.jointNames.length; i < l; i ++ ) {
2055 |
2056 | var jointId = skinEntry.jointNames[ i ];
2057 | var jointNode = getJointNode( jointId );
2058 |
2059 | if ( jointNode ) {
2060 |
2061 | bones.push( jointNode );
2062 |
2063 | var m = skinEntry.inverseBindMatrices.array;
2064 | var mat = new THREE.Matrix4().fromArray( m, i * 16 );
2065 | boneInverses.push( mat );
2066 |
2067 | } else {
2068 |
2069 | console.warn( "WARNING: joint: '" + jointId + "' could not be found" );
2070 |
2071 | }
2072 |
2073 | }
2074 |
2075 | child.bind( new THREE.Skeleton( bones, boneInverses ), skinEntry.bindShapeMatrix );
2076 |
2077 | var buildBoneGraph = function ( parentJson, parentObject, property ) {
2078 |
2079 | var children = parentJson[ property ];
2080 |
2081 | if ( children === undefined ) return;
2082 |
2083 | for ( var i = 0, il = children.length; i < il; i ++ ) {
2084 |
2085 | var nodeId = children[ i ];
2086 | var bone = __nodes[ nodeId ];
2087 | var boneJson = json.nodes[ nodeId ];
2088 |
2089 | if ( bone !== undefined && bone.isBone === true && boneJson !== undefined ) {
2090 |
2091 | parentObject.add( bone );
2092 | buildBoneGraph( boneJson, bone, 'children' );
2093 |
2094 | }
2095 |
2096 | }
2097 |
2098 | };
2099 |
2100 | buildBoneGraph( node, child, 'skeletons' );
2101 |
2102 | }
2103 |
2104 | _node.add( child );
2105 |
2106 | }
2107 |
2108 | }
2109 |
2110 | }
2111 |
2112 | if ( node.camera !== undefined ) {
2113 |
2114 | var camera = dependencies.cameras[ node.camera ];
2115 |
2116 | _node.add( camera );
2117 |
2118 | }
2119 |
2120 | if ( node.extensions
2121 | && node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ]
2122 | && node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ) {
2123 |
2124 | var extensionLights = extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].lights;
2125 | var light = extensionLights[ node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ];
2126 |
2127 | _node.add( light );
2128 |
2129 | }
2130 |
2131 | return _node;
2132 |
2133 | } );
2134 |
2135 | } );
2136 |
2137 | } );
2138 |
2139 | };
2140 |
2141 | GLTFParser.prototype.loadScenes = function () {
2142 |
2143 | var json = this.json;
2144 |
2145 | // scene node hierachy builder
2146 |
2147 | function buildNodeHierachy( nodeId, parentObject, allNodes ) {
2148 |
2149 | var _node = allNodes[ nodeId ];
2150 | parentObject.add( _node );
2151 |
2152 | var node = json.nodes[ nodeId ];
2153 |
2154 | if ( node.children ) {
2155 |
2156 | var children = node.children;
2157 |
2158 | for ( var i = 0, l = children.length; i < l; i ++ ) {
2159 |
2160 | var child = children[ i ];
2161 | buildNodeHierachy( child, _node, allNodes );
2162 |
2163 | }
2164 |
2165 | }
2166 |
2167 | }
2168 |
2169 | return this._withDependencies( [
2170 |
2171 | "nodes"
2172 |
2173 | ] ).then( function ( dependencies ) {
2174 |
2175 | return _each( json.scenes, function ( scene ) {
2176 |
2177 | var _scene = new THREE.Scene();
2178 | if ( scene.name !== undefined ) _scene.name = scene.name;
2179 |
2180 | if ( scene.extras ) _scene.userData = scene.extras;
2181 |
2182 | var nodes = scene.nodes || [];
2183 |
2184 | for ( var i = 0, l = nodes.length; i < l; i ++ ) {
2185 |
2186 | var nodeId = nodes[ i ];
2187 | buildNodeHierachy( nodeId, _scene, dependencies.nodes );
2188 |
2189 | }
2190 |
2191 | _scene.traverse( function ( child ) {
2192 |
2193 | // Register raw material meshes with LegacyGLTFLoader.Shaders
2194 | if ( child.material && child.material.isRawShaderMaterial ) {
2195 |
2196 | child.gltfShader = new GLTFShader( child, dependencies.nodes );
2197 | child.onBeforeRender = function(renderer, scene, camera){
2198 | this.gltfShader.update(scene, camera);
2199 | };
2200 |
2201 | }
2202 |
2203 | } );
2204 |
2205 | return _scene;
2206 |
2207 | } );
2208 |
2209 | } );
2210 |
2211 | };
2212 |
2213 | return LegacyGLTFLoader;
2214 |
2215 | } )();
2216 |
--------------------------------------------------------------------------------
/third_party/three.js/js/MTLLoader.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Loads a Wavefront .mtl file specifying materials
3 | *
4 | * @author angelxuanchang
5 | */
6 |
7 | THREE.MTLLoader = function ( manager ) {
8 |
9 | this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
10 |
11 | };
12 |
13 | THREE.MTLLoader.prototype = {
14 |
15 | constructor: THREE.MTLLoader,
16 |
17 | /**
18 | * Loads and parses a MTL asset from a URL.
19 | *
20 | * @param {String} url - URL to the MTL file.
21 | * @param {Function} [onLoad] - Callback invoked with the loaded object.
22 | * @param {Function} [onProgress] - Callback for download progress.
23 | * @param {Function} [onError] - Callback for download errors.
24 | *
25 | * @see setPath setTexturePath
26 | *
27 | * @note In order for relative texture references to resolve correctly
28 | * you must call setPath and/or setTexturePath explicitly prior to load.
29 | */
30 | load: function ( url, onLoad, onProgress, onError ) {
31 |
32 | var scope = this;
33 |
34 | var loader = new THREE.FileLoader( this.manager );
35 | loader.setPath( this.path );
36 | loader.load( url, function ( text ) {
37 |
38 | onLoad( scope.parse( text ) );
39 |
40 | }, onProgress, onError );
41 |
42 | },
43 |
44 | /**
45 | * Set base path for resolving references.
46 | * If set this path will be prepended to each loaded and found reference.
47 | *
48 | * @see setTexturePath
49 | * @param {String} path
50 | *
51 | * @example
52 | * mtlLoader.setPath( 'assets/obj/' );
53 | * mtlLoader.load( 'my.mtl', ... );
54 | */
55 | setPath: function ( path ) {
56 |
57 | this.path = path;
58 |
59 | },
60 |
61 | /**
62 | * Set base path for resolving texture references.
63 | * If set this path will be prepended found texture reference.
64 | * If not set and setPath is, it will be used as texture base path.
65 | *
66 | * @see setPath
67 | * @param {String} path
68 | *
69 | * @example
70 | * mtlLoader.setPath( 'assets/obj/' );
71 | * mtlLoader.setTexturePath( 'assets/textures/' );
72 | * mtlLoader.load( 'my.mtl', ... );
73 | */
74 | setTexturePath: function ( path ) {
75 |
76 | this.texturePath = path;
77 |
78 | },
79 |
80 | setBaseUrl: function ( path ) {
81 |
82 | console.warn( 'THREE.MTLLoader: .setBaseUrl() is deprecated. Use .setTexturePath( path ) for texture path or .setPath( path ) for general base path instead.' );
83 |
84 | this.setTexturePath( path );
85 |
86 | },
87 |
88 | setCrossOrigin: function ( value ) {
89 |
90 | this.crossOrigin = value;
91 |
92 | },
93 |
94 | setMaterialOptions: function ( value ) {
95 |
96 | this.materialOptions = value;
97 |
98 | },
99 |
100 | /**
101 | * Parses a MTL file.
102 | *
103 | * @param {String} text - Content of MTL file
104 | * @return {THREE.MTLLoader.MaterialCreator}
105 | *
106 | * @see setPath setTexturePath
107 | *
108 | * @note In order for relative texture references to resolve correctly
109 | * you must call setPath and/or setTexturePath explicitly prior to parse.
110 | */
111 | parse: function ( text ) {
112 |
113 | var lines = text.split( '\n' );
114 | var info = {};
115 | var delimiter_pattern = /\s+/;
116 | var materialsInfo = {};
117 |
118 | for ( var i = 0; i < lines.length; i ++ ) {
119 |
120 | var line = lines[ i ];
121 | line = line.trim();
122 |
123 | if ( line.length === 0 || line.charAt( 0 ) === '#' ) {
124 |
125 | // Blank line or comment ignore
126 | continue;
127 |
128 | }
129 |
130 | var pos = line.indexOf( ' ' );
131 |
132 | var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
133 | key = key.toLowerCase();
134 |
135 | var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : '';
136 | value = value.trim();
137 |
138 | if ( key === 'newmtl' ) {
139 |
140 | // New material
141 |
142 | info = { name: value };
143 | materialsInfo[ value ] = info;
144 |
145 | } else if ( info ) {
146 |
147 | if ( key === 'ka' || key === 'kd' || key === 'ks' ) {
148 |
149 | var ss = value.split( delimiter_pattern, 3 );
150 | info[ key ] = [ parseFloat( ss[ 0 ] ), parseFloat( ss[ 1 ] ), parseFloat( ss[ 2 ] ) ];
151 |
152 | } else {
153 |
154 | info[ key ] = value;
155 |
156 | }
157 |
158 | }
159 |
160 | }
161 |
162 | var materialCreator = new THREE.MTLLoader.MaterialCreator( this.texturePath || this.path, this.materialOptions );
163 | materialCreator.setCrossOrigin( this.crossOrigin );
164 | materialCreator.setManager( this.manager );
165 | materialCreator.setMaterials( materialsInfo );
166 | return materialCreator;
167 |
168 | }
169 |
170 | };
171 |
172 | /**
173 | * Create a new THREE-MTLLoader.MaterialCreator
174 | * @param baseUrl - Url relative to which textures are loaded
175 | * @param options - Set of options on how to construct the materials
176 | * side: Which side to apply the material
177 | * THREE.FrontSide (default), THREE.BackSide, THREE.DoubleSide
178 | * wrap: What type of wrapping to apply for textures
179 | * THREE.RepeatWrapping (default), THREE.ClampToEdgeWrapping, THREE.MirroredRepeatWrapping
180 | * normalizeRGB: RGBs need to be normalized to 0-1 from 0-255
181 | * Default: false, assumed to be already normalized
182 | * ignoreZeroRGBs: Ignore values of RGBs (Ka,Kd,Ks) that are all 0's
183 | * Default: false
184 | * @constructor
185 | */
186 |
187 | THREE.MTLLoader.MaterialCreator = function ( baseUrl, options ) {
188 |
189 | this.baseUrl = baseUrl || '';
190 | this.options = options;
191 | this.materialsInfo = {};
192 | this.materials = {};
193 | this.materialsArray = [];
194 | this.nameLookup = {};
195 |
196 | this.side = ( this.options && this.options.side ) ? this.options.side : THREE.FrontSide;
197 | this.wrap = ( this.options && this.options.wrap ) ? this.options.wrap : THREE.RepeatWrapping;
198 |
199 | };
200 |
201 | THREE.MTLLoader.MaterialCreator.prototype = {
202 |
203 | constructor: THREE.MTLLoader.MaterialCreator,
204 |
205 | crossOrigin: 'Anonymous',
206 |
207 | setCrossOrigin: function ( value ) {
208 |
209 | this.crossOrigin = value;
210 |
211 | },
212 |
213 | setManager: function ( value ) {
214 |
215 | this.manager = value;
216 |
217 | },
218 |
219 | setMaterials: function ( materialsInfo ) {
220 |
221 | this.materialsInfo = this.convert( materialsInfo );
222 | this.materials = {};
223 | this.materialsArray = [];
224 | this.nameLookup = {};
225 |
226 | },
227 |
228 | convert: function ( materialsInfo ) {
229 |
230 | if ( ! this.options ) return materialsInfo;
231 |
232 | var converted = {};
233 |
234 | for ( var mn in materialsInfo ) {
235 |
236 | // Convert materials info into normalized form based on options
237 |
238 | var mat = materialsInfo[ mn ];
239 |
240 | var covmat = {};
241 |
242 | converted[ mn ] = covmat;
243 |
244 | for ( var prop in mat ) {
245 |
246 | var save = true;
247 | var value = mat[ prop ];
248 | var lprop = prop.toLowerCase();
249 |
250 | switch ( lprop ) {
251 |
252 | case 'kd':
253 | case 'ka':
254 | case 'ks':
255 |
256 | // Diffuse color (color under white light) using RGB values
257 |
258 | if ( this.options && this.options.normalizeRGB ) {
259 |
260 | value = [ value[ 0 ] / 255, value[ 1 ] / 255, value[ 2 ] / 255 ];
261 |
262 | }
263 |
264 | if ( this.options && this.options.ignoreZeroRGBs ) {
265 |
266 | if ( value[ 0 ] === 0 && value[ 1 ] === 0 && value[ 2 ] === 0 ) {
267 |
268 | // ignore
269 |
270 | save = false;
271 |
272 | }
273 |
274 | }
275 |
276 | break;
277 |
278 | default:
279 |
280 | break;
281 |
282 | }
283 |
284 | if ( save ) {
285 |
286 | covmat[ lprop ] = value;
287 |
288 | }
289 |
290 | }
291 |
292 | }
293 |
294 | return converted;
295 |
296 | },
297 |
298 | preload: function () {
299 |
300 | for ( var mn in this.materialsInfo ) {
301 |
302 | this.create( mn );
303 |
304 | }
305 |
306 | },
307 |
308 | getIndex: function ( materialName ) {
309 |
310 | return this.nameLookup[ materialName ];
311 |
312 | },
313 |
314 | getAsArray: function () {
315 |
316 | var index = 0;
317 |
318 | for ( var mn in this.materialsInfo ) {
319 |
320 | this.materialsArray[ index ] = this.create( mn );
321 | this.nameLookup[ mn ] = index;
322 | index ++;
323 |
324 | }
325 |
326 | return this.materialsArray;
327 |
328 | },
329 |
330 | create: function ( materialName ) {
331 |
332 | if ( this.materials[ materialName ] === undefined ) {
333 |
334 | this.createMaterial_( materialName );
335 |
336 | }
337 |
338 | return this.materials[ materialName ];
339 |
340 | },
341 |
342 | createMaterial_: function ( materialName ) {
343 |
344 | // Create material
345 |
346 | var scope = this;
347 | var mat = this.materialsInfo[ materialName ];
348 | var params = {
349 |
350 | name: materialName,
351 | side: this.side
352 |
353 | };
354 |
355 | function resolveURL( baseUrl, url ) {
356 |
357 | if ( typeof url !== 'string' || url === '' )
358 | return '';
359 |
360 | // Absolute URL
361 | if ( /^https?:\/\//i.test( url ) ) return url;
362 |
363 | return baseUrl + url;
364 |
365 | }
366 |
367 | function setMapForType( mapType, value ) {
368 |
369 | if ( params[ mapType ] ) return; // Keep the first encountered texture
370 |
371 | var texParams = scope.getTextureParams( value, params );
372 | var map = scope.loadTexture( resolveURL( scope.baseUrl, texParams.url ) );
373 |
374 | map.repeat.copy( texParams.scale );
375 | map.offset.copy( texParams.offset );
376 |
377 | map.wrapS = scope.wrap;
378 | map.wrapT = scope.wrap;
379 |
380 | params[ mapType ] = map;
381 |
382 | }
383 |
384 | for ( var prop in mat ) {
385 |
386 | var value = mat[ prop ];
387 | var n;
388 |
389 | if ( value === '' ) continue;
390 |
391 | switch ( prop.toLowerCase() ) {
392 |
393 | // Ns is material specular exponent
394 |
395 | case 'kd':
396 |
397 | // Diffuse color (color under white light) using RGB values
398 |
399 | params.color = new THREE.Color().fromArray( value );
400 |
401 | break;
402 |
403 | case 'ks':
404 |
405 | // Specular color (color when light is reflected from shiny surface) using RGB values
406 | params.specular = new THREE.Color().fromArray( value );
407 |
408 | break;
409 |
410 | case 'map_kd':
411 |
412 | // Diffuse texture map
413 |
414 | setMapForType( "map", value );
415 |
416 | break;
417 |
418 | case 'map_ks':
419 |
420 | // Specular map
421 |
422 | setMapForType( "specularMap", value );
423 |
424 | break;
425 |
426 | case 'norm':
427 |
428 | setMapForType( "normalMap", value );
429 |
430 | break;
431 |
432 | case 'map_bump':
433 | case 'bump':
434 |
435 | // Bump texture map
436 |
437 | setMapForType( "bumpMap", value );
438 |
439 | break;
440 |
441 | case 'ns':
442 |
443 | // The specular exponent (defines the focus of the specular highlight)
444 | // A high exponent results in a tight, concentrated highlight. Ns values normally range from 0 to 1000.
445 |
446 | params.shininess = parseFloat( value );
447 |
448 | break;
449 |
450 | case 'd':
451 | n = parseFloat( value );
452 |
453 | if ( n < 1 ) {
454 |
455 | params.opacity = n;
456 | params.transparent = true;
457 |
458 | }
459 |
460 | break;
461 |
462 | case 'tr':
463 | n = parseFloat( value );
464 |
465 | if ( n > 0 ) {
466 |
467 | params.opacity = 1 - n;
468 | params.transparent = true;
469 |
470 | }
471 |
472 | break;
473 |
474 | default:
475 | break;
476 |
477 | }
478 |
479 | }
480 |
481 | this.materials[ materialName ] = new THREE.MeshPhongMaterial( params );
482 | return this.materials[ materialName ];
483 |
484 | },
485 |
486 | getTextureParams: function ( value, matParams ) {
487 |
488 | var texParams = {
489 |
490 | scale: new THREE.Vector2( 1, 1 ),
491 | offset: new THREE.Vector2( 0, 0 )
492 |
493 | };
494 |
495 | var items = value.split( /\s+/ );
496 | var pos;
497 |
498 | pos = items.indexOf( '-bm' );
499 |
500 | if ( pos >= 0 ) {
501 |
502 | matParams.bumpScale = parseFloat( items[ pos + 1 ] );
503 | items.splice( pos, 2 );
504 |
505 | }
506 |
507 | pos = items.indexOf( '-s' );
508 |
509 | if ( pos >= 0 ) {
510 |
511 | texParams.scale.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
512 | items.splice( pos, 4 ); // we expect 3 parameters here!
513 |
514 | }
515 |
516 | pos = items.indexOf( '-o' );
517 |
518 | if ( pos >= 0 ) {
519 |
520 | texParams.offset.set( parseFloat( items[ pos + 1 ] ), parseFloat( items[ pos + 2 ] ) );
521 | items.splice( pos, 4 ); // we expect 3 parameters here!
522 |
523 | }
524 |
525 | texParams.url = items.join( ' ' ).trim();
526 | return texParams;
527 |
528 | },
529 |
530 | loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
531 |
532 | var texture;
533 | var loader = THREE.Loader.Handlers.get( url );
534 | var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;
535 |
536 | if ( loader === null ) {
537 |
538 | loader = new THREE.TextureLoader( manager );
539 |
540 | }
541 |
542 | if ( loader.setCrossOrigin ) loader.setCrossOrigin( this.crossOrigin );
543 | texture = loader.load( url, onLoad, onProgress, onError );
544 |
545 | if ( mapping !== undefined ) texture.mapping = mapping;
546 |
547 | return texture;
548 |
549 | }
550 |
551 | };
552 |
--------------------------------------------------------------------------------
/third_party/three.js/js/OBJLoader.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author mrdoob / http://mrdoob.com/
3 | */
4 |
5 | THREE.OBJLoader = ( function () {
6 |
7 | // o object_name | g group_name
8 | var object_pattern = /^[og]\s*(.+)?/;
9 | // mtllib file_reference
10 | var material_library_pattern = /^mtllib /;
11 | // usemtl material_name
12 | var material_use_pattern = /^usemtl /;
13 |
14 | function ParserState() {
15 |
16 | var state = {
17 | objects: [],
18 | object: {},
19 |
20 | vertices: [],
21 | normals: [],
22 | colors: [],
23 | uvs: [],
24 |
25 | materialLibraries: [],
26 |
27 | startObject: function ( name, fromDeclaration ) {
28 |
29 | // If the current object (initial from reset) is not from a g/o declaration in the parsed
30 | // file. We need to use it for the first parsed g/o to keep things in sync.
31 | if ( this.object && this.object.fromDeclaration === false ) {
32 |
33 | this.object.name = name;
34 | this.object.fromDeclaration = ( fromDeclaration !== false );
35 | return;
36 |
37 | }
38 |
39 | var previousMaterial = ( this.object && typeof this.object.currentMaterial === 'function' ? this.object.currentMaterial() : undefined );
40 |
41 | if ( this.object && typeof this.object._finalize === 'function' ) {
42 |
43 | this.object._finalize( true );
44 |
45 | }
46 |
47 | this.object = {
48 | name: name || '',
49 | fromDeclaration: ( fromDeclaration !== false ),
50 |
51 | geometry: {
52 | vertices: [],
53 | normals: [],
54 | colors: [],
55 | uvs: []
56 | },
57 | materials: [],
58 | smooth: true,
59 |
60 | startMaterial: function ( name, libraries ) {
61 |
62 | var previous = this._finalize( false );
63 |
64 | // New usemtl declaration overwrites an inherited material, except if faces were declared
65 | // after the material, then it must be preserved for proper MultiMaterial continuation.
66 | if ( previous && ( previous.inherited || previous.groupCount <= 0 ) ) {
67 |
68 | this.materials.splice( previous.index, 1 );
69 |
70 | }
71 |
72 | var material = {
73 | index: this.materials.length,
74 | name: name || '',
75 | mtllib: ( Array.isArray( libraries ) && libraries.length > 0 ? libraries[ libraries.length - 1 ] : '' ),
76 | smooth: ( previous !== undefined ? previous.smooth : this.smooth ),
77 | groupStart: ( previous !== undefined ? previous.groupEnd : 0 ),
78 | groupEnd: - 1,
79 | groupCount: - 1,
80 | inherited: false,
81 |
82 | clone: function ( index ) {
83 |
84 | var cloned = {
85 | index: ( typeof index === 'number' ? index : this.index ),
86 | name: this.name,
87 | mtllib: this.mtllib,
88 | smooth: this.smooth,
89 | groupStart: 0,
90 | groupEnd: - 1,
91 | groupCount: - 1,
92 | inherited: false
93 | };
94 | cloned.clone = this.clone.bind( cloned );
95 | return cloned;
96 |
97 | }
98 | };
99 |
100 | this.materials.push( material );
101 |
102 | return material;
103 |
104 | },
105 |
106 | currentMaterial: function () {
107 |
108 | if ( this.materials.length > 0 ) {
109 |
110 | return this.materials[ this.materials.length - 1 ];
111 |
112 | }
113 |
114 | return undefined;
115 |
116 | },
117 |
118 | _finalize: function ( end ) {
119 |
120 | var lastMultiMaterial = this.currentMaterial();
121 | if ( lastMultiMaterial && lastMultiMaterial.groupEnd === - 1 ) {
122 |
123 | lastMultiMaterial.groupEnd = this.geometry.vertices.length / 3;
124 | lastMultiMaterial.groupCount = lastMultiMaterial.groupEnd - lastMultiMaterial.groupStart;
125 | lastMultiMaterial.inherited = false;
126 |
127 | }
128 |
129 | // Ignore objects tail materials if no face declarations followed them before a new o/g started.
130 | if ( end && this.materials.length > 1 ) {
131 |
132 | for ( var mi = this.materials.length - 1; mi >= 0; mi -- ) {
133 |
134 | if ( this.materials[ mi ].groupCount <= 0 ) {
135 |
136 | this.materials.splice( mi, 1 );
137 |
138 | }
139 |
140 | }
141 |
142 | }
143 |
144 | // Guarantee at least one empty material, this makes the creation later more straight forward.
145 | if ( end && this.materials.length === 0 ) {
146 |
147 | this.materials.push( {
148 | name: '',
149 | smooth: this.smooth
150 | } );
151 |
152 | }
153 |
154 | return lastMultiMaterial;
155 |
156 | }
157 | };
158 |
159 | // Inherit previous objects material.
160 | // Spec tells us that a declared material must be set to all objects until a new material is declared.
161 | // If a usemtl declaration is encountered while this new object is being parsed, it will
162 | // overwrite the inherited material. Exception being that there was already face declarations
163 | // to the inherited material, then it will be preserved for proper MultiMaterial continuation.
164 |
165 | if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {
166 |
167 | var declared = previousMaterial.clone( 0 );
168 | declared.inherited = true;
169 | this.object.materials.push( declared );
170 |
171 | }
172 |
173 | this.objects.push( this.object );
174 |
175 | },
176 |
177 | finalize: function () {
178 |
179 | if ( this.object && typeof this.object._finalize === 'function' ) {
180 |
181 | this.object._finalize( true );
182 |
183 | }
184 |
185 | },
186 |
187 | parseVertexIndex: function ( value, len ) {
188 |
189 | var index = parseInt( value, 10 );
190 | return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
191 |
192 | },
193 |
194 | parseNormalIndex: function ( value, len ) {
195 |
196 | var index = parseInt( value, 10 );
197 | return ( index >= 0 ? index - 1 : index + len / 3 ) * 3;
198 |
199 | },
200 |
201 | parseUVIndex: function ( value, len ) {
202 |
203 | var index = parseInt( value, 10 );
204 | return ( index >= 0 ? index - 1 : index + len / 2 ) * 2;
205 |
206 | },
207 |
208 | addVertex: function ( a, b, c ) {
209 |
210 | var src = this.vertices;
211 | var dst = this.object.geometry.vertices;
212 |
213 | dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
214 | dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
215 | dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
216 |
217 | },
218 |
219 | addVertexLine: function ( a ) {
220 |
221 | var src = this.vertices;
222 | var dst = this.object.geometry.vertices;
223 |
224 | dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
225 |
226 | },
227 |
228 | addNormal: function ( a, b, c ) {
229 |
230 | var src = this.normals;
231 | var dst = this.object.geometry.normals;
232 |
233 | dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
234 | dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
235 | dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
236 |
237 | },
238 |
239 | addColor: function ( a, b, c ) {
240 |
241 | var src = this.colors;
242 | var dst = this.object.geometry.colors;
243 |
244 | dst.push( src[ a + 0 ], src[ a + 1 ], src[ a + 2 ] );
245 | dst.push( src[ b + 0 ], src[ b + 1 ], src[ b + 2 ] );
246 | dst.push( src[ c + 0 ], src[ c + 1 ], src[ c + 2 ] );
247 |
248 | },
249 |
250 | addUV: function ( a, b, c ) {
251 |
252 | var src = this.uvs;
253 | var dst = this.object.geometry.uvs;
254 |
255 | dst.push( src[ a + 0 ], src[ a + 1 ] );
256 | dst.push( src[ b + 0 ], src[ b + 1 ] );
257 | dst.push( src[ c + 0 ], src[ c + 1 ] );
258 |
259 | },
260 |
261 | addUVLine: function ( a ) {
262 |
263 | var src = this.uvs;
264 | var dst = this.object.geometry.uvs;
265 |
266 | dst.push( src[ a + 0 ], src[ a + 1 ] );
267 |
268 | },
269 |
270 | addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {
271 |
272 | var vLen = this.vertices.length;
273 |
274 | var ia = this.parseVertexIndex( a, vLen );
275 | var ib = this.parseVertexIndex( b, vLen );
276 | var ic = this.parseVertexIndex( c, vLen );
277 |
278 | this.addVertex( ia, ib, ic );
279 |
280 | if ( ua !== undefined ) {
281 |
282 | var uvLen = this.uvs.length;
283 |
284 | ia = this.parseUVIndex( ua, uvLen );
285 | ib = this.parseUVIndex( ub, uvLen );
286 | ic = this.parseUVIndex( uc, uvLen );
287 |
288 | this.addUV( ia, ib, ic );
289 |
290 | }
291 |
292 | if ( na !== undefined ) {
293 |
294 | // Normals are many times the same. If so, skip function call and parseInt.
295 | var nLen = this.normals.length;
296 | ia = this.parseNormalIndex( na, nLen );
297 |
298 | ib = na === nb ? ia : this.parseNormalIndex( nb, nLen );
299 | ic = na === nc ? ia : this.parseNormalIndex( nc, nLen );
300 |
301 | this.addNormal( ia, ib, ic );
302 |
303 | }
304 |
305 | if ( this.colors.length > 0 ) {
306 |
307 | this.addColor( ia, ib, ic );
308 |
309 | }
310 |
311 | },
312 |
313 | addLineGeometry: function ( vertices, uvs ) {
314 |
315 | this.object.geometry.type = 'Line';
316 |
317 | var vLen = this.vertices.length;
318 | var uvLen = this.uvs.length;
319 |
320 | for ( var vi = 0, l = vertices.length; vi < l; vi ++ ) {
321 |
322 | this.addVertexLine( this.parseVertexIndex( vertices[ vi ], vLen ) );
323 |
324 | }
325 |
326 | for ( var uvi = 0, l = uvs.length; uvi < l; uvi ++ ) {
327 |
328 | this.addUVLine( this.parseUVIndex( uvs[ uvi ], uvLen ) );
329 |
330 | }
331 |
332 | }
333 |
334 | };
335 |
336 | state.startObject( '', false );
337 |
338 | return state;
339 |
340 | }
341 |
342 | //
343 |
344 | function OBJLoader( manager ) {
345 |
346 | this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
347 |
348 | this.materials = null;
349 |
350 | }
351 |
352 | OBJLoader.prototype = {
353 |
354 | constructor: OBJLoader,
355 |
356 | load: function ( url, onLoad, onProgress, onError ) {
357 |
358 | var scope = this;
359 |
360 | var loader = new THREE.FileLoader( scope.manager );
361 | loader.setPath( this.path );
362 | loader.load( url, function ( text ) {
363 |
364 | onLoad( scope.parse( text ) );
365 |
366 | }, onProgress, onError );
367 |
368 | },
369 |
370 | setPath: function ( value ) {
371 |
372 | this.path = value;
373 |
374 | },
375 |
376 | setMaterials: function ( materials ) {
377 |
378 | this.materials = materials;
379 |
380 | return this;
381 |
382 | },
383 |
384 | parse: function ( text ) {
385 |
386 | console.time( 'OBJLoader' );
387 |
388 | var state = new ParserState();
389 |
390 | if ( text.indexOf( '\r\n' ) !== - 1 ) {
391 |
392 | // This is faster than String.split with regex that splits on both
393 | text = text.replace( /\r\n/g, '\n' );
394 |
395 | }
396 |
397 | if ( text.indexOf( '\\\n' ) !== - 1 ) {
398 |
399 | // join lines separated by a line continuation character (\)
400 | text = text.replace( /\\\n/g, '' );
401 |
402 | }
403 |
404 | var lines = text.split( '\n' );
405 | var line = '', lineFirstChar = '';
406 | var lineLength = 0;
407 | var result = [];
408 |
409 | // Faster to just trim left side of the line. Use if available.
410 | var trimLeft = ( typeof ''.trimLeft === 'function' );
411 |
412 | for ( var i = 0, l = lines.length; i < l; i ++ ) {
413 |
414 | line = lines[ i ];
415 |
416 | line = trimLeft ? line.trimLeft() : line.trim();
417 |
418 | lineLength = line.length;
419 |
420 | if ( lineLength === 0 ) continue;
421 |
422 | lineFirstChar = line.charAt( 0 );
423 |
424 | // @todo invoke passed in handler if any
425 | if ( lineFirstChar === '#' ) continue;
426 |
427 | if ( lineFirstChar === 'v' ) {
428 |
429 | var data = line.split( /\s+/ );
430 |
431 | switch ( data[ 0 ] ) {
432 |
433 | case 'v':
434 | state.vertices.push(
435 | parseFloat( data[ 1 ] ),
436 | parseFloat( data[ 2 ] ),
437 | parseFloat( data[ 3 ] )
438 | );
439 | if ( data.length === 8 ) {
440 |
441 | state.colors.push(
442 | parseFloat( data[ 4 ] ),
443 | parseFloat( data[ 5 ] ),
444 | parseFloat( data[ 6 ] )
445 |
446 | );
447 |
448 | }
449 | break;
450 | case 'vn':
451 | state.normals.push(
452 | parseFloat( data[ 1 ] ),
453 | parseFloat( data[ 2 ] ),
454 | parseFloat( data[ 3 ] )
455 | );
456 | break;
457 | case 'vt':
458 | state.uvs.push(
459 | parseFloat( data[ 1 ] ),
460 | parseFloat( data[ 2 ] )
461 | );
462 | break;
463 |
464 | }
465 |
466 | } else if ( lineFirstChar === 'f' ) {
467 |
468 | var lineData = line.substr( 1 ).trim();
469 | var vertexData = lineData.split( /\s+/ );
470 | var faceVertices = [];
471 |
472 | // Parse the face vertex data into an easy to work with format
473 |
474 | for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) {
475 |
476 | var vertex = vertexData[ j ];
477 |
478 | if ( vertex.length > 0 ) {
479 |
480 | var vertexParts = vertex.split( '/' );
481 | faceVertices.push( vertexParts );
482 |
483 | }
484 |
485 | }
486 |
487 | // Draw an edge between the first vertex and all subsequent vertices to form an n-gon
488 |
489 | var v1 = faceVertices[ 0 ];
490 |
491 | for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
492 |
493 | var v2 = faceVertices[ j ];
494 | var v3 = faceVertices[ j + 1 ];
495 |
496 | state.addFace(
497 | v1[ 0 ], v2[ 0 ], v3[ 0 ],
498 | v1[ 1 ], v2[ 1 ], v3[ 1 ],
499 | v1[ 2 ], v2[ 2 ], v3[ 2 ]
500 | );
501 |
502 | }
503 |
504 | } else if ( lineFirstChar === 'l' ) {
505 |
506 | var lineParts = line.substring( 1 ).trim().split( " " );
507 | var lineVertices = [], lineUVs = [];
508 |
509 | if ( line.indexOf( "/" ) === - 1 ) {
510 |
511 | lineVertices = lineParts;
512 |
513 | } else {
514 |
515 | for ( var li = 0, llen = lineParts.length; li < llen; li ++ ) {
516 |
517 | var parts = lineParts[ li ].split( "/" );
518 |
519 | if ( parts[ 0 ] !== "" ) lineVertices.push( parts[ 0 ] );
520 | if ( parts[ 1 ] !== "" ) lineUVs.push( parts[ 1 ] );
521 |
522 | }
523 |
524 | }
525 | state.addLineGeometry( lineVertices, lineUVs );
526 |
527 | } else if ( ( result = object_pattern.exec( line ) ) !== null ) {
528 |
529 | // o object_name
530 | // or
531 | // g group_name
532 |
533 | // WORKAROUND: https://bugs.chromium.org/p/v8/issues/detail?id=2869
534 | // var name = result[ 0 ].substr( 1 ).trim();
535 | var name = ( " " + result[ 0 ].substr( 1 ).trim() ).substr( 1 );
536 |
537 | state.startObject( name );
538 |
539 | } else if ( material_use_pattern.test( line ) ) {
540 |
541 | // material
542 |
543 | state.object.startMaterial( line.substring( 7 ).trim(), state.materialLibraries );
544 |
545 | } else if ( material_library_pattern.test( line ) ) {
546 |
547 | // mtl file
548 |
549 | state.materialLibraries.push( line.substring( 7 ).trim() );
550 |
551 | } else if ( lineFirstChar === 's' ) {
552 |
553 | result = line.split( ' ' );
554 |
555 | // smooth shading
556 |
557 | // @todo Handle files that have varying smooth values for a set of faces inside one geometry,
558 | // but does not define a usemtl for each face set.
559 | // This should be detected and a dummy material created (later MultiMaterial and geometry groups).
560 | // This requires some care to not create extra material on each smooth value for "normal" obj files.
561 | // where explicit usemtl defines geometry groups.
562 | // Example asset: examples/models/obj/cerberus/Cerberus.obj
563 |
564 | /*
565 | * http://paulbourke.net/dataformats/obj/
566 | * or
567 | * http://www.cs.utah.edu/~boulos/cs3505/obj_spec.pdf
568 | *
569 | * From chapter "Grouping" Syntax explanation "s group_number":
570 | * "group_number is the smoothing group number. To turn off smoothing groups, use a value of 0 or off.
571 | * Polygonal elements use group numbers to put elements in different smoothing groups. For free-form
572 | * surfaces, smoothing groups are either turned on or off; there is no difference between values greater
573 | * than 0."
574 | */
575 | if ( result.length > 1 ) {
576 |
577 | var value = result[ 1 ].trim().toLowerCase();
578 | state.object.smooth = ( value !== '0' && value !== 'off' );
579 |
580 | } else {
581 |
582 | // ZBrush can produce "s" lines #11707
583 | state.object.smooth = true;
584 |
585 | }
586 | var material = state.object.currentMaterial();
587 | if ( material ) material.smooth = state.object.smooth;
588 |
589 | } else {
590 |
591 | // Handle null terminated files without exception
592 | if ( line === '\0' ) continue;
593 |
594 | throw new Error( 'THREE.OBJLoader: Unexpected line: "' + line + '"' );
595 |
596 | }
597 |
598 | }
599 |
600 | state.finalize();
601 |
602 | var container = new THREE.Group();
603 | container.materialLibraries = [].concat( state.materialLibraries );
604 |
605 | for ( var i = 0, l = state.objects.length; i < l; i ++ ) {
606 |
607 | var object = state.objects[ i ];
608 | var geometry = object.geometry;
609 | var materials = object.materials;
610 | var isLine = ( geometry.type === 'Line' );
611 |
612 | // Skip o/g line declarations that did not follow with any faces
613 | if ( geometry.vertices.length === 0 ) continue;
614 |
615 | var buffergeometry = new THREE.BufferGeometry();
616 |
617 | buffergeometry.addAttribute( 'position', new THREE.Float32BufferAttribute( geometry.vertices, 3 ) );
618 |
619 | if ( geometry.normals.length > 0 ) {
620 |
621 | buffergeometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( geometry.normals, 3 ) );
622 |
623 | } else {
624 |
625 | buffergeometry.computeVertexNormals();
626 |
627 | }
628 |
629 | if ( geometry.colors.length > 0 ) {
630 |
631 | buffergeometry.addAttribute( 'color', new THREE.Float32BufferAttribute( geometry.colors, 3 ) );
632 |
633 | }
634 |
635 | if ( geometry.uvs.length > 0 ) {
636 |
637 | buffergeometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( geometry.uvs, 2 ) );
638 |
639 | }
640 |
641 | // Create materials
642 |
643 | var createdMaterials = [];
644 |
645 | for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
646 |
647 | var sourceMaterial = materials[ mi ];
648 | var material = undefined;
649 |
650 | if ( this.materials !== null ) {
651 |
652 | material = this.materials.create( sourceMaterial.name );
653 |
654 | // mtl etc. loaders probably can't create line materials correctly, copy properties to a line material.
655 | if ( isLine && material && ! ( material instanceof THREE.LineBasicMaterial ) ) {
656 |
657 | var materialLine = new THREE.LineBasicMaterial();
658 | materialLine.copy( material );
659 | materialLine.lights = false; // TOFIX
660 | material = materialLine;
661 |
662 | }
663 |
664 | }
665 |
666 | if ( ! material ) {
667 |
668 | material = ( ! isLine ? new THREE.MeshPhongMaterial() : new THREE.LineBasicMaterial() );
669 | material.name = sourceMaterial.name;
670 |
671 | }
672 |
673 | material.flatShading = sourceMaterial.smooth ? false : true;
674 |
675 | createdMaterials.push( material );
676 |
677 | }
678 |
679 | // Create mesh
680 |
681 | var mesh;
682 |
683 | if ( createdMaterials.length > 1 ) {
684 |
685 | for ( var mi = 0, miLen = materials.length; mi < miLen; mi ++ ) {
686 |
687 | var sourceMaterial = materials[ mi ];
688 | buffergeometry.addGroup( sourceMaterial.groupStart, sourceMaterial.groupCount, mi );
689 |
690 | }
691 |
692 | mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, createdMaterials ) : new THREE.LineSegments( buffergeometry, createdMaterials ) );
693 |
694 | } else {
695 |
696 | mesh = ( ! isLine ? new THREE.Mesh( buffergeometry, createdMaterials[ 0 ] ) : new THREE.LineSegments( buffergeometry, createdMaterials[ 0 ] ) );
697 |
698 | }
699 |
700 | mesh.name = object.name;
701 |
702 | container.add( mesh );
703 |
704 | }
705 |
706 | console.timeEnd( 'OBJLoader' );
707 |
708 | return container;
709 |
710 | }
711 |
712 | };
713 |
714 | return OBJLoader;
715 |
716 | } )();
717 |
--------------------------------------------------------------------------------
/tiltbrush-sample.html:
--------------------------------------------------------------------------------
1 |
2 |
19 |
20 |
21 |
22 |
23 |
24 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | Title
56 | by Author
57 |
58 |
59 |
60 |
61 |
143 |
144 |
145 |
--------------------------------------------------------------------------------