@inweb/viewer-three 26.9.3 → 26.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/plugins/components/AxesHelperComponent.js +23 -22
  2. package/dist/plugins/components/AxesHelperComponent.js.map +1 -1
  3. package/dist/plugins/components/AxesHelperComponent.min.js +23 -0
  4. package/dist/plugins/components/AxesHelperComponent.module.js +31 -9
  5. package/dist/plugins/components/AxesHelperComponent.module.js.map +1 -1
  6. package/dist/plugins/components/ExtentsHelperComponent.js +23 -22
  7. package/dist/plugins/components/ExtentsHelperComponent.js.map +1 -1
  8. package/dist/plugins/components/ExtentsHelperComponent.min.js +23 -0
  9. package/dist/plugins/components/ExtentsHelperComponent.module.js +28 -6
  10. package/dist/plugins/components/ExtentsHelperComponent.module.js.map +1 -1
  11. package/dist/plugins/components/LightHelperComponent.js +23 -22
  12. package/dist/plugins/components/LightHelperComponent.js.map +1 -1
  13. package/dist/plugins/components/LightHelperComponent.min.js +23 -0
  14. package/dist/plugins/components/LightHelperComponent.module.js +35 -9
  15. package/dist/plugins/components/LightHelperComponent.module.js.map +1 -1
  16. package/dist/plugins/components/RoomEnvironmentComponent.js +23 -97
  17. package/dist/plugins/components/RoomEnvironmentComponent.js.map +1 -1
  18. package/dist/plugins/components/RoomEnvironmentComponent.min.js +23 -0
  19. package/dist/plugins/components/RoomEnvironmentComponent.module.js +27 -7
  20. package/dist/plugins/components/RoomEnvironmentComponent.module.js.map +1 -1
  21. package/dist/plugins/components/StatsPanelComponent.js +23 -92
  22. package/dist/plugins/components/StatsPanelComponent.js.map +1 -1
  23. package/dist/plugins/components/StatsPanelComponent.min.js +23 -0
  24. package/dist/plugins/components/StatsPanelComponent.module.js +26 -5
  25. package/dist/plugins/components/StatsPanelComponent.module.js.map +1 -1
  26. package/dist/plugins/loaders/GLTFCloudLoader.js +31 -2515
  27. package/dist/plugins/loaders/GLTFCloudLoader.js.map +1 -1
  28. package/dist/plugins/loaders/GLTFCloudLoader.min.js +23 -0
  29. package/dist/plugins/loaders/GLTFCloudLoader.module.js +35 -20
  30. package/dist/plugins/loaders/GLTFCloudLoader.module.js.map +1 -1
  31. package/dist/plugins/loaders/IFCXLoader.js +35 -689
  32. package/dist/plugins/loaders/IFCXLoader.js.map +1 -1
  33. package/dist/plugins/loaders/IFCXLoader.min.js +23 -0
  34. package/dist/plugins/loaders/IFCXLoader.module.js +833 -859
  35. package/dist/plugins/loaders/IFCXLoader.module.js.map +1 -1
  36. package/dist/plugins/loaders/PotreeLoader.js +26 -70
  37. package/dist/plugins/loaders/PotreeLoader.js.map +1 -1
  38. package/dist/plugins/loaders/PotreeLoader.min.js +23 -0
  39. package/dist/plugins/loaders/PotreeLoader.module.js +37 -15
  40. package/dist/plugins/loaders/PotreeLoader.module.js.map +1 -1
  41. package/dist/viewer-three.js +1502 -55140
  42. package/dist/viewer-three.js.map +1 -1
  43. package/dist/viewer-three.min.js +26 -3
  44. package/dist/viewer-three.module.js +3584 -3660
  45. package/dist/viewer-three.module.js.map +1 -1
  46. package/package.json +5 -5
@@ -1,652 +1,301 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
3
+ // All rights reserved.
4
+ //
5
+ // This software and its documentation and related materials are owned by
6
+ // the Alliance. The software may only be incorporated into application
7
+ // programs owned by members of the Alliance, subject to a signed
8
+ // Membership Agreement and Supplemental Software License Agreement with the
9
+ // Alliance. The structure and organization of this software are the valuable
10
+ // trade secrets of the Alliance and its suppliers. The software is also
11
+ // protected by copyright law and international treaty provisions. Application
12
+ // programs incorporating this software must include the following statement
13
+ // with their copyright notices:
14
+ //
15
+ // This application incorporates Open Design Alliance software pursuant to a
16
+ // license agreement with Open Design Alliance.
17
+ // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
18
+ // All rights reserved.
19
+ //
20
+ // By use of this software, its documentation or related materials, you
21
+ // acknowledge and accept the above terms.
22
+ ///////////////////////////////////////////////////////////////////////////////
23
+
1
24
  (function (global, factory) {
2
25
  typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('three'), require('@inweb/viewer-three')) :
3
26
  typeof define === 'function' && define.amd ? define(['three', '@inweb/viewer-three'], factory) :
4
27
  (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.THREE, global.ODA.Three));
5
28
  })(this, (function (three, viewerThree) { 'use strict';
6
29
 
7
- /**
8
- * Returns a new indexed geometry based on `TrianglesDrawMode` draw mode.
9
- * This mode corresponds to the `gl.TRIANGLES` primitive in WebGL.
10
- *
11
- * @param {BufferGeometry} geometry - The geometry to convert.
12
- * @param {number} drawMode - The current draw mode.
13
- * @return {BufferGeometry} The new geometry using `TrianglesDrawMode`.
14
- */
15
30
  function toTrianglesDrawMode( geometry, drawMode ) {
16
-
17
31
  if ( drawMode === three.TrianglesDrawMode ) {
18
-
19
32
  console.warn( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.' );
20
33
  return geometry;
21
-
22
34
  }
23
-
24
35
  if ( drawMode === three.TriangleFanDrawMode || drawMode === three.TriangleStripDrawMode ) {
25
-
26
36
  let index = geometry.getIndex();
27
-
28
- // generate index if not present
29
-
30
37
  if ( index === null ) {
31
-
32
38
  const indices = [];
33
-
34
39
  const position = geometry.getAttribute( 'position' );
35
-
36
40
  if ( position !== undefined ) {
37
-
38
41
  for ( let i = 0; i < position.count; i ++ ) {
39
-
40
42
  indices.push( i );
41
-
42
43
  }
43
-
44
44
  geometry.setIndex( indices );
45
45
  index = geometry.getIndex();
46
-
47
46
  } else {
48
-
49
47
  console.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );
50
48
  return geometry;
51
-
52
49
  }
53
-
54
50
  }
55
-
56
- //
57
-
58
51
  const numberOfTriangles = index.count - 2;
59
52
  const newIndices = [];
60
-
61
53
  if ( drawMode === three.TriangleFanDrawMode ) {
62
-
63
- // gl.TRIANGLE_FAN
64
-
65
54
  for ( let i = 1; i <= numberOfTriangles; i ++ ) {
66
-
67
55
  newIndices.push( index.getX( 0 ) );
68
56
  newIndices.push( index.getX( i ) );
69
57
  newIndices.push( index.getX( i + 1 ) );
70
-
71
58
  }
72
-
73
59
  } else {
74
-
75
- // gl.TRIANGLE_STRIP
76
-
77
60
  for ( let i = 0; i < numberOfTriangles; i ++ ) {
78
-
79
61
  if ( i % 2 === 0 ) {
80
-
81
62
  newIndices.push( index.getX( i ) );
82
63
  newIndices.push( index.getX( i + 1 ) );
83
64
  newIndices.push( index.getX( i + 2 ) );
84
-
85
65
  } else {
86
-
87
66
  newIndices.push( index.getX( i + 2 ) );
88
67
  newIndices.push( index.getX( i + 1 ) );
89
68
  newIndices.push( index.getX( i ) );
90
-
91
69
  }
92
-
93
70
  }
94
-
95
71
  }
96
-
97
72
  if ( ( newIndices.length / 3 ) !== numberOfTriangles ) {
98
-
99
73
  console.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );
100
-
101
74
  }
102
-
103
- // build final geometry
104
-
105
75
  const newGeometry = geometry.clone();
106
76
  newGeometry.setIndex( newIndices );
107
77
  newGeometry.clearGroups();
108
-
109
78
  return newGeometry;
110
-
111
79
  } else {
112
-
113
80
  console.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:', drawMode );
114
81
  return geometry;
115
-
116
82
  }
117
-
118
83
  }
119
84
 
120
- /**
121
- * A loader for the glTF 2.0 format.
122
- *
123
- * [glTF]{@link https://www.khronos.org/gltf/} (GL Transmission Format) is an [open format specification]{@link https://github.com/KhronosGroup/glTF/tree/main/specification/2.0}
124
- * for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf) or binary (.glb)
125
- * format. External files store textures (.jpg, .png) and additional binary data (.bin). A glTF asset may deliver
126
- * one or more scenes, including meshes, materials, textures, skins, skeletons, morph targets, animations, lights,
127
- * and/or cameras.
128
- *
129
- * `GLTFLoader` uses {@link ImageBitmapLoader} whenever possible. Be advised that image bitmaps are not
130
- * automatically GC-collected when they are no longer referenced, and they require special handling during
131
- * the disposal process.
132
- *
133
- * `GLTFLoader` supports the following glTF 2.0 extensions:
134
- * - KHR_draco_mesh_compression
135
- * - KHR_materials_clearcoat
136
- * - KHR_materials_dispersion
137
- * - KHR_materials_ior
138
- * - KHR_materials_specular
139
- * - KHR_materials_transmission
140
- * - KHR_materials_iridescence
141
- * - KHR_materials_unlit
142
- * - KHR_materials_volume
143
- * - KHR_mesh_quantization
144
- * - KHR_lights_punctual
145
- * - KHR_texture_basisu
146
- * - KHR_texture_transform
147
- * - EXT_texture_webp
148
- * - EXT_meshopt_compression
149
- * - EXT_mesh_gpu_instancing
150
- *
151
- * The following glTF 2.0 extension is supported by an external user plugin:
152
- * - [KHR_materials_variants]{@link https://github.com/takahirox/three-gltf-extensions}
153
- * - [MSFT_texture_dds]{@link https://github.com/takahirox/three-gltf-extensions}
154
- *
155
- * ```js
156
- * const loader = new GLTFLoader();
157
- *
158
- * // Optional: Provide a DRACOLoader instance to decode compressed mesh data
159
- * const dracoLoader = new DRACOLoader();
160
- * dracoLoader.setDecoderPath( '/examples/jsm/libs/draco/' );
161
- * loader.setDRACOLoader( dracoLoader );
162
- *
163
- * const gltf = await loader.loadAsync( 'models/gltf/duck/duck.gltf' );
164
- * scene.add( gltf.scene );
165
- * ```
166
- *
167
- * @augments Loader
168
- * @three_import import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
169
- */
170
85
  class GLTFLoader extends three.Loader {
171
-
172
- /**
173
- * Constructs a new glTF loader.
174
- *
175
- * @param {LoadingManager} [manager] - The loading manager.
176
- */
177
86
  constructor( manager ) {
178
-
179
87
  super( manager );
180
-
181
88
  this.dracoLoader = null;
182
89
  this.ktx2Loader = null;
183
90
  this.meshoptDecoder = null;
184
-
185
91
  this.pluginCallbacks = [];
186
-
187
92
  this.register( function ( parser ) {
188
-
189
93
  return new GLTFMaterialsClearcoatExtension( parser );
190
-
191
94
  } );
192
-
193
95
  this.register( function ( parser ) {
194
-
195
96
  return new GLTFMaterialsDispersionExtension( parser );
196
-
197
97
  } );
198
-
199
98
  this.register( function ( parser ) {
200
-
201
99
  return new GLTFTextureBasisUExtension( parser );
202
-
203
100
  } );
204
-
205
101
  this.register( function ( parser ) {
206
-
207
102
  return new GLTFTextureWebPExtension( parser );
208
-
209
103
  } );
210
-
211
104
  this.register( function ( parser ) {
212
-
213
105
  return new GLTFTextureAVIFExtension( parser );
214
-
215
106
  } );
216
-
217
107
  this.register( function ( parser ) {
218
-
219
108
  return new GLTFMaterialsSheenExtension( parser );
220
-
221
109
  } );
222
-
223
110
  this.register( function ( parser ) {
224
-
225
111
  return new GLTFMaterialsTransmissionExtension( parser );
226
-
227
112
  } );
228
-
229
113
  this.register( function ( parser ) {
230
-
231
114
  return new GLTFMaterialsVolumeExtension( parser );
232
-
233
115
  } );
234
-
235
116
  this.register( function ( parser ) {
236
-
237
117
  return new GLTFMaterialsIorExtension( parser );
238
-
239
118
  } );
240
-
241
119
  this.register( function ( parser ) {
242
-
243
120
  return new GLTFMaterialsEmissiveStrengthExtension( parser );
244
-
245
121
  } );
246
-
247
122
  this.register( function ( parser ) {
248
-
249
123
  return new GLTFMaterialsSpecularExtension( parser );
250
-
251
124
  } );
252
-
253
125
  this.register( function ( parser ) {
254
-
255
126
  return new GLTFMaterialsIridescenceExtension( parser );
256
-
257
127
  } );
258
-
259
128
  this.register( function ( parser ) {
260
-
261
129
  return new GLTFMaterialsAnisotropyExtension( parser );
262
-
263
130
  } );
264
-
265
131
  this.register( function ( parser ) {
266
-
267
132
  return new GLTFMaterialsBumpExtension( parser );
268
-
269
133
  } );
270
-
271
134
  this.register( function ( parser ) {
272
-
273
135
  return new GLTFLightsExtension( parser );
274
-
275
136
  } );
276
-
277
137
  this.register( function ( parser ) {
278
-
279
138
  return new GLTFMeshoptCompression( parser );
280
-
281
139
  } );
282
-
283
140
  this.register( function ( parser ) {
284
-
285
141
  return new GLTFMeshGpuInstancing( parser );
286
-
287
142
  } );
288
-
289
143
  }
290
-
291
- /**
292
- * Starts loading from the given URL and passes the loaded glTF asset
293
- * to the `onLoad()` callback.
294
- *
295
- * @param {string} url - The path/URL of the file to be loaded. This can also be a data URI.
296
- * @param {function(GLTFLoader~LoadObject)} onLoad - Executed when the loading process has been finished.
297
- * @param {onProgressCallback} onProgress - Executed while the loading is in progress.
298
- * @param {onErrorCallback} onError - Executed when errors occur.
299
- */
300
144
  load( url, onLoad, onProgress, onError ) {
301
-
302
145
  const scope = this;
303
-
304
146
  let resourcePath;
305
-
306
147
  if ( this.resourcePath !== '' ) {
307
-
308
148
  resourcePath = this.resourcePath;
309
-
310
149
  } else if ( this.path !== '' ) {
311
-
312
- // If a base path is set, resources will be relative paths from that plus the relative path of the gltf file
313
- // Example path = 'https://my-cnd-server.com/', url = 'assets/models/model.gltf'
314
- // resourcePath = 'https://my-cnd-server.com/assets/models/'
315
- // referenced resource 'model.bin' will be loaded from 'https://my-cnd-server.com/assets/models/model.bin'
316
- // referenced resource '../textures/texture.png' will be loaded from 'https://my-cnd-server.com/assets/textures/texture.png'
317
150
  const relativeUrl = three.LoaderUtils.extractUrlBase( url );
318
151
  resourcePath = three.LoaderUtils.resolveURL( relativeUrl, this.path );
319
-
320
152
  } else {
321
-
322
153
  resourcePath = three.LoaderUtils.extractUrlBase( url );
323
-
324
154
  }
325
-
326
- // Tells the LoadingManager to track an extra item, which resolves after
327
- // the model is fully loaded. This means the count of items loaded will
328
- // be incorrect, but ensures manager.onLoad() does not fire early.
329
155
  this.manager.itemStart( url );
330
-
331
156
  const _onError = function ( e ) {
332
-
333
157
  if ( onError ) {
334
-
335
158
  onError( e );
336
-
337
159
  } else {
338
-
339
160
  console.error( e );
340
-
341
161
  }
342
-
343
162
  scope.manager.itemError( url );
344
163
  scope.manager.itemEnd( url );
345
-
346
164
  };
347
-
348
165
  const loader = new three.FileLoader( this.manager );
349
-
350
166
  loader.setPath( this.path );
351
167
  loader.setResponseType( 'arraybuffer' );
352
168
  loader.setRequestHeader( this.requestHeader );
353
169
  loader.setWithCredentials( this.withCredentials );
354
-
355
170
  loader.load( url, function ( data ) {
356
-
357
171
  try {
358
-
359
172
  scope.parse( data, resourcePath, function ( gltf ) {
360
-
361
173
  onLoad( gltf );
362
-
363
174
  scope.manager.itemEnd( url );
364
-
365
175
  }, _onError );
366
-
367
176
  } catch ( e ) {
368
-
369
177
  _onError( e );
370
-
371
178
  }
372
-
373
179
  }, onProgress, _onError );
374
-
375
180
  }
376
-
377
- /**
378
- * Sets the given Draco loader to this loader. Required for decoding assets
379
- * compressed with the `KHR_draco_mesh_compression` extension.
380
- *
381
- * @param {DRACOLoader} dracoLoader - The Draco loader to set.
382
- * @return {GLTFLoader} A reference to this loader.
383
- */
384
181
  setDRACOLoader( dracoLoader ) {
385
-
386
182
  this.dracoLoader = dracoLoader;
387
183
  return this;
388
-
389
184
  }
390
-
391
- /**
392
- * Sets the given KTX2 loader to this loader. Required for loading KTX2
393
- * compressed textures.
394
- *
395
- * @param {KTX2Loader} ktx2Loader - The KTX2 loader to set.
396
- * @return {GLTFLoader} A reference to this loader.
397
- */
398
185
  setKTX2Loader( ktx2Loader ) {
399
-
400
186
  this.ktx2Loader = ktx2Loader;
401
187
  return this;
402
-
403
188
  }
404
-
405
- /**
406
- * Sets the given meshopt decoder. Required for decoding assets
407
- * compressed with the `EXT_meshopt_compression` extension.
408
- *
409
- * @param {Object} meshoptDecoder - The meshopt decoder to set.
410
- * @return {GLTFLoader} A reference to this loader.
411
- */
412
189
  setMeshoptDecoder( meshoptDecoder ) {
413
-
414
190
  this.meshoptDecoder = meshoptDecoder;
415
191
  return this;
416
-
417
192
  }
418
-
419
- /**
420
- * Registers a plugin callback. This API is internally used to implement the various
421
- * glTF extensions but can also used by third-party code to add additional logic
422
- * to the loader.
423
- *
424
- * @param {function(parser:GLTFParser)} callback - The callback function to register.
425
- * @return {GLTFLoader} A reference to this loader.
426
- */
427
193
  register( callback ) {
428
-
429
194
  if ( this.pluginCallbacks.indexOf( callback ) === -1 ) {
430
-
431
195
  this.pluginCallbacks.push( callback );
432
-
433
196
  }
434
-
435
197
  return this;
436
-
437
198
  }
438
-
439
- /**
440
- * Unregisters a plugin callback.
441
- *
442
- * @param {Function} callback - The callback function to unregister.
443
- * @return {GLTFLoader} A reference to this loader.
444
- */
445
199
  unregister( callback ) {
446
-
447
200
  if ( this.pluginCallbacks.indexOf( callback ) !== -1 ) {
448
-
449
201
  this.pluginCallbacks.splice( this.pluginCallbacks.indexOf( callback ), 1 );
450
-
451
202
  }
452
-
453
203
  return this;
454
-
455
204
  }
456
-
457
- /**
458
- * Parses the given FBX data and returns the resulting group.
459
- *
460
- * @param {string|ArrayBuffer} data - The raw glTF data.
461
- * @param {string} path - The URL base path.
462
- * @param {function(GLTFLoader~LoadObject)} onLoad - Executed when the loading process has been finished.
463
- * @param {onErrorCallback} onError - Executed when errors occur.
464
- */
465
205
  parse( data, path, onLoad, onError ) {
466
-
467
206
  let json;
468
207
  const extensions = {};
469
208
  const plugins = {};
470
209
  const textDecoder = new TextDecoder();
471
-
472
210
  if ( typeof data === 'string' ) {
473
-
474
211
  json = JSON.parse( data );
475
-
476
212
  } else if ( data instanceof ArrayBuffer ) {
477
-
478
213
  const magic = textDecoder.decode( new Uint8Array( data, 0, 4 ) );
479
-
480
214
  if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {
481
-
482
215
  try {
483
-
484
216
  extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );
485
-
486
217
  } catch ( error ) {
487
-
488
218
  if ( onError ) onError( error );
489
219
  return;
490
-
491
220
  }
492
-
493
221
  json = JSON.parse( extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content );
494
-
495
222
  } else {
496
-
497
223
  json = JSON.parse( textDecoder.decode( data ) );
498
-
499
224
  }
500
-
501
225
  } else {
502
-
503
226
  json = data;
504
-
505
227
  }
506
-
507
228
  if ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {
508
-
509
229
  if ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) );
510
230
  return;
511
-
512
231
  }
513
-
514
232
  const parser = new GLTFParser( json, {
515
-
516
233
  path: path || this.resourcePath || '',
517
234
  crossOrigin: this.crossOrigin,
518
235
  requestHeader: this.requestHeader,
519
236
  manager: this.manager,
520
237
  ktx2Loader: this.ktx2Loader,
521
238
  meshoptDecoder: this.meshoptDecoder
522
-
523
239
  } );
524
-
525
240
  parser.fileLoader.setRequestHeader( this.requestHeader );
526
-
527
241
  for ( let i = 0; i < this.pluginCallbacks.length; i ++ ) {
528
-
529
242
  const plugin = this.pluginCallbacks[ i ]( parser );
530
-
531
243
  if ( ! plugin.name ) console.error( 'THREE.GLTFLoader: Invalid plugin found: missing name' );
532
-
533
244
  plugins[ plugin.name ] = plugin;
534
-
535
- // Workaround to avoid determining as unknown extension
536
- // in addUnknownExtensionsToUserData().
537
- // Remove this workaround if we move all the existing
538
- // extension handlers to plugin system
539
245
  extensions[ plugin.name ] = true;
540
-
541
246
  }
542
-
543
247
  if ( json.extensionsUsed ) {
544
-
545
248
  for ( let i = 0; i < json.extensionsUsed.length; ++ i ) {
546
-
547
249
  const extensionName = json.extensionsUsed[ i ];
548
250
  const extensionsRequired = json.extensionsRequired || [];
549
-
550
251
  switch ( extensionName ) {
551
-
552
252
  case EXTENSIONS.KHR_MATERIALS_UNLIT:
553
253
  extensions[ extensionName ] = new GLTFMaterialsUnlitExtension();
554
254
  break;
555
-
556
255
  case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
557
256
  extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );
558
257
  break;
559
-
560
258
  case EXTENSIONS.KHR_TEXTURE_TRANSFORM:
561
259
  extensions[ extensionName ] = new GLTFTextureTransformExtension();
562
260
  break;
563
-
564
261
  case EXTENSIONS.KHR_MESH_QUANTIZATION:
565
262
  extensions[ extensionName ] = new GLTFMeshQuantizationExtension();
566
263
  break;
567
-
568
264
  default:
569
-
570
265
  if ( extensionsRequired.indexOf( extensionName ) >= 0 && plugins[ extensionName ] === undefined ) {
571
-
572
266
  console.warn( 'THREE.GLTFLoader: Unknown extension "' + extensionName + '".' );
573
-
574
267
  }
575
-
576
268
  }
577
-
578
269
  }
579
-
580
270
  }
581
-
582
271
  parser.setExtensions( extensions );
583
272
  parser.setPlugins( plugins );
584
273
  parser.parse( onLoad, onError );
585
-
586
274
  }
587
-
588
- /**
589
- * Async version of {@link GLTFLoader#parse}.
590
- *
591
- * @async
592
- * @param {string|ArrayBuffer} data - The raw glTF data.
593
- * @param {string} path - The URL base path.
594
- * @return {Promise<GLTFLoader~LoadObject>} A Promise that resolves with the loaded glTF when the parsing has been finished.
595
- */
596
275
  parseAsync( data, path ) {
597
-
598
276
  const scope = this;
599
-
600
277
  return new Promise( function ( resolve, reject ) {
601
-
602
278
  scope.parse( data, path, resolve, reject );
603
-
604
279
  } );
605
-
606
280
  }
607
-
608
281
  }
609
-
610
- /* GLTFREGISTRY */
611
-
612
282
  function GLTFRegistry() {
613
-
614
283
  let objects = {};
615
-
616
284
  return {
617
-
618
285
  get: function ( key ) {
619
-
620
286
  return objects[ key ];
621
-
622
287
  },
623
-
624
288
  add: function ( key, object ) {
625
-
626
289
  objects[ key ] = object;
627
-
628
290
  },
629
-
630
291
  remove: function ( key ) {
631
-
632
292
  delete objects[ key ];
633
-
634
293
  },
635
-
636
294
  removeAll: function () {
637
-
638
295
  objects = {};
639
-
640
296
  }
641
-
642
297
  };
643
-
644
298
  }
645
-
646
- /*********************************/
647
- /********** EXTENSIONS ***********/
648
- /*********************************/
649
-
650
299
  const EXTENSIONS = {
651
300
  KHR_BINARY_GLTF: 'KHR_binary_glTF',
652
301
  KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
@@ -671,84 +320,50 @@
671
320
  EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',
672
321
  EXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing'
673
322
  };
674
-
675
- /**
676
- * Punctual Lights Extension
677
- *
678
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
679
- *
680
- * @private
681
- */
682
323
  class GLTFLightsExtension {
683
-
684
324
  constructor( parser ) {
685
-
686
325
  this.parser = parser;
687
326
  this.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;
688
-
689
- // Object3D instance caches
690
327
  this.cache = { refs: {}, uses: {} };
691
-
692
328
  }
693
-
694
329
  _markDefs() {
695
-
696
330
  const parser = this.parser;
697
331
  const nodeDefs = this.parser.json.nodes || [];
698
-
699
332
  for ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {
700
-
701
333
  const nodeDef = nodeDefs[ nodeIndex ];
702
-
703
334
  if ( nodeDef.extensions
704
335
  && nodeDef.extensions[ this.name ]
705
336
  && nodeDef.extensions[ this.name ].light !== undefined ) {
706
-
707
337
  parser._addNodeRef( this.cache, nodeDef.extensions[ this.name ].light );
708
-
709
338
  }
710
-
711
339
  }
712
-
713
340
  }
714
-
715
341
  _loadLight( lightIndex ) {
716
-
717
342
  const parser = this.parser;
718
343
  const cacheKey = 'light:' + lightIndex;
719
344
  let dependency = parser.cache.get( cacheKey );
720
-
721
345
  if ( dependency ) return dependency;
722
-
723
346
  const json = parser.json;
724
347
  const extensions = ( json.extensions && json.extensions[ this.name ] ) || {};
725
348
  const lightDefs = extensions.lights || [];
726
349
  const lightDef = lightDefs[ lightIndex ];
727
350
  let lightNode;
728
-
729
351
  const color = new three.Color( 0xffffff );
730
-
731
352
  if ( lightDef.color !== undefined ) color.setRGB( lightDef.color[ 0 ], lightDef.color[ 1 ], lightDef.color[ 2 ], three.LinearSRGBColorSpace );
732
-
733
353
  const range = lightDef.range !== undefined ? lightDef.range : 0;
734
-
735
354
  switch ( lightDef.type ) {
736
-
737
355
  case 'directional':
738
356
  lightNode = new three.DirectionalLight( color );
739
357
  lightNode.target.position.set( 0, 0, -1 );
740
358
  lightNode.add( lightNode.target );
741
359
  break;
742
-
743
360
  case 'point':
744
361
  lightNode = new three.PointLight( color );
745
362
  lightNode.distance = range;
746
363
  break;
747
-
748
364
  case 'spot':
749
365
  lightNode = new three.SpotLight( color );
750
366
  lightNode.distance = range;
751
- // Handle spotlight properties.
752
367
  lightDef.spot = lightDef.spot || {};
753
368
  lightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;
754
369
  lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
@@ -757,1303 +372,634 @@
757
372
  lightNode.target.position.set( 0, 0, -1 );
758
373
  lightNode.add( lightNode.target );
759
374
  break;
760
-
761
375
  default:
762
376
  throw new Error( 'THREE.GLTFLoader: Unexpected light type: ' + lightDef.type );
763
-
764
377
  }
765
-
766
- // Some lights (e.g. spot) default to a position other than the origin. Reset the position
767
- // here, because node-level parsing will only override position if explicitly specified.
768
378
  lightNode.position.set( 0, 0, 0 );
769
-
770
379
  assignExtrasToUserData( lightNode, lightDef );
771
-
772
380
  if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;
773
-
774
381
  lightNode.name = parser.createUniqueName( lightDef.name || ( 'light_' + lightIndex ) );
775
-
776
382
  dependency = Promise.resolve( lightNode );
777
-
778
383
  parser.cache.add( cacheKey, dependency );
779
-
780
384
  return dependency;
781
-
782
385
  }
783
-
784
386
  getDependency( type, index ) {
785
-
786
387
  if ( type !== 'light' ) return;
787
-
788
388
  return this._loadLight( index );
789
-
790
389
  }
791
-
792
390
  createNodeAttachment( nodeIndex ) {
793
-
794
391
  const self = this;
795
392
  const parser = this.parser;
796
393
  const json = parser.json;
797
394
  const nodeDef = json.nodes[ nodeIndex ];
798
395
  const lightDef = ( nodeDef.extensions && nodeDef.extensions[ this.name ] ) || {};
799
396
  const lightIndex = lightDef.light;
800
-
801
397
  if ( lightIndex === undefined ) return null;
802
-
803
398
  return this._loadLight( lightIndex ).then( function ( light ) {
804
-
805
399
  return parser._getNodeRef( self.cache, lightIndex, light );
806
-
807
400
  } );
808
-
809
401
  }
810
-
811
402
  }
812
-
813
- /**
814
- * Unlit Materials Extension
815
- *
816
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit
817
- *
818
- * @private
819
- */
820
403
  class GLTFMaterialsUnlitExtension {
821
-
822
404
  constructor() {
823
-
824
405
  this.name = EXTENSIONS.KHR_MATERIALS_UNLIT;
825
-
826
406
  }
827
-
828
407
  getMaterialType() {
829
-
830
408
  return three.MeshBasicMaterial;
831
-
832
409
  }
833
-
834
410
  extendParams( materialParams, materialDef, parser ) {
835
-
836
411
  const pending = [];
837
-
838
412
  materialParams.color = new three.Color( 1.0, 1.0, 1.0 );
839
413
  materialParams.opacity = 1.0;
840
-
841
414
  const metallicRoughness = materialDef.pbrMetallicRoughness;
842
-
843
415
  if ( metallicRoughness ) {
844
-
845
416
  if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
846
-
847
417
  const array = metallicRoughness.baseColorFactor;
848
-
849
418
  materialParams.color.setRGB( array[ 0 ], array[ 1 ], array[ 2 ], three.LinearSRGBColorSpace );
850
419
  materialParams.opacity = array[ 3 ];
851
-
852
420
  }
853
-
854
421
  if ( metallicRoughness.baseColorTexture !== undefined ) {
855
-
856
422
  pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, three.SRGBColorSpace ) );
857
-
858
423
  }
859
-
860
424
  }
861
-
862
425
  return Promise.all( pending );
863
-
864
426
  }
865
-
866
427
  }
867
-
868
- /**
869
- * Materials Emissive Strength Extension
870
- *
871
- * Specification: https://github.com/KhronosGroup/glTF/blob/5768b3ce0ef32bc39cdf1bef10b948586635ead3/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md
872
- *
873
- * @private
874
- */
875
428
  class GLTFMaterialsEmissiveStrengthExtension {
876
-
877
429
  constructor( parser ) {
878
-
879
430
  this.parser = parser;
880
431
  this.name = EXTENSIONS.KHR_MATERIALS_EMISSIVE_STRENGTH;
881
-
882
432
  }
883
-
884
433
  extendMaterialParams( materialIndex, materialParams ) {
885
-
886
434
  const parser = this.parser;
887
435
  const materialDef = parser.json.materials[ materialIndex ];
888
-
889
436
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
890
-
891
437
  return Promise.resolve();
892
-
893
438
  }
894
-
895
439
  const emissiveStrength = materialDef.extensions[ this.name ].emissiveStrength;
896
-
897
440
  if ( emissiveStrength !== undefined ) {
898
-
899
441
  materialParams.emissiveIntensity = emissiveStrength;
900
-
901
442
  }
902
-
903
443
  return Promise.resolve();
904
-
905
444
  }
906
-
907
445
  }
908
-
909
- /**
910
- * Clearcoat Materials Extension
911
- *
912
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_clearcoat
913
- *
914
- * @private
915
- */
916
446
  class GLTFMaterialsClearcoatExtension {
917
-
918
447
  constructor( parser ) {
919
-
920
448
  this.parser = parser;
921
449
  this.name = EXTENSIONS.KHR_MATERIALS_CLEARCOAT;
922
-
923
450
  }
924
-
925
451
  getMaterialType( materialIndex ) {
926
-
927
452
  const parser = this.parser;
928
453
  const materialDef = parser.json.materials[ materialIndex ];
929
-
930
454
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
931
-
932
455
  return three.MeshPhysicalMaterial;
933
-
934
456
  }
935
-
936
457
  extendMaterialParams( materialIndex, materialParams ) {
937
-
938
458
  const parser = this.parser;
939
459
  const materialDef = parser.json.materials[ materialIndex ];
940
-
941
460
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
942
-
943
461
  return Promise.resolve();
944
-
945
462
  }
946
-
947
463
  const pending = [];
948
-
949
464
  const extension = materialDef.extensions[ this.name ];
950
-
951
465
  if ( extension.clearcoatFactor !== undefined ) {
952
-
953
466
  materialParams.clearcoat = extension.clearcoatFactor;
954
-
955
467
  }
956
-
957
468
  if ( extension.clearcoatTexture !== undefined ) {
958
-
959
469
  pending.push( parser.assignTexture( materialParams, 'clearcoatMap', extension.clearcoatTexture ) );
960
-
961
470
  }
962
-
963
471
  if ( extension.clearcoatRoughnessFactor !== undefined ) {
964
-
965
472
  materialParams.clearcoatRoughness = extension.clearcoatRoughnessFactor;
966
-
967
473
  }
968
-
969
474
  if ( extension.clearcoatRoughnessTexture !== undefined ) {
970
-
971
475
  pending.push( parser.assignTexture( materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture ) );
972
-
973
476
  }
974
-
975
477
  if ( extension.clearcoatNormalTexture !== undefined ) {
976
-
977
478
  pending.push( parser.assignTexture( materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture ) );
978
-
979
479
  if ( extension.clearcoatNormalTexture.scale !== undefined ) {
980
-
981
480
  const scale = extension.clearcoatNormalTexture.scale;
982
-
983
481
  materialParams.clearcoatNormalScale = new three.Vector2( scale, scale );
984
-
985
482
  }
986
-
987
483
  }
988
-
989
484
  return Promise.all( pending );
990
-
991
485
  }
992
-
993
486
  }
994
-
995
- /**
996
- * Materials dispersion Extension
997
- *
998
- * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_dispersion
999
- *
1000
- * @private
1001
- */
1002
487
  class GLTFMaterialsDispersionExtension {
1003
-
1004
488
  constructor( parser ) {
1005
-
1006
489
  this.parser = parser;
1007
490
  this.name = EXTENSIONS.KHR_MATERIALS_DISPERSION;
1008
-
1009
491
  }
1010
-
1011
492
  getMaterialType( materialIndex ) {
1012
-
1013
493
  const parser = this.parser;
1014
494
  const materialDef = parser.json.materials[ materialIndex ];
1015
-
1016
495
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
1017
-
1018
496
  return three.MeshPhysicalMaterial;
1019
-
1020
497
  }
1021
-
1022
498
  extendMaterialParams( materialIndex, materialParams ) {
1023
-
1024
499
  const parser = this.parser;
1025
500
  const materialDef = parser.json.materials[ materialIndex ];
1026
-
1027
501
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
1028
-
1029
502
  return Promise.resolve();
1030
-
1031
503
  }
1032
-
1033
504
  const extension = materialDef.extensions[ this.name ];
1034
-
1035
505
  materialParams.dispersion = extension.dispersion !== undefined ? extension.dispersion : 0;
1036
-
1037
506
  return Promise.resolve();
1038
-
1039
507
  }
1040
-
1041
508
  }
1042
-
1043
- /**
1044
- * Iridescence Materials Extension
1045
- *
1046
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_iridescence
1047
- *
1048
- * @private
1049
- */
1050
509
  class GLTFMaterialsIridescenceExtension {
1051
-
1052
510
  constructor( parser ) {
1053
-
1054
511
  this.parser = parser;
1055
512
  this.name = EXTENSIONS.KHR_MATERIALS_IRIDESCENCE;
1056
-
1057
513
  }
1058
-
1059
514
  getMaterialType( materialIndex ) {
1060
-
1061
515
  const parser = this.parser;
1062
516
  const materialDef = parser.json.materials[ materialIndex ];
1063
-
1064
517
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
1065
-
1066
518
  return three.MeshPhysicalMaterial;
1067
-
1068
519
  }
1069
-
1070
520
  extendMaterialParams( materialIndex, materialParams ) {
1071
-
1072
521
  const parser = this.parser;
1073
522
  const materialDef = parser.json.materials[ materialIndex ];
1074
-
1075
523
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
1076
-
1077
524
  return Promise.resolve();
1078
-
1079
525
  }
1080
-
1081
526
  const pending = [];
1082
-
1083
527
  const extension = materialDef.extensions[ this.name ];
1084
-
1085
528
  if ( extension.iridescenceFactor !== undefined ) {
1086
-
1087
529
  materialParams.iridescence = extension.iridescenceFactor;
1088
-
1089
530
  }
1090
-
1091
531
  if ( extension.iridescenceTexture !== undefined ) {
1092
-
1093
532
  pending.push( parser.assignTexture( materialParams, 'iridescenceMap', extension.iridescenceTexture ) );
1094
-
1095
533
  }
1096
-
1097
534
  if ( extension.iridescenceIor !== undefined ) {
1098
-
1099
535
  materialParams.iridescenceIOR = extension.iridescenceIor;
1100
-
1101
536
  }
1102
-
1103
537
  if ( materialParams.iridescenceThicknessRange === undefined ) {
1104
-
1105
538
  materialParams.iridescenceThicknessRange = [ 100, 400 ];
1106
-
1107
539
  }
1108
-
1109
540
  if ( extension.iridescenceThicknessMinimum !== undefined ) {
1110
-
1111
541
  materialParams.iridescenceThicknessRange[ 0 ] = extension.iridescenceThicknessMinimum;
1112
-
1113
542
  }
1114
-
1115
543
  if ( extension.iridescenceThicknessMaximum !== undefined ) {
1116
-
1117
544
  materialParams.iridescenceThicknessRange[ 1 ] = extension.iridescenceThicknessMaximum;
1118
-
1119
545
  }
1120
-
1121
546
  if ( extension.iridescenceThicknessTexture !== undefined ) {
1122
-
1123
547
  pending.push( parser.assignTexture( materialParams, 'iridescenceThicknessMap', extension.iridescenceThicknessTexture ) );
1124
-
1125
548
  }
1126
-
1127
549
  return Promise.all( pending );
1128
-
1129
550
  }
1130
-
1131
551
  }
1132
-
1133
- /**
1134
- * Sheen Materials Extension
1135
- *
1136
- * Specification: https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_sheen
1137
- *
1138
- * @private
1139
- */
1140
552
  class GLTFMaterialsSheenExtension {
1141
-
1142
553
  constructor( parser ) {
1143
-
1144
554
  this.parser = parser;
1145
555
  this.name = EXTENSIONS.KHR_MATERIALS_SHEEN;
1146
-
1147
556
  }
1148
-
1149
557
  getMaterialType( materialIndex ) {
1150
-
1151
558
  const parser = this.parser;
1152
559
  const materialDef = parser.json.materials[ materialIndex ];
1153
-
1154
560
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
1155
-
1156
561
  return three.MeshPhysicalMaterial;
1157
-
1158
562
  }
1159
-
1160
563
  extendMaterialParams( materialIndex, materialParams ) {
1161
-
1162
564
  const parser = this.parser;
1163
565
  const materialDef = parser.json.materials[ materialIndex ];
1164
-
1165
566
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
1166
-
1167
567
  return Promise.resolve();
1168
-
1169
568
  }
1170
-
1171
569
  const pending = [];
1172
-
1173
570
  materialParams.sheenColor = new three.Color( 0, 0, 0 );
1174
571
  materialParams.sheenRoughness = 0;
1175
572
  materialParams.sheen = 1;
1176
-
1177
573
  const extension = materialDef.extensions[ this.name ];
1178
-
1179
574
  if ( extension.sheenColorFactor !== undefined ) {
1180
-
1181
575
  const colorFactor = extension.sheenColorFactor;
1182
576
  materialParams.sheenColor.setRGB( colorFactor[ 0 ], colorFactor[ 1 ], colorFactor[ 2 ], three.LinearSRGBColorSpace );
1183
-
1184
577
  }
1185
-
1186
578
  if ( extension.sheenRoughnessFactor !== undefined ) {
1187
-
1188
579
  materialParams.sheenRoughness = extension.sheenRoughnessFactor;
1189
-
1190
580
  }
1191
-
1192
581
  if ( extension.sheenColorTexture !== undefined ) {
1193
-
1194
582
  pending.push( parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, three.SRGBColorSpace ) );
1195
-
1196
583
  }
1197
-
1198
584
  if ( extension.sheenRoughnessTexture !== undefined ) {
1199
-
1200
585
  pending.push( parser.assignTexture( materialParams, 'sheenRoughnessMap', extension.sheenRoughnessTexture ) );
1201
-
1202
586
  }
1203
-
1204
587
  return Promise.all( pending );
1205
-
1206
588
  }
1207
-
1208
589
  }
1209
-
1210
- /**
1211
- * Transmission Materials Extension
1212
- *
1213
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission
1214
- * Draft: https://github.com/KhronosGroup/glTF/pull/1698
1215
- *
1216
- * @private
1217
- */
1218
590
  class GLTFMaterialsTransmissionExtension {
1219
-
1220
591
  constructor( parser ) {
1221
-
1222
592
  this.parser = parser;
1223
593
  this.name = EXTENSIONS.KHR_MATERIALS_TRANSMISSION;
1224
-
1225
594
  }
1226
-
1227
595
  getMaterialType( materialIndex ) {
1228
-
1229
596
  const parser = this.parser;
1230
597
  const materialDef = parser.json.materials[ materialIndex ];
1231
-
1232
598
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
1233
-
1234
599
  return three.MeshPhysicalMaterial;
1235
-
1236
600
  }
1237
-
1238
601
  extendMaterialParams( materialIndex, materialParams ) {
1239
-
1240
602
  const parser = this.parser;
1241
603
  const materialDef = parser.json.materials[ materialIndex ];
1242
-
1243
604
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
1244
-
1245
605
  return Promise.resolve();
1246
-
1247
606
  }
1248
-
1249
607
  const pending = [];
1250
-
1251
608
  const extension = materialDef.extensions[ this.name ];
1252
-
1253
609
  if ( extension.transmissionFactor !== undefined ) {
1254
-
1255
610
  materialParams.transmission = extension.transmissionFactor;
1256
-
1257
611
  }
1258
-
1259
612
  if ( extension.transmissionTexture !== undefined ) {
1260
-
1261
613
  pending.push( parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) );
1262
-
1263
614
  }
1264
-
1265
615
  return Promise.all( pending );
1266
-
1267
616
  }
1268
-
1269
617
  }
1270
-
1271
- /**
1272
- * Materials Volume Extension
1273
- *
1274
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_volume
1275
- *
1276
- * @private
1277
- */
1278
618
  class GLTFMaterialsVolumeExtension {
1279
-
1280
619
  constructor( parser ) {
1281
-
1282
620
  this.parser = parser;
1283
621
  this.name = EXTENSIONS.KHR_MATERIALS_VOLUME;
1284
-
1285
622
  }
1286
-
1287
623
  getMaterialType( materialIndex ) {
1288
-
1289
624
  const parser = this.parser;
1290
625
  const materialDef = parser.json.materials[ materialIndex ];
1291
-
1292
626
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
1293
-
1294
627
  return three.MeshPhysicalMaterial;
1295
-
1296
628
  }
1297
-
1298
629
  extendMaterialParams( materialIndex, materialParams ) {
1299
-
1300
630
  const parser = this.parser;
1301
631
  const materialDef = parser.json.materials[ materialIndex ];
1302
-
1303
632
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
1304
-
1305
633
  return Promise.resolve();
1306
-
1307
634
  }
1308
-
1309
635
  const pending = [];
1310
-
1311
636
  const extension = materialDef.extensions[ this.name ];
1312
-
1313
637
  materialParams.thickness = extension.thicknessFactor !== undefined ? extension.thicknessFactor : 0;
1314
-
1315
638
  if ( extension.thicknessTexture !== undefined ) {
1316
-
1317
639
  pending.push( parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) );
1318
-
1319
640
  }
1320
-
1321
641
  materialParams.attenuationDistance = extension.attenuationDistance || Infinity;
1322
-
1323
642
  const colorArray = extension.attenuationColor || [ 1, 1, 1 ];
1324
643
  materialParams.attenuationColor = new three.Color().setRGB( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ], three.LinearSRGBColorSpace );
1325
-
1326
644
  return Promise.all( pending );
1327
-
1328
645
  }
1329
-
1330
646
  }
1331
-
1332
- /**
1333
- * Materials ior Extension
1334
- *
1335
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_ior
1336
- *
1337
- * @private
1338
- */
1339
647
  class GLTFMaterialsIorExtension {
1340
-
1341
648
  constructor( parser ) {
1342
-
1343
649
  this.parser = parser;
1344
650
  this.name = EXTENSIONS.KHR_MATERIALS_IOR;
1345
-
1346
651
  }
1347
-
1348
652
  getMaterialType( materialIndex ) {
1349
-
1350
653
  const parser = this.parser;
1351
654
  const materialDef = parser.json.materials[ materialIndex ];
1352
-
1353
655
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
1354
-
1355
656
  return three.MeshPhysicalMaterial;
1356
-
1357
657
  }
1358
-
1359
658
  extendMaterialParams( materialIndex, materialParams ) {
1360
-
1361
659
  const parser = this.parser;
1362
660
  const materialDef = parser.json.materials[ materialIndex ];
1363
-
1364
661
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
1365
-
1366
662
  return Promise.resolve();
1367
-
1368
663
  }
1369
-
1370
664
  const extension = materialDef.extensions[ this.name ];
1371
-
1372
665
  materialParams.ior = extension.ior !== undefined ? extension.ior : 1.5;
1373
-
1374
666
  return Promise.resolve();
1375
-
1376
667
  }
1377
-
1378
668
  }
1379
-
1380
- /**
1381
- * Materials specular Extension
1382
- *
1383
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_specular
1384
- *
1385
- * @private
1386
- */
1387
669
  class GLTFMaterialsSpecularExtension {
1388
-
1389
670
  constructor( parser ) {
1390
-
1391
671
  this.parser = parser;
1392
672
  this.name = EXTENSIONS.KHR_MATERIALS_SPECULAR;
1393
-
1394
673
  }
1395
-
1396
674
  getMaterialType( materialIndex ) {
1397
-
1398
675
  const parser = this.parser;
1399
676
  const materialDef = parser.json.materials[ materialIndex ];
1400
-
1401
677
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
1402
-
1403
678
  return three.MeshPhysicalMaterial;
1404
-
1405
679
  }
1406
-
1407
680
  extendMaterialParams( materialIndex, materialParams ) {
1408
-
1409
681
  const parser = this.parser;
1410
682
  const materialDef = parser.json.materials[ materialIndex ];
1411
-
1412
683
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
1413
-
1414
684
  return Promise.resolve();
1415
-
1416
685
  }
1417
-
1418
686
  const pending = [];
1419
-
1420
687
  const extension = materialDef.extensions[ this.name ];
1421
-
1422
688
  materialParams.specularIntensity = extension.specularFactor !== undefined ? extension.specularFactor : 1.0;
1423
-
1424
689
  if ( extension.specularTexture !== undefined ) {
1425
-
1426
690
  pending.push( parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) );
1427
-
1428
691
  }
1429
-
1430
692
  const colorArray = extension.specularColorFactor || [ 1, 1, 1 ];
1431
693
  materialParams.specularColor = new three.Color().setRGB( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ], three.LinearSRGBColorSpace );
1432
-
1433
694
  if ( extension.specularColorTexture !== undefined ) {
1434
-
1435
695
  pending.push( parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, three.SRGBColorSpace ) );
1436
-
1437
696
  }
1438
-
1439
697
  return Promise.all( pending );
1440
-
1441
698
  }
1442
-
1443
699
  }
1444
-
1445
-
1446
- /**
1447
- * Materials bump Extension
1448
- *
1449
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/EXT_materials_bump
1450
- *
1451
- * @private
1452
- */
1453
700
  class GLTFMaterialsBumpExtension {
1454
-
1455
701
  constructor( parser ) {
1456
-
1457
702
  this.parser = parser;
1458
703
  this.name = EXTENSIONS.EXT_MATERIALS_BUMP;
1459
-
1460
704
  }
1461
-
1462
705
  getMaterialType( materialIndex ) {
1463
-
1464
706
  const parser = this.parser;
1465
707
  const materialDef = parser.json.materials[ materialIndex ];
1466
-
1467
708
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
1468
-
1469
709
  return three.MeshPhysicalMaterial;
1470
-
1471
710
  }
1472
-
1473
711
  extendMaterialParams( materialIndex, materialParams ) {
1474
-
1475
712
  const parser = this.parser;
1476
713
  const materialDef = parser.json.materials[ materialIndex ];
1477
-
1478
714
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
1479
-
1480
715
  return Promise.resolve();
1481
-
1482
716
  }
1483
-
1484
717
  const pending = [];
1485
-
1486
718
  const extension = materialDef.extensions[ this.name ];
1487
-
1488
719
  materialParams.bumpScale = extension.bumpFactor !== undefined ? extension.bumpFactor : 1.0;
1489
-
1490
720
  if ( extension.bumpTexture !== undefined ) {
1491
-
1492
721
  pending.push( parser.assignTexture( materialParams, 'bumpMap', extension.bumpTexture ) );
1493
-
1494
722
  }
1495
-
1496
723
  return Promise.all( pending );
1497
-
1498
724
  }
1499
-
1500
725
  }
1501
-
1502
- /**
1503
- * Materials anisotropy Extension
1504
- *
1505
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_anisotropy
1506
- *
1507
- * @private
1508
- */
1509
726
  class GLTFMaterialsAnisotropyExtension {
1510
-
1511
727
  constructor( parser ) {
1512
-
1513
728
  this.parser = parser;
1514
729
  this.name = EXTENSIONS.KHR_MATERIALS_ANISOTROPY;
1515
-
1516
730
  }
1517
-
1518
731
  getMaterialType( materialIndex ) {
1519
-
1520
732
  const parser = this.parser;
1521
733
  const materialDef = parser.json.materials[ materialIndex ];
1522
-
1523
734
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
1524
-
1525
735
  return three.MeshPhysicalMaterial;
1526
-
1527
736
  }
1528
-
1529
737
  extendMaterialParams( materialIndex, materialParams ) {
1530
-
1531
738
  const parser = this.parser;
1532
739
  const materialDef = parser.json.materials[ materialIndex ];
1533
-
1534
740
  if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
1535
-
1536
741
  return Promise.resolve();
1537
-
1538
742
  }
1539
-
1540
743
  const pending = [];
1541
-
1542
744
  const extension = materialDef.extensions[ this.name ];
1543
-
1544
745
  if ( extension.anisotropyStrength !== undefined ) {
1545
-
1546
746
  materialParams.anisotropy = extension.anisotropyStrength;
1547
-
1548
747
  }
1549
-
1550
748
  if ( extension.anisotropyRotation !== undefined ) {
1551
-
1552
749
  materialParams.anisotropyRotation = extension.anisotropyRotation;
1553
-
1554
750
  }
1555
-
1556
751
  if ( extension.anisotropyTexture !== undefined ) {
1557
-
1558
752
  pending.push( parser.assignTexture( materialParams, 'anisotropyMap', extension.anisotropyTexture ) );
1559
-
1560
753
  }
1561
-
1562
754
  return Promise.all( pending );
1563
-
1564
755
  }
1565
-
1566
756
  }
1567
-
1568
- /**
1569
- * BasisU Texture Extension
1570
- *
1571
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_basisu
1572
- *
1573
- * @private
1574
- */
1575
757
  class GLTFTextureBasisUExtension {
1576
-
1577
758
  constructor( parser ) {
1578
-
1579
759
  this.parser = parser;
1580
760
  this.name = EXTENSIONS.KHR_TEXTURE_BASISU;
1581
-
1582
761
  }
1583
-
1584
762
  loadTexture( textureIndex ) {
1585
-
1586
763
  const parser = this.parser;
1587
764
  const json = parser.json;
1588
-
1589
765
  const textureDef = json.textures[ textureIndex ];
1590
-
1591
766
  if ( ! textureDef.extensions || ! textureDef.extensions[ this.name ] ) {
1592
-
1593
767
  return null;
1594
-
1595
768
  }
1596
-
1597
769
  const extension = textureDef.extensions[ this.name ];
1598
770
  const loader = parser.options.ktx2Loader;
1599
-
1600
771
  if ( ! loader ) {
1601
-
1602
772
  if ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {
1603
-
1604
773
  throw new Error( 'THREE.GLTFLoader: setKTX2Loader must be called before loading KTX2 textures' );
1605
-
1606
774
  } else {
1607
-
1608
- // Assumes that the extension is optional and that a fallback texture is present
1609
775
  return null;
1610
-
1611
776
  }
1612
-
1613
777
  }
1614
-
1615
778
  return parser.loadTextureImage( textureIndex, extension.source, loader );
1616
-
1617
779
  }
1618
-
1619
780
  }
1620
-
1621
- /**
1622
- * WebP Texture Extension
1623
- *
1624
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_webp
1625
- *
1626
- * @private
1627
- */
1628
781
  class GLTFTextureWebPExtension {
1629
-
1630
782
  constructor( parser ) {
1631
-
1632
783
  this.parser = parser;
1633
784
  this.name = EXTENSIONS.EXT_TEXTURE_WEBP;
1634
-
1635
785
  }
1636
-
1637
786
  loadTexture( textureIndex ) {
1638
-
1639
787
  const name = this.name;
1640
788
  const parser = this.parser;
1641
789
  const json = parser.json;
1642
-
1643
790
  const textureDef = json.textures[ textureIndex ];
1644
-
1645
791
  if ( ! textureDef.extensions || ! textureDef.extensions[ name ] ) {
1646
-
1647
792
  return null;
1648
-
1649
793
  }
1650
-
1651
794
  const extension = textureDef.extensions[ name ];
1652
795
  const source = json.images[ extension.source ];
1653
-
1654
796
  let loader = parser.textureLoader;
1655
797
  if ( source.uri ) {
1656
-
1657
798
  const handler = parser.options.manager.getHandler( source.uri );
1658
799
  if ( handler !== null ) loader = handler;
1659
-
1660
800
  }
1661
-
1662
801
  return parser.loadTextureImage( textureIndex, extension.source, loader );
1663
-
1664
802
  }
1665
-
1666
803
  }
1667
-
1668
- /**
1669
- * AVIF Texture Extension
1670
- *
1671
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_texture_avif
1672
- *
1673
- * @private
1674
- */
1675
804
  class GLTFTextureAVIFExtension {
1676
-
1677
805
  constructor( parser ) {
1678
-
1679
806
  this.parser = parser;
1680
807
  this.name = EXTENSIONS.EXT_TEXTURE_AVIF;
1681
-
1682
808
  }
1683
-
1684
809
  loadTexture( textureIndex ) {
1685
-
1686
810
  const name = this.name;
1687
811
  const parser = this.parser;
1688
812
  const json = parser.json;
1689
-
1690
813
  const textureDef = json.textures[ textureIndex ];
1691
-
1692
814
  if ( ! textureDef.extensions || ! textureDef.extensions[ name ] ) {
1693
-
1694
815
  return null;
1695
-
1696
816
  }
1697
-
1698
817
  const extension = textureDef.extensions[ name ];
1699
818
  const source = json.images[ extension.source ];
1700
-
1701
819
  let loader = parser.textureLoader;
1702
820
  if ( source.uri ) {
1703
-
1704
821
  const handler = parser.options.manager.getHandler( source.uri );
1705
822
  if ( handler !== null ) loader = handler;
1706
-
1707
823
  }
1708
-
1709
824
  return parser.loadTextureImage( textureIndex, extension.source, loader );
1710
-
1711
825
  }
1712
-
1713
826
  }
1714
-
1715
- /**
1716
- * meshopt BufferView Compression Extension
1717
- *
1718
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_meshopt_compression
1719
- *
1720
- * @private
1721
- */
1722
827
  class GLTFMeshoptCompression {
1723
-
1724
828
  constructor( parser ) {
1725
-
1726
829
  this.name = EXTENSIONS.EXT_MESHOPT_COMPRESSION;
1727
830
  this.parser = parser;
1728
-
1729
831
  }
1730
-
1731
832
  loadBufferView( index ) {
1732
-
1733
833
  const json = this.parser.json;
1734
834
  const bufferView = json.bufferViews[ index ];
1735
-
1736
835
  if ( bufferView.extensions && bufferView.extensions[ this.name ] ) {
1737
-
1738
836
  const extensionDef = bufferView.extensions[ this.name ];
1739
-
1740
837
  const buffer = this.parser.getDependency( 'buffer', extensionDef.buffer );
1741
838
  const decoder = this.parser.options.meshoptDecoder;
1742
-
1743
839
  if ( ! decoder || ! decoder.supported ) {
1744
-
1745
840
  if ( json.extensionsRequired && json.extensionsRequired.indexOf( this.name ) >= 0 ) {
1746
-
1747
841
  throw new Error( 'THREE.GLTFLoader: setMeshoptDecoder must be called before loading compressed files' );
1748
-
1749
842
  } else {
1750
-
1751
- // Assumes that the extension is optional and that fallback buffer data is present
1752
843
  return null;
1753
-
1754
844
  }
1755
-
1756
845
  }
1757
-
1758
846
  return buffer.then( function ( res ) {
1759
-
1760
847
  const byteOffset = extensionDef.byteOffset || 0;
1761
848
  const byteLength = extensionDef.byteLength || 0;
1762
-
1763
849
  const count = extensionDef.count;
1764
850
  const stride = extensionDef.byteStride;
1765
-
1766
851
  const source = new Uint8Array( res, byteOffset, byteLength );
1767
-
1768
852
  if ( decoder.decodeGltfBufferAsync ) {
1769
-
1770
853
  return decoder.decodeGltfBufferAsync( count, stride, source, extensionDef.mode, extensionDef.filter ).then( function ( res ) {
1771
-
1772
854
  return res.buffer;
1773
-
1774
855
  } );
1775
-
1776
856
  } else {
1777
-
1778
- // Support for MeshoptDecoder 0.18 or earlier, without decodeGltfBufferAsync
1779
857
  return decoder.ready.then( function () {
1780
-
1781
858
  const result = new ArrayBuffer( count * stride );
1782
859
  decoder.decodeGltfBuffer( new Uint8Array( result ), count, stride, source, extensionDef.mode, extensionDef.filter );
1783
860
  return result;
1784
-
1785
861
  } );
1786
-
1787
862
  }
1788
-
1789
863
  } );
1790
-
1791
864
  } else {
1792
-
1793
865
  return null;
1794
-
1795
866
  }
1796
-
1797
867
  }
1798
-
1799
868
  }
1800
-
1801
- /**
1802
- * GPU Instancing Extension
1803
- *
1804
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/EXT_mesh_gpu_instancing
1805
- *
1806
- * @private
1807
- */
1808
869
  class GLTFMeshGpuInstancing {
1809
-
1810
870
  constructor( parser ) {
1811
-
1812
871
  this.name = EXTENSIONS.EXT_MESH_GPU_INSTANCING;
1813
872
  this.parser = parser;
1814
-
1815
873
  }
1816
-
1817
874
  createNodeMesh( nodeIndex ) {
1818
-
1819
875
  const json = this.parser.json;
1820
876
  const nodeDef = json.nodes[ nodeIndex ];
1821
-
1822
877
  if ( ! nodeDef.extensions || ! nodeDef.extensions[ this.name ] ||
1823
878
  nodeDef.mesh === undefined ) {
1824
-
1825
879
  return null;
1826
-
1827
880
  }
1828
-
1829
881
  const meshDef = json.meshes[ nodeDef.mesh ];
1830
-
1831
- // No Points or Lines + Instancing support yet
1832
-
1833
882
  for ( const primitive of meshDef.primitives ) {
1834
-
1835
883
  if ( primitive.mode !== WEBGL_CONSTANTS.TRIANGLES &&
1836
884
  primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_STRIP &&
1837
885
  primitive.mode !== WEBGL_CONSTANTS.TRIANGLE_FAN &&
1838
886
  primitive.mode !== undefined ) {
1839
-
1840
887
  return null;
1841
-
1842
888
  }
1843
-
1844
889
  }
1845
-
1846
890
  const extensionDef = nodeDef.extensions[ this.name ];
1847
891
  const attributesDef = extensionDef.attributes;
1848
-
1849
- // @TODO: Can we support InstancedMesh + SkinnedMesh?
1850
-
1851
892
  const pending = [];
1852
893
  const attributes = {};
1853
-
1854
894
  for ( const key in attributesDef ) {
1855
-
1856
895
  pending.push( this.parser.getDependency( 'accessor', attributesDef[ key ] ).then( accessor => {
1857
-
1858
896
  attributes[ key ] = accessor;
1859
897
  return attributes[ key ];
1860
-
1861
898
  } ) );
1862
-
1863
899
  }
1864
-
1865
900
  if ( pending.length < 1 ) {
1866
-
1867
901
  return null;
1868
-
1869
902
  }
1870
-
1871
903
  pending.push( this.parser.createNodeMesh( nodeIndex ) );
1872
-
1873
904
  return Promise.all( pending ).then( results => {
1874
-
1875
905
  const nodeObject = results.pop();
1876
906
  const meshes = nodeObject.isGroup ? nodeObject.children : [ nodeObject ];
1877
- const count = results[ 0 ].count; // All attribute counts should be same
907
+ const count = results[ 0 ].count;
1878
908
  const instancedMeshes = [];
1879
-
1880
909
  for ( const mesh of meshes ) {
1881
-
1882
- // Temporal variables
1883
910
  const m = new three.Matrix4();
1884
911
  const p = new three.Vector3();
1885
912
  const q = new three.Quaternion();
1886
913
  const s = new three.Vector3( 1, 1, 1 );
1887
-
1888
914
  const instancedMesh = new three.InstancedMesh( mesh.geometry, mesh.material, count );
1889
-
1890
915
  for ( let i = 0; i < count; i ++ ) {
1891
-
1892
916
  if ( attributes.TRANSLATION ) {
1893
-
1894
917
  p.fromBufferAttribute( attributes.TRANSLATION, i );
1895
-
1896
918
  }
1897
-
1898
919
  if ( attributes.ROTATION ) {
1899
-
1900
920
  q.fromBufferAttribute( attributes.ROTATION, i );
1901
-
1902
921
  }
1903
-
1904
922
  if ( attributes.SCALE ) {
1905
-
1906
923
  s.fromBufferAttribute( attributes.SCALE, i );
1907
-
1908
924
  }
1909
-
1910
925
  instancedMesh.setMatrixAt( i, m.compose( p, q, s ) );
1911
-
1912
926
  }
1913
-
1914
- // Add instance attributes to the geometry, excluding TRS.
1915
927
  for ( const attributeName in attributes ) {
1916
-
1917
928
  if ( attributeName === '_COLOR_0' ) {
1918
-
1919
929
  const attr = attributes[ attributeName ];
1920
930
  instancedMesh.instanceColor = new three.InstancedBufferAttribute( attr.array, attr.itemSize, attr.normalized );
1921
-
1922
931
  } else if ( attributeName !== 'TRANSLATION' &&
1923
932
  attributeName !== 'ROTATION' &&
1924
933
  attributeName !== 'SCALE' ) {
1925
-
1926
934
  mesh.geometry.setAttribute( attributeName, attributes[ attributeName ] );
1927
-
1928
935
  }
1929
-
1930
936
  }
1931
-
1932
- // Just in case
1933
937
  three.Object3D.prototype.copy.call( instancedMesh, mesh );
1934
-
1935
938
  this.parser.assignFinalMaterial( instancedMesh );
1936
-
1937
939
  instancedMeshes.push( instancedMesh );
1938
-
1939
940
  }
1940
-
1941
941
  if ( nodeObject.isGroup ) {
1942
-
1943
942
  nodeObject.clear();
1944
-
1945
943
  nodeObject.add( ... instancedMeshes );
1946
-
1947
944
  return nodeObject;
1948
-
1949
945
  }
1950
-
1951
946
  return instancedMeshes[ 0 ];
1952
-
1953
947
  } );
1954
-
1955
948
  }
1956
-
1957
949
  }
1958
-
1959
- /* BINARY EXTENSION */
1960
950
  const BINARY_EXTENSION_HEADER_MAGIC = 'glTF';
1961
951
  const BINARY_EXTENSION_HEADER_LENGTH = 12;
1962
952
  const BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };
1963
-
1964
953
  class GLTFBinaryExtension {
1965
-
1966
954
  constructor( data ) {
1967
-
1968
955
  this.name = EXTENSIONS.KHR_BINARY_GLTF;
1969
956
  this.content = null;
1970
957
  this.body = null;
1971
-
1972
958
  const headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );
1973
959
  const textDecoder = new TextDecoder();
1974
-
1975
960
  this.header = {
1976
961
  magic: textDecoder.decode( new Uint8Array( data.slice( 0, 4 ) ) ),
1977
962
  version: headerView.getUint32( 4, true ),
1978
963
  length: headerView.getUint32( 8, true )
1979
964
  };
1980
-
1981
965
  if ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {
1982
-
1983
966
  throw new Error( 'THREE.GLTFLoader: Unsupported glTF-Binary header.' );
1984
-
1985
967
  } else if ( this.header.version < 2.0 ) {
1986
-
1987
968
  throw new Error( 'THREE.GLTFLoader: Legacy binary file detected.' );
1988
-
1989
969
  }
1990
-
1991
970
  const chunkContentsLength = this.header.length - BINARY_EXTENSION_HEADER_LENGTH;
1992
971
  const chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );
1993
972
  let chunkIndex = 0;
1994
-
1995
973
  while ( chunkIndex < chunkContentsLength ) {
1996
-
1997
974
  const chunkLength = chunkView.getUint32( chunkIndex, true );
1998
975
  chunkIndex += 4;
1999
-
2000
976
  const chunkType = chunkView.getUint32( chunkIndex, true );
2001
977
  chunkIndex += 4;
2002
-
2003
978
  if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {
2004
-
2005
979
  const contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );
2006
980
  this.content = textDecoder.decode( contentArray );
2007
-
2008
981
  } else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {
2009
-
2010
982
  const byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;
2011
983
  this.body = data.slice( byteOffset, byteOffset + chunkLength );
2012
-
2013
984
  }
2014
-
2015
- // Clients must ignore chunks with unknown types.
2016
-
2017
985
  chunkIndex += chunkLength;
2018
-
2019
986
  }
2020
-
2021
987
  if ( this.content === null ) {
2022
-
2023
988
  throw new Error( 'THREE.GLTFLoader: JSON content not found.' );
2024
-
2025
989
  }
2026
-
2027
990
  }
2028
-
2029
991
  }
2030
-
2031
- /**
2032
- * DRACO Mesh Compression Extension
2033
- *
2034
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
2035
- *
2036
- * @private
2037
- */
2038
992
  class GLTFDracoMeshCompressionExtension {
2039
-
2040
993
  constructor( json, dracoLoader ) {
2041
-
2042
994
  if ( ! dracoLoader ) {
2043
-
2044
995
  throw new Error( 'THREE.GLTFLoader: No DRACOLoader instance provided.' );
2045
-
2046
996
  }
2047
-
2048
997
  this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
2049
998
  this.json = json;
2050
999
  this.dracoLoader = dracoLoader;
2051
1000
  this.dracoLoader.preload();
2052
-
2053
1001
  }
2054
-
2055
1002
  decodePrimitive( primitive, parser ) {
2056
-
2057
1003
  const json = this.json;
2058
1004
  const dracoLoader = this.dracoLoader;
2059
1005
  const bufferViewIndex = primitive.extensions[ this.name ].bufferView;
@@ -2061,235 +1007,114 @@
2061
1007
  const threeAttributeMap = {};
2062
1008
  const attributeNormalizedMap = {};
2063
1009
  const attributeTypeMap = {};
2064
-
2065
1010
  for ( const attributeName in gltfAttributeMap ) {
2066
-
2067
1011
  const threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();
2068
-
2069
1012
  threeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ];
2070
-
2071
1013
  }
2072
-
2073
1014
  for ( const attributeName in primitive.attributes ) {
2074
-
2075
1015
  const threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();
2076
-
2077
1016
  if ( gltfAttributeMap[ attributeName ] !== undefined ) {
2078
-
2079
1017
  const accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];
2080
1018
  const componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
2081
-
2082
1019
  attributeTypeMap[ threeAttributeName ] = componentType.name;
2083
1020
  attributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true;
2084
-
2085
1021
  }
2086
-
2087
1022
  }
2088
-
2089
1023
  return parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {
2090
-
2091
1024
  return new Promise( function ( resolve, reject ) {
2092
-
2093
1025
  dracoLoader.decodeDracoFile( bufferView, function ( geometry ) {
2094
-
2095
1026
  for ( const attributeName in geometry.attributes ) {
2096
-
2097
1027
  const attribute = geometry.attributes[ attributeName ];
2098
1028
  const normalized = attributeNormalizedMap[ attributeName ];
2099
-
2100
1029
  if ( normalized !== undefined ) attribute.normalized = normalized;
2101
-
2102
1030
  }
2103
-
2104
1031
  resolve( geometry );
2105
-
2106
1032
  }, threeAttributeMap, attributeTypeMap, three.LinearSRGBColorSpace, reject );
2107
-
2108
1033
  } );
2109
-
2110
1034
  } );
2111
-
2112
1035
  }
2113
-
2114
1036
  }
2115
-
2116
- /**
2117
- * Texture Transform Extension
2118
- *
2119
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_transform
2120
- *
2121
- * @private
2122
- */
2123
1037
  class GLTFTextureTransformExtension {
2124
-
2125
1038
  constructor() {
2126
-
2127
1039
  this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;
2128
-
2129
1040
  }
2130
-
2131
1041
  extendTexture( texture, transform ) {
2132
-
2133
1042
  if ( ( transform.texCoord === undefined || transform.texCoord === texture.channel )
2134
1043
  && transform.offset === undefined
2135
1044
  && transform.rotation === undefined
2136
1045
  && transform.scale === undefined ) {
2137
-
2138
- // See https://github.com/mrdoob/three.js/issues/21819.
2139
1046
  return texture;
2140
-
2141
1047
  }
2142
-
2143
1048
  texture = texture.clone();
2144
-
2145
1049
  if ( transform.texCoord !== undefined ) {
2146
-
2147
1050
  texture.channel = transform.texCoord;
2148
-
2149
1051
  }
2150
-
2151
1052
  if ( transform.offset !== undefined ) {
2152
-
2153
1053
  texture.offset.fromArray( transform.offset );
2154
-
2155
1054
  }
2156
-
2157
1055
  if ( transform.rotation !== undefined ) {
2158
-
2159
1056
  texture.rotation = transform.rotation;
2160
-
2161
1057
  }
2162
-
2163
1058
  if ( transform.scale !== undefined ) {
2164
-
2165
1059
  texture.repeat.fromArray( transform.scale );
2166
-
2167
1060
  }
2168
-
2169
1061
  texture.needsUpdate = true;
2170
-
2171
1062
  return texture;
2172
-
2173
1063
  }
2174
-
2175
1064
  }
2176
-
2177
- /**
2178
- * Mesh Quantization Extension
2179
- *
2180
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization
2181
- *
2182
- * @private
2183
- */
2184
1065
  class GLTFMeshQuantizationExtension {
2185
-
2186
1066
  constructor() {
2187
-
2188
1067
  this.name = EXTENSIONS.KHR_MESH_QUANTIZATION;
2189
-
2190
1068
  }
2191
-
2192
1069
  }
2193
-
2194
- /*********************************/
2195
- /********** INTERPOLATION ********/
2196
- /*********************************/
2197
-
2198
- // Spline Interpolation
2199
- // Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation
2200
1070
  class GLTFCubicSplineInterpolant extends three.Interpolant {
2201
-
2202
1071
  constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) {
2203
-
2204
1072
  super( parameterPositions, sampleValues, sampleSize, resultBuffer );
2205
-
2206
1073
  }
2207
-
2208
1074
  copySampleValue_( index ) {
2209
-
2210
- // Copies a sample value to the result buffer. See description of glTF
2211
- // CUBICSPLINE values layout in interpolate_() function below.
2212
-
2213
1075
  const result = this.resultBuffer,
2214
1076
  values = this.sampleValues,
2215
1077
  valueSize = this.valueSize,
2216
1078
  offset = index * valueSize * 3 + valueSize;
2217
-
2218
1079
  for ( let i = 0; i !== valueSize; i ++ ) {
2219
-
2220
1080
  result[ i ] = values[ offset + i ];
2221
-
2222
1081
  }
2223
-
2224
1082
  return result;
2225
-
2226
1083
  }
2227
-
2228
1084
  interpolate_( i1, t0, t, t1 ) {
2229
-
2230
1085
  const result = this.resultBuffer;
2231
1086
  const values = this.sampleValues;
2232
1087
  const stride = this.valueSize;
2233
-
2234
1088
  const stride2 = stride * 2;
2235
1089
  const stride3 = stride * 3;
2236
-
2237
1090
  const td = t1 - t0;
2238
-
2239
1091
  const p = ( t - t0 ) / td;
2240
1092
  const pp = p * p;
2241
1093
  const ppp = pp * p;
2242
-
2243
1094
  const offset1 = i1 * stride3;
2244
1095
  const offset0 = offset1 - stride3;
2245
-
2246
1096
  const s2 = -2 * ppp + 3 * pp;
2247
1097
  const s3 = ppp - pp;
2248
1098
  const s0 = 1 - s2;
2249
1099
  const s1 = s3 - pp + p;
2250
-
2251
- // Layout of keyframe output values for CUBICSPLINE animations:
2252
- // [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]
2253
1100
  for ( let i = 0; i !== stride; i ++ ) {
2254
-
2255
- const p0 = values[ offset0 + i + stride ]; // splineVertex_k
2256
- const m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)
2257
- const p1 = values[ offset1 + i + stride ]; // splineVertex_k+1
2258
- const m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)
2259
-
1101
+ const p0 = values[ offset0 + i + stride ];
1102
+ const m0 = values[ offset0 + i + stride2 ] * td;
1103
+ const p1 = values[ offset1 + i + stride ];
1104
+ const m1 = values[ offset1 + i ] * td;
2260
1105
  result[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;
2261
-
2262
1106
  }
2263
-
2264
1107
  return result;
2265
-
2266
1108
  }
2267
-
2268
1109
  }
2269
-
2270
1110
  const _quaternion = new three.Quaternion();
2271
-
2272
1111
  class GLTFCubicSplineQuaternionInterpolant extends GLTFCubicSplineInterpolant {
2273
-
2274
1112
  interpolate_( i1, t0, t, t1 ) {
2275
-
2276
1113
  const result = super.interpolate_( i1, t0, t, t1 );
2277
-
2278
1114
  _quaternion.fromArray( result ).normalize().toArray( result );
2279
-
2280
1115
  return result;
2281
-
2282
1116
  }
2283
-
2284
1117
  }
2285
-
2286
-
2287
- /*********************************/
2288
- /********** INTERNALS ************/
2289
- /*********************************/
2290
-
2291
- /* CONSTANTS */
2292
-
2293
1118
  const WEBGL_CONSTANTS = {
2294
1119
  POINTS: 0,
2295
1120
  LINES: 1,
@@ -2298,7 +1123,6 @@
2298
1123
  TRIANGLES: 4,
2299
1124
  TRIANGLE_STRIP: 5,
2300
1125
  TRIANGLE_FAN: 6};
2301
-
2302
1126
  const WEBGL_COMPONENT_TYPES = {
2303
1127
  5120: Int8Array,
2304
1128
  5121: Uint8Array,
@@ -2307,7 +1131,6 @@
2307
1131
  5125: Uint32Array,
2308
1132
  5126: Float32Array
2309
1133
  };
2310
-
2311
1134
  const WEBGL_FILTERS = {
2312
1135
  9728: three.NearestFilter,
2313
1136
  9729: three.LinearFilter,
@@ -2316,13 +1139,11 @@
2316
1139
  9986: three.NearestMipmapLinearFilter,
2317
1140
  9987: three.LinearMipmapLinearFilter
2318
1141
  };
2319
-
2320
1142
  const WEBGL_WRAPPINGS = {
2321
1143
  33071: three.ClampToEdgeWrapping,
2322
1144
  33648: three.MirroredRepeatWrapping,
2323
1145
  10497: three.RepeatWrapping
2324
1146
  };
2325
-
2326
1147
  const WEBGL_TYPE_SIZES = {
2327
1148
  'SCALAR': 1,
2328
1149
  'VEC2': 2,
@@ -2332,7 +1153,6 @@
2332
1153
  'MAT3': 9,
2333
1154
  'MAT4': 16
2334
1155
  };
2335
-
2336
1156
  const ATTRIBUTES = {
2337
1157
  POSITION: 'position',
2338
1158
  NORMAL: 'normal',
@@ -2345,38 +1165,24 @@
2345
1165
  WEIGHTS_0: 'skinWeight',
2346
1166
  JOINTS_0: 'skinIndex',
2347
1167
  };
2348
-
2349
1168
  const PATH_PROPERTIES = {
2350
1169
  scale: 'scale',
2351
1170
  translation: 'position',
2352
1171
  rotation: 'quaternion',
2353
1172
  weights: 'morphTargetInfluences'
2354
1173
  };
2355
-
2356
1174
  const INTERPOLATION = {
2357
- CUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each
2358
- // keyframe track will be initialized with a default interpolation type, then modified.
1175
+ CUBICSPLINE: undefined,
2359
1176
  LINEAR: three.InterpolateLinear,
2360
1177
  STEP: three.InterpolateDiscrete
2361
1178
  };
2362
-
2363
1179
  const ALPHA_MODES = {
2364
1180
  OPAQUE: 'OPAQUE',
2365
1181
  MASK: 'MASK',
2366
1182
  BLEND: 'BLEND'
2367
1183
  };
2368
-
2369
- /**
2370
- * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
2371
- *
2372
- * @private
2373
- * @param {Object<string, Material>} cache
2374
- * @return {Material}
2375
- */
2376
1184
  function createDefaultMaterial( cache ) {
2377
-
2378
1185
  if ( cache[ 'DefaultMaterial' ] === undefined ) {
2379
-
2380
1186
  cache[ 'DefaultMaterial' ] = new three.MeshStandardMaterial( {
2381
1187
  color: 0xFFFFFF,
2382
1188
  emissive: 0x000000,
@@ -2386,399 +1192,207 @@
2386
1192
  depthTest: true,
2387
1193
  side: three.FrontSide
2388
1194
  } );
2389
-
2390
1195
  }
2391
-
2392
1196
  return cache[ 'DefaultMaterial' ];
2393
-
2394
1197
  }
2395
-
2396
1198
  function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {
2397
-
2398
- // Add unknown glTF extensions to an object's userData.
2399
-
2400
1199
  for ( const name in objectDef.extensions ) {
2401
-
2402
1200
  if ( knownExtensions[ name ] === undefined ) {
2403
-
2404
1201
  object.userData.gltfExtensions = object.userData.gltfExtensions || {};
2405
1202
  object.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];
2406
-
2407
1203
  }
2408
-
2409
1204
  }
2410
-
2411
1205
  }
2412
-
2413
- /**
2414
- *
2415
- * @private
2416
- * @param {Object3D|Material|BufferGeometry|Object} object
2417
- * @param {GLTF.definition} gltfDef
2418
- */
2419
1206
  function assignExtrasToUserData( object, gltfDef ) {
2420
-
2421
1207
  if ( gltfDef.extras !== undefined ) {
2422
-
2423
1208
  if ( typeof gltfDef.extras === 'object' ) {
2424
-
2425
1209
  Object.assign( object.userData, gltfDef.extras );
2426
-
2427
1210
  } else {
2428
-
2429
1211
  console.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );
2430
-
2431
1212
  }
2432
-
2433
1213
  }
2434
-
2435
1214
  }
2436
-
2437
- /**
2438
- * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
2439
- *
2440
- * @private
2441
- * @param {BufferGeometry} geometry
2442
- * @param {Array<GLTF.Target>} targets
2443
- * @param {GLTFParser} parser
2444
- * @return {Promise<BufferGeometry>}
2445
- */
2446
1215
  function addMorphTargets( geometry, targets, parser ) {
2447
-
2448
1216
  let hasMorphPosition = false;
2449
1217
  let hasMorphNormal = false;
2450
1218
  let hasMorphColor = false;
2451
-
2452
1219
  for ( let i = 0, il = targets.length; i < il; i ++ ) {
2453
-
2454
1220
  const target = targets[ i ];
2455
-
2456
1221
  if ( target.POSITION !== undefined ) hasMorphPosition = true;
2457
1222
  if ( target.NORMAL !== undefined ) hasMorphNormal = true;
2458
1223
  if ( target.COLOR_0 !== undefined ) hasMorphColor = true;
2459
-
2460
1224
  if ( hasMorphPosition && hasMorphNormal && hasMorphColor ) break;
2461
-
2462
1225
  }
2463
-
2464
1226
  if ( ! hasMorphPosition && ! hasMorphNormal && ! hasMorphColor ) return Promise.resolve( geometry );
2465
-
2466
1227
  const pendingPositionAccessors = [];
2467
1228
  const pendingNormalAccessors = [];
2468
1229
  const pendingColorAccessors = [];
2469
-
2470
1230
  for ( let i = 0, il = targets.length; i < il; i ++ ) {
2471
-
2472
1231
  const target = targets[ i ];
2473
-
2474
1232
  if ( hasMorphPosition ) {
2475
-
2476
1233
  const pendingAccessor = target.POSITION !== undefined
2477
1234
  ? parser.getDependency( 'accessor', target.POSITION )
2478
1235
  : geometry.attributes.position;
2479
-
2480
1236
  pendingPositionAccessors.push( pendingAccessor );
2481
-
2482
1237
  }
2483
-
2484
1238
  if ( hasMorphNormal ) {
2485
-
2486
1239
  const pendingAccessor = target.NORMAL !== undefined
2487
1240
  ? parser.getDependency( 'accessor', target.NORMAL )
2488
1241
  : geometry.attributes.normal;
2489
-
2490
1242
  pendingNormalAccessors.push( pendingAccessor );
2491
-
2492
1243
  }
2493
-
2494
1244
  if ( hasMorphColor ) {
2495
-
2496
1245
  const pendingAccessor = target.COLOR_0 !== undefined
2497
1246
  ? parser.getDependency( 'accessor', target.COLOR_0 )
2498
1247
  : geometry.attributes.color;
2499
-
2500
1248
  pendingColorAccessors.push( pendingAccessor );
2501
-
2502
1249
  }
2503
-
2504
1250
  }
2505
-
2506
1251
  return Promise.all( [
2507
1252
  Promise.all( pendingPositionAccessors ),
2508
1253
  Promise.all( pendingNormalAccessors ),
2509
1254
  Promise.all( pendingColorAccessors )
2510
1255
  ] ).then( function ( accessors ) {
2511
-
2512
1256
  const morphPositions = accessors[ 0 ];
2513
1257
  const morphNormals = accessors[ 1 ];
2514
1258
  const morphColors = accessors[ 2 ];
2515
-
2516
1259
  if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;
2517
1260
  if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;
2518
1261
  if ( hasMorphColor ) geometry.morphAttributes.color = morphColors;
2519
1262
  geometry.morphTargetsRelative = true;
2520
-
2521
1263
  return geometry;
2522
-
2523
1264
  } );
2524
-
2525
1265
  }
2526
-
2527
- /**
2528
- *
2529
- * @private
2530
- * @param {Mesh} mesh
2531
- * @param {GLTF.Mesh} meshDef
2532
- */
2533
1266
  function updateMorphTargets( mesh, meshDef ) {
2534
-
2535
1267
  mesh.updateMorphTargets();
2536
-
2537
1268
  if ( meshDef.weights !== undefined ) {
2538
-
2539
1269
  for ( let i = 0, il = meshDef.weights.length; i < il; i ++ ) {
2540
-
2541
1270
  mesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];
2542
-
2543
1271
  }
2544
-
2545
1272
  }
2546
-
2547
- // .extras has user-defined data, so check that .extras.targetNames is an array.
2548
1273
  if ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {
2549
-
2550
1274
  const targetNames = meshDef.extras.targetNames;
2551
-
2552
1275
  if ( mesh.morphTargetInfluences.length === targetNames.length ) {
2553
-
2554
1276
  mesh.morphTargetDictionary = {};
2555
-
2556
1277
  for ( let i = 0, il = targetNames.length; i < il; i ++ ) {
2557
-
2558
1278
  mesh.morphTargetDictionary[ targetNames[ i ] ] = i;
2559
-
2560
1279
  }
2561
-
2562
1280
  } else {
2563
-
2564
1281
  console.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' );
2565
-
2566
1282
  }
2567
-
2568
1283
  }
2569
-
2570
1284
  }
2571
-
2572
1285
  function createPrimitiveKey( primitiveDef ) {
2573
-
2574
1286
  let geometryKey;
2575
-
2576
1287
  const dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];
2577
-
2578
1288
  if ( dracoExtension ) {
2579
-
2580
1289
  geometryKey = 'draco:' + dracoExtension.bufferView
2581
1290
  + ':' + dracoExtension.indices
2582
1291
  + ':' + createAttributesKey( dracoExtension.attributes );
2583
-
2584
1292
  } else {
2585
-
2586
1293
  geometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;
2587
-
2588
1294
  }
2589
-
2590
1295
  if ( primitiveDef.targets !== undefined ) {
2591
-
2592
1296
  for ( let i = 0, il = primitiveDef.targets.length; i < il; i ++ ) {
2593
-
2594
1297
  geometryKey += ':' + createAttributesKey( primitiveDef.targets[ i ] );
2595
-
2596
1298
  }
2597
-
2598
1299
  }
2599
-
2600
1300
  return geometryKey;
2601
-
2602
1301
  }
2603
-
2604
1302
  function createAttributesKey( attributes ) {
2605
-
2606
1303
  let attributesKey = '';
2607
-
2608
1304
  const keys = Object.keys( attributes ).sort();
2609
-
2610
1305
  for ( let i = 0, il = keys.length; i < il; i ++ ) {
2611
-
2612
1306
  attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';
2613
-
2614
1307
  }
2615
-
2616
1308
  return attributesKey;
2617
-
2618
1309
  }
2619
-
2620
1310
  function getNormalizedComponentScale( constructor ) {
2621
-
2622
- // Reference:
2623
- // https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization#encoding-quantized-data
2624
-
2625
1311
  switch ( constructor ) {
2626
-
2627
1312
  case Int8Array:
2628
1313
  return 1 / 127;
2629
-
2630
1314
  case Uint8Array:
2631
1315
  return 1 / 255;
2632
-
2633
1316
  case Int16Array:
2634
1317
  return 1 / 32767;
2635
-
2636
1318
  case Uint16Array:
2637
1319
  return 1 / 65535;
2638
-
2639
1320
  default:
2640
1321
  throw new Error( 'THREE.GLTFLoader: Unsupported normalized accessor component type.' );
2641
-
2642
1322
  }
2643
-
2644
1323
  }
2645
-
2646
1324
  function getImageURIMimeType( uri ) {
2647
-
2648
1325
  if ( uri.search( /\.jpe?g($|\?)/i ) > 0 || uri.search( /^data\:image\/jpeg/ ) === 0 ) return 'image/jpeg';
2649
1326
  if ( uri.search( /\.webp($|\?)/i ) > 0 || uri.search( /^data\:image\/webp/ ) === 0 ) return 'image/webp';
2650
1327
  if ( uri.search( /\.ktx2($|\?)/i ) > 0 || uri.search( /^data\:image\/ktx2/ ) === 0 ) return 'image/ktx2';
2651
-
2652
1328
  return 'image/png';
2653
-
2654
1329
  }
2655
-
2656
1330
  const _identityMatrix = new three.Matrix4();
2657
-
2658
- /* GLTF PARSER */
2659
-
2660
1331
  class GLTFParser {
2661
-
2662
1332
  constructor( json = {}, options = {} ) {
2663
-
2664
1333
  this.json = json;
2665
1334
  this.extensions = {};
2666
1335
  this.plugins = {};
2667
1336
  this.options = options;
2668
-
2669
- // loader object cache
2670
1337
  this.cache = new GLTFRegistry();
2671
-
2672
- // associations between Three.js objects and glTF elements
2673
1338
  this.associations = new Map();
2674
-
2675
- // BufferGeometry caching
2676
1339
  this.primitiveCache = {};
2677
-
2678
- // Node cache
2679
1340
  this.nodeCache = {};
2680
-
2681
- // Object3D instance caches
2682
1341
  this.meshCache = { refs: {}, uses: {} };
2683
1342
  this.cameraCache = { refs: {}, uses: {} };
2684
1343
  this.lightCache = { refs: {}, uses: {} };
2685
-
2686
1344
  this.sourceCache = {};
2687
1345
  this.textureCache = {};
2688
-
2689
- // Track node names, to ensure no duplicates
2690
1346
  this.nodeNamesUsed = {};
2691
-
2692
- // Use an ImageBitmapLoader if imageBitmaps are supported. Moves much of the
2693
- // expensive work of uploading a texture to the GPU off the main thread.
2694
-
2695
1347
  let isSafari = false;
2696
1348
  let safariVersion = -1;
2697
1349
  let isFirefox = false;
2698
1350
  let firefoxVersion = -1;
2699
-
2700
1351
  if ( typeof navigator !== 'undefined' ) {
2701
-
2702
1352
  const userAgent = navigator.userAgent;
2703
-
2704
1353
  isSafari = /^((?!chrome|android).)*safari/i.test( userAgent ) === true;
2705
1354
  const safariMatch = userAgent.match( /Version\/(\d+)/ );
2706
1355
  safariVersion = isSafari && safariMatch ? parseInt( safariMatch[ 1 ], 10 ) : -1;
2707
-
2708
1356
  isFirefox = userAgent.indexOf( 'Firefox' ) > -1;
2709
1357
  firefoxVersion = isFirefox ? userAgent.match( /Firefox\/([0-9]+)\./ )[ 1 ] : -1;
2710
-
2711
1358
  }
2712
-
2713
1359
  if ( typeof createImageBitmap === 'undefined' || ( isSafari && safariVersion < 17 ) || ( isFirefox && firefoxVersion < 98 ) ) {
2714
-
2715
1360
  this.textureLoader = new three.TextureLoader( this.options.manager );
2716
-
2717
1361
  } else {
2718
-
2719
1362
  this.textureLoader = new three.ImageBitmapLoader( this.options.manager );
2720
-
2721
1363
  }
2722
-
2723
1364
  this.textureLoader.setCrossOrigin( this.options.crossOrigin );
2724
1365
  this.textureLoader.setRequestHeader( this.options.requestHeader );
2725
-
2726
1366
  this.fileLoader = new three.FileLoader( this.options.manager );
2727
1367
  this.fileLoader.setResponseType( 'arraybuffer' );
2728
-
2729
1368
  if ( this.options.crossOrigin === 'use-credentials' ) {
2730
-
2731
1369
  this.fileLoader.setWithCredentials( true );
2732
-
2733
1370
  }
2734
-
2735
1371
  }
2736
-
2737
1372
  setExtensions( extensions ) {
2738
-
2739
1373
  this.extensions = extensions;
2740
-
2741
1374
  }
2742
-
2743
1375
  setPlugins( plugins ) {
2744
-
2745
1376
  this.plugins = plugins;
2746
-
2747
1377
  }
2748
-
2749
1378
  parse( onLoad, onError ) {
2750
-
2751
1379
  const parser = this;
2752
1380
  const json = this.json;
2753
1381
  const extensions = this.extensions;
2754
-
2755
- // Clear the loader cache
2756
1382
  this.cache.removeAll();
2757
1383
  this.nodeCache = {};
2758
-
2759
- // Mark the special nodes/meshes in json for efficient parse
2760
1384
  this._invokeAll( function ( ext ) {
2761
-
2762
1385
  return ext._markDefs && ext._markDefs();
2763
-
2764
1386
  } );
2765
-
2766
1387
  Promise.all( this._invokeAll( function ( ext ) {
2767
-
2768
1388
  return ext.beforeRoot && ext.beforeRoot();
2769
-
2770
1389
  } ) ).then( function () {
2771
-
2772
1390
  return Promise.all( [
2773
-
2774
1391
  parser.getDependencies( 'scene' ),
2775
1392
  parser.getDependencies( 'animation' ),
2776
1393
  parser.getDependencies( 'camera' ),
2777
-
2778
1394
  ] );
2779
-
2780
1395
  } ).then( function ( dependencies ) {
2781
-
2782
1396
  const result = {
2783
1397
  scene: dependencies[ 0 ][ json.scene || 0 ],
2784
1398
  scenes: dependencies[ 0 ],
@@ -2788,1852 +1402,914 @@
2788
1402
  parser: parser,
2789
1403
  userData: {}
2790
1404
  };
2791
-
2792
1405
  addUnknownExtensionsToUserData( extensions, result, json );
2793
-
2794
1406
  assignExtrasToUserData( result, json );
2795
-
2796
1407
  return Promise.all( parser._invokeAll( function ( ext ) {
2797
-
2798
1408
  return ext.afterRoot && ext.afterRoot( result );
2799
-
2800
1409
  } ) ).then( function () {
2801
-
2802
1410
  for ( const scene of result.scenes ) {
2803
-
2804
1411
  scene.updateMatrixWorld();
2805
-
2806
1412
  }
2807
-
2808
1413
  onLoad( result );
2809
-
2810
1414
  } );
2811
-
2812
1415
  } ).catch( onError );
2813
-
2814
1416
  }
2815
-
2816
- /**
2817
- * Marks the special nodes/meshes in json for efficient parse.
2818
- *
2819
- * @private
2820
- */
2821
1417
  _markDefs() {
2822
-
2823
1418
  const nodeDefs = this.json.nodes || [];
2824
1419
  const skinDefs = this.json.skins || [];
2825
1420
  const meshDefs = this.json.meshes || [];
2826
-
2827
- // Nothing in the node definition indicates whether it is a Bone or an
2828
- // Object3D. Use the skins' joint references to mark bones.
2829
1421
  for ( let skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) {
2830
-
2831
1422
  const joints = skinDefs[ skinIndex ].joints;
2832
-
2833
1423
  for ( let i = 0, il = joints.length; i < il; i ++ ) {
2834
-
2835
1424
  nodeDefs[ joints[ i ] ].isBone = true;
2836
-
2837
1425
  }
2838
-
2839
1426
  }
2840
-
2841
- // Iterate over all nodes, marking references to shared resources,
2842
- // as well as skeleton joints.
2843
1427
  for ( let nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {
2844
-
2845
1428
  const nodeDef = nodeDefs[ nodeIndex ];
2846
-
2847
1429
  if ( nodeDef.mesh !== undefined ) {
2848
-
2849
1430
  this._addNodeRef( this.meshCache, nodeDef.mesh );
2850
-
2851
- // Nothing in the mesh definition indicates whether it is
2852
- // a SkinnedMesh or Mesh. Use the node's mesh reference
2853
- // to mark SkinnedMesh if node has skin.
2854
1431
  if ( nodeDef.skin !== undefined ) {
2855
-
2856
1432
  meshDefs[ nodeDef.mesh ].isSkinnedMesh = true;
2857
-
2858
1433
  }
2859
-
2860
1434
  }
2861
-
2862
1435
  if ( nodeDef.camera !== undefined ) {
2863
-
2864
1436
  this._addNodeRef( this.cameraCache, nodeDef.camera );
2865
-
2866
1437
  }
2867
-
2868
1438
  }
2869
-
2870
1439
  }
2871
-
2872
- /**
2873
- * Counts references to shared node / Object3D resources. These resources
2874
- * can be reused, or "instantiated", at multiple nodes in the scene
2875
- * hierarchy. Mesh, Camera, and Light instances are instantiated and must
2876
- * be marked. Non-scenegraph resources (like Materials, Geometries, and
2877
- * Textures) can be reused directly and are not marked here.
2878
- *
2879
- * Example: CesiumMilkTruck sample model reuses "Wheel" meshes.
2880
- *
2881
- * @private
2882
- * @param {Object} cache
2883
- * @param {Object3D} index
2884
- */
2885
1440
  _addNodeRef( cache, index ) {
2886
-
2887
1441
  if ( index === undefined ) return;
2888
-
2889
1442
  if ( cache.refs[ index ] === undefined ) {
2890
-
2891
1443
  cache.refs[ index ] = cache.uses[ index ] = 0;
2892
-
2893
1444
  }
2894
-
2895
1445
  cache.refs[ index ] ++;
2896
-
2897
1446
  }
2898
-
2899
- /**
2900
- * Returns a reference to a shared resource, cloning it if necessary.
2901
- *
2902
- * @private
2903
- * @param {Object} cache
2904
- * @param {number} index
2905
- * @param {Object} object
2906
- * @return {Object}
2907
- */
2908
1447
  _getNodeRef( cache, index, object ) {
2909
-
2910
1448
  if ( cache.refs[ index ] <= 1 ) return object;
2911
-
2912
1449
  const ref = object.clone();
2913
-
2914
- // Propagates mappings to the cloned object, prevents mappings on the
2915
- // original object from being lost.
2916
1450
  const updateMappings = ( original, clone ) => {
2917
-
2918
1451
  const mappings = this.associations.get( original );
2919
1452
  if ( mappings != null ) {
2920
-
2921
1453
  this.associations.set( clone, mappings );
2922
-
2923
1454
  }
2924
-
2925
1455
  for ( const [ i, child ] of original.children.entries() ) {
2926
-
2927
1456
  updateMappings( child, clone.children[ i ] );
2928
-
2929
1457
  }
2930
-
2931
1458
  };
2932
-
2933
1459
  updateMappings( object, ref );
2934
-
2935
1460
  ref.name += '_instance_' + ( cache.uses[ index ] ++ );
2936
-
2937
1461
  return ref;
2938
-
2939
1462
  }
2940
-
2941
1463
  _invokeOne( func ) {
2942
-
2943
1464
  const extensions = Object.values( this.plugins );
2944
1465
  extensions.push( this );
2945
-
2946
1466
  for ( let i = 0; i < extensions.length; i ++ ) {
2947
-
2948
1467
  const result = func( extensions[ i ] );
2949
-
2950
1468
  if ( result ) return result;
2951
-
2952
1469
  }
2953
-
2954
1470
  return null;
2955
-
2956
1471
  }
2957
-
2958
1472
  _invokeAll( func ) {
2959
-
2960
1473
  const extensions = Object.values( this.plugins );
2961
1474
  extensions.unshift( this );
2962
-
2963
1475
  const pending = [];
2964
-
2965
1476
  for ( let i = 0; i < extensions.length; i ++ ) {
2966
-
2967
1477
  const result = func( extensions[ i ] );
2968
-
2969
1478
  if ( result ) pending.push( result );
2970
-
2971
1479
  }
2972
-
2973
1480
  return pending;
2974
-
2975
1481
  }
2976
-
2977
- /**
2978
- * Requests the specified dependency asynchronously, with caching.
2979
- *
2980
- * @private
2981
- * @param {string} type
2982
- * @param {number} index
2983
- * @return {Promise<Object3D|Material|THREE.Texture|AnimationClip|ArrayBuffer|Object>}
2984
- */
2985
1482
  getDependency( type, index ) {
2986
-
2987
1483
  const cacheKey = type + ':' + index;
2988
1484
  let dependency = this.cache.get( cacheKey );
2989
-
2990
1485
  if ( ! dependency ) {
2991
-
2992
1486
  switch ( type ) {
2993
-
2994
1487
  case 'scene':
2995
1488
  dependency = this.loadScene( index );
2996
1489
  break;
2997
-
2998
1490
  case 'node':
2999
1491
  dependency = this._invokeOne( function ( ext ) {
3000
-
3001
1492
  return ext.loadNode && ext.loadNode( index );
3002
-
3003
1493
  } );
3004
1494
  break;
3005
-
3006
1495
  case 'mesh':
3007
1496
  dependency = this._invokeOne( function ( ext ) {
3008
-
3009
1497
  return ext.loadMesh && ext.loadMesh( index );
3010
-
3011
1498
  } );
3012
1499
  break;
3013
-
3014
1500
  case 'accessor':
3015
1501
  dependency = this.loadAccessor( index );
3016
1502
  break;
3017
-
3018
1503
  case 'bufferView':
3019
1504
  dependency = this._invokeOne( function ( ext ) {
3020
-
3021
1505
  return ext.loadBufferView && ext.loadBufferView( index );
3022
-
3023
1506
  } );
3024
1507
  break;
3025
-
3026
1508
  case 'buffer':
3027
1509
  dependency = this.loadBuffer( index );
3028
1510
  break;
3029
-
3030
1511
  case 'material':
3031
1512
  dependency = this._invokeOne( function ( ext ) {
3032
-
3033
1513
  return ext.loadMaterial && ext.loadMaterial( index );
3034
-
3035
1514
  } );
3036
1515
  break;
3037
-
3038
1516
  case 'texture':
3039
1517
  dependency = this._invokeOne( function ( ext ) {
3040
-
3041
1518
  return ext.loadTexture && ext.loadTexture( index );
3042
-
3043
1519
  } );
3044
1520
  break;
3045
-
3046
1521
  case 'skin':
3047
1522
  dependency = this.loadSkin( index );
3048
1523
  break;
3049
-
3050
1524
  case 'animation':
3051
1525
  dependency = this._invokeOne( function ( ext ) {
3052
-
3053
1526
  return ext.loadAnimation && ext.loadAnimation( index );
3054
-
3055
1527
  } );
3056
1528
  break;
3057
-
3058
1529
  case 'camera':
3059
1530
  dependency = this.loadCamera( index );
3060
1531
  break;
3061
-
3062
1532
  default:
3063
1533
  dependency = this._invokeOne( function ( ext ) {
3064
-
3065
1534
  return ext != this && ext.getDependency && ext.getDependency( type, index );
3066
-
3067
1535
  } );
3068
-
3069
1536
  if ( ! dependency ) {
3070
-
3071
1537
  throw new Error( 'Unknown type: ' + type );
3072
-
3073
1538
  }
3074
-
3075
1539
  break;
3076
-
3077
1540
  }
3078
-
3079
1541
  this.cache.add( cacheKey, dependency );
3080
-
3081
1542
  }
3082
-
3083
1543
  return dependency;
3084
-
3085
1544
  }
3086
-
3087
- /**
3088
- * Requests all dependencies of the specified type asynchronously, with caching.
3089
- *
3090
- * @private
3091
- * @param {string} type
3092
- * @return {Promise<Array<Object>>}
3093
- */
3094
1545
  getDependencies( type ) {
3095
-
3096
1546
  let dependencies = this.cache.get( type );
3097
-
3098
1547
  if ( ! dependencies ) {
3099
-
3100
1548
  const parser = this;
3101
1549
  const defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || [];
3102
-
3103
1550
  dependencies = Promise.all( defs.map( function ( def, index ) {
3104
-
3105
1551
  return parser.getDependency( type, index );
3106
-
3107
1552
  } ) );
3108
-
3109
1553
  this.cache.add( type, dependencies );
3110
-
3111
1554
  }
3112
-
3113
1555
  return dependencies;
3114
-
3115
1556
  }
3116
-
3117
- /**
3118
- * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
3119
- *
3120
- * @private
3121
- * @param {number} bufferIndex
3122
- * @return {Promise<ArrayBuffer>}
3123
- */
3124
1557
  loadBuffer( bufferIndex ) {
3125
-
3126
1558
  const bufferDef = this.json.buffers[ bufferIndex ];
3127
1559
  const loader = this.fileLoader;
3128
-
3129
1560
  if ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) {
3130
-
3131
1561
  throw new Error( 'THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.' );
3132
-
3133
1562
  }
3134
-
3135
- // If present, GLB container is required to be the first buffer.
3136
1563
  if ( bufferDef.uri === undefined && bufferIndex === 0 ) {
3137
-
3138
1564
  return Promise.resolve( this.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body );
3139
-
3140
1565
  }
3141
-
3142
1566
  const options = this.options;
3143
-
3144
1567
  return new Promise( function ( resolve, reject ) {
3145
-
3146
1568
  loader.load( three.LoaderUtils.resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {
3147
-
3148
1569
  reject( new Error( 'THREE.GLTFLoader: Failed to load buffer "' + bufferDef.uri + '".' ) );
3149
-
3150
1570
  } );
3151
-
3152
1571
  } );
3153
-
3154
1572
  }
3155
-
3156
- /**
3157
- * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
3158
- *
3159
- * @private
3160
- * @param {number} bufferViewIndex
3161
- * @return {Promise<ArrayBuffer>}
3162
- */
3163
1573
  loadBufferView( bufferViewIndex ) {
3164
-
3165
1574
  const bufferViewDef = this.json.bufferViews[ bufferViewIndex ];
3166
-
3167
1575
  return this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {
3168
-
3169
1576
  const byteLength = bufferViewDef.byteLength || 0;
3170
1577
  const byteOffset = bufferViewDef.byteOffset || 0;
3171
1578
  return buffer.slice( byteOffset, byteOffset + byteLength );
3172
-
3173
1579
  } );
3174
-
3175
1580
  }
3176
-
3177
- /**
3178
- * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors
3179
- *
3180
- * @private
3181
- * @param {number} accessorIndex
3182
- * @return {Promise<BufferAttribute|InterleavedBufferAttribute>}
3183
- */
3184
1581
  loadAccessor( accessorIndex ) {
3185
-
3186
1582
  const parser = this;
3187
1583
  const json = this.json;
3188
-
3189
1584
  const accessorDef = this.json.accessors[ accessorIndex ];
3190
-
3191
1585
  if ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {
3192
-
3193
1586
  const itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];
3194
1587
  const TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
3195
1588
  const normalized = accessorDef.normalized === true;
3196
-
3197
1589
  const array = new TypedArray( accessorDef.count * itemSize );
3198
1590
  return Promise.resolve( new three.BufferAttribute( array, itemSize, normalized ) );
3199
-
3200
1591
  }
3201
-
3202
1592
  const pendingBufferViews = [];
3203
-
3204
1593
  if ( accessorDef.bufferView !== undefined ) {
3205
-
3206
1594
  pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.bufferView ) );
3207
-
3208
1595
  } else {
3209
-
3210
1596
  pendingBufferViews.push( null );
3211
-
3212
1597
  }
3213
-
3214
1598
  if ( accessorDef.sparse !== undefined ) {
3215
-
3216
1599
  pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );
3217
1600
  pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );
3218
-
3219
1601
  }
3220
-
3221
1602
  return Promise.all( pendingBufferViews ).then( function ( bufferViews ) {
3222
-
3223
1603
  const bufferView = bufferViews[ 0 ];
3224
-
3225
1604
  const itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];
3226
1605
  const TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
3227
-
3228
- // For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.
3229
1606
  const elementBytes = TypedArray.BYTES_PER_ELEMENT;
3230
1607
  const itemBytes = elementBytes * itemSize;
3231
1608
  const byteOffset = accessorDef.byteOffset || 0;
3232
1609
  const byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined;
3233
1610
  const normalized = accessorDef.normalized === true;
3234
1611
  let array, bufferAttribute;
3235
-
3236
- // The buffer is not interleaved if the stride is the item size in bytes.
3237
1612
  if ( byteStride && byteStride !== itemBytes ) {
3238
-
3239
- // Each "slice" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer
3240
- // This makes sure that IBA.count reflects accessor.count properly
3241
1613
  const ibSlice = Math.floor( byteOffset / byteStride );
3242
1614
  const ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count;
3243
1615
  let ib = parser.cache.get( ibCacheKey );
3244
-
3245
1616
  if ( ! ib ) {
3246
-
3247
1617
  array = new TypedArray( bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes );
3248
-
3249
- // Integer parameters to IB/IBA are in array elements, not bytes.
3250
1618
  ib = new three.InterleavedBuffer( array, byteStride / elementBytes );
3251
-
3252
1619
  parser.cache.add( ibCacheKey, ib );
3253
-
3254
1620
  }
3255
-
3256
1621
  bufferAttribute = new three.InterleavedBufferAttribute( ib, itemSize, ( byteOffset % byteStride ) / elementBytes, normalized );
3257
-
3258
1622
  } else {
3259
-
3260
1623
  if ( bufferView === null ) {
3261
-
3262
1624
  array = new TypedArray( accessorDef.count * itemSize );
3263
-
3264
1625
  } else {
3265
-
3266
1626
  array = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );
3267
-
3268
1627
  }
3269
-
3270
1628
  bufferAttribute = new three.BufferAttribute( array, itemSize, normalized );
3271
-
3272
1629
  }
3273
-
3274
- // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors
3275
1630
  if ( accessorDef.sparse !== undefined ) {
3276
-
3277
1631
  const itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;
3278
1632
  const TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];
3279
-
3280
1633
  const byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;
3281
1634
  const byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;
3282
-
3283
1635
  const sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices );
3284
1636
  const sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize );
3285
-
3286
1637
  if ( bufferView !== null ) {
3287
-
3288
- // Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.
3289
1638
  bufferAttribute = new three.BufferAttribute( bufferAttribute.array.slice(), bufferAttribute.itemSize, bufferAttribute.normalized );
3290
-
3291
1639
  }
3292
-
3293
- // Ignore normalized since we copy from sparse
3294
1640
  bufferAttribute.normalized = false;
3295
-
3296
1641
  for ( let i = 0, il = sparseIndices.length; i < il; i ++ ) {
3297
-
3298
1642
  const index = sparseIndices[ i ];
3299
-
3300
1643
  bufferAttribute.setX( index, sparseValues[ i * itemSize ] );
3301
1644
  if ( itemSize >= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] );
3302
1645
  if ( itemSize >= 3 ) bufferAttribute.setZ( index, sparseValues[ i * itemSize + 2 ] );
3303
1646
  if ( itemSize >= 4 ) bufferAttribute.setW( index, sparseValues[ i * itemSize + 3 ] );
3304
1647
  if ( itemSize >= 5 ) throw new Error( 'THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.' );
3305
-
3306
1648
  }
3307
-
3308
1649
  bufferAttribute.normalized = normalized;
3309
-
3310
1650
  }
3311
-
3312
1651
  return bufferAttribute;
3313
-
3314
1652
  } );
3315
-
3316
1653
  }
3317
-
3318
- /**
3319
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures
3320
- *
3321
- * @private
3322
- * @param {number} textureIndex
3323
- * @return {Promise<THREE.Texture|null>}
3324
- */
3325
1654
  loadTexture( textureIndex ) {
3326
-
3327
1655
  const json = this.json;
3328
1656
  const options = this.options;
3329
1657
  const textureDef = json.textures[ textureIndex ];
3330
1658
  const sourceIndex = textureDef.source;
3331
1659
  const sourceDef = json.images[ sourceIndex ];
3332
-
3333
1660
  let loader = this.textureLoader;
3334
-
3335
1661
  if ( sourceDef.uri ) {
3336
-
3337
1662
  const handler = options.manager.getHandler( sourceDef.uri );
3338
1663
  if ( handler !== null ) loader = handler;
3339
-
3340
1664
  }
3341
-
3342
1665
  return this.loadTextureImage( textureIndex, sourceIndex, loader );
3343
-
3344
1666
  }
3345
-
3346
1667
  loadTextureImage( textureIndex, sourceIndex, loader ) {
3347
-
3348
1668
  const parser = this;
3349
1669
  const json = this.json;
3350
-
3351
1670
  const textureDef = json.textures[ textureIndex ];
3352
1671
  const sourceDef = json.images[ sourceIndex ];
3353
-
3354
1672
  const cacheKey = ( sourceDef.uri || sourceDef.bufferView ) + ':' + textureDef.sampler;
3355
-
3356
1673
  if ( this.textureCache[ cacheKey ] ) {
3357
-
3358
- // See https://github.com/mrdoob/three.js/issues/21559.
3359
1674
  return this.textureCache[ cacheKey ];
3360
-
3361
1675
  }
3362
-
3363
1676
  const promise = this.loadImageSource( sourceIndex, loader ).then( function ( texture ) {
3364
-
3365
1677
  texture.flipY = false;
3366
-
3367
1678
  texture.name = textureDef.name || sourceDef.name || '';
3368
-
3369
1679
  if ( texture.name === '' && typeof sourceDef.uri === 'string' && sourceDef.uri.startsWith( 'data:image/' ) === false ) {
3370
-
3371
1680
  texture.name = sourceDef.uri;
3372
-
3373
1681
  }
3374
-
3375
1682
  const samplers = json.samplers || {};
3376
1683
  const sampler = samplers[ textureDef.sampler ] || {};
3377
-
3378
1684
  texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || three.LinearFilter;
3379
1685
  texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || three.LinearMipmapLinearFilter;
3380
1686
  texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || three.RepeatWrapping;
3381
1687
  texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || three.RepeatWrapping;
3382
1688
  texture.generateMipmaps = ! texture.isCompressedTexture && texture.minFilter !== three.NearestFilter && texture.minFilter !== three.LinearFilter;
3383
-
3384
1689
  parser.associations.set( texture, { textures: textureIndex } );
3385
-
3386
1690
  return texture;
3387
-
3388
1691
  } ).catch( function () {
3389
-
3390
1692
  return null;
3391
-
3392
1693
  } );
3393
-
3394
1694
  this.textureCache[ cacheKey ] = promise;
3395
-
3396
1695
  return promise;
3397
-
3398
1696
  }
3399
-
3400
1697
  loadImageSource( sourceIndex, loader ) {
3401
-
3402
1698
  const parser = this;
3403
1699
  const json = this.json;
3404
1700
  const options = this.options;
3405
-
3406
1701
  if ( this.sourceCache[ sourceIndex ] !== undefined ) {
3407
-
3408
1702
  return this.sourceCache[ sourceIndex ].then( ( texture ) => texture.clone() );
3409
-
3410
1703
  }
3411
-
3412
1704
  const sourceDef = json.images[ sourceIndex ];
3413
-
3414
1705
  const URL = self.URL || self.webkitURL;
3415
-
3416
1706
  let sourceURI = sourceDef.uri || '';
3417
1707
  let isObjectURL = false;
3418
-
3419
1708
  if ( sourceDef.bufferView !== undefined ) {
3420
-
3421
- // Load binary image data from bufferView, if provided.
3422
-
3423
1709
  sourceURI = parser.getDependency( 'bufferView', sourceDef.bufferView ).then( function ( bufferView ) {
3424
-
3425
1710
  isObjectURL = true;
3426
1711
  const blob = new Blob( [ bufferView ], { type: sourceDef.mimeType } );
3427
1712
  sourceURI = URL.createObjectURL( blob );
3428
1713
  return sourceURI;
3429
-
3430
1714
  } );
3431
-
3432
1715
  } else if ( sourceDef.uri === undefined ) {
3433
-
3434
1716
  throw new Error( 'THREE.GLTFLoader: Image ' + sourceIndex + ' is missing URI and bufferView' );
3435
-
3436
1717
  }
3437
-
3438
1718
  const promise = Promise.resolve( sourceURI ).then( function ( sourceURI ) {
3439
-
3440
1719
  return new Promise( function ( resolve, reject ) {
3441
-
3442
1720
  let onLoad = resolve;
3443
-
3444
1721
  if ( loader.isImageBitmapLoader === true ) {
3445
-
3446
1722
  onLoad = function ( imageBitmap ) {
3447
-
3448
1723
  const texture = new three.Texture( imageBitmap );
3449
1724
  texture.needsUpdate = true;
3450
-
3451
1725
  resolve( texture );
3452
-
3453
1726
  };
3454
-
3455
1727
  }
3456
-
3457
1728
  loader.load( three.LoaderUtils.resolveURL( sourceURI, options.path ), onLoad, undefined, reject );
3458
-
3459
1729
  } );
3460
-
3461
1730
  } ).then( function ( texture ) {
3462
-
3463
- // Clean up resources and configure Texture.
3464
-
3465
1731
  if ( isObjectURL === true ) {
3466
-
3467
1732
  URL.revokeObjectURL( sourceURI );
3468
-
3469
1733
  }
3470
-
3471
1734
  assignExtrasToUserData( texture, sourceDef );
3472
-
3473
1735
  texture.userData.mimeType = sourceDef.mimeType || getImageURIMimeType( sourceDef.uri );
3474
-
3475
1736
  return texture;
3476
-
3477
1737
  } ).catch( function ( error ) {
3478
-
3479
1738
  console.error( 'THREE.GLTFLoader: Couldn\'t load texture', sourceURI );
3480
1739
  throw error;
3481
-
3482
1740
  } );
3483
-
3484
1741
  this.sourceCache[ sourceIndex ] = promise;
3485
1742
  return promise;
3486
-
3487
1743
  }
3488
-
3489
- /**
3490
- * Asynchronously assigns a texture to the given material parameters.
3491
- *
3492
- * @private
3493
- * @param {Object} materialParams
3494
- * @param {string} mapName
3495
- * @param {Object} mapDef
3496
- * @param {string} [colorSpace]
3497
- * @return {Promise<Texture>}
3498
- */
3499
1744
  assignTexture( materialParams, mapName, mapDef, colorSpace ) {
3500
-
3501
1745
  const parser = this;
3502
-
3503
1746
  return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {
3504
-
3505
1747
  if ( ! texture ) return null;
3506
-
3507
1748
  if ( mapDef.texCoord !== undefined && mapDef.texCoord > 0 ) {
3508
-
3509
1749
  texture = texture.clone();
3510
1750
  texture.channel = mapDef.texCoord;
3511
-
3512
1751
  }
3513
-
3514
1752
  if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {
3515
-
3516
1753
  const transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;
3517
-
3518
1754
  if ( transform ) {
3519
-
3520
1755
  const gltfReference = parser.associations.get( texture );
3521
1756
  texture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );
3522
1757
  parser.associations.set( texture, gltfReference );
3523
-
3524
1758
  }
3525
-
3526
1759
  }
3527
-
3528
1760
  if ( colorSpace !== undefined ) {
3529
-
3530
1761
  texture.colorSpace = colorSpace;
3531
-
3532
1762
  }
3533
-
3534
1763
  materialParams[ mapName ] = texture;
3535
-
3536
1764
  return texture;
3537
-
3538
1765
  } );
3539
-
3540
1766
  }
3541
-
3542
- /**
3543
- * Assigns final material to a Mesh, Line, or Points instance. The instance
3544
- * already has a material (generated from the glTF material options alone)
3545
- * but reuse of the same glTF material may require multiple threejs materials
3546
- * to accommodate different primitive types, defines, etc. New materials will
3547
- * be created if necessary, and reused from a cache.
3548
- *
3549
- * @private
3550
- * @param {Object3D} mesh Mesh, Line, or Points instance.
3551
- */
3552
1767
  assignFinalMaterial( mesh ) {
3553
-
3554
1768
  const geometry = mesh.geometry;
3555
1769
  let material = mesh.material;
3556
-
3557
1770
  const useDerivativeTangents = geometry.attributes.tangent === undefined;
3558
1771
  const useVertexColors = geometry.attributes.color !== undefined;
3559
1772
  const useFlatShading = geometry.attributes.normal === undefined;
3560
-
3561
1773
  if ( mesh.isPoints ) {
3562
-
3563
1774
  const cacheKey = 'PointsMaterial:' + material.uuid;
3564
-
3565
1775
  let pointsMaterial = this.cache.get( cacheKey );
3566
-
3567
1776
  if ( ! pointsMaterial ) {
3568
-
3569
1777
  pointsMaterial = new three.PointsMaterial();
3570
1778
  three.Material.prototype.copy.call( pointsMaterial, material );
3571
1779
  pointsMaterial.color.copy( material.color );
3572
1780
  pointsMaterial.map = material.map;
3573
- pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px
3574
-
1781
+ pointsMaterial.sizeAttenuation = false;
3575
1782
  this.cache.add( cacheKey, pointsMaterial );
3576
-
3577
1783
  }
3578
-
3579
1784
  material = pointsMaterial;
3580
-
3581
1785
  } else if ( mesh.isLine ) {
3582
-
3583
1786
  const cacheKey = 'LineBasicMaterial:' + material.uuid;
3584
-
3585
1787
  let lineMaterial = this.cache.get( cacheKey );
3586
-
3587
1788
  if ( ! lineMaterial ) {
3588
-
3589
1789
  lineMaterial = new three.LineBasicMaterial();
3590
1790
  three.Material.prototype.copy.call( lineMaterial, material );
3591
1791
  lineMaterial.color.copy( material.color );
3592
1792
  lineMaterial.map = material.map;
3593
-
3594
1793
  this.cache.add( cacheKey, lineMaterial );
3595
-
3596
1794
  }
3597
-
3598
1795
  material = lineMaterial;
3599
-
3600
1796
  }
3601
-
3602
- // Clone the material if it will be modified
3603
1797
  if ( useDerivativeTangents || useVertexColors || useFlatShading ) {
3604
-
3605
1798
  let cacheKey = 'ClonedMaterial:' + material.uuid + ':';
3606
-
3607
1799
  if ( useDerivativeTangents ) cacheKey += 'derivative-tangents:';
3608
1800
  if ( useVertexColors ) cacheKey += 'vertex-colors:';
3609
1801
  if ( useFlatShading ) cacheKey += 'flat-shading:';
3610
-
3611
1802
  let cachedMaterial = this.cache.get( cacheKey );
3612
-
3613
1803
  if ( ! cachedMaterial ) {
3614
-
3615
1804
  cachedMaterial = material.clone();
3616
-
3617
1805
  if ( useVertexColors ) cachedMaterial.vertexColors = true;
3618
1806
  if ( useFlatShading ) cachedMaterial.flatShading = true;
3619
-
3620
1807
  if ( useDerivativeTangents ) {
3621
-
3622
- // https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995
3623
1808
  if ( cachedMaterial.normalScale ) cachedMaterial.normalScale.y *= -1;
3624
1809
  if ( cachedMaterial.clearcoatNormalScale ) cachedMaterial.clearcoatNormalScale.y *= -1;
3625
-
3626
1810
  }
3627
-
3628
1811
  this.cache.add( cacheKey, cachedMaterial );
3629
-
3630
1812
  this.associations.set( cachedMaterial, this.associations.get( material ) );
3631
-
3632
1813
  }
3633
-
3634
1814
  material = cachedMaterial;
3635
-
3636
1815
  }
3637
-
3638
1816
  mesh.material = material;
3639
-
3640
1817
  }
3641
-
3642
- getMaterialType( /* materialIndex */ ) {
3643
-
1818
+ getMaterialType( ) {
3644
1819
  return three.MeshStandardMaterial;
3645
-
3646
1820
  }
3647
-
3648
- /**
3649
- * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials
3650
- *
3651
- * @private
3652
- * @param {number} materialIndex
3653
- * @return {Promise<Material>}
3654
- */
3655
1821
  loadMaterial( materialIndex ) {
3656
-
3657
1822
  const parser = this;
3658
1823
  const json = this.json;
3659
1824
  const extensions = this.extensions;
3660
1825
  const materialDef = json.materials[ materialIndex ];
3661
-
3662
1826
  let materialType;
3663
1827
  const materialParams = {};
3664
1828
  const materialExtensions = materialDef.extensions || {};
3665
-
3666
1829
  const pending = [];
3667
-
3668
1830
  if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {
3669
-
3670
1831
  const kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];
3671
1832
  materialType = kmuExtension.getMaterialType();
3672
1833
  pending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );
3673
-
3674
1834
  } else {
3675
-
3676
- // Specification:
3677
- // https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
3678
-
3679
1835
  const metallicRoughness = materialDef.pbrMetallicRoughness || {};
3680
-
3681
1836
  materialParams.color = new three.Color( 1.0, 1.0, 1.0 );
3682
1837
  materialParams.opacity = 1.0;
3683
-
3684
1838
  if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
3685
-
3686
1839
  const array = metallicRoughness.baseColorFactor;
3687
-
3688
1840
  materialParams.color.setRGB( array[ 0 ], array[ 1 ], array[ 2 ], three.LinearSRGBColorSpace );
3689
1841
  materialParams.opacity = array[ 3 ];
3690
-
3691
1842
  }
3692
-
3693
1843
  if ( metallicRoughness.baseColorTexture !== undefined ) {
3694
-
3695
1844
  pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture, three.SRGBColorSpace ) );
3696
-
3697
1845
  }
3698
-
3699
1846
  materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
3700
1847
  materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
3701
-
3702
1848
  if ( metallicRoughness.metallicRoughnessTexture !== undefined ) {
3703
-
3704
1849
  pending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );
3705
1850
  pending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );
3706
-
3707
1851
  }
3708
-
3709
1852
  materialType = this._invokeOne( function ( ext ) {
3710
-
3711
1853
  return ext.getMaterialType && ext.getMaterialType( materialIndex );
3712
-
3713
1854
  } );
3714
-
3715
1855
  pending.push( Promise.all( this._invokeAll( function ( ext ) {
3716
-
3717
1856
  return ext.extendMaterialParams && ext.extendMaterialParams( materialIndex, materialParams );
3718
-
3719
1857
  } ) ) );
3720
-
3721
1858
  }
3722
-
3723
1859
  if ( materialDef.doubleSided === true ) {
3724
-
3725
1860
  materialParams.side = three.DoubleSide;
3726
-
3727
1861
  }
3728
-
3729
1862
  const alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;
3730
-
3731
1863
  if ( alphaMode === ALPHA_MODES.BLEND ) {
3732
-
3733
1864
  materialParams.transparent = true;
3734
-
3735
- // See: https://github.com/mrdoob/three.js/issues/17706
3736
1865
  materialParams.depthWrite = false;
3737
-
3738
1866
  } else {
3739
-
3740
1867
  materialParams.transparent = false;
3741
-
3742
1868
  if ( alphaMode === ALPHA_MODES.MASK ) {
3743
-
3744
1869
  materialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
3745
-
3746
1870
  }
3747
-
3748
1871
  }
3749
-
3750
1872
  if ( materialDef.normalTexture !== undefined && materialType !== three.MeshBasicMaterial ) {
3751
-
3752
1873
  pending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );
3753
-
3754
1874
  materialParams.normalScale = new three.Vector2( 1, 1 );
3755
-
3756
1875
  if ( materialDef.normalTexture.scale !== undefined ) {
3757
-
3758
1876
  const scale = materialDef.normalTexture.scale;
3759
-
3760
1877
  materialParams.normalScale.set( scale, scale );
3761
-
3762
1878
  }
3763
-
3764
1879
  }
3765
-
3766
1880
  if ( materialDef.occlusionTexture !== undefined && materialType !== three.MeshBasicMaterial ) {
3767
-
3768
1881
  pending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );
3769
-
3770
1882
  if ( materialDef.occlusionTexture.strength !== undefined ) {
3771
-
3772
1883
  materialParams.aoMapIntensity = materialDef.occlusionTexture.strength;
3773
-
3774
1884
  }
3775
-
3776
1885
  }
3777
-
3778
1886
  if ( materialDef.emissiveFactor !== undefined && materialType !== three.MeshBasicMaterial ) {
3779
-
3780
1887
  const emissiveFactor = materialDef.emissiveFactor;
3781
1888
  materialParams.emissive = new three.Color().setRGB( emissiveFactor[ 0 ], emissiveFactor[ 1 ], emissiveFactor[ 2 ], three.LinearSRGBColorSpace );
3782
-
3783
1889
  }
3784
-
3785
1890
  if ( materialDef.emissiveTexture !== undefined && materialType !== three.MeshBasicMaterial ) {
3786
-
3787
1891
  pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture, three.SRGBColorSpace ) );
3788
-
3789
1892
  }
3790
-
3791
1893
  return Promise.all( pending ).then( function () {
3792
-
3793
1894
  const material = new materialType( materialParams );
3794
-
3795
1895
  if ( materialDef.name ) material.name = materialDef.name;
3796
-
3797
1896
  assignExtrasToUserData( material, materialDef );
3798
-
3799
1897
  parser.associations.set( material, { materials: materialIndex } );
3800
-
3801
1898
  if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );
3802
-
3803
1899
  return material;
3804
-
3805
1900
  } );
3806
-
3807
1901
  }
3808
-
3809
- /**
3810
- * When Object3D instances are targeted by animation, they need unique names.
3811
- *
3812
- * @private
3813
- * @param {string} originalName
3814
- * @return {string}
3815
- */
3816
1902
  createUniqueName( originalName ) {
3817
-
3818
1903
  const sanitizedName = three.PropertyBinding.sanitizeNodeName( originalName || '' );
3819
-
3820
1904
  if ( sanitizedName in this.nodeNamesUsed ) {
3821
-
3822
1905
  return sanitizedName + '_' + ( ++ this.nodeNamesUsed[ sanitizedName ] );
3823
-
3824
1906
  } else {
3825
-
3826
1907
  this.nodeNamesUsed[ sanitizedName ] = 0;
3827
-
3828
1908
  return sanitizedName;
3829
-
3830
1909
  }
3831
-
3832
1910
  }
3833
-
3834
- /**
3835
- * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry
3836
- *
3837
- * Creates BufferGeometries from primitives.
3838
- *
3839
- * @private
3840
- * @param {Array<GLTF.Primitive>} primitives
3841
- * @return {Promise<Array<BufferGeometry>>}
3842
- */
3843
1911
  loadGeometries( primitives ) {
3844
-
3845
1912
  const parser = this;
3846
1913
  const extensions = this.extensions;
3847
1914
  const cache = this.primitiveCache;
3848
-
3849
1915
  function createDracoPrimitive( primitive ) {
3850
-
3851
1916
  return extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]
3852
1917
  .decodePrimitive( primitive, parser )
3853
1918
  .then( function ( geometry ) {
3854
-
3855
1919
  return addPrimitiveAttributes( geometry, primitive, parser );
3856
-
3857
1920
  } );
3858
-
3859
1921
  }
3860
-
3861
1922
  const pending = [];
3862
-
3863
1923
  for ( let i = 0, il = primitives.length; i < il; i ++ ) {
3864
-
3865
1924
  const primitive = primitives[ i ];
3866
1925
  const cacheKey = createPrimitiveKey( primitive );
3867
-
3868
- // See if we've already created this geometry
3869
1926
  const cached = cache[ cacheKey ];
3870
-
3871
1927
  if ( cached ) {
3872
-
3873
- // Use the cached geometry if it exists
3874
1928
  pending.push( cached.promise );
3875
-
3876
1929
  } else {
3877
-
3878
1930
  let geometryPromise;
3879
-
3880
1931
  if ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {
3881
-
3882
- // Use DRACO geometry if available
3883
1932
  geometryPromise = createDracoPrimitive( primitive );
3884
-
3885
1933
  } else {
3886
-
3887
- // Otherwise create a new geometry
3888
1934
  geometryPromise = addPrimitiveAttributes( new three.BufferGeometry(), primitive, parser );
3889
-
3890
1935
  }
3891
-
3892
- // Cache this geometry
3893
1936
  cache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };
3894
-
3895
1937
  pending.push( geometryPromise );
3896
-
3897
1938
  }
3898
-
3899
1939
  }
3900
-
3901
1940
  return Promise.all( pending );
3902
-
3903
1941
  }
3904
-
3905
- /**
3906
- * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes
3907
- *
3908
- * @private
3909
- * @param {number} meshIndex
3910
- * @return {Promise<Group|Mesh|SkinnedMesh|Line|Points>}
3911
- */
3912
1942
  loadMesh( meshIndex ) {
3913
-
3914
1943
  const parser = this;
3915
1944
  const json = this.json;
3916
1945
  const extensions = this.extensions;
3917
-
3918
1946
  const meshDef = json.meshes[ meshIndex ];
3919
1947
  const primitives = meshDef.primitives;
3920
-
3921
1948
  const pending = [];
3922
-
3923
1949
  for ( let i = 0, il = primitives.length; i < il; i ++ ) {
3924
-
3925
1950
  const material = primitives[ i ].material === undefined
3926
1951
  ? createDefaultMaterial( this.cache )
3927
1952
  : this.getDependency( 'material', primitives[ i ].material );
3928
-
3929
1953
  pending.push( material );
3930
-
3931
1954
  }
3932
-
3933
1955
  pending.push( parser.loadGeometries( primitives ) );
3934
-
3935
1956
  return Promise.all( pending ).then( function ( results ) {
3936
-
3937
1957
  const materials = results.slice( 0, results.length - 1 );
3938
1958
  const geometries = results[ results.length - 1 ];
3939
-
3940
1959
  const meshes = [];
3941
-
3942
1960
  for ( let i = 0, il = geometries.length; i < il; i ++ ) {
3943
-
3944
1961
  const geometry = geometries[ i ];
3945
1962
  const primitive = primitives[ i ];
3946
-
3947
- // 1. create Mesh
3948
-
3949
1963
  let mesh;
3950
-
3951
1964
  const material = materials[ i ];
3952
-
3953
1965
  if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||
3954
1966
  primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
3955
1967
  primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||
3956
1968
  primitive.mode === undefined ) {
3957
-
3958
- // .isSkinnedMesh isn't in glTF spec. See ._markDefs()
3959
1969
  mesh = meshDef.isSkinnedMesh === true
3960
1970
  ? new three.SkinnedMesh( geometry, material )
3961
1971
  : new three.Mesh( geometry, material );
3962
-
3963
1972
  if ( mesh.isSkinnedMesh === true ) {
3964
-
3965
- // normalize skin weights to fix malformed assets (see #15319)
3966
1973
  mesh.normalizeSkinWeights();
3967
-
3968
1974
  }
3969
-
3970
1975
  if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
3971
-
3972
1976
  mesh.geometry = toTrianglesDrawMode( mesh.geometry, three.TriangleStripDrawMode );
3973
-
3974
1977
  } else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
3975
-
3976
1978
  mesh.geometry = toTrianglesDrawMode( mesh.geometry, three.TriangleFanDrawMode );
3977
-
3978
1979
  }
3979
-
3980
1980
  } else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
3981
-
3982
1981
  mesh = new three.LineSegments( geometry, material );
3983
-
3984
1982
  } else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {
3985
-
3986
1983
  mesh = new three.Line( geometry, material );
3987
-
3988
1984
  } else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
3989
-
3990
1985
  mesh = new three.LineLoop( geometry, material );
3991
-
3992
1986
  } else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
3993
-
3994
1987
  mesh = new three.Points( geometry, material );
3995
-
3996
1988
  } else {
3997
-
3998
1989
  throw new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );
3999
-
4000
1990
  }
4001
-
4002
1991
  if ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {
4003
-
4004
1992
  updateMorphTargets( mesh, meshDef );
4005
-
4006
1993
  }
4007
-
4008
1994
  mesh.name = parser.createUniqueName( meshDef.name || ( 'mesh_' + meshIndex ) );
4009
-
4010
1995
  assignExtrasToUserData( mesh, meshDef );
4011
-
4012
1996
  if ( primitive.extensions ) addUnknownExtensionsToUserData( extensions, mesh, primitive );
4013
-
4014
1997
  parser.assignFinalMaterial( mesh );
4015
-
4016
1998
  meshes.push( mesh );
4017
-
4018
1999
  }
4019
-
4020
2000
  for ( let i = 0, il = meshes.length; i < il; i ++ ) {
4021
-
4022
2001
  parser.associations.set( meshes[ i ], {
4023
2002
  meshes: meshIndex,
4024
2003
  primitives: i
4025
2004
  } );
4026
-
4027
2005
  }
4028
-
4029
2006
  if ( meshes.length === 1 ) {
4030
-
4031
2007
  if ( meshDef.extensions ) addUnknownExtensionsToUserData( extensions, meshes[ 0 ], meshDef );
4032
-
4033
2008
  return meshes[ 0 ];
4034
-
4035
2009
  }
4036
-
4037
2010
  const group = new three.Group();
4038
-
4039
2011
  if ( meshDef.extensions ) addUnknownExtensionsToUserData( extensions, group, meshDef );
4040
-
4041
2012
  parser.associations.set( group, { meshes: meshIndex } );
4042
-
4043
2013
  for ( let i = 0, il = meshes.length; i < il; i ++ ) {
4044
-
4045
2014
  group.add( meshes[ i ] );
4046
-
4047
2015
  }
4048
-
4049
2016
  return group;
4050
-
4051
2017
  } );
4052
-
4053
2018
  }
4054
-
4055
- /**
4056
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras
4057
- *
4058
- * @private
4059
- * @param {number} cameraIndex
4060
- * @return {Promise<THREE.Camera>}
4061
- */
4062
2019
  loadCamera( cameraIndex ) {
4063
-
4064
2020
  let camera;
4065
2021
  const cameraDef = this.json.cameras[ cameraIndex ];
4066
2022
  const params = cameraDef[ cameraDef.type ];
4067
-
4068
2023
  if ( ! params ) {
4069
-
4070
2024
  console.warn( 'THREE.GLTFLoader: Missing camera parameters.' );
4071
2025
  return;
4072
-
4073
2026
  }
4074
-
4075
2027
  if ( cameraDef.type === 'perspective' ) {
4076
-
4077
2028
  camera = new three.PerspectiveCamera( three.MathUtils.radToDeg( params.yfov ), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6 );
4078
-
4079
2029
  } else if ( cameraDef.type === 'orthographic' ) {
4080
-
4081
2030
  camera = new three.OrthographicCamera( - params.xmag, params.xmag, params.ymag, - params.ymag, params.znear, params.zfar );
4082
-
4083
2031
  }
4084
-
4085
2032
  if ( cameraDef.name ) camera.name = this.createUniqueName( cameraDef.name );
4086
-
4087
2033
  assignExtrasToUserData( camera, cameraDef );
4088
-
4089
2034
  return Promise.resolve( camera );
4090
-
4091
2035
  }
4092
-
4093
- /**
4094
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
4095
- *
4096
- * @private
4097
- * @param {number} skinIndex
4098
- * @return {Promise<Skeleton>}
4099
- */
4100
2036
  loadSkin( skinIndex ) {
4101
-
4102
2037
  const skinDef = this.json.skins[ skinIndex ];
4103
-
4104
2038
  const pending = [];
4105
-
4106
2039
  for ( let i = 0, il = skinDef.joints.length; i < il; i ++ ) {
4107
-
4108
2040
  pending.push( this._loadNodeShallow( skinDef.joints[ i ] ) );
4109
-
4110
2041
  }
4111
-
4112
2042
  if ( skinDef.inverseBindMatrices !== undefined ) {
4113
-
4114
2043
  pending.push( this.getDependency( 'accessor', skinDef.inverseBindMatrices ) );
4115
-
4116
2044
  } else {
4117
-
4118
2045
  pending.push( null );
4119
-
4120
2046
  }
4121
-
4122
2047
  return Promise.all( pending ).then( function ( results ) {
4123
-
4124
2048
  const inverseBindMatrices = results.pop();
4125
2049
  const jointNodes = results;
4126
-
4127
- // Note that bones (joint nodes) may or may not be in the
4128
- // scene graph at this time.
4129
-
4130
2050
  const bones = [];
4131
2051
  const boneInverses = [];
4132
-
4133
2052
  for ( let i = 0, il = jointNodes.length; i < il; i ++ ) {
4134
-
4135
2053
  const jointNode = jointNodes[ i ];
4136
-
4137
2054
  if ( jointNode ) {
4138
-
4139
2055
  bones.push( jointNode );
4140
-
4141
2056
  const mat = new three.Matrix4();
4142
-
4143
2057
  if ( inverseBindMatrices !== null ) {
4144
-
4145
2058
  mat.fromArray( inverseBindMatrices.array, i * 16 );
4146
-
4147
2059
  }
4148
-
4149
2060
  boneInverses.push( mat );
4150
-
4151
2061
  } else {
4152
-
4153
2062
  console.warn( 'THREE.GLTFLoader: Joint "%s" could not be found.', skinDef.joints[ i ] );
4154
-
4155
2063
  }
4156
-
4157
2064
  }
4158
-
4159
2065
  return new three.Skeleton( bones, boneInverses );
4160
-
4161
2066
  } );
4162
-
4163
2067
  }
4164
-
4165
- /**
4166
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations
4167
- *
4168
- * @private
4169
- * @param {number} animationIndex
4170
- * @return {Promise<AnimationClip>}
4171
- */
4172
2068
  loadAnimation( animationIndex ) {
4173
-
4174
2069
  const json = this.json;
4175
2070
  const parser = this;
4176
-
4177
2071
  const animationDef = json.animations[ animationIndex ];
4178
2072
  const animationName = animationDef.name ? animationDef.name : 'animation_' + animationIndex;
4179
-
4180
2073
  const pendingNodes = [];
4181
2074
  const pendingInputAccessors = [];
4182
2075
  const pendingOutputAccessors = [];
4183
2076
  const pendingSamplers = [];
4184
2077
  const pendingTargets = [];
4185
-
4186
2078
  for ( let i = 0, il = animationDef.channels.length; i < il; i ++ ) {
4187
-
4188
2079
  const channel = animationDef.channels[ i ];
4189
2080
  const sampler = animationDef.samplers[ channel.sampler ];
4190
2081
  const target = channel.target;
4191
2082
  const name = target.node;
4192
2083
  const input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input;
4193
2084
  const output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output;
4194
-
4195
2085
  if ( target.node === undefined ) continue;
4196
-
4197
2086
  pendingNodes.push( this.getDependency( 'node', name ) );
4198
2087
  pendingInputAccessors.push( this.getDependency( 'accessor', input ) );
4199
2088
  pendingOutputAccessors.push( this.getDependency( 'accessor', output ) );
4200
2089
  pendingSamplers.push( sampler );
4201
2090
  pendingTargets.push( target );
4202
-
4203
2091
  }
4204
-
4205
2092
  return Promise.all( [
4206
-
4207
2093
  Promise.all( pendingNodes ),
4208
2094
  Promise.all( pendingInputAccessors ),
4209
2095
  Promise.all( pendingOutputAccessors ),
4210
2096
  Promise.all( pendingSamplers ),
4211
2097
  Promise.all( pendingTargets )
4212
-
4213
2098
  ] ).then( function ( dependencies ) {
4214
-
4215
2099
  const nodes = dependencies[ 0 ];
4216
2100
  const inputAccessors = dependencies[ 1 ];
4217
2101
  const outputAccessors = dependencies[ 2 ];
4218
2102
  const samplers = dependencies[ 3 ];
4219
2103
  const targets = dependencies[ 4 ];
4220
-
4221
2104
  const tracks = [];
4222
-
4223
2105
  for ( let i = 0, il = nodes.length; i < il; i ++ ) {
4224
-
4225
2106
  const node = nodes[ i ];
4226
2107
  const inputAccessor = inputAccessors[ i ];
4227
2108
  const outputAccessor = outputAccessors[ i ];
4228
2109
  const sampler = samplers[ i ];
4229
2110
  const target = targets[ i ];
4230
-
4231
2111
  if ( node === undefined ) continue;
4232
-
4233
2112
  if ( node.updateMatrix ) {
4234
-
4235
2113
  node.updateMatrix();
4236
-
4237
2114
  }
4238
-
4239
2115
  const createdTracks = parser._createAnimationTracks( node, inputAccessor, outputAccessor, sampler, target );
4240
-
4241
2116
  if ( createdTracks ) {
4242
-
4243
2117
  for ( let k = 0; k < createdTracks.length; k ++ ) {
4244
-
4245
2118
  tracks.push( createdTracks[ k ] );
4246
-
4247
2119
  }
4248
-
4249
2120
  }
4250
-
4251
2121
  }
4252
-
4253
2122
  return new three.AnimationClip( animationName, undefined, tracks );
4254
-
4255
2123
  } );
4256
-
4257
2124
  }
4258
-
4259
2125
  createNodeMesh( nodeIndex ) {
4260
-
4261
2126
  const json = this.json;
4262
2127
  const parser = this;
4263
2128
  const nodeDef = json.nodes[ nodeIndex ];
4264
-
4265
2129
  if ( nodeDef.mesh === undefined ) return null;
4266
-
4267
2130
  return parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) {
4268
-
4269
2131
  const node = parser._getNodeRef( parser.meshCache, nodeDef.mesh, mesh );
4270
-
4271
- // if weights are provided on the node, override weights on the mesh.
4272
2132
  if ( nodeDef.weights !== undefined ) {
4273
-
4274
2133
  node.traverse( function ( o ) {
4275
-
4276
2134
  if ( ! o.isMesh ) return;
4277
-
4278
2135
  for ( let i = 0, il = nodeDef.weights.length; i < il; i ++ ) {
4279
-
4280
2136
  o.morphTargetInfluences[ i ] = nodeDef.weights[ i ];
4281
-
4282
2137
  }
4283
-
4284
2138
  } );
4285
-
4286
2139
  }
4287
-
4288
2140
  return node;
4289
-
4290
2141
  } );
4291
-
4292
2142
  }
4293
-
4294
- /**
4295
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy
4296
- *
4297
- * @private
4298
- * @param {number} nodeIndex
4299
- * @return {Promise<Object3D>}
4300
- */
4301
2143
  loadNode( nodeIndex ) {
4302
-
4303
2144
  const json = this.json;
4304
2145
  const parser = this;
4305
-
4306
2146
  const nodeDef = json.nodes[ nodeIndex ];
4307
-
4308
2147
  const nodePending = parser._loadNodeShallow( nodeIndex );
4309
-
4310
2148
  const childPending = [];
4311
2149
  const childrenDef = nodeDef.children || [];
4312
-
4313
2150
  for ( let i = 0, il = childrenDef.length; i < il; i ++ ) {
4314
-
4315
2151
  childPending.push( parser.getDependency( 'node', childrenDef[ i ] ) );
4316
-
4317
2152
  }
4318
-
4319
2153
  const skeletonPending = nodeDef.skin === undefined
4320
2154
  ? Promise.resolve( null )
4321
2155
  : parser.getDependency( 'skin', nodeDef.skin );
4322
-
4323
2156
  return Promise.all( [
4324
2157
  nodePending,
4325
2158
  Promise.all( childPending ),
4326
2159
  skeletonPending
4327
2160
  ] ).then( function ( results ) {
4328
-
4329
2161
  const node = results[ 0 ];
4330
2162
  const children = results[ 1 ];
4331
2163
  const skeleton = results[ 2 ];
4332
-
4333
2164
  if ( skeleton !== null ) {
4334
-
4335
- // This full traverse should be fine because
4336
- // child glTF nodes have not been added to this node yet.
4337
2165
  node.traverse( function ( mesh ) {
4338
-
4339
2166
  if ( ! mesh.isSkinnedMesh ) return;
4340
-
4341
2167
  mesh.bind( skeleton, _identityMatrix );
4342
-
4343
2168
  } );
4344
-
4345
2169
  }
4346
-
4347
2170
  for ( let i = 0, il = children.length; i < il; i ++ ) {
4348
-
4349
2171
  node.add( children[ i ] );
4350
-
4351
2172
  }
4352
-
4353
2173
  return node;
4354
-
4355
2174
  } );
4356
-
4357
2175
  }
4358
-
4359
- // ._loadNodeShallow() parses a single node.
4360
- // skin and child nodes are created and added in .loadNode() (no '_' prefix).
4361
2176
  _loadNodeShallow( nodeIndex ) {
4362
-
4363
2177
  const json = this.json;
4364
2178
  const extensions = this.extensions;
4365
2179
  const parser = this;
4366
-
4367
- // This method is called from .loadNode() and .loadSkin().
4368
- // Cache a node to avoid duplication.
4369
-
4370
2180
  if ( this.nodeCache[ nodeIndex ] !== undefined ) {
4371
-
4372
2181
  return this.nodeCache[ nodeIndex ];
4373
-
4374
2182
  }
4375
-
4376
2183
  const nodeDef = json.nodes[ nodeIndex ];
4377
-
4378
- // reserve node's name before its dependencies, so the root has the intended name.
4379
2184
  const nodeName = nodeDef.name ? parser.createUniqueName( nodeDef.name ) : '';
4380
-
4381
2185
  const pending = [];
4382
-
4383
2186
  const meshPromise = parser._invokeOne( function ( ext ) {
4384
-
4385
2187
  return ext.createNodeMesh && ext.createNodeMesh( nodeIndex );
4386
-
4387
2188
  } );
4388
-
4389
2189
  if ( meshPromise ) {
4390
-
4391
2190
  pending.push( meshPromise );
4392
-
4393
2191
  }
4394
-
4395
2192
  if ( nodeDef.camera !== undefined ) {
4396
-
4397
2193
  pending.push( parser.getDependency( 'camera', nodeDef.camera ).then( function ( camera ) {
4398
-
4399
2194
  return parser._getNodeRef( parser.cameraCache, nodeDef.camera, camera );
4400
-
4401
2195
  } ) );
4402
-
4403
2196
  }
4404
-
4405
2197
  parser._invokeAll( function ( ext ) {
4406
-
4407
2198
  return ext.createNodeAttachment && ext.createNodeAttachment( nodeIndex );
4408
-
4409
2199
  } ).forEach( function ( promise ) {
4410
-
4411
2200
  pending.push( promise );
4412
-
4413
2201
  } );
4414
-
4415
2202
  this.nodeCache[ nodeIndex ] = Promise.all( pending ).then( function ( objects ) {
4416
-
4417
2203
  let node;
4418
-
4419
- // .isBone isn't in glTF spec. See ._markDefs
4420
2204
  if ( nodeDef.isBone === true ) {
4421
-
4422
2205
  node = new three.Bone();
4423
-
4424
2206
  } else if ( objects.length > 1 ) {
4425
-
4426
2207
  node = new three.Group();
4427
-
4428
2208
  } else if ( objects.length === 1 ) {
4429
-
4430
2209
  node = objects[ 0 ];
4431
-
4432
2210
  } else {
4433
-
4434
2211
  node = new three.Object3D();
4435
-
4436
2212
  }
4437
-
4438
2213
  if ( node !== objects[ 0 ] ) {
4439
-
4440
2214
  for ( let i = 0, il = objects.length; i < il; i ++ ) {
4441
-
4442
2215
  node.add( objects[ i ] );
4443
-
4444
2216
  }
4445
-
4446
2217
  }
4447
-
4448
2218
  if ( nodeDef.name ) {
4449
-
4450
2219
  node.userData.name = nodeDef.name;
4451
2220
  node.name = nodeName;
4452
-
4453
2221
  }
4454
-
4455
2222
  assignExtrasToUserData( node, nodeDef );
4456
-
4457
2223
  if ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );
4458
-
4459
2224
  if ( nodeDef.matrix !== undefined ) {
4460
-
4461
2225
  const matrix = new three.Matrix4();
4462
2226
  matrix.fromArray( nodeDef.matrix );
4463
2227
  node.applyMatrix4( matrix );
4464
-
4465
2228
  } else {
4466
-
4467
2229
  if ( nodeDef.translation !== undefined ) {
4468
-
4469
2230
  node.position.fromArray( nodeDef.translation );
4470
-
4471
2231
  }
4472
-
4473
2232
  if ( nodeDef.rotation !== undefined ) {
4474
-
4475
2233
  node.quaternion.fromArray( nodeDef.rotation );
4476
-
4477
2234
  }
4478
-
4479
2235
  if ( nodeDef.scale !== undefined ) {
4480
-
4481
2236
  node.scale.fromArray( nodeDef.scale );
4482
-
4483
2237
  }
4484
-
4485
2238
  }
4486
-
4487
2239
  if ( ! parser.associations.has( node ) ) {
4488
-
4489
2240
  parser.associations.set( node, {} );
4490
-
4491
2241
  } else if ( nodeDef.mesh !== undefined && parser.meshCache.refs[ nodeDef.mesh ] > 1 ) {
4492
-
4493
2242
  const mapping = parser.associations.get( node );
4494
2243
  parser.associations.set( node, { ...mapping } );
4495
-
4496
2244
  }
4497
-
4498
2245
  parser.associations.get( node ).nodes = nodeIndex;
4499
-
4500
2246
  return node;
4501
-
4502
2247
  } );
4503
-
4504
2248
  return this.nodeCache[ nodeIndex ];
4505
-
4506
2249
  }
4507
-
4508
- /**
4509
- * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes
4510
- *
4511
- * @private
4512
- * @param {number} sceneIndex
4513
- * @return {Promise<Group>}
4514
- */
4515
2250
  loadScene( sceneIndex ) {
4516
-
4517
2251
  const extensions = this.extensions;
4518
2252
  const sceneDef = this.json.scenes[ sceneIndex ];
4519
2253
  const parser = this;
4520
-
4521
- // Loader returns Group, not Scene.
4522
- // See: https://github.com/mrdoob/three.js/issues/18342#issuecomment-578981172
4523
2254
  const scene = new three.Group();
4524
2255
  if ( sceneDef.name ) scene.name = parser.createUniqueName( sceneDef.name );
4525
-
4526
2256
  assignExtrasToUserData( scene, sceneDef );
4527
-
4528
2257
  if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );
4529
-
4530
2258
  const nodeIds = sceneDef.nodes || [];
4531
-
4532
2259
  const pending = [];
4533
-
4534
2260
  for ( let i = 0, il = nodeIds.length; i < il; i ++ ) {
4535
-
4536
2261
  pending.push( parser.getDependency( 'node', nodeIds[ i ] ) );
4537
-
4538
2262
  }
4539
-
4540
2263
  return Promise.all( pending ).then( function ( nodes ) {
4541
-
4542
2264
  for ( let i = 0, il = nodes.length; i < il; i ++ ) {
4543
-
4544
2265
  scene.add( nodes[ i ] );
4545
-
4546
2266
  }
4547
-
4548
- // Removes dangling associations, associations that reference a node that
4549
- // didn't make it into the scene.
4550
2267
  const reduceAssociations = ( node ) => {
4551
-
4552
2268
  const reducedAssociations = new Map();
4553
-
4554
2269
  for ( const [ key, value ] of parser.associations ) {
4555
-
4556
2270
  if ( key instanceof three.Material || key instanceof three.Texture ) {
4557
-
4558
2271
  reducedAssociations.set( key, value );
4559
-
4560
2272
  }
4561
-
4562
2273
  }
4563
-
4564
2274
  node.traverse( ( node ) => {
4565
-
4566
2275
  const mappings = parser.associations.get( node );
4567
-
4568
2276
  if ( mappings != null ) {
4569
-
4570
2277
  reducedAssociations.set( node, mappings );
4571
-
4572
2278
  }
4573
-
4574
2279
  } );
4575
-
4576
2280
  return reducedAssociations;
4577
-
4578
2281
  };
4579
-
4580
2282
  parser.associations = reduceAssociations( scene );
4581
-
4582
2283
  return scene;
4583
-
4584
2284
  } );
4585
-
4586
2285
  }
4587
-
4588
2286
  _createAnimationTracks( node, inputAccessor, outputAccessor, sampler, target ) {
4589
-
4590
2287
  const tracks = [];
4591
-
4592
2288
  const targetName = node.name ? node.name : node.uuid;
4593
2289
  const targetNames = [];
4594
-
4595
2290
  if ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {
4596
-
4597
2291
  node.traverse( function ( object ) {
4598
-
4599
2292
  if ( object.morphTargetInfluences ) {
4600
-
4601
2293
  targetNames.push( object.name ? object.name : object.uuid );
4602
-
4603
2294
  }
4604
-
4605
2295
  } );
4606
-
4607
2296
  } else {
4608
-
4609
2297
  targetNames.push( targetName );
4610
-
4611
2298
  }
4612
-
4613
2299
  let TypedKeyframeTrack;
4614
-
4615
2300
  switch ( PATH_PROPERTIES[ target.path ] ) {
4616
-
4617
2301
  case PATH_PROPERTIES.weights:
4618
-
4619
2302
  TypedKeyframeTrack = three.NumberKeyframeTrack;
4620
2303
  break;
4621
-
4622
2304
  case PATH_PROPERTIES.rotation:
4623
-
4624
2305
  TypedKeyframeTrack = three.QuaternionKeyframeTrack;
4625
2306
  break;
4626
-
4627
2307
  case PATH_PROPERTIES.translation:
4628
2308
  case PATH_PROPERTIES.scale:
4629
-
4630
2309
  TypedKeyframeTrack = three.VectorKeyframeTrack;
4631
2310
  break;
4632
-
4633
2311
  default:
4634
-
4635
2312
  switch ( outputAccessor.itemSize ) {
4636
-
4637
2313
  case 1:
4638
2314
  TypedKeyframeTrack = three.NumberKeyframeTrack;
4639
2315
  break;
@@ -4642,293 +2318,133 @@
4642
2318
  default:
4643
2319
  TypedKeyframeTrack = three.VectorKeyframeTrack;
4644
2320
  break;
4645
-
4646
2321
  }
4647
-
4648
2322
  break;
4649
-
4650
2323
  }
4651
-
4652
2324
  const interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : three.InterpolateLinear;
4653
-
4654
-
4655
2325
  const outputArray = this._getArrayFromAccessor( outputAccessor );
4656
-
4657
2326
  for ( let j = 0, jl = targetNames.length; j < jl; j ++ ) {
4658
-
4659
2327
  const track = new TypedKeyframeTrack(
4660
2328
  targetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],
4661
2329
  inputAccessor.array,
4662
2330
  outputArray,
4663
2331
  interpolation
4664
2332
  );
4665
-
4666
- // Override interpolation with custom factory method.
4667
2333
  if ( sampler.interpolation === 'CUBICSPLINE' ) {
4668
-
4669
2334
  this._createCubicSplineTrackInterpolant( track );
4670
-
4671
2335
  }
4672
-
4673
2336
  tracks.push( track );
4674
-
4675
2337
  }
4676
-
4677
2338
  return tracks;
4678
-
4679
2339
  }
4680
-
4681
2340
  _getArrayFromAccessor( accessor ) {
4682
-
4683
2341
  let outputArray = accessor.array;
4684
-
4685
2342
  if ( accessor.normalized ) {
4686
-
4687
2343
  const scale = getNormalizedComponentScale( outputArray.constructor );
4688
2344
  const scaled = new Float32Array( outputArray.length );
4689
-
4690
2345
  for ( let j = 0, jl = outputArray.length; j < jl; j ++ ) {
4691
-
4692
2346
  scaled[ j ] = outputArray[ j ] * scale;
4693
-
4694
2347
  }
4695
-
4696
2348
  outputArray = scaled;
4697
-
4698
2349
  }
4699
-
4700
2350
  return outputArray;
4701
-
4702
2351
  }
4703
-
4704
2352
  _createCubicSplineTrackInterpolant( track ) {
4705
-
4706
2353
  track.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {
4707
-
4708
- // A CUBICSPLINE keyframe in glTF has three output values for each input value,
4709
- // representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()
4710
- // must be divided by three to get the interpolant's sampleSize argument.
4711
-
4712
2354
  const interpolantType = ( this instanceof three.QuaternionKeyframeTrack ) ? GLTFCubicSplineQuaternionInterpolant : GLTFCubicSplineInterpolant;
4713
-
4714
2355
  return new interpolantType( this.times, this.values, this.getValueSize() / 3, result );
4715
-
4716
2356
  };
4717
-
4718
- // Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.
4719
2357
  track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;
4720
-
4721
2358
  }
4722
-
4723
2359
  }
4724
-
4725
- /**
4726
- *
4727
- * @private
4728
- * @param {BufferGeometry} geometry
4729
- * @param {GLTF.Primitive} primitiveDef
4730
- * @param {GLTFParser} parser
4731
- */
4732
2360
  function computeBounds( geometry, primitiveDef, parser ) {
4733
-
4734
2361
  const attributes = primitiveDef.attributes;
4735
-
4736
2362
  const box = new three.Box3();
4737
-
4738
2363
  if ( attributes.POSITION !== undefined ) {
4739
-
4740
2364
  const accessor = parser.json.accessors[ attributes.POSITION ];
4741
-
4742
2365
  const min = accessor.min;
4743
2366
  const max = accessor.max;
4744
-
4745
- // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.
4746
-
4747
2367
  if ( min !== undefined && max !== undefined ) {
4748
-
4749
2368
  box.set(
4750
2369
  new three.Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
4751
2370
  new three.Vector3( max[ 0 ], max[ 1 ], max[ 2 ] )
4752
2371
  );
4753
-
4754
2372
  if ( accessor.normalized ) {
4755
-
4756
2373
  const boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );
4757
2374
  box.min.multiplyScalar( boxScale );
4758
2375
  box.max.multiplyScalar( boxScale );
4759
-
4760
2376
  }
4761
-
4762
2377
  } else {
4763
-
4764
2378
  console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );
4765
-
4766
2379
  return;
4767
-
4768
2380
  }
4769
-
4770
2381
  } else {
4771
-
4772
2382
  return;
4773
-
4774
2383
  }
4775
-
4776
2384
  const targets = primitiveDef.targets;
4777
-
4778
2385
  if ( targets !== undefined ) {
4779
-
4780
2386
  const maxDisplacement = new three.Vector3();
4781
2387
  const vector = new three.Vector3();
4782
-
4783
2388
  for ( let i = 0, il = targets.length; i < il; i ++ ) {
4784
-
4785
2389
  const target = targets[ i ];
4786
-
4787
2390
  if ( target.POSITION !== undefined ) {
4788
-
4789
2391
  const accessor = parser.json.accessors[ target.POSITION ];
4790
2392
  const min = accessor.min;
4791
2393
  const max = accessor.max;
4792
-
4793
- // glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.
4794
-
4795
2394
  if ( min !== undefined && max !== undefined ) {
4796
-
4797
- // we need to get max of absolute components because target weight is [-1,1]
4798
2395
  vector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) );
4799
2396
  vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );
4800
2397
  vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );
4801
-
4802
-
4803
2398
  if ( accessor.normalized ) {
4804
-
4805
2399
  const boxScale = getNormalizedComponentScale( WEBGL_COMPONENT_TYPES[ accessor.componentType ] );
4806
2400
  vector.multiplyScalar( boxScale );
4807
-
4808
2401
  }
4809
-
4810
- // Note: this assumes that the sum of all weights is at most 1. This isn't quite correct - it's more conservative
4811
- // to assume that each target can have a max weight of 1. However, for some use cases - notably, when morph targets
4812
- // are used to implement key-frame animations and as such only two are active at a time - this results in very large
4813
- // boxes. So for now we make a box that's sometimes a touch too small but is hopefully mostly of reasonable size.
4814
2402
  maxDisplacement.max( vector );
4815
-
4816
2403
  } else {
4817
-
4818
2404
  console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );
4819
-
4820
2405
  }
4821
-
4822
2406
  }
4823
-
4824
2407
  }
4825
-
4826
- // As per comment above this box isn't conservative, but has a reasonable size for a very large number of morph targets.
4827
2408
  box.expandByVector( maxDisplacement );
4828
-
4829
2409
  }
4830
-
4831
2410
  geometry.boundingBox = box;
4832
-
4833
2411
  const sphere = new three.Sphere();
4834
-
4835
2412
  box.getCenter( sphere.center );
4836
2413
  sphere.radius = box.min.distanceTo( box.max ) / 2;
4837
-
4838
2414
  geometry.boundingSphere = sphere;
4839
-
4840
2415
  }
4841
-
4842
- /**
4843
- *
4844
- * @private
4845
- * @param {BufferGeometry} geometry
4846
- * @param {GLTF.Primitive} primitiveDef
4847
- * @param {GLTFParser} parser
4848
- * @return {Promise<BufferGeometry>}
4849
- */
4850
2416
  function addPrimitiveAttributes( geometry, primitiveDef, parser ) {
4851
-
4852
2417
  const attributes = primitiveDef.attributes;
4853
-
4854
2418
  const pending = [];
4855
-
4856
2419
  function assignAttributeAccessor( accessorIndex, attributeName ) {
4857
-
4858
2420
  return parser.getDependency( 'accessor', accessorIndex )
4859
2421
  .then( function ( accessor ) {
4860
-
4861
2422
  geometry.setAttribute( attributeName, accessor );
4862
-
4863
2423
  } );
4864
-
4865
2424
  }
4866
-
4867
2425
  for ( const gltfAttributeName in attributes ) {
4868
-
4869
2426
  const threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase();
4870
-
4871
- // Skip attributes already provided by e.g. Draco extension.
4872
2427
  if ( threeAttributeName in geometry.attributes ) continue;
4873
-
4874
2428
  pending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );
4875
-
4876
2429
  }
4877
-
4878
2430
  if ( primitiveDef.indices !== undefined && ! geometry.index ) {
4879
-
4880
2431
  const accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) {
4881
-
4882
2432
  geometry.setIndex( accessor );
4883
-
4884
2433
  } );
4885
-
4886
2434
  pending.push( accessor );
4887
-
4888
2435
  }
4889
-
4890
2436
  if ( three.ColorManagement.workingColorSpace !== three.LinearSRGBColorSpace && 'COLOR_0' in attributes ) {
4891
-
4892
2437
  console.warn( `THREE.GLTFLoader: Converting vertex colors from "srgb-linear" to "${three.ColorManagement.workingColorSpace}" not supported.` );
4893
-
4894
2438
  }
4895
-
4896
2439
  assignExtrasToUserData( geometry, primitiveDef );
4897
-
4898
2440
  computeBounds( geometry, primitiveDef, parser );
4899
-
4900
2441
  return Promise.all( pending ).then( function () {
4901
-
4902
2442
  return primitiveDef.targets !== undefined
4903
2443
  ? addMorphTargets( geometry, primitiveDef.targets, parser )
4904
2444
  : geometry;
4905
-
4906
2445
  } );
4907
-
4908
2446
  }
4909
2447
 
4910
- ///////////////////////////////////////////////////////////////////////////////
4911
- // Copyright (C) 2002-2025, Open Design Alliance (the "Alliance").
4912
- // All rights reserved.
4913
- //
4914
- // This software and its documentation and related materials are owned by
4915
- // the Alliance. The software may only be incorporated into application
4916
- // programs owned by members of the Alliance, subject to a signed
4917
- // Membership Agreement and Supplemental Software License Agreement with the
4918
- // Alliance. The structure and organization of this software are the valuable
4919
- // trade secrets of the Alliance and its suppliers. The software is also
4920
- // protected by copyright law and international treaty provisions. Application
4921
- // programs incorporating this software must include the following statement
4922
- // with their copyright notices:
4923
- //
4924
- // This application incorporates Open Design Alliance software pursuant to a
4925
- // license agreement with Open Design Alliance.
4926
- // Open Design Alliance Copyright (C) 2002-2025 by Open Design Alliance.
4927
- // All rights reserved.
4928
- //
4929
- // By use of this software, its documentation or related materials, you
4930
- // acknowledge and accept the above terms.
4931
- ///////////////////////////////////////////////////////////////////////////////
4932
2448
  class GLTFCloudLoader extends viewerThree.Loader {
4933
2449
  constructor(viewer) {
4934
2450
  super();