Browse Source

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

hena-3 10 years ago
parent
commit
73524eabfe

File diff suppressed because it is too large
+ 260 - 84
build/three.js


File diff suppressed because it is too large
+ 77 - 71
build/three.min.js


+ 20 - 2
docs/api/core/Geometry.html

@@ -102,12 +102,30 @@
 
 
 		<h3>[property:Array skinWeights]</h3>
 		<h3>[property:Array skinWeights]</h3>
 		<div>
 		<div>
-		Array of skinning weights, matching number and order of vertices.
+		Array of [page:Vector4 Vector4s] representing the skinning weights as used in a [page:SkinnedMesh],
+		The weights match the number and order of vertices in the geometry. The weighted values
+		are typically between the values of 0 and 1 and affect the amount that the individuals bones affect
+		a given vertex.
 		</div>
 		</div>
 
 
 		<h3>[property:Array skinIndices]</h3>
 		<h3>[property:Array skinIndices]</h3>
 		<div>
 		<div>
-		Array of skinning indices, matching number and order of vertices.
+		Array of [page:Vector4 Vector4s] representing the indices of individual bones in the [page:Skeleton.bones] array,
+		The indices match the number and order of vertices in the geometry.
+		<code>
+		// e.g.
+		geometry.skinIndices[15] = new THREE.Vector4(   0,   5,   9, 0 );
+		geometry.skinWeights[15] = new THREE.Vector4( 0.2, 0.5, 0.3, 0 );
+		
+		// corresponds with the following vertex
+		geometry.vertices[15];
+		
+		// these bones will be used like so:
+		skeleton.bones[0]; // weight of 0.2
+		skeleton.bones[5]; // weight of 0.5
+		skeleton.bones[9]; // weight of 0.3
+		skeleton.bones[0]; // weight of 0
+		</code>
 		</div>
 		</div>
 
 
 		<h3>[property:Object boundingBox]</h3>
 		<h3>[property:Object boundingBox]</h3>

+ 17 - 8
docs/api/objects/Bone.html

@@ -11,25 +11,34 @@
 
 
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
-		<div class="desc">A bone which is part of a [page:SkinnedMesh].</div>
-
+		<div class="desc">
+		A bone which is part of a [page:Skeleton]. The skeleton in turn is used by the [page:SkinnedMesh].
+		Bones are almost identical to a blank [page:Object3D].
+		</div>
+		
+		<h3>Example</h3>
+		
+		<code>
+		var root = new THREE.Bone();
+		var child = new THREE.Bone();
+		
+		root.add( child );
+		child.position.y = 5;
+		</code>
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:SkinnedMesh belongsToSkin])</h3>
-		<div>
-		belongsToSkin -- An instance of [page:SkinnedMesh].
-		</div>
+		<h3>[name]([page:SkinnedMesh skin])</h3>
 		<div>
 		<div>
-		This creates a new instance of a bone from the skin.
+		skin — (optional) The [page:SkinnedMesh] to which the bone belongs.
 		</div>
 		</div>
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
 
 
 		<h3>[property:SkinnedMesh skin]</h3>
 		<h3>[property:SkinnedMesh skin]</h3>
 		<div>
 		<div>
-		The skin that contains this bone.
+		An optional reference to the [page:SkinnedMesh].
 		</div>
 		</div>
 
 
 
 

+ 128 - 0
docs/api/objects/Skeleton.html

@@ -0,0 +1,128 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<script src="../../list.js"></script>
+		<script src="../../page.js"></script>
+		<link type="text/css" rel="stylesheet" href="../../page.css" />
+	</head>
+	<body>
+		
+		<h1>[name]</h1>
+
+		<div class="desc">
+		Use an array of [page:Bone bones] to create a skeleton that can be used by a [page:SkinnedMesh].
+		WebGL only.
+		</div>
+
+		<h2>Example</h2>
+
+		<code>
+		// Create a simple "arm"
+		
+		var bones = [];
+		
+		var shoulder = new THREE.Bone();
+		var elbow = new THREE.Bone();
+		var hand = new THREE.Bone();
+		
+		shoulder.add( elbow );
+		elbow.add( hand );
+
+		bones.push( shoulder );
+		bones.push( elbow );
+		bones.push( hand );
+		
+		shoulder.position.y = -5;
+		elbow.position.y = 0;
+		hand.position.y = 5;
+		
+		var armSkeleton = THREE.Skeleton( bones );
+		
+		// See THREE.SkinnedMesh for an example of usage with a mesh
+		</code>
+
+		<h2>Constructor</h2>
+
+
+		<h3>[name]( [page:Array bones], [page:Array boneInverses], [page:Boolean useVertexTexture]  )</h3>
+		<div>
+		bones — The array of [page:bone bones]<br/>
+		boneInverses — (optional) An array of [page:Matrix4 Matrix4s]<br/>
+		useVertexTexture — (optional) Whether or not to use a vertex texture in the shader.
+		</div>
+		<div>
+		The constructor automatically sets up all of the properties below.
+		</div>
+
+
+		<h2>Properties</h2>
+		
+		<h3>[property:Array bones]</h3>
+		<div>
+		The array of [page:bone bones]
+		</div>
+		
+		
+		<h3>[property:Boolean useVertexTexture]</h3>
+		<div>
+		Whether or not to use a vertex texture in the shader, set in the constructor. Not all devices
+		support floating point pixel textures. If this option is set then the bone matrices will be packed into
+		a texture and sent to the shader. This method allows a much larger set of bones to be used. Otherwise
+		the vertex shader will use uniforms, which do not allow for as many bones to be used. The exact
+		numbers vary between devices.
+		</div>
+		
+		
+		<h3>[property:Array boneInverses]</h3>
+		<div>
+		An array of [page:Matrix4 Matrix4s] that represent the inverse of the matrixWorld of the individual bones.
+		</div>
+		
+		
+		<h3>[property:Integer boneTextureWidth]</h3>
+		<div>
+		The width of the vertex data texture.
+		</div>
+		
+		
+		<h3>[property:Integer boneTextureHeight]</h3>
+		<div>
+		The height of the vertex data texture.
+		</div>
+		
+		
+		<h3>[property:Float32Array boneMatrices]</h3>
+		<div>
+		The array buffer holding the bone data when using a vertex texture.
+		</div>
+		
+		
+		<h3>[property:DataTexture boneTexture]</h3>
+		<div>
+		The [page:DataTexture] holding the bone data when using a vertex texture.
+		</div>
+		
+
+		<h2>Methods</h2>
+
+		<h3>[method:null calculateInverses]()</h3>
+		<div>Generates the boneInverses.</div>
+		
+		
+		<h3>[method:null pose]()</h3>
+		<div>Returns the skeleton to the base pose.</div>
+		
+		
+		<h3>[method:null update]()</h3>
+		<div>
+		Updates the [page:Float32Array boneMatrices] and [page:DataTexture boneTexture] after changing the bones.
+		This is called automatically by the [page:WebGLRenderer] if the skeleton is used with a [page:SkinnedMesh].
+		</div>
+		
+		
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 76 - 12
docs/api/objects/SkinnedMesh.html

@@ -11,27 +11,60 @@
 
 
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
-		<div class="desc">An 3d object that has bones data. These Bones can then be used to animate the vertices of the object.</div>
-
+		<div class="desc">A mesh that has a [page:Skeleton] with [page:Bone bones] that can then be used to animate the vertices of the geometry.</div>
+
+		<h2>Example</h2>
+		
+		<iframe src='../../scenes/bones-browser.html'></iframe>
+		
+		<code>
+		var geometry = new THREE.CylinderGeometry( 5, 5, 5, 5, 15, 5, 30 );
+		
+		//Create the skin indices and skin weights
+		for ( var i = 0; i < geometry.vertices.length; i ++ ) {
+			
+			// Imaginary functions to calculate the indices and weights
+			var skinIndex = calculateSkinIndex( geometry.vertices, i );
+			var skinWeight = calculateSkinWeight( geometry.vertices, i );
+			
+			// Ease between each bone
+			geometry.skinIndices.push( new THREE.Vector4( skinIndex, skinIndex + 1, 0, 0 ) );
+			geometry.skinWeights.push( new THREE.Vector4( 1 - skinWeight, skinWeight, 0, 0 ) );		
+			
+		}
+		
+		var mesh = THREE.SkinnedMesh( geometry, material );
+
+		// See example from THREE.Skeleton for the armSkeleton
+		var rootBone = armSkeleton.bones[ 0 ];
+		mesh.add( rootBone );
+		
+		// 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;
+		</code>
+		
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
 		<h3>[name]([page:Geometry geometry], [page:Material material], [page:boolean useVertexTexture])</h3>
 		<h3>[name]([page:Geometry geometry], [page:Material material], [page:boolean useVertexTexture])</h3>
 		<div>
 		<div>
-                geometry — An instance of [page:Geometry].<br />
-                material — An instance of [page:Material] (optional).<br />
-		useVertexTexture -- Defines wether a vertex texture can be used (optional).
-		</div>
-		<div>
-		This Creates a new instance of skinnedMesh.
+        geometry — An instance of [page:Geometry]. [page:Geometry.skinIndices] and [page:Geometry.skinWeights] should be set.<br />
+        material — An instance of [page:Material] (optional).<br />
+		useVertexTexture -- Defines whether a vertex texture can be used (optional).
 		</div>
 		</div>
 
 
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
 
 
 
 
-
 		<h3>[property:array bones]</h3>
 		<h3>[property:array bones]</h3>
 		<div>
 		<div>
 		This contains the array of bones for this mesh. These should be set in the constructor.
 		This contains the array of bones for this mesh. These should be set in the constructor.
@@ -52,19 +85,50 @@
 		This array of matrices contains the matrices of the bones. These get calculated in the constructor.
 		This array of matrices contains the matrices of the bones. These get calculated in the constructor.
 		</div>
 		</div>
 
 
+		<h3>[property:string bindMode]</h3>
+		<div>
+		Either "attached" or "detached". "attached" uses the [page:SkinnedMesh.matrixWorld] property for the base transform
+		matrix of the bones. "detached" uses the [page:SkinnedMesh.bindMatrix].
+		</div>
+		
+		<h3>[property:Matrix4 bindMatrix]</h3>
+		<div>
+		The base matrix that is used for the bound bone transforms.
+		</div>
+
+		<h3>[property:Matrix4 inverseBindMatrix]</h3>
+		<div>
+		The inverse of the bindMatrix.
+		</div>
+
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
+		<h3>[method:null bind]([page:Skeleton skeleton], [page:Matrix4 bindMatrix])</h3>
+		<div>
+		skeleton — [page:Skeleton]<br/>
+		bindMatrix — [page:Matrix4] that represents the base transform of the skeleton
+		</div>
+		<div>
+		Bind a skeleton to the skinned mesh. The bindMatrix gets saved to .bindMatrix property and the .bindMatrixInverse
+		gets calculated.
+		</div>
+		
+		<h3>[method:null normalizeSkinWeights]()</h3>
+		<div>
+		Normalizes the [page:Geometry.skinWeights] vectors. Does not affect [page:BufferGeometry].
+		</div>
+
 		<h3>[method:null pose]()</h3>
 		<h3>[method:null pose]()</h3>
 		<div>
 		<div>
-		This method sets the skinnedmesh in the rest pose.
+		This method sets the skinned mesh in the rest pose.
 		</div>
 		</div>
 
 
 		<h3>[method:Bone addBone]([page:Bone bone])</h3>
 		<h3>[method:Bone addBone]([page:Bone bone])</h3>
 		<div>
 		<div>
-		bone -- This is the bone that needs to be added. (optional)
+		bone  This is the bone that needs to be added. (optional)
 		</div>
 		</div>
 		<div>
 		<div>
-		This method adds the bone to the skinnedmesh when it is provided. It creates a new bone and adds that when no bone is given.
+		This method adds the bone to the skinned mesh when it is provided. It creates a new bone and adds that when no bone is given.
 		</div>
 		</div>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

+ 1 - 0
docs/list.js

@@ -116,6 +116,7 @@ var list = {
 			[ "MorphAnimMesh", "api/objects/MorphAnimMesh" ],
 			[ "MorphAnimMesh", "api/objects/MorphAnimMesh" ],
 			[ "PointCloud", "api/objects/PointCloud" ],
 			[ "PointCloud", "api/objects/PointCloud" ],
 			[ "SkinnedMesh", "api/objects/SkinnedMesh" ],
 			[ "SkinnedMesh", "api/objects/SkinnedMesh" ],
+			[ "Skeleton", "api/objects/Skeleton" ],
 			[ "Sprite", "api/objects/Sprite" ]
 			[ "Sprite", "api/objects/Sprite" ]
 		],
 		],
 
 

+ 2 - 0
docs/manual/introduction/Creating-a-scene.html

@@ -21,8 +21,10 @@
 		<div>Before you can use Three.js, you need somewhere to display it. Save the following HTML to a file on your computer, along with a copy of <a href="http://threejs.org/build/three.min.js">three.min.js</a> in the js/ directory, and open it in your browser.</div>
 		<div>Before you can use Three.js, you need somewhere to display it. Save the following HTML to a file on your computer, along with a copy of <a href="http://threejs.org/build/three.min.js">three.min.js</a> in the js/ directory, and open it in your browser.</div>
 
 
 		<code>
 		<code>
+		&lt;!DOCTYPE html&gt;
 		&lt;html&gt;
 		&lt;html&gt;
 			&lt;head&gt;
 			&lt;head&gt;
+				&lt;meta charset=utf-8&gt;
 				&lt;title&gt;My first Three.js app&lt;/title&gt;
 				&lt;title&gt;My first Three.js app&lt;/title&gt;
 				&lt;style&gt;
 				&lt;style&gt;
 					body { margin: 0; }
 					body { margin: 0; }

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

@@ -0,0 +1,272 @@
+<!doctype html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8">
+		<title>Three.js Bones Browser</title>
+		<style>
+			@font-face {
+				font-family: 'inconsolata';
+				src: url('../files/inconsolata.woff') format('woff');
+				font-weight: normal;
+				font-style: normal;
+			}
+			
+			body {
+				margin:0;
+				font-family: 'inconsolata';
+				font-size: 15px;
+				line-height: 18px;
+				overflow: hidden;
+			}
+			
+			canvas { width: 100%; height: 100% }
+			
+			#newWindow {
+				display: block;
+				position: absolute;
+				bottom: 0.3em;
+				left: 0.5em;
+				color: #fff;
+			}
+		</style>
+	</head>
+	<body>
+		
+		<a id='newWindow' href='./bones-browser.html' target='_blank'>Open in New Window</a>
+		
+		<script src="../../build/three.min.js"></script>
+		<script src='../../examples/js/libs/dat.gui.min.js'></script>
+		<script src="../../examples/js/controls/OrbitControls.js"></script>
+		
+		<script>
+
+			var gui, scene, camera, renderer, orbit, ambientLight, lights, mesh, bones, skeletonHelper;
+
+			var state = {
+
+				animateBones : false
+
+			};
+
+			function initScene () {
+
+				gui = new dat.GUI();
+				scene = new THREE.Scene();
+				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 200 );
+				camera.position.z = 30;
+				camera.position.y = 30;
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				document.body.appendChild( renderer.domElement );
+
+				orbit = new THREE.OrbitControls( camera, renderer.domElement );
+				orbit.noZoom = true;
+
+				ambientLight = new THREE.AmbientLight( 0x000000 );
+				scene.add( ambientLight );
+
+				lights = [];
+				lights[ 0 ] = new THREE.PointLight( 0xffffff, 1, 0 );
+				lights[ 1 ] = new THREE.PointLight( 0xffffff, 1, 0 );
+				lights[ 2 ] = new THREE.PointLight( 0xffffff, 1, 0 );
+
+				lights[ 0 ].position.set( 0, 200, 0 );
+				lights[ 1 ].position.set( 100, 200, 100 );
+				lights[ 2 ].position.set( -100, -200, -100 );
+
+				scene.add( lights[ 0 ] );
+				scene.add( lights[ 1 ] );
+				scene.add( lights[ 2 ] );
+
+				window.addEventListener( 'resize', function () {
+
+					camera.aspect = window.innerWidth / window.innerHeight;
+					camera.updateProjectionMatrix();
+
+					renderer.setSize( window.innerWidth, window.innerHeight );
+
+				}, false );
+
+				initBones();
+				setupDatGui();
+
+			}
+
+			function createGeometry ( sizing ) {
+
+				var geometry = new THREE.CylinderGeometry(
+					5,                       // radiusTop
+					5,                       // radiusBottom
+					sizing.height,           // height
+					8,                       // radiusSegments
+					sizing.segmentCount * 3, // heightSegments
+					true                     // openEnded
+				);
+
+				for ( var i = 0; i < geometry.vertices.length; i ++ ) {
+
+					var vertex = geometry.vertices[ i ];
+					var y = ( vertex.y + sizing.halfHeight );
+
+					var skinIndex = Math.floor( y / sizing.segmentHeight );
+					var skinWeight = ( y % sizing.segmentHeight ) / sizing.segmentHeight;
+
+					geometry.skinIndices.push( new THREE.Vector4( skinIndex, skinIndex + 1, 0, 0 ) );
+					geometry.skinWeights.push( new THREE.Vector4( 1 - skinWeight, skinWeight, 0, 0 ) );
+
+				}
+
+				return geometry;
+
+			};
+
+			function createBones ( sizing ) {
+
+				bones = [];
+
+				var prevBone = new THREE.Bone();
+				bones.push( prevBone );
+				prevBone.position.y = -sizing.halfHeight;
+
+				for ( var i = 0; i < sizing.segmentCount; i ++ ) {
+
+					var bone = new THREE.Bone();
+					bone.position.y = sizing.segmentHeight;
+					bones.push( bone );
+					prevBone.add( bone );
+					prevBone = bone;
+
+				}
+
+				return bones;
+
+			};
+
+			function createMesh ( geometry, bones ) {
+
+				var material = new THREE.MeshPhongMaterial( {
+					skinning : true,
+					color: 0x156289,
+					emissive: 0x072534,
+					side: THREE.DoubleSide,
+					shading: THREE.FlatShading
+				} );
+
+				var mesh = new THREE.SkinnedMesh( geometry,	material );
+				var skeleton = new THREE.Skeleton( bones );
+	
+				mesh.add( bones[ 0 ] );
+	
+				mesh.bind( skeleton );
+				skeleton.calculateInverses();
+
+				skeletonHelper = new THREE.SkeletonHelper( mesh );
+				skeletonHelper.material.linewidth = 2;
+				scene.add( skeletonHelper );
+
+				return mesh;
+	
+			};
+
+			function setupDatGui () {
+	
+				var folder = gui.addFolder( "General Options" );
+	
+				folder.add( state, "animateBones" );
+				folder.__controllers[ 0 ].name( "Animate Bones" );
+
+				folder.add( mesh, "pose" );
+				folder.__controllers[ 1 ].name( ".pose()" );
+	
+				var bones = mesh.skeleton.bones;
+	
+				for ( var i = 0; i < bones.length; i ++ ) {
+		
+					var bone = bones[ i ];
+		
+					folder = gui.addFolder( "Bone " + i );
+	
+					folder.add( bone.position, 'x', -10 + bone.position.x, 10 + bone.position.x );
+					folder.add( bone.position, 'y', -10 + bone.position.y, 10 + bone.position.y );
+					folder.add( bone.position, 'z', -10 + bone.position.z, 10 + bone.position.z );
+
+					folder.add( bone.rotation, 'x', -Math.PI * 0.5, Math.PI * 0.5 );
+					folder.add( bone.rotation, 'y', -Math.PI * 0.5, Math.PI * 0.5 );
+					folder.add( bone.rotation, 'z', -Math.PI * 0.5, Math.PI * 0.5 );
+		
+					folder.add( bone.scale, 'x', 0, 2 );
+					folder.add( bone.scale, 'y', 0, 2 );
+					folder.add( bone.scale, 'z', 0, 2 );
+
+					folder.__controllers[ 0 ].name( "position.x" );
+					folder.__controllers[ 1 ].name( "position.y" );
+					folder.__controllers[ 2 ].name( "position.z" );
+		
+					folder.__controllers[ 3 ].name( "rotation.x" );
+					folder.__controllers[ 4 ].name( "rotation.y" );
+					folder.__controllers[ 5 ].name( "rotation.z" );
+		
+					folder.__controllers[ 6 ].name( "scale.x" );
+					folder.__controllers[ 7 ].name( "scale.y" );
+					folder.__controllers[ 8 ].name( "scale.z" );
+		
+				}
+				
+			}
+
+			function initBones () {
+	
+				var segmentHeight = 8;
+				var segmentCount = 4;
+				var height = segmentHeight * segmentCount;
+				var halfHeight = height * 0.5;
+
+				var sizing = {
+					segmentHeight : segmentHeight,
+					segmentCount : segmentCount,
+					height : height,
+					halfHeight : halfHeight
+				};
+
+				var geometry = createGeometry( sizing );
+				var bones = createBones( sizing );
+				mesh = createMesh( geometry, bones );
+
+				mesh.scale.multiplyScalar( 1 );
+				scene.add( mesh );
+
+			};
+
+			function render () {
+	
+				requestAnimationFrame( render );
+
+				var time = Date.now() * 0.001;
+	
+				var bone = mesh;
+
+	
+				//Wiggle the bones
+				if ( state.animateBones ) {
+		
+					for ( var i = 0; i < mesh.skeleton.bones.length; i ++ ) {
+		
+						mesh.skeleton.bones[ i ].rotation.z = Math.sin( time ) * 2 / mesh.skeleton.bones.length;
+		
+					}
+		
+				}
+
+				skeletonHelper.update();
+	
+				renderer.render( scene, camera );
+	
+			};
+
+			initScene();
+			render();
+			
+		</script>
+	</body>
+</html>

+ 1 - 14
examples/js/BlendCharacterGui.js

@@ -7,7 +7,6 @@ function BlendCharacterGui(animations) {
 	var controls = {
 	var controls = {
 
 
 		gui: null,
 		gui: null,
-		"Lock Camera": false,
 		"Show Model": true,
 		"Show Model": true,
 		"Show Skeleton": false,
 		"Show Skeleton": false,
 		"Time Scale": 1.0,
 		"Time Scale": 1.0,
@@ -55,7 +54,6 @@ function BlendCharacterGui(animations) {
 		var playback = controls.gui.addFolder( 'Playback' );
 		var playback = controls.gui.addFolder( 'Playback' );
 		var blending = controls.gui.addFolder( 'Blend Tuning' );
 		var blending = controls.gui.addFolder( 'Blend Tuning' );
 
 
-		settings.add( controls, "Lock Camera" ).onChange( controls.lockCameraChanged );
 		settings.add( controls, "Show Model" ).onChange( controls.showModelChanged );
 		settings.add( controls, "Show Model" ).onChange( controls.showModelChanged );
 		settings.add( controls, "Show Skeleton" ).onChange( controls.showSkeletonChanged );
 		settings.add( controls, "Show Skeleton" ).onChange( controls.showSkeletonChanged );
 		settings.add( controls, "Time Scale", 0, 1, 0.01 );
 		settings.add( controls, "Time Scale", 0, 1, 0.01 );
@@ -174,17 +172,6 @@ function BlendCharacterGui(animations) {
 
 
 	};
 	};
 
 
-	controls.lockCameraChanged = function() {
-
-		var data = {
-			detail: {
-				shouldLock: controls['Lock Camera']
-			}
-		};
-
-		window.dispatchEvent( new CustomEvent( 'toggle-lock-camera', data ) );
-	};
-
 	controls.showSkeletonChanged = function() {
 	controls.showSkeletonChanged = function() {
 
 
 		var data = {
 		var data = {
@@ -211,4 +198,4 @@ function BlendCharacterGui(animations) {
 
 
 	init.call(this);
 	init.call(this);
 
 
-}
+}

+ 3 - 3
examples/js/libs/stats.min.js

@@ -1,5 +1,5 @@
 // stats.js - http://github.com/mrdoob/stats.js
 // stats.js - http://github.com/mrdoob/stats.js
 var Stats=function(){function f(a,e,b){a=document.createElement(a);a.id=e;a.style.cssText=b;return a}function l(a,e,b){var c=f("div",a,"padding:0 0 3px 3px;text-align:left;background:"+b),d=f("div",a+"Text","font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px;color:"+e);d.innerHTML=a.toUpperCase();c.appendChild(d);a=f("div",a+"Graph","width:74px;height:30px;background:"+e);c.appendChild(a);for(e=0;74>e;e++)a.appendChild(f("span","","width:1px;height:30px;float:left;opacity:0.9;background:"+
 var Stats=function(){function f(a,e,b){a=document.createElement(a);a.id=e;a.style.cssText=b;return a}function l(a,e,b){var c=f("div",a,"padding:0 0 3px 3px;text-align:left;background:"+b),d=f("div",a+"Text","font-family:Helvetica,Arial,sans-serif;font-size:9px;font-weight:bold;line-height:15px;color:"+e);d.innerHTML=a.toUpperCase();c.appendChild(d);a=f("div",a+"Graph","width:74px;height:30px;background:"+e);c.appendChild(a);for(e=0;74>e;e++)a.appendChild(f("span","","width:1px;height:30px;float:left;opacity:0.9;background:"+
-b));return c}function m(a){for(var b=c.children,d=0;d<b.length;d++)b[d].style.display=d===a?"block":"none";n=a}function p(a,b){a.appendChild(a.firstChild).style.height=Math.min(30,30-30*b)+"px"}var q=performance&&performance.now?performance.now.bind(performance):Date.now,k=q(),r=k,t=0,n=0,c=f("div","stats","width:80px;opacity:0.9;cursor:pointer");c.addEventListener("mousedown",function(a){a.preventDefault();m(++n%c.children.length)},!1);var d=0,u=Infinity,v=0,b=l("fps","#0ff","#002"),A=b.children[0],
-B=b.children[1];c.appendChild(b);var g=0,w=Infinity,x=0,b=l("ms","#0f0","#020"),C=b.children[0],D=b.children[1];c.appendChild(b);if(performance&&performance.memory){var h=0,y=Infinity,z=0,b=l("mb","#f08","#201"),E=b.children[0],F=b.children[1];c.appendChild(b)}m(n);return{REVISION:14,domElement:c,setMode:m,begin:function(){k=q()},end:function(){var a=q();g=a-k;w=Math.min(w,g);x=Math.max(x,g);C.textContent=(g|0)+" MS ("+(w|0)+"-"+(x|0)+")";p(D,g/200);t++;if(a>r+1E3&&(d=Math.round(1E3*t/(a-r)),u=Math.min(u,
-d),v=Math.max(v,d),A.textContent=d+" FPS ("+u+"-"+v+")",p(B,d/100),r=a,t=0,void 0!==h)){var b=performance.memory.usedJSHeapSize,c=performance.memory.jsHeapSizeLimit;h=Math.round(9.54E-7*b);y=Math.min(y,h);z=Math.max(z,h);E.textContent=h+" MB ("+y+"-"+z+")";p(F,b/c)}return a},update:function(){k=this.end()}}};"object"===typeof module&&(module.exports=Stats);
+b));return c}function m(a){for(var b=c.children,d=0;d<b.length;d++)b[d].style.display=d===a?"block":"none";n=a}function p(a,b){a.appendChild(a.firstChild).style.height=Math.min(30,30-30*b)+"px"}var q=self.performance&&self.performance.now?self.performance.now.bind(performance):Date.now,k=q(),r=k,t=0,n=0,c=f("div","stats","width:80px;opacity:0.9;cursor:pointer");c.addEventListener("mousedown",function(a){a.preventDefault();m(++n%c.children.length)},!1);var d=0,u=Infinity,v=0,b=l("fps","#0ff","#002"),
+A=b.children[0],B=b.children[1];c.appendChild(b);var g=0,w=Infinity,x=0,b=l("ms","#0f0","#020"),C=b.children[0],D=b.children[1];c.appendChild(b);if(self.performance&&self.performance.memory){var h=0,y=Infinity,z=0,b=l("mb","#f08","#201"),E=b.children[0],F=b.children[1];c.appendChild(b)}m(n);return{REVISION:14,domElement:c,setMode:m,begin:function(){k=q()},end:function(){var a=q();g=a-k;w=Math.min(w,g);x=Math.max(x,g);C.textContent=(g|0)+" MS ("+(w|0)+"-"+(x|0)+")";p(D,g/200);t++;if(a>r+1E3&&(d=Math.round(1E3*
+t/(a-r)),u=Math.min(u,d),v=Math.max(v,d),A.textContent=d+" FPS ("+u+"-"+v+")",p(B,d/100),r=a,t=0,void 0!==h)){var b=performance.memory.usedJSHeapSize,c=performance.memory.jsHeapSizeLimit;h=Math.round(9.54E-7*b);y=Math.min(y,h);z=Math.max(z,h);E.textContent=h+" MB ("+y+"-"+z+")";p(F,b/c)}return a},update:function(){k=this.end()}}};"object"===typeof module&&(module.exports=Stats);

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

@@ -516,7 +516,7 @@ THREE.Projector = function () {
 
 
 						var face = faces[ f ];
 						var face = faces[ f ];
 
 
-						var material = isFaceMaterial === true
+						material = isFaceMaterial === true
 							 ? objectMaterials.materials[ face.materialIndex ]
 							 ? objectMaterials.materials[ face.materialIndex ]
 							 : object.material;
 							 : object.material;
 
 

+ 0 - 9
examples/webgl_animation_skinning_blending.html

@@ -94,7 +94,6 @@
 				window.addEventListener( 'weight-animation', onWeightAnimation );
 				window.addEventListener( 'weight-animation', onWeightAnimation );
 				window.addEventListener( 'crossfade', onCrossfade );
 				window.addEventListener( 'crossfade', onCrossfade );
 				window.addEventListener( 'warp', onWarp );
 				window.addEventListener( 'warp', onWarp );
-				window.addEventListener( 'toggle-lock-camera', onLockCameraToggle );
 				window.addEventListener( 'toggle-show-skeleton', onShowSkeleton );
 				window.addEventListener( 'toggle-show-skeleton', onShowSkeleton );
 				window.addEventListener( 'toggle-show-model', onShowModel );
 				window.addEventListener( 'toggle-show-model', onShowModel );
 
 
@@ -184,14 +183,6 @@
 
 
 			}
 			}
 
 
-
-			function onLockCameraToggle( event ) {
-
-				var shouldLock = event.detail.shouldLock;
-				controls.enabled = !shouldLock;
-
-			}
-
 			function onShowSkeleton( event ) {
 			function onShowSkeleton( event ) {
 
 
 				var shouldShow = event.detail.shouldShow;
 				var shouldShow = event.detail.shouldShow;

+ 46 - 61
examples/webgl_modifier_tessellation.html

@@ -64,7 +64,7 @@
 				vNormal = normal;
 				vNormal = normal;
 				vColor = customColor;
 				vColor = customColor;
 
 
-				vec3 newPosition = position + amplitude * displacement;
+				vec3 newPosition = position + normal * amplitude * displacement;
 				gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
 				gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
 
 
 			}
 			}
@@ -78,7 +78,7 @@
 
 
 			void main() {
 			void main() {
 
 
-				const float ambient = 0.005;
+				const float ambient = 0.4;
 
 
 				vec3 light = vec3( 1.0 );
 				vec3 light = vec3( 1.0 );
 				light = normalize( light );
 				light = normalize( light );
@@ -86,7 +86,6 @@
 				float directional = max( dot( vNormal, light ), 0.0 );
 				float directional = max( dot( vNormal, light ), 0.0 );
 
 
 				gl_FragColor = vec4( ( directional + ambient ) * vColor, 1.0 );
 				gl_FragColor = vec4( ( directional + ambient ) * vColor, 1.0 );
-				gl_FragColor.xyz = sqrt( gl_FragColor.xyz );
 
 
 			}
 			}
 
 
@@ -109,8 +108,8 @@
 
 
 		function init() {
 		function init() {
 
 
-			camera = new THREE.PerspectiveCamera( 25, WIDTH / HEIGHT, 1, 10000 );
-			camera.position.z = 350;
+			camera = new THREE.PerspectiveCamera( 40, WIDTH / HEIGHT, 1, 10000 );
+			camera.position.set( -100, 100, 200 );
 
 
 			controls = new THREE.TrackballControls( camera );
 			controls = new THREE.TrackballControls( camera );
 
 
@@ -118,31 +117,6 @@
 
 
 			//
 			//
 
 
-			attributes = {
-
-				displacement: {	type: 'v3', value: [] },
-				customColor:  {	type: 'c', value: [] }
-
-			};
-
-			uniforms = {
-
-				amplitude: { type: "f", value: 0.0 }
-
-			};
-
-			var shaderMaterial = new THREE.ShaderMaterial( {
-
-				uniforms: 		uniforms,
-				attributes:     attributes,
-				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
-				fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
-				shading: 		THREE.FlatShading,
-				side: 			THREE.DoubleSide
-
-			});
-
-
 			var geometry = new THREE.TextGeometry( "THREE.JS", {
 			var geometry = new THREE.TextGeometry( "THREE.JS", {
 
 
 				size: 40,
 				size: 40,
@@ -159,8 +133,6 @@
 
 
 			});
 			});
 
 
-			geometry.dynamic = true;
-
 			geometry.center();
 			geometry.center();
 
 
 			var tessellateModifier = new THREE.TessellateModifier( 8 );
 			var tessellateModifier = new THREE.TessellateModifier( 8 );
@@ -174,57 +146,68 @@
 			var explodeModifier = new THREE.ExplodeModifier();
 			var explodeModifier = new THREE.ExplodeModifier();
 			explodeModifier.modify( geometry );
 			explodeModifier.modify( geometry );
 
 
-			var vertices = geometry.vertices;
+			var numFaces = geometry.faces.length;
+
+			//
+
+			geometry = new THREE.BufferGeometry().fromGeometry( geometry );
 
 
-			var colors = attributes.customColor.value;
-			var displacement = attributes.displacement.value;
+			var colors = new Float32Array( numFaces * 3 * 3 );
+			var displacement = new Float32Array( numFaces * 3 * 3 );
 
 
-			var nv, v = 0;
+			var color = new THREE.Color();
 
 
-			for ( var f = 0; f < geometry.faces.length; f ++ ) {
+			for ( var f = 0; f < numFaces; f ++ ) {
 
 
-				var face = geometry.faces[ f ];
+				var index = 9 * f;
 
 
-				if ( face instanceof THREE.Face3 ) {
+				var h = 0.2 * Math.random();
+				var s = 0.5 + 0.5 * Math.random();
+				var l = 0.5 + 0.5 * Math.random();
+
+				color.setHSL( h, s, l );
 
 
-					nv = 3;
+				var d = 10 * ( 0.5 - Math.random() );
+
+				for ( var i = 0; i < 3; i ++ ) {
 
 
-				} else {
+					colors[ index + ( 3 * i )     ] = color.r;
+					colors[ index + ( 3 * i ) + 1 ] = color.g;
+					colors[ index + ( 3 * i ) + 2 ] = color.b;
 
 
-					nv = 4;
+					displacement[ index + ( 3 * i )     ] = d;
+					displacement[ index + ( 3 * i ) + 1 ] = d;
+					displacement[ index + ( 3 * i ) + 2 ] = d;
 
 
 				}
 				}
 
 
-				var h = 0.15 * Math.random();
-				var s = 0.5 + 0.5 * Math.random();
-				var l = 0.5 + 0.5 * Math.random();
+			}
 
 
-				var d = 10 * ( 0.5 - Math.random() );
+			geometry.addAttribute( 'customColor', new THREE.BufferAttribute( colors, 3 ) );
+			geometry.addAttribute( 'displacement', new THREE.BufferAttribute( displacement, 3 ) );
 
 
-				var x = 2 * ( 0.5 - Math.random() );
-				var y = 2 * ( 0.5 - Math.random() );
-				var z = 2 * ( 0.5 - Math.random() );
+			//
 
 
-				for ( var i = 0; i < nv; i ++ ) {
+			attributes = [ `displacement`, `customColor` ];
 
 
-					colors[ v ] = new THREE.Color();
-					displacement[ v ] = new THREE.Vector3();
+			uniforms = {
 
 
-					colors[ v ].setHSL( h, s, l );
-					colors[ v ].convertGammaToLinear();
+				amplitude: { type: "f", value: 0.0 }
 
 
-					displacement[ v ].set( x, y, z );
+			};
 
 
-					v += 1;
+			var shaderMaterial = new THREE.ShaderMaterial( {
 
 
-				}
+				uniforms: 		uniforms,
+				attributes:     attributes,
+				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
+				fragmentShader: document.getElementById( 'fragmentshader' ).textContent
 
 
-			}
+			});
 
 
-			console.log( "faces", geometry.faces.length );
+			//
 
 
 			mesh = new THREE.Mesh( geometry, shaderMaterial );
 			mesh = new THREE.Mesh( geometry, shaderMaterial );
-			mesh.rotation.set( 0.5, 0.5, 0 );
 
 
 			scene.add( mesh );
 			scene.add( mesh );
 
 
@@ -259,6 +242,7 @@
 			requestAnimationFrame( animate );
 			requestAnimationFrame( animate );
 
 
 			render();
 			render();
+
 			stats.update();
 			stats.update();
 
 
 		}
 		}
@@ -267,9 +251,10 @@
 
 
 			var time = Date.now() * 0.001;
 			var time = Date.now() * 0.001;
 
 
-			uniforms.amplitude.value = Math.sin( time * 0.5 );
+			uniforms.amplitude.value = 1.0 + Math.sin( time * 0.5 );
 
 
 			controls.update();
 			controls.update();
+
 			renderer.render( scene, camera );
 			renderer.render( scene, camera );
 
 
 		}
 		}

+ 31 - 0
src/core/BufferGeometry.js

@@ -194,11 +194,13 @@ THREE.BufferGeometry.prototype = {
 			direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
 			direct.normalsNeedUpdate = geometry.normalsNeedUpdate;
 			direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
 			direct.colorsNeedUpdate = geometry.colorsNeedUpdate;
 			direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
 			direct.uvsNeedUpdate = geometry.uvsNeedUpdate;
+			direct.tangentsNeedUpdate = geometry.tangentsNeedUpdate;
 
 
 			geometry.verticesNeedUpdate = false;
 			geometry.verticesNeedUpdate = false;
 			geometry.normalsNeedUpdate = false;
 			geometry.normalsNeedUpdate = false;
 			geometry.colorsNeedUpdate = false;
 			geometry.colorsNeedUpdate = false;
 			geometry.uvsNeedUpdate = false;
 			geometry.uvsNeedUpdate = false;
+			geometry.tangentsNeedUpdate = false;
 
 
 			geometry = direct;
 			geometry = direct;
 
 
@@ -249,6 +251,21 @@ THREE.BufferGeometry.prototype = {
 
 
 		}
 		}
 
 
+		if ( geometry.tangentsNeedUpdate === true ) {
+
+			var attribute = this.attributes.tangent;
+
+			if ( attribute !== undefined ) {
+
+				attribute.copyVector4sArray( geometry.tangents );
+				attribute.needsUpdate = true;
+
+			}
+
+			geometry.tangentsNeedUpdate = false;
+
+		}
+
 		return this;
 		return this;
 
 
 	},
 	},
@@ -298,6 +315,20 @@ THREE.BufferGeometry.prototype = {
 
 
 		}
 		}
 
 
+		if ( geometry.uvs2.length > 0 ) {
+
+			var uvs2 = new Float32Array( geometry.uvs2.length * 2 );
+			this.addAttribute( 'uv2', new THREE.BufferAttribute( uvs2, 2 ).copyVector2sArray( geometry.uvs2 ) );
+
+		}
+
+		if ( geometry.tangents.length > 0 ) {
+
+			var tangents = new Float32Array( geometry.tangents.length * 4 );
+			this.addAttribute( 'tangent', new THREE.BufferAttribute( tangents, 4 ).copyVector4sArray( geometry.tangents ) );
+
+		}
+
 		// morphs
 		// morphs
 
 
 		if ( geometry.morphTargets.length > 0 ) {
 		if ( geometry.morphTargets.length > 0 ) {

+ 33 - 2
src/core/DirectGeometry.js

@@ -18,6 +18,7 @@ THREE.DirectGeometry = function () {
 	this.colors = [];
 	this.colors = [];
 	this.uvs = [];
 	this.uvs = [];
 	this.uvs2 = [];
 	this.uvs2 = [];
+	this.tangents = [];
 
 
 	this.morphTargets = [];
 	this.morphTargets = [];
 	this.morphColors = [];
 	this.morphColors = [];
@@ -37,6 +38,7 @@ THREE.DirectGeometry = function () {
 	this.normalsNeedUpdate = false;
 	this.normalsNeedUpdate = false;
 	this.colorsNeedUpdate = false;
 	this.colorsNeedUpdate = false;
 	this.uvsNeedUpdate = false;
 	this.uvsNeedUpdate = false;
+	this.tangentsNeedUpdate = false;
 
 
 };
 };
 
 
@@ -61,6 +63,14 @@ THREE.DirectGeometry.prototype = {
 
 
 	},
 	},
 
 
+	computeTangents: function () {
+
+		console.warn( 'THREE.DirectGeometry: computeTangents() is not a method of this type of geometry.' );
+		return this;
+
+	},
+
+
 	fromGeometry: function ( geometry ) {
 	fromGeometry: function ( geometry ) {
 
 
 		var faces = geometry.faces;
 		var faces = geometry.faces;
@@ -70,6 +80,8 @@ THREE.DirectGeometry.prototype = {
 		var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
 		var hasFaceVertexUv = faceVertexUvs[ 0 ] && faceVertexUvs[ 0 ].length > 0;
 		var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
 		var hasFaceVertexUv2 = faceVertexUvs[ 1 ] && faceVertexUvs[ 1 ].length > 0;
 
 
+		var hasTangents = geometry.hasTangents;
+
 		// morphs
 		// morphs
 
 
 		var morphTargets = geometry.morphTargets;
 		var morphTargets = geometry.morphTargets;
@@ -153,7 +165,7 @@ THREE.DirectGeometry.prototype = {
 
 
 				} else {
 				} else {
 
 
-					console.warn( 'THREE.BufferGeometry.fromGeometry(): Undefined vertexUv', i );
+					console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv ', i );
 
 
 					this.uvs.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() );
 					this.uvs.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() );
 
 
@@ -171,7 +183,7 @@ THREE.DirectGeometry.prototype = {
 
 
 				} else {
 				} else {
 
 
-					console.warn( 'THREE.BufferGeometry.fromGeometry(): Undefined vertexUv2', i );
+					console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined vertexUv2 ', i );
 
 
 					this.uvs2.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() );
 					this.uvs2.push( new THREE.Vector2(), new THREE.Vector2(), new THREE.Vector2() );
 
 
@@ -179,6 +191,24 @@ THREE.DirectGeometry.prototype = {
 
 
 			}
 			}
 
 
+			if ( hasTangents === true ) {
+
+				var vertexTangents = face.vertexTangents;
+
+				if ( vertexTangents.length === 3 ) {
+
+					this.tangents.push( vertexTangents[ 0 ], vertexTangents[ 1 ], vertexTangents[ 2 ] );
+
+				} else {
+
+					console.warn( 'THREE.DirectGeometry.fromGeometry(): Undefined tangents ', i );
+
+					this.tangents.push( new THREE.Vector4(), new THREE.Vector4(), new THREE.Vector4() );
+
+				}
+
+			}
+
 			// morphs
 			// morphs
 
 
 			for ( var j = 0; j < morphTargetsLength; j ++ ) {
 			for ( var j = 0; j < morphTargetsLength; j ++ ) {
@@ -226,6 +256,7 @@ THREE.DirectGeometry.prototype = {
 		this.normalsNeedUpdate = geometry.normalsNeedUpdate;
 		this.normalsNeedUpdate = geometry.normalsNeedUpdate;
 		this.colorsNeedUpdate = geometry.colorsNeedUpdate;
 		this.colorsNeedUpdate = geometry.colorsNeedUpdate;
 		this.uvsNeedUpdate = geometry.uvsNeedUpdate;
 		this.uvsNeedUpdate = geometry.uvsNeedUpdate;
+		this.tangentsNeedUpdate = geometry.tangentsNeedUpdate;
 
 
 		return this;
 		return this;
 
 

+ 43 - 4
src/core/Geometry.js

@@ -45,8 +45,6 @@ THREE.Geometry = function () {
 	this.colorsNeedUpdate = false;
 	this.colorsNeedUpdate = false;
 	this.lineDistancesNeedUpdate = false;
 	this.lineDistancesNeedUpdate = false;
 
 
-	this.groupsNeedUpdate = false;
-
 };
 };
 
 
 THREE.Geometry.prototype = {
 THREE.Geometry.prototype = {
@@ -105,11 +103,18 @@ THREE.Geometry.prototype = {
 		var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
 		var normals = attributes.normal !== undefined ? attributes.normal.array : undefined;
 		var colors = attributes.color !== undefined ? attributes.color.array : undefined;
 		var colors = attributes.color !== undefined ? attributes.color.array : undefined;
 		var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
 		var uvs = attributes.uv !== undefined ? attributes.uv.array : undefined;
+		var uvs2 = attributes.uv2 !== undefined ? attributes.uv2.array : undefined;
+		var tangents = attributes.tangent !== undefined ? attributes.tangent.array : undefined;
+
+		if ( uvs2 !== undefined ) this.faceVertexUvs[ 1 ] = [];
+		if ( tangents !== undefined ) this.hasTangents = true;
 
 
 		var tempNormals = [];
 		var tempNormals = [];
 		var tempUVs = [];
 		var tempUVs = [];
+		var tempUVs2 = [];
+		var tempTangents = [];
 
 
-		for ( var i = 0, j = 0; i < vertices.length; i += 3, j += 2 ) {
+		for ( var i = 0, j = 0, k = 0; i < vertices.length; i += 3, j += 2, k += 4 ) {
 
 
 			scope.vertices.push( new THREE.Vector3( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] ) );
 			scope.vertices.push( new THREE.Vector3( vertices[ i ], vertices[ i + 1 ], vertices[ i + 2 ] ) );
 
 
@@ -131,6 +136,18 @@ THREE.Geometry.prototype = {
 
 
 			}
 			}
 
 
+			if ( uvs2 !== undefined ) {
+
+				tempUVs2.push( new THREE.Vector2( uvs2[ j ], uvs2[ j + 1 ] ) );
+
+			}
+
+			if ( tangents !== undefined ) {
+
+				tempTangents.push( new THREE.Vector4( tangents[ k ], tangents[ k + 1 ], tangents[ k + 2 ], tangents[ k + 3 ] ) );
+
+			}
+
 		}
 		}
 
 
 		var addFace = function ( a, b, c ) {
 		var addFace = function ( a, b, c ) {
@@ -138,7 +155,9 @@ THREE.Geometry.prototype = {
 			var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : [];
 			var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : [];
 			var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
 			var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
 
 
-			scope.faces.push( new THREE.Face3( a, b, c, vertexNormals, vertexColors ) );
+			var face = new THREE.Face3( a, b, c, vertexNormals, vertexColors );
+
+			scope.faces.push( face );
 
 
 			if ( uvs !== undefined ) {
 			if ( uvs !== undefined ) {
 
 
@@ -146,6 +165,18 @@ THREE.Geometry.prototype = {
 
 
 			}
 			}
 
 
+			if ( uvs2 !== undefined ) {
+
+				scope.faceVertexUvs[ 1 ].push( [ tempUVs2[ a ].clone(), tempUVs2[ b ].clone(), tempUVs2[ c ].clone() ] );
+
+			}
+
+			if ( tangents !== undefined ) {
+
+				face.vertexTangents.push( tempTangents[ a ].clone(), tempTangents[ b ].clone(), tempTangents[ c ].clone() );
+
+			}
+
 		};
 		};
 
 
 		if ( indices !== undefined ) {
 		if ( indices !== undefined ) {
@@ -1071,6 +1102,14 @@ THREE.Geometry.prototype = {
 
 
 		this.dispatchEvent( { type: 'dispose' } );
 		this.dispatchEvent( { type: 'dispose' } );
 
 
+	},
+
+	// Backwards compatibility
+
+	set groupsNeedUpdate ( value ) {
+
+		if ( value === true ) this.dispose();
+
 	}
 	}
 
 
 };
 };

+ 1 - 1
src/extras/FontUtils.js

@@ -31,7 +31,7 @@ THREE.FontUtils = {
 
 
 		try {
 		try {
 
 
-			return this.faces[ this.face ][ this.weight ][ this.style ];
+			return this.faces[ this.face.toLowerCase() ][ this.weight ][ this.style ];
 
 
 		} catch (e) {
 		} catch (e) {
 
 

+ 29 - 0
src/lights/AreaLight.js

@@ -1,6 +1,7 @@
 /**
 /**
  * @author MPanknin / http://www.redplant.de/
  * @author MPanknin / http://www.redplant.de/
  * @author alteredq / http://alteredqualia.com/
  * @author alteredq / http://alteredqualia.com/
+ * @author prafullit
  */
  */
 
 
 THREE.AreaLight = function ( color, intensity ) {
 THREE.AreaLight = function ( color, intensity ) {
@@ -26,3 +27,31 @@ THREE.AreaLight = function ( color, intensity ) {
 THREE.AreaLight.prototype = Object.create( THREE.Light.prototype );
 THREE.AreaLight.prototype = Object.create( THREE.Light.prototype );
 THREE.AreaLight.prototype.constructor = THREE.AreaLight;
 THREE.AreaLight.prototype.constructor = THREE.AreaLight;
 
 
+THREE.AreaLight.prototype.clone = function () {
+
+	var light = new THREE.AreaLight();
+
+	THREE.Light.prototype.clone.call( this, light );
+
+	light.normal.copy(this.normal);
+	light.right.copy(this.right);
+	light.intensity = this.intensity;
+	light.width = this.width;
+	light.height = this.height;
+	light.constantAttenuation = this.constantAttenuation;
+	light.linearAttenuation = this.linearAttenuation;
+	light.quadraticAttenuation = this.quadraticAttenuation
+
+	return light;
+
+};
+
+THREE.AreaLight.prototype.toJSON = function ( meta ) {
+
+	var data = THREE.Object3D.prototype.toJSON.call( this, meta );
+
+	data.object.color = this.color.getHex();
+	data.object.intensity = this.intensity;
+
+	return data;
+};

+ 46 - 4
src/materials/MeshFaceMaterial.js

@@ -4,11 +4,53 @@
 
 
 THREE.MeshFaceMaterial = function ( materials ) {
 THREE.MeshFaceMaterial = function ( materials ) {
 
 
-	console.error( 'THREE.MeshFaceMaterial has been removed.' );
+	this.uuid = THREE.Math.generateUUID();
 
 
-	var material = Array.isArray( materials ) ? materials[ 0 ] : new THREE.MeshBasicMaterial();
-	material.materials = []; // temporal workaround
+	this.type = 'MeshFaceMaterial';
 
 
-	return material;
+	this.materials = materials instanceof Array ? materials : [];
+
+};
+
+THREE.MeshFaceMaterial.prototype = {
+
+	constructor: THREE.MeshFaceMaterial,
+
+	toJSON: function () {
+
+		var output = {
+			metadata: {
+				version: 4.2,
+				type: 'material',
+				generator: 'MaterialExporter'
+			},
+			uuid: this.uuid,
+			type: this.type,
+			materials: []
+		};
+
+		for ( var i = 0, l = this.materials.length; i < l; i ++ ) {
+
+			output.materials.push( this.materials[ i ].toJSON() );
+
+		}
+
+		return output;
+
+	},
+
+	clone: function () {
+
+		var material = new THREE.MeshFaceMaterial();
+
+		for ( var i = 0; i < this.materials.length; i ++ ) {
+
+			material.materials.push( this.materials[ i ].clone() );
+
+		}
+
+		return material;
+
+	}
 
 
 };
 };

+ 41 - 19
src/objects/LOD.js

@@ -8,7 +8,18 @@ THREE.LOD = function () {
 
 
 	THREE.Object3D.call( this );
 	THREE.Object3D.call( this );
 
 
-	this.objects = [];
+	Object.defineProperties( this, {
+		levels: {
+			enumerable: true,
+			value: []
+		},
+		objects: {
+			get: function () {
+				console.warn( 'THREE.LOD: .objects has been renamed to .levels.' );
+				return this.levels;
+			}
+		}
+	} );
 
 
 };
 };
 
 
@@ -22,9 +33,11 @@ THREE.LOD.prototype.addLevel = function ( object, distance ) {
 
 
 	distance = Math.abs( distance );
 	distance = Math.abs( distance );
 
 
-	for ( var l = 0; l < this.objects.length; l ++ ) {
+	var levels = this.levels;
+
+	for ( var l = 0; l < levels.length; l ++ ) {
 
 
-		if ( distance < this.objects[ l ].distance ) {
+		if ( distance < levels[ l ].distance ) {
 
 
 			break;
 			break;
 
 
@@ -32,16 +45,19 @@ THREE.LOD.prototype.addLevel = function ( object, distance ) {
 
 
 	}
 	}
 
 
-	this.objects.splice( l, 0, { distance: distance, object: object } );
+	levels.splice( l, 0, { distance: distance, object: object } );
+
 	this.add( object );
 	this.add( object );
 
 
 };
 };
 
 
 THREE.LOD.prototype.getObjectForDistance = function ( distance ) {
 THREE.LOD.prototype.getObjectForDistance = function ( distance ) {
 
 
-	for ( var i = 1, l = this.objects.length; i < l; i ++ ) {
+	var levels = this.levels;
+
+	for ( var i = 1, l = levels.length; i < l; i ++ ) {
 
 
-		if ( distance < this.objects[ i ].distance ) {
+		if ( distance < levels[ i ].distance ) {
 
 
 			break;
 			break;
 
 
@@ -49,7 +65,7 @@ THREE.LOD.prototype.getObjectForDistance = function ( distance ) {
 
 
 	}
 	}
 
 
-	return this.objects[ i - 1 ].object;
+	return levels[ i - 1 ].object;
 
 
 };
 };
 
 
@@ -76,21 +92,23 @@ THREE.LOD.prototype.update = function () {
 
 
 	return function ( camera ) {
 	return function ( camera ) {
 
 
-		if ( this.objects.length > 1 ) {
+		var levels = this.levels;
+
+		if ( levels.length > 1 ) {
 
 
 			v1.setFromMatrixPosition( camera.matrixWorld );
 			v1.setFromMatrixPosition( camera.matrixWorld );
 			v2.setFromMatrixPosition( this.matrixWorld );
 			v2.setFromMatrixPosition( this.matrixWorld );
 
 
 			var distance = v1.distanceTo( v2 );
 			var distance = v1.distanceTo( v2 );
 
 
-			this.objects[ 0 ].object.visible = true;
+			levels[ 0 ].object.visible = true;
 
 
-			for ( var i = 1, l = this.objects.length; i < l; i ++ ) {
+			for ( var i = 1, l = levels.length; i < l; i ++ ) {
 
 
-				if ( distance >= this.objects[ i ].distance ) {
+				if ( distance >= levels[ i ].distance ) {
 
 
-					this.objects[ i - 1 ].object.visible = false;
-					this.objects[ i     ].object.visible = true;
+					levels[ i - 1 ].object.visible = false;
+					levels[ i     ].object.visible = true;
 
 
 				} else {
 				} else {
 
 
@@ -102,7 +120,7 @@ THREE.LOD.prototype.update = function () {
 
 
 			for ( ; i < l; i ++ ) {
 			for ( ; i < l; i ++ ) {
 
 
-				this.objects[ i ].object.visible = false;
+				levels[ i ].object.visible = false;
 
 
 			}
 			}
 
 
@@ -116,12 +134,16 @@ THREE.LOD.prototype.clone = function ( object ) {
 
 
 	if ( object === undefined ) object = new THREE.LOD();
 	if ( object === undefined ) object = new THREE.LOD();
 
 
-	THREE.Object3D.prototype.clone.call( this, object );
+	THREE.Object3D.prototype.clone.call( this, object, false );
+
+	var levels = this.levels;
+
+	for ( var i = 0, l = levels.length; i < l; i ++ ) {
+
+		var level = levels[ i ];
+
+		object.addLevel( level.object.clone(), level.distance );
 
 
-	for ( var i = 0, l = this.objects.length; i < l; i ++ ) {
-		var x = this.objects[ i ].object.clone();
-		x.visible = i === 0;
-		object.addLevel( x, this.objects[ i ].distance );
 	}
 	}
 
 
 	return object;
 	return object;

+ 17 - 20
src/objects/Mesh.js

@@ -69,6 +69,9 @@ THREE.Mesh.prototype.raycast = ( function () {
 	return function ( raycaster, intersects ) {
 	return function ( raycaster, intersects ) {
 
 
 		var geometry = this.geometry;
 		var geometry = this.geometry;
+		var material = this.material;
+
+		if ( material === undefined ) return;
 
 
 		// Checking boundingSphere distance to ray
 		// Checking boundingSphere distance to ray
 
 
@@ -98,16 +101,12 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 
 		}
 		}
 
 
-		if ( geometry instanceof THREE.BufferGeometry ) {
-
-			var material = this.material;
+		var a, b, c;
 
 
-			if ( material === undefined ) return;
+		if ( geometry instanceof THREE.BufferGeometry ) {
 
 
 			var attributes = geometry.attributes;
 			var attributes = geometry.attributes;
 
 
-			var a, b, c;
-
 			if ( attributes.index !== undefined ) {
 			if ( attributes.index !== undefined ) {
 
 
 				var indices = attributes.index.array;
 				var indices = attributes.index.array;
@@ -159,9 +158,9 @@ THREE.Mesh.prototype.raycast = ( function () {
 							distance: distance,
 							distance: distance,
 							point: intersectionPoint,
 							point: intersectionPoint,
 							face: new THREE.Face3( a, b, c, THREE.Triangle.normal( vA, vB, vC ) ),
 							face: new THREE.Face3( a, b, c, THREE.Triangle.normal( vA, vB, vC ) ),
-							faceIndex: Math.floor(i/3), // triangle number in indices buffer semantics
+							faceIndex: Math.floor( i / 3 ), // triangle number in indices buffer semantics
 							object: this
 							object: this
-							
+
 						} );
 						} );
 
 
 					}
 					}
@@ -216,26 +215,24 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 
 		} else if ( geometry instanceof THREE.Geometry ) {
 		} else if ( geometry instanceof THREE.Geometry ) {
 
 
-			var isFaceMaterial = this.material instanceof THREE.MeshFaceMaterial;
-			var objectMaterials = isFaceMaterial === true ? this.material.materials : null;
-
-			var a, b, c;
+			var isFaceMaterial = material instanceof THREE.MeshFaceMaterial;
+			var materials = isFaceMaterial === true ? material.materials : null;
 
 
 			var vertices = geometry.vertices;
 			var vertices = geometry.vertices;
+			var faces = geometry.faces;
 
 
-			for ( var f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
-
-				var face = geometry.faces[ f ];
+			for ( var f = 0, fl = faces.length; f < fl; f ++ ) {
 
 
-				var material = isFaceMaterial === true ? objectMaterials[ face.materialIndex ] : this.material;
+				var face = faces[ f ];
+				var faceMaterial = isFaceMaterial === true ? materials[ face.materialIndex ] : material;
 
 
-				if ( material === undefined ) continue;
+				if ( faceMaterial === undefined ) continue;
 
 
 				a = vertices[ face.a ];
 				a = vertices[ face.a ];
 				b = vertices[ face.b ];
 				b = vertices[ face.b ];
 				c = vertices[ face.c ];
 				c = vertices[ face.c ];
 
 
-				if ( material.morphTargets === true ) {
+				if ( faceMaterial.morphTargets === true ) {
 
 
 					var morphTargets = geometry.morphTargets;
 					var morphTargets = geometry.morphTargets;
 					var morphInfluences = this.morphTargetInfluences;
 					var morphInfluences = this.morphTargetInfluences;
@@ -276,13 +273,13 @@ THREE.Mesh.prototype.raycast = ( function () {
 
 
 				}
 				}
 
 
-				if ( material.side === THREE.BackSide ) {
+				if ( faceMaterial.side === THREE.BackSide ) {
 
 
 					var intersectionPoint = ray.intersectTriangle( c, b, a, true );
 					var intersectionPoint = ray.intersectTriangle( c, b, a, true );
 
 
 				} else {
 				} else {
 
 
-					var intersectionPoint = ray.intersectTriangle( a, b, c, material.side !== THREE.DoubleSide );
+					var intersectionPoint = ray.intersectTriangle( a, b, c, faceMaterial.side !== THREE.DoubleSide );
 
 
 				}
 				}
 
 

+ 11 - 17
src/objects/PointCloud.js

@@ -83,21 +83,21 @@ THREE.PointCloud.prototype.raycast = ( function () {
 
 
 				if ( offsets.length === 0 ) {
 				if ( offsets.length === 0 ) {
 
 
-					var offset = {
+					offsets.push( {
 						start: 0,
 						start: 0,
 						count: indices.length,
 						count: indices.length,
 						index: 0
 						index: 0
-					};
-
-					offsets = [ offset ];
+					} );
 
 
 				}
 				}
 
 
 				for ( var oi = 0, ol = offsets.length; oi < ol; ++ oi ) {
 				for ( var oi = 0, ol = offsets.length; oi < ol; ++ oi ) {
 
 
-					var start = offsets[ oi ].start;
-					var count = offsets[ oi ].count;
-					var index = offsets[ oi ].index;
+					var offset = offsets[ oi ];
+
+					var start = offset.start;
+					var count = offset.count;
+					var index = offset.index;
 
 
 					for ( var i = start, il = start + count; i < il; i ++ ) {
 					for ( var i = start, il = start + count; i < il; i ++ ) {
 
 
@@ -113,15 +113,9 @@ THREE.PointCloud.prototype.raycast = ( function () {
 
 
 			} else {
 			} else {
 
 
-				var pointCount = positions.length / 3;
-
-				for ( var i = 0; i < pointCount; i ++ ) {
+				for ( var i = 0, l = positions.length / 3; i < l; i ++ ) {
 
 
-					position.set(
-						positions[ 3 * i ],
-						positions[ 3 * i + 1 ],
-						positions[ 3 * i + 2 ]
-					);
+					position.fromArray( positions, i * 3 );
 
 
 					testPoint( position, i );
 					testPoint( position, i );
 
 
@@ -131,9 +125,9 @@ THREE.PointCloud.prototype.raycast = ( function () {
 
 
 		} else {
 		} else {
 
 
-			var vertices = this.geometry.vertices;
+			var vertices = geometry.vertices;
 
 
-			for ( var i = 0; i < vertices.length; i ++ ) {
+			for ( var i = 0, l = vertices.length; i < l; i ++ ) {
 
 
 				testPoint( vertices[ i ], i );
 				testPoint( vertices[ i ], i );
 
 

+ 8 - 17
src/objects/Skeleton.js

@@ -20,25 +20,16 @@ THREE.Skeleton = function ( bones, boneInverses, useVertexTexture ) {
 	// create a bone texture or an array of floats
 	// create a bone texture or an array of floats
 
 
 	if ( this.useVertexTexture ) {
 	if ( this.useVertexTexture ) {
-
+		
 		// layout (1 matrix = 4 pixels)
 		// layout (1 matrix = 4 pixels)
 		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
 		//      RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
-		//  with  8x8  pixel texture max   16 bones  (8 * 8  / 4)
-		//       16x16 pixel texture max   64 bones (16 * 16 / 4)
-		//       32x32 pixel texture max  256 bones (32 * 32 / 4)
-		//       64x64 pixel texture max 1024 bones (64 * 64 / 4)
-
-		var size;
-
-		if ( this.bones.length > 256 )
-			size = 64;
-		else if ( this.bones.length > 64 )
-			size = 32;
-		else if ( this.bones.length > 16 )
-			size = 16;
-		else
-			size = 8;
-
+		//  with  8x8  pixel texture max   16 bones * 4 pixels =  (8 * 8)
+		//       16x16 pixel texture max   64 bones * 4 pixels = (16 * 16)
+		//       32x32 pixel texture max  256 bones * 4 pixels = (32 * 32)
+		//       64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64)
+		
+		var size = THREE.Math.nextPowerOfTwo( Math.sqrt( this.bones.length * 4 ) ); // 4 pixels needed for 1 matrix
+		
 		this.boneTextureWidth = size;
 		this.boneTextureWidth = size;
 		this.boneTextureHeight = size;
 		this.boneTextureHeight = size;
 
 

+ 25 - 32
src/renderers/WebGLRenderer.js

@@ -1006,6 +1006,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 		if ( material.visible === false ) return;
 		if ( material.visible === false ) return;
 
 
+		setMaterial( material );
+
 		var geometry = objects.geometries.get( object );
 		var geometry = objects.geometries.get( object );
 		var program = setProgram( camera, lights, fog, material, object );
 		var program = setProgram( camera, lights, fog, material, object );
 
 
@@ -1606,8 +1608,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			var overrideMaterial = scene.overrideMaterial;
 			var overrideMaterial = scene.overrideMaterial;
 
 
-			setMaterial( overrideMaterial );
-
 			renderObjects( opaqueObjects, camera, lights, fog, overrideMaterial );
 			renderObjects( opaqueObjects, camera, lights, fog, overrideMaterial );
 			renderObjects( transparentObjects, camera, lights, fog, overrideMaterial );
 			renderObjects( transparentObjects, camera, lights, fog, overrideMaterial );
 			renderObjectsImmediate( objects.objectsImmediate, '', camera, lights, fog, overrideMaterial );
 			renderObjectsImmediate( objects.objectsImmediate, '', camera, lights, fog, overrideMaterial );
@@ -1727,7 +1727,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	function renderObjects( renderList, camera, lights, fog, overrideMaterial ) {
 	function renderObjects( renderList, camera, lights, fog, overrideMaterial ) {
 
 
-		var material;
+		var material = overrideMaterial;
 
 
 		for ( var i = 0, l = renderList.length; i < l; i ++ ) {
 		for ( var i = 0, l = renderList.length; i < l; i ++ ) {
 
 
@@ -1737,21 +1737,22 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			setupMatrices( object, camera );
 			setupMatrices( object, camera );
 
 
-			if ( overrideMaterial ) {
+			if ( overrideMaterial === null ) material = object.material;
 
 
-				material = overrideMaterial;
+			if ( material instanceof THREE.MeshFaceMaterial ) {
 
 
-			} else {
+				var materials = material.materials;
 
 
-				material = object.material;
+				for ( var j = 0, jl = materials.length; j < jl; j ++ ) {
 
 
-				if ( ! material ) continue;
+					_this.renderBufferDirect( camera, lights, fog, materials[ j ], object );
 
 
-				setMaterial( material );
+				}
+
+				continue;
 
 
 			}
 			}
 
 
-			_this.setMaterialFaces( material );
 			_this.renderBufferDirect( camera, lights, fog, material, object );
 			_this.renderBufferDirect( camera, lights, fog, material, object );
 
 
 		}
 		}
@@ -1760,7 +1761,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, overrideMaterial ) {
 	function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, overrideMaterial ) {
 
 
-		var material;
+		var material = overrideMaterial;
 
 
 		for ( var i = 0, l = renderList.length; i < l; i ++ ) {
 		for ( var i = 0, l = renderList.length; i < l; i ++ ) {
 
 
@@ -1769,19 +1770,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 			if ( object.visible === true ) {
 			if ( object.visible === true ) {
 
 
-				if ( overrideMaterial ) {
-
-					material = overrideMaterial;
-
-				} else {
-
-					material = webglObject[ materialType ];
-
-					if ( ! material ) continue;
-
-					setMaterial( material );
-
-				}
+				if ( overrideMaterial === null ) material = webglObject[ materialType ];
 
 
 				_this.renderImmediateObject( camera, lights, fog, material, object );
 				_this.renderImmediateObject( camera, lights, fog, material, object );
 
 
@@ -1793,12 +1782,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
 	this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
 
 
+		setMaterial( material );
+
 		var program = setProgram( camera, lights, fog, material, object );
 		var program = setProgram( camera, lights, fog, material, object );
 
 
 		_currentGeometryProgram = '';
 		_currentGeometryProgram = '';
 
 
-		_this.setMaterialFaces( material );
-
 		if ( object.immediateRenderCallback ) {
 		if ( object.immediateRenderCallback ) {
 
 
 			object.immediateRenderCallback( program, _gl, _frustum );
 			object.immediateRenderCallback( program, _gl, _frustum );
@@ -2048,6 +2037,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	function setMaterial( material ) {
 	function setMaterial( material ) {
 
 
+		setMaterialFaces( material );
+
 		if ( material.transparent === true ) {
 		if ( material.transparent === true ) {
 
 
 			state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha );
 			state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha );
@@ -2066,6 +2057,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	}
 	}
 
 
+	function setMaterialFaces( material ) {
+
+		state.setDoubleSided( material.side === THREE.DoubleSide );
+		state.setFlipSided( material.side === THREE.BackSide );
+
+	}
+
 	function setProgram( camera, lights, fog, material, object ) {
 	function setProgram( camera, lights, fog, material, object ) {
 
 
 		_usedTextureUnits = 0;
 		_usedTextureUnits = 0;
@@ -3150,12 +3148,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	};
 	};
 
 
-	this.setMaterialFaces = function ( material ) {
-
-		state.setDoubleSided( material.side === THREE.DoubleSide );
-		state.setFlipSided( material.side === THREE.BackSide );
-
-	};
+	this.setMaterialFaces = setMaterialFaces;
 
 
 	// Textures
 	// Textures
 
 

+ 1 - 1
src/renderers/shaders/ShaderChunk/color_vertex.glsl

@@ -1,5 +1,5 @@
 #ifdef USE_COLOR
 #ifdef USE_COLOR
 
 
-	vColor.xyz = inputToLinear( color.xyz );
+	vColor.xyz = color.xyz;
 
 
 #endif
 #endif

+ 0 - 3
src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl

@@ -209,9 +209,6 @@
 
 
 	}
 	}
 
 
-	// NOTE: I am unsure if this is correct in linear space.  -bhouston, Dec 29, 2014
-	shadowColor = inputToLinear( shadowColor );
-
 	outgoingLight = outgoingLight * shadowColor;
 	outgoingLight = outgoingLight * shadowColor;
 
 
 #endif
 #endif

+ 7 - 6
src/renderers/webgl/WebGLGeometries.js

@@ -37,14 +37,11 @@ THREE.WebGLGeometries = function ( gl, info ) {
 	function onGeometryDispose( event ) {
 	function onGeometryDispose( event ) {
 
 
 		var geometry = event.target;
 		var geometry = event.target;
+		var buffergeometry = geometries[ geometry.id ];
 
 
-		geometry.removeEventListener( 'dispose', onGeometryDispose );
-
-		geometry = geometries[ geometry.id ];
-
-		for ( var name in geometry.attributes ) {
+		for ( var name in buffergeometry.attributes ) {
 
 
-			var attribute = geometry.attributes[ name ];
+			var attribute = buffergeometry.attributes[ name ];
 
 
 			if ( attribute.buffer !== undefined ) {
 			if ( attribute.buffer !== undefined ) {
 
 
@@ -56,6 +53,10 @@ THREE.WebGLGeometries = function ( gl, info ) {
 
 
 		}
 		}
 
 
+		geometry.removeEventListener( 'dispose', onGeometryDispose );
+
+		delete geometries[ geometry.id ];
+
 		info.memory.geometries --;
 		info.memory.geometries --;
 
 
 	}
 	}

+ 8 - 7
utils/build/includes/canvas.json

@@ -21,7 +21,9 @@
 	"src/core/Object3D.js",
 	"src/core/Object3D.js",
 	"src/core/Face3.js",
 	"src/core/Face3.js",
 	"src/core/Face4.js",
 	"src/core/Face4.js",
+	"src/core/BufferAttribute.js",
 	"src/core/Geometry.js",
 	"src/core/Geometry.js",
+	"src/core/BufferGeometry.js",
 	"src/cameras/Camera.js",
 	"src/cameras/Camera.js",
 	"src/cameras/OrthographicCamera.js",
 	"src/cameras/OrthographicCamera.js",
 	"src/cameras/PerspectiveCamera.js",
 	"src/cameras/PerspectiveCamera.js",
@@ -29,9 +31,11 @@
 	"src/lights/AmbientLight.js",
 	"src/lights/AmbientLight.js",
 	"src/lights/DirectionalLight.js",
 	"src/lights/DirectionalLight.js",
 	"src/lights/PointLight.js",
 	"src/lights/PointLight.js",
+	"src/loaders/Cache.js",
 	"src/loaders/Loader.js",
 	"src/loaders/Loader.js",
 	"src/loaders/ImageLoader.js",
 	"src/loaders/ImageLoader.js",
 	"src/loaders/JSONLoader.js",
 	"src/loaders/JSONLoader.js",
+	"src/loaders/LoadingManager.js",
 	"src/loaders/MaterialLoader.js",
 	"src/loaders/MaterialLoader.js",
 	"src/loaders/TextureLoader.js",
 	"src/loaders/TextureLoader.js",
 	"src/materials/Material.js",
 	"src/materials/Material.js",
@@ -43,21 +47,18 @@
 	"src/materials/MeshNormalMaterial.js",
 	"src/materials/MeshNormalMaterial.js",
 	"src/materials/MeshFaceMaterial.js",
 	"src/materials/MeshFaceMaterial.js",
 	"src/materials/SpriteMaterial.js",
 	"src/materials/SpriteMaterial.js",
-	"src/materials/SpriteCanvasMaterial.js",
 	"src/textures/Texture.js",
 	"src/textures/Texture.js",
+	"src/textures/CompressedTexture.js",
 	"src/textures/DataTexture.js",
 	"src/textures/DataTexture.js",
 	"src/textures/VideoTexture.js",
 	"src/textures/VideoTexture.js",
 	"src/objects/Group.js",
 	"src/objects/Group.js",
 	"src/objects/Line.js",
 	"src/objects/Line.js",
+	"src/objects/LineSegments.js",
 	"src/objects/Mesh.js",
 	"src/objects/Mesh.js",
 	"src/objects/Bone.js",
 	"src/objects/Bone.js",
 	"src/objects/Skeleton.js",
 	"src/objects/Skeleton.js",
 	"src/objects/Sprite.js",
 	"src/objects/Sprite.js",
 	"src/scenes/Scene.js",
 	"src/scenes/Scene.js",
-	"src/renderers/CanvasRenderer.js",
-	"src/renderers/renderables/RenderableVertex.js",
-	"src/renderers/renderables/RenderableFace.js",
-	"src/renderers/renderables/RenderableObject.js",
-	"src/renderers/renderables/RenderableSprite.js",
-	"src/renderers/renderables/RenderableLine.js"
+	"examples/js/renderers/Projector.js",
+	"examples/js/renderers/CanvasRenderer.js"
 ]
 ]

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