Browse Source

Merge pull request #10536 from takahirox/UpdateGLTFLoader

Update gltf loader
Mr.doob 8 years ago
parent
commit
6db8a5dd4e
1 changed files with 243 additions and 39 deletions
  1. 243 39
      examples/js/loaders/GLTFLoader.js

+ 243 - 39
examples/js/loaders/GLTFLoader.js

@@ -2,6 +2,7 @@
  * @author Rich Tibbett / https://github.com/richtr
  * @author Rich Tibbett / https://github.com/richtr
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  * @author Tony Parisi / http://www.tonyparisi.com/
  * @author Tony Parisi / http://www.tonyparisi.com/
+ * @author Takahiro / https://github.com/takahirox
  */
  */
 
 
 THREE.GLTFLoader = ( function () {
 THREE.GLTFLoader = ( function () {
@@ -315,6 +316,48 @@ THREE.GLTFLoader = ( function () {
 		10497: THREE.RepeatWrapping
 		10497: THREE.RepeatWrapping
 	};
 	};
 
 
+	var WEBGL_SIDES = {
+		1028: THREE.BackSide,  // Culling front
+		1029: THREE.FrontSide  // Culling back
+		//1032: THREE.NoSide   // Culling front and back, what to do?
+	};
+
+	var WEBGL_DEPTH_FUNCS = {
+		512: THREE.NeverDepth,
+		513: THREE.LessDepth,
+		514: THREE.EqualDepth,
+		515: THREE.LessEqualDepth,
+		516: THREE.GreaterEqualDepth,
+		517: THREE.NotEqualDepth,
+		518: THREE.GreaterEqualDepth,
+		519: THREE.AlwaysDepth
+	};
+
+	var WEBGL_BLEND_EQUATIONS = {
+		32774: THREE.AddEquation,
+		32778: THREE.SubtractEquation,
+		32779: THREE.ReverseSubtractEquation
+	};
+
+	var WEBGL_BLEND_FUNCS = {
+		0: THREE.ZeroFactor,
+		1: THREE.OneFactor,
+		768: THREE.SrcColorFactor,
+		769: THREE.OneMinusSrcColorFactor,
+		770: THREE.SrcAlphaFactor,
+		771: THREE.OneMinusSrcAlphaFactor,
+		772: THREE.DstAlphaFactor,
+		773: THREE.OneMinusDstAlphaFactor,
+		774: THREE.DstColorFactor,
+		775: THREE.OneMinusDstColorFactor,
+		776: THREE.SrcAlphaSaturateFactor
+		// The followings are not supported by Three.js yet
+		//32769: CONSTANT_COLOR,
+		//32770: ONE_MINUS_CONSTANT_COLOR,
+		//32771: CONSTANT_ALPHA,
+		//32772: ONE_MINUS_CONSTANT_COLOR
+	};
+
 	var WEBGL_TYPE_SIZES = {
 	var WEBGL_TYPE_SIZES = {
 		'SCALAR': 1,
 		'SCALAR': 1,
 		'VEC2': 2,
 		'VEC2': 2,
@@ -336,6 +379,15 @@ THREE.GLTFLoader = ( function () {
 		STEP: THREE.InterpolateDiscrete
 		STEP: THREE.InterpolateDiscrete
 	};
 	};
 
 
+	var STATES_ENABLES = {
+		2884: 'CULL_FACE',
+		2929: 'DEPTH_TEST',
+		3042: 'BLEND',
+		3089: 'SCISSOR_TEST',
+		32823: 'POLYGON_OFFSET_FILL',
+		32926: 'SAMPLE_ALPHA_TO_COVERAGE'
+	};
+
 	/* UTILITY FUNCTIONS */
 	/* UTILITY FUNCTIONS */
 
 
 	function _each( object, callback, thisObj ) {
 	function _each( object, callback, thisObj ) {
@@ -504,6 +556,20 @@ THREE.GLTFLoader = ( function () {
 
 
 	}
 	}
 
 
+	function createDefaultMaterial() {
+
+		return new THREE.MeshPhongMaterial( {
+			color: 0x00000,
+			emissive: 0x888888,
+			specular: 0x000000,
+			shininess: 0,
+			transparent: false,
+			depthTest: true,
+			side: THREE.FrontSide
+		} );
+
+	};
+
 	// Deferred constructor for RawShaderMaterial types
 	// Deferred constructor for RawShaderMaterial types
 	function DeferredShaderMaterial( params ) {
 	function DeferredShaderMaterial( params ) {
 
 
@@ -644,7 +710,7 @@ THREE.GLTFLoader = ( function () {
 			return new Promise( function ( resolve ) {
 			return new Promise( function ( resolve ) {
 
 
 				var loader = new THREE.FileLoader();
 				var loader = new THREE.FileLoader();
-				loader.responseType = 'text';
+				loader.setResponseType( 'text' );
 				loader.load( resolveURL( shader.uri, options.path ), function ( shaderText ) {
 				loader.load( resolveURL( shader.uri, options.path ), function ( shaderText ) {
 
 
 					resolve( shaderText );
 					resolve( shaderText );
@@ -664,12 +730,12 @@ THREE.GLTFLoader = ( function () {
 
 
 		return _each( json.buffers, function ( buffer ) {
 		return _each( json.buffers, function ( buffer ) {
 
 
-			if ( buffer.type === 'arraybuffer' ) {
+			if ( buffer.type === 'arraybuffer' || buffer.type === undefined ) {
 
 
 				return new Promise( function ( resolve ) {
 				return new Promise( function ( resolve ) {
 
 
 					var loader = new THREE.FileLoader();
 					var loader = new THREE.FileLoader();
-					loader.responseType = 'arraybuffer';
+					loader.setResponseType( 'arraybuffer' );
 					loader.load( resolveURL( buffer.uri, options.path ), function ( buffer ) {
 					loader.load( resolveURL( buffer.uri, options.path ), function ( buffer ) {
 
 
 						resolve( buffer );
 						resolve( buffer );
@@ -678,6 +744,10 @@ THREE.GLTFLoader = ( function () {
 
 
 				} );
 				} );
 
 
+			} else {
+
+				console.warn( 'THREE.GLTFLoader: ' + buffer.type + ' buffer type is not supported' );
+
 			}
 			}
 
 
 		} );
 		} );
@@ -920,7 +990,9 @@ THREE.GLTFLoader = ( function () {
 							if ( WEBGL_TYPE[ ptype ] ) {
 							if ( WEBGL_TYPE[ ptype ] ) {
 
 
 								var pcount = shaderParam.count;
 								var pcount = shaderParam.count;
-								var value = material.values[ pname ];
+								var value;
+
+								if ( material.values !== undefined ) value = material.values[ pname ];
 
 
 								var uvalue = new WEBGL_TYPE[ ptype ]();
 								var uvalue = new WEBGL_TYPE[ ptype ]();
 								var usemantic = shaderParam.semantic;
 								var usemantic = shaderParam.semantic;
@@ -996,7 +1068,7 @@ THREE.GLTFLoader = ( function () {
 
 
 											}
 											}
 
 
-										}	else {
+										} else {
 
 
 											if ( shaderParam && shaderParam.value ) {
 											if ( shaderParam && shaderParam.value ) {
 
 
@@ -1017,7 +1089,19 @@ THREE.GLTFLoader = ( function () {
 
 
 									case WEBGL_CONSTANTS.SAMPLER_2D:
 									case WEBGL_CONSTANTS.SAMPLER_2D:
 
 
-										uvalue = value ? dependencies.textures[ value ] : null;
+										if ( value !== undefined ) {
+
+											uvalue = dependencies.textures[ value ];
+
+										} else if ( shaderParam.value !== undefined ) {
+
+											uvalue = dependencies.textures[ shaderParam.value ];
+
+										} else {
+
+											uvalue = null;
+
+										}
 
 
 										break;
 										break;
 
 
@@ -1037,6 +1121,102 @@ THREE.GLTFLoader = ( function () {
 
 
 						}
 						}
 
 
+						var states = technique.states || {};
+						var enables = states.enable || [];
+						var functions = states.functions || {};
+
+						var enableCullFace = false;
+						var enableDepthTest = false;
+						var enableBlend = false;
+
+						for ( var i = 0, il = enables.length; i < il; i ++ ) {
+
+							var enable = enables[ i ];
+
+							switch( STATES_ENABLES[ enable ] ) {
+
+								case 'CULL_FACE':
+
+									enableCullFace = true;
+
+									break;
+
+								case 'DEPTH_TEST':
+
+									enableDepthTest = true;
+
+									break;
+
+								case 'BLEND':
+
+									enableBlend = true;
+
+									break;
+
+								// TODO: implement
+								case 'SCISSOR_TEST':
+								case 'POLYGON_OFFSET_FILL':
+								case 'SAMPLE_ALPHA_TO_COVERAGE':
+
+									break;
+
+								default:
+
+									throw new Error( "Unknown technique.states.enable: " + enable );
+
+							}
+
+						}
+
+						if ( enableCullFace ) {
+
+							materialParams.side = functions.cullFace !== undefined ? WEBGL_SIDES[ functions.cullFace ] : THREE.FrontSide;
+
+						} else {
+
+							materialParams.side = THREE.DoubleSide;
+
+						}
+
+						materialParams.depthTest = enableDepthTest;
+						materialParams.depthFunc = functions.depthFunc !== undefined ? WEBGL_DEPTH_FUNCS[ functions.depthFunc ] : THREE.LessDepth;
+						materialParams.depthWrite = functions.depthMask !== undefined ? functions.depthMask[ 0 ] : true;
+
+						materialParams.blending = enableBlend ? THREE.CustomBlending : THREE.NoBlending;
+						materialParams.transparent = enableBlend;
+
+						var blendEquationSeparate = functions.blendEquationSeparate;
+
+						if ( blendEquationSeparate !== undefined ) {
+
+							materialParams.blendEquation = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 0 ] ];
+							materialParams.blendEquationAlpha = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 1 ] ];
+
+						} else {
+
+							materialParams.blendEquation = THREE.AddEquation;
+							materialParams.blendEquationAlpha = THREE.AddEquation;
+
+						}
+
+						var blendFuncSeparate = functions.blendFuncSeparate;
+
+						if ( blendFuncSeparate !== undefined ) {
+
+							materialParams.blendSrc = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 0 ] ];
+							materialParams.blendDst = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 1 ] ];
+							materialParams.blendSrcAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 2 ] ];
+							materialParams.blendDstAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 3 ] ];
+
+						} else {
+
+							materialParams.blendSrc = THREE.OneFactor;
+							materialParams.blendDst = THREE.ZeroFactor;
+							materialParams.blendSrcAlpha = THREE.OneFactor;
+							materialParams.blendDstAlpha = THREE.ZeroFactor;
+
+						}
+
 					}
 					}
 
 
 				}
 				}
@@ -1108,7 +1288,7 @@ THREE.GLTFLoader = ( function () {
 				}
 				}
 
 
 				var _material = new materialType( materialParams );
 				var _material = new materialType( materialParams );
-				_material.name = material.name;
+				if ( material.name !== undefined ) _material.name = material.name;
 
 
 				return _material;
 				return _material;
 
 
@@ -1132,7 +1312,7 @@ THREE.GLTFLoader = ( function () {
 			return _each( json.meshes, function ( mesh ) {
 			return _each( json.meshes, function ( mesh ) {
 
 
 				var group = new THREE.Object3D();
 				var group = new THREE.Object3D();
-				group.name = mesh.name;
+				if ( mesh.name !== undefined ) group.name = mesh.name;
 
 
 				if ( mesh.extras ) group.userData = mesh.extras;
 				if ( mesh.extras ) group.userData = mesh.extras;
 
 
@@ -1190,7 +1370,7 @@ THREE.GLTFLoader = ( function () {
 
 
 						}
 						}
 
 
-						var material = dependencies.materials[ primitive.material ];
+						var material = dependencies.materials !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial();
 
 
 						var meshNode = new THREE.Mesh( geometry, material );
 						var meshNode = new THREE.Mesh( geometry, material );
 						meshNode.castShadow = true;
 						meshNode.castShadow = true;
@@ -1282,7 +1462,7 @@ THREE.GLTFLoader = ( function () {
 				// yfov = ( yfov === undefined && xfov ) ? xfov / aspect_ratio : yfov;
 				// yfov = ( yfov === undefined && xfov ) ? xfov / aspect_ratio : yfov;
 
 
 				var _camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( xfov ), aspect_ratio, camera.perspective.znear || 1, camera.perspective.zfar || 2e6 );
 				var _camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( xfov ), aspect_ratio, camera.perspective.znear || 1, camera.perspective.zfar || 2e6 );
-				_camera.name = camera.name;
+				if ( camera.name !== undefined ) _camera.name = camera.name;
 
 
 				if ( camera.extras ) _camera.userData = camera.extras;
 				if ( camera.extras ) _camera.userData = camera.extras;
 
 
@@ -1291,7 +1471,7 @@ THREE.GLTFLoader = ( function () {
 			} else if ( camera.type == "orthographic" && camera.orthographic ) {
 			} else if ( camera.type == "orthographic" && camera.orthographic ) {
 
 
 				var _camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, camera.orthographic.znear, camera.orthographic.zfar );
 				var _camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, camera.orthographic.znear, camera.orthographic.zfar );
-				_camera.name = camera.name;
+				if ( camera.name !== undefined ) _camera.name = camera.name;
 
 
 				if ( camera.extras ) _camera.userData = camera.extras;
 				if ( camera.extras ) _camera.userData = camera.extras;
 
 
@@ -1349,12 +1529,12 @@ THREE.GLTFLoader = ( function () {
 					var channel = animation.channels[ channelId ];
 					var channel = animation.channels[ channelId ];
 					var sampler = animation.samplers[ channel.sampler ];
 					var sampler = animation.samplers[ channel.sampler ];
 
 
-					if ( sampler && animation.parameters ) {
+					if ( sampler ) {
 
 
 						var target = channel.target;
 						var target = channel.target;
 						var name = target.id;
 						var name = target.id;
-						var input = animation.parameters[ sampler.input ];
-						var output = animation.parameters[ sampler.output ];
+						var input = animation.parameters !== undefined ? animation.parameters[ sampler.input ] : sampler.input;
+						var output = animation.parameters !== undefined ? animation.parameters[ sampler.output ] : sampler.output;
 
 
 						var inputAccessor = dependencies.accessors[ input ];
 						var inputAccessor = dependencies.accessors[ input ];
 						var outputAccessor = dependencies.accessors[ output ];
 						var outputAccessor = dependencies.accessors[ output ];
@@ -1370,11 +1550,13 @@ THREE.GLTFLoader = ( function () {
 								? THREE.QuaternionKeyframeTrack
 								? THREE.QuaternionKeyframeTrack
 								: THREE.VectorKeyframeTrack;
 								: THREE.VectorKeyframeTrack;
 
 
+							var targetName = node.name ? node.name : node.uuid;
+
 							// KeyframeTrack.optimize() will modify given 'times' and 'values'
 							// KeyframeTrack.optimize() will modify given 'times' and 'values'
 							// buffers before creating a truncated copy to keep. Because buffers may
 							// buffers before creating a truncated copy to keep. Because buffers may
 							// be reused by other tracks, make copies here.
 							// be reused by other tracks, make copies here.
 							tracks.push( new TypedKeyframeTrack(
 							tracks.push( new TypedKeyframeTrack(
-								node.name + '.' + PATH_PROPERTIES[ target.path ],
+								targetName + '.' + PATH_PROPERTIES[ target.path ],
 								THREE.AnimationUtils.arraySlice( inputAccessor.array, 0 ),
 								THREE.AnimationUtils.arraySlice( inputAccessor.array, 0 ),
 								THREE.AnimationUtils.arraySlice( outputAccessor.array, 0 ),
 								THREE.AnimationUtils.arraySlice( outputAccessor.array, 0 ),
 								INTERPOLATION[ sampler.interpolation ]
 								INTERPOLATION[ sampler.interpolation ]
@@ -1408,20 +1590,18 @@ THREE.GLTFLoader = ( function () {
 			if ( node.jointName ) {
 			if ( node.jointName ) {
 
 
 				_node = new THREE.Bone();
 				_node = new THREE.Bone();
+				_node.name = node.name !== undefined ? node.name : node.jointName;
 				_node.jointName = node.jointName;
 				_node.jointName = node.jointName;
 
 
 			} else {
 			} else {
 
 
 				_node = new THREE.Object3D();
 				_node = new THREE.Object3D();
+				if ( node.name !== undefined ) _node.name = node.name;
 
 
 			}
 			}
 
 
-			_node.name = node.name;
-
 			if ( node.extras ) _node.userData = node.extras;
 			if ( node.extras ) _node.userData = node.extras;
 
 
-			_node.matrixAutoUpdate = false;
-
 			if ( node.matrix !== undefined ) {
 			if ( node.matrix !== undefined ) {
 
 
 				matrix.fromArray( node.matrix );
 				matrix.fromArray( node.matrix );
@@ -1531,6 +1711,22 @@ THREE.GLTFLoader = ( function () {
 								// Replace Mesh with SkinnedMesh in library
 								// Replace Mesh with SkinnedMesh in library
 								if ( skinEntry ) {
 								if ( skinEntry ) {
 
 
+									var getJointNode = function ( jointId ) {
+
+										var keys = Object.keys( __nodes );
+
+										for ( var i = 0, il = keys.length; i < il; i ++ ) {
+
+											var n = __nodes[ keys[ i ] ];
+
+											if ( n.jointName === jointId ) return n;
+
+										}
+
+										return null;
+
+									}
+
 									var geometry = originalGeometry;
 									var geometry = originalGeometry;
 									var material = originalMaterial;
 									var material = originalMaterial;
 									material.skinning = true;
 									material.skinning = true;
@@ -1542,30 +1738,13 @@ THREE.GLTFLoader = ( function () {
 									var bones = [];
 									var bones = [];
 									var boneInverses = [];
 									var boneInverses = [];
 
 
-									var keys = Object.keys( __nodes );
-
 									for ( var i = 0, l = skinEntry.jointNames.length; i < l; i ++ ) {
 									for ( var i = 0, l = skinEntry.jointNames.length; i < l; i ++ ) {
 
 
 										var jointId = skinEntry.jointNames[ i ];
 										var jointId = skinEntry.jointNames[ i ];
-
-										var jointNode;
-
-										for ( var j = 0, jl = keys.length; j < jl; j ++ ) {
-
-											var n = __nodes[ keys[ j ] ];
-
-											if ( n.jointName === jointId ) {
-
-												jointNode = n;
-												break;
-
-											}
-
-										}
+										var jointNode = getJointNode( jointId );
 
 
 										if ( jointNode ) {
 										if ( jointNode ) {
 
 
-											jointNode.skin = child;
 											bones.push( jointNode );
 											bones.push( jointNode );
 
 
 											var m = skinEntry.inverseBindMatrices.array;
 											var m = skinEntry.inverseBindMatrices.array;
@@ -1582,6 +1761,31 @@ THREE.GLTFLoader = ( function () {
 
 
 									child.bind( new THREE.Skeleton( bones, boneInverses, false ), skinEntry.bindShapeMatrix );
 									child.bind( new THREE.Skeleton( bones, boneInverses, false ), skinEntry.bindShapeMatrix );
 
 
+									var buildBoneGraph = function ( parentJson, parentObject, property ) {
+
+										var children = parentJson[ property ];
+
+										if ( children === undefined ) return;
+
+										for ( var i = 0, il = children.length; i < il; i ++ ) {
+
+											var nodeId = children[ i ];
+											var bone = __nodes[ nodeId ];
+											var boneJson = json.nodes[ nodeId ];
+
+											if ( bone !== undefined && bone.isBone === true && boneJson !== undefined ) {
+
+												parentObject.add( bone );
+												buildBoneGraph( boneJson, bone, 'children' );
+
+											}
+
+										}
+
+									}
+
+									buildBoneGraph( node, child, 'skeletons' );
+
 								}
 								}
 
 
 								_node.add( child );
 								_node.add( child );
@@ -1653,7 +1857,7 @@ THREE.GLTFLoader = ( function () {
 								lightNode = new THREE.PointLight( color );
 								lightNode = new THREE.PointLight( color );
 								break;
 								break;
 
 
-							case "spot ":
+							case "spot":
 								lightNode = new THREE.SpotLight( color );
 								lightNode = new THREE.SpotLight( color );
 								lightNode.position.set( 0, 0, 1 );
 								lightNode.position.set( 0, 0, 1 );
 								break;
 								break;
@@ -1719,7 +1923,7 @@ THREE.GLTFLoader = ( function () {
 			return _each( json.scenes, function ( scene ) {
 			return _each( json.scenes, function ( scene ) {
 
 
 				var _scene = new THREE.Scene();
 				var _scene = new THREE.Scene();
-				_scene.name = scene.name;
+				if ( scene.name !== undefined ) _scene.name = scene.name;
 
 
 				if ( scene.extras ) _scene.userData = scene.extras;
 				if ( scene.extras ) _scene.userData = scene.extras;