Переглянути джерело

Merge remote-tracking branch 'mrdoob/dev' into dev

Daniel 10 роки тому
батько
коміт
353a27ee2e
100 змінених файлів з 4719 додано та 4126 видалено
  1. 310 170
      build/three.js
  2. 297 304
      build/three.min.js
  3. 1 1
      docs/api/core/BufferAttribute.html
  4. 91 3
      docs/api/core/BufferGeometry.html
  5. 41 2
      docs/api/core/Geometry.html
  6. 2 2
      docs/api/core/Raycaster.html
  7. 4 2
      docs/api/extras/core/Path.html
  8. 6 3
      docs/api/extras/curves/EllipseCurve.html
  9. 10 63
      docs/api/lights/DirectionalLight.html
  10. 8 3
      docs/api/loaders/Cache.html
  11. 7 5
      docs/api/math/Color.html
  12. 42 20
      docs/api/math/Quaternion.html
  13. 6 4
      docs/api/math/Vector2.html
  14. 5 4
      docs/api/math/Vector3.html
  15. 5 6
      docs/api/math/Vector4.html
  16. 5 12
      docs/api/objects/Mesh.html
  17. 0 3
      docs/api/objects/SkinnedMesh.html
  18. 10 8
      docs/api/renderers/WebGLRenderer.html
  19. 15 23
      docs/api/textures/DataTexture.html
  20. 6 4
      docs/manual/introduction/Creating-a-scene.html
  21. 1 2
      docs/scenes/bones-browser.html
  22. 1 1
      docs/scenes/geometry-browser.html
  23. 1 0
      editor/css/dark.css
  24. 1 0
      editor/css/light.css
  25. 2 0
      editor/index.html
  26. 0 3
      editor/js/Config.js
  27. 8 7
      editor/js/Editor.js
  28. 81 0
      editor/js/History.js
  29. 28 6
      editor/js/Loader.js
  30. 29 1
      editor/js/Menubar.Edit.js
  31. 22 7
      editor/js/Sidebar.Animation.js
  32. 9 31
      editor/js/Sidebar.Geometry.BufferGeometry.js
  33. 1 15
      editor/js/Sidebar.Geometry.Modifiers.js
  34. 23 6
      editor/js/Sidebar.Material.js
  35. 3 3
      editor/js/Sidebar.Object3D.js
  36. 38 54
      editor/js/Viewport.js
  37. 3 3
      editor/js/libs/app.js
  38. 1 1
      examples/canvas_geometry_cube.html
  39. 1 2
      examples/canvas_geometry_earth.html
  40. 2 4
      examples/canvas_geometry_terrain.html
  41. 1 1
      examples/canvas_interactive_voxelpainter.html
  42. 9 0
      examples/canvas_materials.html
  43. 0 345
      examples/canvas_particles_shapes.html
  44. 3 3
      examples/canvas_particles_sprites.html
  45. 1 1
      examples/css3d_molecules.html
  46. 10 6
      examples/index.html
  47. 2 2
      examples/js/AudioObject.js
  48. 11 22
      examples/js/BlendCharacter.js
  49. 33 27
      examples/js/BlendCharacterGui.js
  50. 52 16
      examples/js/Car.js
  51. 137 92
      examples/js/Cloth.js
  52. 96 92
      examples/js/CurveExtras.js
  53. 13 1
      examples/js/Detector.js
  54. 505 0
      examples/js/GPUParticleSystem.js
  55. 64 64
      examples/js/Gyroscope.js
  56. 4 8
      examples/js/MD2Character.js
  57. 13 13
      examples/js/MD2CharacterComplex.js
  58. 282 278
      examples/js/MarchingCubes.js
  59. 31 30
      examples/js/Mirror.js
  60. 163 128
      examples/js/Ocean.js
  61. 69 46
      examples/js/Octree.js
  62. 15 3
      examples/js/PRNG.js
  63. 72 57
      examples/js/ParametricGeometries.js
  64. 29 31
      examples/js/ShaderDeferred.js
  65. 6 6
      examples/js/ShaderGodRays.js
  66. 37 43
      examples/js/ShaderSkin.js
  67. 25 26
      examples/js/ShaderTerrain.js
  68. 177 177
      examples/js/ShaderToon.js
  69. 28 20
      examples/js/SimulationRenderer.js
  70. 11 12
      examples/js/SkyShader.js
  71. 0 835
      examples/js/Sparks.js
  72. 18 10
      examples/js/TypedArrayUtils.js
  73. 17 1
      examples/js/UCSCharacter.js
  74. 36 26
      examples/js/WaterShader.js
  75. 7 6
      examples/js/cameras/CombinedCamera.js
  76. 6 0
      examples/js/controls/DeviceOrientationControls.js
  77. 14 7
      examples/js/controls/DragControls.js
  78. 37 8
      examples/js/controls/EditorControls.js
  79. 31 9
      examples/js/controls/FirstPersonControls.js
  80. 39 15
      examples/js/controls/FlyControls.js
  81. 13 7
      examples/js/controls/MouseControls.js
  82. 823 414
      examples/js/controls/OrbitControls.js
  83. 58 28
      examples/js/controls/OrthographicTrackballControls.js
  84. 7 1
      examples/js/controls/PointerLockControls.js
  85. 63 36
      examples/js/controls/TrackballControls.js
  86. 87 79
      examples/js/controls/TransformControls.js
  87. 8 2
      examples/js/controls/VRControls.js
  88. 14 14
      examples/js/crossfade/gui.js
  89. 10 8
      examples/js/crossfade/scenes.js
  90. 28 26
      examples/js/crossfade/transition.js
  91. 20 12
      examples/js/curves/NURBSCurve.js
  92. 15 9
      examples/js/curves/NURBSSurface.js
  93. 190 112
      examples/js/curves/NURBSUtils.js
  94. 14 12
      examples/js/effects/AnaglyphEffect.js
  95. 68 51
      examples/js/effects/AsciiEffect.js
  96. 11 11
      examples/js/effects/ParallaxBarrierEffect.js
  97. 13 5
      examples/js/effects/StereoEffect.js
  98. 24 23
      examples/js/effects/VREffect.js
  99. 20 18
      examples/js/exporters/STLBinaryExporter.js
  100. 3 3
      examples/js/exporters/STLExporter.js

Різницю між файлами не показано, бо вона завелика
+ 310 - 170
build/three.js


Різницю між файлами не показано, бо вона завелика
+ 297 - 304
build/three.min.js


+ 1 - 1
docs/api/core/BufferAttribute.html

@@ -17,7 +17,7 @@
 		<h2>Constructor</h2>
 		<h3>[name]([page:Array array], [page:Integer itemSize])</h3>
 		<div>
-		Instantiates this attibute with data from the associated buffer. The array can either be a regular Array or a Typed Array.
+		Instantiates this attribute with data from the associated buffer. The array can either be a regular Array or a Typed Array.
 		itemSize gives the number of values of the array that should be associated with a particular vertex.
 		</div>
 

+ 91 - 3
docs/api/core/BufferGeometry.html

@@ -129,7 +129,7 @@
 		When set, it holds certain buffers in memory to have faster updates for this object. When unset, it deletes those buffers and   saves memory.
 		</div> -->
 
-		<h3>[property:Array drawCalls] (previously [property:Array offsets])</h3>
+		<h3>[property:Array drawcalls] (previously [property:Array offsets])</h3>
 		<div>
 		For geometries that use indexed triangles, this Array can be used to split the object into multiple WebGL draw calls. Each draw call will draw some subset of the vertices in this geometry using the configured [page:Material shader]. This may be necessary if, for instance, you have more than 65535 vertices in your object.
 		Each element is an object of the form:
@@ -176,14 +176,67 @@
 
 		<h3>[method:null addDrawCall]( [page:Integer start], [page:Integer count], [page:Integer indexOffset] )</h3>
 		<div>
-		Adds a draw call to this geometry; see the drawcalls property for details.
+		Adds a draw call to this geometry; see the [page:BufferGeometry.drawcalls drawcalls] property for details.
+		</div>
+    
+		<h3>[method:null clearDrawCalls]( )</h3>
+		<div>
+		Clears all draw calls.
 		</div>
-
 
 		<h3>[method:null applyMatrix]( [page:Matrix4 matrix] )</h3>
 		<div>
 		Bakes matrix transform directly into vertex coordinates.
 		</div>
+    
+		<h3>[method:null center] ()</h3>
+		<div>
+		Center the geometry based on the bounding box.
+		</div>
+    
+		<h3>[method:BufferGeometry rotateX] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the X axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:BufferGeometry rotateY] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the Y axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:BufferGeometry rotateZ] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the Z axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:BufferGeometry translate] ( [page:Float x], [page:Float y], [page:Float z] )</h3>
+		<div>
+		Translate the geometry. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.position] for typical real-time mesh translation.
+		</div>
+
+		<h3>[method:BufferGeometry scale] ( [page:Float x], [page:Float y], [page:Float z] )</h3>
+		<div>
+		Scale the geometry data. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.scale] for typical real-time mesh scaling.
+		</div>
+
+		<h3>[method:BufferGeometry lookAt] ( [page:Vector3 vector] )</h3>
+		<div>
+		vector - A world vector to look at.<br />
+		</div>
+		<div>
+		Rotates the geometry to face point in space. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.lookAt] for typical real-time mesh usage.
+		</div>
+
+		<h3>[method:BufferGeometry setFromObject] ( [page:Object3D object] )</h3>
+		<div>
+		Sets the attributes for this BufferGeometry from an [page:Object3D].
+		</div>
 
 		<h3>[method:null computeVertexNormals]()</h3>
 		<div>
@@ -209,6 +262,19 @@
 		Bounding spheres aren't computed by default. They need to be explicitly computed, otherwise they are *null*.
 		</div>
 
+		<h3>[method:null computeOffsets] ( [page:Integer size] )</h3>
+		<div>
+		Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices.
+		This method will effectively rewrite the index buffer and remap all attributes to match the new indices.
+		WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets.
+		size - Defaults to 65535 or 4294967296 if extension OES_element_index_uint supported, but allows for larger or smaller chunks.
+		</div>
+
+		<h3>[method:null merge]( [page:BufferGeometry bufferGeometry], [page:Integer offset] )</h3>
+		<div>
+		Merge in another BufferGeometry with an optional offset of where to start merging in.
+		</div>
+
 		<h3>[method:null dispose]()</h3>
 		<div>
 		Disposes the object from memory. <br />
@@ -225,12 +291,34 @@
 		Returns the [page:BufferAttribute attribute] with the specified name.
 		</div>
 
+		<h3>[method:BufferAttribute removeAttribute]( [page:String name] )</h3>
+		<div>
+		Removes the [page:BufferAttribute attribute] with the specified name.
+		</div>
+
 		<h3>[method:null normalizeNormals]()</h3>
 		<div>
 		Every normal vector in a geometry will have a magnitude of 1.
 		This will correct lighting on the geometry surfaces.
 		</div>
 
+		<h3>[method:Object toJSON]()</h3>
+		<div>
+		Returns a raw object representation of the BufferGeometry.
+		</div>
+		
+		<h3>[method:BufferGeometry clone]()</h3>
+		<div>
+		Creates a clone of this BufferGeometry.
+		</div>
+		
+		<h3>[method:BufferGeometry copy]( [page:BufferGeometry bufferGeometry] )</h3>
+		<div>
+		Copies another BufferGeometry to this BufferGeometry.
+		</div>
+		
+		
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

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

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
@@ -204,10 +204,49 @@
 		Bakes matrix transform directly into vertex coordinates.
 		</div>
 
-		<h3>[method:null center]()</h3>
+		<h3>[method:null center] ()</h3>
 		<div>
 		Center the geometry based on the bounding box.
 		</div>
+    
+		<h3>[method:Geometry rotateX] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the X axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:Geometry rotateY] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the Y axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:Geometry rotateZ] ( [page:Float radians] )</h3>
+		<div>
+		Rotate the geometry about the Z axis. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.rotation] for typical real-time mesh rotation.
+		</div>
+
+		<h3>[method:Geometry translate] ( [page:Float x], [page:Float y], [page:Float z] )</h3>
+		<div>
+		Translate the geometry. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.position] for typical real-time mesh translation.
+		</div>
+
+		<h3>[method:Geometry scale] ( [page:Float x], [page:Float y], [page:Float z] )</h3>
+		<div>
+		Scale the geometry data. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.scale] for typical real-time mesh scaling.
+		</div>
+
+		<h3>[method:Geometry lookAt] ( [page:Vector3 vector] )</h3>
+		<div>
+		vector - A world vector to look at.<br />
+		</div>
+		<div>
+		Rotates the geometry to face point in space. This is typically done as a one time operation, and not during a loop
+    Use [page:Object3D.lookAt] for typical real-time mesh usage.
+		</div>
 
 		<h3>[method:null computeFaceNormals]()</h3>
 		<div>

+ 2 - 2
docs/api/core/Raycaster.html

@@ -71,7 +71,7 @@
 		<h3>[name]( [page:Vector3 origin], [page:Vector3 direction], [page:Float near], [page:Float far] ) {</h3>
 		<div>
 		[page:Vector3 origin] — The origin vector where the ray casts from.<br />
-		[page:Vector3 direction] — The direction vector that  gives direction to the ray.<br />
+		[page:Vector3 direction] — The direction vector that gives direction to the ray. Should be normalized.<br />
 		[page:Float near] — All results returned are further away than near. Near can't be negative. Default value is 0.<br />
 		[page:Float far] — All results returned are closer then far. Far can't be lower then near . Default value is Infinity.
 		</div>
@@ -109,7 +109,7 @@
 		<h3>[method:null set]( [page:Vector3 origin], [page:Vector3 direction] )</h3>
 		<div>
 		[page:Vector3 origin] — The origin vector where the ray casts from.<br />
-		[page:Vector3 direction] — The direction vector that  gives direction to the ray.
+		[page:Vector3 direction] — The normalized direction vector that gives direction to the ray.
 		</div>
 		<div>
 		Updates the ray with a new origin and direction.

+ 4 - 2
docs/api/extras/core/Path.html

@@ -81,7 +81,7 @@
 		</div>
 		<div>Draw an arc absolutely positioned</div>
 
-		<h3>[method:null ellipse]( [page:Float x], [page:Float y], [page:Float xRadius], [page:Float yRadius], [page:Float startAngle], [page:Float endAngle], [page:Float clockwise] )</h3>
+		<h3>[method:null ellipse]( [page:Float x], [page:Float y], [page:Float xRadius], [page:Float yRadius], [page:Float startAngle], [page:Float endAngle], [page:Float clockwise], [page:Float rotation] )</h3>
 		<div>
 		x, y -- The center of the ellipse offset from the last call
 		xRadius -- The radius of the ellipse in the x axis
@@ -89,10 +89,11 @@
 		startAngle -- The start angle in radians
 		endAngle -- The end angle in radians
 		clockwise -- Sweep the ellipse clockwise. Defaults to false
+		rotation -- The rotation angle of the ellipse in radians, counterclockwise from the positive X axis. Optional, defaults to 0
 		</div>
 		<div>Draw an ellipse offset from the last call</div>
 
-		<h3>[method:null absellipse]( [page:Float x], [page:Float y], [page:Float xRadius], [page:Float yRadius], [page:Float startAngle], [page:Float endAngle], [page:Float clockwise] )</h3>
+		<h3>[method:null absellipse]( [page:Float x], [page:Float y], [page:Float xRadius], [page:Float yRadius], [page:Float startAngle], [page:Float endAngle], [page:Float clockwise], [page:Float rotation] )</h3>
 		<div>
 		x, y -- The absolute center of the ellipse
 		xRadius -- The radius of the ellipse in the x axis
@@ -100,6 +101,7 @@
 		startAngle -- The start angle in radians
 		endAngle -- The end angle in radians
 		clockwise -- Sweep the ellipse clockwise. Defaults to false
+		rotation -- The rotation angle of the ellipse in radians, counterclockwise from the positive X axis. Optional, defaults to 0
 		</div>
 		<div>Draw an ellipse absolutely positioned</div>
 

+ 6 - 3
docs/api/extras/curves/EllipseCurve.html

@@ -21,7 +21,8 @@ var curve = new THREE.EllipseCurve(
 	0,  0,            // ax, aY
 	10, 10,           // xRadius, yRadius
 	0,  2 * Math.PI,  // aStartAngle, aEndAngle
-	false             // aClockwise
+	false,            // aClockwise
+	0                 // aRotation 
 );
 
 var path = new THREE.Path( curve.getPoints( 50 ) );
@@ -35,7 +36,7 @@ var ellipse = new THREE.Line( geometry, material );
 		<h2>Constructor</h2>
 
 
-		<h3>[name]( [page:Float aX], [page:Float aY], [page:Float xRadius], [page:Float yRadius], [page:Radians aStartAngle], [page:Radians aEndAngle], [page:Boolean aClockwise] )</h3>
+		<h3>[name]( [page:Float aX], [page:Float aY], [page:Float xRadius], [page:Float yRadius], [page:Radians aStartAngle], [page:Radians aEndAngle], [page:Boolean aClockwise], [page:Radians aRotation] )</h3>
 		<div>
 			aX – The X center of the ellipse<br/>
 			aY – The Y center of the ellipse<br/>
@@ -43,7 +44,8 @@ var ellipse = new THREE.Line( geometry, material );
 			yRadius – The radius of the ellipse in the y direction<br/>
 			aStartAngle – The start angle of the curve in radians starting from the middle right side<br/>
 			aEndAngle – The end angle of the curve in radians starting from the middle right side<br/>
-			aClockwise – Whether the ellipse is clockwise<br/><br/>
+			aClockwise – Whether the ellipse is clockwise<br/>
+			aRotation – The rotation angle of the ellipse in radians, counterclockwise from the positive X axis (optional)<br/><br/>
 
 			<strong>Note:</strong> When going clockwise it's best to set the start angle to (Math.PI * 2) and then work towards lower numbers.
 		</div>
@@ -58,6 +60,7 @@ var ellipse = new THREE.Line( geometry, material );
 		<h3>[property:Float aStartAngle]</h3>
 		<h3>[property:Float aEndAngle]</h3>
 		<h3>[property:Boolean aClockwise]</h3>
+		<h3>[property:Float aRotation]</h3>
 
 		<h2>Methods</h2>
 

+ 10 - 63
docs/api/lights/DirectionalLight.html

@@ -27,7 +27,7 @@
 		<div>[example:webgl_geometry_extrude_splines geometry / extrude / splines ]</div>
 		<div>[example:webgl_materials_bumpmap materials / bumpmap ]</div>
 		<div>[example:webgl_materials_cubemap_balls_reflection materials / cubemap / balls / reflection ]</div>
-		
+
 		<code>// White directional light at half intensity shining from the top.
 
 var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
@@ -68,13 +68,13 @@ scene.add( directionalLight );</code>
 			If set to *true* light will only cast shadow but not contribute any lighting (as if *intensity* was 0 but cheaper to compute).<br />
 			Default — *false*.
 		</div>
-		
+
 		<h3>[property:Boolean castShadow]</h3>
 		<div>
 			If set to true light will cast dynamic shadows. Warning: This is expensive and requires tweaking to get shadows looking right.<br />
 			Default — *false*.
 		</div>
-		
+
 		<h3>[property:Float shadowCameraNear]</h3>
 		<div>
 			Orthographic shadow camera frustum parameter.<br />
@@ -141,90 +141,37 @@ scene.add( directionalLight );</code>
 			Default — *512*.
 		</div>
 
-		<h3>[property:Boolean shadowCascade]</h3>
-		<div>
-			**Experimental** If true, use a series of shadow maps in a cascade. This can give better z-depth resolution for a directional light. <br />
-			Default — *false*.
-		</div>
-
-		<h3>[property:Integer shadowCascadeCount]</h3>
-		<div>
-			Number of shadow maps to allocate in a cascade (one after another). <br />
-			Default — *2*.
-		</div>
-
-		<h3>[property:Vector3 shadowCascadeOffset]</h3>
-		<div>
-			A relative position to real camera where virtual shadow cameras are attached. A magic vector; scene and light orientation dependent. <br />
-			Default — *Three.Vector3( 0, 0, -1000 )*.
-		</div>
-
-		<h3>[property:Array shadowCascadeBias]</h3>
-		<div>
-			An array of shadowMapBias values for the corresponding shadow map in the cascade, near to far. <br />
-			Default — <strong>[ 0, 0, 0 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeWidth]</h3>
-		<div>
-			An array of shadowMapWidth values for the corresponding shadow map in the cascade, near to far. <br />
-			Default — <strong>[ 512, 512, 512 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeHeight]</h3>
-		<div>
-			An array of shadowMapHeight values for the corresponding shadow map in the cascade, near to far. <br />
-			Default — <strong>[ 512, 512, 512 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeNearZ]</h3>
-		<div>
-			An array of shadowMapNear values for the corresponding shadow map in the cascade, near to far. These typically start with -1.0 (near plane) and match with the previous shadowCascadeFarZ array value.<br />
-			Default — <strong>[ -1.000, 0.990, 0.998 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeFarZ]</h3>
-		<div>
-			An array of shadowMapFar values for the corresponding shadow map in the cascade, near to far. These typically match with the next shadowCascadeNearZ array value, ending in 1.0.<br />
-			Default — <strong>[ 0.990, 0.998, 1.000 ]</strong>.
-		</div>
-
-		<h3>[property:Array shadowCascadeArray]</h3>
-		<div>
-			Array of size shadowCascadeCount of [page:DirectionalLight THREE.DirectionalLight] objects. This holds the series of separate shadow maps in a cascade, near to far. Created internally.
-		</div>
-
 		<h3>[property:Vector2 shadowMapSize]</h3>
 		<div>
 			The shadowMapWidth and shadowMapHeight stored in a [page:Vector2 THREE.Vector2]. Set internally during rendering.
-		</div> 
+		</div>
 
 		<h3>[property:OrthographicCamera shadowCamera]</h3>
 		<div>
 			The shadow's view of the world. Computed internally during rendering from the shadowCamera* settings.
-		</div> 
+		</div>
 
 		<h3>[property:Matrix4 shadowMatrix]</h3>
 		<div>
 			Model to shadow camera space, to compute location and depth in shadow map. Computed internally during rendering.
-		</div> 
+		</div>
 
 		<h3>[property:WebGLRenderTarget shadowMap]</h3>
 		<div>
 		    The depth map generated using the shadowCamera; a location beyond a pixel's depth is in shadow. Computed internally during rendering.
-		</div> 
-		
+		</div>
+
 		<h2>Methods</h2>
 		<h3>[method:DirectionalLight clone]()</h3>
 		<div>
 		It returns a clone of DirectionalLight.
 		</div>
-		
+
 		<h3>[method:JSON toJSON]()</h3>
 		<div>
 		Return DirectionalLight data in JSON format.
 		</div>
-		
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 8 - 3
docs/api/loaders/Cache.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
@@ -23,6 +23,11 @@
 
 		<h2>Properties</h2>
 
+		<h3>[property:Boolean enabled]</h3>
+		<div>
+		Whether caching is enabled. Default is *false*.
+		</div>
+
 		<h3>[property:Object files]</h3>
 		<div>
 		An [page:Object object] that hold cached values.
@@ -34,7 +39,7 @@
 		<h3>[method:null add]( [page:String key], value )</h3>
 		<div>
 		[page:String key] — required. A string key <br />
-		[page:Object] value — <br />
+		[page:Object] value — A value <br />
 		</div>
 		<div>
 		Adds a cache entry with that key to hold the value. If this key already holds a value, it is overwritten.
@@ -45,7 +50,7 @@
 		[page:String key] — required. A string key <br />
 		</div>
 		<div>
-		Get the value of key. If the key does not exist the null value is returned.
+		Get the value of key. If the key does not exist *undefined* is returned.
 		</div>
 
 		<h3>[method:null remove]( [page:String key] )</h3>

+ 7 - 5
docs/api/math/Color.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
@@ -18,7 +18,9 @@
 		<h2>Example</h2>
 		<code>var color = new THREE.Color();</code>
 		<code>var color = new THREE.Color( 0xff0000 );</code>
-		<code>var color = new THREE.Color("rgb(255,0,0)");</code>
+		<code>var color = new THREE.Color("rgb(255, 0, 0)");</code>
+		<code>var color = new THREE.Color("rgb(100%, 0%, 0%)");</code>
+		<code>var color = new THREE.Color("hsl(0, 100%, 50%)");</code>
 		<code>var color = new THREE.Color( 1, 0, 0 );</code>
 
 
@@ -27,7 +29,7 @@
 
 		<h3>[name]( value )</h3>
 		<div>
-		value — optional argument that sets initial color.  Can be a hexadecimal or a CSS-style string, for example, "rgb(250, 0,0)", "rgb(100%,0%,0%)", "#ff0000", "#f00", or "red", or three arguments that represent color channels.
+		value — optional argument that sets initial color.  Can be a hexadecimal or a CSS-style string, for example, "rgb(250, 0,0)", "rgb(100%,0%,0%)", "hsl(0, 100%, 50%)", "#ff0000", "#f00", or "red", or three arguments that represent color channels.
 		</div>
 
 		<h2>Properties</h2>
@@ -113,10 +115,10 @@
 
 		<h3>[method:Color setStyle]( [page:String style] ) [page:Color this]</h3>
 		<div>
-		style — color as a CSS-style string, for example, "rgb(250, 0,0)", "rgb(100%,0%,0%)", "#ff0000", "#f00", or "red"
+		style — color as a CSS-style string.
 		</div>
 		<div>
-		Sets this color	from a CSS-style string.
+		Sets this color from a CSS-style string. For example, "rgb(250, 0,0)", "rgb(100%, 0%, 0%)", "hsl(0, 100%, 50%)", "#ff0000", "#f00", or "red". Transluent colors such as "rgba(255, 0, 0, 0.5)" and "hsla(0, 100%, 50%, 0.5)" are also accepted, but the alpha-channel coordinate will be discarded.
 		</div>
 
 		<h3>[method:String getStyle]()</h3>

+ 42 - 20
docs/api/math/Quaternion.html

@@ -120,26 +120,6 @@
 		Clones this quaternion.
 		</div>
 
-
-		<h2>Static methods</h2>
-
-		<h3>[method:Quaternion slerp]( [page:Quaternion qa], [page:Quaternion qb], [page:Quaternion qm], [page:Float t] )</h3>
-		<div>
-		Adapted from [link:http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/].
-		</div>
-
-
-		<h3>[method:Quaternion slerp]([page:Quaternion qb], [page:float t])</h3>
-		<div>
-		qb -- Target quaternion rotation.<br />
-		t -- Normalized [0..1] interpolation factor.
-		</div>
-		<div>
-		Handles the spherical linear interpolation between this quaternion's configuration
-		and that of *qb*. *t* represents how close to the current (0) or target (1) rotation the
-		result should be.
-		</div>
-
 		<h3>[method:Array toArray]( [page:Array array] )</h3>
 		<div>
 		array -- Array to store the quaternion.
@@ -176,6 +156,48 @@
 		represents the same rotation in the opposite direction about the rotational axis.
 		</div>
 
+		<h3>[method:Quaternion slerp]([page:Quaternion quaternionB], [page:float t])</h3>
+		<div>
+		quaternionB -- The other quaternion rotation<br />
+		t -- Normalized 0 to 1 interpolation factor
+		</div>
+		<div>
+		Handles the spherical linear interpolation between quaternions. *t* represents the amount of rotation
+		between this quaternion (where *t* is 0) and quaternionB (where *t* is 1). This quaternion is set to
+		the result. Also see the static version of the *slerp* below.
+		</div>
+		<code>
+		// rotate a mesh towards a target quaternion
+		mesh.quaternion.slerp( endQuaternion, 0.01 );
+		</code>
+		
+		
+		<h2>Static Methods</h2>
+
+		<h3>[method:Quaternion slerp]( [page:Quaternion qStart], [page:Quaternion qEnd], [page:Quaternion qTarget], [page:Float t] )</h3>
+		<div>
+		qStart -- The starting quaternion (where *t* is 0)<br />
+		qEnd -- The ending quaternion (where *t* is 1)<br />
+		qTarget -- The target quaternion that gets set with the result<br />
+		t -- Normalized 0 to 1 interpolation factor
+		</div>
+		<div>
+		Unlike the normal method, the static version of slerp sets a target quaternion to the result of the slerp operation.
+		</div>
+		<code>
+		// Code setup
+		var startQuaternion = new THREE.Quaternion().set( 0, 0, 0, 1 ).normalize();
+		var endQuaternion = new THREE.Quaternion().set( 1, 1, 1, 1 ).normalize();
+		var t = 0;
+		</code>
+		<code>
+		// Update a mesh's rotation in the loop
+		t = ( t + 0.01 ) % 1; // constant angular momentum
+		THREE.Quaternion.slerp( startQuaternion, endQuaternion, mesh.quaternion, t );
+		</code>
+		
+		<!-- Note: Do not add non-static methods to the bottom of this page. Put them above the <h2>Static Methods</h2> -->
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 6 - 4
docs/api/math/Vector2.html

@@ -152,7 +152,8 @@
 		max -- [page:Vector2] containing the max x and y values in the desired range
 		</div>
 		<div>
-		If this vector's x or y value is greater than the max vector's x or y value, it is replaced by the corresponding value. <br />	If this vector's x or y value is less than the min vector's x or y value, it is replace by the corresponding value.
+		If this vector's x or y value is greater than the max vector's x or y value, it is replaced by the corresponding value. <br /><br />
+		If this vector's x or y value is less than the min vector's x or y value, it is replaced by the corresponding value.
 		</div>
 
 		<h3>[method:Vector2 clampScalar]([page:Float min], [page:Float max]) [page:Vector2 this]</h3>
@@ -161,7 +162,8 @@
 		max -- [page:Float] the maximum value the components will be clamped to
 		</div>
 		<div>
-		If this vector's x or y values are greater than the max value, they are replaced by the max value. <br />  If this vector's x or y values are less than the min value, they are replace by the min value.
+		If this vector's x or y values are greater than the max value, they are replaced by the max value. <br /><br />
+		If this vector's x or y values are less than the min value, they are replaced by the min value.
 		</div>
 
 		<h3>[method:Vector2 floor]()</h3>
@@ -251,7 +253,7 @@
 		v -- [page:Vector2]
 		</div>
 		<div>
-		If this vector's x or y value is less than v's x or y value, replace that value with the corresponding min value.
+		If this vector's x or y value is greater than v's x or y value, replace that value with the corresponding min value.
 		</div>
 
 		<h3>[method:Vector2 max]([page:Vector2 v]) [page:Vector2 this]</h3>
@@ -259,7 +261,7 @@
 		v -- [page:Vector2]
 		</div>
 		<div>
-		If this vector's x or y value is greater than v's x or y value, replace that value with the corresponding max value.
+		If this vector's x or y value is less than v's x or y value, replace that value with the corresponding max value.
 		</div>
 
 		<h3>[method:Vector2 setX]([page:Float x]) [page:Vector2 this]</h3>

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

@@ -193,7 +193,7 @@
 		</div>
 		<div>
 		If this vector's x, y or z value is greater than the max vector's x, y or z value, it is replaced by the corresponding value. <br /><br />
-		If this vector's x, y or z value is less than the min vector's x, y or z value, it is replace by the corresponding value.
+		If this vector's x, y or z value is less than the min vector's x, y or z value, it is replaced by the corresponding value.
 		</div>
 
 		<h3>[method:Vector3 clampScalar]([page:Float min], [page:Float max]) [page:Vector3 this]</h3>
@@ -202,7 +202,8 @@
 		max -- [page:Float] the maximum value the components will be clamped to
 		</div>
 		<div>
-		If this vector's x, y or z values are greater than the max value, they are replaced by the max value. <br />  If this vector's x, y or z values are less than the min value, they are replace by the min value.
+		If this vector's x, y or z values are greater than the max value, they are replaced by the max value. <br /><br />
+		If this vector's x, y or z values are less than the min value, they are replaced by the min value.
 		</div>
 
 		<h3>[method:Vector3 floor]()</h3>
@@ -278,7 +279,7 @@
 		v -- [page:Vector3]
 		</div>
 		<div>
-		If this vector's x, y, or z value is less than vector v's x, y, or z value, that value is replaced by the corresponding vector v value.
+		If this vector's x, y, or z value is greater than vector v's x, y, or z value, that value is replaced by the corresponding vector v value.
 		</div>
 
 		<h3>[method:Vector3 max]([page:Vector3 v]) [page:Vector3 this]</h3>
@@ -286,7 +287,7 @@
 		v -- [page:Vector3]
 		</div>
 		<div>
-		If this vector's x, y, or z value is greater than vector v's x, y, or z value, that value is replaced by the corresponding vector v value.
+		If this vector's x, y, or z value is less than vector v's x, y, or z value, that value is replaced by the corresponding vector v value.
 		</div>
 
 		<h3>[method:Vector3 setComponent]([page:Integer index], [page:Float value]) [page:Vector3 this]</h3>

+ 5 - 6
docs/api/math/Vector4.html

@@ -137,8 +137,7 @@
 		</div>
 		<div>
 		If this vector's x, y, z, or w value is greater than the max vector's x, y, z, or w value, it is replaced by the corresponding value.<br/><br/>
-
-		If this vector's x, y, z, or w value is less than the min vector's x, y, z, or w value, it is replace by the corresponding value.
+		If this vector's x, y, z, or w value is less than the min vector's x, y, z, or w value, it is replaced by the corresponding value.
 		</div>
 
 		<h3>[method:Vector4 clampScalar]([page:Float min], [page:Float max]) [page:Vector4 this]</h3>
@@ -147,8 +146,8 @@
 		max -- [page:Float] the maximum value the components will be clamped to
 		</div>
 		<div>
-		If this vector's x, y, z or w values are greater than the max value, they are replaced by the max value. <br />
-		If this vector's x, y, z or w values are less than the min value, they are replace by the min value.
+		If this vector's x, y, z or w values are greater than the max value, they are replaced by the max value. <br /><br />
+		If this vector's x, y, z or w values are less than the min value, they are replaced by the min value.
 		</div>
 
 		<h3>[method:Vector4 floor]()</h3>
@@ -184,7 +183,7 @@
 		v -- [page:Vector4]
 		</div>
 		<div>
-		If this vector's x, y, z, or w value is less than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value.
+		If this vector's x, y, z, or w value is greater than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value.
 		</div>
 
 		<h3>[method:Vector4 max]([page:Vector4 v]) [page:Vector4 this]</h3>
@@ -192,7 +191,7 @@
 		v -- [page:Vector4]
 		</div>
 		<div>
-		If this vector's x, y, z, or w value is greater than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value.
+		If this vector's x, y, z, or w value is less than vector v's x, y, z, or w value, that value is replaced by the corresponding vector v value.
 		</div>
 
 		<h3>[method:Vector4 addScalar]([page:Float s]) [page:Vector4 this]</h3>

+ 5 - 12
docs/api/objects/Mesh.html

@@ -44,29 +44,22 @@
 
 		<div>An instance of [page:Material], defining the object's appearance. Default is a [page:MeshBasicMaterial] with wireframe mode enabled and randomised colour.</div>
 		
-		<h3>[property:Array morphTargetForcedOrder]</h3>
-		
-		<div>
-		An array of indices specifying the order that the morphs will be applied. Undefined by
-		default, but reset to a blank array by [page:Mesh.updateMorphTargets updateMorphTargets].
-		</div>
-		
 		<h3>[property:Array morphTargetInfluences]</h3>
-		
+
 		<div>
 		An array of weights typically from 0-1 that specify how much of the morph is applied.
 		Undefined by default, but reset to a blank array by [page:Mesh.updateMorphTargets updateMorphTargets].
 		</div>
-		
+
 		<h3>[property:Array morphTargetDictionary]</h3>
-		
+
 		<div>
 		A dictionary of morphTargets based on the morphTarget.name property.
 		Undefined by default, but rebuilt [page:Mesh.updateMorphTargets updateMorphTargets].
 		</div>
 
 		<h3>[property:Integer morphTargetBase]</h3>
-		
+
 		<div>
 		Specify the index of the morph that should be used as the base morph. Replaces the positions.
 		Undefined by default, but reset to -1 (non set) by [page:Mesh.updateMorphTargets updateMorphTargets].
@@ -97,7 +90,7 @@
 		<div>
 		Get intersections between a casted ray and this mesh. [page:Raycaster.intersectObject] will call this method.
 		</div>
-		
+
 		<h3>[method:Object3D clone]([page:Object3D object])</h3>
 		<div>
 		object -- (optional) Object3D which needs to be cloned. If undefined, clone method will create a new cloned Mesh Object.

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

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

+ 10 - 8
docs/api/renderers/WebGLRenderer.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
@@ -23,13 +23,15 @@
 
 		<div>
 		canvas — A [page:Canvas] where the renderer draws its output.<br />
-		precision — shader precision. Can be *"highp"*, *"mediump"* or *"lowp"*.<br />
+		context — The [page:RenderingContext] context to use.<br />
+		precision — Shader precision. Can be *"highp"*, *"mediump"* or *"lowp"*. Defaults to *"highp"* if supported by the device.<br />
 		alpha — [page:Boolean], default is *false*.<br />
 		premultipliedAlpha — [page:Boolean], default is *true*.<br />
 		antialias — [page:Boolean], default is *false*.<br />
 		stencil — [page:Boolean], default is *true*.<br />
 		preserveDrawingBuffer — [page:Boolean], default is *false*.<br />
-		maxLights — [page:Integer], default is *4*.<br />
+		depth — [page:Boolean], default is *true*.<br />
+		logarithmicDepthBuffer — [page:Boolean], default is *false*.<br />
 		</div>
 
 		<h2>Properties</h2>
@@ -70,10 +72,6 @@
 		<div>Note: Sorting is used to attempt to properly render objects that have some degree of transparency.  By definition, sorting objects may not work in all cases.  Depending on the needs of application, it may be neccessary to turn off sorting and use other methods to deal with transparency rendering e.g. manually determining the object rendering order.</div>
 
 
-		<h3>[property:Boolean autoUpdateObjects]</h3>
-
-		<div>Defines whether the renderer should auto update objects. Default is true.</div>
-
 		<h3>[property:Boolean gammaInput]</h3>
 
 		<div>Default is false. If set, then it expects that all textures and colors are premultiplied gamma.</div>
@@ -161,12 +159,16 @@
 		Return the WebGL context.
 		</div>
 
+		<h3>[method:WebGLContextAttributes getContextAttributes]()</h3>
+		<div>
+		Returns an object that describes the attributes set on the WebGL context when it was created.
+		</div>
+
 		<h3>[method:Boolean supportsVertexTextures]()</h3>
 		<div>
 		Return a [page:Boolean] true if the context supports vertex textures.
 		</div>
 
-
 		<h3>[method:null setSize]( [page:Integer width], [page:Integer height] )</h3>
 		<div>Resizes the output canvas to (width, height), and also sets the viewport to fit that size, starting in (0, 0).</div>
 

+ 15 - 23
docs/api/textures/DataTexture.html

@@ -12,44 +12,36 @@
 
 		<h1>[name]</h1>
 
-		<div class="desc">
-		Creates a texture directly from bitmapdata, width and height.
-		</div>
+		<div class="desc">Creates a texture directly from raw data, width and height.</div>
 
 
 		<h2>Constructor</h2>
 
-
-		<h3>[name]([page:ArraybufferView data], [page:Integer width], [page:Integer height], [page:number format], [page:number type], [page:number mapping], [page:number wrapS], [page:number wrapT], [page:number magFilter], [page:number minFilter], [page:number anisotropy])</h3>
+		<h3>[name]( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy )</h3>
 		<div>
-		data -- The data should be arraybufferview. It contains the data of image based on the type and format.<br />
-		width -- The width of the image. <br />
-		height -- The height of the image. <br />
-		format -- The default is THREE.RGBAFormat for the texture. Other formats are: THREE.AlphaFormat, THREE.RGBFormat, THREE.LuminanceFormat, and THREE.LuminanceAlphaFormat. There are also compressed texture formats, if the S3TC extension is supported: THREE.RGB_S3TC_DXT1_Format, THREE.RGBA_S3TC_DXT1_Format, THREE.RGBA_S3TC_DXT3_Format, and THREE.RGBA_S3TC_DXT5_Format.<br />
-		type -- The default is THREE.UnsignedByteType. Other valid types (as WebGL allows) are THREE.ByteType, THREE.ShortType, THREE.UnsignedShortType, THREE.IntType, THREE.UnsignedIntType, THREE.FloatType, THREE.UnsignedShort4444Type, THREE.UnsignedShort5551Type, and THREE.UnsignedShort565Type.<br />
-		mapping -- How the image is applied to the object. An object type of THREE.UVMapping is the default, where the U,V coordinates are used to apply the map, and a single texture is expected. The other types are THREE.CubeReflectionMapping, for cube maps used as a reflection map; THREE.CubeRefractionMapping, refraction mapping; and THREE.SphericalReflectionMapping, a spherical reflection map projection.<br />
-		wrapS -- The default is THREE.ClampToEdgeWrapping, where the edge is clamped to the outer edge texels. The other two choices are THREE.RepeatWrapping and THREE.MirroredRepeatWrapping.<br />
-		wrapT -- The default is THREE.ClampToEdgeWrapping, where the edge is clamped to the outer edge texels. The other two choices are THREE.RepeatWrapping and THREE.MirroredRepeatWrapping.<br />
-		magFilter -- How the texture is sampled when a texel covers more than one pixel. The default is THREE.LinearFilter, which takes the four closest texels and bilinearly interpolates among them. The other option is THREE.NearestFilter, which uses the value of the closest texel.<br />
-		minFilter -- How the texture is sampled when a texel covers less than one pixel. The default is THREE.LinearMipMapLinearFilter, which uses mipmapping and a trilinear filter. Other choices are THREE.NearestFilter, THREE.NearestMipMapNearestFilter, THREE.NearestMipMapLinearFilter, THREE.LinearFilter, and THREE.LinearMipMapNearestFilter. These vary whether the nearest texel or nearest four texels are retrieved on the nearest mipmap or nearest two mipmaps. Interpolation occurs among the samples retrieved.<br />
-		anisotropy -- The number of samples taken along the axis through the pixel that has the highest density of texels. By default, this value is 1. A higher value gives a less blurry result than a basic mipmap, at the cost of more texture samples being used. Use renderer.getMaxAnisotropy() to find the maximum valid anisotropy value for the GPU; this value is usually a power of 2.
+			The data argument must be an ArrayBuffer or a typed array view.
+			Further parameters correspond to the properties inherited from [page:Texture], where both magFilter and minFilter default to THREE.NearestFilter. The properties flipY and generateMipmaps are intially set to false.
 		</div>
 		<div>
-		This loads a image through the bitmap values. The values are dependant on the type and format.
-	 	If the type is THREE.UnsignedByteType, a Uint8Array must be supplied. If it is THREE.UnsignedShort4444Type, THREE.UnsignedShort5551Type or THREE.UnsignedShort565Type, a Uint16Array must be supplied.<br />
-	 	If the format is THREE.RGBAFormat, data needs 4 values for 1 pixel. These are supplied in the Red,Green,Blue and alpha sequence. <br />
-	 	Except if the type is THREE.UnsignedShort4444Type, THREE.UnsignedShort5551Type or THREE.UnsignedShort565Type.
-		</div>
+			The interpretation of the data depends on type and format:
+			If the type is THREE.UnsignedByteType, a Uint8Array will be useful for addressing the texel data.
+			If the format is THREE.RGBAFormat, data needs four values for one texel; Red, Green, Blue and Alpha (typically the opacity). Similarly, THREE.RGBFormat specifies a format where only three values are used for each texel.<br />
 
+			For the packed types, THREE.UnsignedShort4444Type, THREE.UnsignedShort5551Type or THREE.UnsignedShort565Type, all color components of one texel can be addressed as bitfields within an integer element of a Uint16Array.<br />
 
-		<h2>Properties</h2>
+			In order to use the types THREE.FloatType and THREE.HalfFloatType, the WebGL implementation must support the respective extensions OES_texture_float and OES_texture_half_float. In order to use THREE.LinearFilter for component-wise, bilinear interpolation of the texels based on these types, the WebGL extensions OES_texture_float_linear or OES_texture_half_float_linear must also be present.
+		</div>
 
+		<h2>Properties</h2>
 
+		<h3>[property:Image image]</h3>
+		<div>
+		Overridden with a record type holding data, width and height.
+		</div>
 
 		<h2>Methods</h2>
 
 
-
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 6 - 4
docs/manual/introduction/Creating-a-scene.html

@@ -60,12 +60,14 @@
 
 		<div>The second one is the <strong>aspect ratio</strong>. You almost always want to use the width of the element divided by the height, or you'll get the same result as when you play old movies on a widescreen TV - the image looks squished.</div>
 
-		<div>The next two attributes are the <strong>near</strong> and <strong>far</strong> clipping plane. What that means, is that objects further away from the camera than the value of <strong>far</strong> or closer than <strong>near</strong> won't be rendered. You don't have to worry about this now, but you may want to use other values in your games to get better performance.</div>
+		<div>The next two attributes are the <strong>near</strong> and <strong>far</strong> clipping plane. What that means, is that objects further away from the camera than the value of <strong>far</strong> or closer than <strong>near</strong> won't be rendered. You don't have to worry about this now, but you may want to use other values in your apps to get better performance.</div>
 
 		<div>Next up is the renderer. This is where the magic happens. In addition to the WebGLRenderer we use here, Three.js comes with a few others, often used as fallbacks for users with older browsers or for those who don't have WebGL support for some reason.</div>
 
-		<div>In addition to creating the renderer instance, we also need to set the size at which we want it to render our app. It's a good idea to use the width and height of the area we want to fill with our game - in this case, the width and height of the browser window. For performance intensive games, you can also give <strong>setSize</strong> smaller values, like <strong>window.innerWidth/2</strong> and <strong>window.innerHeight/2</strong>, for half the resolution. This does not mean that the game will only fill half the window, but rather look a bit blurry and scaled up.</div>
-
+		<div>In addition to creating the renderer instance, we also need to set the size at which we want it to render our app. It's a good idea to use the width and height of the area we want to fill with our app - in this case, the width and height of the browser window. For performance intensive apps, you can also give <strong>setSize</strong> smaller values, like <strong>window.innerWidth/2</strong> and <strong>window.innerHeight/2</strong>, which will make the app render at half size.</div>
+		
+		<div>If you wish to keep the size of your app but render it at a lower resolution, you can do so by calling <strong>setSize</strong> with false as <strong>updateStyle</strong>. For example, <strong>setSize(window.innerWidth/2, window.innerHeight/2, false)</strong> will render your app at half resolution, given that your &lt;canvas&gt; has 100% width and height.</div>
+		
 		<div>Last but not least, we add the <strong>renderer</strong> element to our HTML document. This is a &lt;canvas&gt; element the renderer uses to display the scene to us.</div>
 
 		<div><em>"That's all good, but where's that cube you promised?"</em> Let's add it now.</div>
@@ -112,7 +114,7 @@
 		cube.rotation.y += 0.1;
 		</code>
 
-		<div>This will be run every frame (60 times per second), and give the cube a nice rotation animation. Basically, anything you want to move or change while the game / app is running has to go through the render loop. You can of course call other functions from there, so that you don't end up with a <strong>render</strong> function that's hundreds of lines.
+		<div>This will be run every frame (60 times per second), and give the cube a nice rotation animation. Basically, anything you want to move or change while the app is running has to go through the render loop. You can of course call other functions from there, so that you don't end up with a <strong>render</strong> function that's hundreds of lines.
 		</div>
 
 		<h2>The result</h2>

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

@@ -61,7 +61,7 @@
 				document.body.appendChild( renderer.domElement );
 
 				orbit = new THREE.OrbitControls( camera, renderer.domElement );
-				orbit.noZoom = true;
+				orbit.enableZoom = false;
 
 				ambientLight = new THREE.AmbientLight( 0x000000 );
 				scene.add( ambientLight );
@@ -159,7 +159,6 @@
 				mesh.add( bones[ 0 ] );
 	
 				mesh.bind( skeleton );
-				skeleton.calculateInverses();
 
 				skeletonHelper = new THREE.SkeletonHelper( mesh );
 				skeletonHelper.material.linewidth = 2;

+ 1 - 1
docs/scenes/geometry-browser.html

@@ -62,7 +62,7 @@
 			document.body.appendChild( renderer.domElement );
 			
 			var orbit = new THREE.OrbitControls( camera, renderer.domElement );
-			orbit.noZoom = true;
+			orbit.enableZoom = false;
 
 			var ambientLight = new THREE.AmbientLight( 0x000000 );
 			scene.add( ambientLight );

+ 1 - 0
editor/css/dark.css

@@ -46,6 +46,7 @@ input.Number {
 
 	#viewport #info {
 		text-shadow: 1px 1px 0px rgba(0,0,0,0.25);
+		pointer-events: none;
 	}
 
 #script {

+ 1 - 0
editor/css/light.css

@@ -39,6 +39,7 @@ input.Number {
 
 	#viewport #info {
 		text-shadow: 1px 1px 0px rgba(0,0,0,0.25);
+		pointer-events: none;
 	}
 
 #script {

+ 2 - 0
editor/index.html

@@ -17,6 +17,7 @@
 		<script src="../examples/js/loaders/AWDLoader.js"></script>
 		<script src="../examples/js/loaders/BabylonLoader.js"></script>
 		<script src="../examples/js/loaders/ColladaLoader.js"></script>
+		<script src="../examples/js/loaders/MD2Loader.js"></script>
 		<script src="../examples/js/loaders/OBJLoader.js"></script>
 		<script src="../examples/js/loaders/PLYLoader.js"></script>
 		<script src="../examples/js/loaders/STLLoader.js"></script>
@@ -83,6 +84,7 @@
 
 		<script src="js/Editor.js"></script>
 		<script src="js/Config.js"></script>
+		<script src="js/History.js"></script>
 		<script src="js/Loader.js"></script>
 		<script src="js/Menubar.js"></script>
 		<script src="js/Menubar.File.js"></script>

+ 0 - 3
editor/js/Config.js

@@ -14,9 +14,6 @@ var Config = function () {
 		'project/renderer/antialias': true,
 		'project/vr': false,
 
-		'camera/position': [ 500, 250, 500 ],
-		'camera/target': [ 0, 0, 0 ],
-
 		'ui/sidebar/animation/collapsed': true,
 		'ui/sidebar/geometry/collapsed': true,
 		'ui/sidebar/material/collapsed': true,

+ 8 - 7
editor/js/Editor.js

@@ -19,9 +19,6 @@ var Editor = function () {
 
 		// actions
 
-		playAnimation: new SIGNALS.Signal(),
-		stopAnimation: new SIGNALS.Signal(),
-
 		// showDialog: new SIGNALS.Signal(),
 
 		// notifications
@@ -70,10 +67,13 @@ var Editor = function () {
 	};
 
 	this.config = new Config();
+	this.history = new History( this );
 	this.storage = new Storage();
 	this.loader = new Loader( this );
 
 	this.camera = new THREE.PerspectiveCamera( 50, 1, 1, 100000 );
+	this.camera.position.set( 500, 250, 500 );
+	this.camera.lookAt( new THREE.Vector3() );
 	this.camera.name = 'Camera';
 
 	this.scene = new THREE.Scene();
@@ -188,7 +188,7 @@ Editor.prototype = {
 
 	removeObject: function ( object ) {
 
-		if ( object.parent === undefined ) return; // avoid deleting the camera or scene
+		if ( object.parent === null ) return; // avoid deleting the camera or scene
 
 		var scope = this;
 
@@ -241,8 +241,8 @@ Editor.prototype = {
 
 	addHelper: function () {
 
-		var geometry = new THREE.SphereGeometry( 20, 4, 2 );
-		var material = new THREE.MeshBasicMaterial( { color: 0xff0000 } );
+		var geometry = new THREE.SphereBufferGeometry( 20, 4, 2 );
+		var material = new THREE.MeshBasicMaterial( { color: 0xff0000, visible: false } );
 
 		return function ( object ) {
 
@@ -282,7 +282,6 @@ Editor.prototype = {
 			var picker = new THREE.Mesh( geometry, material );
 			picker.name = 'picker';
 			picker.userData.object = object;
-			picker.visible = false;
 			helper.add( picker );
 
 			this.sceneHelpers.add( helper );
@@ -411,6 +410,8 @@ Editor.prototype = {
 
 	clear: function () {
 
+		this.history.clear();
+
 		this.camera.position.set( 500, 250, 500 );
 		this.camera.lookAt( new THREE.Vector3() );
 

+ 81 - 0
editor/js/History.js

@@ -0,0 +1,81 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+var History = function ( editor ) {
+
+	this.array = [];
+	this.arrayLength = -1;
+
+	this.current = -1;
+	this.isRecording = true;
+
+	//
+
+	var scope = this;
+	var signals = editor.signals;
+
+	signals.objectAdded.add( function ( object ) {
+
+		if ( scope.isRecording === false ) return;
+
+		scope.add(
+			function () {
+				editor.removeObject( object );
+				editor.select( null );
+			},
+			function () {
+				editor.addObject( object );
+				editor.select( object );
+			}
+		);
+
+	} );
+
+};
+
+History.prototype = {
+
+	add: function ( undo, redo ) {
+
+		this.current ++;
+
+		this.array[ this.current ] = { undo: undo, redo: redo };
+		this.arrayLength = this.current;
+
+	},
+
+	undo: function () {
+
+		if ( this.current < 0 ) return;
+
+		this.isRecording = false;
+
+		this.array[ this.current -- ].undo();
+
+		this.isRecording = true;
+
+	},
+
+	redo: function () {
+
+		if ( this.current === this.arrayLength ) return;
+
+		this.isRecording = false;
+
+		this.array[ ++ this.current ].redo();
+
+		this.isRecording = true;
+
+	},
+
+	clear: function () {
+
+		this.array = [];
+		this.arrayLength = -1;
+
+		this.current = -1;
+
+	}
+
+};

+ 28 - 6
editor/js/Loader.js

@@ -113,14 +113,12 @@ var Loader = function ( editor ) {
 					var xml = parser.parseFromString( contents, 'text/xml' );
 
 					var loader = new THREE.ColladaLoader();
-					loader.parse( xml, function ( collada ) {
+					var collada = loader.parse( xml );
 
-						collada.scene.name = filename;
+					collada.scene.name = filename;
 
-						editor.addObject( collada.scene );
-						editor.select( collada.scene );
-
-					} );
+					editor.addObject( collada.scene );
+					editor.select( collada.scene );
 
 				}, false );
 				reader.readAsText( file );
@@ -184,6 +182,30 @@ var Loader = function ( editor ) {
 
 				break;
 
+				case 'md2':
+
+					var reader = new FileReader();
+					reader.addEventListener( 'load', function ( event ) {
+
+						var contents = event.target.result;
+
+						var geometry = new THREE.MD2Loader().parse( contents );
+						var material = new THREE.MeshPhongMaterial( {
+							morphTargets: true,
+							morphNormals: true
+						} );
+
+						var object = new THREE.MorphAnimMesh( geometry, material );
+						object.name = filename;
+
+						editor.addObject( object );
+						editor.select( object );
+
+					}, false );
+					reader.readAsArrayBuffer( file );
+
+					break;
+
 			case 'obj':
 
 				var reader = new FileReader();

+ 29 - 1
editor/js/Menubar.Edit.js

@@ -16,6 +16,34 @@ Menubar.Edit = function ( editor ) {
 	options.setClass( 'options' );
 	container.add( options );
 
+	// Undo
+
+	var option = new UI.Panel();
+	option.setClass( 'option' );
+	option.setTextContent( 'Undo' );
+	option.onClick( function () {
+
+		editor.history.undo();
+
+	} );
+	options.add( option );
+
+	// Redo
+
+	var option = new UI.Panel();
+	option.setClass( 'option' );
+	option.setTextContent( 'Redo' );
+	option.onClick( function () {
+
+		editor.history.redo();
+
+	} );
+	options.add( option );
+
+	// ---
+
+	options.add( new UI.HorizontalRule() );
+
 	// Clone
 
 	var option = new UI.Panel();
@@ -25,7 +53,7 @@ Menubar.Edit = function ( editor ) {
 
 		var object = editor.selected;
 
-		if ( object.parent === undefined ) return; // avoid cloning the camera or scene
+		if ( object.parent === null ) return; // avoid cloning the camera or scene
 
 		object = object.clone();
 

+ 22 - 7
editor/js/Sidebar.Animation.js

@@ -50,6 +50,25 @@ Sidebar.Animation = function ( editor ) {
 
 				animations[ child.id ] = new THREE.Animation( child, child.geometry.animation );
 
+			} else if ( child instanceof THREE.MorphAnimMesh ) {
+
+				var animation = new THREE.MorphAnimation( child );
+				animation.duration = 30;
+
+				// temporal hack for THREE.AnimationHandler
+				animation._play = animation.play;
+				animation.play = function () {
+					this._play();
+					THREE.AnimationHandler.play( this );
+				};
+				animation.resetBlendWeights = function () {};
+				animation.stop = function () {
+					this.pause();
+					THREE.AnimationHandler.stop( this );
+				};
+
+				animations[ child.id ] = animation;
+
 			}
 
 		} );
@@ -60,27 +79,23 @@ Sidebar.Animation = function ( editor ) {
 
 		container.setDisplay( 'none' );
 
-		if ( object instanceof THREE.SkinnedMesh ) {
+		if ( object instanceof THREE.SkinnedMesh || object instanceof THREE.MorphAnimMesh ) {
 
 			animationsRow.clear();
 
 			var animation = animations[ object.id ];
 
-			var playButton = new UI.Button().setLabel( 'Play' ).onClick( function () {
+			var playButton = new UI.Button( 'Play' ).onClick( function () {
 
 				animation.play();
 
-				signals.playAnimation.dispatch( animation );
-
 			} );
 			animationsRow.add( playButton );
 
-			var pauseButton = new UI.Button().setLabel( 'Stop' ).onClick( function () {
+			var pauseButton = new UI.Button( 'Stop' ).onClick( function () {
 
 				animation.stop();
 
-				signals.stopAnimation.dispatch( animation );
-
 			} );
 			animationsRow.add( pauseButton );
 

+ 9 - 31
editor/js/Sidebar.Geometry.BufferGeometry.js

@@ -6,47 +6,25 @@ Sidebar.Geometry.BufferGeometry = function ( signals ) {
 
 	var container = new UI.Panel();
 
-	// vertices
-
-	var verticesRow = new UI.Panel();
-	var vertices = new UI.Text().setFontSize( '12px' );
-
-	verticesRow.add( new UI.Text( 'Vertices' ).setWidth( '90px' ) );
-	verticesRow.add( vertices );
-
-	container.add( verticesRow );
-
-	// faces
-
-	var facesRow = new UI.Panel();
-	var faces = new UI.Text().setFontSize( '12px' );
-
-	facesRow.add( new UI.Text( 'Faces' ).setWidth( '90px' ) );
-	facesRow.add( faces );
-
-	container.add( facesRow );
-
-	//
-
-	var update = function ( object ) {
+	function update( object ) {
 
 		if ( object === null ) return;
 
 		var geometry = object.geometry;
 
-		if ( geometry instanceof THREE.BufferGeometry ) { 
+		if ( geometry instanceof THREE.BufferGeometry ) {
 
+			container.clear();
 			container.setDisplay( 'block' );
 
-			vertices.setValue( ( geometry.attributes.position.array.length / 3 ).format() );
-
-			if ( geometry.attributes.index !== undefined ) {
-
-				faces.setValue( ( geometry.attributes.index.array.length / 3 ).format() );
+			var attributes = geometry.attributes;
 
-			} else {
+			for ( var name in attributes ) {
 
-				faces.setValue( ( geometry.attributes.position.array.length / 9 ).format() );
+				var panel = new UI.Panel();
+				panel.add( new UI.Text( name ).setWidth( '90px' ) );
+				panel.add( new UI.Text( ( attributes[ name ].count ).format() ).setFontSize( '12px' ) );
+				container.add( panel );
 
 			}
 

+ 1 - 15
editor/js/Sidebar.Geometry.Modifiers.js

@@ -35,21 +35,7 @@ Sidebar.Geometry.Modifiers = function ( signals, object ) {
 
 	var isBufferGeometry = geometry instanceof THREE.BufferGeometry;
 
-	if ( geometry instanceof THREE.BufferGeometry ) {
-
-		var button = new UI.Button( 'Convert to Geometry' );
-		button.onClick( function () {
-
-			if ( confirm( 'Are you sure?' ) === false ) return;
-
-			object.geometry = new THREE.Geometry().fromBufferGeometry( object.geometry );
-
-			signals.geometryChanged.dispatch( object );
-
-		} );
-		container.add( button );
-
-	} else {
+	if ( geometry instanceof THREE.Geometry ) {
 
 		var button = new UI.Button( 'Convert to BufferGeometry' );
 		button.onClick( function () {

+ 23 - 6
editor/js/Sidebar.Material.js

@@ -346,6 +346,16 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialTransparentRow );
 
+	// alpha test
+
+	var materialAlphaTestRow = new UI.Panel();
+	var materialAlphaTest = new UI.Number().setWidth( '60px' ).setRange( 0, 1 ).onChange( update );
+
+	materialAlphaTestRow.add( new UI.Text( 'Alpha Test' ).setWidth( '90px' ) );
+	materialAlphaTestRow.add( materialAlphaTest );
+
+	container.add( materialAlphaTestRow );
+
 	// wireframe
 
 	var materialWireframeRow = new UI.Panel();
@@ -425,12 +435,6 @@ Sidebar.Material = function ( editor ) {
 
 				if ( material.vertexColors !== vertexColors ) {
 
-					if ( geometry instanceof THREE.Geometry ) {
-
-						geometry.groupsNeedUpdate = true;
-
-					}
-
 					material.vertexColors = vertexColors;
 					material.needsUpdate = true;
 
@@ -606,6 +610,12 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
+			if ( material.alphaTest !== undefined ) {
+
+				material.alphaTest = materialAlphaTest.getValue();
+
+			}
+
 			if ( material.wireframe !== undefined ) {
 
 				material.wireframe = materialWireframe.getValue();
@@ -658,6 +668,7 @@ Sidebar.Material = function ( editor ) {
 			'blending': materialBlendingRow,
 			'opacity': materialOpacityRow,
 			'transparent': materialTransparentRow,
+			'alphaTest': materialAlphaTestRow,
 			'wireframe': materialWireframeRow
 		};
 
@@ -858,6 +869,12 @@ Sidebar.Material = function ( editor ) {
 
 		}
 
+		if ( material.alphaTest !== undefined ) {
+
+			materialAlphaTest.setValue( material.alphaTest );
+
+		}
+
 		if ( material.wireframe !== undefined ) {
 
 			materialWireframe.setValue( material.wireframe );

+ 3 - 3
editor/js/Sidebar.Object3D.js

@@ -132,7 +132,7 @@ Sidebar.Object3D = function ( editor ) {
 	// scale
 
 	var objectScaleRow = new UI.Panel();
-	var objectScaleLock = new UI.Checkbox().setPosition( 'absolute' ).setLeft( '75px' );
+	var objectScaleLock = new UI.Checkbox( true ).setPosition( 'absolute' ).setLeft( '75px' );
 	var objectScaleX = new UI.Number( 1 ).setRange( 0.01, Infinity ).setWidth( '50px' ).onChange( updateScaleX );
 	var objectScaleY = new UI.Number( 1 ).setRange( 0.01, Infinity ).setWidth( '50px' ).onChange( updateScaleY );
 	var objectScaleZ = new UI.Number( 1 ).setRange( 0.01, Infinity ).setWidth( '50px' ).onChange( updateScaleZ );
@@ -342,7 +342,7 @@ Sidebar.Object3D = function ( editor ) {
 
 		if ( object !== null ) {
 
-			if ( object.parent !== undefined ) {
+			if ( object.parent !== null ) {
 
 				var newParentId = parseInt( objectParent.getValue() );
 
@@ -535,7 +535,7 @@ Sidebar.Object3D = function ( editor ) {
 		objectUUID.setValue( object.uuid );
 		objectName.setValue( object.name );
 
-		if ( object.parent !== undefined ) {
+		if ( object.parent !== null ) {
 
 			objectParent.setValue( object.parent.id );
 

+ 38 - 54
editor/js/Viewport.js

@@ -25,8 +25,6 @@ var Viewport = function ( editor ) {
 	//
 
 	var camera = editor.camera;
-	camera.position.fromArray( editor.config.getKey( 'camera/position' ) );
-	camera.lookAt( new THREE.Vector3().fromArray( editor.config.getKey( 'camera/target' ) ) );
 
 	//
 
@@ -36,6 +34,8 @@ var Viewport = function ( editor ) {
 	selectionBox.visible = false;
 	sceneHelpers.add( selectionBox );
 
+	var matrix = new THREE.Matrix4();
+
 	var transformControls = new THREE.TransformControls( camera, container.dom );
 	transformControls.addEventListener( 'change', function () {
 
@@ -58,12 +58,37 @@ var Viewport = function ( editor ) {
 	} );
 	transformControls.addEventListener( 'mouseDown', function () {
 
+		var object = transformControls.object;
+
+		matrix.copy( object.matrix );
+
 		controls.enabled = false;
 
 	} );
 	transformControls.addEventListener( 'mouseUp', function () {
 
-		signals.objectChanged.dispatch( transformControls.object );
+		var object = transformControls.object;
+
+		if ( matrix.equals( object.matrix ) === false ) {
+
+			( function ( matrix1, matrix2 ) {
+
+				editor.history.add(
+					function () {
+						matrix1.decompose( object.position, object.quaternion, object.scale );
+						signals.objectChanged.dispatch( object );
+					},
+					function () {
+						matrix2.decompose( object.position, object.quaternion, object.scale );
+						signals.objectChanged.dispatch( object );
+					}
+				);
+
+			} )( matrix.clone(), object.matrix.clone() );
+
+		}
+
+		signals.objectChanged.dispatch( object );
 		controls.enabled = true;
 
 	} );
@@ -85,19 +110,13 @@ var Viewport = function ( editor ) {
 
 	// events
 
-	var getIntersects = function ( point, object ) {
+	function getIntersects( point, objects ) {
 
 		mouse.set( ( point.x * 2 ) - 1, - ( point.y * 2 ) + 1 );
 
 		raycaster.setFromCamera( mouse, camera );
 
-		if ( Array.isArray( object ) ) {
-
-			return raycaster.intersectObjects( object );
-
-		}
-
-		return raycaster.intersectObject( object );
+		return raycaster.intersectObjects( objects );
 
 	};
 
@@ -105,14 +124,14 @@ var Viewport = function ( editor ) {
 	var onUpPosition = new THREE.Vector2();
 	var onDoubleClickPosition = new THREE.Vector2();
 
-	var getMousePosition = function ( dom, x, y ) {
+	function getMousePosition( dom, x, y ) {
 
 		var rect = dom.getBoundingClientRect();
 		return [ ( x - rect.left ) / rect.width, ( y - rect.top ) / rect.height ];
 
 	};
 
-	var handleClick = function () {
+	function handleClick() {
 
 		if ( onDownPosition.distanceTo( onUpPosition ) == 0 ) {
 
@@ -146,7 +165,7 @@ var Viewport = function ( editor ) {
 
 	};
 
-	var onMouseDown = function ( event ) {
+	function onMouseDown( event ) {
 
 		event.preventDefault();
 
@@ -157,7 +176,7 @@ var Viewport = function ( editor ) {
 
 	};
 
-	var onMouseUp = function ( event ) {
+	function onMouseUp( event ) {
 
 		var array = getMousePosition( container.dom, event.clientX, event.clientY );
 		onUpPosition.fromArray( array );
@@ -168,7 +187,7 @@ var Viewport = function ( editor ) {
 
 	};
 
-	var onTouchStart = function ( event ) {
+	function onTouchStart( event ) {
 
 		var touch = event.changedTouches[ 0 ];
 
@@ -179,7 +198,7 @@ var Viewport = function ( editor ) {
 
 	};
 
-	var onTouchEnd = function ( event ) {
+	function onTouchEnd( event ) {
 
 		var touch = event.changedTouches[ 0 ];
 
@@ -192,7 +211,7 @@ var Viewport = function ( editor ) {
 
 	};
 
-	var onDoubleClick = function ( event ) {
+	function onDoubleClick( event ) {
 
 		var array = getMousePosition( container.dom, event.clientX, event.clientY );
 		onDoubleClickPosition.fromArray( array );
@@ -217,7 +236,6 @@ var Viewport = function ( editor ) {
 	// otherwise controls.enabled doesn't work.
 
 	var controls = new THREE.EditorControls( camera, container.dom );
-	controls.center.fromArray( editor.config.getKey( 'camera/target' ) );
 	controls.addEventListener( 'change', function () {
 
 		transformControls.update();
@@ -307,21 +325,6 @@ var Viewport = function ( editor ) {
 
 	signals.cameraChanged.add( function () {
 
-		if ( saveTimeout !== undefined ) {
-
-			clearTimeout( saveTimeout );
-
-		}
-
-		saveTimeout = setTimeout( function () {
-
-			editor.config.setKey(
-				'camera/position', camera.position.toArray(),
-				'camera/target', controls.center.toArray()
-			);
-
-		}, 1000 );
-
 		render();
 
 	} );
@@ -381,6 +384,7 @@ var Viewport = function ( editor ) {
 
 	signals.objectChanged.add( function ( object ) {
 
+		selectionBox.update( object );
 		transformControls.update();
 
 		if ( object instanceof THREE.PerspectiveCamera ) {
@@ -501,26 +505,6 @@ var Viewport = function ( editor ) {
 
 	} );
 
-	var animations = [];
-
-	signals.playAnimation.add( function ( animation ) {
-
-		animations.push( animation );
-
-	} );
-
-	signals.stopAnimation.add( function ( animation ) {
-
-		var index = animations.indexOf( animation );
-
-		if ( index !== -1 ) {
-
-			animations.splice( index, 1 );
-
-		}
-
-	} );
-
 	//
 
 	var renderer = null;

+ 3 - 3
editor/js/libs/app.js

@@ -101,7 +101,7 @@ var APP = {
 
 			if ( vr === true ) {
 
-				if ( camera.parent === undefined ) {
+				if ( camera.parent === null ) {
 
 					// camera needs to be in the scene so camera2 matrix updates
 
@@ -167,7 +167,7 @@ var APP = {
 
 				} catch (e) {
 
-					console.error(e.stack || e);
+					console.error( ( e.message || e ), ( e.stack || "" ) );
 
 				}
 
@@ -212,7 +212,7 @@ var APP = {
 			dispatch( events.start, arguments );
 
 			request = requestAnimationFrame( animate );
-			prevTime = performance.now();
+			prevTime = ( window.performance || Date ).now();
 		};
 
 		this.stop = function () {

+ 1 - 1
examples/canvas_geometry_cube.html

@@ -82,7 +82,7 @@
 				// Plane
 
 				var geometry = new THREE.PlaneBufferGeometry( 200, 200 );
-				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+				geometry.rotateX( - Math.PI / 2 );
 
 				var material = new THREE.MeshBasicMaterial( { color: 0xe0e0e0, overdraw: 0.5 } );
 

+ 1 - 2
examples/canvas_geometry_earth.html

@@ -100,8 +100,7 @@
 				context.fillStyle = gradient;
 				context.fillRect( 0, 0, canvas.width, canvas.height );
 
-				var texture = new THREE.Texture( canvas );
-				texture.needsUpdate = true;
+				var texture = new THREE.CanvasTexture( canvas );
 
 				var geometry = new THREE.PlaneBufferGeometry( 300, 300, 3, 3 );
 				var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );

+ 2 - 4
examples/canvas_geometry_terrain.html

@@ -69,15 +69,13 @@
 				scene = new THREE.Scene();
 
 				var data = generateHeight( 1024, 1024 );
-				var texture = new THREE.Texture( generateTexture( data, 1024, 1024 ) );
-				texture.needsUpdate = true;
-
+				var texture = new THREE.CanvasTexture( generateTexture( data, 1024, 1024 ) );
 				var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
 
 				var quality = 16, step = 1024 / quality;
 
 				var geometry = new THREE.PlaneGeometry( 2000, 2000, quality - 1, quality - 1 );
-				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+				geometry.rotateX( - Math.PI / 2 );
 
 				for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
 

+ 1 - 1
examples/canvas_interactive_voxelpainter.html

@@ -82,7 +82,7 @@
 				mouse = new THREE.Vector2();
 
 				var geometry = new THREE.PlaneBufferGeometry( 1000, 1000 );
-				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+				geometry.rotateX( - Math.PI / 2 );
 
 				plane = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { visible: false } ) );
 				scene.add( plane );

+ 9 - 0
examples/canvas_materials.html

@@ -80,6 +80,15 @@
 
 				];
 
+				for ( var i = 0, l = geometry.faces.length; i < l; i ++ ) {
+
+					var face = geometry.faces[ i ];
+					if ( Math.random() > 0.5 ) face.materialIndex = Math.floor( Math.random() * materials.length );
+
+				}
+
+				materials.push( new THREE.MeshFaceMaterial( materials ) );
+
 				objects = [];
 
 				for ( var i = 0, l = materials.length; i < l; i ++ ) {

+ 0 - 345
examples/canvas_particles_shapes.html

@@ -1,345 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js canvas - particles with shapes</title>
-		<meta charset="utf-8">
-		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<style>
-			body {
-				font-family: Monospace;
-				background-color: #f0f0f0;
-				margin: 0px;
-				overflow: hidden;
-			}
-		</style>
-	</head>
-	<body>
-
-
-		<script src="../build/three.min.js"></script>
-
-		<script src="js/renderers/Projector.js"></script>
-		<script src="js/renderers/CanvasRenderer.js"></script>
-
-		<script src="js/libs/stats.min.js"></script>
-		<script src="js/libs/tween.min.js"></script>
-		<script src="js/Sparks.js"></script>
-
-		<!-- load the font file from canvas-text -->
-
-		<script src="fonts/helvetiker_regular.typeface.js"></script>
-
-
-		<script>
-
-			var container, stats;
-
-			var camera, scene, renderer;
-
-			var group, text, plane;
-
-			var targetRotation = 0;
-			var targetRotationOnMouseDown = 0;
-
-			var mouseX = 0;
-			var mouseXOnMouseDown = 0;
-
-			var windowHalfX = window.innerWidth / 2;
-			var windowHalfY = window.innerHeight / 2;
-
-			var heartShape, particleCloud, sparksEmitter, emitterPos;
-			var _rotation = 0;
-			var timeOnShapePath = 0;
-
-			init();
-			animate();
-
-			function init() {
-
-				container = document.createElement( 'div' );
-				document.body.appendChild( container );
-
-				var info = document.createElement( 'div' );
-				info.style.position = 'absolute';
-				info.style.top = '10px';
-				info.style.width = '100%';
-				info.style.textAlign = 'center';
-				info.innerHTML = 'Three.js with Love. Simple Particle Systems with Shapes by <a href="http://www.lab4games.net/zz85/blog">zz85</a><br>Move your mouse.';
-				container.appendChild( info );
-
-				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
-				camera.position.set( 0, 150, 700 );
-
-				scene = new THREE.Scene();
-
-				group = new THREE.Group();
-				scene.add( group );
-
-				// Get text from hash
-
-				var string = "THREE.JS";
-				var hash = document.location.hash.substr( 1 );
-
-				if ( hash.length !== 0 ) {
-
-					string = hash;
-
-				}
-
-				var text3d = new THREE.TextGeometry( string, {
-
-					size: 80,
-					height: 20,
-					curveSegments: 2,
-					font: "helvetiker"
-
-				});
-
-				text3d.computeBoundingBox();
-				var centerOffset = -0.5 * ( text3d.boundingBox.max.x - text3d.boundingBox.min.x );
-
-				var textMaterial = new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, overdraw: 0.5 } );
-
-				text = new THREE.Mesh( text3d, textMaterial );
-
-				// Potentially, we can extract the vertices or faces of the text to generate particles too.
-				// Geo > Vertices > Position
-
-				text.position.x = centerOffset;
-				text.position.y = 100;
-				text.position.z = 0;
-
-				text.rotation.x = 0;
-				text.rotation.y = Math.PI * 2;
-
-				group.add( text );
-
-
-				particleCloud = new THREE.Object3D(); // Just a group
-				particleCloud.y = 800;
-				group.add( particleCloud );
-
-				// Create Particle Systems
-
-				// Heart
-
-				var x = 0, y = 0;
-
-				heartShape = new THREE.Shape();
-
-				heartShape.moveTo( x + 25, y + 25 );
-				heartShape.bezierCurveTo( x + 25, y + 25, x + 20, y, x, y );
-				heartShape.bezierCurveTo( x - 30, y, x - 30, y + 35,x - 30,y + 35 );
-				heartShape.bezierCurveTo( x - 30, y + 55, x - 10, y + 77, x + 25, y + 95 );
-				heartShape.bezierCurveTo( x + 60, y + 77, x + 80, y + 55, x + 80, y + 35 );
-				heartShape.bezierCurveTo( x + 80, y + 35, x + 80, y, x + 50, y );
-				heartShape.bezierCurveTo( x + 35, y, x + 25, y + 25, x + 25, y + 25 );
-
-				var hue = 0;
-
-				var hearts = function ( context ) {
-
-					context.globalAlpha = 0.5;
-					var x = 0, y = 0;
-					context.scale(0.05, -0.05); // Scale so canvas render can redraw within bounds
-					context.beginPath();
-					 // From http://blog.burlock.org/html5/130-paths
-					context.bezierCurveTo( x + 2.5, y + 2.5, x + 2.0, y, x, y );
-					context.bezierCurveTo( x - 3.0, y, x - 3.0, y + 3.5,x - 3.0,y + 3.5 );
-					context.bezierCurveTo( x - 3.0, y + 5.5, x - 1.0, y + 7.7, x + 2.5, y + 9.5 );
-					context.bezierCurveTo( x + 6.0, y + 7.7, x + 8.0, y + 5.5, x + 8.0, y + 3.5 );
-					context.bezierCurveTo( x + 8.0, y + 3.5, x + 8.0, y, x + 5.0, y );
-					context.bezierCurveTo( x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5 );
-					context.fill();
-					context.lineWidth = 0.5; //0.05
-					context.stroke();
-
-				};
-
-				var setTargetParticle = function() {
-
-					var material = new THREE.SpriteCanvasMaterial( {
-						program: hearts
-					} );
-
-					material.color.setHSL(hue, 1, 0.75);
-					hue += 0.001;
-					if (hue>1) hue-=1;
-
-					particle = new THREE.Sprite( material );
-
-					particle.scale.x = particle.scale.y = Math.random() * 40 + 40;
-					particleCloud.add( particle );
-
-					return particle;
-
-				};
-
-				var onParticleCreated = function( p ) {
-
-					p.target.position.copy( p.position );
-
-				};
-
-				var onParticleDead = function( particle ) {
-
-					particle.target.visible = false;
-					particleCloud.remove( particle.target );
-
-				};
-
-				sparksEmitter = new SPARKS.Emitter(new SPARKS.SteadyCounter(160));
-
-				emitterpos = new THREE.Vector3();
-
-				sparksEmitter.addInitializer(new SPARKS.Position( new SPARKS.PointZone( emitterpos ) ) );
-				sparksEmitter.addInitializer(new SPARKS.Lifetime(0,2));
-				sparksEmitter.addInitializer(new SPARKS.Target(null, setTargetParticle));
-
-				sparksEmitter.addInitializer(new SPARKS.Velocity(new SPARKS.PointZone(new THREE.Vector3(0,-50,10))));
-
-				// TOTRY Set velocity to move away from centroid
-
-				sparksEmitter.addAction(new SPARKS.Age());
-				//sparksEmitter.addAction(new SPARKS.Accelerate(0.2));
-				sparksEmitter.addAction(new SPARKS.Move());
-				sparksEmitter.addAction(new SPARKS.RandomDrift(50,50,2000));
-
-				sparksEmitter.addCallback("created", onParticleCreated);
-				sparksEmitter.addCallback("dead", onParticleDead);
-				sparksEmitter.addCallback("updated", function( particle ) {
-
-					particle.target.position.copy( particle.position );
-
-				});
-
-				sparksEmitter.start();
-
-				// End Particles
-
-
-				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				container.appendChild( renderer.domElement );
-
-				stats = new Stats();
-				stats.domElement.style.position = 'absolute';
-				stats.domElement.style.top = '0px';
-				container.appendChild( stats.domElement );
-
-				document.addEventListener( 'mousedown', onDocumentMouseDown, false );
-				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
-				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
-
-				//
-
-				window.addEventListener( 'resize', onWindowResize, false );
-
-			}
-
-			function onWindowResize() {
-
-				windowHalfX = window.innerWidth / 2;
-				windowHalfY = window.innerHeight / 2;
-
-				camera.aspect = window.innerWidth / window.innerHeight;
-				camera.updateProjectionMatrix();
-
-				renderer.setSize( window.innerWidth, window.innerHeight );
-
-			}
-
-			//
-
-			document.addEventListener( 'mousemove', onDocumentMouseMove, false );
-
-			function onDocumentMouseDown( event ) {
-
-				event.preventDefault();
-
-				mouseXOnMouseDown = event.clientX - windowHalfX;
-				targetRotationOnMouseDown = targetRotation;
-
-				if ( sparksEmitter.isRunning() ) {
-
-					sparksEmitter.stop();
-
-				} else {
-
-					sparksEmitter.start();
-
-				}
-
-			}
-
-			function onDocumentMouseMove( event ) {
-
-				mouseX = event.clientX - windowHalfX;
-
-				targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
-
-			}
-
-			function onDocumentTouchStart( event ) {
-
-				if ( event.touches.length == 1 ) {
-
-					event.preventDefault();
-
-					mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
-					targetRotationOnMouseDown = targetRotation;
-
-				}
-
-			}
-
-			function onDocumentTouchMove( event ) {
-
-				if ( event.touches.length == 1 ) {
-
-					event.preventDefault();
-
-					mouseX = event.touches[ 0 ].pageX - windowHalfX;
-					targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
-
-				}
-
-			}
-
-			//
-
-			function animate() {
-
-				requestAnimationFrame( animate );
-
-				render();
-				stats.update();
-
-			}
-
-			function render() {
-
-				timeOnShapePath += 0.0337;
-
-				if (timeOnShapePath > 1) timeOnShapePath -= 1;
-
-				// TODO Create a PointOnShape Action/Zone in the particle engine
-				var pointOnShape = heartShape.getPointAt( timeOnShapePath );
-
-				emitterpos.x = pointOnShape.x * 5 - 100;
-				emitterpos.y = -pointOnShape.y * 5 + 400;
-
-				// Pretty cool effect if you enable this
-				// particleCloud.rotation.y += 0.05;
-
-				group.rotation.y += ( targetRotation - group.rotation.y ) * 0.05;
-				renderer.render( scene, camera );
-
-			}
-
-		</script>
-
-	</body>
-</html>

+ 3 - 3
examples/canvas_particles_sprites.html

@@ -12,7 +12,7 @@
 			}
 
 			a {
-				color:#0078ff;
+				color: #0078ff;
 			}
 		</style>
 	</head>
@@ -49,7 +49,7 @@
 				scene = new THREE.Scene();
 
 				var material = new THREE.SpriteMaterial( {
-					map: new THREE.Texture( generateSprite() ),
+					map: new THREE.CanvasTexture( generateSprite() ),
 					blending: THREE.AdditiveBlending
 				} );
 
@@ -136,7 +136,7 @@
 
 				new TWEEN.Tween( particle.scale )
 					.delay( delay )
-					.to( { x: 0, y: 0 }, 10000 )
+					.to( { x: 0.01, y: 0.01 }, 10000 )
 					.start();
 
 			}

+ 1 - 1
examples/css3d_molecules.html

@@ -347,7 +347,7 @@
 				loader.load( url, function ( geometry, geometryBonds ) {
 
 					var offset = geometry.center();
-					geometryBonds.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
+					geometryBonds.translate( offset.x, offset.y, offset.z );
 
 					for ( var i = 0; i < geometry.vertices.length; i ++ ) {
 

+ 10 - 6
examples/index.html

@@ -88,7 +88,7 @@
 
 			#button {
 				position: fixed;
-				top: 20px;
+				bottom: 20px;
 				right: 20px;
 				padding: 8px;
 				color: #fff;
@@ -225,6 +225,7 @@
 				"webgl_geometry_text",
 				"webgl_geometry_text2",
 				"webgl_gpgpu_birds",
+				"webgl_gpu_particle_system",
 				"webgl_hdr",
 				"webgl_helpers",
 				"webgl_interactive_buffergeometry",
@@ -257,13 +258,21 @@
 				"webgl_loader_ctm_materials",
 				"webgl_loader_gltf",
 				"webgl_loader_json_blender",
+				"webgl_loader_json_claraio",
 				"webgl_loader_json_objconverter",
+				"webgl_loader_md2",
+				"webgl_loader_md2_control",
 				"webgl_loader_msgpack",
 				"webgl_loader_obj",
 				"webgl_loader_obj_mtl",
 				"webgl_loader_pdb",
 				"webgl_loader_ply",
 				"webgl_loader_sea3d",
+				"webgl_loader_sea3d_hierarchy",
+				"webgl_loader_sea3d_keyframe",
+				"webgl_loader_sea3d_morph",
+				"webgl_loader_sea3d_skinning",
+				"webgl_loader_sea3d_sound",
 				"webgl_loader_scene",
 				"webgl_loader_stl",
 				"webgl_loader_utf8",
@@ -278,7 +287,6 @@
 				"webgl_materials_bumpmap",
 				"webgl_materials_bumpmap_skin",
 				"webgl_materials_cars",
-				"webgl_materials_cars_camaro",
 				"webgl_materials_cubemap",
 				"webgl_materials_cubemap_balls_reflection",
 				"webgl_materials_cubemap_balls_refraction",
@@ -310,8 +318,6 @@
 				"webgl_morphtargets",
 				"webgl_morphtargets_horse",
 				"webgl_morphtargets_human",
-				"webgl_morphtargets_md2",
-				"webgl_morphtargets_md2_control",
 				"webgl_multiple_canvases_circle",
 				"webgl_multiple_canvases_complex",
 				"webgl_multiple_canvases_grid",
@@ -327,7 +333,6 @@
 				"webgl_particles_billboards_colors",
 				"webgl_particles_dynamic",
 				"webgl_particles_random",
-				"webgl_particles_shapes",
 				"webgl_particles_sprites",
 				"webgl_performance",
 				"webgl_performance_doublesided",
@@ -453,7 +458,6 @@
 				"canvas_morphtargets_horse",
 				"canvas_particles_floor",
 				"canvas_particles_random",
-				"canvas_particles_shapes",
 				"canvas_particles_sprites",
 				"canvas_particles_waves",
 				"canvas_performance",

+ 2 - 2
examples/js/AudioObject.js

@@ -118,7 +118,7 @@ THREE.AudioObject = function ( url, volume, playbackRate, loop ) {
 
 		cameraUp.copy( camera.up );
 
-		cameraFront.set( 0, 0, -1 );
+		cameraFront.set( 0, 0, - 1 );
 		cameraFront.transformDirection( camera.matrixWorld );
 
 		this.listener.setPosition( cameraPosition.x, cameraPosition.y, cameraPosition.z );
@@ -130,7 +130,7 @@ THREE.AudioObject = function ( url, volume, playbackRate, loop ) {
 
 		if ( this.directionalSource ) {
 
-			soundFront.set( 0, 0, -1 );
+			soundFront.set( 0, 0, - 1 );
 			soundFront.transformDirection( this.matrixWorld );
 
 			soundUp.copy( this.up );

+ 11 - 22
examples/js/BlendCharacter.js

@@ -29,14 +29,6 @@ THREE.BlendCharacter = function () {
 
 			}
 
-			// Create the debug visualization
-
-			scope.skeletonHelper = new THREE.SkeletonHelper( scope );
-			scope.skeletonHelper.material.linewidth = 3;
-			scope.add( scope.skeletonHelper );
-
-			scope.showSkeleton( false );
-
 			// Loading is complete, fire the callback
 			if ( onLoad !== undefined ) onLoad();
 
@@ -70,14 +62,13 @@ THREE.BlendCharacter = function () {
 
 				// interpolate the weight for the current time
 
-				data.anim.weight = data.startWeight + (data.endWeight - data.startWeight) * data.timeElapsed / data.duration;
+				data.anim.weight = data.startWeight + ( data.endWeight - data.startWeight ) * data.timeElapsed / data.duration;
 
 			}
 
 		}
 
 		this.updateWarps( dt );
-		this.skeletonHelper.update();
 
 	};
 
@@ -126,7 +117,7 @@ THREE.BlendCharacter = function () {
 
 	};
 
-	this.play = function(animName, weight) {
+	this.play = function( animName, weight ) {
 
 		this.animations[ animName ].play( 0, weight );
 
@@ -181,7 +172,7 @@ THREE.BlendCharacter = function () {
 
 	};
 
-	this.applyWeight = function(animName, weight) {
+	this.applyWeight = function( animName, weight ) {
 
 		this.animations[ animName ].weight = weight;
 
@@ -221,7 +212,9 @@ THREE.BlendCharacter = function () {
 		for ( a in this.animations ) {
 
 			if ( this.animations[ a ].isPlaying ) {
-				this.animations[ a ].stop(0);
+
+				this.animations[ a ].stop( 0 );
+
 			}
 
 			this.animations[ a ].weight = 0;
@@ -233,12 +226,6 @@ THREE.BlendCharacter = function () {
 
 	};
 
-	this.showSkeleton = function( boolean ) {
-
-		this.skeletonHelper.visible = boolean;
-
-	};
-
 	this.showModel = function( boolean ) {
 
 		this.visible = boolean;
@@ -259,12 +246,14 @@ THREE.BlendCharacter.prototype.getForward = function() {
 
 		// pull the character's forward basis vector out of the matrix
 		forward.set(
-			-this.matrix.elements[ 8 ],
-			-this.matrix.elements[ 9 ],
-			-this.matrix.elements[ 10 ]
+			- this.matrix.elements[ 8 ],
+			- this.matrix.elements[ 9 ],
+			- this.matrix.elements[ 10 ]
 		);
 
 		return forward;
+
 	}
+
 };
 

+ 33 - 27
examples/js/BlendCharacterGui.js

@@ -2,7 +2,7 @@
  * @author Michael Guerrero / http://realitymeltdown.com
  */
 
-function BlendCharacterGui(animations) {
+function BlendCharacterGui( animations ) {
 
 	var controls = {
 
@@ -22,27 +22,27 @@ function BlendCharacterGui(animations) {
 
 	this.showModel = function() {
 
-		return controls['Show Model'];
+		return controls[ 'Show Model' ];
 
 	};
 
 	this.showSkeleton = function() {
 
-		return controls['Show Skeleton'];
+		return controls[ 'Show Skeleton' ];
 
 	};
 
 	this.getTimeScale = function() {
 
-		return controls['Time Scale'];
+		return controls[ 'Time Scale' ];
 
 	};
 
 	this.update = function() {
 
-		controls[ 'idle'] = animations[ 'idle' ].weight;
-		controls[ 'walk'] = animations[ 'walk' ].weight;
-		controls[ 'run'] = animations[ 'run' ].weight;
+		controls[ 'idle' ] = animations[ 'idle' ].weight;
+		controls[ 'walk' ] = animations[ 'walk' ].weight;
+		controls[ 'run' ] = animations[ 'run' ].weight;
 
 	};
 
@@ -68,9 +68,9 @@ function BlendCharacterGui(animations) {
 		playback.add( controls, "walk to run" );
 		playback.add( controls, "warp walk to run" );
 
-		blending.add( controls, "idle", 0, 1, 0.01).listen().onChange( controls.weight );
-		blending.add( controls, "walk", 0, 1, 0.01).listen().onChange( controls.weight );
-		blending.add( controls, "run", 0, 1, 0.01).listen().onChange( controls.weight );
+		blending.add( controls, "idle", 0, 1, 0.01 ).listen().onChange( controls.weight );
+		blending.add( controls, "walk", 0, 1, 0.01 ).listen().onChange( controls.weight );
+		blending.add( controls, "run", 0, 1, 0.01 ).listen().onChange( controls.weight );
 
 		settings.open();
 		playback.open();
@@ -86,18 +86,19 @@ function BlendCharacterGui(animations) {
 
 				anims: [ "idle", "walk", "run" ],
 
-				weights: [ controls['idle'],
-						   controls['walk'],
-						   controls['run'] ]
+				weights: [ controls[ 'idle' ],
+						   controls[ 'walk' ],
+						   controls[ 'run' ] ]
 			}
 
 		};
+
 	};
 
 	controls.start = function() {
 
 		var startEvent = new CustomEvent( 'start-animation', getAnimationData() );
-		window.dispatchEvent(startEvent);
+		window.dispatchEvent( startEvent );
 
 	};
 
@@ -117,21 +118,22 @@ function BlendCharacterGui(animations) {
 
 	controls.step = function() {
 
-		var stepData = { detail: { stepSize: controls['Step Size'] } };
-		window.dispatchEvent( new CustomEvent('step-animation', stepData ));
+		var stepData = { detail: { stepSize: controls[ 'Step Size' ] } };
+		window.dispatchEvent( new CustomEvent( 'step-animation', stepData ) );
 
 	};
 
 	controls.weight = function() {
 
 		// renormalize
-		var sum = controls['idle'] + controls['walk'] + controls['run'];
-		controls['idle'] /= sum;
-		controls['walk'] /= sum;
-		controls['run'] /= sum;
+		var sum = controls[ 'idle' ] + controls[ 'walk' ] + controls[ 'run' ];
+		controls[ 'idle' ] /= sum;
+		controls[ 'walk' ] /= sum;
+		controls[ 'run' ] /= sum;
 
 		var weightEvent = new CustomEvent( 'weight-animation', getAnimationData() );
-		window.dispatchEvent(weightEvent);
+		window.dispatchEvent( weightEvent );
+
 	};
 
 	controls.crossfade = function( from, to ) {
@@ -142,6 +144,7 @@ function BlendCharacterGui(animations) {
 		fadeData.detail.time = controls[ "Crossfade Time" ];
 
 		window.dispatchEvent( new CustomEvent( 'crossfade', fadeData ) );
+
 	};
 
 	controls.warp = function( from, to ) {
@@ -152,21 +155,22 @@ function BlendCharacterGui(animations) {
 		warpData.detail.time = controls[ "Crossfade Time" ];
 
 		window.dispatchEvent( new CustomEvent( 'warp', warpData ) );
+
 	};
 
-	controls['idle to walk'] = function() {
+	controls[ 'idle to walk' ] = function() {
 
 		controls.crossfade( 'idle', 'walk' );
 
 	};
 
-	controls['walk to run'] = function() {
+	controls[ 'walk to run' ] = function() {
 
 		controls.crossfade( 'walk', 'run' );
 
 	};
 
-	controls['warp walk to run'] = function() {
+	controls[ 'warp walk to run' ] = function() {
 
 		controls.warp( 'walk', 'run' );
 
@@ -176,11 +180,12 @@ function BlendCharacterGui(animations) {
 
 		var data = {
 			detail: {
-				shouldShow: controls['Show Skeleton']
+				shouldShow: controls[ 'Show Skeleton' ]
 			}
 		};
 
 		window.dispatchEvent( new CustomEvent( 'toggle-show-skeleton', data ) );
+
 	};
 
 
@@ -188,14 +193,15 @@ function BlendCharacterGui(animations) {
 
 		var data = {
 			detail: {
-				shouldShow: controls['Show Model']
+				shouldShow: controls[ 'Show Model' ]
 			}
 		};
 
 		window.dispatchEvent( new CustomEvent( 'toggle-show-model', data ) );
+
 	};
 
 
-	init.call(this);
+	init.call( this );
 
 }

+ 52 - 16
examples/js/Car.js

@@ -27,7 +27,7 @@ THREE.Car = function () {
 	// car "feel" parameters
 
 	this.MAX_SPEED = 2200;
-	this.MAX_REVERSE_SPEED = -1500;
+	this.MAX_REVERSE_SPEED = - 1500;
 
 	this.MAX_WHEEL_ROTATION = 0.6;
 
@@ -107,8 +107,16 @@ THREE.Car = function () {
 
 		var loader = new THREE.JSONLoader();
 
-		loader.load( bodyURL, function( geometry, materials ) { createBody( geometry, materials ) } );
-		loader.load( wheelURL, function( geometry, materials ) { createWheels( geometry, materials ) } );
+		loader.load( bodyURL, function( geometry, materials ) {
+
+			createBody( geometry, materials )
+
+		} );
+		loader.load( wheelURL, function( geometry, materials ) {
+
+			createWheels( geometry, materials )
+
+		} );
 
 	};
 
@@ -116,8 +124,16 @@ THREE.Car = function () {
 
 		var loader = new THREE.BinaryLoader();
 
-		loader.load( bodyURL, function( geometry, materials ) { createBody( geometry, materials ) } );
-		loader.load( wheelURL, function( geometry, materials ) { createWheels( geometry, materials ) } );
+		loader.load( bodyURL, function( geometry, materials ) {
+
+			createBody( geometry, materials )
+
+		} );
+		loader.load( wheelURL, function( geometry, materials ) {
+
+			createWheels( geometry, materials )
+
+		} );
 
 	};
 
@@ -128,7 +144,7 @@ THREE.Car = function () {
 		if ( controls.moveForward ) {
 
 			this.speed = THREE.Math.clamp( this.speed + delta * this.FRONT_ACCELERATION, this.MAX_REVERSE_SPEED, this.MAX_SPEED );
-			this.acceleration = THREE.Math.clamp( this.acceleration + delta, -1, 1 );
+			this.acceleration = THREE.Math.clamp( this.acceleration + delta, - 1, 1 );
 
 		}
 
@@ -136,7 +152,7 @@ THREE.Car = function () {
 
 
 			this.speed = THREE.Math.clamp( this.speed - delta * this.BACK_ACCELERATION, this.MAX_REVERSE_SPEED, this.MAX_SPEED );
-			this.acceleration = THREE.Math.clamp( this.acceleration - delta, -1, 1 );
+			this.acceleration = THREE.Math.clamp( this.acceleration - delta, - 1, 1 );
 
 		}
 
@@ -168,7 +184,7 @@ THREE.Car = function () {
 				var k = exponentialEaseOut( this.speed / this.MAX_REVERSE_SPEED );
 
 				this.speed = THREE.Math.clamp( this.speed + k * delta * this.BACK_ACCELERATION, this.MAX_REVERSE_SPEED, 0 );
-				this.acceleration = THREE.Math.clamp( this.acceleration + k * delta, -1, 0 );
+				this.acceleration = THREE.Math.clamp( this.acceleration + k * delta, - 1, 0 );
 
 			}
 
@@ -307,7 +323,7 @@ THREE.Car = function () {
 
 			// front right wheel
 
-			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( -s, s, s ) );
+			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( - s, s, s ) );
 
 			scope.frontRightWheelRoot.position.add( delta );
 
@@ -321,7 +337,7 @@ THREE.Car = function () {
 
 			// back left wheel
 
-			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( s, s, -s ) );
+			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( s, s, - s ) );
 			delta.z -= scope.backWheelOffset;
 
 			scope.backLeftWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
@@ -333,7 +349,7 @@ THREE.Car = function () {
 
 			// back right wheel
 
-			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( -s, s, -s ) );
+			delta.multiplyVectors( scope.wheelOffset, new THREE.Vector3( - s, s, - s ) );
 			delta.z -= scope.backWheelOffset;
 
 			scope.backRightWheelMesh = new THREE.Mesh( scope.wheelGeometry, wheelFaceMaterial );
@@ -362,10 +378,30 @@ THREE.Car = function () {
 
 	}
 
-	function quadraticEaseOut( k ) { return - k * ( k - 2 ); }
-	function cubicEaseOut( k ) { return -- k * k * k + 1; }
-	function circularEaseOut( k ) { return Math.sqrt( 1 - -- k * k ); }
-	function sinusoidalEaseOut( k ) { return Math.sin( k * Math.PI / 2 ); }
-	function exponentialEaseOut( k ) { return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1; }
+	function quadraticEaseOut( k ) {
+
+		return - k * ( k - 2 );
+
+	}
+	function cubicEaseOut( k ) {
+
+		return -- k * k * k + 1;
+
+	}
+	function circularEaseOut( k ) {
+
+		return Math.sqrt( 1 - -- k * k );
+
+	}
+	function sinusoidalEaseOut( k ) {
+
+		return Math.sin( k * Math.PI / 2 );
+
+	}
+	function exponentialEaseOut( k ) {
+
+		return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
+
+	}
 
 };

+ 137 - 92
examples/js/Cloth.js

@@ -19,12 +19,12 @@ var restDistance = 25;
 var xSegs = 10; //
 var ySegs = 10; //
 
-var clothFunction = plane(restDistance * xSegs, restDistance * ySegs);
+var clothFunction = plane( restDistance * xSegs, restDistance * ySegs );
 
-var cloth = new Cloth(xSegs, ySegs);
+var cloth = new Cloth( xSegs, ySegs );
 
 var GRAVITY = 981 * 1.4; // 
-var gravity = new THREE.Vector3( 0, -GRAVITY, 0 ).multiplyScalar(MASS);
+var gravity = new THREE.Vector3( 0, - GRAVITY, 0 ).multiplyScalar( MASS );
 
 
 var TIMESTEP = 18 / 1000;
@@ -35,9 +35,9 @@ var pins = [];
 
 var wind = true;
 var windStrength = 2;
-var windForce = new THREE.Vector3(0,0,0);
+var windForce = new THREE.Vector3( 0, 0, 0 );
 
-var ballPosition = new THREE.Vector3(0, -45, 0);
+var ballPosition = new THREE.Vector3( 0, - 45, 0 );
 var ballSize = 60; //40
 
 var tmpForce = new THREE.Vector3();
@@ -45,64 +45,76 @@ var tmpForce = new THREE.Vector3();
 var lastTime;
 
 
-function plane(width, height) {
+function plane( width, height ) {
 
-	return function(u, v) {
-		var x = (u - 0.5) * width;
-		var y = (v + 0.5) * height;
+	return function( u, v ) {
+
+		var x = ( u - 0.5 ) * width;
+		var y = ( v + 0.5 ) * height;
 		var z = 0;
 
-		return new THREE.Vector3(x, y, z);
+		return new THREE.Vector3( x, y, z );
+
 	};
+
 }
 
-function Particle(x, y, z, mass) {
-	this.position = clothFunction(x, y); // position
-	this.previous = clothFunction(x, y); // previous
-	this.original = clothFunction(x, y); 
-	this.a = new THREE.Vector3(0, 0, 0); // acceleration
+function Particle( x, y, z, mass ) {
+
+	this.position = clothFunction( x, y ); // position
+	this.previous = clothFunction( x, y ); // previous
+	this.original = clothFunction( x, y ); 
+	this.a = new THREE.Vector3( 0, 0, 0 ); // acceleration
 	this.mass = mass;
 	this.invMass = 1 / mass;
 	this.tmp = new THREE.Vector3();
 	this.tmp2 = new THREE.Vector3();
+
 }
 
 // Force -> Acceleration
-Particle.prototype.addForce = function(force) {
+Particle.prototype.addForce = function( force ) {
+
 	this.a.add(
-		this.tmp2.copy(force).multiplyScalar(this.invMass)
+		this.tmp2.copy( force ).multiplyScalar( this.invMass )
 	);
+
 };
 
 
 // Performs verlet integration
-Particle.prototype.integrate = function(timesq) {
-	var newPos = this.tmp.subVectors(this.position, this.previous);
-	newPos.multiplyScalar(DRAG).add(this.position);
-	newPos.add(this.a.multiplyScalar(timesq));
+Particle.prototype.integrate = function( timesq ) {
+
+	var newPos = this.tmp.subVectors( this.position, this.previous );
+	newPos.multiplyScalar( DRAG ).add( this.position );
+	newPos.add( this.a.multiplyScalar( timesq ) );
 
 	this.tmp = this.previous;
 	this.previous = this.position;
 	this.position = newPos;
 
-	this.a.set(0, 0, 0);
+	this.a.set( 0, 0, 0 );
+
 };
 
 
 var diff = new THREE.Vector3();
 
-function satisifyConstrains(p1, p2, distance) {
-	diff.subVectors(p2.position, p1.position);
+function satisifyConstrains( p1, p2, distance ) {
+
+	diff.subVectors( p2.position, p1.position );
 	var currentDist = diff.length();
-	if (currentDist == 0) return; // prevents division by 0
-	var correction = diff.multiplyScalar(1 - distance / currentDist);
-	var correctionHalf = correction.multiplyScalar(0.5);
-	p1.position.add(correctionHalf);
-	p2.position.sub(correctionHalf);
+	if ( currentDist == 0 ) return; // prevents division by 0
+	var correction = diff.multiplyScalar( 1 - distance / currentDist );
+	var correctionHalf = correction.multiplyScalar( 0.5 );
+	p1.position.add( correctionHalf );
+	p2.position.sub( correctionHalf );
+
 }
 
 
-function Cloth(w, h) {
+function Cloth( w, h ) {
+
 	w = w || 10;
 	h = h || 10;
 	this.w = w;
@@ -114,49 +126,59 @@ function Cloth(w, h) {
 	var u, v;
 
 	// Create particles
-	for (v = 0; v <= h; v ++) {
-		for (u = 0; u <= w; u ++) {
+	for ( v = 0; v <= h; v ++ ) {
+
+		for ( u = 0; u <= w; u ++ ) {
+
 			particles.push(
-				new Particle(u / w, v / h, 0, MASS)
+				new Particle( u / w, v / h, 0, MASS )
 			);
+
 		}
+
 	}
 
 	// Structural
 
-	for (v = 0; v < h; v ++) {
-		for (u = 0; u < w; u ++) {
+	for ( v = 0; v < h; v ++ ) {
+
+		for ( u = 0; u < w; u ++ ) {
 
-			constrains.push([
-				particles[index(u, v)],
-				particles[index(u, v + 1)],
+			constrains.push( [
+				particles[ index( u, v ) ],
+				particles[ index( u, v + 1 ) ],
 				restDistance
-			]);
+			] );
 
-			constrains.push([
-				particles[index(u, v)],
-				particles[index(u + 1, v)],
+			constrains.push( [
+				particles[ index( u, v ) ],
+				particles[ index( u + 1, v ) ],
 				restDistance
-			]);
+			] );
 
 		}
+
 	}
 
-	for (u = w, v = 0; v < h; v ++) {
-		constrains.push([
-			particles[index(u, v)],
-			particles[index(u, v + 1)],
+	for ( u = w, v = 0; v < h; v ++ ) {
+
+		constrains.push( [
+			particles[ index( u, v ) ],
+			particles[ index( u, v + 1 ) ],
 			restDistance
 
-		]);
+		] );
+
 	}
 
-	for (v = h, u = 0; u < w; u ++) {
-		constrains.push([
-			particles[index(u, v)],
-			particles[index(u + 1, v)],
+	for ( v = h, u = 0; u < w; u ++ ) {
+
+		constrains.push( [
+			particles[ index( u, v ) ],
+			particles[ index( u + 1, v ) ],
 			restDistance
-		]);
+		] );
+
 	}
 
 
@@ -189,91 +211,114 @@ function Cloth(w, h) {
 	this.particles = particles;
 	this.constrains = constrains;
 
-	function index(u, v) {
-		return u + v * (w + 1);
+	function index( u, v ) {
+
+		return u + v * ( w + 1 );
+
 	}
 
 	this.index = index;
 
 }
 
-function simulate(time) {
-	if (!lastTime) {
+function simulate( time ) {
+
+	if ( ! lastTime ) {
+
 		lastTime = time;
 		return;
+
 	}
 	
 	var i, il, particles, particle, pt, constrains, constrain;
 
 	// Aerodynamics forces
-	if (wind) {
+	if ( wind ) {
+
 		var face, faces = clothGeometry.faces, normal;
 
 		particles = cloth.particles;
 
-		for (i = 0,il = faces.length; i < il; i ++) {
-			face = faces[i];
+		for ( i = 0, il = faces.length; i < il; i ++ ) {
+
+			face = faces[ i ];
 			normal = face.normal;
 
-			tmpForce.copy(normal).normalize().multiplyScalar(normal.dot(windForce));
-			particles[face.a].addForce(tmpForce);
-			particles[face.b].addForce(tmpForce);
-			particles[face.c].addForce(tmpForce);
+			tmpForce.copy( normal ).normalize().multiplyScalar( normal.dot( windForce ) );
+			particles[ face.a ].addForce( tmpForce );
+			particles[ face.b ].addForce( tmpForce );
+			particles[ face.c ].addForce( tmpForce );
+
 		}
+
 	}
 	
-	for (particles = cloth.particles, i = 0, il = particles.length
-			; i < il; i ++) {
-		particle = particles[i];
-		particle.addForce(gravity);
+	for ( particles = cloth.particles, i = 0, il = particles.length
+			; i < il; i ++ ) {
+
+		particle = particles[ i ];
+		particle.addForce( gravity );
+
+		particle.integrate( TIMESTEP_SQ );
 
-		particle.integrate(TIMESTEP_SQ);
 	}
 
 	// Start Constrains
 
 	constrains = cloth.constrains,
 	il = constrains.length;
-	for (i = 0; i < il; i ++) {
-		constrain = constrains[i];
-		satisifyConstrains(constrain[0], constrain[1], constrain[2]);
+	for ( i = 0; i < il; i ++ ) {
+
+		constrain = constrains[ i ];
+		satisifyConstrains( constrain[ 0 ], constrain[ 1 ], constrain[ 2 ] );
+
 	}
 
 	// Ball Constrains
 
 
-	ballPosition.z = -Math.sin(Date.now() / 600) * 90 ; //+ 40;
-	ballPosition.x = Math.cos(Date.now() / 400) * 70;
+	ballPosition.z = - Math.sin( Date.now() / 600 ) * 90 ; //+ 40;
+	ballPosition.x = Math.cos( Date.now() / 400 ) * 70;
+
+	if ( sphere.visible )
+	for ( particles = cloth.particles, i = 0, il = particles.length
+			; i < il; i ++ ) {
 
-	if (sphere.visible)
-	for (particles = cloth.particles, i = 0, il = particles.length
-			; i < il; i ++) {
-		particle = particles[i];
+		particle = particles[ i ];
 		pos = particle.position;
-		diff.subVectors(pos, ballPosition);
-		if (diff.length() < ballSize) {
+		diff.subVectors( pos, ballPosition );
+		if ( diff.length() < ballSize ) {
+
 			// collided
-			diff.normalize().multiplyScalar(ballSize);
-			pos.copy(ballPosition).add(diff);
+			diff.normalize().multiplyScalar( ballSize );
+			pos.copy( ballPosition ).add( diff );
+
 		}
+
 	}
 
 	// Floor Constains
-	for (particles = cloth.particles, i = 0, il = particles.length
-			; i < il; i ++) {
-		particle = particles[i];
+	for ( particles = cloth.particles, i = 0, il = particles.length
+			; i < il; i ++ ) {
+
+		particle = particles[ i ];
 		pos = particle.position;
-		if (pos.y < -250) {
-			pos.y = -250;
+		if ( pos.y < - 250 ) {
+
+			pos.y = - 250;
+
 		}
+
 	}
 
 	// Pin Constrains
-	for (i = 0, il = pins.length; i < il; i ++) {
-		var xy = pins[i];
-		var p = particles[xy];
-		p.position.copy(p.original);
-		p.previous.copy(p.original);
+	for ( i = 0, il = pins.length; i < il; i ++ ) {
+
+		var xy = pins[ i ];
+		var p = particles[ xy ];
+		p.position.copy( p.original );
+		p.previous.copy( p.original );
+
 	}
 
 

+ 96 - 92
examples/js/CurveExtras.js

@@ -17,32 +17,34 @@ THREE.Curves = {};
 
  THREE.Curves.GrannyKnot = THREE.Curve.create( function() {},
 
-	 function(t) {
+	 function( t ) {
+
 		t = 2 * Math.PI * t;
 
-		var x = -0.22 * Math.cos(t) - 1.28 * Math.sin(t) - 0.44 * Math.cos(3 * t) - 0.78 * Math.sin(3 * t);
-		var y = -0.1 * Math.cos(2 * t) - 0.27 * Math.sin(2 * t) + 0.38 * Math.cos(4 * t) + 0.46 * Math.sin(4 * t);
-		var z = 0.7 * Math.cos(3 * t) - 0.4 * Math.sin(3 * t);
-		return new THREE.Vector3(x, y, z).multiplyScalar(20);
+		var x = - 0.22 * Math.cos( t ) - 1.28 * Math.sin( t ) - 0.44 * Math.cos( 3 * t ) - 0.78 * Math.sin( 3 * t );
+		var y = - 0.1 * Math.cos( 2 * t ) - 0.27 * Math.sin( 2 * t ) + 0.38 * Math.cos( 4 * t ) + 0.46 * Math.sin( 4 * t );
+		var z = 0.7 * Math.cos( 3 * t ) - 0.4 * Math.sin( 3 * t );
+		return new THREE.Vector3( x, y, z ).multiplyScalar( 20 );
+
 	}
 );
 
 THREE.Curves.HeartCurve = THREE.Curve.create(
 
-function(s) {
+function( s ) {
 
-	this.scale = (s === undefined) ? 5 : s;
+	this.scale = ( s === undefined ) ? 5 : s;
 
 },
 
-function(t) {
+function( t ) {
 
 	t *= 2 * Math.PI;
 
-	var tx = 16 * Math.pow(Math.sin(t), 3);
-	var ty = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t), tz = 0;
+	var tx = 16 * Math.pow( Math.sin( t ), 3 );
+	var ty = 13 * Math.cos( t ) - 5 * Math.cos( 2 * t ) - 2 * Math.cos( 3 * t ) - Math.cos( 4 * t ), tz = 0;
 
-	return new THREE.Vector3(tx, ty, tz).multiplyScalar(this.scale);
+	return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
 
 }
 
@@ -53,20 +55,21 @@ function(t) {
 // Viviani's Curve
 THREE.Curves.VivianiCurve = THREE.Curve.create(
 
-	function(radius) {
+	function( radius ) {
 
 		this.radius = radius;
+
 	},
 
-	function(t) {
+	function( t ) {
 
 		t = t * 4 * Math.PI; // Normalized to 0..1
 		var a = this.radius / 2;
-		var tx = a * (1 + Math.cos(t)),
-			ty = a * Math.sin(t),
-			tz = 2 * a * Math.sin(t / 2);
+		var tx = a * ( 1 + Math.cos( t ) ),
+			ty = a * Math.sin( t ),
+			tz = 2 * a * Math.sin( t / 2 );
 
-		return new THREE.Vector3(tx, ty, tz);
+		return new THREE.Vector3( tx, ty, tz );
 
 	}
 
@@ -79,17 +82,17 @@ THREE.Curves.KnotCurve = THREE.Curve.create(
 
 	},
 
-	function(t) {
+	function( t ) {
 
 		t *= 2 * Math.PI;
 
 		var R = 10;
 		var s = 50;
-		var tx = s * Math.sin(t),
-			ty = Math.cos(t) * (R + s * Math.cos(t)),
-			tz = Math.sin(t) * (R + s * Math.cos(t));
+		var tx = s * Math.sin( t ),
+			ty = Math.cos( t ) * ( R + s * Math.cos( t ) ),
+			tz = Math.sin( t ) * ( R + s * Math.cos( t ) );
 
-		return new THREE.Vector3(tx, ty, tz);
+		return new THREE.Vector3( tx, ty, tz );
 
 	}
 
@@ -101,16 +104,16 @@ THREE.Curves.HelixCurve = THREE.Curve.create(
 
 	},
 
-	function(t) {
+	function( t ) {
 
 		var a = 30; // radius
 		var b = 150; //height
 		var t2 = 2 * Math.PI * t * b / 30;
-		var tx = Math.cos(t2) * a,
-			ty = Math.sin(t2) * a,
+		var tx = Math.cos( t2 ) * a,
+			ty = Math.sin( t2 ) * a,
 			tz = b * t;
 
-		return new THREE.Vector3(tx, ty, tz);
+		return new THREE.Vector3( tx, ty, tz );
 
 	}
 
@@ -118,20 +121,20 @@ THREE.Curves.HelixCurve = THREE.Curve.create(
 
 THREE.Curves.TrefoilKnot = THREE.Curve.create(
 
-	function(s) {
+	function( s ) {
 
-		this.scale = (s === undefined) ? 10 : s;
+		this.scale = ( s === undefined ) ? 10 : s;
 
 	},
 
-	function(t) {
+	function( t ) {
 
 		t *= Math.PI * 2;
-		var tx = (2 + Math.cos(3 * t)) * Math.cos(2 * t),
-			ty = (2 + Math.cos(3 * t)) * Math.sin(2 * t),
-			tz = Math.sin(3 * t);
+		var tx = ( 2 + Math.cos( 3 * t ) ) * Math.cos( 2 * t ),
+			ty = ( 2 + Math.cos( 3 * t ) ) * Math.sin( 2 * t ),
+			tz = Math.sin( 3 * t );
 
-		return new THREE.Vector3(tx, ty, tz).multiplyScalar(this.scale);
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
 
 	}
 
@@ -139,22 +142,22 @@ THREE.Curves.TrefoilKnot = THREE.Curve.create(
 
 THREE.Curves.TorusKnot = THREE.Curve.create(
 
-	function(s) {
+	function( s ) {
 
-		this.scale = (s === undefined) ? 10 : s;
+		this.scale = ( s === undefined ) ? 10 : s;
 
 	},
 
-	function(t) {
+	function( t ) {
 
 		var p = 3,
 			q = 4;
 		t *= Math.PI * 2;
-		var tx = (2 + Math.cos(q * t)) * Math.cos(p * t),
-			ty = (2 + Math.cos(q * t)) * Math.sin(p * t),
-			tz = Math.sin(q * t);
+		var tx = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t ),
+			ty = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t ),
+			tz = Math.sin( q * t );
 
-		return new THREE.Vector3(tx, ty, tz).multiplyScalar(this.scale);
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
 
 	}
 
@@ -163,22 +166,22 @@ THREE.Curves.TorusKnot = THREE.Curve.create(
 
 THREE.Curves.CinquefoilKnot = THREE.Curve.create(
 
-	function(s) {
+	function( s ) {
 
-		this.scale = (s === undefined) ? 10 : s;
+		this.scale = ( s === undefined ) ? 10 : s;
 
 	},
 
-	function(t) {
+	function( t ) {
 
 		var p = 2,
 			q = 5;
 		t *= Math.PI * 2;
-		var tx = (2 + Math.cos(q * t)) * Math.cos(p * t),
-			ty = (2 + Math.cos(q * t)) * Math.sin(p * t),
-			tz = Math.sin(q * t);
+		var tx = ( 2 + Math.cos( q * t ) ) * Math.cos( p * t ),
+			ty = ( 2 + Math.cos( q * t ) ) * Math.sin( p * t ),
+			tz = Math.sin( q * t );
 
-		return new THREE.Vector3(tx, ty, tz).multiplyScalar(this.scale);
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
 
 	}
 
@@ -187,20 +190,20 @@ THREE.Curves.CinquefoilKnot = THREE.Curve.create(
 
 THREE.Curves.TrefoilPolynomialKnot = THREE.Curve.create(
 
-	function(s) {
+	function( s ) {
 
-		this.scale = (s === undefined) ? 10 : s;
+		this.scale = ( s === undefined ) ? 10 : s;
 
 	},
 
-	function(t) {
+	function( t ) {
 
 		t = t * 4 - 2;
-		var tx = Math.pow(t, 3) - 3 * t,
-			ty = Math.pow(t, 4) - 4 * t * t,
-			tz = 1 / 5 * Math.pow(t, 5) - 2 * t;
+		var tx = Math.pow( t, 3 ) - 3 * t,
+			ty = Math.pow( t, 4 ) - 4 * t * t,
+			tz = 1 / 5 * Math.pow( t, 5 ) - 2 * t;
 
-		return new THREE.Vector3(tx, ty, tz).multiplyScalar(this.scale);
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
 
 	}
 
@@ -212,7 +215,7 @@ THREE.Curves.TrefoilPolynomialKnot = THREE.Curve.create(
 //     t * r + x;
 //   };
 // }
-var scaleTo = function(x, y, t) {
+var scaleTo = function( x, y, t ) {
 
 	var r = y - x;
 	return t * r + x;
@@ -221,20 +224,20 @@ var scaleTo = function(x, y, t) {
 
 THREE.Curves.FigureEightPolynomialKnot = THREE.Curve.create(
 
-	function(s) {
+	function( s ) {
 
-		this.scale = (s === undefined) ? 1 : s;
+		this.scale = ( s === undefined ) ? 1 : s;
 
 	},
 
-	function(t) {
+	function( t ) {
 
-		t = scaleTo(-4, 4, t);
-		var tx = 2 / 5 * t * (t * t - 7) * (t * t - 10),
-			ty = Math.pow(t, 4) - 13 * t * t,
-			tz = 1 / 10 * t * (t * t - 4) * (t * t - 9) * (t * t - 12);
+		t = scaleTo( - 4, 4, t );
+		var tx = 2 / 5 * t * ( t * t - 7 ) * ( t * t - 10 ),
+			ty = Math.pow( t, 4 ) - 13 * t * t,
+			tz = 1 / 10 * t * ( t * t - 4 ) * ( t * t - 9 ) * ( t * t - 12 );
 
-		return new THREE.Vector3(tx, ty, tz).multiplyScalar(this.scale);
+		return new THREE.Vector3( tx, ty, tz ).multiplyScalar( this.scale );
 
 	}
 
@@ -242,21 +245,21 @@ THREE.Curves.FigureEightPolynomialKnot = THREE.Curve.create(
 
 THREE.Curves.DecoratedTorusKnot4a = THREE.Curve.create(
 
-	function(s) {
+	function( s ) {
 
-		this.scale = (s === undefined) ? 40 : s;
+		this.scale = ( s === undefined ) ? 40 : s;
 
 	},
 
-	function(t) {
+	function( t ) {
 
 		t *= Math.PI * 2;
 		var
-		x = Math.cos(2 * t) * (1 + 0.6 * (Math.cos(5 * t) + 0.75 * Math.cos(10 * t))),
-			y = Math.sin(2 * t) * (1 + 0.6 * (Math.cos(5 * t) + 0.75 * Math.cos(10 * t))),
-			z = 0.35 * Math.sin(5 * t);
+		x = Math.cos( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) ),
+			y = Math.sin( 2 * t ) * ( 1 + 0.6 * ( Math.cos( 5 * t ) + 0.75 * Math.cos( 10 * t ) ) ),
+			z = 0.35 * Math.sin( 5 * t );
 
-		return new THREE.Vector3(x, y, z).multiplyScalar(this.scale);
+		return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
 
 	}
 
@@ -265,19 +268,20 @@ THREE.Curves.DecoratedTorusKnot4a = THREE.Curve.create(
 
 THREE.Curves.DecoratedTorusKnot4b = THREE.Curve.create(
 
-	function(s) {
+	function( s ) {
 
-		this.scale = (s === undefined) ? 40 : s;
+		this.scale = ( s === undefined ) ? 40 : s;
 
 	},
 
-	function(t) {
+	function( t ) {
+
 		var fi = t * Math.PI * 2;
-		var x = Math.cos(2 * fi) * (1 + 0.45 * Math.cos(3 * fi) + 0.4 * Math.cos(9 * fi)),
-			y = Math.sin(2 * fi) * (1 + 0.45 * Math.cos(3 * fi) + 0.4 * Math.cos(9 * fi)),
-			z = 0.2 * Math.sin(9 * fi);
+		var x = Math.cos( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) ),
+			y = Math.sin( 2 * fi ) * ( 1 + 0.45 * Math.cos( 3 * fi ) + 0.4 * Math.cos( 9 * fi ) ),
+			z = 0.2 * Math.sin( 9 * fi );
 
-		return new THREE.Vector3(x, y, z).multiplyScalar(this.scale);
+		return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
 
 	}
 
@@ -286,20 +290,20 @@ THREE.Curves.DecoratedTorusKnot4b = THREE.Curve.create(
 
 THREE.Curves.DecoratedTorusKnot5a = THREE.Curve.create(
 
-	function(s) {
+	function( s ) {
 
-		this.scale = (s === undefined) ? 40 : s;
+		this.scale = ( s === undefined ) ? 40 : s;
 
 	},
 
-	function(t) {
+	function( t ) {
 
 		var fi = t * Math.PI * 2;
-		var x = Math.cos(3 * fi) * (1 + 0.3 * Math.cos(5 * fi) + 0.5 * Math.cos(10 * fi)),
-			y = Math.sin(3 * fi) * (1 + 0.3 * Math.cos(5 * fi) + 0.5 * Math.cos(10 * fi)),
-			z = 0.2 * Math.sin(20 * fi);
+		var x = Math.cos( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) ),
+			y = Math.sin( 3 * fi ) * ( 1 + 0.3 * Math.cos( 5 * fi ) + 0.5 * Math.cos( 10 * fi ) ),
+			z = 0.2 * Math.sin( 20 * fi );
 
-		return new THREE.Vector3(x, y, z).multiplyScalar(this.scale);
+		return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
 
 	}
 
@@ -307,21 +311,21 @@ THREE.Curves.DecoratedTorusKnot5a = THREE.Curve.create(
 
 THREE.Curves.DecoratedTorusKnot5c = THREE.Curve.create(
 
-	function(s) {
+	function( s ) {
 
-		this.scale = (s === undefined) ? 40 : s;
+		this.scale = ( s === undefined ) ? 40 : s;
 
 	},
 
-	function(t) {
+	function( t ) {
 
 		var fi = t * Math.PI * 2;
-		var x = Math.cos(4 * fi) * (1 + 0.5 * (Math.cos(5 * fi) + 0.4 * Math.cos(20 * fi))),
-			y = Math.sin(4 * fi) * (1 + 0.5 * (Math.cos(5 * fi) + 0.4 * Math.cos(20 * fi))),
-			z = 0.35 * Math.sin(15 * fi);
+		var x = Math.cos( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) ),
+			y = Math.sin( 4 * fi ) * ( 1 + 0.5 * ( Math.cos( 5 * fi ) + 0.4 * Math.cos( 20 * fi ) ) ),
+			z = 0.35 * Math.sin( 15 * fi );
 
-		return new THREE.Vector3(x, y, z).multiplyScalar(this.scale);
+		return new THREE.Vector3( x, y, z ).multiplyScalar( this.scale );
 
 	}
 
-);
+);

+ 13 - 1
examples/js/Detector.js

@@ -6,7 +6,19 @@
 var Detector = {
 
 	canvas: !! window.CanvasRenderingContext2D,
-	webgl: ( function () { try { var canvas = document.createElement( 'canvas' ); return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) ); } catch ( e ) { return false; } } )(),
+	webgl: ( function () {
+
+		try {
+
+			var canvas = document.createElement( 'canvas' ); return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) );
+
+		} catch ( e ) {
+
+			return false;
+
+		}
+
+	} )(),
 	workers: !! window.Worker,
 	fileapi: window.File && window.FileReader && window.FileList && window.Blob,
 

+ 505 - 0
examples/js/GPUParticleSystem.js

@@ -0,0 +1,505 @@
+/*
+ * GPU Particle System
+ * @author flimshaw - Charlie Hoey - http://charliehoey.com
+ *
+ * A simple to use, general purpose GPU system.  Particles are spawn-and-forget with
+ * several options available, and do not require monitoring or cleanup after spawning.
+ * Because the paths of all particles are completely deterministic once spawned, the scale
+ * and direction of time is also variable.
+ *
+ * Currently uses a static wrapping perlin noise texture for turbulence, and a small png texture for
+ * particles, but adding support for a particle texture atlas or changing to a different type of turbulence
+ * would be a fairly light day's work.
+ *
+ * Shader and javascript packing code derrived from several Stack Overflow examples.
+ *
+ */
+
+THREE.GPUParticleSystem = function(options) {
+
+  var self = this;
+  var options = options || {};
+
+  // parse options and use defaults
+  self.PARTICLE_COUNT = options.maxParticles || 1000000;
+  self.PARTICLE_CONTAINERS = options.containerCount || 1;
+  self.PARTICLES_PER_CONTAINER = Math.ceil(self.PARTICLE_COUNT / self.PARTICLE_CONTAINERS);
+  self.PARTICLE_CURSOR = 0;
+  self.time = 0;
+
+
+  // Custom vertex and fragement shader
+  var GPUParticleShader = {
+
+    vertexShader: [
+
+      'precision highp float;',
+      'const vec4 bitSh = vec4(256. * 256. * 256., 256. * 256., 256., 1.);',
+      'const vec4 bitMsk = vec4(0.,vec3(1./256.0));',
+      'const vec4 bitShifts = vec4(1.) / bitSh;',
+
+      '#define FLOAT_MAX  1.70141184e38',
+      '#define FLOAT_MIN  1.17549435e-38',
+
+      'lowp vec4 encode_float(highp float v) {',
+      'highp float av = abs(v);',
+
+      '//Handle special cases',
+      'if(av < FLOAT_MIN) {',
+      'return vec4(0.0, 0.0, 0.0, 0.0);',
+      '} else if(v > FLOAT_MAX) {',
+      'return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;',
+      '} else if(v < -FLOAT_MAX) {',
+      'return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;',
+      '}',
+
+      'highp vec4 c = vec4(0,0,0,0);',
+
+      '//Compute exponent and mantissa',
+      'highp float e = floor(log2(av));',
+      'highp float m = av * pow(2.0, -e) - 1.0;',
+
+      //Unpack mantissa
+      'c[1] = floor(128.0 * m);',
+      'm -= c[1] / 128.0;',
+      'c[2] = floor(32768.0 * m);',
+      'm -= c[2] / 32768.0;',
+      'c[3] = floor(8388608.0 * m);',
+
+      '//Unpack exponent',
+      'highp float ebias = e + 127.0;',
+      'c[0] = floor(ebias / 2.0);',
+      'ebias -= c[0] * 2.0;',
+      'c[1] += floor(ebias) * 128.0;',
+
+      '//Unpack sign bit',
+      'c[0] += 128.0 * step(0.0, -v);',
+
+      '//Scale back to range',
+      'return c / 255.0;',
+      '}',
+
+      'vec4 pack(const in float depth)',
+      '{',
+      'const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);',
+      'const vec4 bit_mask  = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);',
+      'vec4 res = fract(depth * bit_shift);',
+      'res -= res.xxyz * bit_mask;',
+      'return res;',
+      '}',
+
+      'float unpack(const in vec4 rgba_depth)',
+      '{',
+      'const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);',
+      'float depth = dot(rgba_depth, bit_shift);',
+      'return depth;',
+      '}',
+
+      'uniform float uTime;',
+      'uniform float uScale;',
+      'uniform sampler2D tNoise;',
+
+      'attribute vec4 particlePositionsStartTime;',
+      'attribute vec4 particleVelColSizeLife;',
+
+      'varying vec4 vColor;',
+      'varying float lifeLeft;',
+
+      'void main() {',
+
+      '// unpack things from our attributes',
+      'vColor = encode_float( particleVelColSizeLife.y );',
+
+      '// convert our velocity back into a value we can use',
+      'vec4 velTurb = encode_float( particleVelColSizeLife.x );',
+      'vec3 velocity = vec3( velTurb.xyz );',
+      'float turbulence = velTurb.w;',
+
+      'vec3 newPosition;',
+
+      'float timeElapsed = uTime - particlePositionsStartTime.a;',
+
+      'lifeLeft = 1. - (timeElapsed / particleVelColSizeLife.w);',
+
+      'gl_PointSize = ( uScale * particleVelColSizeLife.z ) * lifeLeft;',
+
+      'velocity.x = ( velocity.x - .5 ) * 3.;',
+      'velocity.y = ( velocity.y - .5 ) * 3.;',
+      'velocity.z = ( velocity.z - .5 ) * 3.;',
+
+      'newPosition = particlePositionsStartTime.xyz + ( velocity * 10. ) * ( uTime - particlePositionsStartTime.a );',
+
+      'vec3 noise = texture2D( tNoise, vec2( newPosition.x * .015 + (uTime * .05), newPosition.y * .02 + (uTime * .015) )).rgb;',
+      'vec3 noiseVel = ( noise.rgb - .5 ) * 30.;',
+
+      'newPosition = mix(newPosition, newPosition + vec3(noiseVel * ( turbulence * 5. ) ), (timeElapsed / particleVelColSizeLife.a) );',
+
+      'if( velocity.y > 0. && velocity.y < .05 ) {',
+      'lifeLeft = 0.;',
+      '}',
+
+      'if( velocity.x < -1.45 ) {',
+      'lifeLeft = 0.;',
+      '}',
+
+      'if( timeElapsed > 0. ) {',
+      'gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );',
+      '} else {',
+      'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
+      'lifeLeft = 0.;',
+      'gl_PointSize = 0.;',
+      '}',
+      '}'
+
+    ].join("\n"),
+
+    fragmentShader: [
+
+      'float scaleLinear(float value, vec2 valueDomain) {',
+      'return (value - valueDomain.x) / (valueDomain.y - valueDomain.x);',
+      '}',
+
+      'float scaleLinear(float value, vec2 valueDomain, vec2 valueRange) {',
+      'return mix(valueRange.x, valueRange.y, scaleLinear(value, valueDomain));',
+      '}',
+
+      'varying vec4 vColor;',
+      'varying float lifeLeft;',
+
+      'uniform sampler2D tSprite;',
+
+      'void main() {',
+
+      'float alpha = 0.;',
+
+      'if( lifeLeft > .995 ) {',
+      'alpha = scaleLinear( lifeLeft, vec2(1., .995), vec2(0., 1.));//mix( 0., 1., ( lifeLeft - .95 ) * 100. ) * .75;',
+      '} else {',
+      'alpha = lifeLeft * .75;',
+      '}',
+
+      'vec4 tex = texture2D( tSprite, gl_PointCoord );',
+
+      'gl_FragColor = vec4( vColor.rgb * tex.a, alpha * tex.a );',
+      '}'
+
+    ].join("\n")
+
+  };
+
+  // preload a million random numbers
+  self.rand = [];
+
+  for (var i = 1e5; i > 0; i--) {
+    self.rand.push(Math.random() - .5);
+  }
+
+  self.random = function() {
+    return ++i >= self.rand.length ? self.rand[i = 1] : self.rand[i];
+  }
+
+  self.particleNoiseTex = THREE.ImageUtils.loadTexture("textures/perlin-512.png");
+  self.particleNoiseTex.wrapS = self.particleNoiseTex.wrapT = THREE.RepeatWrapping;
+
+  self.particleSpriteTex = THREE.ImageUtils.loadTexture("textures/particle2.png");
+  self.particleSpriteTex.wrapS = self.particleSpriteTex.wrapT = THREE.RepeatWrapping;
+
+  self.particleShaderMat = new THREE.ShaderMaterial({
+    transparent: true,
+    depthWrite: false,
+    uniforms: {
+      "uTime": {
+        type: "f",
+        value: 0.0
+      },
+      "uScale": {
+        type: "f",
+        value: 1.0
+      },
+      "tNoise": {
+        type: "t",
+        value: self.particleNoiseTex
+      },
+      "tSprite": {
+        type: "t",
+        value: self.particleSpriteTex
+      }
+    },
+    blending: THREE.AdditiveBlending,
+    vertexShader: GPUParticleShader.vertexShader,
+    fragmentShader: GPUParticleShader.fragmentShader
+  });
+
+  // define defaults for all values
+  self.particleShaderMat.defaultAttributeValues.particlePositionsStartTime = [0, 0, 0, 0];
+  self.particleShaderMat.defaultAttributeValues.particleVelColSizeLife = [0, 0, 0, 0];
+
+  self.particleContainers = [];
+
+
+  // extend Object3D
+  THREE.Object3D.apply(this, arguments);
+
+  this.init = function() {
+
+    for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
+
+      var c = new THREE.GPUParticleContainer(self.PARTICLES_PER_CONTAINER, self);
+      self.particleContainers.push(c);
+      self.add(c);
+
+    }
+
+  }
+
+  this.spawnParticle = function(options) {
+
+    self.PARTICLE_CURSOR++;
+    if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
+      self.PARTICLE_CURSOR = 1;
+    }
+
+    var currentContainer = self.particleContainers[Math.floor(self.PARTICLE_CURSOR / self.PARTICLES_PER_CONTAINER)];
+
+    currentContainer.spawnParticle(options);
+
+  }
+
+  this.update = function(time) {
+    for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
+
+      self.particleContainers[i].update(time);
+
+    }
+  };
+
+  this.init();
+
+}
+
+THREE.GPUParticleSystem.prototype = Object.create(THREE.Object3D.prototype);
+THREE.GPUParticleSystem.prototype.constructor = THREE.GPUParticleSystem;
+
+
+// Subclass for particle containers, allows for very large arrays to be spread out
+THREE.GPUParticleContainer = function(maxParticles, particleSystem) {
+
+  var self = this;
+  self.PARTICLE_COUNT = maxParticles || 100000;
+  self.PARTICLE_CURSOR = 0;
+  self.time = 0;
+  self.DPR = window.devicePixelRatio;
+  self.GPUParticleSystem = particleSystem;
+
+  var particlesPerArray = Math.floor(self.PARTICLE_COUNT / self.MAX_ATTRIBUTES);
+
+  // extend Object3D
+  THREE.Object3D.apply(this, arguments);
+
+  // construct a couple small arrays used for packing variables into floats etc
+  var UINT8_VIEW = new Uint8Array(4)
+  var FLOAT_VIEW = new Float32Array(UINT8_VIEW.buffer)
+
+  function decodeFloat(x, y, z, w) {
+    UINT8_VIEW[0] = Math.floor(w)
+    UINT8_VIEW[1] = Math.floor(z)
+    UINT8_VIEW[2] = Math.floor(y)
+    UINT8_VIEW[3] = Math.floor(x)
+    return FLOAT_VIEW[0]
+  }
+
+  function componentToHex(c) {
+    var hex = c.toString(16);
+    return hex.length == 1 ? "0" + hex : hex;
+  }
+
+  function rgbToHex(r, g, b) {
+    return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
+  }
+
+  function hexToRgb(hex) {
+    var r = hex >> 16;
+    var g = (hex & 0x00FF00) >> 8;
+    var b = hex & 0x0000FF;
+
+    if (r > 0) r--;
+    if (g > 0) g--;
+    if (b > 0) b--;
+
+    return [r, g, b];
+  };
+
+  self.particles = [];
+  self.deadParticles = [];
+  self.particlesAvailableSlot = [];
+
+  // create a container for particles
+  self.particleUpdate = false;
+
+  // Shader Based Particle System
+  self.particleShaderGeo = new THREE.BufferGeometry();
+
+  // new hyper compressed attributes
+  self.particleVertices = new Float32Array(self.PARTICLE_COUNT * 3); // position
+  self.particlePositionsStartTime = new Float32Array(self.PARTICLE_COUNT * 4); // position
+  self.particleVelColSizeLife = new Float32Array(self.PARTICLE_COUNT * 4);
+
+  for (var i = 0; i < self.PARTICLE_COUNT; i++) {
+    self.particlePositionsStartTime[i * 4 + 0] = 100; //x
+    self.particlePositionsStartTime[i * 4 + 1] = 0; //y
+    self.particlePositionsStartTime[i * 4 + 2] = 0.0; //z
+    self.particlePositionsStartTime[i * 4 + 3] = 0.0; //startTime
+
+    self.particleVertices[i * 3 + 0] = 0; //x
+    self.particleVertices[i * 3 + 1] = 0; //y
+    self.particleVertices[i * 3 + 2] = 0.0; //z
+
+    self.particleVelColSizeLife[i * 4 + 0] = decodeFloat(128, 128, 0, 0); //vel
+    self.particleVelColSizeLife[i * 4 + 1] = decodeFloat(0, 254, 0, 254); //color
+    self.particleVelColSizeLife[i * 4 + 2] = 1.0; //size
+    self.particleVelColSizeLife[i * 4 + 3] = 0.0; //lifespan
+  }
+
+  self.particleShaderGeo.addAttribute('position', new THREE.BufferAttribute(self.particleVertices, 3));
+  self.particleShaderGeo.addAttribute('particlePositionsStartTime', new THREE.BufferAttribute(self.particlePositionsStartTime, 4).setDynamic(true));
+  self.particleShaderGeo.addAttribute('particleVelColSizeLife', new THREE.BufferAttribute(self.particleVelColSizeLife, 4).setDynamic(true));
+
+  self.posStart = self.particleShaderGeo.getAttribute('particlePositionsStartTime')
+  self.velCol = self.particleShaderGeo.getAttribute('particleVelColSizeLife');
+
+  self.particleShaderMat = self.GPUParticleSystem.particleShaderMat;
+
+  this.init = function() {
+    self.particleSystem = new THREE.PointCloud(self.particleShaderGeo, self.particleShaderMat);
+    self.particleSystem.frustumCulled = false;
+    this.add(self.particleSystem);
+  };
+
+  var options = {},
+    position = new THREE.Vector3(),
+    velocity = new THREE.Vector3(),
+    positionRandomness = 0.,
+    velocityRandomness = 0.,
+    color = 0xffffff,
+    colorRandomness = 0.,
+    turbulence = 0.,
+    lifetime = 0.,
+    size = 0.,
+    sizeRandomness = 0.,
+    i;
+
+  var maxVel = 2;
+  var maxSource = 250;
+  this.offset = 0;
+  this.count = 0;
+
+  this.spawnParticle = function(options) {
+
+    options = options || {};
+
+    // setup reasonable default values for all arguments
+    position = options.position !== undefined ? position.copy(options.position) : position.set(0., 0., 0.);
+    velocity = options.velocity !== undefined ? velocity.copy(options.velocity) : velocity.set(0., 0., 0.);
+    positionRandomness = options.positionRandomness !== undefined ? options.positionRandomness : 0.0;
+    velocityRandomness = options.velocityRandomness !== undefined ? options.velocityRandomness : 0.0;
+    color = options.color !== undefined ? options.color : 0xffffff;
+    colorRandomness = options.colorRandomness !== undefined ? options.colorRandomness : 1.0;
+    turbulence = options.turbulence !== undefined ? options.turbulence : 1.0;
+    lifetime = options.lifetime !== undefined ? options.lifetime : 5.0;
+    size = options.size !== undefined ? options.size : 10;
+    sizeRandomness = options.sizeRandomness !== undefined ? options.sizeRandomness : 0.0,
+      smoothPosition = options.smoothPosition !== undefined ? options.smoothPosition : false;
+
+    if (self.DPR !== undefined) size *= self.DPR;
+
+    i = self.PARTICLE_CURSOR;
+
+    self.posStart.array[i * 4 + 0] = position.x + ((particleSystem.random()) * positionRandomness); // - ( velocity.x * particleSystem.random() ); //x
+    self.posStart.array[i * 4 + 1] = position.y + ((particleSystem.random()) * positionRandomness); // - ( velocity.y * particleSystem.random() ); //y
+    self.posStart.array[i * 4 + 2] = position.z + ((particleSystem.random()) * positionRandomness); // - ( velocity.z * particleSystem.random() ); //z
+    self.posStart.array[i * 4 + 3] = self.time + (particleSystem.random() * 2e-2); //startTime
+
+    if (smoothPosition === true) {
+      self.posStart.array[i * 4 + 0] += -(velocity.x * particleSystem.random()); //x
+      self.posStart.array[i * 4 + 1] += -(velocity.y * particleSystem.random()); //y
+      self.posStart.array[i * 4 + 2] += -(velocity.z * particleSystem.random()); //z
+    }
+
+    var velX = velocity.x + (particleSystem.random()) * velocityRandomness;
+    var velY = velocity.y + (particleSystem.random()) * velocityRandomness;
+    var velZ = velocity.z + (particleSystem.random()) * velocityRandomness;
+
+    // convert turbulence rating to something we can pack into a vec4
+    var turbulence = Math.floor(turbulence * 254);
+
+    // clamp our value to between 0. and 1.
+    velX = Math.floor(maxSource * ((velX - -maxVel) / (maxVel - -maxVel)));
+    velY = Math.floor(maxSource * ((velY - -maxVel) / (maxVel - -maxVel)));
+    velZ = Math.floor(maxSource * ((velZ - -maxVel) / (maxVel - -maxVel)));
+
+    self.velCol.array[i * 4 + 0] = decodeFloat(velX, velY, velZ, turbulence); //vel
+
+    var rgb = hexToRgb(color);
+
+    for (var c = 0; c < rgb.length; c++) {
+      rgb[c] = Math.floor(rgb[c] + ((particleSystem.random()) * colorRandomness) * 254);
+      if (rgb[c] > 254) rgb[c] = 254;
+      if (rgb[c] < 0) rgb[c] = 0;
+    }
+
+    self.velCol.array[i * 4 + 1] = decodeFloat(rgb[0], rgb[1], rgb[2], 254); //color
+    self.velCol.array[i * 4 + 2] = size + (particleSystem.random()) * sizeRandomness; //size
+    self.velCol.array[i * 4 + 3] = lifetime; //lifespan
+
+    if (this.offset == 0) {
+      this.offset = self.PARTICLE_CURSOR;
+    }
+
+    self.count++;
+
+    self.PARTICLE_CURSOR++;
+
+    if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
+      self.PARTICLE_CURSOR = 0;
+    }
+
+    self.particleUpdate = true;
+
+  }
+
+  this.update = function(time) {
+
+    self.time = time;
+    self.particleShaderMat.uniforms['uTime'].value = time;
+
+    this.geometryUpdate();
+
+  };
+
+  this.geometryUpdate = function() {
+    if (self.particleUpdate == true) {
+      self.particleUpdate = false;
+
+      // if we can get away with a partial buffer update, do so
+      if (self.offset + self.count < self.PARTICLE_COUNT) {
+        self.posStart.updateRange.offset = self.velCol.updateRange.offset = self.offset * 4;
+        self.posStart.updateRange.count = self.velCol.updateRange.count = self.count * 4;
+      } else {
+        self.posStart.updateRange.offset = 0;
+        self.posStart.updateRange.count = self.velCol.updateRange.count = (self.PARTICLE_COUNT * 4);
+      }
+
+      self.posStart.needsUpdate = true;
+      self.velCol.needsUpdate = true;
+
+      self.offset = 0;
+      self.count = 0;
+    }
+  }
+
+  this.init();
+
+}
+
+THREE.GPUParticleContainer.prototype = Object.create(THREE.Object3D.prototype);
+THREE.GPUParticleContainer.prototype.constructor = THREE.GPUParticleContainer;

+ 64 - 64
src/extras/core/Gyroscope.js → examples/js/Gyroscope.js

@@ -1,65 +1,65 @@
-/**
- * @author alteredq / http://alteredqualia.com/
- */
-
-THREE.Gyroscope = function () {
-
-	THREE.Object3D.call( this );
-
-};
-
-THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.Gyroscope = function () {
+
+	THREE.Object3D.call( this );
+
+};
+
+THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
 THREE.Gyroscope.prototype.constructor = THREE.Gyroscope;
-
-THREE.Gyroscope.prototype.updateMatrixWorld = ( function () {
-
-	var translationObject = new THREE.Vector3();
-	var quaternionObject = new THREE.Quaternion();
-	var scaleObject = new THREE.Vector3();
-
-	var translationWorld = new THREE.Vector3();
-	var quaternionWorld = new THREE.Quaternion();
-	var scaleWorld = new THREE.Vector3();
-
-	return function ( force ) {
-
-		this.matrixAutoUpdate && this.updateMatrix();
-
-		// update matrixWorld
-
-		if ( this.matrixWorldNeedsUpdate || force ) {
-
-			if ( this.parent ) {
-
-				this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
-
-				this.matrixWorld.decompose( translationWorld, quaternionWorld, scaleWorld );
-				this.matrix.decompose( translationObject, quaternionObject, scaleObject );
-
-				this.matrixWorld.compose( translationWorld, quaternionObject, scaleWorld );
-
-
-			} else {
-
-				this.matrixWorld.copy( this.matrix );
-
-			}
-
-
-			this.matrixWorldNeedsUpdate = false;
-
-			force = true;
-
-		}
-
-		// update children
-
-		for ( var i = 0, l = this.children.length; i < l; i ++ ) {
-
-			this.children[ i ].updateMatrixWorld( force );
-
-		}
-
-	};
-	
-}() );
+
+THREE.Gyroscope.prototype.updateMatrixWorld = ( function () {
+
+	var translationObject = new THREE.Vector3();
+	var quaternionObject = new THREE.Quaternion();
+	var scaleObject = new THREE.Vector3();
+
+	var translationWorld = new THREE.Vector3();
+	var quaternionWorld = new THREE.Quaternion();
+	var scaleWorld = new THREE.Vector3();
+
+	return function updateMatrixWorld( force ) {
+
+		this.matrixAutoUpdate && this.updateMatrix();
+
+		// update matrixWorld
+
+		if ( this.matrixWorldNeedsUpdate || force ) {
+
+			if ( this.parent !== null ) {
+
+				this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
+
+				this.matrixWorld.decompose( translationWorld, quaternionWorld, scaleWorld );
+				this.matrix.decompose( translationObject, quaternionObject, scaleObject );
+
+				this.matrixWorld.compose( translationWorld, quaternionObject, scaleWorld );
+
+
+			} else {
+
+				this.matrixWorld.copy( this.matrix );
+
+			}
+
+
+			this.matrixWorldNeedsUpdate = false;
+
+			force = true;
+
+		}
+
+		// update children
+
+		for ( var i = 0, l = this.children.length; i < l; i ++ ) {
+
+			this.children[ i ].updateMatrixWorld( force );
+
+		}
+
+	};
+
+}() );

+ 4 - 8
examples/js/MD2Character.js

@@ -39,7 +39,7 @@ THREE.MD2Character = function () {
 
 		// BODY
 
-		var loader = new THREE.JSONLoader();
+		var loader = new THREE.MD2Loader();
 
 		loader.load( config.baseUrl + config.body, function( geo ) {
 
@@ -199,17 +199,13 @@ THREE.MD2Character = function () {
 
 	function createPart( geometry, skinMap ) {
 
-		geometry.computeMorphNormals();
-
-		var whiteMap = THREE.ImageUtils.generateDataTexture( 1, 1, new THREE.Color( 0xffffff ) );
-		var materialWireframe = new THREE.MeshPhongMaterial( { color: 0xffaa00, specular: 0x111111, shininess: 50, wireframe: true, shading: THREE.SmoothShading, map: whiteMap, morphTargets: true, morphNormals: true, metal: false } );
-
-		var materialTexture = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shininess: 50, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true, metal: false } );
+		var materialWireframe = new THREE.MeshLambertMaterial( { color: 0xffaa00, wireframe: true, shading: THREE.SmoothShading, morphTargets: true, morphNormals: true } );
+		var materialTexture = new THREE.MeshLambertMaterial( { color: 0xffffff, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true } );
 
 		//
 
 		var mesh = new THREE.MorphAnimMesh( geometry, materialTexture );
-		mesh.rotation.y = -Math.PI / 2;
+		mesh.rotation.y = - Math.PI / 2;
 
 		mesh.castShadow = true;
 		mesh.receiveShadow = true;

+ 13 - 13
examples/js/MD2CharacterComplex.js

@@ -16,7 +16,7 @@ THREE.MD2CharacterComplex = function () {
 	// movement model parameters
 
 	this.maxSpeed = 275;
-	this.maxReverseSpeed = -275;
+	this.maxReverseSpeed = - 275;
 
 	this.frontAcceleration = 600;
 	this.backAcceleration = 600;
@@ -152,7 +152,7 @@ THREE.MD2CharacterComplex = function () {
 
 		// BODY
 
-		var loader = new THREE.JSONLoader();
+		var loader = new THREE.MD2Loader();
 
 		loader.load( config.baseUrl + config.body, function( geo ) {
 
@@ -261,7 +261,7 @@ THREE.MD2CharacterComplex = function () {
 
 	this.setAnimation = function ( animationName ) {
 
-		if ( animationName === this.activeAnimation || !animationName ) return;
+		if ( animationName === this.activeAnimation || ! animationName ) return;
 
 		if ( this.meshBody ) {
 
@@ -388,7 +388,7 @@ THREE.MD2CharacterComplex = function () {
 		}
 
 
-		if ( Math.abs( this.speed ) < 0.2 * this.maxSpeed && !( controls.moveLeft || controls.moveRight || controls.moveForward || controls.moveBackward ) ) {
+		if ( Math.abs( this.speed ) < 0.2 * this.maxSpeed && ! ( controls.moveLeft || controls.moveRight || controls.moveForward || controls.moveBackward ) ) {
 
 			if ( this.activeAnimation !== idleAnimation ) {
 
@@ -447,7 +447,7 @@ THREE.MD2CharacterComplex = function () {
 		if ( controls.crouch ) 	this.maxSpeed = this.crouchSpeed;
 		else this.maxSpeed = this.walkSpeed;
 
-		this.maxReverseSpeed = -this.maxSpeed;
+		this.maxReverseSpeed = - this.maxSpeed;
 
 		if ( controls.moveForward )  this.speed = THREE.Math.clamp( this.speed + delta * this.frontAcceleration, this.maxReverseSpeed, this.maxSpeed );
 		if ( controls.moveBackward ) this.speed = THREE.Math.clamp( this.speed - delta * this.backAcceleration, this.maxReverseSpeed, this.maxSpeed );
@@ -522,17 +522,13 @@ THREE.MD2CharacterComplex = function () {
 
 	function createPart( geometry, skinMap ) {
 
-		geometry.computeMorphNormals();
-
-		var whiteMap = THREE.ImageUtils.generateDataTexture( 1, 1, new THREE.Color( 0xffffff ) );
-		var materialWireframe = new THREE.MeshPhongMaterial( { color: 0xffaa00, specular: 0x111111, shininess: 50, wireframe: true, shading: THREE.SmoothShading, map: whiteMap, morphTargets: true, morphNormals: true, metal: true } );
-
-		var materialTexture = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shininess: 50, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true, metal: true } );
+		var materialWireframe = new THREE.MeshLambertMaterial( { color: 0xffaa00, wireframe: true, shading: THREE.SmoothShading, morphTargets: true, morphNormals: true } );
+		var materialTexture = new THREE.MeshLambertMaterial( { color: 0xffffff, wireframe: false, shading: THREE.SmoothShading, map: skinMap, morphTargets: true, morphNormals: true } );
 
 		//
 
 		var mesh = new THREE.MorphBlendMesh( geometry, materialTexture );
-		mesh.rotation.y = -Math.PI / 2;
+		mesh.rotation.y = - Math.PI / 2;
 
 		//
 
@@ -554,6 +550,10 @@ THREE.MD2CharacterComplex = function () {
 
 	}
 
-	function exponentialEaseOut( k ) { return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1; }
+	function exponentialEaseOut( k ) {
+
+		return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
+
+	}
 
 };

+ 282 - 278
examples/js/MarchingCubes.js

@@ -47,8 +47,6 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 		this.vlist = new Float32Array( 12 * 3 );
 		this.nlist = new Float32Array( 12 * 3 );
 
-		this.firstDraw = true;
-
 		// immediate render mode simulator
 
 		this.maxCount = 4096; // TODO: find the fastest size for this buffer
@@ -80,7 +78,11 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 	// Polygonization
 	///////////////////////
 
-	this.lerp = function( a, b, t ) { return a + ( b - a ) * t; };
+	this.lerp = function( a, b, t ) {
+
+		return a + ( b - a ) * t;
+
+	};
 
 	this.VIntX = function( q, pout, nout, offset, isol, x, y, z, valp1, valp2 ) {
 
@@ -137,7 +139,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 		if ( this.normal_cache[ q3 ] === 0.0 ) {
 
-			this.normal_cache[ q3     ] = this.field[ q - 1  ] 	    - this.field[ q + 1 ];
+			this.normal_cache[ q3 ] = this.field[ q - 1 ] 	    - this.field[ q + 1 ];
 			this.normal_cache[ q3 + 1 ] = this.field[ q - this.yd ] - this.field[ q + this.yd ];
 			this.normal_cache[ q3 + 2 ] = this.field[ q - this.zd ] - this.field[ q + this.zd ];
 
@@ -296,7 +298,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 		// here is where triangles are created
 
-		while ( THREE.triTable[ cubeindex + i ] != -1 ) {
+		while ( THREE.triTable[ cubeindex + i ] != - 1 ) {
 
 			o1 = cubeindex + i;
 			o2 = o1 + 1;
@@ -426,12 +428,14 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 	this.end = function( renderCallback ) {
 
-		if ( this.count === 0 )
-			return;
+		if ( this.count === 0 ) return;
+
+		for ( var i = this.count * 3; i < this.positionArray.length; i ++ ) {
 
-		for ( var i = this.count * 3; i < this.positionArray.length; i ++ )
 			this.positionArray[ i ] = 0.0;
 
+		}
+
 		this.hasPositions = true;
 		this.hasNormals = true;
 
@@ -653,22 +657,22 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 		// Triangulate. Yeah, this is slow.
 
-		var q, x, y, z, fx, fy, fz, y_offset, z_offset, smin2 = this.size - 2;
+		var smin2 = this.size - 2;
 
-		for ( z = 1; z < smin2; z ++ ) {
+		for ( var z = 1; z < smin2; z ++ ) {
 
-			z_offset = this.size2 * z;
-			fz = ( z - this.halfsize ) / this.halfsize; //+ 1
+			var z_offset = this.size2 * z;
+			var fz = ( z - this.halfsize ) / this.halfsize; //+ 1
 
-			for ( y = 1; y < smin2; y ++ ) {
+			for ( var y = 1; y < smin2; y ++ ) {
 
-				y_offset = z_offset + this.size * y;
-				fy = ( y - this.halfsize ) / this.halfsize; //+ 1
+				var y_offset = z_offset + this.size * y;
+				var fy = ( y - this.halfsize ) / this.halfsize; //+ 1
 
-				for ( x = 1; x < smin2; x ++ ) {
+				for ( var x = 1; x < smin2; x ++ ) {
 
-					fx = ( x - this.halfsize ) / this.halfsize; //+ 1
-					q = y_offset + x;
+					var fx = ( x - this.halfsize ) / this.halfsize; //+ 1
+					var q = y_offset + x;
 
 					this.polygonize( fx, fy, fz, q, this.isolation, renderCallback );
 
@@ -762,7 +766,7 @@ THREE.MarchingCubes.prototype.constructor = THREE.MarchingCubes;
 // http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/
 // who in turn got them from Cory Gene Bloyd.
 
-THREE.edgeTable = new Int32Array([
+THREE.edgeTable = new Int32Array( [
 0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
 0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
 0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
@@ -794,262 +798,262 @@ THREE.edgeTable = new Int32Array([
 0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
 0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,
 0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
-0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ]);
-
-THREE.triTable = new Int32Array([
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 8, 3, 9, 8, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 8, 3, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-9, 2, 10, 0, 2, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-2, 8, 3, 2, 10, 8, 10, 9, 8, -1, -1, -1, -1, -1, -1, -1,
-3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 11, 2, 8, 11, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 9, 0, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 11, 2, 1, 9, 11, 9, 8, 11, -1, -1, -1, -1, -1, -1, -1,
-3, 10, 1, 11, 10, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 10, 1, 0, 8, 10, 8, 11, 10, -1, -1, -1, -1, -1, -1, -1,
-3, 9, 0, 3, 11, 9, 11, 10, 9, -1, -1, -1, -1, -1, -1, -1,
-9, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-4, 3, 0, 7, 3, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 1, 9, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-4, 1, 9, 4, 7, 1, 7, 3, 1, -1, -1, -1, -1, -1, -1, -1,
-1, 2, 10, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-3, 4, 7, 3, 0, 4, 1, 2, 10, -1, -1, -1, -1, -1, -1, -1,
-9, 2, 10, 9, 0, 2, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1,
-2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, -1, -1, -1, -1,
-8, 4, 7, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-11, 4, 7, 11, 2, 4, 2, 0, 4, -1, -1, -1, -1, -1, -1, -1,
-9, 0, 1, 8, 4, 7, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1,
-4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, -1, -1, -1, -1,
-3, 10, 1, 3, 11, 10, 7, 8, 4, -1, -1, -1, -1, -1, -1, -1,
-1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, -1, -1, -1, -1,
-4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, -1, -1, -1, -1,
-4, 7, 11, 4, 11, 9, 9, 11, 10, -1, -1, -1, -1, -1, -1, -1,
-9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-9, 5, 4, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 5, 4, 1, 5, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-8, 5, 4, 8, 3, 5, 3, 1, 5, -1, -1, -1, -1, -1, -1, -1,
-1, 2, 10, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-3, 0, 8, 1, 2, 10, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1,
-5, 2, 10, 5, 4, 2, 4, 0, 2, -1, -1, -1, -1, -1, -1, -1,
-2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, -1, -1, -1, -1,
-9, 5, 4, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 11, 2, 0, 8, 11, 4, 9, 5, -1, -1, -1, -1, -1, -1, -1,
-0, 5, 4, 0, 1, 5, 2, 3, 11, -1, -1, -1, -1, -1, -1, -1,
-2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, -1, -1, -1, -1,
-10, 3, 11, 10, 1, 3, 9, 5, 4, -1, -1, -1, -1, -1, -1, -1,
-4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, -1, -1, -1, -1,
-5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, -1, -1, -1, -1,
-5, 4, 8, 5, 8, 10, 10, 8, 11, -1, -1, -1, -1, -1, -1, -1,
-9, 7, 8, 5, 7, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-9, 3, 0, 9, 5, 3, 5, 7, 3, -1, -1, -1, -1, -1, -1, -1,
-0, 7, 8, 0, 1, 7, 1, 5, 7, -1, -1, -1, -1, -1, -1, -1,
-1, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-9, 7, 8, 9, 5, 7, 10, 1, 2, -1, -1, -1, -1, -1, -1, -1,
-10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, -1, -1, -1, -1,
-8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, -1, -1, -1, -1,
-2, 10, 5, 2, 5, 3, 3, 5, 7, -1, -1, -1, -1, -1, -1, -1,
-7, 9, 5, 7, 8, 9, 3, 11, 2, -1, -1, -1, -1, -1, -1, -1,
-9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, -1, -1, -1, -1,
-2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, -1, -1, -1, -1,
-11, 2, 1, 11, 1, 7, 7, 1, 5, -1, -1, -1, -1, -1, -1, -1,
-9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, -1, -1, -1, -1,
-5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, -1,
-11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, -1,
-11, 10, 5, 7, 11, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 8, 3, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-9, 0, 1, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 8, 3, 1, 9, 8, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1,
-1, 6, 5, 2, 6, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 6, 5, 1, 2, 6, 3, 0, 8, -1, -1, -1, -1, -1, -1, -1,
-9, 6, 5, 9, 0, 6, 0, 2, 6, -1, -1, -1, -1, -1, -1, -1,
-5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, -1, -1, -1, -1,
-2, 3, 11, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-11, 0, 8, 11, 2, 0, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1,
-0, 1, 9, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1, -1, -1, -1,
-5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, -1, -1, -1, -1,
-6, 3, 11, 6, 5, 3, 5, 1, 3, -1, -1, -1, -1, -1, -1, -1,
-0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, -1, -1, -1, -1,
-3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, -1, -1, -1, -1,
-6, 5, 9, 6, 9, 11, 11, 9, 8, -1, -1, -1, -1, -1, -1, -1,
-5, 10, 6, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-4, 3, 0, 4, 7, 3, 6, 5, 10, -1, -1, -1, -1, -1, -1, -1,
-1, 9, 0, 5, 10, 6, 8, 4, 7, -1, -1, -1, -1, -1, -1, -1,
-10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, -1, -1, -1, -1,
-6, 1, 2, 6, 5, 1, 4, 7, 8, -1, -1, -1, -1, -1, -1, -1,
-1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, -1, -1, -1, -1,
-8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, -1, -1, -1, -1,
-7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, -1,
-3, 11, 2, 7, 8, 4, 10, 6, 5, -1, -1, -1, -1, -1, -1, -1,
-5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, -1, -1, -1, -1,
-0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, -1, -1, -1, -1,
-9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, -1,
-8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, -1, -1, -1, -1,
-5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, -1,
-0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, -1,
-6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, -1, -1, -1, -1,
-10, 4, 9, 6, 4, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-4, 10, 6, 4, 9, 10, 0, 8, 3, -1, -1, -1, -1, -1, -1, -1,
-10, 0, 1, 10, 6, 0, 6, 4, 0, -1, -1, -1, -1, -1, -1, -1,
-8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, -1, -1, -1, -1,
-1, 4, 9, 1, 2, 4, 2, 6, 4, -1, -1, -1, -1, -1, -1, -1,
-3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, -1, -1, -1, -1,
-0, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-8, 3, 2, 8, 2, 4, 4, 2, 6, -1, -1, -1, -1, -1, -1, -1,
-10, 4, 9, 10, 6, 4, 11, 2, 3, -1, -1, -1, -1, -1, -1, -1,
-0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, -1, -1, -1, -1,
-3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, -1, -1, -1, -1,
-6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, -1,
-9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, -1, -1, -1, -1,
-8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, -1,
-3, 11, 6, 3, 6, 0, 0, 6, 4, -1, -1, -1, -1, -1, -1, -1,
-6, 4, 8, 11, 6, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-7, 10, 6, 7, 8, 10, 8, 9, 10, -1, -1, -1, -1, -1, -1, -1,
-0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, -1, -1, -1, -1,
-10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, -1, -1, -1, -1,
-10, 6, 7, 10, 7, 1, 1, 7, 3, -1, -1, -1, -1, -1, -1, -1,
-1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, -1, -1, -1, -1,
-2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, -1,
-7, 8, 0, 7, 0, 6, 6, 0, 2, -1, -1, -1, -1, -1, -1, -1,
-7, 3, 2, 6, 7, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, -1, -1, -1, -1,
-2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, -1,
-1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, -1,
-11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, -1, -1, -1, -1,
-8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, -1,
-0, 9, 1, 11, 6, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, -1, -1, -1, -1,
-7, 11, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-3, 0, 8, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 1, 9, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-8, 1, 9, 8, 3, 1, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1,
-10, 1, 2, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 2, 10, 3, 0, 8, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1,
-2, 9, 0, 2, 10, 9, 6, 11, 7, -1, -1, -1, -1, -1, -1, -1,
-6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, -1, -1, -1, -1,
-7, 2, 3, 6, 2, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-7, 0, 8, 7, 6, 0, 6, 2, 0, -1, -1, -1, -1, -1, -1, -1,
-2, 7, 6, 2, 3, 7, 0, 1, 9, -1, -1, -1, -1, -1, -1, -1,
-1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, -1, -1, -1, -1,
-10, 7, 6, 10, 1, 7, 1, 3, 7, -1, -1, -1, -1, -1, -1, -1,
-10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, -1, -1, -1, -1,
-0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, -1, -1, -1, -1,
-7, 6, 10, 7, 10, 8, 8, 10, 9, -1, -1, -1, -1, -1, -1, -1,
-6, 8, 4, 11, 8, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-3, 6, 11, 3, 0, 6, 0, 4, 6, -1, -1, -1, -1, -1, -1, -1,
-8, 6, 11, 8, 4, 6, 9, 0, 1, -1, -1, -1, -1, -1, -1, -1,
-9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, -1, -1, -1, -1,
-6, 8, 4, 6, 11, 8, 2, 10, 1, -1, -1, -1, -1, -1, -1, -1,
-1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, -1, -1, -1, -1,
-4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, -1, -1, -1, -1,
-10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, -1,
-8, 2, 3, 8, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1,
-0, 4, 2, 4, 6, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, -1, -1, -1, -1,
-1, 9, 4, 1, 4, 2, 2, 4, 6, -1, -1, -1, -1, -1, -1, -1,
-8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, -1, -1, -1, -1,
-10, 1, 0, 10, 0, 6, 6, 0, 4, -1, -1, -1, -1, -1, -1, -1,
-4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, -1,
-10, 9, 4, 6, 10, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-4, 9, 5, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 8, 3, 4, 9, 5, 11, 7, 6, -1, -1, -1, -1, -1, -1, -1,
-5, 0, 1, 5, 4, 0, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1,
-11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, -1, -1, -1, -1,
-9, 5, 4, 10, 1, 2, 7, 6, 11, -1, -1, -1, -1, -1, -1, -1,
-6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, -1, -1, -1, -1,
-7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, -1, -1, -1, -1,
-3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, -1,
-7, 2, 3, 7, 6, 2, 5, 4, 9, -1, -1, -1, -1, -1, -1, -1,
-9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, -1, -1, -1, -1,
-3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, -1, -1, -1, -1,
-6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, -1,
-9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, -1, -1, -1, -1,
-1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, -1,
-4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, -1,
-7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, -1, -1, -1, -1,
-6, 9, 5, 6, 11, 9, 11, 8, 9, -1, -1, -1, -1, -1, -1, -1,
-3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, -1, -1, -1, -1,
-0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, -1, -1, -1, -1,
-6, 11, 3, 6, 3, 5, 5, 3, 1, -1, -1, -1, -1, -1, -1, -1,
-1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, -1, -1, -1, -1,
-0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, -1,
-11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, -1,
-6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, -1, -1, -1, -1,
-5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, -1, -1, -1, -1,
-9, 5, 6, 9, 6, 0, 0, 6, 2, -1, -1, -1, -1, -1, -1, -1,
-1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, -1,
-1, 5, 6, 2, 1, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, -1,
-10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, -1, -1, -1, -1,
-0, 3, 8, 5, 6, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-10, 5, 6, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-11, 5, 10, 7, 5, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-11, 5, 10, 11, 7, 5, 8, 3, 0, -1, -1, -1, -1, -1, -1, -1,
-5, 11, 7, 5, 10, 11, 1, 9, 0, -1, -1, -1, -1, -1, -1, -1,
-10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, -1, -1, -1, -1,
-11, 1, 2, 11, 7, 1, 7, 5, 1, -1, -1, -1, -1, -1, -1, -1,
-0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, -1, -1, -1, -1,
-9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, -1, -1, -1, -1,
-7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, -1,
-2, 5, 10, 2, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1,
-8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, -1, -1, -1, -1,
-9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, -1, -1, -1, -1,
-9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, -1,
-1, 3, 5, 3, 7, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 8, 7, 0, 7, 1, 1, 7, 5, -1, -1, -1, -1, -1, -1, -1,
-9, 0, 3, 9, 3, 5, 5, 3, 7, -1, -1, -1, -1, -1, -1, -1,
-9, 8, 7, 5, 9, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-5, 8, 4, 5, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1,
-5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, -1, -1, -1, -1,
-0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, -1, -1, -1, -1,
-10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, -1,
-2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, -1, -1, -1, -1,
-0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, -1,
-0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, -1,
-9, 4, 5, 2, 11, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, -1, -1, -1, -1,
-5, 10, 2, 5, 2, 4, 4, 2, 0, -1, -1, -1, -1, -1, -1, -1,
-3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, -1,
-5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, -1, -1, -1, -1,
-8, 4, 5, 8, 5, 3, 3, 5, 1, -1, -1, -1, -1, -1, -1, -1,
-0, 4, 5, 1, 0, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, -1, -1, -1, -1,
-9, 4, 5, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-4, 11, 7, 4, 9, 11, 9, 10, 11, -1, -1, -1, -1, -1, -1, -1,
-0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, -1, -1, -1, -1,
-1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, -1, -1, -1, -1,
-3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, -1,
-4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, -1, -1, -1, -1,
-9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, -1,
-11, 7, 4, 11, 4, 2, 2, 4, 0, -1, -1, -1, -1, -1, -1, -1,
-11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, -1, -1, -1, -1,
-2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, -1, -1, -1, -1,
-9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, -1,
-3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, -1,
-1, 10, 2, 8, 7, 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-4, 9, 1, 4, 1, 7, 7, 1, 3, -1, -1, -1, -1, -1, -1, -1,
-4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, -1, -1, -1, -1,
-4, 0, 3, 7, 4, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-4, 8, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-9, 10, 8, 10, 11, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-3, 0, 9, 3, 9, 11, 11, 9, 10, -1, -1, -1, -1, -1, -1, -1,
-0, 1, 10, 0, 10, 8, 8, 10, 11, -1, -1, -1, -1, -1, -1, -1,
-3, 1, 10, 11, 3, 10, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 2, 11, 1, 11, 9, 9, 11, 8, -1, -1, -1, -1, -1, -1, -1,
-3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, -1, -1, -1, -1,
-0, 2, 11, 8, 0, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-3, 2, 11, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-2, 3, 8, 2, 8, 10, 10, 8, 9, -1, -1, -1, -1, -1, -1, -1,
-9, 10, 2, 0, 9, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, -1, -1, -1, -1,
-1, 10, 2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 3, 8, 9, 1, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 9, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-0, 3, 8, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
--1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ]);
+0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ] );
+
+THREE.triTable = new Int32Array( [
+- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 8, 3, 9, 8, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 2, 10, 0, 2, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 8, 3, 2, 10, 8, 10, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 11, 2, 8, 11, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 9, 0, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 11, 2, 1, 9, 11, 9, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 10, 1, 11, 10, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 10, 1, 0, 8, 10, 8, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 9, 0, 3, 11, 9, 11, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 3, 0, 7, 3, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 9, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 1, 9, 4, 7, 1, 7, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 4, 7, 3, 0, 4, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 2, 10, 9, 0, 2, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
+8, 4, 7, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 4, 7, 11, 2, 4, 2, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 0, 1, 8, 4, 7, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, - 1, - 1, - 1, - 1,
+3, 10, 1, 3, 11, 10, 7, 8, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, - 1, - 1, - 1, - 1,
+4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
+4, 7, 11, 4, 11, 9, 9, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 4, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 5, 4, 1, 5, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 5, 4, 8, 3, 5, 3, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 8, 1, 2, 10, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 2, 10, 5, 4, 2, 4, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, - 1, - 1, - 1, - 1,
+9, 5, 4, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 11, 2, 0, 8, 11, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 5, 4, 0, 1, 5, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, - 1, - 1, - 1, - 1,
+10, 3, 11, 10, 1, 3, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, - 1, - 1, - 1, - 1,
+5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
+5, 4, 8, 5, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 7, 8, 5, 7, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 3, 0, 9, 5, 3, 5, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 7, 8, 0, 1, 7, 1, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 7, 8, 9, 5, 7, 10, 1, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, - 1, - 1, - 1, - 1,
+8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, - 1, - 1, - 1, - 1,
+2, 10, 5, 2, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 9, 5, 7, 8, 9, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
+2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, - 1, - 1, - 1, - 1,
+11, 2, 1, 11, 1, 7, 7, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, - 1, - 1, - 1, - 1,
+5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, - 1,
+11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, - 1,
+11, 10, 5, 7, 11, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 0, 1, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 8, 3, 1, 9, 8, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 6, 5, 2, 6, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 6, 5, 1, 2, 6, 3, 0, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 6, 5, 9, 0, 6, 0, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, - 1, - 1, - 1, - 1,
+2, 3, 11, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 0, 8, 11, 2, 0, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 9, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, - 1, - 1, - 1, - 1,
+6, 3, 11, 6, 5, 3, 5, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
+3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, - 1, - 1, - 1, - 1,
+6, 5, 9, 6, 9, 11, 11, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 10, 6, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 3, 0, 4, 7, 3, 6, 5, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 9, 0, 5, 10, 6, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
+6, 1, 2, 6, 5, 1, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, - 1, - 1, - 1, - 1,
+8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, - 1, - 1, - 1, - 1,
+7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, - 1,
+3, 11, 2, 7, 8, 4, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
+0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1,
+9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, - 1,
+8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
+5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, - 1,
+0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, - 1,
+6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, - 1, - 1, - 1, - 1,
+10, 4, 9, 6, 4, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 10, 6, 4, 9, 10, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 0, 1, 10, 6, 0, 6, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
+1, 4, 9, 1, 2, 4, 2, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, - 1, - 1, - 1, - 1,
+0, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 3, 2, 8, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 4, 9, 10, 6, 4, 11, 2, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, - 1, - 1, - 1, - 1,
+3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
+6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, - 1,
+9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, - 1, - 1, - 1, - 1,
+8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, - 1,
+3, 11, 6, 3, 6, 0, 0, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+6, 4, 8, 11, 6, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 10, 6, 7, 8, 10, 8, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, - 1, - 1, - 1, - 1,
+10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, - 1, - 1, - 1, - 1,
+10, 6, 7, 10, 7, 1, 1, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
+2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, - 1,
+7, 8, 0, 7, 0, 6, 6, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 3, 2, 6, 7, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
+2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, - 1,
+1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, - 1,
+11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, - 1, - 1, - 1, - 1,
+8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, - 1,
+0, 9, 1, 11, 6, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, - 1, - 1, - 1, - 1,
+7, 11, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 8, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 9, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 1, 9, 8, 3, 1, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 1, 2, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 3, 0, 8, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 9, 0, 2, 10, 9, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, - 1, - 1, - 1, - 1,
+7, 2, 3, 6, 2, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+7, 0, 8, 7, 6, 0, 6, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 7, 6, 2, 3, 7, 0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, - 1, - 1, - 1, - 1,
+10, 7, 6, 10, 1, 7, 1, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, - 1, - 1, - 1, - 1,
+0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, - 1, - 1, - 1, - 1,
+7, 6, 10, 7, 10, 8, 8, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+6, 8, 4, 11, 8, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 6, 11, 3, 0, 6, 0, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 6, 11, 8, 4, 6, 9, 0, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, - 1, - 1, - 1, - 1,
+6, 8, 4, 6, 11, 8, 2, 10, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, - 1, - 1, - 1, - 1,
+4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, - 1, - 1, - 1, - 1,
+10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, - 1,
+8, 2, 3, 8, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, - 1, - 1, - 1, - 1,
+1, 9, 4, 1, 4, 2, 2, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, - 1, - 1, - 1, - 1,
+10, 1, 0, 10, 0, 6, 6, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, - 1,
+10, 9, 4, 6, 10, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 9, 5, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 4, 9, 5, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 0, 1, 5, 4, 0, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, - 1, - 1, - 1, - 1,
+9, 5, 4, 10, 1, 2, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, - 1, - 1, - 1, - 1,
+7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, - 1, - 1, - 1, - 1,
+3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, - 1,
+7, 2, 3, 7, 6, 2, 5, 4, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, - 1, - 1, - 1, - 1,
+3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, - 1, - 1, - 1, - 1,
+6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, - 1,
+9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, - 1, - 1, - 1, - 1,
+1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, - 1,
+4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, - 1,
+7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, - 1, - 1, - 1, - 1,
+6, 9, 5, 6, 11, 9, 11, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, - 1, - 1, - 1, - 1,
+0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, - 1, - 1, - 1, - 1,
+6, 11, 3, 6, 3, 5, 5, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, - 1, - 1, - 1, - 1,
+0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, - 1,
+11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, - 1,
+6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, - 1, - 1, - 1, - 1,
+5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, - 1, - 1, - 1, - 1,
+9, 5, 6, 9, 6, 0, 0, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, - 1,
+1, 5, 6, 2, 1, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, - 1,
+10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, - 1, - 1, - 1, - 1,
+0, 3, 8, 5, 6, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 5, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 5, 10, 7, 5, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 5, 10, 11, 7, 5, 8, 3, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 11, 7, 5, 10, 11, 1, 9, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, - 1, - 1, - 1, - 1,
+11, 1, 2, 11, 7, 1, 7, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, - 1, - 1, - 1, - 1,
+9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, - 1, - 1, - 1, - 1,
+7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, - 1,
+2, 5, 10, 2, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, - 1, - 1, - 1, - 1,
+9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, - 1, - 1, - 1, - 1,
+9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, - 1,
+1, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 7, 0, 7, 1, 1, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 0, 3, 9, 3, 5, 5, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 8, 7, 5, 9, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 8, 4, 5, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, - 1, - 1, - 1, - 1,
+0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, - 1, - 1, - 1, - 1,
+10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, - 1,
+2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, - 1, - 1, - 1, - 1,
+0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, - 1,
+0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, - 1,
+9, 4, 5, 2, 11, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, - 1, - 1, - 1, - 1,
+5, 10, 2, 5, 2, 4, 4, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, - 1,
+5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, - 1, - 1, - 1, - 1,
+8, 4, 5, 8, 5, 3, 3, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 4, 5, 1, 0, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, - 1, - 1, - 1, - 1,
+9, 4, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 11, 7, 4, 9, 11, 9, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, - 1, - 1, - 1, - 1,
+1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, - 1, - 1, - 1, - 1,
+3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, - 1,
+4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, - 1, - 1, - 1, - 1,
+9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, - 1,
+11, 7, 4, 11, 4, 2, 2, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, - 1, - 1, - 1, - 1,
+2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, - 1, - 1, - 1, - 1,
+9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, - 1,
+3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, - 1,
+1, 10, 2, 8, 7, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 9, 1, 4, 1, 7, 7, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, - 1, - 1, - 1, - 1,
+4, 0, 3, 7, 4, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+4, 8, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 9, 3, 9, 11, 11, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 1, 10, 0, 10, 8, 8, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 1, 10, 11, 3, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 2, 11, 1, 11, 9, 9, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, - 1, - 1, - 1, - 1,
+0, 2, 11, 8, 0, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+3, 2, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 3, 8, 2, 8, 10, 10, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+9, 10, 2, 0, 9, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, - 1, - 1, - 1, - 1,
+1, 10, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+1, 3, 8, 9, 1, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 9, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+0, 3, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 ] );

+ 31 - 30
examples/js/Mirror.js

@@ -2,9 +2,9 @@
  * @author Slayvin / http://slayvin.net
  */
 
-THREE.ShaderLib['mirror'] = {
+THREE.ShaderLib[ 'mirror' ] = {
 
-	uniforms: { "mirrorColor": { type: "c", value: new THREE.Color(0x7F7F7F) },
+	uniforms: { "mirrorColor": { type: "c", value: new THREE.Color( 0x7F7F7F ) },
 				"mirrorSampler": { type: "t", value: null },
 				"textureMatrix" : { type: "m4", value: new THREE.Matrix4() }
 	},
@@ -25,7 +25,7 @@ THREE.ShaderLib['mirror'] = {
 
 		"}"
 
-	].join("\n"),
+	].join( "\n" ),
 
 	fragmentShader: [
 
@@ -37,7 +37,7 @@ THREE.ShaderLib['mirror'] = {
 		"float blendOverlay(float base, float blend) {",
 			"return( base < 0.5 ? ( 2.0 * base * blend ) : (1.0 - 2.0 * ( 1.0 - base ) * ( 1.0 - blend ) ) );",
 		"}",
-		
+
 		"void main() {",
 
 			"vec4 color = texture2DProj(mirrorSampler, mirrorCoord);",
@@ -47,7 +47,7 @@ THREE.ShaderLib['mirror'] = {
 
 		"}"
 
-	].join("\n")
+	].join( "\n" )
 
 };
 
@@ -66,7 +66,7 @@ THREE.Mirror = function ( renderer, camera, options ) {
 
 	this.clipBias = options.clipBias !== undefined ? options.clipBias : 0.0;
 
-	var mirrorColor = options.color !== undefined ? new THREE.Color(options.color) : new THREE.Color(0x7F7F7F);
+	var mirrorColor = options.color !== undefined ? new THREE.Color( options.color ) : new THREE.Color( 0x7F7F7F );
 
 	this.renderer = renderer;
 	this.mirrorPlane = new THREE.Plane();
@@ -74,25 +74,25 @@ THREE.Mirror = function ( renderer, camera, options ) {
 	this.mirrorWorldPosition = new THREE.Vector3();
 	this.cameraWorldPosition = new THREE.Vector3();
 	this.rotationMatrix = new THREE.Matrix4();
-	this.lookAtPosition = new THREE.Vector3(0, 0, -1);
+	this.lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
 	this.clipPlane = new THREE.Vector4();
-	
+
 	// For debug only, show the normal and plane of the mirror
 	var debugMode = options.debugMode !== undefined ? options.debugMode : false;
 
 	if ( debugMode ) {
 
-		var arrow = new THREE.ArrowHelper(new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 0, 0, 0 ), 10, 0xffff80 );
+		var arrow = new THREE.ArrowHelper( new THREE.Vector3( 0, 0, 1 ), new THREE.Vector3( 0, 0, 0 ), 10, 0xffff80 );
 		var planeGeometry = new THREE.Geometry();
-		planeGeometry.vertices.push( new THREE.Vector3( -10, -10, 0 ) );
-		planeGeometry.vertices.push( new THREE.Vector3( 10, -10, 0 ) );
+		planeGeometry.vertices.push( new THREE.Vector3( - 10, - 10, 0 ) );
+		planeGeometry.vertices.push( new THREE.Vector3( 10, - 10, 0 ) );
 		planeGeometry.vertices.push( new THREE.Vector3( 10, 10, 0 ) );
-		planeGeometry.vertices.push( new THREE.Vector3( -10, 10, 0 ) );
-		planeGeometry.vertices.push( planeGeometry.vertices[0] );
+		planeGeometry.vertices.push( new THREE.Vector3( - 10, 10, 0 ) );
+		planeGeometry.vertices.push( planeGeometry.vertices[ 0 ] );
 		var plane = new THREE.Line( planeGeometry, new THREE.LineBasicMaterial( { color: 0xffff80 } ) );
 
-		this.add(arrow);
-		this.add(plane);
+		this.add( arrow );
+		this.add( plane );
 
 	}
 
@@ -132,7 +132,7 @@ THREE.Mirror = function ( renderer, camera, options ) {
 	this.material.uniforms.mirrorColor.value = mirrorColor;
 	this.material.uniforms.textureMatrix.value = this.textureMatrix;
 
-	if ( !THREE.Math.isPowerOfTwo(width) || !THREE.Math.isPowerOfTwo( height ) ) {
+	if ( ! THREE.Math.isPowerOfTwo( width ) || ! THREE.Math.isPowerOfTwo( height ) ) {
 
 		this.texture.generateMipmaps = false;
 		this.tempTexture.generateMipmaps = false;
@@ -171,6 +171,7 @@ THREE.Mirror.prototype.renderWithMirror = function ( otherMirror ) {
 
 	// restore texture matrix of other mirror
 	otherMirror.updateTextureMatrix();
+
 };
 
 THREE.Mirror.prototype.updateTextureMatrix = function () {
@@ -192,7 +193,7 @@ THREE.Mirror.prototype.updateTextureMatrix = function () {
 
 	this.rotationMatrix.extractRotation( this.camera.matrixWorld );
 
-	this.lookAtPosition.set(0, 0, -1);
+	this.lookAtPosition.set( 0, 0, - 1 );
 	this.lookAtPosition.applyMatrix4( this.rotationMatrix );
 	this.lookAtPosition.add( this.cameraWorldPosition );
 
@@ -200,7 +201,7 @@ THREE.Mirror.prototype.updateTextureMatrix = function () {
 	target.reflect( this.normal ).negate();
 	target.add( this.mirrorWorldPosition );
 
-	this.up.set( 0, -1, 0 );
+	this.up.set( 0, - 1, 0 );
 	this.up.applyMatrix4( this.rotationMatrix );
 	this.up.reflect( this.normal ).negate();
 
@@ -230,20 +231,20 @@ THREE.Mirror.prototype.updateTextureMatrix = function () {
 	var q = new THREE.Vector4();
 	var projectionMatrix = this.mirrorCamera.projectionMatrix;
 
-	q.x = ( Math.sign(this.clipPlane.x) + projectionMatrix.elements[8] ) / projectionMatrix.elements[0];
-	q.y = ( Math.sign(this.clipPlane.y) + projectionMatrix.elements[9] ) / projectionMatrix.elements[5];
+	q.x = ( Math.sign( this.clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
+	q.y = ( Math.sign( this.clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
 	q.z = - 1.0;
-	q.w = ( 1.0 + projectionMatrix.elements[10] ) / projectionMatrix.elements[14];
+	q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
 
 	// Calculate the scaled plane vector
 	var c = new THREE.Vector4();
-	c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot(q) );
+	c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot( q ) );
 
 	// Replacing the third row of the projection matrix
-	projectionMatrix.elements[2] = c.x;
-	projectionMatrix.elements[6] = c.y;
-	projectionMatrix.elements[10] = c.z + 1.0 - this.clipBias;
-	projectionMatrix.elements[14] = c.w;
+	projectionMatrix.elements[ 2 ] = c.x;
+	projectionMatrix.elements[ 6 ] = c.y;
+	projectionMatrix.elements[ 10 ] = c.z + 1.0 - this.clipBias;
+	projectionMatrix.elements[ 14 ] = c.w;
 
 };
 
@@ -256,13 +257,13 @@ THREE.Mirror.prototype.render = function () {
 	// Render the mirrored view of the current scene into the target texture
 	var scene = this;
 
-	while ( scene.parent !== undefined ) {
+	while ( scene.parent !== null ) {
 
 		scene = scene.parent;
 
 	}
 
-	if ( scene !== undefined && scene instanceof THREE.Scene) {
+	if ( scene !== undefined && scene instanceof THREE.Scene ) {
 
 		// We can't render ourself to ourself
 		var visible = this.material.visible;
@@ -285,13 +286,13 @@ THREE.Mirror.prototype.renderTemp = function () {
 	// Render the mirrored view of the current scene into the target texture
 	var scene = this;
 
-	while ( scene.parent !== undefined ) {
+	while ( scene.parent !== null ) {
 
 		scene = scene.parent;
 
 	}
 
-	if ( scene !== undefined && scene instanceof THREE.Scene) {
+	if ( scene !== undefined && scene instanceof THREE.Scene ) {
 
 		this.renderer.render( scene, this.mirrorCamera, this.tempTexture, true );
 

+ 163 - 128
examples/js/Ocean.js

@@ -1,47 +1,50 @@
-THREE.Ocean = function (renderer, camera, scene, options) {
+THREE.Ocean = function ( renderer, camera, scene, options ) {
+
 	// flag used to trigger parameter changes
 	this.changed = true;
 	this.initial = true;
-	
+
 	// Assign required parameters as object properties
 	this.oceanCamera = new THREE.OrthographicCamera(); //camera.clone();
 	this.oceanCamera.position.z = 1;
 	this.renderer = renderer;
 	this.renderer.clearColor( 0xffffff );
-	
+
 	this.scene = new THREE.Scene();
-	
+
 	// Enable necessary extensions
-	this.renderer.context.getExtension('OES_texture_float');
-	this.renderer.context.getExtension('OES_texture_float_linear');
-	
+	this.renderer.context.getExtension( 'OES_texture_float' );
+	this.renderer.context.getExtension( 'OES_texture_float_linear' );
+
 	// Assign optional parameters as variables and object properties
-	function optionalParameter(value, defaultValue) {
+	function optionalParameter( value, defaultValue ) {
+
 		return value !== undefined ? value : defaultValue;
+
 	}
 	options = options || {};
-	this.clearColor = optionalParameter(options.CLEAR_COLOR, [ 1.0, 1.0, 1.0, 0.0 ]);
-	this.geometryOrigin = optionalParameter(options.GEOMETRY_ORIGIN, [ -1000.0, -1000.0 ]);
-	this.sunDirectionX = optionalParameter(options.SUN_DIRECTION[0], -1.0);
-	this.sunDirectionY = optionalParameter(options.SUN_DIRECTION[1], 1.0);
-	this.sunDirectionZ = optionalParameter(options.SUN_DIRECTION[2], 1.0);
-	this.oceanColor = optionalParameter(options.OCEAN_COLOR, new THREE.Vector3(0.004, 0.016, 0.047));
-	this.skyColor = optionalParameter(options.SKY_COLOR, new THREE.Vector3(3.2, 9.6, 12.8));
-	this.exposure = optionalParameter(options.EXPOSURE, 0.35);
-	this.geometryResolution = optionalParameter(options.GEOMETRY_RESOLUTION, 32);
-	this.geometrySize = optionalParameter(options.GEOMETRY_SIZE, 2000);
-	this.resolution = optionalParameter(options.RESOLUTION, 64);
-	this.floatSize = optionalParameter(options.SIZE_OF_FLOAT, 4);
-	this.windX = optionalParameter(options.INITIAL_WIND[0], 10.0),
-	this.windY = optionalParameter(options.INITIAL_WIND[1], 10.0),
-	this.size = optionalParameter(options.INITIAL_SIZE, 250.0),
-	this.choppiness = optionalParameter(options.INITIAL_CHOPPINESS, 1.5);
-	
-	// 
+	this.clearColor = optionalParameter( options.CLEAR_COLOR, [ 1.0, 1.0, 1.0, 0.0 ] );
+	this.geometryOrigin = optionalParameter( options.GEOMETRY_ORIGIN, [ - 1000.0, - 1000.0 ] );
+	this.sunDirectionX = optionalParameter( options.SUN_DIRECTION[ 0 ], - 1.0 );
+	this.sunDirectionY = optionalParameter( options.SUN_DIRECTION[ 1 ], 1.0 );
+	this.sunDirectionZ = optionalParameter( options.SUN_DIRECTION[ 2 ], 1.0 );
+	this.oceanColor = optionalParameter( options.OCEAN_COLOR, new THREE.Vector3( 0.004, 0.016, 0.047 ) );
+	this.skyColor = optionalParameter( options.SKY_COLOR, new THREE.Vector3( 3.2, 9.6, 12.8 ) );
+	this.exposure = optionalParameter( options.EXPOSURE, 0.35 );
+	this.geometryResolution = optionalParameter( options.GEOMETRY_RESOLUTION, 32 );
+	this.geometrySize = optionalParameter( options.GEOMETRY_SIZE, 2000 );
+	this.resolution = optionalParameter( options.RESOLUTION, 64 );
+	this.floatSize = optionalParameter( options.SIZE_OF_FLOAT, 4 );
+	this.windX = optionalParameter( options.INITIAL_WIND[ 0 ], 10.0 ),
+	this.windY = optionalParameter( options.INITIAL_WIND[ 1 ], 10.0 ),
+	this.size = optionalParameter( options.INITIAL_SIZE, 250.0 ),
+	this.choppiness = optionalParameter( options.INITIAL_CHOPPINESS, 1.5 );
+
+	//
 	this.matrixNeedsUpdate = false;
-	
+
 	// Setup framebuffer pipeline
-	var renderTargetType = optionalParameter(options.USE_HALF_FLOAT, false) ? THREE.HalfFloatType : THREE.FloatType;
+	var renderTargetType = optionalParameter( options.USE_HALF_FLOAT, false ) ? THREE.HalfFloatType : THREE.FloatType;
 	var LinearClampParams = {
 		minFilter: THREE.LinearFilter,
 		magFilter: THREE.LinearFilter,
@@ -61,7 +64,7 @@
 		format: THREE.RGBAFormat,
 		stencilBuffer: false,
 		depthBuffer: false,
-		premultiplyAlpha:false,
+		premultiplyAlpha: false,
 		type: renderTargetType
 	};
 	var NearestRepeatParams = {
@@ -75,109 +78,107 @@
 		premultiplyAlpha: false,
 		type: renderTargetType
 	};
-	this.initialSpectrumFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, NearestRepeatParams);
-	this.spectrumFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, NearestClampParams);
-	this.pingPhaseFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, NearestClampParams);
-	this.pongPhaseFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, NearestClampParams);
-	this.pingTransformFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, NearestClampParams);
-	this.pongTransformFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, NearestClampParams);
-	this.displacementMapFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, LinearClampParams);
-	this.normalMapFramebuffer = new THREE.WebGLRenderTarget(this.resolution, this.resolution, LinearClampParams);
-	
+	this.initialSpectrumFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestRepeatParams );
+	this.spectrumFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.pingPhaseFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.pongPhaseFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.pingTransformFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.pongTransformFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, NearestClampParams );
+	this.displacementMapFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, LinearClampParams );
+	this.normalMapFramebuffer = new THREE.WebGLRenderTarget( this.resolution, this.resolution, LinearClampParams );
+
 	// Define shaders and constant uniforms
 	////////////////////////////////////////
-	
+
 	// 0 - The vertex shader used in all of the simulation steps
-	var fullscreeenVertexShader = THREE.ShaderLib["ocean_sim_vertex"];
-		
+	var fullscreeenVertexShader = THREE.ShaderLib[ "ocean_sim_vertex" ];
+
 	// 1 - Horizontal wave vertices used for FFT
-	var oceanHorizontalShader = THREE.ShaderLib["ocean_subtransform"];
-	var oceanHorizontalUniforms = THREE.UniformsUtils.clone(oceanHorizontalShader.uniforms);
-	this.materialOceanHorizontal = new THREE.ShaderMaterial({
+	var oceanHorizontalShader = THREE.ShaderLib[ "ocean_subtransform" ];
+	var oceanHorizontalUniforms = THREE.UniformsUtils.clone( oceanHorizontalShader.uniforms );
+	this.materialOceanHorizontal = new THREE.ShaderMaterial( {
 		uniforms: oceanHorizontalUniforms,
 		vertexShader: fullscreeenVertexShader.vertexShader,
 		fragmentShader: "#define HORIZONTAL \n" + oceanHorizontalShader.fragmentShader
-	});
+	} );
 	this.materialOceanHorizontal.uniforms.u_transformSize = { type: "f", value: this.resolution };
 	this.materialOceanHorizontal.uniforms.u_subtransformSize = { type: "f", value: null };
 	this.materialOceanHorizontal.uniforms.u_input = { type: "t", value: null };
 	this.materialOceanHorizontal.depthTest = false;
-	
+
 	// 2 - Vertical wave vertices used for FFT
-	var oceanVerticalShader = THREE.ShaderLib["ocean_subtransform"];
-	var oceanVerticalUniforms = THREE.UniformsUtils.clone(oceanVerticalShader.uniforms);
-	this.materialOceanVertical = new THREE.ShaderMaterial({
+	var oceanVerticalShader = THREE.ShaderLib[ "ocean_subtransform" ];
+	var oceanVerticalUniforms = THREE.UniformsUtils.clone( oceanVerticalShader.uniforms );
+	this.materialOceanVertical = new THREE.ShaderMaterial( {
 		uniforms: oceanVerticalUniforms,
 		vertexShader: fullscreeenVertexShader.vertexShader,
 		fragmentShader: oceanVerticalShader.fragmentShader
-	});
+	} );
 	this.materialOceanVertical.uniforms.u_transformSize = { type: "f", value: this.resolution };
 	this.materialOceanVertical.uniforms.u_subtransformSize = { type: "f", value: null };
 	this.materialOceanVertical.uniforms.u_input = { type: "t", value: null };
 	this.materialOceanVertical.depthTest = false;
-	
+
 	// 3 - Initial spectrum used to generate height map
-	var initialSpectrumShader = THREE.ShaderLib["ocean_initial_spectrum"];
-	var initialSpectrumUniforms = THREE.UniformsUtils.clone(initialSpectrumShader.uniforms);
-	this.materialInitialSpectrum = new THREE.ShaderMaterial({
+	var initialSpectrumShader = THREE.ShaderLib[ "ocean_initial_spectrum" ];
+	var initialSpectrumUniforms = THREE.UniformsUtils.clone( initialSpectrumShader.uniforms );
+	this.materialInitialSpectrum = new THREE.ShaderMaterial( {
 		uniforms: initialSpectrumUniforms,
 		vertexShader: fullscreeenVertexShader.vertexShader,
-		fragmentShader:initialSpectrumShader.fragmentShader
-	});
+		fragmentShader: initialSpectrumShader.fragmentShader
+	} );
 	this.materialInitialSpectrum.uniforms.u_wind = { type: "v2", value: new THREE.Vector2() };
 	this.materialInitialSpectrum.uniforms.u_resolution = { type: "f", value: this.resolution };
 	this.materialInitialSpectrum.depthTest = false;
-	
+
 	// 4 - Phases used to animate heightmap
-	var phaseShader = THREE.ShaderLib["ocean_phase"];
-	var phaseUniforms = THREE.UniformsUtils.clone(phaseShader.uniforms);
-	this.materialPhase = new THREE.ShaderMaterial({
+	var phaseShader = THREE.ShaderLib[ "ocean_phase" ];
+	var phaseUniforms = THREE.UniformsUtils.clone( phaseShader.uniforms );
+	this.materialPhase = new THREE.ShaderMaterial( {
 		uniforms: phaseUniforms,
 		vertexShader: fullscreeenVertexShader.vertexShader,
 		fragmentShader: phaseShader.fragmentShader
-	});
+	} );
 	this.materialPhase.uniforms.u_resolution = { type: "f", value: this.resolution };
 	this.materialPhase.depthTest = false;
-	
+
 	// 5 - Shader used to update spectrum
-	var spectrumShader = THREE.ShaderLib["ocean_spectrum"];
-	var spectrumUniforms = THREE.UniformsUtils.clone(spectrumShader.uniforms);
-	this.materialSpectrum = new THREE.ShaderMaterial({
+	var spectrumShader = THREE.ShaderLib[ "ocean_spectrum" ];
+	var spectrumUniforms = THREE.UniformsUtils.clone( spectrumShader.uniforms );
+	this.materialSpectrum = new THREE.ShaderMaterial( {
 		uniforms: spectrumUniforms,
 		vertexShader: fullscreeenVertexShader.vertexShader,
 		fragmentShader: spectrumShader.fragmentShader
-	});
+	} );
 	this.materialSpectrum.uniforms.u_initialSpectrum = { type: "t", value: null };
 	this.materialSpectrum.uniforms.u_resolution = { type: "f", value: this.resolution };
 	this.materialSpectrum.depthTest = false;
 
 	// 6 - Shader used to update spectrum normals
-	var normalShader = THREE.ShaderLib["ocean_normals"];
-	var normalUniforms = THREE.UniformsUtils.clone(normalShader.uniforms);
-	this.materialNormal = new THREE.ShaderMaterial({
+	var normalShader = THREE.ShaderLib[ "ocean_normals" ];
+	var normalUniforms = THREE.UniformsUtils.clone( normalShader.uniforms );
+	this.materialNormal = new THREE.ShaderMaterial( {
 		uniforms: normalUniforms,
 		vertexShader: fullscreeenVertexShader.vertexShader,
 		fragmentShader: normalShader.fragmentShader
-	});
+	} );
 	this.materialNormal.uniforms.u_displacementMap = { type: "t", value: null };
 	this.materialNormal.uniforms.u_resolution = { type: "f", value: this.resolution };
 	this.materialNormal.depthTest = false;
 
 	// 7 - Shader used to update normals
-	var oceanShader = THREE.ShaderLib["ocean_main"];
-	var oceanUniforms = THREE.UniformsUtils.clone(oceanShader.uniforms);
-	var oceanAttributes = THREE.UniformsUtils.clone(oceanShader.attributes);
-	this.materialOcean = new THREE.ShaderMaterial({
-		attributes: oceanAttributes,
+	var oceanShader = THREE.ShaderLib[ "ocean_main" ];
+	var oceanUniforms = THREE.UniformsUtils.clone( oceanShader.uniforms );
+	this.materialOcean = new THREE.ShaderMaterial( {
 		uniforms: oceanUniforms,
 		vertexShader: oceanShader.vertexShader,
 		fragmentShader: oceanShader.fragmentShader
-	});
+	} );
 	// this.materialOcean.wireframe = true;
 	this.materialOcean.uniforms.u_geometrySize = { type: "f", value: this.resolution };
 	this.materialOcean.uniforms.u_displacementMap = { type: "t", value: this.displacementMapFramebuffer };
-	this.materialOcean.uniforms.u_normalMap = { type: "t", value: this.normalMapFramebuffer }; 
-	this.materialOcean.uniforms.u_oceanColor = { type: "v3", value: this.oceanColor }; 
+	this.materialOcean.uniforms.u_normalMap = { type: "t", value: this.normalMapFramebuffer };
+	this.materialOcean.uniforms.u_oceanColor = { type: "v3", value: this.oceanColor };
 	this.materialOcean.uniforms.u_skyColor = { type: "v3", value: this.skyColor };
 	this.materialOcean.uniforms.u_sunDirection = { type: "v3", value: new THREE.Vector3( this.sunDirectionX, this.sunDirectionY, this.sunDirectionZ ) };
 	this.materialOcean.uniforms.u_exposure = { type: "f", value: this.exposure };
@@ -193,136 +194,170 @@
 
 	// Create the simulation plane
 	this.screenQuad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ) );
-	this.scene.add(this.screenQuad);
+	this.scene.add( this.screenQuad );
 
 	// Initialise spectrum data
 	this.generateSeedPhaseTexture();
 
 	// Generate the ocean mesh
 	this.generateMesh();
+
 };
 
 THREE.Ocean.prototype.generateMesh = function () {
 
 	var geometry = new THREE.PlaneBufferGeometry( this.geometrySize, this.geometrySize, this.geometryResolution, this.geometryResolution );
 
-	geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+	geometry.rotateX( - Math.PI / 2 );
 
 	this.oceanMesh = new THREE.Mesh( geometry, this.materialOcean );
+
 };
 
 THREE.Ocean.prototype.render = function () {
+
 	this.scene.overrideMaterial = null;
-	
-	if (this.changed)
+
+	if ( this.changed )
 		this.renderInitialSpectrum();
-	
+
 	this.renderWavePhase();
 	this.renderSpectrum();
 	this.renderSpectrumFFT();
 	this.renderNormalMap();
 	this.scene.overrideMaterial = null;
+
 };
 
 THREE.Ocean.prototype.generateSeedPhaseTexture = function() {
+
 	// Setup the seed texture
 	this.pingPhase = true;
-	var phaseArray = new window.Float32Array(this.resolution * this.resolution * 4);
-	for (var i = 0; i < this.resolution; i ++) {
-		for (var j = 0; j < this.resolution; j ++) {
-			phaseArray[i * this.resolution * 4 + j * 4] =  Math.random() * 2.0 * Math.PI;
-			phaseArray[i * this.resolution * 4 + j * 4 + 1] = 0.0;
-			phaseArray[i * this.resolution * 4 + j * 4 + 2] = 0.0;
-			phaseArray[i * this.resolution * 4 + j * 4 + 3] = 0.0;
+	var phaseArray = new window.Float32Array( this.resolution * this.resolution * 4 );
+	for ( var i = 0; i < this.resolution; i ++ ) {
+
+		for ( var j = 0; j < this.resolution; j ++ ) {
+
+			phaseArray[ i * this.resolution * 4 + j * 4 ] =  Math.random() * 2.0 * Math.PI;
+			phaseArray[ i * this.resolution * 4 + j * 4 + 1 ] = 0.0;
+			phaseArray[ i * this.resolution * 4 + j * 4 + 2 ] = 0.0;
+			phaseArray[ i * this.resolution * 4 + j * 4 + 3 ] = 0.0;
+
 		}
+
 	}
-	
-	this.pingPhaseTexture = new THREE.DataTexture(phaseArray, this.resolution, this.resolution, THREE.RGBAFormat);
-	this.pingPhaseTexture.minFilter = THREE.NearestFilter;
-	this.pingPhaseTexture.magFilter = THREE.NearestFilter;
+
+	this.pingPhaseTexture = new THREE.DataTexture( phaseArray, this.resolution, this.resolution, THREE.RGBAFormat );
 	this.pingPhaseTexture.wrapS = THREE.ClampToEdgeWrapping;
 	this.pingPhaseTexture.wrapT = THREE.ClampToEdgeWrapping;
 	this.pingPhaseTexture.type = THREE.FloatType;
 	this.pingPhaseTexture.needsUpdate = true;
+
 };
 
 THREE.Ocean.prototype.renderInitialSpectrum = function () {
+
 	this.scene.overrideMaterial = this.materialInitialSpectrum;
 	this.materialInitialSpectrum.uniforms.u_wind.value.set( this.windX, this.windY );
 	this.materialInitialSpectrum.uniforms.u_size.value = this.size;
-	this.renderer.render(this.scene, this.oceanCamera, this.initialSpectrumFramebuffer, true);
+	this.renderer.render( this.scene, this.oceanCamera, this.initialSpectrumFramebuffer, true );
+
 };
 
 THREE.Ocean.prototype.renderWavePhase = function () {
+
 	this.scene.overrideMaterial = this.materialPhase;
 	this.screenQuad.material = this.materialPhase;
-	if (this.initial) {
+	if ( this.initial ) {
+
 		this.materialPhase.uniforms.u_phases.value = this.pingPhaseTexture;
 		this.initial = false;
+
 	}else {
+
 		this.materialPhase.uniforms.u_phases.value = this.pingPhase ? this.pingPhaseFramebuffer  : this.pongPhaseFramebuffer;
+
 	}
 	this.materialPhase.uniforms.u_deltaTime.value = this.deltaTime;
 	this.materialPhase.uniforms.u_size.value = this.size;
-	this.renderer.render(this.scene, this.oceanCamera, this.pingPhase ? this.pongPhaseFramebuffer : this.pingPhaseFramebuffer);
-	this.pingPhase = !this.pingPhase;
+	this.renderer.render( this.scene, this.oceanCamera, this.pingPhase ? this.pongPhaseFramebuffer : this.pingPhaseFramebuffer );
+	this.pingPhase = ! this.pingPhase;
+
 };
 
 THREE.Ocean.prototype.renderSpectrum = function () {
+
 	this.scene.overrideMaterial = this.materialSpectrum;
 	this.materialSpectrum.uniforms.u_initialSpectrum.value = this.initialSpectrumFramebuffer;
 	this.materialSpectrum.uniforms.u_phases.value = this.pingPhase ? this.pingPhaseFramebuffer : this.pongPhaseFramebuffer;
 	this.materialSpectrum.uniforms.u_choppiness.value = this.choppiness ;
 	this.materialSpectrum.uniforms.u_size.value = this.size ;
-	this.renderer.render(this.scene, this.oceanCamera, this.spectrumFramebuffer);
+	this.renderer.render( this.scene, this.oceanCamera, this.spectrumFramebuffer );
+
 };
 
 THREE.Ocean.prototype.renderSpectrumFFT = function() {
+
 	// GPU FFT using Stockham formulation
-	var iterations = Math.log( this.resolution ) / Math.log(2); // log2
-	
+	var iterations = Math.log( this.resolution ) / Math.log( 2 ); // log2
+
 	this.scene.overrideMaterial = this.materialOceanHorizontal;
 
-	for (var i = 0; i < iterations; i ++) {
-		if (i === 0) {
+	for ( var i = 0; i < iterations; i ++ ) {
+
+		if ( i === 0 ) {
+
 			this.materialOceanHorizontal.uniforms.u_input.value = this.spectrumFramebuffer;
-			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow(2, (i % (iterations)) + 1);
-			this.renderer.render(this.scene, this.oceanCamera, this.pingTransformFramebuffer);
-		} 
-		else if (i % 2 === 1) {
+			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
+
+		} else if ( i % 2 === 1 ) {
+
 			this.materialOceanHorizontal.uniforms.u_input.value = this.pingTransformFramebuffer;
-			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow(2, (i % (iterations)) + 1);
-			this.renderer.render(this.scene, this.oceanCamera, this.pongTransformFramebuffer);
-		}
-		else {
+			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pongTransformFramebuffer );
+
+		} else {
+
 			this.materialOceanHorizontal.uniforms.u_input.value = this.pongTransformFramebuffer;
-			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow(2, (i % (iterations)) + 1);
-			this.renderer.render(this.scene, this.oceanCamera, this.pingTransformFramebuffer);
+			this.materialOceanHorizontal.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
+
 		}
+
 	}
 	this.scene.overrideMaterial = this.materialOceanVertical;
-	for (var i = iterations; i < iterations * 2; i ++) {
-		if (i === iterations * 2 - 1) {
-			this.materialOceanVertical.uniforms.u_input.value = (iterations % 2 === 0) ? this.pingTransformFramebuffer : this.pongTransformFramebuffer;
-			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow(2, (i % (iterations)) + 1);
-			this.renderer.render(this.scene, this.oceanCamera, this.displacementMapFramebuffer);
-		}
-		else if (i % 2 === 1) {
+	for ( var i = iterations; i < iterations * 2; i ++ ) {
+
+		if ( i === iterations * 2 - 1 ) {
+
+			this.materialOceanVertical.uniforms.u_input.value = ( iterations % 2 === 0 ) ? this.pingTransformFramebuffer : this.pongTransformFramebuffer;
+			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.displacementMapFramebuffer );
+
+		} else if ( i % 2 === 1 ) {
+
 			this.materialOceanVertical.uniforms.u_input.value = this.pingTransformFramebuffer;
-			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow(2, (i % (iterations)) + 1);
-			this.renderer.render(this.scene, this.oceanCamera, this.pongTransformFramebuffer);
-		}
-		else {
+			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pongTransformFramebuffer );
+
+		} else {
+
 			this.materialOceanVertical.uniforms.u_input.value = this.pongTransformFramebuffer;
-			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow(2, (i % (iterations)) + 1);
-			this.renderer.render(this.scene, this.oceanCamera, this.pingTransformFramebuffer);
+			this.materialOceanVertical.uniforms.u_subtransformSize.value = Math.pow( 2, ( i % ( iterations ) ) + 1 );
+			this.renderer.render( this.scene, this.oceanCamera, this.pingTransformFramebuffer );
+
 		}
+
 	}
+
 };
 
 THREE.Ocean.prototype.renderNormalMap = function () {
+
 	this.scene.overrideMaterial = this.materialNormal;
-	if (this.changed) this.materialNormal.uniforms.u_size.value = this.size;
+	if ( this.changed ) this.materialNormal.uniforms.u_size.value = this.size;
 	this.materialNormal.uniforms.u_displacementMap.value = this.displacementMapFramebuffer;
-	this.renderer.render(this.scene, this.oceanCamera, this.normalMapFramebuffer, true);
+	this.renderer.render( this.scene, this.oceanCamera, this.normalMapFramebuffer, true );
+
 };

+ 69 - 46
examples/js/Octree.js

@@ -7,7 +7,9 @@
  * based on Dynamic Octree by Piko3D @ http://www.piko3d.com/ and Octree by Marek Pawlowski @ pawlowski.it
  *
  */
- ( function ( THREE ) { "use strict";
+ ( function ( THREE ) {
+
+	"use strict";
 	
 	/*===================================================
 
@@ -16,15 +18,21 @@
 	=====================================================*/
 	
 	function isNumber ( n ) {
-		return !isNaN( n ) && isFinite( n );
+
+		return ! isNaN( n ) && isFinite( n );
+
 	}
 	
 	function isArray ( target ) {
+
 		return Object.prototype.toString.call( target ) === '[object Array]';
+
 	}
 	
 	function toArray ( target ) {
+
 		return target ? ( isArray ( target ) !== true ? [ target ] : target ) : [];
+
 	}
 	
 	function indexOfValue( array, value ) {
@@ -39,7 +47,7 @@
 			
 		}
 		
-		return -1;
+		return - 1;
 		
 	}
 	
@@ -55,7 +63,7 @@
 			
 		}
 		
-		return -1;
+		return - 1;
 		
 	}
 
@@ -77,7 +85,7 @@
 		
 		this.nodeCount = 0;
 		
-		this.INDEX_INSIDE_CROSS = -1;
+		this.INDEX_INSIDE_CROSS = - 1;
 		this.INDEX_OUTSIDE_OFFSET = 2;
 		
 		this.INDEX_OUTSIDE_POS_X = isNumber( parameters.INDEX_OUTSIDE_POS_X ) ? parameters.INDEX_OUTSIDE_POS_X : 0;
@@ -89,11 +97,11 @@
 		
 		this.INDEX_OUTSIDE_MAP = [];
 		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_POS_X ] = { index: this.INDEX_OUTSIDE_POS_X, count: 0, x: 1, y: 0, z: 0 };
-		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_X ] = { index: this.INDEX_OUTSIDE_NEG_X, count: 0, x: -1, y: 0, z: 0 };
+		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_X ] = { index: this.INDEX_OUTSIDE_NEG_X, count: 0, x: - 1, y: 0, z: 0 };
 		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_POS_Y ] = { index: this.INDEX_OUTSIDE_POS_Y, count: 0, x: 0, y: 1, z: 0 };
-		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_Y ] = { index: this.INDEX_OUTSIDE_NEG_Y, count: 0, x: 0, y: -1, z: 0 };
+		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_Y ] = { index: this.INDEX_OUTSIDE_NEG_Y, count: 0, x: 0, y: - 1, z: 0 };
 		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_POS_Z ] = { index: this.INDEX_OUTSIDE_POS_Z, count: 0, x: 0, y: 0, z: 1 };
-		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_Z ] = { index: this.INDEX_OUTSIDE_NEG_Z, count: 0, x: 0, y: 0, z: -1 };
+		this.INDEX_OUTSIDE_MAP[ this.INDEX_OUTSIDE_NEG_Z ] = { index: this.INDEX_OUTSIDE_NEG_Z, count: 0, x: 0, y: 0, z: - 1 };
 		
 		this.FLAG_POS_X = 1 << ( this.INDEX_OUTSIDE_POS_X + 1 );
 		this.FLAG_NEG_X = 1 << ( this.INDEX_OUTSIDE_NEG_X + 1 );
@@ -194,13 +202,13 @@
 			
 			// check uuid to avoid duplicates
 			
-			if ( !object.uuid ) {
+			if ( ! object.uuid ) {
 				
 				object.uuid = THREE.Math.generateUUID();
 				
 			}
 			
-			if ( !this.objectsMap[ object.uuid ] ) {
+			if ( ! this.objectsMap[ object.uuid ] ) {
 				
 				// store
 				
@@ -287,7 +295,7 @@
 				
 				index = indexOfValue( this.objects, object );
 				
-				if ( index !== -1 ) {
+				if ( index !== - 1 ) {
 					
 					this.objects.splice( index, 1 );
 					
@@ -303,7 +311,7 @@
 						
 						index = indexOfValue( this.objectsData, objectData );
 						
-						if ( index !== -1 ) {
+						if ( index !== - 1 ) {
 							
 							this.objectsData.splice( index, 1 );
 							
@@ -319,7 +327,7 @@
 				
 				index = indexOfPropertyWithValue( this.objectsDeferred, 'object', object );
 				
-				if ( index !== -1 ) {
+				if ( index !== - 1 ) {
 					
 					this.objectsDeferred.splice( index, 1 );
 					
@@ -378,7 +386,7 @@
 				
 				// if position has changed since last organization of object in tree
 				
-				if ( node instanceof THREE.OctreeNode && !objectData.positionLast.equals( objectData.position ) ) {
+				if ( node instanceof THREE.OctreeNode && ! objectData.positionLast.equals( objectData.position ) ) {
 					
 					// get octant index of object within current node
 					
@@ -477,7 +485,7 @@
 			
 			// ensure radius (i.e. distance of ray) is a number
 			
-			if ( !( radius > 0 ) ) {
+			if ( ! ( radius > 0 ) ) {
 				
 				radius = Number.MAX_VALUE;
 				
@@ -520,7 +528,7 @@
 					
 					// if needed, create new result data
 					
-					if ( resultObjectIndex === -1 ) {
+					if ( resultObjectIndex === - 1 ) {
 						
 						resultData = {
 							object: object,
@@ -860,7 +868,7 @@
 			
 			node.indexOctant = indexOctant;
 			
-			if ( indexOfValue( this.nodesIndices, indexOctant ) === -1 ) {
+			if ( indexOfValue( this.nodesIndices, indexOctant ) === - 1 ) {
 				
 				this.nodesIndices.push( indexOctant );
 				
@@ -908,13 +916,13 @@
 			indexOctant = this.getOctantIndex( object );
 			
 			// if object fully contained by an octant, add to subtree
-			if ( indexOctant > -1 && this.nodesIndices.length > 0 ) {
+			if ( indexOctant > - 1 && this.nodesIndices.length > 0 ) {
 				
 				node = this.branch( indexOctant );
 				
 				node.addObject( object );
 				
-			} else if ( indexOctant < -1 && this.parent instanceof THREE.OctreeNode ) {
+			} else if ( indexOctant < - 1 && this.parent instanceof THREE.OctreeNode ) {
 				
 				// if object lies outside bounds, add to parent node
 				
@@ -926,7 +934,7 @@
 				
 				index = indexOfValue( this.objects, object );
 				
-				if ( index === -1 ) {
+				if ( index === - 1 ) {
 					
 					this.objects.push( object );
 					
@@ -992,7 +1000,7 @@
 		removeObjectRecursive: function ( object, removeData ) {
 			
 			var i, l,
-				index = -1,
+				index = - 1,
 				objectData,
 				node,
 				objectRemoved;
@@ -1006,7 +1014,7 @@
 				
 				index = indexOfValue( this.objects, object );
 				
-				if ( index !== -1 ) {
+				if ( index !== - 1 ) {
 					
 					this.objects.splice( index, 1 );
 					object.node = undefined;
@@ -1034,7 +1042,7 @@
 						
 						objectRemoved = true;
 						
-						if ( !objectData.faces && !objectData.vertices ) {
+						if ( ! objectData.faces && ! objectData.vertices ) {
 							
 							removeData.searchComplete = true;
 							break;
@@ -1115,12 +1123,12 @@
 				indexOctant = this.getOctantIndex( object );
 				
 				// if lies within octant
-				if ( indexOctant > -1 ) {
+				if ( indexOctant > - 1 ) {
 					
 					objectsSplit.push( object );
 					objectsSplitOctants.push( indexOctant );
 				
-				} else if ( indexOctant < -1 ) {
+				} else if ( indexOctant < - 1 ) {
 					
 					// lies outside radius
 					
@@ -1139,7 +1147,7 @@
 			
 			// if has objects to split
 			
-			if ( objectsSplit.length > 0) {
+			if ( objectsSplit.length > 0 ) {
 				
 				objectsRemaining = objectsRemaining.concat( this.split( objectsSplit, objectsSplitOctants ) );
 				
@@ -1147,7 +1155,7 @@
 			
 			// if has objects to expand
 			
-			if ( objectsExpand.length > 0) {
+			if ( objectsExpand.length > 0 ) {
 				
 				objectsRemaining = objectsRemaining.concat( this.expand( objectsExpand, objectsExpandOctants ) );
 				
@@ -1193,7 +1201,7 @@
 					
 					// if object contained by octant, branch this tree
 					
-					if ( indexOctant > -1 ) {
+					if ( indexOctant > - 1 ) {
 						
 						node = this.branch( indexOctant );
 						
@@ -1247,7 +1255,7 @@
 				radius = ( this.radiusOverlap ) * 0.5;
 				overlap = radius * this.tree.overlapPct;
 				radiusOffset = radius - overlap;
-				offset = this.utilVec31Branch.set( indexOctant & 1 ? radiusOffset : -radiusOffset, indexOctant & 2 ? radiusOffset : -radiusOffset, indexOctant & 4 ? radiusOffset : -radiusOffset );
+				offset = this.utilVec31Branch.set( indexOctant & 1 ? radiusOffset : - radiusOffset, indexOctant & 2 ? radiusOffset : - radiusOffset, indexOctant & 4 ? radiusOffset : - radiusOffset );
 				position = new THREE.Vector3().addVectors( this.position, offset );
 				
 				// node
@@ -1332,11 +1340,11 @@
 					
 					// if object outside this, include in calculations
 					
-					if ( indexOctant < -1 ) {
+					if ( indexOctant < - 1 ) {
 						
 						// convert octant index to outside flags
 						
-						flagsOutside = -indexOctant - this.tree.INDEX_OUTSIDE_OFFSET;
+						flagsOutside = - indexOctant - this.tree.INDEX_OUTSIDE_OFFSET;
 						
 						// check against bitwise flags
 						
@@ -1438,7 +1446,7 @@
 					// get this octant indices based on octant normal
 					
 					indexOctant = this.getOctantIndexFromPosition( octantX, octantY, octantZ );
-					indexOctantInverse = this.getOctantIndexFromPosition( -octantX, -octantY, -octantZ );
+					indexOctantInverse = this.getOctantIndexFromPosition( - octantX, - octantY, - octantZ );
 					
 					// properties
 					
@@ -1453,7 +1461,7 @@
 					// parent offset is difference between radius + overlap of parent and child
 					
 					radiusOffset = ( radiusParent + overlapParent ) - ( radius + overlap );
-					offset.set( indexOctant & 1 ? radiusOffset : -radiusOffset, indexOctant & 2 ? radiusOffset : -radiusOffset, indexOctant & 4 ? radiusOffset : -radiusOffset );
+					offset.set( indexOctant & 1 ? radiusOffset : - radiusOffset, indexOctant & 2 ? radiusOffset : - radiusOffset, indexOctant & 4 ? radiusOffset : - radiusOffset );
 					position = new THREE.Vector3().addVectors( this.position, offset );
 					
 					// parent
@@ -1735,7 +1743,7 @@
 					
 				}
 				
-				objectData.indexOctant = -indexOctant - this.tree.INDEX_OUTSIDE_OFFSET;
+				objectData.indexOctant = - indexOctant - this.tree.INDEX_OUTSIDE_OFFSET;
 				
 				return objectData.indexOctant;
 				
@@ -1743,13 +1751,13 @@
 			
 			// return octant index from delta xyz
 			
-			if ( deltaX - radiusObj > -overlap ) {
+			if ( deltaX - radiusObj > - overlap ) {
 				
 				// x right
 				
 				indexOctant = indexOctant | 1;
 				
-			} else if ( !( deltaX + radiusObj < overlap ) ) {
+			} else if ( ! ( deltaX + radiusObj < overlap ) ) {
 				
 				// x left
 				
@@ -1758,13 +1766,13 @@
 				
 			}
 			
-			if ( deltaY - radiusObj > -overlap ) {
+			if ( deltaY - radiusObj > - overlap ) {
 				
 				// y right
 				
 				indexOctant = indexOctant | 2;
 				
-			} else if ( !( deltaY + radiusObj < overlap ) ) {
+			} else if ( ! ( deltaY + radiusObj < overlap ) ) {
 				
 				// y left
 				
@@ -1774,13 +1782,13 @@
 			}
 			
 			
-			if ( deltaZ - radiusObj > -overlap ) {
+			if ( deltaZ - radiusObj > - overlap ) {
 				
 				// z right
 				
 				indexOctant = indexOctant | 4;
 				
-			} else if ( !( deltaZ + radiusObj < overlap ) ) {
+			} else if ( ! ( deltaZ + radiusObj < overlap ) ) {
 				
 				// z left
 				
@@ -1870,21 +1878,33 @@
 				pz = position.z;
 			
 			if ( px < this.left ) {
+
 				distance -= Math.pow( px - this.left, 2 );
+
 			} else if ( px > this.right ) {
+
 				distance -= Math.pow( px - this.right, 2 );
+
 			}
 			
 			if ( py < this.bottom ) {
+
 				distance -= Math.pow( py - this.bottom, 2 );
+
 			} else if ( py > this.top ) {
+
 				distance -= Math.pow( py - this.top, 2 );
+
 			}
 			
 			if ( pz < this.back ) {
+
 				distance -= Math.pow( pz - this.back, 2 );
+
 			} else if ( pz > this.front ) {
+
 				distance -= Math.pow( pz - this.front, 2 );
+
 			}
 			
 			return distance >= 0;
@@ -1905,20 +1925,23 @@
 				t4 = ( this.top - origin.y ) * directionPct.y,
 				t5 = ( this.back - origin.z ) * directionPct.z,
 				t6 = ( this.front - origin.z ) * directionPct.z,
-				tmax = Math.min( Math.min( Math.max( t1, t2), Math.max( t3, t4) ), Math.max( t5, t6) ),
+				tmax = Math.min( Math.min( Math.max( t1, t2 ), Math.max( t3, t4 ) ), Math.max( t5, t6 ) ),
 				tmin;
 
 			// ray would intersect in reverse direction, i.e. this is behind ray
-			if (tmax < 0)
-			{
+			if ( tmax < 0 ) {
+
 				return false;
+
 			}
 			
-			tmin = Math.max( Math.max( Math.min( t1, t2), Math.min( t3, t4)), Math.min( t5, t6));
+			tmin = Math.max( Math.max( Math.min( t1, t2 ), Math.min( t3, t4 ) ), Math.min( t5, t6 ) );
 			
 			// if tmin > tmax or tmin > ray distance, ray doesn't intersect AABB
 			if ( tmin > tmax || tmin > distance ) {
+
 				return false;
+
 			}
 			
 			return true;
@@ -1942,7 +1965,7 @@
 				
 			} else {
 
-				depth = !depth || this.depth > depth ? this.depth : depth;
+				depth = ! depth || this.depth > depth ? this.depth : depth;
 
 			}
 
@@ -2111,4 +2134,4 @@
 		
 	};
 
-}( THREE ) );
+}( THREE ) );

+ 15 - 3
examples/js/PRNG.js

@@ -4,8 +4,20 @@
 var PRNG = function () {
 
 	this.seed = 1;
-	this.next = function() { return (this.gen() / 2147483647); };
-	this.nextRange = function(min, max)	{ return min + ((max - min) * this.next()) };
-	this.gen = function() { return this.seed = (this.seed * 16807) % 2147483647; };
+	this.next = function() {
+
+		return ( this.gen() / 2147483647 );
+
+	};
+	this.nextRange = function( min, max )	{
+
+		return min + ( ( max - min ) * this.next() )
+
+	};
+	this.gen = function() {
+
+		return this.seed = ( this.seed * 16807 ) % 2147483647;
+
+	};
 
 };

+ 72 - 57
examples/js/ParametricGeometries.js

@@ -8,37 +8,46 @@
 
 THREE.ParametricGeometries = {
 
-	klein: function (v, u) {
+	klein: function ( v, u ) {
+
 		u *= Math.PI;
 		v *= 2 * Math.PI;
 
 		u = u * 2;
 		var x, y, z;
-		if (u < Math.PI) {
-			x = 3 * Math.cos(u) * (1 + Math.sin(u)) + (2 * (1 - Math.cos(u) / 2)) * Math.cos(u) * Math.cos(v);
-			z = -8 * Math.sin(u) - 2 * (1 - Math.cos(u) / 2) * Math.sin(u) * Math.cos(v);
+		if ( u < Math.PI ) {
+
+			x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( u ) * Math.cos( v );
+			z = - 8 * Math.sin( u ) - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( u ) * Math.cos( v );
+
 		} else {
-			x = 3 * Math.cos(u) * (1 + Math.sin(u)) + (2 * (1 - Math.cos(u) / 2)) * Math.cos(v + Math.PI);
-			z = -8 * Math.sin(u);
+
+			x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( v + Math.PI );
+			z = - 8 * Math.sin( u );
+
 		}
 
-		y = -2 * (1 - Math.cos(u) / 2) * Math.sin(v);
+		y = - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( v );
+
+		return new THREE.Vector3( x, y, z );
 
-		return new THREE.Vector3(x, y, z);
 	},
 
-	plane: function (width, height) {
+	plane: function ( width, height ) {
+
+		return function( u, v ) {
 
-		return function(u, v) {
 			var x = u * width;
 			var y = 0;
 			var z = v * height;
 
-			return new THREE.Vector3(x, y, z);
+			return new THREE.Vector3( x, y, z );
+
 		};
+
 	},
 
-	mobius: function(u, t) {
+	mobius: function( u, t ) {
 
 		// flat mobius strip
 		// http://www.wolframalpha.com/input/?i=M%C3%B6bius+strip+parametric+equations&lk=1&a=ClashPrefs_*Surface.MoebiusStrip.SurfaceProperty.ParametricEquations-
@@ -48,14 +57,14 @@ THREE.ParametricGeometries = {
 		var x, y, z;
 
 		var a = 2;
-		x = Math.cos(v) * (a + u * Math.cos(v / 2));
-		y = Math.sin(v) * (a + u * Math.cos(v / 2));
-		z = u * Math.sin(v / 2);
-		return new THREE.Vector3(x, y, z);
+		x = Math.cos( v ) * ( a + u * Math.cos( v / 2 ) );
+		y = Math.sin( v ) * ( a + u * Math.cos( v / 2 ) );
+		z = u * Math.sin( v / 2 );
+		return new THREE.Vector3( x, y, z );
 
 	},
 
-	mobius3d: function(u, t) {
+	mobius3d: function( u, t ) {
 
 		// volumetric mobius strip
 		u *= Math.PI;
@@ -65,11 +74,12 @@ THREE.ParametricGeometries = {
 		var phi = u / 2;
 		var major = 2.25, a = 0.125, b = 0.65;
 		var x, y, z;
-		x = a * Math.cos(t) * Math.cos(phi) - b * Math.sin(t) * Math.sin(phi);
-		z = a * Math.cos(t) * Math.sin(phi) + b * Math.sin(t) * Math.cos(phi);
-		y = (major + x) * Math.sin(u);
-		x = (major + x) * Math.cos(u);
-		return new THREE.Vector3(x, y, z);
+		x = a * Math.cos( t ) * Math.cos( phi ) - b * Math.sin( t ) * Math.sin( phi );
+		z = a * Math.cos( t ) * Math.sin( phi ) + b * Math.sin( t ) * Math.cos( phi );
+		y = ( major + x ) * Math.sin( u );
+		x = ( major + x ) * Math.cos( u );
+		return new THREE.Vector3( x, y, z );
+
 	}
 
 };
@@ -81,14 +91,14 @@ THREE.ParametricGeometries = {
  *
  *********************************************/
 
-THREE.ParametricGeometries.TubeGeometry = function(path, segments, radius, segmentsRadius, closed, debug) {
+THREE.ParametricGeometries.TubeGeometry = function( path, segments, radius, segmentsRadius, closed, debug ) {
 
 	this.path = path;
 	this.segments = segments || 64;
 	this.radius = radius || 1;
 	this.segmentsRadius = segmentsRadius || 8;
 	this.closed = closed || false;
-	if (debug) this.debug = new THREE.Object3D();
+	if ( debug ) this.debug = new THREE.Object3D();
 
 
 	var scope = this,
@@ -102,50 +112,52 @@ THREE.ParametricGeometries.TubeGeometry = function(path, segments, radius, segme
 		cx, cy, pos, pos2 = new THREE.Vector3(),
 		i, j, ip, jp, a, b, c, d, uva, uvb, uvc, uvd;
 
-	var frames = new THREE.TubeGeometry.FrenetFrames(path, segments, closed),
+	var frames = new THREE.TubeGeometry.FrenetFrames( path, segments, closed ),
 		tangents = frames.tangents,
 		normals = frames.normals,
 		binormals = frames.binormals;
 
-		// proxy internals
+	// proxy internals
 	this.tangents = tangents;
 	this.normals = normals;
 	this.binormals = binormals;
 
 
 
-	var ParametricTube = function(u, v) {
+	var ParametricTube = function( u, v ) {
+
 		v *= 2 * Math.PI;
 
-		i = u * (numpoints - 1);
-		i = Math.floor(i);
+		i = u * ( numpoints - 1 );
+		i = Math.floor( i );
 
-		pos = path.getPointAt(u);
+		pos = path.getPointAt( u );
 
-		tangent = tangents[i];
-		normal = normals[i];
-		binormal = binormals[i];
+		tangent = tangents[ i ];
+		normal = normals[ i ];
+		binormal = binormals[ i ];
 
-		if (scope.debug) {
+		if ( scope.debug ) {
 
-			scope.debug.add(new THREE.ArrowHelper(tangent, pos, radius, 0x0000ff));
-			scope.debug.add(new THREE.ArrowHelper(normal, pos, radius, 0xff0000));
-			scope.debug.add(new THREE.ArrowHelper(binormal, pos, radius, 0x00ff00));
+			scope.debug.add( new THREE.ArrowHelper( tangent, pos, radius, 0x0000ff ) );
+			scope.debug.add( new THREE.ArrowHelper( normal, pos, radius, 0xff0000 ) );
+			scope.debug.add( new THREE.ArrowHelper( binormal, pos, radius, 0x00ff00 ) );
 
 		}
 
-		cx = -scope.radius * Math.cos(v); // TODO: Hack: Negating it so it faces outside.
-		cy = scope.radius * Math.sin(v);
+		cx = - scope.radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
+		cy = scope.radius * Math.sin( v );
 
-		pos2.copy(pos);
+		pos2.copy( pos );
 		pos2.x += cx * normal.x + cy * binormal.x;
 		pos2.y += cx * normal.y + cy * binormal.y;
 		pos2.z += cx * normal.z + cy * binormal.z;
 
 		return pos2.clone();
+
 	};
 
-	THREE.ParametricGeometry.call(this, ParametricTube, segments, segmentsRadius);
+	THREE.ParametricGeometry.call( this, ParametricTube, segments, segmentsRadius );
 
 };
 
@@ -176,17 +188,17 @@ THREE.ParametricGeometries.TorusKnotGeometry = function ( radius, tube, segments
 		function() {
 		},
 
-		function(t) {
+		function( t ) {
 
 			t *= Math.PI * 2;
 
 			var r = 0.5;
 
-			var tx = (1 + r * Math.cos(q * t)) * Math.cos(p * t),
-				ty = (1 + r * Math.cos(q * t)) * Math.sin(p * t),
-				tz = r * Math.sin(q * t);
+			var tx = ( 1 + r * Math.cos( q * t ) ) * Math.cos( p * t ),
+				ty = ( 1 + r * Math.cos( q * t ) ) * Math.sin( p * t ),
+				tz = r * Math.sin( q * t );
 
-			return new THREE.Vector3(tx, ty * heightScale, tz).multiplyScalar(radius);
+			return new THREE.Vector3( tx, ty * heightScale, tz ).multiplyScalar( radius );
 
 		}
 
@@ -209,21 +221,23 @@ THREE.ParametricGeometries.TorusKnotGeometry.prototype.constructor = THREE.Param
   * Parametric Replacement for SphereGeometry
   *
   *********************************************/
-THREE.ParametricGeometries.SphereGeometry = function(size, u, v) {
+THREE.ParametricGeometries.SphereGeometry = function( size, u, v ) {
+
+	function sphere( u, v ) {
 
-	function sphere(u, v) {
 		u *= Math.PI;
 		v *= 2 * Math.PI;
 
-		var x = size * Math.sin(u) * Math.cos(v);
-		var y = size * Math.sin(u) * Math.sin(v);
-		var z = size * Math.cos(u);
+		var x = size * Math.sin( u ) * Math.cos( v );
+		var y = size * Math.sin( u ) * Math.sin( v );
+		var z = size * Math.cos( u );
+
 
+		return new THREE.Vector3( x, y, z );
 
-		return new THREE.Vector3(x, y, z);
 	}
 
-	THREE.ParametricGeometry.call(this, sphere, u, v, !true);
+	THREE.ParametricGeometry.call( this, sphere, u, v, ! true );
 
 };
 
@@ -237,18 +251,19 @@ THREE.ParametricGeometries.SphereGeometry.prototype.constructor = THREE.Parametr
   *
   *********************************************/
 
-THREE.ParametricGeometries.PlaneGeometry = function(width, depth, segmentsWidth, segmentsDepth) {
+THREE.ParametricGeometries.PlaneGeometry = function( width, depth, segmentsWidth, segmentsDepth ) {
 
-	function plane(u, v) {
+	function plane( u, v ) {
 
 		var x = u * width;
 		var y = 0;
 		var z = v * depth;
 
-		return new THREE.Vector3(x, y, z);
+		return new THREE.Vector3( x, y, z );
+
 	}
 
-	THREE.ParametricGeometry.call(this, plane, segmentsWidth, segmentsDepth);
+	THREE.ParametricGeometry.call( this, plane, segmentsWidth, segmentsDepth );
 
 };
 

+ 29 - 31
examples/js/ShaderDeferred.js

@@ -23,7 +23,7 @@ THREE.DeferredShaderChunk = {
 
 		"}"
 
-	].join("\n"),
+	].join( "\n" ),
 
 	computeVertexPositionVS: [
 
@@ -41,13 +41,13 @@ THREE.DeferredShaderChunk = {
 		"vertexPositionVS.xyz /= vertexPositionVS.w;",
 		"vertexPositionVS.w = 1.0;"
 
-	].join("\n"),
+	].join( "\n" ),
 
 	computeNormal: [
 
 		"vec3 normal = normalDepth.xyz * 2.0 - 1.0;"
 
-	].join("\n"),
+	].join( "\n" ),
 
 	unpackColorMap: [
 
@@ -59,7 +59,7 @@ THREE.DeferredShaderChunk = {
 		"float wrapAround = sign( colorMap.z );",
 		"float additiveSpecular = sign( colorMap.y );"
 
-	].join("\n"),
+	].join( "\n" ),
 
 	computeDiffuse: [
 
@@ -85,7 +85,7 @@ THREE.DeferredShaderChunk = {
 
 		"}"
 
-	].join("\n"),
+	].join( "\n" ),
 
 	computeSpecular: [
 
@@ -103,14 +103,14 @@ THREE.DeferredShaderChunk = {
 		"vec3 schlick = specularColor + vec3( 1.0 - specularColor ) * pow( 1.0 - dot( lightVector, halfVector ), 5.0 );",
 		"vec3 specular = schlick * max( pow( dotNormalHalf, shininess ), 0.0 ) * diffuse * specularNormalization;"
 
-	].join("\n"),
+	].join( "\n" ),
 
 	combine: [
 
 		"vec3 light = lightIntensity * lightColor;",
 		"gl_FragColor = vec4( light * ( albedo * diffuse + specular ), attenuation );"
 
-	].join("\n")
+	].join( "\n" )
 
 };
 
@@ -305,7 +305,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader : [
 
@@ -346,7 +346,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -364,8 +364,6 @@ THREE.ShaderDeferred = {
 
 			"#ifdef USE_BUMPMAP",
 
-				"#extension GL_OES_standard_derivatives : enable\n",
-
 				"varying vec2 vUv;",
 				"varying vec3 vViewPosition;",
 
@@ -391,7 +389,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader : [
 
@@ -434,7 +432,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -528,7 +526,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader : [
 
@@ -542,7 +540,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -556,7 +554,7 @@ THREE.ShaderDeferred = {
 			viewWidth: 		{ type: "f", value: 800 },
 			viewHeight: 	{ type: "f", value: 600 },
 
-			lightPositionVS:{ type: "v3", value: new THREE.Vector3( 0, 0, 0 ) },
+			lightPositionVS: { type: "v3", value: new THREE.Vector3( 0, 0, 0 ) },
 			lightColor: 	{ type: "c", value: new THREE.Color( 0x000000 ) },
 			lightIntensity: { type: "f", value: 1.0 },
 			lightRadius: 	{ type: "f", value: 1.0 }
@@ -614,7 +612,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader : [
 
@@ -627,7 +625,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -641,8 +639,8 @@ THREE.ShaderDeferred = {
 			viewWidth: 		{ type: "f", value: 800 },
 			viewHeight: 	{ type: "f", value: 600 },
 
-			lightPositionVS :{ type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
-			lightDirectionVS:{ type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
+			lightPositionVS : { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
+			lightDirectionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
 			lightColor: 	{ type: "c", value: new THREE.Color( 0x000000 ) },
 			lightIntensity: { type: "f", value: 1.0 },
 			lightDistance: 	{ type: "f", value: 1.0 },
@@ -718,7 +716,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader : [
 
@@ -730,7 +728,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -788,7 +786,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader : [
 
@@ -800,7 +798,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -886,7 +884,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader : [
 
@@ -898,7 +896,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -913,7 +911,7 @@ THREE.ShaderDeferred = {
 			viewHeight: 	{ type: "f", value: 600 },
 
 			lightPositionVS: { type: "v3", value: new THREE.Vector3( 0, 1, 0 ) },
-			lightNormalVS: 	 { type: "v3", value: new THREE.Vector3( 0, -1, 0 ) },
+			lightNormalVS: 	 { type: "v3", value: new THREE.Vector3( 0, - 1, 0 ) },
 			lightRightVS:  	 { type: "v3", value: new THREE.Vector3( 1, 0, 0 ) },
 			lightUpVS:  	 { type: "v3", value: new THREE.Vector3( 1, 0, 0 ) },
 
@@ -1041,7 +1039,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader : [
 
@@ -1053,7 +1051,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -1087,7 +1085,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader : [
 
@@ -1099,7 +1097,7 @@ THREE.ShaderDeferred = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	}
 

+ 6 - 6
examples/js/ShaderGodRays.js

@@ -71,7 +71,7 @@ THREE.ShaderGodRays = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		fragmentShader: [
 
@@ -157,7 +157,7 @@ THREE.ShaderGodRays = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -203,7 +203,7 @@ THREE.ShaderGodRays = {
 
 			"}"
 
-			].join("\n"),
+			].join( "\n" ),
 
 		fragmentShader: [
 
@@ -226,7 +226,7 @@ THREE.ShaderGodRays = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -273,7 +273,7 @@ THREE.ShaderGodRays = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		fragmentShader: [
 
@@ -301,7 +301,7 @@ THREE.ShaderGodRays = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	}
 

+ 37 - 43
examples/js/ShaderSkin.js

@@ -30,27 +30,27 @@ THREE.ShaderSkin = {
 
 			{
 
-			"enableBump"	: { type: "i", value: 0 },
-			"enableSpecular": { type: "i", value: 0 },
+				"enableBump"	: { type: "i", value: 0 },
+				"enableSpecular": { type: "i", value: 0 },
 
-			"tDiffuse"	: { type: "t", value: null },
-			"tBeckmann"	: { type: "t", value: null },
+				"tDiffuse"	: { type: "t", value: null },
+				"tBeckmann"	: { type: "t", value: null },
 
-			"diffuse":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
-			"specular": { type: "c", value: new THREE.Color( 0x111111 ) },
-			"opacity": 	  { type: "f", value: 1 },
+				"diffuse":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
+				"specular": { type: "c", value: new THREE.Color( 0x111111 ) },
+				"opacity": 	  { type: "f", value: 1 },
 
-			"uRoughness": 	  		{ type: "f", value: 0.15 },
-			"uSpecularBrightness": 	{ type: "f", value: 0.75 },
+				"uRoughness": 	  		{ type: "f", value: 0.15 },
+				"uSpecularBrightness": 	{ type: "f", value: 0.75 },
 
-			"bumpMap"	: { type: "t", value: null },
-			"bumpScale" : { type: "f", value: 1 },
+				"bumpMap"	: { type: "t", value: null },
+				"bumpScale" : { type: "f", value: 1 },
 
-			"specularMap" : { type: "t", value: null },
+				"specularMap" : { type: "t", value: null },
 
-			"offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
+				"offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
 
-			"uWrapRGB":	{ type: "v3", value: new THREE.Vector3( 0.75, 0.375, 0.1875 ) }
+				"uWrapRGB":	{ type: "v3", value: new THREE.Vector3( 0.75, 0.375, 0.1875 ) }
 
 			}
 
@@ -197,9 +197,7 @@ THREE.ShaderSkin = {
 
 					"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 
-						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
-
-						"vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
+						"vec3 lVector = pointLightPosition[ i ] + vViewPosition.xyz;",
 
 						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
 
@@ -279,7 +277,7 @@ THREE.ShaderSkin = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader: [
 
@@ -338,26 +336,26 @@ THREE.ShaderSkin = {
 
 			{
 
-			"passID": { type: "i", value: 0 },
+				"passID": { type: "i", value: 0 },
 
-			"tDiffuse"	: { type: "t", value: null },
-			"tNormal"	: { type: "t", value: null },
+				"tDiffuse"	: { type: "t", value: null },
+				"tNormal"	: { type: "t", value: null },
 
-			"tBlur1"	: { type: "t", value: null },
-			"tBlur2"	: { type: "t", value: null },
-			"tBlur3"	: { type: "t", value: null },
-			"tBlur4"	: { type: "t", value: null },
+				"tBlur1"	: { type: "t", value: null },
+				"tBlur2"	: { type: "t", value: null },
+				"tBlur3"	: { type: "t", value: null },
+				"tBlur4"	: { type: "t", value: null },
 
-			"tBeckmann"	: { type: "t", value: null },
+				"tBeckmann"	: { type: "t", value: null },
 
-			"uNormalScale": { type: "f", value: 1.0 },
+				"uNormalScale": { type: "f", value: 1.0 },
 
-			"diffuse":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
-			"specular": { type: "c", value: new THREE.Color( 0x111111 ) },
-			"opacity": 	  { type: "f", value: 1 },
+				"diffuse":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
+				"specular": { type: "c", value: new THREE.Color( 0x111111 ) },
+				"opacity": 	  { type: "f", value: 1 },
 
-			"uRoughness": 	  		{ type: "f", value: 0.15 },
-			"uSpecularBrightness": 	{ type: "f", value: 0.75 }
+				"uRoughness": 	  		{ type: "f", value: 0.15 },
+				"uSpecularBrightness": 	{ type: "f", value: 0.75 }
 
 			}
 
@@ -570,7 +568,7 @@ THREE.ShaderSkin = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader: [
 
@@ -628,9 +626,7 @@ THREE.ShaderSkin = {
 
 					"for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
 
-						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
-
-						"vec3 lVector = lPosition.xyz - mvPosition.xyz;",
+						"vec3 lVector = pointLightPosition[ i ] - mvPosition.xyz;",
 
 						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
 
@@ -659,7 +655,7 @@ THREE.ShaderSkin = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShaderUV: [
 
@@ -717,9 +713,7 @@ THREE.ShaderSkin = {
 
 					"for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
 
-						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
-
-						"vec3 lVector = lPosition.xyz - mvPosition.xyz;",
+						"vec3 lVector = pointLightPosition[ i ] - mvPosition.xyz;",
 
 						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
 
@@ -735,7 +729,7 @@ THREE.ShaderSkin = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	},
 
@@ -762,7 +756,7 @@ THREE.ShaderSkin = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		fragmentShader: [
 
@@ -794,7 +788,7 @@ THREE.ShaderSkin = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	}
 

+ 25 - 26
examples/js/ShaderTerrain.js

@@ -23,32 +23,32 @@ THREE.ShaderTerrain = {
 
 			{
 
-			"enableDiffuse1"  : { type: "i", value: 0 },
-			"enableDiffuse2"  : { type: "i", value: 0 },
-			"enableSpecular"  : { type: "i", value: 0 },
-			"enableReflection": { type: "i", value: 0 },
+				"enableDiffuse1"  : { type: "i", value: 0 },
+				"enableDiffuse2"  : { type: "i", value: 0 },
+				"enableSpecular"  : { type: "i", value: 0 },
+				"enableReflection": { type: "i", value: 0 },
 
-			"tDiffuse1"	   : { type: "t", value: null },
-			"tDiffuse2"	   : { type: "t", value: null },
-			"tDetail"	   : { type: "t", value: null },
-			"tNormal"	   : { type: "t", value: null },
-			"tSpecular"	   : { type: "t", value: null },
-			"tDisplacement": { type: "t", value: null },
+				"tDiffuse1"	   : { type: "t", value: null },
+				"tDiffuse2"	   : { type: "t", value: null },
+				"tDetail"	   : { type: "t", value: null },
+				"tNormal"	   : { type: "t", value: null },
+				"tSpecular"	   : { type: "t", value: null },
+				"tDisplacement": { type: "t", value: null },
 
-			"uNormalScale": { type: "f", value: 1.0 },
+				"uNormalScale": { type: "f", value: 1.0 },
 
-			"uDisplacementBias": { type: "f", value: 0.0 },
-			"uDisplacementScale": { type: "f", value: 1.0 },
+				"uDisplacementBias": { type: "f", value: 0.0 },
+				"uDisplacementScale": { type: "f", value: 1.0 },
 
-			"diffuse": { type: "c", value: new THREE.Color( 0xeeeeee ) },
-			"specular": { type: "c", value: new THREE.Color( 0x111111 ) },
-			"shininess": { type: "f", value: 30 },
-			"opacity": { type: "f", value: 1 },
+				"diffuse": { type: "c", value: new THREE.Color( 0xeeeeee ) },
+				"specular": { type: "c", value: new THREE.Color( 0x111111 ) },
+				"shininess": { type: "f", value: 30 },
+				"opacity": { type: "f", value: 1 },
 
-			"uRepeatBase"    : { type: "v2", value: new THREE.Vector2( 1, 1 ) },
-			"uRepeatOverlay" : { type: "v2", value: new THREE.Vector2( 1, 1 ) },
+				"uRepeatBase"    : { type: "v2", value: new THREE.Vector2( 1, 1 ) },
+				"uRepeatOverlay" : { type: "v2", value: new THREE.Vector2( 1, 1 ) },
 
-			"uOffset" : { type: "v2", value: new THREE.Vector2( 0, 0 ) }
+				"uOffset" : { type: "v2", value: new THREE.Vector2( 0, 0 ) }
 
 			}
 
@@ -168,8 +168,7 @@ THREE.ShaderTerrain = {
 
 					"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 
-						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
-						"vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
+						"vec3 lVector = pointLightPosition[ i ] + vViewPosition.xyz;",
 
 						"float attenuation = calcLightAttenuation( length( lVector ), pointLightDistance[ i ], pointLightDecay[i] );",
 
@@ -198,7 +197,7 @@ THREE.ShaderTerrain = {
 
 					"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 
-						"vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );",
+						"vec3 dirVector = directionalLightDirection[ i ];",
 						"vec3 dirHalfVector = normalize( dirVector + viewPosition );",
 
 						"float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
@@ -222,7 +221,7 @@ THREE.ShaderTerrain = {
 
 					"for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
 
-						"vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );",
+						"vec3 lVector = hemisphereLightDirection[ i ];",
 
 						// diffuse
 
@@ -263,7 +262,7 @@ THREE.ShaderTerrain = {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		vertexShader: [
 
@@ -336,7 +335,7 @@ THREE.ShaderTerrain = {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	}
 

+ 177 - 177
examples/js/ShaderToon.js

@@ -12,320 +12,320 @@
 
 THREE.ShaderToon = {
 
-'toon1' : {
+	'toon1' : {
 
-	uniforms: {
+		uniforms: {
 
-		"uDirLightPos":	{ type: "v3", value: new THREE.Vector3() },
-		"uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
+			"uDirLightPos":	{ type: "v3", value: new THREE.Vector3() },
+			"uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
 
-		"uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) },
+			"uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) },
 
-		"uBaseColor":  { type: "c", value: new THREE.Color( 0xffffff ) }
+			"uBaseColor":  { type: "c", value: new THREE.Color( 0xffffff ) }
 
-	},
+		},
 
-	vertexShader: [
+		vertexShader: [
 
-		"varying vec3 vNormal;",
-		"varying vec3 vRefract;",
+			"varying vec3 vNormal;",
+			"varying vec3 vRefract;",
 
-		"void main() {",
+			"void main() {",
 
-			"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
-			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
-			"vec3 worldNormal = normalize ( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );",
+				"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+				"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+				"vec3 worldNormal = normalize ( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );",
 
-			"vNormal = normalize( normalMatrix * normal );",
+				"vNormal = normalize( normalMatrix * normal );",
 
-			"vec3 I = worldPosition.xyz - cameraPosition;",
-			"vRefract = refract( normalize( I ), worldNormal, 1.02 );",
+				"vec3 I = worldPosition.xyz - cameraPosition;",
+				"vRefract = refract( normalize( I ), worldNormal, 1.02 );",
 
-			"gl_Position = projectionMatrix * mvPosition;",
+				"gl_Position = projectionMatrix * mvPosition;",
 
-		"}"
+			"}"
 
-	].join("\n"),
+		].join( "\n" ),
 
-	fragmentShader: [
+		fragmentShader: [
 
-		"uniform vec3 uBaseColor;",
+			"uniform vec3 uBaseColor;",
 
-		"uniform vec3 uDirLightPos;",
-		"uniform vec3 uDirLightColor;",
+			"uniform vec3 uDirLightPos;",
+			"uniform vec3 uDirLightColor;",
 
-		"uniform vec3 uAmbientLightColor;",
+			"uniform vec3 uAmbientLightColor;",
 
-		"varying vec3 vNormal;",
+			"varying vec3 vNormal;",
 
-		"varying vec3 vRefract;",
+			"varying vec3 vRefract;",
 
-		"void main() {",
+			"void main() {",
 
-			"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
-			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
+				"float directionalLightWeighting = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
+				"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
 
-			"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
-			"intensity += length(lightWeighting) * 0.2;",
+				"float intensity = smoothstep( - 0.5, 1.0, pow( length(lightWeighting), 20.0 ) );",
+				"intensity += length(lightWeighting) * 0.2;",
 
-			"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
-			"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
-			"intensity = intensity * 0.2 + 0.3;",
+				"float cameraWeighting = dot( normalize( vNormal ), vRefract );",
+				"intensity += pow( 1.0 - length( cameraWeighting ), 6.0 );",
+				"intensity = intensity * 0.2 + 0.3;",
 
-			"if ( intensity < 0.50 ) {",
+				"if ( intensity < 0.50 ) {",
 
-				"gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
+					"gl_FragColor = vec4( 2.0 * intensity * uBaseColor, 1.0 );",
 
-			"} else {",
+				"} else {",
 
-				"gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
+					"gl_FragColor = vec4( 1.0 - 2.0 * ( 1.0 - intensity ) * ( 1.0 - uBaseColor ), 1.0 );",
 
-			"}",
+				"}",
 
-		"}"
+			"}"
 
-	].join("\n")
+		].join( "\n" )
 
-},
+	},
 
-'toon2' : {
+	'toon2' : {
 
-	uniforms: {
+		uniforms: {
 
-		"uDirLightPos":	{ type: "v3", value: new THREE.Vector3() },
-		"uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
+			"uDirLightPos":	{ type: "v3", value: new THREE.Vector3() },
+			"uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
 
-		"uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) },
+			"uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) },
 
-		"uBaseColor":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
-		"uLineColor1": { type: "c", value: new THREE.Color( 0x808080 ) },
-		"uLineColor2": { type: "c", value: new THREE.Color( 0x000000 ) },
-		"uLineColor3": { type: "c", value: new THREE.Color( 0x000000 ) },
-		"uLineColor4": { type: "c", value: new THREE.Color( 0x000000 ) }
+			"uBaseColor":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
+			"uLineColor1": { type: "c", value: new THREE.Color( 0x808080 ) },
+			"uLineColor2": { type: "c", value: new THREE.Color( 0x000000 ) },
+			"uLineColor3": { type: "c", value: new THREE.Color( 0x000000 ) },
+			"uLineColor4": { type: "c", value: new THREE.Color( 0x000000 ) }
 
-	},
+		},
 
-	vertexShader: [
+		vertexShader: [
 
-		"varying vec3 vNormal;",
+			"varying vec3 vNormal;",
 
-		"void main() {",
+			"void main() {",
 
-			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
-			"vNormal = normalize( normalMatrix * normal );",
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+				"vNormal = normalize( normalMatrix * normal );",
 
-		"}"
+			"}"
 
-	].join("\n"),
+		].join( "\n" ),
 
-	fragmentShader: [
+		fragmentShader: [
 
-		"uniform vec3 uBaseColor;",
-		"uniform vec3 uLineColor1;",
-		"uniform vec3 uLineColor2;",
-		"uniform vec3 uLineColor3;",
-		"uniform vec3 uLineColor4;",
+			"uniform vec3 uBaseColor;",
+			"uniform vec3 uLineColor1;",
+			"uniform vec3 uLineColor2;",
+			"uniform vec3 uLineColor3;",
+			"uniform vec3 uLineColor4;",
 
-		"uniform vec3 uDirLightPos;",
-		"uniform vec3 uDirLightColor;",
+			"uniform vec3 uDirLightPos;",
+			"uniform vec3 uDirLightColor;",
 
-		"uniform vec3 uAmbientLightColor;",
+			"uniform vec3 uAmbientLightColor;",
 
-		"varying vec3 vNormal;",
+			"varying vec3 vNormal;",
 
-		"void main() {",
+			"void main() {",
 
-			"float camera = max( dot( normalize( vNormal ), vec3( 0.0, 0.0, 1.0 ) ), 0.4);",
-			"float light = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
+				"float camera = max( dot( normalize( vNormal ), vec3( 0.0, 0.0, 1.0 ) ), 0.4);",
+				"float light = max( dot( normalize( vNormal ), uDirLightPos ), 0.0);",
 
-			"gl_FragColor = vec4( uBaseColor, 1.0 );",
+				"gl_FragColor = vec4( uBaseColor, 1.0 );",
 
-			"if ( length(uAmbientLightColor + uDirLightColor * light) < 1.00 ) {",
+				"if ( length(uAmbientLightColor + uDirLightColor * light) < 1.00 ) {",
 
-				"gl_FragColor *= vec4( uLineColor1, 1.0 );",
+					"gl_FragColor *= vec4( uLineColor1, 1.0 );",
 
-			"}",
+				"}",
+
+				"if ( length(uAmbientLightColor + uDirLightColor * camera) < 0.50 ) {",
 
-			"if ( length(uAmbientLightColor + uDirLightColor * camera) < 0.50 ) {",
+					"gl_FragColor *= vec4( uLineColor2, 1.0 );",
 
-				"gl_FragColor *= vec4( uLineColor2, 1.0 );",
+				"}",
 
-			"}",
+			"}"
 
-		"}"
+		].join( "\n" )
 
-	].join("\n")
+	},
 
-},
+	'hatching' : {
 
-'hatching' : {
+		uniforms: {
 
-	uniforms: {
+			"uDirLightPos":	{ type: "v3", value: new THREE.Vector3() },
+			"uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
 
-		"uDirLightPos":	{ type: "v3", value: new THREE.Vector3() },
-		"uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
+			"uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) },
 
-		"uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) },
+			"uBaseColor":  { type: "c", value: new THREE.Color( 0xffffff ) },
+			"uLineColor1": { type: "c", value: new THREE.Color( 0x000000 ) },
+			"uLineColor2": { type: "c", value: new THREE.Color( 0x000000 ) },
+			"uLineColor3": { type: "c", value: new THREE.Color( 0x000000 ) },
+			"uLineColor4": { type: "c", value: new THREE.Color( 0x000000 ) }
 
-		"uBaseColor":  { type: "c", value: new THREE.Color( 0xffffff ) },
-		"uLineColor1": { type: "c", value: new THREE.Color( 0x000000 ) },
-		"uLineColor2": { type: "c", value: new THREE.Color( 0x000000 ) },
-		"uLineColor3": { type: "c", value: new THREE.Color( 0x000000 ) },
-		"uLineColor4": { type: "c", value: new THREE.Color( 0x000000 ) }
+		},
 
-	},
+		vertexShader: [
 
-	vertexShader: [
+			"varying vec3 vNormal;",
 
-		"varying vec3 vNormal;",
+			"void main() {",
 
-		"void main() {",
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+				"vNormal = normalize( normalMatrix * normal );",
 
-			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
-			"vNormal = normalize( normalMatrix * normal );",
+			"}"
 
-		"}"
+		].join( "\n" ),
 
-	].join("\n"),
+		fragmentShader: [
 
-	fragmentShader: [
+			"uniform vec3 uBaseColor;",
+			"uniform vec3 uLineColor1;",
+			"uniform vec3 uLineColor2;",
+			"uniform vec3 uLineColor3;",
+			"uniform vec3 uLineColor4;",
 
-		"uniform vec3 uBaseColor;",
-		"uniform vec3 uLineColor1;",
-		"uniform vec3 uLineColor2;",
-		"uniform vec3 uLineColor3;",
-		"uniform vec3 uLineColor4;",
+			"uniform vec3 uDirLightPos;",
+			"uniform vec3 uDirLightColor;",
 
-		"uniform vec3 uDirLightPos;",
-		"uniform vec3 uDirLightColor;",
+			"uniform vec3 uAmbientLightColor;",
 
-		"uniform vec3 uAmbientLightColor;",
+			"varying vec3 vNormal;",
 
-		"varying vec3 vNormal;",
+			"void main() {",
 
-		"void main() {",
+				"float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);",
+				"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
 
-			"float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);",
-			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
+				"gl_FragColor = vec4( uBaseColor, 1.0 );",
 
-			"gl_FragColor = vec4( uBaseColor, 1.0 );",
+				"if ( length(lightWeighting) < 1.00 ) {",
 
-			"if ( length(lightWeighting) < 1.00 ) {",
+					"if ( mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {",
 
-				"if ( mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {",
+						"gl_FragColor = vec4( uLineColor1, 1.0 );",
 
-					"gl_FragColor = vec4( uLineColor1, 1.0 );",
+					"}",
 
 				"}",
 
-			"}",
+				"if ( length(lightWeighting) < 0.75 ) {",
 
-			"if ( length(lightWeighting) < 0.75 ) {",
+					"if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {",
 
-				"if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {",
-
-					"gl_FragColor = vec4( uLineColor2, 1.0 );",
+						"gl_FragColor = vec4( uLineColor2, 1.0 );",
 
+					"}",
 				"}",
-			"}",
 
-			"if ( length(lightWeighting) < 0.50 ) {",
+				"if ( length(lightWeighting) < 0.50 ) {",
 
-				"if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {",
+					"if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {",
 
-					"gl_FragColor = vec4( uLineColor3, 1.0 );",
+						"gl_FragColor = vec4( uLineColor3, 1.0 );",
 
+					"}",
 				"}",
-			"}",
 
-			"if ( length(lightWeighting) < 0.3465 ) {",
+				"if ( length(lightWeighting) < 0.3465 ) {",
 
-				"if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {",
+					"if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {",
 
-					"gl_FragColor = vec4( uLineColor4, 1.0 );",
+						"gl_FragColor = vec4( uLineColor4, 1.0 );",
 
+					"}",
 				"}",
-			"}",
 
-		"}"
+			"}"
 
-	].join("\n")
+		].join( "\n" )
 
-},
+	},
 
-'dotted' : {
+	'dotted' : {
 
-	uniforms: {
+		uniforms: {
 
-		"uDirLightPos":	{ type: "v3", value: new THREE.Vector3() },
-		"uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
+			"uDirLightPos":	{ type: "v3", value: new THREE.Vector3() },
+			"uDirLightColor": { type: "c", value: new THREE.Color( 0xeeeeee ) },
 
-		"uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) },
+			"uAmbientLightColor": { type: "c", value: new THREE.Color( 0x050505 ) },
 
-		"uBaseColor":  { type: "c", value: new THREE.Color( 0xffffff ) },
-		"uLineColor1": { type: "c", value: new THREE.Color( 0x000000 ) }
+			"uBaseColor":  { type: "c", value: new THREE.Color( 0xffffff ) },
+			"uLineColor1": { type: "c", value: new THREE.Color( 0x000000 ) }
 
-	},
+		},
+
+		vertexShader: [
 
-	vertexShader: [
+			"varying vec3 vNormal;",
 
-		"varying vec3 vNormal;",
+			"void main() {",
 
-		"void main() {",
+				"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+				"vNormal = normalize( normalMatrix * normal );",
 
-			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
-			"vNormal = normalize( normalMatrix * normal );",
+			"}"
 
-		"}"
+		].join( "\n" ),
 
-	].join("\n"),
+		fragmentShader: [
 
-	fragmentShader: [
+			"uniform vec3 uBaseColor;",
+			"uniform vec3 uLineColor1;",
+			"uniform vec3 uLineColor2;",
+			"uniform vec3 uLineColor3;",
+			"uniform vec3 uLineColor4;",
 
-		"uniform vec3 uBaseColor;",
-		"uniform vec3 uLineColor1;",
-		"uniform vec3 uLineColor2;",
-		"uniform vec3 uLineColor3;",
-		"uniform vec3 uLineColor4;",
+			"uniform vec3 uDirLightPos;",
+			"uniform vec3 uDirLightColor;",
 
-		"uniform vec3 uDirLightPos;",
-		"uniform vec3 uDirLightColor;",
+			"uniform vec3 uAmbientLightColor;",
 
-		"uniform vec3 uAmbientLightColor;",
+			"varying vec3 vNormal;",
 
-		"varying vec3 vNormal;",
+			"void main() {",
 
-		"void main() {",
+				"float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);",
+				"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
 
-			"float directionalLightWeighting = max( dot( normalize(vNormal), uDirLightPos ), 0.0);",
-			"vec3 lightWeighting = uAmbientLightColor + uDirLightColor * directionalLightWeighting;",
+				"gl_FragColor = vec4( uBaseColor, 1.0 );",
 
-			"gl_FragColor = vec4( uBaseColor, 1.0 );",
+				"if ( length(lightWeighting) < 1.00 ) {",
 
-			"if ( length(lightWeighting) < 1.00 ) {",
+					"if ( ( mod(gl_FragCoord.x, 4.001) + mod(gl_FragCoord.y, 4.0) ) > 6.00 ) {",
 
-				"if ( ( mod(gl_FragCoord.x, 4.001) + mod(gl_FragCoord.y, 4.0) ) > 6.00 ) {",
+						"gl_FragColor = vec4( uLineColor1, 1.0 );",
 
-					"gl_FragColor = vec4( uLineColor1, 1.0 );",
+					"}",
 
 				"}",
 
-			"}",
+				"if ( length(lightWeighting) < 0.50 ) {",
 
-			"if ( length(lightWeighting) < 0.50 ) {",
+					"if ( ( mod(gl_FragCoord.x + 2.0, 4.001) + mod(gl_FragCoord.y + 2.0, 4.0) ) > 6.00 ) {",
 
-				"if ( ( mod(gl_FragCoord.x + 2.0, 4.001) + mod(gl_FragCoord.y + 2.0, 4.0) ) > 6.00 ) {",
+						"gl_FragColor = vec4( uLineColor1, 1.0 );",
 
-					"gl_FragColor = vec4( uLineColor1, 1.0 );",
+					"}",
 
 				"}",
 
-			"}",
-
-		"}"
+			"}"
 
-	].join("\n")
+		].join( "\n" )
 
-}
+	}
 
 };

+ 28 - 20
examples/js/SimulationRenderer.js

@@ -10,7 +10,7 @@
  *
  */
 
-function SimulationRenderer(WIDTH, renderer) {
+function SimulationRenderer( WIDTH, renderer ) {
 
 	WIDTH = WIDTH || 4;
 	var camera = new THREE.Camera();
@@ -19,14 +19,18 @@ function SimulationRenderer(WIDTH, renderer) {
 	// Init RTT stuff
 	gl = renderer.getContext();
 
-	if ( !gl.getExtension( "OES_texture_float" )) {
+	if ( ! gl.getExtension( "OES_texture_float" ) ) {
+
 		alert( "No OES_texture_float support for float textures!" );
 		return;
+
 	}
 
-	if ( gl.getParameter(gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS) == 0) {
+	if ( gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ) == 0 ) {
+
 		alert( "No support for vertex shader textures!" );
 		return;
+
 	}
 
 	var scene = new THREE.Scene();
@@ -77,7 +81,7 @@ function SimulationRenderer(WIDTH, renderer) {
 			predator: { type: "v3", value: new THREE.Vector3() }
 		},
 		defines: {
-			WIDTH: WIDTH.toFixed(2)
+			WIDTH: WIDTH.toFixed( 2 )
 		},
 		vertexShader: document.getElementById( 'vertexShader' ).textContent,
 		fragmentShader: document.getElementById( 'fragmentShaderVelocity' ).textContent
@@ -92,6 +96,7 @@ function SimulationRenderer(WIDTH, renderer) {
 	var rtPosition1, rtPosition2, rtVelocity1, rtVelocity2;
 
 	function init() {
+
 		var dtPosition = generatePositionTexture();
 		var dtVelocity = generateVelocityTexture();
 
@@ -100,19 +105,21 @@ function SimulationRenderer(WIDTH, renderer) {
 		rtVelocity1 = getRenderTarget( THREE.RGBFormat );
 		rtVelocity2 = rtVelocity1.clone();
 
-		simulator.renderTexture(dtPosition, rtPosition1);
-		simulator.renderTexture(rtPosition1, rtPosition2);
+		simulator.renderTexture( dtPosition, rtPosition1 );
+		simulator.renderTexture( rtPosition1, rtPosition2 );
 
-		simulator.renderTexture(dtVelocity, rtVelocity1);
-		simulator.renderTexture(rtVelocity1, rtVelocity2);
+		simulator.renderTexture( dtVelocity, rtVelocity1 );
+		simulator.renderTexture( rtVelocity1, rtVelocity2 );
 
 		simulator.velocityUniforms.testing.value = 10;
+
 	}
 
 	this.init = init;
 
 	function getRenderTarget( type ) {
-		var renderTarget = new THREE.WebGLRenderTarget(WIDTH, WIDTH, {
+
+		var renderTarget = new THREE.WebGLRenderTarget( WIDTH, WIDTH, {
 			wrapS: THREE.RepeatWrapping,
 			wrapT: THREE.RepeatWrapping,
 			minFilter: THREE.NearestFilter,
@@ -120,20 +127,24 @@ function SimulationRenderer(WIDTH, renderer) {
 			format: type,
 			type: THREE.FloatType,
 			stencilBuffer: false
-		});
+		} );
 
 		return renderTarget;
+
 	}
 
 	// Takes a texture, and render out as another texture
 	this.renderTexture = function ( input, output ) {
+
 		mesh.material = passThruShader;
 		uniforms.texture.value = input;
 		renderer.render( scene, camera, output );
+
 	};
 
 
-	this.renderPosition = function(position, velocity, output, delta) {
+	this.renderPosition = function( position, velocity, output, delta ) {
+
 		mesh.material = positionShader;
 		positionShader.uniforms.texturePosition.value = position;
 		positionShader.uniforms.textureVelocity.value = velocity;
@@ -141,9 +152,11 @@ function SimulationRenderer(WIDTH, renderer) {
 		positionShader.uniforms.delta.value = delta;
 		renderer.render( scene, camera, output );
 		this.currentPosition = output;
+
 	};
 
-	this.renderVelocity = function(position, velocity, output, delta) {
+	this.renderVelocity = function( position, velocity, output, delta ) {
+
 		mesh.material = velocityShader;
 		velocityShader.uniforms.texturePosition.value = position;
 		velocityShader.uniforms.textureVelocity.value = velocity;
@@ -151,11 +164,12 @@ function SimulationRenderer(WIDTH, renderer) {
 		velocityShader.uniforms.delta.value = delta;
 		renderer.render( scene, camera, output );
 		this.currentVelocity = output;
+
 	};
 
 	this.simulate = function( delta ) {
 
-		if (flipflop) {
+		if ( flipflop ) {
 
 			simulator.renderVelocity( rtPosition1, rtVelocity1, rtVelocity2, delta );
 			simulator.renderPosition( rtPosition1, rtVelocity2, rtPosition2, delta );
@@ -167,7 +181,7 @@ function SimulationRenderer(WIDTH, renderer) {
 
 		}
 
-		flipflop = !flipflop;
+		flipflop = ! flipflop;
 
 	};
 
@@ -189,10 +203,7 @@ function SimulationRenderer(WIDTH, renderer) {
 		}
 
 		var texture = new THREE.DataTexture( a, WIDTH, WIDTH, THREE.RGBAFormat, THREE.FloatType );
-		texture.minFilter = THREE.NearestFilter;
-		texture.magFilter = THREE.NearestFilter;
 		texture.needsUpdate = true;
-		texture.flipY = false;
 
 		return texture;
 
@@ -215,10 +226,7 @@ function SimulationRenderer(WIDTH, renderer) {
 		}
 
 		var texture = new THREE.DataTexture( a, WIDTH, WIDTH, THREE.RGBFormat, THREE.FloatType );
-		texture.minFilter = THREE.NearestFilter;
-		texture.magFilter = THREE.NearestFilter;
 		texture.needsUpdate = true;
-		texture.flipY = false;
 
 		return texture;
 

+ 11 - 12
examples/js/SkyShader.js

@@ -14,15 +14,15 @@
  * Three.js integration by zz85 http://twitter.com/blurspline
 */
 
-THREE.ShaderLib['sky'] = {
+THREE.ShaderLib[ 'sky' ] = {
 
 	uniforms: {
 
-		luminance:	 { type: "f", value:1 },
-		turbidity:	 { type: "f", value:2 },
-		reileigh:	 { type: "f", value:1 },
-		mieCoefficient:	 { type: "f", value:0.005 },
-		mieDirectionalG: { type: "f", value:0.8 },
+		luminance:	 { type: "f", value: 1 },
+		turbidity:	 { type: "f", value: 2 },
+		reileigh:	 { type: "f", value: 1 },
+		mieCoefficient:	 { type: "f", value: 0.005 },
+		mieDirectionalG: { type: "f", value: 0.8 },
 		sunPosition: 	 { type: "v3", value: new THREE.Vector3() }
 
 	},
@@ -40,7 +40,7 @@ THREE.ShaderLib['sky'] = {
 
 		"}",
 
-	].join("\n"),
+	].join( "\n" ),
 
 	fragmentShader: [
 
@@ -62,9 +62,6 @@ THREE.ShaderLib['sky'] = {
 		"uniform float mieCoefficient;",
 		"uniform float mieDirectionalG;",
 
-		"vec3 sunDirection = normalize(sunPosition);",
-		"float reileighCoefficient = reileigh;",
-
 		"// constants for atmospheric scattering",
 		"const float e = 2.71828182845904523536028747135266249775724709369995957;",
 		"const float pi = 3.141592653589793238462643383279502884197169;",
@@ -160,7 +157,9 @@ THREE.ShaderLib['sky'] = {
 
 			 "// gl_FragColor = vec4(sunfade, sunfade, sunfade, 1.0);",
 
-			"reileighCoefficient = reileighCoefficient - (1.0* (1.0-sunfade));",
+			"float reileighCoefficient = reileigh - (1.0* (1.0-sunfade));",
+
+			"vec3 sunDirection = normalize(sunPosition);",
 
 			"float sunE = sunIntensity(dot(sunDirection, up));",
 
@@ -235,7 +234,7 @@ THREE.ShaderLib['sky'] = {
 			"gl_FragColor.a = 1.0;",
 		"}",
 
-	].join("\n")
+	].join( "\n" )
 
 };
 

+ 0 - 835
examples/js/Sparks.js

@@ -1,835 +0,0 @@
-/*
- * @author zz85 (http://github.com/zz85 http://www.lab4games.net/zz85/blog)
- *
- * a simple to use javascript 3d particles system inspired by FliNT and Stardust
- * created with TWEEN.js and THREE.js
- *
- * for feature requests or bugs, please visit https://github.com/zz85/sparks.js
- *
- * licensed under the MIT license
- */
-
-var SPARKS = {};
-
-/********************************
-* Emitter Class
-*
-*   Creates and Manages Particles
-*********************************/
-
-SPARKS.Emitter = function (counter) {
-
-	this._counter = counter ? counter : new SPARKS.SteadyCounter(10); // provides number of particles to produce
-
-	this._particles = [];
-
-
-	this._initializers = []; // use for creation of particles
-	this._actions = [];     // uses action to update particles
-	this._activities = [];  //  not supported yet
-
-	this._handlers = [];
-
-	this.callbacks = {};
-};
-
-
-SPARKS.Emitter.prototype = {
-
-	_TIMESTEP: 15,
-	_timer: null,
-	_lastTime: null,
-	_timerStep: 10,
-	_velocityVerlet: true,
-
-	// run its built in timer / stepping
-	start: function() {
-		this._lastTime = Date.now();
-		this._timer = setTimeout(this.step, this._timerStep, this);
-		this._isRunning = true;
-	},
-
-	stop: function() {
-		this._isRunning = false;
-		clearTimeout(this._timer);
-	},
-
-	isRunning: function() {
-		return this._isRunning & true;
-	},
-
-	// Step gets called upon by the engine
-	// but attempts to call update() on a regular basics
-	// This method is also described in http://gameclosure.com/2011/04/11/deterministic-delta-tee-in-js-games/
-	step: function(emitter) {
-
-		var time = Date.now();
-		var elapsed = time - emitter._lastTime;
-
-		if (!this._velocityVerlet) {
-			// if elapsed is way higher than time step, (usually after switching tabs, or excution cached in ff)
-			// we will drop cycles. perhaps set to a limit of 10 or something?
-			var maxBlock = emitter._TIMESTEP * 20;
-
-			if (elapsed >= maxBlock) {
-				//console.log('warning: sparks.js is fast fowarding engine, skipping steps', elapsed / emitter._TIMESTEP);
-				//emitter.update( (elapsed - maxBlock) / 1000);
-				elapsed = maxBlock;
-			}
-
-			while (elapsed >= emitter._TIMESTEP) {
-				emitter.update(emitter._TIMESTEP / 1000);
-				elapsed -= emitter._TIMESTEP;
-			}
-			emitter._lastTime = time - elapsed;
-
-		} else {
-			emitter.update(elapsed / 1000);
-			emitter._lastTime = time;
-		}
-
-
-
-		if (emitter._isRunning)
-		setTimeout(emitter.step, emitter._timerStep, emitter);
-
-	},
-
-
-	// Update particle engine in seconds, not milliseconds
-    update: function(time) {
-
-	var i, j;
-	var len = this._counter.updateEmitter( this, time );
-
-        // Create particles
-	for ( i = 0; i < len; i ++ ) {
-		this.createParticle();
-	}
-
-        // Update activities
-	len = this._activities.length;
-	for ( i = 0; i < len; i ++ )
-        {
-		this._activities[i].update( this, time );
-	}
-
-
-	len = this._actions.length;
-
-	var particle;
-	var action;
-	var len2 = this._particles.length;
-
-	for ( j = 0; j < len; j ++ )
-        {
-		action = this._actions[j];
-		for ( i = 0; i < len2; ++ i )
-            {
-			particle = this._particles[i];
-			action.update( this, particle, time );
-		}
-	}
-
-
-        // remove dead particles
-	for ( i = len2; i --; )
-        {
-		particle = this._particles[i];
-		if ( particle.isDead )
-            {
-                //particle =
-			this._particles.splice( i, 1 );
-			this.dispatchEvent("dead", particle);
-			SPARKS.VectorPool.release(particle.position); //
-			SPARKS.VectorPool.release(particle.velocity);
-
-		} else {
-			this.dispatchEvent("updated", particle);
-		}
-	}
-
-	this.dispatchEvent("loopUpdated");
-
-    },
-
-    createParticle: function() {
-	var particle = new SPARKS.Particle();
-        // In future, use a Particle Factory
-	var len = this._initializers.length, i;
-
-	for ( i = 0; i < len; i ++ ) {
-		this._initializers[i].initialize( this, particle );
-	}
-
-	this._particles.push( particle );
-
-	this.dispatchEvent("created", particle); // ParticleCreated
-
-	return particle;
-    },
-
-    addInitializer: function (initializer) {
-	this._initializers.push(initializer);
-    },
-
-    addAction: function (action) {
-	this._actions.push(action);
-    },
-
-    removeInitializer: function (initializer) {
-	var index = this._initializers.indexOf(initializer);
-	if (index > -1) {
-		this._initializers.splice( index, 1 );
-	}
-    },
-
-    removeAction: function (action) {
-	var index = this._actions.indexOf(action);
-	if (index > -1) {
-		this._actions.splice( index, 1 );
-	}
-		//console.log('removeAction', index, this._actions);
-    },
-
-    addCallback: function(name, callback) {
-	this.callbacks[name] = callback;
-    },
-
-    dispatchEvent: function(name, args) {
-	var callback = this.callbacks[name];
-	if (callback) {
-		callback(args);
-	}
-
-    }
-
-
-};
-
-
-/*
- * Constant Names for
- * Events called by emitter.dispatchEvent()
- *
- */
-SPARKS.EVENT_PARTICLE_CREATED = "created";
-SPARKS.EVENT_PARTICLE_UPDATED = "updated";
-SPARKS.EVENT_PARTICLE_DEAD = "dead";
-SPARKS.EVENT_LOOP_UPDATED = "loopUpdated";
-
-
-
-/*
- * Steady Counter attempts to produces a particle rate steadily
- *
- */
-
-// Number of particles per seconds
-SPARKS.SteadyCounter = function(rate) {
-	this.rate = rate;
-
-	// we use a shortfall counter to make up for slow emitters
-	this.leftover = 0;
-
-};
-
-SPARKS.SteadyCounter.prototype.updateEmitter = function(emitter, time) {
-
-	var targetRelease = time * this.rate + this.leftover;
-	var actualRelease = Math.floor(targetRelease);
-
-	this.leftover = targetRelease - actualRelease;
-
-	return actualRelease;
-};
-
-
-/*
- * Shot Counter produces specified particles
- * on a single impluse or burst
- */
-
-SPARKS.ShotCounter = function(particles) {
-	this.particles = particles;
-	this.used = false;
-};
-
-SPARKS.ShotCounter.prototype.updateEmitter = function(emitter, time) {
-
-	if (this.used) {
-		return 0;
-	} else {
-		this.used = true;
-	}
-
-	return this.particles;
-};
-
-
-/********************************
-* Particle Class
-*
-*   Represents a single particle
-*********************************/
-SPARKS.Particle = function() {
-
-    /**
-     * The lifetime of the particle, in seconds.
-     */
-	this.lifetime = 0;
-
-    /**
-     * The age of the particle, in seconds.
-     */
-	this.age = 0;
-
-    /**
-     * The energy of the particle.
-     */
-	this.energy = 1;
-
-    /**
-     * Whether the particle is dead and should be removed from the stage.
-     */
-	this.isDead = false;
-
-	this.target = null; // tag
-
-    /**
-     * For 3D
-     */
-
-	this.position = SPARKS.VectorPool.get().set(0, 0, 0); //new THREE.Vector3( 0, 0, 0 );
-	this.velocity = SPARKS.VectorPool.get().set(0, 0, 0); //new THREE.Vector3( 0, 0, 0 );
-	this._oldvelocity = SPARKS.VectorPool.get().set(0, 0, 0);
-     // rotation vec3
-     // angVelocity vec3
-     // faceAxis vec3
-
-};
-
-
-/********************************
-* Action Classes
-*
-*   An abstract class which have
-*   update function
-*********************************/
-SPARKS.Action = function() {
-	this._priority = 0;
-};
-
-
-SPARKS.Age = function(easing) {
-	this._easing = (easing == null) ? TWEEN.Easing.Linear.None : easing;
-};
-
-SPARKS.Age.prototype.update = function (emitter, particle, time) {
-	particle.age += time;
-	if ( particle.age >= particle.lifetime )
-    {
-		particle.energy = 0;
-		particle.isDead = true;
-	}
-    else
-	{
-		var t = this._easing(particle.age / particle.lifetime);
-		particle.energy = -1 * t + 1;
-	}
-};
-
-/*
-// Mark particle as dead when particle's < 0
-
-SPARKS.Death = function(easing) {
-    this._easing = (easing == null) ? TWEEN.Linear.None : easing;
-};
-
-SPARKS.Death.prototype.update = function (emitter, particle, time) {
-    if (particle.life <= 0) {
-        particle.isDead = true;
-    }
-};
-*/
-
-
-SPARKS.Move = function() {
-
-};
-
-SPARKS.Move.prototype.update = function(emitter, particle, time) {
-    // attempt verlet velocity updating.
-	var p = particle.position;
-	var v = particle.velocity;
-	var old = particle._oldvelocity;
-
-	if (this._velocityVerlet) {
-		p.x += (v.x + old.x) * 0.5 * time;
-		p.y += (v.y + old.y) * 0.5 * time;
-		p.z += (v.z + old.z) * 0.5 * time;
-	} else {
-		p.x += v.x * time;
-		p.y += v.y * time;
-		p.z += v.z * time;
-	}
-
-    //  OldVel = Vel;
-    // Vel = Vel + Accel * dt;
-    // Pos = Pos + (vel + Vel + Accel * dt) * 0.5 * dt;
-
-
-
-};
-
-/* Marks particles found in specified zone dead */
-SPARKS.DeathZone = function(zone) {
-	this.zone = zone;
-};
-
-SPARKS.DeathZone.prototype.update = function(emitter, particle, time) {
-
-	if (this.zone.contains(particle.position)) {
-		particle.isDead = true;
-	}
-
-};
-
-/*
- * SPARKS.ActionZone applies an action when particle is found in zone
- */
-SPARKS.ActionZone = function(action, zone) {
-	this.action = action;
-	this.zone = zone;
-};
-
-SPARKS.ActionZone.prototype.update = function(emitter, particle, time) {
-
-	if (this.zone.contains(particle.position)) {
-		this.action.update( emitter, particle, time );
-	}
-
-};
-
-/*
- * Accelerate action affects velocity in specified 3d direction
- */
-SPARKS.Accelerate = function(x,y,z) {
-
-	if (x instanceof THREE.Vector3) {
-		this.acceleration = x;
-		return;
-	}
-
-	this.acceleration = new THREE.Vector3(x,y,z);
-
-};
-
-SPARKS.Accelerate.prototype.update = function(emitter, particle, time) {
-	var acc = this.acceleration;
-
-	var v = particle.velocity;
-
-	particle._oldvelocity.set(v.x, v.y, v.z);
-
-	v.x += acc.x * time;
-	v.y += acc.y * time;
-	v.z += acc.z * time;
-
-};
-
-/*
- * Accelerate Factor accelerate based on a factor of particle's velocity.
- */
-SPARKS.AccelerateFactor = function(factor) {
-	this.factor = factor;
-};
-
-SPARKS.AccelerateFactor.prototype.update = function(emitter, particle, time) {
-	var factor = this.factor;
-
-	var v = particle.velocity;
-	var len = v.length();
-	var adjFactor;
-	if (len > 0) {
-
-		adjFactor = factor * time / len;
-		adjFactor += 1;
-
-		v.multiplyScalar(adjFactor);
-		// v.x *= adjFactor;
-		// 	    v.y *= adjFactor;
-		// 	    v.z *= adjFactor;
-	}
-
-};
-
-/*
-AccelerateNormal
- * AccelerateVelocity affects velocity based on its velocity direction
- */
-SPARKS.AccelerateVelocity = function(factor) {
-
-	this.factor = factor;
-
-};
-
-SPARKS.AccelerateVelocity.prototype.update = function(emitter, particle, time) {
-	var factor = this.factor;
-
-	var v = particle.velocity;
-
-
-	v.z += - v.x * factor;
-	v.y += v.z * factor;
-	v.x +=  v.y * factor;
-
-};
-
-
-/* Set the max ammount of x,y,z drift movements in a second */
-SPARKS.RandomDrift = function(x,y,z) {
-	if (x instanceof THREE.Vector3) {
-		this.drift = x;
-		return;
-	}
-
-	this.drift = new THREE.Vector3(x,y,z);
-};
-
-
-SPARKS.RandomDrift.prototype.update = function(emitter, particle, time) {
-	var drift = this.drift;
-
-	var v = particle.velocity;
-
-	v.x += ( Math.random() - 0.5 ) * drift.x * time;
-	v.y += ( Math.random() - 0.5 ) * drift.y * time;
-	v.z += ( Math.random() - 0.5 ) * drift.z * time;
-
-};
-
-/********************************
-* Zone Classes
-*
-*   An abstract classes which have
-*   getLocation() function
-*********************************/
-SPARKS.Zone = function() {
-};
-
-// TODO, contains() for Zone
-
-SPARKS.PointZone = function(pos) {
-	this.pos = pos;
-};
-
-SPARKS.PointZone.prototype.getLocation = function() {
-	return this.pos;
-};
-
-SPARKS.PointZone = function(pos) {
-	this.pos = pos;
-};
-
-SPARKS.PointZone.prototype.getLocation = function() {
-	return this.pos;
-};
-
-SPARKS.LineZone = function(start, end) {
-	this.start = start;
-	this.end = end;
-	this._length = end.clone().sub( start );
-};
-
-SPARKS.LineZone.prototype.getLocation = function() {
-	var len = this._length.clone();
-
-	len.multiplyScalar( Math.random() );
-	return len.add( this.start );
-
-};
-
-// Basically a RectangleZone
-SPARKS.ParallelogramZone = function(corner, side1, side2) {
-	this.corner = corner;
-	this.side1 = side1;
-	this.side2 = side2;
-};
-
-SPARKS.ParallelogramZone.prototype.getLocation = function() {
-
-	var d1 = this.side1.clone().multiplyScalar( Math.random() );
-	var d2 = this.side2.clone().multiplyScalar( Math.random() );
-	d1.add(d2);
-	return d1.add( this.corner );
-
-};
-
-SPARKS.CubeZone = function(position, x, y, z) {
-	this.position = position;
-	this.x = x;
-	this.y = y;
-	this.z = z;
-};
-
-SPARKS.CubeZone.prototype.getLocation = function() {
-    //TODO use pool?
-
-	var location = this.position.clone();
-	location.x += Math.random() * this.x;
-	location.y += Math.random() * this.y;
-	location.z += Math.random() * this.z;
-
-	return location;
-
-};
-
-
-SPARKS.CubeZone.prototype.contains = function(position) {
-
-	var startX = this.position.x;
-	var startY = this.position.y;
-	var startZ = this.position.z;
-	var x = this.x; // width
-	var y = this.y; // depth
-	var z = this.z; // height
-
-	if (x < 0) {
-		startX += x;
-		x = Math.abs(x);
-	}
-
-	if (y < 0) {
-		startY += y;
-		y = Math.abs(y);
-	}
-
-	if (z < 0) {
-		startZ += z;
-		z = Math.abs(z);
-	}
-
-	var diffX = position.x - startX;
-	var diffY = position.y - startY;
-	var diffZ = position.z - startZ;
-
-	if ( (diffX > 0) && (diffX < x) &&
-			(diffY > 0) && (diffY < y) &&
-			(diffZ > 0) && (diffZ < z) ) {
-		return true;
-	}
-
-	return false;
-
-};
-
-
-
-/**
- * The constructor creates a DiscZone 3D zone.
- *
- * @param centre The point at the center of the disc.
- * @param normal A vector normal to the disc.
- * @param outerRadius The outer radius of the disc.
- * @param innerRadius The inner radius of the disc. This defines the hole
- * in the center of the disc. If set to zero, there is no hole.
- */
-
-/*
-// BUGGY!!
-SPARKS.DiscZone = function(center, radiusNormal, outerRadius, innerRadius) {
-    this.center = center;
-	this.radiusNormal = radiusNormal;
-	this.outerRadius = (outerRadius==undefined) ? 0 : outerRadius;
-	this.innerRadius = (innerRadius==undefined) ? 0 : innerRadius;
-
-};
-
-SPARKS.DiscZone.prototype.getLocation = function() {
-    var rand = Math.random();
-	var _innerRadius = this.innerRadius;
-	var _outerRadius = this.outerRadius;
-	var center = this.center;
-	var _normal = this.radiusNormal;
-
-	_distToOrigin = _normal.dot( center );
-
-	var radius = _innerRadius + (1 - rand * rand ) * ( _outerRadius - _innerRadius );
-	var angle = Math.random() * SPARKS.Utils.TWOPI;
-
-	var _distToOrigin = _normal.dot( center );
-	var axes = SPARKS.Utils.getPerpendiculars( _normal.clone() );
-	var _planeAxis1 = axes[0];
-	var _planeAxis2 = axes[1];
-
-	var p = _planeAxis1.clone();
-	p.multiplyScalar( radius * Math.cos( angle ) );
-	var p2 = _planeAxis2.clone();
-	p2.multiplyScalar( radius * Math.sin( angle ) );
-	p.add( p2 );
-	return _center.add( p );
-
-};
-*/
-
-SPARKS.SphereCapZone = function(x, y, z, minr, maxr, angle) {
-	this.x = x;
-	this.y = y;
-	this.z = z;
-	this.minr = minr;
-	this.maxr = maxr;
-	this.angle = angle;
-};
-
-SPARKS.SphereCapZone.prototype.getLocation = function() {
-	var theta = Math.PI * 2  * SPARKS.Utils.random();
-	var r = SPARKS.Utils.random();
-
-    //new THREE.Vector3
-	var v =  SPARKS.VectorPool.get().set(r * Math.cos(theta), -1 / Math.tan(this.angle * SPARKS.Utils.DEGREE_TO_RADIAN), r * Math.sin(theta));
-
-    //v.length = StardustMath.interpolate(0, _minRadius, 1, _maxRadius, Math.random());
-
-	var i = this.minr - ((this.minr - this.maxr) *  Math.random() );
-	v.multiplyScalar(i);
-
-	v.__markedForReleased = true;
-
-	return v;
-};
-
-
-/********************************
-* Initializer Classes
-*
-*   Classes which initializes
-*   particles. Implements initialize( emitter:Emitter, particle:Particle )
-*********************************/
-
-// Specifies random life between max and min
-SPARKS.Lifetime = function(min, max) {
-	this._min = min;
-
-	this._max = max ? max : min;
-
-};
-
-SPARKS.Lifetime.prototype.initialize = function( emitter/*Emitter*/, particle/*Particle*/ ) {
-	particle.lifetime = this._min + SPARKS.Utils.random() * ( this._max - this._min );
-};
-
-
-SPARKS.Position = function(zone) {
-	this.zone = zone;
-};
-
-SPARKS.Position.prototype.initialize = function( emitter/*Emitter*/, particle/*Particle*/ ) {
-	var pos = this.zone.getLocation();
-	particle.position.set(pos.x, pos.y, pos.z);
-};
-
-SPARKS.Velocity = function(zone) {
-	this.zone = zone;
-};
-
-SPARKS.Velocity.prototype.initialize = function( emitter/*Emitter*/, particle/*Particle*/ ) {
-	var pos = this.zone.getLocation();
-	particle.velocity.set(pos.x, pos.y, pos.z);
-	if (pos.__markedForReleased) {
-		//console.log("release");
-		SPARKS.VectorPool.release(pos);
-		pos.__markedForReleased = false;
-	}
-};
-
-SPARKS.Target = function(target, callback) {
-	this.target = target;
-	this.callback = callback;
-};
-
-SPARKS.Target.prototype.initialize = function( emitter, particle ) {
-
-	if (this.callback) {
-		particle.target = this.callback();
-	} else {
-		particle.target = this.target;
-	}
-
-};
-
-/********************************
-* VectorPool
-*
-*  Reuse much of Vectors if possible
-*********************************/
-
-SPARKS.VectorPool = {
-	__pools: [],
-
-	// Get a new Vector
-	get: function() {
-		if (this.__pools.length > 0) {
-			return this.__pools.pop();
-		}
-
-		return this._addToPool();
-
-	},
-
-	// Release a vector back into the pool
-	release: function(v) {
-		this.__pools.push(v);
-	},
-
-	// Create a bunch of vectors and add to the pool
-	_addToPool: function() {
-		//console.log("creating some pools");
-
-		for (var i = 0, size = 100; i < size; i ++) {
-			this.__pools.push(new THREE.Vector3());
-		}
-
-		return new THREE.Vector3();
-
-	}
-
-
-
-};
-
-
-/********************************
-* Util Classes
-*
-*   Classes which initializes
-*   particles. Implements initialize( emitter:Emitter, particle:Particle )
-*********************************/
-SPARKS.Utils = {
-    random: function() {
-	return Math.random();
-    },
-    DEGREE_TO_RADIAN: Math.PI / 180,
-	TWOPI: Math.PI * 2,
-
-	getPerpendiculars: function(normal) {
-		var p1 = this.getPerpendicular( normal );
-		var p2 = normal.cross( p1 );
-		p2.normalize();
-		return [ p1, p2 ];
-	},
-
-	getPerpendicular: function( v )
-	{
-		if ( v.x == 0 )
-		{
-			return new THREE.Vector3D( 1, 0, 0 );
-		}
-		else
-		{
-			var temp = new THREE.Vector3( v.y, -v.x, 0 );
-			return temp.normalize();
-		}
-	}
-
-};

+ 18 - 10
examples/js/TypedArrayUtils.js

@@ -21,7 +21,7 @@ THREE.TypedArrayUtils = {};
 THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
 
 	var stack = [];
-	var sp = -1;
+	var sp = - 1;
 	var left = 0;
 	var right = arr.length / eleSize - 1;
 	var tmp = 0.0, x = 0, y = 0;
@@ -56,7 +56,7 @@ THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
 				
 				i = j - 1;
 				
-				while ( i >= left && arr[ i * eleSize + orderElement ] > swap[orderElement ] ) {
+				while ( i >= left && arr[ i * eleSize + orderElement ] > swap[ orderElement ] ) {
 
 					for ( x = 0; x < eleSize; x ++ ) {
 
@@ -76,7 +76,7 @@ THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
 
 			}
 			
-			if ( sp == -1 ) break;
+			if ( sp == - 1 ) break;
 
 			right = stack[ sp -- ]; //?
 			left = stack[ sp -- ];
@@ -215,7 +215,7 @@ THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
 		median = Math.floor( plength / 2 );
 		
 		node = new self.Node( getPointSet( points, median ), depth, parent, median + pos );
-		node.left = buildTree( points.subarray( 0, median * eleSize), depth + 1, node, pos );
+		node.left = buildTree( points.subarray( 0, median * eleSize ), depth + 1, node, pos );
 		node.right = buildTree( points.subarray( ( median + 1 ) * eleSize, points.length ), depth + 1, node, pos + median + 1 );
 
 		return node;
@@ -224,7 +224,11 @@ THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
 
 	this.root = buildTree( points, 0, null, 0 );
 		
-	this.getMaxDepth = function () { return maxDepth; };
+	this.getMaxDepth = function () {
+
+		return maxDepth;
+
+	};
 	
 	this.nearest = function ( point, maxNodes, maxDistance ) {
 	
@@ -240,15 +244,19 @@ THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
 
 		bestNodes = new THREE.TypedArrayUtils.Kdtree.BinaryHeap(
 
-			function ( e ) { return -e[ 1 ]; }
+			function ( e ) {
 
-		);
+				return - e[ 1 ];
+
+			}
+
+					);
 
 		function nearestSearch( node ) {
 
 			var bestChild,
 				dimension = node.depth % eleSize,
-				ownDistance = metric(point, node.obj),
+				ownDistance = metric( point, node.obj ),
 				linearDistance = 0,
 				otherChild,
 				i,
@@ -330,7 +338,7 @@ THREE.TypedArrayUtils.quicksortIP = function ( arr, eleSize, orderElement ) {
 
 			// if there's still room or the current distance is nearer than the best distance
 
-			if ( bestNodes.size() < maxNodes || Math.abs(linearDistance) < bestNodes.peek()[ 1 ] ) {
+			if ( bestNodes.size() < maxNodes || Math.abs( linearDistance ) < bestNodes.peek()[ 1 ] ) {
 
 				if ( bestChild === node.left ) {
 
@@ -591,4 +599,4 @@ THREE.TypedArrayUtils.Kdtree.BinaryHeap.prototype = {
 
 	}
 
-};
+};

+ 17 - 1
examples/js/UCSCharacter.js

@@ -38,6 +38,7 @@ THREE.UCSCharacter = function() {
 		var loader = new THREE.JSONLoader();
 		console.log( config.baseUrl + config.character );
 		loader.load( config.baseUrl + config.character, function( geometry ) {
+
 			geometry.computeBoundingBox();
 			geometry.computeVertexNormals();
 
@@ -56,28 +57,40 @@ THREE.UCSCharacter = function() {
 			animation = new THREE.Animation( mesh, geometry.animation );
 			animation.play();
 			
-			scope.setSkin(0);
+			scope.setSkin( 0 );
 			
 			scope.checkLoadComplete();
+
 		} );
 
 	};
 	
 	this.setSkin = function( index ) {
+
 		if ( mesh && scope.materials ) {
+
 			mesh.material = scope.materials[ index ];
+
 		}
+
 	};
 	
 	this.updateMorphs = function( influences ) {
+
 		if ( mesh ) {
+
 			for ( var i = 0; i < scope.numMorphs; i ++ ) {
+
 				mesh.morphTargetInfluences[ i ] = influences[ scope.morphs[ i ] ] / 100;
+
 			}
+
 		}
+
 	};
 	
 	function loadTextures( baseUrl, textureUrls ) {
+
 		var mapping = THREE.UVMapping;
 		var textures = [];
 
@@ -89,9 +102,11 @@ THREE.UCSCharacter = function() {
 		}
 
 		return textures;
+
 	}
 
 	function createMaterials( skins ) {
+
 		var materials = [];
 		
 		for ( var i = 0; i < skins.length; i ++ ) {
@@ -107,6 +122,7 @@ THREE.UCSCharacter = function() {
 		}
 		
 		return materials;
+
 	}
 
 	this.checkLoadComplete = function () {

+ 36 - 26
examples/js/WaterShader.js

@@ -7,7 +7,7 @@
  * @author Jonas Wagner / http://29a.ch/ && http://29a.ch/slides/2012/webglwater/ : Water shader explanations in WebGL
  */
 
-THREE.ShaderLib['water'] = {
+THREE.ShaderLib[ 'water' ] = {
 
 	uniforms: { "normalSampler":	{ type: "t", value: null },
 				"mirrorSampler":	{ type: "t", value: null },
@@ -35,7 +35,7 @@ THREE.ShaderLib['water'] = {
 		'	mirrorCoord = textureMatrix * mirrorCoord;',
 		'	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
 		'}'
-	].join('\n'),
+	].join( '\n' ),
 
 	fragmentShader: [
 		'precision highp float;',
@@ -98,7 +98,7 @@ THREE.ShaderLib['water'] = {
 		'	vec3 albedo = mix( sunColor * diffuseLight * 0.3 + scatter, ( vec3( 0.1 ) + reflectionSample * 0.9 + reflectionSample * specularLight ), reflectance );',
 		'	gl_FragColor = vec4( albedo, alpha );',
 		'}'
-	].join('\n')
+	].join( '\n' )
 
 };
 
@@ -108,7 +108,9 @@ THREE.Water = function ( renderer, camera, scene, options ) {
 	this.name = 'water_' + this.id;
 
 	function optionalParameter ( value, defaultValue ) {
+
 		return value !== undefined ? value : defaultValue;
+
 	}
 
 	options = options || {};
@@ -134,15 +136,16 @@ THREE.Water = function ( renderer, camera, scene, options ) {
 	this.mirrorWorldPosition = new THREE.Vector3();
 	this.cameraWorldPosition = new THREE.Vector3();
 	this.rotationMatrix = new THREE.Matrix4();
-	this.lookAtPosition = new THREE.Vector3( 0, 0, -1 );
+	this.lookAtPosition = new THREE.Vector3( 0, 0, - 1 );
 	this.clipPlane = new THREE.Vector4();
 	
 	if ( camera instanceof THREE.PerspectiveCamera )
 		this.camera = camera;
-	else 
-	{
+	else {
+
 		this.camera = new THREE.PerspectiveCamera();
-		console.log(this.name + ': camera is not a Perspective Camera!')
+		console.log( this.name + ': camera is not a Perspective Camera!' )
+
 	}
 
 	this.textureMatrix = new THREE.Matrix4();
@@ -174,16 +177,18 @@ THREE.Water = function ( renderer, camera, scene, options ) {
 	
 	this.material.uniforms.eye.value = this.eye;
 	
-	if ( !THREE.Math.isPowerOfTwo(width) || !THREE.Math.isPowerOfTwo(height) )
-	{
+	if ( ! THREE.Math.isPowerOfTwo( width ) || ! THREE.Math.isPowerOfTwo( height ) ) {
+
 		this.texture.generateMipmaps = false;
 		this.texture.minFilter = THREE.LinearFilter;
 		this.tempTexture.generateMipmaps = false;
 		this.tempTexture.minFilter = THREE.LinearFilter;
+
 	}
 
 	this.updateTextureMatrix();
 	this.render();
+
 };
 
 THREE.Water.prototype = Object.create( THREE.Mirror.prototype );
@@ -192,7 +197,11 @@ THREE.Water.prototype.constructor = THREE.Water;
 
 THREE.Water.prototype.updateTextureMatrix = function () {
 
-	function sign(x) { return x ? x < 0 ? -1 : 1 : 0; }
+	function sign( x ) {
+
+		return x ? x < 0 ? - 1 : 1 : 0;
+
+	}
 
 	this.updateMatrixWorld();
 	this.camera.updateMatrixWorld();
@@ -211,7 +220,7 @@ THREE.Water.prototype.updateTextureMatrix = function () {
 
 	this.rotationMatrix.extractRotation( this.camera.matrixWorld );
 
-	this.lookAtPosition.set(0, 0, -1);
+	this.lookAtPosition.set( 0, 0, - 1 );
 	this.lookAtPosition.applyMatrix4( this.rotationMatrix );
 	this.lookAtPosition.add( this.cameraWorldPosition );
 
@@ -219,7 +228,7 @@ THREE.Water.prototype.updateTextureMatrix = function () {
 	target.reflect( this.normal ).negate();
 	target.add( this.mirrorWorldPosition );
 
-	this.up.set(0, -1, 0);
+	this.up.set( 0, - 1, 0 );
 	this.up.applyMatrix4( this.rotationMatrix );
 	this.up.reflect( this.normal ).negate();
 
@@ -230,43 +239,44 @@ THREE.Water.prototype.updateTextureMatrix = function () {
 
 	this.mirrorCamera.updateProjectionMatrix();
 	this.mirrorCamera.updateMatrixWorld();
-	this.mirrorCamera.matrixWorldInverse.getInverse(this.mirrorCamera.matrixWorld);
+	this.mirrorCamera.matrixWorldInverse.getInverse( this.mirrorCamera.matrixWorld );
 
 	// Update the texture matrix
 	this.textureMatrix.set( 0.5, 0.0, 0.0, 0.5,
 							0.0, 0.5, 0.0, 0.5,
 							0.0, 0.0, 0.5, 0.5,
 							0.0, 0.0, 0.0, 1.0 );
-	this.textureMatrix.multiply(this.mirrorCamera.projectionMatrix);
-	this.textureMatrix.multiply(this.mirrorCamera.matrixWorldInverse);
+	this.textureMatrix.multiply( this.mirrorCamera.projectionMatrix );
+	this.textureMatrix.multiply( this.mirrorCamera.matrixWorldInverse );
 
 	// Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html
 	// Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf
 	this.mirrorPlane.setFromNormalAndCoplanarPoint( this.normal, this.mirrorWorldPosition );
-	this.mirrorPlane.applyMatrix4(this.mirrorCamera.matrixWorldInverse);
+	this.mirrorPlane.applyMatrix4( this.mirrorCamera.matrixWorldInverse );
 
-	this.clipPlane.set(this.mirrorPlane.normal.x, this.mirrorPlane.normal.y, this.mirrorPlane.normal.z, this.mirrorPlane.constant );
+	this.clipPlane.set( this.mirrorPlane.normal.x, this.mirrorPlane.normal.y, this.mirrorPlane.normal.z, this.mirrorPlane.constant );
 
 	var q = new THREE.Vector4();
 	var projectionMatrix = this.mirrorCamera.projectionMatrix;
 
-	q.x = (sign(this.clipPlane.x) + projectionMatrix.elements[8]) / projectionMatrix.elements[0];
-	q.y = (sign(this.clipPlane.y) + projectionMatrix.elements[9]) / projectionMatrix.elements[5];
-	q.z = -1.0;
-	q.w = (1.0 + projectionMatrix.elements[10]) / projectionMatrix.elements[14];
+	q.x = ( sign( this.clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ];
+	q.y = ( sign( this.clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ];
+	q.z = - 1.0;
+	q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ];
 
 	// Calculate the scaled plane vector
 	var c = new THREE.Vector4();
-	c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot(q) );
+	c = this.clipPlane.multiplyScalar( 2.0 / this.clipPlane.dot( q ) );
 
 	// Replacing the third row of the projection matrix
-	projectionMatrix.elements[2] = c.x;
-	projectionMatrix.elements[6] = c.y;
-	projectionMatrix.elements[10] = c.z + 1.0 - this.clipBias;
-	projectionMatrix.elements[14] = c.w;
+	projectionMatrix.elements[ 2 ] = c.x;
+	projectionMatrix.elements[ 6 ] = c.y;
+	projectionMatrix.elements[ 10 ] = c.z + 1.0 - this.clipBias;
+	projectionMatrix.elements[ 14 ] = c.w;
 	
 	var worldCoordinates = new THREE.Vector3();
 	worldCoordinates.setFromMatrixPosition( this.camera.matrixWorld );
 	this.eye = worldCoordinates;
 	this.material.uniforms.eye.value = this.eye;
+
 };

+ 7 - 6
examples/js/cameras/CombinedCamera.js

@@ -15,10 +15,10 @@ THREE.CombinedCamera = function ( width, height, fov, near, far, orthoNear, orth
 
 	this.fov = fov;
 
-	this.left = -width / 2;
+	this.left = - width / 2;
 	this.right = width / 2;
 	this.top = height / 2;
-	this.bottom = -height / 2;
+	this.bottom = - height / 2;
 
 	// We could also handle the projectionMatrix internally, but just wanted to test nested camera objects
 
@@ -73,10 +73,10 @@ THREE.CombinedCamera.prototype.toOrthographic = function () {
 	halfHeight /= this.zoom;
 	halfWidth /= this.zoom;
 
-	this.cameraO.left = -halfWidth;
+	this.cameraO.left = - halfWidth;
 	this.cameraO.right = halfWidth;
 	this.cameraO.top = halfHeight;
-	this.cameraO.bottom = -halfHeight;
+	this.cameraO.bottom = - halfHeight;
 
 	// this.cameraO.left = -farHalfWidth;
 	// this.cameraO.right = farHalfWidth;
@@ -103,10 +103,10 @@ THREE.CombinedCamera.prototype.toOrthographic = function () {
 THREE.CombinedCamera.prototype.setSize = function( width, height ) {
 
 	this.cameraP.aspect = width / height;
-	this.left = -width / 2;
+	this.left = - width / 2;
 	this.right = width / 2;
 	this.top = height / 2;
-	this.bottom = -height / 2;
+	this.bottom = - height / 2;
 
 };
 
@@ -158,6 +158,7 @@ THREE.CombinedCamera.prototype.setLens = function ( focalLength, frameHeight ) {
 	this.setFov( fov );
 
 	return fov;
+
 };
 
 

+ 6 - 0
examples/js/controls/DeviceOrientationControls.js

@@ -88,6 +88,12 @@ THREE.DeviceOrientationControls = function ( object ) {
 
 	};
 
+	this.dispose = function () {
+
+		this.disconnect();
+
+	};
+
 	this.connect();
 
 };

+ 14 - 7
examples/js/controls/DragControls.js

@@ -25,7 +25,7 @@ THREE.DragControls = function( _camera, _objects, _domElement ) {
 	var me = this;
 	this.on = function( event, handler ) {
 		
-		if ( !_listeners[ event ] ) _listeners[ event ] = [];
+		if ( ! _listeners[ event ] ) _listeners[ event ] = [];
 
 		_listeners[ event ].push( handler );
 		return me;
@@ -35,9 +35,9 @@ THREE.DragControls = function( _camera, _objects, _domElement ) {
 	this.off = function( event, handler ) {
 		
 		var l = _listeners[ event ];
-		if ( !l ) return me;
+		if ( ! l ) return me;
 
-		if ( l.indexOf( handler ) > -1 ) {
+		if ( l.indexOf( handler ) > - 1 ) {
 			
 			l.splice( handler, 1 );
 		
@@ -50,9 +50,9 @@ THREE.DragControls = function( _camera, _objects, _domElement ) {
 	var notify = function( event, data, member ) {
 			
 		var l = _listeners[ event ];
-		if ( !l ) return;
+		if ( ! l ) return;
 
-		if ( !member ) {
+		if ( ! member ) {
 					
 			for ( var i = 0; i < l.length; i ++ ) {
 						
@@ -96,6 +96,12 @@ THREE.DragControls = function( _camera, _objects, _domElement ) {
 	
 	};
 
+	this.dispose = function() {
+
+		me.deactivate();
+
+	};
+
 	this.activate();
 
 	function onDocumentMouseMove( event ) {
@@ -103,7 +109,7 @@ THREE.DragControls = function( _camera, _objects, _domElement ) {
 		event.preventDefault();
 
 		_mouse.x = ( event.clientX / _domElement.width ) * 2 - 1;
-		_mouse.y = -( event.clientY / _domElement.height ) * 2 + 1;
+		_mouse.y = - ( event.clientY / _domElement.height ) * 2 + 1;
 
 		_raycaster.setFromCamera( _mouse, _camera );
 		var ray = _raycaster.ray;
@@ -118,6 +124,7 @@ THREE.DragControls = function( _camera, _objects, _domElement ) {
 
 			var denom = normal.dot( ray.direction );
 			if ( denom == 0 ) {
+
 				// bail
 				console.log( 'no or infinite solutions' );
 				return;
@@ -188,7 +195,7 @@ THREE.DragControls = function( _camera, _objects, _domElement ) {
 		event.preventDefault();
 
 		_mouse.x = ( event.clientX / _domElement.width ) * 2 - 1;
-		_mouse.y = -( event.clientY / _domElement.height ) * 2 + 1;
+		_mouse.y = - ( event.clientY / _domElement.height ) * 2 + 1;
 
 		_raycaster.setFromCamera( _mouse, _camera );
 		var intersects = _raycaster.intersectObjects( _objects );

+ 37 - 8
examples/js/controls/EditorControls.js

@@ -19,7 +19,7 @@ THREE.EditorControls = function ( object, domElement ) {
 	var scope = this;
 	var vector = new THREE.Vector3();
 
-	var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2 };
+	var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2 };
 	var state = STATE.NONE;
 
 	var center = this.center;
@@ -39,7 +39,7 @@ THREE.EditorControls = function ( object, domElement ) {
 		if ( frame && target.geometry ) {
 
 			scale = ( scale.x + scale.y + scale.z ) / 3;
-			center.add(target.geometry.boundingSphere.center.clone().multiplyScalar( scale ));
+			center.add( target.geometry.boundingSphere.center.clone().multiplyScalar( scale ) );
 			var radius = target.geometry.boundingSphere.radius * ( scale );
 			var pos = object.position.clone().sub( center ).normalize().multiplyScalar( radius * 2 );
 			object.position.copy( center ).add( pos );
@@ -185,11 +185,15 @@ THREE.EditorControls = function ( object, domElement ) {
 
 		var delta = 0;
 
-		if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
+		if ( event.wheelDelta ) {
+
+			// WebKit / Opera / Explorer 9
 
 			delta = - event.wheelDelta;
 
-		} else if ( event.detail ) { // Firefox
+		} else if ( event.detail ) {
+
+			// Firefox
 
 			delta = event.detail * 10;
 
@@ -199,7 +203,30 @@ THREE.EditorControls = function ( object, domElement ) {
 
 	}
 
-	domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+	function contextmenu( event ) {
+
+		event.preventDefault();
+
+	}
+
+	this.dispose = function() {
+
+		domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		domElement.removeEventListener( 'mousedown', onMouseDown, false );
+		domElement.removeEventListener( 'mousewheel', onMouseWheel, false );
+		domElement.removeEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
+
+		domElement.removeEventListener( 'mousemove', onMouseMove, false );
+		domElement.removeEventListener( 'mouseup', onMouseUp, false );
+		domElement.removeEventListener( 'mouseout', onMouseUp, false );
+		domElement.removeEventListener( 'dblclick', onMouseUp, false );
+
+		domElement.removeEventListener( 'touchstart', touchStart, false );
+		domElement.removeEventListener( 'touchmove', touchMove, false );
+
+	}
+
+	domElement.addEventListener( 'contextmenu', contextmenu, false );
 	domElement.addEventListener( 'mousedown', onMouseDown, false );
 	domElement.addEventListener( 'mousewheel', onMouseWheel, false );
 	domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
@@ -250,7 +277,9 @@ THREE.EditorControls = function ( object, domElement ) {
 			var closest = touches[ 0 ];
 
 			for ( var i in touches ) {
-				if ( closest.distanceTo(touch) > touches[ i ].distanceTo(touch) ) closest = touches[ i ];
+
+				if ( closest.distanceTo( touch ) > touches[ i ].distanceTo( touch ) ) closest = touches[ i ];
+
 			}
 
 			return closest;
@@ -275,8 +304,8 @@ THREE.EditorControls = function ( object, domElement ) {
 
 				var offset0 = touches[ 0 ].clone().sub( getClosest( touches[ 0 ], prevTouches ) );
 				var offset1 = touches[ 1 ].clone().sub( getClosest( touches[ 1 ], prevTouches ) );
-				offset0.x = -offset0.x;
-				offset1.x = -offset1.x;
+				offset0.x = - offset0.x;
+				offset1.x = - offset1.x;
 
 				scope.pan( offset0.add( offset1 ).multiplyScalar( 0.5 ) );
 

+ 31 - 9
examples/js/controls/FirstPersonControls.js

@@ -52,7 +52,7 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 	if ( this.domElement !== document ) {
 
-		this.domElement.setAttribute( 'tabindex', -1 );
+		this.domElement.setAttribute( 'tabindex', - 1 );
 
 	}
 
@@ -203,7 +203,7 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 		var actualMoveSpeed = delta * this.movementSpeed;
 
-		if ( this.moveForward || ( this.autoForward && !this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) );
+		if ( this.moveForward || ( this.autoForward && ! this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) );
 		if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed );
 
 		if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed );
@@ -214,7 +214,7 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 		var actualLookSpeed = delta * this.lookSpeed;
 
-		if ( !this.activeLook ) {
+		if ( ! this.activeLook ) {
 
 			actualLookSpeed = 0;
 
@@ -253,15 +253,37 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 	};
 
+	function contextmenu( event ) {
 
-	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+		event.preventDefault();
+
+	}
+
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', _onMouseDown, false );
+		this.domElement.removeEventListener( 'mousemove', _onMouseMove, false );
+		this.domElement.removeEventListener( 'mouseup', _onMouseUp, false );
+
+		window.removeEventListener( 'keydown', _onKeyDown, false );
+		window.removeEventListener( 'keyup', _onKeyUp, false );
+
+	}
+
+	var _onMouseMove = bind( this, this.onMouseMove );
+	var _onMouseDown = bind( this, this.onMouseDown );
+	var _onMouseUp = bind( this, this.onMouseUp );
+	var _onKeyDown = bind( this, this.onKeyDown );
+	var _onKeyUp = bind( this, this.onKeyUp );
 
-	this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false );
-	this.domElement.addEventListener( 'mousedown', bind( this, this.onMouseDown ), false );
-	this.domElement.addEventListener( 'mouseup', bind( this, this.onMouseUp ), false );
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+	this.domElement.addEventListener( 'mousemove', _onMouseMove, false );
+	this.domElement.addEventListener( 'mousedown', _onMouseDown, false );
+	this.domElement.addEventListener( 'mouseup', _onMouseUp, false );
 
-	window.addEventListener( 'keydown', bind( this, this.onKeyDown ), false );
-	window.addEventListener( 'keyup', bind( this, this.onKeyUp ), false );
+	window.addEventListener( 'keydown', _onKeyDown, false );
+	window.addEventListener( 'keyup', _onKeyUp, false );
 
 	function bind( scope, fn ) {
 

+ 39 - 15
examples/js/controls/FlyControls.js

@@ -7,7 +7,7 @@ THREE.FlyControls = function ( object, domElement ) {
 	this.object = object;
 
 	this.domElement = ( domElement !== undefined ) ? domElement : document;
-	if ( domElement ) this.domElement.setAttribute( 'tabindex', -1 );
+	if ( domElement ) this.domElement.setAttribute( 'tabindex', - 1 );
 
 	// API
 
@@ -141,7 +141,7 @@ THREE.FlyControls = function ( object, domElement ) {
 
 	this.mousemove = function( event ) {
 
-		if ( !this.dragToLook || this.mouseStatus > 0 ) {
+		if ( ! this.dragToLook || this.mouseStatus > 0 ) {
 
 			var container = this.getContainerDimensions();
 			var halfWidth  = container.size[ 0 ] / 2;
@@ -204,11 +204,11 @@ THREE.FlyControls = function ( object, domElement ) {
 
 	this.updateMovementVector = function() {
 
-		var forward = ( this.moveState.forward || ( this.autoForward && !this.moveState.back ) ) ? 1 : 0;
+		var forward = ( this.moveState.forward || ( this.autoForward && ! this.moveState.back ) ) ? 1 : 0;
 
-		this.moveVector.x = ( -this.moveState.left    + this.moveState.right );
-		this.moveVector.y = ( -this.moveState.down    + this.moveState.up );
-		this.moveVector.z = ( -forward + this.moveState.back );
+		this.moveVector.x = ( - this.moveState.left    + this.moveState.right );
+		this.moveVector.y = ( - this.moveState.down    + this.moveState.up );
+		this.moveVector.z = ( - forward + this.moveState.back );
 
 		//console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] );
 
@@ -216,9 +216,9 @@ THREE.FlyControls = function ( object, domElement ) {
 
 	this.updateRotationVector = function() {
 
-		this.rotationVector.x = ( -this.moveState.pitchDown + this.moveState.pitchUp );
-		this.rotationVector.y = ( -this.moveState.yawRight  + this.moveState.yawLeft );
-		this.rotationVector.z = ( -this.moveState.rollRight + this.moveState.rollLeft );
+		this.rotationVector.x = ( - this.moveState.pitchDown + this.moveState.pitchUp );
+		this.rotationVector.y = ( - this.moveState.yawRight  + this.moveState.yawLeft );
+		this.rotationVector.z = ( - this.moveState.rollRight + this.moveState.rollLeft );
 
 		//console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] );
 
@@ -254,14 +254,38 @@ THREE.FlyControls = function ( object, domElement ) {
 
 	}
 
-	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+	function contextmenu( event ) {
 
-	this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false );
-	this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false );
-	this.domElement.addEventListener( 'mouseup',   bind( this, this.mouseup ), false );
+		event.preventDefault();
+
+	}
+
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', _mousedown, false );
+		this.domElement.removeEventListener( 'mousemove', _mousemove, false );
+		this.domElement.removeEventListener( 'mouseup', _mouseup, false );
+
+		window.removeEventListener( 'keydown', _keydown, false );
+		window.removeEventListener( 'keyup', _keyup, false );
+
+	}
+
+	var _mousemove = bind( this, this.mousemove );
+	var _mousedown = bind( this, this.mousedown );
+	var _mouseup = bind( this, this.mouseup );
+	var _keydown = bind( this, this.keydown );
+	var _keyup = bind( this, this.keyup );
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+
+	this.domElement.addEventListener( 'mousemove', _mousemove, false );
+	this.domElement.addEventListener( 'mousedown', _mousedown, false );
+	this.domElement.addEventListener( 'mouseup',   _mouseup, false );
 
-	window.addEventListener( 'keydown', bind( this, this.keydown ), false );
-	window.addEventListener( 'keyup',   bind( this, this.keyup ), false );
+	window.addEventListener( 'keydown', _keydown, false );
+	window.addEventListener( 'keyup',   _keyup, false );
 
 	this.updateMovementVector();
 	this.updateRotationVector();

+ 13 - 7
examples/js/controls/MouseControls.js

@@ -9,9 +9,9 @@ THREE.MouseControls = function ( object ) {
 	var scope = this;
 	var PI_2 = Math.PI / 2;
 	var mouseQuat = {
-    x: new THREE.Quaternion(),
-    y: new THREE.Quaternion()
-  };
+		x: new THREE.Quaternion(),
+		y: new THREE.Quaternion()
+	};
 	var object = object;
 	var xVector = new THREE.Vector3( 1, 0, 0 );
 	var yVector = new THREE.Vector3( 0, 1, 0 );
@@ -35,9 +35,9 @@ THREE.MouseControls = function ( object ) {
 	this.enabled = true;
 
 	this.orientation = {
-    x: 0,
-    y: 0,
-  };
+		x: 0,
+		y: 0,
+	};
 
 	this.update = function() {
 
@@ -45,11 +45,17 @@ THREE.MouseControls = function ( object ) {
 
 		mouseQuat.x.setFromAxisAngle( xVector, this.orientation.x );
 		mouseQuat.y.setFromAxisAngle( yVector, this.orientation.y );
-		object.quaternion.copy(mouseQuat.y).multiply(mouseQuat.x);
+		object.quaternion.copy( mouseQuat.y ).multiply( mouseQuat.x );
 		return;
 
 	};
 
+	this.dispose = function() {
+
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+
+	}
+
 	document.addEventListener( 'mousemove', onMouseMove, false );
 
 };

+ 823 - 414
examples/js/controls/OrbitControls.js

@@ -7,700 +7,1109 @@
  */
 /*global THREE, console */
 
-// This set of controls performs orbiting, dollying (zooming), and panning. It maintains
-// the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is
-// supported.
-//
-//    Orbit - left mouse / touch: one finger move
-//    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
-//    Pan - right mouse, or arrow keys / touch: three finter swipe
+( function () {
 
-THREE.OrbitControls = function ( object, domElement ) {
+	function OrbitConstraint ( object ) {
 
-	this.object = object;
-	this.domElement = ( domElement !== undefined ) ? domElement : document;
+		this.object = object;
 
-	// API
+		// "target" sets the location of focus, where the object orbits around
+		// and where it pans with respect to.
+		this.target = new THREE.Vector3();
 
-	// Set to false to disable this control
-	this.enabled = true;
+		// Limits to how far you can dolly in and out ( PerspectiveCamera only )
+		this.minDistance = 0;
+		this.maxDistance = Infinity;
 
-	// "target" sets the location of focus, where the control orbits around
-	// and where it pans with respect to.
-	this.target = new THREE.Vector3();
+		// Limits to how far you can zoom in and out ( OrthographicCamera only )
+		this.minZoom = 0;
+		this.maxZoom = Infinity;
 
-	// center is old, deprecated; use "target" instead
-	this.center = this.target;
+		// How far you can orbit vertically, upper and lower limits.
+		// Range is 0 to Math.PI radians.
+		this.minPolarAngle = 0; // radians
+		this.maxPolarAngle = Math.PI; // radians
 
-	// This option actually enables dollying in and out; left as "zoom" for
-	// backwards compatibility
-	this.noZoom = false;
-	this.zoomSpeed = 1.0;
+		// How far you can orbit horizontally, upper and lower limits.
+		// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
+		this.minAzimuthAngle = - Infinity; // radians
+		this.maxAzimuthAngle = Infinity; // radians
 
-	// Limits to how far you can dolly in and out ( PerspectiveCamera only )
-	this.minDistance = 0;
-	this.maxDistance = Infinity;
+		// Set to true to enable damping (inertia)
+		// If damping is enabled, you must call controls.update() in your animation loop
+		this.enableDamping = false;
+		this.dampingFactor = 0.25;
 
-	// Limits to how far you can zoom in and out ( OrthographicCamera only )
-	this.minZoom = 0;
-	this.maxZoom = Infinity;
+		////////////
+		// internals
 
-	// Set to true to disable this control
-	this.noRotate = false;
-	this.rotateSpeed = 1.0;
+		var scope = this;
 
-	// Set to true to disable this control
-	this.noPan = false;
-	this.keyPanSpeed = 7.0;	// pixels moved per arrow key push
+		var EPS = 0.000001;
 
-	// Set to true to automatically rotate around the target
-	this.autoRotate = false;
-	this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
+		// Current position in spherical coordinate system.
+		var theta;
+		var phi;
 
-	// How far you can orbit vertically, upper and lower limits.
-	// Range is 0 to Math.PI radians.
-	this.minPolarAngle = 0; // radians
-	this.maxPolarAngle = Math.PI; // radians
+		// Pending changes
+		var phiDelta = 0;
+		var thetaDelta = 0;
+		var scale = 1;
+		var panOffset = new THREE.Vector3();
+		var zoomChanged = false;
 
-	// How far you can orbit horizontally, upper and lower limits.
-	// If set, must be a sub-interval of the interval [ - Math.PI, Math.PI ].
-	this.minAzimuthAngle = - Infinity; // radians
-	this.maxAzimuthAngle = Infinity; // radians
+		// API
 
-	// Set to true to disable use of the keys
-	this.noKeys = false;
+		this.getPolarAngle = function () {
 
-	// The four arrow keys
-	this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
+			return phi;
 
-	// Mouse buttons
-	this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
+		};
 
-	////////////
-	// internals
+		this.getAzimuthalAngle = function () {
 
-	var scope = this;
+			return theta;
 
-	var EPS = 0.000001;
+		};
 
-	var rotateStart = new THREE.Vector2();
-	var rotateEnd = new THREE.Vector2();
-	var rotateDelta = new THREE.Vector2();
+		this.rotateLeft = function ( angle ) {
 
-	var panStart = new THREE.Vector2();
-	var panEnd = new THREE.Vector2();
-	var panDelta = new THREE.Vector2();
-	var panOffset = new THREE.Vector3();
+			thetaDelta -= angle;
 
-	var offset = new THREE.Vector3();
+		};
 
-	var dollyStart = new THREE.Vector2();
-	var dollyEnd = new THREE.Vector2();
-	var dollyDelta = new THREE.Vector2();
+		this.rotateUp = function ( angle ) {
 
-	var theta;
-	var phi;
-	var phiDelta = 0;
-	var thetaDelta = 0;
-	var scale = 1;
-	var pan = new THREE.Vector3();
+			phiDelta -= angle;
 
-	var lastPosition = new THREE.Vector3();
-	var lastQuaternion = new THREE.Quaternion();
+		};
 
-	var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
+		// pass in distance in world space to move left
+		this.panLeft = function() {
 
-	var state = STATE.NONE;
+			var v = new THREE.Vector3();
 
-	// for reset
+			return function panLeft ( distance ) {
 
-	this.target0 = this.target.clone();
-	this.position0 = this.object.position.clone();
-	this.zoom0 = this.object.zoom;
+				var te = this.object.matrix.elements;
 
-	// so camera.up is the orbit axis
+				// get X column of matrix
+				v.set( te[ 0 ], te[ 1 ], te[ 2 ] );
+				v.multiplyScalar( - distance );
 
-	var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
-	var quatInverse = quat.clone().inverse();
+				panOffset.add( v );
 
-	// events
+			};
 
-	var changeEvent = { type: 'change' };
-	var startEvent = { type: 'start' };
-	var endEvent = { type: 'end' };
+		}();
 
-	this.rotateLeft = function ( angle ) {
+		// pass in distance in world space to move up
+		this.panUp = function() {
 
-		if ( angle === undefined ) {
+			var v = new THREE.Vector3();
 
-			angle = getAutoRotationAngle();
+			return function panUp ( distance ) {
 
-		}
+				var te = this.object.matrix.elements;
 
-		thetaDelta -= angle;
+				// get Y column of matrix
+				v.set( te[ 4 ], te[ 5 ], te[ 6 ] );
+				v.multiplyScalar( distance );
 
-	};
+				panOffset.add( v );
 
-	this.rotateUp = function ( angle ) {
+			};
 
-		if ( angle === undefined ) {
+		}();
 
-			angle = getAutoRotationAngle();
+		// pass in x,y of change desired in pixel space,
+		// right and down are positive
+		this.pan = function ( deltaX, deltaY, screenWidth, screenHeight ) {
 
-		}
+			if ( scope.object instanceof THREE.PerspectiveCamera ) {
 
-		phiDelta -= angle;
+				// perspective
+				var position = scope.object.position;
+				var offset = position.clone().sub( scope.target );
+				var targetDistance = offset.length();
 
-	};
+				// half of the fov is center to top of screen
+				targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
 
-	// pass in distance in world space to move left
-	this.panLeft = function ( distance ) {
+				// we actually don't use screenWidth, since perspective camera is fixed to screen height
+				scope.panLeft( 2 * deltaX * targetDistance / screenHeight );
+				scope.panUp( 2 * deltaY * targetDistance / screenHeight );
 
-		var te = this.object.matrix.elements;
+			} else if ( scope.object instanceof THREE.OrthographicCamera ) {
 
-		// get X column of matrix
-		panOffset.set( te[ 0 ], te[ 1 ], te[ 2 ] );
-		panOffset.multiplyScalar( - distance );
+				// orthographic
+				scope.panLeft( deltaX * ( scope.object.right - scope.object.left ) / screenWidth );
+				scope.panUp( deltaY * ( scope.object.top - scope.object.bottom ) / screenHeight );
 
-		pan.add( panOffset );
+			} else {
 
-	};
+				// camera neither orthographic or perspective
+				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
+
+			}
+
+		};
+
+		this.dollyIn = function ( dollyScale ) {
+
+			if ( scope.object instanceof THREE.PerspectiveCamera ) {
+
+				scale /= dollyScale;
+
+			} else if ( scope.object instanceof THREE.OrthographicCamera ) {
+
+				scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom * dollyScale ) );
+				scope.object.updateProjectionMatrix();
+				zoomChanged = true;
+
+			} else {
+
+				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+
+			}
+
+		};
+
+		this.dollyOut = function ( dollyScale ) {
+
+			if ( scope.object instanceof THREE.PerspectiveCamera ) {
+
+				scale *= dollyScale;
+
+			} else if ( scope.object instanceof THREE.OrthographicCamera ) {
+
+				scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / dollyScale ) );
+				scope.object.updateProjectionMatrix();
+				zoomChanged = true;
+
+			} else {
+
+				console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+
+			}
+
+		};
+
+		this.update = function() {
+
+			var offset = new THREE.Vector3();
+
+			// so camera.up is the orbit axis
+			var quat = new THREE.Quaternion().setFromUnitVectors( object.up, new THREE.Vector3( 0, 1, 0 ) );
+			var quatInverse = quat.clone().inverse();
+
+			var lastPosition = new THREE.Vector3();
+			var lastQuaternion = new THREE.Quaternion();
+
+			return function () {
+
+				var position = this.object.position;
+
+				offset.copy( position ).sub( this.target );
 
-	// pass in distance in world space to move up
-	this.panUp = function ( distance ) {
+				// rotate offset to "y-axis-is-up" space
+				offset.applyQuaternion( quat );
 
-		var te = this.object.matrix.elements;
+				// angle from z-axis around y-axis
 
-		// get Y column of matrix
-		panOffset.set( te[ 4 ], te[ 5 ], te[ 6 ] );
-		panOffset.multiplyScalar( distance );
+				theta = Math.atan2( offset.x, offset.z );
 
-		pan.add( panOffset );
+				// angle from y-axis
+
+				phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
+
+				theta += thetaDelta;
+				phi += phiDelta;
+
+				// restrict theta to be between desired limits
+				theta = Math.max( this.minAzimuthAngle, Math.min( this.maxAzimuthAngle, theta ) );
+
+				// restrict phi to be between desired limits
+				phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
+
+				// restrict phi to be betwee EPS and PI-EPS
+				phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
+
+				var radius = offset.length() * scale;
+
+				// restrict radius to be between desired limits
+				radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
+
+				// move target to panned location
+				this.target.add( panOffset );
+
+				offset.x = radius * Math.sin( phi ) * Math.sin( theta );
+				offset.y = radius * Math.cos( phi );
+				offset.z = radius * Math.sin( phi ) * Math.cos( theta );
+
+				// rotate offset back to "camera-up-vector-is-up" space
+				offset.applyQuaternion( quatInverse );
+
+				position.copy( this.target ).add( offset );
+
+				this.object.lookAt( this.target );
+
+				if ( this.enableDamping === true ) {
+
+					thetaDelta *= ( 1 - this.dampingFactor );
+					phiDelta *= ( 1 - this.dampingFactor );
+
+				} else {
+
+					thetaDelta = 0;
+					phiDelta = 0;
+
+				}
+
+				scale = 1;
+				panOffset.set( 0, 0, 0 );
+
+				// update condition is:
+				// min(camera displacement, camera rotation in radians)^2 > EPS
+				// using small-angle approximation cos(x/2) = 1 - x^2 / 8
+
+				if ( zoomChanged ||
+					 lastPosition.distanceToSquared( this.object.position ) > EPS ||
+				    8 * ( 1 - lastQuaternion.dot( this.object.quaternion ) ) > EPS ) {
+
+					lastPosition.copy( this.object.position );
+					lastQuaternion.copy( this.object.quaternion );
+					zoomChanged = false;
+
+					return true;
+
+				}
+
+				return false;
+
+			};
+
+		}();
 
 	};
 
-	// pass in x,y of change desired in pixel space,
-	// right and down are positive
-	this.pan = function ( deltaX, deltaY ) {
 
-		var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+	// This set of controls performs orbiting, dollying (zooming), and panning. It maintains
+	// the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is
+	// supported.
+	//
+	//    Orbit - left mouse / touch: one finger move
+	//    Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
+	//    Pan - right mouse, or arrow keys / touch: three finter swipe
+
+	THREE.OrbitControls = function ( object, domElement ) {
+
+		var constraint = new OrbitConstraint( object );
+
+		this.domElement = ( domElement !== undefined ) ? domElement : document;
 
-		if ( scope.object instanceof THREE.PerspectiveCamera ) {
+		// API
 
-			// perspective
-			var position = scope.object.position;
-			var offset = position.clone().sub( scope.target );
-			var targetDistance = offset.length();
+		Object.defineProperty( this, 'constraint', {
+
+			get: function() {
+
+				return constraint;
+
+			}
 
-			// half of the fov is center to top of screen
-			targetDistance *= Math.tan( ( scope.object.fov / 2 ) * Math.PI / 180.0 );
+		} );
 
-			// we actually don't use screenWidth, since perspective camera is fixed to screen height
-			scope.panLeft( 2 * deltaX * targetDistance / element.clientHeight );
-			scope.panUp( 2 * deltaY * targetDistance / element.clientHeight );
+		this.getPolarAngle = function () {
 
-		} else if ( scope.object instanceof THREE.OrthographicCamera ) {
+			return constraint.getPolarAngle();
 
-			// orthographic
-			scope.panLeft( deltaX * (scope.object.right - scope.object.left) / element.clientWidth );
-			scope.panUp( deltaY * (scope.object.top - scope.object.bottom) / element.clientHeight );
+		};
 
-		} else {
+		this.getAzimuthalAngle = function () {
 
-			// camera neither orthographic or perspective
-			console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
+			return constraint.getAzimuthalAngle();
+
+		};
+
+		// Set to false to disable this control
+		this.enabled = true;
+
+		// center is old, deprecated; use "target" instead
+		this.center = this.target;
+
+		// This option actually enables dollying in and out; left as "zoom" for
+		// backwards compatibility.
+		// Set to false to disable zooming
+		this.enableZoom = true;
+		this.zoomSpeed = 1.0;
+
+		// Set to false to disable rotating
+		this.enableRotate = true;
+		this.rotateSpeed = 1.0;
+
+		// Set to false to disable panning
+		this.enablePan = true;
+		this.keyPanSpeed = 7.0;	// pixels moved per arrow key push
+
+		// Set to true to automatically rotate around the target
+		// If auto-rotate is enabled, you must call controls.update() in your animation loop
+		this.autoRotate = false;
+		this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
+
+		// Set to false to disable use of the keys
+		this.enableKeys = true;
+
+		// The four arrow keys
+		this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
+
+		// Mouse buttons
+		this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
+
+		////////////
+		// internals
+
+		var scope = this;
+
+		var rotateStart = new THREE.Vector2();
+		var rotateEnd = new THREE.Vector2();
+		var rotateDelta = new THREE.Vector2();
+
+		var panStart = new THREE.Vector2();
+		var panEnd = new THREE.Vector2();
+		var panDelta = new THREE.Vector2();
+
+		var dollyStart = new THREE.Vector2();
+		var dollyEnd = new THREE.Vector2();
+		var dollyDelta = new THREE.Vector2();
+
+		var STATE = { NONE : - 1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
+
+		var state = STATE.NONE;
+
+		// for reset
+
+		this.target0 = this.target.clone();
+		this.position0 = this.object.position.clone();
+		this.zoom0 = this.object.zoom;
+
+		// events
+
+		var changeEvent = { type: 'change' };
+		var startEvent = { type: 'start' };
+		var endEvent = { type: 'end' };
+
+		// pass in x,y of change desired in pixel space,
+		// right and down are positive
+		function pan( deltaX, deltaY ) {
+
+			var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+
+			constraint.pan( deltaX, deltaY, element.clientWidth, element.clientHeight );
 
 		}
 
-	};
+		this.update = function () {
 
-	this.dollyIn = function ( dollyScale ) {
+			if ( this.autoRotate && state === STATE.NONE ) {
 
-		if ( dollyScale === undefined ) {
+				constraint.rotateLeft( getAutoRotationAngle() );
+
+			}
 
-			dollyScale = getZoomScale();
+			if ( constraint.update() === true ) {
+
+				this.dispatchEvent( changeEvent );
+
+			}
+
+		};
+
+		this.reset = function () {
+
+			state = STATE.NONE;
+
+			this.target.copy( this.target0 );
+			this.object.position.copy( this.position0 );
+			this.object.zoom = this.zoom0;
+
+			this.object.updateProjectionMatrix();
+			this.dispatchEvent( changeEvent );
+
+			this.update();
+
+		};
+
+		function getAutoRotationAngle() {
+
+			return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
+
+		}
+
+		function getZoomScale() {
+
+			return Math.pow( 0.95, scope.zoomSpeed );
 
 		}
 
-		if ( scope.object instanceof THREE.PerspectiveCamera ) {
+		function onMouseDown( event ) {
+
+			if ( scope.enabled === false ) return;
+
+			event.preventDefault();
+
+			if ( event.button === scope.mouseButtons.ORBIT ) {
+
+				if ( scope.enableRotate === false ) return;
+
+				state = STATE.ROTATE;
+
+				rotateStart.set( event.clientX, event.clientY );
+
+			} else if ( event.button === scope.mouseButtons.ZOOM ) {
+
+				if ( scope.enableZoom === false ) return;
 
-			scale /= dollyScale;
+				state = STATE.DOLLY;
 
-		} else if ( scope.object instanceof THREE.OrthographicCamera ) {
+				dollyStart.set( event.clientX, event.clientY );
 
-			scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom * dollyScale ) );
-			scope.object.updateProjectionMatrix();
-			scope.dispatchEvent( changeEvent );
+			} else if ( event.button === scope.mouseButtons.PAN ) {
 
-		} else {
+				if ( scope.enablePan === false ) return;
 
-			console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+				state = STATE.PAN;
+
+				panStart.set( event.clientX, event.clientY );
+
+			}
+
+			if ( state !== STATE.NONE ) {
+
+				document.addEventListener( 'mousemove', onMouseMove, false );
+				document.addEventListener( 'mouseup', onMouseUp, false );
+				scope.dispatchEvent( startEvent );
+
+			}
 
 		}
 
-	};
+		function onMouseMove( event ) {
+
+			if ( scope.enabled === false ) return;
+
+			event.preventDefault();
+
+			var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+
+			if ( state === STATE.ROTATE ) {
+
+				if ( scope.enableRotate === false ) return;
+
+				rotateEnd.set( event.clientX, event.clientY );
+				rotateDelta.subVectors( rotateEnd, rotateStart );
+
+				// rotating across whole screen goes 360 degrees around
+				constraint.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
 
-	this.dollyOut = function ( dollyScale ) {
+				// rotating up and down along whole screen attempts to go 360, but limited to 180
+				constraint.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
+
+				rotateStart.copy( rotateEnd );
+
+			} else if ( state === STATE.DOLLY ) {
+
+				if ( scope.enableZoom === false ) return;
+
+				dollyEnd.set( event.clientX, event.clientY );
+				dollyDelta.subVectors( dollyEnd, dollyStart );
+
+				if ( dollyDelta.y > 0 ) {
+
+					constraint.dollyIn( getZoomScale() );
+
+				} else if ( dollyDelta.y < 0 ) {
+
+					constraint.dollyOut( getZoomScale() );
+
+				}
+
+				dollyStart.copy( dollyEnd );
+
+			} else if ( state === STATE.PAN ) {
+
+				if ( scope.enablePan === false ) return;
+
+				panEnd.set( event.clientX, event.clientY );
+				panDelta.subVectors( panEnd, panStart );
+
+				pan( panDelta.x, panDelta.y );
+
+				panStart.copy( panEnd );
+
+			}
+
+			if ( state !== STATE.NONE ) scope.update();
+
+		}
+
+		function onMouseUp( /* event */ ) {
+
+			if ( scope.enabled === false ) return;
+
+			document.removeEventListener( 'mousemove', onMouseMove, false );
+			document.removeEventListener( 'mouseup', onMouseUp, false );
+			scope.dispatchEvent( endEvent );
+			state = STATE.NONE;
+
+		}
+
+		function onMouseWheel( event ) {
 
-		if ( dollyScale === undefined ) {
+			if ( scope.enabled === false || scope.enableZoom === false || state !== STATE.NONE ) return;
 
-			dollyScale = getZoomScale();
+			event.preventDefault();
+			event.stopPropagation();
+
+			var delta = 0;
+
+			if ( event.wheelDelta !== undefined ) {
+
+				// WebKit / Opera / Explorer 9
+
+				delta = event.wheelDelta;
+
+			} else if ( event.detail !== undefined ) {
+
+				// Firefox
+
+				delta = - event.detail;
+
+			}
+
+			if ( delta > 0 ) {
+
+				constraint.dollyOut( getZoomScale() );
+
+			} else if ( delta < 0 ) {
+
+				constraint.dollyIn( getZoomScale() );
+
+			}
+
+			scope.update();
+			scope.dispatchEvent( startEvent );
+			scope.dispatchEvent( endEvent );
 
 		}
 
-		if ( scope.object instanceof THREE.PerspectiveCamera ) {
+		function onKeyDown( event ) {
+
+			if ( scope.enabled === false || scope.enableKeys === false || scope.enablePan === false ) return;
 
-			scale *= dollyScale;
+			switch ( event.keyCode ) {
 
-		} else if ( scope.object instanceof THREE.OrthographicCamera ) {
+				case scope.keys.UP:
+					pan( 0, scope.keyPanSpeed );
+					scope.update();
+					break;
 
-			scope.object.zoom = Math.max( this.minZoom, Math.min( this.maxZoom, this.object.zoom / dollyScale ) );
-			scope.object.updateProjectionMatrix();
-			scope.dispatchEvent( changeEvent );
+				case scope.keys.BOTTOM:
+					pan( 0, - scope.keyPanSpeed );
+					scope.update();
+					break;
 
-		} else {
+				case scope.keys.LEFT:
+					pan( scope.keyPanSpeed, 0 );
+					scope.update();
+					break;
 
-			console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - dolly/zoom disabled.' );
+				case scope.keys.RIGHT:
+					pan( - scope.keyPanSpeed, 0 );
+					scope.update();
+					break;
+
+			}
 
 		}
 
-	};
+		function touchstart( event ) {
+
+			if ( scope.enabled === false ) return;
+
+			switch ( event.touches.length ) {
+
+				case 1:	// one-fingered touch: rotate
+
+					if ( scope.enableRotate === false ) return;
+
+					state = STATE.TOUCH_ROTATE;
+
+					rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+					break;
 
-	this.update = function () {
+				case 2:	// two-fingered touch: dolly
 
-		var position = this.object.position;
+					if ( scope.enableZoom === false ) return;
 
-		offset.copy( position ).sub( this.target );
+					state = STATE.TOUCH_DOLLY;
 
-		// rotate offset to "y-axis-is-up" space
-		offset.applyQuaternion( quat );
+					var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+					var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+					var distance = Math.sqrt( dx * dx + dy * dy );
+					dollyStart.set( 0, distance );
+					break;
 
-		// angle from z-axis around y-axis
+				case 3: // three-fingered touch: pan
 
-		theta = Math.atan2( offset.x, offset.z );
+					if ( scope.enablePan === false ) return;
 
-		// angle from y-axis
+					state = STATE.TOUCH_PAN;
 
-		phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
+					panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+					break;
 
-		if ( this.autoRotate && state === STATE.NONE ) {
+				default:
 
-			this.rotateLeft( getAutoRotationAngle() );
+					state = STATE.NONE;
+
+			}
+
+			if ( state !== STATE.NONE ) scope.dispatchEvent( startEvent );
 
 		}
 
-		theta += thetaDelta;
-		phi += phiDelta;
+		function touchmove( event ) {
 
-		// restrict theta to be between desired limits
-		theta = Math.max( this.minAzimuthAngle, Math.min( this.maxAzimuthAngle, theta ) );
+			if ( scope.enabled === false ) return;
 
-		// restrict phi to be between desired limits
-		phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
+			event.preventDefault();
+			event.stopPropagation();
 
-		// restrict phi to be betwee EPS and PI-EPS
-		phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
+			var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
 
-		var radius = offset.length() * scale;
+			switch ( event.touches.length ) {
 
-		// restrict radius to be between desired limits
-		radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
+				case 1: // one-fingered touch: rotate
 
-		// move target to panned location
-		this.target.add( pan );
+					if ( scope.enableRotate === false ) return;
+					if ( state !== STATE.TOUCH_ROTATE ) return;
 
-		offset.x = radius * Math.sin( phi ) * Math.sin( theta );
-		offset.y = radius * Math.cos( phi );
-		offset.z = radius * Math.sin( phi ) * Math.cos( theta );
+					rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+					rotateDelta.subVectors( rotateEnd, rotateStart );
 
-		// rotate offset back to "camera-up-vector-is-up" space
-		offset.applyQuaternion( quatInverse );
+					// rotating across whole screen goes 360 degrees around
+					constraint.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
+					// rotating up and down along whole screen attempts to go 360, but limited to 180
+					constraint.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
 
-		position.copy( this.target ).add( offset );
+					rotateStart.copy( rotateEnd );
 
-		this.object.lookAt( this.target );
+					scope.update();
+					break;
 
-		thetaDelta = 0;
-		phiDelta = 0;
-		scale = 1;
-		pan.set( 0, 0, 0 );
+				case 2: // two-fingered touch: dolly
 
-		// update condition is:
-		// min(camera displacement, camera rotation in radians)^2 > EPS
-		// using small-angle approximation cos(x/2) = 1 - x^2 / 8
+					if ( scope.enableZoom === false ) return;
+					if ( state !== STATE.TOUCH_DOLLY ) return;
 
-		if ( lastPosition.distanceToSquared( this.object.position ) > EPS
-		    || 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS ) {
+					var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+					var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+					var distance = Math.sqrt( dx * dx + dy * dy );
 
-			this.dispatchEvent( changeEvent );
+					dollyEnd.set( 0, distance );
+					dollyDelta.subVectors( dollyEnd, dollyStart );
+
+					if ( dollyDelta.y > 0 ) {
+
+						constraint.dollyOut( getZoomScale() );
+
+					} else if ( dollyDelta.y < 0 ) {
+
+						constraint.dollyIn( getZoomScale() );
 
-			lastPosition.copy( this.object.position );
-			lastQuaternion.copy (this.object.quaternion );
+					}
+
+					dollyStart.copy( dollyEnd );
+
+					scope.update();
+					break;
+
+				case 3: // three-fingered touch: pan
+
+					if ( scope.enablePan === false ) return;
+					if ( state !== STATE.TOUCH_PAN ) return;
+
+					panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+					panDelta.subVectors( panEnd, panStart );
+
+					pan( panDelta.x, panDelta.y );
+
+					panStart.copy( panEnd );
+
+					scope.update();
+					break;
+
+				default:
+
+					state = STATE.NONE;
+
+			}
 
 		}
 
-	};
+		function touchend( /* event */ ) {
 
+			if ( scope.enabled === false ) return;
 
-	this.reset = function () {
+			scope.dispatchEvent( endEvent );
+			state = STATE.NONE;
 
-		state = STATE.NONE;
+		}
+
+		function contextmenu( event ) {
+
+			event.preventDefault();
+
+		}
 
-		this.target.copy( this.target0 );
-		this.object.position.copy( this.position0 );
-		this.object.zoom = this.zoom0;
+		this.dispose = function() {
 
-		this.object.updateProjectionMatrix();
-		this.dispatchEvent( changeEvent );
+			this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+			this.domElement.removeEventListener( 'mousedown', onMouseDown, false );
+			this.domElement.removeEventListener( 'mousewheel', onMouseWheel, false );
+			this.domElement.removeEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
 
+			this.domElement.removeEventListener( 'touchstart', touchstart, false );
+			this.domElement.removeEventListener( 'touchend', touchend, false );
+			this.domElement.removeEventListener( 'touchmove', touchmove, false );
+
+			document.removeEventListener( 'mousemove', onMouseMove, false );
+			document.removeEventListener( 'mouseup', onMouseUp, false );
+
+			window.removeEventListener( 'keydown', onKeyDown, false );
+
+		}
+
+		this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+
+		this.domElement.addEventListener( 'mousedown', onMouseDown, false );
+		this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
+		this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
+
+		this.domElement.addEventListener( 'touchstart', touchstart, false );
+		this.domElement.addEventListener( 'touchend', touchend, false );
+		this.domElement.addEventListener( 'touchmove', touchmove, false );
+
+		window.addEventListener( 'keydown', onKeyDown, false );
+
+		// force an update at start
 		this.update();
 
 	};
 
-	this.getPolarAngle = function () {
+	THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
+	THREE.OrbitControls.prototype.constructor = THREE.OrbitControls;
 
-		return phi;
+	Object.defineProperties( THREE.OrbitControls.prototype, {
 
-	};
+		object: {
 
-	this.getAzimuthalAngle = function () {
+			get: function () {
 
-		return theta
+				return this.constraint.object;
 
-	};
+			}
 
-	function getAutoRotationAngle() {
+		},
 
-		return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
+		target: {
 
-	}
+			get: function () {
 
-	function getZoomScale() {
+				return this.constraint.target;
 
-		return Math.pow( 0.95, scope.zoomSpeed );
+			},
 
-	}
+			set: function ( value ) {
 
-	function onMouseDown( event ) {
+				console.warn( 'THREE.OrbitControls: target is now immutable. Use target.set() instead.' );
+				this.constraint.target.copy( value );
 
-		if ( scope.enabled === false ) return;
-		event.preventDefault();
+			}
 
-		if ( event.button === scope.mouseButtons.ORBIT ) {
-			if ( scope.noRotate === true ) return;
+		},
 
-			state = STATE.ROTATE;
+		minDistance : {
 
-			rotateStart.set( event.clientX, event.clientY );
+			get: function () {
 
-		} else if ( event.button === scope.mouseButtons.ZOOM ) {
-			if ( scope.noZoom === true ) return;
+				return this.constraint.minDistance;
 
-			state = STATE.DOLLY;
+			},
 
-			dollyStart.set( event.clientX, event.clientY );
+			set: function ( value ) {
 
-		} else if ( event.button === scope.mouseButtons.PAN ) {
-			if ( scope.noPan === true ) return;
+				this.constraint.minDistance = value;
 
-			state = STATE.PAN;
+			}
 
-			panStart.set( event.clientX, event.clientY );
+		},
 
-		}
+		maxDistance : {
 
-		if ( state !== STATE.NONE ) {
-			document.addEventListener( 'mousemove', onMouseMove, false );
-			document.addEventListener( 'mouseup', onMouseUp, false );
-			scope.dispatchEvent( startEvent );
-		}
+			get: function () {
 
-	}
+				return this.constraint.maxDistance;
 
-	function onMouseMove( event ) {
+			},
 
-		if ( scope.enabled === false ) return;
+			set: function ( value ) {
 
-		event.preventDefault();
+				this.constraint.maxDistance = value;
 
-		var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+			}
+
+		},
 
-		if ( state === STATE.ROTATE ) {
+		minZoom : {
 
-			if ( scope.noRotate === true ) return;
+			get: function () {
 
-			rotateEnd.set( event.clientX, event.clientY );
-			rotateDelta.subVectors( rotateEnd, rotateStart );
+				return this.constraint.minZoom;
 
-			// rotating across whole screen goes 360 degrees around
-			scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
+			},
 
-			// rotating up and down along whole screen attempts to go 360, but limited to 180
-			scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
+			set: function ( value ) {
 
-			rotateStart.copy( rotateEnd );
+				this.constraint.minZoom = value;
 
-		} else if ( state === STATE.DOLLY ) {
+			}
 
-			if ( scope.noZoom === true ) return;
+		},
 
-			dollyEnd.set( event.clientX, event.clientY );
-			dollyDelta.subVectors( dollyEnd, dollyStart );
+		maxZoom : {
 
-			if ( dollyDelta.y > 0 ) {
+			get: function () {
 
-				scope.dollyIn();
+				return this.constraint.maxZoom;
 
-			} else if ( dollyDelta.y < 0 ) {
+			},
 
-				scope.dollyOut();
+			set: function ( value ) {
+
+				this.constraint.maxZoom = value;
 
 			}
 
-			dollyStart.copy( dollyEnd );
+		},
 
-		} else if ( state === STATE.PAN ) {
+		minPolarAngle : {
 
-			if ( scope.noPan === true ) return;
+			get: function () {
 
-			panEnd.set( event.clientX, event.clientY );
-			panDelta.subVectors( panEnd, panStart );
+				return this.constraint.minPolarAngle;
 
-			scope.pan( panDelta.x, panDelta.y );
+			},
 
-			panStart.copy( panEnd );
+			set: function ( value ) {
 
-		}
+				this.constraint.minPolarAngle = value;
 
-		if ( state !== STATE.NONE ) scope.update();
+			}
 
-	}
+		},
 
-	function onMouseUp( /* event */ ) {
+		maxPolarAngle : {
 
-		if ( scope.enabled === false ) return;
+			get: function () {
 
-		document.removeEventListener( 'mousemove', onMouseMove, false );
-		document.removeEventListener( 'mouseup', onMouseUp, false );
-		scope.dispatchEvent( endEvent );
-		state = STATE.NONE;
+				return this.constraint.maxPolarAngle;
 
-	}
+			},
 
-	function onMouseWheel( event ) {
+			set: function ( value ) {
 
-		if ( scope.enabled === false || scope.noZoom === true || state !== STATE.NONE ) return;
+				this.constraint.maxPolarAngle = value;
 
-		event.preventDefault();
-		event.stopPropagation();
+			}
 
-		var delta = 0;
+		},
 
-		if ( event.wheelDelta !== undefined ) { // WebKit / Opera / Explorer 9
+		minAzimuthAngle : {
 
-			delta = event.wheelDelta;
+			get: function () {
 
-		} else if ( event.detail !== undefined ) { // Firefox
+				return this.constraint.minAzimuthAngle;
 
-			delta = - event.detail;
+			},
 
-		}
+			set: function ( value ) {
 
-		if ( delta > 0 ) {
+				this.constraint.minAzimuthAngle = value;
 
-			scope.dollyOut();
+			}
 
-		} else if ( delta < 0 ) {
+		},
 
-			scope.dollyIn();
+		maxAzimuthAngle : {
 
-		}
+			get: function () {
 
-		scope.update();
-		scope.dispatchEvent( startEvent );
-		scope.dispatchEvent( endEvent );
+				return this.constraint.maxAzimuthAngle;
 
-	}
+			},
 
-	function onKeyDown( event ) {
+			set: function ( value ) {
 
-		if ( scope.enabled === false || scope.noKeys === true || scope.noPan === true ) return;
+				this.constraint.maxAzimuthAngle = value;
 
-		switch ( event.keyCode ) {
+			}
 
-			case scope.keys.UP:
-				scope.pan( 0, scope.keyPanSpeed );
-				scope.update();
-				break;
+		},
 
-			case scope.keys.BOTTOM:
-				scope.pan( 0, - scope.keyPanSpeed );
-				scope.update();
-				break;
+		enableDamping : {
 
-			case scope.keys.LEFT:
-				scope.pan( scope.keyPanSpeed, 0 );
-				scope.update();
-				break;
+			get: function () {
 
-			case scope.keys.RIGHT:
-				scope.pan( - scope.keyPanSpeed, 0 );
-				scope.update();
-				break;
+				return this.constraint.enableDamping;
 
-		}
+			},
 
-	}
+			set: function ( value ) {
 
-	function touchstart( event ) {
+				this.constraint.enableDamping = value;
 
-		if ( scope.enabled === false ) return;
+			}
 
-		switch ( event.touches.length ) {
+		},
 
-			case 1:	// one-fingered touch: rotate
+		dampingFactor : {
 
-				if ( scope.noRotate === true ) return;
+			get: function () {
 
-				state = STATE.TOUCH_ROTATE;
+				return this.constraint.dampingFactor;
 
-				rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
-				break;
+			},
 
-			case 2:	// two-fingered touch: dolly
+			set: function ( value ) {
 
-				if ( scope.noZoom === true ) return;
+				this.constraint.dampingFactor = value;
 
-				state = STATE.TOUCH_DOLLY;
+			}
 
-				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
-				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
-				var distance = Math.sqrt( dx * dx + dy * dy );
-				dollyStart.set( 0, distance );
-				break;
+		},
 
-			case 3: // three-fingered touch: pan
+		// backward compatibility
 
-				if ( scope.noPan === true ) return;
+		noZoom: {
 
-				state = STATE.TOUCH_PAN;
+			get: function () {
 
-				panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
-				break;
+				console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );
+				return ! this.enableZoom;
 
-			default:
+			},
 
-				state = STATE.NONE;
+			set: function ( value ) {
 
-		}
+				console.warn( 'THREE.OrbitControls: .noZoom has been deprecated. Use .enableZoom instead.' );
+				this.enableZoom = ! value;
 
-		if ( state !== STATE.NONE ) scope.dispatchEvent( startEvent );
+			}
 
-	}
+		},
 
-	function touchmove( event ) {
+		noRotate: {
 
-		if ( scope.enabled === false ) return;
+			get: function () {
 
-		event.preventDefault();
-		event.stopPropagation();
+				console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );
+				return ! this.enableRotate;
 
-		var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
+			},
 
-		switch ( event.touches.length ) {
+			set: function ( value ) {
 
-			case 1: // one-fingered touch: rotate
+				console.warn( 'THREE.OrbitControls: .noRotate has been deprecated. Use .enableRotate instead.' );
+				this.enableRotate = ! value;
 
-				if ( scope.noRotate === true ) return;
-				if ( state !== STATE.TOUCH_ROTATE ) return;
+			}
 
-				rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
-				rotateDelta.subVectors( rotateEnd, rotateStart );
+		},
 
-				// rotating across whole screen goes 360 degrees around
-				scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
-				// rotating up and down along whole screen attempts to go 360, but limited to 180
-				scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
+		noPan: {
 
-				rotateStart.copy( rotateEnd );
+			get: function () {
 
-				scope.update();
-				break;
+				console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );
+				return ! this.enablePan;
 
-			case 2: // two-fingered touch: dolly
+			},
 
-				if ( scope.noZoom === true ) return;
-				if ( state !== STATE.TOUCH_DOLLY ) return;
+			set: function ( value ) {
 
-				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
-				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
-				var distance = Math.sqrt( dx * dx + dy * dy );
+				console.warn( 'THREE.OrbitControls: .noPan has been deprecated. Use .enablePan instead.' );
+				this.enablePan = ! value;
 
-				dollyEnd.set( 0, distance );
-				dollyDelta.subVectors( dollyEnd, dollyStart );
+			}
 
-				if ( dollyDelta.y > 0 ) {
+		},
 
-					scope.dollyOut();
+		noKeys: {
 
-				} else if ( dollyDelta.y < 0 ) {
+			get: function () {
 
-					scope.dollyIn();
+				console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );
+				return ! this.enableKeys;
 
-				}
+			},
 
-				dollyStart.copy( dollyEnd );
+			set: function ( value ) {
 
-				scope.update();
-				break;
+				console.warn( 'THREE.OrbitControls: .noKeys has been deprecated. Use .enableKeys instead.' );
+				this.enableKeys = ! value;
 
-			case 3: // three-fingered touch: pan
+			}
 
-				if ( scope.noPan === true ) return;
-				if ( state !== STATE.TOUCH_PAN ) return;
+		},
 
-				panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
-				panDelta.subVectors( panEnd, panStart );
+		staticMoving : {
 
-				scope.pan( panDelta.x, panDelta.y );
+			get: function () {
 
-				panStart.copy( panEnd );
+				console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );
+				return ! this.constraint.enableDamping;
 
-				scope.update();
-				break;
+			},
 
-			default:
+			set: function ( value ) {
 
-				state = STATE.NONE;
+				console.warn( 'THREE.OrbitControls: .staticMoving has been deprecated. Use .enableDamping instead.' );
+				this.constraint.enableDamping = ! value;
 
-		}
+			}
 
-	}
+		},
 
-	function touchend( /* event */ ) {
+		dynamicDampingFactor : {
 
-		if ( scope.enabled === false ) return;
+			get: function () {
 
-		scope.dispatchEvent( endEvent );
-		state = STATE.NONE;
+				console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );
+				return this.constraint.dampingFactor;
 
-	}
+			},
 
-	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
-	this.domElement.addEventListener( 'mousedown', onMouseDown, false );
-	this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
-	this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
+			set: function ( value ) {
 
-	this.domElement.addEventListener( 'touchstart', touchstart, false );
-	this.domElement.addEventListener( 'touchend', touchend, false );
-	this.domElement.addEventListener( 'touchmove', touchmove, false );
+				console.warn( 'THREE.OrbitControls: .dynamicDampingFactor has been renamed. Use .dampingFactor instead.' );
+				this.constraint.dampingFactor = value;
 
-	window.addEventListener( 'keydown', onKeyDown, false );
+			}
 
-	// force an update at start
-	this.update();
+		}
 
-};
+	} );
 
-THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );
-THREE.OrbitControls.prototype.constructor = THREE.OrbitControls;
+}() );

+ 58 - 28
examples/js/controls/OrthographicTrackballControls.js

@@ -8,7 +8,7 @@
 THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	var _this = this;
-	var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
+	var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
 
 	this.object = object;
 	this.domElement = ( domElement !== undefined ) ? domElement : document;
@@ -123,7 +123,7 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 		var vector = new THREE.Vector2();
 
-		return function ( pageX, pageY ) {
+		return function getMouseOnScreen( pageX, pageY ) {
 
 			vector.set(
 				( pageX - _this.screen.left ) / _this.screen.width,
@@ -142,7 +142,7 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 		var objectUp = new THREE.Vector3();
 		var mouseOnBall = new THREE.Vector3();
 
-		return function ( pageX, pageY ) {
+		return function getMouseProjectionOnBall( pageX, pageY ) {
 
 			mouseOnBall.set(
 				( pageX - _this.screen.width * 0.5 - _this.screen.left ) / _this.radius,
@@ -186,13 +186,13 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	}() );
 
-	this.rotateCamera = (function() {
+	this.rotateCamera = ( function() {
 
 		var axis = new THREE.Vector3(),
 			quaternion = new THREE.Quaternion();
 
 
-		return function () {
+		return function rotateCamera() {
 
 			var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
 
@@ -202,7 +202,7 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 				angle *= _this.rotateSpeed;
 
-				quaternion.setFromAxisAngle( axis, -angle );
+				quaternion.setFromAxisAngle( axis, - angle );
 
 				_eye.applyQuaternion( quaternion );
 				_this.object.up.applyQuaternion( quaternion );
@@ -223,9 +223,10 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 				_changed = true;
 
 			}
+
 		}
 
-	}());
+	}() );
 
 	this.zoomCamera = function () {
 
@@ -264,13 +265,13 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	};
 
-	this.panCamera = (function() {
+	this.panCamera = ( function() {
 
 		var mouseChange = new THREE.Vector2(),
 			objectUp = new THREE.Vector3(),
 			pan = new THREE.Vector3();
 
-		return function () {
+		return function panCamera() {
 
 			mouseChange.copy( _panEnd ).sub( _panStart );
 
@@ -301,21 +302,22 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 				_changed = true;
 
 			}
+
 		}
 
-	}());
+	}() );
 
 	this.update = function () {
 
 		_eye.subVectors( _this.object.position, _this.target );
 
-		if ( !_this.noRotate ) {
+		if ( ! _this.noRotate ) {
 
 			_this.rotateCamera();
 
 		}
 
-		if ( !_this.noZoom ) {
+		if ( ! _this.noZoom ) {
 
 			_this.zoomCamera();
 
@@ -327,7 +329,7 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 		}
 
-		if ( !_this.noPan ) {
+		if ( ! _this.noPan ) {
 
 			_this.panCamera();
 
@@ -385,15 +387,15 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 			return;
 
-		} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {
+		} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {
 
 			_state = STATE.ROTATE;
 
-		} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {
+		} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {
 
 			_state = STATE.ZOOM;
 
-		} else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {
+		} else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {
 
 			_state = STATE.PAN;
 
@@ -424,20 +426,20 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 		}
 
-		if ( _state === STATE.ROTATE && !_this.noRotate ) {
+		if ( _state === STATE.ROTATE && ! _this.noRotate ) {
 
 			_rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
 			_rotateEnd.copy( _rotateStart );
 
-		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
+		} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
 
 			_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
-			_zoomEnd.copy(_zoomStart);
+			_zoomEnd.copy( _zoomStart );
 
-		} else if ( _state === STATE.PAN && !_this.noPan ) {
+		} else if ( _state === STATE.PAN && ! _this.noPan ) {
 
 			_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
-			_panEnd.copy(_panStart)
+			_panEnd.copy( _panStart )
 
 		}
 
@@ -455,15 +457,15 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 		event.preventDefault();
 		event.stopPropagation();
 
-		if ( _state === STATE.ROTATE && !_this.noRotate ) {
+		if ( _state === STATE.ROTATE && ! _this.noRotate ) {
 
 			_rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
 
-		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
+		} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
 
 			_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 
-		} else if ( _state === STATE.PAN && !_this.noPan ) {
+		} else if ( _state === STATE.PAN && ! _this.noPan ) {
 
 			_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 
@@ -495,11 +497,15 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 		var delta = 0;
 
-		if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
+		if ( event.wheelDelta ) {
+
+			// WebKit / Opera / Explorer 9
 
 			delta = event.wheelDelta / 40;
 
-		} else if ( event.detail ) { // Firefox
+		} else if ( event.detail ) {
+
+			// Firefox
 
 			delta = - event.detail / 3;
 
@@ -600,10 +606,34 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	}
 
-	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+	function contextmenu( event ) {
 
-	this.domElement.addEventListener( 'mousedown', mousedown, false );
+		event.preventDefault();
+
+	}
 
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', mousedown, false );
+		this.domElement.removeEventListener( 'mousewheel', mousewheel, false );
+		this.domElement.removeEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
+
+		this.domElement.removeEventListener( 'touchstart', touchstart, false );
+		this.domElement.removeEventListener( 'touchend', touchend, false );
+		this.domElement.removeEventListener( 'touchmove', touchmove, false );
+
+		document.removeEventListener( 'mousemove', mousemove, false );
+		document.removeEventListener( 'mouseup', mouseup, false );
+
+		window.removeEventListener( 'keydown', keydown, false );
+		window.removeEventListener( 'keyup', keyup, false );
+
+	}
+
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+	this.domElement.addEventListener( 'mousedown', mousedown, false );
 	this.domElement.addEventListener( 'mousewheel', mousewheel, false );
 	this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
 

+ 7 - 1
examples/js/controls/PointerLockControls.js

@@ -31,6 +31,12 @@ THREE.PointerLockControls = function ( camera ) {
 
 	};
 
+	this.dispose = function() {
+
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+
+	}
+
 	document.addEventListener( 'mousemove', onMouseMove, false );
 
 	this.enabled = false;
@@ -45,7 +51,7 @@ THREE.PointerLockControls = function ( camera ) {
 
 		// assumes the camera itself is not rotated
 
-		var direction = new THREE.Vector3( 0, 0, -1 );
+		var direction = new THREE.Vector3( 0, 0, - 1 );
 		var rotation = new THREE.Euler( 0, 0, 0, "YXZ" );
 
 		return function( v ) {

+ 63 - 36
examples/js/controls/TrackballControls.js

@@ -8,7 +8,7 @@
 THREE.TrackballControls = function ( object, domElement ) {
 
 	var _this = this;
-	var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
+	var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
 
 	this.object = object;
 	this.domElement = ( domElement !== undefined ) ? domElement : document;
@@ -115,7 +115,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 		var vector = new THREE.Vector2();
 
-		return function ( pageX, pageY ) {
+		return function getMouseOnScreen( pageX, pageY ) {
 
 			vector.set(
 				( pageX - _this.screen.left ) / _this.screen.width,
@@ -132,7 +132,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 		var vector = new THREE.Vector2();
 
-		return function ( pageX, pageY ) {
+		return function getMouseOnCircle( pageX, pageY ) {
 
 			vector.set(
 				( ( pageX - _this.screen.width * 0.5 - _this.screen.left ) / ( _this.screen.width * 0.5 ) ),
@@ -140,11 +140,12 @@ THREE.TrackballControls = function ( object, domElement ) {
 			);
 
 			return vector;
+
 		};
 
 	}() );
 
-	this.rotateCamera = (function() {
+	this.rotateCamera = ( function() {
 
 		var axis = new THREE.Vector3(),
 			quaternion = new THREE.Quaternion(),
@@ -154,7 +155,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 			moveDirection = new THREE.Vector3(),
 			angle;
 
-		return function () {
+		return function rotateCamera() {
 
 			moveDirection.set( _moveCurr.x - _movePrev.x, _moveCurr.y - _movePrev.y, 0 );
 			angle = moveDirection.length();
@@ -183,9 +184,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 				_lastAxis.copy( axis );
 				_lastAngle = angle;
 
-			}
-
-			else if ( !_this.staticMoving && _lastAngle ) {
+			} else if ( ! _this.staticMoving && _lastAngle ) {
 
 				_lastAngle *= Math.sqrt( 1.0 - _this.dynamicDampingFactor );
 				_eye.copy( _this.object.position ).sub( _this.target );
@@ -199,7 +198,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 		};
 
-	}());
+	}() );
 
 
 	this.zoomCamera = function () {
@@ -236,13 +235,13 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 	};
 
-	this.panCamera = (function() {
+	this.panCamera = ( function() {
 
 		var mouseChange = new THREE.Vector2(),
 			objectUp = new THREE.Vector3(),
 			pan = new THREE.Vector3();
 
-		return function () {
+		return function panCamera() {
 
 			mouseChange.copy( _panEnd ).sub( _panStart );
 
@@ -267,13 +266,14 @@ THREE.TrackballControls = function ( object, domElement ) {
 				}
 
 			}
+
 		};
 
-	}());
+	}() );
 
 	this.checkDistances = function () {
 
-		if ( !_this.noZoom || !_this.noPan ) {
+		if ( ! _this.noZoom || ! _this.noPan ) {
 
 			if ( _eye.lengthSq() > _this.maxDistance * _this.maxDistance ) {
 
@@ -297,19 +297,19 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 		_eye.subVectors( _this.object.position, _this.target );
 
-		if ( !_this.noRotate ) {
+		if ( ! _this.noRotate ) {
 
 			_this.rotateCamera();
 
 		}
 
-		if ( !_this.noZoom ) {
+		if ( ! _this.noZoom ) {
 
 			_this.zoomCamera();
 
 		}
 
-		if ( !_this.noPan ) {
+		if ( ! _this.noPan ) {
 
 			_this.panCamera();
 
@@ -364,15 +364,15 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 			return;
 
-		} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {
+		} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && ! _this.noRotate ) {
 
 			_state = STATE.ROTATE;
 
-		} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {
+		} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && ! _this.noZoom ) {
 
 			_state = STATE.ZOOM;
 
-		} else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {
+		} else if ( event.keyCode === _this.keys[ STATE.PAN ] && ! _this.noPan ) {
 
 			_state = STATE.PAN;
 
@@ -403,20 +403,20 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 		}
 
-		if ( _state === STATE.ROTATE && !_this.noRotate ) {
+		if ( _state === STATE.ROTATE && ! _this.noRotate ) {
 
 			_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
-			_movePrev.copy(_moveCurr);
+			_movePrev.copy( _moveCurr );
 
-		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
+		} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
 
 			_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
-			_zoomEnd.copy(_zoomStart);
+			_zoomEnd.copy( _zoomStart );
 
-		} else if ( _state === STATE.PAN && !_this.noPan ) {
+		} else if ( _state === STATE.PAN && ! _this.noPan ) {
 
 			_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
-			_panEnd.copy(_panStart);
+			_panEnd.copy( _panStart );
 
 		}
 
@@ -434,16 +434,16 @@ THREE.TrackballControls = function ( object, domElement ) {
 		event.preventDefault();
 		event.stopPropagation();
 
-		if ( _state === STATE.ROTATE && !_this.noRotate ) {
+		if ( _state === STATE.ROTATE && ! _this.noRotate ) {
 
-			_movePrev.copy(_moveCurr);
+			_movePrev.copy( _moveCurr );
 			_moveCurr.copy( getMouseOnCircle( event.pageX, event.pageY ) );
 
-		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
+		} else if ( _state === STATE.ZOOM && ! _this.noZoom ) {
 
 			_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 
-		} else if ( _state === STATE.PAN && !_this.noPan ) {
+		} else if ( _state === STATE.PAN && ! _this.noPan ) {
 
 			_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 
@@ -475,11 +475,15 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 		var delta = 0;
 
-		if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
+		if ( event.wheelDelta ) {
+
+			// WebKit / Opera / Explorer 9
 
 			delta = event.wheelDelta / 40;
 
-		} else if ( event.detail ) { // Firefox
+		} else if ( event.detail ) {
+
+			// Firefox
 
 			delta = - event.detail / 3;
 
@@ -500,7 +504,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 			case 1:
 				_state = STATE.TOUCH_ROTATE;
 				_moveCurr.copy( getMouseOnCircle( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
-				_movePrev.copy(_moveCurr);
+				_movePrev.copy( _moveCurr );
 				break;
 
 			case 2:
@@ -534,7 +538,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 
 			case 1:
-				_movePrev.copy(_moveCurr);
+				_movePrev.copy( _moveCurr );
 				_moveCurr.copy( getMouseOnCircle(  event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
 				break;
 
@@ -562,7 +566,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 
 			case 1:
-				_movePrev.copy(_moveCurr);
+				_movePrev.copy( _moveCurr );
 				_moveCurr.copy( getMouseOnCircle(  event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
 				break;
 
@@ -582,10 +586,33 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 	}
 
-	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+	function contextmenu( event ) {
 
-	this.domElement.addEventListener( 'mousedown', mousedown, false );
+		event.preventDefault();
+
+	}
+
+	this.dispose = function() {
+
+		this.domElement.removeEventListener( 'contextmenu', contextmenu, false );
+		this.domElement.removeEventListener( 'mousedown', mousedown, false );
+		this.domElement.removeEventListener( 'mousewheel', mousewheel, false );
+		this.domElement.removeEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
+
+		this.domElement.removeEventListener( 'touchstart', touchstart, false );
+		this.domElement.removeEventListener( 'touchend', touchend, false );
+		this.domElement.removeEventListener( 'touchmove', touchmove, false );
 
+		document.removeEventListener( 'mousemove', mousemove, false );
+		document.removeEventListener( 'mouseup', mouseup, false );
+
+		window.removeEventListener( 'keydown', keydown, false );
+		window.removeEventListener( 'keyup', keyup, false );
+
+	}
+
+	this.domElement.addEventListener( 'contextmenu', contextmenu, false );
+	this.domElement.addEventListener( 'mousedown', mousedown, false );
 	this.domElement.addEventListener( 'mousewheel', mousewheel, false );
 	this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
 

+ 87 - 79
examples/js/controls/TransformControls.js

@@ -3,7 +3,7 @@
  */
  /*jshint sub:true*/
 
-(function () {
+( function () {
 
 	'use strict';
 
@@ -95,9 +95,9 @@
 			this.pickers = new THREE.Object3D();
 			this.planes = new THREE.Object3D();
 
-			this.add(this.handles);
-			this.add(this.pickers);
-			this.add(this.planes);
+			this.add( this.handles );
+			this.add( this.pickers );
+			this.add( this.planes );
 
 			//// PLANES
 
@@ -111,15 +111,17 @@
 				"XYZE": new THREE.Mesh( planeGeometry, planeMaterial )
 			};
 
-			this.activePlane = planes["XYZE"];
+			this.activePlane = planes[ "XYZE" ];
 
-			planes["YZ"].rotation.set( 0, Math.PI / 2, 0 );
-			planes["XZ"].rotation.set( -Math.PI / 2, 0, 0 );
+			planes[ "YZ" ].rotation.set( 0, Math.PI / 2, 0 );
+			planes[ "XZ" ].rotation.set( - Math.PI / 2, 0, 0 );
+
+			for ( var i in planes ) {
+
+				planes[ i ].name = i;
+				this.planes.add( planes[ i ] );
+				this.planes[ i ] = planes[ i ];
 
-			for (var i in planes) {
-				planes[i].name = i;
-				this.planes.add(planes[i]);
-				this.planes[i] = planes[i];
 			}
 
 			//// HANDLES AND PICKERS
@@ -128,16 +130,16 @@
 
 				for ( var name in gizmoMap ) {
 
-					for ( i = gizmoMap[name].length; i --;) {
+					for ( i = gizmoMap[ name ].length; i --; ) {
 
-						var object = gizmoMap[name][i][0];
-						var position = gizmoMap[name][i][1];
-						var rotation = gizmoMap[name][i][2];
+						var object = gizmoMap[ name ][ i ][ 0 ];
+						var position = gizmoMap[ name ][ i ][ 1 ];
+						var rotation = gizmoMap[ name ][ i ][ 2 ];
 
 						object.name = name;
 
-						if ( position ) object.position.set( position[0], position[1], position[2] );
-						if ( rotation ) object.rotation.set( rotation[0], rotation[1], rotation[2] );
+						if ( position ) object.position.set( position[ 0 ], position[ 1 ], position[ 2 ] );
+						if ( rotation ) object.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation[ 2 ] );
 
 						parent.add( object );
 
@@ -147,14 +149,14 @@
 
 			};
 
-			setupGizmos(this.handleGizmos, this.handles);
-			setupGizmos(this.pickerGizmos, this.pickers);
+			setupGizmos( this.handleGizmos, this.handles );
+			setupGizmos( this.pickerGizmos, this.pickers );
 
 			// reset Transformations
 
-			this.traverse(function ( child ) {
+			this.traverse( function ( child ) {
 
-				if (child instanceof THREE.Mesh) {
+				if ( child instanceof THREE.Mesh ) {
 
 					child.updateMatrix();
 
@@ -168,7 +170,7 @@
 
 				}
 
-			});
+			} );
 
 		};
 
@@ -205,13 +207,13 @@
 		var vec2 = new THREE.Vector3( 0, 1, 0 );
 		var lookAtMatrix = new THREE.Matrix4();
 
-		this.traverse( function(child) {
+		this.traverse( function( child ) {
 
-			if ( child.name.search("E") !== -1 ) {
+			if ( child.name.search( "E" ) !== - 1 ) {
 
 				child.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( eye, vec1, vec2 ) );
 
-			} else if ( child.name.search("X") !== -1 || child.name.search("Y") !== -1 || child.name.search("Z") !== -1 ) {
+			} else if ( child.name.search( "X" ) !== - 1 || child.name.search( "Y" ) !== - 1 || child.name.search( "Z" ) !== - 1 ) {
 
 				child.quaternion.setFromEuler( rotation );
 
@@ -244,7 +246,7 @@
 		this.handleGizmos = {
 
 			X: [
-				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0xff0000 } ) ), [ 0.5, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ],
+				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0xff0000 } ) ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ],
 				[ new THREE.Line( lineXGeometry, new GizmoLineMaterial( { color: 0xff0000 } ) ) ]
 			],
 
@@ -271,7 +273,7 @@
 			],
 
 			XZ: [
-				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0xff00ff, opacity: 0.25 } ) ), [ 0.15, 0, 0.15 ], [ -Math.PI / 2, 0, 0 ] ]
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.29, 0.29 ), new GizmoMaterial( { color: 0xff00ff, opacity: 0.25 } ) ), [ 0.15, 0, 0.15 ], [ - Math.PI / 2, 0, 0 ] ]
 			]
 
 		};
@@ -279,7 +281,7 @@
 		this.pickerGizmos = {
 
 			X: [
-				[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0.6, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ]
+				[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0.6, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ]
 			],
 
 			Y: [
@@ -303,7 +305,7 @@
 			],
 
 			XZ: [
-				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), pickerMaterial ), [ 0.2, 0, 0.2 ], [ -Math.PI / 2, 0, 0 ] ]
+				[ new THREE.Mesh( new THREE.PlaneBufferGeometry( 0.4, 0.4 ), pickerMaterial ), [ 0.2, 0, 0.2 ], [ - Math.PI / 2, 0, 0 ] ]
 			]
 
 		};
@@ -317,7 +319,7 @@
 
 				this.activePlane = this.planes[ "XY" ];
 
-				if ( Math.abs(eye.y) > Math.abs(eye.z) ) this.activePlane = this.planes[ "XZ" ];
+				if ( Math.abs( eye.y ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "XZ" ];
 
 			}
 
@@ -325,7 +327,7 @@
 
 				this.activePlane = this.planes[ "XY" ];
 
-				if ( Math.abs(eye.x) > Math.abs(eye.z) ) this.activePlane = this.planes[ "YZ" ];
+				if ( Math.abs( eye.x ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "YZ" ];
 
 			}
 
@@ -333,7 +335,7 @@
 
 				this.activePlane = this.planes[ "XZ" ];
 
-				if ( Math.abs(eye.x) > Math.abs(eye.y) ) this.activePlane = this.planes[ "YZ" ];
+				if ( Math.abs( eye.x ) > Math.abs( eye.y ) ) this.activePlane = this.planes[ "YZ" ];
 
 			}
 
@@ -380,23 +382,23 @@
 		this.handleGizmos = {
 
 			X: [
-				[ new THREE.Line( new CircleGeometry(1,'x',0.5), new GizmoLineMaterial( { color: 0xff0000 } ) ) ]
+				[ new THREE.Line( new CircleGeometry( 1, 'x', 0.5 ), new GizmoLineMaterial( { color: 0xff0000 } ) ) ]
 			],
 
 			Y: [
-				[ new THREE.Line( new CircleGeometry(1,'y',0.5), new GizmoLineMaterial( { color: 0x00ff00 } ) ) ]
+				[ new THREE.Line( new CircleGeometry( 1, 'y', 0.5 ), new GizmoLineMaterial( { color: 0x00ff00 } ) ) ]
 			],
 
 			Z: [
-				[ new THREE.Line( new CircleGeometry(1,'z',0.5), new GizmoLineMaterial( { color: 0x0000ff } ) ) ]
+				[ new THREE.Line( new CircleGeometry( 1, 'z', 0.5 ), new GizmoLineMaterial( { color: 0x0000ff } ) ) ]
 			],
 
 			E: [
-				[ new THREE.Line( new CircleGeometry(1.25,'z',1), new GizmoLineMaterial( { color: 0xcccc00 } ) ) ]
+				[ new THREE.Line( new CircleGeometry( 1.25, 'z', 1 ), new GizmoLineMaterial( { color: 0xcccc00 } ) ) ]
 			],
 
 			XYZE: [
-				[ new THREE.Line( new CircleGeometry(1,'z',1), new GizmoLineMaterial( { color: 0x787878 } ) ) ]
+				[ new THREE.Line( new CircleGeometry( 1, 'z', 1 ), new GizmoLineMaterial( { color: 0x787878 } ) ) ]
 			]
 
 		};
@@ -404,7 +406,7 @@
 		this.pickerGizmos = {
 
 			X: [
-				[ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.12, 4, 12, Math.PI ), pickerMaterial ), [ 0, 0, 0 ], [ 0, -Math.PI / 2, -Math.PI / 2 ] ]
+				[ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.12, 4, 12, Math.PI ), pickerMaterial ), [ 0, 0, 0 ], [ 0, - Math.PI / 2, - Math.PI / 2 ] ]
 			],
 
 			Y: [
@@ -412,7 +414,7 @@
 			],
 
 			Z: [
-				[ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.12, 4, 12, Math.PI ), pickerMaterial ), [ 0, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ]
+				[ new THREE.Mesh( new THREE.TorusGeometry( 1, 0.12, 4, 12, Math.PI ), pickerMaterial ), [ 0, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ]
 			],
 
 			E: [
@@ -443,8 +445,8 @@
 
 			var group = {
 
-				handles: this["handles"],
-				pickers: this["pickers"],
+				handles: this[ "handles" ],
+				pickers: this[ "pickers" ],
 
 			};
 
@@ -459,19 +461,19 @@
 			var quaternionZ = new THREE.Quaternion();
 			var eye = eye2.clone();
 
-			worldRotation.copy( this.planes["XY"].rotation );
+			worldRotation.copy( this.planes[ "XY" ].rotation );
 			tempQuaternion.setFromEuler( worldRotation );
 
 			tempMatrix.makeRotationFromQuaternion( tempQuaternion ).getInverse( tempMatrix );
 			eye.applyMatrix4( tempMatrix );
 
-			this.traverse(function(child) {
+			this.traverse( function( child ) {
 
 				tempQuaternion.setFromEuler( worldRotation );
 
 				if ( child.name === "X" ) {
 
-					quaternionX.setFromAxisAngle( unitX, Math.atan2( -eye.y, eye.z ) );
+					quaternionX.setFromAxisAngle( unitX, Math.atan2( - eye.y, eye.z ) );
 					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
 					child.quaternion.copy( tempQuaternion );
 
@@ -493,7 +495,7 @@
 
 				}
 
-			});
+			} );
 
 		};
 
@@ -527,7 +529,7 @@
 		this.handleGizmos = {
 
 			X: [
-				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0xff0000 } ) ), [ 0.5, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ],
+				[ new THREE.Mesh( arrowGeometry, new GizmoMaterial( { color: 0xff0000 } ) ), [ 0.5, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ],
 				[ new THREE.Line( lineXGeometry, new GizmoLineMaterial( { color: 0xff0000 } ) ) ]
 			],
 
@@ -550,7 +552,7 @@
 		this.pickerGizmos = {
 
 			X: [
-				[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0.6, 0, 0 ], [ 0, 0, -Math.PI / 2 ] ]
+				[ new THREE.Mesh( new THREE.CylinderGeometry( 0.2, 0, 1, 4, 1, false ), pickerMaterial ), [ 0.6, 0, 0 ], [ 0, 0, - Math.PI / 2 ] ]
 			],
 
 			Y: [
@@ -573,18 +575,24 @@
 			eye.applyMatrix4( tempMatrix.getInverse( tempMatrix.extractRotation( this.planes[ "XY" ].matrixWorld ) ) );
 
 			if ( axis === "X" ) {
+
 				this.activePlane = this.planes[ "XY" ];
-				if ( Math.abs(eye.y) > Math.abs(eye.z) ) this.activePlane = this.planes[ "XZ" ];
+				if ( Math.abs( eye.y ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "XZ" ];
+
 			}
 
 			if ( axis === "Y" ) {
+
 				this.activePlane = this.planes[ "XY" ];
-				if ( Math.abs(eye.x) > Math.abs(eye.z) ) this.activePlane = this.planes[ "YZ" ];
+				if ( Math.abs( eye.x ) > Math.abs( eye.z ) ) this.activePlane = this.planes[ "YZ" ];
+
 			}
 
 			if ( axis === "Z" ) {
+
 				this.activePlane = this.planes[ "XZ" ];
-				if ( Math.abs(eye.x) > Math.abs(eye.y) ) this.activePlane = this.planes[ "YZ" ];
+				if ( Math.abs( eye.x ) > Math.abs( eye.y ) ) this.activePlane = this.planes[ "YZ" ];
+
 			}
 
 			if ( axis === "XYZ" ) this.activePlane = this.planes[ "XYZE" ];
@@ -626,9 +634,9 @@
 			"scale": new THREE.TransformGizmoScale()
 		};
 
-		for (var type in _gizmo) {
+		for ( var type in _gizmo ) {
 
-			var gizmoObj = _gizmo[type];
+			var gizmoObj = _gizmo[ type ];
 
 			gizmoObj.visible = ( type === _mode );
 			this.add( gizmoObj );
@@ -735,7 +743,7 @@
 
 			if ( _mode === "scale" ) scope.space = "local";
 
-			for (var type in _gizmo) _gizmo[type].visible = ( type === _mode );
+			for ( var type in _gizmo ) _gizmo[ type ].visible = ( type === _mode );
 
 			this.update();
 			scope.dispatchEvent( changeEvent );
@@ -784,15 +792,15 @@
 
 			if ( scope.space === "local" ) {
 
-				_gizmo[_mode].update( worldRotation, eye );
+				_gizmo[ _mode ].update( worldRotation, eye );
 
 			} else if ( scope.space === "world" ) {
 
-				_gizmo[_mode].update( new THREE.Euler(), eye );
+				_gizmo[ _mode ].update( new THREE.Euler(), eye );
 
 			}
 
-			_gizmo[_mode].highlight( scope.axis );
+			_gizmo[ _mode ].highlight( scope.axis );
 
 		};
 
@@ -802,7 +810,7 @@
 
 			var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
 
-			var intersect = intersectObjects( pointer, _gizmo[_mode].pickers.children );
+			var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
 
 			var axis = null;
 
@@ -832,7 +840,7 @@
 
 			if ( pointer.button === 0 || pointer.button === undefined ) {
 
-				var intersect = intersectObjects( pointer, _gizmo[_mode].pickers.children );
+				var intersect = intersectObjects( pointer, _gizmo[ _mode ].pickers.children );
 
 				if ( intersect ) {
 
@@ -847,9 +855,9 @@
 
 					eye.copy( camPosition ).sub( worldPosition ).normalize();
 
-					_gizmo[_mode].setActivePlane( scope.axis, eye );
+					_gizmo[ _mode ].setActivePlane( scope.axis, eye );
 
-					var planeIntersect = intersectObjects( pointer, [ _gizmo[_mode].activePlane ] );
+					var planeIntersect = intersectObjects( pointer, [ _gizmo[ _mode ].activePlane ] );
 
 					if ( planeIntersect ) {
 
@@ -878,9 +886,9 @@
 
 			if ( scope.object === undefined || scope.axis === null || _dragging === false ) return;
 
-			var pointer = event.changedTouches ? event.changedTouches[0] : event;
+			var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
 
-			var planeIntersect = intersectObjects( pointer, [ _gizmo[_mode].activePlane ] );
+			var planeIntersect = intersectObjects( pointer, [ _gizmo[ _mode ].activePlane ] );
 
 			if ( planeIntersect === false ) return;
 
@@ -892,15 +900,15 @@
 			if ( _mode === "translate" ) {
 
 				point.sub( offset );
-				point.multiply(parentScale);
+				point.multiply( parentScale );
 
 				if ( scope.space === "local" ) {
 
 					point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
 
-					if ( scope.axis.search("X") === -1 ) point.x = 0;
-					if ( scope.axis.search("Y") === -1 ) point.y = 0;
-					if ( scope.axis.search("Z") === -1 ) point.z = 0;
+					if ( scope.axis.search( "X" ) === - 1 ) point.x = 0;
+					if ( scope.axis.search( "Y" ) === - 1 ) point.y = 0;
+					if ( scope.axis.search( "Z" ) === - 1 ) point.z = 0;
 
 					point.applyMatrix4( oldRotationMatrix );
 
@@ -909,11 +917,11 @@
 
 				}
 
-				if ( scope.space === "world" || scope.axis.search("XYZ") !== -1 ) {
+				if ( scope.space === "world" || scope.axis.search( "XYZ" ) !== - 1 ) {
 
-					if ( scope.axis.search("X") === -1 ) point.x = 0;
-					if ( scope.axis.search("Y") === -1 ) point.y = 0;
-					if ( scope.axis.search("Z") === -1 ) point.z = 0;
+					if ( scope.axis.search( "X" ) === - 1 ) point.x = 0;
+					if ( scope.axis.search( "Y" ) === - 1 ) point.y = 0;
+					if ( scope.axis.search( "Z" ) === - 1 ) point.z = 0;
 
 					point.applyMatrix4( tempMatrix.getInverse( parentRotationMatrix ) );
 
@@ -924,20 +932,20 @@
 
 				if ( scope.snap !== null ) {
 
-					if ( scope.axis.search("X") !== -1 ) scope.object.position.x = Math.round( scope.object.position.x / scope.snap ) * scope.snap;
-					if ( scope.axis.search("Y") !== -1 ) scope.object.position.y = Math.round( scope.object.position.y / scope.snap ) * scope.snap;
-					if ( scope.axis.search("Z") !== -1 ) scope.object.position.z = Math.round( scope.object.position.z / scope.snap ) * scope.snap;
+					if ( scope.axis.search( "X" ) !== - 1 ) scope.object.position.x = Math.round( scope.object.position.x / scope.snap ) * scope.snap;
+					if ( scope.axis.search( "Y" ) !== - 1 ) scope.object.position.y = Math.round( scope.object.position.y / scope.snap ) * scope.snap;
+					if ( scope.axis.search( "Z" ) !== - 1 ) scope.object.position.z = Math.round( scope.object.position.z / scope.snap ) * scope.snap;
 
 				}
 
 			} else if ( _mode === "scale" ) {
 
 				point.sub( offset );
-				point.multiply(parentScale);
+				point.multiply( parentScale );
 
 				if ( scope.space === "local" ) {
 
-					if ( scope.axis === "XYZ") {
+					if ( scope.axis === "XYZ" ) {
 
 						scale = 1 + ( ( point.y ) / 50 );
 
@@ -984,10 +992,10 @@
 
 				} else if ( scope.axis === "XYZE" ) {
 
-					quaternionE.setFromEuler( point.clone().cross(tempVector).normalize() ); // rotation axis
+					quaternionE.setFromEuler( point.clone().cross( tempVector ).normalize() ); // rotation axis
 
 					tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
-					quaternionX.setFromAxisAngle( quaternionE, - point.clone().angleTo(tempVector) );
+					quaternionX.setFromAxisAngle( quaternionE, - point.clone().angleTo( tempVector ) );
 					quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
 
 					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
@@ -1069,7 +1077,7 @@
 			ray.setFromCamera( pointerVector, camera );
 
 			var intersections = ray.intersectObjects( objects, true );
-			return intersections[0] ? intersections[0] : false;
+			return intersections[ 0 ] ? intersections[ 0 ] : false;
 
 		}
 
@@ -1078,4 +1086,4 @@
 	THREE.TransformControls.prototype = Object.create( THREE.Object3D.prototype );
 	THREE.TransformControls.prototype.constructor = THREE.TransformControls;
 
-}());
+}() );

+ 8 - 2
examples/js/controls/VRControls.js

@@ -15,7 +15,7 @@ THREE.VRControls = function ( object, onError ) {
 
 		var oculusDevices = devices.filter( function ( device ) {
 
-			return device.deviceName.toLowerCase().indexOf('oculus') !== -1;
+			return device.deviceName.toLowerCase().indexOf( 'oculus' ) !== - 1;
 
 		} );
 
@@ -23,7 +23,7 @@ THREE.VRControls = function ( object, onError ) {
 
 			return devices.filter( function ( device ) {
 
-				return device.deviceName.toLowerCase().indexOf('cardboard') === -1;
+				return device.deviceName.toLowerCase().indexOf( 'cardboard' ) === - 1;
 
 			} );
 
@@ -116,4 +116,10 @@ THREE.VRControls = function ( object, onError ) {
 
 	};
 
+	this.dispose = function () {
+
+		vrInputs = [];
+
+	};
+
 };

+ 14 - 14
examples/js/crossfade/gui.js

@@ -12,28 +12,28 @@ function initGUI() {
 	
 	var gui = new dat.GUI();
 
-	gui.add(transitionParams, "useTexture").onChange(function(value) {
+	gui.add( transitionParams, "useTexture" ).onChange( function( value ) {
 		
-		transition.useTexture(value);
+		transition.useTexture( value );
 		
-	});
+	} );
 	
-	gui.add(transitionParams, 'loopTexture');
+	gui.add( transitionParams, 'loopTexture' );
 	
-	gui.add(transitionParams, 'texture', { Perlin: 0, Squares: 1, Cells: 2, Distort: 3, Gradient: 4, Radial: 5 } ).onChange(function(value) {
+	gui.add( transitionParams, 'texture', { Perlin: 0, Squares: 1, Cells: 2, Distort: 3, Gradient: 4, Radial: 5 } ).onChange( function( value ) {
 		
-		transition.setTexture(value);
+		transition.setTexture( value );
 		
-	}).listen();
+	} ).listen();
 		
-	gui.add(transitionParams, "textureThreshold", 0, 1, 0.01).onChange(function(value) {
+	gui.add( transitionParams, "textureThreshold", 0, 1, 0.01 ).onChange( function( value ) {
 		
-		transition.setTextureThreshold(value);
+		transition.setTextureThreshold( value );
 		
-	});
+	} );
 
-	gui.add(transitionParams, "animateTransition");
-	gui.add(transitionParams, "transition", 0, 1, 0.01).listen();
-	gui.add(transitionParams, "transitionSpeed", 0.5, 5, 0.01);
+	gui.add( transitionParams, "animateTransition" );
+	gui.add( transitionParams, "transition", 0, 1, 0.01 ).listen();
+	gui.add( transitionParams, "transitionSpeed", 0.5, 5, 0.01 );
 	
-}
+}

+ 10 - 8
examples/js/crossfade/scenes.js

@@ -1,4 +1,4 @@
-function generateGeometry(objectType, numObjects) {
+function generateGeometry( objectType, numObjects ) {
 
 	var geometry = new THREE.Geometry();
 
@@ -38,18 +38,19 @@ function generateGeometry(objectType, numObjects) {
 
 		scale.x = Math.random() * 200 + 100;
 
-		if ( objectType == "cube" )
-		{
+		if ( objectType == "cube" ) {
+
 			geom = new THREE.BoxGeometry( 1, 1, 1 );
 			scale.y = Math.random() * 200 + 100;
 			scale.z = Math.random() * 200 + 100;
 			color.setRGB( 0, 0, Math.random() + 0.1 );
-		}
-		else if ( objectType == "sphere" )
-		{
+
+		} else if ( objectType == "sphere" ) {
+
 			geom = new THREE.IcosahedronGeometry( 1, 1 );
 			scale.y = scale.z = scale.x;
 			color.setRGB( Math.random() + 0.1, 0, 0 );
+
 		}
 
 		// give the geom's vertices a random color, to be displayed
@@ -85,7 +86,7 @@ function Scene ( type, numObjects, cameraZ, fov, rotationSpeed, clearColor ) {
 	this.scene.add( light );
 
 	this.rotationSpeed = rotationSpeed;
-	defaultMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors	} );
+	defaultMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors	} );
 	this.mesh = new THREE.Mesh( generateGeometry( type, numObjects ), defaultMaterial );
 	this.scene.add( this.mesh );
 
@@ -100,10 +101,11 @@ function Scene ( type, numObjects, cameraZ, fov, rotationSpeed, clearColor ) {
 
 		renderer.setClearColor( this.clearColor );
 
-		if (rtt)
+		if ( rtt )
 			renderer.render( this.scene, this.camera, this.fbo, true );
 		else
 			renderer.render( this.scene, this.camera );
 
 	};
+
 }

+ 28 - 26
examples/js/crossfade/transition.js

@@ -2,13 +2,13 @@ function Transition ( sceneA, sceneB ) {
 
 	this.scene = new THREE.Scene();
 	
-	this.cameraOrtho = new THREE.OrthographicCamera(window.innerWidth / -2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / -2, -10, 10);
+	this.cameraOrtho = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 10, 10 );
 
 	this.textures = [];
-	for (var i = 0; i < 6; i ++)
-		this.textures[i] = new THREE.ImageUtils.loadTexture('textures/transition/transition' + (i + 1) + '.png');
+	for ( var i = 0; i < 6; i ++ )
+		this.textures[ i ] = new THREE.ImageUtils.loadTexture( 'textures/transition/transition' + ( i + 1 ) + '.png' );
 				
-	this.quadmaterial = new THREE.ShaderMaterial({
+	this.quadmaterial = new THREE.ShaderMaterial( {
 
 		uniforms: {
 
@@ -34,7 +34,7 @@ function Transition ( sceneA, sceneB ) {
 			},
 			tMixTexture: {
 				type: "t",
-				value: this.textures[0]
+				value: this.textures[ 0 ]
 			}
 		},
 		vertexShader: [
@@ -48,7 +48,7 @@ function Transition ( sceneA, sceneB ) {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 		fragmentShader: [
 
 			"uniform float mixRatio;",
@@ -81,14 +81,14 @@ function Transition ( sceneA, sceneB ) {
 			"}",
 		"}"
 
-		].join("\n")
+		].join( "\n" )
 
-	});
+	} );
 
-	quadgeometry = new THREE.PlaneBufferGeometry(window.innerWidth, window.innerHeight);
+	quadgeometry = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
 	
-	this.quad = new THREE.Mesh(quadgeometry, this.quadmaterial);
-	this.scene.add(this.quad);
+	this.quad = new THREE.Mesh( quadgeometry, this.quadmaterial );
+	this.scene.add( this.quad );
 
 	// Link both scenes and their FBOs
 	this.sceneA = sceneA;
@@ -113,29 +113,30 @@ function Transition ( sceneA, sceneB ) {
 	
 	this.setTexture = function ( i ) {
 		
-		this.quadmaterial.uniforms.tMixTexture.value = this.textures[i];
+		this.quadmaterial.uniforms.tMixTexture.value = this.textures[ i ];
 		
 	};
 	
 	this.render = function( delta ) {
 		
 		// Transition animation
-		if (transitionParams.animateTransition)
-		{
-			var t = (1 + Math.sin(transitionParams.transitionSpeed * clock.getElapsedTime() / Math.PI)) / 2;
-			transitionParams.transition = THREE.Math.smoothstep(t, 0.3, 0.7);
+		if ( transitionParams.animateTransition ) {
+
+			var t = ( 1 + Math.sin( transitionParams.transitionSpeed * clock.getElapsedTime() / Math.PI ) ) / 2;
+			transitionParams.transition = THREE.Math.smoothstep( t, 0.3, 0.7 );
 			
 			// Change the current alpha texture after each transition
-			if (transitionParams.loopTexture && (transitionParams.transition == 0 || transitionParams.transition == 1))
-			{
-				if (this.needChange)
-				{
-					transitionParams.texture = (transitionParams.texture + 1)%this.textures.length;
-					this.quadmaterial.uniforms.tMixTexture.value = this.textures[transitionParams.texture];
+			if ( transitionParams.loopTexture && ( transitionParams.transition == 0 || transitionParams.transition == 1 ) ) {
+
+				if ( this.needChange ) {
+
+					transitionParams.texture = ( transitionParams.texture + 1 ) % this.textures.length;
+					this.quadmaterial.uniforms.tMixTexture.value = this.textures[ transitionParams.texture ];
 					this.needChange = false;
+
 				}
-			}	
-			else
+
+			} else
 				this.needChange = true;
 				
 		}
@@ -143,11 +144,11 @@ function Transition ( sceneA, sceneB ) {
 		this.quadmaterial.uniforms.mixRatio.value = transitionParams.transition;
 
 		// Prevent render both scenes when it's not necessary
-		if (transitionParams.transition == 0) {
+		if ( transitionParams.transition == 0 ) {
 			
 			this.sceneB.render( delta, false );
 		
-		} else if (transitionParams.transition == 1) {
+		} else if ( transitionParams.transition == 1 ) {
 		
 			this.sceneA.render( delta, false );
 			
@@ -162,4 +163,5 @@ function Transition ( sceneA, sceneB ) {
 		}
 
 	}
+
 }

+ 20 - 12
examples/js/curves/NURBSCurve.js

@@ -13,14 +13,17 @@
  *	NURBS curve
  **************************************************************/
 
-THREE.NURBSCurve = function ( degree, knots /* array of reals */, controlPoints /* array of Vector(2|3|4) */) {
+THREE.NURBSCurve = function ( degree, knots /* array of reals */, controlPoints /* array of Vector(2|3|4) */ ) {
 
 	this.degree = degree;
 	this.knots = knots;
 	this.controlPoints = [];
-	for (var i = 0; i < controlPoints.length; ++ i) { // ensure Vector4 for control points
-		var point = controlPoints[i];
-		this.controlPoints[i] = new THREE.Vector4(point.x, point.y, point.z, point.w);
+	for ( var i = 0; i < controlPoints.length; ++ i ) {
+
+		// ensure Vector4 for control points
+		var point = controlPoints[ i ];
+		this.controlPoints[ i ] = new THREE.Vector4( point.x, point.y, point.z, point.w );
+
 	}
 
 };
@@ -32,26 +35,31 @@ THREE.NURBSCurve.prototype.constructor = THREE.NURBSCurve;
 
 THREE.NURBSCurve.prototype.getPoint = function ( t ) {
 
-	var u = this.knots[0] + t * (this.knots[this.knots.length - 1] - this.knots[0]); // linear mapping t->u
+	var u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] ); // linear mapping t->u
 
 	// following results in (wx, wy, wz, w) homogeneous point
-	var hpoint = THREE.NURBSUtils.calcBSplinePoint(this.degree, this.knots, this.controlPoints, u);
+	var hpoint = THREE.NURBSUtils.calcBSplinePoint( this.degree, this.knots, this.controlPoints, u );
+
+	if ( hpoint.w != 1.0 ) {
+
+		// project to 3D space: (wx, wy, wz, w) -> (x, y, z, 1)
+		hpoint.divideScalar( hpoint.w );
 
-	if (hpoint.w != 1.0) { // project to 3D space: (wx, wy, wz, w) -> (x, y, z, 1)
-		hpoint.divideScalar(hpoint.w);
 	}
 
-	return new THREE.Vector3(hpoint.x, hpoint.y, hpoint.z);
+	return new THREE.Vector3( hpoint.x, hpoint.y, hpoint.z );
+
 };
 
 
 THREE.NURBSCurve.prototype.getTangent = function ( t ) {
 
-	var u = this.knots[0] + t * (this.knots[this.knots.length - 1] - this.knots[0]);
-	var ders = THREE.NURBSUtils.calcNURBSDerivatives(this.degree, this.knots, this.controlPoints, u, 1);
-	var tangent = ders[1].clone();
+	var u = this.knots[ 0 ] + t * ( this.knots[ this.knots.length - 1 ] - this.knots[ 0 ] );
+	var ders = THREE.NURBSUtils.calcNURBSDerivatives( this.degree, this.knots, this.controlPoints, u, 1 );
+	var tangent = ders[ 1 ].clone();
 	tangent.normalize();
 
 	return tangent;
+
 };
 

+ 15 - 9
examples/js/curves/NURBSSurface.js

@@ -11,7 +11,7 @@
  *	NURBS surface
  **************************************************************/
 
-THREE.NURBSSurface = function ( degree1, degree2, knots1, knots2 /* arrays of reals */, controlPoints /* array^2 of Vector(2|3|4) */) {
+THREE.NURBSSurface = function ( degree1, degree2, knots1, knots2 /* arrays of reals */, controlPoints /* array^2 of Vector(2|3|4) */ ) {
 
 	this.degree1 = degree1;
 	this.degree2 = degree2;
@@ -23,13 +23,18 @@ THREE.NURBSSurface = function ( degree1, degree2, knots1, knots2 /* arrays of re
 	var len2 = knots2.length - degree2 - 1;
 
 	// ensure Vector4 for control points
-	for (var i = 0; i < len1; ++ i) {
-		this.controlPoints[i] = [];
-		for (var j = 0; j < len2; ++ j) {
-			var point = controlPoints[i][j];
-			this.controlPoints[i][j] = new THREE.Vector4(point.x, point.y, point.z, point.w);
+	for ( var i = 0; i < len1; ++ i ) {
+
+		this.controlPoints[ i ] = [];
+		for ( var j = 0; j < len2; ++ j ) {
+
+			var point = controlPoints[ i ][ j ];
+			this.controlPoints[ i ][ j ] = new THREE.Vector4( point.x, point.y, point.z, point.w );
+
 		}
+
 	}
+
 };
 
 
@@ -39,10 +44,11 @@ THREE.NURBSSurface.prototype = {
 
 	getPoint: function ( t1, t2 ) {
 
-		var u = this.knots1[0] + t1 * (this.knots1[this.knots1.length - 1] - this.knots1[0]); // linear mapping t1->u
-		var v = this.knots2[0] + t2 * (this.knots2[this.knots2.length - 1] - this.knots2[0]); // linear mapping t2->u
+		var u = this.knots1[ 0 ] + t1 * ( this.knots1[ this.knots1.length - 1 ] - this.knots1[ 0 ] ); // linear mapping t1->u
+		var v = this.knots2[ 0 ] + t2 * ( this.knots2[ this.knots2.length - 1 ] - this.knots2[ 0 ] ); // linear mapping t2->u
+
+		return THREE.NURBSUtils.calcSurfacePoint( this.degree1, this.degree2, this.knots1, this.knots2, this.controlPoints, u, v );
 
-		return THREE.NURBSUtils.calcSurfacePoint(this.degree1, this.degree2, this.knots1, this.knots2, this.controlPoints, u, v);
 	}
 };
 

+ 190 - 112
examples/js/curves/NURBSUtils.js

@@ -23,32 +23,43 @@ THREE.NURBSUtils = {
 	returns the span
 	*/
 	findSpan: function( p,  u,  U ) {
+
 		var n = U.length - p - 1;
 
-		if (u >= U[n]) {
+		if ( u >= U[ n ] ) {
+
 			return n - 1;
+
 		}
 
-		if (u <= U[p]) {
+		if ( u <= U[ p ] ) {
+
 			return p;
+
 		}
 
 		var low = p;
 		var high = n;
-		var mid = Math.floor((low + high) / 2);
+		var mid = Math.floor( ( low + high ) / 2 );
 
-		while (u < U[mid] || u >= U[mid + 1]) {
+		while ( u < U[ mid ] || u >= U[ mid + 1 ] ) {
 		  
-			if (u < U[mid]) {
+			if ( u < U[ mid ] ) {
+
 				high = mid;
+
 			} else {
+
 				low = mid;
+
 			}
 
-			mid = Math.floor((low + high) / 2);
+			mid = Math.floor( ( low + high ) / 2 );
+
 		}
 
 		return mid;
+
 	},
     
 		
@@ -63,31 +74,35 @@ THREE.NURBSUtils = {
 	returns array[p+1] with basis functions values.
 	*/
 	calcBasisFunctions: function( span, u, p, U ) {
+
 		var N = [];
 		var left = [];
 		var right = [];
-		N[0] = 1.0;
+		N[ 0 ] = 1.0;
 
-		for (var j = 1; j <= p; ++ j) {
+		for ( var j = 1; j <= p; ++ j ) {
 	   
-			left[j] = u - U[span + 1 - j];
-			right[j] = U[span + j] - u;
+			left[ j ] = u - U[ span + 1 - j ];
+			right[ j ] = U[ span + j ] - u;
 
 			var saved = 0.0;
 
-			for (var r = 0; r < j; ++ r) {
+			for ( var r = 0; r < j; ++ r ) {
 
-				var rv = right[r + 1];
-				var lv = left[j - r];
-				var temp = N[r] / (rv + lv);
-				N[r] = saved + rv * temp;
+				var rv = right[ r + 1 ];
+				var lv = left[ j - r ];
+				var temp = N[ r ] / ( rv + lv );
+				N[ r ] = saved + rv * temp;
 				saved = lv * temp;
+
 			 }
 
-			 N[j] = saved;
+			 N[ j ] = saved;
+
 		 }
 
 		 return N;
+
 	},
 
 
@@ -102,21 +117,25 @@ THREE.NURBSUtils = {
 	returns point for given u
 	*/
 	calcBSplinePoint: function( p, U, P, u ) {
-		var span = this.findSpan(p, u, U);
-		var N = this.calcBasisFunctions(span, u, p, U);
-		var C = new THREE.Vector4(0, 0, 0, 0);
 
-		for (var j = 0; j <= p; ++ j) {
-			var point = P[span - p + j];
-			var Nj = N[j];
+		var span = this.findSpan( p, u, U );
+		var N = this.calcBasisFunctions( span, u, p, U );
+		var C = new THREE.Vector4( 0, 0, 0, 0 );
+
+		for ( var j = 0; j <= p; ++ j ) {
+
+			var point = P[ span - p + j ];
+			var Nj = N[ j ];
 			var wNj = point.w * Nj;
 			C.x += point.x * wNj;
 			C.y += point.y * wNj;
 			C.z += point.z * wNj;
 			C.w += point.w * Nj;
+
 		}
 
 		return C;
+
 	},
 
 
@@ -134,142 +153,175 @@ THREE.NURBSUtils = {
 	calcBasisFunctionDerivatives: function( span,  u,  p,  n,  U ) {
 
 		var zeroArr = [];
-		for (var i = 0; i <= p; ++ i)
-			zeroArr[i] = 0.0;
+		for ( var i = 0; i <= p; ++ i )
+			zeroArr[ i ] = 0.0;
 
 		var ders = [];
-		for (var i = 0; i <= n; ++ i)
-			ders[i] = zeroArr.slice(0);
+		for ( var i = 0; i <= n; ++ i )
+			ders[ i ] = zeroArr.slice( 0 );
 
 		var ndu = [];
-		for (var i = 0; i <= p; ++ i)
-			ndu[i] = zeroArr.slice(0);
+		for ( var i = 0; i <= p; ++ i )
+			ndu[ i ] = zeroArr.slice( 0 );
 
-		ndu[0][0] = 1.0;
+		ndu[ 0 ][ 0 ] = 1.0;
 
-		var left = zeroArr.slice(0);
-		var right = zeroArr.slice(0);
+		var left = zeroArr.slice( 0 );
+		var right = zeroArr.slice( 0 );
 
-		for (var j = 1; j <= p; ++ j) {
-			left[j] = u - U[span + 1 - j];
-			right[j] = U[span + j] - u;
+		for ( var j = 1; j <= p; ++ j ) {
+
+			left[ j ] = u - U[ span + 1 - j ];
+			right[ j ] = U[ span + j ] - u;
 
 			var saved = 0.0;
 
-			for (var r = 0; r < j; ++ r) {
-				var rv = right[r + 1];
-				var lv = left[j - r];
-				ndu[j][r] = rv + lv;
+			for ( var r = 0; r < j; ++ r ) {
+
+				var rv = right[ r + 1 ];
+				var lv = left[ j - r ];
+				ndu[ j ][ r ] = rv + lv;
 
-				var temp = ndu[r][j - 1] / ndu[j][r];
-				ndu[r][j] = saved + rv * temp;
+				var temp = ndu[ r ][ j - 1 ] / ndu[ j ][ r ];
+				ndu[ r ][ j ] = saved + rv * temp;
 				saved = lv * temp;
+
 			}
 
-			ndu[j][j] = saved;
+			ndu[ j ][ j ] = saved;
+
 		}
 
-		for (var j = 0; j <= p; ++ j) {
-			ders[0][j] = ndu[j][p];
+		for ( var j = 0; j <= p; ++ j ) {
+
+			ders[ 0 ][ j ] = ndu[ j ][ p ];
+
 		}
 
-		for (var r = 0; r <= p; ++ r) {
+		for ( var r = 0; r <= p; ++ r ) {
+
 			var s1 = 0;
 			var s2 = 1;
 
 			var a = [];
-			for (var i = 0; i <= p; ++ i) {
-				a[i] = zeroArr.slice(0);
+			for ( var i = 0; i <= p; ++ i ) {
+
+				a[ i ] = zeroArr.slice( 0 );
+
 			}
-			a[0][0] = 1.0;
+			a[ 0 ][ 0 ] = 1.0;
+
+			for ( var k = 1; k <= n; ++ k ) {
 
-			for (var k = 1; k <= n; ++ k) {
 				var d = 0.0;
 				var rk = r - k;
 				var pk = p - k;
 
-				if (r >= k) {
-					a[s2][0] = a[s1][0] / ndu[pk + 1][rk];
-					d = a[s2][0] * ndu[rk][pk];
+				if ( r >= k ) {
+
+					a[ s2 ][ 0 ] = a[ s1 ][ 0 ] / ndu[ pk + 1 ][ rk ];
+					d = a[ s2 ][ 0 ] * ndu[ rk ][ pk ];
+
 				}
 
-				var j1 = (rk >= -1) ? 1 : -rk;
-				var j2 = (r - 1 <= pk) ? k - 1 :  p - r;
+				var j1 = ( rk >= - 1 ) ? 1 : - rk;
+				var j2 = ( r - 1 <= pk ) ? k - 1 :  p - r;
+
+				for ( var j = j1; j <= j2; ++ j ) {
+
+					a[ s2 ][ j ] = ( a[ s1 ][ j ] - a[ s1 ][ j - 1 ] ) / ndu[ pk + 1 ][ rk + j ];
+					d += a[ s2 ][ j ] * ndu[ rk + j ][ pk ];
 
-				for (var j = j1; j <= j2; ++ j) {
-					a[s2][j] = (a[s1][j] - a[s1][j - 1]) / ndu[pk + 1][rk + j];
-					d += a[s2][j] * ndu[rk + j][pk];
 				}
 
-				if (r <= pk) {
-					a[s2][k] = -a[s1][k - 1] / ndu[pk + 1][r];
-					d += a[s2][k] * ndu[r][pk];
+				if ( r <= pk ) {
+
+					a[ s2 ][ k ] = - a[ s1 ][ k - 1 ] / ndu[ pk + 1 ][ r ];
+					d += a[ s2 ][ k ] * ndu[ r ][ pk ];
+
 				}
 
-				ders[k][r] = d;
+				ders[ k ][ r ] = d;
 
 				var j = s1;
 				s1 = s2;
 				s2 = j;
+
 			}
+
 		}
 
 		var r = p;
 
-		for (var k = 1; k <= n; ++ k) {
-			for (var j = 0; j <= p; ++ j) {
-				ders[k][j] *= r;
+		for ( var k = 1; k <= n; ++ k ) {
+
+			for ( var j = 0; j <= p; ++ j ) {
+
+				ders[ k ][ j ] *= r;
+
 			}
 			r *= p - k;
+
 		}
 
 		return ders;
+
 	},
 
 
- 	/*
-	Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2.
+	/*
+		Calculate derivatives of a B-Spline. See The NURBS Book, page 93, algorithm A3.2.
 
-	p  : degree
-	U  : knot vector
-	P  : control points
-	u  : Parametric points
-	nd : number of derivatives
+		p  : degree
+		U  : knot vector
+		P  : control points
+		u  : Parametric points
+		nd : number of derivatives
 
-	returns array[d+1] with derivatives
-	*/
+		returns array[d+1] with derivatives
+		*/
 	calcBSplineDerivatives: function( p,  U,  P,  u,  nd ) {
+
 		var du = nd < p ? nd : p;
 		var CK = [];
-		var span = this.findSpan(p, u, U);
-		var nders = this.calcBasisFunctionDerivatives(span, u, p, du, U);
+		var span = this.findSpan( p, u, U );
+		var nders = this.calcBasisFunctionDerivatives( span, u, p, du, U );
 		var Pw = [];
 
-		for (var i = 0; i < P.length; ++ i) {
-			var point = P[i].clone();
+		for ( var i = 0; i < P.length; ++ i ) {
+
+			var point = P[ i ].clone();
 			var w = point.w;
 
 			point.x *= w;
 			point.y *= w;
 			point.z *= w;
 
-			Pw[i] = point;
+			Pw[ i ] = point;
+
 		}
-		for (var k = 0; k <= du; ++ k) {
-			var point = Pw[span - p].clone().multiplyScalar(nders[k][0]);
+		for ( var k = 0; k <= du; ++ k ) {
+
+			var point = Pw[ span - p ].clone().multiplyScalar( nders[ k ][ 0 ] );
+
+			for ( var j = 1; j <= p; ++ j ) {
+
+				point.add( Pw[ span - p + j ].clone().multiplyScalar( nders[ k ][ j ] ) );
 
-			for (var j = 1; j <= p; ++ j) {
-				point.add(Pw[span - p + j].clone().multiplyScalar(nders[k][j]));
 			}
 
-			CK[k] = point;
+			CK[ k ] = point;
+
 		}
 
-		for (var k = du + 1; k <= nd + 1; ++ k) {
-			CK[k] = new THREE.Vector4(0, 0, 0);
+		for ( var k = du + 1; k <= nd + 1; ++ k ) {
+
+			CK[ k ] = new THREE.Vector4( 0, 0, 0 );
+
 		}
 
 		return CK;
+
 	},
 
 
@@ -279,23 +331,31 @@ THREE.NURBSUtils = {
 	returns k!/(i!(k-i)!)
 	*/
 	calcKoverI: function( k, i ) {
+
 		var nom = 1;
 
-		for (var j = 2; j <= k; ++ j) {
+		for ( var j = 2; j <= k; ++ j ) {
+
 			nom *= j;
+
 		}
 
 		var denom = 1;
 
-		for (var j = 2; j <= i; ++ j) {
+		for ( var j = 2; j <= i; ++ j ) {
+
 			denom *= j;
+
 		}
 
-		for (var j = 2; j <= k - i; ++ j) {
+		for ( var j = 2; j <= k - i; ++ j ) {
+
 			denom *= j;
+
 		}
 
 		return nom / denom;
+
 	},
 
 
@@ -307,29 +367,37 @@ THREE.NURBSUtils = {
 	returns array with derivatives for rational curve.
 	*/
 	calcRationalCurveDerivatives: function ( Pders ) {
+
 		var nd = Pders.length;
 		var Aders = [];
 		var wders = [];
 
-		for (var i = 0; i < nd; ++ i) {
-			var point = Pders[i];
-			Aders[i] = new THREE.Vector3(point.x, point.y, point.z);
-			wders[i] = point.w;
+		for ( var i = 0; i < nd; ++ i ) {
+
+			var point = Pders[ i ];
+			Aders[ i ] = new THREE.Vector3( point.x, point.y, point.z );
+			wders[ i ] = point.w;
+
 		}
 
 		var CK = [];
 
-		for (var k = 0; k < nd; ++ k) {
-			var v = Aders[k].clone();
+		for ( var k = 0; k < nd; ++ k ) {
+
+			var v = Aders[ k ].clone();
+
+			for ( var i = 1; i <= k; ++ i ) {
+
+				v.sub( CK[ k - i ].clone().multiplyScalar( this.calcKoverI( k, i ) * wders[ i ] ) );
 
-			for (var i = 1; i <= k; ++ i) {
-				v.sub(CK[k - i].clone().multiplyScalar(this.calcKoverI(k, i) * wders[i]));
 			}
 
-			CK[k] = v.divideScalar(wders[0]);
+			CK[ k ] = v.divideScalar( wders[ 0 ] );
+
 		}
 
 		return CK;
+
 	},
 
 
@@ -345,8 +413,10 @@ THREE.NURBSUtils = {
 	returns array with derivatives.
 	*/
 	calcNURBSDerivatives: function( p,  U,  P,  u,  nd ) {
-		var Pders = this.calcBSplineDerivatives(p, U, P, u, nd);
-		return this.calcRationalCurveDerivatives(Pders);
+
+		var Pders = this.calcBSplineDerivatives( p, U, P, u, nd );
+		return this.calcRationalCurveDerivatives( Pders );
+
 	},
 
 
@@ -361,31 +431,39 @@ THREE.NURBSUtils = {
 	returns point for given (u, v)
 	*/
 	calcSurfacePoint: function( p, q, U, V, P, u, v ) {
-		var uspan = this.findSpan(p, u, U);
-		var vspan = this.findSpan(q, v, V);
-		var Nu = this.calcBasisFunctions(uspan, u, p, U);
-		var Nv = this.calcBasisFunctions(vspan, v, q, V);
+
+		var uspan = this.findSpan( p, u, U );
+		var vspan = this.findSpan( q, v, V );
+		var Nu = this.calcBasisFunctions( uspan, u, p, U );
+		var Nv = this.calcBasisFunctions( vspan, v, q, V );
 		var temp = [];
 
-		for (var l = 0; l <= q; ++ l) {
-			temp[l] = new THREE.Vector4(0, 0, 0, 0);
-			for (var k = 0; k <= p; ++ k) {
-				var point = P[uspan - p + k][vspan - q + l].clone();
+		for ( var l = 0; l <= q; ++ l ) {
+
+			temp[ l ] = new THREE.Vector4( 0, 0, 0, 0 );
+			for ( var k = 0; k <= p; ++ k ) {
+
+				var point = P[ uspan - p + k ][ vspan - q + l ].clone();
 				var w = point.w;
 				point.x *= w;
 				point.y *= w;
 				point.z *= w;
-				temp[l].add(point.multiplyScalar(Nu[k]));
+				temp[ l ].add( point.multiplyScalar( Nu[ k ] ) );
+
 			}
+
 		}
 
-		var Sw = new THREE.Vector4(0, 0, 0, 0);
-		for (var l = 0; l <= q; ++ l) {
-			Sw.add(temp[l].multiplyScalar(Nv[l]));
+		var Sw = new THREE.Vector4( 0, 0, 0, 0 );
+		for ( var l = 0; l <= q; ++ l ) {
+
+			Sw.add( temp[ l ].multiplyScalar( Nv[ l ] ) );
+
 		}
 
-		Sw.divideScalar(Sw.w);
-		return new THREE.Vector3(Sw.x, Sw.y, Sw.z);
+		Sw.divideScalar( Sw.w );
+		return new THREE.Vector3( Sw.x, Sw.y, Sw.z );
+
 	}
 
 };

+ 14 - 12
examples/js/effects/AnaglyphEffect.js

@@ -17,7 +17,7 @@ THREE.AnaglyphEffect = function ( renderer, width, height ) {
 	var _cameraR = new THREE.PerspectiveCamera();
 	_cameraR.matrixAutoUpdate = false;
 
-	var _camera = new THREE.OrthographicCamera( -1, 1, 1, - 1, 0, 1 );
+	var _camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
 
 	var _scene = new THREE.Scene();
 
@@ -49,7 +49,7 @@ THREE.AnaglyphEffect = function ( renderer, width, height ) {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		fragmentShader: [
 
@@ -71,7 +71,7 @@ THREE.AnaglyphEffect = function ( renderer, width, height ) {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	} );
 
@@ -105,7 +105,7 @@ THREE.AnaglyphEffect = function ( renderer, width, height ) {
 
 		scene.updateMatrixWorld();
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		var hasCameraChanged = ( _aspect !== camera.aspect ) || ( _near !== camera.near ) || ( _far !== camera.far ) || ( _fov !== camera.fov );
 
@@ -124,26 +124,26 @@ THREE.AnaglyphEffect = function ( renderer, width, height ) {
 
 			// translate xOffset
 
-			eyeRight.elements[12] = eyeSep;
-			eyeLeft.elements[12] = -eyeSep;
+			eyeRight.elements[ 12 ] = eyeSep;
+			eyeLeft.elements[ 12 ] = - eyeSep;
 
 			// for left eye
 
-			xmin = -ymax * _aspect + eyeSepOnProjection;
+			xmin = - ymax * _aspect + eyeSepOnProjection;
 			xmax = ymax * _aspect + eyeSepOnProjection;
 
-			projectionMatrix.elements[0] = 2 * _near / ( xmax - xmin );
-			projectionMatrix.elements[8] = ( xmax + xmin ) / ( xmax - xmin );
+			projectionMatrix.elements[ 0 ] = 2 * _near / ( xmax - xmin );
+			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
 
 			_cameraL.projectionMatrix.copy( projectionMatrix );
 
 			// for right eye
 
-			xmin = -ymax * _aspect - eyeSepOnProjection;
+			xmin = - ymax * _aspect - eyeSepOnProjection;
 			xmax = ymax * _aspect - eyeSepOnProjection;
 
-			projectionMatrix.elements[0] = 2 * _near / ( xmax - xmin );
-			projectionMatrix.elements[8] = ( xmax + xmin ) / ( xmax - xmin );
+			projectionMatrix.elements[ 0 ] = 2 * _near / ( xmax - xmin );
+			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
 
 			_cameraR.projectionMatrix.copy( projectionMatrix );
 
@@ -168,8 +168,10 @@ THREE.AnaglyphEffect = function ( renderer, width, height ) {
 	};
 
 	this.dispose = function() {
+
 		if ( _renderTargetL ) _renderTargetL.dispose();
 		if ( _renderTargetR ) _renderTargetR.dispose();
+
 	}
 
 };

+ 68 - 51
examples/js/effects/AsciiEffect.js

@@ -17,25 +17,25 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 	// darker bolder character set from https://github.com/saw/Canvas-ASCII-Art/
 	// ' .\'`^",:;Il!i~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$'.split('');
 
-	if ( !options ) options = {};
+	if ( ! options ) options = {};
 
 	// Some ASCII settings
 
-	var bResolution = !options['resolution'] ? 0.15 : options['resolution']; // Higher for more details
-	var iScale = !options['scale'] ? 1 : options['scale'];
-	var bColor = !options['color'] ? false : options['color']; // nice but slows down rendering!
-	var bAlpha = !options['alpha'] ? false : options['alpha']; // Transparency
-	var bBlock = !options['block'] ? false : options['block']; // blocked characters. like good O dos
-	var bInvert = !options['invert'] ? false : options['invert']; // black is white, white is black
+	var bResolution = ! options[ 'resolution' ] ? 0.15 : options[ 'resolution' ]; // Higher for more details
+	var iScale = ! options[ 'scale' ] ? 1 : options[ 'scale' ];
+	var bColor = ! options[ 'color' ] ? false : options[ 'color' ]; // nice but slows down rendering!
+	var bAlpha = ! options[ 'alpha' ] ? false : options[ 'alpha' ]; // Transparency
+	var bBlock = ! options[ 'block' ] ? false : options[ 'block' ]; // blocked characters. like good O dos
+	var bInvert = ! options[ 'invert' ] ? false : options[ 'invert' ]; // black is white, white is black
 
 	var strResolution = 'low';
 
 	var width, height;
 
-	var domElement = document.createElement('div');
+	var domElement = document.createElement( 'div' );
 	domElement.style.cursor = 'default';
 
-	var oAscii = document.createElement("table");
+	var oAscii = document.createElement( "table" );
 	domElement.appendChild( oAscii );
 
 	var iWidth, iHeight;
@@ -86,8 +86,8 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 
 		if ( oImg.style.backgroundColor ) {
 
-			oAscii.rows[0].cells[0].style.backgroundColor = oImg.style.backgroundColor;
-			oAscii.rows[0].cells[0].style.color = oImg.style.color;
+			oAscii.rows[ 0 ].cells[ 0 ].style.backgroundColor = oImg.style.backgroundColor;
+			oAscii.rows[ 0 ].cells[ 0 ].style.color = oImg.style.color;
 
 		}
 
@@ -96,8 +96,8 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 
 		var oStyle = oAscii.style;
 		oStyle.display = "inline";
-		oStyle.width = Math.round(iWidth / fResolution * iScale) + "px";
-		oStyle.height = Math.round(iHeight / fResolution * iScale) + "px";
+		oStyle.width = Math.round( iWidth / fResolution * iScale ) + "px";
+		oStyle.height = Math.round( iHeight / fResolution * iScale ) + "px";
 		oStyle.whiteSpace = "pre";
 		oStyle.margin = "0px";
 		oStyle.padding = "0px";
@@ -107,28 +107,33 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 		oStyle.lineHeight = fLineHeight + "px";
 		oStyle.textAlign = "left";
 		oStyle.textDecoration = "none";
+
 	}
 
 
-	var aDefaultCharList = (" .,:;i1tfLCG08@").split("");
-	var aDefaultColorCharList = (" CGO08@").split("");
+	var aDefaultCharList = ( " .,:;i1tfLCG08@" ).split( "" );
+	var aDefaultColorCharList = ( " CGO08@" ).split( "" );
 	var strFont = "courier new, monospace";
 
 	var oCanvasImg = renderer.domElement;
 
-	var oCanvas = document.createElement("canvas");
-	if (!oCanvas.getContext) {
+	var oCanvas = document.createElement( "canvas" );
+	if ( ! oCanvas.getContext ) {
+
 		return;
+
 	}
 
-	var oCtx = oCanvas.getContext("2d");
-	if (!oCtx.getImageData) {
+	var oCtx = oCanvas.getContext( "2d" );
+	if ( ! oCtx.getImageData ) {
+
 		return;
+
 	}
 
-	var aCharList = (bColor ? aDefaultColorCharList : aDefaultCharList);
+	var aCharList = ( bColor ? aDefaultColorCharList : aDefaultCharList );
 
-	if (charSet) aCharList = charSet;
+	if ( charSet ) aCharList = charSet;
 
 	var fResolution = 0.5;
 
@@ -144,8 +149,8 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 
 	// Setup dom
 
-	var fFontSize = (2 / fResolution) * iScale;
-	var fLineHeight = (2 / fResolution) * iScale;
+	var fFontSize = ( 2 / fResolution ) * iScale;
+	var fLineHeight = ( 2 / fResolution ) * iScale;
 
 	// adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width.
 
@@ -153,36 +158,36 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 
 	if ( strResolution == "low" ) {
 
-		switch (iScale) {
-			case 1 : fLetterSpacing = -1; break;
+		switch ( iScale ) {
+			case 1 : fLetterSpacing = - 1; break;
 			case 2 :
-			case 3 : fLetterSpacing = -2.1; break;
-			case 4 : fLetterSpacing = -3.1; break;
-			case 5 : fLetterSpacing = -4.15; break;
+			case 3 : fLetterSpacing = - 2.1; break;
+			case 4 : fLetterSpacing = - 3.1; break;
+			case 5 : fLetterSpacing = - 4.15; break;
 		}
 
 	}
 
 	if ( strResolution == "medium" ) {
 
-		switch (iScale) {
+		switch ( iScale ) {
 			case 1 : fLetterSpacing = 0; break;
-			case 2 : fLetterSpacing = -1; break;
-			case 3 : fLetterSpacing = -1.04; break;
+			case 2 : fLetterSpacing = - 1; break;
+			case 3 : fLetterSpacing = - 1.04; break;
 			case 4 :
-			case 5 : fLetterSpacing = -2.1; break;
+			case 5 : fLetterSpacing = - 2.1; break;
 		}
 
 	}
 
 	if ( strResolution == "high" ) {
 
-		switch (iScale) {
+		switch ( iScale ) {
 			case 1 :
 			case 2 : fLetterSpacing = 0; break;
 			case 3 :
 			case 4 :
-			case 5 : fLetterSpacing = -1; break;
+			case 5 : fLetterSpacing = - 1; break;
 		}
 
 	}
@@ -197,61 +202,72 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 
 		oCtx.clearRect( 0, 0, iWidth, iHeight );
 		oCtx.drawImage( oCanvasImg, 0, 0, iWidth, iHeight );
-		var oImgData = oCtx.getImageData(0, 0, iWidth, iHeight).data;
+		var oImgData = oCtx.getImageData( 0, 0, iWidth, iHeight ).data;
 
 		// Coloring loop starts now
 		var strChars = "";
 
 		// console.time('rendering');
 
-		for (var y = 0; y < iHeight; y+=2) {
-			for (var x = 0; x < iWidth; x ++) {
-				var iOffset = (y * iWidth + x) * 4;
+		for ( var y = 0; y < iHeight; y += 2 ) {
 
-				var iRed = oImgData[iOffset];
-				var iGreen = oImgData[iOffset + 1];
-				var iBlue = oImgData[iOffset + 2];
-				var iAlpha = oImgData[iOffset + 3];
+			for ( var x = 0; x < iWidth; x ++ ) {
+
+				var iOffset = ( y * iWidth + x ) * 4;
+
+				var iRed = oImgData[ iOffset ];
+				var iGreen = oImgData[ iOffset + 1 ];
+				var iBlue = oImgData[ iOffset + 2 ];
+				var iAlpha = oImgData[ iOffset + 3 ];
 				var iCharIdx;
 
 				var fBrightness;
 
-				fBrightness = (0.3 * iRed + 0.59 * iGreen + 0.11 * iBlue) / 255;
+				fBrightness = ( 0.3 * iRed + 0.59 * iGreen + 0.11 * iBlue ) / 255;
 				// fBrightness = (0.3*iRed + 0.5*iGreen + 0.3*iBlue) / 255;
 
-				if (iAlpha == 0) {
+				if ( iAlpha == 0 ) {
+
 					// should calculate alpha instead, but quick hack :)
 					//fBrightness *= (iAlpha / 255);
 					fBrightness = 1;
 
 				}
 
-				iCharIdx = Math.floor((1 - fBrightness) * (aCharList.length - 1));
+				iCharIdx = Math.floor( ( 1 - fBrightness ) * ( aCharList.length - 1 ) );
+
+				if ( bInvert ) {
 
-				if (bInvert) {
 					iCharIdx = aCharList.length - iCharIdx - 1;
+
 				}
 
 				// good for debugging
 				//fBrightness = Math.floor(fBrightness * 10);
 				//strThisChar = fBrightness;
 
-				var strThisChar = aCharList[iCharIdx];
+				var strThisChar = aCharList[ iCharIdx ];
 
-				if (strThisChar === undefined || strThisChar == " ")
+				if ( strThisChar === undefined || strThisChar == " " )
 					strThisChar = "&nbsp;";
 
-				if (bColor) {
+				if ( bColor ) {
+
 					strChars += "<span style='"
 						+ "color:rgb(" + iRed + "," + iGreen + "," + iBlue + ");"
-						+ (bBlock ? "background-color:rgb(" + iRed + "," + iGreen + "," + iBlue + ");" : "")
-						+ (bAlpha ? "opacity:" + (iAlpha / 255) + ";" : "")
+						+ ( bBlock ? "background-color:rgb(" + iRed + "," + iGreen + "," + iBlue + ");" : "" )
+						+ ( bAlpha ? "opacity:" + ( iAlpha / 255 ) + ";" : "" )
 						+ "'>" + strThisChar + "</span>";
+
 				} else {
+
 					strChars += strThisChar;
+
 				}
+
 			}
 			strChars += "<br/>";
+
 		}
 
 		oAscii.innerHTML = "<tr><td>" + strChars + "</td></tr>";
@@ -259,6 +275,7 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 		// console.timeEnd('rendering');
 
 		// return oAscii;
+
 	}
 
 	// end modified asciifyImage block

+ 11 - 11
examples/js/effects/ParallaxBarrierEffect.js

@@ -48,7 +48,7 @@ THREE.ParallaxBarrierEffect = function ( renderer ) {
 
 			"}"
 
-		].join("\n"),
+		].join( "\n" ),
 
 		fragmentShader: [
 
@@ -72,7 +72,7 @@ THREE.ParallaxBarrierEffect = function ( renderer ) {
 
 			"}"
 
-		].join("\n")
+		].join( "\n" )
 
 	} );
 
@@ -104,7 +104,7 @@ THREE.ParallaxBarrierEffect = function ( renderer ) {
 
 		scene.updateMatrixWorld();
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
+		if ( camera.parent === null ) camera.updateMatrixWorld();
 
 		var hasCameraChanged = ( _aspect !== camera.aspect ) || ( _near !== camera.near ) || ( _far !== camera.far ) || ( _fov !== camera.fov );
 
@@ -123,26 +123,26 @@ THREE.ParallaxBarrierEffect = function ( renderer ) {
 
 			// translate xOffset
 
-			eyeRight.elements[12] = eyeSep;
-			eyeLeft.elements[12] = -eyeSep;
+			eyeRight.elements[ 12 ] = eyeSep;
+			eyeLeft.elements[ 12 ] = - eyeSep;
 
 			// for left eye
 
-			xmin = -ymax * _aspect + eyeSepOnProjection;
+			xmin = - ymax * _aspect + eyeSepOnProjection;
 			xmax = ymax * _aspect + eyeSepOnProjection;
 
-			projectionMatrix.elements[0] = 2 * _near / ( xmax - xmin );
-			projectionMatrix.elements[8] = ( xmax + xmin ) / ( xmax - xmin );
+			projectionMatrix.elements[ 0 ] = 2 * _near / ( xmax - xmin );
+			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
 
 			_cameraL.projectionMatrix.copy( projectionMatrix );
 
 			// for right eye
 
-			xmin = -ymax * _aspect - eyeSepOnProjection;
+			xmin = - ymax * _aspect - eyeSepOnProjection;
 			xmax = ymax * _aspect - eyeSepOnProjection;
 
-			projectionMatrix.elements[0] = 2 * _near / ( xmax - xmin );
-			projectionMatrix.elements[8] = ( xmax + xmin ) / ( xmax - xmin );
+			projectionMatrix.elements[ 0 ] = 2 * _near / ( xmax - xmin );
+			projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin );
 
 			_cameraR.projectionMatrix.copy( projectionMatrix );
 

+ 13 - 5
examples/js/effects/StereoEffect.js

@@ -19,20 +19,28 @@ THREE.StereoEffect = function ( renderer ) {
 	Object.defineProperties( this, {
 		separation: {
 			get: function () {
+
 				return scope.eyeSeparation;
+
 			},
 			set: function ( value ) {
+
 				console.warn( 'THREE.StereoEffect: .separation is now .eyeSeparation.' );
 				scope.eyeSeparation = value;
+
 			}
 		},
 		targetDistance: {
 			get: function () {
+
 				return scope.focalLength;
+
 			},
 			set: function ( value ) {
+
 				console.warn( 'THREE.StereoEffect: .targetDistance is now .focalLength.' );
 				scope.focalLength = value;
+
 			}
 		}
 	} );
@@ -70,8 +78,8 @@ THREE.StereoEffect = function ( renderer ) {
 
 		scene.updateMatrixWorld();
 
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
-	
+		if ( camera.parent === null ) camera.updateMatrixWorld();
+
 		camera.matrixWorld.decompose( _position, _quaternion, _scale );
 
 		// Effective fov of the camera
@@ -83,7 +91,7 @@ THREE.StereoEffect = function ( renderer ) {
 		_halfFocalWidth = _halfFocalHeight * 0.5 * camera.aspect;
 
 		_top = _halfFocalHeight * _ndfl;
-		_bottom = -_top;
+		_bottom = - _top;
 		_innerFactor = ( _halfFocalWidth + this.eyeSeparation / 2.0 ) / ( _halfFocalWidth * 2.0 );
 		_outerFactor = 1.0 - _innerFactor;
 
@@ -93,7 +101,7 @@ THREE.StereoEffect = function ( renderer ) {
 		// left
 
 		_cameraL.projectionMatrix.makeFrustum(
-			-_outer,
+			- _outer,
 			_inner,
 			_bottom,
 			_top,
@@ -108,7 +116,7 @@ THREE.StereoEffect = function ( renderer ) {
 		// right
 
 		_cameraR.projectionMatrix.makeFrustum(
-			-_inner,
+			- _inner,
 			_outer,
 			_bottom,
 			_top,

+ 24 - 23
examples/js/effects/VREffect.js

@@ -133,7 +133,7 @@ THREE.VREffect = function ( renderer, onError ) {
 			renderer.enableScissorTest( true );
 			renderer.clear();
 
-			if ( camera.parent === undefined ) camera.updateMatrixWorld();
+			if ( camera.parent === null ) camera.updateMatrixWorld();
 
 			cameraL.projectionMatrix = fovToProjection( eyeFOVL, true, camera.near, camera.far );
 			cameraR.projectionMatrix = fovToProjection( eyeFOVR, true, camera.near, camera.far );
@@ -172,10 +172,10 @@ THREE.VREffect = function ( renderer, onError ) {
 
 	function fovToNDCScaleOffset( fov ) {
 
-		var pxscale = 2.0 / (fov.leftTan + fov.rightTan);
-		var pxoffset = (fov.leftTan - fov.rightTan) * pxscale * 0.5;
-		var pyscale = 2.0 / (fov.upTan + fov.downTan);
-		var pyoffset = (fov.upTan - fov.downTan) * pyscale * 0.5;
+		var pxscale = 2.0 / ( fov.leftTan + fov.rightTan );
+		var pxoffset = ( fov.leftTan - fov.rightTan ) * pxscale * 0.5;
+		var pyscale = 2.0 / ( fov.upTan + fov.downTan );
+		var pyoffset = ( fov.upTan - fov.downTan ) * pyscale * 0.5;
 		return { scale: [ pxscale, pyscale ], offset: [ pxoffset, pyoffset ] };
 
 	}
@@ -186,44 +186,45 @@ THREE.VREffect = function ( renderer, onError ) {
 		zNear = zNear === undefined ? 0.01 : zNear;
 		zFar = zFar === undefined ? 10000.0 : zFar;
 
-		var handednessScale = rightHanded ? -1.0 : 1.0;
+		var handednessScale = rightHanded ? - 1.0 : 1.0;
 
 		// start with an identity matrix
 		var mobj = new THREE.Matrix4();
 		var m = mobj.elements;
 
 		// and with scale/offset info for normalized device coords
-		var scaleAndOffset = fovToNDCScaleOffset(fov);
+		var scaleAndOffset = fovToNDCScaleOffset( fov );
 
 		// X result, map clip edges to [-w,+w]
-		m[0 * 4 + 0] = scaleAndOffset.scale[0];
-		m[0 * 4 + 1] = 0.0;
-		m[0 * 4 + 2] = scaleAndOffset.offset[0] * handednessScale;
-		m[0 * 4 + 3] = 0.0;
+		m[ 0 * 4 + 0 ] = scaleAndOffset.scale[ 0 ];
+		m[ 0 * 4 + 1 ] = 0.0;
+		m[ 0 * 4 + 2 ] = scaleAndOffset.offset[ 0 ] * handednessScale;
+		m[ 0 * 4 + 3 ] = 0.0;
 
 		// Y result, map clip edges to [-w,+w]
 		// Y offset is negated because this proj matrix transforms from world coords with Y=up,
 		// but the NDC scaling has Y=down (thanks D3D?)
-		m[1 * 4 + 0] = 0.0;
-		m[1 * 4 + 1] = scaleAndOffset.scale[1];
-		m[1 * 4 + 2] = -scaleAndOffset.offset[1] * handednessScale;
-		m[1 * 4 + 3] = 0.0;
+		m[ 1 * 4 + 0 ] = 0.0;
+		m[ 1 * 4 + 1 ] = scaleAndOffset.scale[ 1 ];
+		m[ 1 * 4 + 2 ] = - scaleAndOffset.offset[ 1 ] * handednessScale;
+		m[ 1 * 4 + 3 ] = 0.0;
 
 		// Z result (up to the app)
-		m[2 * 4 + 0] = 0.0;
-		m[2 * 4 + 1] = 0.0;
-		m[2 * 4 + 2] = zFar / (zNear - zFar) * -handednessScale;
-		m[2 * 4 + 3] = (zFar * zNear) / (zNear - zFar);
+		m[ 2 * 4 + 0 ] = 0.0;
+		m[ 2 * 4 + 1 ] = 0.0;
+		m[ 2 * 4 + 2 ] = zFar / ( zNear - zFar ) * - handednessScale;
+		m[ 2 * 4 + 3 ] = ( zFar * zNear ) / ( zNear - zFar );
 
 		// W result (= Z in)
-		m[3 * 4 + 0] = 0.0;
-		m[3 * 4 + 1] = 0.0;
-		m[3 * 4 + 2] = handednessScale;
-		m[3 * 4 + 3] = 0.0;
+		m[ 3 * 4 + 0 ] = 0.0;
+		m[ 3 * 4 + 1 ] = 0.0;
+		m[ 3 * 4 + 2 ] = handednessScale;
+		m[ 3 * 4 + 3 ] = 0.0;
 
 		mobj.transpose();
 
 		return mobj;
+
 	}
 
 	function fovToProjection( fov, rightHanded, zNear, zFar ) {

+ 20 - 18
examples/js/exporters/STLBinaryExporter.js

@@ -3,7 +3,7 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mudcube / http://mudcu.be/
  */
- 
+
 THREE.STLBinaryExporter = function () {};
 
 THREE.STLBinaryExporter.prototype = {
@@ -15,24 +15,26 @@ THREE.STLBinaryExporter.prototype = {
 		var vector = new THREE.Vector3();
 		var normalMatrixWorld = new THREE.Matrix3();
 
-		return function ( scene ) {
+		return function parse( scene ) {
 
 			var triangles = 0;
 			scene.traverse( function ( object ) {
-				if ( !(object instanceof THREE.Mesh) ) return;
+
+				if ( ! ( object instanceof THREE.Mesh ) ) return;
 				triangles += object.geometry.faces.length;
-			});
+
+			} );
 
 			var offset = 80; // skip header
 			var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
-			var arrayBuffer = new ArrayBuffer(bufferLength);
-			var output = new DataView(arrayBuffer);
-			output.setUint32(offset, triangles, true); offset += 4;
+			var arrayBuffer = new ArrayBuffer( bufferLength );
+			var output = new DataView( arrayBuffer );
+			output.setUint32( offset, triangles, true ); offset += 4;
 
 			scene.traverse( function ( object ) {
 
-				if ( !(object instanceof THREE.Mesh) ) return;
-				if ( !(object.geometry instanceof THREE.Geometry )) return;
+				if ( ! ( object instanceof THREE.Mesh ) ) return;
+				if ( ! ( object.geometry instanceof THREE.Geometry ) ) return;
 
 				var geometry = object.geometry;
 				var matrixWorld = object.matrixWorld;
@@ -48,9 +50,9 @@ THREE.STLBinaryExporter.prototype = {
 
 					vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
 
-					output.setFloat32(offset, vector.x, true); offset += 4; // normal
-					output.setFloat32(offset, vector.y, true); offset += 4;
-					output.setFloat32(offset, vector.z, true); offset += 4;
+					output.setFloat32( offset, vector.x, true ); offset += 4; // normal
+					output.setFloat32( offset, vector.y, true ); offset += 4;
+					output.setFloat32( offset, vector.z, true ); offset += 4;
 
 					var indices = [ face.a, face.b, face.c ];
 
@@ -58,22 +60,22 @@ THREE.STLBinaryExporter.prototype = {
 
 						vector.copy( vertices[ indices[ j ] ] ).applyMatrix4( matrixWorld );
 
-						output.setFloat32(offset, vector.x, true); offset += 4; // vertices
-						output.setFloat32(offset, vector.y, true); offset += 4;
-						output.setFloat32(offset, vector.z, true); offset += 4;
+						output.setFloat32( offset, vector.x, true ); offset += 4; // vertices
+						output.setFloat32( offset, vector.y, true ); offset += 4;
+						output.setFloat32( offset, vector.z, true ); offset += 4;
 
 					}
 
-					output.setUint16(offset, 0, true); offset += 2; // attribute byte count					
+					output.setUint16( offset, 0, true ); offset += 2; // attribute byte count
 
 				}
 
 			} );
-			
+
 			return output;
 
 		};
 
 	}() )
 
-};
+};

+ 3 - 3
examples/js/exporters/STLExporter.js

@@ -2,7 +2,7 @@
  * @author kovacsv / http://kovacsv.hu/
  * @author mrdoob / http://mrdoob.com/
  */
- 
+
 THREE.STLExporter = function () {};
 
 THREE.STLExporter.prototype = {
@@ -14,7 +14,7 @@ THREE.STLExporter.prototype = {
 		var vector = new THREE.Vector3();
 		var normalMatrixWorld = new THREE.Matrix3();
 
-		return function ( scene ) {
+		return function parse( scene ) {
 
 			var output = '';
 
@@ -72,4 +72,4 @@ THREE.STLExporter.prototype = {
 
 	}() )
 
-};
+};

Деякі файли не було показано, через те що забагато файлів було змінено