GLTFLoader.js 78.7 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

494 495 496 497
	}

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

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

		for ( var attributeName in gltfAttributeMap ) {

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

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

512
		}
513

514
		for ( attributeName in primitive.attributes ) {
515

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

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

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

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

			}
527

528
		}
529

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

532
			return new Promise( function ( resolve ) {
533

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

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

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

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

					}

					resolve( geometry );

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

			} );

		} );

	};

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

		this.name = EXTENSIONS.KHR_TEXTURE_TRANSFORM;

	}

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

		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 );

		}

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

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

		}

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

		return texture;

	};

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

		return {

609 610
			name: EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS,

611 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
			specularGlossinessParams: [
				'color',
				'map',
				'lightMap',
				'lightMapIntensity',
				'aoMap',
				'aoMapIntensity',
				'emissive',
				'emissiveIntensity',
				'emissiveMap',
				'bumpMap',
				'bumpScale',
				'normalMap',
				'displacementMap',
				'displacementScale',
				'displacementBias',
				'specularMap',
				'specular',
				'glossinessMap',
				'glossiness',
				'alphaMap',
				'envMap',
				'envMapIntensity',
				'refractionRatio',
			],

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

				return THREE.ShaderMaterial;

			},

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

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

				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 );',
667
					'	texelSpecular = sRGBToLinear( texelSpecular );',
668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689
					'	// 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 已提交
690 691 692 693 694 695 696
					.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 );
697 698 699 700 701 702 703 704 705 706 707

				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 已提交
708 709 710
				materialParams.vertexShader = shader.vertexShader;
				materialParams.fragmentShader = fragmentShader;
				materialParams.uniforms = uniforms;
M
Mugen87 已提交
711
				materialParams.defines = { 'STANDARD': '' };
712

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

716
				var pending = [];
717

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

					var array = pbrSpecularGlossiness.diffuseFactor;

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

				}

				if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {

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

				}

T
Takahiro 已提交
733 734 735
				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 );
736 737 738

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

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

				}

				if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {

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

				}

751
				return Promise.all( pending );
752

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

			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
				} );

770 771
				material.isGLTFSpecularGlossinessMaterial = true;

772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789
				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 已提交
790

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

				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;

			},

816 817 818 819 820 821 822 823 824 825 826 827
			/**
			 * 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}
			 */
828 829 830 831 832 833 834 835
			cloneMaterial: function ( source ) {

				var target = source.clone();

				target.isGLTFSpecularGlossinessMaterial = true;

				var params = this.specularGlossinessParams;

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

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

				}

				return target;

			},

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

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

					return;

				}

856 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
				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;

					}

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

929
						uvScaleMap.updateMatrix();
930 931

					}
932

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

935 936
				}

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

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

942 943 944 945
					// 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 已提交
946
					uniforms.flipEnvMap.value = material.envMap.isCubeTexture ? - 1 : 1;
947 948 949 950 951

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

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

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

				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
972
					defines.USE_ROUGHNESSMAP = '';
973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988

				}

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

					delete defines.USE_GLOSSINESSMAP;
					delete defines.USE_ROUGHNESSMAP;

				}

			}

		};

	}

989 990 991 992 993 994 995 996 997 998 999
	/**
	 * 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;

	}

1000 1001 1002 1003 1004 1005 1006 1007 1008 1009
	/*********************************/
	/********** 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 已提交
1010
	}
1011

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

1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038
	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_;

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

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

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

1048
		var td = t1 - t0;
1049

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

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

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

1062 1063 1064
		// 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 ++ ) {
1065

M
Mugen87 已提交
1066 1067 1068 1069
			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)
1070

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

		}

1075 1076 1077
		return result;

	};
1078

D
Don McCurdy 已提交
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
	/*********************************/
	/********** 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,
1096
		POINTS: 0,
D
Don McCurdy 已提交
1097
		LINES: 1,
1098 1099 1100 1101 1102
		LINE_LOOP: 2,
		LINE_STRIP: 3,
		TRIANGLES: 4,
		TRIANGLE_STRIP: 5,
		TRIANGLE_FAN: 6,
D
Don McCurdy 已提交
1103
		UNSIGNED_BYTE: 5121,
1104
		UNSIGNED_SHORT: 5123
D
Don McCurdy 已提交
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118
	};

	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 已提交
1119 1120 1121 1122
		9984: THREE.NearestMipmapNearestFilter,
		9985: THREE.LinearMipmapNearestFilter,
		9986: THREE.NearestMipmapLinearFilter,
		9987: THREE.LinearMipmapLinearFilter
D
Don McCurdy 已提交
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140
	};

	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
	};

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

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

	var INTERPOLATION = {
1160 1161
		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 已提交
1162 1163 1164 1165
		LINEAR: THREE.InterpolateLinear,
		STEP: THREE.InterpolateDiscrete
	};

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

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

1177 1178
	/* UTILITY FUNCTIONS */

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

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

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

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

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

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

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

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

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

	}

1205 1206
	var defaultMaterial;

1207 1208 1209
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
	 */
D
Don McCurdy 已提交
1210 1211
	function createDefaultMaterial() {

1212
		defaultMaterial = defaultMaterial || new THREE.MeshStandardMaterial( {
1213 1214 1215 1216
			color: 0xFFFFFF,
			emissive: 0x000000,
			metalness: 1,
			roughness: 1,
D
Don McCurdy 已提交
1217 1218 1219 1220 1221
			transparent: false,
			depthTest: true,
			side: THREE.FrontSide
		} );

1222 1223
		return defaultMaterial;

D
Don McCurdy 已提交
1224 1225
	}

1226
	function addUnknownExtensionsToUserData( knownExtensions, object, objectDef ) {
1227 1228 1229 1230 1231

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

		for ( var name in objectDef.extensions ) {

1232
			if ( knownExtensions[ name ] === undefined ) {
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242

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

			}

		}

	}

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

		if ( gltfDef.extras !== undefined ) {

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

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

			} else {

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

			}

		}

	}

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

1275 1276 1277 1278 1279 1280 1281 1282 1283
		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 已提交
1284

1285
			if ( hasMorphPosition && hasMorphNormal ) break;
D
Don McCurdy 已提交
1286

1287 1288
		}

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

1291 1292
		var pendingPositionAccessors = [];
		var pendingNormalAccessors = [];
D
Don McCurdy 已提交
1293 1294 1295 1296 1297

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

			var target = targets[ i ];

1298
			if ( hasMorphPosition ) {
D
Don McCurdy 已提交
1299

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

D
Don McCurdy 已提交
1304
				pendingPositionAccessors.push( pendingAccessor );
D
Don McCurdy 已提交
1305

T
Takahiro 已提交
1306
			}
D
Don McCurdy 已提交
1307

T
Takahiro 已提交
1308
			if ( hasMorphNormal ) {
D
Don McCurdy 已提交
1309

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

D
Don McCurdy 已提交
1314
				pendingNormalAccessors.push( pendingAccessor );
D
Don McCurdy 已提交
1315

T
Takahiro 已提交
1316
			}
D
Don McCurdy 已提交
1317

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

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

T
Takahiro 已提交
1325 1326
			var morphPositions = accessors[ 0 ];
			var morphNormals = accessors[ 1 ];
1327

T
Takahiro 已提交
1328 1329
			if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;
			if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;
1330
			geometry.morphTargetsRelative = true;
T
Takahiro 已提交
1331 1332

			return geometry;
D
Don McCurdy 已提交
1333

T
Takahiro 已提交
1334
		} );
1335

1336 1337 1338 1339 1340 1341 1342 1343
	}

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

D
Don McCurdy 已提交
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355
		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 已提交
1356
		// .extras has user-defined data, so check that .extras.targetNames is an array.
T
Takahiro 已提交
1357 1358
		if ( meshDef.extras && Array.isArray( meshDef.extras.targetNames ) ) {

1359
			var targetNames = meshDef.extras.targetNames;
T
Takahiro 已提交
1360

1361
			if ( mesh.morphTargetInfluences.length === targetNames.length ) {
1362

1363
				mesh.morphTargetDictionary = {};
1364

1365 1366 1367
				for ( var i = 0, il = targetNames.length; i < il; i ++ ) {

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

1369 1370 1371
				}

			} else {
1372

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

			}

		}

1379 1380
	}

R
Riccardo Padovani 已提交
1381
	function createPrimitiveKey( primitiveDef ) {
1382

R
Riccardo Padovani 已提交
1383
		var dracoExtension = primitiveDef.extensions && primitiveDef.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ];
1384
		var geometryKey;
1385

1386
		if ( dracoExtension ) {
1387

1388 1389 1390
			geometryKey = 'draco:' + dracoExtension.bufferView
				+ ':' + dracoExtension.indices
				+ ':' + createAttributesKey( dracoExtension.attributes );
1391

1392 1393
		} else {

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

1396 1397
		}

1398
		return geometryKey;
T
Takahiro 已提交
1399

1400 1401
	}

1402
	function createAttributesKey( attributes ) {
T
Takahiro 已提交
1403

1404
		var attributesKey = '';
T
Takahiro 已提交
1405

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

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

1410
			attributesKey += keys[ i ] + ':' + attributes[ keys[ i ] ] + ';';
1411

T
Takahiro 已提交
1412
		}
1413

1414
		return attributesKey;
1415

T
Takahiro 已提交
1416
	}
1417

D
Don McCurdy 已提交
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
	/* GLTF PARSER */

	function GLTFParser( json, extensions, options ) {

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

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

1429
		// BufferGeometry caching
1430
		this.primitiveCache = {};
1431

M
Mugen87 已提交
1432 1433 1434
		this.textureLoader = new THREE.TextureLoader( this.options.manager );
		this.textureLoader.setCrossOrigin( this.options.crossOrigin );

M
Mugen87 已提交
1435 1436 1437
		this.fileLoader = new THREE.FileLoader( this.options.manager );
		this.fileLoader.setResponseType( 'arraybuffer' );

1438 1439 1440 1441 1442 1443
		if ( this.options.crossOrigin === 'use-credentials' ) {

			this.fileLoader.setWithCredentials( true );

		}

D
Don McCurdy 已提交
1444 1445
	}

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

1448
		var parser = this;
T
Takahiro 已提交
1449
		var json = this.json;
1450
		var extensions = this.extensions;
D
Don McCurdy 已提交
1451

T
Takahiro 已提交
1452 1453
		// Clear the loader cache
		this.cache.removeAll();
D
Don McCurdy 已提交
1454

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

1458
		Promise.all( [
D
Don McCurdy 已提交
1459

1460 1461 1462
			this.getDependencies( 'scene' ),
			this.getDependencies( 'animation' ),
			this.getDependencies( 'camera' ),
D
Don McCurdy 已提交
1463

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

1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476
			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 已提交
1477

1478 1479
			assignExtrasToUserData( result, json );

1480
			onLoad( result );
D
Don McCurdy 已提交
1481

T
Takahiro 已提交
1482
		} ).catch( onError );
D
Don McCurdy 已提交
1483

T
Takahiro 已提交
1484
	};
D
Don McCurdy 已提交
1485

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

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

T
Takahiro 已提交
1495 1496
		var meshReferences = {};
		var meshUses = {};
D
Don McCurdy 已提交
1497

T
Takahiro 已提交
1498 1499 1500
		// 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 已提交
1501

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

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

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

T
Takahiro 已提交
1508
			}
D
Don McCurdy 已提交
1509

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

T
Takahiro 已提交
1512 1513 1514 1515 1516 1517
		// 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 已提交
1518

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

T
Takahiro 已提交
1521
			if ( nodeDef.mesh !== undefined ) {
1522

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

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

T
Takahiro 已提交
1527
				}
D
Don McCurdy 已提交
1528

T
Takahiro 已提交
1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545
				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 已提交
1546 1547 1548

	};

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

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

M
Mugen87 已提交
1560
		if ( ! dependency ) {
1561

T
Takahiro 已提交
1562 1563 1564 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
			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 已提交
1608 1609
				case 'light':
					dependency = this.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].loadLight( index );
M
Mugen87 已提交
1610
					break;
T
Takahiro 已提交
1611

T
Takahiro 已提交
1612 1613 1614 1615 1616
				default:
					throw new Error( 'Unknown type: ' + type );

			}

1617 1618 1619 1620 1621 1622 1623 1624
			this.cache.add( cacheKey, dependency );

		}

		return dependency;

	};

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

1632 1633 1634 1635 1636 1637 1638 1639
		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 已提交
1640

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

1643 1644 1645 1646 1647
			} ) );

			this.cache.add( type, dependencies );

		}
D
Don McCurdy 已提交
1648

1649
		return dependencies;
D
Don McCurdy 已提交
1650 1651 1652

	};

1653 1654 1655 1656 1657 1658
	/**
	 * 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 已提交
1659

1660
		var bufferDef = this.json.buffers[ bufferIndex ];
M
Mugen87 已提交
1661
		var loader = this.fileLoader;
D
Don McCurdy 已提交
1662

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

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

1667
		}
D
Don McCurdy 已提交
1668

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

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

1674
		}
D
Don McCurdy 已提交
1675

1676
		var options = this.options;
D
Don McCurdy 已提交
1677

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

1680 1681
			loader.load( resolveURL( bufferDef.uri, options.path ), resolve, undefined, function () {

1682
				reject( new Error( 'THREE.GLTFLoader: Failed to load buffer "' + bufferDef.uri + '".' ) );
1683 1684

			} );
D
Don McCurdy 已提交
1685 1686 1687 1688 1689

		} );

	};

1690 1691 1692 1693 1694 1695 1696
	/**
	 * 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 ) {

1697
		var bufferViewDef = this.json.bufferViews[ bufferViewIndex ];
1698

1699
		return this.getDependency( 'buffer', bufferViewDef.buffer ).then( function ( buffer ) {
1700

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

		} );

	};

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

1716
		var parser = this;
D
Don McCurdy 已提交
1717 1718
		var json = this.json;

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

1721 1722 1723 1724 1725
		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).
1726
			return Promise.resolve( null );
1727 1728 1729

		}

T
Takahiro 已提交
1730
		var pendingBufferViews = [];
1731

T
Takahiro 已提交
1732
		if ( accessorDef.bufferView !== undefined ) {
1733

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

T
Takahiro 已提交
1736
		} else {
1737

T
Takahiro 已提交
1738
			pendingBufferViews.push( null );
1739

T
Takahiro 已提交
1740
		}
1741

T
Takahiro 已提交
1742
		if ( accessorDef.sparse !== undefined ) {
1743

T
Takahiro 已提交
1744 1745
			pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.indices.bufferView ) );
			pendingBufferViews.push( this.getDependency( 'bufferView', accessorDef.sparse.values.bufferView ) );
1746

T
Takahiro 已提交
1747
		}
1748

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

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

T
Takahiro 已提交
1753 1754
			var itemSize = WEBGL_TYPE_SIZES[ accessorDef.type ];
			var TypedArray = WEBGL_COMPONENT_TYPES[ accessorDef.componentType ];
1755

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

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

1767 1768 1769 1770
				// 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;
1771 1772
				var ib = parser.cache.get( ibCacheKey );

D
Don McCurdy 已提交
1773
				if ( ! ib ) {
1774

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

1777 1778 1779 1780 1781 1782
					// 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 已提交
1783

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

T
Takahiro 已提交
1786
			} else {
D
Don McCurdy 已提交
1787

T
Takahiro 已提交
1788
				if ( bufferView === null ) {
1789

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

T
Takahiro 已提交
1792
				} else {
1793

1794
					array = new TypedArray( bufferView, byteOffset, accessorDef.count * itemSize );
D
Don McCurdy 已提交
1795 1796 1797

				}

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

T
Takahiro 已提交
1800
			}
1801

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

T
Takahiro 已提交
1805 1806
				var itemSizeIndices = WEBGL_TYPE_SIZES.SCALAR;
				var TypedArrayIndices = WEBGL_COMPONENT_TYPES[ accessorDef.sparse.indices.componentType ];
1807

T
Takahiro 已提交
1808 1809
				var byteOffsetIndices = accessorDef.sparse.indices.byteOffset || 0;
				var byteOffsetValues = accessorDef.sparse.values.byteOffset || 0;
1810

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

T
Takahiro 已提交
1814 1815 1816
				if ( bufferView !== null ) {

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

T
Takahiro 已提交
1819
				}
1820

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

T
Takahiro 已提交
1823
					var index = sparseIndices[ i ];
1824

T
Takahiro 已提交
1825 1826 1827 1828 1829
					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.' );
1830 1831 1832

				}

T
Takahiro 已提交
1833
			}
1834

T
Takahiro 已提交
1835
			return bufferAttribute;
D
Don McCurdy 已提交
1836 1837 1838 1839 1840

		} );

	};

1841 1842 1843 1844 1845 1846 1847 1848
	/**
	 * 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 已提交
1849 1850
		var json = this.json;
		var options = this.options;
M
Mugen87 已提交
1851
		var textureLoader = this.textureLoader;
D
Don McCurdy 已提交
1852

1853
		var URL = window.URL || window.webkitURL;
D
Don McCurdy 已提交
1854

1855
		var textureDef = json.textures[ textureIndex ];
1856 1857 1858 1859

		var textureExtensions = textureDef.extensions || {};

		var source;
1860

1861 1862 1863 1864 1865 1866 1867 1868 1869 1870
		if ( textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {

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

		} else {

			source = json.images[ textureDef.source ];

		}

1871 1872
		var sourceURI = source.uri;
		var isObjectURL = false;
D
Don McCurdy 已提交
1873

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

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

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

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

T
Takahiro 已提交
1885
			} );
D
Don McCurdy 已提交
1886

1887
		}
D
Don McCurdy 已提交
1888

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

1891
			// Load Texture resource.
D
Don McCurdy 已提交
1892

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

1895
			if ( ! loader ) {
1896

1897 1898 1899
				loader = textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ]
					? parser.extensions[ EXTENSIONS.MSFT_TEXTURE_DDS ].ddsLoader
					: textureLoader;
1900 1901

			}
D
Don McCurdy 已提交
1902

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

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

1907
			} );
D
Don McCurdy 已提交
1908

1909
		} ).then( function ( texture ) {
D
Don McCurdy 已提交
1910

1911
			// Clean up resources and configure Texture.
D
Don McCurdy 已提交
1912

1913
			if ( isObjectURL === true ) {
D
Don McCurdy 已提交
1914

1915
				URL.revokeObjectURL( sourceURI );
D
Don McCurdy 已提交
1916

1917
			}
D
Don McCurdy 已提交
1918

1919
			texture.flipY = false;
D
Don McCurdy 已提交
1920

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

1923 1924 1925 1926 1927 1928 1929
			// Ignore unknown mime types, like DDS files.
			if ( source.mimeType in MIME_TYPE_FORMATS ) {

				texture.format = MIME_TYPE_FORMATS[ source.mimeType ];

			}

1930 1931
			var samplers = json.samplers || {};
			var sampler = samplers[ textureDef.sampler ] || {};
D
Don McCurdy 已提交
1932

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

1938
			return texture;
D
Don McCurdy 已提交
1939

1940
		} );
D
Don McCurdy 已提交
1941

1942
	};
D
Don McCurdy 已提交
1943

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

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

1955 1956
		return this.getDependency( 'texture', mapDef.index ).then( function ( texture ) {

T
Takahiro 已提交
1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969
			if ( ! texture.isCompressedTexture ) {

				switch ( mapName ) {

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

				}
1970 1971 1972

			}

1973 1974
			if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {

D
Don McCurdy 已提交
1975 1976 1977 1978 1979 1980 1981
				var transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;

				if ( transform ) {

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

				}
1982 1983

			}
1984

1985
			materialParams[ mapName ] = texture;
D
Don McCurdy 已提交
1986 1987 1988 1989 1990

		} );

	};

1991 1992 1993 1994 1995 1996 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
	/**
	 * 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;
2024
				pointsMaterial.sizeAttenuation = false; // glTF spec says points should be 1px
2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 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

				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 ) {

			console.log( 'THREE.GLTFLoader: Duplicating UVs to support aoMap.' );
2093
			geometry.setAttribute( 'uv2', new THREE.BufferAttribute( geometry.attributes.uv.array, 2 ) );
2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107

		}

		if ( material.isGLTFSpecularGlossinessMaterial ) {

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

		}

		mesh.material = material;

	};

2108 2109
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#materials
T
Takahiro 已提交
2110 2111
	 * @param {number} materialIndex
	 * @return {Promise<THREE.Material>}
2112
	 */
T
Takahiro 已提交
2113
	GLTFParser.prototype.loadMaterial = function ( materialIndex ) {
D
Don McCurdy 已提交
2114

2115
		var parser = this;
D
Don McCurdy 已提交
2116
		var json = this.json;
2117
		var extensions = this.extensions;
M
Mugen87 已提交
2118
		var materialDef = json.materials[ materialIndex ];
D
Don McCurdy 已提交
2119

T
Takahiro 已提交
2120 2121 2122
		var materialType;
		var materialParams = {};
		var materialExtensions = materialDef.extensions || {};
2123

2124
		var pending = [];
2125

2126
		if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {
2127

T
Takahiro 已提交
2128
			var sgExtension = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ];
T
Takahiro 已提交
2129
			materialType = sgExtension.getMaterialType();
2130
			pending.push( sgExtension.extendParams( materialParams, materialDef, parser ) );
2131

2132 2133 2134
		} else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_UNLIT ] ) {

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

2138
		} else {
2139

T
Takahiro 已提交
2140 2141
			// Specification:
			// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
2142

T
Takahiro 已提交
2143
			materialType = THREE.MeshStandardMaterial;
2144

2145
			var metallicRoughness = materialDef.pbrMetallicRoughness || {};
2146

T
Takahiro 已提交
2147 2148
			materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
			materialParams.opacity = 1.0;
2149

T
Takahiro 已提交
2150
			if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
2151

T
Takahiro 已提交
2152
				var array = metallicRoughness.baseColorFactor;
2153

T
Takahiro 已提交
2154 2155
				materialParams.color.fromArray( array );
				materialParams.opacity = array[ 3 ];
2156

T
Takahiro 已提交
2157
			}
2158

T
Takahiro 已提交
2159
			if ( metallicRoughness.baseColorTexture !== undefined ) {
2160

2161
				pending.push( parser.assignTexture( materialParams, 'map', metallicRoughness.baseColorTexture ) );
2162

T
Takahiro 已提交
2163
			}
2164

T
Takahiro 已提交
2165 2166
			materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
			materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
2167

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

2170 2171
				pending.push( parser.assignTexture( materialParams, 'metalnessMap', metallicRoughness.metallicRoughnessTexture ) );
				pending.push( parser.assignTexture( materialParams, 'roughnessMap', metallicRoughness.metallicRoughnessTexture ) );
D
Don McCurdy 已提交
2172

2173
			}
D
Don McCurdy 已提交
2174

T
Takahiro 已提交
2175
		}
2176

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

T
Takahiro 已提交
2179
			materialParams.side = THREE.DoubleSide;
D
Don McCurdy 已提交
2180

T
Takahiro 已提交
2181
		}
D
Don McCurdy 已提交
2182

T
Takahiro 已提交
2183
		var alphaMode = materialDef.alphaMode || ALPHA_MODES.OPAQUE;
2184

2185
		if ( alphaMode === ALPHA_MODES.BLEND ) {
2186

T
Takahiro 已提交
2187
			materialParams.transparent = true;
2188

2189 2190 2191 2192
		} else {

			materialParams.transparent = false;

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

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

2197
			}
D
Don McCurdy 已提交
2198

T
Takahiro 已提交
2199
		}
2200

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

2203
			pending.push( parser.assignTexture( materialParams, 'normalMap', materialDef.normalTexture ) );
2204

T
Takahiro 已提交
2205 2206 2207 2208 2209
			materialParams.normalScale = new THREE.Vector2( 1, 1 );

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

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

2211
			}
D
Don McCurdy 已提交
2212

T
Takahiro 已提交
2213
		}
D
Don McCurdy 已提交
2214

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

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

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

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

2223
			}
D
Don McCurdy 已提交
2224

T
Takahiro 已提交
2225
		}
D
Don McCurdy 已提交
2226

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

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

T
Takahiro 已提交
2231
		}
D
Don McCurdy 已提交
2232

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

2235
			pending.push( parser.assignTexture( materialParams, 'emissiveMap', materialDef.emissiveTexture ) );
2236

T
Takahiro 已提交
2237
		}
2238

2239
		return Promise.all( pending ).then( function () {
2240

T
Takahiro 已提交
2241
			var material;
2242

T
Takahiro 已提交
2243
			if ( materialType === THREE.ShaderMaterial ) {
2244

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

T
Takahiro 已提交
2247
			} else {
2248

T
Takahiro 已提交
2249
				material = new materialType( materialParams );
2250

T
Takahiro 已提交
2251
			}
D
Don McCurdy 已提交
2252

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

2255
			// baseColorTexture, emissiveTexture, and specularGlossinessTexture use sRGB encoding.
T
Takahiro 已提交
2256 2257
			if ( material.map ) material.map.encoding = THREE.sRGBEncoding;
			if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
2258
			if ( material.specularMap ) material.specularMap.encoding = THREE.sRGBEncoding;
2259

2260
			assignExtrasToUserData( material, materialDef );
D
Don McCurdy 已提交
2261

2262
			if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );
2263

T
Takahiro 已提交
2264
			return material;
D
Don McCurdy 已提交
2265 2266 2267 2268 2269

		} );

	};

2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287
	/**
	 * @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 ];
			var min = accessor.min;
			var max = accessor.max;

			box.set(
W
WestLangley 已提交
2288 2289
				new THREE.Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
				new THREE.Vector3( max[ 0 ], max[ 1 ], max[ 2 ] ) );
2290 2291 2292 2293

		} else {

			return;
W
WestLangley 已提交
2294

2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313
		}

		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;

					// we need to get max of absolute components because target weight is [-1,1]
W
WestLangley 已提交
2314 2315 2316
					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 ] ) ) );
2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336

					box.expandByVector( vector );

				}

			}

		}

		geometry.boundingBox = box;

		var sphere = new THREE.Sphere();

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

		geometry.boundingSphere = sphere;

	}

2337
	/**
T
Takahiro 已提交
2338 2339 2340 2341
	 * @param {THREE.BufferGeometry} geometry
	 * @param {GLTF.Primitive} primitiveDef
	 * @param {GLTFParser} parser
	 * @return {Promise<THREE.BufferGeometry>}
2342
	 */
T
Takahiro 已提交
2343
	function addPrimitiveAttributes( geometry, primitiveDef, parser ) {
2344 2345 2346

		var attributes = primitiveDef.attributes;

2347
		var pending = [];
T
Takahiro 已提交
2348

2349
		function assignAttributeAccessor( accessorIndex, attributeName ) {
T
Takahiro 已提交
2350 2351 2352 2353

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

2354
					geometry.setAttribute( attributeName, accessor );
T
Takahiro 已提交
2355 2356 2357 2358 2359

				} );

		}

2360
		for ( var gltfAttributeName in attributes ) {
2361

S
Sneha Belkhale 已提交
2362
			var threeAttributeName = ATTRIBUTES[ gltfAttributeName ] || gltfAttributeName.toLowerCase();
T
Takahiro 已提交
2363 2364

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

2367
			pending.push( assignAttributeAccessor( attributes[ gltfAttributeName ], threeAttributeName ) );
2368 2369 2370

		}

2371
		if ( primitiveDef.indices !== undefined && ! geometry.index ) {
2372

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

T
Takahiro 已提交
2375
				geometry.setIndex( accessor );
2376

T
Takahiro 已提交
2377 2378 2379
			} );

			pending.push( accessor );
2380 2381 2382

		}

2383
		assignExtrasToUserData( geometry, primitiveDef );
2384

2385 2386
		computeBounds( geometry, primitiveDef, parser );

2387
		return Promise.all( pending ).then( function () {
T
Takahiro 已提交
2388 2389 2390 2391 2392 2393 2394

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

		} );

2395 2396
	}

T
Takahiro 已提交
2397 2398
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry
T
Takahiro 已提交
2399 2400 2401
	 *
	 * Creates BufferGeometries from primitives.
	 *
T
Takahiro 已提交
2402
	 * @param {Array<GLTF.Primitive>} primitives
T
Takahiro 已提交
2403 2404
	 * @return {Promise<Array<THREE.BufferGeometry>>}
	 */
D
Don McCurdy 已提交
2405
	GLTFParser.prototype.loadGeometries = function ( primitives ) {
D
Don McCurdy 已提交
2406

2407 2408
		var parser = this;
		var extensions = this.extensions;
2409 2410
		var cache = this.primitiveCache;

2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422
		function createDracoPrimitive( primitive ) {

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

					return addPrimitiveAttributes( geometry, primitive, parser );

				} );

		}

2423
		var pending = [];
D
Don McCurdy 已提交
2424

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

T
Takahiro 已提交
2427
			var primitive = primitives[ i ];
R
Riccardo Padovani 已提交
2428
			var cacheKey = createPrimitiveKey( primitive );
D
Don McCurdy 已提交
2429

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

T
Takahiro 已提交
2433
			if ( cached ) {
2434

T
Takahiro 已提交
2435
				// Use the cached geometry if it exists
2436
				pending.push( cached.promise );
T
Takahiro 已提交
2437 2438

			} else {
D
Don McCurdy 已提交
2439

T
Takahiro 已提交
2440
				var geometryPromise;
2441

T
Takahiro 已提交
2442
				if ( primitive.extensions && primitive.extensions[ EXTENSIONS.KHR_DRACO_MESH_COMPRESSION ] ) {
2443 2444

					// Use DRACO geometry if available
2445
					geometryPromise = createDracoPrimitive( primitive );
2446

T
Takahiro 已提交
2447
				} else {
2448

2449
					// Otherwise create a new geometry
T
Takahiro 已提交
2450 2451 2452
					geometryPromise = addPrimitiveAttributes( new THREE.BufferGeometry(), primitive, parser );

				}
D
Don McCurdy 已提交
2453

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

2457
				pending.push( geometryPromise );
T
Takahiro 已提交
2458

T
Takahiro 已提交
2459
			}
2460

T
Takahiro 已提交
2461
		}
D
Don McCurdy 已提交
2462

2463
		return Promise.all( pending );
2464

D
Don McCurdy 已提交
2465
	};
D
Don McCurdy 已提交
2466

D
Don McCurdy 已提交
2467 2468
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#meshes
T
Takahiro 已提交
2469
	 * @param {number} meshIndex
D
Daniel Hritzkiv 已提交
2470
	 * @return {Promise<THREE.Group|THREE.Mesh|THREE.SkinnedMesh>}
D
Don McCurdy 已提交
2471
	 */
T
Takahiro 已提交
2472
	GLTFParser.prototype.loadMesh = function ( meshIndex ) {
D
Don McCurdy 已提交
2473

T
Takahiro 已提交
2474
		var parser = this;
D
Don McCurdy 已提交
2475
		var json = this.json;
D
Don McCurdy 已提交
2476

M
Mugen87 已提交
2477
		var meshDef = json.meshes[ meshIndex ];
T
Takahiro 已提交
2478
		var primitives = meshDef.primitives;
D
Don McCurdy 已提交
2479

2480
		var pending = [];
T
Takahiro 已提交
2481

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

T
Takahiro 已提交
2484 2485 2486 2487 2488
			var material = primitives[ i ].material === undefined
				? createDefaultMaterial()
				: this.getDependency( 'material', primitives[ i ].material );

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

T
Takahiro 已提交
2490 2491
		}

2492
		return Promise.all( pending ).then( function ( originalMaterials ) {
D
Don McCurdy 已提交
2493

T
Takahiro 已提交
2494
			return parser.loadGeometries( primitives ).then( function ( geometries ) {
D
Don McCurdy 已提交
2495

T
Takahiro 已提交
2496
				var meshes = [];
D
Don McCurdy 已提交
2497

T
Takahiro 已提交
2498
				for ( var i = 0, il = geometries.length; i < il; i ++ ) {
D
Don McCurdy 已提交
2499

T
Takahiro 已提交
2500
					var geometry = geometries[ i ];
T
Takahiro 已提交
2501
					var primitive = primitives[ i ];
2502

T
Takahiro 已提交
2503
					// 1. create Mesh
2504

T
Takahiro 已提交
2505
					var mesh;
2506

2507
					var material = originalMaterials[ i ];
2508

T
Takahiro 已提交
2509 2510 2511 2512
					if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES ||
						primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ||
						primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ||
						primitive.mode === undefined ) {
2513

T
Takahiro 已提交
2514 2515 2516 2517
						// .isSkinnedMesh isn't in glTF spec. See .markDefs()
						mesh = meshDef.isSkinnedMesh === true
							? new THREE.SkinnedMesh( geometry, material )
							: new THREE.Mesh( geometry, material );
2518

M
Mugen87 已提交
2519
						if ( mesh.isSkinnedMesh === true && ! mesh.geometry.attributes.skinWeight.normalized ) {
2520 2521 2522 2523 2524 2525

							// 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 已提交
2526

M
Mugen87 已提交
2527
						if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP || primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
2528

M
Mugen87 已提交
2529
							console.warn( 'THREE.GLTFLoader: The draw modes triangle strip and fan are not supported anymore.' );
2530 2531 2532

						}

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

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

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

T
Takahiro 已提交
2539
						mesh = new THREE.Line( geometry, material );
T
Takahiro 已提交
2540

T
Takahiro 已提交
2541
					} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
2542

T
Takahiro 已提交
2543
						mesh = new THREE.LineLoop( geometry, material );
2544

T
Takahiro 已提交
2545
					} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
D
Don McCurdy 已提交
2546

T
Takahiro 已提交
2547
						mesh = new THREE.Points( geometry, material );
D
Don McCurdy 已提交
2548

T
Takahiro 已提交
2549
					} else {
D
Don McCurdy 已提交
2550

T
Takahiro 已提交
2551
						throw new Error( 'THREE.GLTFLoader: Primitive mode unsupported: ' + primitive.mode );
D
Don McCurdy 已提交
2552

T
Takahiro 已提交
2553
					}
2554

2555
					if ( Object.keys( mesh.geometry.morphAttributes ).length > 0 ) {
2556

2557
						updateMorphTargets( mesh, meshDef );
2558

T
Takahiro 已提交
2559
					}
T
Takahiro 已提交
2560

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

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

2565
					assignExtrasToUserData( mesh, meshDef );
T
Takahiro 已提交
2566

2567
					parser.assignFinalMaterial( mesh );
T
Takahiro 已提交
2568

2569
					meshes.push( mesh );
2570

T
Takahiro 已提交
2571
				}
T
Takahiro 已提交
2572

T
Takahiro 已提交
2573
				if ( meshes.length === 1 ) {
T
Takahiro 已提交
2574

T
Takahiro 已提交
2575
					return meshes[ 0 ];
D
Don McCurdy 已提交
2576

T
Takahiro 已提交
2577 2578
				}

T
Takahiro 已提交
2579
				var group = new THREE.Group();
D
Don McCurdy 已提交
2580

T
Takahiro 已提交
2581
				for ( var i = 0, il = meshes.length; i < il; i ++ ) {
T
Takahiro 已提交
2582

T
Takahiro 已提交
2583
					group.add( meshes[ i ] );
D
Don McCurdy 已提交
2584

T
Takahiro 已提交
2585
				}
D
Don McCurdy 已提交
2586

T
Takahiro 已提交
2587
				return group;
D
Don McCurdy 已提交
2588 2589 2590 2591 2592 2593 2594

			} );

		} );

	};

2595 2596
	/**
	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#cameras
D
Don McCurdy 已提交
2597 2598
	 * @param {number} cameraIndex
	 * @return {Promise<THREE.Camera>}
2599
	 */
D
Don McCurdy 已提交
2600
	GLTFParser.prototype.loadCamera = function ( cameraIndex ) {
D
Don McCurdy 已提交
2601

D
Don McCurdy 已提交
2602 2603 2604
		var camera;
		var cameraDef = this.json.cameras[ cameraIndex ];
		var params = cameraDef[ cameraDef.type ];
D
Don McCurdy 已提交
2605

D
Don McCurdy 已提交
2606
		if ( ! params ) {
D
Don McCurdy 已提交
2607

D
Don McCurdy 已提交
2608 2609
			console.warn( 'THREE.GLTFLoader: Missing camera parameters.' );
			return;
D
Don McCurdy 已提交
2610

D
Don McCurdy 已提交
2611
		}
D
Don McCurdy 已提交
2612

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

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

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

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

D
Don McCurdy 已提交
2621
		}
2622

D
Don McCurdy 已提交
2623
		if ( cameraDef.name !== undefined ) camera.name = cameraDef.name;
2624 2625

		assignExtrasToUserData( camera, cameraDef );
2626

D
Don McCurdy 已提交
2627
		return Promise.resolve( camera );
D
Don McCurdy 已提交
2628 2629 2630

	};

T
Takahiro 已提交
2631 2632 2633 2634 2635 2636
	/**
	 * 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 已提交
2637

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

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

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

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

T
Takahiro 已提交
2646
		}
D
Don McCurdy 已提交
2647

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

T
Takahiro 已提交
2650
			skinEntry.inverseBindMatrices = accessor;
D
Don McCurdy 已提交
2651

T
Takahiro 已提交
2652
			return skinEntry;
D
Don McCurdy 已提交
2653 2654 2655 2656 2657

		} );

	};

T
Takahiro 已提交
2658 2659 2660 2661 2662 2663
	/**
	 * 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 已提交
2664 2665 2666

		var json = this.json;

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

2669 2670 2671 2672 2673
		var pendingNodes = [];
		var pendingInputAccessors = [];
		var pendingOutputAccessors = [];
		var pendingSamplers = [];
		var pendingTargets = [];
D
Don McCurdy 已提交
2674

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

T
Takahiro 已提交
2677 2678 2679 2680 2681 2682
			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 已提交
2683

2684 2685 2686 2687 2688
			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 已提交
2689

T
Takahiro 已提交
2690
		}
D
Don McCurdy 已提交
2691

T
Takahiro 已提交
2692
		return Promise.all( [
D
Don McCurdy 已提交
2693

2694 2695 2696 2697 2698
			Promise.all( pendingNodes ),
			Promise.all( pendingInputAccessors ),
			Promise.all( pendingOutputAccessors ),
			Promise.all( pendingSamplers ),
			Promise.all( pendingTargets )
D
Don McCurdy 已提交
2699

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

T
Takahiro 已提交
2702 2703 2704 2705 2706
			var nodes = dependencies[ 0 ];
			var inputAccessors = dependencies[ 1 ];
			var outputAccessors = dependencies[ 2 ];
			var samplers = dependencies[ 3 ];
			var targets = dependencies[ 4 ];
D
Don McCurdy 已提交
2707

T
Takahiro 已提交
2708
			var tracks = [];
T
Takahiro 已提交
2709

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

T
Takahiro 已提交
2712 2713 2714 2715 2716
				var node = nodes[ i ];
				var inputAccessor = inputAccessors[ i ];
				var outputAccessor = outputAccessors[ i ];
				var sampler = samplers[ i ];
				var target = targets[ i ];
T
Takahiro 已提交
2717

T
Takahiro 已提交
2718
				if ( node === undefined ) continue;
T
Takahiro 已提交
2719

T
Takahiro 已提交
2720 2721
				node.updateMatrix();
				node.matrixAutoUpdate = true;
T
Takahiro 已提交
2722

T
Takahiro 已提交
2723
				var TypedKeyframeTrack;
T
Takahiro 已提交
2724

T
Takahiro 已提交
2725
				switch ( PATH_PROPERTIES[ target.path ] ) {
T
Takahiro 已提交
2726

T
Takahiro 已提交
2727
					case PATH_PROPERTIES.weights:
T
Takahiro 已提交
2728

T
Takahiro 已提交
2729 2730
						TypedKeyframeTrack = THREE.NumberKeyframeTrack;
						break;
D
Don McCurdy 已提交
2731

T
Takahiro 已提交
2732
					case PATH_PROPERTIES.rotation:
2733

T
Takahiro 已提交
2734 2735
						TypedKeyframeTrack = THREE.QuaternionKeyframeTrack;
						break;
2736

T
Takahiro 已提交
2737 2738 2739
					case PATH_PROPERTIES.position:
					case PATH_PROPERTIES.scale:
					default:
T
Takahiro 已提交
2740

T
Takahiro 已提交
2741 2742
						TypedKeyframeTrack = THREE.VectorKeyframeTrack;
						break;
T
Takahiro 已提交
2743

T
Takahiro 已提交
2744
				}
T
Takahiro 已提交
2745

T
Takahiro 已提交
2746
				var targetName = node.name ? node.name : node.uuid;
T
Takahiro 已提交
2747

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

T
Takahiro 已提交
2750
				var targetNames = [];
T
Takahiro 已提交
2751

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

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

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

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

T
Takahiro 已提交
2761
						}
T
Takahiro 已提交
2762

T
Takahiro 已提交
2763
					} );
T
Takahiro 已提交
2764

T
Takahiro 已提交
2765
				} else {
2766

T
Takahiro 已提交
2767
					targetNames.push( targetName );
2768

T
Takahiro 已提交
2769
				}
2770

2771 2772 2773 2774
				var outputArray = outputAccessor.array;

				if ( outputAccessor.normalized ) {

2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797
					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.' );

					}
2798 2799 2800 2801 2802

					var scaled = new Float32Array( outputArray.length );

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

M
Mugen87 已提交
2803
						scaled[ j ] = outputArray[ j ] * scale;
2804 2805 2806 2807 2808 2809 2810

					}

					outputArray = scaled;

				}

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

T
Takahiro 已提交
2813 2814
					var track = new TypedKeyframeTrack(
						targetNames[ j ] + '.' + PATH_PROPERTIES[ target.path ],
2815
						inputAccessor.array,
2816
						outputArray,
T
Takahiro 已提交
2817 2818
						interpolation
					);
2819

2820
					// Override interpolation with custom factory method.
T
Takahiro 已提交
2821
					if ( sampler.interpolation === 'CUBICSPLINE' ) {
2822

T
Takahiro 已提交
2823
						track.createInterpolant = function InterpolantFactoryMethodGLTFCubicSpline( result ) {
2824

T
Takahiro 已提交
2825 2826 2827
							// 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.
2828

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

T
Takahiro 已提交
2831 2832
						};

2833
						// Mark as CUBICSPLINE. `track.getInterpolation()` doesn't support custom interpolants.
T
Takahiro 已提交
2834
						track.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline = true;
D
Don McCurdy 已提交
2835 2836 2837

					}

T
Takahiro 已提交
2838 2839
					tracks.push( track );

D
Don McCurdy 已提交
2840 2841
				}

T
Takahiro 已提交
2842
			}
D
Don McCurdy 已提交
2843

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

T
Takahiro 已提交
2846
			return new THREE.AnimationClip( name, undefined, tracks );
D
Don McCurdy 已提交
2847 2848 2849 2850 2851

		} );

	};

T
Takahiro 已提交
2852 2853 2854 2855 2856 2857
	/**
	 * 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 已提交
2858 2859 2860

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

M
Mugen87 已提交
2863 2864
		var meshReferences = json.meshReferences;
		var meshUses = json.meshUses;
D
Don McCurdy 已提交
2865

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

M
Mugen87 已提交
2868
		return ( function () {
2869

V
vyv03354 已提交
2870
			var pending = [];
2871

V
vyv03354 已提交
2872
			if ( nodeDef.mesh !== undefined ) {
2873

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

T
Takahiro 已提交
2876
					var node;
D
Don McCurdy 已提交
2877

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

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

T
Takahiro 已提交
2882 2883
						node = mesh.clone();
						node.name += '_instance_' + instanceNum;
D
Don McCurdy 已提交
2884

T
Takahiro 已提交
2885 2886
						// onBeforeRender copy for Specular-Glossiness
						node.onBeforeRender = mesh.onBeforeRender;
D
Don McCurdy 已提交
2887

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

T
Takahiro 已提交
2890 2891
							node.children[ i ].name += '_instance_' + instanceNum;
							node.children[ i ].onBeforeRender = mesh.children[ i ].onBeforeRender;
D
Don McCurdy 已提交
2892

T
Takahiro 已提交
2893 2894 2895
						}

					} else {
2896

T
Takahiro 已提交
2897
						node = mesh;
D
Don McCurdy 已提交
2898

T
Takahiro 已提交
2899 2900
					}

2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917
					// 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 ];

							}

						} );

					}

2918
					return node;
T
Takahiro 已提交
2919

V
vyv03354 已提交
2920 2921 2922 2923 2924
				} ) );

			}

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

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

V
vyv03354 已提交
2928
			}
D
Don McCurdy 已提交
2929

V
vyv03354 已提交
2930
			if ( nodeDef.extensions
T
Takahiro 已提交
2931 2932
				&& nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ]
				&& nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light !== undefined ) {
D
Don McCurdy 已提交
2933

V
vyv03354 已提交
2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954
				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 已提交
2955
				node = objects[ 0 ];
D
Don McCurdy 已提交
2956

T
Takahiro 已提交
2957
			} else {
2958

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

T
Takahiro 已提交
2961
			}
D
Don McCurdy 已提交
2962

V
vyv03354 已提交
2963
			if ( node !== objects[ 0 ] ) {
V
vyv03354 已提交
2964 2965 2966

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

V
vyv03354 已提交
2967
					node.add( objects[ i ] );
V
vyv03354 已提交
2968 2969 2970 2971

				}

			}
T
Takahiro 已提交
2972

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

2975
				node.userData.name = nodeDef.name;
T
Takahiro 已提交
2976
				node.name = THREE.PropertyBinding.sanitizeNodeName( nodeDef.name );
D
Don McCurdy 已提交
2977

T
Takahiro 已提交
2978
			}
D
Don McCurdy 已提交
2979

2980
			assignExtrasToUserData( node, nodeDef );
D
Don McCurdy 已提交
2981

2982
			if ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );
2983

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

T
Takahiro 已提交
2986 2987 2988
				var matrix = new THREE.Matrix4();
				matrix.fromArray( nodeDef.matrix );
				node.applyMatrix( matrix );
D
Don McCurdy 已提交
2989

T
Takahiro 已提交
2990
			} else {
D
Don McCurdy 已提交
2991

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

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

T
Takahiro 已提交
2996
				}
2997

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

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

T
Takahiro 已提交
3002
				}
D
Don McCurdy 已提交
3003

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

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

T
Takahiro 已提交
3008
				}
D
Don McCurdy 已提交
3009

T
Takahiro 已提交
3010
			}
D
Don McCurdy 已提交
3011

T
Takahiro 已提交
3012
			return node;
D
Don McCurdy 已提交
3013

T
Takahiro 已提交
3014
		} );
D
Don McCurdy 已提交
3015

T
Takahiro 已提交
3016
	};
3017

T
Takahiro 已提交
3018 3019 3020 3021 3022 3023
	/**
	 * 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 已提交
3024

T
Takahiro 已提交
3025
		// scene node hierachy builder
D
Don McCurdy 已提交
3026

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

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

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

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

T
Takahiro 已提交
3035
				// build skeleton here as well
D
Don McCurdy 已提交
3036

T
Takahiro 已提交
3037
				var skinEntry;
D
Don McCurdy 已提交
3038

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

T
Takahiro 已提交
3041
					skinEntry = skin;
D
Don McCurdy 已提交
3042

3043
					var pendingJoints = [];
D
Don McCurdy 已提交
3044

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

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

T
Takahiro 已提交
3049
					}
T
Takahiro 已提交
3050

3051
					return Promise.all( pendingJoints );
T
Takahiro 已提交
3052

T
Takahiro 已提交
3053
				} ).then( function ( jointNodes ) {
3054

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

V
vyv03354 已提交
3057
						if ( ! mesh.isMesh ) return;
T
Takahiro 已提交
3058 3059 3060 3061 3062

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

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

T
Takahiro 已提交
3064
							var jointNode = jointNodes[ j ];
3065

T
Takahiro 已提交
3066
							if ( jointNode ) {
3067

T
Takahiro 已提交
3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084
								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 ] );

							}
3085 3086

						}
D
Don McCurdy 已提交
3087

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

V
vyv03354 已提交
3090
					} );
D
Don McCurdy 已提交
3091

T
Takahiro 已提交
3092
					return node;
D
Don McCurdy 已提交
3093

T
Takahiro 已提交
3094 3095 3096
				} );

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

T
Takahiro 已提交
3098
				// build node hierachy
D
Don McCurdy 已提交
3099

T
Takahiro 已提交
3100
				parentObject.add( node );
D
Don McCurdy 已提交
3101

3102
				var pending = [];
D
Don McCurdy 已提交
3103

T
Takahiro 已提交
3104
				if ( nodeDef.children ) {
D
Don McCurdy 已提交
3105

T
Takahiro 已提交
3106
					var children = nodeDef.children;
D
Don McCurdy 已提交
3107

T
Takahiro 已提交
3108 3109 3110
					for ( var i = 0, il = children.length; i < il; i ++ ) {

						var child = children[ i ];
3111
						pending.push( buildNodeHierachy( child, node, json, parser ) );
T
Takahiro 已提交
3112 3113

					}
D
Don McCurdy 已提交
3114 3115 3116

				}

3117
				return Promise.all( pending );
T
Takahiro 已提交
3118 3119

			} );
D
Don McCurdy 已提交
3120 3121 3122

		}

T
Takahiro 已提交
3123
		return function loadScene( sceneIndex ) {
D
Don McCurdy 已提交
3124

T
Takahiro 已提交
3125 3126 3127
			var json = this.json;
			var extensions = this.extensions;
			var sceneDef = this.json.scenes[ sceneIndex ];
T
Takahiro 已提交
3128
			var parser = this;
D
Don McCurdy 已提交
3129

T
Takahiro 已提交
3130 3131
			var scene = new THREE.Scene();
			if ( sceneDef.name !== undefined ) scene.name = sceneDef.name;
D
Don McCurdy 已提交
3132

T
Takahiro 已提交
3133
			assignExtrasToUserData( scene, sceneDef );
D
Don McCurdy 已提交
3134

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

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

3139
			var pending = [];
3140

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

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

T
Takahiro 已提交
3145
			}
D
Don McCurdy 已提交
3146

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

T
Takahiro 已提交
3149
				return scene;
D
Don McCurdy 已提交
3150 3151 3152

			} );

T
Takahiro 已提交
3153
		};
D
Don McCurdy 已提交
3154

T
Takahiro 已提交
3155
	}();
D
Don McCurdy 已提交
3156

3157
	return GLTFLoader;
D
Don McCurdy 已提交
3158 3159

} )();