Browse Source

Merge branch 'dev' into dev

Mr.doob 8 years ago
parent
commit
96ca9bba3a

+ 1 - 1
docs/api/geometries/RingBufferGeometry.html

@@ -44,7 +44,7 @@
 
 
 		<h3>[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])</h3>
 		<h3>[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])</h3>
 		<div>
 		<div>
-		innerRadius — Default is 0, but it doesn't work right when innerRadius is set to 0.<br />
+		innerRadius — Default is 20. <br />
 		outerRadius — Default is 50. <br />
 		outerRadius — Default is 50. <br />
 		thetaSegments — Number of segments.  A higher number means the ring will be more round.  Minimum is 3.  Default is 8. <br />
 		thetaSegments — Number of segments.  A higher number means the ring will be more round.  Minimum is 3.  Default is 8. <br />
 		phiSegments — Minimum is 1.  Default is 8.<br />
 		phiSegments — Minimum is 1.  Default is 8.<br />

+ 1 - 1
docs/api/geometries/RingGeometry.html

@@ -44,7 +44,7 @@
 
 
 		<h3>[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])</h3>
 		<h3>[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])</h3>
 		<div>
 		<div>
-		innerRadius — Default is 0, but it doesn't work right when innerRadius is set to 0.<br />
+		innerRadius — Default is 20. <br />
 		outerRadius — Default is 50. <br />
 		outerRadius — Default is 50. <br />
 		thetaSegments — Number of segments.  A higher number means the ring will be more round.  Minimum is 3.  Default is 8. <br />
 		thetaSegments — Number of segments.  A higher number means the ring will be more round.  Minimum is 3.  Default is 8. <br />
 		phiSegments — Minimum is 1.  Default is 8.<br />
 		phiSegments — Minimum is 1.  Default is 8.<br />

+ 6 - 1
docs/api/materials/Material.html

@@ -252,7 +252,12 @@
 		<div>
 		<div>
 		Defines whether this material is visible. Default is *true*.
 		Defines whether this material is visible. Default is *true*.
 		</div>
 		</div>
-
+		
+		<h3>[property:object userData]</h3>
+		<div>
+		An object that can be used to store custom data about the Material. It should not hold
+		references to functions as these will not be cloned.
+		</div>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 

+ 8 - 7
docs/examples/loaders/GLTF2Loader.html

@@ -19,7 +19,7 @@
 		for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf)
 		for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf)
 		or binary (.glb) format. External files store textures (.jpg, .png, ...) and additional binary
 		or binary (.glb) format. External files store textures (.jpg, .png, ...) and additional binary
 		data (.bin). A glTF asset may deliver one or more scenes, including meshes, materials,
 		data (.bin). A glTF asset may deliver one or more scenes, including meshes, materials,
-		textures, shaders, skins, skeletons, morph targets, animations, lights, and/or cameras.
+		textures, skins, skeletons, morph targets, animations, lights, and/or cameras.
 		</div>
 		</div>
 
 
 		<h2>Extensions</h2>
 		<h2>Extensions</h2>
@@ -30,17 +30,18 @@
 
 
 		<ul>
 		<ul>
 			<li>
 			<li>
-				KHR_lights
+				<a target="_blank" href="https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_pbrSpecularGlossiness">
+					KHR_materials_pbrSpecularGlossiness
+				</a>
 			</li>
 			</li>
 			<li>
 			<li>
 				<a target="_blank" href="https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_common">
 				<a target="_blank" href="https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_common">
 					KHR_materials_common
 					KHR_materials_common
 				</a>
 				</a>
+				(experimental)
 			</li>
 			</li>
 			<li>
 			<li>
-				<a target="_blank" href="https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_pbrSpecularGlossiness">
-					KHR_materials_pbrSpecularGlossiness
-				</a>
+				KHR_lights (experimental)
 			</li>
 			</li>
 		</ul>
 		</ul>
 
 
@@ -91,7 +92,7 @@
 
 
 		<h3>[method:null setPath]( [page:String path] )</h3>
 		<h3>[method:null setPath]( [page:String path] )</h3>
 		<div>
 		<div>
-		[page:String path] — Base path for loading additional resources e.g. textures, GLSL shaders, .bin data.
+		[page:String path] — Base path for loading additional resources e.g. textures and .bin data.
 		</div>
 		</div>
 		<div>
 		<div>
 		Set the base path for additional resources.
 		Set the base path for additional resources.
@@ -106,7 +107,7 @@
 		<div>
 		<div>
 		[page:Object json] — <em>JSON</em> object to parse.<br />
 		[page:Object json] — <em>JSON</em> object to parse.<br />
 		[page:Function callBack] — Will be called when parse completes.<br />
 		[page:Function callBack] — Will be called when parse completes.<br />
-		[page:String path] — The base path from which to find subsequent glTF resources such as textures, GLSL shaders and .bin data files.<br />
+		[page:String path] — The base path from which to find subsequent glTF resources such as textures and .bin data files.<br />
 		</div>
 		</div>
 		<div>
 		<div>
 		Parse a glTF-based <em>JSON</em> structure and fire [page:Function callback] when complete. The argument to [page:Function callback] will be an [page:object] that contains loaded parts: .[page:Scene scene], .[page:Array scenes], .[page:Array cameras], and .[page:Array animations].
 		Parse a glTF-based <em>JSON</em> structure and fire [page:Function callback] when complete. The argument to [page:Function callback] will be an [page:object] that contains loaded parts: .[page:Scene scene], .[page:Array scenes], .[page:Array cameras], and .[page:Array animations].

+ 10 - 5
examples/css3d_molecules.html

@@ -344,13 +344,17 @@
 
 
 				objects = [];
 				objects = [];
 
 
-				loader.load( url, function ( geometry, geometryBonds ) {
+				loader.load( url, function ( pdb ) {
 
 
-					var offset = geometry.center();
+					var geometryAtoms = pdb.geometryAtoms;
+					var geometryBonds = pdb.geometryBonds;
+					var json = pdb.json;
+
+					var offset = geometryAtoms.center();
 					geometryBonds.translate( offset.x, offset.y, offset.z );
 					geometryBonds.translate( offset.x, offset.y, offset.z );
 
 
-					var positions = geometry.getAttribute( 'position' );
-					var colors = geometry.getAttribute( 'color' );
+					var positions = geometryAtoms.getAttribute( 'position' );
+					var colors = geometryAtoms.getAttribute( 'color' );
 
 
 					var position = new THREE.Vector3();
 					var position = new THREE.Vector3();
 					var color = new THREE.Color();
 					var color = new THREE.Color();
@@ -365,7 +369,8 @@
 						color.g = colors.getY( i );
 						color.g = colors.getY( i );
 						color.b = colors.getZ( i );
 						color.b = colors.getZ( i );
 
 
-						var element = geometry.elements[ i ];
+						var atom = json.atoms[ i ];
+						var element = atom[ 4 ];
 
 
 						if ( ! colorSpriteMap[ element ] ) {
 						if ( ! colorSpriteMap[ element ] ) {
 
 

+ 1 - 0
examples/files.js

@@ -323,6 +323,7 @@ var files = {
 		"misc_lights_test",
 		"misc_lights_test",
 		"misc_lookat",
 		"misc_lookat",
 		"misc_sound",
 		"misc_sound",
+		"misc_sound_visualizer",
 		"misc_ubiquity_test",
 		"misc_ubiquity_test",
 		"misc_ubiquity_test2",
 		"misc_ubiquity_test2",
 		"misc_uv_tests"
 		"misc_uv_tests"

+ 1 - 1
examples/js/GPUParticleSystem.js

@@ -77,7 +77,7 @@ THREE.GPUParticleSystem = function( options ) {
 			'	v.y = ( velocity.y - 0.5 ) * 3.0;',
 			'	v.y = ( velocity.y - 0.5 ) * 3.0;',
 			'	v.z = ( velocity.z - 0.5 ) * 3.0;',
 			'	v.z = ( velocity.z - 0.5 ) * 3.0;',
 
 
-			'	newPosition = positionStart + ( v * 10.0 ) * ( uTime - startTime );',
+			'	newPosition = positionStart + ( v * 10.0 ) * timeElapsed;',
 
 
 			'	vec3 noise = texture2D( tNoise, vec2( newPosition.x * 0.015 + ( uTime * 0.05 ), newPosition.y * 0.02 + ( uTime * 0.015 ) ) ).rgb;',
 			'	vec3 noise = texture2D( tNoise, vec2( newPosition.x * 0.015 + ( uTime * 0.05 ), newPosition.y * 0.02 + ( uTime * 0.015 ) ) ).rgb;',
 			'	vec3 noiseVel = ( noise.rgb - 0.5 ) * 30.0;',
 			'	vec3 noiseVel = ( noise.rgb - 0.5 ) * 30.0;',

+ 16 - 10
examples/js/loaders/3MFLoader.js

@@ -1,3 +1,7 @@
+/**
+ * @author technohippy / https://github.com/technohippy
+ */
+
 THREE.ThreeMFLoader = function ( manager ) {
 THREE.ThreeMFLoader = function ( manager ) {
 
 
 	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
@@ -14,9 +18,9 @@ THREE.ThreeMFLoader.prototype = {
 		var scope = this;
 		var scope = this;
 		var loader = new THREE.FileLoader( scope.manager );
 		var loader = new THREE.FileLoader( scope.manager );
 		loader.setResponseType( 'arraybuffer' );
 		loader.setResponseType( 'arraybuffer' );
-		loader.load( url, function( text ) {
+		loader.load( url, function( buffer ) {
 
 
-			onLoad( scope.parse( text ) );
+			onLoad( scope.parse( buffer ) );
 
 
 		}, onProgress, onError );
 		}, onProgress, onError );
 
 
@@ -51,7 +55,7 @@ THREE.ThreeMFLoader.prototype = {
 
 
 				if ( e instanceof ReferenceError ) {
 				if ( e instanceof ReferenceError ) {
 
 
-					console.log( '	jszip missing and file is compressed.' );
+					console.error( 'THREE.ThreeMFLoader: jszip missing and file is compressed.' );
 					return null;
 					return null;
 
 
 				}
 				}
@@ -95,7 +99,7 @@ THREE.ThreeMFLoader.prototype = {
 
 
 				if ( TextDecoder === undefined ) {
 				if ( TextDecoder === undefined ) {
 
 
-					console.log( '	TextDecoder not present.	Please use TextDecoder polyfill.' );
+					console.error( 'THREE.ThreeMFLoader: TextDecoder not present. Please use a TextDecoder polyfill.' );
 					return null;
 					return null;
 
 
 				}
 				}
@@ -105,7 +109,7 @@ THREE.ThreeMFLoader.prototype = {
 
 
 				if ( xmlData.documentElement.nodeName.toLowerCase() !== 'model' ) {
 				if ( xmlData.documentElement.nodeName.toLowerCase() !== 'model' ) {
 
 
-					console.log( '	Error loading 3MF - no 3MF document found: ' + modelPart );
+					console.error( 'THREE.ThreeMFLoader: Error loading 3MF - no 3MF document found: ', modelPart );
 
 
 				}
 				}
 
 
@@ -372,7 +376,6 @@ THREE.ThreeMFLoader.prototype = {
 		function parseResourcesNode( resourcesNode ) {
 		function parseResourcesNode( resourcesNode ) {
 
 
 			var resourcesData = {};
 			var resourcesData = {};
-			var geometry, material;
 			var basematerialsNode = resourcesNode.querySelector( 'basematerials' );
 			var basematerialsNode = resourcesNode.querySelector( 'basematerials' );
 
 
 			if ( basematerialsNode ) {
 			if ( basematerialsNode ) {
@@ -499,8 +502,10 @@ THREE.ThreeMFLoader.prototype = {
 
 
 		function applyExtensions( extensions, meshData, modelXml, data3mf ) {
 		function applyExtensions( extensions, meshData, modelXml, data3mf ) {
 
 
-			if ( !extensions ) {
+			if ( ! extensions ) {
+
 				return;
 				return;
+
 			}
 			}
 
 
 			var availableExtensions = [];
 			var availableExtensions = [];
@@ -530,6 +535,7 @@ THREE.ThreeMFLoader.prototype = {
 				extension.apply( modelXml, extensions[ extension[ 'ns' ] ], meshData );
 				extension.apply( modelXml, extensions[ extension[ 'ns' ] ], meshData );
 
 
 			}
 			}
+
 		}
 		}
 
 
 		function buildMeshes( data3mf ) {
 		function buildMeshes( data3mf ) {
@@ -590,14 +596,14 @@ THREE.ThreeMFLoader.prototype = {
 		var data3mf = loadDocument( data );
 		var data3mf = loadDocument( data );
 		var meshes = buildMeshes( data3mf );
 		var meshes = buildMeshes( data3mf );
 
 
-		return build( meshes, data3mf[ 'rels' ], data3mf )
+		return build( meshes, data3mf[ 'rels' ], data3mf );
 
 
 	},
 	},
 
 
-    addExtension: function( extension ) {
+	addExtension: function( extension ) {
 
 
 		this.availableExtensions.push( extension );
 		this.availableExtensions.push( extension );
 
 
-    }
+	}
 
 
 };
 };

+ 124 - 178
examples/js/loaders/AssimpJSONLoader.js

@@ -27,38 +27,38 @@ THREE.AssimpJSONLoader.prototype = {
 
 
 		var scope = this;
 		var scope = this;
 
 
-		this.texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : this.extractUrlBase( url );
+		var path = THREE.Loader.prototype.extractUrlBase( url );
 
 
 		var loader = new THREE.FileLoader( this.manager );
 		var loader = new THREE.FileLoader( this.manager );
 		loader.load( url, function ( text ) {
 		loader.load( url, function ( text ) {
 
 
-			var json = JSON.parse( text ), scene, metadata;
+			var json = JSON.parse( text );
+			var metadata = json.__metadata__;
+
+			// check if __metadata__ meta header is present
+			// this header is used to disambiguate between different JSON-based file formats
 
 
-			// Check __metadata__ meta header if present
-			// This header is used to disambiguate between
-			// different JSON-based file formats.
-			metadata = json.__metadata__;
 			if ( typeof metadata !== 'undefined' ) {
 			if ( typeof metadata !== 'undefined' ) {
 
 
-				// Check if assimp2json at all
+				// check if assimp2json at all
+
 				if ( metadata.format !== 'assimp2json' ) {
 				if ( metadata.format !== 'assimp2json' ) {
 
 
-					onError( 'Not an assimp2json scene' );
+					onError( 'THREE.AssimpJSONLoader: Not an assimp2json scene.' );
 					return;
 					return;
 
 
-				}
-				// Check major format version
-				else if ( metadata.version < 100 && metadata.version >= 200 ) {
+				// check major format version
+
+				} else if ( metadata.version < 100 && metadata.version >= 200 ) {
 
 
-					onError( 'Unsupported assimp2json file format version' );
+					onError( 'THREE.AssimpJSONLoader: Unsupported assimp2json file format version.' );
 					return;
 					return;
 
 
 				}
 				}
 
 
 			}
 			}
 
 
-			scene = scope.parse( json );
-			onLoad( scene );
+			onLoad( scope.parse( json, path ) );
 
 
 		}, onProgress, onError );
 		}, onProgress, onError );
 
 
@@ -70,249 +70,195 @@ THREE.AssimpJSONLoader.prototype = {
 
 
 	},
 	},
 
 
-	setTexturePath: function ( value ) {
+	parse: function ( json, path ) {
 
 
-		this.texturePath = value;
+		function parseList( json, handler ) {
 
 
-	},
-
-	extractUrlBase: function ( url ) {
+			var meshes = new Array( json.length );
 
 
-		// from three/src/loaders/Loader.js
-		var parts = url.split( '/' );
-		parts.pop();
-		return ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/';
-
-	},
+			for ( var i = 0; i < json.length; ++ i ) {
 
 
-	parse: function ( json ) {
+				meshes[ i ] = handler.call( this, json[ i ] );
 
 
-		var meshes = this.parseList ( json.meshes, this.parseMesh );
-		var materials = this.parseList ( json.materials, this.parseMaterial );
-		return this.parseObject( json, json.rootnode, meshes, materials );
-
-	},
-
-	parseList : function( json, handler ) {
-
-		var meshes = new Array( json.length );
-		for ( var i = 0; i < json.length; ++ i ) {
+			}
 
 
-			meshes[ i ] = handler.call( this, json[ i ] );
+			return meshes;
 
 
 		}
 		}
-		return meshes;
-
-	},
 
 
-	parseMesh : function( json ) {
+		function parseMesh( json ) {
 
 
-		var geometry = new THREE.BufferGeometry();
+			var geometry = new THREE.BufferGeometry();
 
 
-		var i, l, face;
+			var i, l, face;
 
 
-		var indices = [];
+			var indices = [];
 
 
-		var vertices = json.vertices || [];
-		var normals = json.normals || [];
-		var uvs = json.texturecoords || [];
-		var colors = json.colors || [];
+			var vertices = json.vertices || [];
+			var normals = json.normals || [];
+			var uvs = json.texturecoords || [];
+			var colors = json.colors || [];
 
 
-		uvs = uvs[ 0 ] || []; // only support for a single set of uvs
+			uvs = uvs[ 0 ] || []; // only support for a single set of uvs
 
 
-		for ( i = 0, l = json.faces.length; i < l; i ++ ) {
+			for ( i = 0, l = json.faces.length; i < l; i ++ ) {
 
 
-			face = json.faces[ i ];
-			indices.push( face[ 0 ], face[ 1 ], face[ 2 ] );
+				face = json.faces[ i ];
+				indices.push( face[ 0 ], face[ 1 ], face[ 2 ] );
 
 
-		}
-
-		geometry.setIndex( indices );
-		geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
-
-		if ( normals.length > 0 ) {
-
-			geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
-
-		}
-
-		if ( uvs.length > 0 ) {
-
-			geometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
+			}
 
 
-		}
+			geometry.setIndex( indices );
+			geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
 
 
-		if ( colors.length > 0 ) {
+			if ( normals.length > 0 ) {
 
 
-			geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
+				geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
 
 
-		}
+			}
 
 
-		geometry.computeBoundingSphere();
+			if ( uvs.length > 0 ) {
 
 
-		return geometry;
+				geometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
 
 
-	},
+			}
 
 
-	parseMaterial : function( json ) {
+			if ( colors.length > 0 ) {
 
 
-		var mat = null;
-		var scope = this;
-		var i, prop, has_textures = [],
+				geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
 
 
-		init_props = {};
+			}
 
 
-		function toColor( value_arr ) {
+			geometry.computeBoundingSphere();
 
 
-			var col = new THREE.Color();
-			col.setRGB( value_arr[ 0 ], value_arr[ 1 ], value_arr[ 2 ] );
-			return col;
+			return geometry;
 
 
 		}
 		}
 
 
-		function defaultTexture() {
+		function parseMaterial( json ) {
 
 
-			var im = new Image();
-			im.width = 1;
-			im.height = 1;
-			return new THREE.Texture( im );
+			var material = new THREE.MeshPhongMaterial();
 
 
-		}
+			for ( var i in json.properties ) {
 
 
-		for ( i in json.properties ) {
+				var property = json.properties[ i ];
+				var key = property.key;
+				var value = property.value;
 
 
-			prop = json.properties[ i ];
+				switch ( key ) {
 
 
-			if ( prop.key === '$tex.file' ) {
+					case '$tex.file': {
 
 
-				// prop.semantic gives the type of the texture
-				// 1: diffuse
-				// 2: specular mao
-				// 5: height map (bumps)
-				// 6: normal map
-				// more values (i.e. emissive, environment) are known by assimp and may be relevant
-				if ( prop.semantic === 1 || prop.semantic === 5 || prop.semantic === 6 || prop.semantic === 2 ) {
+						var semantic =  property.semantic;
 
 
-					( function( semantic ) {
+						// prop.semantic gives the type of the texture
+						// 1: diffuse
+						// 2: specular mao
+						// 5: height map (bumps)
+						// 6: normal map
+						// more values (i.e. emissive, environment) are known by assimp and may be relevant
 
 
-						var loader = new THREE.TextureLoader( scope.manager ),
-						keyname;
+						if ( semantic === 1 || semantic === 2 || semantic === 5 || semantic === 6 ) {
 
 
-						if ( semantic === 1 ) {
+							var keyname;
 
 
-							keyname = 'map';
+							switch ( semantic ) {
 
 
-						} else if ( semantic === 5 ) {
+								case 1:
+									keyname = 'map';
+									break;
+								case 2:
+									keyname = 'specularMap';
+									break;
+								case 5:
+									keyname = 'bumpMap';
+									break;
+								case 6:
+									keyname = 'normalMap';
+									break;
 
 
-							keyname = 'bumpMap';
+							}
 
 
-						} else if ( semantic === 6 ) {
+							var texture = textureLoader.load( value );
 
 
-							keyname = 'normalMap';
+							// TODO: read texture settings from assimp.
+							// Wrapping is the default, though.
 
 
-						} else if ( semantic === 2 ) {
+							texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
 
 
-							keyname = 'specularMap';
+							material[ keyname ] = texture;
 
 
 						}
 						}
 
 
-						has_textures.push( keyname );
+						break;
 
 
-						loader.setCrossOrigin( this.crossOrigin );
-						var material_url = scope.texturePath + '/' + prop.value;
-						material_url = material_url.replace( /\\/g, '/' );
-						loader.load( material_url, function( tex ) {
+					}
 
 
-							if ( tex ) {
+					case '?mat.name':
+						material.name = value;
+						break;
 
 
-								// TODO: read texture settings from assimp.
-								// Wrapping is the default, though.
-								tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
+					case '$clr.diffuse':
+						material.color.fromArray( value );
+						break;
 
 
-								mat[ keyname ] = tex;
-								mat.needsUpdate = true;
+					case '$clr.specular':
+						material.specular.fromArray( value );
+						break;
 
 
-							}
+					case '$clr.emissive':
+						material.emissive.fromArray( value );
+						break;
 
 
-						} );
+					case '$mat.shininess':
+						material.shininess = value;
+						break;
 
 
-					} )( prop.semantic );
+					case '$mat.shadingm':
+						// aiShadingMode_Flat
+						material.flatShading = ( value === 1 ) ? true : false;
+						break;
 
 
 				}
 				}
 
 
-			} else if ( prop.key === '?mat.name' ) {
-
-				init_props.name = prop.value;
-
-			} else if ( prop.key === '$clr.diffuse' ) {
-
-				init_props.color = toColor( prop.value );
-
-			} else if ( prop.key === '$clr.specular' ) {
-
-				init_props.specular = toColor( prop.value );
+			}
 
 
-			} else if ( prop.key === '$clr.emissive' ) {
+			return material;
 
 
-				init_props.emissive = toColor( prop.value );
+		}
 
 
-			} else if ( prop.key === '$mat.shadingm' ) {
+		function parseObject( json, node, meshes, materials ) {
 
 
-				// aiShadingMode_Flat
-				if ( prop.value === 1 ) {
+			var obj = new THREE.Object3D(),	i, idx;
 
 
-					init_props.flatShading = true;
+			obj.name = node.name || '';
+			obj.matrix = new THREE.Matrix4().fromArray( node.transformation ).transpose();
+			obj.matrix.decompose( obj.position, obj.quaternion, obj.scale );
 
 
-				}
+			for ( i = 0; node.meshes && i < node.meshes.length; i ++ ) {
 
 
-			} else if ( prop.key === '$mat.shininess' ) {
-
-				init_props.shininess = prop.value;
+				idx = node.meshes[ i ];
+				obj.add( new THREE.Mesh( meshes[ idx ], materials[ json.meshes[ idx ].materialindex ] ) );
 
 
 			}
 			}
 
 
-		}
-
-		// note: three.js does not like it when a texture is added after the geometry
-		// has been rendered once, see http://stackoverflow.com/questions/16531759/.
-		// for this reason we fill all slots upfront with default textures
-		if ( has_textures.length ) {
+			for ( i = 0; node.children && i < node.children.length; i ++ ) {
 
 
-			for ( i = has_textures.length - 1; i >= 0; -- i ) {
-
-				init_props[ has_textures[ i ]] = defaultTexture();
+				obj.add( parseObject( json, node.children[ i ], meshes, materials ) );
 
 
 			}
 			}
 
 
-		}
-
-		mat = new THREE.MeshPhongMaterial( init_props );
-		return mat;
-
-	},
-
-	parseObject : function( json, node, meshes, materials ) {
-
-		var obj = new THREE.Object3D(),	i, idx;
-
-		obj.name = node.name || "";
-		obj.matrix = new THREE.Matrix4().fromArray( node.transformation ).transpose();
-		obj.matrix.decompose( obj.position, obj.quaternion, obj.scale );
-
-		for ( i = 0; node.meshes && i < node.meshes.length; ++ i ) {
-
-			idx = node.meshes[ i ];
-			obj.add( new THREE.Mesh( meshes[ idx ], materials[ json.meshes[ idx ].materialindex ] ) );
+			return obj;
 
 
 		}
 		}
 
 
-		for ( i = 0; node.children && i < node.children.length; ++ i ) {
+		var textureLoader = new THREE.TextureLoader( this.manager );
+		textureLoader.setPath( path ).setCrossOrigin( this.crossOrigin );
 
 
-			obj.add( this.parseObject( json, node.children[ i ], meshes, materials ) );
-
-		}
-
-		return obj;
+		var meshes = parseList ( json.meshes, parseMesh );
+		var materials = parseList ( json.materials, parseMaterial );
+		return parseObject( json, json.rootnode, meshes, materials );
 
 
 	}
 	}
+
 };
 };

File diff suppressed because it is too large
+ 836 - 789
examples/js/loaders/AssimpLoader.js


+ 27 - 1
examples/js/loaders/ColladaLoader2.js

@@ -1980,7 +1980,11 @@ THREE.ColladaLoader.prototype = {
 
 
 				// material
 				// material
 
 
-				materialKeys.push( primitive.material );
+				if ( primitive.material ) {
+
+					materialKeys.push( primitive.material );
+
+				}
 
 
 				// geometry data
 				// geometry data
 
 
@@ -3122,6 +3126,24 @@ THREE.ColladaLoader.prototype = {
 
 
 				var materials = resolveMaterialBinding( geometry.materialKeys, instanceMaterials );
 				var materials = resolveMaterialBinding( geometry.materialKeys, instanceMaterials );
 
 
+				// handle case if no materials are defined
+
+				if ( materials.length === 0 ) {
+
+					if ( type === 'lines' || type === 'linestrips' ) {
+
+						materials.push( new THREE.LineBasicMaterial() );
+
+					} else {
+
+						materials.push( new THREE.MeshPhongMaterial() );
+
+					}
+
+				}
+
+				// regard skinning
+
 				var skinning = ( geometry.data.attributes.skinIndex !== undefined );
 				var skinning = ( geometry.data.attributes.skinIndex !== undefined );
 
 
 				if ( skinning ) {
 				if ( skinning ) {
@@ -3134,8 +3156,12 @@ THREE.ColladaLoader.prototype = {
 
 
 				}
 				}
 
 
+				// choose between a single or multi materials (material array)
+
 				var material = ( materials.length === 1 ) ? materials[ 0 ] : materials;
 				var material = ( materials.length === 1 ) ? materials[ 0 ] : materials;
 
 
+				// now create a specific 3D object
+
 				var object;
 				var object;
 
 
 				switch ( type ) {
 				switch ( type ) {

+ 36 - 14
examples/js/loaders/FBXLoader.js

@@ -185,12 +185,12 @@
 	/**
 	/**
 	 * Parses map of images referenced in FBXTree.
 	 * Parses map of images referenced in FBXTree.
 	 * @param {{Objects: {subNodes: {Texture: Object.<string, FBXTextureNode>}}}} FBXTree
 	 * @param {{Objects: {subNodes: {Texture: Object.<string, FBXTextureNode>}}}} FBXTree
-	 * @returns {Map<number, string(image blob URL)>}
+	 * @returns {Map<number, string(image blob/data URL)>}
 	 */
 	 */
 	function parseImages( FBXTree ) {
 	function parseImages( FBXTree ) {
 
 
 		/**
 		/**
-		 * @type {Map<number, string(image blob URL)>}
+		 * @type {Map<number, string(image blob/data URL)>}
 		 */
 		 */
 		var imageMap = new Map();
 		var imageMap = new Map();
 
 
@@ -220,12 +220,11 @@
 
 
 	/**
 	/**
 	 * @param {videoNode} videoNode - Node to get texture image information from.
 	 * @param {videoNode} videoNode - Node to get texture image information from.
-	 * @returns {string} - image blob URL
+	 * @returns {string} - image blob/data URL
 	 */
 	 */
 	function parseImage( videoNode ) {
 	function parseImage( videoNode ) {
 
 
-		var buffer = videoNode.properties.Content;
-		var array = new Uint8Array( buffer );
+		var content = videoNode.properties.Content;
 		var fileName = videoNode.properties.RelativeFilename || videoNode.properties.Filename;
 		var fileName = videoNode.properties.RelativeFilename || videoNode.properties.Filename;
 		var extension = fileName.slice( fileName.lastIndexOf( '.' ) + 1 ).toLowerCase();
 		var extension = fileName.slice( fileName.lastIndexOf( '.' ) + 1 ).toLowerCase();
 
 
@@ -260,7 +259,16 @@
 
 
 		}
 		}
 
 
-		return window.URL.createObjectURL( new Blob( [ array ], { type: type } ) );
+		if ( typeof content === 'string' ) {
+
+			return 'data:' + type + ';base64,' + content;
+
+		} else {
+
+			var array = new Uint8Array( content );
+			return window.URL.createObjectURL( new Blob( [ array ], { type: type } ) );
+
+		}
 
 
 	}
 	}
 
 
@@ -268,7 +276,7 @@
 	 * Parses map of textures referenced in FBXTree.
 	 * Parses map of textures referenced in FBXTree.
 	 * @param {{Objects: {subNodes: {Texture: Object.<string, FBXTextureNode>}}}} FBXTree
 	 * @param {{Objects: {subNodes: {Texture: Object.<string, FBXTextureNode>}}}} FBXTree
 	 * @param {THREE.TextureLoader} loader
 	 * @param {THREE.TextureLoader} loader
-	 * @param {Map<number, string(image blob URL)>} imageMap
+	 * @param {Map<number, string(image blob/data URL)>} imageMap
 	 * @param {Map<number, {parents: {ID: number, relationship: string}[], children: {ID: number, relationship: string}[]}>} connections
 	 * @param {Map<number, {parents: {ID: number, relationship: string}[], children: {ID: number, relationship: string}[]}>} connections
 	 * @returns {Map<number, THREE.Texture>}
 	 * @returns {Map<number, THREE.Texture>}
 	 */
 	 */
@@ -298,7 +306,7 @@
 	/**
 	/**
 	 * @param {textureNode} textureNode - Node to get texture information from.
 	 * @param {textureNode} textureNode - Node to get texture information from.
 	 * @param {THREE.TextureLoader} loader
 	 * @param {THREE.TextureLoader} loader
-	 * @param {Map<number, string(image blob URL)>} imageMap
+	 * @param {Map<number, string(image blob/data URL)>} imageMap
 	 * @param {Map<number, {parents: {ID: number, relationship: string}[], children: {ID: number, relationship: string}[]}>} connections
 	 * @param {Map<number, {parents: {ID: number, relationship: string}[], children: {ID: number, relationship: string}[]}>} connections
 	 * @returns {THREE.Texture}
 	 * @returns {THREE.Texture}
 	 */
 	 */
@@ -345,7 +353,7 @@
 
 
 		var currentPath = loader.path;
 		var currentPath = loader.path;
 
 
-		if ( fileName.indexOf( 'blob:' ) === 0 ) {
+		if ( fileName.indexOf( 'blob:' ) === 0 || fileName.indexOf( 'data:' ) === 0 ) {
 
 
 			loader.setPath( undefined );
 			loader.setPath( undefined );
 
 
@@ -3619,25 +3627,28 @@
 
 
 			var split = text.split( '\n' );
 			var split = text.split( '\n' );
 
 
-			for ( var line in split ) {
+			for ( var lineNum = 0, lineLength = split.length; lineNum < lineLength; lineNum ++ ) {
 
 
-				var l = split[ line ];
+				var l = split[ lineNum ];
 
 
-				// short cut
+				// skip comment line
 				if ( l.match( /^[\s\t]*;/ ) ) {
 				if ( l.match( /^[\s\t]*;/ ) ) {
 
 
 					continue;
 					continue;
 
 
-				} // skip comment line
+				}
+
+				// skip empty line
 				if ( l.match( /^[\s\t]*$/ ) ) {
 				if ( l.match( /^[\s\t]*$/ ) ) {
 
 
 					continue;
 					continue;
 
 
-				} // skip empty line
+				}
 
 
 				// beginning of node
 				// beginning of node
 				var beginningOfNodeExp = new RegExp( '^\\t{' + this.currentIndent + '}(\\w+):(.*){', '' );
 				var beginningOfNodeExp = new RegExp( '^\\t{' + this.currentIndent + '}(\\w+):(.*){', '' );
 				var match = l.match( beginningOfNodeExp );
 				var match = l.match( beginningOfNodeExp );
+
 				if ( match ) {
 				if ( match ) {
 
 
 					var nodeName = match[ 1 ].trim().replace( /^"/, '' ).replace( /"$/, '' );
 					var nodeName = match[ 1 ].trim().replace( /^"/, '' ).replace( /"$/, '' );
@@ -3655,11 +3666,21 @@
 				// node's property
 				// node's property
 				var propExp = new RegExp( '^\\t{' + ( this.currentIndent ) + '}(\\w+):[\\s\\t\\r\\n](.*)' );
 				var propExp = new RegExp( '^\\t{' + ( this.currentIndent ) + '}(\\w+):[\\s\\t\\r\\n](.*)' );
 				var match = l.match( propExp );
 				var match = l.match( propExp );
+
 				if ( match ) {
 				if ( match ) {
 
 
 					var propName = match[ 1 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
 					var propName = match[ 1 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
 					var propValue = match[ 2 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
 					var propValue = match[ 2 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
 
 
+					// for special case: base64 image data follows "Content: ," line
+					//	Content: ,
+					//	 "iVB..."
+					if ( propName === 'Content' && propValue === ',' ) {
+
+						propValue = split[ ++ lineNum ].replace( /"/g, '' ).trim();
+
+					}
+
 					this.parseNodeProperty( l, propName, propValue );
 					this.parseNodeProperty( l, propName, propValue );
 					continue;
 					continue;
 
 
@@ -3667,6 +3688,7 @@
 
 
 				// end of node
 				// end of node
 				var endOfNodeExp = new RegExp( '^\\t{' + ( this.currentIndent - 1 ) + '}}' );
 				var endOfNodeExp = new RegExp( '^\\t{' + ( this.currentIndent - 1 ) + '}}' );
+
 				if ( l.match( endOfNodeExp ) ) {
 				if ( l.match( endOfNodeExp ) ) {
 
 
 					this.nodeEnd();
 					this.nodeEnd();

+ 39 - 615
examples/js/loaders/GLTF2Loader.js

@@ -106,12 +106,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 				}
 				}
 
 
-				if ( json.extensionsUsed.indexOf( EXTENSIONS.KHR_TECHNIQUE_WEBGL ) >= 0 ) {
-
-					extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ] = new GLTFTechniqueWebglExtension( json );
-
-				}
-
 			}
 			}
 
 
 			console.time( 'GLTF2Loader' );
 			console.time( 'GLTF2Loader' );
@@ -194,109 +188,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 	}
 	}
 
 
-	/* GLTFSHADER */
-
-	function GLTFShader( targetNode, allNodes ) {
-
-		var boundUniforms = {};
-
-		// bind each uniform to its source node
-
-		var uniforms = targetNode.material.uniforms;
-
-		for ( var uniformId in uniforms ) {
-
-			var uniform = uniforms[ uniformId ];
-
-			if ( uniform.semantic ) {
-
-				var sourceNodeRef = uniform.node;
-
-				var sourceNode = targetNode;
-
-				if ( sourceNodeRef ) {
-
-					sourceNode = allNodes[ sourceNodeRef ];
-
-				}
-
-				boundUniforms[ uniformId ] = {
-					semantic: uniform.semantic,
-					sourceNode: sourceNode,
-					targetNode: targetNode,
-					uniform: uniform
-				};
-
-			}
-
-		}
-
-		this.boundUniforms = boundUniforms;
-		this._m4 = new THREE.Matrix4();
-
-	}
-
-	// Update - update all the uniform values
-	GLTFShader.prototype.update = function ( scene, camera ) {
-
-		var boundUniforms = this.boundUniforms;
-
-		for ( var name in boundUniforms ) {
-
-			var boundUniform = boundUniforms[ name ];
-
-			switch ( boundUniform.semantic ) {
-
-				case 'MODELVIEW':
-
-					var m4 = boundUniform.uniform.value;
-					m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld );
-					break;
-
-				case 'MODELVIEWINVERSETRANSPOSE':
-
-					var m3 = boundUniform.uniform.value;
-					this._m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld );
-					m3.getNormalMatrix( this._m4 );
-					break;
-
-				case 'PROJECTION':
-
-					var m4 = boundUniform.uniform.value;
-					m4.copy( camera.projectionMatrix );
-					break;
-
-				case 'JOINTMATRIX':
-
-					var m4v = boundUniform.uniform.value;
-
-					for ( var mi = 0; mi < m4v.length; mi ++ ) {
-
-						// So it goes like this:
-						// SkinnedMesh world matrix is already baked into MODELVIEW;
-						// transform joints to local space,
-						// then transform using joint's inverse
-						m4v[ mi ]
-							.getInverse( boundUniform.sourceNode.matrixWorld )
-							.multiply( boundUniform.targetNode.skeleton.bones[ mi ].matrixWorld )
-							.multiply( boundUniform.targetNode.skeleton.boneInverses[ mi ] )
-							.multiply( boundUniform.targetNode.bindMatrix );
-
-					}
-
-					break;
-
-				default :
-
-					console.warn( 'THREE.GLTF2Loader: Unhandled shader semantic: ' + boundUniform.semantic );
-					break;
-
-			}
-
-		}
-
-	};
-
 	/*********************************/
 	/*********************************/
 	/********** EXTENSIONS ***********/
 	/********** EXTENSIONS ***********/
 	/*********************************/
 	/*********************************/
@@ -558,304 +449,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 	}
 	}
 
 
-	/**
-	 * WebGL Technique Extension
-	 *
-	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_technique_webgl
-	 */
-	function GLTFTechniqueWebglExtension( json ) {
-
-		this.name = EXTENSIONS.KHR_TECHNIQUE_WEBGL;
-
-		var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ] ) || {};
-
-		this.techniques = extension.techniques || {};
-		this.programs = extension.programs || {};
-		this.shaders = extension.shaders || {};
-
-	}
-
-	GLTFTechniqueWebglExtension.prototype.getMaterialType = function () {
-
-		return DeferredShaderMaterial;
-
-	};
-
-	GLTFTechniqueWebglExtension.prototype.extendParams = function ( materialParams, material, dependencies ) {
-
-		var extension = material[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ];
-		var technique = dependencies.techniques[ extension.technique ];
-
-		materialParams.uniforms = {};
-
-		var program = dependencies.programs[ technique.program ];
-
-		if ( program === undefined ) {
-
-			return;
-
-		}
-
-		materialParams.fragmentShader = dependencies.shaders[ program.fragmentShader ];
-
-		if ( ! materialParams.fragmentShader ) {
-
-			throw new Error( 'THREE.GLTF2Loader: Missing fragment shader definition: ' + program.fragmentShader );
-
-		}
-
-		var vertexShader = dependencies.shaders[ program.vertexShader ];
-
-		if ( ! vertexShader ) {
-
-			throw new Error( 'THREE.GLTF2Loader: Missing vertex shader definition: ' + program.vertexShader );
-
-		}
-
-		// IMPORTANT: FIX VERTEX SHADER ATTRIBUTE DEFINITIONS
-		materialParams.vertexShader = replaceTHREEShaderAttributes( vertexShader, technique );
-
-		var uniforms = technique.uniforms;
-
-		for ( var uniformId in uniforms ) {
-
-			var pname = uniforms[ uniformId ];
-			var shaderParam = technique.parameters[ pname ];
-
-			var ptype = shaderParam.type;
-
-			if ( WEBGL_TYPE[ ptype ] ) {
-
-				var pcount = shaderParam.count;
-				var value;
-
-				if ( material.values !== undefined ) value = material.values[ pname ];
-
-				var uvalue = new WEBGL_TYPE[ ptype ]();
-				var usemantic = shaderParam.semantic;
-				var unode = shaderParam.node;
-
-				switch ( ptype ) {
-
-					case WEBGL_CONSTANTS.FLOAT:
-
-						uvalue = shaderParam.value;
-
-						if ( pname === 'transparency' ) {
-
-							materialParams.transparent = true;
-
-						}
-
-						if ( value !== undefined ) {
-
-							uvalue = value;
-
-						}
-
-						break;
-
-					case WEBGL_CONSTANTS.FLOAT_VEC2:
-					case WEBGL_CONSTANTS.FLOAT_VEC3:
-					case WEBGL_CONSTANTS.FLOAT_VEC4:
-					case WEBGL_CONSTANTS.FLOAT_MAT3:
-
-						if ( shaderParam && shaderParam.value ) {
-
-							uvalue.fromArray( shaderParam.value );
-
-						}
-
-						if ( value ) {
-
-							uvalue.fromArray( value );
-
-						}
-
-						break;
-
-					case WEBGL_CONSTANTS.FLOAT_MAT2:
-
-						// what to do?
-						console.warn( 'THREE.GLTF2Loader: FLOAT_MAT2 is not a supported uniform type.' );
-						break;
-
-					case WEBGL_CONSTANTS.FLOAT_MAT4:
-
-						if ( pcount ) {
-
-							uvalue = new Array( pcount );
-
-							for ( var mi = 0; mi < pcount; mi ++ ) {
-
-								uvalue[ mi ] = new WEBGL_TYPE[ ptype ]();
-
-							}
-
-							if ( shaderParam && shaderParam.value ) {
-
-								var m4v = shaderParam.value;
-								uvalue.fromArray( m4v );
-
-							}
-
-							if ( value ) {
-
-								uvalue.fromArray( value );
-
-							}
-
-						} else {
-
-							if ( shaderParam && shaderParam.value ) {
-
-								var m4 = shaderParam.value;
-								uvalue.fromArray( m4 );
-
-							}
-
-							if ( value ) {
-
-								uvalue.fromArray( value );
-
-							}
-
-						}
-
-						break;
-
-					case WEBGL_CONSTANTS.SAMPLER_2D:
-
-						if ( value !== undefined ) {
-
-							uvalue = dependencies.textures[ value ];
-
-						} else if ( shaderParam.value !== undefined ) {
-
-							uvalue = dependencies.textures[ shaderParam.value ];
-
-						} else {
-
-							uvalue = null;
-
-						}
-
-						break;
-
-				}
-
-				materialParams.uniforms[ uniformId ] = {
-					value: uvalue,
-					semantic: usemantic,
-					node: unode
-				};
-
-			} else {
-
-				throw new Error( 'THREE.GLTF2Loader: Unknown shader uniform param type: ' + ptype );
-
-			}
-
-		}
-
-		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( 'THREE.GLTF2Loader: 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;
-
-		}
-
-	};
-
 	/**
 	/**
 	 * Specular-Glossiness Extension
 	 * Specular-Glossiness Extension
 	 *
 	 *
@@ -1181,13 +774,15 @@ THREE.GLTF2Loader = ( function () {
 		LINEAR: 9729,
 		LINEAR: 9729,
 		REPEAT: 10497,
 		REPEAT: 10497,
 		SAMPLER_2D: 35678,
 		SAMPLER_2D: 35678,
-		TRIANGLES: 4,
+		POINTS: 0,
 		LINES: 1,
 		LINES: 1,
+		LINE_LOOP: 2,
+		LINE_STRIP: 3,
+		TRIANGLES: 4,
+		TRIANGLE_STRIP: 5,
+		TRIANGLE_FAN: 6,
 		UNSIGNED_BYTE: 5121,
 		UNSIGNED_BYTE: 5121,
-		UNSIGNED_SHORT: 5123,
-
-		VERTEX_SHADER: 35633,
-		FRAGMENT_SHADER: 35632
+		UNSIGNED_SHORT: 5123
 	};
 	};
 
 
 	var WEBGL_TYPE = {
 	var WEBGL_TYPE = {
@@ -1463,105 +1058,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 	}
 	}
 
 
-	// Three.js seems too dependent on attribute names so globally
-	// replace those in the shader code
-	function replaceTHREEShaderAttributes( shaderText, technique ) {
-
-		// Expected technique attributes
-		var attributes = {};
-
-		for ( var attributeId in technique.attributes ) {
-
-			var pname = technique.attributes[ attributeId ];
-
-			var param = technique.parameters[ pname ];
-			var atype = param.type;
-			var semantic = param.semantic;
-
-			attributes[ attributeId ] = {
-				type: atype,
-				semantic: semantic
-			};
-
-		}
-
-		// Figure out which attributes to change in technique
-
-		var shaderParams = technique.parameters;
-		var shaderAttributes = technique.attributes;
-		var params = {};
-
-		for ( var attributeId in attributes ) {
-
-			var pname = shaderAttributes[ attributeId ];
-			var shaderParam = shaderParams[ pname ];
-			var semantic = shaderParam.semantic;
-			if ( semantic ) {
-
-				params[ attributeId ] = shaderParam;
-
-			}
-
-		}
-
-		for ( var pname in params ) {
-
-			var param = params[ pname ];
-			var semantic = param.semantic;
-
-			var regEx = new RegExp( '\\b' + pname + '\\b', 'g' );
-
-			switch ( semantic ) {
-
-				case 'POSITION':
-
-					shaderText = shaderText.replace( regEx, 'position' );
-					break;
-
-				case 'NORMAL':
-
-					shaderText = shaderText.replace( regEx, 'normal' );
-					break;
-
-				case 'TEXCOORD_0':
-				case 'TEXCOORD0':
-				case 'TEXCOORD':
-
-					shaderText = shaderText.replace( regEx, 'uv' );
-					break;
-
-				case 'TEXCOORD_1':
-
-					shaderText = shaderText.replace( regEx, 'uv2' );
-					break;
-
-				case 'COLOR_0':
-				case 'COLOR0':
-				case 'COLOR':
-
-					shaderText = shaderText.replace( regEx, 'color' );
-					break;
-
-				case 'WEIGHTS_0':
-				case 'WEIGHT': // WEIGHT semantic deprecated.
-
-					shaderText = shaderText.replace( regEx, 'skinWeight' );
-					break;
-
-				case 'JOINTS_0':
-				case 'JOINT': // JOINT semantic deprecated.
-
-					shaderText = shaderText.replace( regEx, 'skinIndex' );
-					break;
-
-			}
-
-		}
-
-		return shaderText;
-
-	}
-
 	/**
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
 	 */
 	 */
@@ -1698,41 +1194,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 	}
 	}
 
 
-	// Deferred constructor for RawShaderMaterial types
-	function DeferredShaderMaterial( params ) {
-
-		this.isDeferredShaderMaterial = true;
-
-		this.params = params;
-
-	}
-
-	DeferredShaderMaterial.prototype.create = function () {
-
-		var uniforms = THREE.UniformsUtils.clone( this.params.uniforms );
-
-		for ( var uniformId in this.params.uniforms ) {
-
-			var originalUniform = this.params.uniforms[ uniformId ];
-
-			if ( originalUniform.value instanceof THREE.Texture ) {
-
-				uniforms[ uniformId ].value = originalUniform.value;
-				uniforms[ uniformId ].value.needsUpdate = true;
-
-			}
-
-			uniforms[ uniformId ].semantic = originalUniform.semantic;
-			uniforms[ uniformId ].node = originalUniform.node;
-
-		}
-
-		this.params.uniforms = uniforms;
-
-		return new THREE.RawShaderMaterial( this.params );
-
-	};
-
 	/* GLTF PARSER */
 	/* GLTF PARSER */
 
 
 	function GLTFParser( json, extensions, options ) {
 	function GLTFParser( json, extensions, options ) {
@@ -1829,50 +1290,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 	};
 	};
 
 
-	GLTFParser.prototype.loadShaders = function () {
-
-		var json = this.json;
-		var options = this.options;
-		var extensions = this.extensions;
-
-		return this._withDependencies( [
-
-			'bufferViews'
-
-		] ).then( function ( dependencies ) {
-
-			var shaders = extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ] !== undefined ? extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ].shaders : json.shaders;
-
-			if ( shaders === undefined ) shaders = {};
-
-			return _each( shaders, function ( shader ) {
-
-				if ( shader.bufferView !== undefined ) {
-
-					var bufferView = dependencies.bufferViews[ shader.bufferView ];
-					var array = new Uint8Array( bufferView );
-					return convertUint8ArrayToString( array );
-
-				}
-
-				return new Promise( function ( resolve ) {
-
-					var loader = new THREE.FileLoader();
-					loader.setResponseType( 'text' );
-					loader.load( resolveURL( shader.uri, options.path ), function ( shaderText ) {
-
-						resolve( shaderText );
-
-					} );
-
-				} );
-
-			} );
-
-		} );
-
-	};
-
 	GLTFParser.prototype.loadBuffers = function () {
 	GLTFParser.prototype.loadBuffers = function () {
 
 
 		var json = this.json;
 		var json = this.json;
@@ -2081,7 +1498,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 		return this._withDependencies( [
 		return this._withDependencies( [
 
 
-			'shaders',
 			'textures'
 			'textures'
 
 
 		] ).then( function ( dependencies ) {
 		] ).then( function ( dependencies ) {
@@ -2227,6 +1643,8 @@ THREE.GLTF2Loader = ( function () {
 				// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materialnormaltexture
 				// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#materialnormaltexture
 				_material.normalScale.x = -1;
 				_material.normalScale.x = -1;
 
 
+				_material.userData = material.extras;
+
 				return _material;
 				return _material;
 
 
 			} );
 			} );
@@ -2237,8 +1655,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 	GLTFParser.prototype.loadGeometries = function ( primitives ) {
 	GLTFParser.prototype.loadGeometries = function ( primitives ) {
 
 
-		var extensions = this.extensions;
-
 		return this._withDependencies( [
 		return this._withDependencies( [
 
 
 			'accessors',
 			'accessors',
@@ -2393,13 +1809,35 @@ THREE.GLTF2Loader = ( function () {
 
 
 							mesh = new THREE.Mesh( geometry, material );
 							mesh = new THREE.Mesh( geometry, material );
 
 
+						} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
+
+							mesh = new THREE.Mesh( geometry, material );
+							mesh.drawMode = THREE.TriangleStripDrawMode;
+
+						} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
+
+							mesh = new THREE.Mesh( geometry, material );
+							mesh.drawMode = THREE.TriangleFanDrawMode;
+
 						} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
 						} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
 
 
 							mesh = new THREE.LineSegments( geometry, material );
 							mesh = new THREE.LineSegments( geometry, material );
 
 
+						} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_STRIP ) {
+
+							mesh = new THREE.Line( geometry, material );
+
+						} else if ( primitive.mode === WEBGL_CONSTANTS.LINE_LOOP ) {
+
+							mesh = new THREE.LineLoop( geometry, material );
+
+						} else if ( primitive.mode === WEBGL_CONSTANTS.POINTS ) {
+
+							mesh = new THREE.Points( geometry, material );
+
 						} else {
 						} else {
 
 
-							throw new Error( 'THREE.GLTF2Loader: Only TRIANGLE and LINE primitives are supported.' );
+							throw new Error( 'THREE.GLTF2Loader: Primitive mode unsupported: ', primitive.mode );
 
 
 						}
 						}
 
 
@@ -2731,6 +2169,7 @@ THREE.GLTF2Loader = ( function () {
 							for ( var childrenId in group.children ) {
 							for ( var childrenId in group.children ) {
 
 
 								var child = group.children[ childrenId ];
 								var child = group.children[ childrenId ];
+								var originalChild = child;
 
 
 								// clone Mesh to add to _node
 								// clone Mesh to add to _node
 
 
@@ -2740,17 +2179,7 @@ THREE.GLTF2Loader = ( function () {
 								var originalUserData = child.userData;
 								var originalUserData = child.userData;
 								var originalName = child.name;
 								var originalName = child.name;
 
 
-								var material;
-
-								if ( originalMaterial.isDeferredShaderMaterial ) {
-
-									originalMaterial = material = originalMaterial.create();
-
-								} else {
-
-									material = originalMaterial;
-
-								}
+								var material = originalMaterial;
 
 
 								switch ( child.type ) {
 								switch ( child.type ) {
 
 
@@ -2766,8 +2195,13 @@ THREE.GLTF2Loader = ( function () {
 										child = new THREE.Line( originalGeometry, material );
 										child = new THREE.Line( originalGeometry, material );
 										break;
 										break;
 
 
+									case 'Points':
+										child = new THREE.Points( originalGeometry, material );
+										break;
+
 									default:
 									default:
 										child = new THREE.Mesh( originalGeometry, material );
 										child = new THREE.Mesh( originalGeometry, material );
+										child.drawMode = originalChild.drawMode;
 
 
 								}
 								}
 
 
@@ -2914,16 +2348,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 				_scene.traverse( function ( child ) {
 				_scene.traverse( function ( child ) {
 
 
-					// Register raw material meshes with GLTF2Loader.Shaders
-					if ( child.material && child.material.isRawShaderMaterial ) {
-
-						child.gltfShader = new GLTFShader( child, dependencies.nodes );
-						child.onBeforeRender = function(renderer, scene, camera){
-							this.gltfShader.update(scene, camera);
-						};
-
-					}
-
 					// for Specular-Glossiness.
 					// for Specular-Glossiness.
 					if ( child.material && child.material.isGLTFSpecularGlossinessMaterial ) {
 					if ( child.material && child.material.isGLTFSpecularGlossinessMaterial ) {
 
 

+ 57 - 135
examples/js/loaders/OBJLoader.js

@@ -4,20 +4,6 @@
 
 
 THREE.OBJLoader = ( function () {
 THREE.OBJLoader = ( function () {
 
 
-	// v float float float
-	var vertex_pattern           = /^v\s+([\d\.\+\-eE]+)\s+([\d\.\+\-eE]+)\s+([\d\.\+\-eE]+)/;
-	// vn float float float
-	var normal_pattern           = /^vn\s+([\d\.\+\-eE]+)\s+([\d\.\+\-eE]+)\s+([\d\.\+\-eE]+)/;
-	// vt float float
-	var uv_pattern               = /^vt\s+([\d\.\+\-eE]+)\s+([\d\.\+\-eE]+)/;
-	// f vertex vertex vertex
-	var face_vertex              = /^f\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)(?:\s+(-?\d+))?/;
-	// f vertex/uv vertex/uv vertex/uv
-	var face_vertex_uv           = /^f\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+))?/;
-	// f vertex/uv/normal vertex/uv/normal vertex/uv/normal
-	var face_vertex_uv_normal    = /^f\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)\s+(-?\d+)\/(-?\d+)\/(-?\d+)(?:\s+(-?\d+)\/(-?\d+)\/(-?\d+))?/;
-	// f vertex//normal vertex//normal vertex//normal
-	var face_vertex_normal       = /^f\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)\s+(-?\d+)\/\/(-?\d+)(?:\s+(-?\d+)\/\/(-?\d+))?/;
 	// o object_name | g group_name
 	// o object_name | g group_name
 	var object_pattern           = /^[og]\s*(.+)?/;
 	var object_pattern           = /^[og]\s*(.+)?/;
 	// mtllib file_reference
 	// mtllib file_reference
@@ -69,7 +55,7 @@ THREE.OBJLoader = ( function () {
 					materials : [],
 					materials : [],
 					smooth : true,
 					smooth : true,
 
 
-					startMaterial : function( name, libraries ) {
+					startMaterial: function ( name, libraries ) {
 
 
 						var previous = this._finalize( false );
 						var previous = this._finalize( false );
 
 
@@ -91,7 +77,7 @@ THREE.OBJLoader = ( function () {
 							groupCount : -1,
 							groupCount : -1,
 							inherited  : false,
 							inherited  : false,
 
 
-							clone : function( index ) {
+							clone: function ( index ) {
 								var cloned = {
 								var cloned = {
 									index      : ( typeof index === 'number' ? index : this.index ),
 									index      : ( typeof index === 'number' ? index : this.index ),
 									name       : this.name,
 									name       : this.name,
@@ -113,7 +99,7 @@ THREE.OBJLoader = ( function () {
 
 
 					},
 					},
 
 
-					currentMaterial : function() {
+					currentMaterial: function () {
 
 
 						if ( this.materials.length > 0 ) {
 						if ( this.materials.length > 0 ) {
 							return this.materials[ this.materials.length - 1 ];
 							return this.materials[ this.materials.length - 1 ];
@@ -123,7 +109,7 @@ THREE.OBJLoader = ( function () {
 
 
 					},
 					},
 
 
-					_finalize : function( end ) {
+					_finalize: function ( end ) {
 
 
 						var lastMultiMaterial = this.currentMaterial();
 						var lastMultiMaterial = this.currentMaterial();
 						if ( lastMultiMaterial && lastMultiMaterial.groupEnd === -1 ) {
 						if ( lastMultiMaterial && lastMultiMaterial.groupEnd === -1 ) {
@@ -166,7 +152,7 @@ THREE.OBJLoader = ( function () {
 				// overwrite the inherited material. Exception being that there was already face declarations
 				// overwrite the inherited material. Exception being that there was already face declarations
 				// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
 				// to the inherited material, then it will be preserved for proper MultiMaterial continuation.
 
 
-				if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === "function" ) {
+				if ( previousMaterial && previousMaterial.name && typeof previousMaterial.clone === 'function' ) {
 
 
 					var declared = previousMaterial.clone( 0 );
 					var declared = previousMaterial.clone( 0 );
 					declared.inherited = true;
 					declared.inherited = true;
@@ -178,7 +164,7 @@ THREE.OBJLoader = ( function () {
 
 
 			},
 			},
 
 
-			finalize : function() {
+			finalize: function () {
 
 
 				if ( this.object && typeof this.object._finalize === 'function' ) {
 				if ( this.object && typeof this.object._finalize === 'function' ) {
 
 
@@ -229,7 +215,7 @@ THREE.OBJLoader = ( function () {
 
 
 			},
 			},
 
 
-			addNormal : function ( a, b, c ) {
+			addNormal: function ( a, b, c ) {
 
 
 				var src = this.normals;
 				var src = this.normals;
 				var dst = this.object.geometry.normals;
 				var dst = this.object.geometry.normals;
@@ -260,27 +246,15 @@ THREE.OBJLoader = ( function () {
 
 
 			},
 			},
 
 
-			addFace: function ( a, b, c, d, ua, ub, uc, ud, na, nb, nc, nd ) {
+			addFace: function ( a, b, c, ua, ub, uc, na, nb, nc ) {
 
 
 				var vLen = this.vertices.length;
 				var vLen = this.vertices.length;
 
 
 				var ia = this.parseVertexIndex( a, vLen );
 				var ia = this.parseVertexIndex( a, vLen );
 				var ib = this.parseVertexIndex( b, vLen );
 				var ib = this.parseVertexIndex( b, vLen );
 				var ic = this.parseVertexIndex( c, vLen );
 				var ic = this.parseVertexIndex( c, vLen );
-				var id;
 
 
-				if ( d === undefined ) {
-
-					this.addVertex( ia, ib, ic );
-
-				} else {
-
-					id = this.parseVertexIndex( d, vLen );
-
-					this.addVertex( ia, ib, id );
-					this.addVertex( ib, ic, id );
-
-				}
+				this.addVertex( ia, ib, ic );
 
 
 				if ( ua !== undefined ) {
 				if ( ua !== undefined ) {
 
 
@@ -290,18 +264,7 @@ THREE.OBJLoader = ( function () {
 					ib = this.parseUVIndex( ub, uvLen );
 					ib = this.parseUVIndex( ub, uvLen );
 					ic = this.parseUVIndex( uc, uvLen );
 					ic = this.parseUVIndex( uc, uvLen );
 
 
-					if ( d === undefined ) {
-
-						this.addUV( ia, ib, ic );
-
-					} else {
-
-						id = this.parseUVIndex( ud, uvLen );
-
-						this.addUV( ia, ib, id );
-						this.addUV( ib, ic, id );
-
-					}
+					this.addUV( ia, ib, ic );
 
 
 				}
 				}
 
 
@@ -314,18 +277,7 @@ THREE.OBJLoader = ( function () {
 					ib = na === nb ? ia : this.parseNormalIndex( nb, nLen );
 					ib = na === nb ? ia : this.parseNormalIndex( nb, nLen );
 					ic = na === nc ? ia : this.parseNormalIndex( nc, nLen );
 					ic = na === nc ? ia : this.parseNormalIndex( nc, nLen );
 
 
-					if ( d === undefined ) {
-
-						this.addNormal( ia, ib, ic );
-
-					} else {
-
-						id = this.parseNormalIndex( nd, nLen );
-
-						this.addNormal( ia, ib, id );
-						this.addNormal( ib, ic, id );
-
-					}
+					this.addNormal( ia, ib, ic );
 
 
 				}
 				}
 
 
@@ -423,7 +375,7 @@ THREE.OBJLoader = ( function () {
 			}
 			}
 
 
 			var lines = text.split( '\n' );
 			var lines = text.split( '\n' );
-			var line = '', lineFirstChar = '', lineSecondChar = '';
+			var line = '', lineFirstChar = '';
 			var lineLength = 0;
 			var lineLength = 0;
 			var result = [];
 			var result = [];
 
 
@@ -447,100 +399,70 @@ THREE.OBJLoader = ( function () {
 
 
 				if ( lineFirstChar === 'v' ) {
 				if ( lineFirstChar === 'v' ) {
 
 
-					lineSecondChar = line.charAt( 1 );
-
-					if ( lineSecondChar === ' ' && ( result = vertex_pattern.exec( line ) ) !== null ) {
-
-						// 0                  1      2      3
-						// ["v 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
-
-						state.vertices.push(
-							parseFloat( result[ 1 ] ),
-							parseFloat( result[ 2 ] ),
-							parseFloat( result[ 3 ] )
-						);
+					var data = line.split( /\s+/ );
+
+					switch ( data[ 0 ] ) {
+
+						case 'v':
+							state.vertices.push(
+								parseFloat( data[ 1 ] ),
+								parseFloat( data[ 2 ] ),
+								parseFloat( data[ 3 ] )
+							);
+							break;
+						case 'vn':
+							state.normals.push(
+								parseFloat( data[ 1 ] ),
+								parseFloat( data[ 2 ] ),
+								parseFloat( data[ 3 ] )
+							);
+						case 'vt':
+							state.uvs.push(
+								parseFloat( data[ 1 ] ),
+								parseFloat( data[ 2 ] )
+							);
+							break;
+					}
 
 
-					} else if ( lineSecondChar === 'n' && ( result = normal_pattern.exec( line ) ) !== null ) {
+				} else if ( lineFirstChar === 'f' ) {
 
 
-						// 0                   1      2      3
-						// ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"]
+					var lineData = line.substr( 1 ).trim();
+					var vertexData = lineData.split( /\s+/ );
+					var faceVertices = [];
 
 
-						state.normals.push(
-							parseFloat( result[ 1 ] ),
-							parseFloat( result[ 2 ] ),
-							parseFloat( result[ 3 ] )
-						);
+					// Parse the face vertex data into an easy to work with format
 
 
-					} else if ( lineSecondChar === 't' && ( result = uv_pattern.exec( line ) ) !== null ) {
+					for ( var j = 0, jl = vertexData.length; j < jl; j ++ ) {
 
 
-						// 0               1      2
-						// ["vt 0.1 0.2", "0.1", "0.2"]
+						var vertex = vertexData[ j ];
 
 
-						state.uvs.push(
-							parseFloat( result[ 1 ] ),
-							parseFloat( result[ 2 ] )
-						);
+						if ( vertex.length > 0 ) {
 
 
-					} else {
+							var vertexParts = vertex.split( '/' );
+							faceVertices.push( vertexParts );
 
 
-						throw new Error( "Unexpected vertex/normal/uv line: '" + line  + "'" );
+						}
 
 
 					}
 					}
 
 
-				} else if ( lineFirstChar === "f" ) {
+					// Draw an edge between the first vertex and all subsequent vertices to form an n-gon
 
 
-					if ( ( result = face_vertex_uv_normal.exec( line ) ) !== null ) {
+					var v1 = faceVertices[ 0 ];
 
 
-						// f vertex/uv/normal vertex/uv/normal vertex/uv/normal
-						// 0                        1    2    3    4    5    6    7    8    9   10         11         12
-						// ["f 1/1/1 2/2/2 3/3/3", "1", "1", "1", "2", "2", "2", "3", "3", "3", undefined, undefined, undefined]
+					for ( var j = 1, jl = faceVertices.length - 1; j < jl; j ++ ) {
 
 
-						state.addFace(
-							result[ 1 ], result[ 4 ], result[ 7 ], result[ 10 ],
-							result[ 2 ], result[ 5 ], result[ 8 ], result[ 11 ],
-							result[ 3 ], result[ 6 ], result[ 9 ], result[ 12 ]
-						);
-
-					} else if ( ( result = face_vertex_uv.exec( line ) ) !== null ) {
-
-						// f vertex/uv vertex/uv vertex/uv
-						// 0                  1    2    3    4    5    6   7          8
-						// ["f 1/1 2/2 3/3", "1", "1", "2", "2", "3", "3", undefined, undefined]
+						var v2 = faceVertices[ j ];
+						var v3 = faceVertices[ j + 1 ];
 
 
 						state.addFace(
 						state.addFace(
-							result[ 1 ], result[ 3 ], result[ 5 ], result[ 7 ],
-							result[ 2 ], result[ 4 ], result[ 6 ], result[ 8 ]
+							v1[ 0 ], v2[ 0 ], v3[ 0 ],
+							v1[ 1 ], v2[ 1 ], v3[ 1 ],
+							v1[ 2 ], v2[ 2 ], v3[ 2 ]
 						);
 						);
 
 
-					} else if ( ( result = face_vertex_normal.exec( line ) ) !== null ) {
-
-						// f vertex//normal vertex//normal vertex//normal
-						// 0                     1    2    3    4    5    6   7          8
-						// ["f 1//1 2//2 3//3", "1", "1", "2", "2", "3", "3", undefined, undefined]
-
-						state.addFace(
-							result[ 1 ], result[ 3 ], result[ 5 ], result[ 7 ],
-							undefined, undefined, undefined, undefined,
-							result[ 2 ], result[ 4 ], result[ 6 ], result[ 8 ]
-						);
-
-					} else if ( ( result = face_vertex.exec( line ) ) !== null ) {
-
-						// f vertex vertex vertex
-						// 0            1    2    3   4
-						// ["f 1 2 3", "1", "2", "3", undefined]
-
-						state.addFace(
-							result[ 1 ], result[ 2 ], result[ 3 ], result[ 4 ]
-						);
-
-					} else {
-
-						throw new Error( "Unexpected face line: '" + line  + "'" );
-
 					}
 					}
 
 
-				} else if ( lineFirstChar === "l" ) {
+				} else if ( lineFirstChar === 'l' ) {
 
 
 					var lineParts = line.substring( 1 ).trim().split( " " );
 					var lineParts = line.substring( 1 ).trim().split( " " );
 					var lineVertices = [], lineUVs = [];
 					var lineVertices = [], lineUVs = [];
@@ -587,7 +509,7 @@ THREE.OBJLoader = ( function () {
 
 
 					state.materialLibraries.push( line.substring( 7 ).trim() );
 					state.materialLibraries.push( line.substring( 7 ).trim() );
 
 
-				} else if ( lineFirstChar === "s" ) {
+				} else if ( lineFirstChar === 's' ) {
 
 
 					result = line.split( ' ' );
 					result = line.split( ' ' );
 
 

+ 82 - 145
examples/js/loaders/OBJLoader2.js

@@ -15,7 +15,7 @@ if ( THREE.OBJLoader2 === undefined ) { THREE.OBJLoader2 = {} }
  */
  */
 THREE.OBJLoader2 = (function () {
 THREE.OBJLoader2 = (function () {
 
 
-	var OBJLOADER2_VERSION = '1.3.1';
+	var OBJLOADER2_VERSION = '1.4.0';
 
 
 	function OBJLoader2( manager ) {
 	function OBJLoader2( manager ) {
 		console.log( "Using THREE.OBJLoader2 version: " + OBJLOADER2_VERSION );
 		console.log( "Using THREE.OBJLoader2 version: " + OBJLOADER2_VERSION );
@@ -189,23 +189,7 @@ THREE.OBJLoader2 = (function () {
 		LINE_VT: 'vt',
 		LINE_VT: 'vt',
 		LINE_VN: 'vn',
 		LINE_VN: 'vn',
 		LINE_MTLLIB: 'mtllib',
 		LINE_MTLLIB: 'mtllib',
-		LINE_USEMTL: 'usemtl',
-		/*
-		 * Build Face/Quad: first element in indexArray is the line identification, therefore offset of one needs to be taken into account
-		 * N-Gons are not supported
-		 * Quad Faces: FaceA: 0, 1, 2  FaceB: 2, 3, 0
-		 *
-		 * 0: "f vertex/uv/normal	vertex/uv/normal	vertex/uv/normal	(vertex/uv/normal)"
-		 * 1: "f vertex/uv		  	vertex/uv		   	vertex/uv		   	(vertex/uv		 )"
-		 * 2: "f vertex//normal	 	vertex//normal	  	vertex//normal	  	(vertex//normal  )"
-		 * 3: "f vertex			 	vertex			  	vertex			  	(vertex		  	 )"
-		 *
-		 * @param indexArray
-		 * @param faceType
-		 */
-		QUAD_INDICES_1: [ 1, 2, 3, 3, 4, 1 ],
-		QUAD_INDICES_2: [ 1, 3, 5, 5, 7, 1 ],
-		QUAD_INDICES_3: [ 1, 4, 7, 7, 10, 1 ]
+		LINE_USEMTL: 'usemtl'
 	};
 	};
 
 
 	var Validator = {
 	var Validator = {
@@ -265,10 +249,9 @@ THREE.OBJLoader2 = (function () {
 		Parser.prototype.parseArrayBuffer = function ( arrayBuffer ) {
 		Parser.prototype.parseArrayBuffer = function ( arrayBuffer ) {
 			var arrayBufferView = new Uint8Array( arrayBuffer );
 			var arrayBufferView = new Uint8Array( arrayBuffer );
 			var length = arrayBufferView.byteLength;
 			var length = arrayBufferView.byteLength;
-			var buffer = new Array( 32 );
+			var buffer = new Array( 128 );
 			var bufferPointer = 0;
 			var bufferPointer = 0;
-			var slashes = new Array( 32 );
-			var slashesPointer = 0;
+			var slashesCount = 0;
 			var reachedFaces = false;
 			var reachedFaces = false;
 			var code;
 			var code;
 			var word = '';
 			var word = '';
@@ -282,7 +265,7 @@ THREE.OBJLoader2 = (function () {
 						break;
 						break;
 
 
 					case Consts.CODE_SLASH:
 					case Consts.CODE_SLASH:
-						slashes[ slashesPointer++ ] = i;
+						slashesCount++;
 						if ( word.length > 0 ) buffer[ bufferPointer++ ] = word;
 						if ( word.length > 0 ) buffer[ bufferPointer++ ] = word;
 						word = '';
 						word = '';
 						break;
 						break;
@@ -290,9 +273,9 @@ THREE.OBJLoader2 = (function () {
 					case Consts.CODE_LF:
 					case Consts.CODE_LF:
 						if ( word.length > 0 ) buffer[ bufferPointer++ ] = word;
 						if ( word.length > 0 ) buffer[ bufferPointer++ ] = word;
 						word = '';
 						word = '';
-						reachedFaces = this.processLine( buffer, bufferPointer, slashes, slashesPointer, reachedFaces );
-						slashesPointer = 0;
+						reachedFaces = this.processLine( buffer, bufferPointer, slashesCount, reachedFaces );
 						bufferPointer = 0;
 						bufferPointer = 0;
+						slashesCount = 0;
 						break;
 						break;
 
 
 					case Consts.CODE_CR:
 					case Consts.CODE_CR:
@@ -313,10 +296,9 @@ THREE.OBJLoader2 = (function () {
 		 */
 		 */
 		Parser.prototype.parseText = function ( text ) {
 		Parser.prototype.parseText = function ( text ) {
 			var length = text.length;
 			var length = text.length;
-			var buffer = new Array( 32 );
+			var buffer = new Array( 128 );
 			var bufferPointer = 0;
 			var bufferPointer = 0;
-			var slashes = new Array( 32 );
-			var slashesPointer = 0;
+			var slashesCount = 0;
 			var reachedFaces = false;
 			var reachedFaces = false;
 			var char;
 			var char;
 			var word = '';
 			var word = '';
@@ -330,7 +312,7 @@ THREE.OBJLoader2 = (function () {
 						break;
 						break;
 
 
 					case Consts.STRING_SLASH:
 					case Consts.STRING_SLASH:
-						slashes[ slashesPointer++ ] = i;
+						slashesCount++;
 						if ( word.length > 0 ) buffer[ bufferPointer++ ] = word;
 						if ( word.length > 0 ) buffer[ bufferPointer++ ] = word;
 						word = '';
 						word = '';
 						break;
 						break;
@@ -338,9 +320,9 @@ THREE.OBJLoader2 = (function () {
 					case Consts.STRING_LF:
 					case Consts.STRING_LF:
 						if ( word.length > 0 ) buffer[ bufferPointer++ ] = word;
 						if ( word.length > 0 ) buffer[ bufferPointer++ ] = word;
 						word = '';
 						word = '';
-						reachedFaces = this.processLine( buffer, bufferPointer, slashes, slashesPointer, reachedFaces );
-						slashesPointer = 0;
+						reachedFaces = this.processLine( buffer, bufferPointer, slashesCount, reachedFaces );
 						bufferPointer = 0;
 						bufferPointer = 0;
+						slashesCount = 0;
 						break;
 						break;
 
 
 					case Consts.STRING_CR:
 					case Consts.STRING_CR:
@@ -352,7 +334,7 @@ THREE.OBJLoader2 = (function () {
 			}
 			}
 		};
 		};
 
 
-		Parser.prototype.processLine = function ( buffer, bufferPointer, slashes, slashesPointer, reachedFaces ) {
+		Parser.prototype.processLine = function ( buffer, bufferPointer, slashesCount, reachedFaces ) {
 			if ( bufferPointer < 1 ) return reachedFaces;
 			if ( bufferPointer < 1 ) return reachedFaces;
 
 
 			var bufferLength = bufferPointer - 1;
 			var bufferLength = bufferPointer - 1;
@@ -393,50 +375,11 @@ THREE.OBJLoader2 = (function () {
 
 
 				case Consts.LINE_F:
 				case Consts.LINE_F:
 					reachedFaces = true;
 					reachedFaces = true;
-					/*
-					 * 0: "f vertex/uv/normal ..."
-					 * 1: "f vertex/uv ..."
-					 * 2: "f vertex//normal ..."
-					 * 3: "f vertex ..."
-					 */
-					var haveQuad = bufferLength % 4 === 0;
-					if ( slashesPointer > 1 && ( slashes[ 1 ] - slashes[ 0 ] ) === 1 ) {
-
-						if ( haveQuad ) {
-							this.rawObject.buildQuadVVn( buffer );
-						} else {
-							this.rawObject.buildFaceVVn( buffer );
-						}
-
-					} else if ( bufferLength === slashesPointer * 2 ) {
-
-						if ( haveQuad ) {
-							this.rawObject.buildQuadVVt( buffer );
-						} else {
-							this.rawObject.buildFaceVVt( buffer );
-						}
-
-					} else if ( bufferLength * 2 === slashesPointer * 3 ) {
-
-						if ( haveQuad ) {
-							this.rawObject.buildQuadVVtVn( buffer );
-						} else {
-							this.rawObject.buildFaceVVtVn( buffer );
-						}
-
-					} else {
-
-						if ( haveQuad ) {
-							this.rawObject.buildQuadV( buffer );
-						} else {
-							this.rawObject.buildFaceV( buffer );
-						}
-
-					}
+					this.rawObject.processFaces( buffer, bufferPointer, slashesCount );
 					break;
 					break;
 
 
 				case Consts.LINE_L:
 				case Consts.LINE_L:
-					if ( bufferLength === slashesPointer * 2 ) {
+					if ( bufferLength === slashesCount * 2 ) {
 
 
 						this.rawObject.buildLineVvt( buffer );
 						this.rawObject.buildLineVvt( buffer );
 
 
@@ -660,98 +603,92 @@ THREE.OBJLoader2 = (function () {
 			}
 			}
 		};
 		};
 
 
-		RawObject.prototype.buildQuadVVtVn = function ( indexArray ) {
-			for ( var i = 0; i < 6; i ++ ) {
-				this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_3[ i ] ] );
-				this.attachFaceVt( indexArray[ Consts.QUAD_INDICES_3[ i ] + 1 ] );
-				this.attachFaceVn( indexArray[ Consts.QUAD_INDICES_3[ i ] + 2 ] );
-			}
-		};
+		RawObject.prototype.processFaces = function ( buffer, bufferPointer, slashesCount ) {
+			var bufferLength = bufferPointer - 1;
+			var i;
 
 
-		RawObject.prototype.buildQuadVVt = function ( indexArray ) {
-			for ( var i = 0; i < 6; i ++ ) {
-				this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_2[ i ] ] );
-				this.attachFaceVt( indexArray[ Consts.QUAD_INDICES_2[ i ] + 1 ] );
-			}
-		};
+			// "f vertex ..."
+			if ( slashesCount === 0 ) {
 
 
-		RawObject.prototype.buildQuadVVn = function ( indexArray ) {
-			for ( var i = 0; i < 6; i ++ ) {
-				this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_2[ i ] ] );
-				this.attachFaceVn( indexArray[ Consts.QUAD_INDICES_2[ i ] + 1 ] );
-			}
-		};
+				for ( i = 2; i < bufferLength - 1; i ++ ) {
 
 
-		RawObject.prototype.buildQuadV = function ( indexArray ) {
-			for ( var i = 0; i < 6; i ++ ) {
-				this.attachFaceV_( indexArray[ Consts.QUAD_INDICES_1[ i ] ] );
-			}
-		};
+					this.attachFace( buffer[ 1     ] );
+					this.attachFace( buffer[ i     ] );
+					this.attachFace( buffer[ i + 1 ] );
 
 
-		RawObject.prototype.buildFaceVVtVn = function ( indexArray ) {
-			for ( var i = 1; i < 10; i += 3 ) {
-				this.attachFaceV_( indexArray[ i ] );
-				this.attachFaceVt( indexArray[ i + 1 ] );
-				this.attachFaceVn( indexArray[ i + 2 ] );
-			}
-		};
+				}
 
 
-		RawObject.prototype.buildFaceVVt = function ( indexArray ) {
-			for ( var i = 1; i < 7; i += 2 ) {
-				this.attachFaceV_( indexArray[ i ] );
-				this.attachFaceVt( indexArray[ i + 1 ] );
-			}
-		};
+				// "f vertex/uv ..."
+			} else if  ( bufferLength === slashesCount * 2 ) {
 
 
-		RawObject.prototype.buildFaceVVn = function ( indexArray ) {
-			for ( var i = 1; i < 7; i += 2 ) {
-				this.attachFaceV_( indexArray[ i ] );
-				this.attachFaceVn( indexArray[ i + 1 ] );
-			}
-		};
+				for ( i = 3; i < bufferLength - 2; i += 2 ) {
+
+					this.attachFace( buffer[ 1     ], buffer[ 2     ] );
+					this.attachFace( buffer[ i     ], buffer[ i + 1 ] );
+					this.attachFace( buffer[ i + 2 ], buffer[ i + 3 ] );
+
+				}
+
+				// "f vertex/uv/normal ..."
+			} else if  ( bufferLength * 2 === slashesCount * 3 ) {
+
+				for ( i = 4; i < bufferLength - 3; i += 3 ) {
+
+					this.attachFace( buffer[ 1     ], buffer[ 2     ], buffer[ 3     ] );
+					this.attachFace( buffer[ i     ], buffer[ i + 1 ], buffer[ i + 2 ] );
+					this.attachFace( buffer[ i + 3 ], buffer[ i + 4 ], buffer[ i + 5 ] );
+
+				}
+
+				// "f vertex//normal ..."
+			} else {
+
+				for ( i = 3; i < bufferLength - 2; i += 2 ) {
+
+					this.attachFace( buffer[ 1     ], undefined, buffer[ 2     ] );
+					this.attachFace( buffer[ i     ], undefined, buffer[ i + 1 ] );
+					this.attachFace( buffer[ i + 2 ], undefined, buffer[ i + 3 ] );
+
+				}
 
 
-		RawObject.prototype.buildFaceV = function ( indexArray ) {
-			for ( var i = 1; i < 4; i ++ ) {
-				this.attachFaceV_( indexArray[ i ] );
 			}
 			}
 		};
 		};
 
 
-		RawObject.prototype.attachFaceV_ = function ( faceIndex ) {
-			var faceIndexInt = parseInt( faceIndex );
-			var index = ( faceIndexInt - this.globalVertexOffset ) * 3;
-
-			var rodiu = this.rawObjectDescriptionInUse;
-			rodiu.vertices.push( this.vertices[ index++ ] );
-			rodiu.vertices.push( this.vertices[ index++ ] );
-			rodiu.vertices.push( this.vertices[ index ] );
+		RawObject.prototype.attachFace = function ( faceIndexV, faceIndexU, faceIndexN ) {
+			var indexV = ( parseInt( faceIndexV ) - this.globalVertexOffset ) * 3;
+			var vertices = this.rawObjectDescriptionInUse.vertices;
+			vertices.push( this.vertices[ indexV ++ ] );
+			vertices.push( this.vertices[ indexV ++ ] );
+			vertices.push( this.vertices[ indexV ] );
 
 
 			if ( this.colors.length > 0 ) {
 			if ( this.colors.length > 0 ) {
 
 
-				index -= 2;
-				rodiu.colors.push( this.colors[ index++ ] );
-				rodiu.colors.push( this.colors[ index++ ] );
-				rodiu.colors.push( this.colors[ index ] );
+				indexV -= 2;
+				var colors = this.rawObjectDescriptionInUse.colors;
+				colors.push( this.colors[ indexV ++ ] );
+				colors.push( this.colors[ indexV ++ ] );
+				colors.push( this.colors[ indexV ] );
 
 
 			}
 			}
-		};
 
 
-		RawObject.prototype.attachFaceVt = function ( faceIndex ) {
-			var faceIndexInt = parseInt( faceIndex );
-			var index = ( faceIndexInt - this.globalUvOffset ) * 2;
+			if ( faceIndexU ) {
 
 
-			var rodiu = this.rawObjectDescriptionInUse;
-			rodiu.uvs.push( this.uvs[ index++ ] );
-			rodiu.uvs.push( this.uvs[ index ] );
-		};
+				var indexU = ( parseInt( faceIndexU ) - this.globalUvOffset ) * 2;
+				var uvs = this.rawObjectDescriptionInUse.uvs;
+				uvs.push( this.uvs[ indexU ++ ] );
+				uvs.push( this.uvs[ indexU ] );
+
+			}
+
+			if ( faceIndexN ) {
 
 
-		RawObject.prototype.attachFaceVn = function ( faceIndex ) {
-			var faceIndexInt = parseInt( faceIndex );
-			var index = ( faceIndexInt - this.globalNormalOffset ) * 3;
+				var indexN = ( parseInt( faceIndexN ) - this.globalNormalOffset ) * 3;
+				var normals = this.rawObjectDescriptionInUse.normals;
+				normals.push( this.normals[ indexN ++ ] );
+				normals.push( this.normals[ indexN ++ ] );
+				normals.push( this.normals[ indexN ] );
 
 
-			var rodiu = this.rawObjectDescriptionInUse;
-			rodiu.normals.push( this.normals[ index++ ] );
-			rodiu.normals.push( this.normals[ index++ ] );
-			rodiu.normals.push( this.normals[ index ] );
+			}
 		};
 		};
 
 
 		/*
 		/*

+ 2 - 2
examples/js/loaders/PCDLoader.js

@@ -36,7 +36,7 @@ THREE.PCDLoader.prototype = {
 
 
 	parse: function ( data, url ) {
 	parse: function ( data, url ) {
 
 
-		function binarryToStr( data ) {
+		function binaryToStr( data ) {
 
 
 			var charArray = new Uint8Array( data );
 			var charArray = new Uint8Array( data );
 
 
@@ -167,7 +167,7 @@ THREE.PCDLoader.prototype = {
 
 
 		}
 		}
 
 
-		var textData = binarryToStr( data );
+		var textData = binaryToStr( data );
 
 
 		// parse header (always ascii format)
 		// parse header (always ascii format)
 
 

+ 1 - 1
examples/js/loaders/WWOBJLoader2.js

@@ -15,7 +15,7 @@ if ( THREE.OBJLoader2 === undefined ) { THREE.OBJLoader2 = {} }
  */
  */
 THREE.OBJLoader2.WWOBJLoader2 = (function () {
 THREE.OBJLoader2.WWOBJLoader2 = (function () {
 
 
-	var WWOBJLOADER2_VERSION = '1.3.1';
+	var WWOBJLOADER2_VERSION = '1.4.0';
 
 
 	var Validator = THREE.OBJLoader2.prototype._getValidator();
 	var Validator = THREE.OBJLoader2.prototype._getValidator();
 
 

+ 1 - 1
examples/js/renderers/CSS3DRenderer.js

@@ -261,7 +261,7 @@ THREE.CSS3DRenderer = function () {
 
 
 	this.render = function ( scene, camera ) {
 	this.render = function ( scene, camera ) {
 
 
-		var fov = 0.5 / Math.tan( THREE.Math.degToRad( camera.getEffectiveFOV() * 0.5 ) ) * _height;
+		var fov = camera.projectionMatrix.elements[ 5 ] * _heightHalf;
 
 
 		if ( cache.camera.fov !== fov ) {
 		if ( cache.camera.fov !== fov ) {
 
 

+ 17 - 17
examples/misc_sound.html

@@ -6,35 +6,35 @@
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
 		<style>
 			body {
 			body {
-				background-color: #000000;
-				margin: 0px;
-				overflow: hidden;
-
-				font-family:Monospace;
-				font-size:13px;
+				background:#777;
+				padding:0;
+				margin:0;
 				font-weight: bold;
 				font-weight: bold;
-				text-align: center;
-			}
-
-			a {
-				color: #0078ff;
+				overflow:hidden;
 			}
 			}
 
 
 			#info {
 			#info {
-				color:#fff;
 				position: absolute;
 				position: absolute;
-				top: 0px; left: 0px; width: 50%;
+				top: 0px;
+				width: 100%;
+				color: #ffffff;
 				padding: 5px;
 				padding: 5px;
-				z-index:100;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+			}
+
+			a {
+				color: #ffffff;
 			}
 			}
 		</style>
 		</style>
 	</head>
 	</head>
 	<body>
 	<body>
 
 
 		<div id="info">
 		<div id="info">
-			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl 3d sounds example -
-			music by <a href="http://www.newgrounds.com/audio/listen/358232" target="_blank" rel="noopener">larrylarrybb</a> and
-			<a href="http://www.newgrounds.com/audio/listen/376737" target="_blank" rel="noopener">skullbeatz</a>  and
+			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - webgl 3d sounds -
+			music by <a href="http://www.newgrounds.com/audio/listen/358232" target="_blank" rel="noopener">larrylarrybb</a>,
+			<a href="http://www.newgrounds.com/audio/listen/376737" target="_blank" rel="noopener">skullbeatz</a> and
 			<a href="http://opengameart.org/content/project-utopia-seamless-loop" target="_blank" rel="noopener">congusbongus</a><br/><br/>
 			<a href="http://opengameart.org/content/project-utopia-seamless-loop" target="_blank" rel="noopener">congusbongus</a><br/><br/>
 			navigate with WASD / arrows / mouse
 			navigate with WASD / arrows / mouse
 		</div>
 		</div>

+ 185 - 0
examples/misc_sound_visualizer.html

@@ -0,0 +1,185 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js misc - sound visualizer</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				background:#777;
+				padding:0;
+				margin:0;
+				font-weight: bold;
+				overflow:hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px;
+				width: 100%;
+				color: #ffffff;
+				padding: 5px;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+			}
+
+			a {
+				color: #ffffff;
+			}
+		</style>
+
+		<script src="../build/three.js"></script>
+		<script src="js/Detector.js"></script>
+
+		<script id="vertexShader" type="x-shader/x-vertex">
+
+			varying vec2 vUv;
+
+			void main() {
+
+				vUv = uv;
+				gl_Position = vec4( position, 1.0 );
+
+			}
+
+		</script>
+
+		<script id="fragmentShader" type="x-shader/x-fragment">
+
+			uniform sampler2D tAudioData;
+
+			varying vec2 vUv;
+
+			void main() {
+
+				vec3 backgroundColor = vec3( 0.0 );
+				vec3 color = vec3( 1.0, 0.0, 0.0 );
+
+				float f = texture2D( tAudioData, vec2( vUv.x, 0.0 ) ).r; // sample data texture (only the red channel is relevant)
+				float i = step( vUv.y, f );
+
+				gl_FragColor = vec4( mix( backgroundColor, color, i ), 1.0 );
+
+			}
+
+		</script>
+
+	</head>
+<body>
+
+	<div id="container"></div>
+	<div id="info">
+		<a href="https://threejs.org" target="_blank">three.js</a> - misc - sound visualizer -
+		music by <a href="http://www.newgrounds.com/audio/listen/358232" target="_blank">larrylarrybb</a>
+	</div>
+
+	<script>
+
+	if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+	var scene, camera, renderer, analyser, uniforms;
+
+	init();
+	animate();
+
+	function init() {
+
+		var fftSize = 2048;
+
+		//
+
+		var container = document.getElementById( 'container' );
+
+		//
+
+		scene = new THREE.Scene();
+
+		//
+
+		renderer = new THREE.WebGLRenderer( { antialias: true } );
+		renderer.setSize( window.innerWidth, window.innerHeight );
+		renderer.setClearColor( 0x000000 );
+		renderer.setPixelRatio( window.devicePixelRatio );
+		container.appendChild( renderer.domElement );
+
+		//
+
+		camera = new THREE.Camera();
+		camera.position.z = 1;
+
+		//
+
+		var audioLoader = new THREE.AudioLoader();
+
+		var listener = new THREE.AudioListener();
+		camera.add( listener );
+
+		var audio = new THREE.Audio( listener );
+		audioLoader.load( 'sounds/358232_j_s_song.mp3', function( buffer ) {
+			audio.setBuffer( buffer );
+			audio.setLoop( true );
+			audio.play();
+		});
+
+		analyser = new THREE.AudioAnalyser( audio, fftSize );
+
+		//
+
+		var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
+
+		//
+
+		var size = fftSize / 2;
+
+		uniforms = {
+			tAudioData: { value: new THREE.DataTexture( analyser.data, size, 1, THREE.LuminanceFormat ) }
+		};
+
+		var material = new THREE.ShaderMaterial( {
+
+			uniforms: uniforms,
+			vertexShader: document.getElementById( 'vertexShader' ).textContent,
+			fragmentShader: document.getElementById( 'fragmentShader' ).textContent
+
+		} );
+
+		//
+
+		var mesh = new THREE.Mesh( geometry, material );
+		scene.add( mesh );
+
+		//
+
+		window.addEventListener( 'resize', onResize, false );
+
+	}
+
+	function onResize() {
+
+		renderer.setSize( window.innerWidth, window.innerHeight );
+
+	}
+
+	function animate() {
+
+		requestAnimationFrame( animate );
+
+		render();
+
+	}
+
+	function render() {
+
+		var data = analyser.getFrequencyData();
+
+		uniforms.tAudioData.value.needsUpdate = true;
+
+		renderer.render( scene, camera );
+
+	}
+
+	</script>
+
+</body>
+</html>

+ 9 - 9
examples/models/assimp/interior/interior.assimp.json

@@ -2373,9 +2373,9 @@
 					,"index": 0
 					,"index": 0
 					,"type": 1
 					,"type": 1
 					,"value": [
 					,"value": [
-						 0.898039
-						,0.898039
-						,0.898039
+						 0.1
+						,0.1
+						,0.1
 					]
 					]
 				}
 				}
 				,{
 				,{
@@ -2490,9 +2490,9 @@
 					,"index": 0
 					,"index": 0
 					,"type": 1
 					,"type": 1
 					,"value": [
 					,"value": [
-						 0.898039
-						,0.898039
-						,0.898039
+						 0.1
+						,0.1
+						,0.1
 					]
 					]
 				}
 				}
 				,{
 				,{
@@ -2607,9 +2607,9 @@
 					,"index": 0
 					,"index": 0
 					,"type": 1
 					,"type": 1
 					,"value": [
 					,"value": [
-						 0.898039
-						,0.898039
-						,0.898039
+						 0.1
+						,0.1
+						,0.1
 					]
 					]
 				}
 				}
 				,{
 				,{

+ 1 - 1
examples/webgl_loader_assimp.html

@@ -93,7 +93,7 @@
 			container.appendChild( stats.dom );
 			container.appendChild( stats.dom );
 
 
 			var loader = new THREE.AssimpLoader();
 			var loader = new THREE.AssimpLoader();
-			loader.load( "./models/assimp/octaminator/Octaminator.assimp", function ( err, result ) {
+			loader.load( './models/assimp/octaminator/Octaminator.assimp', function ( result ) {
 
 
 				var object = result.object;
 				var object = result.object;
 
 

+ 35 - 45
examples/webgl_loader_assimp2json.html

@@ -68,84 +68,75 @@
 
 
 			*/
 			*/
 
 
-			var container, stats;
-			var camera, scene, renderer, objects;
-			var clock = new THREE.Clock();
+			var container, stats, clock;
+			var camera, scene, renderer;
 
 
-			// init scene
 			init();
 			init();
+			animate();
 
 
-			var onProgress = function ( xhr ) {
-				if ( xhr.lengthComputable ) {
-					var percentComplete = xhr.loaded / xhr.total * 100;
-					console.log( Math.round(percentComplete, 2) + '% downloaded' );
-				}
-			};
+			//
 
 
-			var onError = function ( xhr ) {
-			};
+			function init() {
 
 
-			// Load jeep model using the AssimpJSONLoader
-			var loader1 = new THREE.AssimpJSONLoader();
-			loader1.load( 'models/assimp/jeep/jeep.assimp.json', function ( object ) {
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
 
 
-				object.scale.multiplyScalar( 0.2 );
-				scene.add( object );
+				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
 
 
-			}, onProgress, onError );
+				scene = new THREE.Scene();
 
 
-			// load interior model
-			var loader2 = new THREE.AssimpJSONLoader();
-			loader2.load( 'models/assimp/interior/interior.assimp.json', function ( object ) {
+				clock = new THREE.Clock();
 
 
-				scene.add( object );
+				// load jeep model
 
 
-			}, onProgress, onError );
+				var loader1 = new THREE.AssimpJSONLoader();
+				loader1.load( 'models/assimp/jeep/jeep.assimp.json', function ( object ) {
 
 
-			animate();
+					object.scale.multiplyScalar( 0.2 );
+					scene.add( object );
 
 
+				} );
 
 
-			//
+				// load interior model
 
 
-			function init() {
+				var loader2 = new THREE.AssimpJSONLoader();
+				loader2.load( 'models/assimp/interior/interior.assimp.json', function ( object ) {
 
 
-				container = document.createElement( 'div' );
-				document.body.appendChild( container );
+					scene.add( object );
 
 
-				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 2000 );
-				camera.position.set( 2, 4, 5 );
+				} );
 
 
-				scene = new THREE.Scene();
-				scene.fog = new THREE.FogExp2( 0x000000, 0.035 );
+				//
 
 
-				// Lights
-				scene.add( new THREE.AmbientLight( 0xcccccc ) );
+				var ambientLight = new THREE.AmbientLight( 0xcccccc, 0.4 );
+				scene.add( ambientLight );
 
 
 				var directionalLight = new THREE.DirectionalLight( 0xeeeeee );
 				var directionalLight = new THREE.DirectionalLight( 0xeeeeee );
-				directionalLight.position.x = Math.random() - 0.5;
-				directionalLight.position.y = Math.random();
-				directionalLight.position.z = Math.random() - 0.5;
+				directionalLight.position.set( 1, 1, - 1 );
 				directionalLight.position.normalize();
 				directionalLight.position.normalize();
 				scene.add( directionalLight );
 				scene.add( directionalLight );
 
 
-				// Renderer
+				//
+
 				renderer = new THREE.WebGLRenderer();
 				renderer = new THREE.WebGLRenderer();
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 
-				// Stats
+				//
+
 				stats = new Stats();
 				stats = new Stats();
 				container.appendChild( stats.dom );
 				container.appendChild( stats.dom );
 
 
-				// Events
+				//
+
 				window.addEventListener( 'resize', onWindowResize, false );
 				window.addEventListener( 'resize', onWindowResize, false );
 
 
 			}
 			}
 
 
 			//
 			//
 
 
-			function onWindowResize( event ) {
+			function onWindowResize() {
 
 
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
@@ -156,7 +147,6 @@
 
 
 			//
 			//
 
 
-			var t = 0;
 			function animate() {
 			function animate() {
 
 
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
@@ -169,11 +159,11 @@
 
 
 			function render() {
 			function render() {
 
 
-				var timer = Date.now() * 0.0005;
+				var elapsedTime = clock.getElapsedTime();
 
 
-				camera.position.x = Math.cos( timer ) * 10;
+				camera.position.x = Math.cos( elapsedTime * 0.5 ) * 10;
 				camera.position.y = 4;
 				camera.position.y = 4;
-				camera.position.z = Math.sin( timer ) * 10;
+				camera.position.z = Math.sin( elapsedTime * 0.5 ) * 10;
 
 
 				camera.lookAt( scene.position );
 				camera.lookAt( scene.position );
 
 

+ 4 - 6
examples/webgl_loader_gltf2.html

@@ -91,7 +91,6 @@
 				<option value="glTF-Binary">None (Binary)</option>
 				<option value="glTF-Binary">None (Binary)</option>
 				<option value="glTF-MaterialsCommon">Common Materials</option>
 				<option value="glTF-MaterialsCommon">Common Materials</option>
 				<option value="glTF-pbrSpecularGlossiness">Specular-Glossiness (PBR)</option>
 				<option value="glTF-pbrSpecularGlossiness">Specular-Glossiness (PBR)</option>
-				<option value="glTF-techniqueWebGL">GLSL</option>
 			</select>
 			</select>
 		</div>
 		</div>
 	</div>
 	</div>
@@ -436,7 +435,6 @@
 					addLights:true,
 					addLights:true,
 					addGround:true,
 					addGround:true,
 					shadows:true,
 					shadows:true,
-					// TODO: 'glTF-techniqueWebGL'
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-MaterialsCommon', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-MaterialsCommon', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 				},
 				},
 				{
 				{
@@ -449,7 +447,7 @@
 					addLights:true,
 					addLights:true,
 					shadows:true,
 					shadows:true,
 					addGround:true,
 					addGround:true,
-					// TODO: 'glTF-MaterialsCommon', 'glTF-techniqueWebGL'
+					// TODO: 'glTF-MaterialsCommon'
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 				},
 				},
 				{
 				{
@@ -459,7 +457,7 @@
 					 addLights:true,
 					 addLights:true,
 					 addGround:true,
 					 addGround:true,
 					 shadows:true,
 					 shadows:true,
-					// TODO: 'glTF-MaterialsCommon', 'glTF-techniqueWebGL'
+					// TODO: 'glTF-MaterialsCommon'
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 				},
 				},
 				{
 				{
@@ -469,7 +467,7 @@
 					addLights:true,
 					addLights:true,
 					addGround:true,
 					addGround:true,
 					shadows:true,
 					shadows:true,
-					// TODO: 'glTF-MaterialsCommon', 'glTF-techniqueWebGL'
+					// TODO: 'glTF-MaterialsCommon'
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 				},
 				},
 				{
 				{
@@ -479,7 +477,7 @@
 					objectRotation: new THREE.Euler(0, 90, 0),
 					objectRotation: new THREE.Euler(0, 90, 0),
 					addLights:true,
 					addLights:true,
 					shadows:true,
 					shadows:true,
-					// TODO: 'glTF-MaterialsCommon', 'glTF-techniqueWebGL'
+					// TODO: 'glTF-MaterialsCommon'
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 					extensions: ['glTF', 'glTF-Embedded', 'glTF-pbrSpecularGlossiness', 'glTF-Binary']
 				},
 				},
 				{
 				{

+ 2 - 2
src/core/Object3D.js

@@ -373,7 +373,7 @@ Object.assign( Object3D.prototype, EventDispatcher.prototype, {
 		}
 		}
 
 
 		return this;
 		return this;
-		
+
 	},
 	},
 
 
 	getObjectById: function ( id ) {
 	getObjectById: function ( id ) {
@@ -613,10 +613,10 @@ Object.assign( Object3D.prototype, EventDispatcher.prototype, {
 		object.type = this.type;
 		object.type = this.type;
 
 
 		if ( this.name !== '' ) object.name = this.name;
 		if ( this.name !== '' ) object.name = this.name;
-		if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
 		if ( this.castShadow === true ) object.castShadow = true;
 		if ( this.castShadow === true ) object.castShadow = true;
 		if ( this.receiveShadow === true ) object.receiveShadow = true;
 		if ( this.receiveShadow === true ) object.receiveShadow = true;
 		if ( this.visible === false ) object.visible = false;
 		if ( this.visible === false ) object.visible = false;
+		if ( JSON.stringify( this.userData ) !== '{}' ) object.userData = this.userData;
 
 
 		object.matrix = this.matrix.toArray();
 		object.matrix = this.matrix.toArray();
 
 

+ 5 - 0
src/loaders/MaterialLoader.js

@@ -81,8 +81,13 @@ Object.assign( MaterialLoader.prototype, {
 		if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
 		if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
 		if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
 		if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;
 		if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
 		if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin;
+
 		if ( json.skinning !== undefined ) material.skinning = json.skinning;
 		if ( json.skinning !== undefined ) material.skinning = json.skinning;
 		if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
 		if ( json.morphTargets !== undefined ) material.morphTargets = json.morphTargets;
+		if ( json.dithering !== undefined ) material.dithering = json.dithering;
+
+		if ( json.visible !== undefined ) material.visible = json.visible;
+		if ( json.userData !== undefined ) material.userData = json.userData;
 
 
 		// Deprecated
 		// Deprecated
 
 

+ 11 - 4
src/materials/Material.js

@@ -61,6 +61,8 @@ function Material() {
 
 
 	this.visible = true;
 	this.visible = true;
 
 
+	this.userData = {};
+
 	this.needsUpdate = true;
 	this.needsUpdate = true;
 
 
 }
 }
@@ -221,17 +223,21 @@ Object.assign( Material.prototype, EventDispatcher.prototype, {
 		data.depthTest = this.depthTest;
 		data.depthTest = this.depthTest;
 		data.depthWrite = this.depthWrite;
 		data.depthWrite = this.depthWrite;
 
 
+		if ( this.dithering === true ) data.dithering = true;
+
 		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
 		if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest;
 		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
 		if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = this.premultipliedAlpha;
+
 		if ( this.wireframe === true ) data.wireframe = this.wireframe;
 		if ( this.wireframe === true ) data.wireframe = this.wireframe;
 		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
 		if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth;
 		if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
 		if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap;
 		if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
 		if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin;
 
 
-		data.skinning = this.skinning;
-		data.morphTargets = this.morphTargets;
+		if ( this.morphTargets === true ) data.morphTargets = true;
+		if ( this.skinning === true ) data.skinning = true;
 
 
-		data.dithering = this.dithering;
+		if ( this.visible === false ) data.visible = false;
+		if ( JSON.stringify( this.userData ) !== '{}' ) data.userData = this.userData;
 
 
 		// TODO: Copied from Object3D.toJSON
 		// TODO: Copied from Object3D.toJSON
 
 
@@ -308,12 +314,13 @@ Object.assign( Material.prototype, EventDispatcher.prototype, {
 		this.dithering = source.dithering;
 		this.dithering = source.dithering;
 
 
 		this.alphaTest = source.alphaTest;
 		this.alphaTest = source.alphaTest;
-
 		this.premultipliedAlpha = source.premultipliedAlpha;
 		this.premultipliedAlpha = source.premultipliedAlpha;
 
 
 		this.overdraw = source.overdraw;
 		this.overdraw = source.overdraw;
 
 
 		this.visible = source.visible;
 		this.visible = source.visible;
+		this.userData = JSON.parse( JSON.stringify( source.userData ) );
+
 		this.clipShadows = source.clipShadows;
 		this.clipShadows = source.clipShadows;
 		this.clipIntersection = source.clipIntersection;
 		this.clipIntersection = source.clipIntersection;
 
 

+ 1 - 1
src/textures/Texture.js

@@ -125,7 +125,7 @@ Object.assign( Texture.prototype, EventDispatcher.prototype, {
 
 
 			var canvas;
 			var canvas;
 
 
-			if ( image.toDataURL !== undefined ) {
+			if ( image instanceof HTMLCanvasElement ) {
 
 
 				canvas = image;
 				canvas = image;
 
 

Some files were not shown because too many files changed in this diff