Ver código fonte

SkinnedMesh.bind() change reflected in docs and loaders

Greg Tatum 10 anos atrás
pai
commit
2f1f87ff4b

+ 0 - 3
docs/api/objects/SkinnedMesh.html

@@ -43,9 +43,6 @@
 		// Bind the skeleton to the mesh
 		mesh.bind( armSkeleton );
 		
-		// Update the inverse matrices in the skeleton to reflect the newly bound skeleton
-		armSkeleton.calculateInverses();
-		
 		// Move the bones and manipulate the model
 		armSkeleton.bones[ 0 ].rotation.x = -0.1;
 		armSkeleton.bones[ 1 ].rotation.x = 0.2;

+ 0 - 1
docs/scenes/bones-browser.html

@@ -159,7 +159,6 @@
 				mesh.add( bones[ 0 ] );
 	
 				mesh.bind( skeleton );
-				skeleton.calculateInverses();
 
 				skeletonHelper = new THREE.SkeletonHelper( mesh );
 				skeletonHelper.material.linewidth = 2;

+ 1438 - 1074
examples/js/loaders/gltf/glTFLoader.js

@@ -4,6 +4,7 @@
 
 
 THREE.glTFLoader = function () {
+
 	this.meshesRequested = 0;
 	this.meshesLoaded = 0;
 	this.pendingMeshes = [];
@@ -14,6 +15,7 @@ THREE.glTFLoader = function () {
 	this.shadersLoaded = 0;
 	this.shaders = {};
 	THREE.Loader.call( this );
+
 };
 
 THREE.glTFLoader.prototype = Object.create( THREE.Loader.prototype );
@@ -24,39 +26,45 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
 	var theLoader = this;
 	// Utilities
 
-	function RgbArraytoHex(colorArray) {
-		if (!colorArray) return 0xFFFFFFFF;
-		var r = Math.floor(colorArray[0] * 255),
-            g = Math.floor(colorArray[1] * 255),
-            b = Math.floor(colorArray[2] * 255),
+	function RgbArraytoHex( colorArray ) {
+
+		if ( ! colorArray ) return 0xFFFFFFFF;
+		var r = Math.floor( colorArray[ 0 ] * 255 ),
+            g = Math.floor( colorArray[ 1 ] * 255 ),
+            b = Math.floor( colorArray[ 2 ] * 255 ),
             a = 255;
 
-		var color = (a << 24) + (r << 16) + (g << 8) + b;
+		var color = ( a << 24 ) + ( r << 16 ) + ( g << 8 ) + b;
 
 		return color;
+
 	}
 
-	function convertAxisAngleToQuaternion(rotations, count)
-    {
+	function convertAxisAngleToQuaternion( rotations, count ) {
+
 		var q = new THREE.Quaternion;
 		var axis = new THREE.Vector3;
 		var euler = new THREE.Vector3;
 
 		var i;
-		for (i = 0; i < count; i ++) {
-			axis.set(rotations[i * 4], rotations[i * 4 + 1],
-    				rotations[i * 4 + 2]).normalize();
-			var angle = rotations[i * 4 + 3];
-			q.setFromAxisAngle(axis, angle);
-			rotations[i * 4] = q.x;
-			rotations[i * 4 + 1] = q.y;
-			rotations[i * 4 + 2] = q.z;
-			rotations[i * 4 + 3] = q.w;
+		for ( i = 0; i < count; i ++ ) {
+
+			axis.set( rotations[ i * 4 ], rotations[ i * 4 + 1 ],
+    				rotations[ i * 4 + 2 ] ).normalize();
+			var angle = rotations[ i * 4 + 3 ];
+			q.setFromAxisAngle( axis, angle );
+			rotations[ i * 4 ] = q.x;
+			rotations[ i * 4 + 1 ] = q.y;
+			rotations[ i * 4 + 2 ] = q.z;
+			rotations[ i * 4 + 3 ] = q.w;
+
 		}
+
 	}
 
-	function componentsPerElementForGLType(glType) {
-		switch (glType) {
+	function componentsPerElementForGLType( glType ) {
+
+		switch ( glType ) {
 			case WebGLRenderingContext.FLOAT :
 			case WebGLRenderingContext.UNSIGNED_BYTE :
 			case WebGLRenderingContext.UNSIGNED_SHORT :
@@ -72,15 +80,21 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
 			default:
 				return null;
 		}
+
 	}
 
+	function LoadTexture( src ) {
+
+		if ( ! src ) {
+
+			return null;
+
+		}
+		return THREE.ImageUtils.loadTexture( src );
 
-	function LoadTexture(src) {
-		if (!src) { return null; }
-		return THREE.ImageUtils.loadTexture(src);
 	}
 
-    // Geometry processing
+	// Geometry processing
 
 	var ClassicGeometry = function() {
 
@@ -95,276 +109,361 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
 
 		this.uvs = null;
 		this.indexArray = null;
+
 	};
 
 	ClassicGeometry.prototype.constructor = ClassicGeometry;
 
 	ClassicGeometry.prototype.buildBufferGeometry = function() {
-        // Build indexed mesh
+
+		// Build indexed mesh
 		var geometry = this.geometry;
 
 		geometry.addAttribute( 'index', new THREE.BufferAttribute( this.indexArray, 1 ) );
 		geometry.addDrawCall( 0, this.indexArray.length );
 
 		geometry.computeBoundingSphere();
+
 	};
 
 	ClassicGeometry.prototype.checkFinished = function() {
-		if (this.indexArray && this.loadedAttributes === this.totalAttributes) {
+
+		if ( this.indexArray && this.loadedAttributes === this.totalAttributes ) {
 
 			this.buildBufferGeometry();
 
 			this.finished = true;
 
-			if (this.onload) {
+			if ( this.onload ) {
+
 				this.onload();
+
 			}
+
 		}
+
 	};
 
-    // Delegate for processing index buffers
+	// Delegate for processing index buffers
 	var IndicesDelegate = function() {};
 
-	IndicesDelegate.prototype.handleError = function(errorCode, info) {
-        // FIXME: report error
-		console.log("ERROR(IndicesDelegate):" + errorCode + ":" + info);
+	IndicesDelegate.prototype.handleError = function( errorCode, info ) {
+
+		// FIXME: report error
+		console.log( "ERROR(IndicesDelegate):" + errorCode + ":" + info );
+
 	};
 
-	IndicesDelegate.prototype.convert = function(resource, ctx) {
-		return new Uint16Array(resource, 0, ctx.indices.count);
+	IndicesDelegate.prototype.convert = function( resource, ctx ) {
+
+		return new Uint16Array( resource, 0, ctx.indices.count );
+
 	};
 
-	IndicesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
+	IndicesDelegate.prototype.resourceAvailable = function( glResource, ctx ) {
+
 		var geometry = ctx.geometry;
 		geometry.indexArray = glResource;
 		geometry.checkFinished();
 		return true;
+
 	};
 
 	var indicesDelegate = new IndicesDelegate();
 
-	var IndicesContext = function(indices, geometry) {
+	var IndicesContext = function( indices, geometry ) {
+
 		this.indices = indices;
 		this.geometry = geometry;
+
 	};
 
-    // Delegate for processing vertex attribute buffers
+	// Delegate for processing vertex attribute buffers
 	var VertexAttributeDelegate = function() {};
 
-	VertexAttributeDelegate.prototype.handleError = function(errorCode, info) {
-        // FIXME: report error
-		console.log("ERROR(VertexAttributeDelegate):" + errorCode + ":" + info);
+	VertexAttributeDelegate.prototype.handleError = function( errorCode, info ) {
+
+		// FIXME: report error
+		console.log( "ERROR(VertexAttributeDelegate):" + errorCode + ":" + info );
+
 	};
 
-	VertexAttributeDelegate.prototype.convert = function(resource, ctx) {
+	VertexAttributeDelegate.prototype.convert = function( resource, ctx ) {
+
 		return resource;
-	};
 
+	};
 
+	VertexAttributeDelegate.prototype.arrayResourceAvailable = function( glResource, ctx ) {
 
-	VertexAttributeDelegate.prototype.arrayResourceAvailable = function(glResource, ctx) {
 		var geom = ctx.geometry;
 		var attribute = ctx.attribute;
 		var semantic = ctx.semantic;
 		var floatArray;
 		var i, l;
-        //FIXME: Float32 is assumed here, but should be checked.
+		//FIXME: Float32 is assumed here, but should be checked.
+
+		if ( semantic == "POSITION" ) {
+
+			// TODO: Should be easy to take strides into account here
+			floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
+			for ( i = 0, l = floatArray.length; i < l; i += 3 ) {
+
+				geom.geometry.vertices.push( new THREE.Vector3( floatArray[ i ], floatArray[ i + 1 ], floatArray[ i + 2 ] ) );
 
-		if (semantic == "POSITION") {
-            // TODO: Should be easy to take strides into account here
-			floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
-			for (i = 0, l = floatArray.length; i < l; i += 3) {
-				geom.geometry.vertices.push( new THREE.Vector3( floatArray[i], floatArray[i + 1], floatArray[i + 2] ) );
 			}
-		} else if (semantic == "NORMAL") {
+
+		} else if ( semantic == "NORMAL" ) {
+
 			geom.geometry.normals = [];
-			floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
-			for (i = 0, l = floatArray.length; i < l; i += 3) {
-				geom.geometry.normals.push( new THREE.Vector3( floatArray[i], floatArray[i + 1], floatArray[i + 2] ) );
+			floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
+			for ( i = 0, l = floatArray.length; i < l; i += 3 ) {
+
+				geom.geometry.normals.push( new THREE.Vector3( floatArray[ i ], floatArray[ i + 1 ], floatArray[ i + 2 ] ) );
+
 			}
-		} else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
+
+		} else if ( ( semantic == "TEXCOORD_0" ) || ( semantic == "TEXCOORD" ) ) {
+
 			geom.uvs = [];
-			floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
-			for (i = 0, l = floatArray.length; i < l; i += 2) {
-				geom.uvs.push( new THREE.Vector2( floatArray[i], 1.0 - floatArray[i + 1] ) );
+			floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
+			for ( i = 0, l = floatArray.length; i < l; i += 2 ) {
+
+				geom.uvs.push( new THREE.Vector2( floatArray[ i ], 1.0 - floatArray[ i + 1 ] ) );
+
 			}
+
 		}
-        else if (semantic == "WEIGHT") {
-	nComponents = componentsPerElementForGLType(attribute.type);
-	floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
-	for (i = 0, l = floatArray.length; i < l; i += 4) {
-		geom.geometry.skinWeights.push( new THREE.Vector4( floatArray[i], floatArray[i + 1], floatArray[i + 2], floatArray[i + 3] ) );
-	}
-        }
-        else if (semantic == "JOINT") {
-	nComponents = componentsPerElementForGLType(attribute.type);
-	floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
-	for (i = 0, l = floatArray.length; i < l; i += 4) {
-		geom.geometry.skinIndices.push( new THREE.Vector4( floatArray[i], floatArray[i + 1], floatArray[i + 2], floatArray[i + 3] ) );
-	}
-        }
+		else if ( semantic == "WEIGHT" ) {
+
+			nComponents = componentsPerElementForGLType( attribute.type );
+			floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
+			for ( i = 0, l = floatArray.length; i < l; i += 4 ) {
+
+				geom.geometry.skinWeights.push( new THREE.Vector4( floatArray[ i ], floatArray[ i + 1 ], floatArray[ i + 2 ], floatArray[ i + 3 ] ) );
+
+			}
+
+		}
+		else if ( semantic == "JOINT" ) {
+
+			nComponents = componentsPerElementForGLType( attribute.type );
+			floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
+			for ( i = 0, l = floatArray.length; i < l; i += 4 ) {
+
+				geom.geometry.skinIndices.push( new THREE.Vector4( floatArray[ i ], floatArray[ i + 1 ], floatArray[ i + 2 ], floatArray[ i + 3 ] ) );
+
+			}
+
+		}
+
 	};
 
-	VertexAttributeDelegate.prototype.bufferResourceAvailable = function(glResource, ctx) {
+	VertexAttributeDelegate.prototype.bufferResourceAvailable = function( glResource, ctx ) {
+
 		var geom = ctx.geometry;
 		var attribute = ctx.attribute;
 		var semantic = ctx.semantic;
 		var floatArray;
 		var i, l;
 		var nComponents;
-        //FIXME: Float32 is assumed here, but should be checked.
+		//FIXME: Float32 is assumed here, but should be checked.
+
+		if ( semantic == "POSITION" ) {
 
-		if (semantic == "POSITION") {
-            // TODO: Should be easy to take strides into account here
-			floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
+			// TODO: Should be easy to take strides into account here
+			floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
 			geom.geometry.addAttribute( 'position', new THREE.BufferAttribute( floatArray, 3 ) );
-		} else if (semantic == "NORMAL") {
-			floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
+
+		} else if ( semantic == "NORMAL" ) {
+
+			floatArray = new Float32Array( glResource, 0, attribute.count * componentsPerElementForGLType( attribute.type ) );
 			geom.geometry.addAttribute( 'normal', new THREE.BufferAttribute( floatArray, 3 ) );
-		} else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
 
-			nComponents = componentsPerElementForGLType(attribute.type);
-			floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
-            // N.B.: flip Y value... should we just set texture.flipY everywhere?
-			for (i = 0; i < floatArray.length / 2; i ++) {
-				floatArray[i * 2 + 1] = 1.0 - floatArray[i * 2 + 1];
+		} else if ( ( semantic == "TEXCOORD_0" ) || ( semantic == "TEXCOORD" ) ) {
+
+			nComponents = componentsPerElementForGLType( attribute.type );
+			floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
+			// N.B.: flip Y value... should we just set texture.flipY everywhere?
+			for ( i = 0; i < floatArray.length / 2; i ++ ) {
+
+				floatArray[ i * 2 + 1 ] = 1.0 - floatArray[ i * 2 + 1 ];
+
 			}
 			geom.geometry.addAttribute( 'uv', new THREE.BufferAttribute( floatArray, nComponents ) );
+
+		}
+		else if ( semantic == "WEIGHT" ) {
+
+			nComponents = componentsPerElementForGLType( attribute.type );
+			floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
+			geom.geometry.addAttribute( 'skinWeight', new THREE.BufferAttribute( floatArray, nComponents ) );
+
+		}
+		else if ( semantic == "JOINT" ) {
+
+			nComponents = componentsPerElementForGLType( attribute.type );
+			floatArray = new Float32Array( glResource, 0, attribute.count * nComponents );
+			geom.geometry.addAttribute( 'skinIndex', new THREE.BufferAttribute( floatArray, nComponents ) );
+
 		}
-        else if (semantic == "WEIGHT") {
-	nComponents = componentsPerElementForGLType(attribute.type);
-	floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
-	geom.geometry.addAttribute( 'skinWeight', new THREE.BufferAttribute( floatArray, nComponents ) );
-        }
-        else if (semantic == "JOINT") {
-	nComponents = componentsPerElementForGLType(attribute.type);
-	floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
-	geom.geometry.addAttribute( 'skinIndex', new THREE.BufferAttribute( floatArray, nComponents ) );
-        }
+
 	};
 
-	VertexAttributeDelegate.prototype.resourceAvailable = function(glResource, ctx) {
+	VertexAttributeDelegate.prototype.resourceAvailable = function( glResource, ctx ) {
 
-		this.bufferResourceAvailable(glResource, ctx);
+		this.bufferResourceAvailable( glResource, ctx );
 
 		var geom = ctx.geometry;
 		geom.loadedAttributes ++;
 		geom.checkFinished();
 		return true;
+
 	};
 
 	var vertexAttributeDelegate = new VertexAttributeDelegate();
 
-	var VertexAttributeContext = function(attribute, semantic, geometry) {
+	var VertexAttributeContext = function( attribute, semantic, geometry ) {
+
 		this.attribute = attribute;
 		this.semantic = semantic;
 		this.geometry = geometry;
+
 	};
 
 	var Mesh = function() {
+
 		this.primitives = [];
 		this.materialsPending = [];
 		this.loadedGeometry = 0;
 		this.onCompleteCallbacks = [];
+
 	};
 
-	Mesh.prototype.addPrimitive = function(geometry, material) {
+	Mesh.prototype.addPrimitive = function( geometry, material ) {
 
 		var self = this;
 		geometry.onload = function() {
+
 			self.loadedGeometry ++;
 			self.checkComplete();
+
 		};
 
-		this.primitives.push({
-            geometry: geometry,
-            material: material,
-            mesh: null
-        });
+		this.primitives.push( {
+			geometry: geometry,
+			material: material,
+			mesh: null
+		} );
+
 	};
 
-	Mesh.prototype.onComplete = function(callback) {
-		this.onCompleteCallbacks.push(callback);
+	Mesh.prototype.onComplete = function( callback ) {
+
+		this.onCompleteCallbacks.push( callback );
 		this.checkComplete();
+
 	};
 
 	Mesh.prototype.checkComplete = function() {
+
 		var self = this;
-		if (this.onCompleteCallbacks.length && this.primitives.length == this.loadedGeometry) {
-			this.onCompleteCallbacks.forEach(function(callback) {
-				callback(self);
-			});
+		if ( this.onCompleteCallbacks.length && this.primitives.length == this.loadedGeometry ) {
+
+			this.onCompleteCallbacks.forEach( function( callback ) {
+
+				callback( self );
+
+			} );
 			this.onCompleteCallbacks = [];
+
 		}
+
 	};
 
-	Mesh.prototype.attachToNode = function(threeNode) {
-        // Assumes that the geometry is complete
-		this.primitives.forEach(function(primitive) {
-            /*if(!primitive.mesh) {
-                primitive.mesh = new THREE.Mesh(primitive.geometry, primitive.material);
-            }*/
+	Mesh.prototype.attachToNode = function( threeNode ) {
+
+		// Assumes that the geometry is complete
+		this.primitives.forEach( function( primitive ) {
+
+			/*if(!primitive.mesh) {
+			                primitive.mesh = new THREE.Mesh(primitive.geometry, primitive.material);
+			            }*/
 			var material = primitive.material;
-			if (!(material instanceof THREE.Material)) {
-				material = theLoader.createShaderMaterial(material);
+			if ( ! ( material instanceof THREE.Material ) ) {
+
+				material = theLoader.createShaderMaterial( material );
+
 			}
 
-			var threeMesh = new THREE.Mesh(primitive.geometry.geometry, material);
+			var threeMesh = new THREE.Mesh( primitive.geometry.geometry, material );
 			threeMesh.castShadow = true;
-			threeNode.add(threeMesh);
-		});
+			threeNode.add( threeMesh );
+
+		} );
+
 	};
 
-    // Delayed-loaded material
-	var Material = function(params) {
+	// Delayed-loaded material
+	var Material = function( params ) {
+
 		this.params = params;
+
 	};
 
-    // Delegate for processing animation parameter buffers
+	// Delegate for processing animation parameter buffers
 	var AnimationParameterDelegate = function() {};
 
-	AnimationParameterDelegate.prototype.handleError = function(errorCode, info) {
-        // FIXME: report error
-		console.log("ERROR(AnimationParameterDelegate):" + errorCode + ":" + info);
+	AnimationParameterDelegate.prototype.handleError = function( errorCode, info ) {
+
+		// FIXME: report error
+		console.log( "ERROR(AnimationParameterDelegate):" + errorCode + ":" + info );
+
 	};
 
-	AnimationParameterDelegate.prototype.convert = function(resource, ctx) {
+	AnimationParameterDelegate.prototype.convert = function( resource, ctx ) {
+
 		var parameter = ctx.parameter;
 
 		var glResource = null;
-		switch (parameter.type) {
+		switch ( parameter.type ) {
 			case WebGLRenderingContext.FLOAT :
 			case WebGLRenderingContext.FLOAT_VEC2 :
 			case WebGLRenderingContext.FLOAT_VEC3 :
 			case WebGLRenderingContext.FLOAT_VEC4 :
-				glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
+				glResource = new Float32Array( resource, 0, parameter.count * componentsPerElementForGLType( parameter.type ) );
 				break;
 			default:
 				break;
 		}
 
 		return glResource;
+
 	};
 
-	AnimationParameterDelegate.prototype.resourceAvailable = function(glResource, ctx) {
+	AnimationParameterDelegate.prototype.resourceAvailable = function( glResource, ctx ) {
+
 		var animation = ctx.animation;
 		var parameter = ctx.parameter;
 		parameter.data = glResource;
-		animation.handleParameterLoaded(parameter);
+		animation.handleParameterLoaded( parameter );
 		return true;
+
 	};
 
 	var animationParameterDelegate = new AnimationParameterDelegate();
 
-	var AnimationParameterContext = function(parameter, animation) {
+	var AnimationParameterContext = function( parameter, animation ) {
+
 		this.parameter = parameter;
 		this.animation = animation;
+
 	};
 
-    // Animations
+	// Animations
 	var Animation = function() {
 
-    	// create Three.js keyframe here
+		// create Three.js keyframe here
 		this.totalParameters = 0;
 		this.loadedParameters = 0;
 		this.parameters = {};
@@ -375,1180 +474,1445 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
 
 	Animation.prototype.constructor = Animation;
 
-	Animation.prototype.handleParameterLoaded = function(parameter) {
-		this.parameters[parameter.name] = parameter;
+	Animation.prototype.handleParameterLoaded = function( parameter ) {
+
+		this.parameters[ parameter.name ] = parameter;
 		this.loadedParameters ++;
 		this.checkFinished();
+
 	};
 
 	Animation.prototype.checkFinished = function() {
-		if (this.loadedParameters === this.totalParameters) {
-            // Build animation
+
+		if ( this.loadedParameters === this.totalParameters ) {
+
+			// Build animation
 			this.finishedLoading = true;
 
-			if (this.onload) {
+			if ( this.onload ) {
+
 				this.onload();
+
 			}
+
 		}
+
 	};
 
-    // Delegate for processing inverse bind matrices buffer
+	// Delegate for processing inverse bind matrices buffer
 	var InverseBindMatricesDelegate = function() {};
 
-	InverseBindMatricesDelegate.prototype.handleError = function(errorCode, info) {
-        // FIXME: report error
-		console.log("ERROR(InverseBindMatricesDelegate):" + errorCode + ":" + info);
+	InverseBindMatricesDelegate.prototype.handleError = function( errorCode, info ) {
+
+		// FIXME: report error
+		console.log( "ERROR(InverseBindMatricesDelegate):" + errorCode + ":" + info );
+
 	};
 
-	InverseBindMatricesDelegate.prototype.convert = function(resource, ctx) {
+	InverseBindMatricesDelegate.prototype.convert = function( resource, ctx ) {
+
 		var parameter = ctx.parameter;
 
 		var glResource = null;
-		switch (parameter.type) {
+		switch ( parameter.type ) {
 			case WebGLRenderingContext.FLOAT_MAT4 :
-				glResource = new Float32Array(resource, 0, parameter.count * componentsPerElementForGLType(parameter.type));
+				glResource = new Float32Array( resource, 0, parameter.count * componentsPerElementForGLType( parameter.type ) );
 				break;
 			default:
 				break;
 		}
 
 		return glResource;
+
 	};
 
-	InverseBindMatricesDelegate.prototype.resourceAvailable = function(glResource, ctx) {
+	InverseBindMatricesDelegate.prototype.resourceAvailable = function( glResource, ctx ) {
+
 		var skin = ctx.skin;
 		skin.inverseBindMatrices = glResource;
 		return true;
+
 	};
 
 	var inverseBindMatricesDelegate = new InverseBindMatricesDelegate();
 
-	var InverseBindMatricesContext = function(param, skin) {
+	var InverseBindMatricesContext = function( param, skin ) {
+
 		this.parameter = param;
 		this.skin = skin;
+
 	};
 
-    // Delegate for processing shaders from external files
+	// Delegate for processing shaders from external files
 	var ShaderDelegate = function() {};
 
-	ShaderDelegate.prototype.handleError = function(errorCode, info) {
-        // FIXME: report error
-		console.log("ERROR(ShaderDelegate):" + errorCode + ":" + info);
+	ShaderDelegate.prototype.handleError = function( errorCode, info ) {
+
+		// FIXME: report error
+		console.log( "ERROR(ShaderDelegate):" + errorCode + ":" + info );
+
 	};
 
-	ShaderDelegate.prototype.convert = function(resource, ctx) {
+	ShaderDelegate.prototype.convert = function( resource, ctx ) {
+
 		return resource;
+
 	};
 
-	ShaderDelegate.prototype.resourceAvailable = function(data, ctx) {
+	ShaderDelegate.prototype.resourceAvailable = function( data, ctx ) {
+
 		theLoader.shadersLoaded ++;
-		theLoader.shaders[ctx.id] = data;
+		theLoader.shaders[ ctx.id ] = data;
 		theLoader.checkComplete();
 		return true;
+
 	};
 
 	var shaderDelegate = new ShaderDelegate();
 
-	var ShaderContext = function(id, path) {
+	var ShaderContext = function( id, path ) {
+
 		this.id = id;
 		this.path = path;
+
 	};
 
-    // Resource management
+	// Resource management
+
+	var ResourceEntry = function( entryID, object, description ) {
 
-	var ResourceEntry = function(entryID, object, description) {
 		this.entryID = entryID;
 		this.object = object;
 		this.description = description;
+
 	};
 
 	var Resources = function() {
+
 		this._entries = {};
+
 	};
 
-	Resources.prototype.setEntry = function(entryID, object, description) {
-		if (!entryID) {
-			console.error("No EntryID provided, cannot store", description);
+	Resources.prototype.setEntry = function( entryID, object, description ) {
+
+		if ( ! entryID ) {
+
+			console.error( "No EntryID provided, cannot store", description );
 			return;
+
 		}
 
-		if (this._entries[entryID]) {
-			console.warn("entry[" + entryID + "] is being overwritten");
+		if ( this._entries[ entryID ] ) {
+
+			console.warn( "entry[" + entryID + "] is being overwritten" );
+
 		}
 
-		this._entries[entryID] = new ResourceEntry(entryID, object, description );
+		this._entries[ entryID ] = new ResourceEntry( entryID, object, description );
+
 	};
 
-	Resources.prototype.getEntry = function(entryID) {
-		return this._entries[entryID];
+	Resources.prototype.getEntry = function( entryID ) {
+
+		return this._entries[ entryID ];
+
 	};
 
 	Resources.prototype.clearEntries = function() {
+
 		this._entries = {};
+
 	};
 
-	LoadDelegate = function() {
-    };
+	LoadDelegate = function() {};
 
-	LoadDelegate.prototype.loadCompleted = function(callback, obj) {
-		callback.call(Window, obj);
-	};
+	LoadDelegate.prototype.loadCompleted = function( callback, obj ) {
 
-    // Loader
+		callback.call( Window, obj );
 
-	var ThreeGLTFLoader = Object.create(glTFParser, {
+	};
 
-        load: {
-            enumerable: true,
-            value: function(userInfo, options) {
-	this.resources = new Resources();
-	this.cameras = [];
-	this.lights = [];
-	this.animations = [];
-	this.joints = {};
-	this.skeltons = {};
-	THREE.GLTFLoaderUtils.init();
-	glTFParser.load.call(this, userInfo, options);
-            }
-        },
-
-        cameras: {
-        	enumerable: true,
-        	writable: true,
-        	value : []
-        },
-
-        lights: {
-        	enumerable: true,
-        	writable: true,
-        	value : []
-        },
-
-        animations: {
-        	enumerable: true,
-        	writable: true,
-        	value : []
-        },
-
-        // Implement WebGLTFLoader handlers
-
-        handleBuffer: {
-            value: function(entryID, description, userInfo) {
-	this.resources.setEntry(entryID, null, description);
-	description.type = "ArrayBuffer";
-	return true;
-            }
-        },
-
-        handleBufferView: {
-            value: function(entryID, description, userInfo) {
-	this.resources.setEntry(entryID, null, description);
-
-	var buffer =  this.resources.getEntry(description.buffer);
-	description.type = "ArrayBufferView";
-
-	var bufferViewEntry = this.resources.getEntry(entryID);
-	bufferViewEntry.buffer = buffer;
-	return true;
-            }
-        },
-
-        handleShader: {
-            value: function(entryID, description, userInfo) {
-	this.resources.setEntry(entryID, null, description);
-	var shaderRequest = {
-        				id : entryID,
-        				path : description.path,
-        		};
-
-	var shaderContext = new ShaderContext(entryID, description.path);
-
-	theLoader.shadersRequested ++;
-	THREE.GLTFLoaderUtils.getFile(shaderRequest, shaderDelegate, shaderContext);
-
-	return true;
-            }
-        },
-
-        handleProgram: {
-            value: function(entryID, description, userInfo) {
-	this.resources.setEntry(entryID, null, description);
-	return true;
-            }
-        },
-
-        handleTechnique: {
-            value: function(entryID, description, userInfo) {
-	this.resources.setEntry(entryID, null, description);
-	return true;
-            }
-        },
-
-        createShaderMaterial : {
-        	value: function(material) {
-
-	var fragmentShader = theLoader.shaders[material.params.fragmentShader];
-	if (!fragmentShader) {
-		console.log("ERROR: Missing fragment shader definition:", material.params.fragmentShader);
-		return new THREE.MeshPhongMaterial;
-	}
+	// Loader
 
-	var vertexShader = theLoader.shaders[material.params.vertexShader];
-	if (!fragmentShader) {
-		console.log("ERROR: Missing vertex shader definition:", material.params.vertexShader);
-		return new THREE.MeshPhongMaterial;
-	}
+	var ThreeGLTFLoader = Object.create( glTFParser, {
 
-	var uniforms = {};
-	var shaderMaterial = new THREE.ShaderMaterial( {
+		load: {
+			enumerable: true,
+			value: function( userInfo, options ) {
 
-        			fragmentShader: fragmentShader,
-        			vertexShader: vertexShader,
-        			uniforms: uniforms,
+				this.resources = new Resources();
+				this.cameras = [];
+				this.lights = [];
+				this.animations = [];
+				this.joints = {};
+				this.skeltons = {};
+				THREE.GLTFLoaderUtils.init();
+				glTFParser.load.call( this, userInfo, options );
 
-        		} );
+			}
+		},
 
-	return new THREE.MeshPhongMaterial(material.params);
-        	}
-        },
+		cameras: {
+			enumerable: true,
+			writable: true,
+			value : []
+		},
 
-        createShaderParams : {
-        	value: function(materialId, values, params, instanceProgram) {
-	var program = this.resources.getEntry(instanceProgram.program);
+		lights: {
+			enumerable: true,
+			writable: true,
+			value : []
+		},
 
-	if (program) {
-		params.fragmentShader = program.description.fragmentShader;
-		params.vertexShader = program.description.vertexShader;
-		params.attributes = instanceProgram.attributes;
-		params.uniforms = instanceProgram.uniforms;
-	}
-        	}
-        },
-
-        threeJSMaterialType : {
-            value: function(materialId, technique, values, params) {
-
-	var materialType = THREE.MeshPhongMaterial;
-	var defaultPass = null;
-	if (technique && technique.description && technique.description.passes)
-        			defaultPass = technique.description.passes.defaultPass;
-
-	if (defaultPass) {
-		if (defaultPass.details && defaultPass.details.commonProfile) {
-			var profile = technique.description.passes.defaultPass.details.commonProfile;
-			if (profile)
-	            		{
-				switch (profile.lightingModel)
-		            		{
-					case 'Blinn' :
-					case 'Phong' :
-						materialType = THREE.MeshPhongMaterial;
-						break;
-
-					case 'Lambert' :
-						materialType = THREE.MeshLambertMaterial;
-						break;
-
-					default :
-						materialType = THREE.MeshBasicMaterial;
-						break;
-				}
+		animations: {
+			enumerable: true,
+			writable: true,
+			value : []
+		},
 
-				if (profile.extras && profile.extras.doubleSided)
-		            		{
-					params.side = THREE.DoubleSide;
-				}
-			}
-		}
-        			else if (defaultPass.instanceProgram) {
+		// Implement WebGLTFLoader handlers
 
-	var instanceProgram = defaultPass.instanceProgram;
+		handleBuffer: {
+			value: function( entryID, description, userInfo ) {
 
-	this.createShaderParams(materialId, values, params, instanceProgram);
+				this.resources.setEntry( entryID, null, description );
+				description.type = "ArrayBuffer";
+				return true;
 
-	var loadshaders = true;
+			}
+		},
 
-	if (loadshaders) {
-		materialType = Material;
-	}
-        			}
-	}
+		handleBufferView: {
+			value: function( entryID, description, userInfo ) {
 
-	var texturePath = null;
-	var textureParams = null;
-	var diffuse = values.diffuse;
-	if (diffuse)
-                {
-		var texture = diffuse;
-		if (texture) {
-			var textureEntry = this.resources.getEntry(texture);
-			if (textureEntry) {
-				{
-					var imageEntry = this.resources.getEntry(textureEntry.description.source);
-					if (imageEntry) {
-						texturePath = imageEntry.description.path;
-					}
+				this.resources.setEntry( entryID, null, description );
 
-					var samplerEntry = this.resources.getEntry(textureEntry.description.sampler);
-					if (samplerEntry) {
-						textureParams = samplerEntry.description;
-					}
-				}
-			}
-		}
-	}
+				var buffer =  this.resources.getEntry( description.buffer );
+				description.type = "ArrayBufferView";
 
-	var texture = LoadTexture(texturePath);
-	if (texture && textureParams) {
+				var bufferViewEntry = this.resources.getEntry( entryID );
+				bufferViewEntry.buffer = buffer;
+				return true;
 
-		if (textureParams.wrapS == WebGLRenderingContext.REPEAT)
-                		texture.wrapS = THREE.RepeatWrapping;
+			}
+		},
 
-		if (textureParams.wrapT == WebGLRenderingContext.REPEAT)
-                		texture.wrapT = THREE.RepeatWrapping;
+		handleShader: {
+			value: function( entryID, description, userInfo ) {
 
-		if (textureParams.magFilter == WebGLRenderingContext.LINEAR)
-                		texture.magFilter = THREE.LinearFilter;
+				this.resources.setEntry( entryID, null, description );
+				var shaderRequest = {
+					id : entryID,
+					path : description.path,
+				};
 
-//                	if (textureParams.minFilter == "LINEAR")
-//               		texture.minFilter = THREE.LinearFilter;
+				var shaderContext = new ShaderContext( entryID, description.path );
 
-		params.map = texture;
-	}
+				theLoader.shadersRequested ++;
+				THREE.GLTFLoaderUtils.getFile( shaderRequest, shaderDelegate, shaderContext );
 
-	var envMapPath = null;
-	var envMapParams = null;
-	var reflective = values.reflective;
-	if (reflective)
-                {
-		var texture = reflective;
-		if (texture) {
-			var textureEntry = this.resources.getEntry(texture);
-			if (textureEntry) {
-				{
-					var imageEntry = this.resources.getEntry(textureEntry.description.source);
-					if (imageEntry) {
-						envMapPath = imageEntry.description.path;
-					}
+				return true;
 
-					var samplerEntry = this.resources.getEntry(textureEntry.description.sampler);
-					if (samplerEntry) {
-						envMapParams = samplerEntry.description;
-					}
-				}
 			}
-		}
-	}
+		},
 
-	var texture = LoadTexture(envMapPath);
-	if (texture && envMapParams) {
+		handleProgram: {
+			value: function( entryID, description, userInfo ) {
 
-		if (envMapParams.wrapS == WebGLRenderingContext.REPEAT)
-                		texture.wrapS = THREE.RepeatWrapping;
+				this.resources.setEntry( entryID, null, description );
+				return true;
 
-		if (envMapParams.wrapT == WebGLRenderingContext.REPEAT)
-                		texture.wrapT = THREE.RepeatWrapping;
+			}
+		},
 
-		if (envMapParams.magFilter == WebGLRenderingContext.LINEAR)
-                		texture.magFilter = THREE.LinearFilter;
+		handleTechnique: {
+			value: function( entryID, description, userInfo ) {
 
-//                	if (envMapParams.minFilter == WebGLRenderingContext.LINEAR)
-//               		texture.minFilter = THREE.LinearFilter;
+				this.resources.setEntry( entryID, null, description );
+				return true;
 
-		params.envMap = texture;
-	}
+			}
+		},
 
-	var shininess = values.shininesss || values.shininess; // N.B.: typo in converter!
-	if (shininess)
-                {
-		shininess = shininess;
-	}
+		createShaderMaterial : {
+			value: function( material ) {
 
-	var diffuseColor = !texturePath ? diffuse : null;
-	var opacity = 1.0;
-	if (values.hasOwnProperty("transparency"))
-                {
-		var USE_A_ONE = true; // for now, hack because file format isn't telling us
-		opacity =  USE_A_ONE ? values.transparency : (1.0 - values.transparency);
-	}
+				var fragmentShader = theLoader.shaders[ material.params.fragmentShader ];
+				if ( ! fragmentShader ) {
 
-                // if (diffuseColor) diffuseColor = [0, 1, 0];
+					console.log( "ERROR: Missing fragment shader definition:", material.params.fragmentShader );
+					return new THREE.MeshPhongMaterial;
 
-	params.color = RgbArraytoHex(diffuseColor);
-	params.opacity = opacity;
-	params.transparent = opacity < 1.0;
-                // hack hack hack
-	if (texturePath && texturePath.toLowerCase().indexOf(".png") != -1)
-                	params.transparent = true;
+				}
 
-	if (!(shininess === undefined))
-                {
-		params.shininess = shininess;
-	}
+				var vertexShader = theLoader.shaders[ material.params.vertexShader ];
+				if ( ! fragmentShader ) {
 
-	if (!(values.emission === undefined))
-                {
-		params.emissive = RgbArraytoHex(values.emission);
-	}
+					console.log( "ERROR: Missing vertex shader definition:", material.params.vertexShader );
+					return new THREE.MeshPhongMaterial;
 
-	if (!(values.specular === undefined))
-                {
-		params.specular = RgbArraytoHex(values.specular);
-	}
+				}
 
-	return materialType;
+				var uniforms = {};
+				var shaderMaterial = new THREE.ShaderMaterial( {
 
-        	}
-        },
+					fragmentShader: fragmentShader,
+					vertexShader: vertexShader,
+					uniforms: uniforms,
 
-        handleMaterial: {
-            value: function(entryID, description, userInfo) {
-                //this should be rewritten using the meta datas that actually create the shader.
-                //here we will infer what needs to be pass to Three.js by looking inside the technique parameters.
-	var technique = this.resources.getEntry(description.instanceTechnique.technique);
-	var materialParams = {};
-	var values = description.instanceTechnique.values;
+				} );
 
-	var materialType = this.threeJSMaterialType(entryID, technique, values, materialParams);
+				return new THREE.MeshPhongMaterial( material.params );
 
-	var material = new materialType(materialParams);
+			}
+		},
 
-	this.resources.setEntry(entryID, material, description);
+		createShaderParams : {
+			value: function( materialId, values, params, instanceProgram ) {
 
-	return true;
-            }
-        },
+				var program = this.resources.getEntry( instanceProgram.program );
 
-        handleMesh: {
-            value: function(entryID, description, userInfo) {
-	var mesh = new Mesh();
-	this.resources.setEntry(entryID, mesh, description);
-	var primitivesDescription = description.primitives;
-	if (!primitivesDescription) {
-                    //FIXME: not implemented in delegate
-		console.log("MISSING_PRIMITIVES for mesh:" + entryID);
-		return false;
-	}
+				if ( program ) {
 
-	for (var i = 0 ; i < primitivesDescription.length ; i ++) {
-		var primitiveDescription = primitivesDescription[i];
-
-		if (primitiveDescription.primitive === WebGLRenderingContext.TRIANGLES) {
-
-			var geometry = new ClassicGeometry();
-			var materialEntry = this.resources.getEntry(primitiveDescription.material);
-
-			mesh.addPrimitive(geometry, materialEntry.object);
-
-			var indices = this.resources.getEntry(primitiveDescription.indices);
-			var bufferEntry = this.resources.getEntry(indices.description.bufferView);
-			var indicesObject = {
-                        		bufferView : bufferEntry,
-                        		byteOffset : indices.description.byteOffset,
-                        		count : indices.description.count,
-                        		id : indices.entryID,
-                        		type : indices.description.type
-                        };
-
-			var indicesContext = new IndicesContext(indicesObject, geometry);
-			var alreadyProcessedIndices = THREE.GLTFLoaderUtils.getBuffer(indicesObject, indicesDelegate, indicesContext);
-                        /*if(alreadyProcessedIndices) {
-                            indicesDelegate.resourceAvailable(alreadyProcessedIndices, indicesContext);
-                        }*/
-
-                        // Load Vertex Attributes
-			var allAttributes = Object.keys(primitiveDescription.attributes);
-			allAttributes.forEach( function(semantic) {
-				geometry.totalAttributes ++;
-
-				var attribute;
-				var attributeID = primitiveDescription.attributes[semantic];
-				var attributeEntry = this.resources.getEntry(attributeID);
-				if (!attributeEntry) {
-                                //let's just use an anonymous object for the attribute
-					attribute = description.attributes[attributeID];
-					attribute.id = attributeID;
-					this.resources.setEntry(attributeID, attribute, attribute);
-
-					var bufferEntry = this.resources.getEntry(attribute.bufferView);
-					attributeEntry = this.resources.getEntry(attributeID);
+					params.fragmentShader = program.description.fragmentShader;
+					params.vertexShader = program.description.vertexShader;
+					params.attributes = instanceProgram.attributes;
+					params.uniforms = instanceProgram.uniforms;
 
-				} else {
-					attribute = attributeEntry.object;
-					attribute.id = attributeID;
-					var bufferEntry = this.resources.getEntry(attribute.bufferView);
 				}
 
-				var attributeObject = {
-                            		bufferView : bufferEntry,
-                            		byteOffset : attribute.byteOffset,
-                            		byteStride : attribute.byteStride,
-                            		count : attribute.count,
-                            		max : attribute.max,
-                            		min : attribute.min,
-                            		type : attribute.type,
-                            		id : attributeID
-                            };
-
-				var attribContext = new VertexAttributeContext(attributeObject, semantic, geometry);
-
-				var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(attributeObject, vertexAttributeDelegate, attribContext);
-                            /*if(alreadyProcessedAttribute) {
-                                vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
-                            }*/
-			}, this);
-		}
-	}
-	return true;
-            }
-        },
-
-        handleCamera: {
-            value: function(entryID, description, userInfo) {
-	var camera;
-	if (description.type == "perspective")
-                {
-		var znear = description.perspective.znear;
-		var zfar = description.perspective.zfar;
-		var yfov = description.perspective.yfov;
-		var xfov = description.perspective.xfov;
-		var aspect_ratio = description.perspective.aspect_ratio;
-
-		if (!aspect_ratio)
-            			aspect_ratio = 1;
-
-		if (yfov === undefined)
-                	{
-			if (xfov)
-                		{
-                			// According to COLLADA spec...
-                			// aspect_ratio = xfov / yfov
-				yfov = xfov / aspect_ratio;
 			}
+		},
 
-		}
-
-		if (yfov)
-                	{
-			camera = new THREE.PerspectiveCamera(yfov, aspect_ratio, znear, zfar);
-		}
-	}
-                else
-	{
-		camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, znear, zfar );
-	}
-
-	if (camera)
-                {
-		this.resources.setEntry(entryID, camera, description);
-	}
-
-	return true;
-            }
-        },
+		threeJSMaterialType : {
+			value: function( materialId, technique, values, params ) {
 
-        handleLight: {
-            value: function(entryID, description, userInfo) {
+				var materialType = THREE.MeshPhongMaterial;
+				var defaultPass = null;
+				if ( technique && technique.description && technique.description.passes )
+			defaultPass = technique.description.passes.defaultPass;
 
-	var light = null;
-	var type = description.type;
-	if (type && description[type])
-        		{
-		var lparams = description[type];
-		var color = RgbArraytoHex(lparams.color);
+				if ( defaultPass ) {
 
-		switch (type) {
-			case "directional" :
-				light = new THREE.DirectionalLight(color);
-				light.position.set(0, 0, 1);
-				break;
+					if ( defaultPass.details && defaultPass.details.commonProfile ) {
 
-			case "point" :
-				light = new THREE.PointLight(color);
-				break;
+						var profile = technique.description.passes.defaultPass.details.commonProfile;
+						if ( profile )
+				{
 
-			case "spot " :
-				light = new THREE.SpotLight(color);
-				light.position.set(0, 0, 1);
-				break;
+							switch ( profile.lightingModel )
+					{
+								case 'Blinn' :
+								case 'Phong' :
+									materialType = THREE.MeshPhongMaterial;
+									break;
 
-			case "ambient" :
-				light = new THREE.AmbientLight(color);
-				break;
-		}
-	}
+								case 'Lambert' :
+									materialType = THREE.MeshLambertMaterial;
+									break;
 
-	if (light)
-        		{
-		this.resources.setEntry(entryID, light, description);
-	}
+								default :
+									materialType = THREE.MeshBasicMaterial;
+									break;
+							}
 
-	return true;
-            }
-        },
-
-        addPendingMesh: {
-            value: function(mesh, threeNode) {
-	theLoader.pendingMeshes.push({
-        			mesh: mesh,
-        			node: threeNode
-        		});
-        	}
-        },
-
-        handleNode: {
-            value: function(entryID, description, userInfo) {
-
-	var threeNode = null;
-	            if (description.jointId) {
-		threeNode = new THREE.Bone();
-		threeNode.jointId = description.jointId;
-		this.joints[description.jointId] = entryID;
-	            }
-	            else {
-		threeNode = new THREE.Object3D();
-	            }
-
-	threeNode.name = description.name;
-
-	this.resources.setEntry(entryID, threeNode, description);
-
-	var m = description.matrix;
-	if (m) {
-		threeNode.applyMatrix(new THREE.Matrix4().fromArray( m ));
-		threeNode.matrixAutoUpdate = false;
-		threeNode.matrixWorldNeedsUpdate = true;
-	}
-	else {
-		var t = description.translation;
-		var r = description.rotation;
-		var s = description.scale;
-
-		var position = t ? new THREE.Vector3(t[0], t[1], t[2]) :
-                		new THREE.Vector3;
-		if (r) {
-			convertAxisAngleToQuaternion(r, 1);
-		}
-		var rotation = r ? new THREE.Quaternion(r[0], r[1], r[2], r[3]) :
-                		new THREE.Quaternion;
-		var scale = s ? new THREE.Vector3(s[0], s[1], s[2]) :
-                		new THREE.Vector3;
-
-		var matrix = new THREE.Matrix4;
-		matrix.compose(position, rotation, scale);
-		threeNode.matrixAutoUpdate = false;
-		threeNode.matrixWorldNeedsUpdate = true;
-		threeNode.applyMatrix(matrix);
-	}
+							if ( profile.extras && profile.extras.doubleSided )
+					{
 
-	var self = this;
+								params.side = THREE.DoubleSide;
 
-                // Iterate through all node meshes and attach the appropriate objects
-                //FIXME: decision needs to be made between these 2 ways, probably meshes will be discarded.
-	var meshEntry;
-	if (description.mesh) {
-		meshEntry = this.resources.getEntry(description.mesh);
-		theLoader.meshesRequested ++;
-		meshEntry.object.onComplete(function(mesh) {
-			self.addPendingMesh(mesh, threeNode);
-			theLoader.meshesLoaded ++;
-			theLoader.checkComplete();
-		});
-	}
+							}
 
-	if (description.meshes) {
-		description.meshes.forEach( function(meshID) {
-			meshEntry = this.resources.getEntry(meshID);
-			theLoader.meshesRequested ++;
-			meshEntry.object.onComplete(function(mesh) {
-				self.addPendingMesh(mesh, threeNode);
-				theLoader.meshesLoaded ++;
-				theLoader.checkComplete();
-			});
-		}, this);
-	}
+						}
 
-	if (description.instanceSkin) {
+					}
+					else if ( defaultPass.instanceProgram ) {
 
-		var skinEntry =  this.resources.getEntry(description.instanceSkin.skin);
+						var instanceProgram = defaultPass.instanceProgram;
 
-		if (skinEntry) {
+						this.createShaderParams( materialId, values, params, instanceProgram );
 
-			var skin = skinEntry.object;
-			description.instanceSkin.skin = skin;
-			threeNode.instanceSkin = description.instanceSkin;
+						var loadshaders = true;
 
-			var sources = description.instanceSkin.sources;
-			skin.meshes = [];
-			sources.forEach( function(meshID) {
-				meshEntry = this.resources.getEntry(meshID);
-				theLoader.meshesRequested ++;
-				meshEntry.object.onComplete(function(mesh) {
+						if ( loadshaders ) {
 
-					skin.meshes.push(mesh);
-					theLoader.meshesLoaded ++;
-					theLoader.checkComplete();
-				});
-			}, this);
+							materialType = Material;
 
-		}
-	}
+						}
 
-	if (description.camera) {
-		var cameraEntry = this.resources.getEntry(description.camera);
-		if (cameraEntry) {
-			threeNode.add(cameraEntry.object);
-			this.cameras.push(cameraEntry.object);
-		}
-	}
+					}
 
-	if (description.light) {
-		var lightEntry = this.resources.getEntry(description.light);
-		if (lightEntry) {
-			threeNode.add(lightEntry.object);
-			this.lights.push(lightEntry.object);
-		}
-	}
+				}
 
-	return true;
-            }
-        },
-
-        buildNodeHirerachy: {
-            value: function(nodeEntryId, parentThreeNode) {
-	var nodeEntry = this.resources.getEntry(nodeEntryId);
-	var threeNode = nodeEntry.object;
-	parentThreeNode.add(threeNode);
-
-	var children = nodeEntry.description.children;
-	if (children) {
-		children.forEach( function(childID) {
-			this.buildNodeHirerachy(childID, threeNode);
-		}, this);
-	}
+				var texturePath = null;
+				var textureParams = null;
+				var diffuse = values.diffuse;
+				if ( diffuse )
+			{
 
-	return threeNode;
-            }
-        },
+					var texture = diffuse;
+					if ( texture ) {
 
-        buildSkin: {
-            value: function(node) {
+						var textureEntry = this.resources.getEntry( texture );
+						if ( textureEntry ) {
 
-	var skin = node.instanceSkin.skin;
-	if (skin) {
-		node.instanceSkin.skeletons.forEach(function(skeleton) {
-			var nodeEntry = this.resources.getEntry(skeleton);
-			if (nodeEntry) {
+							{
 
-				var rootSkeleton = nodeEntry.object;
+								var imageEntry = this.resources.getEntry( textureEntry.description.source );
+								if ( imageEntry ) {
 
-				var dobones = true;
+									texturePath = imageEntry.description.path;
 
-				var i, len = skin.meshes.length;
-				for (i = 0; i < len; i ++) {
-					var mesh = skin.meshes[i];
-					var threeMesh = null;
-					mesh.primitives.forEach(function(primitive) {
+								}
 
-						var material = primitive.material;
-						if (!(material instanceof THREE.Material)) {
-							material = this.createShaderMaterial(material);
-						}
+								var samplerEntry = this.resources.getEntry( textureEntry.description.sampler );
+								if ( samplerEntry ) {
 
-						threeMesh = new THREE.SkinnedMesh(primitive.geometry.geometry, material, false);
-						threeMesh.add(rootSkeleton);
+									textureParams = samplerEntry.description;
 
-						var geometry = primitive.geometry.geometry;
-						var j;
-						if (geometry.vertices) {
-							for ( j = 0; j < geometry.vertices.length; j ++ ) {
-								geometry.vertices[j].applyMatrix4( skin.bindShapeMatrix );
-							}
-						}
-                                    else if (geometry.attributes.position) {
-	var a = geometry.attributes.position.array;
-	var v = new THREE.Vector3;
-	                            		for ( j = 0; j < a.length / 3; j ++ ) {
-		v.set(a[j * 3], a[j * 3 + 1], a[j * 3 + 2]);
-		v.applyMatrix4( skin.bindShapeMatrix );
-		a[j * 3] = v.x;
-		a[j * 3 + 1] = v.y;
-		a[j * 3 + 2] = v.z;
-	                            		}
-                                    }
-
-						if (threeMesh && dobones) {
-
-							material.skinning = true;
-
-							threeMesh.boneInverses = [];
-							var jointsIds = skin.jointsIds;
-							var bones = [];
-							var boneInverses = [];
-							var i, len = jointsIds.length;
-							for (i = 0; i < len; i ++) {
-								var jointId = jointsIds[i];
-								var nodeForJoint = this.joints[jointId];
-								var joint = this.resources.getEntry(nodeForJoint).object;
-								if (joint) {
-
-									joint.skin = threeMesh;
-									bones.push(joint);
-
-									var m = skin.inverseBindMatrices;
-									var mat = new THREE.Matrix4().set(
-        	                                            m[i * 16 + 0],  m[i * 16 + 4],  m[i * 16 + 8],  m[i * 16 + 12],
-        	                                            m[i * 16 + 1],  m[i * 16 + 5],  m[i * 16 + 9],  m[i * 16 + 13],
-        	                                            m[i * 16 + 2],  m[i * 16 + 6],  m[i * 16 + 10], m[i * 16 + 14],
-        	                                            m[i * 16 + 3],  m[i * 16 + 7],  m[i * 16 + 11], m[i * 16 + 15]
-        	                                        );
-									boneInverses.push(mat);
-
-								} else {
-									console.log("WARNING: jointId:" + jointId + " cannot be found in skeleton:" + skeleton);
 								}
+
 							}
 
-							threeMesh.bind(new THREE.Skeleton(bones, boneInverses, false));
 						}
 
-						if (threeMesh) {
-							threeMesh.castShadow = true;
-							node.add(threeMesh);
-						}
+					}
 
-					}, this);
 				}
 
-			}
+				var texture = LoadTexture( texturePath );
+				if ( texture && textureParams ) {
 
+					if ( textureParams.wrapS == WebGLRenderingContext.REPEAT )
+			texture.wrapS = THREE.RepeatWrapping;
 
-		}, this);
+					if ( textureParams.wrapT == WebGLRenderingContext.REPEAT )
+			texture.wrapT = THREE.RepeatWrapping;
 
-	}
-            }
-        },
+					if ( textureParams.magFilter == WebGLRenderingContext.LINEAR )
+			texture.magFilter = THREE.LinearFilter;
 
-        buildSkins: {
-            value: function(node) {
+					//                	if (textureParams.minFilter == "LINEAR")
+					//               		texture.minFilter = THREE.LinearFilter;
 
-	if (node.instanceSkin)
-        			this.buildSkin(node);
+					params.map = texture;
 
-	var children = node.children;
-	if (children) {
-		children.forEach( function(child) {
-			this.buildSkins(child);
-		}, this);
-	}
-            }
-        },
+				}
 
-        createMeshAnimations : {
-        	value : function(root) {
-	this.buildSkins(root);
-        		}
-        },
+				var envMapPath = null;
+				var envMapParams = null;
+				var reflective = values.reflective;
+				if ( reflective )
+			{
 
-        handleScene: {
-            value: function(entryID, description, userInfo) {
+					var texture = reflective;
+					if ( texture ) {
 
-	if (!description.nodes) {
-		console.log("ERROR: invalid file required nodes property is missing from scene");
-		return false;
-	}
+						var textureEntry = this.resources.getEntry( texture );
+						if ( textureEntry ) {
 
-	description.nodes.forEach( function(nodeUID) {
-		this.buildNodeHirerachy(nodeUID, userInfo.rootObj);
-	}, this);
+							{
 
-	if (this.delegate) {
-		this.delegate.loadCompleted(userInfo.callback, userInfo.rootObj);
-	}
+								var imageEntry = this.resources.getEntry( textureEntry.description.source );
+								if ( imageEntry ) {
 
-	return true;
-            }
-        },
+									envMapPath = imageEntry.description.path;
 
-        handleImage: {
-            value: function(entryID, description, userInfo) {
-	this.resources.setEntry(entryID, null, description);
-	return true;
-            }
-        },
+								}
 
-        addNodeAnimationChannel : {
-        	value : function(name, channel, interp) {
-	if (!this.nodeAnimationChannels)
-        			this.nodeAnimationChannels = {};
+								var samplerEntry = this.resources.getEntry( textureEntry.description.sampler );
+								if ( samplerEntry ) {
 
-	if (!this.nodeAnimationChannels[name]) {
-		this.nodeAnimationChannels[name] = [];
-	}
+									envMapParams = samplerEntry.description;
 
-	this.nodeAnimationChannels[name].push(interp);
-        	},
-        },
-
-        createAnimations : {
-        	value : function() {
-	for (var name in this.nodeAnimationChannels) {
-		var nodeAnimationChannels = this.nodeAnimationChannels[name];
-		var i, len = nodeAnimationChannels.length;
-        			//console.log(" animation channels for node " + name);
-        			//for (i = 0; i < len; i++) {
-        			//	console.log(nodeAnimationChannels[i]);
-        			//}
-		var anim = new THREE.glTFAnimation(nodeAnimationChannels);
-		anim.name = "animation_" + name;
-		this.animations.push(anim);
-	}
-        	}
-        },
+								}
+
+							}
 
-        buildAnimation: {
-        	value : function(animation) {
+						}
 
-	var interps = [];
-	            var i, len = animation.channels.length;
-	            for (i = 0; i < len; i ++) {
+					}
 
-		var channel = animation.channels[i];
-		var sampler = animation.samplers[channel.sampler];
-		if (sampler) {
+				}
 
-			var input = animation.parameters[sampler.input];
-			if (input && input.data) {
+				var texture = LoadTexture( envMapPath );
+				if ( texture && envMapParams ) {
 
-				var output = animation.parameters[sampler.output];
-				if (output && output.data) {
+					if ( envMapParams.wrapS == WebGLRenderingContext.REPEAT )
+			texture.wrapS = THREE.RepeatWrapping;
 
-					var target = channel.target;
-					var node = this.resources.getEntry(target.id);
-					if (node) {
+					if ( envMapParams.wrapT == WebGLRenderingContext.REPEAT )
+			texture.wrapT = THREE.RepeatWrapping;
 
-						var path = target.path;
+					if ( envMapParams.magFilter == WebGLRenderingContext.LINEAR )
+			texture.magFilter = THREE.LinearFilter;
 
-						if (path == "rotation")
-		            				{
-							convertAxisAngleToQuaternion(output.data, output.count);
-						}
+					//                	if (envMapParams.minFilter == WebGLRenderingContext.LINEAR)
+					//               		texture.minFilter = THREE.LinearFilter;
+
+					params.envMap = texture;
 
-						var interp = {
-			            					keys : input.data,
-			            					values : output.data,
-			            					count : input.count,
-			            					target : node.object,
-			            					path : path,
-			            					type : sampler.interpolation
-			            			};
-
-						this.addNodeAnimationChannel(target.id, channel, interp);
-						interps.push(interp);
-					}
 				}
-			}
-		}
-	            }
-        	}
-        },
 
-        handleAnimation: {
-            value: function(entryID, description, userInfo) {
+				var shininess = values.shininesss || values.shininess; // N.B.: typo in converter!
+				if ( shininess )
+			{
 
-	var self = this;
-	            theLoader.animationsRequested ++;
-	            var animation = new Animation();
-	animation.name = entryID;
-	            animation.onload = function() {
-	            	// self.buildAnimation(animation);
-		theLoader.animationsLoaded ++;
-		theLoader.animations.push(animation);
-		theLoader.checkComplete();
-	            };
-
-	            animation.channels = description.channels;
-	            animation.samplers = description.samplers;
-	            this.resources.setEntry(entryID, animation, description);
-	            var parameters = description.parameters;
-	            if (!parameters) {
-	                //FIXME: not implemented in delegate
-		console.log("MISSING_PARAMETERS for animation:" + entryID);
-		return false;
-	            }
-
-                // Load parameter buffers
-	var params = Object.keys(parameters);
-	params.forEach( function(param) {
-
-		animation.totalParameters ++;
-		var parameter = parameters[param];
-		var accessor = this.resources.getEntry(parameter);
-		if (!accessor)
-                    	debugger;
-		accessor = accessor.object;
-		var bufferView = this.resources.getEntry(accessor.bufferView);
-		var paramObject = {
-                    		bufferView : bufferView,
-                    		byteOffset : accessor.byteOffset,
-                    		count : accessor.count,
-                    		type : accessor.type,
-                    		id : accessor.bufferView,
-                    		name : param
-                    };
-
-		var paramContext = new AnimationParameterContext(paramObject, animation);
-
-		var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(paramObject, animationParameterDelegate, paramContext);
-                    /*if(alreadyProcessedAttribute) {
-                        vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
+					shininess = shininess;
+
+				}
+
+				var diffuseColor = ! texturePath ? diffuse : null;
+				var opacity = 1.0;
+				if ( values.hasOwnProperty( "transparency" ) )
+			{
+
+					var USE_A_ONE = true; // for now, hack because file format isn't telling us
+					opacity =  USE_A_ONE ? values.transparency : ( 1.0 - values.transparency );
+
+				}
+
+				// if (diffuseColor) diffuseColor = [0, 1, 0];
+
+				params.color = RgbArraytoHex( diffuseColor );
+				params.opacity = opacity;
+				params.transparent = opacity < 1.0;
+				// hack hack hack
+				if ( texturePath && texturePath.toLowerCase().indexOf( ".png" ) != - 1 )
+			params.transparent = true;
+
+				if ( ! ( shininess === undefined ) )
+			{
+
+					params.shininess = shininess;
+
+				}
+
+				if ( ! ( values.emission === undefined ) )
+			{
+
+					params.emissive = RgbArraytoHex( values.emission );
+
+				}
+
+				if ( ! ( values.specular === undefined ) )
+			{
+
+					params.specular = RgbArraytoHex( values.specular );
+
+				}
+
+				return materialType;
+
+			}
+		},
+
+		handleMaterial: {
+			value: function( entryID, description, userInfo ) {
+
+				//this should be rewritten using the meta datas that actually create the shader.
+				//here we will infer what needs to be pass to Three.js by looking inside the technique parameters.
+				var technique = this.resources.getEntry( description.instanceTechnique.technique );
+				var materialParams = {};
+				var values = description.instanceTechnique.values;
+
+				var materialType = this.threeJSMaterialType( entryID, technique, values, materialParams );
+
+				var material = new materialType( materialParams );
+
+				this.resources.setEntry( entryID, material, description );
+
+				return true;
+
+			}
+		},
+
+		handleMesh: {
+			value: function( entryID, description, userInfo ) {
+
+				var mesh = new Mesh();
+				this.resources.setEntry( entryID, mesh, description );
+				var primitivesDescription = description.primitives;
+				if ( ! primitivesDescription ) {
+
+					//FIXME: not implemented in delegate
+					console.log( "MISSING_PRIMITIVES for mesh:" + entryID );
+					return false;
+
+				}
+
+				for ( var i = 0 ; i < primitivesDescription.length ; i ++ ) {
+
+					var primitiveDescription = primitivesDescription[ i ];
+
+					if ( primitiveDescription.primitive === WebGLRenderingContext.TRIANGLES ) {
+
+						var geometry = new ClassicGeometry();
+						var materialEntry = this.resources.getEntry( primitiveDescription.material );
+
+						mesh.addPrimitive( geometry, materialEntry.object );
+
+						var indices = this.resources.getEntry( primitiveDescription.indices );
+						var bufferEntry = this.resources.getEntry( indices.description.bufferView );
+						var indicesObject = {
+				bufferView : bufferEntry,
+				byteOffset : indices.description.byteOffset,
+				count : indices.description.count,
+				id : indices.entryID,
+				type : indices.description.type
+			};
+
+						var indicesContext = new IndicesContext( indicesObject, geometry );
+						var alreadyProcessedIndices = THREE.GLTFLoaderUtils.getBuffer( indicesObject, indicesDelegate, indicesContext );
+						/*if(alreadyProcessedIndices) {
+						                            indicesDelegate.resourceAvailable(alreadyProcessedIndices, indicesContext);
+						                        }*/
+						
+						// Load Vertex Attributes
+						var allAttributes = Object.keys( primitiveDescription.attributes );
+						allAttributes.forEach( function( semantic ) {
+
+							geometry.totalAttributes ++;
+
+							var attribute;
+							var attributeID = primitiveDescription.attributes[ semantic ];
+							var attributeEntry = this.resources.getEntry( attributeID );
+							if ( ! attributeEntry ) {
+
+								//let's just use an anonymous object for the attribute
+								attribute = description.attributes[ attributeID ];
+								attribute.id = attributeID;
+								this.resources.setEntry( attributeID, attribute, attribute );
+
+								var bufferEntry = this.resources.getEntry( attribute.bufferView );
+								attributeEntry = this.resources.getEntry( attributeID );
+
+							} else {
+
+								attribute = attributeEntry.object;
+								attribute.id = attributeID;
+								var bufferEntry = this.resources.getEntry( attribute.bufferView );
+
+							}
+
+							var attributeObject = {
+					bufferView : bufferEntry,
+					byteOffset : attribute.byteOffset,
+					byteStride : attribute.byteStride,
+					count : attribute.count,
+					max : attribute.max,
+					min : attribute.min,
+					type : attribute.type,
+					id : attributeID
+				};
+
+							var attribContext = new VertexAttributeContext( attributeObject, semantic, geometry );
+
+							var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer( attributeObject, vertexAttributeDelegate, attribContext );
+							/*if(alreadyProcessedAttribute) {
+							                                vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
+							                            }*/
+							
+						}, this );
+
+					}
+
+				}
+				return true;
+
+			}
+		},
+
+		handleCamera: {
+			value: function( entryID, description, userInfo ) {
+
+				var camera;
+				if ( description.type == "perspective" ) {
+
+					var znear = description.perspective.znear;
+					var zfar = description.perspective.zfar;
+					var yfov = description.perspective.yfov;
+					var xfov = description.perspective.xfov;
+					var aspect_ratio = description.perspective.aspect_ratio;
+
+					if ( ! aspect_ratio ) {
+						
+						aspect_ratio = 1;
+						
+					}
+
+					if ( yfov === undefined ) {
+
+						if ( xfov )	{
+
+							// According to COLLADA spec...
+							// aspect_ratio = xfov / yfov
+							yfov = xfov / aspect_ratio;
+
+						}
+
+					}
+
+					if ( yfov )	{
+
+						camera = new THREE.PerspectiveCamera( yfov, aspect_ratio, znear, zfar );
+
+					}
+
+				} else {
+
+					camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, znear, zfar );
+					
+				}
+
+				if ( camera ) {
+
+					this.resources.setEntry( entryID, camera, description );
+
+				}
+
+				return true;
+
+			}
+		},
+
+		handleLight: {
+			value: function( entryID, description, userInfo ) {
+
+				var light = null;
+				var type = description.type;
+				if ( type && description[ type ] ) {
+
+					var lparams = description[ type ];
+					var color = RgbArraytoHex( lparams.color );
+
+					switch ( type ) {
+						case "directional" :
+							light = new THREE.DirectionalLight( color );
+							light.position.set( 0, 0, 1 );
+							break;
+
+						case "point" :
+							light = new THREE.PointLight( color );
+							break;
+
+						case "spot " :
+							light = new THREE.SpotLight( color );
+							light.position.set( 0, 0, 1 );
+							break;
+
+						case "ambient" :
+							light = new THREE.AmbientLight( color );
+							break;
+					}
+
+				}
+
+				if ( light ) {
+
+					this.resources.setEntry( entryID, light, description );
+
+				}
+
+				return true;
+
+			}
+		},
+
+		addPendingMesh: {
+			value: function( mesh, threeNode ) {
+
+				theLoader.pendingMeshes.push( {
+					
+					mesh: mesh,
+					node: threeNode
+					
+				} );
+
+			}
+		},
+
+		handleNode: {
+			value: function( entryID, description, userInfo ) {
+
+				var threeNode = null;
+				if ( description.jointId ) {
+
+					threeNode = new THREE.Bone();
+					threeNode.jointId = description.jointId;
+					this.joints[ description.jointId ] = entryID;
+
+				}
+				else {
+
+					threeNode = new THREE.Object3D();
+
+				}
+
+				threeNode.name = description.name;
+
+				this.resources.setEntry( entryID, threeNode, description );
+
+				var m = description.matrix;
+				if ( m ) {
+
+					threeNode.applyMatrix( new THREE.Matrix4().fromArray( m ) );
+					threeNode.matrixAutoUpdate = false;
+					threeNode.matrixWorldNeedsUpdate = true;
+
+				} else {
+
+					var t = description.translation;
+					var r = description.rotation;
+					var s = description.scale;
+
+					var position = t ? new THREE.Vector3( t[ 0 ], t[ 1 ], t[ 2 ] ) : new THREE.Vector3;
+					
+					if ( r ) {
+
+						convertAxisAngleToQuaternion( r, 1 );
+
+					}
+					
+					var rotation = r ? new THREE.Quaternion( r[ 0 ], r[ 1 ], r[ 2 ], r[ 3 ] ) : new THREE.Quaternion;
+					var scale = s ? new THREE.Vector3( s[ 0 ], s[ 1 ], s[ 2 ] ) : new THREE.Vector3;
+
+					var matrix = new THREE.Matrix4;
+					matrix.compose( position, rotation, scale );
+					threeNode.matrixAutoUpdate = false;
+					threeNode.matrixWorldNeedsUpdate = true;
+					threeNode.applyMatrix( matrix );
+
+				}
+
+				var self = this;
+
+				// Iterate through all node meshes and attach the appropriate objects
+				//FIXME: decision needs to be made between these 2 ways, probably meshes will be discarded.
+				var meshEntry;
+				if ( description.mesh ) {
+
+					meshEntry = this.resources.getEntry( description.mesh );
+					theLoader.meshesRequested ++;
+					meshEntry.object.onComplete( function( mesh ) {
+
+						self.addPendingMesh( mesh, threeNode );
+						theLoader.meshesLoaded ++;
+						theLoader.checkComplete();
+
+					} );
+
+				}
+
+				if ( description.meshes ) {
+
+					description.meshes.forEach( function( meshID ) {
+
+						meshEntry = this.resources.getEntry( meshID );
+						theLoader.meshesRequested ++;
+						meshEntry.object.onComplete( function( mesh ) {
+
+							self.addPendingMesh( mesh, threeNode );
+							theLoader.meshesLoaded ++;
+							theLoader.checkComplete();
+
+						} );
+
+					}, this );
+
+				}
+
+				if ( description.instanceSkin ) {
+
+					var skinEntry =  this.resources.getEntry( description.instanceSkin.skin );
+
+					if ( skinEntry ) {
+
+						var skin = skinEntry.object;
+						description.instanceSkin.skin = skin;
+						threeNode.instanceSkin = description.instanceSkin;
+
+						var sources = description.instanceSkin.sources;
+						skin.meshes = [];
+						sources.forEach( function( meshID ) {
+
+							meshEntry = this.resources.getEntry( meshID );
+							theLoader.meshesRequested ++;
+							meshEntry.object.onComplete( function( mesh ) {
+
+								skin.meshes.push( mesh );
+								theLoader.meshesLoaded ++;
+								theLoader.checkComplete();
+
+							} );
+
+						}, this );
+
+					}
+
+				}
+
+				if ( description.camera ) {
+
+					var cameraEntry = this.resources.getEntry( description.camera );
+					if ( cameraEntry ) {
+
+						threeNode.add( cameraEntry.object );
+						this.cameras.push( cameraEntry.object );
+
+					}
+
+				}
+
+				if ( description.light ) {
+
+					var lightEntry = this.resources.getEntry( description.light );
+					if ( lightEntry ) {
+
+						threeNode.add( lightEntry.object );
+						this.lights.push( lightEntry.object );
+
+					}
+
+				}
+
+				return true;
+
+			}
+		},
+
+		buildNodeHirerachy: {
+			value: function( nodeEntryId, parentThreeNode ) {
+
+				var nodeEntry = this.resources.getEntry( nodeEntryId );
+				var threeNode = nodeEntry.object;
+				parentThreeNode.add( threeNode );
+
+				var children = nodeEntry.description.children;
+				if ( children ) {
+
+					children.forEach( function( childID ) {
+
+						this.buildNodeHirerachy( childID, threeNode );
+
+					}, this );
+
+				}
+
+				return threeNode;
+
+			}
+		},
+
+		buildSkin: {
+			value: function( node ) {
+
+				var skin = node.instanceSkin.skin;
+				if ( skin ) {
+
+					node.instanceSkin.skeletons.forEach( function( skeleton ) {
+
+						var nodeEntry = this.resources.getEntry( skeleton );
+						if ( nodeEntry ) {
+
+							var rootSkeleton = nodeEntry.object;
+
+							var dobones = true;
+
+							var i, len = skin.meshes.length;
+							for ( i = 0; i < len; i ++ ) {
+
+								var mesh = skin.meshes[ i ];
+								var threeMesh = null;
+								mesh.primitives.forEach( function( primitive ) {
+
+									var material = primitive.material;
+									if ( ! ( material instanceof THREE.Material ) ) {
+
+										material = this.createShaderMaterial( material );
+
+									}
+
+									threeMesh = new THREE.SkinnedMesh( primitive.geometry.geometry, material, false );
+									threeMesh.add( rootSkeleton );
+
+									var geometry = primitive.geometry.geometry;
+									var j;
+									if ( geometry.vertices ) {
+
+										for ( j = 0; j < geometry.vertices.length; j ++ ) {
+
+											geometry.vertices[ j ].applyMatrix4( skin.bindShapeMatrix );
+
+										}
+
+									} else if ( geometry.attributes.position ) {
+
+										var a = geometry.attributes.position.array;
+										var v = new THREE.Vector3;
+										for ( j = 0; j < a.length / 3; j ++ ) {
+
+											v.set( a[ j * 3 ], a[ j * 3 + 1 ], a[ j * 3 + 2 ] );
+											v.applyMatrix4( skin.bindShapeMatrix );
+											a[ j * 3 ] = v.x;
+											a[ j * 3 + 1 ] = v.y;
+											a[ j * 3 + 2 ] = v.z;
+
+										}
+
+									}
+
+									if ( threeMesh && dobones ) {
+
+										material.skinning = true;
+
+										threeMesh.boneInverses = [];
+										var jointsIds = skin.jointsIds;
+										var bones = [];
+										var boneInverses = [];
+										var i, len = jointsIds.length;
+										for ( i = 0; i < len; i ++ ) {
+
+											var jointId = jointsIds[ i ];
+											var nodeForJoint = this.joints[ jointId ];
+											var joint = this.resources.getEntry( nodeForJoint ).object;
+											if ( joint ) {
+
+												joint.skin = threeMesh;
+												bones.push( joint );
+
+												var m = skin.inverseBindMatrices;
+												var mat = new THREE.Matrix4().set(
+													m[ i * 16 + 0 ],  m[ i * 16 + 4 ],  m[ i * 16 + 8 ],  m[ i * 16 + 12 ],
+													m[ i * 16 + 1 ],  m[ i * 16 + 5 ],  m[ i * 16 + 9 ],  m[ i * 16 + 13 ],
+													m[ i * 16 + 2 ],  m[ i * 16 + 6 ],  m[ i * 16 + 10 ], m[ i * 16 + 14 ],
+													m[ i * 16 + 3 ],  m[ i * 16 + 7 ],  m[ i * 16 + 11 ], m[ i * 16 + 15 ]
+												);
+												boneInverses.push( mat );
+
+											} else {
+
+												console.log( "WARNING: jointId:" + jointId + " cannot be found in skeleton:" + skeleton );
+
+											}
+
+										}
+										
+										threeMesh.bind( new THREE.Skeleton( bones, boneInverses, false ), threeMesh.matrixWorld );
+
+									}
+
+									if ( threeMesh ) {
+
+										threeMesh.castShadow = true;
+										node.add( threeMesh );
+
+									}
+
+								}, this );
+
+							}
+
+						}
+
+
+					}, this );
+
+				}
+
+			}
+		},
+
+		buildSkins: {
+			value: function( node ) {
+
+				if ( node.instanceSkin ) {
+					this.buildSkin( node );
+				}
+
+				var children = node.children;
+				
+				if ( children ) {
+
+					children.forEach( function( child ) {
+
+						this.buildSkins( child );
+
+					}, this );
+
+				}
+
+			}
+		},
+
+		createMeshAnimations : {
+			value : function( root ) {
+
+				this.buildSkins( root );
+
+			}
+		},
+
+		handleScene: {
+			value: function( entryID, description, userInfo ) {
+
+				if ( ! description.nodes ) {
+
+					console.log( "ERROR: invalid file required nodes property is missing from scene" );
+					return false;
+
+				}
+
+				description.nodes.forEach( function( nodeUID ) {
+
+					this.buildNodeHirerachy( nodeUID, userInfo.rootObj );
+
+				}, this );
+
+				if ( this.delegate ) {
+
+					this.delegate.loadCompleted( userInfo.callback, userInfo.rootObj );
+
+				}
+
+				return true;
+
+			}
+		},
+
+		handleImage: {
+			value: function( entryID, description, userInfo ) {
+
+				this.resources.setEntry( entryID, null, description );
+				return true;
+
+			}
+		},
+
+		addNodeAnimationChannel : {
+			value : function( name, channel, interp ) {
+
+				if ( ! this.nodeAnimationChannels ) {
+					
+					this.nodeAnimationChannels = {};
+					
+				}
+
+				if ( ! this.nodeAnimationChannels[ name ] ) {
+
+					this.nodeAnimationChannels[ name ] = [];
+
+				}
+
+				this.nodeAnimationChannels[ name ].push( interp );
+
+			},
+		},
+
+		createAnimations : {
+			value : function() {
+
+				for ( var name in this.nodeAnimationChannels ) {
+
+					var nodeAnimationChannels = this.nodeAnimationChannels[ name ];
+					var i, len = nodeAnimationChannels.length;
+					//console.log(" animation channels for node " + name);
+					//for (i = 0; i < len; i++) {
+					//	console.log(nodeAnimationChannels[i]);
+					//}
+					var anim = new THREE.glTFAnimation( nodeAnimationChannels );
+					anim.name = "animation_" + name;
+					this.animations.push( anim );
+
+				}
+
+			}
+		},
+
+		buildAnimation: {
+			value : function( animation ) {
+
+				var interps = [];
+				var i, len = animation.channels.length;
+				for ( i = 0; i < len; i ++ ) {
+
+					var channel = animation.channels[ i ];
+					var sampler = animation.samplers[ channel.sampler ];
+					if ( sampler ) {
+
+						var input = animation.parameters[ sampler.input ];
+						if ( input && input.data ) {
+
+							var output = animation.parameters[ sampler.output ];
+							if ( output && output.data ) {
+
+								var target = channel.target;
+								var node = this.resources.getEntry( target.id );
+								if ( node ) {
+
+									var path = target.path;
+
+									if ( path == "rotation" ) {
+
+										convertAxisAngleToQuaternion( output.data, output.count );
+
+									}
+
+									var interp = {
+										keys : input.data,
+										values : output.data,
+										count : input.count,
+										target : node.object,
+										path : path,
+										type : sampler.interpolation
+									};
+
+									this.addNodeAnimationChannel( target.id, channel, interp );
+									interps.push( interp );
+
+								}
+
+							}
+
+						}
+
+					}
+
+				}
+
+			}
+		},
+
+		handleAnimation: {
+			value: function( entryID, description, userInfo ) {
+
+				var self = this;
+				theLoader.animationsRequested ++;
+				var animation = new Animation();
+				animation.name = entryID;
+				animation.onload = function() {
+
+					// self.buildAnimation(animation);
+					theLoader.animationsLoaded ++;
+					theLoader.animations.push( animation );
+					theLoader.checkComplete();
+
+				};
+
+				animation.channels = description.channels;
+				animation.samplers = description.samplers;
+				this.resources.setEntry( entryID, animation, description );
+				var parameters = description.parameters;
+				if ( ! parameters ) {
+
+					//FIXME: not implemented in delegate
+					console.log( "MISSING_PARAMETERS for animation:" + entryID );
+					return false;
+
+				}
+
+				// Load parameter buffers
+				var params = Object.keys( parameters );
+				params.forEach( function( param ) {
+
+					animation.totalParameters ++;
+					var parameter = parameters[ param ];
+					var accessor = this.resources.getEntry( parameter );
+					
+					if ( ! accessor ) {
+						debugger;
+					}
+					
+					accessor = accessor.object;
+					var bufferView = this.resources.getEntry( accessor.bufferView );
+					var paramObject = {
+						bufferView : bufferView,
+						byteOffset : accessor.byteOffset,
+						count : accessor.count,
+						type : accessor.type,
+						id : accessor.bufferView,
+						name : param
+					};
+
+					var paramContext = new AnimationParameterContext( paramObject, animation );
+
+					var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer( paramObject, animationParameterDelegate, paramContext );
+					/*if ( alreadyProcessedAttribute ) {
+	                        vertexAttributeDelegate.resourceAvailable(alreadyProcessedAttribute, attribContext);
                     }*/
-	}, this);
-
-	            return true;
-            }
-        },
-
-        handleAccessor: {
-            value: function(entryID, description, userInfo) {
-	    		// Save attribute entry
-	    		this.resources.setEntry(entryID, description, description);
-	return true;
-            }
-        },
-
-        handleSkin: {
-            value: function(entryID, description, userInfo) {
-	    		// Save skin entry
-
-	var skin = {
-        		};
-
-	var m = description.bindShapeMatrix;
-	            skin.bindShapeMatrix = new THREE.Matrix4().fromArray( m );
-
-	            skin.jointsIds = description.joints;
-	            var inverseBindMatricesDescription = description.inverseBindMatrices;
-	            skin.inverseBindMatricesDescription = inverseBindMatricesDescription;
-	            skin.inverseBindMatricesDescription.id = entryID + "_inverseBindMatrices";
-
-	var bufferEntry = this.resources.getEntry(inverseBindMatricesDescription.bufferView);
-
-	var paramObject = {
-                		bufferView : bufferEntry,
-                		byteOffset : inverseBindMatricesDescription.byteOffset,
-                		count : inverseBindMatricesDescription.count,
-                		type : inverseBindMatricesDescription.type,
-                		id : inverseBindMatricesDescription.bufferView,
-                		name : skin.inverseBindMatricesDescription.id
-                };
-
-	            var context = new InverseBindMatricesContext(paramObject, skin);
-
-	var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer(paramObject, inverseBindMatricesDelegate, context);
-
-	            var bufferView = this.resources.getEntry(skin.inverseBindMatricesDescription.bufferView);
-	            skin.inverseBindMatricesDescription.bufferView =
-	            	bufferView.object;
-	    		this.resources.setEntry(entryID, skin, description);
-	return true;
-            }
-        },
-
-        handleSampler: {
-            value: function(entryID, description, userInfo) {
-	    		// Save attribute entry
-	    		this.resources.setEntry(entryID, description, description);
-	return true;
-            }
-        },
-
-        handleTexture: {
-            value: function(entryID, description, userInfo) {
-	    		// Save attribute entry
-	    		this.resources.setEntry(entryID, null, description);
-	return true;
-            }
-        },
-
-        handleError: {
-            value: function(msg) {
-
-	throw new Error(msg);
-	return true;
-        	}
-        },
-
-        _delegate: {
-            value: new LoadDelegate,
-            writable: true
-        },
-
-        delegate: {
-            enumerable: true,
-            get: function() {
-	return this._delegate;
-            },
-            set: function(value) {
-	this._delegate = value;
-            }
-        }
-    });
-
-
-    // Loader
-
-	var Context = function(rootObj, callback) {
+					
+				}, this );
+
+				return true;
+
+			}
+		},
+
+		handleAccessor: {
+			
+			value: function( entryID, description, userInfo ) {
+
+				// Save attribute entry
+				this.resources.setEntry( entryID, description, description );
+				return true;
+
+			}
+		},
+
+		handleSkin: {
+			
+			value: function( entryID, description, userInfo ) {
+
+				// Save skin entry
+
+				var skin = {};
+
+				var m = description.bindShapeMatrix;
+				skin.bindShapeMatrix = new THREE.Matrix4().fromArray( m );
+
+				skin.jointsIds = description.joints;
+				var inverseBindMatricesDescription = description.inverseBindMatrices;
+				skin.inverseBindMatricesDescription = inverseBindMatricesDescription;
+				skin.inverseBindMatricesDescription.id = entryID + "_inverseBindMatrices";
+
+				var bufferEntry = this.resources.getEntry( inverseBindMatricesDescription.bufferView );
+
+				var paramObject = {
+					
+					bufferView : bufferEntry,
+					byteOffset : inverseBindMatricesDescription.byteOffset,
+					count : inverseBindMatricesDescription.count,
+					type : inverseBindMatricesDescription.type,
+					id : inverseBindMatricesDescription.bufferView,
+					name : skin.inverseBindMatricesDescription.id
+					
+				};
+
+				var context = new InverseBindMatricesContext( paramObject, skin );
+
+				var alreadyProcessedAttribute = THREE.GLTFLoaderUtils.getBuffer( paramObject, inverseBindMatricesDelegate, context );
+
+				var bufferView = this.resources.getEntry( skin.inverseBindMatricesDescription.bufferView );
+				skin.inverseBindMatricesDescription.bufferView =
+				bufferView.object;
+				this.resources.setEntry( entryID, skin, description );
+				return true;
+
+			}
+		},
+
+		handleSampler: {
+			value: function( entryID, description, userInfo ) {
+
+				// Save attribute entry
+				this.resources.setEntry( entryID, description, description );
+				return true;
+
+			}
+		},
+
+		handleTexture: {
+			value: function( entryID, description, userInfo ) {
+
+				// Save attribute entry
+				this.resources.setEntry( entryID, null, description );
+				return true;
+
+			}
+		},
+
+		handleError: {
+			value: function( msg ) {
+
+				throw new Error( msg );
+				return true;
+
+			}
+		},
+
+		_delegate: {
+			value: new LoadDelegate,
+			writable: true
+		},
+
+		delegate: {
+			enumerable: true,
+			get: function() {
+
+				return this._delegate;
+
+			},
+			set: function( value ) {
+
+				this._delegate = value;
+
+			}
+		}
+	} );
+
+
+	// Loader
+
+	var Context = function( rootObj, callback ) {
+
 		this.rootObj = rootObj;
 		this.callback = callback;
+
 	};
 
 	var rootObj = new THREE.Object3D();
 
 	var self = this;
 
-	var loader = Object.create(ThreeGLTFLoader);
-	loader.initWithPath(url);
-	loader.load(new Context(rootObj,
-    					function(obj) {
-    					}),
-    			null);
+	var loader = Object.create( ThreeGLTFLoader );
+	loader.initWithPath( url );
+	loader.load( new Context( rootObj, function( obj ) {} ), null );
 
 	this.loader = loader;
 	this.callback = callback;
 	this.rootObj = rootObj;
 	return rootObj;
+
 };
 
 THREE.glTFLoader.prototype.callLoadedCallback = function() {
+
 	var result = {
-			scene : this.rootObj,
-			cameras : this.loader.cameras,
-			animations : this.loader.animations,
+		scene : this.rootObj,
+		cameras : this.loader.cameras,
+		animations : this.loader.animations,
 	};
 
-	this.callback(result);
+	this.callback( result );
+
 };
 
 THREE.glTFLoader.prototype.checkComplete = function() {
-	if (this.meshesLoaded == this.meshesRequested
+
+	if ( this.meshesLoaded == this.meshesRequested
 			&& this.shadersLoaded == this.shadersRequested
-			&& this.animationsLoaded == this.animationsRequested)
+			&& this.animationsLoaded == this.animationsRequested )
 	{
 
-		for (var i = 0; i < this.pendingMeshes.length; i ++) {
-			var pending = this.pendingMeshes[i];
-			pending.mesh.attachToNode(pending.node);
+		for ( var i = 0; i < this.pendingMeshes.length; i ++ ) {
+
+			var pending = this.pendingMeshes[ i ];
+			pending.mesh.attachToNode( pending.node );
+
 		}
 
-		for (var i = 0; i < this.animationsLoaded; i ++) {
-			var animation = this.animations[i];
-			this.loader.buildAnimation(animation);
+		for ( var i = 0; i < this.animationsLoaded; i ++ ) {
+
+			var animation = this.animations[ i ];
+			this.loader.buildAnimation( animation );
+
 		}
 
 		this.loader.createAnimations();
-		this.loader.createMeshAnimations(this.rootObj);
+		this.loader.createMeshAnimations( this.rootObj );
 
 		this.callLoadedCallback();
+
 	}
+
 };