2
0
Эх сурвалжийг харах

Merge branch 'dev' into FixSkinningShadow

Conflicts:
	src/renderers/webgl/WebGLShadowMap.js
takahiro 8 жил өмнө
parent
commit
0a24f91309
48 өөрчлөгдсөн 2147 нэмэгдсэн , 2267 устгасан
  1. 485 528
      build/three.js
  2. 331 333
      build/three.min.js
  3. 485 528
      build/three.module.js
  4. 6 6
      docs/api/math/Line3.html
  5. 4 4
      docs/api/math/Math.html
  6. 6 6
      docs/api/math/Quaternion.html
  7. 20 21
      docs/api/math/Vector2.html
  8. 5 5
      docs/api/math/Vector3.html
  9. 18 19
      docs/api/math/Vector4.html
  10. 2 2
      docs/scenes/js/geometry.js
  11. 8 0
      examples/js/controls/OrbitControls.js
  12. 9 20
      examples/js/loaders/GLTF2Loader.js
  13. 14 13
      examples/js/loaders/GLTFLoader.js
  14. 72 81
      examples/js/renderers/CanvasRenderer.js
  15. 75 35
      examples/js/renderers/Projector.js
  16. 12 0
      examples/models/json/suzanne.json
  17. 0 2
      examples/webgl_effects_peppersghost.html
  18. 1 3
      examples/webgl_loader_gltf.html
  19. 2 2
      examples/webgl_performance.html
  20. 2 2
      examples/webgl_performance_static.html
  21. 1 1
      package.json
  22. 0 16
      src/cameras/Camera.js
  23. 4 0
      src/core/BufferAttribute.js
  24. 5 5
      src/core/Layers.js
  25. 18 3
      src/core/Object3D.js
  26. 11 0
      src/lights/RectAreaLight.js
  27. 7 0
      src/loaders/ObjectLoader.js
  28. 1 0
      src/materials/SpriteMaterial.js
  29. 12 8
      src/math/Quaternion.js
  30. 24 33
      src/math/Vector2.js
  31. 4 22
      src/math/Vector3.js
  32. 4 15
      src/math/Vector4.js
  33. 1 0
      src/objects/Points.js
  34. 139 127
      src/renderers/WebGLRenderer.js
  35. 153 0
      src/renderers/webgl/WebGLAttributes.js
  36. 99 54
      src/renderers/webgl/WebGLGeometries.js
  37. 16 225
      src/renderers/webgl/WebGLObjects.js
  38. 19 17
      src/renderers/webgl/WebGLProperties.js
  39. 20 20
      src/renderers/webgl/WebGLShadowMap.js
  40. 16 53
      src/renderers/webgl/WebGLState.js
  41. 9 10
      src/renderers/webgl/WebGLTextures.js
  42. 2 2
      src/renderers/webgl/plugins/LensFlarePlugin.js
  43. 2 2
      src/renderers/webgl/plugins/SpritePlugin.js
  44. 10 30
      test/unit/src/core/Object3D.js
  45. 4 5
      test/unit/src/math/Triangle.js
  46. 1 1
      test/unit/src/math/Vector2.js
  47. 1 1
      test/unit/src/math/Vector3.js
  48. 7 7
      test/unit/src/math/Vector4.js

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 485 - 528
build/three.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 331 - 333
build/three.min.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 485 - 528
build/three.module.js


+ 6 - 6
docs/api/math/Line3.html

@@ -40,7 +40,7 @@
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
 		<h3>[method:Line3 applyMatrix4]( [page:Matrix4 matrix] )</h3>
 		<h3>[method:Line3 applyMatrix4]( [page:Matrix4 matrix] )</h3>
-		<div>Apply a matrix transform to the line segment.</div>
+		<div>Applies a matrix transform to the line segment.</div>
 
 
 		<h3>[method:Vector3 at]( [page:Float t], [page:Vector3 optionalTarget] )</h3>
 		<h3>[method:Vector3 at]( [page:Float t], [page:Vector3 optionalTarget] )</h3>
 		<div>
 		<div>
@@ -48,12 +48,12 @@
 		[page:Vector3 optionalTarget] - (optional) if specified, the result will be copied into this [page:Vector3],
 		[page:Vector3 optionalTarget] - (optional) if specified, the result will be copied into this [page:Vector3],
 		otherwise a new [page:Vector3] will be created.<br /><br />
 		otherwise a new [page:Vector3] will be created.<br /><br />
 
 
-		Return a vector at a certain position along the line. When [page:Float t] = 0, it returns the start vector,
+		Returns a vector at a certain position along the line. When [page:Float t] = 0, it returns the start vector,
 		and when [page:Float t] = 1 it returns the end vector.<br />
 		and when [page:Float t] = 1 it returns the end vector.<br />
 		</div>
 		</div>
 
 
 		<h3>[method:Line3 clone]()</h3>
 		<h3>[method:Line3 clone]()</h3>
-		<div>Return a new [page:Line3] with the same [page:.start start] and [page:.end end] vectors as this one.</div>
+		<div>Returns a new [page:Line3] with the same [page:.start start] and [page:.end end] vectors as this one.</div>
 
 
 		<h3>[method:Vector3 closestPointToPoint]( [page:Vector3 point], [page:Boolean clampToLine], [page:Vector3 optionalTarget] )</h3>
 		<h3>[method:Vector3 closestPointToPoint]( [page:Vector3 point], [page:Boolean clampToLine], [page:Vector3 optionalTarget] )</h3>
 		<div>
 		<div>
@@ -72,7 +72,7 @@
 		[page:Boolean clampToLine] - Whether to clamp the result to the range [0, 1].<br /><br />
 		[page:Boolean clampToLine] - Whether to clamp the result to the range [0, 1].<br /><br />
 
 
 		Returns a point parameter based on the closest point as projected on the line segement.
 		Returns a point parameter based on the closest point as projected on the line segement.
-		If clamp to line is true, then the returned value will be between 0 and 1.
+		If [page:Boolean clampToLine] is true, then the returned value will be between 0 and 1.
 		</div>
 		</div>
 
 
 		<h3>[method:Line3 copy]( [page:Line3 line] )</h3>
 		<h3>[method:Line3 copy]( [page:Line3 line] )</h3>
@@ -109,13 +109,13 @@
 			[page:Vector3 optionalTarget] - (optional) if specified, the result will be copied into this [page:Vector3],
 			[page:Vector3 optionalTarget] - (optional) if specified, the result will be copied into this [page:Vector3],
 			otherwise a new [page:Vector3] will be created.<br /><br />
 			otherwise a new [page:Vector3] will be created.<br /><br />
 
 
-		Return the center of the line segment.
+		Returns the center of the line segment.
 		</div>
 		</div>
 
 
 		<h3>[method:Line3 set]( [page:Vector3 start], [page:Vector3 end] )</h3>
 		<h3>[method:Line3 set]( [page:Vector3 start], [page:Vector3 end] )</h3>
 		<div>
 		<div>
 		[page:Vector3 start] - set the [page:.start start point] of the line.<br />
 		[page:Vector3 start] - set the [page:.start start point] of the line.<br />
-		end - [page:Vector3] - set the [page:.end end point] of the line.<br /><br />
+		[page:Vector3 end] - set the [page:.end end point] of the line.<br /><br />
 
 
 		Sets the start and end values by copying the provided vectors.
 		Sets the start and end values by copying the provided vectors.
 		</div>
 		</div>

+ 4 - 4
docs/api/math/Math.html

@@ -30,7 +30,7 @@
 		<div>
 		<div>
 		[page:Integer n], [page:Integer m] - Integers<br /><br />
 		[page:Integer n], [page:Integer m] - Integers<br /><br />
 
 
-		Compute the Euclidean modulo of m % [page:Integer n], that is:
+		Computes the Euclidean modulo of [page:Integer m] % [page:Integer n], that is:
 		<code>( ( n % m ) + m ) % m</code>
 		<code>( ( n % m ) + m ) % m</code>
 		</div>
 		</div>
 
 
@@ -71,10 +71,10 @@
 		</div>
 		</div>
 
 
 		<h3>[method:Integer nearestPowerOfTwo]( [page:Number n] )</h3>
 		<h3>[method:Integer nearestPowerOfTwo]( [page:Number n] )</h3>
-		<div>	Return the nearest power of 2 to a given number [page:Number n].</div>
+		<div>	Returns the nearest power of 2 to a given number [page:Number n].</div>
 
 
 		<h3>[method:Integer nextPowerOfTwo]( [page:Number n] )</h3>
 		<h3>[method:Integer nextPowerOfTwo]( [page:Number n] )</h3>
-		<div>Return the nearest power of 2 that is bigger than [page:Number n].</div>
+		<div>Returns the nearest power of 2 that is bigger than [page:Number n].</div>
 
 
 		<h3>[method:Float radToDeg]( [page:Float radians] )</h3>
 		<h3>[method:Float radToDeg]( [page:Float radians] )</h3>
 		<div>Converts radians to degrees.</div>
 		<div>Converts radians to degrees.</div>
@@ -83,7 +83,7 @@
 		<div>Random float in the interval [page:Float low] to [page:Float high].</div>
 		<div>Random float in the interval [page:Float low] to [page:Float high].</div>
 
 
 		<h3>[method:Float randFloatSpread]( [page:Float range] )</h3>
 		<h3>[method:Float randFloatSpread]( [page:Float range] )</h3>
-		<div>Random float in the intercal *- [page:Float range] / 2* to *[page:Float range] / 2*.</div>
+		<div>Random float in the interval *- [page:Float range] / 2* to *[page:Float range] / 2*.</div>
 
 
 		<h3>[method:Integer randInt]( [page:Integer low], [page:Integer high] )</h3>
 		<h3>[method:Integer randInt]( [page:Integer low], [page:Integer high] )</h3>
 		<div>Random integer in the interval [page:Float low] to [page:Float high].</div>
 		<div>Random integer in the interval [page:Float low] to [page:Float high].</div>

+ 6 - 6
docs/api/math/Quaternion.html

@@ -89,7 +89,7 @@
 
 
 		<h3>[method:Float dot]( [page:Quaternion v] )</h3>
 		<h3>[method:Float dot]( [page:Quaternion v] )</h3>
 		<div>
 		<div>
-			Calculate the [link:https://en.wikipedia.org/wiki/Dot_product dot product] of
+			Calculates the [link:https://en.wikipedia.org/wiki/Dot_product dot product] of
 			quaternions [page:Quaternion v] and this one.
 			quaternions [page:Quaternion v] and this one.
 		</div>
 		</div>
 
 
@@ -137,11 +137,11 @@
 		</div>
 		</div>
 
 
 		<h3>[method:Quaternion onChange]( [page:Function onChangeCallback] )</h3>
 		<h3>[method:Quaternion onChange]( [page:Function onChangeCallback] )</h3>
-		<div>Set the [page:.onChangeCallback onChangeCallback]() method.</div>
+		<div>Sets the [page:.onChangeCallback onChangeCallback]() method.</div>
 
 
 		<h3>[method:Quaternion onChangeCallback]( )</h3>
 		<h3>[method:Quaternion onChangeCallback]( )</h3>
 		<div>
 		<div>
-			This function is called whenever and of the following occur:
+			This function is called whenever any of the following occurs:
 			<ul>
 			<ul>
 				<li>
 				<li>
 					The [page:.x x], [page:.y y], [page:.z z] or
 					The [page:.x x], [page:.y y], [page:.z z] or
@@ -188,7 +188,7 @@
 		<div>
 		<div>
 		Sets this quaternion from rotation specified by [page:Vector3 axis] and [page:Float angle].<br />
 		Sets this quaternion from rotation specified by [page:Vector3 axis] and [page:Float angle].<br />
 		Adapted from the method [link:http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm here].<br />
 		Adapted from the method [link:http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm here].<br />
-		*Axis* is asumed to be normalized, *angle* is in radians.
+		*Axis* is assumed to be normalized, *angle* is in radians.
 		</div>
 		</div>
 
 
 		<h3>[method:Quaternion setFromEuler]( [page:Euler euler] )</h3>
 		<h3>[method:Quaternion setFromEuler]( [page:Euler euler] )</h3>
@@ -210,8 +210,8 @@
 
 
 		<h3>[method:Array toArray]( [page:Array array], [page:Integer offset] )</h3>
 		<h3>[method:Array toArray]( [page:Array array], [page:Integer offset] )</h3>
 		<div>
 		<div>
-		[page:Array array] - An optional array to store the quaternion. If not specified a new array will be created.<br/>
-		[page:Integer offset] - optional) if specified, the result will be copied
+		[page:Array array] - An optional array to store the quaternion. If not specified, a new array will be created.<br/>
+		[page:Integer offset] - (optional) if specified, the result will be copied
 		into this [page:Array].<br /><br />
 		into this [page:Array].<br /><br />
 
 
 		Returns the numerical elements of this quaternion in an array of format [x, y, z, w].
 		Returns the numerical elements of this quaternion in an array of format [x, y, z, w].

+ 20 - 21
docs/api/math/Vector2.html

@@ -54,7 +54,7 @@
 		[page:Float x] - the x value of the vector. Default is *0*.<br />
 		[page:Float x] - the x value of the vector. Default is *0*.<br />
 		[page:Float y] -  the y value of the vector. Default is *0*.<br /><br />
 		[page:Float y] -  the y value of the vector. Default is *0*.<br /><br />
 
 
-		Created a new [name].
+		Creates a new [name].
 		</div>
 		</div>
 
 
 
 
@@ -64,7 +64,7 @@
 		<div>
 		<div>
 			Used to check whether this or derived classes are Vector2s. Default is *true*.<br /><br />
 			Used to check whether this or derived classes are Vector2s. Default is *true*.<br /><br />
 
 
-			You should not change this, as it used internally for optimisation.
+			You should not change this, as it is used internally for optimisation.
 		</div>
 		</div>
 
 
 		<h3>[property:Float height]</h3>
 		<h3>[property:Float height]</h3>
@@ -84,7 +84,7 @@
 		<div>Adds [page:Vector2 v] to this vector.</div>
 		<div>Adds [page:Vector2 v] to this vector.</div>
 
 
 		<h3>[method:Vector2 addScalar]( [page:Float s] )</h3>
 		<h3>[method:Vector2 addScalar]( [page:Float s] )</h3>
-		<div>Add the scalar value s to this vector's [page:.x x] and [page:.y y] values.</div>
+		<div>Adds the scalar value [page:Float s] to this vector's [page:.x x] and [page:.y y] values.</div>
 
 
 		<h3>[method:Vector2 addScaledVector]( [page:Vector2 v], [page:Float s] )</h3>
 		<h3>[method:Vector2 addScaledVector]( [page:Vector2 v], [page:Float s] )</h3>
 		<div>Adds the multiple of [page:Vector2 v] and [page:Float s] to this vector.</div>
 		<div>Adds the multiple of [page:Vector2 v] and [page:Float s] to this vector.</div>
@@ -131,13 +131,13 @@
 
 
 		<h3>[method:Vector2 clone]()</h3>
 		<h3>[method:Vector2 clone]()</h3>
 		<div>
 		<div>
-		Returns a new vector2 with the same [page:.x x] and [page:.y y] values as this one.
+		Returns a new Vector2 with the same [page:.x x] and [page:.y y] values as this one.
 		</div>
 		</div>
 
 
 		<h3>[method:Vector2 copy]( [page:Vector2 v] )</h3>
 		<h3>[method:Vector2 copy]( [page:Vector2 v] )</h3>
 		<div>
 		<div>
-			Copies the values of the passed vector2's [page:.x x] and [page:.y y]
-			properties to this vector2.
+			Copies the values of the passed Vector2's [page:.x x] and [page:.y y]
+			properties to this Vector2.
 		</div>
 		</div>
 
 
 		<h3>[method:Float distanceTo]( [page:Vector2 v] )</h3>
 		<h3>[method:Float distanceTo]( [page:Vector2 v] )</h3>
@@ -166,7 +166,7 @@
 
 
 		<h3>[method:Float dot]( [page:Vector2 v] )</h3>
 		<h3>[method:Float dot]( [page:Vector2 v] )</h3>
 		<div>
 		<div>
-		Calculate the [link:https://en.wikipedia.org/wiki/Dot_product dot product] of this
+		Calculates the [link:https://en.wikipedia.org/wiki/Dot_product dot product] of this
 	  vector and [page:Vector2 v].
 	  vector and [page:Vector2 v].
 		</div>
 		</div>
 
 
@@ -179,9 +179,9 @@
 		<h3>[method:Vector2 fromArray]( [page:Array array], [page:Integer offset] )</h3>
 		<h3>[method:Vector2 fromArray]( [page:Array array], [page:Integer offset] )</h3>
 		<div>
 		<div>
 		[page:Array array] - the source array.<br />
 		[page:Array array] - the source array.<br />
-		[page:Integer offset] - ( optional) offset into the array. Default is 0.<br /><br />
+		[page:Integer offset] - (optional) offset into the array. Default is 0.<br /><br />
 
 
-		Sets this vector's [page:.x x] value to be array[0] and [page:.y y] value to be array[1].
+		Sets this vector's [page:.x x] value to be array[ offset ] and [page:.y y] value to be array[ offset + 1 ].
 		</div>
 		</div>
 
 
 		<h3>[method:Vector2 fromBufferAttribute]( [page:BufferAttribute attribute], [page:Integer index] )</h3>
 		<h3>[method:Vector2 fromBufferAttribute]( [page:BufferAttribute attribute], [page:Integer index] )</h3>
@@ -221,7 +221,7 @@
 		[page:Vector2 v] - [page:Vector2] to interpolate towards.<br />
 		[page:Vector2 v] - [page:Vector2] to interpolate towards.<br />
 		alpha - interpolation factor in the closed interval [0, 1].<br /><br />
 		alpha - interpolation factor in the closed interval [0, 1].<br /><br />
 
 
-		Linearly interpolate between this vector and [page:Vector2 v], where alpha is the
+		Linearly interpolates between this vector and [page:Vector2 v], where alpha is the
 		distance along the line - alpha = 0 will be this vector, and alpha = 1 will be [page:Vector2 v].
 		distance along the line - alpha = 0 will be this vector, and alpha = 1 will be [page:Vector2 v].
 		</div>
 		</div>
 
 
@@ -241,19 +241,19 @@
 
 
 		<h3>[method:Vector2 normalize]()</h3>
 		<h3>[method:Vector2 normalize]()</h3>
 		<div>
 		<div>
-		Convert this vector to a [link:https://en.wikipedia.org/wiki/Unit_vector unit vector] - that is, sets it equal to the vector with the same direction
+		Converts this vector to a [link:https://en.wikipedia.org/wiki/Unit_vector unit vector] - that is, sets it equal to the vector with the same direction
 		as this one, but [page:.length length] 1.
 		as this one, but [page:.length length] 1.
 		</div>
 		</div>
 
 
 		<h3>[method:Vector2 max]( [page:Vector2 v] )</h3>
 		<h3>[method:Vector2 max]( [page:Vector2 v] )</h3>
 		<div>
 		<div>
-		If this vector's x or y value is less than [page:Vector2 v's] x or y value, replace
+		If this vector's x or y value is less than [page:Vector2 v]'s x or y value, replace
 		that value with the corresponding max value.
 		that value with the corresponding max value.
 		</div>
 		</div>
 
 
 		<h3>[method:Vector2 min]( [page:Vector2 v] )</h3>
 		<h3>[method:Vector2 min]( [page:Vector2 v] )</h3>
 		<div>
 		<div>
-		If this vector's x or y value is greater than [page:Vector2 v's] x or y value, replace
+		If this vector's x or y value is greater than [page:Vector2 v]'s x or y value, replace
 		that value with the corresponding min value.
 		that value with the corresponding min value.
 		</div>
 		</div>
 
 
@@ -269,7 +269,7 @@
 			[page:Vector2 center] - the point around which to rotate.<br />
 			[page:Vector2 center] - the point around which to rotate.<br />
 			[page:float angle] - the angle to rotate, in radians.<br /><br />
 			[page:float angle] - the angle to rotate, in radians.<br /><br />
 
 
-			Rotate the vector arounf [page:Vector2 center] by [page:float angle] radians.
+			Rotates the vector around [page:Vector2 center] by [page:float angle] radians.
 		</div>
 		</div>
 
 
 		<h3>[method:Vector2 round]()</h3>
 		<h3>[method:Vector2 round]()</h3>
@@ -294,34 +294,33 @@
 
 
 		<h3>[method:Vector2 setLength]( [page:Float l] )</h3>
 		<h3>[method:Vector2 setLength]( [page:Float l] )</h3>
 		<div>
 		<div>
-		Set this vector to the vector with the same direction as this one, but [page:.length length]
+		Sets this vector to the vector with the same direction as this one, but [page:.length length]
 		[page:Float l].
 		[page:Float l].
 		</div>
 		</div>
 
 
 		<h3>[method:Vector2 setScalar]( [page:Float scalar] )</h3>
 		<h3>[method:Vector2 setScalar]( [page:Float scalar] )</h3>
 		<div>
 		<div>
-		Set the [page:.x x] and [page:.y y] values of this vector both equal to [page:Float scalar].
+		Sets the [page:.x x] and [page:.y y] values of this vector both equal to [page:Float scalar].
 		</div>
 		</div>
 
 
 		<h3>[method:Vector2 setX]( [page:Float x] )</h3>
 		<h3>[method:Vector2 setX]( [page:Float x] )</h3>
-		<div>Replace this vector's [page:.x x] value with [page:Float x].</div>
+		<div>Replaces this vector's [page:.x x] value with [page:Float x].</div>
 
 
 		<h3>[method:Vector2 setY]( [page:Float y] )</h3>
 		<h3>[method:Vector2 setY]( [page:Float y] )</h3>
-		<div>Replace this vector's [page:.y y] value with [page:Float y].</div>
+		<div>Replaces this vector's [page:.y y] value with [page:Float y].</div>
 
 
 		<h3>[method:Vector2 sub]( [page:Vector2 v] )</h3>
 		<h3>[method:Vector2 sub]( [page:Vector2 v] )</h3>
 		<div>Subtracts [page:Vector2 v] from this vector.</div>
 		<div>Subtracts [page:Vector2 v] from this vector.</div>
 
 
 		<h3>[method:Vector2 subScalar]( [page:Float s] )</h3>
 		<h3>[method:Vector2 subScalar]( [page:Float s] )</h3>
-		<div>Subtracts [page:Float s]  from this vector's [page:.x x] and [page:.y y] compnents.</div>
+		<div>Subtracts [page:Float s]  from this vector's [page:.x x] and [page:.y y] components.</div>
 
 
 		<h3>[method:Vector2 subVectors]( [page:Vector2 a], [page:Vector2 b] )</h3>
 		<h3>[method:Vector2 subVectors]( [page:Vector2 a], [page:Vector2 b] )</h3>
 		<div>Sets this vector to [page:Vector2 a] - [page:Vector2 b].</div>
 		<div>Sets this vector to [page:Vector2 a] - [page:Vector2 b].</div>
 
 
 		<h3>[method:Array toArray]( [page:Array array], [page:Integer offset] )</h3>
 		<h3>[method:Array toArray]( [page:Array array], [page:Integer offset] )</h3>
 		<div>
 		<div>
-		[page:Array array] - (optional) array to store the vector to. If this is not provided
-		a new array will be created.<br />
+		[page:Array array] - (optional) array to store the vector to. If this is not provided, a new array will be created.<br />
 		[page:Integer offset] - (optional) optional offset into the array.<br /><br />
 		[page:Integer offset] - (optional) optional offset into the array.<br /><br />
 
 
 		Returns an array [x, y], or copies x and y into the provided [page:Array array].
 		Returns an array [x, y], or copies x and y into the provided [page:Array array].

+ 5 - 5
docs/api/math/Vector3.html

@@ -65,7 +65,7 @@ var d = a.distanceTo( b );
 		<div>
 		<div>
 			Used to check whether this or derived classes are Vector3s. Default is *true*.<br /><br />
 			Used to check whether this or derived classes are Vector3s. Default is *true*.<br /><br />
 
 
-			You should not change this, as it used internally for optimisation.
+			You should not change this, as it is used internally for optimisation.
 		</div>
 		</div>
 
 
 		<h3>[property:Float x]</h3>
 		<h3>[property:Float x]</h3>
@@ -81,7 +81,7 @@ var d = a.distanceTo( b );
 		<div>Adds [page:Vector3 v] to this vector.</div>
 		<div>Adds [page:Vector3 v] to this vector.</div>
 
 
 		<h3>[method:Vector3 addScalar]( [page:Float s] )</h3>
 		<h3>[method:Vector3 addScalar]( [page:Float s] )</h3>
-		<div>Add the scalar value s to this vector's [page:.x x], [page:.y y] and [page:.z z] values.</div>
+		<div>Adds the scalar value s to this vector's [page:.x x], [page:.y y] and [page:.z z] values.</div>
 
 
 		<h3>[method:Vector3 addScaledVector]( [page:Vector3 v], [page:Float s] )</h3>
 		<h3>[method:Vector3 addScaledVector]( [page:Vector3 v], [page:Float s] )</h3>
 		<div>Adds the multiple of [page:Vector3 v] and [page:Float s] to this vector.</div>
 		<div>Adds the multiple of [page:Vector3 v] and [page:Float s] to this vector.</div>
@@ -104,7 +104,7 @@ var d = a.distanceTo( b );
 		</div>
 		</div>
 
 
 		<h3>[method:Vector3 applyMatrix3]( [page:Matrix3 m] )</h3>
 		<h3>[method:Vector3 applyMatrix3]( [page:Matrix3 m] )</h3>
-		<div>Multiply this vector by [page:Matrix3 m]</div>
+		<div>Multiplies this vector by [page:Matrix3 m]</div>
 
 
 		<h3>[method:Vector3 applyMatrix4]( [page:Matrix4 m] )</h3>
 		<h3>[method:Vector3 applyMatrix4]( [page:Matrix4 m] )</h3>
 		<div>
 		<div>
@@ -284,13 +284,13 @@ var d = a.distanceTo( b );
 
 
 		<h3>[method:Vector3 max]( [page:Vector3 v] )</h3>
 		<h3>[method:Vector3 max]( [page:Vector3 v] )</h3>
 		<div>
 		<div>
-		If this vector's x, y or z value is less than [page:Vector3 v's] x, y or z value, replace
+		If this vector's x, y or z value is less than [page:Vector3 v]'s x, y or z value, replace
 		that value with the corresponding max value.
 		that value with the corresponding max value.
 		</div>
 		</div>
 
 
 		<h3>[method:Vector3 min]( [page:Vector3 v] )</h3>
 		<h3>[method:Vector3 min]( [page:Vector3 v] )</h3>
 		<div>
 		<div>
-		If this vector's x, y or z value is greater than [page:Vector3 v's] x, y or z value, replace
+		If this vector's x, y or z value is greater than [page:Vector3 v]'s x, y or z value, replace
 		that value with the corresponding min value.
 		that value with the corresponding min value.
 		</div>
 		</div>
 
 

+ 18 - 19
docs/api/math/Vector4.html

@@ -22,7 +22,7 @@
 			<li>
 			<li>
 				A direction and length in 4D space. In three.js the length will always be the
 				A direction and length in 4D space. In three.js the length will always be the
 				[link:https://en.wikipedia.org/wiki/Euclidean_distance Euclidean distance]
 				[link:https://en.wikipedia.org/wiki/Euclidean_distance Euclidean distance]
-				(straight-line distance) from (0, 0, 0, 0, 0) to (x, y, z, w) and the direction is also
+				(straight-line distance) from (0, 0, 0, 0) to (x, y, z, w) and the direction is also
 				measured from (0, 0, 0, 0) towards (x, y, z, w).
 				measured from (0, 0, 0, 0) towards (x, y, z, w).
 			</li>
 			</li>
 			<li>
 			<li>
@@ -42,7 +42,7 @@ var a = new THREE.Vector4( 0, 1, 0, 0 );
 //no arguments; will be initialised to (0, 0, 0, 1)
 //no arguments; will be initialised to (0, 0, 0, 1)
 var b = new THREE.Vector4( );
 var b = new THREE.Vector4( );
 
 
-var d = a.distanceTo( b );
+var d = a.dot( b );
 		</code>
 		</code>
 
 
 
 
@@ -65,7 +65,7 @@ var d = a.distanceTo( b );
 		<div>
 		<div>
 			Used to check whether this or derived classes are Vector4s. Default is *true*.<br /><br />
 			Used to check whether this or derived classes are Vector4s. Default is *true*.<br /><br />
 
 
-			You should not change this, as it used internally for optimisation.
+			You should not change this, as it is used internally for optimisation.
 		</div>
 		</div>
 
 
 		<h3>[property:Float x]</h3>
 		<h3>[property:Float x]</h3>
@@ -83,7 +83,7 @@ var d = a.distanceTo( b );
 		<div>Adds [page:Vector4 v] to this vector.</div>
 		<div>Adds [page:Vector4 v] to this vector.</div>
 
 
 		<h3>[method:Vector4 addScalar]( [page:Float s] )</h3>
 		<h3>[method:Vector4 addScalar]( [page:Float s] )</h3>
-		<div>Add the scalar value s to this vector's [page:.x x], [page:.y y], [page:.z z] and [page:.w w] values.</div>
+		<div>Adds the scalar value s to this vector's [page:.x x], [page:.y y], [page:.z z] and [page:.w w] values.</div>
 
 
 		<h3>[method:Vector4 addScaledVector]( [page:Vector4 v], [page:Float s] )</h3>
 		<h3>[method:Vector4 addScaledVector]( [page:Vector4 v], [page:Float s] )</h3>
 		<div>Adds the multiple of [page:Vector4 v] and [page:Float s] to this vector.</div>
 		<div>Adds the multiple of [page:Vector4 v] and [page:Float s] to this vector.</div>
@@ -93,7 +93,7 @@ var d = a.distanceTo( b );
 
 
 		<h3>[method:Vector4 applyMatrix4]( [page:Matrix4 m] )</h3>
 		<h3>[method:Vector4 applyMatrix4]( [page:Matrix4 m] )</h3>
 		<div>
 		<div>
-		Multiply this vector by 4 x 4 [page:Matrix4 m].
+		Multiplies this vector by 4 x 4 [page:Matrix4 m].
 		</div>
 		</div>
 
 
 		<h3>[method:Vector4 ceil]()</h3>
 		<h3>[method:Vector4 ceil]()</h3>
@@ -138,7 +138,7 @@ var d = a.distanceTo( b );
 
 
 		<h3>[method:Float dot]( [page:Vector4 v] )</h3>
 		<h3>[method:Float dot]( [page:Vector4 v] )</h3>
 		<div>
 		<div>
-		Calculate the [link:https://en.wikipedia.org/wiki/Dot_product dot product] of this
+		Calculates the [link:https://en.wikipedia.org/wiki/Dot_product dot product] of this
 		vector and [page:Vector4 v].
 		vector and [page:Vector4 v].
 		</div>
 		</div>
 
 
@@ -151,7 +151,7 @@ var d = a.distanceTo( b );
 		<h3>[method:Vector4 fromArray]( [page:Array array], [page:Integer offset] )</h3>
 		<h3>[method:Vector4 fromArray]( [page:Array array], [page:Integer offset] )</h3>
 		<div>
 		<div>
 		[page:Array array] - the source array.<br />
 		[page:Array array] - the source array.<br />
-		[page:Integer offset] - ( optional) offset into the array. Default is 0.<br /><br />
+		[page:Integer offset] - (optional) offset into the array. Default is 0.<br /><br />
 
 
 		Sets this vector's [page:.x x] value to be array[ offset + 0 ], [page:.y y] value to be array[ offset + 1 ]
 		Sets this vector's [page:.x x] value to be array[ offset + 0 ], [page:.y y] value to be array[ offset + 1 ]
 		[page:.z z] value to be array[ offset + 2 ] and [page:.w w ] value to be array[ offset + 3 ].
 		[page:.z z] value to be array[ offset + 2 ] and [page:.w w ] value to be array[ offset + 3 ].
@@ -196,7 +196,7 @@ var d = a.distanceTo( b );
 		[page:Vector4 v] - [page:Vector4] to interpolate towards.<br />
 		[page:Vector4 v] - [page:Vector4] to interpolate towards.<br />
 		alpha - interpolation factor in the closed interval [0, 1].<br /><br />
 		alpha - interpolation factor in the closed interval [0, 1].<br /><br />
 
 
-		Linearly interpolate between this vector and [page:Vector4 v], where alpha is the
+		Linearly interpolates between this vector and [page:Vector4 v], where alpha is the
 		distance along the line - alpha = 0 will be this vector, and alpha = 1 will be [page:Vector4 v].
 		distance along the line - alpha = 0 will be this vector, and alpha = 1 will be [page:Vector4 v].
 		</div>
 		</div>
 
 
@@ -216,7 +216,7 @@ var d = a.distanceTo( b );
 
 
 		<h3>[method:Vector4 normalize]()</h3>
 		<h3>[method:Vector4 normalize]()</h3>
 		<div>
 		<div>
-		Convert this vector to a [link:https://en.wikipedia.org/wiki/Unit_vector unit vector] - that is, sets it equal to the vector with the same direction
+		Converts this vector to a [link:https://en.wikipedia.org/wiki/Unit_vector unit vector] - that is, sets it equal to the vector with the same direction
 		as this one, but [page:.length length] 1.
 		as this one, but [page:.length length] 1.
 		</div>
 		</div>
 
 
@@ -250,7 +250,7 @@ var d = a.distanceTo( b );
 		<div>
 		<div>
 			[page:Quaterion q] - a normalized [page:Quaterion]<br /><br />
 			[page:Quaterion q] - a normalized [page:Quaterion]<br /><br />
 
 
-			Set the [page:.x x], [page:.y y] and [page:.z z] components of this vector to the
+			Sets the [page:.x x], [page:.y y] and [page:.z z] components of this vector to the
 			quaternion's axis and [page:.w w] to the angle.
 			quaternion's axis and [page:.w w] to the angle.
 		</div>
 		</div>
 
 
@@ -258,7 +258,7 @@ var d = a.distanceTo( b );
 		<div>
 		<div>
 			 [page:Matrix4 m] - a [page:Matrix4] of which the upper left 3x3 matrix is a pure rotation matrix.<br /><br />
 			 [page:Matrix4 m] - a [page:Matrix4] of which the upper left 3x3 matrix is a pure rotation matrix.<br /><br />
 
 
-			Set the [page:.x x], [page:.y y] and [page:.z z] to the axis of rotation and [page:.w w] to the angle.
+			Sets the [page:.x x], [page:.y y] and [page:.z z] to the axis of rotation and [page:.w w] to the angle.
 		</div>
 		</div>
 
 
 		<h3>[method:null setComponent]( [page:Integer index], [page:Float value] )</h3>
 		<h3>[method:null setComponent]( [page:Integer index], [page:Float value] )</h3>
@@ -275,26 +275,26 @@ var d = a.distanceTo( b );
 
 
 		<h3>[method:Vector4 setLength]( [page:Float l] )</h3>
 		<h3>[method:Vector4 setLength]( [page:Float l] )</h3>
 		<div>
 		<div>
-		Set this vector to the vector with the same direction as this one, but [page:.length length]
+		Sets this vector to the vector with the same direction as this one, but [page:.length length]
 		[page:Float l].
 		[page:Float l].
 		</div>
 		</div>
 
 
 		<h3>[method:Vector4 setScalar]( [page:Float scalar] )</h3>
 		<h3>[method:Vector4 setScalar]( [page:Float scalar] )</h3>
 		<div>
 		<div>
-		Set the [page:.x x], [page:.y y], [page:.z z] and [page:.w w] values of this vector both equal to [page:Float scalar].
+		Sets the [page:.x x], [page:.y y], [page:.z z] and [page:.w w] values of this vector both equal to [page:Float scalar].
 		</div>
 		</div>
 
 
 		<h3>[method:Vector4 setX]( [page:Float x] )</h3>
 		<h3>[method:Vector4 setX]( [page:Float x] )</h3>
-		<div>Replace this vector's [page:.x x] value with [page:Float x].</div>
+		<div>Replaces this vector's [page:.x x] value with [page:Float x].</div>
 
 
 		<h3>[method:Vector4 setY]( [page:Float y] )</h3>
 		<h3>[method:Vector4 setY]( [page:Float y] )</h3>
-		<div>Replace this vector's [page:.y y] value with [page:Float y].</div>
+		<div>Replaces this vector's [page:.y y] value with [page:Float y].</div>
 
 
 		<h3>[method:Vector4 setZ]( [page:Float z] )</h3>
 		<h3>[method:Vector4 setZ]( [page:Float z] )</h3>
-		<div>Replace this vector's [page:.z z] value with [page:Float z].</div>
+		<div>Replaces this vector's [page:.z z] value with [page:Float z].</div>
 
 
 		<h3>[method:Vector4 setW]( [page:Float w] )</h3>
 		<h3>[method:Vector4 setW]( [page:Float w] )</h3>
-		<div>Replace this vector's [page:.w w] value with [page:Float w].</div>
+		<div>Replaces this vector's [page:.w w] value with [page:Float w].</div>
 
 
 		<h3>[method:Vector4 sub]( [page:Vector4 v] )</h3>
 		<h3>[method:Vector4 sub]( [page:Vector4 v] )</h3>
 		<div>Subtracts [page:Vector4 v] from this vector.</div>
 		<div>Subtracts [page:Vector4 v] from this vector.</div>
@@ -307,8 +307,7 @@ var d = a.distanceTo( b );
 
 
 		<h3>[method:Array toArray]( [page:Array array], [page:Integer offset] )</h3>
 		<h3>[method:Array toArray]( [page:Array array], [page:Integer offset] )</h3>
 		<div>
 		<div>
-		[page:Array array] - (optional) array to store the vector to. If this is not provided
-		a new array will be created.<br />
+		[page:Array array] - (optional) array to store the vector to. If this is not provided, a new array will be created.<br />
 		[page:Integer offset] - (optional) optional offset into the array.<br /><br />
 		[page:Integer offset] - (optional) optional offset into the array.<br /><br />
 
 
 		Returns an array [x, y, z, w], or copies x, y, z and w into the provided [page:Array array].
 		Returns an array [x, y, z, w], or copies x, y, z and w into the provided [page:Array array].

+ 2 - 2
docs/scenes/js/geometry.js

@@ -744,7 +744,7 @@ var guis = {
 
 
 		var folder = gui.addFolder( 'THREE.RingBufferGeometry' );
 		var folder = gui.addFolder( 'THREE.RingBufferGeometry' );
 
 
-		folder.add( data, 'innerRadius', 0, 30 ).onChange( generateGeometry );
+		folder.add( data, 'innerRadius', 1, 30 ).onChange( generateGeometry );
 		folder.add( data, 'outerRadius', 1, 30 ).onChange( generateGeometry );
 		folder.add( data, 'outerRadius', 1, 30 ).onChange( generateGeometry );
 		folder.add( data, 'thetaSegments', 1, 30 ).step( 1 ).onChange( generateGeometry );
 		folder.add( data, 'thetaSegments', 1, 30 ).step( 1 ).onChange( generateGeometry );
 		folder.add( data, 'phiSegments', 1, 30 ).step( 1 ).onChange( generateGeometry );
 		folder.add( data, 'phiSegments', 1, 30 ).step( 1 ).onChange( generateGeometry );
@@ -778,7 +778,7 @@ var guis = {
 
 
 		var folder = gui.addFolder( 'THREE.RingGeometry' );
 		var folder = gui.addFolder( 'THREE.RingGeometry' );
 
 
-		folder.add( data, 'innerRadius', 0, 30 ).onChange( generateGeometry );
+		folder.add( data, 'innerRadius', 1, 30 ).onChange( generateGeometry );
 		folder.add( data, 'outerRadius', 1, 30 ).onChange( generateGeometry );
 		folder.add( data, 'outerRadius', 1, 30 ).onChange( generateGeometry );
 		folder.add( data, 'thetaSegments', 1, 30 ).step( 1 ).onChange( generateGeometry );
 		folder.add( data, 'thetaSegments', 1, 30 ).step( 1 ).onChange( generateGeometry );
 		folder.add( data, 'phiSegments', 1, 30 ).step( 1 ).onChange( generateGeometry );
 		folder.add( data, 'phiSegments', 1, 30 ).step( 1 ).onChange( generateGeometry );

+ 8 - 0
examples/js/controls/OrbitControls.js

@@ -96,6 +96,14 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 
 	};
 	};
 
 
+	this.saveState = function () {
+
+		scope.target0.copy( scope.target );
+		scope.position0.copy( scope.object.position );
+		scope.zoom0 = scope.object.zoom;
+
+	};
+
 	this.reset = function () {
 	this.reset = function () {
 
 
 		scope.target.copy( scope.target0 );
 		scope.target.copy( scope.target0 );

+ 9 - 20
examples/js/loaders/GLTF2Loader.js

@@ -136,15 +136,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 			update: function ( scene, camera ) {
 			update: function ( scene, camera ) {
 
 
-				// update scene graph
-
-				scene.updateMatrixWorld();
-
-				// update camera matrices and frustum
-
-				camera.updateMatrixWorld();
-				camera.matrixWorldInverse.getInverse( camera.matrixWorld );
-
 				for ( var name in objects ) {
 				for ( var name in objects ) {
 
 
 					var object = objects[ name ];
 					var object = objects[ name ];
@@ -163,10 +154,6 @@ THREE.GLTF2Loader = ( function () {
 
 
 	}
 	}
 
 
-	/* GLTFSHADERS */
-
-	GLTF2Loader.Shaders = new GLTFRegistry();
-
 	/* GLTFSHADER */
 	/* GLTFSHADER */
 
 
 	function GLTFShader( targetNode, allNodes ) {
 	function GLTFShader( targetNode, allNodes ) {
@@ -1063,7 +1050,7 @@ THREE.GLTF2Loader = ( function () {
 
 
 			return _each( json.textures, function ( texture ) {
 			return _each( json.textures, function ( texture ) {
 
 
-				if ( texture.source ) {
+				if ( texture.source !== undefined ) {
 
 
 					return new Promise( function ( resolve ) {
 					return new Promise( function ( resolve ) {
 
 
@@ -1103,7 +1090,7 @@ THREE.GLTF2Loader = ( function () {
 
 
 							_texture.type = texture.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ texture.type ] : THREE.UnsignedByteType;
 							_texture.type = texture.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ texture.type ] : THREE.UnsignedByteType;
 
 
-							if ( texture.sampler ) {
+							if ( texture.sampler !== undefined ) {
 
 
 								var sampler = json.samplers[ texture.sampler ];
 								var sampler = json.samplers[ texture.sampler ];
 
 
@@ -1632,7 +1619,7 @@ THREE.GLTF2Loader = ( function () {
 
 
 						}
 						}
 
 
-						if ( primitive.indices ) {
+						if ( primitive.indices !== undefined ) {
 
 
 							geometry.setIndex( dependencies.accessors[ primitive.indices ] );
 							geometry.setIndex( dependencies.accessors[ primitive.indices ] );
 
 
@@ -1682,7 +1669,7 @@ THREE.GLTF2Loader = ( function () {
 
 
 						var meshNode;
 						var meshNode;
 
 
-						if ( primitive.indices ) {
+						if ( primitive.indices !== undefined ) {
 
 
 							geometry.setIndex( dependencies.accessors[ primitive.indices ] );
 							geometry.setIndex( dependencies.accessors[ primitive.indices ] );
 
 
@@ -1999,7 +1986,7 @@ THREE.GLTF2Loader = ( function () {
 
 
 								var skinEntry;
 								var skinEntry;
 
 
-								if ( node.skin ) {
+								if ( node.skin !== undefined ) {
 
 
 									skinEntry = dependencies.skins[ node.skin ];
 									skinEntry = dependencies.skins[ node.skin ];
 
 
@@ -2177,8 +2164,10 @@ THREE.GLTF2Loader = ( function () {
 					// Register raw material meshes with GLTF2Loader.Shaders
 					// Register raw material meshes with GLTF2Loader.Shaders
 					if ( child.material && child.material.isRawShaderMaterial ) {
 					if ( child.material && child.material.isRawShaderMaterial ) {
 
 
-						var xshader = new GLTFShader( child, dependencies.nodes );
-						GLTF2Loader.Shaders.add( child.uuid, xshader );
+						child.gltfShader = new GLTFShader( child, dependencies.nodes );
+						child.onBeforeRender = function(renderer, scene, camera){
+							this.gltfShader.update(scene, camera);
+						};
 
 
 					}
 					}
 
 

+ 14 - 13
examples/js/loaders/GLTFLoader.js

@@ -135,15 +135,6 @@ THREE.GLTFLoader = ( function () {
 
 
 			update: function ( scene, camera ) {
 			update: function ( scene, camera ) {
 
 
-				// update scene graph
-
-				scene.updateMatrixWorld();
-
-				// update camera matrices and frustum
-
-				camera.updateMatrixWorld();
-				camera.matrixWorldInverse.getInverse( camera.matrixWorld );
-
 				for ( var name in objects ) {
 				for ( var name in objects ) {
 
 
 					var object = objects[ name ];
 					var object = objects[ name ];
@@ -164,7 +155,15 @@ THREE.GLTFLoader = ( function () {
 
 
 	/* GLTFSHADERS */
 	/* GLTFSHADERS */
 
 
-	GLTFLoader.Shaders = new GLTFRegistry();
+	GLTFLoader.Shaders = {
+
+		update: function () {
+
+			console.warn( 'THREE.GLTFLoader.Shaders has been deprecated, and now updates automatically.' );
+
+		}
+
+	};
 
 
 	/* GLTFSHADER */
 	/* GLTFSHADER */
 
 
@@ -1109,7 +1108,7 @@ THREE.GLTFLoader = ( function () {
 							if ( texture.internalFormat !== undefined && _texture.format !== WEBGL_TEXTURE_FORMATS[ texture.internalFormat ] ) {
 							if ( texture.internalFormat !== undefined && _texture.format !== WEBGL_TEXTURE_FORMATS[ texture.internalFormat ] ) {
 
 
 								console.warn( 'THREE.GLTFLoader: Three.js doesn\'t support texture internalFormat which is different from texture format. ' +
 								console.warn( 'THREE.GLTFLoader: Three.js doesn\'t support texture internalFormat which is different from texture format. ' +
-								              'internalFormat will be forced to be the same value as format.' );
+															'internalFormat will be forced to be the same value as format.' );
 
 
 							}
 							}
 
 
@@ -2175,8 +2174,10 @@ THREE.GLTFLoader = ( function () {
 					// Register raw material meshes with GLTFLoader.Shaders
 					// Register raw material meshes with GLTFLoader.Shaders
 					if ( child.material && child.material.isRawShaderMaterial ) {
 					if ( child.material && child.material.isRawShaderMaterial ) {
 
 
-						var xshader = new GLTFShader( child, dependencies.nodes );
-						GLTFLoader.Shaders.add( child.uuid, xshader );
+						child.gltfShader = new GLTFShader( child, dependencies.nodes );
+						child.onBeforeRender = function(renderer, scene, camera){
+							this.gltfShader.update(scene, camera);
+						};
 
 
 					}
 					}
 
 

+ 72 - 81
examples/js/renderers/CanvasRenderer.js

@@ -9,7 +9,7 @@ THREE.SpriteCanvasMaterial = function ( parameters ) {
 	this.type = 'SpriteCanvasMaterial';
 	this.type = 'SpriteCanvasMaterial';
 
 
 	this.color = new THREE.Color( 0xffffff );
 	this.color = new THREE.Color( 0xffffff );
-	this.program = function ( context, color ) {};
+	this.program = function () {};
 
 
 	this.setValues( parameters );
 	this.setValues( parameters );
 
 
@@ -17,6 +17,7 @@ THREE.SpriteCanvasMaterial = function ( parameters ) {
 
 
 THREE.SpriteCanvasMaterial.prototype = Object.create( THREE.Material.prototype );
 THREE.SpriteCanvasMaterial.prototype = Object.create( THREE.Material.prototype );
 THREE.SpriteCanvasMaterial.prototype.constructor = THREE.SpriteCanvasMaterial;
 THREE.SpriteCanvasMaterial.prototype.constructor = THREE.SpriteCanvasMaterial;
+THREE.SpriteCanvasMaterial.prototype.isSpriteCanvasMaterial = true;
 
 
 THREE.SpriteCanvasMaterial.prototype.clone = function () {
 THREE.SpriteCanvasMaterial.prototype.clone = function () {
 
 
@@ -39,78 +40,69 @@ THREE.CanvasRenderer = function ( parameters ) {
 	parameters = parameters || {};
 	parameters = parameters || {};
 
 
 	var _this = this,
 	var _this = this,
-	_renderData, _elements, _lights,
-	_projector = new THREE.Projector(),
+		_renderData, _elements, _lights,
+		_projector = new THREE.Projector(),
 
 
-	_canvas = parameters.canvas !== undefined
-			 ? parameters.canvas
-			 : document.createElement( 'canvas' ),
+		_canvas = parameters.canvas !== undefined
+				 ? parameters.canvas
+				 : document.createElement( 'canvas' ),
 
 
-	_canvasWidth = _canvas.width,
-	_canvasHeight = _canvas.height,
-	_canvasWidthHalf = Math.floor( _canvasWidth / 2 ),
-	_canvasHeightHalf = Math.floor( _canvasHeight / 2 ),
+		_canvasWidth = _canvas.width,
+		_canvasHeight = _canvas.height,
+		_canvasWidthHalf = Math.floor( _canvasWidth / 2 ),
+		_canvasHeightHalf = Math.floor( _canvasHeight / 2 ),
 
 
-	_viewportX = 0,
-	_viewportY = 0,
-	_viewportWidth = _canvasWidth,
-	_viewportHeight = _canvasHeight,
+		_viewportX = 0,
+		_viewportY = 0,
+		_viewportWidth = _canvasWidth,
+		_viewportHeight = _canvasHeight,
 
 
-	_pixelRatio = 1,
+		_pixelRatio = 1,
 
 
-	_context = _canvas.getContext( '2d', {
-		alpha: parameters.alpha === true
-	} ),
+		_context = _canvas.getContext( '2d', {
+			alpha: parameters.alpha === true
+		} ),
 
 
-	_clearColor = new THREE.Color( 0x000000 ),
-	_clearAlpha = parameters.alpha === true ? 0 : 1,
+		_clearColor = new THREE.Color( 0x000000 ),
+		_clearAlpha = parameters.alpha === true ? 0 : 1,
 
 
-	_contextGlobalAlpha = 1,
-	_contextGlobalCompositeOperation = 0,
-	_contextStrokeStyle = null,
-	_contextFillStyle = null,
-	_contextLineWidth = null,
-	_contextLineCap = null,
-	_contextLineJoin = null,
-	_contextLineDash = [],
+		_contextGlobalAlpha = 1,
+		_contextGlobalCompositeOperation = 0,
+		_contextStrokeStyle = null,
+		_contextFillStyle = null,
+		_contextLineWidth = null,
+		_contextLineCap = null,
+		_contextLineJoin = null,
+		_contextLineDash = [],
 
 
-	_camera,
+		_v1, _v2, _v3,
 
 
-	_v1, _v2, _v3, _v4,
-	_v5 = new THREE.RenderableVertex(),
-	_v6 = new THREE.RenderableVertex(),
+		_v1x, _v1y, _v2x, _v2y, _v3x, _v3y,
 
 
-	_v1x, _v1y, _v2x, _v2y, _v3x, _v3y,
-	_v4x, _v4y, _v5x, _v5y, _v6x, _v6y,
+		_color = new THREE.Color(),
 
 
-	_color = new THREE.Color(),
-	_color1 = new THREE.Color(),
-	_color2 = new THREE.Color(),
-	_color3 = new THREE.Color(),
-	_color4 = new THREE.Color(),
+		_diffuseColor = new THREE.Color(),
+		_emissiveColor = new THREE.Color(),
 
 
-	_diffuseColor = new THREE.Color(),
-	_emissiveColor = new THREE.Color(),
+		_lightColor = new THREE.Color(),
 
 
-	_lightColor = new THREE.Color(),
+		_patterns = {},
 
 
-	_patterns = {},
+		_uvs,
+		_uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y,
 
 
-	_image, _uvs,
-	_uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y,
+		_clipBox = new THREE.Box2(),
+		_clearBox = new THREE.Box2(),
+		_elemBox = new THREE.Box2(),
 
 
-	_clipBox = new THREE.Box2(),
-	_clearBox = new THREE.Box2(),
-	_elemBox = new THREE.Box2(),
+		_ambientLight = new THREE.Color(),
+		_directionalLights = new THREE.Color(),
+		_pointLights = new THREE.Color(),
 
 
-	_ambientLight = new THREE.Color(),
-	_directionalLights = new THREE.Color(),
-	_pointLights = new THREE.Color(),
-
-	_vector3 = new THREE.Vector3(), // Needed for PointLight
-	_centroid = new THREE.Vector3(),
-	_normal = new THREE.Vector3(),
-	_normalViewMatrix = new THREE.Matrix3();
+		_vector3 = new THREE.Vector3(), // Needed for PointLight
+		_centroid = new THREE.Vector3(),
+		_normal = new THREE.Vector3(),
+		_normalViewMatrix = new THREE.Matrix3();
 
 
 	/* TODO
 	/* TODO
 	_canvas.mozImageSmoothingEnabled = false;
 	_canvas.mozImageSmoothingEnabled = false;
@@ -266,10 +258,10 @@ THREE.CanvasRenderer = function ( parameters ) {
 			_clearBox.intersect( _clipBox );
 			_clearBox.intersect( _clipBox );
 			_clearBox.expandByScalar( 2 );
 			_clearBox.expandByScalar( 2 );
 
 
-			_clearBox.min.x = _clearBox.min.x + _canvasWidthHalf;
-			_clearBox.min.y =  - _clearBox.min.y + _canvasHeightHalf;		// higher y value !
-			_clearBox.max.x = _clearBox.max.x + _canvasWidthHalf;
-			_clearBox.max.y =  - _clearBox.max.y + _canvasHeightHalf;		// lower y value !
+			_clearBox.min.x =   _clearBox.min.x + _canvasWidthHalf;
+			_clearBox.min.y = - _clearBox.min.y + _canvasHeightHalf;		// higher y value !
+			_clearBox.max.x =   _clearBox.max.x + _canvasWidthHalf;
+			_clearBox.max.y = - _clearBox.max.y + _canvasHeightHalf;		// lower y value !
 
 
 			if ( _clearAlpha < 1 ) {
 			if ( _clearAlpha < 1 ) {
 
 
@@ -312,7 +304,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 	this.render = function ( scene, camera ) {
 	this.render = function ( scene, camera ) {
 
 
-		if ( camera instanceof THREE.Camera === false ) {
+		if ( camera.isCamera === undefined ) {
 
 
 			console.error( 'THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.' );
 			console.error( 'THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.' );
 			return;
 			return;
@@ -341,7 +333,6 @@ THREE.CanvasRenderer = function ( parameters ) {
 		_renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );
 		_renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );
 		_elements = _renderData.elements;
 		_elements = _renderData.elements;
 		_lights = _renderData.lights;
 		_lights = _renderData.lights;
-		_camera = camera;
 
 
 		_normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse );
 		_normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse );
 
 
@@ -454,17 +445,17 @@ THREE.CanvasRenderer = function ( parameters ) {
 			var light = _lights[ l ];
 			var light = _lights[ l ];
 			var lightColor = light.color;
 			var lightColor = light.color;
 
 
-			if ( light instanceof THREE.AmbientLight ) {
+			if ( light.isAmbientLight ) {
 
 
 				_ambientLight.add( lightColor );
 				_ambientLight.add( lightColor );
 
 
-			} else if ( light instanceof THREE.DirectionalLight ) {
+			} else if ( light.isDirectionalLight ) {
 
 
 				// for sprites
 				// for sprites
 
 
 				_directionalLights.add( lightColor );
 				_directionalLights.add( lightColor );
 
 
-			} else if ( light instanceof THREE.PointLight ) {
+			} else if ( light.isPointLight ) {
 
 
 				// for sprites
 				// for sprites
 
 
@@ -484,7 +475,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 			_lightColor.copy( light.color );
 			_lightColor.copy( light.color );
 
 
-			if ( light instanceof THREE.DirectionalLight ) {
+			if ( light.isDirectionalLight ) {
 
 
 				var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize();
 				var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld ).normalize();
 
 
@@ -496,7 +487,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 				color.add( _lightColor.multiplyScalar( amount ) );
 				color.add( _lightColor.multiplyScalar( amount ) );
 
 
-			} else if ( light instanceof THREE.PointLight ) {
+			} else if ( light.isPointLight ) {
 
 
 				var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld );
 				var lightPosition = _vector3.setFromMatrixPosition( light.matrixWorld );
 
 
@@ -530,7 +521,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 		_elemBox.min.set( v1.x - dist, v1.y - dist );
 		_elemBox.min.set( v1.x - dist, v1.y - dist );
 		_elemBox.max.set( v1.x + dist, v1.y + dist );
 		_elemBox.max.set( v1.x + dist, v1.y + dist );
 
 
-		if ( material instanceof THREE.SpriteMaterial ) {
+		if ( material.isSpriteMaterial ) {
 
 
 			var texture = material.map;
 			var texture = material.map;
 
 
@@ -586,7 +577,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 			}
 			}
 
 
-		} else if ( material instanceof THREE.SpriteCanvasMaterial ) {
+		} else if ( material.isSpriteCanvasMaterial ) {
 
 
 			setStrokeStyle( material.color.getStyle() );
 			setStrokeStyle( material.color.getStyle() );
 			setFillStyle( material.color.getStyle() );
 			setFillStyle( material.color.getStyle() );
@@ -623,7 +614,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 		_context.moveTo( v1.positionScreen.x, v1.positionScreen.y );
 		_context.moveTo( v1.positionScreen.x, v1.positionScreen.y );
 		_context.lineTo( v2.positionScreen.x, v2.positionScreen.y );
 		_context.lineTo( v2.positionScreen.x, v2.positionScreen.y );
 
 
-		if ( material instanceof THREE.LineBasicMaterial ) {
+		if ( material.isLineBasicMaterial ) {
 
 
 			setLineWidth( material.linewidth );
 			setLineWidth( material.linewidth );
 			setLineCap( material.linecap );
 			setLineCap( material.linecap );
@@ -670,7 +661,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 			_context.stroke();
 			_context.stroke();
 			_elemBox.expandByScalar( material.linewidth * 2 );
 			_elemBox.expandByScalar( material.linewidth * 2 );
 
 
-		} else if ( material instanceof THREE.LineDashedMaterial ) {
+		} else if ( material.isLineDashedMaterial ) {
 
 
 			setLineWidth( material.linewidth );
 			setLineWidth( material.linewidth );
 			setLineCap( material.linecap );
 			setLineCap( material.linecap );
@@ -702,7 +693,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 		drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y );
 		drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y );
 
 
-		if ( ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) && material.map === null ) {
+		if ( ( material.isMeshLambertMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial ) && material.map === null ) {
 
 
 			_diffuseColor.copy( material.color );
 			_diffuseColor.copy( material.color );
 			_emissiveColor.copy( material.emissive );
 			_emissiveColor.copy( material.emissive );
@@ -725,9 +716,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 				 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
 				 ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin )
 				 : fillPath( _color );
 				 : fillPath( _color );
 
 
-		} else if ( material instanceof THREE.MeshBasicMaterial ||
-				    material instanceof THREE.MeshLambertMaterial ||
-				    material instanceof THREE.MeshPhongMaterial ) {
+		} else if ( material.isMeshBasicMaterial || material.isMeshLambertMaterial || material.isMeshPhongMaterial || material.isMeshStandardMaterial ) {
 
 
 			if ( material.map !== null ) {
 			if ( material.map !== null ) {
 
 
@@ -776,7 +765,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 			}
 			}
 
 
-		} else if ( material instanceof THREE.MeshNormalMaterial ) {
+		} else if ( material.isMeshNormalMaterial ) {
 
 
 			_normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix );
 			_normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix );
 
 
@@ -944,10 +933,10 @@ THREE.CanvasRenderer = function ( parameters ) {
 		// http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
 		// http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
 
 
 		var a, b, c, d, e, f, det, idet,
 		var a, b, c, d, e, f, det, idet,
-		offsetX = texture.offset.x / texture.repeat.x,
-		offsetY = texture.offset.y / texture.repeat.y,
-		width = texture.image.width * texture.repeat.x,
-		height = texture.image.height * texture.repeat.y;
+			offsetX = texture.offset.x / texture.repeat.x,
+			offsetY = texture.offset.y / texture.repeat.y,
+			width = texture.image.width * texture.repeat.x,
+			height = texture.image.height * texture.repeat.y;
 
 
 		u0 = ( u0 + offsetX ) * width;
 		u0 = ( u0 + offsetX ) * width;
 		v0 = ( v0 + offsetY ) * height;
 		v0 = ( v0 + offsetY ) * height;
@@ -985,6 +974,7 @@ THREE.CanvasRenderer = function ( parameters ) {
 
 
 	}
 	}
 
 
+	/*
 	function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) {
 	function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) {
 
 
 		// http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
 		// http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
@@ -1022,13 +1012,14 @@ THREE.CanvasRenderer = function ( parameters ) {
 		_context.restore();
 		_context.restore();
 
 
 	}
 	}
+	*/
 
 
 	// Hide anti-alias gaps
 	// Hide anti-alias gaps
 
 
 	function expand( v1, v2, pixels ) {
 	function expand( v1, v2, pixels ) {
 
 
 		var x = v2.x - v1.x, y = v2.y - v1.y,
 		var x = v2.x - v1.x, y = v2.y - v1.y,
-		det = x * x + y * y, idet;
+			det = x * x + y * y, idet;
 
 
 		if ( det === 0 ) return;
 		if ( det === 0 ) return;
 
 

+ 75 - 35
examples/js/renderers/Projector.js

@@ -99,33 +99,32 @@ THREE.RenderableSprite = function () {
 THREE.Projector = function () {
 THREE.Projector = function () {
 
 
 	var _object, _objectCount, _objectPool = [], _objectPoolLength = 0,
 	var _object, _objectCount, _objectPool = [], _objectPoolLength = 0,
-	_vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0,
-	_face, _faceCount, _facePool = [], _facePoolLength = 0,
-	_line, _lineCount, _linePool = [], _linePoolLength = 0,
-	_sprite, _spriteCount, _spritePool = [], _spritePoolLength = 0,
+		_vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0,
+		_face, _faceCount, _facePool = [], _facePoolLength = 0,
+		_line, _lineCount, _linePool = [], _linePoolLength = 0,
+		_sprite, _spriteCount, _spritePool = [], _spritePoolLength = 0,
 
 
-	_renderData = { objects: [], lights: [], elements: [] },
+		_renderData = { objects: [], lights: [], elements: [] },
 
 
-	_vector3 = new THREE.Vector3(),
-	_vector4 = new THREE.Vector4(),
+		_vector3 = new THREE.Vector3(),
+		_vector4 = new THREE.Vector4(),
 
 
-	_clipBox = new THREE.Box3( new THREE.Vector3( - 1, - 1, - 1 ), new THREE.Vector3( 1, 1, 1 ) ),
-	_boundingBox = new THREE.Box3(),
-	_points3 = new Array( 3 ),
-	_points4 = new Array( 4 ),
+		_clipBox = new THREE.Box3( new THREE.Vector3( - 1, - 1, - 1 ), new THREE.Vector3( 1, 1, 1 ) ),
+		_boundingBox = new THREE.Box3(),
+		_points3 = new Array( 3 ),
 
 
-	_viewMatrix = new THREE.Matrix4(),
-	_viewProjectionMatrix = new THREE.Matrix4(),
+		_viewMatrix = new THREE.Matrix4(),
+		_viewProjectionMatrix = new THREE.Matrix4(),
 
 
-	_modelMatrix,
-	_modelViewProjectionMatrix = new THREE.Matrix4(),
+		_modelMatrix,
+		_modelViewProjectionMatrix = new THREE.Matrix4(),
 
 
-	_normalMatrix = new THREE.Matrix3(),
+		_normalMatrix = new THREE.Matrix3(),
 
 
-	_frustum = new THREE.Frustum(),
+		_frustum = new THREE.Frustum(),
 
 
-	_clippedVertex1PositionScreen = new THREE.Vector4(),
-	_clippedVertex2PositionScreen = new THREE.Vector4();
+		_clippedVertex1PositionScreen = new THREE.Vector4(),
+		_clippedVertex2PositionScreen = new THREE.Vector4();
 
 
 	//
 	//
 
 
@@ -143,7 +142,7 @@ THREE.Projector = function () {
 
 
 	};
 	};
 
 
-	this.pickingRay = function ( vector, camera ) {
+	this.pickingRay = function () {
 
 
 		console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
 		console.error( 'THREE.Projector: .pickingRay() is now raycaster.setFromCamera().' );
 
 
@@ -154,6 +153,7 @@ THREE.Projector = function () {
 	var RenderList = function () {
 	var RenderList = function () {
 
 
 		var normals = [];
 		var normals = [];
+		var colors = [];
 		var uvs = [];
 		var uvs = [];
 
 
 		var object = null;
 		var object = null;
@@ -169,6 +169,7 @@ THREE.Projector = function () {
 			normalMatrix.getNormalMatrix( object.matrixWorld );
 			normalMatrix.getNormalMatrix( object.matrixWorld );
 
 
 			normals.length = 0;
 			normals.length = 0;
+			colors.length = 0;
 			uvs.length = 0;
 			uvs.length = 0;
 
 
 		}
 		}
@@ -209,6 +210,12 @@ THREE.Projector = function () {
 
 
 		}
 		}
 
 
+		function pushColor( r, g, b ) {
+
+			colors.push( r, g, b );
+
+		}
+
 		function pushUv( x, y ) {
 		function pushUv( x, y ) {
 
 
 			uvs.push( x, y );
 			uvs.push( x, y );
@@ -241,17 +248,36 @@ THREE.Projector = function () {
 			var v1 = _vertexPool[ a ];
 			var v1 = _vertexPool[ a ];
 			var v2 = _vertexPool[ b ];
 			var v2 = _vertexPool[ b ];
 
 
-			_line = getNextLineInPool();
+			// Clip
+
+			v1.positionScreen.copy( v1.position ).applyMatrix4( _modelViewProjectionMatrix );
+			v2.positionScreen.copy( v2.position ).applyMatrix4( _modelViewProjectionMatrix );
+
+			if ( clipLine( v1.positionScreen, v2.positionScreen ) === true ) {
+
+				// Perform the perspective divide
+				v1.positionScreen.multiplyScalar( 1 / v1.positionScreen.w );
+				v2.positionScreen.multiplyScalar( 1 / v2.positionScreen.w );
 
 
-			_line.id = object.id;
-			_line.v1.copy( v1 );
-			_line.v2.copy( v2 );
-			_line.z = ( v1.positionScreen.z + v2.positionScreen.z ) / 2;
-			_line.renderOrder = object.renderOrder;
+				_line = getNextLineInPool();
+				_line.id = object.id;
+				_line.v1.copy( v1 );
+				_line.v2.copy( v2 );
+				_line.z = Math.max( v1.positionScreen.z, v2.positionScreen.z );
+				_line.renderOrder = object.renderOrder;
 
 
-			_line.material = object.material;
+				_line.material = object.material;
 
 
-			_renderData.elements.push( _line );
+				if ( object.material.vertexColors === THREE.VertexColors ) {
+
+					_line.vertexColors[ 0 ].fromArray( colors, a * 3 );
+					_line.vertexColors[ 1 ].fromArray( colors, b * 3 );
+
+				}
+
+				_renderData.elements.push( _line );
+
+			}
 
 
 		}
 		}
 
 
@@ -307,10 +333,11 @@ THREE.Projector = function () {
 			checkBackfaceCulling: checkBackfaceCulling,
 			checkBackfaceCulling: checkBackfaceCulling,
 			pushVertex: pushVertex,
 			pushVertex: pushVertex,
 			pushNormal: pushNormal,
 			pushNormal: pushNormal,
+			pushColor: pushColor,
 			pushUv: pushUv,
 			pushUv: pushUv,
 			pushLine: pushLine,
 			pushLine: pushLine,
 			pushTriangle: pushTriangle
 			pushTriangle: pushTriangle
-		}
+		};
 
 
 	};
 	};
 
 
@@ -609,6 +636,8 @@ THREE.Projector = function () {
 
 
 			} else if ( object instanceof THREE.Line ) {
 			} else if ( object instanceof THREE.Line ) {
 
 
+				_modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
+
 				if ( geometry instanceof THREE.BufferGeometry ) {
 				if ( geometry instanceof THREE.BufferGeometry ) {
 
 
 					var attributes = geometry.attributes;
 					var attributes = geometry.attributes;
@@ -623,6 +652,18 @@ THREE.Projector = function () {
 
 
 						}
 						}
 
 
+						if ( attributes.color !== undefined ) {
+
+							var colors = attributes.color.array;
+
+							for ( var i = 0, l = colors.length; i < l; i += 3 ) {
+
+								renderList.pushColor( colors[ i ], colors[ i + 1 ], colors[ i + 2 ] );
+
+							}
+
+						}
+
 						if ( geometry.index !== null ) {
 						if ( geometry.index !== null ) {
 
 
 							var indices = geometry.index.array;
 							var indices = geometry.index.array;
@@ -649,8 +690,6 @@ THREE.Projector = function () {
 
 
 				} else if ( geometry instanceof THREE.Geometry ) {
 				} else if ( geometry instanceof THREE.Geometry ) {
 
 
-					_modelViewProjectionMatrix.multiplyMatrices( _viewProjectionMatrix, _modelMatrix );
-
 					var vertices = object.geometry.vertices;
 					var vertices = object.geometry.vertices;
 
 
 					if ( vertices.length === 0 ) continue;
 					if ( vertices.length === 0 ) continue;
@@ -861,10 +900,11 @@ THREE.Projector = function () {
 
 
 		// Calculate the boundary coordinate of each vertex for the near and far clip planes,
 		// Calculate the boundary coordinate of each vertex for the near and far clip planes,
 		// Z = -1 and Z = +1, respectively.
 		// Z = -1 and Z = +1, respectively.
-		bc1near =  s1.z + s1.w,
-		bc2near =  s2.z + s2.w,
-		bc1far =  - s1.z + s1.w,
-		bc2far =  - s2.z + s2.w;
+
+			bc1near = s1.z + s1.w,
+			bc2near = s2.z + s2.w,
+			bc1far = - s1.z + s1.w,
+			bc2far = - s2.z + s2.w;
 
 
 		if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) {
 		if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) {
 
 

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 12 - 0
examples/models/json/suzanne.json


+ 0 - 2
examples/webgl_effects_peppersghost.html

@@ -125,8 +125,6 @@
 
 
 		function render() {
 		function render() {
 
 
-				camera.lookAt( scene.position );
-
 				group.rotation.y += 0.01;
 				group.rotation.y += 0.01;
 
 
 				effect.render( scene, camera );
 				effect.render( scene, camera );

+ 1 - 3
examples/webgl_loader_gltf.html

@@ -202,8 +202,7 @@
 					scene.add(ground);
 					scene.add(ground);
 				}
 				}
 
 
-				THREE.GLTF2Loader.Shaders.removeAll(); // remove all previous shaders
-				loader = new THREE.GLTF2Loader;
+				loader = new THREE.GLTF2Loader();
 
 
 				for (var i = 0; i < extensionSelect.children.length; i++) {
 				for (var i = 0; i < extensionSelect.children.length; i++) {
 					var child = extensionSelect.children[i];
 					var child = extensionSelect.children[i];
@@ -338,7 +337,6 @@
 			function animate() {
 			function animate() {
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
 				if (mixer) mixer.update(clock.getDelta());
 				if (mixer) mixer.update(clock.getDelta());
-				THREE.GLTF2Loader.Shaders.update(scene, camera);
 				if (cameraIndex == 0)
 				if (cameraIndex == 0)
 					orbitControls.update();
 					orbitControls.update();
 				render();
 				render();

+ 2 - 2
examples/webgl_performance.html

@@ -52,8 +52,8 @@
 
 
 				var material = new THREE.MeshNormalMaterial();
 				var material = new THREE.MeshNormalMaterial();
 
 
-				var loader = new THREE.JSONLoader();
-				loader.load( 'obj/Suzanne.js', function ( geometry ) {
+				var loader = new THREE.BufferGeometryLoader();
+				loader.load( 'models/json/suzanne.json', function ( geometry ) {
 
 
 					geometry.computeVertexNormals();
 					geometry.computeVertexNormals();
 
 

+ 2 - 2
examples/webgl_performance_static.html

@@ -50,8 +50,8 @@
 
 
 				var material = new THREE.MeshNormalMaterial();
 				var material = new THREE.MeshNormalMaterial();
 
 
-				var loader = new THREE.JSONLoader();
-				loader.load( 'obj/Suzanne.js', function ( geometry ) {
+				var loader = new THREE.BufferGeometryLoader();
+				loader.load( 'models/json/suzanne.json', function ( geometry ) {
 
 
 					geometry.computeVertexNormals();
 					geometry.computeVertexNormals();
 
 

+ 1 - 1
package.json

@@ -33,7 +33,7 @@
     "build-closure": "rollup -c && java -jar utils/build/compiler/closure-compiler-v20160713.jar --warning_level=VERBOSE --jscomp_off=globalThis --jscomp_off=checkTypes --externs utils/build/externs.js --language_in=ECMASCRIPT5_STRICT --js build/three.js --js_output_file build/three.min.js",
     "build-closure": "rollup -c && java -jar utils/build/compiler/closure-compiler-v20160713.jar --warning_level=VERBOSE --jscomp_off=globalThis --jscomp_off=checkTypes --externs utils/build/externs.js --language_in=ECMASCRIPT5_STRICT --js build/three.js --js_output_file build/three.min.js",
     "dev": "rollup -c -w",
     "dev": "rollup -c -w",
     "lint": "eslint src",
     "lint": "eslint src",
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "test": "rollup -c test/rollup.unit.config.js -w"
   },
   },
   "keywords": [
   "keywords": [
     "three",
     "three",

+ 0 - 16
src/cameras/Camera.js

@@ -41,22 +41,6 @@ Camera.prototype.getWorldDirection = function () {
 
 
 }();
 }();
 
 
-Camera.prototype.lookAt = function () {
-
-	// This routine does not support cameras with rotated and/or translated parent(s)
-
-	var m1 = new Matrix4();
-
-	return function lookAt( vector ) {
-
-		m1.lookAt( this.position, vector, this.up );
-
-		this.quaternion.setFromRotationMatrix( m1 );
-
-	};
-
-}();
-
 Camera.prototype.clone = function () {
 Camera.prototype.clone = function () {
 
 
 	return new this.constructor().copy( this );
 	return new this.constructor().copy( this );

+ 4 - 0
src/core/BufferAttribute.js

@@ -8,6 +8,8 @@ import { _Math } from '../math/Math';
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
+var bufferAttributeId = 0;
+
 function BufferAttribute( array, itemSize, normalized ) {
 function BufferAttribute( array, itemSize, normalized ) {
 
 
 	if ( Array.isArray( array ) ) {
 	if ( Array.isArray( array ) ) {
@@ -16,6 +18,8 @@ function BufferAttribute( array, itemSize, normalized ) {
 
 
 	}
 	}
 
 
+	Object.defineProperty( this, 'id', { value: bufferAttributeId ++ } );
+
 	this.uuid = _Math.generateUUID();
 	this.uuid = _Math.generateUUID();
 
 
 	this.array = array;
 	this.array = array;

+ 5 - 5
src/core/Layers.js

@@ -4,7 +4,7 @@
 
 
 function Layers() {
 function Layers() {
 
 
-	this.mask = 1;
+	this.mask = 1 | 0;
 
 
 }
 }
 
 
@@ -12,25 +12,25 @@ Object.assign( Layers.prototype, {
 
 
 	set: function ( channel ) {
 	set: function ( channel ) {
 
 
-		this.mask = 1 << channel;
+		this.mask = 1 << channel | 0;
 
 
 	},
 	},
 
 
 	enable: function ( channel ) {
 	enable: function ( channel ) {
 
 
-		this.mask |= 1 << channel;
+		this.mask |= 1 << channel | 0;
 
 
 	},
 	},
 
 
 	toggle: function ( channel ) {
 	toggle: function ( channel ) {
 
 
-		this.mask ^= 1 << channel;
+		this.mask ^= 1 << channel | 0;
 
 
 	},
 	},
 
 
 	disable: function ( channel ) {
 	disable: function ( channel ) {
 
 
-		this.mask &= ~ ( 1 << channel );
+		this.mask &= ~ ( 1 << channel | 0 );
 
 
 	},
 	},
 
 

+ 18 - 3
src/core/Object3D.js

@@ -279,7 +279,22 @@ Object.assign( Object3D.prototype, EventDispatcher.prototype, {
 
 
 		return function lookAt( vector ) {
 		return function lookAt( vector ) {
 
 
-			m1.lookAt( vector, this.position, this.up );
+			if ( this.position.distanceToSquared( vector ) === 0 ) {
+
+				console.warn( 'THREE.Object3D.lookAt(): target vector is the same as object position.' );
+				return;
+
+			}
+
+			if ( this.isCamera ) {
+
+				m1.lookAt( this.position, vector, this.up );
+
+			} else {
+
+				m1.lookAt( vector, this.position, this.up );
+
+			}
 
 
 			this.quaternion.setFromRotationMatrix( m1 );
 			this.quaternion.setFromRotationMatrix( m1 );
 
 
@@ -526,9 +541,9 @@ Object.assign( Object3D.prototype, EventDispatcher.prototype, {
 
 
 	updateMatrixWorld: function ( force ) {
 	updateMatrixWorld: function ( force ) {
 
 
-		if ( this.matrixAutoUpdate === true ) this.updateMatrix();
+		if ( this.matrixAutoUpdate ) this.updateMatrix();
 
 
-		if ( this.matrixWorldNeedsUpdate === true || force === true ) {
+		if ( this.matrixWorldNeedsUpdate || force ) {
 
 
 			if ( this.parent === null ) {
 			if ( this.parent === null ) {
 
 

+ 11 - 0
src/lights/RectAreaLight.js

@@ -43,6 +43,17 @@ RectAreaLight.prototype = Object.assign( Object.create( Light.prototype ), {
 
 
 		return this;
 		return this;
 
 
+	},
+
+	toJSON: function ( meta ) {
+
+		var data = Light.prototype.toJSON.call( this, meta );
+
+		data.object.width = this.width;
+		data.object.height = this.height;
+
+		return data;
+
 	}
 	}
 
 
 } );
 } );

+ 7 - 0
src/loaders/ObjectLoader.js

@@ -38,6 +38,7 @@ import { SpotLight } from '../lights/SpotLight';
 import { PointLight } from '../lights/PointLight';
 import { PointLight } from '../lights/PointLight';
 import { DirectionalLight } from '../lights/DirectionalLight';
 import { DirectionalLight } from '../lights/DirectionalLight';
 import { AmbientLight } from '../lights/AmbientLight';
 import { AmbientLight } from '../lights/AmbientLight';
+import { RectAreaLight } from '../lights/RectAreaLight';
 import { OrthographicCamera } from '../cameras/OrthographicCamera';
 import { OrthographicCamera } from '../cameras/OrthographicCamera';
 import { PerspectiveCamera } from '../cameras/PerspectiveCamera';
 import { PerspectiveCamera } from '../cameras/PerspectiveCamera';
 import { Scene } from '../scenes/Scene';
 import { Scene } from '../scenes/Scene';
@@ -626,6 +627,12 @@ Object.assign( ObjectLoader.prototype, {
 
 
 					break;
 					break;
 
 
+				case 'RectAreaLight':
+
+					object = new RectAreaLight( data.color, data.intensity, data.width, data.height );
+
+					break;
+
 				case 'SpotLight':
 				case 'SpotLight':
 
 
 					object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );
 					object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay );

+ 1 - 0
src/materials/SpriteMaterial.js

@@ -34,6 +34,7 @@ function SpriteMaterial( parameters ) {
 
 
 SpriteMaterial.prototype = Object.create( Material.prototype );
 SpriteMaterial.prototype = Object.create( Material.prototype );
 SpriteMaterial.prototype.constructor = SpriteMaterial;
 SpriteMaterial.prototype.constructor = SpriteMaterial;
+SpriteMaterial.prototype.isSpriteMaterial = true;
 
 
 SpriteMaterial.prototype.copy = function ( source ) {
 SpriteMaterial.prototype.copy = function ( source ) {
 
 

+ 12 - 8
src/math/Quaternion.js

@@ -197,24 +197,28 @@ Object.assign( Quaternion.prototype, {
 
 
 	setFromEuler: function ( euler, update ) {
 	setFromEuler: function ( euler, update ) {
 
 
-		if ( (euler && euler.isEuler) === false ) {
+		if ( ( euler && euler.isEuler ) === false ) {
 
 
 			throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
 			throw new Error( 'THREE.Quaternion: .setFromEuler() now expects an Euler rotation rather than a Vector3 and order.' );
 
 
 		}
 		}
 
 
+		var x = euler._x, y = euler._y, z = euler._z, order = euler.order;
+
 		// http://www.mathworks.com/matlabcentral/fileexchange/
 		// http://www.mathworks.com/matlabcentral/fileexchange/
 		// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
 		// 	20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
 		//	content/SpinCalc.m
 		//	content/SpinCalc.m
 
 
-		var c1 = Math.cos( euler._x / 2 );
-		var c2 = Math.cos( euler._y / 2 );
-		var c3 = Math.cos( euler._z / 2 );
-		var s1 = Math.sin( euler._x / 2 );
-		var s2 = Math.sin( euler._y / 2 );
-		var s3 = Math.sin( euler._z / 2 );
+		var cos = Math.cos;
+		var sin = Math.sin;
+
+		var c1 = cos( x / 2 );
+		var c2 = cos( y / 2 );
+		var c3 = cos( z / 2 );
 
 
-		var order = euler.order;
+		var s1 = sin( x / 2 );
+		var s2 = sin( y / 2 );
+		var s3 = sin( z / 2 );
 
 
 		if ( order === 'XYZ' ) {
 		if ( order === 'XYZ' ) {
 
 

+ 24 - 33
src/math/Vector2.js

@@ -15,35 +15,35 @@ function Vector2( x, y ) {
 Object.defineProperties( Vector2.prototype, {
 Object.defineProperties( Vector2.prototype, {
 
 
 	"width" : {
 	"width" : {
-		
-		get: function () { 
-			
-			return this.x; 
-		
+
+		get: function () {
+
+			return this.x;
+
 		},
 		},
-		
-		set: function ( value ) { 
-			
-			this.x = value; 
-		
+
+		set: function ( value ) {
+
+			this.x = value;
+
 		}
 		}
-		
+
 	},
 	},
 
 
 	"height" : {
 	"height" : {
-		
-		get: function () { 
-			
-			return this.y; 
-		
+
+		get: function () {
+
+			return this.y;
+
 		},
 		},
-		
-		set: function ( value ) { 
-			
-			this.y = value; 
-		
+
+		set: function ( value ) {
+
+			this.y = value;
+
 		}
 		}
-		
+
 	}
 	}
 
 
 } );
 } );
@@ -215,17 +215,8 @@ Object.assign( Vector2.prototype, {
 
 
 	multiplyScalar: function ( scalar ) {
 	multiplyScalar: function ( scalar ) {
 
 
-		if ( isFinite( scalar ) ) {
-
-			this.x *= scalar;
-			this.y *= scalar;
-
-		} else {
-
-			this.x = 0;
-			this.y = 0;
-
-		}
+		this.x *= scalar;
+		this.y *= scalar;
 
 
 		return this;
 		return this;
 
 

+ 4 - 22
src/math/Vector3.js

@@ -214,19 +214,9 @@ Object.assign( Vector3.prototype, {
 
 
 	multiplyScalar: function ( scalar ) {
 	multiplyScalar: function ( scalar ) {
 
 
-		if ( isFinite( scalar ) ) {
-
-			this.x *= scalar;
-			this.y *= scalar;
-			this.z *= scalar;
-
-		} else {
-
-			this.x = 0;
-			this.y = 0;
-			this.z = 0;
-
-		}
+		this.x *= scalar;
+		this.y *= scalar;
+		this.z *= scalar;
 
 
 		return this;
 		return this;
 
 
@@ -648,7 +638,7 @@ Object.assign( Vector3.prototype, {
 
 
 	},
 	},
 
 
-	setFromCylindrical: function( c ) {
+	setFromCylindrical: function ( c ) {
 
 
 		this.x = c.radius * Math.sin( c.theta );
 		this.x = c.radius * Math.sin( c.theta );
 		this.y = c.y;
 		this.y = c.y;
@@ -680,14 +670,6 @@ Object.assign( Vector3.prototype, {
 
 
 	setFromMatrixColumn: function ( m, index ) {
 	setFromMatrixColumn: function ( m, index ) {
 
 
-		if ( typeof m === 'number' ) {
-
-			console.warn( 'THREE.Vector3: setFromMatrixColumn now expects ( matrix, index ).' );
-			var temp = m;
-			m = index;
-			index = temp;
-
-		}
 
 
 		return this.fromArray( m.elements, index * 4 );
 		return this.fromArray( m.elements, index * 4 );
 
 

+ 4 - 15
src/math/Vector4.js

@@ -213,21 +213,10 @@ Object.assign( Vector4.prototype, {
 
 
 	multiplyScalar: function ( scalar ) {
 	multiplyScalar: function ( scalar ) {
 
 
-		if ( isFinite( scalar ) ) {
-
-			this.x *= scalar;
-			this.y *= scalar;
-			this.z *= scalar;
-			this.w *= scalar;
-
-		} else {
-
-			this.x = 0;
-			this.y = 0;
-			this.z = 0;
-			this.w = 0;
-
-		}
+		this.x *= scalar;
+		this.y *= scalar;
+		this.z *= scalar;
+		this.w *= scalar;
 
 
 		return this;
 		return this;
 
 

+ 1 - 0
src/objects/Points.js

@@ -46,6 +46,7 @@ Points.prototype = Object.assign( Object.create( Object3D.prototype ), {
 
 
 			sphere.copy( geometry.boundingSphere );
 			sphere.copy( geometry.boundingSphere );
 			sphere.applyMatrix4( matrixWorld );
 			sphere.applyMatrix4( matrixWorld );
+			sphere.radius += threshold;
 
 
 			if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
 			if ( raycaster.ray.intersectsSphere( sphere ) === false ) return;
 
 

+ 139 - 127
src/renderers/WebGLRenderer.js

@@ -1,4 +1,4 @@
-import { REVISION, MaxEquation, MinEquation, RGB_ETC1_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, SrcAlphaSaturateFactor, OneMinusDstColorFactor, DstColorFactor, OneMinusDstAlphaFactor, DstAlphaFactor, OneMinusSrcAlphaFactor, SrcAlphaFactor, OneMinusSrcColorFactor, SrcColorFactor, OneFactor, ZeroFactor, ReverseSubtractEquation, SubtractEquation, AddEquation, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RGBAFormat, RGBFormat, AlphaFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort565Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestFilter, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, FrontFaceDirectionCW, NoBlending, BackSide, DoubleSide, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, NoColors, FlatShading, LinearToneMapping } from '../constants';
+import { REVISION, MaxEquation, MinEquation, RGB_ETC1_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT5_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT1_Format, RGB_S3TC_DXT1_Format, SrcAlphaSaturateFactor, OneMinusDstColorFactor, DstColorFactor, OneMinusDstAlphaFactor, DstAlphaFactor, OneMinusSrcAlphaFactor, SrcAlphaFactor, OneMinusSrcColorFactor, SrcColorFactor, OneFactor, ZeroFactor, ReverseSubtractEquation, SubtractEquation, AddEquation, DepthFormat, DepthStencilFormat, LuminanceAlphaFormat, LuminanceFormat, RGBAFormat, RGBFormat, AlphaFormat, HalfFloatType, FloatType, UnsignedIntType, IntType, UnsignedShortType, ShortType, ByteType, UnsignedInt248Type, UnsignedShort565Type, UnsignedShort5551Type, UnsignedShort4444Type, UnsignedByteType, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestFilter, MirroredRepeatWrapping, ClampToEdgeWrapping, RepeatWrapping, FrontFaceDirectionCW, NoBlending, BackSide, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, NoColors, FlatShading, LinearToneMapping } from '../constants';
 import { Matrix4 } from '../math/Matrix4';
 import { Matrix4 } from '../math/Matrix4';
 import { WebGLUniforms } from './webgl/WebGLUniforms';
 import { WebGLUniforms } from './webgl/WebGLUniforms';
 import { UniformsUtils } from './shaders/UniformsUtils';
 import { UniformsUtils } from './shaders/UniformsUtils';
@@ -13,11 +13,13 @@ import { PlaneBufferGeometry } from '../geometries/PlaneGeometry';
 import { MeshBasicMaterial } from '../materials/MeshBasicMaterial';
 import { MeshBasicMaterial } from '../materials/MeshBasicMaterial';
 import { PerspectiveCamera } from '../cameras/PerspectiveCamera';
 import { PerspectiveCamera } from '../cameras/PerspectiveCamera';
 import { OrthographicCamera } from '../cameras/OrthographicCamera';
 import { OrthographicCamera } from '../cameras/OrthographicCamera';
+import { WebGLAttributes } from './webgl/WebGLAttributes';
 import { WebGLIndexedBufferRenderer } from './webgl/WebGLIndexedBufferRenderer';
 import { WebGLIndexedBufferRenderer } from './webgl/WebGLIndexedBufferRenderer';
 import { WebGLBufferRenderer } from './webgl/WebGLBufferRenderer';
 import { WebGLBufferRenderer } from './webgl/WebGLBufferRenderer';
+import { WebGLGeometries } from './webgl/WebGLGeometries';
 import { WebGLLights } from './webgl/WebGLLights';
 import { WebGLLights } from './webgl/WebGLLights';
-import { WebGLPrograms } from './webgl/WebGLPrograms';
 import { WebGLObjects } from './webgl/WebGLObjects';
 import { WebGLObjects } from './webgl/WebGLObjects';
+import { WebGLPrograms } from './webgl/WebGLPrograms';
 import { WebGLTextures } from './webgl/WebGLTextures';
 import { WebGLTextures } from './webgl/WebGLTextures';
 import { WebGLProperties } from './webgl/WebGLProperties';
 import { WebGLProperties } from './webgl/WebGLProperties';
 import { WebGLState } from './webgl/WebGLState';
 import { WebGLState } from './webgl/WebGLState';
@@ -25,7 +27,7 @@ import { WebGLCapabilities } from './webgl/WebGLCapabilities';
 import { BufferGeometry } from '../core/BufferGeometry';
 import { BufferGeometry } from '../core/BufferGeometry';
 import { WebGLExtensions } from './webgl/WebGLExtensions';
 import { WebGLExtensions } from './webgl/WebGLExtensions';
 import { Vector3 } from '../math/Vector3';
 import { Vector3 } from '../math/Vector3';
-import { Sphere } from '../math/Sphere';
+// import { Sphere } from '../math/Sphere';
 import { WebGLClipping } from './webgl/WebGLClipping';
 import { WebGLClipping } from './webgl/WebGLClipping';
 import { Frustum } from '../math/Frustum';
 import { Frustum } from '../math/Frustum';
 import { Vector4 } from '../math/Vector4';
 import { Vector4 } from '../math/Vector4';
@@ -156,8 +158,6 @@ function WebGLRenderer( parameters ) {
 		_clippingEnabled = false,
 		_clippingEnabled = false,
 		_localClippingEnabled = false,
 		_localClippingEnabled = false,
 
 
-		_sphere = new Sphere(),
-
 		// camera matrices cache
 		// camera matrices cache
 
 
 		_projScreenMatrix = new Matrix4(),
 		_projScreenMatrix = new Matrix4(),
@@ -172,18 +172,18 @@ function WebGLRenderer( parameters ) {
 
 
 			hash: '',
 			hash: '',
 
 
-		ambient: [ 0, 0, 0 ],
-		directional: [],
-		directionalShadowMap: [],
-		directionalShadowMatrix: [],
-		spot: [],
-		spotShadowMap: [],
-		spotShadowMatrix: [],
-		rectArea: [],
-		point: [],
-		pointShadowMap: [],
-		pointShadowMatrix: [],
-		hemi: [],
+			ambient: [ 0, 0, 0 ],
+			directional: [],
+			directionalShadowMap: [],
+			directionalShadowMatrix: [],
+			spot: [],
+			spotShadowMap: [],
+			spotShadowMatrix: [],
+			rectArea: [],
+			point: [],
+			pointShadowMap: [],
+			pointShadowMatrix: [],
+			hemi: [],
 
 
 			shadows: []
 			shadows: []
 
 
@@ -191,8 +191,14 @@ function WebGLRenderer( parameters ) {
 
 
 		// info
 		// info
 
 
+		_infoMemory = {
+			geometries: 0,
+			textures: 0
+		},
+
 		_infoRender = {
 		_infoRender = {
 
 
+			frame: 0,
 			calls: 0,
 			calls: 0,
 			vertices: 0,
 			vertices: 0,
 			faces: 0,
 			faces: 0,
@@ -203,12 +209,7 @@ function WebGLRenderer( parameters ) {
 	this.info = {
 	this.info = {
 
 
 		render: _infoRender,
 		render: _infoRender,
-		memory: {
-
-			geometries: 0,
-			textures: 0
-
-		},
+		memory: _infoMemory,
 		programs: null
 		programs: null
 
 
 	};
 	};
@@ -220,7 +221,7 @@ function WebGLRenderer( parameters ) {
 
 
 	try {
 	try {
 
 
-		var attributes = {
+		var contextAttributes = {
 			alpha: _alpha,
 			alpha: _alpha,
 			depth: _depth,
 			depth: _depth,
 			stencil: _stencil,
 			stencil: _stencil,
@@ -229,7 +230,7 @@ function WebGLRenderer( parameters ) {
 			preserveDrawingBuffer: _preserveDrawingBuffer
 			preserveDrawingBuffer: _preserveDrawingBuffer
 		};
 		};
 
 
-		_gl = _context || _canvas.getContext( 'webgl', attributes ) || _canvas.getContext( 'experimental-webgl', attributes );
+		_gl = _context || _canvas.getContext( 'webgl', contextAttributes ) || _canvas.getContext( 'experimental-webgl', contextAttributes );
 
 
 		if ( _gl === null ) {
 		if ( _gl === null ) {
 
 
@@ -284,9 +285,12 @@ function WebGLRenderer( parameters ) {
 	var capabilities = new WebGLCapabilities( _gl, extensions, parameters );
 	var capabilities = new WebGLCapabilities( _gl, extensions, parameters );
 
 
 	var state = new WebGLState( _gl, extensions, paramThreeToGL );
 	var state = new WebGLState( _gl, extensions, paramThreeToGL );
+
 	var properties = new WebGLProperties();
 	var properties = new WebGLProperties();
-	var textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, paramThreeToGL, this.info );
-	var objects = new WebGLObjects( _gl, properties, this.info );
+	var textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, paramThreeToGL, _infoMemory );
+	var attributes = new WebGLAttributes( _gl );
+	var geometries = new WebGLGeometries( _gl, attributes, _infoMemory );
+	var objects = new WebGLObjects( _gl, geometries, _infoRender );
 	var programCache = new WebGLPrograms( this, capabilities );
 	var programCache = new WebGLPrograms( this, capabilities );
 	var lightCache = new WebGLLights();
 	var lightCache = new WebGLLights();
 
 
@@ -518,12 +522,12 @@ function WebGLRenderer( parameters ) {
 
 
 	this.resetGLState = resetGLState;
 	this.resetGLState = resetGLState;
 
 
-	this.dispose = function() {
+	this.dispose = function () {
 
 
 		transparentObjects = [];
 		transparentObjects = [];
-		transparentObjectsLastIndex = -1;
+		transparentObjectsLastIndex = - 1;
 		opaqueObjects = [];
 		opaqueObjects = [];
-		opaqueObjectsLastIndex = -1;
+		opaqueObjectsLastIndex = - 1;
 
 
 		_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
 		_canvas.removeEventListener( 'webglcontextlost', onContextLost, false );
 
 
@@ -539,6 +543,7 @@ function WebGLRenderer( parameters ) {
 		setDefaultGLState();
 		setDefaultGLState();
 
 
 		properties.clear();
 		properties.clear();
+		objects.clear();
 
 
 	}
 	}
 
 
@@ -558,7 +563,7 @@ function WebGLRenderer( parameters ) {
 
 
 		releaseMaterialProgramReference( material );
 		releaseMaterialProgramReference( material );
 
 
-		properties.delete( material );
+		properties.remove( material );
 
 
 	}
 	}
 
 
@@ -579,6 +584,16 @@ function WebGLRenderer( parameters ) {
 
 
 	// Buffer rendering
 	// Buffer rendering
 
 
+	function renderObjectImmediate( object, program, material ) {
+
+		object.render( function ( object ) {
+
+			_this.renderBufferImmediate( object, program, material );
+
+		} );
+
+	}
+
 	this.renderBufferImmediate = function ( object, program, material ) {
 	this.renderBufferImmediate = function ( object, program, material ) {
 
 
 		state.initAttributes();
 		state.initAttributes();
@@ -590,15 +605,15 @@ function WebGLRenderer( parameters ) {
 		if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
 		if ( object.hasUvs && ! buffers.uv ) buffers.uv = _gl.createBuffer();
 		if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
 		if ( object.hasColors && ! buffers.color ) buffers.color = _gl.createBuffer();
 
 
-		var attributes = program.getAttributes();
+		var programAttributes = program.getAttributes();
 
 
 		if ( object.hasPositions ) {
 		if ( object.hasPositions ) {
 
 
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.position );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
 
 
-			state.enableAttribute( attributes.position );
-			_gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
+			state.enableAttribute( programAttributes.position );
+			_gl.vertexAttribPointer( programAttributes.position, 3, _gl.FLOAT, false, 0, 0 );
 
 
 		}
 		}
 
 
@@ -637,9 +652,9 @@ function WebGLRenderer( parameters ) {
 
 
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
 
 
-			state.enableAttribute( attributes.normal );
+			state.enableAttribute( programAttributes.normal );
 
 
-			_gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
+			_gl.vertexAttribPointer( programAttributes.normal, 3, _gl.FLOAT, false, 0, 0 );
 
 
 		}
 		}
 
 
@@ -648,7 +663,7 @@ function WebGLRenderer( parameters ) {
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.uv );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
 
 
-			state.enableAttribute( attributes.uv );
+			state.enableAttribute( programAttributes.uv );
 
 
 			_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
 			_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
 
 
@@ -659,9 +674,9 @@ function WebGLRenderer( parameters ) {
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
 			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffers.color );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
 			_gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
 
 
-			state.enableAttribute( attributes.color );
+			state.enableAttribute( programAttributes.color );
 
 
-			_gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
+			_gl.vertexAttribPointer( programAttributes.color, 3, _gl.FLOAT, false, 0, 0 );
 
 
 		}
 		}
 
 
@@ -673,14 +688,16 @@ function WebGLRenderer( parameters ) {
 
 
 	};
 	};
 
 
+	var program, geometryProgram, updateBuffers;
+
 	this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
 	this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
 
 
-		setMaterial( material );
+		state.setMaterial( material );
 
 
-		var program = setProgram( camera, fog, material, object );
+		program = setProgram( camera, fog, material, object );
+		geometryProgram = geometry.id + '_' + program.id + '_' + material.wireframe;
 
 
-		var updateBuffers = false;
-		var geometryProgram = geometry.id + '_' + program.id + '_' + material.wireframe;
+		updateBuffers = false;
 
 
 		if ( geometryProgram !== _currentGeometryProgram ) {
 		if ( geometryProgram !== _currentGeometryProgram ) {
 
 
@@ -695,6 +712,8 @@ function WebGLRenderer( parameters ) {
 
 
 		if ( morphTargetInfluences !== undefined ) {
 		if ( morphTargetInfluences !== undefined ) {
 
 
+			// TODO Remove allocations
+
 			var activeInfluences = [];
 			var activeInfluences = [];
 
 
 			for ( var i = 0, l = morphTargetInfluences.length; i < l; i ++ ) {
 			for ( var i = 0, l = morphTargetInfluences.length; i < l; i ++ ) {
@@ -741,8 +760,7 @@ function WebGLRenderer( parameters ) {
 
 
 			}
 			}
 
 
-			program.getUniforms().setValue(
-				_gl, 'morphTargetInfluences', morphInfluences );
+			program.getUniforms().setValue( _gl, 'morphTargetInfluences', morphInfluences );
 
 
 			updateBuffers = true;
 			updateBuffers = true;
 
 
@@ -756,22 +774,18 @@ function WebGLRenderer( parameters ) {
 
 
 		if ( material.wireframe === true ) {
 		if ( material.wireframe === true ) {
 
 
-			index = objects.getWireframeAttribute( geometry );
+			index = geometries.getWireframeAttribute( geometry );
 			rangeFactor = 2;
 			rangeFactor = 2;
 
 
 		}
 		}
 
 
-		var renderer;
+		var renderer = bufferRenderer;
 
 
 		if ( index !== null ) {
 		if ( index !== null ) {
 
 
 			renderer = indexedBufferRenderer;
 			renderer = indexedBufferRenderer;
 			renderer.setIndex( index );
 			renderer.setIndex( index );
 
 
-		} else {
-
-			renderer = bufferRenderer;
-
 		}
 		}
 
 
 		if ( updateBuffers ) {
 		if ( updateBuffers ) {
@@ -780,7 +794,7 @@ function WebGLRenderer( parameters ) {
 
 
 			if ( index !== null ) {
 			if ( index !== null ) {
 
 
-				_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, objects.getAttributeBuffer( index ) );
+				_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, attributes.get( index ).buffer );
 
 
 			}
 			}
 
 
@@ -927,9 +941,9 @@ function WebGLRenderer( parameters ) {
 					var normalized = geometryAttribute.normalized;
 					var normalized = geometryAttribute.normalized;
 					var size = geometryAttribute.itemSize;
 					var size = geometryAttribute.itemSize;
 
 
-					var attributeProperties = objects.getAttributeProperties( geometryAttribute );
+					var attributeProperties = attributes.get( geometryAttribute );
 
 
-					var buffer = attributeProperties.__webglBuffer;
+					var buffer = attributeProperties.buffer;
 					var type = attributeProperties.type;
 					var type = attributeProperties.type;
 					var bytesPerElement = attributeProperties.bytesPerElement;
 					var bytesPerElement = attributeProperties.bytesPerElement;
 
 
@@ -1111,7 +1125,7 @@ function WebGLRenderer( parameters ) {
 		_localClippingEnabled = this.localClippingEnabled;
 		_localClippingEnabled = this.localClippingEnabled;
 		_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
 		_clippingEnabled = _clipping.init( this.clippingPlanes, _localClippingEnabled, camera );
 
 
-		projectObject( scene, camera );
+		projectObject( scene, camera, _this.sortObjects );
 
 
 		opaqueObjects.length = opaqueObjectsLastIndex + 1;
 		opaqueObjects.length = opaqueObjectsLastIndex + 1;
 		transparentObjects.length = transparentObjectsLastIndex + 1;
 		transparentObjects.length = transparentObjectsLastIndex + 1;
@@ -1137,6 +1151,7 @@ function WebGLRenderer( parameters ) {
 
 
 		//
 		//
 
 
+		_infoRender.frame ++;
 		_infoRender.calls = 0;
 		_infoRender.calls = 0;
 		_infoRender.vertices = 0;
 		_infoRender.vertices = 0;
 		_infoRender.faces = 0;
 		_infoRender.faces = 0;
@@ -1263,9 +1278,9 @@ function WebGLRenderer( parameters ) {
 
 
 		// Ensure depth buffer writing is enabled so it can be cleared on next render
 		// Ensure depth buffer writing is enabled so it can be cleared on next render
 
 
-		state.setDepthTest( true );
-		state.setDepthWrite( true );
-		state.setColorWrite( true );
+		state.buffers.depth.setTest( true );
+		state.buffers.depth.setMask( true );
+		state.buffers.color.setMask( true );
 
 
 		// _gl.finish();
 		// _gl.finish();
 
 
@@ -1293,7 +1308,7 @@ function WebGLRenderer( parameters ) {
 
 
 		var renderItem = array[ index ];
 		var renderItem = array[ index ];
 
 
-		if ( renderItem !== undefined ) {
+		if ( renderItem ) {
 
 
 			renderItem.id = object.id;
 			renderItem.id = object.id;
 			renderItem.object = object;
 			renderItem.object = object;
@@ -1320,8 +1335,11 @@ function WebGLRenderer( parameters ) {
 
 
 	}
 	}
 
 
+	/*
 	// TODO Duplicated code (Frustum)
 	// TODO Duplicated code (Frustum)
 
 
+	var _sphere = new Sphere();
+
 	function isObjectViewable( object ) {
 	function isObjectViewable( object ) {
 
 
 		var geometry = object.geometry;
 		var geometry = object.geometry;
@@ -1370,12 +1388,13 @@ function WebGLRenderer( parameters ) {
 		return true;
 		return true;
 
 
 	}
 	}
+	*/
 
 
-	function projectObject( object, camera ) {
+	function projectObject( object, camera, sortObjects ) {
 
 
-		if ( object.visible === false ) return;
+		if ( ! object.visible ) return;
 
 
-		var visible = ( object.layers.mask & camera.layers.mask ) !== 0;
+		var visible = object.layers.test( camera.layers );
 
 
 		if ( visible ) {
 		if ( visible ) {
 
 
@@ -1385,7 +1404,7 @@ function WebGLRenderer( parameters ) {
 
 
 			} else if ( object.isSprite ) {
 			} else if ( object.isSprite ) {
 
 
-				if ( object.frustumCulled === false || isSpriteViewable( object ) === true ) {
+				if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
 
 
 					sprites.push( object );
 					sprites.push( object );
 
 
@@ -1397,10 +1416,10 @@ function WebGLRenderer( parameters ) {
 
 
 			} else if ( object.isImmediateRenderObject ) {
 			} else if ( object.isImmediateRenderObject ) {
 
 
-				if ( _this.sortObjects === true ) {
+				if ( sortObjects ) {
 
 
-					_vector3.setFromMatrixPosition( object.matrixWorld );
-					_vector3.applyMatrix4( _projScreenMatrix );
+					_vector3.setFromMatrixPosition( object.matrixWorld )
+						.applyMatrix4( _projScreenMatrix );
 
 
 				}
 				}
 
 
@@ -1414,12 +1433,12 @@ function WebGLRenderer( parameters ) {
 
 
 				}
 				}
 
 
-				if ( object.frustumCulled === false || isObjectViewable( object ) === true ) {
+				if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
 
 
-					if ( _this.sortObjects === true ) {
+					if ( sortObjects ) {
 
 
-						_vector3.setFromMatrixPosition( object.matrixWorld );
-						_vector3.applyMatrix4( _projScreenMatrix );
+						_vector3.setFromMatrixPosition( object.matrixWorld )
+							.applyMatrix4( _projScreenMatrix );
 
 
 					}
 					}
 
 
@@ -1435,7 +1454,7 @@ function WebGLRenderer( parameters ) {
 							var group = groups[ i ];
 							var group = groups[ i ];
 							var groupMaterial = material[ group.materialIndex ];
 							var groupMaterial = material[ group.materialIndex ];
 
 
-							if ( groupMaterial && groupMaterial.visible === true ) {
+							if ( groupMaterial && groupMaterial.visible ) {
 
 
 								pushRenderItem( object, geometry, groupMaterial, _vector3.z, group );
 								pushRenderItem( object, geometry, groupMaterial, _vector3.z, group );
 
 
@@ -1443,7 +1462,7 @@ function WebGLRenderer( parameters ) {
 
 
 						}
 						}
 
 
-					} else if ( material.visible === true ) {
+					} else if ( material.visible ) {
 
 
 						pushRenderItem( object, geometry, material, _vector3.z, null );
 						pushRenderItem( object, geometry, material, _vector3.z, null );
 
 
@@ -1459,7 +1478,7 @@ function WebGLRenderer( parameters ) {
 
 
 		for ( var i = 0, l = children.length; i < l; i ++ ) {
 		for ( var i = 0, l = children.length; i < l; i ++ ) {
 
 
-			projectObject( children[ i ], camera );
+			projectObject( children[ i ], camera, sortObjects );
 
 
 		}
 		}
 
 
@@ -1483,17 +1502,13 @@ function WebGLRenderer( parameters ) {
 
 
 			if ( object.isImmediateRenderObject ) {
 			if ( object.isImmediateRenderObject ) {
 
 
-				setMaterial( material );
+				state.setMaterial( material );
 
 
 				var program = setProgram( camera, scene.fog, material, object );
 				var program = setProgram( camera, scene.fog, material, object );
 
 
 				_currentGeometryProgram = '';
 				_currentGeometryProgram = '';
 
 
-				object.render( function ( object ) {
-
-					_this.renderBufferImmediate( object, program, material );
-
-				} );
+				renderObjectImmediate( object, program, material );
 
 
 			} else {
 			} else {
 
 
@@ -1575,7 +1590,7 @@ function WebGLRenderer( parameters ) {
 
 
 		}
 		}
 
 
-		var attributes = program.getAttributes();
+		var programAttributes = program.getAttributes();
 
 
 		if ( material.morphTargets ) {
 		if ( material.morphTargets ) {
 
 
@@ -1583,7 +1598,7 @@ function WebGLRenderer( parameters ) {
 
 
 			for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
 			for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
 
 
-				if ( attributes[ 'morphTarget' + i ] >= 0 ) {
+				if ( programAttributes[ 'morphTarget' + i ] >= 0 ) {
 
 
 					material.numSupportedMorphTargets ++;
 					material.numSupportedMorphTargets ++;
 
 
@@ -1599,7 +1614,7 @@ function WebGLRenderer( parameters ) {
 
 
 			for ( var i = 0; i < _this.maxMorphNormals; i ++ ) {
 			for ( var i = 0; i < _this.maxMorphNormals; i ++ ) {
 
 
-				if ( attributes[ 'morphNormal' + i ] >= 0 ) {
+				if ( programAttributes[ 'morphNormal' + i ] >= 0 ) {
 
 
 					material.numSupportedMorphNormals ++;
 					material.numSupportedMorphNormals ++;
 
 
@@ -1656,26 +1671,6 @@ function WebGLRenderer( parameters ) {
 
 
 	}
 	}
 
 
-	function setMaterial( material ) {
-
-		material.side === DoubleSide
-			? state.disable( _gl.CULL_FACE )
-			: state.enable( _gl.CULL_FACE );
-
-		state.setFlipSided( material.side === BackSide );
-
-		material.transparent === true
-			? state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha )
-			: state.setBlending( NoBlending );
-
-		state.setDepthFunc( material.depthFunc );
-		state.setDepthTest( material.depthTest );
-		state.setDepthWrite( material.depthWrite );
-		state.setColorWrite( material.colorWrite );
-		state.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
-
-	}
-
 	function setProgram( camera, fog, material, object ) {
 	function setProgram( camera, fog, material, object ) {
 
 
 		_usedTextureUnits = 0;
 		_usedTextureUnits = 0;
@@ -2289,7 +2284,8 @@ function WebGLRenderer( parameters ) {
 
 
 			if ( light.castShadow ) {
 			if ( light.castShadow ) {
 
 
-				_lights.shadows[ lightShadowsLength ++ ] = light;
+				_lights.shadows[ lightShadowsLength ] = light;
+				lightShadowsLength ++;
 
 
 			}
 			}
 
 
@@ -2301,7 +2297,7 @@ function WebGLRenderer( parameters ) {
 
 
 	function setupLights( lights, camera ) {
 	function setupLights( lights, camera ) {
 
 
-		var l, ll, light,
+		var l, ll, light, shadow,
 			r = 0, g = 0, b = 0,
 			r = 0, g = 0, b = 0,
 			color,
 			color,
 			intensity,
 			intensity,
@@ -2310,11 +2306,11 @@ function WebGLRenderer( parameters ) {
 
 
 			viewMatrix = camera.matrixWorldInverse,
 			viewMatrix = camera.matrixWorldInverse,
 
 
-		directionalLength = 0,
-		pointLength = 0,
-		spotLength = 0,
-		rectAreaLength = 0,
-		hemiLength = 0;
+			directionalLength = 0,
+			pointLength = 0,
+			spotLength = 0,
+			rectAreaLength = 0,
+			hemiLength = 0;
 
 
 		for ( l = 0, ll = lights.length; l < ll; l ++ ) {
 		for ( l = 0, ll = lights.length; l < ll; l ++ ) {
 
 
@@ -2346,15 +2342,19 @@ function WebGLRenderer( parameters ) {
 
 
 				if ( light.castShadow ) {
 				if ( light.castShadow ) {
 
 
-					uniforms.shadowBias = light.shadow.bias;
-					uniforms.shadowRadius = light.shadow.radius;
-					uniforms.shadowMapSize = light.shadow.mapSize;
+					shadow = light.shadow;
+
+					uniforms.shadowBias = shadow.bias;
+					uniforms.shadowRadius = shadow.radius;
+					uniforms.shadowMapSize = shadow.mapSize;
 
 
 				}
 				}
 
 
 				_lights.directionalShadowMap[ directionalLength ] = shadowMap;
 				_lights.directionalShadowMap[ directionalLength ] = shadowMap;
 				_lights.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
 				_lights.directionalShadowMatrix[ directionalLength ] = light.shadow.matrix;
-				_lights.directional[ directionalLength ++ ] = uniforms;
+				_lights.directional[ directionalLength ] = uniforms;
+
+				directionalLength ++;
 
 
 			} else if ( light.isSpotLight ) {
 			} else if ( light.isSpotLight ) {
 
 
@@ -2379,15 +2379,19 @@ function WebGLRenderer( parameters ) {
 
 
 				if ( light.castShadow ) {
 				if ( light.castShadow ) {
 
 
-					uniforms.shadowBias = light.shadow.bias;
-					uniforms.shadowRadius = light.shadow.radius;
-					uniforms.shadowMapSize = light.shadow.mapSize;
+					shadow = light.shadow;
+
+					uniforms.shadowBias = shadow.bias;
+					uniforms.shadowRadius = shadow.radius;
+					uniforms.shadowMapSize = shadow.mapSize;
 
 
 				}
 				}
 
 
 				_lights.spotShadowMap[ spotLength ] = shadowMap;
 				_lights.spotShadowMap[ spotLength ] = shadowMap;
 				_lights.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
 				_lights.spotShadowMatrix[ spotLength ] = light.shadow.matrix;
-				_lights.spot[ spotLength ++ ] = uniforms;
+				_lights.spot[ spotLength ] = uniforms;
+
+				spotLength ++;
 
 
 			} else if ( light.isRectAreaLight ) {
 			} else if ( light.isRectAreaLight ) {
 
 
@@ -2419,7 +2423,9 @@ function WebGLRenderer( parameters ) {
 				// TODO (abelnation): RectAreaLight distance?
 				// TODO (abelnation): RectAreaLight distance?
 				// uniforms.distance = distance;
 				// uniforms.distance = distance;
 
 
-				_lights.rectArea[ rectAreaLength ++ ] = uniforms;
+				_lights.rectArea[ rectAreaLength ] = uniforms;
+
+				rectAreaLength ++;
 
 
 			} else if ( light.isPointLight ) {
 			} else if ( light.isPointLight ) {
 
 
@@ -2436,9 +2442,11 @@ function WebGLRenderer( parameters ) {
 
 
 				if ( light.castShadow ) {
 				if ( light.castShadow ) {
 
 
-					uniforms.shadowBias = light.shadow.bias;
-					uniforms.shadowRadius = light.shadow.radius;
-					uniforms.shadowMapSize = light.shadow.mapSize;
+					shadow = light.shadow;
+
+					uniforms.shadowBias = shadow.bias;
+					uniforms.shadowRadius = shadow.radius;
+					uniforms.shadowMapSize = shadow.mapSize;
 
 
 				}
 				}
 
 
@@ -2455,7 +2463,9 @@ function WebGLRenderer( parameters ) {
 				_vector3.setFromMatrixPosition( light.matrixWorld ).negate();
 				_vector3.setFromMatrixPosition( light.matrixWorld ).negate();
 				_lights.pointShadowMatrix[ pointLength ].identity().setPosition( _vector3 );
 				_lights.pointShadowMatrix[ pointLength ].identity().setPosition( _vector3 );
 
 
-				_lights.point[ pointLength ++ ] = uniforms;
+				_lights.point[ pointLength ] = uniforms;
+
+				pointLength ++;
 
 
 			} else if ( light.isHemisphereLight ) {
 			} else if ( light.isHemisphereLight ) {
 
 
@@ -2468,7 +2478,9 @@ function WebGLRenderer( parameters ) {
 				uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
 				uniforms.skyColor.copy( light.color ).multiplyScalar( intensity );
 				uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
 				uniforms.groundColor.copy( light.groundColor ).multiplyScalar( intensity );
 
 
-				_lights.hemi[ hemiLength ++ ] = uniforms;
+				_lights.hemi[ hemiLength ] = uniforms;
+
+				hemiLength ++;
 
 
 			}
 			}
 
 
@@ -2519,7 +2531,7 @@ function WebGLRenderer( parameters ) {
 	this.allocTextureUnit = allocTextureUnit;
 	this.allocTextureUnit = allocTextureUnit;
 
 
 	// this.setTexture2D = setTexture2D;
 	// this.setTexture2D = setTexture2D;
-	this.setTexture2D = ( function() {
+	this.setTexture2D = ( function () {
 
 
 		var warned = false;
 		var warned = false;
 
 
@@ -2545,7 +2557,7 @@ function WebGLRenderer( parameters ) {
 
 
 	}() );
 	}() );
 
 
-	this.setTexture = ( function() {
+	this.setTexture = ( function () {
 
 
 		var warned = false;
 		var warned = false;
 
 
@@ -2564,7 +2576,7 @@ function WebGLRenderer( parameters ) {
 
 
 	}() );
 	}() );
 
 
-	this.setTextureCube = ( function() {
+	this.setTextureCube = ( function () {
 
 
 		var warned = false;
 		var warned = false;
 
 
@@ -2606,7 +2618,7 @@ function WebGLRenderer( parameters ) {
 
 
 	}() );
 	}() );
 
 
-	this.getCurrentRenderTarget = function() {
+	this.getCurrentRenderTarget = function () {
 
 
 		return _currentRenderTarget;
 		return _currentRenderTarget;
 
 

+ 153 - 0
src/renderers/webgl/WebGLAttributes.js

@@ -0,0 +1,153 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+function WebGLAttributes( gl ) {
+
+	var buffers = {};
+
+	function createBuffer( attribute, bufferType ) {
+
+		var array = attribute.array;
+		var usage = attribute.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
+
+		var buffer = gl.createBuffer();
+
+		gl.bindBuffer( bufferType, buffer );
+		gl.bufferData( bufferType, array, usage );
+
+		attribute.onUploadCallback();
+
+		var type = gl.FLOAT;
+
+		if ( array instanceof Float32Array ) {
+
+			type = gl.FLOAT;
+
+		} else if ( array instanceof Float64Array ) {
+
+			console.warn( "Unsupported data buffer format: Float64Array" );
+
+		} else if ( array instanceof Uint16Array ) {
+
+			type = gl.UNSIGNED_SHORT;
+
+		} else if ( array instanceof Int16Array ) {
+
+			type = gl.SHORT;
+
+		} else if ( array instanceof Uint32Array ) {
+
+			type = gl.UNSIGNED_INT;
+
+		} else if ( array instanceof Int32Array ) {
+
+			type = gl.INT;
+
+		} else if ( array instanceof Int8Array ) {
+
+			type = gl.BYTE;
+
+		} else if ( array instanceof Uint8Array ) {
+
+			type = gl.UNSIGNED_BYTE;
+
+		}
+
+		return {
+			buffer: buffer,
+			type: type,
+			bytesPerElement: array.BYTES_PER_ELEMENT,
+			version: attribute.version
+		};
+
+	}
+
+	function updateBuffer( buffer, attribute, bufferType ) {
+
+		var array = attribute.array;
+		var updateRange = attribute.updateRange;
+
+		gl.bindBuffer( bufferType, buffer );
+
+		if ( attribute.dynamic === false ) {
+
+			gl.bufferData( bufferType, array, gl.STATIC_DRAW );
+
+		} else if ( updateRange.count === - 1 ) {
+
+			// Not using update ranges
+
+			gl.bufferSubData( bufferType, 0, array );
+
+		} else if ( updateRange.count === 0 ) {
+
+			console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' );
+
+		} else {
+
+			gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT,
+				array.subarray( updateRange.offset, updateRange.offset + updateRange.count ) );
+
+			updateRange.count = 0; // reset range
+
+		}
+
+	}
+
+	//
+
+	function get( attribute ) {
+
+		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
+
+		return buffers[ attribute.id ];
+
+	}
+
+	function remove( attribute ) {
+
+		var data = buffers[ attribute.id ];
+
+		if ( data ) {
+
+			gl.deleteBuffer( data.buffer );
+
+			delete buffers[ attribute.id ];
+
+		}
+
+	}
+
+	function update( attribute, bufferType ) {
+
+		if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data;
+
+		var data = buffers[ attribute.id ];
+
+		if ( data === undefined ) {
+
+			buffers[ attribute.id ] = createBuffer( attribute, bufferType );
+
+		} else if ( data.version < attribute.version ) {
+
+			updateBuffer( data.buffer, attribute, bufferType );
+
+			data.version = attribute.version;
+
+		}
+
+	}
+
+	return {
+
+		get: get,
+		remove: remove,
+		update: update
+
+	};
+
+}
+
+
+export { WebGLAttributes };

+ 99 - 54
src/renderers/webgl/WebGLGeometries.js

@@ -2,11 +2,14 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
+import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute';
 import { BufferGeometry } from '../../core/BufferGeometry';
 import { BufferGeometry } from '../../core/BufferGeometry';
+import { arrayMax } from '../../utils';
 
 
-function WebGLGeometries( gl, properties, info ) {
+function WebGLGeometries( gl, attributes, infoMemory ) {
 
 
 	var geometries = {};
 	var geometries = {};
+	var wireframeAttributes = {};
 
 
 	function onGeometryDispose( event ) {
 	function onGeometryDispose( event ) {
 
 
@@ -15,132 +18,174 @@ function WebGLGeometries( gl, properties, info ) {
 
 
 		if ( buffergeometry.index !== null ) {
 		if ( buffergeometry.index !== null ) {
 
 
-			deleteAttribute( buffergeometry.index );
+			attributes.remove( buffergeometry.index );
 
 
 		}
 		}
 
 
-		deleteAttributes( buffergeometry.attributes );
+		for ( var name in buffergeometry.attributes ) {
+
+			attributes.remove( buffergeometry.attributes[ name ] );
+
+		}
 
 
 		geometry.removeEventListener( 'dispose', onGeometryDispose );
 		geometry.removeEventListener( 'dispose', onGeometryDispose );
 
 
 		delete geometries[ geometry.id ];
 		delete geometries[ geometry.id ];
 
 
-		// TODO
+		// TODO Remove duplicate code
 
 
-		var property = properties.get( geometry );
+		var attribute = wireframeAttributes[ geometry.id ];
 
 
-		if ( property.wireframe ) {
+		if ( attribute ) {
 
 
-			deleteAttribute( property.wireframe );
+			attributes.remove( attribute );
+			delete wireframeAttributes[ geometry.id ];
 
 
 		}
 		}
 
 
-		properties.delete( geometry );
+		attribute = wireframeAttributes[ buffergeometry.id ];
 
 
-		var bufferproperty = properties.get( buffergeometry );
+		if ( attribute ) {
 
 
-		if ( bufferproperty.wireframe ) {
-
-			deleteAttribute( bufferproperty.wireframe );
+			attributes.remove( attribute );
+			delete wireframeAttributes[ buffergeometry.id ];
 
 
 		}
 		}
 
 
-		properties.delete( buffergeometry );
-
 		//
 		//
 
 
-		info.memory.geometries --;
+		infoMemory.geometries --;
 
 
 	}
 	}
 
 
-	function getAttributeBuffer( attribute ) {
+	function get( object, geometry ) {
 
 
-		if ( attribute.isInterleavedBufferAttribute ) {
+		var buffergeometry = geometries[ geometry.id ];
 
 
-			return properties.get( attribute.data ).__webglBuffer;
+		if ( buffergeometry ) return buffergeometry;
 
 
-		}
+		geometry.addEventListener( 'dispose', onGeometryDispose );
 
 
-		return properties.get( attribute ).__webglBuffer;
+		if ( geometry.isBufferGeometry ) {
 
 
-	}
+			buffergeometry = geometry;
 
 
-	function deleteAttribute( attribute ) {
+		} else if ( geometry.isGeometry ) {
 
 
-		var buffer = getAttributeBuffer( attribute );
+			if ( geometry._bufferGeometry === undefined ) {
 
 
-		if ( buffer !== undefined ) {
+				geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
+
+			}
 
 
-			gl.deleteBuffer( buffer );
-			removeAttributeBuffer( attribute );
+			buffergeometry = geometry._bufferGeometry;
 
 
 		}
 		}
 
 
+		geometries[ geometry.id ] = buffergeometry;
+
+		infoMemory.geometries ++;
+
+		return buffergeometry;
+
 	}
 	}
 
 
-	function deleteAttributes( attributes ) {
+	function update( geometry ) {
 
 
-		for ( var name in attributes ) {
+		var index = geometry.index;
+		var geometryAttributes = geometry.attributes;
 
 
-			deleteAttribute( attributes[ name ] );
+		if ( index !== null ) {
+
+			attributes.update( index, gl.ELEMENT_ARRAY_BUFFER );
 
 
 		}
 		}
 
 
-	}
+		for ( var name in geometryAttributes ) {
 
 
-	function removeAttributeBuffer( attribute ) {
+			attributes.update( geometryAttributes[ name ], gl.ARRAY_BUFFER );
 
 
-		if ( attribute.isInterleavedBufferAttribute ) {
+		}
 
 
-			properties.delete( attribute.data );
+		// morph targets
 
 
-		} else {
+		var morphAttributes = geometry.morphAttributes;
+
+		for ( var name in morphAttributes ) {
+
+			var array = morphAttributes[ name ];
 
 
-			properties.delete( attribute );
+			for ( var i = 0, l = array.length; i < l; i ++ ) {
+
+				attributes.update( array[ i ], gl.ARRAY_BUFFER );
+
+			}
 
 
 		}
 		}
 
 
 	}
 	}
 
 
-	return {
+	function getWireframeAttribute( geometry ) {
 
 
-		get: function ( object ) {
+		var attribute = wireframeAttributes[ geometry.id ];
 
 
-			var geometry = object.geometry;
+		if ( attribute ) return attribute;
 
 
-			if ( geometries[ geometry.id ] !== undefined ) {
+		var indices = [];
 
 
-				return geometries[ geometry.id ];
+		var geometryIndex = geometry.index;
+		var geometryAttributes = geometry.attributes;
 
 
-			}
+		// console.time( 'wireframe' );
 
 
-			geometry.addEventListener( 'dispose', onGeometryDispose );
+		if ( geometryIndex !== null ) {
 
 
-			var buffergeometry;
+			var array = geometryIndex.array;
 
 
-			if ( geometry.isBufferGeometry ) {
+			for ( var i = 0, l = array.length; i < l; i += 3 ) {
 
 
-				buffergeometry = geometry;
+				var a = array[ i + 0 ];
+				var b = array[ i + 1 ];
+				var c = array[ i + 2 ];
 
 
-			} else if ( geometry.isGeometry ) {
+				indices.push( a, b, b, c, c, a );
 
 
-				if ( geometry._bufferGeometry === undefined ) {
+			}
+
+		} else {
 
 
-					geometry._bufferGeometry = new BufferGeometry().setFromObject( object );
+			var array = geometryAttributes.position.array;
 
 
-				}
+			for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
 
 
-				buffergeometry = geometry._bufferGeometry;
+				var a = i + 0;
+				var b = i + 1;
+				var c = i + 2;
+
+				indices.push( a, b, b, c, c, a );
 
 
 			}
 			}
 
 
-			geometries[ geometry.id ] = buffergeometry;
+		}
 
 
-			info.memory.geometries ++;
+		// console.timeEnd( 'wireframe' );
 
 
-			return buffergeometry;
+		attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
 
 
-		}
+		attributes.update( attribute, gl.ELEMENT_ARRAY_BUFFER );
+
+		wireframeAttributes[ geometry.id ] = attribute;
+
+		return attribute;
+
+	}
+
+	return {
+
+		get: get,
+		update: update,
+
+		getWireframeAttribute: getWireframeAttribute
 
 
 	};
 	};
 
 

+ 16 - 225
src/renderers/webgl/WebGLObjects.js

@@ -2,256 +2,47 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-import { Uint16BufferAttribute, Uint32BufferAttribute } from '../../core/BufferAttribute';
-import { arrayMax } from '../../utils';
-import { WebGLGeometries } from './WebGLGeometries';
+function WebGLObjects( gl, geometries, infoRender ) {
 
 
-function WebGLObjects( gl, properties, info ) {
-
-	var geometries = new WebGLGeometries( gl, properties, info );
-
-	//
+	var updateList = {};
 
 
 	function update( object ) {
 	function update( object ) {
 
 
-		// TODO: Avoid updating twice (when using shadowMap). Maybe add frame counter.
-
-		var geometry = geometries.get( object );
-
-		if ( object.geometry.isGeometry ) {
-
-			geometry.updateFromObject( object );
-
-		}
-
-		var index = geometry.index;
-		var attributes = geometry.attributes;
+		var frame = infoRender.frame;
 
 
-		if ( index !== null ) {
-
-			updateAttribute( index, gl.ELEMENT_ARRAY_BUFFER );
-
-		}
-
-		for ( var name in attributes ) {
-
-			updateAttribute( attributes[ name ], gl.ARRAY_BUFFER );
-
-		}
+		var geometry = object.geometry;
+		var buffergeometry = geometries.get( object, geometry );
 
 
-		// morph targets
+		// Update once per frame
 
 
-		var morphAttributes = geometry.morphAttributes;
+		if ( updateList[ buffergeometry.id ] !== frame ) {
 
 
-		for ( var name in morphAttributes ) {
+			if ( geometry.isGeometry ) {
 
 
-			var array = morphAttributes[ name ];
-
-			for ( var i = 0, l = array.length; i < l; i ++ ) {
-
-				updateAttribute( array[ i ], gl.ARRAY_BUFFER );
+				buffergeometry.updateFromObject( object );
 
 
 			}
 			}
 
 
-		}
-
-		return geometry;
-
-	}
-
-	function updateAttribute( attribute, bufferType ) {
-
-		var data = ( attribute.isInterleavedBufferAttribute ) ? attribute.data : attribute;
-
-		var attributeProperties = properties.get( data );
-
-		if ( attributeProperties.__webglBuffer === undefined ) {
-
-			createBuffer( attributeProperties, data, bufferType );
-
-		} else if ( attributeProperties.version !== data.version ) {
-
-			updateBuffer( attributeProperties, data, bufferType );
-
-		}
-
-	}
-
-	function createBuffer( attributeProperties, data, bufferType ) {
-
-		attributeProperties.__webglBuffer = gl.createBuffer();
-		gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
-
-		var usage = data.dynamic ? gl.DYNAMIC_DRAW : gl.STATIC_DRAW;
-
-		gl.bufferData( bufferType, data.array, usage );
-
-		var type = gl.FLOAT;
-		var array = data.array;
-
-		if ( array instanceof Float32Array ) {
-
-			type = gl.FLOAT;
-
-		} else if ( array instanceof Float64Array ) {
-
-			console.warn( "Unsupported data buffer format: Float64Array" );
-
-		} else if ( array instanceof Uint16Array ) {
-
-			type = gl.UNSIGNED_SHORT;
-
-		} else if ( array instanceof Int16Array ) {
+			geometries.update( buffergeometry );
 
 
-			type = gl.SHORT;
-
-		} else if ( array instanceof Uint32Array ) {
-
-			type = gl.UNSIGNED_INT;
-
-		} else if ( array instanceof Int32Array ) {
-
-			type = gl.INT;
-
-		} else if ( array instanceof Int8Array ) {
-
-			type = gl.BYTE;
-
-		} else if ( array instanceof Uint8Array ) {
-
-			type = gl.UNSIGNED_BYTE;
+			updateList[ buffergeometry.id ] = frame;
 
 
 		}
 		}
 
 
-		attributeProperties.bytesPerElement = array.BYTES_PER_ELEMENT;
-		attributeProperties.type = type;
-		attributeProperties.version = data.version;
-
-		data.onUploadCallback();
+		return buffergeometry;
 
 
 	}
 	}
 
 
-	function updateBuffer( attributeProperties, data, bufferType ) {
-
-		gl.bindBuffer( bufferType, attributeProperties.__webglBuffer );
-
-		if ( data.dynamic === false ) {
-
-			gl.bufferData( bufferType, data.array, gl.STATIC_DRAW );
-
-		} else if ( data.updateRange.count === - 1 ) {
-
-			// Not using update ranges
+	function clear() {
 
 
-			gl.bufferSubData( bufferType, 0, data.array );
-
-		} else if ( data.updateRange.count === 0 ) {
-
-			console.error( 'THREE.WebGLObjects.updateBuffer: dynamic THREE.BufferAttribute marked as needsUpdate but updateRange.count is 0, ensure you are using set methods or updating manually.' );
-
-		} else {
-
-			gl.bufferSubData( bufferType, data.updateRange.offset * data.array.BYTES_PER_ELEMENT,
-							  data.array.subarray( data.updateRange.offset, data.updateRange.offset + data.updateRange.count ) );
-
-			data.updateRange.count = 0; // reset range
-
-		}
-
-		attributeProperties.version = data.version;
-
-	}
-
-	function getAttributeBuffer( attribute ) {
-
-		if ( attribute.isInterleavedBufferAttribute ) {
-
-			return properties.get( attribute.data ).__webglBuffer;
-
-		}
-
-		return properties.get( attribute ).__webglBuffer;
-
-	}
-
-	function getAttributeProperties( attribute ) {
-
-		if ( attribute.isInterleavedBufferAttribute ) {
-
-			return properties.get( attribute.data );
-
-		}
-
-		return properties.get( attribute );
-
-	}
-
-	function getWireframeAttribute( geometry ) {
-
-		var property = properties.get( geometry );
-
-		if ( property.wireframe !== undefined ) {
-
-			return property.wireframe;
-
-		}
-
-		var indices = [];
-
-		var index = geometry.index;
-		var attributes = geometry.attributes;
-
-		// console.time( 'wireframe' );
-
-		if ( index !== null ) {
-
-			var array = index.array;
-
-			for ( var i = 0, l = array.length; i < l; i += 3 ) {
-
-				var a = array[ i + 0 ];
-				var b = array[ i + 1 ];
-				var c = array[ i + 2 ];
-
-				indices.push( a, b, b, c, c, a );
-
-			}
-
-		} else {
-
-			var array = attributes.position.array;
-
-			for ( var i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) {
-
-				var a = i + 0;
-				var b = i + 1;
-				var c = i + 2;
-
-				indices.push( a, b, b, c, c, a );
-
-			}
-
-		}
-
-		// console.timeEnd( 'wireframe' );
-
-		var attribute = new ( arrayMax( indices ) > 65535 ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 );
-
-		updateAttribute( attribute, gl.ELEMENT_ARRAY_BUFFER );
-
-		property.wireframe = attribute;
-
-		return attribute;
+		updateList = {};
 
 
 	}
 	}
 
 
 	return {
 	return {
 
 
-		getAttributeBuffer: getAttributeBuffer,
-		getAttributeProperties: getAttributeProperties,
-		getWireframeAttribute: getWireframeAttribute,
-
-		update: update
+		update: update,
+		clear: clear
 
 
 	};
 	};
 
 

+ 19 - 17
src/renderers/webgl/WebGLProperties.js

@@ -6,36 +6,38 @@ function WebGLProperties() {
 
 
 	var properties = {};
 	var properties = {};
 
 
-	return {
+	function get( object ) {
 
 
-		get: function ( object ) {
+		var uuid = object.uuid;
+		var map = properties[ uuid ];
 
 
-			var uuid = object.uuid;
-			var map = properties[ uuid ];
+		if ( map === undefined ) {
 
 
-			if ( map === undefined ) {
+			map = {};
+			properties[ uuid ] = map;
 
 
-				map = {};
-				properties[ uuid ] = map;
+		}
 
 
-			}
+		return map;
 
 
-			return map;
+	}
 
 
-		},
+	function remove( object ) {
 
 
-		delete: function ( object ) {
+		delete properties[ object.uuid ];
 
 
-			delete properties[ object.uuid ];
+	}
 
 
-		},
+	function clear() {
 
 
-		clear: function () {
+		properties = {};
 
 
-			properties = {};
-
-		}
+	}
 
 
+	return {
+		get: get,
+		remove: remove,
+		clear: clear
 	};
 	};
 
 
 }
 }

+ 20 - 20
src/renderers/webgl/WebGLShadowMap.js

@@ -18,27 +18,27 @@ import { Frustum } from '../../math/Frustum';
 function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 
 
 	var _gl = _renderer.context,
 	var _gl = _renderer.context,
-	_state = _renderer.state,
-	_frustum = new Frustum(),
-	_projScreenMatrix = new Matrix4(),
+		_state = _renderer.state,
+		_frustum = new Frustum(),
+		_projScreenMatrix = new Matrix4(),
 
 
-	_lightShadows = _lights.shadows,
+		_lightShadows = _lights.shadows,
 
 
-	_shadowMapSize = new Vector2(),
-	_maxShadowMapSize = new Vector2( capabilities.maxTextureSize, capabilities.maxTextureSize ),
+		_shadowMapSize = new Vector2(),
+		_maxShadowMapSize = new Vector2( capabilities.maxTextureSize, capabilities.maxTextureSize ),
 
 
-	_lookTarget = new Vector3(),
-	_lightPositionWorld = new Vector3(),
+		_lookTarget = new Vector3(),
+		_lightPositionWorld = new Vector3(),
 
 
-	_MorphingFlag = 1,
-	_SkinningFlag = 2,
+		_MorphingFlag = 1,
+		_SkinningFlag = 2,
 
 
-	_NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
+		_NumberOfMaterialVariants = ( _MorphingFlag | _SkinningFlag ) + 1,
 
 
-	_depthMaterials = new Array( _NumberOfMaterialVariants ),
-	_distanceMaterials = new Array( _NumberOfMaterialVariants ),
+		_depthMaterials = new Array( _NumberOfMaterialVariants ),
+		_distanceMaterials = new Array( _NumberOfMaterialVariants ),
 
 
-	_materialCache = {};
+		_materialCache = {};
 
 
 	var cubeDirections = [
 	var cubeDirections = [
 		new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
 		new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ),
@@ -111,9 +111,9 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 		if ( _lightShadows.length === 0 ) return;
 		if ( _lightShadows.length === 0 ) return;
 
 
 		// Set GL state for depth map.
 		// Set GL state for depth map.
-		_state.buffers.color.setClear( 1, 1, 1, 1 );
 		_state.disable( _gl.BLEND );
 		_state.disable( _gl.BLEND );
-		_state.setDepthTest( true );
+		_state.buffers.color.setClear( 1, 1, 1, 1 );
+		_state.buffers.depth.setTest( true );
 		_state.setScissorTest( false );
 		_state.setScissorTest( false );
 
 
 		// render depth map
 		// render depth map
@@ -393,11 +393,11 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 
 
 		if ( object.visible === false ) return;
 		if ( object.visible === false ) return;
 
 
-		var visible = ( object.layers.mask & camera.layers.mask ) !== 0;
+		var visible = object.layers.test( camera.layers );
 
 
 		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
 		if ( visible && ( object.isMesh || object.isLine || object.isPoints ) ) {
 
 
-			if ( object.castShadow && ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) ) {
+			if ( object.castShadow && ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) ) {
 
 
 				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
 				object.modelViewMatrix.multiplyMatrices( shadowCamera.matrixWorldInverse, object.matrixWorld );
 
 
@@ -413,7 +413,7 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 						var group = groups[ k ];
 						var group = groups[ k ];
 						var groupMaterial = material[ group.materialIndex ];
 						var groupMaterial = material[ group.materialIndex ];
 
 
-						if ( groupMaterial && groupMaterial.visible === true ) {
+						if ( groupMaterial && groupMaterial.visible ) {
 
 
 							var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld );
 							var depthMaterial = getDepthMaterial( object, groupMaterial, isPointLight, _lightPositionWorld );
 							_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
 							_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, group );
@@ -422,7 +422,7 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 
 
 					}
 					}
 
 
-				} else if ( material.visible === true ) {
+				} else if ( material.visible ) {
 
 
 					var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld );
 					var depthMaterial = getDepthMaterial( object, material, isPointLight, _lightPositionWorld );
 					_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );
 					_renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null );

+ 16 - 53
src/renderers/webgl/WebGLState.js

@@ -2,7 +2,7 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-import { NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceFront, CullFaceBack, CullFaceNone, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NoBlending, NormalBlending } from '../../constants';
+import { NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDepth, LessDepth, AlwaysDepth, NeverDepth, CullFaceFront, CullFaceBack, CullFaceNone, CustomBlending, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NoBlending, NormalBlending, DoubleSide, BackSide } from '../../constants';
 import { Vector4 } from '../../math/Vector4';
 import { Vector4 } from '../../math/Vector4';
 
 
 function WebGLState( gl, extensions, paramThreeToGL ) {
 function WebGLState( gl, extensions, paramThreeToGL ) {
@@ -383,7 +383,7 @@ function WebGLState( gl, extensions, paramThreeToGL ) {
 		stencilBuffer.setClear( 0 );
 		stencilBuffer.setClear( 0 );
 
 
 		enable( gl.DEPTH_TEST );
 		enable( gl.DEPTH_TEST );
-		setDepthFunc( LessEqualDepth );
+		depthBuffer.setFunc( LessEqualDepth );
 
 
 		setFlipSided( false );
 		setFlipSided( false );
 		setCullFace( CullFaceBack );
 		setCullFace( CullFaceBack );
@@ -625,53 +625,24 @@ function WebGLState( gl, extensions, paramThreeToGL ) {
 
 
 	}
 	}
 
 
-	// TODO Deprecate
+	function setMaterial( material ) {
 
 
-	function setColorWrite( colorWrite ) {
+		material.side === DoubleSide
+			? disable( gl.CULL_FACE )
+			: enable( gl.CULL_FACE );
 
 
-		colorBuffer.setMask( colorWrite );
+		setFlipSided( material.side === BackSide );
 
 
-	}
-
-	function setDepthTest( depthTest ) {
-
-		depthBuffer.setTest( depthTest );
-
-	}
-
-	function setDepthWrite( depthWrite ) {
-
-		depthBuffer.setMask( depthWrite );
-
-	}
-
-	function setDepthFunc( depthFunc ) {
-
-		depthBuffer.setFunc( depthFunc );
-
-	}
+		material.transparent === true
+			? setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha )
+			: setBlending( NoBlending );
 
 
-	function setStencilTest( stencilTest ) {
+		depthBuffer.setFunc( material.depthFunc );
+		depthBuffer.setTest( material.depthTest );
+		depthBuffer.setMask( material.depthWrite );
+		colorBuffer.setMask( material.colorWrite );
 
 
-		stencilBuffer.setTest( stencilTest );
-
-	}
-
-	function setStencilWrite( stencilWrite ) {
-
-		stencilBuffer.setMask( stencilWrite );
-
-	}
-
-	function setStencilFunc( stencilFunc, stencilRef, stencilMask ) {
-
-		stencilBuffer.setFunc( stencilFunc, stencilRef, stencilMask );
-
-	}
-
-	function setStencilOp( stencilFail, stencilZFail, stencilZPass ) {
-
-		stencilBuffer.setOp( stencilFail, stencilZFail, stencilZPass );
+		setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
 
 
 	}
 	}
 
 
@@ -934,15 +905,7 @@ function WebGLState( gl, extensions, paramThreeToGL ) {
 		getCompressedTextureFormats: getCompressedTextureFormats,
 		getCompressedTextureFormats: getCompressedTextureFormats,
 
 
 		setBlending: setBlending,
 		setBlending: setBlending,
-
-		setColorWrite: setColorWrite,
-		setDepthTest: setDepthTest,
-		setDepthWrite: setDepthWrite,
-		setDepthFunc: setDepthFunc,
-		setStencilTest: setStencilTest,
-		setStencilWrite: setStencilWrite,
-		setStencilFunc: setStencilFunc,
-		setStencilOp: setStencilOp,
+		setMaterial: setMaterial,
 
 
 		setFlipSided: setFlipSided,
 		setFlipSided: setFlipSided,
 		setCullFace: setCullFace,
 		setCullFace: setCullFace,

+ 9 - 10
src/renderers/webgl/WebGLTextures.js

@@ -5,9 +5,8 @@
 import { LinearFilter, NearestFilter, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, ClampToEdgeWrapping, NearestMipMapLinearFilter, NearestMipMapNearestFilter } from '../../constants';
 import { LinearFilter, NearestFilter, RGBFormat, RGBAFormat, DepthFormat, DepthStencilFormat, UnsignedShortType, UnsignedIntType, UnsignedInt248Type, FloatType, HalfFloatType, ClampToEdgeWrapping, NearestMipMapLinearFilter, NearestMipMapNearestFilter } from '../../constants';
 import { _Math } from '../../math/Math';
 import { _Math } from '../../math/Math';
 
 
-function WebGLTextures( _gl, extensions, state, properties, capabilities, paramThreeToGL, info ) {
+function WebGLTextures( _gl, extensions, state, properties, capabilities, paramThreeToGL, infoMemory ) {
 
 
-	var _infoMemory = info.memory;
 	var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext );
 	var _isWebGL2 = ( typeof WebGL2RenderingContext !== 'undefined' && _gl instanceof WebGL2RenderingContext );
 
 
 	//
 	//
@@ -96,7 +95,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT
 
 
 		deallocateTexture( texture );
 		deallocateTexture( texture );
 
 
-		_infoMemory.textures --;
+		infoMemory.textures --;
 
 
 
 
 	}
 	}
@@ -109,7 +108,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT
 
 
 		deallocateRenderTarget( renderTarget );
 		deallocateRenderTarget( renderTarget );
 
 
-		_infoMemory.textures --;
+		infoMemory.textures --;
 
 
 	}
 	}
 
 
@@ -136,7 +135,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT
 		}
 		}
 
 
 		// remove all webgl properties
 		// remove all webgl properties
-		properties.delete( texture );
+		properties.remove( texture );
 
 
 	}
 	}
 
 
@@ -175,8 +174,8 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT
 
 
 		}
 		}
 
 
-		properties.delete( renderTarget.texture );
-		properties.delete( renderTarget );
+		properties.remove( renderTarget.texture );
+		properties.remove( renderTarget );
 
 
 	}
 	}
 
 
@@ -228,7 +227,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT
 
 
 					textureProperties.__image__webglTextureCube = _gl.createTexture();
 					textureProperties.__image__webglTextureCube = _gl.createTexture();
 
 
-					_infoMemory.textures ++;
+					infoMemory.textures ++;
 
 
 				}
 				}
 
 
@@ -399,7 +398,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT
 
 
 			textureProperties.__webglTexture = _gl.createTexture();
 			textureProperties.__webglTexture = _gl.createTexture();
 
 
-			_infoMemory.textures ++;
+			infoMemory.textures ++;
 
 
 		}
 		}
 
 
@@ -700,7 +699,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, paramT
 
 
 		textureProperties.__webglTexture = _gl.createTexture();
 		textureProperties.__webglTexture = _gl.createTexture();
 
 
-		_infoMemory.textures ++;
+		infoMemory.textures ++;
 
 
 		var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
 		var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
 		var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );
 		var isTargetPowerOfTwo = isPowerOfTwo( renderTarget );

+ 2 - 2
src/renderers/webgl/plugins/LensFlarePlugin.js

@@ -228,7 +228,7 @@ function LensFlarePlugin( renderer, flares ) {
 		gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
 		gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, elementBuffer );
 
 
 		state.disable( gl.CULL_FACE );
 		state.disable( gl.CULL_FACE );
-		state.setDepthWrite( false );
+		state.buffers.depth.setMask( false );
 
 
 		for ( var i = 0, l = flares.length; i < l; i ++ ) {
 		for ( var i = 0, l = flares.length; i < l; i ++ ) {
 
 
@@ -353,7 +353,7 @@ function LensFlarePlugin( renderer, flares ) {
 
 
 		state.enable( gl.CULL_FACE );
 		state.enable( gl.CULL_FACE );
 		state.enable( gl.DEPTH_TEST );
 		state.enable( gl.DEPTH_TEST );
-		state.setDepthWrite( true );
+		state.buffers.depth.setMask( true );
 
 
 		renderer.resetGLState();
 		renderer.resetGLState();
 
 

+ 2 - 2
src/renderers/webgl/plugins/SpritePlugin.js

@@ -224,8 +224,8 @@ function SpritePlugin( renderer, sprites ) {
 			gl.uniform2fv( uniforms.scale, scale );
 			gl.uniform2fv( uniforms.scale, scale );
 
 
 			state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
 			state.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
-			state.setDepthTest( material.depthTest );
-			state.setDepthWrite( material.depthWrite );
+			state.buffers.depth.setTest( material.depthTest );
+			state.buffers.depth.setMask( material.depthWrite );
 
 
 			if ( material.map ) {
 			if ( material.map ) {
 
 

+ 10 - 30
test/unit/src/core/Object3D.js

@@ -12,8 +12,7 @@ QUnit.test( "rotateX" , function( assert ) {
 	var angleInRad = 1.562;
 	var angleInRad = 1.562;
 	obj.rotateX(angleInRad);
 	obj.rotateX(angleInRad);
 
 
-	// should calculate the correct rotation on x
-	checkIfFloatsAreEqual(obj.rotation.x, angleInRad, assert);
+	assert.numEqual( obj.rotation.x, angleInRad, "x is equal" );
 });
 });
 
 
 QUnit.test( "rotateY" , function( assert ) {
 QUnit.test( "rotateY" , function( assert ) {
@@ -22,8 +21,7 @@ QUnit.test( "rotateY" , function( assert ) {
 	var angleInRad = -0.346;
 	var angleInRad = -0.346;
 	obj.rotateY(angleInRad);
 	obj.rotateY(angleInRad);
 
 
-	// should calculate the correct rotation on y
-	checkIfFloatsAreEqual(obj.rotation.y, angleInRad, assert);
+	assert.numEqual( obj.rotation.y, angleInRad, "y is equal" );
 });
 });
 
 
 QUnit.test( "rotateZ" , function( assert ) {
 QUnit.test( "rotateZ" , function( assert ) {
@@ -32,71 +30,53 @@ QUnit.test( "rotateZ" , function( assert ) {
 	var angleInRad = 1;
 	var angleInRad = 1;
 	obj.rotateZ(angleInRad);
 	obj.rotateZ(angleInRad);
 
 
-	// should calculate the correct rotation on y
-	checkIfFloatsAreEqual(obj.rotation.z, angleInRad, assert);
+	assert.numEqual( obj.rotation.z, angleInRad, "z is equal" );
 });
 });
 
 
 QUnit.test( "translateOnAxis" , function( assert ) {
 QUnit.test( "translateOnAxis" , function( assert ) {
 	var obj = new THREE.Object3D();
 	var obj = new THREE.Object3D();
 
 
-	// get a reference object for comparing
-	var reference = {x: 1, y: 1.23, z: -4.56};
 	obj.translateOnAxis(new THREE.Vector3(1, 0, 0), 1);
 	obj.translateOnAxis(new THREE.Vector3(1, 0, 0), 1);
 	obj.translateOnAxis(new THREE.Vector3(0, 1, 0), 1.23);
 	obj.translateOnAxis(new THREE.Vector3(0, 1, 0), 1.23);
 	obj.translateOnAxis(new THREE.Vector3(0, 0, 1), -4.56);
 	obj.translateOnAxis(new THREE.Vector3(0, 0, 1), -4.56);
 
 
-	checkIfPropsAreEqual(reference, obj.position, assert);
+	assert.propEqual( obj.position, { x: 1, y: 1.23, z: -4.56 } );
 });
 });
 
 
 QUnit.test( "translateX" , function( assert ) {
 QUnit.test( "translateX" , function( assert ) {
 	var obj = new THREE.Object3D();
 	var obj = new THREE.Object3D();
 	obj.translateX(1.234);
 	obj.translateX(1.234);
 
 
-	assert.ok( obj.position.x === 1.234 , "x is equal" );
+	assert.numEqual( obj.position.x, 1.234, "x is equal" );
 });
 });
 
 
 QUnit.test( "translateY" , function( assert ) {
 QUnit.test( "translateY" , function( assert ) {
 	var obj = new THREE.Object3D();
 	var obj = new THREE.Object3D();
 	obj.translateY(1.234);
 	obj.translateY(1.234);
 
 
-	assert.ok( obj.position.y === 1.234 , "y is equal" );
+	assert.numEqual( obj.position.y, 1.234, "y is equal" );
 });
 });
 
 
 QUnit.test( "translateZ" , function( assert ) {
 QUnit.test( "translateZ" , function( assert ) {
 	var obj = new THREE.Object3D();
 	var obj = new THREE.Object3D();
 	obj.translateZ(1.234);
 	obj.translateZ(1.234);
 
 
-	assert.ok( obj.position.z === 1.234 , "z is equal" );
+	assert.numEqual( obj.position.z, 1.234, "z is equal" );
 });
 });
 
 
 QUnit.test( "lookAt" , function( assert ) {
 QUnit.test( "lookAt" , function( assert ) {
 	var obj = new THREE.Object3D();
 	var obj = new THREE.Object3D();
 	obj.lookAt(new THREE.Vector3(0, -1, 1));
 	obj.lookAt(new THREE.Vector3(0, -1, 1));
 
 
-	assert.ok( obj.rotation.x * RadToDeg === 45 , "x is equal" );
+	assert.numEqual( obj.rotation.x * RadToDeg, 45, "x is equal" );
 });
 });
 
 
 QUnit.test( "getWorldRotation" , function( assert ) {
 QUnit.test( "getWorldRotation" , function( assert ) {
 	var obj = new THREE.Object3D();
 	var obj = new THREE.Object3D();
 
 
 	obj.lookAt(new THREE.Vector3(0, -1, 1));
 	obj.lookAt(new THREE.Vector3(0, -1, 1));
-	assert.ok( obj.getWorldRotation().x * RadToDeg === 45 , "x is equal" );
+	assert.numEqual( obj.getWorldRotation().x * RadToDeg, 45, "x is equal" );
 
 
 	obj.lookAt(new THREE.Vector3(1, 0, 0));
 	obj.lookAt(new THREE.Vector3(1, 0, 0));
-	assert.ok( obj.getWorldRotation().y * RadToDeg === 90 , "y is equal" );
+	assert.numEqual( obj.getWorldRotation().y * RadToDeg, 90, "y is equal" );
 });
 });
-
-function checkIfPropsAreEqual(reference, obj, assert) {
-	assert.ok( obj.x === reference.x , "x is equal" );
-	assert.ok( obj.y === reference.y , "y is equal!" );
-	assert.ok( obj.z === reference.z , "z is equal!" );
-}
-
-// since float equal checking is a mess in js, one solution is to cut off
-// decimal places
-function checkIfFloatsAreEqual(f1, f2, assert) {
-	var f1Rounded = ((f1 * 1000) | 0) / 1000;
-	var f2Rounded = ((f2 * 1000) | 0) / 1000;
-
-	assert.ok( f1Rounded === f2Rounded, "passed" );
-}

+ 4 - 5
test/unit/src/math/Triangle.js

@@ -96,11 +96,10 @@ QUnit.test( "normal" , function( assert ) {
 QUnit.test( "plane" , function( assert ) {
 QUnit.test( "plane" , function( assert ) {
 	var a = new THREE.Triangle();
 	var a = new THREE.Triangle();
 
 
-	// artificial normal is created in this case.
-	assert.ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" );
-	assert.ok( a.plane().distanceToPoint( a.b ) == 0, "Passed!" );
-	assert.ok( a.plane().distanceToPoint( a.c ) == 0, "Passed!" );
-	assert.ok( a.plane().normal.equals( a.normal() ), "Passed!" );
+	assert.ok( isNaN( a.plane().distanceToPoint( a.a ) ), "Passed!" );
+	assert.ok( isNaN( a.plane().distanceToPoint( a.b ) ), "Passed!" );
+	assert.ok( isNaN( a.plane().distanceToPoint( a.c ) ), "Passed!" );
+	assert.propEqual( a.plane().normal, {x: NaN, y: NaN, z: NaN}, "Passed!" );
 
 
 	a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
 	a = new THREE.Triangle( new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ) );
 	assert.ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" );
 	assert.ok( a.plane().distanceToPoint( a.a ) == 0, "Passed!" );

+ 1 - 1
test/unit/src/math/Vector2.js

@@ -225,7 +225,7 @@ QUnit.test( "setLength" , function( assert ) {
 	a = new THREE.Vector2( 0, 0 );
 	a = new THREE.Vector2( 0, 0 );
 	assert.ok( a.length() == 0, "Passed!" );
 	assert.ok( a.length() == 0, "Passed!" );
 	a.setLength( y );
 	a.setLength( y );
-	assert.ok( a.length() == 0, "Passed!" );
+	assert.ok( isNaN( a.length() ), "Passed!" );
 });
 });
 
 
 QUnit.test( "lerp/clone", function( assert ) {
 QUnit.test( "lerp/clone", function( assert ) {

+ 1 - 1
test/unit/src/math/Vector3.js

@@ -235,7 +235,7 @@ QUnit.test( "setLength" , function( assert ) {
 	a = new THREE.Vector3( 0, 0, 0 );
 	a = new THREE.Vector3( 0, 0, 0 );
 	assert.ok( a.length() == 0, "Passed!" );
 	assert.ok( a.length() == 0, "Passed!" );
 	a.setLength( y );
 	a.setLength( y );
-	assert.ok( a.length() == 0, "Passed!" );
+	assert.ok( isNaN( a.length() ), "Passed!" );
 
 
 });
 });
 
 

+ 7 - 7
test/unit/src/math/Vector4.js

@@ -132,9 +132,9 @@ QUnit.test( "multiply/divide", function( assert ) {
 
 
 	b.multiplyScalar( -2 );
 	b.multiplyScalar( -2 );
 	assert.ok( b.x == 2*x, "Passed!" );
 	assert.ok( b.x == 2*x, "Passed!" );
-	assert.ok( b.y == 2*y, "Passed!" );	
-	assert.ok( b.z == 2*z, "Passed!" );	
-	assert.ok( b.w == 2*w, "Passed!" );	
+	assert.ok( b.y == 2*y, "Passed!" );
+	assert.ok( b.z == 2*z, "Passed!" );
+	assert.ok( b.w == 2*w, "Passed!" );
 
 
 	a.divideScalar( -2 );
 	a.divideScalar( -2 );
 	assert.ok( a.x == x, "Passed!" );
 	assert.ok( a.x == x, "Passed!" );
@@ -202,7 +202,7 @@ QUnit.test( "length/lengthSq", function( assert ) {
 	var c = new THREE.Vector4( 0, 0, z, 0 );
 	var c = new THREE.Vector4( 0, 0, z, 0 );
 	var d = new THREE.Vector4( 0, 0, 0, w );
 	var d = new THREE.Vector4( 0, 0, 0, w );
 	var e = new THREE.Vector4( 0, 0, 0, 0 );
 	var e = new THREE.Vector4( 0, 0, 0, 0 );
-	
+
 	assert.ok( a.length() == x, "Passed!" );
 	assert.ok( a.length() == x, "Passed!" );
 	assert.ok( a.lengthSq() == x*x, "Passed!" );
 	assert.ok( a.lengthSq() == x*x, "Passed!" );
 	assert.ok( b.length() == y, "Passed!" );
 	assert.ok( b.length() == y, "Passed!" );
@@ -224,7 +224,7 @@ QUnit.test( "normalize" , function( assert ) {
 	var b = new THREE.Vector4( 0, -y, 0, 0 );
 	var b = new THREE.Vector4( 0, -y, 0, 0 );
 	var c = new THREE.Vector4( 0, 0, z, 0 );
 	var c = new THREE.Vector4( 0, 0, z, 0 );
 	var d = new THREE.Vector4( 0, 0, 0, -w );
 	var d = new THREE.Vector4( 0, 0, 0, -w );
-	
+
 	a.normalize();
 	a.normalize();
 	assert.ok( a.length() == 1, "Passed!" );
 	assert.ok( a.length() == 1, "Passed!" );
 	assert.ok( a.x == 1, "Passed!" );
 	assert.ok( a.x == 1, "Passed!" );
@@ -249,7 +249,7 @@ QUnit.test( "distanceTo/distanceToSquared", function() {
 	var c = new THREE.Vector4( 0, 0, z, 0 );
 	var c = new THREE.Vector4( 0, 0, z, 0 );
 	var d = new THREE.Vector4( 0, 0, 0, -w );
 	var d = new THREE.Vector4( 0, 0, 0, -w );
 	var e = new THREE.Vector4();
 	var e = new THREE.Vector4();
-	
+
 	ok( a.distanceTo( e ) == x, "Passed!" );
 	ok( a.distanceTo( e ) == x, "Passed!" );
 	ok( a.distanceToSquared( e ) == x*x, "Passed!" );
 	ok( a.distanceToSquared( e ) == x*x, "Passed!" );
 
 
@@ -275,7 +275,7 @@ QUnit.test( "setLength" , function( assert ) {
 	a = new THREE.Vector4( 0, 0, 0, 0 );
 	a = new THREE.Vector4( 0, 0, 0, 0 );
 	assert.ok( a.length() == 0, "Passed!" );
 	assert.ok( a.length() == 0, "Passed!" );
 	a.setLength( y );
 	a.setLength( y );
-	assert.ok( a.length() == 0, "Passed!" );
+	assert.ok( isNaN( a.length() ), "Passed!" );
 });
 });
 
 
 QUnit.test( "lerp/clone", function( assert ) {
 QUnit.test( "lerp/clone", function( assert ) {

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно