GLTFLoader.js 81.5 KB
Newer Older
D
Don McCurdy 已提交
1 2 3 4 5 6 7 8
/**
 * @author Rich Tibbett / https://github.com/richtr
 * @author mrdoob / http://mrdoob.com/
 * @author Tony Parisi / http://www.tonyparisi.com/
 * @author Takahiro / https://github.com/takahirox
 * @author Don McCurdy / https://www.donmccurdy.com
 */

9
THREE.GLTFLoader = ( function () {
D
Don McCurdy 已提交
10

11
	function GLTFLoader( manager ) {
D
Don McCurdy 已提交
12

M
Mugen87 已提交
13 14
		THREE.Loader.call( this, manager );

15
		this.dracoLoader = null;
M
Mugen87 已提交
16
		this.ddsLoader = null;
D
Don McCurdy 已提交
17 18 19

	}

M
Mugen87 已提交
20
	GLTFLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
D
Don McCurdy 已提交
21

22
		constructor: GLTFLoader,
D
Don McCurdy 已提交
23 24 25 26 27

		load: function ( url, onLoad, onProgress, onError ) {

			var scope = this;

28 29
			var resourcePath;

M
Mugen87 已提交
30
			if ( this.resourcePath !== '' ) {
31 32 33

				resourcePath = this.resourcePath;

M
Mugen87 已提交
34
			} else if ( this.path !== '' ) {
35 36 37 38 39 40 41 42

				resourcePath = this.path;

			} else {

				resourcePath = THREE.LoaderUtils.extractUrlBase( url );

			}
D
Don McCurdy 已提交
43

44 45 46 47
			// Tells the LoadingManager to track an extra item, which resolves after
			// the model is fully loaded. This means the count of items loaded will
			// be incorrect, but ensures manager.onLoad() does not fire early.
			scope.manager.itemStart( url );
48 49 50 51 52 53 54 55 56 57 58 59 60

			var _onError = function ( e ) {

				if ( onError ) {

					onError( e );

				} else {

					console.error( e );

				}

61
				scope.manager.itemError( url );
62
				scope.manager.itemEnd( url );
63 64

			};
D
Don McCurdy 已提交
65 66 67

			var loader = new THREE.FileLoader( scope.manager );

T
Takahiro 已提交
68
			loader.setPath( this.path );
D
Don McCurdy 已提交
69 70
			loader.setResponseType( 'arraybuffer' );

71 72 73 74 75 76
			if ( scope.crossOrigin === 'use-credentials' ) {

				loader.setWithCredentials( true );

			}

D
Don McCurdy 已提交
77 78
			loader.load( url, function ( data ) {

79 80
				try {

81
					scope.parse( data, resourcePath, function ( gltf ) {
82

83
						onLoad( gltf );
84

85
						scope.manager.itemEnd( url );
D
Don McCurdy 已提交
86

87
					}, _onError );
D
Don McCurdy 已提交
88

89
				} catch ( e ) {
90

91
					_onError( e );
92 93

				}
D
Don McCurdy 已提交
94

95
			}, onProgress, _onError );
D
Don McCurdy 已提交
96 97 98

		},

99 100 101
		setDRACOLoader: function ( dracoLoader ) {

			this.dracoLoader = dracoLoader;
102
			return this;
103 104 105

		},

M
Mugen87 已提交
106 107 108 109 110 111 112
		setDDSLoader: function ( ddsLoader ) {

			this.ddsLoader = ddsLoader;
			return this;

		},

113
		parse: function ( data, path, onLoad, onError ) {
D
Don McCurdy 已提交
114 115 116 117

			var content;
			var extensions = {};

118
			if ( typeof data === 'string' ) {
D
Don McCurdy 已提交
119

120
				content = data;
D
Don McCurdy 已提交
121 122 123

			} else {

124
				var magic = THREE.LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) );
D
Don McCurdy 已提交
125

126
				if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {
127

T
Takahiro 已提交
128 129 130 131 132 133
					try {

						extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );

					} catch ( error ) {

T
Takahiro 已提交
134
						if ( onError ) onError( error );
T
Takahiro 已提交
135 136 137 138
						return;

					}

139 140 141
					content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;

				} else {
D
Don McCurdy 已提交
142

143
					content = THREE.LoaderUtils.decodeText( new Uint8Array( data ) );
144 145 146 147

				}

			}
D
Don McCurdy 已提交
148

149
			var json = JSON.parse( content );
150

151
			if ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {
152

M
Mugen87 已提交
153
				if ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) );
154 155 156 157
				return;

			}

158
			if ( json.extensionsUsed ) {
D
Don McCurdy 已提交
159

160
				for ( var i = 0; i < json.extensionsUsed.length; ++ i ) {
161

162
					var extensionName = json.extensionsUsed[ i ];
163
					var extensionsRequired = json.extensionsRequired || [];
164

165
					switch ( extensionName ) {
166

167
						case EXTENSIONS.KHR_LIGHTS_PUNCTUAL:
168 169
							extensions[ extensionName ] = new GLTFLightsExtension( json );
							break;
170

171
						case EXTENSIONS.KHR_MATERIALS_UNLIT:
G
Gero3 已提交
172
							extensions[ extensionName ] = new GLTFMaterialsUnlitExtension();
173
							break;
174

175
						case EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS:
G
Gero3 已提交
176
							extensions[ extensionName ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
177
							break;
178

179
						case EXTENSIONS.KHR_DRACO_MESH_COMPRESSION:
180
							extensions[ extensionName ] = new GLTFDracoMeshCompressionExtension( json, this.dracoLoader );
181
							break;
182

D
Don McCurdy 已提交
183
						case EXTENSIONS.MSFT_TEXTURE_DDS:
184
							extensions[ extensionName ] = new GLTFTextureDDSExtension( this.ddsLoader );
185 186 187
							break;

						case EXTENSIONS.KHR_TEXTURE_TRANSFORM:
188
							extensions[ extensionName ] = new GLTFTextureTransformExtension();
D
Don McCurdy 已提交
189
							break;
D
Don McCurdy 已提交
190

191 192 193 194
						case EXTENSIONS.KHR_MESH_QUANTIZATION:
							extensions[ extensionName ] = new GLTFMeshQuantizationExtension();
							break;

195
						default:
196

197
							if ( extensionsRequired.indexOf( extensionName ) >= 0 ) {
198

199
								console.warn( 'THREE.GLTFLoader: Unknown extension "' + extensionName + '".' );
200

201
							}
202

203
					}
204 205 206

				}

D
Don McCurdy 已提交
207 208 209 210
			}

			var parser = new GLTFParser( json, extensions, {

211
				path: path || this.resourcePath || '',
M
Mugen87 已提交
212 213
				crossOrigin: this.crossOrigin,
				manager: this.manager
D
Don McCurdy 已提交
214 215 216

			} );

217
			parser.parse( onLoad, onError );
D
Don McCurdy 已提交
218 219 220

		}

M
Mugen87 已提交
221
	} );
D
Don McCurdy 已提交
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264

	/* GLTFREGISTRY */

	function GLTFRegistry() {

		var objects = {};

		return	{

			get: function ( key ) {

				return objects[ key ];

			},

			add: function ( key, object ) {

				objects[ key ] = object;

			},

			remove: function ( key ) {

				delete objects[ key ];

			},

			removeAll: function () {

				objects = {};

			}

		};

	}

	/*********************************/
	/********** EXTENSIONS ***********/
	/*********************************/

	var EXTENSIONS = {
		KHR_BINARY_GLTF: 'KHR_binary_glTF',
265
		KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
266
		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
267
		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
268
		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
269
		KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
270
		KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
271
		MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
D
Don McCurdy 已提交
272 273
	};

274 275 276
	/**
	 * DDS Texture Extension
	 *
277
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Vendor/MSFT_texture_dds
M
Mugen87 已提交
278
	 *
279
	 */
M
Mugen87 已提交
280
	function GLTFTextureDDSExtension( ddsLoader ) {
281

M
Mugen87 已提交
282
		if ( ! ddsLoader ) {
283 284 285 286 287

			throw new Error( 'THREE.GLTFLoader: Attempting to load .dds texture without importing THREE.DDSLoader' );

		}

288
		this.name = EXTENSIONS.MSFT_TEXTURE_DDS;
M
Mugen87 已提交
289
		this.ddsLoader = ddsLoader;
290 291 292

	}

293
	/**
294
	 * Punctual Lights Extension
295
	 *
296
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_lights_punctual
297 298
	 */
	function GLTFLightsExtension( json ) {
D
Don McCurdy 已提交
299

300
		this.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;
D
Don McCurdy 已提交
301

302
		var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ] ) || {};
T
Takahiro 已提交
303
		this.lightDefs = extension.lights || [];
D
Don McCurdy 已提交
304

T
Takahiro 已提交
305
	}
D
Don McCurdy 已提交
306

T
Takahiro 已提交
307
	GLTFLightsExtension.prototype.loadLight = function ( lightIndex ) {
D
Don McCurdy 已提交
308

T
Takahiro 已提交
309 310
		var lightDef = this.lightDefs[ lightIndex ];
		var lightNode;
D
Don McCurdy 已提交
311

T
Takahiro 已提交
312 313
		var color = new THREE.Color( 0xffffff );
		if ( lightDef.color !== undefined ) color.fromArray( lightDef.color );
314

T
Takahiro 已提交
315
		var range = lightDef.range !== undefined ? lightDef.range : 0;
D
Don McCurdy 已提交
316

T
Takahiro 已提交
317
		switch ( lightDef.type ) {
D
Don McCurdy 已提交
318

T
Takahiro 已提交
319 320
			case 'directional':
				lightNode = new THREE.DirectionalLight( color );
M
Mugen87 已提交
321
				lightNode.target.position.set( 0, 0, - 1 );
T
Takahiro 已提交
322 323
				lightNode.add( lightNode.target );
				break;
D
Don McCurdy 已提交
324

T
Takahiro 已提交
325 326 327 328
			case 'point':
				lightNode = new THREE.PointLight( color );
				lightNode.distance = range;
				break;
D
Don McCurdy 已提交
329

T
Takahiro 已提交
330 331 332 333 334 335 336 337 338
			case 'spot':
				lightNode = new THREE.SpotLight( color );
				lightNode.distance = range;
				// Handle spotlight properties.
				lightDef.spot = lightDef.spot || {};
				lightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;
				lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
				lightNode.angle = lightDef.spot.outerConeAngle;
				lightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;
M
Mugen87 已提交
339
				lightNode.target.position.set( 0, 0, - 1 );
T
Takahiro 已提交
340 341
				lightNode.add( lightNode.target );
				break;
D
Don McCurdy 已提交
342

T
Takahiro 已提交
343 344
			default:
				throw new Error( 'THREE.GLTFLoader: Unexpected light type, "' + lightDef.type + '".' );
345

T
Takahiro 已提交
346
		}
347

348 349 350 351
		// Some lights (e.g. spot) default to a position other than the origin. Reset the position
		// here, because node-level parsing will only override position if explicitly specified.
		lightNode.position.set( 0, 0, 0 );

T
Takahiro 已提交
352
		lightNode.decay = 2;
353

T
Takahiro 已提交
354
		if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;
D
Don McCurdy 已提交
355

T
Takahiro 已提交
356
		lightNode.name = lightDef.name || ( 'light_' + lightIndex );
D
Don McCurdy 已提交
357

T
Takahiro 已提交
358
		return Promise.resolve( lightNode );
D
Don McCurdy 已提交
359

T
Takahiro 已提交
360
	};
D
Don McCurdy 已提交
361

362
	/**
363
	 * Unlit Materials Extension
364
	 *
365
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_unlit
366
	 */
T
Takahiro 已提交
367
	function GLTFMaterialsUnlitExtension() {
368 369 370 371 372

		this.name = EXTENSIONS.KHR_MATERIALS_UNLIT;

	}

T
Takahiro 已提交
373
	GLTFMaterialsUnlitExtension.prototype.getMaterialType = function () {
374 375 376 377 378

		return THREE.MeshBasicMaterial;

	};

T
Takahiro 已提交
379
	GLTFMaterialsUnlitExtension.prototype.extendParams = function ( materialParams, materialDef, parser ) {
380

381
		var pending = [];
382 383 384 385

		materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
		materialParams.opacity = 1.0;

T
Takahiro 已提交
386
		var metallicRoughness = materialDef.pbrMetallicRoughness;
387

388
		if ( metallicRoughness ) {
389

390
			if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
391

392 393 394 395
				var array = metallicRoughness.baseColorFactor;

				materialParams.color.fromArray( array );
				materialParams.opacity = array[ 3 ];
396

397
			}
398

399 400
			if ( metallicRoughness.baseColorTexture !== undefined ) {

401
				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
402 403

			}
404 405 406

		}

407
		return Promise.all( pending );
408 409 410

	};

D
Don McCurdy 已提交
411
	/* BINARY EXTENSION */
412 413 414
	var BINARY_EXTENSION_HEADER_MAGIC = 'glTF';
	var BINARY_EXTENSION_HEADER_LENGTH = 12;
	var BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };
D
Don McCurdy 已提交
415 416 417 418

	function GLTFBinaryExtension( data ) {

		this.name = EXTENSIONS.KHR_BINARY_GLTF;
419 420
		this.content = null;
		this.body = null;
D
Don McCurdy 已提交
421 422 423

		var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );

424
		this.header = {
425
			magic: THREE.LoaderUtils.decodeText( new Uint8Array( data.slice( 0, 4 ) ) ),
D
Don McCurdy 已提交
426
			version: headerView.getUint32( 4, true ),
427
			length: headerView.getUint32( 8, true )
D
Don McCurdy 已提交
428 429
		};

430
		if ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {
D
Don McCurdy 已提交
431

432
			throw new Error( 'THREE.GLTFLoader: Unsupported glTF-Binary header.' );
D
Don McCurdy 已提交
433

434
		} else if ( this.header.version < 2.0 ) {
D
Don McCurdy 已提交
435

M
Mugen87 已提交
436
			throw new Error( 'THREE.GLTFLoader: Legacy binary file detected.' );
D
Don McCurdy 已提交
437 438 439

		}

440 441
		var chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );
		var chunkIndex = 0;
D
Don McCurdy 已提交
442

443
		while ( chunkIndex < chunkView.byteLength ) {
D
Don McCurdy 已提交
444

445 446
			var chunkLength = chunkView.getUint32( chunkIndex, true );
			chunkIndex += 4;
D
Don McCurdy 已提交
447

448 449
			var chunkType = chunkView.getUint32( chunkIndex, true );
			chunkIndex += 4;
D
Don McCurdy 已提交
450

451
			if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {
D
Don McCurdy 已提交
452

453
				var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );
454
				this.content = THREE.LoaderUtils.decodeText( contentArray );
D
Don McCurdy 已提交
455

456
			} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {
D
Don McCurdy 已提交
457

458 459
				var byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;
				this.body = data.slice( byteOffset, byteOffset + chunkLength );
D
Don McCurdy 已提交
460

461
			}
D
Don McCurdy 已提交
462

463
			// Clients must ignore chunks with unknown types.
D
Don McCurdy 已提交
464

465 466 467 468 469 470
			chunkIndex += chunkLength;

		}

		if ( this.content === null ) {

471
			throw new Error( 'THREE.GLTFLoader: JSON content not found.' );
472 473 474 475

		}

	}
D
Don McCurdy 已提交
476

477 478 479
	/**
	 * DRACO Mesh Compression Extension
	 *
480
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_draco_mesh_compression
481
	 */
M
Mugen87 已提交
482
	function GLTFDracoMeshCompressionExtension( json, dracoLoader ) {
483 484 485 486 487 488 489 490

		if ( ! dracoLoader ) {

			throw new Error( 'THREE.GLTFLoader: No DRACOLoader instance provided.' );

		}

		this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
491
		this.json = json;
492
		this.dracoLoader = dracoLoader;
493
		this.dracoLoader.preload();
494

495 496 497 498
	}

	GLTFDracoMeshCompressionExtension.prototype.decodePrimitive = function ( primitive, parser ) {

499
		var json = this.json;
500 501
		var dracoLoader = this.dracoLoader;
		var bufferViewIndex = primitive.extensions[ this.name ].bufferView;
502 503
		var gltfAttributeMap = primitive.extensions[ this.name ].attributes;
		var threeAttributeMap = {};
504 505
		var attributeNormalizedMap = {};
		var attributeTypeMap = {};
506 507 508

		for ( var attributeName in gltfAttributeMap ) {

509
			var threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();
510

511
			threeAttributeMap[ threeAttributeName ] = gltfAttributeMap[ attributeName ];
512

513
		}
514

515
		for ( attributeName in primitive.attributes ) {
516

517 518 519
			var threeAttributeName = ATTRIBUTES[ attributeName ] || attributeName.toLowerCase();

			if ( gltfAttributeMap[ attributeName ] !== undefined ) {
520

521 522
				var accessorDef = json.accessors[ primitive.attributes[ attributeName ] ];
				var componentType = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
523

524 525
				attributeTypeMap[ threeAttributeName ] = componentType;
				attributeNormalizedMap[ threeAttributeName ] = accessorDef.normalized === true;
526 527

			}
528

529
		}
530

531
		return parser.getDependency( 'bufferView', bufferViewIndex ).then( function ( bufferView ) {
532

533
			return new Promise( function ( resolve ) {
534

535
				dracoLoader.decodeDracoFile( bufferView, function ( geometry ) {
536

537
					for ( var attributeName in geometry.attributes ) {
538

539 540 541 542
						var attribute = geometry.attributes[ attributeName ];
						var normalized = attributeNormalizedMap[ attributeName ];

						if ( normalized !== undefined ) attribute.normalized = normalized;
543 544 545 546 547

					}

					resolve( geometry );

548
				}, threeAttributeMap, attributeTypeMap );
549 550 551 552 553 554 555

			} );

		} );

	};

556 557 558
	/**
	 * Texture Transform Extension
	 *
559
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_texture_transform
560
	 */
T
Takahiro 已提交
561
	function GLTFTextureTransformExtension() {
562 563 564 565 566

		this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;

	}

D
Don McCurdy 已提交
567
	GLTFTextureTransformExtension.prototype.extendTexture = function ( texture, transform ) {
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588

		texture = texture.clone();

		if ( transform.offset !== undefined ) {

			texture.offset.fromArray( transform.offset );

		}

		if ( transform.rotation !== undefined ) {

			texture.rotation = transform.rotation;

		}

		if ( transform.scale !== undefined ) {

			texture.repeat.fromArray( transform.scale );

		}

589 590 591 592 593 594
		if ( transform.texCoord !== undefined ) {

			console.warn( 'THREE.GLTFLoader: Custom UV sets in "' + this.name + '" extension not yet supported.' );

		}

595 596 597 598 599 600
		texture.needsUpdate = true;

		return texture;

	};

601 602 603
	/**
	 * Specular-Glossiness Extension
	 *
604
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_pbrSpecularGlossiness
605
	 */
606 607 608 609
	function GLTFMaterialsPbrSpecularGlossinessExtension() {

		return {

610 611
			name: EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS,

612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
			specularGlossinessParams: [
				'color',
				'map',
				'lightMap',
				'lightMapIntensity',
				'aoMap',
				'aoMapIntensity',
				'emissive',
				'emissiveIntensity',
				'emissiveMap',
				'bumpMap',
				'bumpScale',
				'normalMap',
				'displacementMap',
				'displacementScale',
				'displacementBias',
				'specularMap',
				'specular',
				'glossinessMap',
				'glossiness',
				'alphaMap',
				'envMap',
				'envMapIntensity',
				'refractionRatio',
			],

638 639 640 641 642 643
			getMaterialType: function () {

				return THREE.ShaderMaterial;

			},

T
Takahiro 已提交
644
			extendParams: function ( materialParams, materialDef, parser ) {
645

T
Takahiro 已提交
646
				var pbrSpecularGlossiness = materialDef.extensions[ this.name ];
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667

				var shader = THREE.ShaderLib[ 'standard' ];

				var uniforms = THREE.UniformsUtils.clone( shader.uniforms );

				var specularMapParsFragmentChunk = [
					'#ifdef USE_SPECULARMAP',
					'	uniform sampler2D specularMap;',
					'#endif'
				].join( '\n' );

				var glossinessMapParsFragmentChunk = [
					'#ifdef USE_GLOSSINESSMAP',
					'	uniform sampler2D glossinessMap;',
					'#endif'
				].join( '\n' );

				var specularMapFragmentChunk = [
					'vec3 specularFactor = specular;',
					'#ifdef USE_SPECULARMAP',
					'	vec4 texelSpecular = texture2D( specularMap, vUv );',
668
					'	texelSpecular = sRGBToLinear( texelSpecular );',
669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
					'	// reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',
					'	specularFactor *= texelSpecular.rgb;',
					'#endif'
				].join( '\n' );

				var glossinessMapFragmentChunk = [
					'float glossinessFactor = glossiness;',
					'#ifdef USE_GLOSSINESSMAP',
					'	vec4 texelGlossiness = texture2D( glossinessMap, vUv );',
					'	// reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture',
					'	glossinessFactor *= texelGlossiness.a;',
					'#endif'
				].join( '\n' );

				var lightPhysicalFragmentChunk = [
					'PhysicalMaterial material;',
					'material.diffuseColor = diffuseColor.rgb;',
					'material.specularRoughness = clamp( 1.0 - glossinessFactor, 0.04, 1.0 );',
					'material.specularColor = specularFactor.rgb;',
				].join( '\n' );

				var fragmentShader = shader.fragmentShader
M
Mugen87 已提交
691 692 693 694 695 696 697
					.replace( 'uniform float roughness;', 'uniform vec3 specular;' )
					.replace( 'uniform float metalness;', 'uniform float glossiness;' )
					.replace( '#include <roughnessmap_pars_fragment>', specularMapParsFragmentChunk )
					.replace( '#include <metalnessmap_pars_fragment>', glossinessMapParsFragmentChunk )
					.replace( '#include <roughnessmap_fragment>', specularMapFragmentChunk )
					.replace( '#include <metalnessmap_fragment>', glossinessMapFragmentChunk )
					.replace( '#include <lights_physical_fragment>', lightPhysicalFragmentChunk );
698 699 700 701 702 703 704 705 706 707 708

				delete uniforms.roughness;
				delete uniforms.metalness;
				delete uniforms.roughnessMap;
				delete uniforms.metalnessMap;

				uniforms.specular = { value: new THREE.Color().setHex( 0x111111 ) };
				uniforms.glossiness = { value: 0.5 };
				uniforms.specularMap = { value: null };
				uniforms.glossinessMap = { value: null };

T
Takahiro 已提交
709 710 711
				materialParams.vertexShader = shader.vertexShader;
				materialParams.fragmentShader = fragmentShader;
				materialParams.uniforms = uniforms;
M
Mugen87 已提交
712
				materialParams.defines = { 'STANDARD': '' };
713

T
Takahiro 已提交
714 715
				materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
				materialParams.opacity = 1.0;
716

717
				var pending = [];
718

719 720 721 722
				if ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) {

					var array = pbrSpecularGlossiness.diffuseFactor;

T
Takahiro 已提交
723 724
					materialParams.color.fromArray( array );
					materialParams.opacity = array[ 3 ];
725 726 727 728 729

				}

				if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {

T
Takahiro 已提交
730
					pending.push( parser.assignTexture( materialParams, 'map', pbrSpecularGlossiness.diffuseTexture ) );
731 732 733

				}

T
Takahiro 已提交
734 735 736
				materialParams.emissive = new THREE.Color( 0.0, 0.0, 0.0 );
				materialParams.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;
				materialParams.specular = new THREE.Color( 1.0, 1.0, 1.0 );
737 738 739

				if ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) {

T
Takahiro 已提交
740
					materialParams.specular.fromArray( pbrSpecularGlossiness.specularFactor );
741 742 743 744 745

				}

				if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {

746
					var specGlossMapDef = pbrSpecularGlossiness.specularGlossinessTexture;
T
Takahiro 已提交
747 748
					pending.push( parser.assignTexture( materialParams, 'glossinessMap', specGlossMapDef ) );
					pending.push( parser.assignTexture( materialParams, 'specularMap', specGlossMapDef ) );
749 750 751

				}

752
				return Promise.all( pending );
753

754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
			},

			createMaterial: function ( params ) {

				// setup material properties based on MeshStandardMaterial for Specular-Glossiness

				var material = new THREE.ShaderMaterial( {
					defines: params.defines,
					vertexShader: params.vertexShader,
					fragmentShader: params.fragmentShader,
					uniforms: params.uniforms,
					fog: true,
					lights: true,
					opacity: params.opacity,
					transparent: params.transparent
				} );

771 772
				material.isGLTFSpecularGlossinessMaterial = true;

773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790
				material.color = params.color;

				material.map = params.map === undefined ? null : params.map;

				material.lightMap = null;
				material.lightMapIntensity = 1.0;

				material.aoMap = params.aoMap === undefined ? null : params.aoMap;
				material.aoMapIntensity = 1.0;

				material.emissive = params.emissive;
				material.emissiveIntensity = 1.0;
				material.emissiveMap = params.emissiveMap === undefined ? null : params.emissiveMap;

				material.bumpMap = params.bumpMap === undefined ? null : params.bumpMap;
				material.bumpScale = 1;

				material.normalMap = params.normalMap === undefined ? null : params.normalMap;
T
Takahiro 已提交
791

792
				if ( params.normalScale ) material.normalScale = params.normalScale;
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816

				material.displacementMap = null;
				material.displacementScale = 1;
				material.displacementBias = 0;

				material.specularMap = params.specularMap === undefined ? null : params.specularMap;
				material.specular = params.specular;

				material.glossinessMap = params.glossinessMap === undefined ? null : params.glossinessMap;
				material.glossiness = params.glossiness;

				material.alphaMap = null;

				material.envMap = params.envMap === undefined ? null : params.envMap;
				material.envMapIntensity = 1.0;

				material.refractionRatio = 0.98;

				material.extensions.derivatives = true;

				return material;

			},

817 818 819 820 821 822 823 824 825 826 827 828
			/**
			 * Clones a GLTFSpecularGlossinessMaterial instance. The ShaderMaterial.copy() method can
			 * copy only properties it knows about or inherits, and misses many properties that would
			 * normally be defined by MeshStandardMaterial.
			 *
			 * This method allows GLTFSpecularGlossinessMaterials to be cloned in the process of
			 * loading a glTF model, but cloning later (e.g. by the user) would require these changes
			 * AND also updating `.onBeforeRender` on the parent mesh.
			 *
			 * @param  {THREE.ShaderMaterial} source
			 * @return {THREE.ShaderMaterial}
			 */
829 830 831 832 833 834 835 836
			cloneMaterial: function ( source ) {

				var target = source.clone();

				target.isGLTFSpecularGlossinessMaterial = true;

				var params = this.specularGlossinessParams;

T
Takahiro 已提交
837
				for ( var i = 0, il = params.length; i < il; i ++ ) {
838

B
but0n 已提交
839
					var value = source[ params[ i ] ];
840
					target[ params[ i ] ] = ( value && value.isColor ) ? value.clone() : value;
841 842 843 844 845 846 847

				}

				return target;

			},

848
			// Here's based on refreshUniformsCommon() and refreshUniformsStandard() in WebGLRenderer.
M
Mugen87 已提交
849
			refreshUniforms: function ( renderer, scene, camera, geometry, material ) {
850

P
Pascal Häusler 已提交
851
				if ( material.isGLTFSpecularGlossinessMaterial !== true ) {
852 853 854 855 856

					return;

				}

857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
				var uniforms = material.uniforms;
				var defines = material.defines;

				uniforms.opacity.value = material.opacity;

				uniforms.diffuse.value.copy( material.color );
				uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );

				uniforms.map.value = material.map;
				uniforms.specularMap.value = material.specularMap;
				uniforms.alphaMap.value = material.alphaMap;

				uniforms.lightMap.value = material.lightMap;
				uniforms.lightMapIntensity.value = material.lightMapIntensity;

				uniforms.aoMap.value = material.aoMap;
				uniforms.aoMapIntensity.value = material.aoMapIntensity;

				// uv repeat and offset setting priorities
				// 1. color map
				// 2. specular map
				// 3. normal map
				// 4. bump map
				// 5. alpha map
				// 6. emissive map

				var uvScaleMap;

				if ( material.map ) {

					uvScaleMap = material.map;

				} else if ( material.specularMap ) {

					uvScaleMap = material.specularMap;

				} else if ( material.displacementMap ) {

					uvScaleMap = material.displacementMap;

				} else if ( material.normalMap ) {

					uvScaleMap = material.normalMap;

				} else if ( material.bumpMap ) {

					uvScaleMap = material.bumpMap;

				} else if ( material.glossinessMap ) {

					uvScaleMap = material.glossinessMap;

				} else if ( material.alphaMap ) {

					uvScaleMap = material.alphaMap;

				} else if ( material.emissiveMap ) {

					uvScaleMap = material.emissiveMap;

				}

				if ( uvScaleMap !== undefined ) {

					// backwards compatibility
					if ( uvScaleMap.isWebGLRenderTarget ) {

						uvScaleMap = uvScaleMap.texture;

					}

928
					if ( uvScaleMap.matrixAutoUpdate === true ) {
929

930
						uvScaleMap.updateMatrix();
931 932

					}
933

934 935
					uniforms.uvTransform.value.copy( uvScaleMap.matrix );

936 937
				}

0
06wj 已提交
938
				if ( material.envMap ) {
939

940
					uniforms.envMap.value = material.envMap;
941
					uniforms.envMapIntensity.value = material.envMapIntensity;
942

943 944 945 946
					// don't flip CubeTexture envMaps, flip everything else:
					//  WebGLRenderTargetCube will be flipped for backwards compatibility
					//  WebGLRenderTargetCube.texture will be flipped because it's a Texture and NOT a CubeTexture
					// this check must be handled differently, or removed entirely, if WebGLRenderTargetCube uses a CubeTexture in the future
0
06wj 已提交
947
					uniforms.flipEnvMap.value = material.envMap.isCubeTexture ? - 1 : 1;
948 949 950 951 952

					uniforms.reflectivity.value = material.reflectivity;
					uniforms.refractionRatio.value = material.refractionRatio;

					uniforms.maxMipLevel.value = renderer.properties.get( material.envMap ).__maxMipLevel;
M
Mugen87 已提交
953

954
				}
955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972

				uniforms.specular.value.copy( material.specular );
				uniforms.glossiness.value = material.glossiness;

				uniforms.glossinessMap.value = material.glossinessMap;

				uniforms.emissiveMap.value = material.emissiveMap;
				uniforms.bumpMap.value = material.bumpMap;
				uniforms.normalMap.value = material.normalMap;

				uniforms.displacementMap.value = material.displacementMap;
				uniforms.displacementScale.value = material.displacementScale;
				uniforms.displacementBias.value = material.displacementBias;

				if ( uniforms.glossinessMap.value !== null && defines.USE_GLOSSINESSMAP === undefined ) {

					defines.USE_GLOSSINESSMAP = '';
					// set USE_ROUGHNESSMAP to enable vUv
973
					defines.USE_ROUGHNESSMAP = '';
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989

				}

				if ( uniforms.glossinessMap.value === null && defines.USE_GLOSSINESSMAP !== undefined ) {

					delete defines.USE_GLOSSINESSMAP;
					delete defines.USE_ROUGHNESSMAP;

				}

			}

		};

	}

990 991 992 993 994 995 996 997 998 999 1000
	/**
	 * Mesh Quantization Extension
	 *
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization
	 */
	function GLTFMeshQuantizationExtension() {

		this.name = EXTENSIONS.KHR_MESH_QUANTIZATION;

	}

1001 1002 1003 1004 1005 1006 1007 1008 1009 1010
	/*********************************/
	/********** INTERPOLATION ********/
	/*********************************/

	// Spline Interpolation
	// Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#appendix-c-spline-interpolation
	function GLTFCubicSplineInterpolant( parameterPositions, sampleValues, sampleSize, resultBuffer ) {

		THREE.Interpolant.call( this, parameterPositions, sampleValues, sampleSize, resultBuffer );

M
Mugen87 已提交
1011
	}
1012

1013 1014
	GLTFCubicSplineInterpolant.prototype = Object.create( THREE.Interpolant.prototype );
	GLTFCubicSplineInterpolant.prototype.constructor = GLTFCubicSplineInterpolant;
1015

1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
	GLTFCubicSplineInterpolant.prototype.copySampleValue_ = function ( index ) {

		// Copies a sample value to the result buffer. See description of glTF
		// CUBICSPLINE values layout in interpolate_() function below.

		var result = this.resultBuffer,
			values = this.sampleValues,
			valueSize = this.valueSize,
			offset = index * valueSize * 3 + valueSize;

		for ( var i = 0; i !== valueSize; i ++ ) {

			result[ i ] = values[ offset + i ];

		}

		return result;

	};

	GLTFCubicSplineInterpolant.prototype.beforeStart_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;

	GLTFCubicSplineInterpolant.prototype.afterEnd_ = GLTFCubicSplineInterpolant.prototype.copySampleValue_;

1040
	GLTFCubicSplineInterpolant.prototype.interpolate_ = function ( i1, t0, t, t1 ) {
1041

1042 1043 1044
		var result = this.resultBuffer;
		var values = this.sampleValues;
		var stride = this.valueSize;
1045

1046 1047
		var stride2 = stride * 2;
		var stride3 = stride * 3;
1048

1049
		var td = t1 - t0;
1050

1051 1052 1053
		var p = ( t - t0 ) / td;
		var pp = p * p;
		var ppp = pp * p;
1054

1055 1056
		var offset1 = i1 * stride3;
		var offset0 = offset1 - stride3;
1057

1058 1059
		var s2 = - 2 * ppp + 3 * pp;
		var s3 = ppp - pp;
A
Andreas Plesch 已提交
1060 1061
		var s0 = 1 - s2;
		var s1 = s3 - pp + p;
1062

1063 1064 1065
		// Layout of keyframe output values for CUBICSPLINE animations:
		//   [ inTangent_1, splineVertex_1, outTangent_1, inTangent_2, splineVertex_2, ... ]
		for ( var i = 0; i !== stride; i ++ ) {
1066

M
Mugen87 已提交
1067 1068 1069 1070
			var p0 = values[ offset0 + i + stride ]; // splineVertex_k
			var m0 = values[ offset0 + i + stride2 ] * td; // outTangent_k * (t_k+1 - t_k)
			var p1 = values[ offset1 + i + stride ]; // splineVertex_k+1
			var m1 = values[ offset1 + i ] * td; // inTangent_k+1 * (t_k+1 - t_k)
1071

1072
			result[ i ] = s0 * p0 + s1 * m0 + s2 * p1 + s3 * m1;
1073 1074 1075

		}

1076 1077 1078
		return result;

	};
1079

D
Don McCurdy 已提交
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
	/*********************************/
	/********** INTERNALS ************/
	/*********************************/

	/* CONSTANTS */

	var WEBGL_CONSTANTS = {
		FLOAT: 5126,
		//FLOAT_MAT2: 35674,
		FLOAT_MAT3: 35675,
		FLOAT_MAT4: 35676,
		FLOAT_VEC2: 35664,
		FLOAT_VEC3: 35665,
		FLOAT_VEC4: 35666,
		LINEAR: 9729,
		REPEAT: 10497,
		SAMPLER_2D: 35678,
1097
		POINTS: 0,
D
Don McCurdy 已提交
1098
		LINES: 1,
1099 1100 1101 1102 1103
		LINE_LOOP: 2,
		LINE_STRIP: 3,
		TRIANGLES: 4,
		TRIANGLE_STRIP: 5,
		TRIANGLE_FAN: 6,
D
Don McCurdy 已提交
1104
		UNSIGNED_BYTE: 5121,
1105
		UNSIGNED_SHORT: 5123
D
Don McCurdy 已提交
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119
	};

	var WEBGL_COMPONENT_TYPES = {
		5120: Int8Array,
		5121: Uint8Array,
		5122: Int16Array,
		5123: Uint16Array,
		5125: Uint32Array,
		5126: Float32Array
	};

	var WEBGL_FILTERS = {
		9728: THREE.NearestFilter,
		9729: THREE.LinearFilter,
W
WestLangley 已提交
1120 1121 1122 1123
		9984: THREE.NearestMipmapNearestFilter,
		9985: THREE.LinearMipmapNearestFilter,
		9986: THREE.NearestMipmapLinearFilter,
		9987: THREE.LinearMipmapLinearFilter
D
Don McCurdy 已提交
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
	};

	var WEBGL_WRAPPINGS = {
		33071: THREE.ClampToEdgeWrapping,
		33648: THREE.MirroredRepeatWrapping,
		10497: THREE.RepeatWrapping
	};

	var WEBGL_TYPE_SIZES = {
		'SCALAR': 1,
		'VEC2': 2,
		'VEC3': 3,
		'VEC4': 4,
		'MAT2': 4,
		'MAT3': 9,
		'MAT4': 16
	};

1142 1143 1144
	var ATTRIBUTES = {
		POSITION: 'position',
		NORMAL: 'normal',
D
Don McCurdy 已提交
1145
		TANGENT: 'tangent',
1146 1147 1148 1149 1150
		TEXCOORD_0: 'uv',
		TEXCOORD_1: 'uv2',
		COLOR_0: 'color',
		WEIGHTS_0: 'skinWeight',
		JOINTS_0: 'skinIndex',
M
Mugen87 已提交
1151
	};
1152

D
Don McCurdy 已提交
1153 1154 1155
	var PATH_PROPERTIES = {
		scale: 'scale',
		translation: 'position',
T
Takahiro 已提交
1156 1157
		rotation: 'quaternion',
		weights: 'morphTargetInfluences'
D
Don McCurdy 已提交
1158 1159 1160
	};

	var INTERPOLATION = {
1161 1162
		CUBICSPLINE: undefined, // We use a custom interpolant (GLTFCubicSplineInterpolation) for CUBICSPLINE tracks. Each
		                        // keyframe track will be initialized with a default interpolation type, then modified.
D
Don McCurdy 已提交
1163 1164 1165 1166
		LINEAR: THREE.InterpolateLinear,
		STEP: THREE.InterpolateDiscrete
	};

1167 1168 1169 1170 1171 1172
	var ALPHA_MODES = {
		OPAQUE: 'OPAQUE',
		MASK: 'MASK',
		BLEND: 'BLEND'
	};

1173 1174 1175 1176 1177
	var MIME_TYPE_FORMATS = {
		'image/png': THREE.RGBAFormat,
		'image/jpeg': THREE.RGBFormat
	};

1178 1179
	/* UTILITY FUNCTIONS */

D
Don McCurdy 已提交
1180 1181 1182
	function resolveURL( url, path ) {

		// Invalid URL
T
Takahiro 已提交
1183
		if ( typeof url !== 'string' || url === '' ) return '';
M
Mugen87 已提交
1184

G
gilnoycloudinary 已提交
1185
		// Host Relative URL
D
Don McCurdy 已提交
1186 1187
		if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) {

M
Mugen87 已提交
1188
			path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' );
D
Don McCurdy 已提交
1189

G
gilnoycloudinary 已提交
1190
		}
D
Don McCurdy 已提交
1191

0
06wj 已提交
1192
		// Absolute URL http://,https://,//
T
Takahiro 已提交
1193
		if ( /^(https?:)?\/\//i.test( url ) ) return url;
D
Don McCurdy 已提交
1194 1195

		// Data URI
T
Takahiro 已提交
1196
		if ( /^data:.*,.*$/i.test( url ) ) return url;
D
Don McCurdy 已提交
1197

1198
		// Blob URL
T
Takahiro 已提交
1199
		if ( /^blob:.*$/i.test( url ) ) return url;
1200

D
Don McCurdy 已提交
1201
		// Relative URL
1202
		return path + url;
D
Don McCurdy 已提交
1203 1204 1205

	}

1206 1207 1208
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
	 */
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223
	function createDefaultMaterial( cache ) {

		if ( cache[ 'DefaultMaterial' ] === undefined ) {

			cache[ 'DefaultMaterial' ] = new THREE.MeshStandardMaterial( {
				color: 0xFFFFFF,
				emissive: 0x000000,
				metalness: 1,
				roughness: 1,
				transparent: false,
				depthTest: true,
				side: THREE.FrontSide
			} );

		}
D
Don McCurdy 已提交
1224

1225
		return cache[ 'DefaultMaterial' ];
1226

D
Don McCurdy 已提交
1227 1228
	}

1229
	function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {
1230 1231 1232 1233 1234

		// Add unknown glTF extensions to an object's userData.

		for ( var name in objectDef.extensions ) {

1235
			if ( knownExtensions[ name ] === undefined ) {
1236 1237 1238 1239 1240 1241 1242 1243 1244 1245

				object.userData.gltfExtensions = object.userData.gltfExtensions || {};
				object.userData.gltfExtensions[ name ] = objectDef.extensions[ name ];

			}

		}

	}

1246 1247
	/**
	 * @param {THREE.Object3D|THREE.Material|THREE.BufferGeometry} object
T
Takahiro 已提交
1248
	 * @param {GLTF.definition} gltfDef
1249 1250 1251 1252 1253 1254 1255
	 */
	function assignExtrasToUserData( object, gltfDef ) {

		if ( gltfDef.extras !== undefined ) {

			if ( typeof gltfDef.extras === 'object' ) {

K
Kalacione 已提交
1256
				Object.assign( object.userData, gltfDef.extras );
1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267

			} else {

				console.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );

			}

		}

	}

D
Don McCurdy 已提交
1268 1269
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
1270
	 *
M
Mugen87 已提交
1271
	 * @param {THREE.BufferGeometry} geometry
1272
	 * @param {Array<GLTF.Target>} targets
T
Takahiro 已提交
1273 1274
	 * @param {GLTFParser} parser
	 * @return {Promise<THREE.BufferGeometry>}
D
Don McCurdy 已提交
1275
	 */
T
Takahiro 已提交
1276
	function addMorphTargets( geometry, targets, parser ) {
D
Don McCurdy 已提交
1277

1278 1279 1280 1281 1282 1283 1284 1285 1286
		var hasMorphPosition = false;
		var hasMorphNormal = false;

		for ( var i = 0, il = targets.length; i < il; i ++ ) {

			var target = targets[ i ];

			if ( target.POSITION !== undefined ) hasMorphPosition = true;
			if ( target.NORMAL !== undefined ) hasMorphNormal = true;
D
Don McCurdy 已提交
1287

1288
			if ( hasMorphPosition && hasMorphNormal ) break;
D
Don McCurdy 已提交
1289

1290 1291
		}

T
Takahiro 已提交
1292
		if ( ! hasMorphPosition && ! hasMorphNormal ) return Promise.resolve( geometry );
1293

1294 1295
		var pendingPositionAccessors = [];
		var pendingNormalAccessors = [];
D
Don McCurdy 已提交
1296 1297 1298 1299 1300

		for ( var i = 0, il = targets.length; i < il; i ++ ) {

			var target = targets[ i ];

1301
			if ( hasMorphPosition ) {
D
Don McCurdy 已提交
1302

D
Don McCurdy 已提交
1303
				var pendingAccessor = target.POSITION !== undefined
T
Takahiro 已提交
1304 1305 1306
					? parser.getDependency( 'accessor', target.POSITION )
					: geometry.attributes.position;

D
Don McCurdy 已提交
1307
				pendingPositionAccessors.push( pendingAccessor );
D
Don McCurdy 已提交
1308

T
Takahiro 已提交
1309
			}
D
Don McCurdy 已提交
1310

T
Takahiro 已提交
1311
			if ( hasMorphNormal ) {
D
Don McCurdy 已提交
1312

D
Don McCurdy 已提交
1313
				var pendingAccessor = target.NORMAL !== undefined
T
Takahiro 已提交
1314 1315 1316
					? parser.getDependency( 'accessor', target.NORMAL )
					: geometry.attributes.normal;

D
Don McCurdy 已提交
1317
				pendingNormalAccessors.push( pendingAccessor );
D
Don McCurdy 已提交
1318

T
Takahiro 已提交
1319
			}
D
Don McCurdy 已提交
1320

T
Takahiro 已提交
1321
		}
D
Don McCurdy 已提交
1322

T
Takahiro 已提交
1323
		return Promise.all( [
1324 1325
			Promise.all( pendingPositionAccessors ),
			Promise.all( pendingNormalAccessors )
T
Takahiro 已提交
1326
		] ).then( function ( accessors ) {
D
Don McCurdy 已提交
1327

T
Takahiro 已提交
1328 1329
			var morphPositions = accessors[ 0 ];
			var morphNormals = accessors[ 1 ];
1330

T
Takahiro 已提交
1331 1332
			if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;
			if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;
1333
			geometry.morphTargetsRelative = true;
T
Takahiro 已提交
1334 1335

			return geometry;
D
Don McCurdy 已提交
1336

T
Takahiro 已提交
1337
		} );
1338

1339 1340 1341 1342 1343 1344 1345 1346
	}

	/**
	 * @param {THREE.Mesh} mesh
	 * @param {GLTF.Mesh} meshDef
	 */
	function updateMorphTargets( mesh, meshDef ) {

D
Don McCurdy 已提交
1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358
		mesh.updateMorphTargets();

		if ( meshDef.weights !== undefined ) {

			for ( var i = 0, il = meshDef.weights.length; i < il; i ++ ) {

				mesh.morphTargetInfluences[ i ] = meshDef.weights[ i ];

			}

		}

T
Takahiro 已提交
1359
		// .extras has user-defined data, so check that .extras.targetNames is an array.
T
Takahiro 已提交
1360 1361
		if ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {

1362
			var targetNames = meshDef.extras.targetNames;
T
Takahiro 已提交
1363

1364
			if ( mesh.morphTargetInfluences.length === targetNames.length ) {
1365

1366
				mesh.morphTargetDictionary = {};
1367

1368 1369 1370
				for ( var i = 0, il = targetNames.length; i < il; i ++ ) {

					mesh.morphTargetDictionary[ targetNames[ i ] ] = i;
1371

1372 1373 1374
				}

			} else {
1375

1376
				console.warn( 'THREE.GLTFLoader: Invalid extras.targetNames length. Ignoring names.' );
T
Takahiro 已提交
1377 1378 1379 1380 1381

			}

		}

1382 1383
	}

R
Riccardo Padovani 已提交
1384
	function createPrimitiveKey( primitiveDef ) {
1385

R
Riccardo Padovani 已提交
1386
		var dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];
1387
		var geometryKey;
1388

1389
		if ( dracoExtension ) {
1390

1391 1392 1393
			geometryKey = 'draco:' + dracoExtension.bufferView
				+ ':' + dracoExtension.indices
				+ ':' + createAttributesKey( dracoExtension.attributes );
1394

1395 1396
		} else {

1397
			geometryKey = primitiveDef.indices + ':' + createAttributesKey( primitiveDef.attributes ) + ':' + primitiveDef.mode;
T
Takahiro 已提交
1398

1399 1400
		}

1401
		return geometryKey;
T
Takahiro 已提交
1402

1403 1404
	}

1405
	function createAttributesKey( attributes ) {
T
Takahiro 已提交
1406

1407
		var attributesKey = '';
T
Takahiro 已提交
1408

R
Riccardo Padovani 已提交
1409
		var keys = Object.keys( attributes ).sort();
1410

1411
		for ( var i = 0, il = keys.length; i < il; i ++ ) {
1412

1413
			attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';
1414

T
Takahiro 已提交
1415
		}
1416

1417
		return attributesKey;
1418

T
Takahiro 已提交
1419
	}
1420

D
Don McCurdy 已提交
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431
	/* GLTF PARSER */

	function GLTFParser( json, extensions, options ) {

		this.json = json || {};
		this.extensions = extensions || {};
		this.options = options || {};

		// loader object cache
		this.cache = new GLTFRegistry();

1432
		// BufferGeometry caching
1433
		this.primitiveCache = {};
1434

M
Mugen87 已提交
1435 1436 1437
		this.textureLoader = new THREE.TextureLoader( this.options.manager );
		this.textureLoader.setCrossOrigin( this.options.crossOrigin );

M
Mugen87 已提交
1438 1439 1440
		this.fileLoader = new THREE.FileLoader( this.options.manager );
		this.fileLoader.setResponseType( 'arraybuffer' );

1441 1442 1443 1444 1445 1446
		if ( this.options.crossOrigin === 'use-credentials' ) {

			this.fileLoader.setWithCredentials( true );

		}

D
Don McCurdy 已提交
1447 1448
	}

T
Takahiro 已提交
1449
	GLTFParser.prototype.parse = function ( onLoad, onError ) {
D
Don McCurdy 已提交
1450

1451
		var parser = this;
T
Takahiro 已提交
1452
		var json = this.json;
1453
		var extensions = this.extensions;
D
Don McCurdy 已提交
1454

T
Takahiro 已提交
1455 1456
		// Clear the loader cache
		this.cache.removeAll();
D
Don McCurdy 已提交
1457

T
Takahiro 已提交
1458 1459
		// Mark the special nodes/meshes in json for efficient parse
		this.markDefs();
D
Don McCurdy 已提交
1460

1461
		Promise.all( [
D
Don McCurdy 已提交
1462

1463 1464 1465
			this.getDependencies( 'scene' ),
			this.getDependencies( 'animation' ),
			this.getDependencies( 'camera' ),
D
Don McCurdy 已提交
1466

T
Takahiro 已提交
1467
		] ).then( function ( dependencies ) {
D
Don McCurdy 已提交
1468

1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479
			var result = {
				scene: dependencies[ 0 ][ json.scene || 0 ],
				scenes: dependencies[ 0 ],
				animations: dependencies[ 1 ],
				cameras: dependencies[ 2 ],
				asset: json.asset,
				parser: parser,
				userData: {}
			};

			addUnknownExtensionsToUserData( extensions, result, json );
D
Don McCurdy 已提交
1480

1481 1482
			assignExtrasToUserData( result, json );

1483
			onLoad( result );
D
Don McCurdy 已提交
1484

T
Takahiro 已提交
1485
		} ).catch( onError );
D
Don McCurdy 已提交
1486

T
Takahiro 已提交
1487
	};
D
Don McCurdy 已提交
1488

T
Takahiro 已提交
1489 1490 1491 1492
	/**
	 * Marks the special nodes/meshes in json for efficient parse.
	 */
	GLTFParser.prototype.markDefs = function () {
D
Don McCurdy 已提交
1493

T
Takahiro 已提交
1494 1495 1496
		var nodeDefs = this.json.nodes || [];
		var skinDefs = this.json.skins || [];
		var meshDefs = this.json.meshes || [];
D
Don McCurdy 已提交
1497

T
Takahiro 已提交
1498 1499
		var meshReferences = {};
		var meshUses = {};
D
Don McCurdy 已提交
1500

T
Takahiro 已提交
1501 1502 1503
		// Nothing in the node definition indicates whether it is a Bone or an
		// Object3D. Use the skins' joint references to mark bones.
		for ( var skinIndex = 0, skinLength = skinDefs.length; skinIndex < skinLength; skinIndex ++ ) {
D
Don McCurdy 已提交
1504

T
Takahiro 已提交
1505
			var joints = skinDefs[ skinIndex ].joints;
D
Don McCurdy 已提交
1506

T
Takahiro 已提交
1507
			for ( var i = 0, il = joints.length; i < il; i ++ ) {
D
Don McCurdy 已提交
1508

T
Takahiro 已提交
1509
				nodeDefs[ joints[ i ] ].isBone = true;
D
Don McCurdy 已提交
1510

T
Takahiro 已提交
1511
			}
D
Don McCurdy 已提交
1512

T
Takahiro 已提交
1513
		}
D
Don McCurdy 已提交
1514

T
Takahiro 已提交
1515 1516 1517 1518 1519 1520
		// Meshes can (and should) be reused by multiple nodes in a glTF asset. To
		// avoid having more than one THREE.Mesh with the same name, count
		// references and rename instances below.
		//
		// Example: CesiumMilkTruck sample model reuses "Wheel" meshes.
		for ( var nodeIndex = 0, nodeLength = nodeDefs.length; nodeIndex < nodeLength; nodeIndex ++ ) {
D
Don McCurdy 已提交
1521

T
Takahiro 已提交
1522
			var nodeDef = nodeDefs[ nodeIndex ];
D
Don McCurdy 已提交
1523

T
Takahiro 已提交
1524
			if ( nodeDef.mesh !== undefined ) {
1525

T
Takahiro 已提交
1526
				if ( meshReferences[ nodeDef.mesh ] === undefined ) {
D
Don McCurdy 已提交
1527

T
Takahiro 已提交
1528
					meshReferences[ nodeDef.mesh ] = meshUses[ nodeDef.mesh ] = 0;
D
Don McCurdy 已提交
1529

T
Takahiro 已提交
1530
				}
D
Don McCurdy 已提交
1531

T
Takahiro 已提交
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548
				meshReferences[ nodeDef.mesh ] ++;

				// Nothing in the mesh definition indicates whether it is
				// a SkinnedMesh or Mesh. Use the node's mesh reference
				// to mark SkinnedMesh if node has skin.
				if ( nodeDef.skin !== undefined ) {

					meshDefs[ nodeDef.mesh ].isSkinnedMesh = true;

				}

			}

		}

		this.json.meshReferences = meshReferences;
		this.json.meshUses = meshUses;
D
Don McCurdy 已提交
1549 1550 1551

	};

1552 1553 1554 1555
	/**
	 * Requests the specified dependency asynchronously, with caching.
	 * @param {string} type
	 * @param {number} index
T
Takahiro 已提交
1556
	 * @return {Promise<THREE.Object3D|THREE.Material|THREE.Texture|THREE.AnimationClip|ArrayBuffer|Object>}
1557 1558 1559 1560 1561 1562
	 */
	GLTFParser.prototype.getDependency = function ( type, index ) {

		var cacheKey = type + ':' + index;
		var dependency = this.cache.get( cacheKey );

M
Mugen87 已提交
1563
		if ( ! dependency ) {
1564

T
Takahiro 已提交
1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
			switch ( type ) {

				case 'scene':
					dependency = this.loadScene( index );
					break;

				case 'node':
					dependency = this.loadNode( index );
					break;

				case 'mesh':
					dependency = this.loadMesh( index );
					break;

				case 'accessor':
					dependency = this.loadAccessor( index );
					break;

				case 'bufferView':
					dependency = this.loadBufferView( index );
					break;

				case 'buffer':
					dependency = this.loadBuffer( index );
					break;

				case 'material':
					dependency = this.loadMaterial( index );
					break;

				case 'texture':
					dependency = this.loadTexture( index );
					break;

				case 'skin':
					dependency = this.loadSkin( index );
					break;

				case 'animation':
					dependency = this.loadAnimation( index );
					break;

				case 'camera':
					dependency = this.loadCamera( index );
					break;

T
Takahiro 已提交
1611 1612
				case 'light':
					dependency = this.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].loadLight( index );
M
Mugen87 已提交
1613
					break;
T
Takahiro 已提交
1614

T
Takahiro 已提交
1615 1616 1617 1618 1619
				default:
					throw new Error( 'Unknown type: ' + type );

			}

1620 1621 1622 1623 1624 1625 1626 1627
			this.cache.add( cacheKey, dependency );

		}

		return dependency;

	};

D
Don McCurdy 已提交
1628 1629 1630 1631 1632 1633 1634
	/**
	 * Requests all dependencies of the specified type asynchronously, with caching.
	 * @param {string} type
	 * @return {Promise<Array<Object>>}
	 */
	GLTFParser.prototype.getDependencies = function ( type ) {

1635 1636 1637 1638 1639 1640 1641 1642
		var dependencies = this.cache.get( type );

		if ( ! dependencies ) {

			var parser = this;
			var defs = this.json[ type + ( type === 'mesh' ? 'es' : 's' ) ] || [];

			dependencies = Promise.all( defs.map( function ( def, index ) {
D
Don McCurdy 已提交
1643

1644
				return parser.getDependency( type, index );
D
Don McCurdy 已提交
1645

1646 1647 1648 1649 1650
			} ) );

			this.cache.add( type, dependencies );

		}
D
Don McCurdy 已提交
1651

1652
		return dependencies;
D
Don McCurdy 已提交
1653 1654 1655

	};

1656 1657 1658 1659 1660 1661
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
	 * @param {number} bufferIndex
	 * @return {Promise<ArrayBuffer>}
	 */
	GLTFParser.prototype.loadBuffer = function ( bufferIndex ) {
D
Don McCurdy 已提交
1662

1663
		var bufferDef = this.json.buffers[ bufferIndex ];
M
Mugen87 已提交
1664
		var loader = this.fileLoader;
D
Don McCurdy 已提交
1665

1666
		if ( bufferDef.type && bufferDef.type !== 'arraybuffer' ) {
D
Don McCurdy 已提交
1667

T
Takahiro 已提交
1668
			throw new Error( 'THREE.GLTFLoader: ' + bufferDef.type + ' buffer type is not supported.' );
D
Don McCurdy 已提交
1669

1670
		}
D
Don McCurdy 已提交
1671

1672 1673
		// If present, GLB container is required to be the first buffer.
		if ( bufferDef.uri === undefined && bufferIndex === 0 ) {
D
Don McCurdy 已提交
1674

1675
			return Promise.resolve( this.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body );
D
Don McCurdy 已提交
1676

1677
		}
D
Don McCurdy 已提交
1678

1679
		var options = this.options;
D
Don McCurdy 已提交
1680

1681
		return new Promise( function ( resolve, reject ) {
D
Don McCurdy 已提交
1682

1683 1684
			loader.load( resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {

1685
				reject( new Error( 'THREE.GLTFLoader: Failed to load buffer "' + bufferDef.uri + '".' ) );
1686 1687

			} );
D
Don McCurdy 已提交
1688 1689 1690 1691 1692

		} );

	};

1693 1694 1695 1696 1697 1698 1699
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#buffers-and-buffer-views
	 * @param {number} bufferViewIndex
	 * @return {Promise<ArrayBuffer>}
	 */
	GLTFParser.prototype.loadBufferView = function ( bufferViewIndex ) {

1700
		var bufferViewDef = this.json.bufferViews[ bufferViewIndex ];
1701

1702
		return this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {
1703

1704 1705 1706
			var byteLength = bufferViewDef.byteLength || 0;
			var byteOffset = bufferViewDef.byteOffset || 0;
			return buffer.slice( byteOffset, byteOffset + byteLength );
D
Don McCurdy 已提交
1707 1708 1709 1710 1711

		} );

	};

T
Takahiro 已提交
1712 1713 1714
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessors
	 * @param {number} accessorIndex
T
Takahiro 已提交
1715
	 * @return {Promise<THREE.BufferAttribute|THREE.InterleavedBufferAttribute>}
T
Takahiro 已提交
1716 1717
	 */
	GLTFParser.prototype.loadAccessor = function ( accessorIndex ) {
D
Don McCurdy 已提交
1718

1719
		var parser = this;
D
Don McCurdy 已提交
1720 1721
		var json = this.json;

T
Takahiro 已提交
1722
		var accessorDef = this.json.accessors[ accessorIndex ];
1723

1724 1725 1726 1727 1728
		if ( accessorDef.bufferView === undefined && accessorDef.sparse === undefined ) {

			// Ignore empty accessors, which may be used to declare runtime
			// information about attributes coming from another source (e.g. Draco
			// compression extension).
1729
			return Promise.resolve( null );
1730 1731 1732

		}

T
Takahiro 已提交
1733
		var pendingBufferViews = [];
1734

T
Takahiro 已提交
1735
		if ( accessorDef.bufferView !== undefined ) {
1736

T
Takahiro 已提交
1737
			pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.bufferView ) );
1738

T
Takahiro 已提交
1739
		} else {
1740

T
Takahiro 已提交
1741
			pendingBufferViews.push( null );
1742

T
Takahiro 已提交
1743
		}
1744

T
Takahiro 已提交
1745
		if ( accessorDef.sparse !== undefined ) {
1746

T
Takahiro 已提交
1747 1748
			pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );
			pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );
1749

T
Takahiro 已提交
1750
		}
1751

T
Takahiro 已提交
1752
		return Promise.all( pendingBufferViews ).then( function ( bufferViews ) {
D
Don McCurdy 已提交
1753

T
Takahiro 已提交
1754
			var bufferView = bufferViews[ 0 ];
D
Don McCurdy 已提交
1755

T
Takahiro 已提交
1756 1757
			var itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];
			var TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
1758

T
Takahiro 已提交
1759 1760 1761
			// For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.
			var elementBytes = TypedArray.BYTES_PER_ELEMENT;
			var itemBytes = elementBytes * itemSize;
1762
			var byteOffset = accessorDef.byteOffset || 0;
1763
			var byteStride = accessorDef.bufferView !== undefined ? json.bufferViews[ accessorDef.bufferView ].byteStride : undefined;
T
Takahiro 已提交
1764 1765
			var normalized = accessorDef.normalized === true;
			var array, bufferAttribute;
D
Don McCurdy 已提交
1766

T
Takahiro 已提交
1767 1768
			// The buffer is not interleaved if the stride is the item size in bytes.
			if ( byteStride && byteStride !== itemBytes ) {
D
Don McCurdy 已提交
1769

1770 1771 1772 1773
				// Each "slice" of the buffer, as defined by 'count' elements of 'byteStride' bytes, gets its own InterleavedBuffer
				// This makes sure that IBA.count reflects accessor.count properly
				var ibSlice = Math.floor( byteOffset / byteStride );
				var ibCacheKey = 'InterleavedBuffer:' + accessorDef.bufferView + ':' + accessorDef.componentType + ':' + ibSlice + ':' + accessorDef.count;
1774 1775
				var ib = parser.cache.get( ibCacheKey );

D
Don McCurdy 已提交
1776
				if ( ! ib ) {
1777

1778
					array = new TypedArray( bufferView, ibSlice * byteStride, accessorDef.count * byteStride / elementBytes );
D
Don McCurdy 已提交
1779

1780 1781 1782 1783 1784 1785
					// Integer parameters to IB/IBA are in array elements, not bytes.
					ib = new THREE.InterleavedBuffer( array, byteStride / elementBytes );

					parser.cache.add( ibCacheKey, ib );

				}
D
Don McCurdy 已提交
1786

M
Mugen87 已提交
1787
				bufferAttribute = new THREE.InterleavedBufferAttribute( ib, itemSize, ( byteOffset % byteStride ) / elementBytes, normalized );
D
Don McCurdy 已提交
1788

T
Takahiro 已提交
1789
			} else {
D
Don McCurdy 已提交
1790

T
Takahiro 已提交
1791
				if ( bufferView === null ) {
1792

T
Takahiro 已提交
1793
					array = new TypedArray( accessorDef.count * itemSize );
D
Don McCurdy 已提交
1794

T
Takahiro 已提交
1795
				} else {
1796

1797
					array = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );
D
Don McCurdy 已提交
1798 1799 1800

				}

T
Takahiro 已提交
1801
				bufferAttribute = new THREE.BufferAttribute( array, itemSize, normalized );
1802

T
Takahiro 已提交
1803
			}
1804

T
Takahiro 已提交
1805 1806
			// https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse-accessors
			if ( accessorDef.sparse !== undefined ) {
1807

T
Takahiro 已提交
1808 1809
				var itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;
				var TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];
1810

T
Takahiro 已提交
1811 1812
				var byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;
				var byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;
1813

T
Takahiro 已提交
1814 1815
				var sparseIndices = new TypedArrayIndices( bufferViews[ 1 ], byteOffsetIndices, accessorDef.sparse.count * itemSizeIndices );
				var sparseValues = new TypedArray( bufferViews[ 2 ], byteOffsetValues, accessorDef.sparse.count * itemSize );
1816

T
Takahiro 已提交
1817 1818 1819
				if ( bufferView !== null ) {

					// Avoid modifying the original ArrayBuffer, if the bufferView wasn't initialized with zeroes.
1820
					bufferAttribute = new THREE.BufferAttribute( bufferAttribute.array.slice(), bufferAttribute.itemSize, bufferAttribute.normalized );
1821

T
Takahiro 已提交
1822
				}
1823

T
Takahiro 已提交
1824
				for ( var i = 0, il = sparseIndices.length; i < il; i ++ ) {
1825

T
Takahiro 已提交
1826
					var index = sparseIndices[ i ];
1827

T
Takahiro 已提交
1828 1829 1830 1831 1832
					bufferAttribute.setX( index, sparseValues[ i * itemSize ] );
					if ( itemSize >= 2 ) bufferAttribute.setY( index, sparseValues[ i * itemSize + 1 ] );
					if ( itemSize >= 3 ) bufferAttribute.setZ( index, sparseValues[ i * itemSize + 2 ] );
					if ( itemSize >= 4 ) bufferAttribute.setW( index, sparseValues[ i * itemSize + 3 ] );
					if ( itemSize >= 5 ) throw new Error( 'THREE.GLTFLoader: Unsupported itemSize in sparse BufferAttribute.' );
1833 1834 1835

				}

T
Takahiro 已提交
1836
			}
1837

T
Takahiro 已提交
1838
			return bufferAttribute;
D
Don McCurdy 已提交
1839 1840 1841 1842 1843

		} );

	};

1844 1845 1846 1847 1848 1849 1850 1851
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#textures
	 * @param {number} textureIndex
	 * @return {Promise<THREE.Texture>}
	 */
	GLTFParser.prototype.loadTexture = function ( textureIndex ) {

		var parser = this;
D
Don McCurdy 已提交
1852 1853
		var json = this.json;
		var options = this.options;
M
Mugen87 已提交
1854
		var textureLoader = this.textureLoader;
D
Don McCurdy 已提交
1855

1856
		var URL = window.URL || window.webkitURL;
D
Don McCurdy 已提交
1857

1858
		var textureDef = json.textures[ textureIndex ];
1859 1860 1861 1862

		var textureExtensions = textureDef.extensions || {};

		var source;
1863

1864 1865 1866 1867 1868 1869 1870 1871 1872 1873
		if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {

			source = json.images[ textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].source ];

		} else {

			source = json.images[ textureDef.source ];

		}

1874 1875
		var sourceURI = source.uri;
		var isObjectURL = false;
D
Don McCurdy 已提交
1876

1877
		if ( source.bufferView !== undefined ) {
D
Don McCurdy 已提交
1878

1879
			// Load binary image data from bufferView, if provided.
D
Don McCurdy 已提交
1880

T
Takahiro 已提交
1881
			sourceURI = parser.getDependency( 'bufferView', source.bufferView ).then( function ( bufferView ) {
D
Don McCurdy 已提交
1882

T
Takahiro 已提交
1883 1884 1885 1886
				isObjectURL = true;
				var blob = new Blob( [ bufferView ], { type: source.mimeType } );
				sourceURI = URL.createObjectURL( blob );
				return sourceURI;
D
Don McCurdy 已提交
1887

T
Takahiro 已提交
1888
			} );
D
Don McCurdy 已提交
1889

1890
		}
D
Don McCurdy 已提交
1891

1892
		return Promise.resolve( sourceURI ).then( function ( sourceURI ) {
D
Don McCurdy 已提交
1893

1894
			// Load Texture resource.
D
Don McCurdy 已提交
1895

M
Mugen87 已提交
1896
			var loader = options.manager.getHandler( sourceURI );
1897

1898
			if ( ! loader ) {
1899

1900 1901 1902
				loader = textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ]
					? parser.extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader
					: textureLoader;
1903 1904

			}
D
Don McCurdy 已提交
1905

1906
			return new Promise( function ( resolve, reject ) {
D
Don McCurdy 已提交
1907

M
Mugen87 已提交
1908
				loader.load( resolveURL( sourceURI, options.path ), resolve, undefined, reject );
D
Don McCurdy 已提交
1909

1910
			} );
D
Don McCurdy 已提交
1911

1912
		} ).then( function ( texture ) {
D
Don McCurdy 已提交
1913

1914
			// Clean up resources and configure Texture.
D
Don McCurdy 已提交
1915

1916
			if ( isObjectURL === true ) {
D
Don McCurdy 已提交
1917

1918
				URL.revokeObjectURL( sourceURI );
D
Don McCurdy 已提交
1919

1920
			}
D
Don McCurdy 已提交
1921

1922
			texture.flipY = false;
D
Don McCurdy 已提交
1923

1924
			if ( textureDef.name !== undefined ) texture.name = textureDef.name;
D
Don McCurdy 已提交
1925

1926 1927 1928 1929 1930 1931 1932
			// Ignore unknown mime types, like DDS files.
			if ( source.mimeType in MIME_TYPE_FORMATS ) {

				texture.format = MIME_TYPE_FORMATS[ source.mimeType ];

			}

1933 1934
			var samplers = json.samplers || {};
			var sampler = samplers[ textureDef.sampler ] || {};
D
Don McCurdy 已提交
1935

1936
			texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter;
W
WestLangley 已提交
1937
			texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.LinearMipmapLinearFilter;
1938 1939
			texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping;
			texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping;
D
Don McCurdy 已提交
1940

1941
			return texture;
D
Don McCurdy 已提交
1942

1943
		} );
D
Don McCurdy 已提交
1944

1945
	};
D
Don McCurdy 已提交
1946

1947 1948 1949
	/**
	 * Asynchronously assigns a texture to the given material parameters.
	 * @param {Object} materialParams
1950 1951 1952
	 * @param {string} mapName
	 * @param {Object} mapDef
	 * @return {Promise}
1953
	 */
1954 1955 1956
	GLTFParser.prototype.assignTexture = function ( materialParams, mapName, mapDef ) {

		var parser = this;
D
Don McCurdy 已提交
1957

1958 1959
		return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {

T
Takahiro 已提交
1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972
			if ( ! texture.isCompressedTexture ) {

				switch ( mapName ) {

					case 'aoMap':
					case 'emissiveMap':
					case 'metalnessMap':
					case 'normalMap':
					case 'roughnessMap':
						texture.format = THREE.RGBFormat;
						break;

				}
1973 1974 1975

			}

1976 1977 1978 1979 1980 1981 1982 1983
			// Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured
			// However, we will copy UV set 0 to UV set 1 on demand for aoMap
			if ( mapDef.texCoord !== undefined && mapDef.texCoord != 0 && ! ( mapName === 'aoMap' && mapDef.texCoord == 1 ) ) {

				console.warn( 'THREE.GLTFLoader: Custom UV set ' + mapDef.texCoord + ' for texture ' + mapName + ' not yet supported.' );

			}

1984 1985
			if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {

D
Don McCurdy 已提交
1986 1987 1988 1989 1990 1991 1992
				var transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;

				if ( transform ) {

					texture = parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ].extendTexture( texture, transform );

				}
1993 1994

			}
1995

1996
			materialParams[ mapName ] = texture;
D
Don McCurdy 已提交
1997 1998 1999 2000 2001

		} );

	};

2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034
	/**
	 * Assigns final material to a Mesh, Line, or Points instance. The instance
	 * already has a material (generated from the glTF material options alone)
	 * but reuse of the same glTF material may require multiple threejs materials
	 * to accomodate different primitive types, defines, etc. New materials will
	 * be created if necessary, and reused from a cache.
	 * @param  {THREE.Object3D} mesh Mesh, Line, or Points instance.
	 */
	GLTFParser.prototype.assignFinalMaterial = function ( mesh ) {

		var geometry = mesh.geometry;
		var material = mesh.material;
		var extensions = this.extensions;

		var useVertexTangents = geometry.attributes.tangent !== undefined;
		var useVertexColors = geometry.attributes.color !== undefined;
		var useFlatShading = geometry.attributes.normal === undefined;
		var useSkinning = mesh.isSkinnedMesh === true;
		var useMorphTargets = Object.keys( geometry.morphAttributes ).length > 0;
		var useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined;

		if ( mesh.isPoints ) {

			var cacheKey = 'PointsMaterial:' + material.uuid;

			var pointsMaterial = this.cache.get( cacheKey );

			if ( ! pointsMaterial ) {

				pointsMaterial = new THREE.PointsMaterial();
				THREE.Material.prototype.copy.call( pointsMaterial, material );
				pointsMaterial.color.copy( material.color );
				pointsMaterial.map = material.map;
2035
				pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px
2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102

				this.cache.add( cacheKey, pointsMaterial );

			}

			material = pointsMaterial;

		} else if ( mesh.isLine ) {

			var cacheKey = 'LineBasicMaterial:' + material.uuid;

			var lineMaterial = this.cache.get( cacheKey );

			if ( ! lineMaterial ) {

				lineMaterial = new THREE.LineBasicMaterial();
				THREE.Material.prototype.copy.call( lineMaterial, material );
				lineMaterial.color.copy( material.color );

				this.cache.add( cacheKey, lineMaterial );

			}

			material = lineMaterial;

		}

		// Clone the material if it will be modified
		if ( useVertexTangents || useVertexColors || useFlatShading || useSkinning || useMorphTargets ) {

			var cacheKey = 'ClonedMaterial:' + material.uuid + ':';

			if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
			if ( useSkinning ) cacheKey += 'skinning:';
			if ( useVertexTangents ) cacheKey += 'vertex-tangents:';
			if ( useVertexColors ) cacheKey += 'vertex-colors:';
			if ( useFlatShading ) cacheKey += 'flat-shading:';
			if ( useMorphTargets ) cacheKey += 'morph-targets:';
			if ( useMorphNormals ) cacheKey += 'morph-normals:';

			var cachedMaterial = this.cache.get( cacheKey );

			if ( ! cachedMaterial ) {

				cachedMaterial = material.isGLTFSpecularGlossinessMaterial
					? extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].cloneMaterial( material )
					: material.clone();

				if ( useSkinning ) cachedMaterial.skinning = true;
				if ( useVertexTangents ) cachedMaterial.vertexTangents = true;
				if ( useVertexColors ) cachedMaterial.vertexColors = THREE.VertexColors;
				if ( useFlatShading ) cachedMaterial.flatShading = true;
				if ( useMorphTargets ) cachedMaterial.morphTargets = true;
				if ( useMorphNormals ) cachedMaterial.morphNormals = true;

				this.cache.add( cacheKey, cachedMaterial );

			}

			material = cachedMaterial;

		}

		// workarounds for mesh and geometry

		if ( material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined ) {

2103
			geometry.setAttribute( 'uv2', new THREE.BufferAttribute( geometry.attributes.uv.array, 2 ) );
2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117

		}

		if ( material.isGLTFSpecularGlossinessMaterial ) {

			// for GLTFSpecularGlossinessMaterial(ShaderMaterial) uniforms runtime update
			mesh.onBeforeRender = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].refreshUniforms;

		}

		mesh.material = material;

	};

2118 2119
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials
T
Takahiro 已提交
2120 2121
	 * @param {number} materialIndex
	 * @return {Promise<THREE.Material>}
2122
	 */
T
Takahiro 已提交
2123
	GLTFParser.prototype.loadMaterial = function ( materialIndex ) {
D
Don McCurdy 已提交
2124

2125
		var parser = this;
D
Don McCurdy 已提交
2126
		var json = this.json;
2127
		var extensions = this.extensions;
M
Mugen87 已提交
2128
		var materialDef = json.materials[ materialIndex ];
D
Don McCurdy 已提交
2129

T
Takahiro 已提交
2130 2131 2132
		var materialType;
		var materialParams = {};
		var materialExtensions = materialDef.extensions || {};
2133

2134
		var pending = [];
2135

2136
		if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {
2137

T
Takahiro 已提交
2138
			var sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];
T
Takahiro 已提交
2139
			materialType = sgExtension.getMaterialType();
2140
			pending.push( sgExtension.extendParams( materialParams, materialDef, parser ) );
2141

2142 2143 2144
		} else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {

			var kmuExtension = extensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ];
T
Takahiro 已提交
2145
			materialType = kmuExtension.getMaterialType();
2146
			pending.push( kmuExtension.extendParams( materialParams, materialDef, parser ) );
2147

2148
		} else {
2149

T
Takahiro 已提交
2150 2151
			// Specification:
			// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
2152

T
Takahiro 已提交
2153
			materialType = THREE.MeshStandardMaterial;
2154

2155
			var metallicRoughness = materialDef.pbrMetallicRoughness || {};
2156

T
Takahiro 已提交
2157 2158
			materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
			materialParams.opacity = 1.0;
2159

T
Takahiro 已提交
2160
			if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
2161

T
Takahiro 已提交
2162
				var array = metallicRoughness.baseColorFactor;
2163

T
Takahiro 已提交
2164 2165
				materialParams.color.fromArray( array );
				materialParams.opacity = array[ 3 ];
2166

T
Takahiro 已提交
2167
			}
2168

T
Takahiro 已提交
2169
			if ( metallicRoughness.baseColorTexture !== undefined ) {
2170

2171
				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
2172

T
Takahiro 已提交
2173
			}
2174

T
Takahiro 已提交
2175 2176
			materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
			materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
2177

T
Takahiro 已提交
2178
			if ( metallicRoughness.metallicRoughnessTexture !== undefined ) {
D
Don McCurdy 已提交
2179

2180 2181
				pending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );
				pending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );
D
Don McCurdy 已提交
2182

2183
			}
D
Don McCurdy 已提交
2184

T
Takahiro 已提交
2185
		}
2186

T
Takahiro 已提交
2187
		if ( materialDef.doubleSided === true ) {
D
Don McCurdy 已提交
2188

T
Takahiro 已提交
2189
			materialParams.side = THREE.DoubleSide;
D
Don McCurdy 已提交
2190

T
Takahiro 已提交
2191
		}
D
Don McCurdy 已提交
2192

T
Takahiro 已提交
2193
		var alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;
2194

2195
		if ( alphaMode === ALPHA_MODES.BLEND ) {
2196

T
Takahiro 已提交
2197
			materialParams.transparent = true;
2198

2199 2200 2201 2202
		} else {

			materialParams.transparent = false;

T
Takahiro 已提交
2203
			if ( alphaMode === ALPHA_MODES.MASK ) {
D
Don McCurdy 已提交
2204

T
Takahiro 已提交
2205
				materialParams.alphaTest = materialDef.alphaCutoff !== undefined ? materialDef.alphaCutoff : 0.5;
D
Don McCurdy 已提交
2206

2207
			}
D
Don McCurdy 已提交
2208

T
Takahiro 已提交
2209
		}
2210

M
Mugen87 已提交
2211
		if ( materialDef.normalTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
2212

2213
			pending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );
2214

T
Takahiro 已提交
2215 2216 2217 2218 2219
			materialParams.normalScale = new THREE.Vector2( 1, 1 );

			if ( materialDef.normalTexture.scale !== undefined ) {

				materialParams.normalScale.set( materialDef.normalTexture.scale, materialDef.normalTexture.scale );
M
Mugen87 已提交
2220

2221
			}
D
Don McCurdy 已提交
2222

T
Takahiro 已提交
2223
		}
D
Don McCurdy 已提交
2224

M
Mugen87 已提交
2225
		if ( materialDef.occlusionTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
D
Don McCurdy 已提交
2226

2227
			pending.push( parser.assignTexture( materialParams, 'aoMap', materialDef.occlusionTexture ) );
D
Don McCurdy 已提交
2228

T
Takahiro 已提交
2229
			if ( materialDef.occlusionTexture.strength !== undefined ) {
D
Don McCurdy 已提交
2230

T
Takahiro 已提交
2231
				materialParams.aoMapIntensity = materialDef.occlusionTexture.strength;
D
Don McCurdy 已提交
2232

2233
			}
D
Don McCurdy 已提交
2234

T
Takahiro 已提交
2235
		}
D
Don McCurdy 已提交
2236

M
Mugen87 已提交
2237
		if ( materialDef.emissiveFactor !== undefined && materialType !== THREE.MeshBasicMaterial ) {
D
Don McCurdy 已提交
2238

2239
			materialParams.emissive = new THREE.Color().fromArray( materialDef.emissiveFactor );
D
Don McCurdy 已提交
2240

T
Takahiro 已提交
2241
		}
D
Don McCurdy 已提交
2242

M
Mugen87 已提交
2243
		if ( materialDef.emissiveTexture !== undefined && materialType !== THREE.MeshBasicMaterial ) {
D
Don McCurdy 已提交
2244

2245
			pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture ) );
2246

T
Takahiro 已提交
2247
		}
2248

2249
		return Promise.all( pending ).then( function () {
2250

T
Takahiro 已提交
2251
			var material;
2252

T
Takahiro 已提交
2253
			if ( materialType === THREE.ShaderMaterial ) {
2254

T
Takahiro 已提交
2255
				material = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );
2256

T
Takahiro 已提交
2257
			} else {
2258

T
Takahiro 已提交
2259
				material = new materialType( materialParams );
2260

T
Takahiro 已提交
2261
			}
D
Don McCurdy 已提交
2262

T
Takahiro 已提交
2263
			if ( materialDef.name !== undefined ) material.name = materialDef.name;
2264

2265
			// baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
T
Takahiro 已提交
2266 2267
			if ( material.map ) material.map.encoding = THREE.sRGBEncoding;
			if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
2268
			if ( material.specularMap ) material.specularMap.encoding = THREE.sRGBEncoding;
2269

2270
			assignExtrasToUserData( material, materialDef );
D
Don McCurdy 已提交
2271

2272
			if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );
2273

T
Takahiro 已提交
2274
			return material;
D
Don McCurdy 已提交
2275 2276 2277 2278 2279

		} );

	};

2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293
	/**
	 * @param {THREE.BufferGeometry} geometry
	 * @param {GLTF.Primitive} primitiveDef
	 * @param {GLTFParser} parser
	 */
	function computeBounds( geometry, primitiveDef, parser ) {

		var attributes = primitiveDef.attributes;

		var box = new THREE.Box3();

		if ( attributes.POSITION !== undefined ) {

			var accessor = parser.json.accessors[ attributes.POSITION ];
2294

2295 2296 2297
			var min = accessor.min;
			var max = accessor.max;

2298 2299
			// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.

2300 2301 2302 2303 2304 2305 2306 2307
			if ( min !== undefined && max !== undefined ) {

				box.set(
					new THREE.Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
					new THREE.Vector3( max[ 0 ], max[ 1 ], max[ 2 ] ) );

			} else {

2308 2309
				console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );

2310 2311 2312
				return;

			}
2313 2314 2315 2316

		} else {

			return;
W
WestLangley 已提交
2317

2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335
		}

		var targets = primitiveDef.targets;

		if ( targets !== undefined ) {

			var vector = new THREE.Vector3();

			for ( var i = 0, il = targets.length; i < il; i ++ ) {

				var target = targets[ i ];

				if ( target.POSITION !== undefined ) {

					var accessor = parser.json.accessors[ target.POSITION ];
					var min = accessor.min;
					var max = accessor.max;

2336 2337
					// glTF requires 'min' and 'max', but VRM (which extends glTF) currently ignores that requirement.

2338 2339 2340 2341 2342 2343
					if ( min !== undefined && max !== undefined ) {

						// we need to get max of absolute components because target weight is [-1,1]
						vector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) );
						vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );
						vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );
2344

2345 2346
						box.expandByVector( vector );

2347 2348 2349 2350
					} else {

						console.warn( 'THREE.GLTFLoader: Missing min/max properties for accessor POSITION.' );

2351
					}
2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369

				}

			}

		}

		geometry.boundingBox = box;

		var sphere = new THREE.Sphere();

		box.getCenter( sphere.center );
		sphere.radius = box.min.distanceTo( box.max ) / 2;

		geometry.boundingSphere = sphere;

	}

2370
	/**
T
Takahiro 已提交
2371 2372 2373 2374
	 * @param {THREE.BufferGeometry} geometry
	 * @param {GLTF.Primitive} primitiveDef
	 * @param {GLTFParser} parser
	 * @return {Promise<THREE.BufferGeometry>}
2375
	 */
T
Takahiro 已提交
2376
	function addPrimitiveAttributes( geometry, primitiveDef, parser ) {
2377 2378 2379

		var attributes = primitiveDef.attributes;

2380
		var pending = [];
T
Takahiro 已提交
2381

2382
		function assignAttributeAccessor( accessorIndex, attributeName ) {
T
Takahiro 已提交
2383 2384 2385 2386

			return parser.getDependency( 'accessor', accessorIndex )
				.then( function ( accessor ) {

2387
					geometry.setAttribute( attributeName, accessor );
T
Takahiro 已提交
2388 2389 2390 2391 2392

				} );

		}

2393
		for ( var gltfAttributeName in attributes ) {
2394

S
Sneha Belkhale 已提交
2395
			var threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase();
T
Takahiro 已提交
2396 2397

			// Skip attributes already provided by e.g. Draco extension.
2398
			if ( threeAttributeName in geometry.attributes ) continue;
2399

2400
			pending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );
2401 2402 2403

		}

2404
		if ( primitiveDef.indices !== undefined && ! geometry.index ) {
2405

T
Takahiro 已提交
2406
			var accessor = parser.getDependency( 'accessor', primitiveDef.indices ).then( function ( accessor ) {
2407

T
Takahiro 已提交
2408
				geometry.setIndex( accessor );
2409

T
Takahiro 已提交
2410 2411 2412
			} );

			pending.push( accessor );
2413 2414 2415

		}

2416
		assignExtrasToUserData( geometry, primitiveDef );
2417

2418 2419
		computeBounds( geometry, primitiveDef, parser );

2420
		return Promise.all( pending ).then( function () {
T
Takahiro 已提交
2421 2422 2423 2424 2425 2426 2427

			return primitiveDef.targets !== undefined
				? addMorphTargets( geometry, primitiveDef.targets, parser )
				: geometry;

		} );

2428 2429
	}

2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523
	/**
	 * @param {THREE.BufferGeometry} geometry
	 * @param {Number} drawMode
	 * @return {THREE.BufferGeometry}
	 */
	function toTrianglesDrawMode( geometry, drawMode ) {

		var index = geometry.getIndex();

		// generate index if not present

		if ( index === null ) {

			var indices = [];

			var position = geometry.getAttribute( 'position' );

			if ( position !== undefined ) {

				for ( var i = 0; i < position.count; i ++ ) {

					indices.push( i );

				}

				geometry.setIndex( indices );
				index = geometry.getIndex();

			} else {

				console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );
				return geometry;

			}

		}

		//

		var numberOfTriangles = index.count - 2;
		var newIndices = [];

		if ( drawMode === THREE.TriangleFanDrawMode ) {

			// gl.TRIANGLE_FAN

			for ( var i = 1; i <= numberOfTriangles; i ++ ) {

				newIndices.push( index.getX( 0 ) );
				newIndices.push( index.getX( i ) );
				newIndices.push( index.getX( i + 1 ) );

			}

		} else {

			// gl.TRIANGLE_STRIP

			for ( var i = 0; i < numberOfTriangles; i ++ ) {

				if ( i % 2 === 0 ) {

					newIndices.push( index.getX( i ) );
					newIndices.push( index.getX( i + 1 ) );
					newIndices.push( index.getX( i + 2 ) );


				} else {

					newIndices.push( index.getX( i + 2 ) );
					newIndices.push( index.getX( i + 1 ) );
					newIndices.push( index.getX( i ) );

				}

			}

		}

		if ( ( newIndices.length / 3 ) !== numberOfTriangles ) {

			console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );

		}

		// build final geometry

		var newGeometry = geometry.clone();
		newGeometry.setIndex( newIndices );

		return newGeometry;

	}

T
Takahiro 已提交
2524 2525
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry
T
Takahiro 已提交
2526 2527 2528
	 *
	 * Creates BufferGeometries from primitives.
	 *
T
Takahiro 已提交
2529
	 * @param {Array<GLTF.Primitive>} primitives
T
Takahiro 已提交
2530 2531
	 * @return {Promise<Array<THREE.BufferGeometry>>}
	 */
D
Don McCurdy 已提交
2532
	GLTFParser.prototype.loadGeometries = function ( primitives ) {
D
Don McCurdy 已提交
2533

2534 2535
		var parser = this;
		var extensions = this.extensions;
2536 2537
		var cache = this.primitiveCache;

2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549
		function createDracoPrimitive( primitive ) {

			return extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ]
				.decodePrimitive( primitive, parser )
				.then( function ( geometry ) {

					return addPrimitiveAttributes( geometry, primitive, parser );

				} );

		}

2550
		var pending = [];
D
Don McCurdy 已提交
2551

T
Takahiro 已提交
2552
		for ( var i = 0, il = primitives.length; i < il; i ++ ) {
D
Don McCurdy 已提交
2553

T
Takahiro 已提交
2554
			var primitive = primitives[ i ];
R
Riccardo Padovani 已提交
2555
			var cacheKey = createPrimitiveKey( primitive );
D
Don McCurdy 已提交
2556

T
Takahiro 已提交
2557
			// See if we've already created this geometry
2558
			var cached = cache[ cacheKey ];
D
Don McCurdy 已提交
2559

T
Takahiro 已提交
2560
			if ( cached ) {
2561

T
Takahiro 已提交
2562
				// Use the cached geometry if it exists
2563
				pending.push( cached.promise );
T
Takahiro 已提交
2564 2565

			} else {
D
Don McCurdy 已提交
2566

T
Takahiro 已提交
2567
				var geometryPromise;
2568

T
Takahiro 已提交
2569
				if ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {
2570 2571

					// Use DRACO geometry if available
2572
					geometryPromise = createDracoPrimitive( primitive );
2573

T
Takahiro 已提交
2574
				} else {
2575

2576
					// Otherwise create a new geometry
T
Takahiro 已提交
2577 2578 2579
					geometryPromise = addPrimitiveAttributes( new THREE.BufferGeometry(), primitive, parser );

				}
D
Don McCurdy 已提交
2580

T
Takahiro 已提交
2581
				// Cache this geometry
2582
				cache[ cacheKey ] = { primitive: primitive, promise: geometryPromise };
D
Don McCurdy 已提交
2583

2584
				pending.push( geometryPromise );
T
Takahiro 已提交
2585

T
Takahiro 已提交
2586
			}
2587

T
Takahiro 已提交
2588
		}
D
Don McCurdy 已提交
2589

2590
		return Promise.all( pending );
2591

D
Don McCurdy 已提交
2592
	};
D
Don McCurdy 已提交
2593

D
Don McCurdy 已提交
2594 2595
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes
T
Takahiro 已提交
2596
	 * @param {number} meshIndex
D
Daniel Hritzkiv 已提交
2597
	 * @return {Promise<THREE.Group|THREE.Mesh|THREE.SkinnedMesh>}
D
Don McCurdy 已提交
2598
	 */
T
Takahiro 已提交
2599
	GLTFParser.prototype.loadMesh = function ( meshIndex ) {
D
Don McCurdy 已提交
2600

T
Takahiro 已提交
2601
		var parser = this;
D
Don McCurdy 已提交
2602
		var json = this.json;
D
Don McCurdy 已提交
2603

M
Mugen87 已提交
2604
		var meshDef = json.meshes[ meshIndex ];
T
Takahiro 已提交
2605
		var primitives = meshDef.primitives;
D
Don McCurdy 已提交
2606

2607
		var pending = [];
T
Takahiro 已提交
2608

T
Takahiro 已提交
2609
		for ( var i = 0, il = primitives.length; i < il; i ++ ) {
T
Takahiro 已提交
2610

T
Takahiro 已提交
2611
			var material = primitives[ i ].material === undefined
2612
				? createDefaultMaterial( this.cache )
T
Takahiro 已提交
2613 2614 2615
				: this.getDependency( 'material', primitives[ i ].material );

			pending.push( material );
T
Takahiro 已提交
2616

T
Takahiro 已提交
2617 2618
		}

2619
		pending.push( parser.loadGeometries( primitives ) );
D
Don McCurdy 已提交
2620

2621
		return Promise.all( pending ).then( function ( results ) {
D
Don McCurdy 已提交
2622

2623 2624
			var materials = results.slice( 0, results.length - 1 );
			var geometries = results[ results.length - 1 ];
D
Don McCurdy 已提交
2625

2626
			var meshes = [];
D
Don McCurdy 已提交
2627

2628
			for ( var i = 0, il = geometries.length; i < il; i ++ ) {
2629

2630 2631
				var geometry = geometries[ i ];
				var primitive = primitives[ i ];
2632

2633
				// 1. create Mesh
2634

2635
				var mesh;
2636

2637
				var material = materials[ i ];
2638

2639 2640 2641 2642
				if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||
					primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
					primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||
					primitive.mode === undefined ) {
2643

2644 2645 2646 2647
					// .isSkinnedMesh isn't in glTF spec. See .markDefs()
					mesh = meshDef.isSkinnedMesh === true
						? new THREE.SkinnedMesh( geometry, material )
						: new THREE.Mesh( geometry, material );
2648

2649
					if ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {
2650

2651 2652 2653
						// we normalize floating point skin weight array to fix malformed assets (see #15319)
						// it's important to skip this for non-float32 data since normalizeSkinWeights assumes non-normalized inputs
						mesh.normalizeSkinWeights();
M
Mugen87 已提交
2654

2655
					}
2656

2657
					if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
2658

2659
						mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleStripDrawMode );
2660

2661
					} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
2662

2663
						mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleFanDrawMode );
2664

2665
					}
T
Takahiro 已提交
2666

2667
				} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
T
Takahiro 已提交
2668

2669
					mesh = new THREE.LineSegments( geometry, material );
T
Takahiro 已提交
2670

2671
				} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {
T
Takahiro 已提交
2672

2673
					mesh = new THREE.Line( geometry, material );
2674

2675
				} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
2676

2677
					mesh = new THREE.LineLoop( geometry, material );
D
Don McCurdy 已提交
2678

2679
				} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
D
Don McCurdy 已提交
2680

2681
					mesh = new THREE.Points( geometry, material );
D
Don McCurdy 已提交
2682

2683
				} else {
D
Don McCurdy 已提交
2684

2685
					throw new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );
2686

2687
				}
2688

2689
				if ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {
2690

2691
					updateMorphTargets( mesh, meshDef );
T
Takahiro 已提交
2692

2693
				}
T
Takahiro 已提交
2694

2695
				mesh.name = meshDef.name || ( 'mesh_' + meshIndex );
T
Takahiro 已提交
2696

2697
				if ( geometries.length > 1 ) mesh.name += '_' + i;
T
Takahiro 已提交
2698

2699
				assignExtrasToUserData( mesh, meshDef );
T
Takahiro 已提交
2700

2701
				parser.assignFinalMaterial( mesh );
2702

2703
				meshes.push( mesh );
T
Takahiro 已提交
2704

2705
			}
T
Takahiro 已提交
2706

2707
			if ( meshes.length === 1 ) {
D
Don McCurdy 已提交
2708

2709
				return meshes[ 0 ];
T
Takahiro 已提交
2710

2711
			}
D
Don McCurdy 已提交
2712

2713
			var group = new THREE.Group();
T
Takahiro 已提交
2714

2715
			for ( var i = 0, il = meshes.length; i < il; i ++ ) {
D
Don McCurdy 已提交
2716

2717
				group.add( meshes[ i ] );
D
Don McCurdy 已提交
2718

2719
			}
D
Don McCurdy 已提交
2720

2721
			return group;
D
Don McCurdy 已提交
2722 2723 2724 2725 2726

		} );

	};

2727 2728
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras
D
Don McCurdy 已提交
2729 2730
	 * @param {number} cameraIndex
	 * @return {Promise<THREE.Camera>}
2731
	 */
D
Don McCurdy 已提交
2732
	GLTFParser.prototype.loadCamera = function ( cameraIndex ) {
D
Don McCurdy 已提交
2733

D
Don McCurdy 已提交
2734 2735 2736
		var camera;
		var cameraDef = this.json.cameras[ cameraIndex ];
		var params = cameraDef[ cameraDef.type ];
D
Don McCurdy 已提交
2737

D
Don McCurdy 已提交
2738
		if ( ! params ) {
D
Don McCurdy 已提交
2739

D
Don McCurdy 已提交
2740 2741
			console.warn( 'THREE.GLTFLoader: Missing camera parameters.' );
			return;
D
Don McCurdy 已提交
2742

D
Don McCurdy 已提交
2743
		}
D
Don McCurdy 已提交
2744

D
Don McCurdy 已提交
2745
		if ( cameraDef.type === 'perspective' ) {
D
Don McCurdy 已提交
2746

2747
			camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( params.yfov ), params.aspectRatio || 1, params.znear || 1, params.zfar || 2e6 );
D
Don McCurdy 已提交
2748

D
Don McCurdy 已提交
2749
		} else if ( cameraDef.type === 'orthographic' ) {
D
Don McCurdy 已提交
2750

M
Mugen87 已提交
2751
			camera = new THREE.OrthographicCamera( params.xmag / - 2, params.xmag / 2, params.ymag / 2, params.ymag / - 2, params.znear, params.zfar );
D
Don McCurdy 已提交
2752

D
Don McCurdy 已提交
2753
		}
2754

D
Don McCurdy 已提交
2755
		if ( cameraDef.name !== undefined ) camera.name = cameraDef.name;
2756 2757

		assignExtrasToUserData( camera, cameraDef );
2758

D
Don McCurdy 已提交
2759
		return Promise.resolve( camera );
D
Don McCurdy 已提交
2760 2761 2762

	};

T
Takahiro 已提交
2763 2764 2765 2766 2767 2768
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins
	 * @param {number} skinIndex
	 * @return {Promise<Object>}
	 */
	GLTFParser.prototype.loadSkin = function ( skinIndex ) {
D
Don McCurdy 已提交
2769

T
Takahiro 已提交
2770
		var skinDef = this.json.skins[ skinIndex ];
D
Don McCurdy 已提交
2771

T
Takahiro 已提交
2772
		var skinEntry = { joints: skinDef.joints };
D
Don McCurdy 已提交
2773

T
Takahiro 已提交
2774
		if ( skinDef.inverseBindMatrices === undefined ) {
D
Don McCurdy 已提交
2775

T
Takahiro 已提交
2776
			return Promise.resolve( skinEntry );
D
Don McCurdy 已提交
2777

T
Takahiro 已提交
2778
		}
D
Don McCurdy 已提交
2779

T
Takahiro 已提交
2780
		return this.getDependency( 'accessor', skinDef.inverseBindMatrices ).then( function ( accessor ) {
D
Don McCurdy 已提交
2781

T
Takahiro 已提交
2782
			skinEntry.inverseBindMatrices = accessor;
D
Don McCurdy 已提交
2783

T
Takahiro 已提交
2784
			return skinEntry;
D
Don McCurdy 已提交
2785 2786 2787 2788 2789

		} );

	};

T
Takahiro 已提交
2790 2791 2792 2793 2794 2795
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations
	 * @param {number} animationIndex
	 * @return {Promise<THREE.AnimationClip>}
	 */
	GLTFParser.prototype.loadAnimation = function ( animationIndex ) {
D
Don McCurdy 已提交
2796 2797 2798

		var json = this.json;

M
Mugen87 已提交
2799
		var animationDef = json.animations[ animationIndex ];
D
Don McCurdy 已提交
2800

2801 2802 2803 2804 2805
		var pendingNodes = [];
		var pendingInputAccessors = [];
		var pendingOutputAccessors = [];
		var pendingSamplers = [];
		var pendingTargets = [];
D
Don McCurdy 已提交
2806

T
Takahiro 已提交
2807
		for ( var i = 0, il = animationDef.channels.length; i < il; i ++ ) {
D
Don McCurdy 已提交
2808

T
Takahiro 已提交
2809 2810 2811 2812 2813 2814
			var channel = animationDef.channels[ i ];
			var sampler = animationDef.samplers[ channel.sampler ];
			var target = channel.target;
			var name = target.node !== undefined ? target.node : target.id; // NOTE: target.id is deprecated.
			var input = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.input ] : sampler.input;
			var output = animationDef.parameters !== undefined ? animationDef.parameters[ sampler.output ] : sampler.output;
D
Don McCurdy 已提交
2815

2816 2817 2818 2819 2820
			pendingNodes.push( this.getDependency( 'node', name ) );
			pendingInputAccessors.push( this.getDependency( 'accessor', input ) );
			pendingOutputAccessors.push( this.getDependency( 'accessor', output ) );
			pendingSamplers.push( sampler );
			pendingTargets.push( target );
D
Don McCurdy 已提交
2821

T
Takahiro 已提交
2822
		}
D
Don McCurdy 已提交
2823

T
Takahiro 已提交
2824
		return Promise.all( [
D
Don McCurdy 已提交
2825

2826 2827 2828 2829 2830
			Promise.all( pendingNodes ),
			Promise.all( pendingInputAccessors ),
			Promise.all( pendingOutputAccessors ),
			Promise.all( pendingSamplers ),
			Promise.all( pendingTargets )
D
Don McCurdy 已提交
2831

T
Takahiro 已提交
2832
		] ).then( function ( dependencies ) {
D
Don McCurdy 已提交
2833

T
Takahiro 已提交
2834 2835 2836 2837 2838
			var nodes = dependencies[ 0 ];
			var inputAccessors = dependencies[ 1 ];
			var outputAccessors = dependencies[ 2 ];
			var samplers = dependencies[ 3 ];
			var targets = dependencies[ 4 ];
D
Don McCurdy 已提交
2839

T
Takahiro 已提交
2840
			var tracks = [];
T
Takahiro 已提交
2841

T
Takahiro 已提交
2842
			for ( var i = 0, il = nodes.length; i < il; i ++ ) {
T
Takahiro 已提交
2843

T
Takahiro 已提交
2844 2845 2846 2847 2848
				var node = nodes[ i ];
				var inputAccessor = inputAccessors[ i ];
				var outputAccessor = outputAccessors[ i ];
				var sampler = samplers[ i ];
				var target = targets[ i ];
T
Takahiro 已提交
2849

T
Takahiro 已提交
2850
				if ( node === undefined ) continue;
T
Takahiro 已提交
2851

T
Takahiro 已提交
2852 2853
				node.updateMatrix();
				node.matrixAutoUpdate = true;
T
Takahiro 已提交
2854

T
Takahiro 已提交
2855
				var TypedKeyframeTrack;
T
Takahiro 已提交
2856

T
Takahiro 已提交
2857
				switch ( PATH_PROPERTIES[ target.path ] ) {
T
Takahiro 已提交
2858

T
Takahiro 已提交
2859
					case PATH_PROPERTIES.weights:
T
Takahiro 已提交
2860

T
Takahiro 已提交
2861 2862
						TypedKeyframeTrack = THREE.NumberKeyframeTrack;
						break;
D
Don McCurdy 已提交
2863

T
Takahiro 已提交
2864
					case PATH_PROPERTIES.rotation:
2865

T
Takahiro 已提交
2866 2867
						TypedKeyframeTrack = THREE.QuaternionKeyframeTrack;
						break;
2868

T
Takahiro 已提交
2869 2870 2871
					case PATH_PROPERTIES.position:
					case PATH_PROPERTIES.scale:
					default:
T
Takahiro 已提交
2872

T
Takahiro 已提交
2873 2874
						TypedKeyframeTrack = THREE.VectorKeyframeTrack;
						break;
T
Takahiro 已提交
2875

T
Takahiro 已提交
2876
				}
T
Takahiro 已提交
2877

T
Takahiro 已提交
2878
				var targetName = node.name ? node.name : node.uuid;
T
Takahiro 已提交
2879

T
Takahiro 已提交
2880
				var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear;
T
Takahiro 已提交
2881

T
Takahiro 已提交
2882
				var targetNames = [];
T
Takahiro 已提交
2883

T
Takahiro 已提交
2884
				if ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {
T
Takahiro 已提交
2885

2886
					// Node may be a THREE.Group (glTF mesh with several primitives) or a THREE.Mesh.
T
Takahiro 已提交
2887
					node.traverse( function ( object ) {
T
Takahiro 已提交
2888

T
Takahiro 已提交
2889
						if ( object.isMesh === true && object.morphTargetInfluences ) {
T
Takahiro 已提交
2890

T
Takahiro 已提交
2891
							targetNames.push( object.name ? object.name : object.uuid );
T
Takahiro 已提交
2892

T
Takahiro 已提交
2893
						}
T
Takahiro 已提交
2894

T
Takahiro 已提交
2895
					} );
T
Takahiro 已提交
2896

T
Takahiro 已提交
2897
				} else {
2898

T
Takahiro 已提交
2899
					targetNames.push( targetName );
2900

T
Takahiro 已提交
2901
				}
2902

2903 2904 2905 2906
				var outputArray = outputAccessor.array;

				if ( outputAccessor.normalized ) {

2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929
					var scale;

					if ( outputArray.constructor === Int8Array ) {

						scale = 1 / 127;

					} else if ( outputArray.constructor === Uint8Array ) {

						scale = 1 / 255;

					} else if ( outputArray.constructor == Int16Array ) {

						scale = 1 / 32767;

					} else if ( outputArray.constructor === Uint16Array ) {

						scale = 1 / 65535;

					} else {

						throw new Error( 'THREE.GLTFLoader: Unsupported output accessor component type.' );

					}
2930 2931 2932 2933 2934

					var scaled = new Float32Array( outputArray.length );

					for ( var j = 0, jl = outputArray.length; j < jl; j ++ ) {

M
Mugen87 已提交
2935
						scaled[ j ] = outputArray[ j ] * scale;
2936 2937 2938 2939 2940 2941 2942

					}

					outputArray = scaled;

				}

T
Takahiro 已提交
2943
				for ( var j = 0, jl = targetNames.length; j < jl; j ++ ) {
2944

T
Takahiro 已提交
2945 2946
					var track = new TypedKeyframeTrack(
						targetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],
2947
						inputAccessor.array,
2948
						outputArray,
T
Takahiro 已提交
2949 2950
						interpolation
					);
2951

2952
					// Override interpolation with custom factory method.
T
Takahiro 已提交
2953
					if ( sampler.interpolation === 'CUBICSPLINE' ) {
2954

T
Takahiro 已提交
2955
						track.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {
2956

T
Takahiro 已提交
2957 2958 2959
							// A CUBICSPLINE keyframe in glTF has three output values for each input value,
							// representing inTangent, splineVertex, and outTangent. As a result, track.getValueSize()
							// must be divided by three to get the interpolant's sampleSize argument.
2960

T
Takahiro 已提交
2961
							return new GLTFCubicSplineInterpolant( this.times, this.values, this.getValueSize() / 3, result );
D
Don McCurdy 已提交
2962

T
Takahiro 已提交
2963 2964
						};

2965
						// Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.
T
Takahiro 已提交
2966
						track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;
D
Don McCurdy 已提交
2967 2968 2969

					}

T
Takahiro 已提交
2970 2971
					tracks.push( track );

D
Don McCurdy 已提交
2972 2973
				}

T
Takahiro 已提交
2974
			}
D
Don McCurdy 已提交
2975

T
Takahiro 已提交
2976
			var name = animationDef.name !== undefined ? animationDef.name : 'animation_' + animationIndex;
D
Don McCurdy 已提交
2977

T
Takahiro 已提交
2978
			return new THREE.AnimationClip( name, undefined, tracks );
D
Don McCurdy 已提交
2979 2980 2981 2982 2983

		} );

	};

T
Takahiro 已提交
2984 2985 2986 2987 2988 2989
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#nodes-and-hierarchy
	 * @param {number} nodeIndex
	 * @return {Promise<THREE.Object3D>}
	 */
	GLTFParser.prototype.loadNode = function ( nodeIndex ) {
D
Don McCurdy 已提交
2990 2991 2992

		var json = this.json;
		var extensions = this.extensions;
T
Takahiro 已提交
2993
		var parser = this;
D
Don McCurdy 已提交
2994

M
Mugen87 已提交
2995 2996
		var meshReferences = json.meshReferences;
		var meshUses = json.meshUses;
D
Don McCurdy 已提交
2997

M
Mugen87 已提交
2998
		var nodeDef = json.nodes[ nodeIndex ];
D
Don McCurdy 已提交
2999

M
Mugen87 已提交
3000
		return ( function () {
3001

V
vyv03354 已提交
3002
			var pending = [];
3003

V
vyv03354 已提交
3004
			if ( nodeDef.mesh !== undefined ) {
3005

V
vyv03354 已提交
3006
				pending.push( parser.getDependency( 'mesh', nodeDef.mesh ).then( function ( mesh ) {
3007

T
Takahiro 已提交
3008
					var node;
D
Don McCurdy 已提交
3009

T
Takahiro 已提交
3010
					if ( meshReferences[ nodeDef.mesh ] > 1 ) {
D
Don McCurdy 已提交
3011

T
Takahiro 已提交
3012
						var instanceNum = meshUses[ nodeDef.mesh ] ++;
D
Don McCurdy 已提交
3013

T
Takahiro 已提交
3014 3015
						node = mesh.clone();
						node.name += '_instance_' + instanceNum;
D
Don McCurdy 已提交
3016

T
Takahiro 已提交
3017 3018
						// onBeforeRender copy for Specular-Glossiness
						node.onBeforeRender = mesh.onBeforeRender;
D
Don McCurdy 已提交
3019

T
Takahiro 已提交
3020
						for ( var i = 0, il = node.children.length; i < il; i ++ ) {
D
Don McCurdy 已提交
3021

T
Takahiro 已提交
3022 3023
							node.children[ i ].name += '_instance_' + instanceNum;
							node.children[ i ].onBeforeRender = mesh.children[ i ].onBeforeRender;
D
Don McCurdy 已提交
3024

T
Takahiro 已提交
3025 3026 3027
						}

					} else {
3028

T
Takahiro 已提交
3029
						node = mesh;
D
Don McCurdy 已提交
3030

T
Takahiro 已提交
3031 3032
					}

3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049
					// if weights are provided on the node, override weights on the mesh.
					if ( nodeDef.weights !== undefined ) {

						node.traverse( function ( o ) {

							if ( ! o.isMesh ) return;

							for ( var i = 0, il = nodeDef.weights.length; i < il; i ++ ) {

								o.morphTargetInfluences[ i ] = nodeDef.weights[ i ];

							}

						} );

					}

3050
					return node;
T
Takahiro 已提交
3051

V
vyv03354 已提交
3052 3053 3054 3055 3056
				} ) );

			}

			if ( nodeDef.camera !== undefined ) {
D
Don McCurdy 已提交
3057

V
vyv03354 已提交
3058
				pending.push( parser.getDependency( 'camera', nodeDef.camera ) );
D
Don McCurdy 已提交
3059

V
vyv03354 已提交
3060
			}
D
Don McCurdy 已提交
3061

V
vyv03354 已提交
3062
			if ( nodeDef.extensions
T
Takahiro 已提交
3063 3064
				&& nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ]
				&& nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light !== undefined ) {
D
Don McCurdy 已提交
3065

V
vyv03354 已提交
3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086
				pending.push( parser.getDependency( 'light', nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light ) );

			}

			return Promise.all( pending );

		}() ).then( function ( objects ) {

			var node;

			// .isBone isn't in glTF spec. See .markDefs
			if ( nodeDef.isBone === true ) {

				node = new THREE.Bone();

			} else if ( objects.length > 1 ) {

				node = new THREE.Group();

			} else if ( objects.length === 1 ) {

V
vyv03354 已提交
3087
				node = objects[ 0 ];
D
Don McCurdy 已提交
3088

T
Takahiro 已提交
3089
			} else {
3090

V
vyv03354 已提交
3091
				node = new THREE.Object3D();
D
Don McCurdy 已提交
3092

T
Takahiro 已提交
3093
			}
D
Don McCurdy 已提交
3094

V
vyv03354 已提交
3095
			if ( node !== objects[ 0 ] ) {
V
vyv03354 已提交
3096 3097 3098

				for ( var i = 0, il = objects.length; i < il; i ++ ) {

V
vyv03354 已提交
3099
					node.add( objects[ i ] );
V
vyv03354 已提交
3100 3101 3102 3103

				}

			}
T
Takahiro 已提交
3104

T
Takahiro 已提交
3105
			if ( nodeDef.name !== undefined ) {
D
Don McCurdy 已提交
3106

3107
				node.userData.name = nodeDef.name;
T
Takahiro 已提交
3108
				node.name = THREE.PropertyBinding.sanitizeNodeName( nodeDef.name );
D
Don McCurdy 已提交
3109

T
Takahiro 已提交
3110
			}
D
Don McCurdy 已提交
3111

3112
			assignExtrasToUserData( node, nodeDef );
D
Don McCurdy 已提交
3113

3114
			if ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );
3115

T
Takahiro 已提交
3116
			if ( nodeDef.matrix !== undefined ) {
D
Don McCurdy 已提交
3117

T
Takahiro 已提交
3118 3119 3120
				var matrix = new THREE.Matrix4();
				matrix.fromArray( nodeDef.matrix );
				node.applyMatrix( matrix );
D
Don McCurdy 已提交
3121

T
Takahiro 已提交
3122
			} else {
D
Don McCurdy 已提交
3123

T
Takahiro 已提交
3124
				if ( nodeDef.translation !== undefined ) {
D
Don McCurdy 已提交
3125

T
Takahiro 已提交
3126
					node.position.fromArray( nodeDef.translation );
D
Don McCurdy 已提交
3127

T
Takahiro 已提交
3128
				}
3129

T
Takahiro 已提交
3130
				if ( nodeDef.rotation !== undefined ) {
D
Don McCurdy 已提交
3131

T
Takahiro 已提交
3132
					node.quaternion.fromArray( nodeDef.rotation );
D
Don McCurdy 已提交
3133

T
Takahiro 已提交
3134
				}
D
Don McCurdy 已提交
3135

T
Takahiro 已提交
3136
				if ( nodeDef.scale !== undefined ) {
D
Don McCurdy 已提交
3137

T
Takahiro 已提交
3138
					node.scale.fromArray( nodeDef.scale );
D
Don McCurdy 已提交
3139

T
Takahiro 已提交
3140
				}
D
Don McCurdy 已提交
3141

T
Takahiro 已提交
3142
			}
D
Don McCurdy 已提交
3143

T
Takahiro 已提交
3144
			return node;
D
Don McCurdy 已提交
3145

T
Takahiro 已提交
3146
		} );
D
Don McCurdy 已提交
3147

T
Takahiro 已提交
3148
	};
3149

T
Takahiro 已提交
3150 3151 3152 3153 3154 3155
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#scenes
	 * @param {number} sceneIndex
	 * @return {Promise<THREE.Scene>}
	 */
	GLTFParser.prototype.loadScene = function () {
D
Don McCurdy 已提交
3156

T
Takahiro 已提交
3157
		// scene node hierachy builder
D
Don McCurdy 已提交
3158

T
Takahiro 已提交
3159
		function buildNodeHierachy( nodeId, parentObject, json, parser ) {
D
Don McCurdy 已提交
3160

T
Takahiro 已提交
3161
			var nodeDef = json.nodes[ nodeId ];
D
Don McCurdy 已提交
3162

T
Takahiro 已提交
3163
			return parser.getDependency( 'node', nodeId ).then( function ( node ) {
D
Don McCurdy 已提交
3164

T
Takahiro 已提交
3165
				if ( nodeDef.skin === undefined ) return node;
D
Don McCurdy 已提交
3166

T
Takahiro 已提交
3167
				// build skeleton here as well
D
Don McCurdy 已提交
3168

T
Takahiro 已提交
3169
				var skinEntry;
D
Don McCurdy 已提交
3170

T
Takahiro 已提交
3171
				return parser.getDependency( 'skin', nodeDef.skin ).then( function ( skin ) {
D
Don McCurdy 已提交
3172

T
Takahiro 已提交
3173
					skinEntry = skin;
D
Don McCurdy 已提交
3174

3175
					var pendingJoints = [];
D
Don McCurdy 已提交
3176

T
Takahiro 已提交
3177
					for ( var i = 0, il = skinEntry.joints.length; i < il; i ++ ) {
D
Don McCurdy 已提交
3178

3179
						pendingJoints.push( parser.getDependency( 'node', skinEntry.joints[ i ] ) );
D
Don McCurdy 已提交
3180

T
Takahiro 已提交
3181
					}
T
Takahiro 已提交
3182

3183
					return Promise.all( pendingJoints );
T
Takahiro 已提交
3184

T
Takahiro 已提交
3185
				} ).then( function ( jointNodes ) {
3186

V
vyv03354 已提交
3187
					node.traverse( function ( mesh ) {
D
Don McCurdy 已提交
3188

V
vyv03354 已提交
3189
						if ( ! mesh.isMesh ) return;
T
Takahiro 已提交
3190 3191 3192 3193 3194

						var bones = [];
						var boneInverses = [];

						for ( var j = 0, jl = jointNodes.length; j < jl; j ++ ) {
3195

T
Takahiro 已提交
3196
							var jointNode = jointNodes[ j ];
3197

T
Takahiro 已提交
3198
							if ( jointNode ) {
3199

T
Takahiro 已提交
3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216
								bones.push( jointNode );

								var mat = new THREE.Matrix4();

								if ( skinEntry.inverseBindMatrices !== undefined ) {

									mat.fromArray( skinEntry.inverseBindMatrices.array, j * 16 );

								}

								boneInverses.push( mat );

							} else {

								console.warn( 'THREE.GLTFLoader: Joint "%s" could not be found.', skinEntry.joints[ j ] );

							}
3217 3218

						}
D
Don McCurdy 已提交
3219

T
Takahiro 已提交
3220
						mesh.bind( new THREE.Skeleton( bones, boneInverses ), mesh.matrixWorld );
D
Don McCurdy 已提交
3221

V
vyv03354 已提交
3222
					} );
D
Don McCurdy 已提交
3223

T
Takahiro 已提交
3224
					return node;
D
Don McCurdy 已提交
3225

T
Takahiro 已提交
3226 3227 3228
				} );

			} ).then( function ( node ) {
D
Don McCurdy 已提交
3229

T
Takahiro 已提交
3230
				// build node hierachy
D
Don McCurdy 已提交
3231

T
Takahiro 已提交
3232
				parentObject.add( node );
D
Don McCurdy 已提交
3233

3234
				var pending = [];
D
Don McCurdy 已提交
3235

T
Takahiro 已提交
3236
				if ( nodeDef.children ) {
D
Don McCurdy 已提交
3237

T
Takahiro 已提交
3238
					var children = nodeDef.children;
D
Don McCurdy 已提交
3239

T
Takahiro 已提交
3240 3241 3242
					for ( var i = 0, il = children.length; i < il; i ++ ) {

						var child = children[ i ];
3243
						pending.push( buildNodeHierachy( child, node, json, parser ) );
T
Takahiro 已提交
3244 3245

					}
D
Don McCurdy 已提交
3246 3247 3248

				}

3249
				return Promise.all( pending );
T
Takahiro 已提交
3250 3251

			} );
D
Don McCurdy 已提交
3252 3253 3254

		}

T
Takahiro 已提交
3255
		return function loadScene( sceneIndex ) {
D
Don McCurdy 已提交
3256

T
Takahiro 已提交
3257 3258 3259
			var json = this.json;
			var extensions = this.extensions;
			var sceneDef = this.json.scenes[ sceneIndex ];
T
Takahiro 已提交
3260
			var parser = this;
D
Don McCurdy 已提交
3261

T
Takahiro 已提交
3262 3263
			var scene = new THREE.Scene();
			if ( sceneDef.name !== undefined ) scene.name = sceneDef.name;
D
Don McCurdy 已提交
3264

T
Takahiro 已提交
3265
			assignExtrasToUserData( scene, sceneDef );
D
Don McCurdy 已提交
3266

T
Takahiro 已提交
3267
			if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );
D
Don McCurdy 已提交
3268

T
Takahiro 已提交
3269
			var nodeIds = sceneDef.nodes || [];
D
Don McCurdy 已提交
3270

3271
			var pending = [];
3272

T
Takahiro 已提交
3273
			for ( var i = 0, il = nodeIds.length; i < il; i ++ ) {
D
Don McCurdy 已提交
3274

3275
				pending.push( buildNodeHierachy( nodeIds[ i ], scene, json, parser ) );
D
Don McCurdy 已提交
3276

T
Takahiro 已提交
3277
			}
D
Don McCurdy 已提交
3278

3279
			return Promise.all( pending ).then( function () {
D
Don McCurdy 已提交
3280

T
Takahiro 已提交
3281
				return scene;
D
Don McCurdy 已提交
3282 3283 3284

			} );

T
Takahiro 已提交
3285
		};
D
Don McCurdy 已提交
3286

T
Takahiro 已提交
3287
	}();
D
Don McCurdy 已提交
3288

3289
	return GLTFLoader;
D
Don McCurdy 已提交
3290 3291

} )();