Bladeren bron

Merge branch 'unify_loaders' of https://github.com/zinefer/three.js into dev

Conflicts:
	examples/js/loaders/AWDLoader.js
	examples/js/loaders/BinaryLoader.js
	examples/js/loaders/ColladaLoader.js
	examples/js/loaders/MTLLoader.js
	examples/js/loaders/OBJMTLLoader.js
	examples/js/loaders/PVRLoader.js
	examples/js/loaders/STLLoader.js
	examples/js/loaders/UTF8Loader.js
	examples/webgl_loader_ply.html
	src/loaders/CompressedTextureLoader.js
	src/loaders/JSONLoader.js
	src/loaders/Loader.js
Mr.doob 10 jaren geleden
bovenliggende
commit
70e4206dbf

+ 852 - 962
examples/js/loaders/AWDLoader.js

@@ -3,98 +3,79 @@
  * Date: 09/12/2013 17:21
  */
 
-THREE.AWDLoader = (function () {
-
-
+(function (){
 
 	var UNCOMPRESSED  = 0,
-      DEFLATE       = 1,
-      LZMA          = 2,
-
-      AWD_FIELD_INT8      = 1,
-      AWD_FIELD_INT16     = 2,
-      AWD_FIELD_INT32     = 3,
-      AWD_FIELD_UINT8     = 4,
-      AWD_FIELD_UINT16    = 5,
-      AWD_FIELD_UINT32    = 6,
-      AWD_FIELD_FLOAT32   = 7,
-      AWD_FIELD_FLOAT64   = 8,
-      AWD_FIELD_BOOL      = 21,
-      AWD_FIELD_COLOR     = 22,
-      AWD_FIELD_BADDR     = 23,
-      AWD_FIELD_STRING    = 31,
-      AWD_FIELD_BYTEARRAY = 32,
-      AWD_FIELD_VECTOR2x1 = 41,
-      AWD_FIELD_VECTOR3x1 = 42,
-      AWD_FIELD_VECTOR4x1 = 43,
-      AWD_FIELD_MTX3x2    = 44,
-      AWD_FIELD_MTX3x3    = 45,
-      AWD_FIELD_MTX4x3    = 46,
-      AWD_FIELD_MTX4x4    = 47,
-
-      BOOL       = 21,
-      COLOR      = 22,
-      BADDR      = 23,
-
-      INT8    = 1,
-      INT16   = 2,
-      INT32   = 3,
-      UINT8   = 4,
-      UINT16  = 5,
-      UINT32  = 6,
-      FLOAT32 = 7,
-      FLOAT64 = 8;
-
+			DEFLATE       = 1,
+			LZMA          = 2,
+
+			AWD_FIELD_INT8      = 1,
+			AWD_FIELD_INT16     = 2,
+			AWD_FIELD_INT32     = 3,
+			AWD_FIELD_UINT8     = 4,
+			AWD_FIELD_UINT16    = 5,
+			AWD_FIELD_UINT32    = 6,
+			AWD_FIELD_FLOAT32   = 7,
+			AWD_FIELD_FLOAT64   = 8,
+			AWD_FIELD_BOOL      = 21,
+			AWD_FIELD_COLOR     = 22,
+			AWD_FIELD_BADDR     = 23,
+			AWD_FIELD_STRING    = 31,
+			AWD_FIELD_BYTEARRAY = 32,
+			AWD_FIELD_VECTOR2x1 = 41,
+			AWD_FIELD_VECTOR3x1 = 42,
+			AWD_FIELD_VECTOR4x1 = 43,
+			AWD_FIELD_MTX3x2    = 44,
+			AWD_FIELD_MTX3x3    = 45,
+			AWD_FIELD_MTX4x3    = 46,
+			AWD_FIELD_MTX4x4    = 47,
+
+			BOOL       = 21,
+			COLOR      = 22,
+			BADDR      = 23,
+
+			INT8    = 1,
+			INT16   = 2,
+			INT32   = 3,
+			UINT8   = 4,
+			UINT16  = 5,
+			UINT32  = 6,
+			FLOAT32 = 7,
+			FLOAT64 = 8;
 
 	var littleEndian = true;
 
-  // ResourcesLoader
-  // =============
-  // handle loading for external resources
-	function ResourcesLoader( awdUrl ) {
-
-		this._baseDir = awdUrl.substr( 0, awdUrl.lastIndexOf( '/' ) + 1 );
-
-		this._loadingManager = new THREE.LoadingManager();
-
-	}
-
-	ResourcesLoader.prototype = {
-
-    loadTexture : function( path ) {
-	var tex = new THREE.Texture();
-
-	var loader = new THREE.ImageLoader( this._loadingManager );
-
-	loader.load( this._baseDir + path, function( image ) {
-		tex.image = image;
-		tex.needsUpdate = true;
-	});
-
-	return tex;
-
-    }
-  };
-
-
-
-	function Block() {
+	function Block(){
 		this.id = 0;
 		this.data = null;
 	}
 
+	AWDProperties = function(){}
 
+	AWDProperties.prototype = {
+		set : function(key, value)
+		{
+			this[key] = value;
+		},
+
+		get : function(key, fallback)
+		{
+			if ( this.hasOwnProperty(key) )
+				return this[key];
+			else return fallback;
+		}
+	}
 
-	function AWDLoader( showStatus ) {
+	THREE.AWDLoader = function ( manager ) {
 
-		THREE.Loader.call( this, showStatus );
+		this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
 		this.trunk = new THREE.Object3D();
 
 		this.materialFactory = undefined;
 
-		this._resourceLoader = null;
-		this._url = '';
+		this._url     = '';
+		this._baseDir = '';
 
 		this._data;
 		this._ptr = 0;
@@ -105,1122 +86,1031 @@ THREE.AWDLoader = (function () {
 		this._compression = 0;
 		this._bodylen = 0xFFFFFFFF;
 
-
 		this._blocks = [ new Block() ];
 
 		this._accuracyMatrix  = false;
 		this._accuracyGeo     = false;
 		this._accuracyProps   = false;
 
-
-	}
-
-
-	AWDLoader.prototype = Object.create( THREE.Loader.prototype );
-	AWDLoader.prototype.constructor = AWDLoader;
-
-	AWDLoader.prototype.load = function ( url, callback ) {
-
-		var that = this;
-		this._url = url;
-		var xhr = new XMLHttpRequest();
-		xhr.open( "GET", url, true );
-		xhr.responseType = 'arraybuffer';
-
-		xhr.onreadystatechange = function () {
-
-			if ( xhr.readyState == 4 ) {
-
-				if ( xhr.status == 200 || xhr.status == 0 ) {
-					that.parse( xhr.response );
-					callback( that.trunk );
-
-				} else {
-
-					console.error( 'AWDLoader: Couldn\'t load ' + url + ' (' + xhr.status + ')' );
-
-				}
-
-			}
-
-		};
-
-		xhr.send( null );
-
 	};
 
-	AWDLoader.prototype.parse = function ( data ) {
+	THREE.AWDLoader.prototype = {
 
-		var blen = data.byteLength;
+		constructor: THREE.AWDLoader,
 
-		this._ptr = 0;
-		this._data = new DataView( data );
+		load: function ( url, onLoad, onProgress, onError ) {
 
-		this._parseHeader( );
+			var scope = this;
 
-		if ( this._compression != 0  ) {
-			console.error( 'compressed AWD not supported' );
-		}
+			this._url = url;
+			this._baseDir = url.substr( 0, url.lastIndexOf( '/' )+1 );
 
-		if (!this._streaming && this._bodylen != data.byteLength - this._ptr ) {
-			console.error('AWDLoader: body len does not match file length', this._bodylen,  blen - this._ptr);
-		}
+			var loader = new THREE.XHRLoader( this.manager );
+			loader.setCrossOrigin( this.crossOrigin );
+			loader.setResponseType('arraybuffer');
+			loader.load( url, function ( text ) {
 
-		while ( this._ptr < blen ) {
-			this.parseNextBlock();
-		}
+				onLoad( scope.parse(text) );
 
-		return this.trunk;
+			}, onProgress, onError );
 
-	};
+		},
 
+		setCrossOrigin: function ( value ) {
 
+			this.crossOrigin = value;
 
-	AWDLoader.prototype.parseNextBlock = function ( ) {
-
-		var assetData,
-        ns, type, len, block,
-        blockId = this.readU32(),
-        ns      = this.readU8(),
-        type    = this.readU8(),
-        flags   = this.readU8(),
-        len     = this.readU32();
-
-
-		switch (type) {
-			case 1:
-				assetData = this.parseMeshData(len);
-				break;
-			case 22:
-				assetData = this.parseContainer(len);
-				break;
-			case 23:
-				assetData = this.parseMeshInstance(len);
-				break;
-			case 81:
-				assetData = this.parseMaterial(len);
-				break;
-			case 82:
-				assetData = this.parseTexture(len);
-				break;
-			case 101:
-				assetData = this.parseSkeleton(len);
-				break;
-
-//      case 111:
-//        assetData = this.parseMeshPoseAnimation(len, true);
-//        break;
-			case 112:
-				assetData = this.parseMeshPoseAnimation(len, false);
-				break;
-			case 113:
-				assetData = this.parseVertexAnimationSet(len);
-				break;
-			case 102:
-				assetData = this.parseSkeletonPose(len);
-				break;
-			case 103:
-				assetData = this.parseSkeletonAnimation(len);
-				break;
-			case 122:
-				assetData = this.parseAnimatorSet(len);
-				break;
-      // case 121:
-      // 	assetData = parseUVAnimation(len);
-      // 	break;
-			default:
-        //debug('Ignoring block!',type, len);
-				this._ptr += len;
-				break;
-		}
+		},
 
+		parse: function ( data ) {
 
-    // Store block reference for later use
-		this._blocks[blockId] = block = new Block();
-		block.data = assetData;
-		block.id = blockId;
+			var blen = data.byteLength;
 
-	};
+			this._ptr = 0;
+			this._data = new DataView( data );
 
+			this._parseHeader( );
 
-	AWDLoader.prototype._parseHeader = function () {
+			if( this._compression != 0  ) {
+				console.error( 'compressed AWD not supported' );
+			}
 
-		var version = this._version,
-        awdmagic =
-            ( this.readU8()<<16)
-        |   ( this.readU8()<<8 )
-        |     this.readU8();
+			if (!this._streaming && this._bodylen != data.byteLength - this._ptr ) {
+				console.error('AWDLoader: body len does not match file length', this._bodylen ,  blen - this._ptr);
+			}
 
-		if ( awdmagic != 4282180 )
-      throw new Error( "AWDLoader - bad magic" );
+			while ( this._ptr < blen ) {
+				this.parseNextBlock();
+			}
 
-		version[0] = this.readU8();
-		version[1] = this.readU8();
+			return this.trunk;
+
+		},
+
+		parseNextBlock: function() {
+
+			var assetData,
+					ns, type, len, block,
+					blockId = this.readU32(),
+					ns      = this.readU8(),
+					type    = this.readU8(),
+					flags   = this.readU8(),
+					len     = this.readU32();
+
+
+			switch (type) {
+				case 1:
+					assetData = this.parseMeshData(len);
+					break;
+				case 22:
+					assetData = this.parseContainer(len);
+					break;
+				case 23:
+					assetData = this.parseMeshInstance(len);
+					break;
+				case 81:
+					assetData = this.parseMaterial(len);
+					break;
+				case 82:
+					assetData = this.parseTexture(len);
+					break;
+				case 101:
+					assetData = this.parseSkeleton(len);
+					break;
+
+	//      case 111:
+	//        assetData = this.parseMeshPoseAnimation(len, true);
+	//        break;
+				case 112:
+					assetData = this.parseMeshPoseAnimation(len, false);
+					break;
+				case 113:
+					assetData = this.parseVertexAnimationSet(len);
+					break;
+				case 102:
+					assetData = this.parseSkeletonPose(len);
+					break;
+				case 103:
+					assetData = this.parseSkeletonAnimation(len);
+					break;
+				case 122:
+					assetData = this.parseAnimatorSet(len);
+					break;
+				// case 121:
+				//  assetData = parseUVAnimation(len);
+				//  break;
+				default:
+					//debug('Ignoring block!',type, len);
+					this._ptr += len;
+					break;
+			}
 
-		var flags = this.readU16();
 
-		this._streaming = (flags & 0x1) == 0x1;
+			// Store block reference for later use
+			this._blocks[blockId] = block = new Block();
+			block.data = assetData;
+			block.id = blockId;
 
-		if ((version[0] === 2) && (version[1] === 1)) {
-			this._accuracyMatrix =  (flags & 0x2) === 0x2;
-			this._accuracyGeo =     (flags & 0x4) === 0x4;
-			this._accuracyProps =   (flags & 0x8) === 0x8;
-		}
 
-		this._geoNrType     = this._accuracyGeo     ? FLOAT64 : FLOAT32;
-		this._matrixNrType  = this._accuracyMatrix  ? FLOAT64 : FLOAT32;
-		this._propsNrType   = this._accuracyProps   ? FLOAT64 : FLOAT32;
+		},
 
-		this._optimized_for_accuracy 	= (flags & 0x2) === 0x2;
+		_parseHeader: function () {
 
-		this._compression = this.readU8();
-		this._bodylen = this.readU32();
+			var version = this._version,
+					awdmagic =
+							( this.readU8()<<16)
+					|   ( this.readU8()<<8 )
+					|     this.readU8();
 
+			if( awdmagic != 4282180 )
+				throw new Error( "AWDLoader - bad magic" );
 
-	};
+			version[0] = this.readU8();
+			version[1] = this.readU8();
 
+			var flags = this.readU16();
 
-	AWDLoader.prototype.parseContainer = function ( len ) {
-		var parent,
-        ctr     = new THREE.Object3D(),
-        par_id  = this.readU32(),
-        mtx     = this.parseMatrix4();
+			this._streaming = (flags & 0x1) == 0x1;
 
-		ctr.name = this.readUTF();
-		ctr.applyMatrix( mtx );
+			if ((version[0] === 2) && (version[1] === 1)) {
+				this._accuracyMatrix =  (flags & 0x2) === 0x2;
+				this._accuracyGeo =     (flags & 0x4) === 0x4;
+				this._accuracyProps =   (flags & 0x8) === 0x8;
+			}
 
-		parent = this._blocks[par_id].data || this.trunk;
-		parent.add(ctr);
+			this._geoNrType     = this._accuracyGeo     ? FLOAT64 : FLOAT32;
+			this._matrixNrType  = this._accuracyMatrix  ? FLOAT64 : FLOAT32;
+			this._propsNrType   = this._accuracyProps   ? FLOAT64 : FLOAT32;
 
-		this.parseProperties({
-      1:this._matrixNrType,
-      2:this._matrixNrType,
-      3:this._matrixNrType,
-      4:UINT8
-    });
+			this._optimized_for_accuracy  = (flags & 0x2) === 0x2;
 
-		ctr.extra = this.parseUserAttributes();
+			this._compression = this.readU8();
+			this._bodylen = this.readU32();
 
-		return ctr;
-	};
+		},
 
+		parseContainer: function ( len ) {
+			var parent,
+					ctr     = new THREE.Object3D(),
+					par_id  = this.readU32(),
+					mtx     = this.parseMatrix4();
 
+			ctr.name = this.readUTF();
+			ctr.applyMatrix( mtx );
 
-	AWDLoader.prototype.parseMeshInstance = function ( len ) {
-		var name,
-        mesh, geometries, meshLen, meshes,
-        par_id, data_id,
-        mtx,
-        materials, mat, mat_id,
-        num_materials,
-        materials_parsed,
-        parent,
-        i;
+			parent = this._blocks[par_id].data || this.trunk;
+			parent.add(ctr);
 
-		par_id        = this.readU32();
-		mtx           = this.parseMatrix4();
-		name          = this.readUTF();
-		data_id       = this.readU32();
-		num_materials = this.readU16();
+			this.parseProperties({
+				1:this._matrixNrType,
+				2:this._matrixNrType,
+				3:this._matrixNrType,
+				4:UINT8
+			});
 
-		geometries = this.getBlock( data_id );
+			ctr.extra = this.parseUserAttributes();
 
-		materials = [];
-		materials_parsed = 0;
+			return ctr;
+		},
 
-		for ( i = 0; i < num_materials; i ++) {
-			mat_id = this.readU32();
-			mat = this.getBlock( mat_id );
-			materials.push( mat );
-		}
+		parseMeshInstance: function ( len ) {
+			var name,
+					mesh, geometries, meshLen, meshes,
+					par_id, data_id,
+					mtx,
+					materials, mat, mat_id,
+					num_materials,
+					materials_parsed,
+					parent,
+					i;
 
+			par_id        = this.readU32();
+			mtx           = this.parseMatrix4();
+			name          = this.readUTF();
+			data_id       = this.readU32();
+			num_materials = this.readU16();
 
+			geometries = this.getBlock( data_id );
 
-		meshLen = geometries.length;
-		meshes = [];
+			materials = [];
+			materials_parsed = 0;
 
-    // TODO : BufferGeometry don't support "geometryGroups" for now.
-    // so we create sub meshes for each groups
-		if ( meshLen  > 1 ) {
-			mesh = new THREE.Object3D();
-			for ( i = 0; i < meshLen; i ++) {
-				var sm = new THREE.Mesh( geometries[i] );
-				meshes.push( sm );
-				mesh.add( sm );
+			for ( i = 0; i < num_materials; i++) {
+				mat_id = this.readU32();
+				mat = this.getBlock( mat_id );
+				materials.push( mat );
 			}
-		}
-		else {
-			mesh = new THREE.Mesh( geometries[0] );
-			meshes.push( mesh );
-		}
-
-		mesh.applyMatrix( mtx );
-		mesh.name = name;
-
-
-		parent = this.getBlock( par_id ) || this.trunk;
-		parent.add( mesh );
-
-
-		var matLen = materials.length;
-		var maxLen = Math.max( meshLen, matLen);
-		for ( i = 0; i < maxLen; i ++ )
-      meshes[ i%meshLen ].material = materials[ i % matLen ];
-
-
-    // Ignore for now
-		this.parseProperties( null );
-		mesh.extra = this.parseUserAttributes();
-
-		return mesh;
-	};
 
+			meshLen = geometries.length;
+			meshes = [];
+
+			// TODO : BufferGeometry don't support "geometryGroups" for now.
+			// so we create sub meshes for each groups
+			if( meshLen  > 1 ) {
+				mesh = new THREE.Object3D();
+				for ( i = 0; i < meshLen; i++) {
+					var sm = new THREE.Mesh( geometries[i] );
+					meshes.push( sm );
+					mesh.add( sm );
+				}
+			}
+			else {
+				mesh = new THREE.Mesh( geometries[0] );
+				meshes.push( mesh );
+			}
 
+			mesh.applyMatrix( mtx );
+			mesh.name = name;
 
-	AWDLoader.prototype.parseMaterial = function ( len ) {
-		var name,
-        type,
-        props,
-        mat,
-        attributes,
-        finalize,
-        num_methods,
-        methods_parsed;
 
-		name        = this.readUTF();
-		type        = this.readU8();
-		num_methods = this.readU8();
+			parent = this.getBlock( par_id ) || this.trunk;
+			parent.add( mesh );
 
-    //log( "AWDLoader parseMaterial ",name )
 
-    // Read material numerical properties
-    // (1=color, 2=bitmap url, 11=alpha_blending, 12=alpha_threshold, 13=repeat)
-		props = this.parseProperties({
-      1:  AWD_FIELD_INT32,
-      2:  AWD_FIELD_BADDR,
-      11: AWD_FIELD_BOOL,
-      12: AWD_FIELD_FLOAT32,
-      13: AWD_FIELD_BOOL
-    });
+			var matLen = materials.length;
+			var maxLen = Math.max( meshLen, matLen);
+			for( i = 0; i< maxLen; i++ )
+				meshes[ i%meshLen ].material = materials[ i % matLen ];
 
-		methods_parsed = 0;
 
-		while ( methods_parsed < num_methods ) {
-			var method_type = this.readU16();
+			// Ignore for now
 			this.parseProperties( null );
-			this.parseUserAttributes();
-		}
-
-		attributes = this.parseUserAttributes();
-
-		if ( this.materialFactory !== undefined ) {
-			mat = this.materialFactory( name );
-			if ( mat ) return mat;
-		}
+			mesh.extra = this.parseUserAttributes();
+
+			return mesh;
+		},
+
+		parseMaterial: function ( len ) {
+			var name,
+					type,
+					props,
+					mat,
+					attributes,
+					finalize,
+					num_methods,
+					methods_parsed;
+
+			name        = this.readUTF();
+			type        = this.readU8();
+			num_methods = this.readU8();
+
+			//log( "AWDLoader parseMaterial ",name )
+
+			// Read material numerical properties
+			// (1=color, 2=bitmap url, 11=alpha_blending, 12=alpha_threshold, 13=repeat)
+			props = this.parseProperties({
+				1:  AWD_FIELD_INT32,
+				2:  AWD_FIELD_BADDR,
+				11: AWD_FIELD_BOOL,
+				12: AWD_FIELD_FLOAT32,
+				13: AWD_FIELD_BOOL
+			});
+
+			methods_parsed = 0;
+
+			while( methods_parsed < num_methods ) {
+				var method_type = this.readU16();
+				this.parseProperties( null );
+				this.parseUserAttributes();
+			}
 
-		mat = new THREE.MeshPhongMaterial();
+			attributes = this.parseUserAttributes();
 
-		if (type === 1) { // Color material
-			mat.color.setHex( props.get(1, 0xcccccc) );
-		}
-    else if (type === 2) { // Bitmap material
-	var tex_addr = props.get(2, 0);
-	mat.map = this.getBlock( tex_addr );
-    }
+			if( this.materialFactory !== undefined ) {
+				mat = this.materialFactory( name );
+				if( mat ) return mat;
+			}
 
-		mat.extra = attributes;
-		mat.alphaThreshold = props.get(12, 0.0);
-		mat.repeat = props.get(13, false);
+			mat = new THREE.MeshPhongMaterial();
 
+			if (type === 1) { // Color material
+				mat.color.setHex( props.get(1, 0xcccccc) );
+			}
+			else if (type === 2) { // Bitmap material
+				var tex_addr = props.get(2, 0);
+				mat.map = this.getBlock( tex_addr );
+			}
 
-		return mat;
-	};
+			mat.extra = attributes;
+			mat.alphaThreshold = props.get(12, 0.0);
+			mat.repeat = props.get(13, false);
 
 
+			return mat;
+		},
 
+		parseTexture: function( len ) {
+			var name = this.readUTF(),
+					type = this.readU8(),
+					asset,
+					data_len;
 
-	AWDLoader.prototype.parseTexture = function( len ) {
+			// External
+			if (type === 0) {
+				data_len = this.readU32();
+				var url = this.readUTFBytes(data_len);
+				console.log( url );
 
+				asset = this.loadTexture( url );
+			} else {
+				// embed texture not supported
+			}
+			// Ignore for now
+			this.parseProperties( null );
 
-		var name = this.readUTF(),
-        type = this.readU8(),
-        asset,
-        data_len;
+			this.parseUserAttributes();
+			return asset;
+		},
 
-    // External
-		if (type === 0) {
-			data_len = this.readU32();
-			var url = this.readUTFBytes(data_len);
-			console.log( url );
+		loadTexture: function( url ) {
+			var tex = new THREE.Texture();
 
-			asset = this.loadTexture( url );
-		} else {
-      // embed texture not supported
-		}
-    // Ignore for now
-		this.parseProperties( null );
+			var loader = new THREE.ImageLoader( this.manager );
 
-		this.parseUserAttributes();
-		return asset;
-	};
+			loader.load( this._baseDir+url, function( image ) {
+				tex.image = image;
+				tex.needsUpdate = true;
+			});
 
-	AWDLoader.prototype.loadTexture = function( url ) {
+			return tex;
+		},
 
-		if ( null === this._resourceLoader )
-      this._resourceLoader = new ResourcesLoader( this._url );
+		parseSkeleton: function( len ) { // Array<Bone>
+			var name          = this.readUTF(),
+					num_joints    = this.readU16(),
+					skeleton      = [],
+					joints_parsed = 0;
 
-		return this._resourceLoader.loadTexture( url );
-	};
+			this.parseProperties( null );
 
-  // broken : skeleton pose format is different than threejs one
-	AWDLoader.prototype.parseSkeleton = function(len) // Array<Bone>
-  {
-		var name          = this.readUTF(),
-        num_joints    = this.readU16(),
-        skeleton      = [],
-        joints_parsed = 0;
+			while (joints_parsed < num_joints) {
+				var joint, ibp;
 
-		this.parseProperties( null );
+				// Ignore joint id
+				this.readU16();
 
-		while (joints_parsed < num_joints) {
-			var joint, ibp;
+				joint = new THREE.Bone();
+				joint.parent = this.readU16() - 1; // 0=null in AWD
+				joint.name = this.readUTF();
 
-      // Ignore joint id
-			this.readU16();
+				ibp = this.parseMatrix4();
+				joint.skinMatrix = ibp;
 
-			joint = new THREE.Bone();
-			joint.parent = this.readU16() - 1; // 0=null in AWD
-			joint.name = this.readUTF();
+				// Ignore joint props/attributes for now
+				this.parseProperties(null);
+				this.parseUserAttributes();
 
-			ibp = this.parseMatrix4();
-			joint.skinMatrix = ibp;
+				skeleton.push(joint);
+				joints_parsed++;
+			}
 
-      // Ignore joint props/attributes for now
-			this.parseProperties(null);
+			// Discard attributes for now
 			this.parseUserAttributes();
 
-			skeleton.push(joint);
-			joints_parsed ++;
-		}
-
-    // Discard attributes for now
-		this.parseUserAttributes();
-
-
-		return skeleton;
-	};
-
-
 
-	AWDLoader.prototype.parseSkeletonPose = function(blockID)
-  {
-		var name = this.readUTF();
+			return skeleton;
+		},
 
+		parseSkeletonPose: function( blockID ) {
+			var name = this.readUTF();
 
-		var num_joints = this.readU16();
-		this.parseProperties(null);
+			var num_joints = this.readU16();
+			this.parseProperties(null);
 
-    // debug( 'parse Skeleton Pose. joints : ' + num_joints);
+			// debug( 'parse Skeleton Pose. joints : ' + num_joints);
 
-		var pose = [];
+			var pose = [];
 
-		var joints_parsed = 0;
+			var joints_parsed = 0;
 
-		while (joints_parsed < num_joints) {
+			while (joints_parsed < num_joints) {
 
-			var joint_pose;
+				var joint_pose;
 
-			var has_transform; //:uint;
-			var mtx_data;
+				var has_transform; //:uint;
+				var mtx_data;
 
-			has_transform = this.readU8();
+				has_transform = this.readU8();
 
-			if (has_transform === 1) {
-				mtx_data = this.parseMatrix4();
-			} else
-			{
-				mtx_data = new THREE.Matrix4();
+				if (has_transform === 1) {
+					mtx_data = this.parseMatrix4();
+				} else
+				{
+					mtx_data = new THREE.Matrix4();
+				}
+				pose[joints_parsed] = mtx_data;
+				joints_parsed++;
 			}
-			pose[joints_parsed] = mtx_data;
-			joints_parsed ++;
-		}
-    // Skip attributes for now
-		this.parseUserAttributes();
-
-		return pose
-	};
-
-	AWDLoader.prototype.parseSkeletonAnimation = function(blockID)
-  {
-		var frame_dur;
-		var pose_addr;
-		var pose;
-
-		var name = this.readUTF();
 
-		var clip = [];
-
-		var num_frames = this.readU16();
-		this.parseProperties(null);
-
-		var frames_parsed = 0;
-		var returnedArray;
-
-
-    // debug( 'parse Skeleton Animation. frames : ' + num_frames);
+			// Skip attributes for now
+			this.parseUserAttributes();
 
-		while (frames_parsed < num_frames) {
-			pose_addr = this.readU32();
-			frame_dur = this.readU16();
+			return pose;
 
-			pose = this._blocks[pose_addr].data;
-      // debug( 'pose address ',pose[2].elements[12],pose[2].elements[13],pose[2].elements[14] );
-			clip.push( {
-        pose : pose,
-        duration : frame_dur
-      } );
+		},
 
-			frames_parsed ++;
-		}
-		if (clip.length == 0) {
-      // debug("Could not this SkeletonClipNode, because no Frames where set.");
-			return;
-		}
-    // Ignore attributes for now
-		this.parseUserAttributes();
-		return clip;
-	};
+		parseSkeletonAnimation: function( blockID ) {
 
+			var frame_dur;
+			var pose_addr;
+			var pose;
 
+			var name = this.readUTF();
 
-	AWDLoader.prototype.parseVertexAnimationSet = function(len)
-  {
-		var poseBlockAdress,
-        name           = this.readUTF(),
-        num_frames     = this.readU16(),
-        props          = this.parseProperties({ 1:UINT16 }),
-        frames_parsed  = 0,
-        skeletonFrames = [];
+			var clip = [];
 
-		while (frames_parsed < num_frames) {
-			poseBlockAdress = this.readU32();
-			skeletonFrames.push(this._blocks[poseBlockAdress].data);
-			frames_parsed ++;
-		}
-
-		this.parseUserAttributes();
+			var num_frames = this.readU16();
+			this.parseProperties( null );
 
+			var frames_parsed = 0;
+			var returnedArray;
 
-		return skeletonFrames;
-	};
+			// debug( 'parse Skeleton Animation. frames : ' + num_frames);
 
+			while ( frames_parsed < num_frames ) {
+				pose_addr = this.readU32();
+				frame_dur = this.readU16();
 
-	AWDLoader.prototype.parseAnimatorSet = function(len)
-  {
-		var targetMesh;
+				pose = this._blocks[pose_addr].data;
+				// debug( 'pose address ',pose[2].elements[12],pose[2].elements[13],pose[2].elements[14] );
+				clip.push( {
+					pose : pose,
+					duration : frame_dur
+				} );
 
-		var animSetBlockAdress; //:int
+				frames_parsed++;
+			}
 
-		var targetAnimationSet; //:AnimationSetBase;
-		var outputString = ""; //:String = "";
-		var name = this.readUTF();
-		var type = this.readU16();
+			if ( clip.length === 0 ) {
+				// debug("Could not this SkeletonClipNode, because no Frames where set.");
+				return;
+			}
+			// Ignore attributes for now
+			this.parseUserAttributes();
+			return clip;
 
-		var props = this.parseProperties({ 1:BADDR });
+		},
 
-		animSetBlockAdress = this.readU32();
-		var targetMeshLength = this.readU16();
+		parseVertexAnimationSet: function( len ) {
 
-		var meshAdresses = []; //:Vector.<uint> = new Vector.<uint>;
+			var poseBlockAdress,
+					name           = this.readUTF(),
+					num_frames     = this.readU16(),
+					props          = this.parseProperties( { 1:UINT16 } ),
+					frames_parsed  = 0,
+					skeletonFrames = [];
 
-		for (var i = 0; i < targetMeshLength; i ++)
-      meshAdresses.push( this.readU32() );
+			while ( frames_parsed < num_frames ) {
+				poseBlockAdress = this.readU32();
+				skeletonFrames.push( this._blocks[poseBlockAdress].data );
+				frames_parsed++;
+			}
 
-		var activeState = this.readU16();
-		var autoplay = Boolean(this.readU8());
-		this.parseUserAttributes();
-		this.parseUserAttributes();
+			this.parseUserAttributes();
 
-		var returnedArray;
-		var targetMeshes = []; //:Vector.<Mesh> = new Vector.<Mesh>;
 
-		for (i = 0; i < meshAdresses.length; i ++) {
-//      returnedArray = getAssetByID(meshAdresses[i], [AssetType.MESH]);
-//      if (returnedArray[0])
-			targetMeshes.push(this._blocks[meshAdresses[i]].data);
-		}
+			return skeletonFrames;
 
-		targetAnimationSet = this._blocks[animSetBlockAdress].data;
-		var thisAnimator;
+		},
 
-		if (type == 1) {
+		parseAnimatorSet: function( len ) {
+			var targetMesh;
 
+			var animSetBlockAdress; //:int
 
-			thisAnimator = {
-        animationSet : targetAnimationSet,
-        skeleton : this._blocks[props.get(1, 0)].data
-      };
+			var targetAnimationSet; //:AnimationSetBase;
+			var outputString = ""; //:String = "";
+			var name = this.readUTF();
+			var type = this.readU16();
 
-		} else if (type == 2) {
-      // debug( "vertex Anim???");
-		}
+			var props = this.parseProperties( { 1:BADDR } );
 
+			animSetBlockAdress = this.readU32();
+			var targetMeshLength = this.readU16();
 
-		for (i = 0; i < targetMeshes.length; i ++) {
-			targetMeshes[i].animator = thisAnimator;
-		}
-    // debug("Parsed a Animator: Name = " + name);
+			var meshAdresses = []; //:Vector.<uint> = new Vector.<uint>;
 
-		return thisAnimator;
-	};
+			for (var i = 0; i < targetMeshLength; i++)
+				meshAdresses.push( this.readU32() );
 
+			var activeState = this.readU16();
+			var autoplay = Boolean( this.readU8() );
+			this.parseUserAttributes();
+			this.parseUserAttributes();
 
+			var returnedArray;
+			var targetMeshes = []; //:Vector.<Mesh> = new Vector.<Mesh>;
 
+			for ( i = 0; i < meshAdresses.length; i++ ) {
+	//      returnedArray = getAssetByID(meshAdresses[i], [AssetType.MESH]);
+	//      if (returnedArray[0])
+					targetMeshes.push( this._blocks[meshAdresses[i]].data );
+			}
 
+			targetAnimationSet = this._blocks[animSetBlockAdress].data;
+			var thisAnimator;
 
+			if (type == 1) {
 
 
-	AWDLoader.prototype.parseMeshData = function ( len ) {
+				thisAnimator = {
+					animationSet : targetAnimationSet,
+					skeleton : this._blocks[props.get(1, 0)].data
+				};
 
-		var name      = this.readUTF(),
-        num_subs  = this.readU16(),
-        geom,
-        subs_parsed = 0,
-        props,
-        buffer,
-        skinW, skinI,
-        geometries = [];
+			} else if (type == 2) {
+				// debug( "vertex Anim???");
+			}
 
 
+			for ( i = 0; i < targetMeshes.length; i++ ) {
+					targetMeshes[i].animator = thisAnimator;
+			}
+			// debug("Parsed a Animator: Name = " + name);
 
+			return thisAnimator;
 
-		props = this.parseProperties({
-      1: this._geoNrType,
-      2: this._geoNrType
-    });
+		},
 
+		parseMeshData: function ( len ) {
+			var name      = this.readUTF(),
+				num_subs  = this.readU16(),
+				geom,
+				subs_parsed = 0,
+				props,
+				buffer,
+				skinW, skinI,
+				geometries = [];
 
+			props = this.parseProperties({
+				1: this._geoNrType,
+				2: this._geoNrType
+			});
 
-    // Loop through sub meshes
-		while (subs_parsed < num_subs) {
+			// Loop through sub meshes
+			while ( subs_parsed < num_subs ) {
 
-			var sm_len, sm_end, attrib;
+				var sm_len, sm_end, attrib;
 
-			geom = new THREE.BufferGeometry();
-			geom.name = name;
-			geometries.push( geom );
+				geom = new THREE.BufferGeometry();
+				geom.name = name;
+				geometries.push( geom );
 
 
-			sm_len = this.readU32();
-			sm_end = this._ptr + sm_len;
+				sm_len = this.readU32();
+				sm_end = this._ptr + sm_len;
 
 
-      // Ignore for now
-			this.parseProperties({ 1:this._geoNrType, 2:this._geoNrType });
+				// Ignore for now
+				this.parseProperties( { 1:this._geoNrType, 2:this._geoNrType } );
 
-      // Loop through data streams
-			while ( this._ptr < sm_end ) {
+				// Loop through data streams
+				while ( this._ptr < sm_end ) {
 
+					var idx = 0,
+							str_type  = this.readU8(),
+							str_ftype = this.readU8(),
+							str_len   = this.readU32(),
+							str_end   = str_len + this._ptr;
 
-				var idx = 0,
-            str_type  = this.readU8(),
-            str_ftype = this.readU8(),
-            str_len   = this.readU32(),
-            str_end   = str_len + this._ptr;
+					// VERTICES
+					// ------------------
+					if ( str_type === 1 ) {
 
+						buffer = new Float32Array( ( str_len / 12 ) * 3 );
+						attrib = new THREE.BufferAttribute( buffer, 3 );
 
+						geom.addAttribute( 'position', attrib );
+						idx = 0;
 
+						while (this._ptr < str_end) {
+							buffer[idx]   = -this.readF32();
+							buffer[idx+1] = this.readF32();
+							buffer[idx+2] = this.readF32();
+							idx+=3;
+						}
+					}
 
+					// INDICES
+					// -----------------
+					else if (str_type === 2) {
 
-        // VERTICES
-        // ------------------
-				if ( str_type === 1 ) {
+						buffer = new Uint16Array( str_len / 2 );
+						attrib = new THREE.BufferAttribute( buffer, 1 );
+						geom.addAttribute( 'index', attrib );
 
-					buffer = new Float32Array( ( str_len / 12 ) * 3 );
-					attrib = new THREE.BufferAttribute( buffer, 3 );
+						geom.offsets.push({
+							start: 0,
+							index: 0,
+							count: str_len/2
+						});
 
-					geom.addAttribute( 'position', attrib );
-					idx = 0;
+						idx = 0;
 
-					while (this._ptr < str_end) {
-						buffer[idx]   = -this.readF32();
-						buffer[idx + 1] = this.readF32();
-						buffer[idx + 2] = this.readF32();
-						idx+=3;
+						while (this._ptr < str_end) {
+							buffer[idx+1]   = this.readU16();
+							buffer[idx]     = this.readU16();
+							buffer[idx+2]   = this.readU16();
+							idx+=3;
+						}
 					}
-				}
-
-
-        // INDICES
-        // -----------------
-        else if (str_type === 2) {
 
-	buffer = new Uint16Array( str_len / 2 );
-	attrib = new THREE.BufferAttribute( buffer, 1 );
-	geom.addAttribute( 'index', attrib );
+					// UVS
+					// -------------------
+					else if (str_type === 3) {
 
-	geom.offsets.push({
-            start: 0,
-            index: 0,
-            count: str_len / 2
-          });
+						buffer = new Float32Array( ( str_len / 8 ) * 2 );
+						attrib = new THREE.BufferAttribute( buffer, 2 );
 
-	idx = 0;
-
-	while (this._ptr < str_end) {
-		buffer[idx + 1]   = this.readU16();
-		buffer[idx]     = this.readU16();
-		buffer[idx + 2]   = this.readU16();
-		idx+=3;
-	}
-        }
-
-        // UVS
-        // -------------------
-        else if (str_type === 3) {
+						geom.addAttribute( 'uv', attrib );
+						idx = 0;
 
-	buffer = new Float32Array( ( str_len / 8 ) * 2 );
-	attrib = new THREE.BufferAttribute( buffer, 2 );
+						while (this._ptr < str_end) {
+							buffer[idx]   = this.readF32();
+							buffer[idx+1] = 1.0-this.readF32();
+							idx+=2;
+						}
+					}
 
-	geom.addAttribute( 'uv', attrib );
-	idx = 0;
+					// NORMALS
+					else if (str_type === 4) {
 
-	while (this._ptr < str_end) {
-		buffer[idx]   = this.readF32();
-		buffer[idx + 1] = 1.0 - this.readF32();
-		idx+=2;
-	}
-        }
+						buffer = new Float32Array( ( str_len / 12 ) * 3 );
+						attrib = new THREE.BufferAttribute( buffer, 3 );
+						geom.addAttribute( 'normal', attrib );
+						idx = 0;
 
-        // NORMALS
-        else if (str_type === 4) {
+						while (this._ptr < str_end) {
+							buffer[idx]   = -this.readF32();
+							buffer[idx+1] = this.readF32();
+							buffer[idx+2] = this.readF32();
+							idx+=3;
+						}
 
-	buffer = new Float32Array( ( str_len / 12 ) * 3 );
-	attrib = new THREE.BufferAttribute( buffer, 3 );
-	geom.addAttribute( 'normal', attrib );
-	idx = 0;
+					}
 
-	while (this._ptr < str_end) {
-		buffer[idx]   = -this.readF32();
-		buffer[idx + 1] = this.readF32();
-		buffer[idx + 2] = this.readF32();
-		idx+=3;
-	}
+					// else if (str_type == 6) {
+					//   skinI = new Float32Array( str_len>>1 );
+					//   idx = 0
+
+					//   while (this._ptr < str_end) {
+					//     skinI[idx]   = this.readU16();
+					//     idx++;
+					//   }
+
+					// }
+					// else if (str_type == 7) {
+					//   skinW = new Float32Array( str_len>>2 );
+					//   idx = 0;
+
+					//   while (this._ptr < str_end) {
+					//     skinW[idx]   = this.readF32();
+					//     idx++;
+					//   }
+					// }
+					else {
+						this._ptr = str_end;
+					}
 
-        }
-
-        // else if (str_type == 6) {
-        //   skinI = new Float32Array( str_len>>1 );
-        //   idx = 0
-
-        //   while (this._ptr < str_end) {
-        //     skinI[idx]   = this.readU16();
-        //     idx++;
-        //   }
-
-        // }
-        // else if (str_type == 7) {
-        //   skinW = new Float32Array( str_len>>2 );
-        //   idx = 0;
-
-        //   while (this._ptr < str_end) {
-        //     skinW[idx]   = this.readF32();
-        //     idx++;
-        //   }
-        // }
-				else {
-					this._ptr = str_end;
 				}
 
+				this.parseUserAttributes();
 
-
+				geom.computeBoundingSphere();
+				subs_parsed++;
 			}
 
-			this.parseUserAttributes();
-
-
-			geom.computeBoundingSphere();
-			subs_parsed ++;
-		}
-
-
-    //geom.computeFaceNormals();
+			//geom.computeFaceNormals();
 
+			this.parseUserAttributes();
+			//finalizeAsset(geom, name);
+
+			return geometries;
+
+		},
+
+		parseMeshPoseAnimation: function( len, poseOnly ) {
+			var num_frames = 1,
+					num_submeshes,
+					frames_parsed,
+					subMeshParsed,
+					frame_dur,
+					x, y, z,
+
+					str_len,
+					str_end,
+					geom,
+					subGeom,
+					idx = 0,
+					clip = {},
+					indices,
+					verts,
+					num_Streams,
+					streamsParsed,
+					streamtypes = [],
+
+					props,
+					thisGeo,
+					name = this.readUTF(),
+					geoAdress = this.readU32();
+
+			var mesh = this.getBlock( geoAdress );
+
+			if (mesh === null) {
+				console.log( "parseMeshPoseAnimation target mesh not found at:", geoAdress );
+				return;
+			}
 
-		this.parseUserAttributes();
-    //finalizeAsset(geom, name);
+			geom = mesh.geometry;
+			geom.morphTargets = [];
 
-		return geometries;
-	};
+			if (!poseOnly)
+				num_frames = this.readU16();
 
-	AWDLoader.prototype.parseMeshPoseAnimation = function(len, poseOnly)
-  {
-		var num_frames = 1,
-        num_submeshes,
-        frames_parsed,
-        subMeshParsed,
-        frame_dur,
-        x, y, z,
-
-        str_len,
-        str_end,
-        geom,
-        subGeom,
-        idx = 0,
-        clip = {},
-        indices,
-        verts,
-        num_Streams,
-        streamsParsed,
-        streamtypes = [],
-
-        props,
-        thisGeo,
-        name = this.readUTF(),
-        geoAdress = this.readU32();
-
-
-		var mesh = this.getBlock( geoAdress );
-
-		if (mesh == null) {
-			console.log( "parseMeshPoseAnimation target mesh not found at:", geoAdress );
-			return;
-		}
+			num_submeshes = this.readU16();
+			num_Streams = this.readU16();
 
-		geom = mesh.geometry;
-		geom.morphTargets = [];
+			// debug("VA num_frames : ", num_frames );
+			// debug("VA num_submeshes : ", num_submeshes );
+			// debug("VA numstreams : ", num_Streams );
 
-		if (!poseOnly)
-      num_frames = this.readU16();
-
-		num_submeshes = this.readU16();
-		num_Streams = this.readU16();
+			streamsParsed = 0;
+			while ( streamsParsed < num_Streams ) {
+				streamtypes.push(this.readU16());
+				streamsParsed++;
+			}
+			props = this.parseProperties( { 1:BOOL, 2:BOOL } );
 
-    // debug("VA num_frames : ", num_frames );
-    // debug("VA num_submeshes : ", num_submeshes );
-    // debug("VA numstreams : ", num_Streams );
+			clip.looping = props.get( 1, true );
+			clip.stitchFinalFrame = props.get( 2, false );
 
-		streamsParsed = 0;
-		while (streamsParsed < num_Streams) {
-			streamtypes.push(this.readU16());
-			streamsParsed ++;
-		}
-		props = this.parseProperties({ 1:BOOL, 2:BOOL });
+			frames_parsed = 0;
 
-		clip.looping = props.get(1, true);
-		clip.stitchFinalFrame = props.get(2, false);
+			while ( frames_parsed < num_frames ) {
 
-		frames_parsed = 0;
+				frame_dur = this.readU16();
+				subMeshParsed = 0;
 
-		while (frames_parsed < num_frames) {
+				while ( subMeshParsed < num_submeshes ) {
 
-			frame_dur = this.readU16();
-			subMeshParsed = 0;
+					streamsParsed = 0;
+					str_len = this.readU32();
+					str_end = this._ptr + str_len;
 
-			while (subMeshParsed < num_submeshes) {
+					while ( streamsParsed < num_Streams ) {
 
-				streamsParsed = 0;
-				str_len = this.readU32();
-				str_end = this._ptr + str_len;
+						if ( streamtypes[streamsParsed] === 1 ) {
 
-				while (streamsParsed < num_Streams) {
+							//geom.addAttribute( 'morphTarget'+frames_parsed, Float32Array, str_len/12, 3 );
+							var buffer = new Float32Array(str_len/4);
+							geom.morphTargets.push( {
+								array : buffer
+							});
 
-					if (streamtypes[streamsParsed] == 1) {
+							//buffer = geom.attributes['morphTarget'+frames_parsed].array
+							idx = 0;
 
-            //geom.addAttribute( 'morphTarget'+frames_parsed, Float32Array, str_len/12, 3 );
-						var buffer = new Float32Array(str_len / 4);
-						geom.morphTargets.push( {
-              array : buffer
-            });
+							while ( this._ptr < str_end ) {
+								buffer[idx]     = this.readF32();
+								buffer[idx+1]   = this.readF32();
+								buffer[idx+2]   = this.readF32();
+								idx += 3;
+							}
 
-            //buffer = geom.attributes['morphTarget'+frames_parsed].array
-						idx = 0;
 
-						while ( this._ptr < str_end ) {
-							buffer[idx]     = this.readF32();
-							buffer[idx + 1]   = this.readF32();
-							buffer[idx + 2]   = this.readF32();
-							idx += 3;
-						}
+							subMeshParsed++;
+						} else
+							this._ptr = str_end;
+						streamsParsed++;
+					}
+				}
 
 
-						subMeshParsed ++;
-					} else
-            this._ptr = str_end;
-					streamsParsed ++;
-				}
+				frames_parsed++;
 			}
 
+			this.parseUserAttributes();
 
-			frames_parsed ++;
-		}
-		this.parseUserAttributes();
+			return null;
+		},
 
-		return null;
-	};
+		getBlock: function ( id ) {
 
+			return this._blocks[id].data;
 
+		},
 
+		parseMatrix4: function () {
 
+			var mtx = new THREE.Matrix4();
+			var e = mtx.elements;
 
+			e[0] = this.readF32();
+			e[1] = this.readF32();
+			e[2] = this.readF32();
+			e[3] = 0.0;
+			//e[3] = 0.0;
 
+			e[4] = this.readF32();
+			e[5] = this.readF32();
+			e[6] = this.readF32();
+			//e[7] = this.readF32();
+			e[7] = 0.0;
 
+			e[8] = this.readF32();
+			e[9] = this.readF32();
+			e[10] = this.readF32();
+			//e[11] = this.readF32();
+			e[11] = 0.0;
 
+			e[12] = -this.readF32();
+			e[13] = this.readF32();
+			e[14] = this.readF32();
+			//e[15] = this.readF32();
+			e[15] = 1.0;
+			return mtx;
 
-	AWDLoader.prototype.getBlock = function ( id ) {
-		return this._blocks[id].data;
-	},
+		},
 
+		parseProperties: function ( expected ) {
+			var list_len = this.readU32();
+			var list_end = this._ptr + list_len;
 
-  AWDLoader.prototype.parseMatrix4 = function ( ) {
-	var mtx = new THREE.Matrix4();
-	var e = mtx.elements;
+			var props = new AWDProperties();
 
-	e[0] = this.readF32();
-	e[1] = this.readF32();
-	e[2] = this.readF32();
-	e[3] = 0.0;
-    //e[3] = 0.0;
+			if( expected ) {
 
-	e[4] = this.readF32();
-	e[5] = this.readF32();
-	e[6] = this.readF32();
-    //e[7] = this.readF32();
-	e[7] = 0.0;
+				while( this._ptr < list_end ) {
 
-	e[8] = this.readF32();
-	e[9] = this.readF32();
-	e[10] = this.readF32();
-    //e[11] = this.readF32();
-	e[11] = 0.0;
-
-	e[12] = -this.readF32();
-	e[13] = this.readF32();
-	e[14] = this.readF32();
-    //e[15] = this.readF32();
-	e[15] = 1.0;
-	return mtx;
-  };
+					var key = this.readU16();
+					var len = this.readU32();
+					var type;
 
+					if( expected.hasOwnProperty( key ) ) {
+						type = expected[ key ];
+						props.set( key, this.parseAttrValue( type, len ) );
+					} else {
+						this._ptr += len;
+					}
+				}
 
-	AWDLoader.prototype.parseProperties = function ( expected ) {
-		var list_len = this.readU32();
-		var list_end = this._ptr + list_len;
+			}
 
-		var props = new AWDProperties();
+			return props;
+		},
+
+		parseUserAttributes: function () {
+			// skip for now
+			this._ptr = this.readU32() + this._ptr;
+			return null;
+		},
+
+		parseAttrValue: function ( type, len ) {
+			var elem_len;
+			var read_func;
+
+			switch (type) {
+				case AWD_FIELD_INT8:
+					elem_len = 1;
+					read_func = this.readI8;
+					break;
+				case AWD_FIELD_INT16:
+					elem_len = 2;
+					read_func = this.readI16;
+					break;
+				case AWD_FIELD_INT32:
+					elem_len = 4;
+					read_func = this.readI32;
+					break;
+				case AWD_FIELD_BOOL:
+				case AWD_FIELD_UINT8:
+					elem_len = 1;
+					read_func = this.readU8;
+					break;
+				case AWD_FIELD_UINT16:
+					elem_len = 2;
+					read_func = this.readU16;
+					break;
+				case AWD_FIELD_UINT32:
+				case AWD_FIELD_BADDR:
+					elem_len = 4;
+					read_func = this.readU32;
+					break;
+				case AWD_FIELD_FLOAT32:
+					elem_len = 4;
+					read_func = this.readF32;
+					break;
+				case AWD_FIELD_FLOAT64:
+					elem_len = 8;
+					read_func = this.readF64;
+					break;
+				case AWD_FIELD_VECTOR2x1:
+				case AWD_FIELD_VECTOR3x1:
+				case AWD_FIELD_VECTOR4x1:
+				case AWD_FIELD_MTX3x2:
+				case AWD_FIELD_MTX3x3:
+				case AWD_FIELD_MTX4x3:
+				case AWD_FIELD_MTX4x4:
+					elem_len = 8;
+					read_func = this.readF64;
+					break;
+			}
 
-		if ( expected ) {
+			if (elem_len < len) {
+				var list;
+				var num_read;
+				var num_elems;
 
-			while ( this._ptr < list_end ) {
+				list = [];
+				num_read = 0;
+				num_elems = len / elem_len;
 
-				var key = this.readU16();
-				var len = this.readU32();
-				var type;
+				while (num_read < num_elems) {
+					list.push(read_func.call( this ) );
+					num_read++;
+				}
 
-				if ( expected.hasOwnProperty( key ) ) {
-					type = expected[ key ];
-					props.set( key, this.parseAttrValue( type, len ) );
+				return list;
+			}
+			else {
+				return read_func.call( this );
+			}
+		},
+
+		readU8: function () {
+			return this._data.getUint8( this._ptr++ );
+		},
+		readI8: function () {
+			return this._data.getInt8( this._ptr++ );
+		},
+		readU16: function () {
+			var a = this._data.getUint16( this._ptr, littleEndian );
+			this._ptr += 2;
+			return a;
+		},
+		readI16: function () {
+			var a = this._data.getInt16( this._ptr, littleEndian );
+			this._ptr += 2;
+			return a;
+		},
+		readU32: function () {
+			var a = this._data.getUint32( this._ptr, littleEndian );
+			this._ptr += 4;
+			return a;
+		},
+		readI32: function () {
+			var a = this._data.getInt32( this._ptr, littleEndian );
+			this._ptr += 4;
+			return a;
+		},
+		readF32: function () {
+			var a = this._data.getFloat32( this._ptr, littleEndian );
+			this._ptr += 4;
+			return a;
+		},
+		readF64: function () {
+			var a = this._data.getFloat64( this._ptr, littleEndian );
+			this._ptr += 8;
+			return a;
+		},
+
+		/**
+	 * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode.
+	 * @param {Array.<number>} bytes UTF-8 byte array.
+	 * @return {string} 16-bit Unicode string.
+	 */
+		readUTF: function () {
+			var len = this.readU16();
+			return this.readUTFBytes( len );
+		},
+
+		/**
+		 * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode.
+		 * @param {Array.<number>} bytes UTF-8 byte array.
+		 * @return {string} 16-bit Unicode string.
+		 */
+		readUTFBytes: function ( len ) {
+			// TODO(user): Use native implementations if/when available
+			var out = [], c = 0;
+
+			while ( out.length < len ) {
+				var c1 = this._data.getUint8( this._ptr++, littleEndian );
+				if (c1 < 128) {
+					out[c++] = String.fromCharCode(c1);
+				} else if (c1 > 191 && c1 < 224) {
+					var c2 = this._data.getUint8( this._ptr++, littleEndian );
+					out[c++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
 				} else {
-					this._ptr += len;
+					var c2 = this._data.getUint8( this._ptr++, littleEndian );
+					var c3 = this._data.getUint8( this._ptr++, littleEndian );
+					out[c++] = String.fromCharCode(
+							(c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63
+					);
 				}
 			}
-
-		}
-
-		return props;
-
-	};
-
-
-	AWDLoader.prototype.parseUserAttributes = function ( ) {
-    // skip for now
-		this._ptr = this.readU32() + this._ptr;
-		return null;
-	};
-
-
-	AWDLoader.prototype.parseAttrValue = function ( type, len ) {
-
-		var elem_len;
-		var read_func;
-
-		switch (type) {
-			case AWD_FIELD_INT8:
-				elem_len = 1;
-				read_func = this.readI8;
-				break;
-			case AWD_FIELD_INT16:
-				elem_len = 2;
-				read_func = this.readI16;
-				break;
-			case AWD_FIELD_INT32:
-				elem_len = 4;
-				read_func = this.readI32;
-				break;
-			case AWD_FIELD_BOOL:
-			case AWD_FIELD_UINT8:
-				elem_len = 1;
-				read_func = this.readU8;
-				break;
-			case AWD_FIELD_UINT16:
-				elem_len = 2;
-				read_func = this.readU16;
-				break;
-			case AWD_FIELD_UINT32:
-			case AWD_FIELD_BADDR:
-				elem_len = 4;
-				read_func = this.readU32;
-				break;
-			case AWD_FIELD_FLOAT32:
-				elem_len = 4;
-				read_func = this.readF32;
-				break;
-			case AWD_FIELD_FLOAT64:
-				elem_len = 8;
-				read_func = this.readF64;
-				break;
-			case AWD_FIELD_VECTOR2x1:
-			case AWD_FIELD_VECTOR3x1:
-			case AWD_FIELD_VECTOR4x1:
-			case AWD_FIELD_MTX3x2:
-			case AWD_FIELD_MTX3x3:
-			case AWD_FIELD_MTX4x3:
-			case AWD_FIELD_MTX4x4:
-				elem_len = 8;
-				read_func = this.readF64;
-				break;
-		}
-
-		if (elem_len < len) {
-			var list;
-			var num_read;
-			var num_elems;
-
-			list = [];
-			num_read = 0;
-			num_elems = len / elem_len;
-
-			while (num_read < num_elems) {
-				list.push(read_func.call( this ) );
-				num_read ++;
-			}
-
-			return list;
-		}
-		else {
-			return read_func.call( this );
+			return out.join('');
 		}
 
 	};
 
-
-	AWDLoader.prototype.readU8 = function () {
-		return this._data.getUint8( this._ptr ++ );
-	};
-	AWDLoader.prototype.readI8 = function () {
-		return this._data.getInt8( this._ptr ++ );
-	};
-
-	AWDLoader.prototype.readU16 = function () {
-		var a = this._data.getUint16( this._ptr, littleEndian );
-		this._ptr += 2;
-		return a;
-	};
-	AWDLoader.prototype.readI16 = function () {
-		var a = this._data.getInt16( this._ptr, littleEndian );
-		this._ptr += 2;
-		return a;
-	};
-
-	AWDLoader.prototype.readU32 = function () {
-		var a = this._data.getUint32( this._ptr, littleEndian );
-		this._ptr += 4;
-		return a;
-	};
-	AWDLoader.prototype.readI32 = function () {
-		var a = this._data.getInt32( this._ptr, littleEndian );
-		this._ptr += 4;
-		return a;
-	};
-	AWDLoader.prototype.readF32 = function () {
-		var a = this._data.getFloat32( this._ptr, littleEndian );
-		this._ptr += 4;
-		return a;
-	};
-	AWDLoader.prototype.readF64 = function () {
-		var a = this._data.getFloat64( this._ptr, littleEndian );
-		this._ptr += 8;
-		return a;
-	};
-
-
-  /**
-   * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode.
-   * @param {Array.<number>} bytes UTF-8 byte array.
-   * @return {string} 16-bit Unicode string.
-   */
-	AWDLoader.prototype.readUTF = function () {
-		var len = this.readU16();
-
-		return this.readUTFBytes( len );
-	};
-
-  /**
-   * Converts a UTF-8 byte array to JavaScript's 16-bit Unicode.
-   * @param {Array.<number>} bytes UTF-8 byte array.
-   * @return {string} 16-bit Unicode string.
-   */
-	AWDLoader.prototype.readUTFBytes = function ( len ) {
-
-
-    // TODO(user): Use native implementations if/when available
-
-		var out = [], c = 0;
-
-		while ( out.length < len ) {
-			var c1 = this._data.getUint8( this._ptr ++, littleEndian );
-			if (c1 < 128) {
-				out[c ++] = String.fromCharCode(c1);
-			} else if (c1 > 191 && c1 < 224) {
-				var c2 = this._data.getUint8( this._ptr ++, littleEndian );
-				out[c ++] = String.fromCharCode((c1 & 31) << 6 | c2 & 63);
-			} else {
-				var c2 = this._data.getUint8( this._ptr ++, littleEndian );
-				var c3 = this._data.getUint8( this._ptr ++, littleEndian );
-				out[c ++] = String.fromCharCode(
-            (c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63
-        );
-			}
-		}
-		return out.join('');
-	};
-
-
-
-
-
-
-
-
-
-	AWDProperties = function() {};
-
-	AWDProperties.prototype = {
-
-
-    set : function(key, value)
-    {
-	this[key] = value;
-    },
-
-    get : function(key, fallback)
-    {
-	if ( this.hasOwnProperty(key) )
-        return this[key];
-      else return fallback;
-    }
-  };
-
-	return AWDLoader;
-
 })();

+ 6 - 4
examples/js/loaders/AssimpJSONLoader.js

@@ -20,13 +20,11 @@ THREE.AssimpJSONLoader.prototype = {
 
 	constructor: THREE.AssimpJSONLoader,
 
-	texturePath : '',
-
-	load: function ( url, onLoad, onProgress, onError, texturePath ) {
+	load: function ( url, onLoad, onProgress, onError ) {
 
 		var scope = this;
 
-		this.texturePath = texturePath && ( typeof texturePath === "string" ) ? texturePath : this.extractUrlBase( url );
+		this.texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : this.extractUrlBase( url );
 
 		var loader = new THREE.XHRLoader( this.manager );
 		loader.setCrossOrigin( this.crossOrigin );
@@ -60,6 +58,10 @@ THREE.AssimpJSONLoader.prototype = {
 		this.crossOrigin = value;
 	},
 
+	setTexturePath: function ( value ) {
+		this.texturePath = value;
+	},
+
 	extractUrlBase: function ( url ) { // from three/src/loaders/Loader.js
 		var parts = url.split( '/' );
 		parts.pop();

+ 434 - 491
examples/js/loaders/BinaryLoader.js

@@ -2,751 +2,694 @@
  * @author alteredq / http://alteredqualia.com/
  */
 
-THREE.BinaryLoader = function ( showStatus ) {
+THREE.BinaryLoader = function ( manager ) {
 
-	THREE.Loader.call( this, showStatus );
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
 };
 
-THREE.BinaryLoader.prototype = Object.create( THREE.Loader.prototype );
-THREE.BinaryLoader.prototype.constructor = THREE.BinaryLoader;
+THREE.BinaryLoader.prototype = {
 
-// Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
-//  - binary models consist of two files: JS and BIN
-//  - parameters
-//		- url (required)
-//		- callback (required)
-//		- texturePath (optional: if not specified, textures will be assumed to be in the same folder as JS model file)
-//		- binaryPath (optional: if not specified, binary file will be assumed to be in the same folder as JS model file)
+	constructor: THREE.BinaryLoader,
 
-THREE.BinaryLoader.prototype.load = function ( url, callback, texturePath, binaryPath ) {
+	// Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
+	//  - binary models consist of two files: JS and BIN
+	//  - parameters
+	//		- url (required)
+	//		- callback (required)
+	//		- texturePath (optional: if not specified, textures will be assumed to be in the same folder as JS model file)
+	//		- binaryPath (optional: if not specified, binary file will be assumed to be in the same folder as JS model file)
+	load: function ( url, onLoad, onProgress, onError ) {
 
-	// todo: unify load API to for easier SceneLoader use
+		// todo: unify load API to for easier SceneLoader use
 
-	texturePath = texturePath || this.extractUrlBase( url );
-	binaryPath = binaryPath || this.extractUrlBase( url );
+		var texturePath = this.texturePath || THREE.Loader.prototype.extractUrlBase( url );
+		var binaryPath  = this.binaryPath || THREE.Loader.prototype.extractUrlBase( url );
 
-	var callbackProgress = this.showProgress ? THREE.Loader.prototype.updateProgress : undefined;
+		// #1 load JS part via web worker
 
-	this.onLoadStart();
+		var scope = this;
 
-	// #1 load JS part via web worker
+		var jsonloader = new THREE.XHRLoader( this.manager );
+		jsonloader.setCrossOrigin( this.crossOrigin );
+		jsonloader.load( url, function ( data ) {
 
-	this.loadAjaxJSON( this, url, callback, texturePath, binaryPath, callbackProgress );
+			var json = JSON.parse( data );
 
-};
-
-THREE.BinaryLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, binaryPath, callbackProgress ) {
-
-	var xhr = new XMLHttpRequest();
-
-	texturePath = texturePath && ( typeof texturePath === "string" ) ? texturePath : this.extractUrlBase( url );
-	binaryPath = binaryPath && ( typeof binaryPath === "string" ) ? binaryPath : this.extractUrlBase( url );
-
-	xhr.onreadystatechange = function () {
-
-		if ( xhr.readyState == 4 ) {
-
-			if ( xhr.status == 200 || xhr.status == 0 ) {
-
-				var json = JSON.parse( xhr.responseText );
-				context.loadAjaxBuffers( json, callback, binaryPath, texturePath, callbackProgress );
-
-			} else {
-
-				console.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
+			var bufferUrl = binaryPath + json.buffers;
 
-			}
-
-		}
-
-	};
-
-	xhr.open( "GET", url, true );
-	xhr.send( null );
-
-};
-
-THREE.BinaryLoader.prototype.loadAjaxBuffers = function ( json, callback, binaryPath, texturePath, callbackProgress ) {
-
-	var scope = this;
+			var bufferLoader = new THREE.XHRLoader( scope.manager );
+			bufferLoader.setCrossOrigin( scope.crossOrigin );
+			bufferLoader.setResponseType( 'arraybuffer' );
+			bufferLoader.load( bufferUrl, function ( bufData ) {
 
-	var xhr = new XMLHttpRequest(),
-		url = binaryPath + json.buffers;
+				// IEWEBGL needs this ???
+				//buffer = ( new Uint8Array( xhr.responseBody ) ).buffer;
 
-	xhr.addEventListener( 'load', function ( event ) {
+				//// iOS and other XMLHttpRequest level 1 ???
 
-		var buffer = xhr.response;
+				scope.parse( bufData, onLoad, texturePath, json.materials );
 
-		if ( buffer === undefined ) {
+			}, onProgress, onError);
 
-			// IEWEBGL needs this
-			buffer = ( new Uint8Array( xhr.responseBody ) ).buffer;
+		}, onProgress, onError );
 
-		}
+	},
 
-		if ( buffer.byteLength == 0 ) {  // iOS and other XMLHttpRequest level 1
+	setBinaryPath: function ( value ) {
 
-			var buffer = new ArrayBuffer( xhr.responseText.length );
+		this.binaryPath = value;
 
-			var bufView = new Uint8Array( buffer );
+	},
 
-			for ( var i = 0, l = xhr.responseText.length; i < l; i ++ ) {
+	setCrossOrigin: function ( value ) {
 
-				bufView[ i ] = xhr.responseText.charCodeAt( i ) & 0xff;
-
-			}
-
-		}
-
-		scope.createBinModel( buffer, callback, texturePath, json.materials );
-
-	}, false );
-
-	if ( callbackProgress !== undefined ) {
-
-		xhr.addEventListener( 'progress', function ( event ) {
-
-			if ( event.lengthComputable ) {
-
-				callbackProgress( event );
-
-			}
-
-		}, false );
-
-	}
-
-	xhr.addEventListener( 'error', function ( event ) {
-
-		console.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
-
-	}, false );
-
-
-	xhr.open( "GET", url, true );
-	xhr.responseType = "arraybuffer";
-	if ( xhr.overrideMimeType ) xhr.overrideMimeType( "text/plain; charset=x-user-defined" );
-	xhr.send( null );
-
-};
+		this.crossOrigin = value;
 
-// Binary AJAX parser
+	},
 
-THREE.BinaryLoader.prototype.createBinModel = function ( data, callback, texturePath, jsonMaterials ) {
+	setTexturePath: function ( value ) {
 
-	var Model = function ( texturePath ) {
+		this.texturePath = value;
 
-		var scope = this,
-			currentOffset = 0,
-			md,
-			normals = [],
-			uvs = [],
-			start_tri_flat, start_tri_smooth, start_tri_flat_uv, start_tri_smooth_uv,
-			start_quad_flat, start_quad_smooth, start_quad_flat_uv, start_quad_smooth_uv,
-			tri_size, quad_size,
-			len_tri_flat, len_tri_smooth, len_tri_flat_uv, len_tri_smooth_uv,
-			len_quad_flat, len_quad_smooth, len_quad_flat_uv, len_quad_smooth_uv;
+	},
 
+	parse: function ( data, callback, texturePath, jsonMaterials ) {
 
-		THREE.Geometry.call( this );
+		var Model = function ( texturePath ) {
 
-		md = parseMetaData( data, currentOffset );
+			var scope = this,
+				currentOffset = 0,
+				md,
+				normals = [],
+				uvs = [],
+				start_tri_flat, start_tri_smooth, start_tri_flat_uv, start_tri_smooth_uv,
+				start_quad_flat, start_quad_smooth, start_quad_flat_uv, start_quad_smooth_uv,
+				tri_size, quad_size,
+				len_tri_flat, len_tri_smooth, len_tri_flat_uv, len_tri_smooth_uv,
+				len_quad_flat, len_quad_smooth, len_quad_flat_uv, len_quad_smooth_uv;
 
-		currentOffset += md.header_bytes;
-/*
-		md.vertex_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
-		md.material_index_bytes = Uint16Array.BYTES_PER_ELEMENT;
-		md.normal_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
-		md.uv_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
-*/
-		// buffers sizes
 
-		tri_size =  md.vertex_index_bytes * 3 + md.material_index_bytes;
-		quad_size = md.vertex_index_bytes * 4 + md.material_index_bytes;
+			THREE.Geometry.call( this );
 
-		len_tri_flat      = md.ntri_flat      * ( tri_size );
-		len_tri_smooth    = md.ntri_smooth    * ( tri_size + md.normal_index_bytes * 3 );
-		len_tri_flat_uv   = md.ntri_flat_uv   * ( tri_size + md.uv_index_bytes * 3 );
-		len_tri_smooth_uv = md.ntri_smooth_uv * ( tri_size + md.normal_index_bytes * 3 + md.uv_index_bytes * 3 );
+			md = parseMetaData( data, currentOffset );
 
-		len_quad_flat      = md.nquad_flat      * ( quad_size );
-		len_quad_smooth    = md.nquad_smooth    * ( quad_size + md.normal_index_bytes * 4 );
-		len_quad_flat_uv   = md.nquad_flat_uv   * ( quad_size + md.uv_index_bytes * 4 );
-		len_quad_smooth_uv = md.nquad_smooth_uv * ( quad_size + md.normal_index_bytes * 4 + md.uv_index_bytes * 4 );
+			currentOffset += md.header_bytes;
+	/*
+			md.vertex_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
+			md.material_index_bytes = Uint16Array.BYTES_PER_ELEMENT;
+			md.normal_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
+			md.uv_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
+	*/
+			// buffers sizes
 
-		// read buffers
+			tri_size =  md.vertex_index_bytes * 3 + md.material_index_bytes;
+			quad_size = md.vertex_index_bytes * 4 + md.material_index_bytes;
 
-		currentOffset += init_vertices( currentOffset );
+			len_tri_flat      = md.ntri_flat      * ( tri_size );
+			len_tri_smooth    = md.ntri_smooth    * ( tri_size + md.normal_index_bytes * 3 );
+			len_tri_flat_uv   = md.ntri_flat_uv   * ( tri_size + md.uv_index_bytes * 3 );
+			len_tri_smooth_uv = md.ntri_smooth_uv * ( tri_size + md.normal_index_bytes * 3 + md.uv_index_bytes * 3 );
 
-		currentOffset += init_normals( currentOffset );
-		currentOffset += handlePadding( md.nnormals * 3 );
+			len_quad_flat      = md.nquad_flat      * ( quad_size );
+			len_quad_smooth    = md.nquad_smooth    * ( quad_size + md.normal_index_bytes * 4 );
+			len_quad_flat_uv   = md.nquad_flat_uv   * ( quad_size + md.uv_index_bytes * 4 );
+			len_quad_smooth_uv = md.nquad_smooth_uv * ( quad_size + md.normal_index_bytes * 4 + md.uv_index_bytes * 4 );
 
-		currentOffset += init_uvs( currentOffset );
+			// read buffers
 
-		start_tri_flat 		= currentOffset;
-		start_tri_smooth    = start_tri_flat    + len_tri_flat    + handlePadding( md.ntri_flat * 2 );
-		start_tri_flat_uv   = start_tri_smooth  + len_tri_smooth  + handlePadding( md.ntri_smooth * 2 );
-		start_tri_smooth_uv = start_tri_flat_uv + len_tri_flat_uv + handlePadding( md.ntri_flat_uv * 2 );
+			currentOffset += init_vertices( currentOffset );
 
-		start_quad_flat     = start_tri_smooth_uv + len_tri_smooth_uv  + handlePadding( md.ntri_smooth_uv * 2 );
-		start_quad_smooth   = start_quad_flat     + len_quad_flat	   + handlePadding( md.nquad_flat * 2 );
-		start_quad_flat_uv  = start_quad_smooth   + len_quad_smooth    + handlePadding( md.nquad_smooth * 2 );
-		start_quad_smooth_uv = start_quad_flat_uv  + len_quad_flat_uv   + handlePadding( md.nquad_flat_uv * 2 );
+			currentOffset += init_normals( currentOffset );
+			currentOffset += handlePadding( md.nnormals * 3 );
 
-		// have to first process faces with uvs
-		// so that face and uv indices match
+			currentOffset += init_uvs( currentOffset );
 
-		init_triangles_flat_uv( start_tri_flat_uv );
-		init_triangles_smooth_uv( start_tri_smooth_uv );
+			start_tri_flat 		= currentOffset;
+			start_tri_smooth    = start_tri_flat    + len_tri_flat    + handlePadding( md.ntri_flat * 2 );
+			start_tri_flat_uv   = start_tri_smooth  + len_tri_smooth  + handlePadding( md.ntri_smooth * 2 );
+			start_tri_smooth_uv = start_tri_flat_uv + len_tri_flat_uv + handlePadding( md.ntri_flat_uv * 2 );
 
-		init_quads_flat_uv( start_quad_flat_uv );
-		init_quads_smooth_uv( start_quad_smooth_uv );
+			start_quad_flat     = start_tri_smooth_uv + len_tri_smooth_uv  + handlePadding( md.ntri_smooth_uv * 2 );
+			start_quad_smooth   = start_quad_flat     + len_quad_flat	   + handlePadding( md.nquad_flat * 2 );
+			start_quad_flat_uv  = start_quad_smooth   + len_quad_smooth    + handlePadding( md.nquad_smooth * 2 );
+			start_quad_smooth_uv= start_quad_flat_uv  + len_quad_flat_uv   + handlePadding( md.nquad_flat_uv * 2 );
 
-		// now we can process untextured faces
+			// have to first process faces with uvs
+			// so that face and uv indices match
 
-		init_triangles_flat( start_tri_flat );
-		init_triangles_smooth( start_tri_smooth );
+			init_triangles_flat_uv( start_tri_flat_uv );
+			init_triangles_smooth_uv( start_tri_smooth_uv );
 
-		init_quads_flat( start_quad_flat );
-		init_quads_smooth( start_quad_smooth );
+			init_quads_flat_uv( start_quad_flat_uv );
+			init_quads_smooth_uv( start_quad_smooth_uv );
 
-		this.computeFaceNormals();
+			// now we can process untextured faces
 
-		function handlePadding( n ) {
+			init_triangles_flat( start_tri_flat );
+			init_triangles_smooth( start_tri_smooth );
 
-			return ( n % 4 ) ? ( 4 - n % 4 ) : 0;
+			init_quads_flat( start_quad_flat );
+			init_quads_smooth( start_quad_smooth );
 
-		}
+			this.computeFaceNormals();
 
-		function parseMetaData( data, offset ) {
+			function handlePadding( n ) {
 
-			var metaData = {
+				return ( n % 4 ) ? ( 4 - n % 4 ) : 0;
 
-				'signature'               :parseString( data, offset,  12 ),
-				'header_bytes'            :parseUChar8( data, offset + 12 ),
-
-				'vertex_coordinate_bytes' :parseUChar8( data, offset + 13 ),
-				'normal_coordinate_bytes' :parseUChar8( data, offset + 14 ),
-				'uv_coordinate_bytes'     :parseUChar8( data, offset + 15 ),
-
-				'vertex_index_bytes'      :parseUChar8( data, offset + 16 ),
-				'normal_index_bytes'      :parseUChar8( data, offset + 17 ),
-				'uv_index_bytes'          :parseUChar8( data, offset + 18 ),
-				'material_index_bytes'    :parseUChar8( data, offset + 19 ),
-
-				'nvertices'    :parseUInt32( data, offset + 20 ),
-				'nnormals'     :parseUInt32( data, offset + 20 + 4 * 1 ),
-				'nuvs'         :parseUInt32( data, offset + 20 + 4 * 2 ),
-
-				'ntri_flat'      :parseUInt32( data, offset + 20 + 4 * 3 ),
-				'ntri_smooth'    :parseUInt32( data, offset + 20 + 4 * 4 ),
-				'ntri_flat_uv'   :parseUInt32( data, offset + 20 + 4 * 5 ),
-				'ntri_smooth_uv' :parseUInt32( data, offset + 20 + 4 * 6 ),
-
-				'nquad_flat'      :parseUInt32( data, offset + 20 + 4 * 7 ),
-				'nquad_smooth'    :parseUInt32( data, offset + 20 + 4 * 8 ),
-				'nquad_flat_uv'   :parseUInt32( data, offset + 20 + 4 * 9 ),
-				'nquad_smooth_uv' :parseUInt32( data, offset + 20 + 4 * 10 )
-
-			};
-/*
-			console.log( "signature: " + metaData.signature );
-
-			console.log( "header_bytes: " + metaData.header_bytes );
-			console.log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes );
-			console.log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes );
-			console.log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes );
-
-			console.log( "vertex_index_bytes: " + metaData.vertex_index_bytes );
-			console.log( "normal_index_bytes: " + metaData.normal_index_bytes );
-			console.log( "uv_index_bytes: " + metaData.uv_index_bytes );
-			console.log( "material_index_bytes: " + metaData.material_index_bytes );
-
-			console.log( "nvertices: " + metaData.nvertices );
-			console.log( "nnormals: " + metaData.nnormals );
-			console.log( "nuvs: " + metaData.nuvs );
-
-			console.log( "ntri_flat: " + metaData.ntri_flat );
-			console.log( "ntri_smooth: " + metaData.ntri_smooth );
-			console.log( "ntri_flat_uv: " + metaData.ntri_flat_uv );
-			console.log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv );
+			}
 
-			console.log( "nquad_flat: " + metaData.nquad_flat );
-			console.log( "nquad_smooth: " + metaData.nquad_smooth );
-			console.log( "nquad_flat_uv: " + metaData.nquad_flat_uv );
-			console.log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv );
+			function parseMetaData( data, offset ) {
+
+				var metaData = {
+
+					'signature'               :parseString( data, offset,  12 ),
+					'header_bytes'            :parseUChar8( data, offset + 12 ),
+
+					'vertex_coordinate_bytes' :parseUChar8( data, offset + 13 ),
+					'normal_coordinate_bytes' :parseUChar8( data, offset + 14 ),
+					'uv_coordinate_bytes'     :parseUChar8( data, offset + 15 ),
+
+					'vertex_index_bytes'      :parseUChar8( data, offset + 16 ),
+					'normal_index_bytes'      :parseUChar8( data, offset + 17 ),
+					'uv_index_bytes'          :parseUChar8( data, offset + 18 ),
+					'material_index_bytes'    :parseUChar8( data, offset + 19 ),
+
+					'nvertices'    :parseUInt32( data, offset + 20 ),
+					'nnormals'     :parseUInt32( data, offset + 20 + 4*1 ),
+					'nuvs'         :parseUInt32( data, offset + 20 + 4*2 ),
+
+					'ntri_flat'      :parseUInt32( data, offset + 20 + 4*3 ),
+					'ntri_smooth'    :parseUInt32( data, offset + 20 + 4*4 ),
+					'ntri_flat_uv'   :parseUInt32( data, offset + 20 + 4*5 ),
+					'ntri_smooth_uv' :parseUInt32( data, offset + 20 + 4*6 ),
+
+					'nquad_flat'      :parseUInt32( data, offset + 20 + 4*7 ),
+					'nquad_smooth'    :parseUInt32( data, offset + 20 + 4*8 ),
+					'nquad_flat_uv'   :parseUInt32( data, offset + 20 + 4*9 ),
+					'nquad_smooth_uv' :parseUInt32( data, offset + 20 + 4*10 )
+
+				};
+	/*
+				console.log( "signature: " + metaData.signature );
+
+				console.log( "header_bytes: " + metaData.header_bytes );
+				console.log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes );
+				console.log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes );
+				console.log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes );
+
+				console.log( "vertex_index_bytes: " + metaData.vertex_index_bytes );
+				console.log( "normal_index_bytes: " + metaData.normal_index_bytes );
+				console.log( "uv_index_bytes: " + metaData.uv_index_bytes );
+				console.log( "material_index_bytes: " + metaData.material_index_bytes );
+
+				console.log( "nvertices: " + metaData.nvertices );
+				console.log( "nnormals: " + metaData.nnormals );
+				console.log( "nuvs: " + metaData.nuvs );
+
+				console.log( "ntri_flat: " + metaData.ntri_flat );
+				console.log( "ntri_smooth: " + metaData.ntri_smooth );
+				console.log( "ntri_flat_uv: " + metaData.ntri_flat_uv );
+				console.log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv );
+
+				console.log( "nquad_flat: " + metaData.nquad_flat );
+				console.log( "nquad_smooth: " + metaData.nquad_smooth );
+				console.log( "nquad_flat_uv: " + metaData.nquad_flat_uv );
+				console.log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv );
+
+				var total = metaData.header_bytes
+						  + metaData.nvertices * metaData.vertex_coordinate_bytes * 3
+						  + metaData.nnormals * metaData.normal_coordinate_bytes * 3
+						  + metaData.nuvs * metaData.uv_coordinate_bytes * 2
+						  + metaData.ntri_flat * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes )
+						  + metaData.ntri_smooth * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 )
+						  + metaData.ntri_flat_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.uv_index_bytes*3 )
+						  + metaData.ntri_smooth_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 + metaData.uv_index_bytes*3 )
+						  + metaData.nquad_flat * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes )
+						  + metaData.nquad_smooth * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 )
+						  + metaData.nquad_flat_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.uv_index_bytes*4 )
+						  + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 );
+				console.log( "total bytes: " + total );
+	*/
+
+				return metaData;
 
-			var total = metaData.header_bytes
-					  + metaData.nvertices * metaData.vertex_coordinate_bytes * 3
-					  + metaData.nnormals * metaData.normal_coordinate_bytes * 3
-					  + metaData.nuvs * metaData.uv_coordinate_bytes * 2
-					  + metaData.ntri_flat * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes )
-					  + metaData.ntri_smooth * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 )
-					  + metaData.ntri_flat_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.uv_index_bytes*3 )
-					  + metaData.ntri_smooth_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 + metaData.uv_index_bytes*3 )
-					  + metaData.nquad_flat * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes )
-					  + metaData.nquad_smooth * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 )
-					  + metaData.nquad_flat_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.uv_index_bytes*4 )
-					  + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 );
-			console.log( "total bytes: " + total );
-*/
+			}
 
-			return metaData;
+			function parseString( data, offset, length ) {
 
-		}
+				var charArray = new Uint8Array( data, offset, length );
 
-		function parseString( data, offset, length ) {
+				var text = "";
 
-			var charArray = new Uint8Array( data, offset, length );
+				for ( var i = 0; i < length; i ++ ) {
 
-			var text = "";
+					text += String.fromCharCode( charArray[ offset + i ] );
 
-			for ( var i = 0; i < length; i ++ ) {
+				}
 
-				text += String.fromCharCode( charArray[ offset + i ] );
+				return text;
 
 			}
 
-			return text;
+			function parseUChar8( data, offset ) {
 
-		}
+				var charArray = new Uint8Array( data, offset, 1 );
 
-		function parseUChar8( data, offset ) {
+				return charArray[ 0 ];
 
-			var charArray = new Uint8Array( data, offset, 1 );
+			}
 
-			return charArray[ 0 ];
+			function parseUInt32( data, offset ) {
 
-		}
+				var intArray = new Uint32Array( data, offset, 1 );
 
-		function parseUInt32( data, offset ) {
+				return intArray[ 0 ];
 
-			var intArray = new Uint32Array( data, offset, 1 );
+			}
 
-			return intArray[ 0 ];
+			function init_vertices( start ) {
 
-		}
+				var nElements = md.nvertices;
 
-		function init_vertices( start ) {
+				var coordArray = new Float32Array( data, start, nElements * 3 );
 
-			var nElements = md.nvertices;
+				var i, x, y, z;
 
-			var coordArray = new Float32Array( data, start, nElements * 3 );
+				for( i = 0; i < nElements; i ++ ) {
 
-			var i, x, y, z;
+					x = coordArray[ i * 3 ];
+					y = coordArray[ i * 3 + 1 ];
+					z = coordArray[ i * 3 + 2 ];
 
-			for ( i = 0; i < nElements; i ++ ) {
+					scope.vertices.push( new THREE.Vector3( x, y, z ) );
 
-				x = coordArray[ i * 3 ];
-				y = coordArray[ i * 3 + 1 ];
-				z = coordArray[ i * 3 + 2 ];
+				}
 
-				scope.vertices.push( new THREE.Vector3( x, y, z ) );
+				return nElements * 3 * Float32Array.BYTES_PER_ELEMENT;
 
 			}
 
-			return nElements * 3 * Float32Array.BYTES_PER_ELEMENT;
+			function init_normals( start ) {
 
-		}
+				var nElements = md.nnormals;
 
-		function init_normals( start ) {
+				if ( nElements ) {
 
-			var nElements = md.nnormals;
+					var normalArray = new Int8Array( data, start, nElements * 3 );
 
-			if ( nElements ) {
+					var i, x, y, z;
 
-				var normalArray = new Int8Array( data, start, nElements * 3 );
-
-				var i, x, y, z;
+					for( i = 0; i < nElements; i ++ ) {
 
-				for ( i = 0; i < nElements; i ++ ) {
+						x = normalArray[ i * 3 ];
+						y = normalArray[ i * 3 + 1 ];
+						z = normalArray[ i * 3 + 2 ];
 
-					x = normalArray[ i * 3 ];
-					y = normalArray[ i * 3 + 1 ];
-					z = normalArray[ i * 3 + 2 ];
+						normals.push( x/127, y/127, z/127 );
 
-					normals.push( x / 127, y / 127, z / 127 );
+					}
 
 				}
 
-			}
+				return nElements * 3 * Int8Array.BYTES_PER_ELEMENT;
 
-			return nElements * 3 * Int8Array.BYTES_PER_ELEMENT;
+			}
 
-		}
+			function init_uvs( start ) {
 
-		function init_uvs( start ) {
+				var nElements = md.nuvs;
 
-			var nElements = md.nuvs;
+				if ( nElements ) {
 
-			if ( nElements ) {
+					var uvArray = new Float32Array( data, start, nElements * 2 );
 
-				var uvArray = new Float32Array( data, start, nElements * 2 );
+					var i, u, v;
 
-				var i, u, v;
+					for( i = 0; i < nElements; i ++ ) {
 
-				for ( i = 0; i < nElements; i ++ ) {
+						u = uvArray[ i * 2 ];
+						v = uvArray[ i * 2 + 1 ];
 
-					u = uvArray[ i * 2 ];
-					v = uvArray[ i * 2 + 1 ];
+						uvs.push( u, v );
 
-					uvs.push( u, v );
+					}
 
 				}
 
-			}
+				return nElements * 2 * Float32Array.BYTES_PER_ELEMENT;
 
-			return nElements * 2 * Float32Array.BYTES_PER_ELEMENT;
+			}
 
-		}
+			function init_uvs3( nElements, offset ) {
 
-		function init_uvs3( nElements, offset ) {
+				var i, uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
 
-			var i, uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
+				var uvIndexBuffer = new Uint32Array( data, offset, 3 * nElements );
 
-			var uvIndexBuffer = new Uint32Array( data, offset, 3 * nElements );
+				for( i = 0; i < nElements; i ++ ) {
 
-			for ( i = 0; i < nElements; i ++ ) {
+					uva = uvIndexBuffer[ i * 3 ];
+					uvb = uvIndexBuffer[ i * 3 + 1 ];
+					uvc = uvIndexBuffer[ i * 3 + 2 ];
 
-				uva = uvIndexBuffer[ i * 3 ];
-				uvb = uvIndexBuffer[ i * 3 + 1 ];
-				uvc = uvIndexBuffer[ i * 3 + 2 ];
+					u1 = uvs[ uva*2 ];
+					v1 = uvs[ uva*2 + 1 ];
 
-				u1 = uvs[ uva * 2 ];
-				v1 = uvs[ uva * 2 + 1 ];
+					u2 = uvs[ uvb*2 ];
+					v2 = uvs[ uvb*2 + 1 ];
 
-				u2 = uvs[ uvb * 2 ];
-				v2 = uvs[ uvb * 2 + 1 ];
+					u3 = uvs[ uvc*2 ];
+					v3 = uvs[ uvc*2 + 1 ];
 
-				u3 = uvs[ uvc * 2 ];
-				v3 = uvs[ uvc * 2 + 1 ];
+					scope.faceVertexUvs[ 0 ].push( [
+						new THREE.Vector2( u1, v1 ),
+						new THREE.Vector2( u2, v2 ),
+						new THREE.Vector2( u3, v3 )
+					] );
 
-				scope.faceVertexUvs[ 0 ].push( [
-					new THREE.Vector2( u1, v1 ),
-					new THREE.Vector2( u2, v2 ),
-					new THREE.Vector2( u3, v3 )
-				] );
+				}
 
 			}
 
-		}
+			function init_uvs4( nElements, offset ) {
 
-		function init_uvs4( nElements, offset ) {
+				var i, uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
 
-			var i, uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
+				var uvIndexBuffer = new Uint32Array( data, offset, 4 * nElements );
 
-			var uvIndexBuffer = new Uint32Array( data, offset, 4 * nElements );
+				for( i = 0; i < nElements; i ++ ) {
 
-			for ( i = 0; i < nElements; i ++ ) {
+					uva = uvIndexBuffer[ i * 4 ];
+					uvb = uvIndexBuffer[ i * 4 + 1 ];
+					uvc = uvIndexBuffer[ i * 4 + 2 ];
+					uvd = uvIndexBuffer[ i * 4 + 3 ];
 
-				uva = uvIndexBuffer[ i * 4 ];
-				uvb = uvIndexBuffer[ i * 4 + 1 ];
-				uvc = uvIndexBuffer[ i * 4 + 2 ];
-				uvd = uvIndexBuffer[ i * 4 + 3 ];
+					u1 = uvs[ uva*2 ];
+					v1 = uvs[ uva*2 + 1 ];
 
-				u1 = uvs[ uva * 2 ];
-				v1 = uvs[ uva * 2 + 1 ];
+					u2 = uvs[ uvb*2 ];
+					v2 = uvs[ uvb*2 + 1 ];
 
-				u2 = uvs[ uvb * 2 ];
-				v2 = uvs[ uvb * 2 + 1 ];
+					u3 = uvs[ uvc*2 ];
+					v3 = uvs[ uvc*2 + 1 ];
 
-				u3 = uvs[ uvc * 2 ];
-				v3 = uvs[ uvc * 2 + 1 ];
+					u4 = uvs[ uvd*2 ];
+					v4 = uvs[ uvd*2 + 1 ];
 
-				u4 = uvs[ uvd * 2 ];
-				v4 = uvs[ uvd * 2 + 1 ];
+					scope.faceVertexUvs[ 0 ].push( [
+						new THREE.Vector2( u1, v1 ),
+						new THREE.Vector2( u2, v2 ),
+						new THREE.Vector2( u4, v4 )
+					] );
 
-				scope.faceVertexUvs[ 0 ].push( [
-					new THREE.Vector2( u1, v1 ),
-					new THREE.Vector2( u2, v2 ),
-					new THREE.Vector2( u4, v4 )
-				] );
+					scope.faceVertexUvs[ 0 ].push( [
+						new THREE.Vector2( u2, v2 ),
+						new THREE.Vector2( u3, v3 ),
+						new THREE.Vector2( u4, v4 )
+					] );
 
-				scope.faceVertexUvs[ 0 ].push( [
-					new THREE.Vector2( u2, v2 ),
-					new THREE.Vector2( u3, v3 ),
-					new THREE.Vector2( u4, v4 )
-				] );
+				}
 
 			}
 
-		}
+			function init_faces3_flat( nElements, offsetVertices, offsetMaterials ) {
 
-		function init_faces3_flat( nElements, offsetVertices, offsetMaterials ) {
+				var i, a, b, c, m;
 
-			var i, a, b, c, m;
+				var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
+				var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
 
-			var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
-			var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
+				for( i = 0; i < nElements; i ++ ) {
 
-			for ( i = 0; i < nElements; i ++ ) {
+					a = vertexIndexBuffer[ i * 3 ];
+					b = vertexIndexBuffer[ i * 3 + 1 ];
+					c = vertexIndexBuffer[ i * 3 + 2 ];
 
-				a = vertexIndexBuffer[ i * 3 ];
-				b = vertexIndexBuffer[ i * 3 + 1 ];
-				c = vertexIndexBuffer[ i * 3 + 2 ];
+					m = materialIndexBuffer[ i ];
 
-				m = materialIndexBuffer[ i ];
+					scope.faces.push( new THREE.Face3( a, b, c ) );
 
-				scope.faces.push( new THREE.Face3( a, b, c ) );
+				}
 
 			}
 
-		}
+			function init_faces4_flat( nElements, offsetVertices, offsetMaterials ) {
 
-		function init_faces4_flat( nElements, offsetVertices, offsetMaterials ) {
+				var i, a, b, c, d, m;
 
-			var i, a, b, c, d, m;
+				var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
+				var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
 
-			var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
-			var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
+				for( i = 0; i < nElements; i ++ ) {
 
-			for ( i = 0; i < nElements; i ++ ) {
+					a = vertexIndexBuffer[ i * 4 ];
+					b = vertexIndexBuffer[ i * 4 + 1 ];
+					c = vertexIndexBuffer[ i * 4 + 2 ];
+					d = vertexIndexBuffer[ i * 4 + 3 ];
 
-				a = vertexIndexBuffer[ i * 4 ];
-				b = vertexIndexBuffer[ i * 4 + 1 ];
-				c = vertexIndexBuffer[ i * 4 + 2 ];
-				d = vertexIndexBuffer[ i * 4 + 3 ];
+					m = materialIndexBuffer[ i ];
 
-				m = materialIndexBuffer[ i ];
+					scope.faces.push( new THREE.Face3( a, b, d ) );
+					scope.faces.push( new THREE.Face3( b, c, d ) );
 
-				scope.faces.push( new THREE.Face3( a, b, d ) );
-				scope.faces.push( new THREE.Face3( b, c, d ) );
+				}
 
 			}
 
-		}
+			function init_faces3_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
 
-		function init_faces3_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
+				var i, a, b, c, m;
+				var na, nb, nc;
 
-			var i, a, b, c, m;
-			var na, nb, nc;
+				var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
+				var normalIndexBuffer = new Uint32Array( data, offsetNormals, 3 * nElements );
+				var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
 
-			var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
-			var normalIndexBuffer = new Uint32Array( data, offsetNormals, 3 * nElements );
-			var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
+				for( i = 0; i < nElements; i ++ ) {
 
-			for ( i = 0; i < nElements; i ++ ) {
+					a = vertexIndexBuffer[ i * 3 ];
+					b = vertexIndexBuffer[ i * 3 + 1 ];
+					c = vertexIndexBuffer[ i * 3 + 2 ];
 
-				a = vertexIndexBuffer[ i * 3 ];
-				b = vertexIndexBuffer[ i * 3 + 1 ];
-				c = vertexIndexBuffer[ i * 3 + 2 ];
+					na = normalIndexBuffer[ i * 3 ];
+					nb = normalIndexBuffer[ i * 3 + 1 ];
+					nc = normalIndexBuffer[ i * 3 + 2 ];
 
-				na = normalIndexBuffer[ i * 3 ];
-				nb = normalIndexBuffer[ i * 3 + 1 ];
-				nc = normalIndexBuffer[ i * 3 + 2 ];
+					m = materialIndexBuffer[ i ];
 
-				m = materialIndexBuffer[ i ];
+					var nax = normals[ na*3     ],
+						nay = normals[ na*3 + 1 ],
+						naz = normals[ na*3 + 2 ],
 
-				var nax = normals[ na * 3     ],
-					nay = normals[ na * 3 + 1 ],
-					naz = normals[ na * 3 + 2 ],
+						nbx = normals[ nb*3     ],
+						nby = normals[ nb*3 + 1 ],
+						nbz = normals[ nb*3 + 2 ],
 
-					nbx = normals[ nb * 3     ],
-					nby = normals[ nb * 3 + 1 ],
-					nbz = normals[ nb * 3 + 2 ],
+						ncx = normals[ nc*3     ],
+						ncy = normals[ nc*3 + 1 ],
+						ncz = normals[ nc*3 + 2 ];
 
-					ncx = normals[ nc * 3     ],
-					ncy = normals[ nc * 3 + 1 ],
-					ncz = normals[ nc * 3 + 2 ];
+					scope.faces.push( new THREE.Face3( a, b, c, [
+						new THREE.Vector3( nax, nay, naz ),
+						new THREE.Vector3( nbx, nby, nbz ),
+						new THREE.Vector3( ncx, ncy, ncz )
+					] ) );
 
-				scope.faces.push( new THREE.Face3( a, b, c, [
-					new THREE.Vector3( nax, nay, naz ),
-					new THREE.Vector3( nbx, nby, nbz ),
-					new THREE.Vector3( ncx, ncy, ncz )
-				] ) );
+				}
 
 			}
 
-		}
+			function init_faces4_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
 
-		function init_faces4_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
+				var i, a, b, c, d, m;
+				var na, nb, nc, nd;
 
-			var i, a, b, c, d, m;
-			var na, nb, nc, nd;
+				var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
+				var normalIndexBuffer = new Uint32Array( data, offsetNormals, 4 * nElements );
+				var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
 
-			var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
-			var normalIndexBuffer = new Uint32Array( data, offsetNormals, 4 * nElements );
-			var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
+				for( i = 0; i < nElements; i ++ ) {
 
-			for ( i = 0; i < nElements; i ++ ) {
+					a = vertexIndexBuffer[ i * 4 ];
+					b = vertexIndexBuffer[ i * 4 + 1 ];
+					c = vertexIndexBuffer[ i * 4 + 2 ];
+					d = vertexIndexBuffer[ i * 4 + 3 ];
 
-				a = vertexIndexBuffer[ i * 4 ];
-				b = vertexIndexBuffer[ i * 4 + 1 ];
-				c = vertexIndexBuffer[ i * 4 + 2 ];
-				d = vertexIndexBuffer[ i * 4 + 3 ];
+					na = normalIndexBuffer[ i * 4 ];
+					nb = normalIndexBuffer[ i * 4 + 1 ];
+					nc = normalIndexBuffer[ i * 4 + 2 ];
+					nd = normalIndexBuffer[ i * 4 + 3 ];
 
-				na = normalIndexBuffer[ i * 4 ];
-				nb = normalIndexBuffer[ i * 4 + 1 ];
-				nc = normalIndexBuffer[ i * 4 + 2 ];
-				nd = normalIndexBuffer[ i * 4 + 3 ];
+					m = materialIndexBuffer[ i ];
 
-				m = materialIndexBuffer[ i ];
+					var nax = normals[ na*3     ],
+						nay = normals[ na*3 + 1 ],
+						naz = normals[ na*3 + 2 ],
 
-				var nax = normals[ na * 3     ],
-					nay = normals[ na * 3 + 1 ],
-					naz = normals[ na * 3 + 2 ],
+						nbx = normals[ nb*3     ],
+						nby = normals[ nb*3 + 1 ],
+						nbz = normals[ nb*3 + 2 ],
 
-					nbx = normals[ nb * 3     ],
-					nby = normals[ nb * 3 + 1 ],
-					nbz = normals[ nb * 3 + 2 ],
+						ncx = normals[ nc*3     ],
+						ncy = normals[ nc*3 + 1 ],
+						ncz = normals[ nc*3 + 2 ],
 
-					ncx = normals[ nc * 3     ],
-					ncy = normals[ nc * 3 + 1 ],
-					ncz = normals[ nc * 3 + 2 ],
+						ndx = normals[ nd*3     ],
+						ndy = normals[ nd*3 + 1 ],
+						ndz = normals[ nd*3 + 2 ];
 
-					ndx = normals[ nd * 3     ],
-					ndy = normals[ nd * 3 + 1 ],
-					ndz = normals[ nd * 3 + 2 ];
+					scope.faces.push( new THREE.Face3( a, b, d, [
+						new THREE.Vector3( nax, nay, naz ),
+						new THREE.Vector3( nbx, nby, nbz ),
+						new THREE.Vector3( ndx, ndy, ndz )
+					] ) );
 
-				scope.faces.push( new THREE.Face3( a, b, d, [
-					new THREE.Vector3( nax, nay, naz ),
-					new THREE.Vector3( nbx, nby, nbz ),
-					new THREE.Vector3( ndx, ndy, ndz )
-				] ) );
+					scope.faces.push( new THREE.Face3( b, c, d, [
+						new THREE.Vector3( nbx, nby, nbz ),
+						new THREE.Vector3( ncx, ncy, ncz ),
+						new THREE.Vector3( ndx, ndy, ndz )
+					] ) );
 
-				scope.faces.push( new THREE.Face3( b, c, d, [
-					new THREE.Vector3( nbx, nby, nbz ),
-					new THREE.Vector3( ncx, ncy, ncz ),
-					new THREE.Vector3( ndx, ndy, ndz )
-				] ) );
+				}
 
 			}
 
-		}
+			function init_triangles_flat( start ) {
 
-		function init_triangles_flat( start ) {
+				var nElements = md.ntri_flat;
 
-			var nElements = md.ntri_flat;
+				if ( nElements ) {
 
-			if ( nElements ) {
+					var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
+					init_faces3_flat( nElements, start, offsetMaterials );
 
-				var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
-				init_faces3_flat( nElements, start, offsetMaterials );
+				}
 
 			}
 
-		}
+			function init_triangles_flat_uv( start ) {
 
-		function init_triangles_flat_uv( start ) {
+				var nElements = md.ntri_flat_uv;
 
-			var nElements = md.ntri_flat_uv;
+				if ( nElements ) {
 
-			if ( nElements ) {
+					var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
+					var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
 
-				var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
-				var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
+					init_faces3_flat( nElements, start, offsetMaterials );
+					init_uvs3( nElements, offsetUvs );
 
-				init_faces3_flat( nElements, start, offsetMaterials );
-				init_uvs3( nElements, offsetUvs );
+				}
 
 			}
 
-		}
+			function init_triangles_smooth( start ) {
 
-		function init_triangles_smooth( start ) {
+				var nElements = md.ntri_smooth;
 
-			var nElements = md.ntri_smooth;
+				if ( nElements ) {
 
-			if ( nElements ) {
+					var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
+					var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
 
-				var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
-				var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
+					init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
 
-				init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
+				}
 
 			}
 
-		}
+			function init_triangles_smooth_uv( start ) {
 
-		function init_triangles_smooth_uv( start ) {
+				var nElements = md.ntri_smooth_uv;
 
-			var nElements = md.ntri_smooth_uv;
+				if ( nElements ) {
 
-			if ( nElements ) {
+					var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
+					var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
+					var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
 
-				var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
-				var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
-				var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
+					init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
+					init_uvs3( nElements, offsetUvs );
 
-				init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
-				init_uvs3( nElements, offsetUvs );
+				}
 
 			}
 
-		}
+			function init_quads_flat( start ) {
 
-		function init_quads_flat( start ) {
+				var nElements = md.nquad_flat;
 
-			var nElements = md.nquad_flat;
+				if ( nElements ) {
 
-			if ( nElements ) {
+					var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
+					init_faces4_flat( nElements, start, offsetMaterials );
 
-				var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
-				init_faces4_flat( nElements, start, offsetMaterials );
+				}
 
 			}
 
-		}
+			function init_quads_flat_uv( start ) {
 
-		function init_quads_flat_uv( start ) {
+				var nElements = md.nquad_flat_uv;
 
-			var nElements = md.nquad_flat_uv;
+				if ( nElements ) {
 
-			if ( nElements ) {
+					var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
+					var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
 
-				var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
-				var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
+					init_faces4_flat( nElements, start, offsetMaterials );
+					init_uvs4( nElements, offsetUvs );
 
-				init_faces4_flat( nElements, start, offsetMaterials );
-				init_uvs4( nElements, offsetUvs );
+				}
 
 			}
 
-		}
+			function init_quads_smooth( start ) {
 
-		function init_quads_smooth( start ) {
+				var nElements = md.nquad_smooth;
 
-			var nElements = md.nquad_smooth;
+				if ( nElements ) {
 
-			if ( nElements ) {
+					var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
+					var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
 
-				var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
-				var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
+					init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
 
-				init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
+				}
 
 			}
 
-		}
+			function init_quads_smooth_uv( start ) {
 
-		function init_quads_smooth_uv( start ) {
+				var nElements = md.nquad_smooth_uv;
 
-			var nElements = md.nquad_smooth_uv;
+				if ( nElements ) {
 
-			if ( nElements ) {
+					var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
+					var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
+					var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
 
-				var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
-				var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
-				var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
+					init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
+					init_uvs4( nElements, offsetUvs );
 
-				init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
-				init_uvs4( nElements, offsetUvs );
+				}
 
 			}
 
-		}
+		};
 
-	};
+		Model.prototype = Object.create( THREE.Geometry.prototype );
+		Model.prototype.constructor = Model;
 
-	Model.prototype = Object.create( THREE.Geometry.prototype );
-	Model.prototype.constructor = Model;
+		var geometry = new Model( texturePath );
+		var materials = THREE.Loader.prototype.initMaterials( jsonMaterials, texturePath, this.crossOrigin );
 
-	var geometry = new Model( texturePath );
-	var materials = this.initMaterials( jsonMaterials, texturePath );
+		if ( THREE.Loader.prototype.needsTangents( materials ) ) geometry.computeTangents();
 
-	if ( this.needsTangents( materials ) ) geometry.computeTangents();
+		callback( geometry, materials );
 
-	callback( geometry, materials );
+	}
 
 };

File diff suppressed because it is too large
+ 457 - 404
examples/js/loaders/ColladaLoader.js


+ 41 - 11
examples/js/loaders/MTLLoader.js

@@ -4,11 +4,9 @@
  * @author angelxuanchang
  */
 
-THREE.MTLLoader = function( baseUrl, options, crossOrigin ) {
+THREE.MTLLoader = function( manager ) {
 
-	this.baseUrl = baseUrl;
-	this.options = options;
-	this.crossOrigin = crossOrigin;
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
 };
 
@@ -20,7 +18,7 @@ THREE.MTLLoader.prototype = {
 
 		var scope = this;
 
-		var loader = new THREE.XHRLoader();
+		var loader = new THREE.XHRLoader( this.manager );
 		loader.setCrossOrigin( this.crossOrigin );
 		loader.load( url, function ( text ) {
 
@@ -30,6 +28,24 @@ THREE.MTLLoader.prototype = {
 
 	},
 
+	setBaseUrl: function( value ) {
+
+		this.baseUrl = value;
+
+	},
+
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
+	},
+
+	setMaterialOptions: function ( value ) {
+
+		this.materialOptions = value;
+
+	},
+
 	/**
 	 * Parses loaded MTL file
 	 * @param text - Content of MTL file
@@ -86,8 +102,9 @@ THREE.MTLLoader.prototype = {
 
 		}
 
-		var materialCreator = new THREE.MTLLoader.MaterialCreator( this.baseUrl, this.options );
-		materialCreator.crossOrigin = this.crossOrigin;
+		var materialCreator = new THREE.MTLLoader.MaterialCreator( this.baseUrl, this.materialOptions );
+		materialCreator.setCrossOrigin( this.crossOrigin );
+		materialCreator.setManager( this.manager );
 		materialCreator.setMaterials( materialsInfo );
 		return materialCreator;
 
@@ -130,6 +147,18 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 
 	constructor: THREE.MTLLoader.MaterialCreator,
 
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
+	},
+
+	setManager: function ( value ) {
+
+		this.manager = value;
+
+	},
+
 	setMaterials: function( materialsInfo ) {
 
 		this.materialsInfo = this.convert( materialsInfo );
@@ -372,10 +401,11 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 	},
 
 
-	loadTexture: function ( url, mapping, onLoad, onError ) {
+	loadTexture: function ( url, mapping, onLoad, onProgress, onError ) {
 
 		var texture;
 		var loader = THREE.Loader.Handlers.get( url );
+		var manager = ( this.manager !== undefined ) ? this.manager : THREE.DefaultLoadingManager;
 
 		if ( loader !== null ) {
 
@@ -385,8 +415,8 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 
 			texture = new THREE.Texture();
 
-			loader = new THREE.ImageLoader();
-			loader.crossOrigin = this.crossOrigin;
+			loader = new THREE.ImageLoader( manager );
+			loader.setCrossOrigin( this.crossOrigin );
 			loader.load( url, function ( image ) {
 
 				texture.image = THREE.MTLLoader.ensurePowerOfTwo_( image );
@@ -394,7 +424,7 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 
 				if ( onLoad ) onLoad( texture );
 
-			} );
+			}, onProgress, onError );
 
 		}
 

+ 6 - 0
examples/js/loaders/OBJLoader.js

@@ -26,6 +26,12 @@ THREE.OBJLoader.prototype = {
 
 	},
 
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
+	},
+
 	parse: function ( text ) {
 
 		console.time( 'OBJLoader' );

+ 9 - 2
examples/js/loaders/OBJMTLLoader.js

@@ -19,8 +19,9 @@ THREE.OBJMTLLoader.prototype = {
 
 		var scope = this;
 
-		var mtlLoader = new THREE.MTLLoader( url.substr( 0, url.lastIndexOf( "/" ) + 1 ) );
-		mtlLoader.crossOrigin = scope.crossOrigin;
+		var mtlLoader = new THREE.MTLLoader( this.manager );
+		mtlLoader.setBaseUrl( url.substr( 0, url.lastIndexOf( "/" ) + 1 ) );
+		mtlLoader.setCrossOrigin( this.crossOrigin );
 		mtlLoader.load( mtlurl, function ( materials ) {
 
 			var materialsCreator = materials;
@@ -56,6 +57,12 @@ THREE.OBJMTLLoader.prototype = {
 
 	},
 
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
+	},
+
 	/**
 	 * Parses loaded .obj file
 	 * @param data - content of .obj file

+ 6 - 0
examples/js/loaders/PDBLoader.js

@@ -27,6 +27,12 @@ THREE.PDBLoader.prototype = {
 
 	},
 
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
+	},
+
 	// Based on CanvasMol PDB parser
 
 	parsePDB: function ( text ) {

+ 17 - 29
examples/js/loaders/PLYLoader.js

@@ -27,7 +27,9 @@
  */
 
 
-THREE.PLYLoader = function () {
+THREE.PLYLoader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
 	this.propertyNameMapping = {};
 
@@ -37,42 +39,30 @@ THREE.PLYLoader.prototype = {
 
 	constructor: THREE.PLYLoader,
 
-	setPropertyNameMapping: function ( mapping ) {
-
-		this.propertyNameMapping = mapping;
-
-	},
-
-	load: function ( url, callback ) {
+	load: function ( url, onLoad, onProgress, onError ) {
 
 		var scope = this;
-		var request = new XMLHttpRequest();
-
-		request.addEventListener( 'load', function ( event ) {
 
-			var geometry = scope.parse( event.target.response );
+		var loader = new THREE.XHRLoader( this.manager );
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.setResponseType( 'arraybuffer' );
+		loader.load( url, function ( text ) {
 
-			scope.dispatchEvent( { type: 'load', content: geometry } );
+			onLoad( scope.parse( text ) );
 
-			if ( callback ) callback( geometry );
+		}, onProgress, onError );
 
-		}, false );
-
-		request.addEventListener( 'progress', function ( event ) {
-
-			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
+	},
 
-		}, false );
+	setCrossOrigin: function ( value ) {
 
-		request.addEventListener( 'error', function () {
+		this.crossOrigin = value;
 
-			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
+	},
 
-		}, false );
+	setPropertyNameMapping: function ( mapping ) {
 
-		request.open( 'GET', url, true );
-		request.responseType = "arraybuffer";
-		request.send( null );
+		this.propertyNameMapping = mapping;
 
 	},
 
@@ -477,6 +467,4 @@ THREE.PLYLoader.prototype = {
 
 	}
 
-};
-
-THREE.EventDispatcher.prototype.apply( THREE.PLYLoader.prototype );
+};

+ 3 - 1
examples/js/loaders/PVRLoader.js

@@ -8,8 +8,10 @@
  *   TODO : implement loadMipmaps option
  */
 
+THREE.PVRLoader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
-THREE.PVRLoader = function () {
 	this._parser = THREE.PVRLoader.parse;
 };
 

+ 8 - 3
examples/js/loaders/STLLoader.js

@@ -43,14 +43,19 @@ THREE.STLLoader.prototype = {
 
 		var loader = new THREE.XHRLoader( scope.manager );
 		loader.setCrossOrigin( this.crossOrigin );
-		loader.setResponseType('arraybuffer');
-		var request = loader.load( url, function ( text ) {
+		loader.setResponseType( 'arraybuffer' );
+		loader.load( url, function ( text ) {
 
 			onLoad( scope.parse( text ) );
 
 		}, onProgress, onError );
 
-		return request;
+	},
+
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
 	},
 
 	parse: function ( data ) {

+ 8 - 1
examples/js/loaders/SVGLoader.js

@@ -11,7 +11,7 @@ THREE.SVGLoader = function ( manager ) {
 
 THREE.SVGLoader.prototype = {
 
-	constructor: THREE.MaterialLoader,
+	constructor: THREE.SVGLoader,
 
 	load: function ( url, onLoad, onProgress, onError ) {
 
@@ -29,5 +29,12 @@ THREE.SVGLoader.prototype = {
 
 		}, onProgress, onError );
 
+	},
+
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
 	}
+
 };

+ 15 - 26
examples/js/loaders/VRMLLoader.js

@@ -2,7 +2,11 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-THREE.VRMLLoader = function () {};
+THREE.VRMLLoader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+
+};
 
 THREE.VRMLLoader.prototype = {
 
@@ -22,35 +26,23 @@ THREE.VRMLLoader.prototype = {
 
 	recordingFieldname: null,
 
-	load: function ( url, callback ) {
+	load: function ( url, onLoad, onProgress, onError ) {
 
 		var scope = this;
-		var request = new XMLHttpRequest();
-
-		request.addEventListener( 'load', function ( event ) {
-
-			var object = scope.parse( event.target.responseText );
-
-			scope.dispatchEvent( { type: 'load', content: object } );
-
-			if ( callback ) callback( object );
 
-		}, false );
+		var loader = new THREE.XHRLoader( this.manager );
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.load( url, function ( text ) {
 
-		request.addEventListener( 'progress', function ( event ) {
+			onLoad( scope.parse( text ) );
 
-			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
+		}, onProgress, onError );
 
-		}, false );
-
-		request.addEventListener( 'error', function () {
-
-			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
+	},
 
-		}, false );
+	setCrossOrigin: function ( value ) {
 
-		request.open( 'GET', url, true );
-		request.send( null );
+		this.crossOrigin = value;
 
 	},
 
@@ -833,7 +825,4 @@ THREE.VRMLLoader.prototype = {
 
 	}
 
-};
-
-THREE.EventDispatcher.prototype.apply( THREE.VRMLLoader.prototype );
-
+};

+ 6 - 0
examples/js/loaders/VTKLoader.js

@@ -26,6 +26,12 @@ THREE.VTKLoader.prototype = {
 
 	},
 
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
+	},
+
 	parse: function ( data ) {
 
 		var indices = [];

+ 1 - 4
examples/webgl_lights_pointlights.html

@@ -68,8 +68,7 @@
 
 				scene = new THREE.Scene();
 
-				loader = new THREE.BinaryLoader( true );
-				document.body.appendChild( loader.statusDomElement );
+				loader = new THREE.BinaryLoader();
 
 				var callback = function( geometry ) {
 
@@ -77,8 +76,6 @@
 					object.scale.x = object.scale.y = object.scale.z = 0.80;
 					scene.add( object );
 
-					loader.statusDomElement.style.display = "none";
-
 				};
 
 				loader.load( "obj/walt/WaltHead_bin.js", callback );

+ 1 - 3
examples/webgl_loader_ply.html

@@ -90,9 +90,8 @@
 				// PLY file
 
 				var loader = new THREE.PLYLoader();
-				loader.addEventListener( 'load', function ( event ) {
+				loader.load( './models/ply/ascii/dolphins.ply', function ( geometry ) {
 
-					var geometry = event.content;
 					var material = new THREE.MeshPhongMaterial( { color: 0x0055ff, specular: 0x111111, shininess: 200 } );
 					var mesh = new THREE.Mesh( geometry, material );
 
@@ -106,7 +105,6 @@
 					scene.add( mesh );
 
 				} );
-				loader.load( './models/ply/ascii/dolphins.ply' );
 
 				// Lights
 

+ 2 - 3
examples/webgl_loader_vrml.html

@@ -79,12 +79,11 @@
 				camera.add( dirLight.target );
 
 				var loader = new THREE.VRMLLoader();
-				loader.addEventListener( 'load', function ( event ) {
+				loader.load( 'models/vrml/house.wrl', function ( object ) {
 
-					scene.add(event.content);
+					scene.add( object );
 
 				} );
-				loader.load( "models/vrml/house.wrl" );
 
 				// renderer
 

+ 11 - 2
src/loaders/BinaryTextureLoader.js

@@ -4,7 +4,9 @@
  * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...)
  */
 
-THREE.DataTextureLoader = THREE.BinaryTextureLoader = function () {
+THREE.DataTextureLoader = THREE.BinaryTextureLoader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
 	// override in sub classes
 	this._parser = null;
@@ -21,7 +23,8 @@ THREE.BinaryTextureLoader.prototype = {
 
 		var texture = new THREE.DataTexture( );
 
-		var loader = new THREE.XHRLoader();
+		var loader = new THREE.XHRLoader( this.manager );
+		loader.setCrossOrigin( this.crossOrigin );
 		loader.setResponseType( 'arraybuffer' );
 
 		loader.load( url, function ( buffer ) {
@@ -82,6 +85,12 @@ THREE.BinaryTextureLoader.prototype = {
 
 		return texture;
 
+	},
+
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
 	}
 
 };

+ 14 - 5
src/loaders/CompressedTextureLoader.js

@@ -4,7 +4,9 @@
  * Abstract Base class to block based textures loader (dds, pvr, ...)
  */
 
-THREE.CompressedTextureLoader = function () {
+THREE.CompressedTextureLoader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
 	// override in sub classes
 	this._parser = null;
@@ -16,7 +18,7 @@ THREE.CompressedTextureLoader.prototype = {
 
 	constructor: THREE.CompressedTextureLoader,
 
-	load: function ( url, onLoad, onError ) {
+	load: function ( url, onLoad, onProgress, onError ) {
 
 		var scope = this;
 
@@ -25,7 +27,8 @@ THREE.CompressedTextureLoader.prototype = {
 		var texture = new THREE.CompressedTexture();
 		texture.image = images;
 
-		var loader = new THREE.XHRLoader();
+		var loader = new THREE.XHRLoader( this.manager );
+		loader.setCrossOrigin( this.crossOrigin );
 		loader.setResponseType( 'arraybuffer' );
 
 		if ( Array.isArray( url ) ) {
@@ -59,7 +62,7 @@ THREE.CompressedTextureLoader.prototype = {
 
 					}
 
-				} );
+				}, onProgress, onError );
 
 			};
 
@@ -115,12 +118,18 @@ THREE.CompressedTextureLoader.prototype = {
 
 				if ( onLoad ) onLoad( texture );
 
-			} );
+			}, onProgress, onError );
 
 		}
 
 		return texture;
 
+	},
+
+	setCrossOrigin: function ( value ) {
+
+		this.crossOrigin = value;
+
 	}
 
 };

+ 1 - 1
src/loaders/GeometryLoader.js

@@ -16,7 +16,7 @@ THREE.GeometryLoader.prototype = {
 
 		var scope = this;
 
-		var loader = new THREE.XHRLoader();
+		var loader = new THREE.XHRLoader( this.manager );
 		loader.setCrossOrigin( this.crossOrigin );
 		loader.load( url, function ( text ) {
 

+ 265 - 309
src/loaders/JSONLoader.js

@@ -3,548 +3,504 @@
  * @author alteredq / http://alteredqualia.com/
  */
 
-THREE.JSONLoader = function ( showStatus ) {
+THREE.JSONLoader = function ( manager ) {
 
-	THREE.Loader.call( this, showStatus );
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
 	this.withCredentials = false;
 
 };
 
-THREE.JSONLoader.prototype = Object.create( THREE.Loader.prototype );
-THREE.JSONLoader.prototype.constructor = THREE.JSONLoader;
+THREE.JSONLoader.prototype = {
 
-THREE.JSONLoader.prototype.load = function ( url, callback, texturePath ) {
+	constructor: THREE.JSONLoader,
 
-	// TODO: unify load API to for easier SceneLoader use
+	load: function( url, onLoad, onProgress, onError ) {
 
-	texturePath = texturePath && ( typeof texturePath === 'string' ) ? texturePath : this.extractUrlBase( url );
+		var scope = this;
 
-	this.onLoadStart();
-	this.loadAjaxJSON( this, url, callback, texturePath );
+		var texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : THREE.Loader.prototype.extractUrlBase( url );
 
-};
-
-THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, callbackProgress ) {
-
-	var xhr = new XMLHttpRequest();
-
-	var length = 0;
-
-	xhr.onreadystatechange = function () {
-
-		if ( xhr.readyState === xhr.DONE ) {
-
-			if ( xhr.status === 200 || xhr.status === 0 ) {
-
-				if ( xhr.responseText ) {
-
-					var json = JSON.parse( xhr.responseText );
-					var metadata = json.metadata;
-
-					if ( metadata !== undefined ) {
-
-						if ( metadata.type === 'object' ) {
-
-							console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
-							return;
-
-						}
+		var loader = new THREE.XHRLoader( this.manager );
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.setWithCredentials( this.withCredentials );
+		loader.load( url, function ( text ) {
 
-						if ( metadata.type === 'scene' ) {
+			var json = JSON.parse( text );
+			var metadata = json.metadata;
 
-							console.error( 'THREE.JSONLoader: ' + url + ' seems to be a Scene. Use THREE.SceneLoader instead.' );
-							return;
+			if ( metadata !== undefined ) {
 
-						}
-
-					}
+				if ( metadata.type === 'object' ) {
 
-					var result = context.parse( json, texturePath );
-					callback( result.geometry, result.materials );
-
-				} else {
-
-					console.error( 'THREE.JSONLoader: ' + url + ' seems to be unreachable or the file is empty.' );
+					console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
+					return;
 
 				}
 
-				// in context of more complex asset initialization
-				// do not block on single failed file
-				// maybe should go even one more level up
-
-				context.onLoadComplete();
-
-			} else {
-
-				console.error( 'THREE.JSONLoader: Couldn\'t load ' + url + ' (' + xhr.status + ')' );
-
-			}
-
-		} else if ( xhr.readyState === xhr.LOADING ) {
-
-			if ( callbackProgress ) {
-
-				if ( length === 0 ) {
+				if ( metadata.type === 'scene' ) {
 
-					length = xhr.getResponseHeader( 'Content-Length' );
+					console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.SceneLoader instead.' );
+					return;
 
 				}
 
-				callbackProgress( { total: length, loaded: xhr.responseText.length } );
-
 			}
 
-		} else if ( xhr.readyState === xhr.HEADERS_RECEIVED ) {
+			var object = scope.parse( json, texturePath );
+			onLoad( object.geometry, object.materials );
 
-			if ( callbackProgress !== undefined ) {
+		} );
 
-				length = xhr.getResponseHeader( 'Content-Length' );
+	},
 
-			}
+	setCrossOrigin: function ( value ) {
 
-		}
+		this.crossOrigin = value;
 
-	};
+	},
 
-	xhr.open( 'GET', url, true );
-	xhr.withCredentials = this.withCredentials;
-	xhr.send( null );
+	setTexturePath: function ( value ) {
 
-};
+		this.texturePath = value;
 
-THREE.JSONLoader.prototype.parse = function ( json, texturePath ) {
+	},
 
-	var geometry = new THREE.Geometry(),
-	scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
+	parse: function ( json, texturePath ) {
 
-	parseModel( scale );
+		var scope = this,
+		geometry = new THREE.Geometry(),
+		scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
 
-	parseSkin();
-	parseMorphing( scale );
+		parseModel( scale );
 
-	geometry.computeFaceNormals();
-	geometry.computeBoundingSphere();
+		parseSkin();
+		parseMorphing( scale );
 
-	function parseModel( scale ) {
+		geometry.computeFaceNormals();
+		geometry.computeBoundingSphere();
 
-		function isBitSet( value, position ) {
+		function parseModel( scale ) {
 
-			return value & ( 1 << position );
+			function isBitSet( value, position ) {
 
-		}
+				return value & ( 1 << position );
+
+			}
 
-		var i, j, fi,
+			var i, j, fi,
 
-		offset, zLength,
+			offset, zLength,
 
 		colorIndex, normalIndex, uvIndex,
 
-		type,
-		isQuad,
-		hasMaterial,
-		hasFaceVertexUv,
-		hasFaceNormal, hasFaceVertexNormal,
-		hasFaceColor, hasFaceVertexColor,
+			type,
+			isQuad,
+			hasMaterial,
+			hasFaceVertexUv,
+			hasFaceNormal, hasFaceVertexNormal,
+			hasFaceColor, hasFaceVertexColor,
 
 		vertex, face, faceA, faceB, hex, normal,
 
-		uvLayer, uv, u, v,
+			uvLayer, uv, u, v,
 
-		faces = json.faces,
-		vertices = json.vertices,
-		normals = json.normals,
-		colors = json.colors,
+			faces = json.faces,
+			vertices = json.vertices,
+			normals = json.normals,
+			colors = json.colors,
 
-		nUvLayers = 0;
+			nUvLayers = 0;
 
-		if ( json.uvs !== undefined ) {
+			if ( json.uvs !== undefined ) {
 
-			// disregard empty arrays
+				// disregard empty arrays
 
-			for ( i = 0; i < json.uvs.length; i ++ ) {
+				for ( i = 0; i < json.uvs.length; i ++ ) {
 
-				if ( json.uvs[ i ].length ) nUvLayers ++;
+					if ( json.uvs[ i ].length ) nUvLayers ++;
 
-			}
+				}
 
-			for ( i = 0; i < nUvLayers; i ++ ) {
+				for ( i = 0; i < nUvLayers; i ++ ) {
 
-				geometry.faceVertexUvs[ i ] = [];
+					geometry.faceVertexUvs[ i ] = [];
 
-			}
+				}
 
-		}
+			}
 
-		offset = 0;
-		zLength = vertices.length;
+			offset = 0;
+			zLength = vertices.length;
 
-		while ( offset < zLength ) {
+			while ( offset < zLength ) {
 
-			vertex = new THREE.Vector3();
+				vertex = new THREE.Vector3();
 
-			vertex.x = vertices[ offset ++ ] * scale;
-			vertex.y = vertices[ offset ++ ] * scale;
-			vertex.z = vertices[ offset ++ ] * scale;
+				vertex.x = vertices[ offset ++ ] * scale;
+				vertex.y = vertices[ offset ++ ] * scale;
+				vertex.z = vertices[ offset ++ ] * scale;
 
-			geometry.vertices.push( vertex );
+				geometry.vertices.push( vertex );
 
-		}
+			}
 
-		offset = 0;
-		zLength = faces.length;
+			offset = 0;
+			zLength = faces.length;
 
-		while ( offset < zLength ) {
+			while ( offset < zLength ) {
 
-			type = faces[ offset ++ ];
+				type = faces[ offset ++ ];
 
 
-			isQuad              = isBitSet( type, 0 );
-			hasMaterial         = isBitSet( type, 1 );
-			hasFaceVertexUv     = isBitSet( type, 3 );
-			hasFaceNormal       = isBitSet( type, 4 );
-			hasFaceVertexNormal = isBitSet( type, 5 );
-			hasFaceColor	     = isBitSet( type, 6 );
-			hasFaceVertexColor  = isBitSet( type, 7 );
+				isQuad              = isBitSet( type, 0 );
+				hasMaterial         = isBitSet( type, 1 );
+				hasFaceVertexUv     = isBitSet( type, 3 );
+				hasFaceNormal       = isBitSet( type, 4 );
+				hasFaceVertexNormal = isBitSet( type, 5 );
+				hasFaceColor	     = isBitSet( type, 6 );
+				hasFaceVertexColor  = isBitSet( type, 7 );
 
-			// console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
+				// console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
 
-			if ( isQuad ) {
+				if ( isQuad ) {
 
-				faceA = new THREE.Face3();
-				faceA.a = faces[ offset ];
-				faceA.b = faces[ offset + 1 ];
-				faceA.c = faces[ offset + 3 ];
+					faceA = new THREE.Face3();
+					faceA.a = faces[ offset ];
+					faceA.b = faces[ offset + 1 ];
+					faceA.c = faces[ offset + 3 ];
 
-				faceB = new THREE.Face3();
-				faceB.a = faces[ offset + 1 ];
-				faceB.b = faces[ offset + 2 ];
-				faceB.c = faces[ offset + 3 ];
+					faceB = new THREE.Face3();
+					faceB.a = faces[ offset + 1 ];
+					faceB.b = faces[ offset + 2 ];
+					faceB.c = faces[ offset + 3 ];
 
-				offset += 4;
+					offset += 4;
 
-				if ( hasMaterial ) {
+					if ( hasMaterial ) {
 
 					offset ++;
 
-				}
+					}
 
-				// to get face <=> uv index correspondence
+					// to get face <=> uv index correspondence
 
-				fi = geometry.faces.length;
+					fi = geometry.faces.length;
 
-				if ( hasFaceVertexUv ) {
+					if ( hasFaceVertexUv ) {
 
-					for ( i = 0; i < nUvLayers; i ++ ) {
+						for ( i = 0; i < nUvLayers; i ++ ) {
 
-						uvLayer = json.uvs[ i ];
+							uvLayer = json.uvs[ i ];
 
-						geometry.faceVertexUvs[ i ][ fi ] = [];
+							geometry.faceVertexUvs[ i ][ fi ] = [];
 						geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
 
-						for ( j = 0; j < 4; j ++ ) {
+							for ( j = 0; j < 4; j ++ ) {
+
+								uvIndex = faces[ offset ++ ];
 
-							uvIndex = faces[ offset ++ ];
+								u = uvLayer[ uvIndex * 2 ];
+								v = uvLayer[ uvIndex * 2 + 1 ];
 
-							u = uvLayer[ uvIndex * 2 ];
-							v = uvLayer[ uvIndex * 2 + 1 ];
+								uv = new THREE.Vector2( u, v );
 
-							uv = new THREE.Vector2( u, v );
+								if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
+								if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
 
-							if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
-							if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
+							}
 
 						}
 
 					}
 
-				}
-
-				if ( hasFaceNormal ) {
-
-					normalIndex = faces[ offset ++ ] * 3;
-
-					faceA.normal.set(
-						normals[ normalIndex ++ ],
-						normals[ normalIndex ++ ],
-						normals[ normalIndex ]
-					);
-
-					faceB.normal.copy( faceA.normal );
-
-				}
-
-				if ( hasFaceVertexNormal ) {
-
-					for ( i = 0; i < 4; i ++ ) {
+					if ( hasFaceNormal ) {
 
 						normalIndex = faces[ offset ++ ] * 3;
 
-						normal = new THREE.Vector3(
+						faceA.normal.set(
 							normals[ normalIndex ++ ],
 							normals[ normalIndex ++ ],
 							normals[ normalIndex ]
 						);
 
-
-						if ( i !== 2 ) faceA.vertexNormals.push( normal );
-						if ( i !== 0 ) faceB.vertexNormals.push( normal );
+						faceB.normal.copy( faceA.normal );
 
 					}
 
-				}
+					if ( hasFaceVertexNormal ) {
 
+						for ( i = 0; i < 4; i ++ ) {
 
-				if ( hasFaceColor ) {
+							normalIndex = faces[ offset ++ ] * 3;
 
-					colorIndex = faces[ offset ++ ];
-					hex = colors[ colorIndex ];
+							normal = new THREE.Vector3(
+								normals[ normalIndex ++ ],
+								normals[ normalIndex ++ ],
+								normals[ normalIndex ]
+							);
 
-					faceA.color.setHex( hex );
-					faceB.color.setHex( hex );
 
-				}
+							if ( i !== 2 ) faceA.vertexNormals.push( normal );
+							if ( i !== 0 ) faceB.vertexNormals.push( normal );
 
+						}
+
+					}
 
-				if ( hasFaceVertexColor ) {
 
-					for ( i = 0; i < 4; i ++ ) {
+					if ( hasFaceColor ) {
 
 						colorIndex = faces[ offset ++ ];
 						hex = colors[ colorIndex ];
 
-						if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
-						if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
+						faceA.color.setHex( hex );
+						faceB.color.setHex( hex );
 
 					}
 
-				}
 
-				geometry.faces.push( faceA );
-				geometry.faces.push( faceB );
+					if ( hasFaceVertexColor ) {
 
-			} else {
+						for ( i = 0; i < 4; i ++ ) {
 
-				face = new THREE.Face3();
-				face.a = faces[ offset ++ ];
-				face.b = faces[ offset ++ ];
-				face.c = faces[ offset ++ ];
+							colorIndex = faces[ offset ++ ];
+							hex = colors[ colorIndex ];
 
-				if ( hasMaterial ) {
+							if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
+							if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
 
-					offset ++;
+						}
 
-				}
+					}
 
-				// to get face <=> uv index correspondence
+					geometry.faces.push( faceA );
+					geometry.faces.push( faceB );
 
-				fi = geometry.faces.length;
+				} else {
 
-				if ( hasFaceVertexUv ) {
+					face = new THREE.Face3();
+					face.a = faces[ offset ++ ];
+					face.b = faces[ offset ++ ];
+					face.c = faces[ offset ++ ];
 
-					for ( i = 0; i < nUvLayers; i ++ ) {
+					if ( hasMaterial ) {
 
-						uvLayer = json.uvs[ i ];
+					offset ++;
 
-						geometry.faceVertexUvs[ i ][ fi ] = [];
+					}
 
-						for ( j = 0; j < 3; j ++ ) {
+					// to get face <=> uv index correspondence
 
-							uvIndex = faces[ offset ++ ];
+					fi = geometry.faces.length;
 
-							u = uvLayer[ uvIndex * 2 ];
-							v = uvLayer[ uvIndex * 2 + 1 ];
+					if ( hasFaceVertexUv ) {
 
-							uv = new THREE.Vector2( u, v );
+						for ( i = 0; i < nUvLayers; i ++ ) {
 
-							geometry.faceVertexUvs[ i ][ fi ].push( uv );
+							uvLayer = json.uvs[ i ];
 
-						}
+							geometry.faceVertexUvs[ i ][ fi ] = [];
 
-					}
+							for ( j = 0; j < 3; j ++ ) {
 
-				}
+								uvIndex = faces[ offset ++ ];
 
-				if ( hasFaceNormal ) {
+								u = uvLayer[ uvIndex * 2 ];
+								v = uvLayer[ uvIndex * 2 + 1 ];
 
-					normalIndex = faces[ offset ++ ] * 3;
+								uv = new THREE.Vector2( u, v );
 
-					face.normal.set(
-						normals[ normalIndex ++ ],
-						normals[ normalIndex ++ ],
-						normals[ normalIndex ]
-					);
+								geometry.faceVertexUvs[ i ][ fi ].push( uv );
 
-				}
+							}
 
-				if ( hasFaceVertexNormal ) {
+						}
+
+					}
 
-					for ( i = 0; i < 3; i ++ ) {
+					if ( hasFaceNormal ) {
 
 						normalIndex = faces[ offset ++ ] * 3;
 
-						normal = new THREE.Vector3(
+						face.normal.set(
 							normals[ normalIndex ++ ],
 							normals[ normalIndex ++ ],
 							normals[ normalIndex ]
 						);
 
-						face.vertexNormals.push( normal );
-
 					}
 
-				}
+					if ( hasFaceVertexNormal ) {
 
+						for ( i = 0; i < 3; i ++ ) {
 
-				if ( hasFaceColor ) {
+							normalIndex = faces[ offset ++ ] * 3;
 
-					colorIndex = faces[ offset ++ ];
-					face.color.setHex( colors[ colorIndex ] );
+							normal = new THREE.Vector3(
+								normals[ normalIndex ++ ],
+								normals[ normalIndex ++ ],
+								normals[ normalIndex ]
+							);
 
-				}
+							face.vertexNormals.push( normal );
 
+						}
+
+					}
 
-				if ( hasFaceVertexColor ) {
 
-					for ( i = 0; i < 3; i ++ ) {
+					if ( hasFaceColor ) {
 
 						colorIndex = faces[ offset ++ ];
-						face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
+						face.color.setHex( colors[ colorIndex ] );
 
 					}
 
-				}
 
-				geometry.faces.push( face );
+					if ( hasFaceVertexColor ) {
+
+						for ( i = 0; i < 3; i ++ ) {
+
+							colorIndex = faces[ offset ++ ];
+							face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
+
+						}
+
+					}
+
+					geometry.faces.push( face );
+
+				}
 
 			}
 
-		}
+		};
 
-	}
+		function parseSkin() {
+			var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
 
-	function parseSkin() {
-		var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
+			if ( json.skinWeights ) {
 
-		if ( json.skinWeights ) {
+				for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
 
-			for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
+					var x =                               json.skinWeights[ i     ];
+					var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
+					var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
+					var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
 
-				var x =                               json.skinWeights[ i     ];
-				var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
-				var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
-				var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
+					geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
 
-				geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
+				}
 
 			}
 
-		}
+			if ( json.skinIndices ) {
 
-		if ( json.skinIndices ) {
+				for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
 
-			for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
+					var a =                               json.skinIndices[ i     ];
+					var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
+					var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
+					var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
 
-				var a =                               json.skinIndices[ i     ];
-				var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
-				var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
-				var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
+					geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
 
-				geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
+				}
 
 			}
 
-		}
+			geometry.bones = json.bones;
 
-		geometry.bones = json.bones;
+			if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
 
-		if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
+					console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
+						geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
 
-			console.warn( 'THREE.JSONLoader: When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
-					geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
+			}
 
-		}
 
+			// could change this to json.animations[0] or remove completely
 
-		// could change this to json.animations[0] or remove completely
+			geometry.animation = json.animation;
+			geometry.animations = json.animations;
 
-		geometry.animation = json.animation;
-		geometry.animations = json.animations;
+		};
 
-	}
+		function parseMorphing( scale ) {
 
-	function parseMorphing( scale ) {
+			if ( json.morphTargets !== undefined ) {
 
-		if ( json.morphTargets !== undefined ) {
+				var i, l, v, vl, dstVertices, srcVertices;
 
-			var i, l, v, vl, dstVertices, srcVertices;
+				for ( i = 0, l = json.morphTargets.length; i < l; i ++ ) {
 
-			for ( i = 0, l = json.morphTargets.length; i < l; i ++ ) {
+					geometry.morphTargets[ i ] = {};
+					geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
+					geometry.morphTargets[ i ].vertices = [];
 
-				geometry.morphTargets[ i ] = {};
-				geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
-				geometry.morphTargets[ i ].vertices = [];
+					dstVertices = geometry.morphTargets[ i ].vertices;
+					srcVertices = json.morphTargets [ i ].vertices;
 
-				dstVertices = geometry.morphTargets[ i ].vertices;
-				srcVertices = json.morphTargets [ i ].vertices;
+					for ( v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
 
-				for ( v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
+						var vertex = new THREE.Vector3();
+						vertex.x = srcVertices[ v ] * scale;
+						vertex.y = srcVertices[ v + 1 ] * scale;
+						vertex.z = srcVertices[ v + 2 ] * scale;
 
-					var vertex = new THREE.Vector3();
-					vertex.x = srcVertices[ v ] * scale;
-					vertex.y = srcVertices[ v + 1 ] * scale;
-					vertex.z = srcVertices[ v + 2 ] * scale;
+						dstVertices.push( vertex );
 
-					dstVertices.push( vertex );
+					}
 
 				}
 
 			}
 
-		}
+			if ( json.morphColors !== undefined ) {
 
-		if ( json.morphColors !== undefined ) {
+				var i, l, c, cl, dstColors, srcColors, color;
 
-			var i, l, c, cl, dstColors, srcColors, color;
+				for ( i = 0, l = json.morphColors.length; i < l; i ++ ) {
 
-			for ( i = 0, l = json.morphColors.length; i < l; i ++ ) {
+					geometry.morphColors[ i ] = {};
+					geometry.morphColors[ i ].name = json.morphColors[ i ].name;
+					geometry.morphColors[ i ].colors = [];
 
-				geometry.morphColors[ i ] = {};
-				geometry.morphColors[ i ].name = json.morphColors[ i ].name;
-				geometry.morphColors[ i ].colors = [];
+					dstColors = geometry.morphColors[ i ].colors;
+					srcColors = json.morphColors [ i ].colors;
 
-				dstColors = geometry.morphColors[ i ].colors;
-				srcColors = json.morphColors [ i ].colors;
+					for ( c = 0, cl = srcColors.length; c < cl; c += 3 ) {
 
-				for ( c = 0, cl = srcColors.length; c < cl; c += 3 ) {
+						color = new THREE.Color( 0xffaa00 );
+						color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] );
+						dstColors.push( color );
 
-					color = new THREE.Color( 0xffaa00 );
-					color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] );
-					dstColors.push( color );
+					}
 
 				}
 
 			}
 
-		}
+		};
 
-	}
+		if ( json.materials === undefined || json.materials.length === 0 ) {
 
-	if ( json.materials === undefined || json.materials.length === 0 ) {
+			return { geometry: geometry };
 
-		return { geometry: geometry };
+		} else {
 
-	} else {
+			var materials = THREE.Loader.prototype.initMaterials( json.materials, texturePath, this.crossOrigin );
 
-		var materials = this.initMaterials( json.materials, texturePath );
+			if ( THREE.Loader.prototype.needsTangents( materials ) ) {
 
-		if ( this.needsTangents( materials ) ) {
+				geometry.computeTangents();
 
-			geometry.computeTangents();
+			}
 
-		}
+			return { geometry: geometry, materials: materials };
 
-		return { geometry: geometry, materials: materials };
+		}
 
 	}
 

+ 166 - 158
src/loaders/Loader.js

@@ -7,8 +7,6 @@ THREE.Loader = function ( showStatus ) {
 	this.showStatus = showStatus;
 	this.statusDomElement = showStatus ? THREE.Loader.prototype.addStatusElement() : null;
 
-	this.imageLoader = new THREE.ImageLoader();
-
 	this.onLoadStart = function () {};
 	this.onLoadProgress = function () {};
 	this.onLoadComplete = function () {};
@@ -73,13 +71,13 @@ THREE.Loader.prototype = {
 
 	},
 
-	initMaterials: function ( materials, texturePath ) {
+	initMaterials: function ( materials, texturePath, crossOrigin ) {
 
 		var array = [];
 
 		for ( var i = 0; i < materials.length; ++ i ) {
 
-			array[ i ] = this.createMaterial( materials[ i ], texturePath );
+			array[ i ] = this.createMaterial( materials[ i ], texturePath, crossOrigin );
 
 		}
 
@@ -101,303 +99,313 @@ THREE.Loader.prototype = {
 
 	},
 
-	createMaterial: function ( m, texturePath ) {
+	createMaterial: ( function () {
 
-		var scope = this;
+		var imageLoader;
 
-		function nearest_pow2( n ) {
+		return function ( m, texturePath, crossOrigin ) {
 
-			var l = Math.log( n ) / Math.LN2;
-			return Math.pow( 2, Math.round(  l ) );
+			var scope = this;
 
-		}
+			if ( crossOrigin === undefined && scope.crossOrigin !== undefined ) crossOrigin = scope.crossOrigin;
+
+			if ( imageLoader === undefined ) imageLoader = new THREE.ImageLoader();
 
-		function create_texture( where, name, sourceFile, repeat, offset, wrap, anisotropy ) {
+			function nearest_pow2( n ) {
 
-			var fullPath = texturePath + sourceFile;
+				var l = Math.log( n ) / Math.LN2;
+				return Math.pow( 2, Math.round(  l ) );
+
+			}
 
-			var texture;
+			function create_texture( where, name, sourceFile, repeat, offset, wrap, anisotropy ) {
 
-			var loader = THREE.Loader.Handlers.get( fullPath );
+				var fullPath = texturePath + sourceFile;
 
-			if ( loader !== null ) {
+				var texture;
 
-				texture = loader.load( fullPath );
+				var loader = THREE.Loader.Handlers.get( fullPath );
 
-			} else {
+				if ( loader !== null ) {
 
-				texture = new THREE.Texture();
+					texture = loader.load( fullPath );
 
-				loader = scope.imageLoader;
-				loader.crossOrigin = scope.crossOrigin;
-				loader.load( fullPath, function ( image ) {
+				} else {
+
+					texture = new THREE.Texture();
+
+					loader = imageLoader;
+					loader.setCrossOrigin( crossOrigin );
+					loader.load( fullPath, function ( image ) {
 
 					if ( THREE.Math.isPowerOfTwo( image.width ) === false ||
 						 THREE.Math.isPowerOfTwo( image.height ) === false ) {
 
-						var width = nearest_pow2( image.width );
-						var height = nearest_pow2( image.height );
+							var width = nearest_pow2( image.width );
+							var height = nearest_pow2( image.height );
 
-						var canvas = document.createElement( 'canvas' );
-						canvas.width = width;
-						canvas.height = height;
+							var canvas = document.createElement( 'canvas' );
+							canvas.width = width;
+							canvas.height = height;
 
-						var context = canvas.getContext( '2d' );
-						context.drawImage( image, 0, 0, width, height );
+							var context = canvas.getContext( '2d' );
+							context.drawImage( image, 0, 0, width, height );
 
-						texture.image = canvas;
+							texture.image = canvas;
 
-					} else {
+						} else {
 
-						texture.image = image;
+							texture.image = image;
 
-					}
+						}
 
-					texture.needsUpdate = true;
+						texture.needsUpdate = true;
 
-				} );
+					} );
 
-			}
+				}
 
-			texture.sourceFile = sourceFile;
+				texture.sourceFile = sourceFile;
 
-			if ( repeat ) {
+				if ( repeat ) {
 
-				texture.repeat.set( repeat[ 0 ], repeat[ 1 ] );
+					texture.repeat.set( repeat[ 0 ], repeat[ 1 ] );
 
-				if ( repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
-				if ( repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
+					if ( repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
+					if ( repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
 
-			}
+				}
 
-			if ( offset ) {
+				if ( offset ) {
 
-				texture.offset.set( offset[ 0 ], offset[ 1 ] );
+					texture.offset.set( offset[ 0 ], offset[ 1 ] );
 
-			}
+				}
 
-			if ( wrap ) {
+				if ( wrap ) {
 
-				var wrapMap = {
-					'repeat': THREE.RepeatWrapping,
-					'mirror': THREE.MirroredRepeatWrapping
-				};
+					var wrapMap = {
+						'repeat': THREE.RepeatWrapping,
+						'mirror': THREE.MirroredRepeatWrapping
+					};
 
-				if ( wrapMap[ wrap[ 0 ] ] !== undefined ) texture.wrapS = wrapMap[ wrap[ 0 ] ];
-				if ( wrapMap[ wrap[ 1 ] ] !== undefined ) texture.wrapT = wrapMap[ wrap[ 1 ] ];
+					if ( wrapMap[ wrap[ 0 ] ] !== undefined ) texture.wrapS = wrapMap[ wrap[ 0 ] ];
+					if ( wrapMap[ wrap[ 1 ] ] !== undefined ) texture.wrapT = wrapMap[ wrap[ 1 ] ];
 
-			}
+				}
 
-			if ( anisotropy ) {
+				if ( anisotropy ) {
 
-				texture.anisotropy = anisotropy;
+					texture.anisotropy = anisotropy;
 
-			}
+				}
 
-			where[ name ] = texture;
+				where[ name ] = texture;
 
-		}
+			}
 
-		function rgb2hex( rgb ) {
+			function rgb2hex( rgb ) {
 
-			return ( rgb[ 0 ] * 255 << 16 ) + ( rgb[ 1 ] * 255 << 8 ) + rgb[ 2 ] * 255;
+				return ( rgb[ 0 ] * 255 << 16 ) + ( rgb[ 1 ] * 255 << 8 ) + rgb[ 2 ] * 255;
 
-		}
+			}
 
-		// defaults
+			// defaults
 
-		var mtype = 'MeshLambertMaterial';
-		var mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, normalMap: null, bumpMap: null, wireframe: false };
+			var mtype = 'MeshLambertMaterial';
+			var mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, normalMap: null, bumpMap: null, wireframe: false };
 
-		// parameters from model file
+			// parameters from model file
 
-		if ( m.shading ) {
+			if ( m.shading ) {
 
-			var shading = m.shading.toLowerCase();
+				var shading = m.shading.toLowerCase();
 
-			if ( shading === 'phong' ) mtype = 'MeshPhongMaterial';
-			else if ( shading === 'basic' ) mtype = 'MeshBasicMaterial';
+				if ( shading === 'phong' ) mtype = 'MeshPhongMaterial';
+				else if ( shading === 'basic' ) mtype = 'MeshBasicMaterial';
 
-		}
+			}
 
-		if ( m.blending !== undefined && THREE[ m.blending ] !== undefined ) {
+			if ( m.blending !== undefined && THREE[ m.blending ] !== undefined ) {
 
-			mpars.blending = THREE[ m.blending ];
+				mpars.blending = THREE[ m.blending ];
 
-		}
+			}
 
-		if ( m.transparent !== undefined ) {
+			if ( m.transparent !== undefined ) {
 
-			mpars.transparent = m.transparent;
+				mpars.transparent = m.transparent;
 
-		}
+			}
 
-		if ( m.opacity !== undefined && m.opacity < 1.0 ) {
+			if ( m.opacity !== undefined && m.opacity < 1.0 ) {
 
-			mpars.transparent = true;
+				mpars.transparent = true;
 
-		}
+			}
 
-		if ( m.depthTest !== undefined ) {
+			if ( m.depthTest !== undefined ) {
 
-			mpars.depthTest = m.depthTest;
+				mpars.depthTest = m.depthTest;
 
-		}
+			}
 
-		if ( m.depthWrite !== undefined ) {
+			if ( m.depthWrite !== undefined ) {
 
-			mpars.depthWrite = m.depthWrite;
+				mpars.depthWrite = m.depthWrite;
 
-		}
+			}
 
-		if ( m.visible !== undefined ) {
+			if ( m.visible !== undefined ) {
 
-			mpars.visible = m.visible;
+				mpars.visible = m.visible;
 
-		}
+			}
 
-		if ( m.flipSided !== undefined ) {
+			if ( m.flipSided !== undefined ) {
 
-			mpars.side = THREE.BackSide;
+				mpars.side = THREE.BackSide;
 
-		}
+			}
 
-		if ( m.doubleSided !== undefined ) {
+			if ( m.doubleSided !== undefined ) {
 
-			mpars.side = THREE.DoubleSide;
+				mpars.side = THREE.DoubleSide;
 
-		}
+			}
 
-		if ( m.wireframe !== undefined ) {
+			if ( m.wireframe !== undefined ) {
 
-			mpars.wireframe = m.wireframe;
+				mpars.wireframe = m.wireframe;
 
-		}
+			}
+
+			if ( m.vertexColors !== undefined ) {
 
-		if ( m.vertexColors !== undefined ) {
+				if ( m.vertexColors === 'face' ) {
 
-			if ( m.vertexColors === 'face' ) {
+					mpars.vertexColors = THREE.FaceColors;
 
-				mpars.vertexColors = THREE.FaceColors;
+				} else if ( m.vertexColors ) {
 
-			} else if ( m.vertexColors ) {
+					mpars.vertexColors = THREE.VertexColors;
 
-				mpars.vertexColors = THREE.VertexColors;
+				}
 
 			}
 
-		}
+			// colors
 
-		// colors
+			if ( m.colorDiffuse ) {
 
-		if ( m.colorDiffuse ) {
+				mpars.color = rgb2hex( m.colorDiffuse );
 
-			mpars.color = rgb2hex( m.colorDiffuse );
+			} else if ( m.DbgColor ) {
 
-		} else if ( m.DbgColor ) {
+				mpars.color = m.DbgColor;
 
-			mpars.color = m.DbgColor;
+			}
 
-		}
+			if ( m.colorSpecular ) {
 
-		if ( m.colorSpecular ) {
+				mpars.specular = rgb2hex( m.colorSpecular );
 
-			mpars.specular = rgb2hex( m.colorSpecular );
+			}
 
-		}
+			if ( m.colorEmissive ) {
 
-		if ( m.colorEmissive ) {
+				mpars.emissive = rgb2hex( m.colorEmissive );
 
-			mpars.emissive = rgb2hex( m.colorEmissive );
+			}
 
-		}
+			// modifiers
 
-		// modifiers
+			if ( m.transparency !== undefined ) {
 
-		if ( m.transparency !== undefined ) {
+				console.warn( 'THREE.Loader: transparency has been renamed to opacity' );
+				m.opacity = m.transparency;
 
-			console.warn( 'THREE.Loader: transparency has been renamed to opacity' );
-			m.opacity = m.transparency;
+			}
 
-		}
+			if ( m.opacity !== undefined ) {
 
-		if ( m.opacity !== undefined ) {
+				mpars.opacity = m.opacity;
 
-			mpars.opacity = m.opacity;
+			}
 
-		}
+			if ( m.specularCoef ) {
 
-		if ( m.specularCoef ) {
+				mpars.shininess = m.specularCoef;
 
-			mpars.shininess = m.specularCoef;
+			}
 
-		}
+			// textures
 
-		// textures
+			if ( m.mapDiffuse && texturePath ) {
 
-		if ( m.mapDiffuse && texturePath ) {
+				create_texture( mpars, 'map', m.mapDiffuse, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
 
-			create_texture( mpars, 'map', m.mapDiffuse, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
+			}
 
-		}
+			if ( m.mapLight && texturePath ) {
 
-		if ( m.mapLight && texturePath ) {
+				create_texture( mpars, 'lightMap', m.mapLight, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
 
-			create_texture( mpars, 'lightMap', m.mapLight, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
+			}
 
-		}
+			if ( m.mapAO && texturePath ) {
 
-		if ( m.mapAO && texturePath ) {
+				create_texture( mpars, 'aoMap', m.mapAO, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
 
-			create_texture( mpars, 'aoMap', m.mapAO, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy );
+			}
 
-		}
+			if ( m.mapBump && texturePath ) {
 
-		if ( m.mapBump && texturePath ) {
+				create_texture( mpars, 'bumpMap', m.mapBump, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
 
-			create_texture( mpars, 'bumpMap', m.mapBump, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
+			}
 
-		}
+			if ( m.mapNormal && texturePath ) {
 
-		if ( m.mapNormal && texturePath ) {
+				create_texture( mpars, 'normalMap', m.mapNormal, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
 
-			create_texture( mpars, 'normalMap', m.mapNormal, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
+			}
 
-		}
+			if ( m.mapSpecular && texturePath ) {
 
-		if ( m.mapSpecular && texturePath ) {
+				create_texture( mpars, 'specularMap', m.mapSpecular, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
 
-			create_texture( mpars, 'specularMap', m.mapSpecular, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
+			}
 
-		}
+			if ( m.mapAlpha && texturePath ) {
 
-		if ( m.mapAlpha && texturePath ) {
+				create_texture( mpars, 'alphaMap', m.mapAlpha, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
 
-			create_texture( mpars, 'alphaMap', m.mapAlpha, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy );
+			}
 
-		}
+			//
 
-		//
+			if ( m.mapBumpScale ) {
 
-		if ( m.mapBumpScale ) {
+				mpars.bumpScale = m.mapBumpScale;
 
-			mpars.bumpScale = m.mapBumpScale;
+			}
 
-		}
+			if ( m.mapNormalFactor ) {
 
-		if ( m.mapNormalFactor ) {
+				mpars.normalScale = new THREE.Vector2( m.mapNormalFactor, m.mapNormalFactor );
 
-			mpars.normalScale = new THREE.Vector2( m.mapNormalFactor, m.mapNormalFactor );
+			}
 
-		}
+			var material = new THREE[ mtype ]( mpars );
 
-		var material = new THREE[ mtype ]( mpars );
+			if ( m.DbgName !== undefined ) material.name = m.DbgName;
 
-		if ( m.DbgName !== undefined ) material.name = m.DbgName;
+			return material;
 
-		return material;
+		};
 
-	}
+	} )()
 
 };
 

+ 24 - 6
src/loaders/LoadingManager.js

@@ -6,7 +6,7 @@ THREE.LoadingManager = function ( onLoad, onProgress, onError ) {
 
 	var scope = this;
 
-	var loaded = 0, total = 0;
+	var isLoading = false, itemsLoaded = 0, itemsTotal = 0;
 
 	this.onLoad = onLoad;
 	this.onProgress = onProgress;
@@ -14,23 +14,41 @@ THREE.LoadingManager = function ( onLoad, onProgress, onError ) {
 
 	this.itemStart = function ( url ) {
 
-		total ++;
+		itemsTotal ++;
+
+		if ( isLoading === false ) {
+
+			if ( scope.onStart !== undefined ) {
+
+				scope.onStart( url, itemsLoaded, itemsTotal );
+
+			}
+
+		}
+
+		isLoading = true;
 
 	};
 
 	this.itemEnd = function ( url ) {
 
-		loaded ++;
+		itemsLoaded ++;
 
 		if ( scope.onProgress !== undefined ) {
 
-			scope.onProgress( url, loaded, total );
+			scope.onProgress( url, itemsLoaded, itemsTotal );
 
 		}
 
-		if ( loaded === total && scope.onLoad !== undefined ) {
+		if ( itemsLoaded === itemsTotal ) {
+
+			isLoading = false;
+
+			if ( scope.onLoad !== undefined ) {
+
+				scope.onLoad();
 
-			scope.onLoad();
+			}
 
 		}
 

+ 7 - 0
src/loaders/XHRLoader.js

@@ -69,6 +69,7 @@ THREE.XHRLoader.prototype = {
 
 		if ( this.crossOrigin !== undefined ) request.crossOrigin = this.crossOrigin;
 		if ( this.responseType !== undefined ) request.responseType = this.responseType;
+		if ( this.withCredentials !== undefined ) request.withCredentials = this.withCredentials;
 
 		request.send( null );
 
@@ -88,6 +89,12 @@ THREE.XHRLoader.prototype = {
 
 		this.crossOrigin = value;
 
+	},
+
+	setWithCredentials: function ( value ) {
+
+		this.withCredentials = value;
+
 	}
 
 };

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