Mr.doob 12 years ago
parent
commit
b92db21658
98 changed files with 2403 additions and 10136 deletions
  1. 296 368
      build/three.js
  2. 116 115
      build/three.min.js
  3. 1 8
      docs/api/core/Geometry.html
  4. 2 3
      docs/api/extras/geometries/ParametricGeometry.html
  5. 14 26
      docs/api/loaders/LoadingManager.html
  6. 0 89
      docs/api/loaders/LoadingMonitor.html
  7. 124 0
      docs/api/math/Euler.html
  8. 1 1
      docs/api/math/Vector2.html
  9. 1 1
      docs/api/textures/Texture.html
  10. 1 1
      docs/index.html
  11. 3 2
      docs/list.js
  12. 24 15
      editor/index.html
  13. 95 10
      editor/js/Editor.js
  14. 20 0
      editor/js/Menubar.Add.js
  15. 1 3
      editor/js/Menubar.js
  16. 50 0
      editor/js/Sidebar.Geometry.CircleGeometry.js
  17. 19 39
      editor/js/Sidebar.Geometry.js
  18. 31 1
      editor/js/Sidebar.Material.js
  19. 11 27
      editor/js/Sidebar.Scene.js
  20. 1 3
      editor/js/Sidebar.js
  21. 6 3
      editor/js/Toolbar.js
  22. 41 39
      editor/js/Viewport.js
  23. 8 0
      editor/js/libs/ui.js
  24. 2 1
      examples/canvas_lines_colors.html
  25. 37 6
      examples/index.html
  26. 1 1
      examples/js/Detector.js
  27. 296 0
      examples/js/Mirror.js
  28. 52 20
      examples/js/controls/EditorControls.js
  29. 684 638
      examples/js/controls/TransformControls.js
  30. 6 0
      examples/js/exporters/ObjectExporter.js
  31. 12 50
      examples/js/loaders/MTLLoader.js
  32. 36 49
      examples/js/loaders/OBJLoader.js
  33. 18 134
      examples/js/loaders/OBJMTLLoader.js
  34. 0 2
      examples/js/renderers/WebGLRenderer2/README.md
  35. 0 3274
      examples/js/renderers/WebGLRenderer2/WebGLRenderer2.js
  36. 0 1570
      examples/js/renderers/WebGLRenderer2/webgl/LowLevelRenderer.js
  37. 0 413
      examples/js/renderers/WebGLRenderer2/webgl/ShaderBuilder.js
  38. 0 206
      examples/js/renderers/WebGLRenderer2/webgl/objects/LineRenderer.js
  39. 0 1618
      examples/js/renderers/WebGLRenderer2/webgl/objects/MeshRenderer.js
  40. 0 127
      examples/js/renderers/WebGLRenderer2/webgl/objects/Object3DRenderer.js
  41. 0 360
      examples/js/renderers/WebGLRenderer2/webgl/objects/ParticleRenderer.js
  42. 0 209
      examples/js/renderers/WebGLRenderer2/webgl/objects/RibbonRenderer.js
  43. 2 2
      examples/js/renderers/WebGLRenderer3.js
  44. 1 1
      examples/misc_controls_fly.html
  45. 43 27
      examples/misc_controls_transform.html
  46. 1 1
      examples/misc_sound.html
  47. BIN
      examples/textures/compressed/Mountains_argb_mip.dds
  48. BIN
      examples/textures/compressed/Mountains_argb_nomip.dds
  49. BIN
      examples/textures/compressed/disturb_argb_mip.dds
  50. BIN
      examples/textures/compressed/disturb_argb_nomip.dds
  51. 2 1
      examples/webgl3_performance.html
  52. 2 2
      examples/webgl_animation_skinning.html
  53. 2 2
      examples/webgl_buffergeometry.html
  54. 1 1
      examples/webgl_buffergeometry_custom_attributes_particles.html
  55. 1 1
      examples/webgl_buffergeometry_lines.html
  56. 2 3
      examples/webgl_buffergeometry_particles.html
  57. 1 1
      examples/webgl_camera.html
  58. 2 1
      examples/webgl_custom_attributes.html
  59. 2 1
      examples/webgl_custom_attributes_lines.html
  60. 1 1
      examples/webgl_custom_attributes_particles.html
  61. 1 1
      examples/webgl_custom_attributes_particles2.html
  62. 1 1
      examples/webgl_custom_attributes_particles3.html
  63. 0 284
      examples/webgl_custom_attributes_ribbons.html
  64. 2 1
      examples/webgl_geometry_dynamic.html
  65. 2 1
      examples/webgl_geometry_minecraft.html
  66. 2 1
      examples/webgl_geometry_minecraft_ao.html
  67. 2 2
      examples/webgl_geometry_minecraft_oculusrift.html
  68. 2 1
      examples/webgl_geometry_terrain_fog.html
  69. 2 1
      examples/webgl_geometry_tessellation.html
  70. 3 2
      examples/webgl_interactive_cubes_gpu.html
  71. 2 2
      examples/webgl_lights_pointlights2.html
  72. 1 1
      examples/webgl_lines_colors.html
  73. 2 1
      examples/webgl_lines_dashed.html
  74. 1 1
      examples/webgl_loader_ctm_materials.html
  75. 2 5
      examples/webgl_loader_obj_mtl.html
  76. 1 1
      examples/webgl_lod.html
  77. 2 1
      examples/webgl_marching_cubes.html
  78. 2 1
      examples/webgl_materials2.html
  79. 1 1
      examples/webgl_materials_blending.html
  80. 1 1
      examples/webgl_materials_blending_custom.html
  81. 2 1
      examples/webgl_materials_bumpmap.html
  82. 2 1
      examples/webgl_materials_bumpmap_skin.html
  83. 2 3
      examples/webgl_materials_cubemap_dynamic.html
  84. 2 3
      examples/webgl_materials_lightmap.html
  85. 2 1
      examples/webgl_materials_normalmap2.html
  86. 59 12
      examples/webgl_materials_texture_compressed.html
  87. 215 0
      examples/webgl_mirror.html
  88. 2 1
      examples/webgl_morphtargets.html
  89. 1 1
      examples/webgl_particles_dynamic.html
  90. 2 1
      examples/webgl_performance.html
  91. 2 1
      examples/webgl_performance_doublesided.html
  92. 1 1
      examples/webgl_postprocessing_dof2.html
  93. 0 317
      examples/webgl_ribbons.html
  94. 1 1
      examples/webgl_sandbox.html
  95. 2 2
      examples/webgl_shading_physical.html
  96. 1 1
      examples/webgl_shadowmap.html
  97. 1 1
      examples/webgl_shadowmap_performance.html
  98. 1 1
      index.html

File diff suppressed because it is too large
+ 296 - 368
build/three.js


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


+ 1 - 8
docs/api/core/Geometry.html

@@ -59,18 +59,11 @@
 		<h3>.[page:Array colors]</h3>
 		<h3>.[page:Array colors]</h3>
 		<div>
 		<div>
 		Array of vertex [page:Color colors], matching number and order of vertices.<br />
 		Array of vertex [page:Color colors], matching number and order of vertices.<br />
-		Used in [page:ParticleSystem], [page:Line] and [page:Ribbon].<br />
+		Used in [page:ParticleSystem] and [page:Line].<br />
 		[page:Mesh Meshes] use per-face-use-of-vertex colors embedded directly in faces.<br />
 		[page:Mesh Meshes] use per-face-use-of-vertex colors embedded directly in faces.<br />
 		To signal an update in this array, [page:Geometry Geometry.colorsNeedUpdate] needs to be set to true.
 		To signal an update in this array, [page:Geometry Geometry.colorsNeedUpdate] needs to be set to true.
 		</div>
 		</div>
 
 
-		<h3>.[page:Array normals]</h3>
-		<div>
-		Array of vertex [page:Vector3 normals], matching number and order of vertices.<br />
-		[link:http://en.wikipedia.org/wiki/Normal_(geometry) Normal vectors] are  nessecary for lighting <br />
-		To signal an update in this array, [page:Geometry Geometry.normalsNeedUpdate] needs to be set to true.
-		</div>
-
 		<h3>.[page:Array faces]</h3>
 		<h3>.[page:Array faces]</h3>
 		<div>
 		<div>
 		Array of [page:Face3 triangles].<br />
 		Array of [page:Face3 triangles].<br />

+ 2 - 3
docs/api/extras/geometries/ParametricGeometry.html

@@ -17,12 +17,11 @@
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:todo func], [page:todo slices], [page:todo stacks], [page:Boolean useTris])</h3>
+		<h3>[name]([page:todo func], [page:todo slices], [page:todo stacks])</h3>
 		<div>
 		<div>
 		func — todo <br />
 		func — todo <br />
 		slices — todo <br />
 		slices — todo <br />
-		stacks — todo <br />
-		useTris — todo
+		stacks — todo
 		</div>
 		</div>
 		<div>
 		<div>
 		todo
 		todo

+ 14 - 26
docs/api/objects/Ribbon.html → docs/api/loaders/LoadingManager.html

@@ -7,43 +7,31 @@
 		<link type="text/css" rel="stylesheet" href="../../page.css" />
 		<link type="text/css" rel="stylesheet" href="../../page.css" />
 	</head>
 	</head>
 	<body>
 	<body>
-		[page:Object3D] &rarr;
-
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
-		<div class="desc">todo</div>
-
+		<div class="desc">Handles and keeps track of loaded and pending data.</div>
+		<code>
+var manager = new THREE.LoadingManager();
+manager.onProgress = function ( item, loaded, total ) {
 
 
-		<h2>Constructor</h2>
+	console.log( item, loaded, total );
 
 
+};
 
 
-		<h3>[name]([page:todo geometry], [page:todo material])</h3>
-		<div>
-		geometry -- todo <br />
-		material -- todo
-		</div>
-		<div>
-		todo
-		</div>
-
+var loader = new THREE.OBJLoader( manager );
+loader.load( 'file.obj', function ( object ) {
 
 
-		<h2>Properties</h2>
+	//
 
 
+} );
+		</code>
 
 
+		<h2>Constructor</h2>
 
 
-		<h3>.[page:todo geometry]</h3>
-		<div>
-		todo
-		</div> 
-
-		<h3>.[page:todo material]</h3>
+		<h3>[name]()</h3>
 		<div>
 		<div>
 		todo
 		todo
-		</div> 
-
-		<h2>Methods</h2>
-
-
+		</div>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>
 
 

+ 0 - 89
docs/api/loaders/LoadingMonitor.html

@@ -1,89 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8" />
-		<script src="../../list.js"></script>
-		<script src="../../page.js"></script>
-		<link type="text/css" rel="stylesheet" href="../../page.css" />
-	</head>
-	<body>
-		<h1>[name]</h1>
-
-		<div class="desc">A LoadingMonitor keeps track of loaded and pending data.</div>
-		<div class="desc">To keep track of a loader, just add it to the monitor:</div>
-<code>monitor.add( imageLoader );
-</code>
-
-		<h2>Constructor</h2>
-
-
-		<h3>[name]()</h3>
-		<div>
-		todo
-		</div>
-
-
-		<h2>Events</h2>
-		
-		<h3>progress</h3>
-		<div class="desc">
-		Dispatched each time a monitored loader completes loading
-		</div>
-		<div>
-		loaded — number of completed loaders<br />
-		total — total number of loaders monitored by this monitor
-		</div>
-		
-		<h3>load</h3>
-		<div id="desc">
-		Dispatched when all loaders have completed loading
-		</div>
-
-
-		<h2>Methods</h2>
-
-		<h3>.add( [page:Loader loader] )</h3>
-		<div>
-		loader — required. Loader to be monitored.
-		</div>
-
-		<h3>.dispatchEvent([page:todo event]) [page:todo]</h3>
-		<div>
-		event -- todo
-		</div>
-		<div>
-		todo
-		</div>
-
-		<h3>.hasEventListener([page:todo type], [page:todo listener]) [page:todo]</h3>
-		<div>
-		type -- todo <br />
-		listener -- todo
-		</div>
-		<div>
-		todo
-		</div>
-
-		<h3>.removeEventListener([page:todo type], [page:todo listener]) [page:todo]</h3>
-		<div>
-		type -- todo <br />
-		listener -- todo
-		</div>
-		<div>
-		todo
-		</div>
-
-		<h3>.addEventListener([page:todo type], [page:todo listener]) [page:todo]</h3>
-		<div>
-		type -- todo <br />
-		listener -- todo
-		</div>
-		<div>
-		todo
-		</div>
-
-		<h2>Source</h2>
-
-		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-	</body>
-</html>

+ 124 - 0
docs/api/math/Euler.html

@@ -0,0 +1,124 @@
+<!DOCTYPE html>
+<html lang="en">
+  <head>
+    <meta charset="utf-8" />
+    <script src="../../list.js"></script>
+    <script src="../../page.js"></script>
+    <link type="text/css" rel="stylesheet" href="../../page.css" />
+  </head>
+  <body>
+    <h1>[name]</h1>
+
+    <div class="desc">Euler Angles.</div>
+
+    <h2>Example</h2>
+
+    <code>var a = new THREE.Euler( 0, 1, 1.57, 'XYZ' );
+    var b = new THREE.Vector3( 1, 0, 1 );
+    b.applyEuler(a);
+    </code>
+
+
+    <h2>Constructor</h2>
+
+
+    <h3>[name]( [page:Float x], [page:Float y], [page:Float z], [page:String Order] )</h3>
+    <div>
+    x -- [page:Float] the angle of the x axis<br />
+    y -- [page:Float] the angle of the y axis<br />
+    z -- [page:Float] the angle of the z axis<br />
+    order -- [page:String] A string representing the order that the rotations are applied, defaults to 'XYZ' (must be upper case).
+    </div>
+    <div>
+    A euler angle for transforming
+    </div>
+
+
+    <h2>Properties</h2>
+
+    <h3>.[page:Float x]</h3>
+
+    <h3>.[page:Float y]</h3>
+
+    <h3>.[page:Float z]</h3>
+
+    <h3>.[page:String order]</h3>
+
+
+
+    <h2>Methods</h2>
+
+    <h3>.set( [page:Float x], [page:Float y], [page:Float z], [page:String order] ) [page:this]</h3>
+    <div>
+    x -- [page:Float] Angle in x axis<br />
+    x -- [page:Float] Angle in x axis<br />
+    x -- [page:Float] Angle in x axis<br />
+    order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
+    </div>
+    <div>
+    Sets the angles of this euler transform.
+    </div>
+
+    <h3>.copy( [page:Euler euler] ) [page:this]</h3>
+    <div>
+    Copies value of *euler* to this euler.
+    </div>
+
+    <h3>.setFromRotationMatrix( [page:Matrix4 m], [page:String order] ) [page:this]</h3>
+    <div>
+    m -- [page:Matrix4] assumes upper 3x3 of matrix is a pure rotation matrix (i.e. unscaled)<br />
+    order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
+    </div>
+    <div>
+    Sets the angles of this euler transform from a pure rotation matrix based on the orientation specified by order.
+    </div>
+
+    <h3>.setFromQuaternion( [page:Quaternion q], [page:String order] ) [page:this]</h3>
+    <div>
+    q -- [page:Quaternion] quaternion must be normalized<br />
+    order -- [page:string] Order of axes, defaults to 'XYZ' (must be upper case)
+    </div>
+    <div>
+    Sets the angles of this euler transform from a normalized quaternion based on the orientation specified by order.
+    </div>
+
+    <h3>.reorder( [page:String newOrder] ) [page:this]</h3>
+    <div>
+    Resets the euler angle with a new order by creating a quaternion from this euler angle and then setting this euler angle with the quaternion and the new order. <br />
+    WARNING: this discards revolution information.
+    </div>
+
+    <h3>.fromArray([page:Array array]) [page:this]</h3>
+    <div>
+    array -- [page:Array] of length 3 or 4. array[3] is an optional order argument.
+    </div>
+    <div>
+    Assigns this euler's x angle to array[0]. <br />
+    Assigns this euler's y angle to array[1]. <br />
+    Assigns this euler's z angle to array[2]. <br />
+    Optionally assigns this euler's order to array[3].
+    </div>
+
+    <h3>.toArray() [page:Array]</h3>
+    <div>
+    Returns an array [x, y, z, order].
+    </div>
+
+    <h3>.equals( [page:Euler euler] ) [page:Boolean]</h3>
+    <div>
+    Checks for strict equality of this euler and *euler*.
+    </div>
+
+    <h3>.clone() [page:Euler]</h3>
+    <div>
+    Returns a new euler created from this euler.
+    </div>
+
+
+
+
+    <h2>Source</h2>
+
+    [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+  </body>
+</html>

+ 1 - 1
docs/api/math/Vector2.html

@@ -123,7 +123,7 @@
 		Normalizes this vector and multiplies it by *l*.
 		Normalizes this vector and multiplies it by *l*.
 		</div>
 		</div>
 
 
-		<h3>.equals( [page:Vector2 v] ) [page:Vector2]</h3>
+		<h3>.equals( [page:Vector2 v] ) [page:Boolean]</h3>
 		<div>
 		<div>
 		Checks for strict equality of this vector and *v*.
 		Checks for strict equality of this vector and *v*.
 		</div>
 		</div>

+ 1 - 1
docs/api/textures/Texture.html

@@ -30,7 +30,7 @@
 
 
 		<h3>.[page:Image image]</h3>
 		<h3>.[page:Image image]</h3>
 		<div>
 		<div>
-		An Image object, typically created using the ImageUtils or [page:ImageLoader ImageLoader] classes. The Image object can include an image (e.g., PNG, JPG, GIF, DDS), video (e.g., MP4, OGG/OGV), or set of six images for a cube map.
+		An Image object, typically created using the ImageUtils or [page:ImageLoader ImageLoader] classes. The Image object can include an image (e.g., PNG, JPG, GIF, DDS), video (e.g., MP4, OGG/OGV), or set of six images for a cube map. To use video as a texture you need to have a playing HTML5 video element as a source for your texture image and continuously update this texture as long as video is playing.
 		</div>
 		</div>
 
 
 		<h3>.[page:object mapping]</h3>
 		<h3>.[page:object mapping]</h3>

+ 1 - 1
docs/index.html

@@ -97,7 +97,7 @@
 
 
 		<script src="list.js"></script>
 		<script src="list.js"></script>
 		<script>
 		<script>
-			var REVISION = '60';
+			var REVISION = '61';
 
 
 			var panel = document.getElementById( 'panel' );
 			var panel = document.getElementById( 'panel' );
 			var viewer = document.getElementById( 'viewer' );
 			var viewer = document.getElementById( 'viewer' );

+ 3 - 2
docs/list.js

@@ -40,7 +40,7 @@ var list = {
 			[ "GeometryLoader", "api/loaders/GeometryLoader" ],
 			[ "GeometryLoader", "api/loaders/GeometryLoader" ],
 			[ "ImageLoader", "api/loaders/ImageLoader" ],
 			[ "ImageLoader", "api/loaders/ImageLoader" ],
 			[ "JSONLoader", "api/loaders/JSONLoader" ],
 			[ "JSONLoader", "api/loaders/JSONLoader" ],
-			[ "LoadingMonitor", "api/loaders/LoadingMonitor" ],
+			[ "LoadingManager", "api/loaders/LoadingManager" ],
 			[ "SceneLoader", "api/loaders/SceneLoader" ],
 			[ "SceneLoader", "api/loaders/SceneLoader" ],
 			[ "TextureLoader", "api/loaders/TextureLoader" ],
 			[ "TextureLoader", "api/loaders/TextureLoader" ],
 		],
 		],
@@ -67,6 +67,7 @@ var list = {
 			[ "Box2", "api/math/Box2" ],
 			[ "Box2", "api/math/Box2" ],
 			[ "Box3", "api/math/Box3" ],
 			[ "Box3", "api/math/Box3" ],
 			[ "Color", "api/math/Color" ],
 			[ "Color", "api/math/Color" ],
+			[ "Euler", "api/math/Euler" ],
 			[ "Frustum", "api/math/Frustum" ],
 			[ "Frustum", "api/math/Frustum" ],
 			[ "Math", "api/math/Math" ],
 			[ "Math", "api/math/Math" ],
 			[ "Matrix3", "api/math/Matrix3" ],
 			[ "Matrix3", "api/math/Matrix3" ],
@@ -90,7 +91,6 @@ var list = {
 			[ "MorphAnimMesh", "api/objects/MorphAnimMesh" ],
 			[ "MorphAnimMesh", "api/objects/MorphAnimMesh" ],
 			[ "Particle", "api/objects/Particle" ],
 			[ "Particle", "api/objects/Particle" ],
 			[ "ParticleSystem", "api/objects/ParticleSystem" ],
 			[ "ParticleSystem", "api/objects/ParticleSystem" ],
-			[ "Ribbon", "api/objects/Ribbon" ],
 			[ "SkinnedMesh", "api/objects/SkinnedMesh" ],
 			[ "SkinnedMesh", "api/objects/SkinnedMesh" ],
 			[ "Sprite", "api/objects/Sprite" ]
 			[ "Sprite", "api/objects/Sprite" ]
 
 
@@ -177,6 +177,7 @@ var list = {
 			[ "AxisHelper", "api/extras/helpers/AxisHelper" ],
 			[ "AxisHelper", "api/extras/helpers/AxisHelper" ],
 			[ "CameraHelper", "api/extras/helpers/CameraHelper" ],
 			[ "CameraHelper", "api/extras/helpers/CameraHelper" ],
 			[ "DirectionalLightHelper", "api/extras/helpers/DirectionalLightHelper" ],
 			[ "DirectionalLightHelper", "api/extras/helpers/DirectionalLightHelper" ],
+			[ "GridHelper", "api/extras/helpers/GridHelper" ],
 			[ "HemisphereLightHelper", "api/extras/helpers/HemisphereLightHelper" ],
 			[ "HemisphereLightHelper", "api/extras/helpers/HemisphereLightHelper" ],
 			[ "PointLightHelper", "api/extras/helpers/PointLightHelper" ],
 			[ "PointLightHelper", "api/extras/helpers/PointLightHelper" ],
 			[ "SpotLightHelper", "api/extras/helpers/SpotLightHelper" ]
 			[ "SpotLightHelper", "api/extras/helpers/SpotLightHelper" ]

+ 24 - 15
editor/index.html

@@ -22,66 +22,74 @@
 			}
 			}
 
 
 			button {
 			button {
-
 				position: relative;
 				position: relative;
-
 			}
 			}
 			
 			
-			.menubar {
+			#menubar {
+				position: absolute;
 				background-color: #eee;
 				background-color: #eee;
 				padding: 0px;
 				padding: 0px;
 				margin: 0px;
 				margin: 0px;
 			}
 			}
 
 
-				.menubar .menu {
+				#menubar .menu {
 					float: left;
 					float: left;
 					width: 50px;
 					width: 50px;
 					cursor: pointer;
 					cursor: pointer;
 				}
 				}
 
 
-					.menubar .menu .options {
+					#menubar .menu .options {
 						padding: 5px 0px;
 						padding: 5px 0px;
 						background-color: #fff;
 						background-color: #fff;
 						width: 140px;
 						width: 140px;
 					}
 					}
 
 
-						.menubar .menu .options hr {
+						#menubar .menu .options hr {
 							border-color: #ddd;
 							border-color: #ddd;
 						}
 						}
 
 
-						.menubar .menu .options .option {
+						#menubar .menu .options .option {
 							color: #666;
 							color: #666;
 							background-color: transparent;
 							background-color: transparent;
 							padding: 5px 10px;
 							padding: 5px 10px;
 							margin: 0px !important;
 							margin: 0px !important;
 						}
 						}
 
 
-							.menubar .menu .options .option:hover {
+							#menubar .menu .options .option:hover {
 								color: #fff;
 								color: #fff;
 								background-color: #08f;
 								background-color: #08f;
 							}
 							}
 
 
 
 
-			.sidebar {
+			#sidebar {
+				position: absolute;
 				width: 300px;
 				width: 300px;
 				background-color: #eee;
 				background-color: #eee;
 				overflow: auto;
 				overflow: auto;
 			}
 			}
 
 
-				.sidebar .Panel {
+				#sidebar .Panel {
 					margin-bottom: 10px;
 					margin-bottom: 10px;
 				}
 				}
 
 
-			.toolbar {
+				#sidebar #outliner .type {
+					padding: 2px 4px;
+					font-size: 10px;
+					background-color: #eee;
+					color: #aaa;
+				}
+
+			#toolbar {
+				position: absolute;
 				background-color: #999;
 				background-color: #999;
 				color: #333;
 				color: #333;
 			}
 			}
 			
 			
-				.toolbar .Panel {
+				#toolbar .Panel {
 					padding: 4px;
 					padding: 4px;
 				}
 				}
 
 
-				.toolbar button {
+				#toolbar button {
 					margin-right: 6px;
 					margin-right: 6px;
 				}
 				}
 
 
@@ -139,11 +147,12 @@
 		<script src="js/Sidebar.Object3D.js"></script>
 		<script src="js/Sidebar.Object3D.js"></script>
 		<script src="js/Sidebar.Geometry.js"></script>
 		<script src="js/Sidebar.Geometry.js"></script>
 		<script src="js/Sidebar.Animation.js"></script>
 		<script src="js/Sidebar.Animation.js"></script>
-		<script src="js/Sidebar.Geometry.PlaneGeometry.js"></script>
+		<script src="js/Sidebar.Geometry.CircleGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.CubeGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.CubeGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.CylinderGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.CylinderGeometry.js"></script>
-		<script src="js/Sidebar.Geometry.SphereGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.IcosahedronGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.IcosahedronGeometry.js"></script>
+		<script src="js/Sidebar.Geometry.PlaneGeometry.js"></script>
+		<script src="js/Sidebar.Geometry.SphereGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.TorusGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.TorusGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.TorusKnotGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.TorusKnotGeometry.js"></script>
 		<script src="js/Sidebar.Material.js"></script>
 		<script src="js/Sidebar.Material.js"></script>

+ 95 - 10
editor/js/Editor.js

@@ -12,6 +12,7 @@ var Editor = function () {
 
 
 		transformModeChanged: new SIGNALS.Signal(),
 		transformModeChanged: new SIGNALS.Signal(),
 		snapChanged: new SIGNALS.Signal(),
 		snapChanged: new SIGNALS.Signal(),
+		spaceChanged: new SIGNALS.Signal(),
 		rendererChanged: new SIGNALS.Signal(),
 		rendererChanged: new SIGNALS.Signal(),
 
 
 		sceneGraphChanged: new SIGNALS.Signal(),
 		sceneGraphChanged: new SIGNALS.Signal(),
@@ -71,6 +72,9 @@ Editor.prototype = {
 
 
 		object.traverse( function ( child ) {
 		object.traverse( function ( child ) {
 
 
+			if ( child.geometry !== undefined ) scope.addGeometry( child.geometry );
+			if ( child.material !== undefined ) scope.addMaterial( child.material );
+
 			scope.addHelper( child );
 			scope.addHelper( child );
 
 
 		} );
 		} );
@@ -103,27 +107,21 @@ Editor.prototype = {
 
 
 	},
 	},
 
 
-	addGeometry: function ( geometry  ) {
-
-	},
+	addGeometry: function ( geometry ) {
 
 
-	removeGeometry: function ( geometry  ) {
+		this.geometries[ geometry.uuid ] = geometry;
 
 
 	},
 	},
 
 
 	addMaterial: function ( material ) {
 	addMaterial: function ( material ) {
 
 
-	},
-
-	removeMaterial: function ( material ) {
+		this.materials[ material.uuid ] = material;
 
 
 	},
 	},
 
 
 	addTexture: function ( texture ) {
 	addTexture: function ( texture ) {
 
 
-	},
-
-	removeTexture: function ( texture ) {
+		this.textures[ texture.uuid ] = texture;
 
 
 	},
 	},
 
 
@@ -279,6 +277,93 @@ Editor.prototype = {
 
 
 		this.select( null );
 		this.select( null );
 
 
+	},
+
+	// utils
+
+	getObjectType: function ( object ) {
+
+		var types = {
+
+			'Scene': THREE.Scene,
+			'PerspectiveCamera': THREE.PerspectiveCamera,
+			'AmbientLight': THREE.AmbientLight,
+			'DirectionalLight': THREE.DirectionalLight,
+			'HemisphereLight': THREE.HemisphereLight,
+			'PointLight': THREE.PointLight,
+			'SpotLight': THREE.SpotLight,
+			'Mesh': THREE.Mesh,
+			'Object3D': THREE.Object3D
+
+		};
+
+		for ( var type in types ) {
+
+			if ( object instanceof types[ type ] ) return type;
+
+		}
+
+	},
+
+	getGeometryType: function ( geometry ) {
+
+		var types = {
+
+			'CircleGeometry': THREE.CircleGeometry,
+			'CubeGeometry': THREE.CubeGeometry,
+			'CylinderGeometry': THREE.CylinderGeometry,
+			'ExtrudeGeometry': THREE.ExtrudeGeometry,
+			'IcosahedronGeometry': THREE.IcosahedronGeometry,
+			'LatheGeometry': THREE.LatheGeometry,
+			'OctahedronGeometry': THREE.OctahedronGeometry,
+			'ParametricGeometry': THREE.ParametricGeometry,
+			'PlaneGeometry': THREE.PlaneGeometry,
+			'PolyhedronGeometry': THREE.PolyhedronGeometry,
+			'ShapeGeometry': THREE.ShapeGeometry,
+			'SphereGeometry': THREE.SphereGeometry,
+			'TetrahedronGeometry': THREE.TetrahedronGeometry,
+			'TextGeometry': THREE.TextGeometry,
+			'TorusGeometry': THREE.TorusGeometry,
+			'TorusKnotGeometry': THREE.TorusKnotGeometry,
+			'TubeGeometry': THREE.TubeGeometry,
+			'Geometry': THREE.Geometry,
+			'BufferGeometry': THREE.BufferGeometry
+
+		};
+
+		for ( var type in types ) {
+
+			if ( geometry instanceof types[ type ] ) return type;
+
+		}
+
+	},
+
+	getMaterialType: function ( material ) {
+
+		var types = {
+
+			'LineBasicMaterial': THREE.LineBasicMaterial,
+			'LineDashedMaterial': THREE.LineDashedMaterial,
+			'MeshBasicMaterial': THREE.MeshBasicMaterial,
+			'MeshDepthMaterial': THREE.MeshDepthMaterial,
+			'MeshFaceMaterial': THREE.MeshFaceMaterial,
+			'MeshLambertMaterial': THREE.MeshLambertMaterial,
+			'MeshNormalMaterial': THREE.MeshNormalMaterial,
+			'MeshPhongMaterial': THREE.MeshPhongMaterial,
+			'ParticleBasicMaterial': THREE.ParticleBasicMaterial,
+			'ParticleCanvasMaterial': THREE.ParticleCanvasMaterial,
+			'ShaderMaterial': THREE.ShaderMaterial,
+			'Material': THREE.Material
+
+		};
+
+		for ( var type in types ) {
+
+			if ( material instanceof types[ type ] ) return type;
+
+		}
+
 	}
 	}
 
 
 }
 }

+ 20 - 0
editor/js/Menubar.Add.js

@@ -73,6 +73,26 @@ Menubar.Add = function ( editor ) {
 	} );
 	} );
 	options.add( option );
 	options.add( option );
 
 
+	// add circle
+
+	var option = new UI.Panel();
+	option.setClass( 'option' );
+	option.setTextContent( 'Circle' );
+	option.onClick( function () {
+
+		var radius = 20;
+		var segments = 8;
+
+		var geometry = new THREE.CircleGeometry( radius, segments );
+		var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial() );
+		mesh.name = 'Circle ' + ( ++ meshCount );
+
+		editor.addObject( mesh );
+		editor.select( mesh );
+
+	} );
+	options.add( option );
+
 	// add cylinder
 	// add cylinder
 
 
 	var option = new UI.Panel();
 	var option = new UI.Panel();

+ 1 - 3
editor/js/Menubar.js

@@ -1,8 +1,6 @@
 var Menubar = function ( editor ) {
 var Menubar = function ( editor ) {
 
 
-	var container = new UI.Panel();
-	container.setPosition( 'absolute' );
-	container.setClass( 'menubar' );
+	var container = new UI.Panel().setId( 'menubar' );
 
 
 	container.add( new Menubar.File( editor ) );
 	container.add( new Menubar.File( editor ) );
 	container.add( new Menubar.Edit( editor ) );
 	container.add( new Menubar.Edit( editor ) );

+ 50 - 0
editor/js/Sidebar.Geometry.CircleGeometry.js

@@ -0,0 +1,50 @@
+Sidebar.Geometry.CircleGeometry = function ( signals, object ) {
+
+	var container = new UI.Panel();
+	container.setBorderTop( '1px solid #ccc' );
+	container.setPaddingTop( '10px' );
+
+	var geometry = object.geometry;
+
+	// radius
+
+	var radiusRow = new UI.Panel();
+	var radius = new UI.Number( geometry.radius ).onChange( update );
+
+	radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ).setColor( '#666' ) );
+	radiusRow.add( radius );
+
+	container.add( radiusRow );
+
+	// segments
+
+	var segmentsRow = new UI.Panel();
+	var segments = new UI.Integer( geometry.segments ).onChange( update );
+
+	segmentsRow.add( new UI.Text( 'Segments' ).setWidth( '90px' ).setColor( '#666' ) );
+	segmentsRow.add( segments );
+
+	container.add( segmentsRow );
+
+	//
+
+	function update() {
+
+		delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
+
+		object.geometry.dispose();
+
+		object.geometry = new THREE.CircleGeometry(
+			radius.getValue(),
+			segments.getValue()
+		);
+
+		object.geometry.computeBoundingSphere();
+
+		signals.objectChanged.dispatch( object );
+
+	}
+
+	return container;
+
+}

+ 19 - 39
editor/js/Sidebar.Geometry.js

@@ -2,37 +2,12 @@ Sidebar.Geometry = function ( editor ) {
 
 
 	var signals = editor.signals;
 	var signals = editor.signals;
 
 
-	var geometryClasses = {
-
-		"CircleGeometry": THREE.CircleGeometry,
-		"CubeGeometry": THREE.CubeGeometry,
-		"CylinderGeometry": THREE.CylinderGeometry,
-		"ExtrudeGeometry": THREE.ExtrudeGeometry,
-		"IcosahedronGeometry": THREE.IcosahedronGeometry,
-		"LatheGeometry": THREE.LatheGeometry,
-		"OctahedronGeometry": THREE.OctahedronGeometry,
-		"ParametricGeometry": THREE.ParametricGeometry,
-		"PlaneGeometry": THREE.PlaneGeometry,
-		"PolyhedronGeometry": THREE.PolyhedronGeometry,
-		"ShapeGeometry": THREE.ShapeGeometry,
-		"SphereGeometry": THREE.SphereGeometry,
-		"TetrahedronGeometry": THREE.TetrahedronGeometry,
-		"TextGeometry": THREE.TextGeometry,
-		"TorusGeometry": THREE.TorusGeometry,
-		"TorusKnotGeometry": THREE.TorusKnotGeometry,
-		"TubeGeometry": THREE.TubeGeometry,
-		"Geometry": THREE.Geometry,
-		"BufferGeometry": THREE.BufferGeometry
-
-	};
-
 	var container = new UI.Panel();
 	var container = new UI.Panel();
 	container.setBorderTop( '1px solid #ccc' );
 	container.setBorderTop( '1px solid #ccc' );
 	container.setPadding( '10px' );
 	container.setPadding( '10px' );
 	container.setDisplay( 'none' );
 	container.setDisplay( 'none' );
 
 
-	var objectType = new UI.Text().setColor( '#666' ).setTextTransform( 'uppercase' );
-	container.add( objectType );
+	container.add( new UI.Text().setValue( 'GEOMETRY' ).setColor( '#666' ) );
 	container.add( new UI.Break(), new UI.Break() );
 	container.add( new UI.Break(), new UI.Break() );
 
 
 	// uuid
 	// uuid
@@ -62,6 +37,16 @@ Sidebar.Geometry = function ( editor ) {
 
 
 	container.add( geometryNameRow );
 	container.add( geometryNameRow );
 
 
+	// class
+
+	var geometryTypeRow = new UI.Panel();
+	var geometryType = new UI.Text().setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' );
+
+	geometryTypeRow.add( new UI.Text( 'Class' ).setWidth( '90px' ).setColor( '#666' ) );
+	geometryTypeRow.add( geometryType );
+
+	container.add( geometryTypeRow );
+
 	// vertices
 	// vertices
 
 
 	var geometryVerticesRow = new UI.Panel();
 	var geometryVerticesRow = new UI.Panel();
@@ -108,7 +93,7 @@ Sidebar.Geometry = function ( editor ) {
 
 
 			container.setDisplay( 'block' );
 			container.setDisplay( 'block' );
 
 
-			objectType.setValue( getGeometryInstanceName( object.geometry ) );
+			geometryType.setValue( editor.getGeometryType( object.geometry ) );
 
 
 			updateFields( geometry );
 			updateFields( geometry );
 
 
@@ -121,9 +106,9 @@ Sidebar.Geometry = function ( editor ) {
 
 
 			}
 			}
 
 
-			if ( geometry instanceof THREE.PlaneGeometry ) {
+			if ( geometry instanceof THREE.CircleGeometry ) {
 
 
-				parameters = new Sidebar.Geometry.PlaneGeometry( signals, object );
+				parameters = new Sidebar.Geometry.CircleGeometry( signals, object );
 				container.add( parameters );
 				container.add( parameters );
 
 
 			} else if ( geometry instanceof THREE.CubeGeometry ) {
 			} else if ( geometry instanceof THREE.CubeGeometry ) {
@@ -146,6 +131,11 @@ Sidebar.Geometry = function ( editor ) {
 				parameters = new Sidebar.Geometry.IcosahedronGeometry( signals, object );
 				parameters = new Sidebar.Geometry.IcosahedronGeometry( signals, object );
 				container.add( parameters );
 				container.add( parameters );
 
 
+			} else if ( geometry instanceof THREE.PlaneGeometry ) {
+
+				parameters = new Sidebar.Geometry.PlaneGeometry( signals, object );
+				container.add( parameters );
+
 			} else if ( geometry instanceof THREE.TorusGeometry ) {
 			} else if ( geometry instanceof THREE.TorusGeometry ) {
 
 
 				parameters = new Sidebar.Geometry.TorusGeometry( signals, object );
 				parameters = new Sidebar.Geometry.TorusGeometry( signals, object );
@@ -200,16 +190,6 @@ Sidebar.Geometry = function ( editor ) {
 
 
 	}
 	}
 
 
-	function getGeometryInstanceName( geometry ) {
-
-		for ( var key in geometryClasses ) {
-
-			if ( geometry instanceof geometryClasses[ key ] ) return key;
-
-		}
-
-	}
-
 	return container;
 	return container;
 
 
 }
 }

+ 31 - 1
editor/js/Sidebar.Material.js

@@ -244,6 +244,23 @@ Sidebar.Material = function ( editor ) {
 	container.add( materialBlendingRow );
 	container.add( materialBlendingRow );
 
 
 
 
+	// side
+
+	var materialSideRow = new UI.Panel();
+	var materialSide = new UI.Select().setOptions( {
+
+		0: 'Front',
+		1: 'Back',
+		2: 'Double'
+
+	} ).setWidth( '150px' ).setColor( '#444' ).setFontSize( '12px' ).onChange( update );
+
+	materialSideRow.add( new UI.Text( 'Side' ).setWidth( '90px' ).setColor( '#666' ) );
+	materialSideRow.add( materialSide );
+
+	container.add( materialSideRow );
+
+
 	// opacity
 	// opacity
 
 
 	var materialOpacityRow = new UI.Panel();
 	var materialOpacityRow = new UI.Panel();
@@ -306,7 +323,7 @@ Sidebar.Material = function ( editor ) {
 
 
 			}
 			}
 
 
-			if ( material instanceof materialClasses[ materialClass.getValue() ] == false ) {
+			if ( material instanceof materialClasses[ materialClass.getValue() ] === false ) {
 
 
 				material = new materialClasses[ materialClass.getValue() ]();
 				material = new materialClasses[ materialClass.getValue() ]();
 				object.material = material;
 				object.material = material;
@@ -483,6 +500,12 @@ Sidebar.Material = function ( editor ) {
 
 
 			}
 			}
 
 
+			if ( material.side !== undefined ) {
+
+				material.side = parseInt( materialSide.getValue() );
+
+			}
+
 			if ( material.opacity !== undefined ) {
 			if ( material.opacity !== undefined ) {
 
 
 				material.opacity = materialOpacity.getValue();
 				material.opacity = materialOpacity.getValue();
@@ -538,6 +561,7 @@ Sidebar.Material = function ( editor ) {
 			'specularMap': materialSpecularMapRow,
 			'specularMap': materialSpecularMapRow,
 			'envMap': materialEnvMapRow,
 			'envMap': materialEnvMapRow,
 			'blending': materialBlendingRow,
 			'blending': materialBlendingRow,
+			'side': materialSideRow,
 			'opacity': materialOpacityRow,
 			'opacity': materialOpacityRow,
 			'transparent': materialTransparentRow,
 			'transparent': materialTransparentRow,
 			'wireframe': materialWireframeRow
 			'wireframe': materialWireframeRow
@@ -676,6 +700,12 @@ Sidebar.Material = function ( editor ) {
 
 
 			}
 			}
 
 
+			if ( material.side !== undefined ) {
+
+				materialSide.setValue( material.side );
+
+			}
+
 			if ( material.opacity !== undefined ) {
 			if ( material.opacity !== undefined ) {
 
 
 				materialOpacity.setValue( material.opacity );
 				materialOpacity.setValue( material.opacity );

+ 11 - 27
editor/js/Sidebar.Scene.js

@@ -9,7 +9,7 @@ Sidebar.Scene = function ( editor ) {
 	container.add( new UI.Text( 'SCENE' ).setColor( '#666' ) );
 	container.add( new UI.Text( 'SCENE' ).setColor( '#666' ) );
 	container.add( new UI.Break(), new UI.Break() );
 	container.add( new UI.Break(), new UI.Break() );
 
 
-	var outliner = new UI.FancySelect().setWidth( '100%' ).setHeight('140px').setColor( '#444' ).setFontSize( '12px' )
+	var outliner = new UI.FancySelect().setId( 'outliner' ).setWidth( '100%' ).setHeight('140px').setColor( '#444' ).setFontSize( '12px' );
 	outliner.onChange( function () {
 	outliner.onChange( function () {
 
 
 		editor.selectById( parseInt( outliner.getValue() ) );
 		editor.selectById( parseInt( outliner.getValue() ) );
@@ -107,30 +107,6 @@ Sidebar.Scene = function ( editor ) {
 
 
 	//
 	//
 
 
-	var getObjectType = function ( object ) {
-
-		var objects = {
-
-			'Scene': THREE.Scene,
-			'PerspectiveCamera': THREE.PerspectiveCamera,
-			'AmbientLight': THREE.AmbientLight,
-			'DirectionalLight': THREE.DirectionalLight,
-			'HemisphereLight': THREE.HemisphereLight,
-			'PointLight': THREE.PointLight,
-			'SpotLight': THREE.SpotLight,
-			'Mesh': THREE.Mesh,
-			'Object3D': THREE.Object3D
-
-		};
-
-		for ( var type in objects ) {
-
-			if ( object instanceof objects[ type ] ) return type;
-
-		}
-
-	}
-
 	var refreshFogUI = function () {
 	var refreshFogUI = function () {
 
 
 		var type = fogType.getValue();
 		var type = fogType.getValue();
@@ -150,7 +126,7 @@ Sidebar.Scene = function ( editor ) {
 
 
 		var options = {};
 		var options = {};
 
 
-		options[ scene.id ] = scene.name + ' <span style="color: #aaa">- ' + getObjectType( scene ) + '</span>';
+		options[ scene.id ] = '<span class="type">' + editor.getObjectType( scene ) + '</span> ' + scene.name;
 
 
 		( function addObjects( objects, pad ) {
 		( function addObjects( objects, pad ) {
 
 
@@ -158,7 +134,15 @@ Sidebar.Scene = function ( editor ) {
 
 
 				var object = objects[ i ];
 				var object = objects[ i ];
 
 
-				options[ object.id ] = pad + object.name + ' <span style="color: #aaa">- ' + getObjectType( object ) + '</span>';
+				var option = pad + '<span class="type">' + editor.getObjectType( object ) + '</span> ' + object.name;
+
+				if ( object instanceof THREE.Mesh ) {
+
+					option += ' ( ' + object.geometry.name + ', ' + object.material.name + ' ) ';
+
+				}
+
+				options[ object.id ] = option;
 
 
 				addObjects( object.children, pad + '&nbsp;&nbsp;&nbsp;' );
 				addObjects( object.children, pad + '&nbsp;&nbsp;&nbsp;' );
 
 

+ 1 - 3
editor/js/Sidebar.js

@@ -1,8 +1,6 @@
 var Sidebar = function ( editor ) {
 var Sidebar = function ( editor ) {
 
 
-	var container = new UI.Panel();
-	container.setPosition( 'absolute' );
-	container.setClass( 'sidebar' );
+	var container = new UI.Panel().setId( 'sidebar' );
 
 
 	container.add( new Sidebar.Renderer( editor ) );
 	container.add( new Sidebar.Renderer( editor ) );
 	container.add( new Sidebar.Scene( editor ) );
 	container.add( new Sidebar.Scene( editor ) );

+ 6 - 3
editor/js/Toolbar.js

@@ -2,9 +2,7 @@ var Toolbar = function ( editor ) {
 
 
 	var signals = editor.signals;
 	var signals = editor.signals;
 
 
-	var container = new UI.Panel();
-	container.setPosition( 'absolute' );
-	container.setClass( 'toolbar' );
+	var container = new UI.Panel().setId( 'toolbar' );
 
 
 	var buttons = new UI.Panel();
 	var buttons = new UI.Panel();
 	container.add( buttons );
 	container.add( buttons );
@@ -43,9 +41,14 @@ var Toolbar = function ( editor ) {
 	buttons.add( snap );
 	buttons.add( snap );
 	buttons.add( new UI.Text( 'snap' ) );
 	buttons.add( new UI.Text( 'snap' ) );
 
 
+	var local = new UI.Checkbox( false ).onChange( update );
+	buttons.add( local );
+	buttons.add( new UI.Text( 'local' ) );
+
 	function update() {
 	function update() {
 
 
 		signals.snapChanged.dispatch( snap.getValue() === true ? grid.getValue() : null );
 		signals.snapChanged.dispatch( snap.getValue() === true ? grid.getValue() : null );
+		signals.spaceChanged.dispatch( local.getValue() === true ? "local" : "world" );
 
 
 	}
 	}
 
 

+ 41 - 39
editor/js/Viewport.js

@@ -43,13 +43,13 @@ var Viewport = function ( editor ) {
 	var transformControls = new THREE.TransformControls( camera, container.dom );
 	var transformControls = new THREE.TransformControls( camera, container.dom );
 	transformControls.addEventListener( 'change', function () {
 	transformControls.addEventListener( 'change', function () {
 
 
-		// TODO: Differentiate from transform hovers change and object transform change
-
-		signals.objectChanged.dispatch( editor.selected );
+        controls.enabled = true;
+        if ( transformControls.axis ) controls.enabled = false;
+        
+		if (editor.selected) signals.objectChanged.dispatch( editor.selected );
 
 
 	} );
 	} );
-	sceneHelpers.add( transformControls.gizmo );
-	transformControls.hide();
+	sceneHelpers.add( transformControls );
 
 
 	// fog
 	// fog
 
 
@@ -68,11 +68,10 @@ var Viewport = function ( editor ) {
 
 
 	var getIntersects = function ( event, object ) {
 	var getIntersects = function ( event, object ) {
 
 
-		var vector = new THREE.Vector3(
-			( event.layerX / container.dom.offsetWidth ) * 2 - 1,
-			- ( event.layerY / container.dom.offsetHeight ) * 2 + 1,
-			0.5
-		);
+	    var rect = container.dom.getBoundingClientRect();
+	    x = (event.clientX - rect.left) / rect.width;
+	    y = (event.clientY - rect.top) / rect.height;
+		var vector = new THREE.Vector3( ( x ) * 2 - 1, - ( y ) * 2 + 1, 0.5 );
 
 
 		projector.unprojectVector( vector, camera );
 		projector.unprojectVector( vector, camera );
 
 
@@ -95,22 +94,23 @@ var Viewport = function ( editor ) {
 
 
 		event.preventDefault();
 		event.preventDefault();
 
 
-		onMouseDownPosition.set( event.layerX, event.layerY );
-
-		if ( transformControls.hovered === false ) {
+	    var rect = container.dom.getBoundingClientRect();
+	    x = (event.clientX - rect.left) / rect.width;
+	    y = (event.clientY - rect.top) / rect.height;
+		onMouseDownPosition.set( x, y );
 
 
-			controls.enabled = true;
-			document.addEventListener( 'mouseup', onMouseUp, false );
-
-		}
+		document.addEventListener( 'mouseup', onMouseUp, false );
 
 
 	};
 	};
 
 
 	var onMouseUp = function ( event ) {
 	var onMouseUp = function ( event ) {
 
 
-		onMouseUpPosition.set( event.layerX, event.layerY );
+	    var rect = container.dom.getBoundingClientRect();
+	    x = (event.clientX - rect.left) / rect.width;
+	    y = (event.clientY - rect.top) / rect.height;
+		onMouseUpPosition.set( x, y );
 
 
-		if ( onMouseDownPosition.distanceTo( onMouseUpPosition ) < 1 ) {
+		if ( onMouseDownPosition.distanceTo( onMouseUpPosition ) == 0 ) {
 
 
 			var intersects = getIntersects( event, objects );
 			var intersects = getIntersects( event, objects );
 
 
@@ -140,8 +140,6 @@ var Viewport = function ( editor ) {
 
 
 		}
 		}
 
 
-		controls.enabled = false;
-
 		document.removeEventListener( 'mouseup', onMouseUp );
 		document.removeEventListener( 'mouseup', onMouseUp );
 
 
 	};
 	};
@@ -171,26 +169,24 @@ var Viewport = function ( editor ) {
 		signals.objectChanged.dispatch( camera );
 		signals.objectChanged.dispatch( camera );
 
 
 	} );
 	} );
-	controls.enabled = false;
 
 
 	// signals
 	// signals
 
 
 	signals.transformModeChanged.add( function ( mode ) {
 	signals.transformModeChanged.add( function ( mode ) {
 
 
 		transformControls.setMode( mode );
 		transformControls.setMode( mode );
-		render();
 
 
 	} );
 	} );
 
 
 	signals.snapChanged.add( function ( dist ) {
 	signals.snapChanged.add( function ( dist ) {
 
 
-		transformControls.snapDist = dist;
+		transformControls.setSnap( dist );
 
 
 	} );
 	} );
 
 
-	signals.snapChanged.add( function ( dist ) {
+	signals.spaceChanged.add( function ( space ) {
 
 
-		snapDist = dist;
+		transformControls.setSpace( space );
 
 
 	} );
 	} );
 
 
@@ -245,20 +241,18 @@ var Viewport = function ( editor ) {
 
 
 	signals.objectAdded.add( function ( object ) {
 	signals.objectAdded.add( function ( object ) {
 
 
-		if ( object instanceof THREE.Light ) {
-
-			updateMaterials();
-
-		}
-
-		objects.push( object );
+		var materialsNeedUpdate = false;
 
 
 		object.traverse( function ( child ) {
 		object.traverse( function ( child ) {
 
 
+			if ( child instanceof THREE.Light ) materialsNeedUpdate = true;
+
 			objects.push( child );
 			objects.push( child );
 
 
 		} );
 		} );
 
 
+		if ( materialsNeedUpdate === true ) updateMaterials();
+
 	} );
 	} );
 
 
 	signals.objectChanged.add( function ( object ) {
 	signals.objectChanged.add( function ( object ) {
@@ -289,13 +283,17 @@ var Viewport = function ( editor ) {
 
 
 	signals.objectRemoved.add( function ( object ) {
 	signals.objectRemoved.add( function ( object ) {
 
 
-		if ( object instanceof THREE.Light ) {
+		var materialsNeedUpdate = false;
 
 
-			updateMaterials();
+		object.traverse( function ( child ) {
 
 
-		}
+			if ( child instanceof THREE.Light ) materialsNeedUpdate = true;
+
+			objects.splice( objects.indexOf( child ), 1 );
+
+		} );
 
 
-		objects.splice( objects.indexOf( object ), 1 );
+		if ( materialsNeedUpdate === true ) updateMaterials();
 
 
 	} );
 	} );
 
 
@@ -390,12 +388,14 @@ var Viewport = function ( editor ) {
 	signals.playAnimations.add( function (animations) {
 	signals.playAnimations.add( function (animations) {
 		
 		
 		function animate() {
 		function animate() {
+
 			requestAnimationFrame( animate );
 			requestAnimationFrame( animate );
 			
 			
-			for (var i = 0; i < animations.length ; i++ ){
+			for ( var i = 0; i < animations.length ; i ++ ) {
+
 				animations[i].update(0.016);
 				animations[i].update(0.016);
-			} 
 
 
+			} 
 
 
 			render();
 			render();
 		}
 		}
@@ -523,6 +523,8 @@ var Viewport = function ( editor ) {
 		renderer.render( scene, camera );
 		renderer.render( scene, camera );
 		renderer.render( sceneHelpers, camera );
 		renderer.render( sceneHelpers, camera );
 
 
+		//console.trace();
+
 	}
 	}
 
 
 	return container;
 	return container;

+ 8 - 0
editor/js/libs/ui.js

@@ -4,6 +4,14 @@ UI.Element = function () {};
 
 
 UI.Element.prototype = {
 UI.Element.prototype = {
 
 
+	setId: function ( id ) {
+
+		this.dom.id = id;
+		
+		return this;
+
+	},
+
 	setClass: function ( name ) {
 	setClass: function ( name ) {
 
 
 		this.dom.className = name;
 		this.dom.className = name;

+ 2 - 1
examples/canvas_lines_colors.html

@@ -76,7 +76,8 @@
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
-				renderer = new THREE.CanvasRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: false } );
+				renderer = new THREE.CanvasRenderer( { antialias: false } );
+				renderer.setClearColor( 0x000000, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 37 - 6
examples/index.html

@@ -85,6 +85,21 @@
 
 
 			}
 			}
 
 
+			#button {
+				position: fixed;
+				top: 20px;
+				right: 20px;
+				padding: 8px;
+				color: #fff;
+				background-color: #555;
+				opacity: 0.7;
+			}
+
+				#button:hover {
+					cursor: pointer;
+					opacity: 1;
+				}
+
 		</style>
 		</style>
 	</head>
 	</head>
 	<body>
 	<body>
@@ -113,7 +128,6 @@
 				"webgl_custom_attributes_particles",
 				"webgl_custom_attributes_particles",
 				"webgl_custom_attributes_particles2",
 				"webgl_custom_attributes_particles2",
 				"webgl_custom_attributes_particles3",
 				"webgl_custom_attributes_particles3",
-				"webgl_custom_attributes_ribbons",
 				"webgl_geometries",
 				"webgl_geometries",
 				"webgl_geometries2",
 				"webgl_geometries2",
 				"webgl_geometry_colors",
 				"webgl_geometry_colors",
@@ -205,6 +219,7 @@
 				"webgl_materials_texture_manualmipmap",
 				"webgl_materials_texture_manualmipmap",
 				"webgl_materials_video",
 				"webgl_materials_video",
 				"webgl_materials_wireframe",
 				"webgl_materials_wireframe",
+				"webgl_mirror",
 				"webgl_morphnormals",
 				"webgl_morphnormals",
 				"webgl_morphtargets",
 				"webgl_morphtargets",
 				"webgl_morphtargets_horse",
 				"webgl_morphtargets_horse",
@@ -233,7 +248,6 @@
 				"webgl_postprocessing_dof",
 				"webgl_postprocessing_dof",
 				"webgl_postprocessing_dof2",
 				"webgl_postprocessing_dof2",
 				"webgl_postprocessing_godrays",
 				"webgl_postprocessing_godrays",
-				"webgl_ribbons",
 				"webgl_rtt",
 				"webgl_rtt",
 				"webgl_sandbox",
 				"webgl_sandbox",
 				"webgl_shader",
 				"webgl_shader",
@@ -328,8 +342,22 @@
 		var container = document.createElement( 'div' );
 		var container = document.createElement( 'div' );
 		list.appendChild( container );
 		list.appendChild( container );
 
 
+		var button = document.createElement( 'div' );
+		button.id = 'button';
+		button.textContent = 'View source';
+		button.addEventListener( 'click', function ( event ) {
+
+			var array = location.href.split( '/' );
+			array.pop();
+
+			window.open( 'view-source:' + array.join( '/' ) + '/' + selected + '.html' );
+
+		}, false );
+		button.style.display = 'none';
+		document.body.appendChild( button );
+
 		var divs = {};
 		var divs = {};
-		var SELECTED = null;
+		var selected = null;
 
 
 		for ( var key in files ) {
 		for ( var key in files ) {
 
 
@@ -367,15 +395,18 @@
 
 
 		var load = function ( file ) {
 		var load = function ( file ) {
 
 
-			if ( SELECTED !== null ) SELECTED.className = 'link';
+			if ( selected !== null ) divs[ selected ].className = 'link';
 
 
-			SELECTED = divs[ file ];
-			SELECTED.className = 'link selected';
+			divs[ file ].className = 'link selected';
 
 
 			window.location.hash = file;
 			window.location.hash = file;
 			viewer.src = file + '.html';
 			viewer.src = file + '.html';
 			viewer.focus();
 			viewer.focus();
 
 
+			button.style.display = '';
+
+			selected = file;
+
 		};
 		};
 
 
 		if ( window.location.hash !== '' ) {
 		if ( window.location.hash !== '' ) {

+ 1 - 1
examples/js/Detector.js

@@ -6,7 +6,7 @@
 var Detector = {
 var Detector = {
 
 
 	canvas: !! window.CanvasRenderingContext2D,
 	canvas: !! window.CanvasRenderingContext2D,
-	webgl: ( function () { try { return !! window.WebGLRenderingContext && !! document.createElement( '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,
 	workers: !! window.Worker,
 	fileapi: window.File && window.FileReader && window.FileList && window.Blob,
 	fileapi: window.File && window.FileReader && window.FileList && window.Blob,
 
 

+ 296 - 0
examples/js/Mirror.js

@@ -0,0 +1,296 @@
+/**
+ * @author Slayvin / http://slayvin.net
+ */
+
+THREE.ShaderLib['mirror'] = {
+
+	uniforms: { "mirrorColor": { type: "c", value: new THREE.Color(0x7F7F7F) },
+				"mirrorSampler": { type: "t", value: null },
+				"textureMatrix" : { type: "m4", value: new THREE.Matrix4() }
+	},
+
+	vertexShader: [
+
+		"uniform mat4 textureMatrix;",
+
+		"varying vec4 mirrorCoord;",
+
+		"void main() {",
+
+			"vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
+			"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+			"mirrorCoord = textureMatrix * worldPosition;",
+
+			"gl_Position = projectionMatrix * mvPosition;",
+
+		"}"
+
+	].join("\n"),
+
+	fragmentShader: [
+
+		"uniform vec3 mirrorColor;",
+		"uniform sampler2D mirrorSampler;",
+
+		"varying vec4 mirrorCoord;",
+
+		"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);",
+			"color = vec4(blendOverlay(mirrorColor.r, color.r), blendOverlay(mirrorColor.g, color.g), blendOverlay(mirrorColor.b, color.b), 1.0);",
+
+			"gl_FragColor = color;",
+
+		"}"
+
+	].join("\n")
+
+};
+
+THREE.Mirror = function ( renderer, camera, options ) {
+
+	THREE.Object3D.call( this );
+
+	this.name = 'mirror_' + this.id;
+
+	function isPowerOfTwo ( value ) {
+		return ( value & ( value - 1 ) ) === 0;
+	};
+
+	options = options || {};
+
+	this.matrixNeedsUpdate = true;
+
+	var width = options.textureWidth !== undefined ? options.textureWidth : 512;
+	var height = options.textureHeight !== undefined ? options.textureHeight : 512;
+
+	this.clipBias = options.clipBias !== undefined ? options.clipBias : 0.0;
+
+	var mirrorColor = options.color !== undefined ? new THREE.Color(options.color) : new THREE.Color(0x7F7F7F);
+
+	this.renderer = renderer;
+	this.mirrorPlane = new THREE.Plane();
+	this.normal = new THREE.Vector3( 0, 0, 1 );
+	this.mirrorWorldPosition = new THREE.Vector3();
+	this.cameraWorldPosition = new THREE.Vector3();
+	this.rotationMatrix = new THREE.Matrix4();
+	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 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( planeGeometry.vertices[0] );
+		var plane = new THREE.Line( planeGeometry, new THREE.LineBasicMaterial( { color: 0xffff80 } ) );
+
+		this.add(arrow);
+		this.add(plane);
+
+	}
+
+	if ( camera instanceof THREE.PerspectiveCamera ) {
+
+		this.camera = camera;
+
+	} else {
+
+		this.camera = new THREE.PerspectiveCamera();
+		console.log( this.name + ': camera is not a Perspective Camera!' );
+
+	}
+
+	this.textureMatrix = new THREE.Matrix4();
+
+	this.mirrorCamera = this.camera.clone();
+
+	this.texture = new THREE.WebGLRenderTarget( width, height );
+	this.tempTexture = new THREE.WebGLRenderTarget( width, height );
+
+	var mirrorShader = THREE.ShaderLib[ "mirror" ];
+	var mirrorUniforms = THREE.UniformsUtils.clone( mirrorShader.uniforms );
+
+	this.material = new THREE.ShaderMaterial( {
+
+		fragmentShader: mirrorShader.fragmentShader,
+		vertexShader: mirrorShader.vertexShader,
+		uniforms: mirrorUniforms
+
+	} );
+
+	this.material.uniforms.mirrorSampler.value = this.texture;
+	this.material.uniforms.mirrorColor.value = mirrorColor;
+	this.material.uniforms.textureMatrix.value = this.textureMatrix;
+
+	if ( !isPowerOfTwo(width) || !isPowerOfTwo( height ) ) {
+
+		this.texture.generateMipmaps = false;
+		this.tempTexture.generateMipmaps = false;
+
+	}
+
+	this.updateTextureMatrix();
+	this.render();
+
+};
+
+THREE.Mirror.prototype = Object.create( THREE.Object3D.prototype );
+
+THREE.Mirror.prototype.renderWithMirror = function ( otherMirror ) {
+
+	// update the mirror matrix to mirror the current view
+	this.updateTextureMatrix();
+	this.matrixNeedsUpdate = false;
+
+	// set the camera of the other mirror so the mirrored view is the reference view
+	var tempCamera = otherMirror.camera;
+	otherMirror.camera = this.mirrorCamera;
+
+	// render the other mirror in temp texture
+	otherMirror.renderTemp();
+	otherMirror.material.uniforms.mirrorSampler.value = otherMirror.tempTexture;
+
+	// render the current mirror
+	this.render();
+	this.matrixNeedsUpdate = true;
+
+	// restore material and camera of other mirror
+	otherMirror.material.uniforms.mirrorSampler.value = otherMirror.texture;
+	otherMirror.camera = tempCamera;
+
+	// restore texture matrix of other mirror
+	otherMirror.updateTextureMatrix();
+};
+
+THREE.Mirror.prototype.updateTextureMatrix = function () {
+
+	var sign = THREE.Math.sign;
+
+	this.updateMatrixWorld();
+	this.camera.updateMatrixWorld();
+
+	this.mirrorWorldPosition.getPositionFromMatrix( this.matrixWorld );
+	this.cameraWorldPosition.getPositionFromMatrix( this.camera.matrixWorld );
+
+	this.rotationMatrix.extractRotation( this.matrixWorld );
+
+	this.normal.set( 0, 0, 1 );
+	this.normal.applyMatrix4( this.rotationMatrix );
+
+	var view = this.mirrorWorldPosition.clone().sub( this.cameraWorldPosition );
+	var reflectView = view.reflect( this.normal );
+	reflectView.add( this.mirrorWorldPosition );
+
+	this.rotationMatrix.extractRotation( this.camera.matrixWorld );
+
+	this.lookAtPosition.set(0, 0, -1);
+	this.lookAtPosition.applyMatrix4( this.rotationMatrix );
+	this.lookAtPosition.add( this.cameraWorldPosition );
+
+	var target = this.mirrorWorldPosition.clone().sub( this.lookAtPosition );
+	var reflectTarget = target.reflect( this.normal );
+	reflectTarget.add( this.mirrorWorldPosition );
+
+	this.up.set( 0, -1, 0 );
+	this.up.applyMatrix4( this.rotationMatrix );
+	var reflectUp = this.up.reflect( this.normal );
+
+	this.mirrorCamera.position.copy(reflectView);
+	this.mirrorCamera.up = reflectUp;
+	this.mirrorCamera.lookAt( reflectTarget );
+
+	this.mirrorCamera.updateProjectionMatrix();
+	this.mirrorCamera.updateMatrixWorld();
+	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 );
+
+	// 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.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];
+
+	// Calculate the scaled plane vector
+	var c = new THREE.Vector4();
+	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;
+
+};
+
+THREE.Mirror.prototype.render = function () {
+
+	if ( this.matrixNeedsUpdate ) this.updateTextureMatrix();
+
+	this.matrixNeedsUpdate = true;
+
+	// Render the mirrored view of the current scene into the target texture
+	var scene = this;
+
+	while ( scene.parent !== undefined ) {
+
+		scene = scene.parent;
+
+	}
+
+	if ( scene !== undefined && scene instanceof THREE.Scene) {
+
+		this.renderer.render( scene, this.mirrorCamera, this.texture, true );
+
+	}
+
+};
+
+THREE.Mirror.prototype.renderTemp = function () {
+
+	if ( this.matrixNeedsUpdate ) this.updateTextureMatrix();
+
+	this.matrixNeedsUpdate = true;
+
+	// Render the mirrored view of the current scene into the target texture
+	var scene = this;
+
+	while ( scene.parent !== undefined ) {
+
+		scene = scene.parent;
+
+	}
+
+	if ( scene !== undefined && scene instanceof THREE.Scene) {
+
+		this.renderer.render( scene, this.mirrorCamera, this.tempTexture, true );
+
+	}
+
+};

+ 52 - 20
examples/js/controls/EditorControls.js

@@ -23,6 +23,8 @@ THREE.EditorControls = function ( object, domElement ) {
 
 
 	var center = new THREE.Vector3();
 	var center = new THREE.Vector3();
 	var normalMatrix = new THREE.Matrix3();
 	var normalMatrix = new THREE.Matrix3();
+	var pointer = new THREE.Vector2();
+	var pointerOld = new THREE.Vector2();
 
 
 	// events
 	// events
 
 
@@ -114,6 +116,8 @@ THREE.EditorControls = function ( object, domElement ) {
 
 
 		}
 		}
 
 
+		pointerOld.set( event.clientX, event.clientY );
+
 		domElement.addEventListener( 'mousemove', onMouseMove, false );
 		domElement.addEventListener( 'mousemove', onMouseMove, false );
 		domElement.addEventListener( 'mouseup', onMouseUp, false );
 		domElement.addEventListener( 'mouseup', onMouseUp, false );
 		domElement.addEventListener( 'mouseout', onMouseUp, false );
 		domElement.addEventListener( 'mouseout', onMouseUp, false );
@@ -126,8 +130,10 @@ THREE.EditorControls = function ( object, domElement ) {
 
 
 		event.preventDefault();
 		event.preventDefault();
 
 
-		var movementX = event.movementX || event.webkitMovementX || event.mozMovementX || event.oMovementX || 0;
-		var movementY = event.movementY || event.webkitMovementY || event.mozMovementY || event.oMovementY || 0;
+		pointer.set( event.clientX, event.clientY );
+
+		var movementX = pointer.x - pointerOld.x;
+		var movementY = pointer.y - pointerOld.y;
 
 
 		if ( state === STATE.ROTATE ) {
 		if ( state === STATE.ROTATE ) {
 
 
@@ -143,6 +149,8 @@ THREE.EditorControls = function ( object, domElement ) {
 
 
 		}
 		}
 
 
+		pointerOld.set( event.clientX, event.clientY );
+
 	}
 	}
 
 
 	function onMouseUp( event ) {
 	function onMouseUp( event ) {
@@ -185,29 +193,37 @@ THREE.EditorControls = function ( object, domElement ) {
 	// touch
 	// touch
 
 
 	var touch = new THREE.Vector3();
 	var touch = new THREE.Vector3();
-	var prevTouch = new THREE.Vector3();
+
+	var touches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
+	var prevTouches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
+
 	var prevDistance = null;
 	var prevDistance = null;
 
 
 	function touchStart( event ) {
 	function touchStart( event ) {
 
 
 		if ( scope.enabled === false ) return;
 		if ( scope.enabled === false ) return;
 
 
-		var touches = event.touches;
+		switch ( event.touches.length ) {
 
 
-		switch ( touches.length ) {
+			case 1:
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				break;
 
 
 			case 2:
 			case 2:
-				var dx = touches[ 0 ].pageX - touches[ 1 ].pageX;
-				var dy = touches[ 0 ].pageY - touches[ 1 ].pageY;
-				prevDistance = Math.sqrt( dx * dx + dy * dy );
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 );
+				prevDistance = touches[ 0 ].distanceTo( touches[ 1 ] );
 				break;
 				break;
 
 
 		}
 		}
 
 
-		prevTouch.set( touches[ 0 ].pageX, touches[ 0 ].pageY, 0 );
+		prevTouches[ 0 ].copy( touches[ 0 ] );
+		prevTouches[ 1 ].copy( touches[ 1 ] );
 
 
 	}
 	}
 
 
+
 	function touchMove( event ) {
 	function touchMove( event ) {
 
 
 		if ( scope.enabled === false ) return;
 		if ( scope.enabled === false ) return;
@@ -215,31 +231,47 @@ THREE.EditorControls = function ( object, domElement ) {
 		event.preventDefault();
 		event.preventDefault();
 		event.stopPropagation();
 		event.stopPropagation();
 
 
-		var touches = event.touches;
+		var getClosest = function( touch, touches ) {
 
 
-		touch.set( touches[ 0 ].pageX, touches[ 0 ].pageY, 0 );
+			var closest = touches[ 0 ];
 
 
-		switch ( touches.length ) {
+			for ( var i in touches ) {
+				if ( closest.distanceTo(touch) > touches[ i ].distanceTo(touch) ) closest = touches[ i ];
+			}
+
+			return closest;
+
+		}
+
+		switch ( event.touches.length ) {
 
 
 			case 1:
 			case 1:
-				scope.rotate( touch.sub( prevTouch ).multiplyScalar( - 0.005 ) );
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				scope.rotate( touches[ 0 ].sub( getClosest( touches[ 0 ] ,prevTouches ) ).multiplyScalar( - 0.005 ) );
 				break;
 				break;
 
 
 			case 2:
 			case 2:
-				var dx = touches[ 0 ].pageX - touches[ 1 ].pageX;
-				var dy = touches[ 0 ].pageY - touches[ 1 ].pageY;
-				var distance = Math.sqrt( dx * dx + dy * dy );
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 );
+				distance = touches[ 0 ].distanceTo( touches[ 1 ] );
 				scope.zoom( new THREE.Vector3( 0, 0, prevDistance - distance ) );
 				scope.zoom( new THREE.Vector3( 0, 0, prevDistance - distance ) );
 				prevDistance = distance;
 				prevDistance = distance;
-				break;
 
 
-			case 3:
-				scope.pan( touch.sub( prevTouch ).setX( - touch.x ) );
+
+				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;
+
+				scope.pan( offset0.add( offset1 ).multiplyScalar( 0.5 ) );
+
 				break;
 				break;
 
 
 		}
 		}
 
 
-		prevTouch.set( touches[ 0 ].pageX, touches[ 0 ].pageY, 0 );
+		prevTouches[ 0 ].copy( touches[ 0 ] );
+		prevTouches[ 1 ].copy( touches[ 1 ] );
 
 
 	}
 	}
 
 

+ 684 - 638
examples/js/controls/TransformControls.js

@@ -2,946 +2,992 @@
  * @author arodic / https://github.com/arodic
  * @author arodic / https://github.com/arodic
  */
  */
 
 
- //"use strict";
+ "use strict";
 
 
-THREE.TransformControls = function ( camera, domElement, doc ) {
+THREE.TransformGizmoMaterial = function ( parameters ) {
 
 
-	// TODO: Make non-uniform scale and rotate play nice in hierarchies
-	// TODO: ADD RXYZ contol
+	THREE.MeshBasicMaterial.call( this );
 
 
-	this.camera = camera;
-	this.domElement = ( domElement !== undefined ) ? domElement : document;
-	this.document = ( doc !== undefined ) ? doc : document;
+	this.depthTest = false;
+	this.depthWrite = false;
+	this.side = THREE.DoubleSide;
+	this.transparent = true;
 
 
-	this.object = undefined;
+	this.setValues( parameters );
 
 
-	this.active = false;
-	this.hovered = false;
+}
 
 
-	this.mode = 'translate';
-	this.space = 'world';
-	this.scale = 1;
+THREE.TransformGizmoMaterial.prototype = Object.create( THREE.MeshBasicMaterial.prototype );
 
 
-	this.snapDist = null;
-	this.modifierAxis = new THREE.Vector3( 1, 1, 1 );
-	this.gizmo = new THREE.Object3D();
+THREE.TransformGizmo = function () {
 
 
-	var scope = this;
+	this.handleGizmos = {
+		X: [
+			new THREE.Mesh( new THREE.CylinderGeometry( 0.005, 0.005, 1, 4, 1, false ), new THREE.TransformGizmoMaterial( { color: 0xff0000 } ) ),
+			new THREE.Vector3( 0.5, 0, 0 ),
+			new THREE.Vector3( 0, 0, -Math.PI/2 )
+		],
+		Y: [
+			new THREE.Mesh( new THREE.CylinderGeometry( 0.005, 0.005, 1, 4, 1, false ), new THREE.TransformGizmoMaterial( { color: 0x00ff00 } ) ),
+			new THREE.Vector3( 0, 0.5, 0 )
+		],
+		Z: [
+			new THREE.Mesh( new THREE.CylinderGeometry( 0.005, 0.005, 1, 4, 1, false ), new THREE.TransformGizmoMaterial( { color: 0x0000ff } ) ),
+			new THREE.Vector3( 0, 0, 0.5 ),
+			new THREE.Vector3( Math.PI/2, 0, 0 )
+		]
+	}
 
 
-	var changeEvent = { type: 'change' };
+	var showPickers = false; //debug
+	var showActivePlane = false; //debug
 
 
-	var showPickers = false; // debug
+	this.init = function () {
 
 
-	var ray = new THREE.Raycaster();
-	var projector = new THREE.Projector();
-	var pointerVector = new THREE.Vector3();
+		THREE.Object3D.call( this );
 
 
-	var point = new THREE.Vector3();
-	var offset = new THREE.Vector3();
+		this.handles = new THREE.Object3D();
+		this.pickers = new THREE.Object3D();
+		this.planes = new THREE.Object3D();
 
 
-	var rotation = new THREE.Vector3();
-	var offsetRotation = new THREE.Vector3();
-	var scale = 1;
+		this.add(this.handles);
+		this.add(this.pickers);
+		this.add(this.planes);
 
 
-	var lookAtMatrix = new THREE.Matrix4();
-	var eye = new THREE.Vector3()
+		//// PLANES
 
 
-	var tempMatrix = new THREE.Matrix4();
-	var tempVector = new THREE.Vector3();
-	var tempQuaternion = new THREE.Quaternion();
-	var unitX = new THREE.Vector3( 1, 0, 0 );
-	var unitY = new THREE.Vector3( 0, 1, 0 );
-	var unitZ = new THREE.Vector3( 0, 0, 1 );
+		var planeGeometry = new THREE.PlaneGeometry( 50, 50, 2, 2 );
+		var planeMaterial = new THREE.MeshBasicMaterial( { wireframe: true } );
+		planeMaterial.side = THREE.DoubleSide;
 
 
-	var quaternionXYZ = new THREE.Quaternion();
-	var quaternionX = new THREE.Quaternion();
-	var quaternionY = new THREE.Quaternion();
-	var quaternionZ = new THREE.Quaternion();
-	var quaternionE = new THREE.Quaternion();
+		var planes = {
+			"XY": new THREE.Mesh( planeGeometry, planeMaterial ),
+			"YZ": new THREE.Mesh( planeGeometry, planeMaterial ),
+			"XZ": new THREE.Mesh( planeGeometry, planeMaterial ),
+			"XYZE": new THREE.Mesh( planeGeometry, planeMaterial )
+		};
 
 
-	var oldPosition = new THREE.Vector3();
-	var oldScale = new THREE.Vector3();
-	var oldRotationMatrix = new THREE.Matrix4();
+		planes["YZ"].rotation.set( 0, Math.PI/2, 0 );
+		planes["XZ"].rotation.set( -Math.PI/2, 0, 0 );
 
 
-	var parentRotationMatrix  = new THREE.Matrix4();
-	var parentScale = new THREE.Vector3();
+		for (var i in planes) {
+			planes[i].name = i;
+			this.planes.add(planes[i]);
+			this.planes[i] = planes[i];
+			planes[i].visible = false;
+		}
 
 
-	var worldPosition = new THREE.Vector3();
-	var worldRotation = new THREE.Euler();
-	var worldRotationMatrix  = new THREE.Matrix4();
-	var camPosition = new THREE.Vector3();
-	var camRotation = new THREE.Euler();
+		//// HANDLES AND PICKERS
+
+		for ( var i in this.handleGizmos ) {
 
 
-	var displayAxes = {};
-	var pickerAxes = {};
-	var intersectionPlanes = {};
-	var intersectionPlaneList = ['XY','YZ','XZ','XYZE']; // E
-	var currentPlane = 'XY';
+			var handle = this.handleGizmos[i][0];
+			handle.name = i;
+			if ( this.handleGizmos[i][1] ) handle.position.set( this.handleGizmos[i][1].x, this.handleGizmos[i][1].y, this.handleGizmos[i][1].z );
+			if ( this.handleGizmos[i][2] ) handle.rotation.set( this.handleGizmos[i][2].x, this.handleGizmos[i][2].y, this.handleGizmos[i][2].z );
+			
+			this.handles.add( handle );
 
 
-	// intersection planes
-	{
+			if ( this.pickerGizmos && this.pickerGizmos[i] ) {
 
 
-		var planes = new THREE.Object3D();
-		this.gizmo.add(planes);
+				var picker = this.pickerGizmos[i][0];
+				if ( this.pickerGizmos[i][1] ) picker.position.set( this.pickerGizmos[i][1].x, this.pickerGizmos[i][1].y, this.pickerGizmos[i][1].z );
+				if ( this.pickerGizmos[i][2] ) picker.rotation.set( this.pickerGizmos[i][2].x, this.pickerGizmos[i][2].y, this.pickerGizmos[i][2].z );
+			
+			} else {
 
 
-		for ( var i in intersectionPlaneList ){
+				var picker = handle.clone();
+
+			}
 
 
-			intersectionPlanes[intersectionPlaneList[i]] = new THREE.Mesh( new THREE.PlaneGeometry( 500, 500 ) );
-			intersectionPlanes[intersectionPlaneList[i]].material.side = THREE.DoubleSide;
-			intersectionPlanes[intersectionPlaneList[i]].visible = false;
-			planes.add(intersectionPlanes[intersectionPlaneList[i]]);
+			picker.name = i;
+			this.pickers.add( picker );
 
 
 		}
 		}
 
 
-		intersectionPlanes['YZ'].rotation.set( 0, Math.PI/2, 0 );
-		intersectionPlanes['XZ'].rotation.set( -Math.PI/2, 0, 0 );
-		bakeTransformations(intersectionPlanes['YZ']);
-		bakeTransformations(intersectionPlanes['XZ']);
+		// reset Transformations
+
+		this.traverse(function (child) {
+			if (child instanceof THREE.Mesh) {			
+				var tempGeometry = new THREE.Geometry();
+				THREE.GeometryUtils.merge( tempGeometry, child );
+				child.geometry = tempGeometry;
+				child.position.set( 0, 0, 0 );
+				child.rotation.set( 0, 0, 0 );
+				child.scale.set( 1, 1, 1 );
+
+			}
+		});
 
 
 	}
 	}
 
 
-	// gizmo geometry
-	{
-
-		displayAxes["translate"] = new THREE.Object3D();
-		displayAxes["rotate"] = new THREE.Object3D();
-		displayAxes["scale"] = new THREE.Object3D();
-		this.gizmo.add( displayAxes["translate"] );
-		this.gizmo.add( displayAxes["rotate"] );
-		this.gizmo.add( displayAxes["scale"] );
-
-		pickerAxes["translate"] = new THREE.Object3D();
-		pickerAxes["rotate"] = new THREE.Object3D();
-		pickerAxes["scale"] = new THREE.Object3D();
-		this.gizmo.add( pickerAxes["translate"] );
-		this.gizmo.add( pickerAxes["rotate"] );
-		this.gizmo.add( pickerAxes["scale"] );
-
-		var HandleMaterial = function ( color, opacity ) {
-			var material = new THREE.MeshBasicMaterial();
-			material.color = color;
-			material.side = THREE.DoubleSide;
-			material.depthTest = false;
-			material.depthWrite = false;
-			material.opacity = opacity !== undefined ? opacity : 1;
-			material.transparent = true;
-			return material;
-		}
+	this.hide = function () {
+
+		for ( var j in this.handles.children ) this.handles.children[j].visible = false;
+
+		for ( var j in this.pickers.children ) this.pickers.children[j].visible = false;
+
+		for ( var j in this.planes.children ) this.planes.children[j].visible = false;
+
+	}
+
+	this.show = function () {
+
+		for ( var i in this.handles.children ) {
+
+			this.handles.children[i].visible = true;
 
 
-		var LineMaterial = function ( color, opacity ) {
-			var material = new THREE.LineBasicMaterial();
-			material.color = color;
-			material.depthTest = false;
-			material.depthWrite = false;
-			material.opacity = opacity !== undefined ? opacity : 1;
-			material.transparent = true;
-			return material;
 		}
 		}
 
 
-		// materials by color
-		var white = new THREE.Color( 0xffffff );
-		var gray = new THREE.Color( 0x808080 );
-		var red = new THREE.Color( 0xff0000 );
-		var green = new THREE.Color( 0x00ff00 );
-		var blue = new THREE.Color( 0x0000ff );
-		var cyan = new THREE.Color( 0x00ffff );
-		var magenta = new THREE.Color( 0xff00ff );
-		var yellow = new THREE.Color( 0xffff00 );
-
-		var geometry, mesh;
-
-		// Line axes
-
-		geometry = new THREE.Geometry();
-		geometry.vertices.push(
-			new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 1, 0, 0 ),
-			new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 1, 0 ),
-			new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, 1 )
-		);
-		geometry.colors.push(
-			red, red, green, green, blue, blue
-		);
-		material = new THREE.LineBasicMaterial( {
-			vertexColors: THREE.VertexColors,
-			depthTest: false,
-			depthWrite: false,
-			transparent: true
-		} );
-		mesh = new THREE.Line( geometry, material, THREE.LinePieces );
-		displayAxes['translate'].add( mesh );
-		displayAxes['scale'].add( mesh.clone() );
-
-		// Translate handles
-
-		mesh = new THREE.Mesh( new THREE.OctahedronGeometry( 0.1, 0 ), HandleMaterial( white, 0.25 ) );
-		mesh.name = 'TXYZ';
-		displayAxes['translate'].add( mesh );
-		pickerAxes['translate'].add( mesh.clone() );
-
-		geometry = new THREE.PlaneGeometry( 0.3, 0.3 );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( yellow, 0.25 ) );
-		mesh.position.set( 0.15, 0.15, 0 );
-		bakeTransformations( mesh );
-		mesh.name = 'TXY';
-		displayAxes['translate'].add( mesh );
-		pickerAxes['translate'].add( mesh.clone() );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( cyan, 0.25 ) );
-		mesh.position.set( 0, 0.15, 0.15 );
-		mesh.rotation.y = Math.PI/2;
-		bakeTransformations( mesh );
-		mesh.name = 'TYZ';
-		displayAxes['translate'].add( mesh );
-		pickerAxes['translate'].add( mesh.clone() );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( magenta, 0.25 ) );
-		mesh.position.set( 0.15, 0, 0.15 );
-		mesh.rotation.x = Math.PI/2;
-		bakeTransformations( mesh );
-		mesh.name = 'TXZ';
-		displayAxes['translate'].add( mesh );
-		pickerAxes['translate'].add( mesh.clone() );
-
-		geometry = new THREE.CylinderGeometry( 0, 0.05, 0.2, 4, 1, true );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( red ) );
-		mesh.position.x = 1.1;
-		mesh.rotation.z = -Math.PI/2;
-		bakeTransformations( mesh );
-		mesh.name = 'TX';
-		displayAxes['translate'].add( mesh );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( green ) );
-		mesh.position.y = 1.1;
-		bakeTransformations( mesh );
-		mesh.name = 'TY';
-		displayAxes['translate'].add( mesh );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( blue ) );
-		mesh.position.z = 1.1;
-		mesh.rotation.x = Math.PI/2;
-		bakeTransformations( mesh );
-		mesh.name = 'TZ';
-		displayAxes['translate'].add( mesh );
-
-		geometry = new THREE.CylinderGeometry( 0.2, 0.1, 0.8, 4, 1, false );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( red ) );
-		mesh.position.x = 0.7;
-		mesh.rotation.z = -Math.PI/2;
-		bakeTransformations( mesh );
-		mesh.name = 'TX';
-		pickerAxes['translate'].add( mesh );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( green ) );
-		mesh.position.y = 0.7;
-		bakeTransformations( mesh );
-		mesh.name = 'TY';
-		pickerAxes['translate'].add( mesh );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( blue ) );
-		mesh.position.z = 0.7;
-		mesh.rotation.x = Math.PI/2;
-		bakeTransformations( mesh );
-		mesh.name = 'TZ';
-		pickerAxes['translate'].add( mesh );
-
-		// scale manipulators
-
-		geometry = new THREE.CubeGeometry( 0.125, 0.125, 0.125 );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( white, 0.25 ) );
-		mesh.name = 'SXYZ';
-		displayAxes['scale'].add( mesh );
-		pickerAxes['scale'].add( mesh.clone() );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( red ) );
-		mesh.position.set( 1.05, 0, 0 );
-		bakeTransformations( mesh );
-		mesh.name = 'SX';
-		displayAxes['scale'].add( mesh );
-		pickerAxes['scale'].add( mesh.clone() );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( green ) );
-		mesh.position.set( 0, 1.05, 0 );
-		bakeTransformations( mesh );
-		mesh.name = 'SY';
-		displayAxes['scale'].add( mesh );
-		pickerAxes['scale'].add( mesh.clone() );
-
-		mesh = new THREE.Mesh( geometry, HandleMaterial( blue ) );
-		mesh.position.set( 0, 0, 1.05 );
-		bakeTransformations( mesh );
-		mesh.name = 'SZ';
-		displayAxes['scale'].add( mesh );
-		pickerAxes['scale'].add( mesh.clone() );
-
-		// rotate manipulators
-
-		var Circle = function ( radius, facing, arc ) {
-
-			geometry = new THREE.Geometry();
-			arc = arc ? arc : 1;
-			for ( var i = 0; i <= 64 * arc; ++i ) {
-				if ( facing == 'x' ) geometry.vertices.push( new THREE.Vector3( 0, Math.cos( i / 32 * Math.PI ), Math.sin( i / 32 * Math.PI ) ).multiplyScalar(radius) );
-				if ( facing == 'y' ) geometry.vertices.push( new THREE.Vector3( Math.cos( i / 32 * Math.PI ), 0, Math.sin( i / 32 * Math.PI ) ).multiplyScalar(radius) );
-				if ( facing == 'z' ) geometry.vertices.push( new THREE.Vector3( Math.sin( i / 32 * Math.PI ), Math.cos( i / 32 * Math.PI ), 0 ).multiplyScalar(radius) );
-			}
+		for ( var i in this.pickers.children ) {
+
+			this.pickers.children[i].visible = showPickers;
 
 
-			return geometry;
 		}
 		}
 
 
-		mesh = new THREE.Line( Circle( 1, 'x', 0.5 ), LineMaterial( red ) );
-		mesh.name = 'RX';
-		displayAxes['rotate'].add( mesh );
+		if (this.activePlane) this.activePlane.visible = showActivePlane;
 
 
-		mesh = new THREE.Line( Circle( 1, 'y', 0.5 ), LineMaterial( green ) );
-		mesh.name = 'RY';
-		displayAxes['rotate'].add( mesh );
+	}
 
 
-		mesh = new THREE.Line( Circle( 1, 'z', 0.5 ), LineMaterial( blue ) );
-		mesh.name = 'RZ';
-		displayAxes['rotate'].add( mesh );
+	this.highlight = function ( axis ) {
 
 
-		mesh = new THREE.Line( Circle( 1, 'z' ), LineMaterial( gray ) );
-		mesh.name = 'RXYZE';
-		displayAxes['rotate'].add( mesh );
+		var handle;
 
 
-		mesh = new THREE.Line( Circle( 1.25, 'z' ), LineMaterial( yellow, 0.25 ) );
-		mesh.name = 'RE';
-		displayAxes['rotate'].add( mesh );
+		for ( var i in this.handleGizmos ) {
 
 
-		geometry = new THREE.TorusGeometry( 1, 0.15, 4, 6, Math.PI );
+			handle = this.handleGizmos[ i ][0];
 
 
-		mesh = new THREE.Mesh( geometry, HandleMaterial( red ) );
-		mesh.rotation.z = -Math.PI/2;
-		mesh.rotation.y = -Math.PI/2;
-		bakeTransformations( mesh );
-		mesh.name = 'RX';
-		pickerAxes['rotate'].add( mesh );
+			if ( handle.material.oldColor ) {
 
 
-		mesh = new THREE.Mesh( geometry, HandleMaterial( green ) );
-		mesh.rotation.z = Math.PI;
-		mesh.rotation.x = -Math.PI/2;
-		bakeTransformations( mesh );
-		mesh.name = 'RY';
-		pickerAxes['rotate'].add( mesh );
+				handle.material.color.copy( handle.material.oldColor );
+				handle.material.opacity = handle.material.oldOpacity;
 
 
-		mesh = new THREE.Mesh( geometry, HandleMaterial( blue ) );
-		mesh.rotation.z = -Math.PI/2;
-		bakeTransformations( mesh );
-		mesh.name = 'RZ';
-		pickerAxes['rotate'].add( mesh );
+			}
 
 
-		mesh = new THREE.Mesh( new THREE.SphereGeometry( 0.95, 12, 12 ), HandleMaterial( white, 0.25 ) );
-		mesh.name = 'RXYZE';
-		pickerAxes['rotate'].add( mesh );
+		}
 
 
-		intersectionPlanes['SPHERE'] = new THREE.Mesh( new THREE.SphereGeometry( 0.95, 12, 12 ) );
-		intersectionPlanes['SPHERE'].visible = false;
-		planes.add(intersectionPlanes['SPHERE']);
+		if ( this.handleGizmos[ axis ] ) {
+		
+			handle = this.handleGizmos[ axis ][0];
 
 
-		mesh = new THREE.Mesh( new THREE.TorusGeometry( 1.30, 0.15, 4, 12 ), HandleMaterial( yellow, 0.25 ) );
-		mesh.name = 'RE';
-		pickerAxes['rotate'].add( mesh );
+			handle.material.oldColor = handle.material.color.clone();
+			handle.material.oldOpacity = handle.material.opacity;
+	 
+			handle.material.color.setRGB( 1, 1, 0 );
+			handle.material.opacity = 1;
 
 
-		mesh = null;
+		}
 
 
 	}
 	}
 
 
-	this.attach = function ( object ) {
+	this.init();
 
 
-		this.object = object;
-	 	this.setMode( scope.mode );
+}
 
 
-		this.domElement.addEventListener( 'mousedown', onMouseDown, false );
-		this.domElement.addEventListener( 'mousemove', onMouseHover, false );
-		this.document.addEventListener( 'keydown', onKeyDown, false );
+THREE.TransformGizmo.prototype = Object.create( THREE.Object3D.prototype );
 
 
-	}
+THREE.TransformGizmo.prototype.update = function ( rotation, eye ) {
 
 
-	this.detach = function ( object ) {
+	var vec1 = new THREE.Vector3( 0, 0, 0 );
+	var vec2 = new THREE.Vector3( 0, 1, 0 );
+	var lookAtMatrix = new THREE.Matrix4();
 
 
-		this.object = undefined;
-		this.hovered = false;
+	for ( var i in this.children ) {
 
 
-	 	this.hide();
+		for ( var j in this.children[i].children ) {
 
 
-		this.domElement.removeEventListener( 'mousedown', onMouseDown, false );
-		this.domElement.removeEventListener( 'mousemove', onMouseHover, false );
-		this.document.removeEventListener( 'keydown', onKeyDown, false );
+			var object = this.children[i].children[j];
 
 
-	}
+			if ( object.name.search("E") != -1 ) {
 
 
-	this.update = function () {
+				object.quaternion.setFromRotationMatrix( lookAtMatrix.lookAt( eye, vec1, vec2 ) );
 
 
-		if ( this.object === undefined ) return;
+			} else {
 
 
-		this.object.updateMatrixWorld();
-		worldPosition.getPositionFromMatrix( this.object.matrixWorld );
-		worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( this.object.matrixWorld ) );
+				object.quaternion.setFromEuler( rotation );
 
 
-		this.camera.updateMatrixWorld();
-		camPosition.getPositionFromMatrix( this.camera.matrixWorld );
-		camRotation.setFromRotationMatrix( tempMatrix.extractRotation( this.camera.matrixWorld ) );
+			}
 
 
-		scale = worldPosition.distanceTo( camPosition ) / 6 * this.scale;
-		this.gizmo.position.copy( worldPosition )
-		this.gizmo.scale.set( scale, scale, scale );
+		}
 
 
-		for ( var i in this.gizmo.children ) {
+	}
 
 
-			for ( var j in this.gizmo.children[i].children ) {
+}
+
+THREE.TransformGizmoTranslate = function () {
+
+	THREE.TransformGizmo.call( this );
+
+	var arrowGeometry = new THREE.CylinderGeometry( 0.005, 0.005, 1, 4, 1, false );
+	var mesh = new THREE.Mesh( new THREE.CylinderGeometry( 0, 0.05, 0.2, 12, 1, false ) );
+	mesh.position.y = 0.5;
+	THREE.GeometryUtils.merge( arrowGeometry, mesh );
+				
+	this.handleGizmos = {
+
+		X: [
+			new THREE.Mesh( arrowGeometry, new THREE.TransformGizmoMaterial( { color: 0xff0000 } ) ),
+			new THREE.Vector3( 0.5, 0, 0 ),
+			new THREE.Vector3( 0, 0, -Math.PI/2 )
+		],
+		Y: [
+			new THREE.Mesh( arrowGeometry, new THREE.TransformGizmoMaterial( { color: 0x00ff00 } ) ),
+			new THREE.Vector3( 0, 0.5, 0 )
+		],
+		Z: [
+			new THREE.Mesh( arrowGeometry, new THREE.TransformGizmoMaterial( { color: 0x0000ff } ) ),
+			new THREE.Vector3( 0, 0, 0.5 ),
+			new THREE.Vector3( Math.PI/2, 0, 0 )
+		],
+		XYZ: [
+			new THREE.Mesh( new THREE.OctahedronGeometry( 0.1, 0 ), new THREE.TransformGizmoMaterial( { color: 0xffffff, opacity: 0.25 } ) )
+		],
+		XY: [
+			new THREE.Mesh( new THREE.PlaneGeometry( 0.29, 0.29 ), new THREE.TransformGizmoMaterial( { color: 0xffff00, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0.15, 0.15, 0 )
+		],
+		YZ: [
+			new THREE.Mesh( new THREE.PlaneGeometry( 0.29, 0.29 ), new THREE.TransformGizmoMaterial( { color: 0x00ffff, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0, 0.15, 0.15 ),
+			new THREE.Vector3( 0, Math.PI/2, 0 )
+		],
+		XZ: [
+			new THREE.Mesh( new THREE.PlaneGeometry( 0.29, 0.29 ), new THREE.TransformGizmoMaterial( { color: 0xff00ff, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0.15, 0, 0.15 ),
+			new THREE.Vector3( -Math.PI/2, 0, 0 )
+		]
 
 
-				var object = this.gizmo.children[i].children[j];
-				var name = object.name;
+	}
 
 
-				if ( name.search('E') != -1 ){
+	this.pickerGizmos = {
+
+		X: [
+			new THREE.Mesh( new THREE.CylinderGeometry( 0.075, 0, 1, 4, 1, false ), new THREE.TransformGizmoMaterial( { color: 0xff0000, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0.6, 0, 0 ),
+			new THREE.Vector3( 0, 0, -Math.PI/2 )
+		],
+		Y: [
+			new THREE.Mesh( new THREE.CylinderGeometry( 0.075, 0, 1, 4, 1, false ), new THREE.TransformGizmoMaterial( { color: 0x00ff00, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0, 0.6, 0 )
+		],
+		Z: [
+			new THREE.Mesh( new THREE.CylinderGeometry( 0.075, 0, 1, 4, 1, false ), new THREE.TransformGizmoMaterial( { color: 0x0000ff, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0, 0, 0.6 ),
+			new THREE.Vector3( Math.PI/2, 0, 0 )
+		]
 
 
-					lookAtMatrix.lookAt( camPosition, worldPosition, tempVector.set( 0, 1, 0 ));
-					object.rotation.setFromRotationMatrix( lookAtMatrix );
+	}
 
 
-				} else {
+	this.setActivePlane = function ( axis, eye ) {
 
 
-					eye.copy( camPosition ).sub( worldPosition ).normalize();
+		var tempMatrix = new THREE.Matrix4();
+		eye.applyProjection( tempMatrix.getInverse( tempMatrix.extractRotation( this.planes[ "XY" ].matrixWorld ) ) );
 
 
-					if ( this.space == 'local' ) {
+		if ( axis == "X" ) {
+			this.activePlane = this.planes[ "XY" ];
+			if ( Math.abs(eye.y) > Math.abs(eye.z) ) this.activePlane = this.planes[ "XZ" ];
+		}
 
 
-						tempQuaternion.setFromEuler( worldRotation );
+		if ( axis == "Y" ){
+			this.activePlane = this.planes[ "XY" ];
+			if ( Math.abs(eye.x) > Math.abs(eye.z) ) this.activePlane = this.planes[ "YZ" ];
+		}
 
 
-						if ( name.search('R') != -1 ){
+		if ( axis == "Z" ){
+			this.activePlane = this.planes[ "XZ" ];
+			if ( Math.abs(eye.x) > Math.abs(eye.y) ) this.activePlane = this.planes[ "YZ" ];
+		}
 
 
-							tempMatrix.makeRotationFromQuaternion( tempQuaternion ).getInverse( tempMatrix );
-							eye.applyProjection( tempMatrix );
+		if ( axis == "XYZ" ) this.activePlane = this.planes[ "XYZE" ];
 
 
-							if ( name == 'RX' ) {
-								quaternionX.setFromAxisAngle( unitX, Math.atan2( -eye.y, eye.z ) );
-								tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
-							}
+		if ( axis == "XY" ) this.activePlane = this.planes[ "XY" ];
 
 
-							if ( name == 'RY' ) {
-								quaternionY.setFromAxisAngle( unitY, Math.atan2( eye.x, eye.z ) );
-								tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionY );
-							}
+		if ( axis == "YZ" ) this.activePlane = this.planes[ "YZ" ];
 
 
-							if ( name == 'RZ' ) {
-								quaternionZ.setFromAxisAngle( unitZ, Math.atan2( eye.y, eye.x ) );
-								tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionZ );
-							}
+		if ( axis == "XZ" ) this.activePlane = this.planes[ "XZ" ];
 
 
-						}
+		this.hide();
+		this.show();
 
 
-						object.quaternion.copy( tempQuaternion );
+	}
 
 
-					} else if ( this.space == 'world' ) {
+	this.init();
 
 
-						object.rotation.set( 0, 0, 0 );
+}
 
 
-						if ( name == 'RX' ) object.rotation.x = Math.atan2( -eye.y, eye.z );
-						if ( name == 'RY' ) object.rotation.y = Math.atan2(  eye.x, eye.z );
-						if ( name == 'RZ' ) object.rotation.z = Math.atan2(  eye.y, eye.x );
+THREE.TransformGizmoTranslate.prototype = Object.create( THREE.TransformGizmo.prototype );
 
 
-					}
+THREE.TransformGizmoRotate = function () {
 
 
-				}
+	THREE.TransformGizmo.call( this );
 
 
-			}
+	this.handleGizmos = {
 
 
-		}
+		X: [
+			new THREE.Mesh( new THREE.TorusGeometry( 1, 0.005, 4, 32, Math.PI ), new THREE.TransformGizmoMaterial( { color: 0xff0000 } ) ),
+			new THREE.Vector3( 0, 0, 0 ),
+			new THREE.Vector3( 0, -Math.PI/2, -Math.PI/2 )
+		],
+		Y: [
+			new THREE.Mesh( new THREE.TorusGeometry( 1, 0.005, 4, 32, Math.PI ), new THREE.TransformGizmoMaterial( { color: 0x00ff00 } ) ),
+			new THREE.Vector3( 0, 0, 0 ),
+			new THREE.Vector3( Math.PI/2, 0, 0 )
+		],
+		Z: [
+			new THREE.Mesh( new THREE.TorusGeometry( 1, 0.005, 4, 32, Math.PI ), new THREE.TransformGizmoMaterial( { color: 0x0000ff } ) ),
+			new THREE.Vector3( 0, 0, 0 ),
+			new THREE.Vector3( 0, 0, -Math.PI/2 )
+		],
+		E: [
+			new THREE.Mesh( new THREE.TorusGeometry( 1.25, 0.005, 4, 64 ), new THREE.TransformGizmoMaterial( { color: 0xffff00, opacity: 0.25 } ) )
+		],
+		XYZE: [
+			new THREE.Mesh( new THREE.TorusGeometry( 1, 0.005, 4, 64 ), new THREE.TransformGizmoMaterial( { color: 0x787878 } ) )
+		]
 
 
 	}
 	}
 
 
-	this.hide = function () {
+	this.pickerGizmos = {
+
+		X: [
+			new THREE.Mesh( new THREE.TorusGeometry( 1, 0.05, 4, 12, Math.PI ), new THREE.TransformGizmoMaterial( { color: 0xff0000, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0, 0, 0 ),
+			new THREE.Vector3( 0, -Math.PI/2, -Math.PI/2 )
+		],
+		Y: [
+			new THREE.Mesh( new THREE.TorusGeometry( 1, 0.05, 4, 12, Math.PI ), new THREE.TransformGizmoMaterial( { color: 0x00ff00, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0, 0, 0 ),
+			new THREE.Vector3( Math.PI/2, 0, 0 )
+		],
+		Z: [
+			new THREE.Mesh( new THREE.TorusGeometry( 1, 0.05, 4, 12, Math.PI ), new THREE.TransformGizmoMaterial( { color: 0x0000ff, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0, 0, 0 ),
+			new THREE.Vector3( 0, 0, -Math.PI/2 )
+		],
+		E: [
+			new THREE.Mesh( new THREE.TorusGeometry( 1.25, 0.05, 2, 24 ), new THREE.TransformGizmoMaterial( { color: 0xffff00, opacity: 0.25 } ) )
+		],
+		XYZE: [
+			new THREE.Mesh( new THREE.Geometry() ) // TODO
+		]
 
 
-		for ( var i in displayAxes ) {
+	}
 
 
-			for ( var j in displayAxes[i].children ) {
+	this.setActivePlane = function ( axis ) {
 
 
-				displayAxes[i].children[j].visible = false;
+		if ( axis == "E" ) this.activePlane = this.planes[ "XYZE" ];
 
 
-			}
+	 	if ( axis == "X" ) this.activePlane = this.planes[ "YZ" ];
 
 
-		}
+		if ( axis == "Y" ) this.activePlane = this.planes[ "XZ" ];
 
 
-		for ( var i in pickerAxes ) {
+		if ( axis == "Z" ) this.activePlane = this.planes[ "XY" ];
 
 
-			for ( var j in pickerAxes[i].children ) {
+		this.hide();
+		this.show();
 
 
-				pickerAxes[i].children[j].visible = false;
+	}
 
 
-			}
+	this.update = function ( rotation, eye2 ) {
+
+		THREE.TransformGizmo.prototype.update.apply( this, arguments );
 
 
+		var group = {
+			handles: this["handles"],
+			pickers: this["pickers"],
 		}
 		}
 
 
-	}
+		var tempMatrix = new THREE.Matrix4();
+		var worldRotation = new THREE.Euler( 0, 0, 1 );
+		var tempQuaternion = new THREE.Quaternion();
+		var unitX = new THREE.Vector3( 1, 0, 0 );
+		var unitY = new THREE.Vector3( 0, 1, 0 );
+		var unitZ = new THREE.Vector3( 0, 0, 1 );
+		var quaternionX = new THREE.Quaternion();
+		var quaternionY = new THREE.Quaternion();
+		var quaternionZ = new THREE.Quaternion();
+		var eye = eye2.clone();
 
 
-	this.setMode = function ( value ) {
+		worldRotation.copy( this.planes["XY"].rotation );
+		tempQuaternion.setFromEuler( worldRotation );
 
 
-		scope.mode = value;
+		tempMatrix.makeRotationFromQuaternion( tempQuaternion ).getInverse( tempMatrix );
+		eye.applyProjection( tempMatrix );
 
 
-		this.hide();
+		for ( var i in group ) {
 
 
-		if ( scope.mode == 'scale' ) scope.space = 'local';
+			for ( var j in group[i].children ) {
 
 
-		for ( var i in displayAxes[this.mode].children ) {
+				var object = group[i].children[j];
 
 
-			displayAxes[this.mode].children[i].visible = true;
+				tempQuaternion.setFromEuler( worldRotation );
 
 
-		}
+				if ( object.name == "X" ) {
+					quaternionX.setFromAxisAngle( unitX, Math.atan2( -eye.y, eye.z ) );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
+					object.quaternion.copy( tempQuaternion );
+				}
 
 
-		for ( var i in pickerAxes[this.mode].children ) {
+				if ( object.name == "Y" ) {
+					quaternionY.setFromAxisAngle( unitY, Math.atan2( eye.x, eye.z ) );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionY );
+					object.quaternion.copy( tempQuaternion );
+				}
 
 
-			pickerAxes[this.mode].children[i].visible = showPickers;
+				if ( object.name == "Z" ) {
+					quaternionZ.setFromAxisAngle( unitZ, Math.atan2( eye.y, eye.x ) );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionZ );
+					object.quaternion.copy( tempQuaternion );
+				}
 
 
+			}
 		}
 		}
 
 
-		scope.update();
-
 	}
 	}
 
 
-	this.setIntersectionPlane = function () {
+	this.init();
 
 
-		eye.copy( camPosition ).sub( worldPosition ).normalize();
+}
 
 
-		if ( this.space == 'local' ) {
+THREE.TransformGizmoRotate.prototype = Object.create( THREE.TransformGizmo.prototype );
 
 
-			eye.applyMatrix4( tempMatrix.getInverse( scope.object.matrixWorld ) );
+THREE.TransformGizmoScale = function () {
 
 
-		}
+	THREE.TransformGizmo.call( this );
 
 
-		if ( isActive("X") ) {
+	var arrowGeometry = new THREE.CylinderGeometry( 0.005, 0.005, 1, 4, 1, false );
+	var mesh = new THREE.Mesh( new THREE.CubeGeometry( 0.125, 0.125, 0.125 ) );
+	mesh.position.y = 0.5;
+	THREE.GeometryUtils.merge( arrowGeometry, mesh );
 
 
-			if ( eye.y > eye.z ) currentPlane = 'XZ';
-			else currentPlane = 'XY';
+	this.handleGizmos = {
 
 
-		}
+		XYZ: [
+			new THREE.Mesh( new THREE.CubeGeometry( 0.125, 0.125, 0.125 ), new THREE.TransformGizmoMaterial( { color: 0xffffff, opacity: 0.25 } ) )
+		],
+		X: [
+			new THREE.Mesh( arrowGeometry, new THREE.TransformGizmoMaterial( { color: 0xff0000 } ) ),
+			new THREE.Vector3( 0.5, 0, 0 ),
+			new THREE.Vector3( 0, 0, -Math.PI/2 )
+		],
+		Y: [
+			new THREE.Mesh( arrowGeometry, new THREE.TransformGizmoMaterial( { color: 0x00ff00 } ) ),
+			new THREE.Vector3( 0, 0.5, 0 )
+		],
+		Z: [
+			new THREE.Mesh( arrowGeometry, new THREE.TransformGizmoMaterial( { color: 0x0000ff } ) ),
+			new THREE.Vector3( 0, 0, 0.5 ),
+			new THREE.Vector3( Math.PI/2, 0, 0 )
+		]
 
 
-		if ( isActive("Y") ) {
+	}
 
 
-			if ( eye.x > eye.z ) currentPlane = 'YZ';
-			else currentPlane = 'XY';
+	this.pickerGizmos = {
+
+		X: [
+			new THREE.Mesh( new THREE.CylinderGeometry( 0.125, 0, 1, 4, 1, false ), new THREE.TransformGizmoMaterial( { color: 0xff0000, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0.6, 0, 0 ),
+			new THREE.Vector3( Math.PI/4, 0, -Math.PI/2 )
+		],
+		Y: [
+			new THREE.Mesh( new THREE.CylinderGeometry( 0.125, 0, 1, 4, 1, false ), new THREE.TransformGizmoMaterial( { color: 0x00ff00, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0, 0.6, 0 ),
+			new THREE.Vector3( 0, Math.PI/4, 0 )
+		],
+		Z: [
+			new THREE.Mesh( new THREE.CylinderGeometry( 0.125, 0, 1, 4, 1, false ), new THREE.TransformGizmoMaterial( { color: 0x0000ff, opacity: 0.25 } ) ),
+			new THREE.Vector3( 0, 0, 0.6 ),
+			new THREE.Vector3( Math.PI/2, Math.PI/4, 0 )
+		]
 
 
-		}
+	}
 
 
-		if ( isActive("Z") ) {
+	this.setActivePlane = function ( axis, eye ) {
 
 
-			if ( eye.x > eye.y ) currentPlane = 'YZ';
-			else currentPlane = 'XZ';
+		var tempMatrix = new THREE.Matrix4();
+		eye.applyProjection( 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 ( isActive("XY") ) {
-
-			currentPlane = 'XY';
+		if ( axis == "Y" ){
+			this.activePlane = this.planes[ "XY" ];
+			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 ( isActive("YZ") ) {
+		if ( axis == "XYZ" ) this.activePlane = this.planes[ "XYZE" ];
 
 
-			currentPlane = 'YZ';
+		this.hide();
+		this.show();
 
 
-		}
+	}
 
 
-		if ( isActive("XZ") ) {
+	this.init();
 
 
-			currentPlane = 'XZ';
+}
 
 
-		}
+THREE.TransformGizmoScale.prototype = Object.create( THREE.TransformGizmo.prototype );
 
 
-		if ( isActive("XYZ") || isActive("E") ) {
+THREE.TransformControls = function ( camera, domElement ) {
 
 
-			currentPlane = 'XYZE';
+	// TODO: Make non-uniform scale and rotate play nice in hierarchies
+	// TODO: ADD RXYZ contol
 
 
-		}
+	THREE.Object3D.call( this );
 
 
-	 	if ( isActive("RX") ) {
+	domElement = ( domElement !== undefined ) ? domElement : document;
 
 
-			currentPlane = 'YZ';
+	this.gizmo = {}
+	this.gizmo["translate"] = new THREE.TransformGizmoTranslate();
+	this.gizmo["rotate"] = new THREE.TransformGizmoRotate();
+	this.gizmo["scale"] = new THREE.TransformGizmoScale();
 
 
-		}
+	this.add(this.gizmo["translate"]);
+	this.add(this.gizmo["rotate"]);
+	this.add(this.gizmo["scale"]);
 
 
-		if ( isActive("RY") ) {
+	this.gizmo["translate"].hide();
+	this.gizmo["rotate"].hide();
+	this.gizmo["scale"].hide();
 
 
-			currentPlane = 'XZ';
+	this.object = false;
+	this.snap = false;
+	this.space = "world";
+	this.size = 1;
+	this.axis = false;
 
 
-		} 
+	var scope = this;
+	
+	var _dragging = false;
+	var _mode = "translate";
+	var _plane = "XY";
 
 
-		if ( isActive("RZ") ) {
+	var changeEvent = { type: "change" };
 
 
-			currentPlane = 'XY';
+	var ray = new THREE.Raycaster();
+	var projector = new THREE.Projector();
+	var pointerVector = new THREE.Vector3();
 
 
-		}
+	var point = new THREE.Vector3();
+	var offset = new THREE.Vector3();
 
 
-		if ( isActive("RXYZ") ) {
+	var rotation = new THREE.Vector3();
+	var offsetRotation = new THREE.Vector3();
+	var scale = 1;
 
 
-			currentPlane = 'SPHERE';
+	var lookAtMatrix = new THREE.Matrix4();
+	var eye = new THREE.Vector3()
 
 
-		}
+	var tempMatrix = new THREE.Matrix4();
+	var tempVector = new THREE.Vector3();
+	var tempQuaternion = new THREE.Quaternion();
+	var unitX = new THREE.Vector3( 1, 0, 0 );
+	var unitY = new THREE.Vector3( 0, 1, 0 );
+	var unitZ = new THREE.Vector3( 0, 0, 1 );
 
 
-	}
+	var quaternionXYZ = new THREE.Quaternion();
+	var quaternionX = new THREE.Quaternion();
+	var quaternionY = new THREE.Quaternion();
+	var quaternionZ = new THREE.Quaternion();
+	var quaternionE = new THREE.Quaternion();
 
 
-	var hovered = null;
-	var hoveredColor = new THREE.Color();
-	var hoveredOpacity = 1;
+	var oldPosition = new THREE.Vector3();
+	var oldScale = new THREE.Vector3();
+	var oldRotationMatrix = new THREE.Matrix4();
 
 
-	function onMouseHover( event ) {
+	var parentRotationMatrix  = new THREE.Matrix4();
+	var parentScale = new THREE.Vector3();
 
 
-		event.preventDefault();
+	var worldPosition = new THREE.Vector3();
+	var worldRotation = new THREE.Euler();
+	var worldRotationMatrix  = new THREE.Matrix4();
+	var camPosition = new THREE.Vector3();
+	var camRotation = new THREE.Euler();
 
 
-		if ( event.button === 0 && scope.active === false ) {
+	domElement.addEventListener( "mousedown", onPointerDown, false );
+	domElement.addEventListener( "touchstart", onPointerDown, false );
 
 
-			var intersect = intersectObjects( event, pickerAxes[scope.mode].children );
+	domElement.addEventListener( "mousemove", onPointerHover, false );
+	domElement.addEventListener( "touchmove", onPointerHover, false );
 
 
-			if ( intersect ) {
+	domElement.addEventListener( "mousemove", onPointerMove, false );
+	domElement.addEventListener( "touchmove", onPointerMove, false );
 
 
-				if ( hovered !== intersect.object ) {
+	domElement.addEventListener( "mouseup", onPointerUp, false );
+	domElement.addEventListener( "mouseout", onPointerUp, false );
+	domElement.addEventListener( "touchend", onPointerUp, false );
+	domElement.addEventListener( "touchcancel", onPointerUp, false );
+	domElement.addEventListener( "touchleave", onPointerUp, false );
 
 
-					if ( hovered !== null ) {
+	this.attach = function ( object ) {
 
 
-						hovered.material.color.copy( hoveredColor );
-						hovered.material.opacity = hoveredOpacity;
+		scope.object = object;
 
 
-					}
+	 	this.gizmo["translate"].hide();
+	 	this.gizmo["rotate"].hide();
+	 	this.gizmo["scale"].hide();
+	 	this.gizmo[_mode].show();
+
+	 	scope.dispatchEvent( changeEvent );
+	 	scope.update();
 
 
-					hovered = intersect.object;
-					hoveredColor.copy( hovered.material.color );
-					hoveredOpacity = hovered.material.opacity;
+	}
 
 
-					hovered.material.color.setRGB( 1, 1, 0 );
-					hovered.material.opacity = 1;
+	this.detach = function ( object ) {
 
 
-					scope.dispatchEvent( changeEvent );
+		scope.object = false;
+		this.axis = false;
 
 
-				}
+	 	this.gizmo["translate"].hide();
+	 	this.gizmo["rotate"].hide();
+	 	this.gizmo["scale"].hide();
 
 
-				scope.hovered = true;
+	}
 
 
-			} else if ( hovered !== null ) {
+	this.setMode = function ( mode ) {
 
 
-				hovered.material.color.copy( hoveredColor );
-				hovered.material.opacity = hoveredOpacity;
+		_mode = mode ? mode : _mode;
 
 
-				hovered = null;
+		if ( _mode == "scale" ) scope.space = "local";
 
 
-				scope.dispatchEvent( changeEvent );
+	 	this.gizmo["translate"].hide();
+	 	this.gizmo["rotate"].hide();
+	 	this.gizmo["scale"].hide();	
+	 	this.gizmo[_mode].show();
 
 
-				scope.hovered = false;
+	 	scope.dispatchEvent( changeEvent );
+		this.update();
 
 
-			}
+	}
 
 
-		}
+	this.setSnap = function ( snap ) {
 
 
-		scope.document.addEventListener( 'mousemove', onMouseMove, false );
-		scope.document.addEventListener( 'mouseup', onMouseUp, false );
+		scope.snap = snap;
 
 
-	};
+	}
 
 
-	function onMouseDown( event ) {
+	this.setSize = function ( size ) {
 
 
-		event.preventDefault();
+		scope.size = size;
+	 	scope.dispatchEvent( changeEvent );
+		this.update();
+	 	
+	}
 
 
-		if ( event.button === 0 ) {
+	this.setSpace = function ( space ) {
 
 
-			var intersect = intersectObjects( event, pickerAxes[scope.mode].children );
+		scope.space = space;
 
 
-			if ( intersect ) {
+	 	scope.dispatchEvent( changeEvent );
+		this.update();
 
 
-				scope.active = intersect.object.name;
+	}
 
 
-				scope.update();
-				scope.setIntersectionPlane();
+	this.update = function () {
 
 
-				var planeIntersect = intersectObjects( event, [intersectionPlanes[currentPlane]] );
+		if ( !scope.object ) return;
 
 
-				if ( planeIntersect ) {
+		scope.object.updateMatrixWorld();
+		worldPosition.getPositionFromMatrix( scope.object.matrixWorld );
+		worldRotation.setFromRotationMatrix( tempMatrix.extractRotation( scope.object.matrixWorld ) );
 
 
-					oldPosition.copy( scope.object.position );
-					oldScale.copy( scope.object.scale );
+		camera.updateMatrixWorld();
+		camPosition.getPositionFromMatrix( camera.matrixWorld );
+		camRotation.setFromRotationMatrix( tempMatrix.extractRotation( camera.matrixWorld ) );
 
 
-					oldRotationMatrix.extractRotation( scope.object.matrix );
-					worldRotationMatrix.extractRotation( scope.object.matrixWorld );
+		scale = worldPosition.distanceTo( camPosition ) / 6 * scope.size;
+		this.position.copy( worldPosition )
+		this.scale.set( scale, scale, scale );
 
 
-					parentRotationMatrix.extractRotation( scope.object.parent.matrixWorld );
-					parentScale.getScaleFromMatrix( tempMatrix.getInverse( scope.object.parent.matrixWorld ) );
+		eye.copy( camPosition ).sub( worldPosition ).normalize();
 
 
-					offset.copy( planeIntersect.point );
+		if ( scope.space == "local" )
+			this.gizmo[_mode].update( worldRotation, eye );
 
 
-				}
+		else if ( scope.space == "world" )
+			this.gizmo[_mode].update( new THREE.Euler(), eye );
 
 
-			}
+		this.gizmo[_mode].highlight( scope.axis );
 
 
-		}
+	}
 
 
-		scope.document.addEventListener( 'mousemove', onMouseMove, false );
-		scope.document.addEventListener( 'mouseup', onMouseUp, false );
+	function onPointerHover( event ) {
 
 
-	};
+		if ( !scope.object || _dragging ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
 
 
-	function onMouseMove( event ) {
+		var pointer = event.touches? event.touches[0] : event;
 
 
-		if ( scope.active ) {
+		var intersect = intersectObjects( pointer, scope.gizmo[_mode].pickers.children );
 
 
-			var planeIntersect = intersectObjects( event, [intersectionPlanes[currentPlane]] );
+		if ( intersect ) {
 
 
-			if ( planeIntersect ) {
+			scope.axis = intersect.object.name;
+			scope.dispatchEvent( changeEvent );
+			scope.update();
 
 
-				point.copy( planeIntersect.point );
+		} else {
 
 
-				if ( ( scope.mode == 'translate' ) && isActive("T") ) {
+			scope.axis = false;
+			scope.dispatchEvent( changeEvent );
+			scope.update();
 
 
-					point.sub( offset );
-					point.multiply(parentScale);
+		}
 
 
-					if ( scope.space == 'local' ) {
+	};
 
 
-						point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+	function onPointerDown( event ) {
 
 
-						if ( !(isActive("X")) || scope.modifierAxis.x != 1 ) point.x = 0;
-						if ( !(isActive("Y")) || scope.modifierAxis.y != 1 ) point.y = 0;
-						if ( !(isActive("Z")) || scope.modifierAxis.z != 1 ) point.z = 0;
-						if ( isActive("XYZ") ) point.set( 0, 0, 0 );
+		if ( !scope.object || _dragging ) return;
 
 
-						point.applyMatrix4( oldRotationMatrix );
+		event.preventDefault();
+		event.stopPropagation();
 
 
-						scope.object.position.copy( oldPosition );
-						scope.object.position.add( point );
+		var pointer = event.touches? event.touches[0] : event;
 
 
-					} 
+		if ( pointer.button === 0 || pointer.button == undefined ) {
 
 
-					if ( scope.space == 'world' || isActive("XYZ") ) {
+			var intersect = intersectObjects( pointer, scope.gizmo[_mode].pickers.children );
 
 
-						if ( !(isActive("X")) || scope.modifierAxis.x != 1 ) point.x = 0;
-						if ( !(isActive("Y")) || scope.modifierAxis.y != 1 ) point.y = 0;
-						if ( !(isActive("Z")) || scope.modifierAxis.z != 1 ) point.z = 0;
+			if ( intersect ) {
 
 
-						point.applyMatrix4( tempMatrix.getInverse( parentRotationMatrix ) );
+				scope.axis = intersect.object.name;
 
 
-						scope.object.position.copy( oldPosition );
-						scope.object.position.add( point );
+				scope.update();
 
 
-						if ( scope.snapDist ) {
-							if ( isActive("X") ) scope.object.position.x = Math.round( scope.object.position.x / scope.snapDist ) * scope.snapDist;
-							if ( isActive("Y") ) scope.object.position.y = Math.round( scope.object.position.y / scope.snapDist ) * scope.snapDist;
-							if ( isActive("Z") ) scope.object.position.z = Math.round( scope.object.position.z / scope.snapDist ) * scope.snapDist;
-						}
+				eye.copy( camPosition ).sub( worldPosition ).normalize();
 
 
-					}
+				scope.gizmo[_mode].setActivePlane( scope.axis, eye );
+
+				var planeIntersect = intersectObjects( pointer, [scope.gizmo[_mode].activePlane] );
+
+				if ( planeIntersect ) {
 
 
-				} else if ( ( scope.mode == 'scale') && isActive("S") ) {
+					oldPosition.copy( scope.object.position );
+					oldScale.copy( scope.object.scale );
 
 
-					point.sub( offset );
-					point.multiply(parentScale);
+					oldRotationMatrix.extractRotation( scope.object.matrix );
+					worldRotationMatrix.extractRotation( scope.object.matrixWorld );
 
 
-					if ( scope.space == 'local' ) {
+					parentRotationMatrix.extractRotation( scope.object.parent.matrixWorld );
+					parentScale.getScaleFromMatrix( tempMatrix.getInverse( scope.object.parent.matrixWorld ) );
 
 
-						if ( isActive("XYZ")) {
+					offset.copy( planeIntersect.point );
 
 
-							scale = 1 + ( ( point.y ) / 50 );
+				}
 
 
-							scope.object.scale.x = oldScale.x * scale;
-							scope.object.scale.y = oldScale.y * scale;
-							scope.object.scale.z = oldScale.z * scale;
+			}
 
 
-						} else {
+		}
 
 
-							point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+		_dragging = true;
 
 
-							if ( !(isActive("X")) || scope.modifierAxis.x != 1 ) point.x = 0;
-							if ( !(isActive("Y")) || scope.modifierAxis.y != 1 ) point.y = 0;
-							if ( !(isActive("Z")) || scope.modifierAxis.z != 1 ) point.z = 0;
+	};
 
 
-							if ( isActive("X") ) scope.object.scale.x = oldScale.x * ( 1 + point.x / 50 );
-							if ( isActive("Y") ) scope.object.scale.y = oldScale.y * ( 1 + point.y / 50 );
-							if ( isActive("Z") ) scope.object.scale.z = oldScale.z * ( 1 + point.z / 50 );
+	function onPointerMove( event ) {
 
 
-						}
+		if ( !scope.object || !scope.axis || !_dragging ) return;
 
 
-					}
+		event.preventDefault();
+		event.stopPropagation();
 
 
-				} else if ( ( scope.mode == 'rotate' ) && isActive("R") ) {
+		var pointer = event.touches? event.touches[0] : event;
 
 
-					point.sub( worldPosition );
-					point.multiply(parentScale);
-					tempVector.copy(offset).sub( worldPosition );
-					tempVector.multiply(parentScale);
+		var planeIntersect = intersectObjects( pointer, [scope.gizmo[_mode].activePlane] );
 
 
-					if ( scope.active == "RE" ) {
+		if ( planeIntersect ) {
 
 
-						point.applyMatrix4( tempMatrix.getInverse( lookAtMatrix ) );
-						tempVector.applyMatrix4( tempMatrix.getInverse( lookAtMatrix ) );
+			point.copy( planeIntersect.point );
 
 
-						rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
-						offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
+			if ( _mode == "translate" ) {
 
 
-						tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
+				point.sub( offset );
+				point.multiply(parentScale);
 
 
-						quaternionE.setFromAxisAngle( eye, rotation.z - offsetRotation.z );
-						quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
+				if ( scope.space == "local" ) {
 
 
-						tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionE );
-						tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
+					point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
 
 
-						scope.object.quaternion.copy( tempQuaternion );
+					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;
 
 
-					} else if ( scope.active == "RXYZE" ) {
+					point.applyMatrix4( oldRotationMatrix );
 
 
-						quaternionE.setFromEuler( point.clone().cross(tempVector).normalize() ); // rotation axis
+					scope.object.position.copy( oldPosition );
+					scope.object.position.add( point );
 
 
-						tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
-						quaternionX.setFromAxisAngle( quaternionE, - point.clone().angleTo(tempVector) );
-						quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
+				} 
 
 
-						tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
-						tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
+				if ( scope.space == "world" || scope.axis.search("XYZ") != -1 ) {
 
 
-						scope.object.quaternion.copy( tempQuaternion );
+					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;
 
 
-					} else if ( scope.space == 'local' ) {
+					point.applyMatrix4( tempMatrix.getInverse( parentRotationMatrix ) );
 
 
-						point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+					scope.object.position.copy( oldPosition );
+					scope.object.position.add( point );
 
 
-						tempVector.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
+					if ( scope.snap ) {
 
 
-						rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
-						offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
+						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;
+					
+					}
 
 
-						quaternionXYZ.setFromRotationMatrix( oldRotationMatrix );
-						quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
-						quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
-						quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
+				}
 
 
-						if ( scope.active == "RX" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionX );
-						if ( scope.active == "RY" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionY );
-						if ( scope.active == "RZ" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionZ );
+			} else if ( _mode == "scale" ) {
 
 
-						scope.object.quaternion.copy( quaternionXYZ );
+				point.sub( offset );
+				point.multiply(parentScale);
 
 
-					} else if ( scope.space == 'world' ) {
+				if ( scope.space == "local" ) {
 
 
-						rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
-						offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
+					if ( scope.axis == "XYZ") {
 
 
-						tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
+						scale = 1 + ( ( point.y ) / 50 );
 
 
-						quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
-						quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
-						quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
-						quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
+						scope.object.scale.x = oldScale.x * scale;
+						scope.object.scale.y = oldScale.y * scale;
+						scope.object.scale.z = oldScale.z * scale;
 
 
-						if ( scope.active == "RX" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
-						if ( scope.active == "RY" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionY );
-						if ( scope.active == "RZ" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionZ );
+					} else {
 
 
-						tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
+						point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
 
 
-						scope.object.quaternion.copy( tempQuaternion );
+						if ( scope.axis == "X" ) scope.object.scale.x = oldScale.x * ( 1 + point.x / 50 );
+						if ( scope.axis == "Y" ) scope.object.scale.y = oldScale.y * ( 1 + point.y / 50 );
+						if ( scope.axis == "Z" ) scope.object.scale.z = oldScale.z * ( 1 + point.z / 50 );
 
 
 					}
 					}
 
 
 				}
 				}
 
 
-			}
+			} else if ( _mode == "rotate" ) {
 
 
-			scope.update();
-			scope.dispatchEvent( changeEvent );
+				point.sub( worldPosition );
+				point.multiply(parentScale);
+				tempVector.copy(offset).sub( worldPosition );
+				tempVector.multiply(parentScale);
 
 
-		}
+				if ( scope.axis == "E" ) {
 
 
-	}
+					point.applyMatrix4( tempMatrix.getInverse( lookAtMatrix ) );
+					tempVector.applyMatrix4( tempMatrix.getInverse( lookAtMatrix ) );
 
 
-	function onMouseUp( event ) {
+					rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
+					offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
 
 
-		scope.active = false;
+					tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
 
 
-		scope.document.removeEventListener( 'mousemove', onMouseMove, false );
-		scope.document.removeEventListener( 'mouseup', onMouseUp, false );
+					quaternionE.setFromAxisAngle( eye, rotation.z - offsetRotation.z );
+					quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
 
 
-	}
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionE );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
 
 
-	function onKeyDown( event ) {
+					scope.object.quaternion.copy( tempQuaternion );
 
 
-		var currentMode = scope.mode;
-		var currentSpace = scope.space;
-		var currentScale = scope.scale;
+				} else if ( scope.axis == "XYZE" ) {
 
 
-		if ( event.keyCode == 87 ) { // W
+					quaternionE.setFromEuler( point.clone().cross(tempVector).normalize() ); // rotation axis
 
 
-			if ( scope.mode == 'translate' ) scope.space = ( scope.space == 'world' ) ? 'local' : 'world';
-			scope.mode = 'translate';
+					tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
+					quaternionX.setFromAxisAngle( quaternionE, - point.clone().angleTo(tempVector) );
+					quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
 
 
-		}
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
 
 
-		if ( event.keyCode == 69 ) { // E
+					scope.object.quaternion.copy( tempQuaternion );
 
 
-			if ( scope.mode == 'rotate' ) scope.space = ( scope.space == 'world' ) ? 'local' : 'world';
-			scope.mode = 'rotate';
+				} else if ( scope.space == "local" ) {
 
 
-		}
+					point.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
 
 
-		if ( event.keyCode == 82 ) { // R
+					tempVector.applyMatrix4( tempMatrix.getInverse( worldRotationMatrix ) );
 
 
-			scope.mode = 'scale';
-			scope.space = 'local';
+					rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
+					offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
 
 
-		}
+					quaternionXYZ.setFromRotationMatrix( oldRotationMatrix );
+					quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
+					quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
+					quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
 
 
-		if ( event.keyCode == 187 || event.keyCode == 107 ) { // +,=,num+
+					if ( scope.axis == "X" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionX );
+					if ( scope.axis == "Y" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionY );
+					if ( scope.axis == "Z" ) quaternionXYZ.multiplyQuaternions( quaternionXYZ, quaternionZ );
 
 
-			scope.scale += 0.1
+					scope.object.quaternion.copy( quaternionXYZ );
 
 
-		}
+				} else if ( scope.space == "world" ) {
 
 
-		if ( event.keyCode == 189 || event.keyCode == 109) { // -,_,num-
+					rotation.set( Math.atan2( point.z, point.y ), Math.atan2( point.x, point.z ), Math.atan2( point.y, point.x ) );
+					offsetRotation.set( Math.atan2( tempVector.z, tempVector.y ), Math.atan2( tempVector.x, tempVector.z ), Math.atan2( tempVector.y, tempVector.x ) );
 
 
-			scope.scale -= 0.1
-			scope.scale = Math.max( scope.scale, 0.1 );
+					tempQuaternion.setFromRotationMatrix( tempMatrix.getInverse( parentRotationMatrix ) );
 
 
-		}
-
-		if ( scope.mode !== currentMode || scope.space !== currentSpace || scope.scale !== currentScale ) {
+					quaternionX.setFromAxisAngle( unitX, rotation.x - offsetRotation.x );
+					quaternionY.setFromAxisAngle( unitY, rotation.y - offsetRotation.y );
+					quaternionZ.setFromAxisAngle( unitZ, rotation.z - offsetRotation.z );
+					quaternionXYZ.setFromRotationMatrix( worldRotationMatrix );
 
 
-			scope.setMode( scope.mode );
-			scope.dispatchEvent( changeEvent );
+					if ( scope.axis == "X" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionX );
+					if ( scope.axis == "Y" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionY );
+					if ( scope.axis == "Z" ) tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionZ );
 
 
-		}
+					tempQuaternion.multiplyQuaternions( tempQuaternion, quaternionXYZ );
 
 
-	}
+					scope.object.quaternion.copy( tempQuaternion );
 
 
-	function intersectObjects( event, objects ) {
+				}
 
 
-		pointerVector.set(
-			( event.layerX / scope.domElement.offsetWidth ) * 2 - 1,
-			- ( event.layerY / scope.domElement.offsetHeight ) * 2 + 1,
-			0.5
-		);
+			}
 
 
-		projector.unprojectVector( pointerVector, scope.camera );
-		ray.set( camPosition, pointerVector.sub( camPosition ).normalize() );
+		}
 
 
-		var intersections = ray.intersectObjects( objects, true );
-		return intersections[0] ? intersections[0] : false;
+		scope.dispatchEvent( changeEvent );
+		scope.update();
 
 
 	}
 	}
 
 
-	function isActive( name ) {
+	function onPointerUp( event ) {
 
 
-		if ( scope.active.search( name ) != -1 ) return true;
-		else return false;
+		scope.axis = false;
+		_dragging = false;
+		scope.dispatchEvent( changeEvent );
+		scope.update();
 
 
 	}
 	}
 
 
-	function bakeTransformations( object ) {
+	function intersectObjects( pointer, objects ) {
 
 
-		var tempGeometry = new THREE.Geometry();
-		THREE.GeometryUtils.merge( tempGeometry, object );
-		object.geometry = tempGeometry;
-		object.position.set( 0, 0, 0 );
-		object.rotation.set( 0, 0, 0 );
-		object.scale.set( 1, 1, 1 );
+	    var rect = domElement.getBoundingClientRect();
+	    var x = (pointer.clientX - rect.left) / rect.width;
+	    var y = (pointer.clientY - rect.top) / rect.height;
+		pointerVector.set( ( x ) * 2 - 1, - ( y ) * 2 + 1, 0.5 );
+
+		projector.unprojectVector( pointerVector, camera );
+		ray.set( camPosition, pointerVector.sub( camPosition ).normalize() );
+
+		var intersections = ray.intersectObjects( objects, true );
+		return intersections[0] ? intersections[0] : false;
 
 
 	}
 	}
 
 
 };
 };
 
 
-THREE.TransformControls.prototype = Object.create( THREE.EventDispatcher.prototype );
+THREE.TransformControls.prototype = Object.create( THREE.Object3D.prototype );

+ 6 - 0
examples/js/exporters/ObjectExporter.js

@@ -60,6 +60,12 @@ THREE.ObjectExporter.prototype = {
 					data.heightSegments = geometry.heightSegments;
 					data.heightSegments = geometry.heightSegments;
 					data.depthSegments = geometry.depthSegments;
 					data.depthSegments = geometry.depthSegments;
 
 
+				} else if ( geometry instanceof THREE.CircleGeometry ) {
+
+					data.type = 'CircleGeometry';
+					data.radius = geometry.radius;
+					data.segments = geometry.segments;
+
 				} else if ( geometry instanceof THREE.CylinderGeometry ) {
 				} else if ( geometry instanceof THREE.CylinderGeometry ) {
 
 
 					data.type = 'CylinderGeometry';
 					data.type = 'CylinderGeometry';

+ 12 - 50
examples/js/loaders/MTLLoader.js

@@ -16,56 +16,18 @@ THREE.MTLLoader.prototype = {
 
 
 	constructor: THREE.MTLLoader,
 	constructor: THREE.MTLLoader,
 
 
-	/**
-	 * Loads a MTL file
-	 *
-	 * Loading progress is indicated by the following events:
-	 *   "load" event (successful loading): type = 'load', content = THREE.MTLLoader.MaterialCreator
-	 *   "error" event (error loading): type = 'load', message
-	 *   "progress" event (progress loading): type = 'progress', loaded, total
-	 *
-	 * @param url - location of MTL file
-	 */
-	load: function( url ) {
+	load: function ( url, onLoad, onProgress, onError ) {
 
 
 		var scope = this;
 		var scope = this;
-		var xhr = new XMLHttpRequest();
-
-		function onloaded( event ) {
-
-			if ( event.target.status === 200 || event.target.status === 0 ) {
-
-				var materialCreator = scope.parse( event.target.responseText );
-
-				// Notify caller, that I'm done
-
-				scope.dispatchEvent( { type: 'load', content: materialCreator } );
-
-			} else {
-
-				scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']',
-					response: event.target.responseText } );
-
-			}
-
-		}
-
-		xhr.addEventListener( 'load', onloaded, false );
-
-		xhr.addEventListener( 'progress', function ( event ) {
-
-			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
-
-		}, false );
 
 
-		xhr.addEventListener( 'error', function () {
+		var loader = new THREE.XHRLoader();
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.load( url, function ( text ) {
 
 
-			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
+			onLoad( scope.parse( text ) );
 
 
-		}, false );
+		} );
 
 
-		xhr.open( 'GET', url, true );
-		xhr.send( null );
 	},
 	},
 
 
 	/**
 	/**
@@ -73,14 +35,14 @@ THREE.MTLLoader.prototype = {
 	 * @param text - Content of MTL file
 	 * @param text - Content of MTL file
 	 * @return {THREE.MTLLoader.MaterialCreator}
 	 * @return {THREE.MTLLoader.MaterialCreator}
 	 */
 	 */
-	parse: function( text ) {
+	parse: function ( text ) {
 
 
 		var lines = text.split( "\n" );
 		var lines = text.split( "\n" );
 		var info = {};
 		var info = {};
 		var delimiter_pattern = /\s+/;
 		var delimiter_pattern = /\s+/;
 		var materialsInfo = {};
 		var materialsInfo = {};
 
 
-			for ( var i = 0; i < lines.length; i ++ ) {
+		for ( var i = 0; i < lines.length; i ++ ) {
 
 
 			var line = lines[ i ];
 			var line = lines[ i ];
 			line = line.trim();
 			line = line.trim();
@@ -94,7 +56,7 @@ THREE.MTLLoader.prototype = {
 
 
 			var pos = line.indexOf( ' ' );
 			var pos = line.indexOf( ' ' );
 
 
-			var key = ( pos >= 0 ) ? line.substring( 0, pos) : line;
+			var key = ( pos >= 0 ) ? line.substring( 0, pos ) : line;
 			key = key.toLowerCase();
 			key = key.toLowerCase();
 
 
 			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : "";
 			var value = ( pos >= 0 ) ? line.substring( pos + 1 ) : "";
@@ -326,7 +288,7 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 
 
 					// Diffuse color (color under white light) using RGB values
 					// Diffuse color (color under white light) using RGB values
 
 
-					params[ 'diffuse' ] = new THREE.Color().setRGB( value[0], value[1], value[2] );
+					params[ 'diffuse' ] = new THREE.Color().fromArray( value );
 
 
 					break;
 					break;
 
 
@@ -334,14 +296,14 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 
 
 					// Ambient color (color under shadow) using RGB values
 					// Ambient color (color under shadow) using RGB values
 
 
-					params[ 'ambient' ] = new THREE.Color().setRGB( value[0], value[1], value[2] );
+					params[ 'ambient' ] = new THREE.Color().fromArray( value );
 
 
 					break;
 					break;
 
 
 				case 'ks':
 				case 'ks':
 
 
 					// Specular color (color when light is reflected from shiny surface) using RGB values
 					// Specular color (color when light is reflected from shiny surface) using RGB values
-					params[ 'specular' ] = new THREE.Color().setRGB( value[0], value[1], value[2] );
+					params[ 'specular' ] = new THREE.Color().fromArray( value );
 
 
 					break;
 					break;
 
 

+ 36 - 49
examples/js/loaders/OBJLoader.js

@@ -26,17 +26,17 @@ THREE.OBJLoader.prototype = {
 
 
 	},
 	},
 
 
-	parse: function ( data ) {
+	parse: function ( text ) {
 
 
 		// fixes
 		// fixes
 
 
-		data = data.replace( /\ \\\r\n/g, '' ); // rhino adds ' \\r\n' some times.
+		text = text.replace( /\ \\\r\n/g, '' ); // rhino adds ' \\r\n' some times.
 
 
 		var replacement = '/f$1$2$4\n/f$2$3$4'; // quads to tris
 		var replacement = '/f$1$2$4\n/f$2$3$4'; // quads to tris
-		data = data.replace( /f( +\d+)( +\d+)( +\d+)( +\d+)/g, replacement );
-		data = data.replace( /f( +\d+\/\d+)( +\d+\/\d+)( +\d+\/\d+)( +\d+\/\d+)/g, replacement );
-		data = data.replace( /f( +\d+\/\d+\/\d+)( +\d+\/\d+\/\d+)( +\d+\/\d+\/\d+)( +\d+\/\d+\/\d+)/g, replacement );
-		data = data.replace( /f( +\d+\/\/\d+)( +\d+\/\/\d+)( +\d+\/\/\d+)( +\d+\/\/\d+)/g, replacement );
+		text = text.replace( /f( +\d+)( +\d+)( +\d+)( +\d+)/g, replacement );
+		text = text.replace( /f( +\d+\/\d+)( +\d+\/\d+)( +\d+\/\d+)( +\d+\/\d+)/g, replacement );
+		text = text.replace( /f( +\d+\/\d+\/\d+)( +\d+\/\d+\/\d+)( +\d+\/\d+\/\d+)( +\d+\/\d+\/\d+)/g, replacement );
+		text = text.replace( /f( +\d+\/\/\d+)( +\d+\/\/\d+)( +\d+\/\/\d+)( +\d+\/\/\d+)/g, replacement );
 
 
 		//
 		//
 
 
@@ -58,43 +58,20 @@ THREE.OBJLoader.prototype = {
 
 
 		}
 		}
 
 
-		function meshN( meshName, materialName ) {
+		var object = new THREE.Object3D();
+		var geometry, material, mesh;
 
 
-			if ( geometry.vertices.length > 0 ) {
+		// create mesh if no objects in text
 
 
-				geometry.mergeVertices();
-				geometry.computeCentroids();
-				geometry.computeFaceNormals();
-				geometry.computeBoundingSphere();
+		if ( /^o /gm.test( text ) === false ) {
 
 
-				object.add( mesh );
-
-				geometry = new THREE.Geometry();
-				mesh = new THREE.Mesh( geometry, material );
-
-				verticesCount = 0;
-
-			}
-
-			if ( meshName !== undefined ) mesh.name = meshName;
-			if ( materialName !== undefined ) {
-
-				material = new THREE.MeshLambertMaterial();
-				material.name = materialName;
-
-				mesh.material = material;
-
-			}
+			geometry = new THREE.Geometry();
+			material = new THREE.MeshLambertMaterial();
+			mesh = new THREE.Mesh( geometry, material );
+			object.add( mesh );
 
 
 		}
 		}
 
 
-		var group = new THREE.Object3D();
-		var object = group;
-
-		var geometry = new THREE.Geometry();
-		var material = new THREE.MeshLambertMaterial();
-		var mesh = new THREE.Mesh( geometry, material );
-
 		var vertices = [];
 		var vertices = [];
 		var verticesCount = 0;
 		var verticesCount = 0;
 		var normals = [];
 		var normals = [];
@@ -110,11 +87,11 @@ THREE.OBJLoader.prototype = {
 
 
 		// vt float float
 		// vt float float
 
 
-		var uv_pattern = /vt( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/
+		var uv_pattern = /vt( +[\d|\.|\+|\-|e]+)( +[\d|\.|\+|\-|e]+)/;
 
 
 		// f vertex vertex vertex
 		// f vertex vertex vertex
 
 
-		var face_pattern1 = /f( +\d+)( +\d+)( +\d+)/
+		var face_pattern1 = /f( +\d+)( +\d+)( +\d+)/;
 
 
 		// f vertex/uv vertex/uv vertex/uv
 		// f vertex/uv vertex/uv vertex/uv
 
 
@@ -130,7 +107,7 @@ THREE.OBJLoader.prototype = {
 
 
 		//
 		//
 
 
-		var lines = data.split( "\n" );
+		var lines = text.split( '\n' );
 
 
 		for ( var i = 0; i < lines.length; i ++ ) {
 		for ( var i = 0; i < lines.length; i ++ ) {
 
 
@@ -262,21 +239,24 @@ THREE.OBJLoader.prototype = {
 
 
 				// object
 				// object
 
 
-				object = new THREE.Object3D();
-				object.name = line.substring( 2 ).trim();
-				group.add( object );
+				geometry = new THREE.Geometry();
+				material = new THREE.MeshLambertMaterial();
+
+				mesh = new THREE.Mesh( geometry, material );
+				mesh.name = line.substring( 2 ).trim();
+				object.add( mesh );
+
+				verticesCount = 0;
 
 
 			} else if ( /^g /.test( line ) ) {
 			} else if ( /^g /.test( line ) ) {
 
 
 				// group
 				// group
 
 
-				meshN( line.substring( 2 ).trim(), undefined );
-
 			} else if ( /^usemtl /.test( line ) ) {
 			} else if ( /^usemtl /.test( line ) ) {
 
 
 				// material
 				// material
 
 
-				meshN( undefined, line.substring( 7 ).trim() );
+				material.name = line.substring( 7 ).trim();
 
 
 			} else if ( /^mtllib /.test( line ) ) {
 			} else if ( /^mtllib /.test( line ) ) {
 
 
@@ -294,10 +274,17 @@ THREE.OBJLoader.prototype = {
 
 
 		}
 		}
 
 
-		// add the last group
-		meshN( undefined, undefined );
+		for ( var i = 0, l = object.children.length; i < l; i ++ ) {
+
+			var geometry = object.children[ i ].geometry;
+
+			geometry.computeCentroids();
+			geometry.computeFaceNormals();
+			geometry.computeBoundingSphere();
+
+		}
 
 
-		return group;
+		return object;
 
 
 	}
 	}
 
 

+ 18 - 134
examples/js/loaders/OBJMTLLoader.js

@@ -11,159 +11,43 @@ THREE.OBJMTLLoader.prototype = {
 
 
 	constructor: THREE.OBJMTLLoader,
 	constructor: THREE.OBJMTLLoader,
 
 
-	/**
-	 * Load a Wavefront OBJ file with materials (MTL file)
-	 *
-	 * Loading progress is indicated by the following events:
-	 *   "load" event (successful loading): type = 'load', content = THREE.Object3D
-	 *   "error" event (error loading): type = 'load', message
-	 *   "progress" event (progress loading): type = 'progress', loaded, total
-	 *
-	 * If the MTL file cannot be loaded, then a MeshLambertMaterial is used as a default
-	 * @param url - Location of OBJ file to load
-	 * @param mtlfileurl - MTL file to load (optional, if not specified, attempts to use MTL specified in OBJ file)
-	 * @param options - Options on how to interpret the material (see THREE.MTLLoader.MaterialCreator )
-	 */
-
-	load: function ( url, mtlfileurl, options ) {
+	load: function ( url, mtlurl, onLoad, onProgress, onError ) {
 
 
 		var scope = this;
 		var scope = this;
-		var xhr = new XMLHttpRequest();
-
-		var mtlDone;           // Is the MTL done (true if no MTL, error loading MTL, or MTL actually loaded)
-		var obj3d;             // Loaded model (from obj file)
-		var materialsCreator;  // Material creator is created when MTL file is loaded
-
-		// Loader for MTL
-
-		var mtlLoader = new THREE.MTLLoader( url.substr( 0, url.lastIndexOf( "/" ) + 1 ), options );
-		mtlLoader.addEventListener( 'load', waitReady );
-		mtlLoader.addEventListener( 'error', waitReady );
-
-		// Try to load mtlfile
-
-		if ( mtlfileurl ) {
-
-			mtlLoader.load( mtlfileurl );
-			mtlDone = false;
-
-		} else {
-
-			mtlDone = true;
-
-		}
-
-		function waitReady( event ) {
 
 
-			if ( event.type === 'load' ) {
+		var mtlLoader = new THREE.MTLLoader( url.substr( 0, url.lastIndexOf( "/" ) + 1 ) );
+		mtlLoader.load( mtlurl, function ( materials ) {
 
 
-				if ( event.content instanceof THREE.MTLLoader.MaterialCreator ) {
+			var materialsCreator = materials;
+			materialsCreator.preload();
 
 
-					// MTL file is loaded
+			var loader = new THREE.XHRLoader( scope.manager );
+			loader.setCrossOrigin( this.crossOrigin );
+			loader.load( url, function ( text ) {
 
 
-					mtlDone = true;
-					materialsCreator = event.content;
-					materialsCreator.preload();
+				var object = scope.parse( text );
 
 
-				} else {
+				object.traverse( function ( object ) {
 
 
-					// OBJ file is loaded
+					if ( object instanceof THREE.Mesh ) {
 
 
-					if ( event.target.status === 200 || event.target.status === 0 ) {
+						if ( object.material.name ) {
 
 
-						var objContent = event.target.responseText;
+							var material = materialsCreator.create( object.material.name );
 
 
-						if ( mtlfileurl ) {
-
-							// Parse with passed in MTL file
-
-							obj3d = scope.parse( objContent );
-
-						} else {
-
-							// No passed in MTL file, look for mtlfile in obj file
-
-							obj3d = scope.parse( objContent, function( mtlfile ) {
-
-								mtlDone = false;
-								mtlLoader.load( mtlLoader.baseUrl + mtlfile );
-
-							} );
+							if ( material ) object.material = material;
 
 
 						}
 						}
 
 
-					} else {
-
-						// Error loading OBJ file....
-
-						scope.dispatchEvent( {
-							type: 'error',
-							message: 'Couldn\'t load URL [' + url + ']',
-							response: event.target.responseText } );
-
 					}
 					}
 
 
-				}
-
-			} else if ( event.type === 'error' ) {
-
-				// MTL failed to load -- oh well, we will just not have material ...
-
-				mtlDone = true;
-
-			}
-
-			if ( mtlDone && obj3d ) {
-
-				// MTL file is loaded and OBJ file is loaded
-				// Apply materials to model
-
-				if ( materialsCreator ) {
-
-					obj3d.traverse( function( object ) {
-
-						if ( object instanceof THREE.Mesh ) {
-
-							if ( object.material.name ) {
-
-								var material = materialsCreator.create( object.material.name );
-								if ( material ) {
-
-									object.material = material;
-
-								}
-
-							}
-
-						}
-
-					} );
-
-				}
-
-				// Notify listeners
-
-				scope.dispatchEvent( { type: 'load', content: obj3d } );
-			}
-
-		}
-
-		xhr.addEventListener( 'load', waitReady, false );
-
-		xhr.addEventListener( 'progress', function ( event ) {
-
-			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
-
-		}, false );
-
-		xhr.addEventListener( 'error', function () {
+				} );
 
 
-			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
+				onLoad( object );
 
 
-		}, false );
+			} );
 
 
-		xhr.open( 'GET', url, true );
-		xhr.send( null );
+		} );
 
 
 	},
 	},
 
 

+ 0 - 2
examples/js/renderers/WebGLRenderer2/README.md

@@ -1,2 +0,0 @@
-This renderer was an attempt by @gero3 to refactor WebGLRenderer.
-It's curently on hold as WebGLRenderer may need even bigger architecture changes.

+ 0 - 3274
examples/js/renderers/WebGLRenderer2/WebGLRenderer2.js

@@ -1,3274 +0,0 @@
-/**
- * @author supereggbert / http://www.paulbrunt.co.uk/
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- * @author szimek / https://github.com/szimek/
- * @author gero3 / https://github.com/gero3/
- */
-
-THREE.WebGLRenderer = function ( parameters ) {
-
-	console.log( 'THREE.WebGLRenderer', THREE.REVISION );
-
-	parameters = parameters || {};
-
-	var info = {
-
-		memory: {
-
-			programs: 0,
-			geometries: 0,
-			textures: 0
-
-		},
-
-		render: {
-
-			calls: 0,
-			vertices: 0,
-			faces: 0,
-			points: 0
-
-		}
-
-	};
-
-
-	var renderer = new THREE.WebGLRenderer.LowLevelRenderer(parameters);
-	var meshRenderer = new THREE.WebGLRenderer.MeshRenderer(renderer, info);
-	var particleRenderer = new THREE.WebGLRenderer.ParticleRenderer(renderer, info);
-	var lineRenderer = new THREE.WebGLRenderer.LineRenderer(renderer, info);
-	var ribbonRenderer = new THREE.WebGLRenderer.RibbonRenderer(renderer, info);
-
-	var shaderBuilder = new THREE.WebGLRenderer.ShaderBuilder(renderer, info);
-
-	// clearing
-
-	this.autoClear = true;
-	this.autoClearColor = true;
-	this.autoClearDepth = true;
-	this.autoClearStencil = true;
-
-	// scene graph
-
-	this.sortObjects = true;
-	this.autoUpdateObjects = true;
-
-	// physically based shading
-
-	this.gammaInput = false;
-	this.gammaOutput = false;
-	this.physicallyBasedShading = false;
-
-	// shadow map
-
-	this.shadowMapEnabled = false;
-	this.shadowMapAutoUpdate = true;
-	this.shadowMapType = THREE.PCFShadowMap;
-	this.shadowMapCullFace = THREE.CullFaceFront;
-	this.shadowMapDebug = false;
-	this.shadowMapCascade = false;
-
-	// morphs
-
-	this.maxMorphTargets = 8;
-	this.maxMorphNormals = 4;
-
-	// flags
-
-	this.autoScaleCubemaps = true;
-
-	// custom render plugins
-
-	this.renderPluginsPre = [];
-	this.renderPluginsPost = [];
-
-	// info
-
-	this.info = info;
-
-
-	// internal properties
-
-	var _this = this,
-
-	// internal state cache
-
-	_currentProgram = null,
-	_currentFramebuffer = null,
-	_currentMaterialId = -1,
-	_currentGeometryGroupHash = null,
-	_currentCamera = null,
-	_geometryGroupCounter = 0,
-
-	_usedTextureUnits = 0,
-
-	// GL state
-
-	_viewportX = 0,
-	_viewportY = 0,
-	_viewportWidth = 0,
-	_viewportHeight = 0,
-	_currentWidth = 0,
-	_currentHeight = 0,
-
-	_enabledAttributes = {},
-
-	// frustum
-
-	_frustum = new THREE.Frustum(),
-
-	 // camera matrices cache
-
-	_projScreenMatrix = new THREE.Matrix4(),
-	_projScreenMatrixPS = new THREE.Matrix4(),
-
-	_vector3 = new THREE.Vector3(),
-
-	// light arrays cache
-
-	_direction = new THREE.Vector3(),
-
-	_lightsNeedUpdate = true,
-
-	_lights = {
-
-		ambient: [ 0, 0, 0 ],
-		directional: { length: 0, colors: [], positions: [] },
-		point: { length: 0, colors: [], positions: [], distances: [] },
-		spot: { length: 0, colors: [], positions: [], distances: [], directions: [], anglesCos: [], exponents: [] },
-		hemi: { length: 0, skyColors: [], groundColors: [], positions: [] }
-
-	};
-
-	// initialize
-
-	this.context = renderer.getContext();
-	this.domElement = renderer.getDomElement();
-	this.getPrecision = renderer.getPrecision;
-
-	// low level API
-
-	this.getPrecision = renderer.getPrecision;
-	this.getContext = renderer.getContext;
-	this.supportsVertexTextures = renderer.supportsVertexTextures;
-	this.supportsFloatTextures = renderer.supportsFloatTextures;
-	this.supportsStandardDerivatives = renderer.supportsStandardDerivatives;
-	this.supportsCompressedTextureS3TC = renderer.supportsCompressedTextureS3TC;
-	this.getMaxAnisotropy  = renderer.getMaxAnisotropy;
-	this.setSize = renderer.setSize;
-	this.setViewport = renderer.setViewport;
-	this.setScissor = renderer.setScissor;
-	this.enableScissorTest = renderer.enableScissorTest;
-	this.setDepthWrite = renderer.setDepthWrite;
-	this.setDepthTest = renderer.setDepthTest;
-	this.setRenderTarget = renderer.setRenderTarget;
-	this.setBlending = renderer.setBlending;
-	this.setTexture = renderer.setTexture;
-	this.setMaterialFaces = renderer.setMaterialFaces;
-	this.setFaceCulling = renderer.setFaceCulling;
-
-	// Clearing
-
-	this.setClearColorHex = renderer.setClearColorHex;
-	this.setClearColor = renderer.setClearColor;
-	this.getClearColor = renderer.getClearColor;
-	this.getClearAlpha = renderer.getClearAlpha;
-	this.clear = renderer.clear;
-	this.clearTarget = renderer.clearTarget;
-
-	// Plugins
-
-	this.addPostPlugin = function ( plugin ) {
-
-		plugin.init( this );
-		this.renderPluginsPost.push( plugin );
-
-	};
-
-	this.addPrePlugin = function ( plugin ) {
-
-		plugin.init( this );
-		this.renderPluginsPre.push( plugin );
-
-	};
-
-	// Rendering
-
-	this.updateShadowMap = function ( scene, camera ) {
-
-		_currentProgram = null;
-		_currentGeometryGroupHash = -1;
-		_currentMaterialId = -1;
-		_lightsNeedUpdate = true;
-
-		renderer.resetState();
-
-
-		this.shadowMapPlugin.update( scene, camera );
-
-	};
-
-	// Events
-
-	var onGeometryDispose = function ( event ) {
-
-		var geometry = event.target;
-
-		geometry.removeEventListener( 'dispose', onGeometryDispose );
-
-		deallocateGeometry( geometry );
-
-		_this.info.memory.geometries --;
-
-	};
-
-	var onTextureDispose = function ( event ) {
-
-		var texture = event.target;
-
-		texture.removeEventListener( 'dispose', onTextureDispose );
-
-		deallocateTexture( texture );
-
-		_this.info.memory.textures --;
-
-
-	};
-
-	var onRenderTargetDispose = function ( event ) {
-
-		var renderTarget = event.target;
-
-		renderTarget.removeEventListener( 'dispose', onRenderTargetDispose );
-
-		deallocateRenderTarget( renderTarget );
-
-		_this.info.memory.textures --;
-
-	};
-
-	var onMaterialDispose = function ( event ) {
-
-		var material = event.target;
-
-		material.removeEventListener( 'dispose', onMaterialDispose );
-
-		deallocateMaterial( material );
-
-	};
-
-	// Buffer deallocation
-
-	var deallocateGeometry = function ( geometry ) {
-
-		var m,ml;
-		geometry.__webglInit = undefined;
-
-		if ( geometry.__webglVertexBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglVertexBuffer );
-		if ( geometry.__webglNormalBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglNormalBuffer );
-		if ( geometry.__webglTangentBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglTangentBuffer );
-		if ( geometry.__webglColorBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglColorBuffer );
-		if ( geometry.__webglUVBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglUVBuffer );
-		if ( geometry.__webglUV2Buffer !== undefined ) renderer.deleteBuffer( geometry.__webglUV2Buffer );
-
-		if ( geometry.__webglSkinIndicesBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglSkinIndicesBuffer );
-		if ( geometry.__webglSkinWeightsBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglSkinWeightsBuffer );
-
-		if ( geometry.__webglFaceBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglFaceBuffer );
-		if ( geometry.__webglLineBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglLineBuffer );
-
-		if ( geometry.__webglLineDistanceBuffer !== undefined ) renderer.deleteBuffer( geometry.__webglLineDistanceBuffer );
-
-		// geometry groups
-
-		if ( geometry.geometryGroups !== undefined ) {
-
-			for ( var g in geometry.geometryGroups ) {
-
-				var geometryGroup = geometry.geometryGroups[ g ];
-
-				if ( geometryGroup.numMorphTargets !== undefined ) {
-
-					for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-						renderer.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
-
-					}
-
-				}
-
-				if ( geometryGroup.numMorphNormals !== undefined ) {
-
-					for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-						renderer.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
-
-					}
-
-				}
-
-				deleteCustomAttributesBuffers( geometryGroup );
-
-			}
-
-		}
-
-		deleteCustomAttributesBuffers( geometry );
-
-	};
-
-	var deallocateTexture = function ( texture ) {
-
-		if ( texture.image && texture.image.__webglTextureCube ) {
-
-			// cube texture
-
-			renderer.deleteTexture( texture.image.__webglTextureCube );
-
-		} else {
-
-			// 2D texture
-
-			if ( ! texture.__webglInit ) return;
-
-			texture.__webglInit = false;
-			renderer.deleteTexture( texture.__webglTexture );
-
-		}
-
-	};
-
-	var deallocateRenderTarget = function ( renderTarget ) {
-
-		if ( !renderTarget || ! renderTarget.__webglTexture ) return;
-
-		renderer.deleteTexture( renderTarget.__webglTexture );
-
-		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
-
-			for ( var i = 0; i < 6; i ++ ) {
-
-				renderer.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
-				renderer.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );
-
-			}
-
-		} else {
-
-			renderer.deleteFramebuffer( renderTarget.__webglFramebuffer );
-			renderer.deleteRenderbuffer( renderTarget.__webglRenderbuffer );
-
-		}
-
-	};
-
-	var deallocateMaterial = function ( material ) {
-
-		var program = material.program;
-
-		if ( program === undefined ) return;
-
-		material.program = undefined;
-
-		// only deallocate GL program if this was the last use of shared program
-		// assumed there is only single copy of any program in the _programs list
-		// (that's how it's constructed)
-
-		shaderBuilder.removeProgram(program)
-
-	};
-
-
-	function deleteCustomAttributesBuffers( geometry ) {
-
-		if ( geometry.__webglCustomAttributesList ) {
-
-			for ( var id in geometry.__webglCustomAttributesList ) {
-
-				renderer.deleteBuffer( geometry.__webglCustomAttributesList[ id ].buffer );
-
-			}
-
-		}
-
-	};
-
-	// Buffer initialization
-
-	function initCustomAttributes ( geometry, object ) {
-
-		var nvertices = geometry.vertices.length;
-
-		var material = object.material;
-
-		if ( material.attributes ) {
-
-			if ( geometry.__webglCustomAttributesList === undefined ) {
-
-				geometry.__webglCustomAttributesList = [];
-
-			}
-
-			for ( var a in material.attributes ) {
-
-				var attribute = material.attributes[ a ];
-
-				if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
-
-					attribute.__webglInitialized = true;
-
-					var size = 1;		// "f" and "i"
-
-					if ( attribute.type === "v2" ) size = 2;
-					else if ( attribute.type === "v3" ) size = 3;
-					else if ( attribute.type === "v4" ) size = 4;
-					else if ( attribute.type === "c"  ) size = 3;
-
-					attribute.size = size;
-
-					attribute.array = new Float32Array( nvertices * size );
-
-					attribute.buffer = renderer.createBuffer();
-					attribute.buffer.belongsToAttribute = a;
-
-					attribute.needsUpdate = true;
-
-				}
-
-				geometry.__webglCustomAttributesList.push( attribute );
-
-			}
-
-		}
-
-	};
-
-	function getBufferMaterial( object, geometryGroup ) {
-
-		return object.material instanceof THREE.MeshFaceMaterial
-			? object.material.materials[ geometryGroup.materialIndex ]
-			: object.material;
-
-	};
-
-	//
-
-	function initDirectBuffers( geometry ) {
-
-		var a, attribute;
-
-		for ( a in geometry.attributes ) {
-
-			attribute = geometry.attributes[ a ];
-
-			if ( attribute.numItems === undefined ) {
-
-				attribute.numItems = attribute.array.length;
-
-			}
-
-			attribute.buffer = renderer.createBuffer();
-
-			if ( a === "index" ) {
-
-				renderer.setStaticIndexBuffer(attribute.buffer,attribute.array);
-
-			} else {
-
-				renderer.setStaticArrayBuffer(attribute.buffer,attribute.array);
-
-			}
-
-		}
-
-	};
-
-	// Buffer setting
-
-	function setDirectBuffers ( geometry, dispose ) {
-
-		var attributes = geometry.attributes;
-
-		var attributeName, attributeItem;
-
-		for ( attributeName in attributes ) {
-
-			attributeItem = attributes[ attributeName ];
-
-			if ( attributeItem.needsUpdate ) {
-
-				if ( attributeName === 'index' ) {
-
-					renderer.setDynamicIndexBuffer(	attributeItem.buffer, attributeItem.array );
-
-				} else {
-
-					renderer.setDynamicArrayBuffer( attributeItem.buffer,  attributeItem.array );
-
-				}
-
-				attributeItem.needsUpdate = false;
-
-			}
-
-			if ( dispose && ! attributeItem.dynamic ) {
-
-				delete attributeItem.array;
-
-			}
-
-		}
-
-	};
-
-	// Buffer rendering
-
-	this.renderBufferImmediate = function ( object, program, material ) {
-
-		if ( object.hasPositions && ! object.__webglVertexBuffer ) object.__webglVertexBuffer = renderer.createBuffer();
-		if ( object.hasNormals && ! object.__webglNormalBuffer ) object.__webglNormalBuffer = renderer.createBuffer();
-		if ( object.hasUvs && ! object.__webglUvBuffer ) object.__webglUvBuffer = renderer.createBuffer();
-		if ( object.hasColors && ! object.__webglColorBuffer ) object.__webglColorBuffer = renderer.createBuffer();
-
-		if ( object.hasPositions ) {
-
-			renderer.setDynamicArrayBuffer( object.__webglVertexBuffer, object.positionArray);
-			renderer.setFloatAttribute(program.attributes.position, object.__webglVertexBuffer, 3, 0);
-
-		}
-
-		if ( object.hasNormals ) {
-
-			if ( material.shading === THREE.FlatShading ) {
-
-				var nx, ny, nz,
-					nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz,
-					normalArray,
-					i, il = object.count * 3;
-
-				for( i = 0; i < il; i += 9 ) {
-
-					normalArray = object.normalArray;
-
-					nax  = normalArray[ i ];
-					nay  = normalArray[ i + 1 ];
-					naz  = normalArray[ i + 2 ];
-
-					nbx  = normalArray[ i + 3 ];
-					nby  = normalArray[ i + 4 ];
-					nbz  = normalArray[ i + 5 ];
-
-					ncx  = normalArray[ i + 6 ];
-					ncy  = normalArray[ i + 7 ];
-					ncz  = normalArray[ i + 8 ];
-
-					nx = ( nax + nbx + ncx ) / 3;
-					ny = ( nay + nby + ncy ) / 3;
-					nz = ( naz + nbz + ncz ) / 3;
-
-					normalArray[ i ] 	 = nx;
-					normalArray[ i + 1 ] = ny;
-					normalArray[ i + 2 ] = nz;
-
-					normalArray[ i + 3 ] = nx;
-					normalArray[ i + 4 ] = ny;
-					normalArray[ i + 5 ] = nz;
-
-					normalArray[ i + 6 ] = nx;
-					normalArray[ i + 7 ] = ny;
-					normalArray[ i + 8 ] = nz;
-
-				}
-
-			}
-
-			renderer.setDynamicArrayBuffer( object.__webglNormalBuffer, object.normalArray);
-			renderer.setFloatAttribute(program.attributes.normal, object.__webglNormalBuffer, 3, 0);
-
-		}
-
-		if ( object.hasUvs && material.map ) {
-
-			renderer.setDynamicArrayBuffer( object.__webglUvBuffer, object.uvArray);
-			renderer.setFloatAttribute(program.attributes.uv, object.__webglUvBuffer, 2, 0);
-
-		}
-
-		if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
-
-			renderer.setDynamicArrayBuffer( object.__webglColorBuffer, object.colorArray);
-			renderer.setFloatAttribute(program.attributes.color, object.__webglColorBuffer, 3, 0);
-
-		}
-
-		renderer.drawTriangles(object.count );
-		object.count = 0;
-
-	};
-
-	this.renderBufferDirect = function ( camera, lights, fog, material, geometry, object ) {
-
-		if ( material.visible === false ) return;
-
-		var program, programAttributes, linewidth, primitives, a, attribute, geometryAttributes;
-		var attributeItem, attributeName, attributePointer, attributeSize;
-
-		program = setProgram( camera, lights, fog, material, object );
-
-		programAttributes = program.attributes;
-		geometryAttributes = geometry.attributes;
-
-		var updateBuffers = false,
-			wireframeBit = material.wireframe ? 1 : 0,
-			geometryHash = ( geometry.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
-
-		if ( geometryHash !== _currentGeometryGroupHash ) {
-
-			_currentGeometryGroupHash = geometryHash;
-			updateBuffers = true;
-
-		}
-
-		if ( updateBuffers ) {
-
-			renderer.disableAttributes();
-
-		}
-
-		// render mesh
-
-		if ( object instanceof THREE.Mesh ) {
-
-			var index = geometryAttributes[ "index" ];
-
-			// indexed triangles
-
-			if ( index ) {
-
-				var offsets = geometry.offsets;
-
-				// if there is more than 1 chunk
-				// must set attribute pointers to use new offsets for each chunk
-				// even if geometry and materials didn't change
-
-				if ( offsets.length > 1 ) updateBuffers = true;
-
-				for ( var i = 0, il = offsets.length; i < il; i ++ ) {
-
-					var startIndex = offsets[ i ].index;
-
-					if ( updateBuffers ) {
-
-						for ( attributeName in geometryAttributes ) {
-
-							if ( attributeName === 'index' ) continue;
-
-							attributePointer = programAttributes[ attributeName ];
-							attributeItem = geometryAttributes[ attributeName ];
-							attributeSize = attributeItem.itemSize;
-
-							if ( attributePointer >= 0 ) {
-
-								renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, startIndex * attributeSize * 4 );
-
-							}
-
-						}
-					}
-
-					// render indexed triangles
-
-					renderer.drawTriangleElements(index.buffer, offsets[ i ].count, offsets[ i ].start * 2);
-
-					_this.info.render.calls ++;
-					_this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
-					_this.info.render.faces += offsets[ i ].count / 3;
-
-				}
-
-			// non-indexed triangles
-
-			} else {
-
-				if ( updateBuffers ) {
-
-					for ( attributeName in geometryAttributes ) {
-
-						attributePointer = programAttributes[ attributeName ];
-						attributeItem = geometryAttributes[ attributeName ];
-						attributeSize = attributeItem.itemSize;
-
-						if ( attributePointer >= 0 ) {
-
-							renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, 0 );
-
-						}
-
-					}
-
-				}
-
-				var position = geometry.attributes[ "position" ];
-
-				// render non-indexed triangles
-
-				renderer.drawTriangles( position.numItems / 3)
-
-				_this.info.render.calls ++;
-				_this.info.render.vertices += position.numItems / 3;
-				_this.info.render.faces += position.numItems / 3 / 3;
-
-			}
-
-		// render particles
-
-		} else if ( object instanceof THREE.ParticleSystem ) {
-
-			if ( updateBuffers ) {
-
-				for ( attributeName in geometryAttributes ) {
-
-					attributePointer = programAttributes[ attributeName ];
-					attributeItem = geometryAttributes[ attributeName ];
-					attributeSize = attributeItem.itemSize;
-
-					if ( attributePointer >= 0 ) {
-
-						renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, 0 );
-
-					}
-
-				}
-
-				var position = geometryAttributes[ "position" ];
-
-				// render particles
-				renderer.drawPoints(position.numItems / 3);
-
-				_this.info.render.calls ++;
-				_this.info.render.points += position.numItems / 3;
-
-			}
-
-		} else if ( object instanceof THREE.Line ) {
-
-			if ( updateBuffers ) {
-
-				for ( attributeName in geometryAttributes ) {
-
-					attributePointer = programAttributes[ attributeName ];
-					attributeItem = geometryAttributes[ attributeName ];
-					attributeSize = attributeItem.itemSize;
-
-					if ( attributePointer >= 0 ) {
-
-						renderer.setFloatAttribute( attributePointer , attributeItem.buffer, attributeSize, 0 );
-
-					}
-
-				}
-
-				var position = geometryAttributes[ "position" ];
-
-				// render lines
-				renderer.setLineWidth( material.linewidth );
-				renderer.drawLineStrip(position.numItems / 3);
-
-				_this.info.render.calls ++;
-				_this.info.render.points += position.numItems;
-
-			}
-
-		}
-
-	};
-
-	this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
-
-		if ( material.visible === false ) return;
-
-		var program, attributes, linewidth, primitives, a, attribute, i, il;
-
-		program = setProgram( camera, lights, fog, material, object );
-
-		attributes = program.attributes;
-
-		var updateBuffers = false,
-			wireframeBit = material.wireframe ? 1 : 0,
-			geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
-
-		if ( geometryGroupHash !== _currentGeometryGroupHash ) {
-
-			_currentGeometryGroupHash = geometryGroupHash;
-			updateBuffers = true;
-
-		}
-
-		if ( updateBuffers ) {
-
-			renderer.disableAttributes();
-
-		}
-
-		// vertices
-
-		if ( !material.morphTargets && attributes.position >= 0 ) {
-
-			if ( updateBuffers ) {
-
-				renderer.setFloatAttribute(attributes.position , geometryGroup.__webglVertexBuffer, 3, 0);
-
-			}
-
-		} else {
-
-			if ( object.morphTargetBase ) {
-
-				setupMorphTargets( material, geometryGroup, object );
-
-			}
-
-		}
-
-
-		if ( updateBuffers ) {
-
-			// custom attributes
-
-			// Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers
-
-			if ( geometryGroup.__webglCustomAttributesList ) {
-
-				for ( i = 0, il = geometryGroup.__webglCustomAttributesList.length; i < il; i ++ ) {
-
-					attribute = geometryGroup.__webglCustomAttributesList[ i ];
-
-					if ( attributes[ attribute.buffer.belongsToAttribute ] >= 0 ) {
-
-						renderer.setFloatAttribute(attributes[ attribute.buffer.belongsToAttribute ] , attribute.buffer, attribute.size, 0);
-
-					}
-
-				}
-
-			}
-
-
-			// colors
-
-			if ( attributes.color >= 0 ) {
-
-				renderer.setFloatAttribute(attributes.color , geometryGroup.__webglColorBuffer,3, 0);
-
-			}
-
-			// normals
-
-			if ( attributes.normal >= 0 ) {
-
-				renderer.setFloatAttribute(attributes.normal, geometryGroup.__webglNormalBuffer, 3, 0);
-
-			}
-
-			// tangents
-
-			if ( attributes.tangent >= 0 ) {
-
-				renderer.setFloatAttribute(attributes.tangent, geometryGroup.__webglTangentBuffer, 4, 0);
-
-			}
-
-			// uvs
-
-			if ( attributes.uv >= 0 ) {
-
-				renderer.setFloatAttribute(attributes.uv, geometryGroup.__webglUVBuffer, 2, 0);
-
-			}
-
-			if ( attributes.uv2 >= 0 ) {
-
-				renderer.setFloatAttribute(attributes.uv2, geometryGroup.__webglUV2Buffer, 2, 0);
-
-			}
-
-			if ( material.skinning &&
-				 attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
-
-				renderer.setFloatAttribute(attributes.skinIndex, geometryGroup.__webglSkinIndicesBuffer, 4, 0);
-				renderer.setFloatAttribute(attributes.skinWeight, geometryGroup.__webglSkinWeightsBuffer, 4, 0);
-
-			}
-
-			// line distances
-
-			if ( attributes.lineDistance >= 0 ) {
-
-				renderer.setFloatAttribute(attributes.lineDistance, geometryGroup.__webglLineDistanceBuffer, 1, 0);
-
-			}
-
-		}
-
-		// render mesh
-
-		if ( object instanceof THREE.Mesh ) {
-
-			// wireframe
-
-			if ( material.wireframe ) {
-
-				renderer.setLineWidth( material.wireframeLinewidth );
-				renderer.drawLineElements(geometryGroup.__webglLineBuffer,geometryGroup.__webglLineCount,0);
-
-			// triangles
-
-			} else {
-
-				renderer.drawTriangleElements( geometryGroup.__webglFaceBuffer, geometryGroup.__webglFaceCount, 0);
-
-			}
-
-			_this.info.render.calls ++;
-			_this.info.render.vertices += geometryGroup.__webglFaceCount;
-			_this.info.render.faces += geometryGroup.__webglFaceCount / 3;
-
-		// render lines
-
-		} else if ( object instanceof THREE.Line ) {
-
-			renderer.setLineWidth( material.linewidth );
-
-			if (object.type === THREE.LineStrip) {
-
-				renderer.drawLineStrip(geometryGroup.__webglLineCount);
-
-			} else {
-
-				renderer.drawLines(geometryGroup.__webglLineCount);
-
-			}
-
-			_this.info.render.calls ++;
-
-		// render particles
-
-		} else if ( object instanceof THREE.ParticleSystem ) {
-
-			renderer.drawPoints(geometryGroup.__webglParticleCount);
-
-			_this.info.render.calls ++;
-			_this.info.render.points += geometryGroup.__webglParticleCount;
-
-		// render ribbon
-
-		} else if ( object instanceof THREE.Ribbon ) {
-
-			renderer.drawTriangleStrip(geometryGroup.__webglVertexCount);
-
-			_this.info.render.calls ++;
-
-		}
-
-	};
-
-	function setupMorphTargets ( material, geometryGroup, object ) {
-
-		// set base
-
-		var attributes = material.program.attributes;
-
-		if ( object.morphTargetBase !== -1 && attributes.position >= 0 ) {
-
-			renderer.setFloatAttribute(attributes.position, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ], 3, 0);
-
-		} else if ( attributes.position >= 0 ) {
-
-			renderer.setFloatAttribute(attributes.position, geometryGroup.__webglVertexBuffer, 3, 0);
-
-		}
-
-		if ( object.morphTargetForcedOrder.length ) {
-
-			// set forced order
-
-			var m = 0;
-			var order = object.morphTargetForcedOrder;
-			var influences = object.morphTargetInfluences;
-
-			while ( m < material.numSupportedMorphTargets && m < order.length ) {
-
-				if ( attributes[ "morphTarget" + m ] >= 0 ) {
-
-					renderer.setFloatAttribute(attributes[ "morphTarget" + m ], geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ], 3, 0);
-
-				}
-
-				if ( attributes[ "morphNormal" + m ] >= 0 && material.morphNormals ) {
-
-					renderer.setFloatAttribute(attributes[ "morphNormal" + m ], geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ], 3, 0);
-
-				}
-
-				object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];
-
-				m ++;
-			}
-
-		} else {
-
-			// find the most influencing
-
-			var influence, activeInfluenceIndices = [];
-			var influences = object.morphTargetInfluences;
-			var i, il = influences.length;
-
-			for ( i = 0; i < il; i ++ ) {
-
-				influence = influences[ i ];
-
-				if ( influence > 0 ) {
-
-					activeInfluenceIndices.push( [ influence, i ] );
-
-				}
-
-			}
-
-			if ( activeInfluenceIndices.length > material.numSupportedMorphTargets ) {
-
-				activeInfluenceIndices.sort( numericalSort );
-				activeInfluenceIndices.length = material.numSupportedMorphTargets;
-
-			} else if ( activeInfluenceIndices.length > material.numSupportedMorphNormals ) {
-
-				activeInfluenceIndices.sort( numericalSort );
-
-			} else if ( activeInfluenceIndices.length === 0 ) {
-
-				activeInfluenceIndices.push( [ 0, 0 ] );
-
-			};
-
-			var influenceIndex, m = 0;
-
-			while ( m < material.numSupportedMorphTargets ) {
-
-				if ( activeInfluenceIndices[ m ] ) {
-
-					influenceIndex = activeInfluenceIndices[ m ][ 1 ];
-
-					if ( attributes[ "morphTarget" + m ] >= 0 ) {
-
-						renderer.setFloatAttribute(attributes[ "morphTarget" + m ], geometryGroup.__webglMorphTargetsBuffers[ influenceIndex ], 3, 0);
-
-					}
-
-					if ( attributes[ "morphNormal" + m ] >= 0 && material.morphNormals ) {
-
-						renderer.setFloatAttribute(attributes[ "morphNormal" + m ], geometryGroup.__webglMorphNormalsBuffers[ influenceIndex ], 3, 0);
-
-					}
-
-					object.__webglMorphTargetInfluences[ m ] = influences[ influenceIndex ];
-
-				} else {
-
-					/*
-					_gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
-
-					if ( material.morphNormals ) {
-
-						_gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
-
-					}
-					*/
-
-					object.__webglMorphTargetInfluences[ m ] = 0;
-
-				}
-
-				m ++;
-
-			}
-
-		}
-
-		// load updated influences uniform
-
-		if ( material.program.uniforms.morphTargetInfluences !== null ) {
-
-			renderer.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences );
-
-		}
-
-	};
-
-	// Sorting
-
-	function painterSortStable ( a, b ) {
-
-		if ( a.z !== b.z ) {
-
-			return b.z - a.z;
-
-		} else {
-
-			return a.id - b.id;
-
-		}
-
-	};
-
-	function numericalSort ( a, b ) {
-
-		return b[ 0 ] - a[ 0 ];
-
-	};
-
-
-	// Rendering
-
-	this.render = function ( scene, camera, renderTarget, forceClear ) {
-
-		if ( camera instanceof THREE.Camera === false ) {
-
-			console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
-			return;
-
-		}
-
-		var i, il,
-
-		webglObject, object,
-		renderList,
-
-		lights = scene.__lights,
-		fog = scene.fog;
-
-		// reset caching for this frame
-
-		_currentMaterialId = -1;
-		_lightsNeedUpdate = true;
-
-		// update scene graph
-
-		if ( scene.autoUpdate === true ) scene.updateMatrixWorld();
-
-		// update camera matrices and frustum
-
-		if ( camera.parent === undefined ) camera.updateMatrixWorld();
-
-		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
-
-		_projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse );
-		_frustum.setFromMatrix( _projScreenMatrix );
-
-		// update WebGL objects
-
-		if ( this.autoUpdateObjects ) this.initWebGLObjects( scene );
-
-		// custom render plugins (pre pass)
-
-		renderPlugins( this.renderPluginsPre, scene, camera );
-
-		//
-
-		_this.info.render.calls = 0;
-		_this.info.render.vertices = 0;
-		_this.info.render.faces = 0;
-		_this.info.render.points = 0;
-
-		renderer.setRenderTarget( renderTarget );
-
-		if ( this.autoClear || forceClear ) {
-
-			this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
-
-		}
-
-		// set matrices for regular objects (frustum culled)
-
-		renderList = scene.__webglObjects;
-
-		for ( i = 0, il = renderList.length; i < il; i ++ ) {
-
-			webglObject = renderList[ i ];
-			object = webglObject.object;
-
-			webglObject.id = i;
-			webglObject.render = false;
-
-			if ( object.visible ) {
-
-				if ( ! ( object instanceof THREE.Mesh || object instanceof THREE.ParticleSystem ) || ! ( object.frustumCulled ) || _frustum.intersectsObject( object ) ) {
-
-					setupMatrices( object, camera );
-
-					unrollBufferMaterial( webglObject );
-
-					webglObject.render = true;
-
-					if ( this.sortObjects === true ) {
-
-						if ( object.renderDepth !== null ) {
-
-							webglObject.z = object.renderDepth;
-
-						} else {
-
-							_vector3.getPositionFromMatrix( object.matrixWorld );
-							_vector3.applyProjection(_projScreenMatrix);
-
-							webglObject.z = _vector3.z;
-
-						}
-
-					}
-
-				}
-
-			}
-
-		}
-
-		if ( this.sortObjects ) {
-
-			renderList.sort( painterSortStable );
-
-		}
-
-		// set matrices for immediate objects
-
-		renderList = scene.__webglObjectsImmediate;
-
-		for ( i = 0, il = renderList.length; i < il; i ++ ) {
-
-			webglObject = renderList[ i ];
-			object = webglObject.object;
-
-			if ( object.visible ) {
-
-				setupMatrices( object, camera );
-
-				unrollImmediateBufferMaterial( webglObject );
-
-			}
-
-		}
-
-		if ( scene.overrideMaterial ) {
-
-			var material = scene.overrideMaterial;
-
-			renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
-			renderer.setDepthTest( material.depthTest );
-			renderer.setDepthWrite( material.depthWrite );
-			renderer.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
-
-			renderObjects( scene.__webglObjects, false, "", camera, lights, fog, true, material );
-			renderObjectsImmediate( scene.__webglObjectsImmediate, "", camera, lights, fog, false, material );
-
-		} else {
-
-			var material = null;
-
-			// opaque pass (front-to-back order)
-
-			renderer.setBlending( THREE.NoBlending );
-
-			renderObjects( scene.__webglObjects, true, "opaque", camera, lights, fog, false, material );
-			renderObjectsImmediate( scene.__webglObjectsImmediate, "opaque", camera, lights, fog, false, material );
-
-			// transparent pass (back-to-front order)
-
-			renderObjects( scene.__webglObjects, false, "transparent", camera, lights, fog, true, material );
-			renderObjectsImmediate( scene.__webglObjectsImmediate, "transparent", camera, lights, fog, true, material );
-
-		}
-
-		// custom render plugins (post pass)
-
-		renderPlugins( this.renderPluginsPost, scene, camera );
-
-
-		// Generate mipmap if we're using any kind of mipmap filtering
-
-		if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {
-
-			renderer.updateRenderTargetMipmap( renderTarget );
-
-		}
-
-		// Ensure depth buffer writing is enabled so it can be cleared on next render
-
-		renderer.setDepthTest( true );
-		renderer.setDepthWrite( true );
-
-		// _gl.finish();
-
-	};
-
-	function renderPlugins( plugins, scene, camera ) {
-
-		if ( ! plugins.length ) return;
-
-		for ( var i = 0, il = plugins.length; i < il; i ++ ) {
-
-			// reset state for plugin (to start from clean slate)
-
-			_currentProgram = null;
-			_currentCamera = null;
-			_currentGeometryGroupHash = -1;
-			_currentMaterialId = -1;
-			_lightsNeedUpdate = true;
-			renderer.resetState();
-
-			plugins[ i ].render( scene, camera, renderer.getCurrentWidth(), renderer.getCurrentHeight() );
-
-			// reset state after plugin (anything could have changed)
-
-			_currentProgram = null;
-			_currentCamera = null;
-			_currentGeometryGroupHash = -1;
-			_currentMaterialId = -1;
-			_lightsNeedUpdate = true;
-			renderer.resetState();
-
-		}
-
-	};
-
-	function renderObjects ( renderList, reverse, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
-
-		var webglObject, object, buffer, material, start, end, delta;
-
-		if ( reverse ) {
-
-			start = renderList.length - 1;
-			end = -1;
-			delta = -1;
-
-		} else {
-
-			start = 0;
-			end = renderList.length;
-			delta = 1;
-		}
-
-		for ( var i = start; i !== end; i += delta ) {
-
-			webglObject = renderList[ i ];
-
-			if ( webglObject.render ) {
-
-				object = webglObject.object;
-				buffer = webglObject.buffer;
-
-				if ( overrideMaterial ) {
-
-					material = overrideMaterial;
-
-				} else {
-
-					material = webglObject[ materialType ];
-
-					if ( ! material ) continue;
-
-					if ( useBlending ) renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
-
-					renderer.setDepthTest( material.depthTest );
-					renderer.setDepthWrite( material.depthWrite );
-					renderer.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
-
-				}
-
-				renderer.setMaterialFaces( material );
-
-				if ( buffer instanceof THREE.BufferGeometry ) {
-
-					_this.renderBufferDirect( camera, lights, fog, material, buffer, object );
-
-				} else {
-
-					_this.renderBuffer( camera, lights, fog, material, buffer, object );
-
-				}
-
-			}
-
-		}
-
-	};
-
-	function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
-
-		var webglObject, object, material, program;
-
-		for ( var i = 0, il = renderList.length; i < il; i ++ ) {
-
-			webglObject = renderList[ i ];
-			object = webglObject.object;
-
-			if ( object.visible ) {
-
-				if ( overrideMaterial ) {
-
-					material = overrideMaterial;
-
-				} else {
-
-					material = webglObject[ materialType ];
-
-					if ( ! material ) continue;
-
-					if ( useBlending ) renderer.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
-
-					renderer.setDepthTest( material.depthTest );
-					renderer.setDepthWrite( material.depthWrite );
-					renderer.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
-
-				}
-
-				_this.renderImmediateObject( camera, lights, fog, material, object );
-
-			}
-
-		}
-
-	};
-
-	this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
-
-		var program = setProgram( camera, lights, fog, material, object );
-
-		_currentGeometryGroupHash = -1;
-
-		renderer.setMaterialFaces( material );
-
-		if ( object.immediateRenderCallback ) {
-
-			object.immediateRenderCallback( program, renderer.getContext(), _frustum );
-
-		} else {
-
-			object.render( function( object ) { _this.renderBufferImmediate( object, program, material ); } );
-
-		}
-
-	};
-
-	function unrollImmediateBufferMaterial ( globject ) {
-
-		var object = globject.object,
-			material = object.material;
-
-		if ( material.transparent ) {
-
-			globject.transparent = material;
-			globject.opaque = null;
-
-		} else {
-
-			globject.opaque = material;
-			globject.transparent = null;
-
-		}
-
-	};
-
-	function unrollBufferMaterial ( globject ) {
-
-		var object = globject.object,
-			buffer = globject.buffer,
-			material, materialIndex, meshMaterial;
-
-		meshMaterial = object.material;
-
-		if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
-
-			materialIndex = buffer.materialIndex;
-
-			material = meshMaterial.materials[ materialIndex ];
-
-			if ( material.transparent ) {
-
-				globject.transparent = material;
-				globject.opaque = null;
-
-			} else {
-
-				globject.opaque = material;
-				globject.transparent = null;
-
-			}
-
-		} else {
-
-			material = meshMaterial;
-
-			if ( material ) {
-
-				if ( material.transparent ) {
-
-					globject.transparent = material;
-					globject.opaque = null;
-
-				} else {
-
-					globject.opaque = material;
-					globject.transparent = null;
-
-				}
-
-			}
-
-		}
-
-	};
-
-	// Geometry splitting
-
-	function sortFacesByMaterial ( geometry, material ) {
-
-		var f, fl, face, materialIndex, vertices,
-			groupHash, hash_map = {};
-
-		var numMorphTargets = geometry.morphTargets.length;
-		var numMorphNormals = geometry.morphNormals.length;
-
-		var usesFaceMaterial = material instanceof THREE.MeshFaceMaterial;
-
-		geometry.geometryGroups = {};
-
-		for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
-
-			face = geometry.faces[ f ];
-			materialIndex = usesFaceMaterial ? face.materialIndex : 0;
-
-			if ( hash_map[ materialIndex ] === undefined ) {
-
-				hash_map[ materialIndex ] = { 'hash': materialIndex, 'counter': 0 };
-
-			}
-
-			groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
-
-			if ( geometry.geometryGroups[ groupHash ] === undefined ) {
-
-				geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
-
-			}
-
-			vertices = face instanceof THREE.Face3 ? 3 : 4;
-
-			if ( geometry.geometryGroups[ groupHash ].vertices + vertices > 65535 ) {
-
-				hash_map[ materialIndex ].counter += 1;
-				groupHash = hash_map[ materialIndex ].hash + '_' + hash_map[ materialIndex ].counter;
-
-				if ( geometry.geometryGroups[ groupHash ] === undefined ) {
-
-					geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
-
-				}
-
-			}
-
-			if ( face instanceof THREE.Face3 ) {
-
-				geometry.geometryGroups[ groupHash ].faces3.push( f );
-
-			} else {
-
-				geometry.geometryGroups[ groupHash ].faces4.push( f );
-
-			}
-
-			geometry.geometryGroups[ groupHash ].vertices += vertices;
-
-		}
-
-		geometry.geometryGroupsList = [];
-
-		for ( var g in geometry.geometryGroups ) {
-
-			geometry.geometryGroups[ g ].id = _geometryGroupCounter ++;
-
-			geometry.geometryGroupsList.push( geometry.geometryGroups[ g ] );
-
-		}
-
-	};
-
-	// Objects refresh
-
-	this.initWebGLObjects = function ( scene ) {
-
-		if ( !scene.__webglObjects ) {
-
-			scene.__webglObjects = [];
-			scene.__webglObjectsImmediate = [];
-			scene.__webglSprites = [];
-			scene.__webglFlares = [];
-
-		}
-
-		while ( scene.__objectsAdded.length ) {
-
-			addObject( scene.__objectsAdded[ 0 ], scene );
-			scene.__objectsAdded.splice( 0, 1 );
-
-		}
-
-		while ( scene.__objectsRemoved.length ) {
-
-			removeObject( scene.__objectsRemoved[ 0 ], scene );
-			scene.__objectsRemoved.splice( 0, 1 );
-
-		}
-
-		// update must be called after objects adding / removal
-
-		for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {
-
-			updateObject( scene.__webglObjects[ o ].object );
-
-		}
-
-	};
-
-	// Objects adding
-
-	function addObject( object, scene ) {
-
-		var g, geometry, material, geometryGroup;
-
-		if ( ! object.__webglInit ) {
-
-			object.__webglInit = true;
-
-			object._modelViewMatrix = new THREE.Matrix4();
-			object._normalMatrix = new THREE.Matrix3();
-
-			if ( object.geometry !== undefined && object.geometry.__webglInit === undefined ) {
-
-				object.geometry.__webglInit = true;
-				object.geometry.addEventListener( 'dispose', onGeometryDispose );
-
-			}
-
-			if ( object instanceof THREE.Mesh ) {
-
-				geometry = object.geometry;
-				material = object.material;
-
-				if ( geometry instanceof THREE.Geometry ) {
-
-					if ( geometry.geometryGroups === undefined ) {
-
-						sortFacesByMaterial( geometry, material );
-
-					}
-
-					// create separate VBOs per geometry chunk
-
-					for ( g in geometry.geometryGroups ) {
-
-						geometryGroup = geometry.geometryGroups[ g ];
-
-						// initialise VBO on the first access
-
-						if ( ! geometryGroup.__webglVertexBuffer ) {
-
-							meshRenderer.createBuffers( geometryGroup );
-							meshRenderer.initBuffers( geometryGroup, object );
-
-							geometry.verticesNeedUpdate = true;
-							geometry.morphTargetsNeedUpdate = true;
-							geometry.elementsNeedUpdate = true;
-							geometry.uvsNeedUpdate = true;
-							geometry.normalsNeedUpdate = true;
-							geometry.tangentsNeedUpdate = true;
-							geometry.colorsNeedUpdate = true;
-
-						}
-
-					}
-
-				} else if ( geometry instanceof THREE.BufferGeometry ) {
-
-					initDirectBuffers( geometry );
-
-				}
-
-			} else if ( object instanceof THREE.Ribbon ) {
-
-				geometry = object.geometry;
-
-				if ( ! geometry.__webglVertexBuffer ) {
-
-					ribbonRenderer.createBuffers( geometry );
-					ribbonRenderer.initBuffers( geometry, object );
-
-					geometry.verticesNeedUpdate = true;
-					geometry.colorsNeedUpdate = true;
-					geometry.normalsNeedUpdate = true;
-
-				}
-
-			} else if ( object instanceof THREE.Line ) {
-
-				geometry = object.geometry;
-
-				if ( ! geometry.__webglVertexBuffer ) {
-
-					if ( geometry instanceof THREE.Geometry ) {
-
-						lineRenderer.createBuffers( geometry );
-						lineRenderer.initBuffers( geometry, object );
-
-						geometry.verticesNeedUpdate = true;
-						geometry.colorsNeedUpdate = true;
-						geometry.lineDistancesNeedUpdate = true;
-
-					} else if ( geometry instanceof THREE.BufferGeometry ) {
-
-						initDirectBuffers( geometry );
-
-					}
-
-				}
-
-			} else if ( object instanceof THREE.ParticleSystem ) {
-
-				geometry = object.geometry;
-
-				if ( ! geometry.__webglVertexBuffer ) {
-
-					if ( geometry instanceof THREE.Geometry ) {
-
-						particleRenderer.createBuffers( geometry );
-						particleRenderer.initBuffers( geometry, object );
-
-						geometry.verticesNeedUpdate = true;
-						geometry.colorsNeedUpdate = true;
-
-					} else if ( geometry instanceof THREE.BufferGeometry ) {
-
-						initDirectBuffers( geometry );
-
-					}
-
-
-				}
-
-			}
-
-		}
-
-		if ( ! object.__webglActive ) {
-
-			if ( object instanceof THREE.Mesh ) {
-
-				geometry = object.geometry;
-
-				if ( geometry instanceof THREE.BufferGeometry ) {
-
-					addBuffer( scene.__webglObjects, geometry, object );
-
-				} else if ( geometry instanceof THREE.Geometry ) {
-
-					for ( g in geometry.geometryGroups ) {
-
-						geometryGroup = geometry.geometryGroups[ g ];
-
-						addBuffer( scene.__webglObjects, geometryGroup, object );
-
-					}
-
-				}
-
-			} else if ( object instanceof THREE.Ribbon ||
-						object instanceof THREE.Line ||
-						object instanceof THREE.ParticleSystem ) {
-
-				geometry = object.geometry;
-				addBuffer( scene.__webglObjects, geometry, object );
-
-			} else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
-
-				addBufferImmediate( scene.__webglObjectsImmediate, object );
-
-			} else if ( object instanceof THREE.Sprite ) {
-
-				scene.__webglSprites.push( object );
-
-			} else if ( object instanceof THREE.LensFlare ) {
-
-				scene.__webglFlares.push( object );
-
-			}
-
-			object.__webglActive = true;
-
-		}
-
-	};
-
-	function addBuffer ( objlist, buffer, object ) {
-
-		objlist.push(
-			{
-				id: null,
-				buffer: buffer,
-				object: object,
-				opaque: null,
-				transparent: null,
-				render: false,
-				z: 0
-			}
-		);
-
-	};
-
-	function addBufferImmediate ( objlist, object ) {
-
-		objlist.push(
-			{
-				object: object,
-				opaque: null,
-				transparent: null
-			}
-		);
-
-	};
-
-	// Objects updates
-
-	function updateObject ( object ) {
-
-		var geometry = object.geometry,
-			geometryGroup, customAttributesDirty, material;
-
-		if ( object instanceof THREE.Mesh ) {
-
-			if ( geometry instanceof THREE.BufferGeometry ) {
-
-				if ( geometry.verticesNeedUpdate || geometry.elementsNeedUpdate ||
-					 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
-					 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate ) {
-
-					setDirectBuffers( geometry, !geometry.dynamic );
-
-				}
-
-				geometry.verticesNeedUpdate = false;
-				geometry.elementsNeedUpdate = false;
-				geometry.uvsNeedUpdate = false;
-				geometry.normalsNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-				geometry.tangentsNeedUpdate = false;
-
-			} else {
-
-				// check all geometry groups
-
-				for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
-
-					geometryGroup = geometry.geometryGroupsList[ i ];
-
-					material = getBufferMaterial( object, geometryGroup );
-
-					if ( geometry.buffersNeedUpdate ) {
-
-						meshRenderer.initBuffers( geometryGroup, object );
-
-					}
-
-					customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
-
-					if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate ||
-						 geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
-						 geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) {
-
-						meshRenderer.setBuffers( geometryGroup, object, !geometry.dynamic, material );
-
-					}
-
-				}
-
-				geometry.verticesNeedUpdate = false;
-				geometry.morphTargetsNeedUpdate = false;
-				geometry.elementsNeedUpdate = false;
-				geometry.uvsNeedUpdate = false;
-				geometry.normalsNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-				geometry.tangentsNeedUpdate = false;
-
-				geometry.buffersNeedUpdate = false;
-
-				material.attributes && clearCustomAttributes( material );
-
-			}
-
-		} else if ( object instanceof THREE.Ribbon ) {
-
-			material = getBufferMaterial( object, geometry );
-
-			customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
-
-			if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.normalsNeedUpdate || customAttributesDirty ) {
-
-				ribbonRenderer.setBuffers( geometry);
-
-			}
-
-			geometry.verticesNeedUpdate = false;
-			geometry.colorsNeedUpdate = false;
-			geometry.normalsNeedUpdate = false;
-
-			material.attributes && clearCustomAttributes( material );
-
-		} else if ( object instanceof THREE.Line ) {
-
-			if ( geometry instanceof THREE.BufferGeometry ) {
-
-				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
-
-					setDirectBuffers( geometry,  !geometry.dynamic );
-
-				}
-
-				geometry.verticesNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-
-			} else {
-
-				material = getBufferMaterial( object, geometry );
-
-				customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
-
-				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || geometry.lineDistancesNeedUpdate || customAttributesDirty ) {
-
-					lineRenderer.setBuffers( geometry);
-
-				}
-
-				geometry.verticesNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-				geometry.lineDistancesNeedUpdate = false;
-
-				material.attributes && clearCustomAttributes( material );
-
-			}
-
-		} else if ( object instanceof THREE.ParticleSystem ) {
-
-			if ( geometry instanceof THREE.BufferGeometry ) {
-
-				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
-
-					setDirectBuffers( geometry, !geometry.dynamic );
-
-				}
-
-				geometry.verticesNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-
-			} else {
-
-				material = getBufferMaterial( object, geometry );
-
-				customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
-
-				if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || object.sortParticles || customAttributesDirty ) {
-
-					particleRenderer.setBuffers( geometry, object, _projScreenMatrix);
-
-				}
-
-				geometry.verticesNeedUpdate = false;
-				geometry.colorsNeedUpdate = false;
-
-				material.attributes && clearCustomAttributes( material );
-
-			}
-
-		}
-
-	};
-
-	// Objects updates - custom attributes check
-
-	function areCustomAttributesDirty ( material ) {
-
-		for ( var a in material.attributes ) {
-
-			if ( material.attributes[ a ].needsUpdate ) return true;
-
-		}
-
-		return false;
-
-	};
-
-	function clearCustomAttributes ( material ) {
-
-		for ( var a in material.attributes ) {
-
-			material.attributes[ a ].needsUpdate = false;
-
-		}
-
-	};
-
-	// Objects removal
-
-	function removeObject ( object, scene ) {
-
-		if ( object instanceof THREE.Mesh  ||
-			 object instanceof THREE.ParticleSystem ||
-			 object instanceof THREE.Ribbon ||
-			 object instanceof THREE.Line ) {
-
-			removeInstances( scene.__webglObjects, object );
-
-		} else if ( object instanceof THREE.Sprite ) {
-
-			removeInstancesDirect( scene.__webglSprites, object );
-
-		} else if ( object instanceof THREE.LensFlare ) {
-
-			removeInstancesDirect( scene.__webglFlares, object );
-
-		} else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
-
-			removeInstances( scene.__webglObjectsImmediate, object );
-
-		}
-
-		object.__webglActive = false;
-
-	};
-
-	function removeInstances ( objlist, object ) {
-
-		for ( var o = objlist.length - 1; o >= 0; o -- ) {
-
-			if ( objlist[ o ].object === object ) {
-
-				objlist.splice( o, 1 );
-
-			}
-
-		}
-
-	};
-
-	function removeInstancesDirect ( objlist, object ) {
-
-		for ( var o = objlist.length - 1; o >= 0; o -- ) {
-
-			if ( objlist[ o ] === object ) {
-
-				objlist.splice( o, 1 );
-
-			}
-
-		}
-
-	};
-
-	// Materials
-
-	this.initMaterial = function ( material, lights, fog, object ) {
-
-		material.addEventListener( 'dispose', onMaterialDispose );
-
-		var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
-
-		if ( material instanceof THREE.MeshDepthMaterial ) {
-
-			shaderID = 'depth';
-
-		} else if ( material instanceof THREE.MeshNormalMaterial ) {
-
-			shaderID = 'normal';
-
-		} else if ( material instanceof THREE.MeshBasicMaterial ) {
-
-			shaderID = 'basic';
-
-		} else if ( material instanceof THREE.MeshLambertMaterial ) {
-
-			shaderID = 'lambert';
-
-		} else if ( material instanceof THREE.MeshPhongMaterial ) {
-
-			shaderID = 'phong';
-
-		} else if ( material instanceof THREE.LineBasicMaterial ) {
-
-			shaderID = 'basic';
-
-		} else if ( material instanceof THREE.LineDashedMaterial ) {
-
-			shaderID = 'dashed';
-
-		} else if ( material instanceof THREE.ParticleBasicMaterial ) {
-
-			shaderID = 'particle_basic';
-
-		}
-
-		if ( shaderID ) {
-
-			setMaterialShaders( material, THREE.ShaderLib[ shaderID ] );
-
-		}
-
-		// heuristics to create shader parameters according to lights in the scene
-		// (not to blow over maxLights budget)
-
-		maxLightCount = allocateLights( lights );
-
-		maxShadows = allocateShadows( lights );
-
-		maxBones = allocateBones( object );
-
-		parameters = {
-
-			map: !!material.map,
-			envMap: !!material.envMap,
-			lightMap: !!material.lightMap,
-			bumpMap: !!material.bumpMap,
-			normalMap: !!material.normalMap,
-			specularMap: !!material.specularMap,
-
-			vertexColors: material.vertexColors,
-
-			fog: fog,
-			useFog: material.fog,
-			fogExp: fog instanceof THREE.FogExp2,
-
-			sizeAttenuation: material.sizeAttenuation,
-
-			skinning: material.skinning,
-			maxBones: maxBones,
-			useVertexTexture: renderer.supportsBoneTextures && object && object.useVertexTexture,
-			boneTextureWidth: object && object.boneTextureWidth,
-			boneTextureHeight: object && object.boneTextureHeight,
-
-			morphTargets: material.morphTargets,
-			morphNormals: material.morphNormals,
-			maxMorphTargets: this.maxMorphTargets,
-			maxMorphNormals: this.maxMorphNormals,
-
-			maxDirLights: maxLightCount.directional,
-			maxPointLights: maxLightCount.point,
-			maxSpotLights: maxLightCount.spot,
-			maxHemiLights: maxLightCount.hemi,
-
-			maxShadows: maxShadows,
-			shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
-			shadowMapType: this.shadowMapType,
-			shadowMapDebug: this.shadowMapDebug,
-			shadowMapCascade: this.shadowMapCascade,
-
-			alphaTest: material.alphaTest,
-			metal: material.metal,
-			perPixel: material.perPixel,
-			wrapAround: material.wrapAround,
-			doubleSided: material.side === THREE.DoubleSide,
-			flipSided: material.side === THREE.BackSide,
-
-			gammaInput : this.gammaInput,
-			gammaOutput  : this.gammaOutput ,
-			physicallyBasedShading : this.physicallyBasedShading
-
-		};
-
-		material.program = shaderBuilder.buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, material.defines, parameters );
-
-		var attributes = material.program.attributes;
-
-		if ( material.morphTargets ) {
-
-			material.numSupportedMorphTargets = 0;
-
-			var id, base = "morphTarget";
-
-			for ( i = 0; i < this.maxMorphTargets; i ++ ) {
-
-				id = base + i;
-
-				if ( attributes[ id ] >= 0 ) {
-
-					material.numSupportedMorphTargets ++;
-
-				}
-
-			}
-
-		}
-
-		if ( material.morphNormals ) {
-
-			material.numSupportedMorphNormals = 0;
-
-			var id, base = "morphNormal";
-
-			for ( i = 0; i < this.maxMorphNormals; i ++ ) {
-
-				id = base + i;
-
-				if ( attributes[ id ] >= 0 ) {
-
-					material.numSupportedMorphNormals ++;
-
-				}
-
-			}
-
-		}
-
-		material.uniformsList = [];
-
-		for ( u in material.uniforms ) {
-
-			material.uniformsList.push( [ material.uniforms[ u ], u ] );
-
-		}
-
-	};
-
-	function setMaterialShaders( material, shaders ) {
-
-		material.uniforms = THREE.UniformsUtils.clone( shaders.uniforms );
-		material.vertexShader = shaders.vertexShader;
-		material.fragmentShader = shaders.fragmentShader;
-
-	};
-
-	function setProgram( camera, lights, fog, material, object ) {
-
-		_usedTextureUnits = 0;
-
-		if ( material.needsUpdate ) {
-
-			if ( material.program ) deallocateMaterial( material );
-
-			_this.initMaterial( material, lights, fog, object );
-			material.needsUpdate = false;
-
-		}
-
-		if ( material.morphTargets ) {
-
-			if ( ! object.__webglMorphTargetInfluences ) {
-
-				object.__webglMorphTargetInfluences = new Float32Array( _this.maxMorphTargets );
-
-			}
-
-		}
-
-		var refreshMaterial = false;
-
-		var program = material.program,
-			p_uniforms = program.uniforms,
-			m_uniforms = material.uniforms;
-
-		if ( program !== _currentProgram ) {
-
-			renderer.useProgram( program );
-			_currentProgram = program;
-
-			refreshMaterial = true;
-
-		}
-
-		if ( material.id !== _currentMaterialId ) {
-
-			_currentMaterialId = material.id;
-			refreshMaterial = true;
-
-		}
-
-		if ( refreshMaterial || camera !== _currentCamera ) {
-
-			renderer.uniformMatrix4fv( p_uniforms.projectionMatrix, camera.projectionMatrix.elements );
-
-			if ( camera !== _currentCamera ) _currentCamera = camera;
-
-		}
-
-		// skinning uniforms must be set even if material didn't change
-		// auto-setting of texture unit for bone texture must go before other textures
-		// not sure why, but otherwise weird things happen
-
-		if ( material.skinning ) {
-
-			if ( renderer.supportsBoneTextures && object.useVertexTexture ) {
-
-				if ( p_uniforms.boneTexture !== null ) {
-
-					var textureUnit = getTextureUnit();
-
-					renderer.uniform1i( p_uniforms.boneTexture, textureUnit );
-					renderer.setTexture( object.boneTexture, textureUnit );
-
-				}
-
-			} else {
-
-				if ( p_uniforms.boneGlobalMatrices !== null ) {
-
-					renderer.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, object.boneMatrices );
-
-				}
-
-			}
-
-		}
-
-		if ( refreshMaterial ) {
-
-			// refresh uniforms common to several materials
-
-			if ( fog && material.fog ) {
-
-				refreshUniformsFog( m_uniforms, fog );
-
-			}
-
-			if ( material instanceof THREE.MeshPhongMaterial ||
-				 material instanceof THREE.MeshLambertMaterial ||
-				 material.lights ) {
-
-				if ( _lightsNeedUpdate ) {
-
-					setupLights( program, lights );
-					_lightsNeedUpdate = false;
-
-				}
-
-				refreshUniformsLights( m_uniforms, _lights );
-
-			}
-
-			if ( material instanceof THREE.MeshBasicMaterial ||
-				 material instanceof THREE.MeshLambertMaterial ||
-				 material instanceof THREE.MeshPhongMaterial ) {
-
-				refreshUniformsCommon( m_uniforms, material );
-
-			}
-
-			// refresh single material specific uniforms
-
-			if ( material instanceof THREE.LineBasicMaterial ) {
-
-				refreshUniformsLine( m_uniforms, material );
-
-			} else if ( material instanceof THREE.LineDashedMaterial ) {
-
-				refreshUniformsLine( m_uniforms, material );
-				refreshUniformsDash( m_uniforms, material );
-
-			} else if ( material instanceof THREE.ParticleBasicMaterial ) {
-
-				refreshUniformsParticle( m_uniforms, material );
-
-			} else if ( material instanceof THREE.MeshPhongMaterial ) {
-
-				refreshUniformsPhong( m_uniforms, material );
-
-			} else if ( material instanceof THREE.MeshLambertMaterial ) {
-
-				refreshUniformsLambert( m_uniforms, material );
-
-			} else if ( material instanceof THREE.MeshDepthMaterial ) {
-
-				m_uniforms.mNear.value = camera.near;
-				m_uniforms.mFar.value = camera.far;
-				m_uniforms.opacity.value = material.opacity;
-
-			} else if ( material instanceof THREE.MeshNormalMaterial ) {
-
-				m_uniforms.opacity.value = material.opacity;
-
-			}
-
-			if ( object.receiveShadow && ! material._shadowPass ) {
-
-				refreshUniformsShadow( m_uniforms, lights );
-
-			}
-
-			// load common uniforms
-
-			loadUniformsGeneric( program, material.uniformsList );
-
-			// load material specific uniforms
-			// (shader material also gets them for the sake of genericity)
-
-			if ( material instanceof THREE.ShaderMaterial ||
-				 material instanceof THREE.MeshPhongMaterial ||
-				 material.envMap ) {
-
-				if ( p_uniforms.cameraPosition !== null ) {
-
-					_vector3.getPositionFromMatrix( camera.matrixWorld );
-					renderer.uniform3f( p_uniforms.cameraPosition, _vector3.x, _vector3.y, _vector3.z );
-
-				}
-
-			}
-
-			if ( material instanceof THREE.MeshPhongMaterial ||
-				 material instanceof THREE.MeshLambertMaterial ||
-				 material instanceof THREE.ShaderMaterial ||
-				 material.skinning ) {
-
-				if ( p_uniforms.viewMatrix !== null ) {
-
-					renderer.uniformMatrix4fv( p_uniforms.viewMatrix, camera.matrixWorldInverse.elements );
-
-				}
-
-			}
-
-		}
-
-		loadUniformsMatrices( p_uniforms, object );
-
-		if ( p_uniforms.modelMatrix !== null ) {
-
-			renderer.uniformMatrix4fv( p_uniforms.modelMatrix, object.matrixWorld.elements );
-
-		}
-
-		return program;
-
-	};
-
-	// Uniforms (refresh uniforms objects)
-
-	function refreshUniformsCommon ( uniforms, material ) {
-
-		uniforms.opacity.value = material.opacity;
-
-		if ( _this.gammaInput ) {
-
-			uniforms.diffuse.value.copyGammaToLinear( material.color );
-
-		} else {
-
-			uniforms.diffuse.value = material.color;
-
-		}
-
-		uniforms.map.value = material.map;
-		uniforms.lightMap.value = material.lightMap;
-		uniforms.specularMap.value = material.specularMap;
-
-		if ( material.bumpMap ) {
-
-			uniforms.bumpMap.value = material.bumpMap;
-			uniforms.bumpScale.value = material.bumpScale;
-
-		}
-
-		if ( material.normalMap ) {
-
-			uniforms.normalMap.value = material.normalMap;
-			uniforms.normalScale.value.copy( material.normalScale );
-
-		}
-
-		// uv repeat and offset setting priorities
-		//	1. color map
-		//	2. specular map
-		//	3. normal map
-		//	4. bump map
-
-		var uvScaleMap;
-
-		if ( material.map ) {
-
-			uvScaleMap = material.map;
-
-		} else if ( material.specularMap ) {
-
-			uvScaleMap = material.specularMap;
-
-		} else if ( material.normalMap ) {
-
-			uvScaleMap = material.normalMap;
-
-		} else if ( material.bumpMap ) {
-
-			uvScaleMap = material.bumpMap;
-
-		}
-
-		if ( uvScaleMap !== undefined ) {
-
-			var offset = uvScaleMap.offset;
-			var repeat = uvScaleMap.repeat;
-
-			uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
-
-		}
-
-		uniforms.envMap.value = material.envMap;
-		uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : -1;
-
-		if ( _this.gammaInput ) {
-
-			//uniforms.reflectivity.value = material.reflectivity * material.reflectivity;
-			uniforms.reflectivity.value = material.reflectivity;
-
-		} else {
-
-			uniforms.reflectivity.value = material.reflectivity;
-
-		}
-
-		uniforms.refractionRatio.value = material.refractionRatio;
-		uniforms.combine.value = material.combine;
-		uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping;
-
-	};
-
-	function refreshUniformsLine ( uniforms, material ) {
-
-		uniforms.diffuse.value = material.color;
-		uniforms.opacity.value = material.opacity;
-
-	};
-
-	function refreshUniformsDash ( uniforms, material ) {
-
-		uniforms.dashSize.value = material.dashSize;
-		uniforms.totalSize.value = material.dashSize + material.gapSize;
-		uniforms.scale.value = material.scale;
-
-	};
-
-	function refreshUniformsParticle ( uniforms, material ) {
-
-		uniforms.psColor.value = material.color;
-		uniforms.opacity.value = material.opacity;
-		uniforms.size.value = material.size;
-		uniforms.scale.value = renderer.getDomElement().height / 2.0; // TODO: Cache this.
-
-		uniforms.map.value = material.map;
-
-	};
-
-	function refreshUniformsFog ( uniforms, fog ) {
-
-		uniforms.fogColor.value = fog.color;
-
-		if ( fog instanceof THREE.Fog ) {
-
-			uniforms.fogNear.value = fog.near;
-			uniforms.fogFar.value = fog.far;
-
-		} else if ( fog instanceof THREE.FogExp2 ) {
-
-			uniforms.fogDensity.value = fog.density;
-
-		}
-
-	};
-
-	function refreshUniformsPhong ( uniforms, material ) {
-
-		uniforms.shininess.value = material.shininess;
-
-		if ( _this.gammaInput ) {
-
-			uniforms.ambient.value.copyGammaToLinear( material.ambient );
-			uniforms.emissive.value.copyGammaToLinear( material.emissive );
-			uniforms.specular.value.copyGammaToLinear( material.specular );
-
-		} else {
-
-			uniforms.ambient.value = material.ambient;
-			uniforms.emissive.value = material.emissive;
-			uniforms.specular.value = material.specular;
-
-		}
-
-		if ( material.wrapAround ) {
-
-			uniforms.wrapRGB.value.copy( material.wrapRGB );
-
-		}
-
-	};
-
-	function refreshUniformsLambert ( uniforms, material ) {
-
-		if ( _this.gammaInput ) {
-
-			uniforms.ambient.value.copyGammaToLinear( material.ambient );
-			uniforms.emissive.value.copyGammaToLinear( material.emissive );
-
-		} else {
-
-			uniforms.ambient.value = material.ambient;
-			uniforms.emissive.value = material.emissive;
-
-		}
-
-		if ( material.wrapAround ) {
-
-			uniforms.wrapRGB.value.copy( material.wrapRGB );
-
-		}
-
-	};
-
-	function refreshUniformsLights ( uniforms, lights ) {
-
-		uniforms.ambientLightColor.value = lights.ambient;
-
-		uniforms.directionalLightColor.value = lights.directional.colors;
-		uniforms.directionalLightDirection.value = lights.directional.positions;
-
-		uniforms.pointLightColor.value = lights.point.colors;
-		uniforms.pointLightPosition.value = lights.point.positions;
-		uniforms.pointLightDistance.value = lights.point.distances;
-
-		uniforms.spotLightColor.value = lights.spot.colors;
-		uniforms.spotLightPosition.value = lights.spot.positions;
-		uniforms.spotLightDistance.value = lights.spot.distances;
-		uniforms.spotLightDirection.value = lights.spot.directions;
-		uniforms.spotLightAngleCos.value = lights.spot.anglesCos;
-		uniforms.spotLightExponent.value = lights.spot.exponents;
-
-		uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors;
-		uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors;
-		uniforms.hemisphereLightDirection.value = lights.hemi.positions;
-
-	};
-
-	function refreshUniformsShadow ( uniforms, lights ) {
-
-		if ( uniforms.shadowMatrix ) {
-
-			var j = 0;
-
-			for ( var i = 0, il = lights.length; i < il; i ++ ) {
-
-				var light = lights[ i ];
-
-				if ( ! light.castShadow ) continue;
-
-				if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) ) {
-
-					uniforms.shadowMap.value[ j ] = light.shadowMap;
-					uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;
-
-					uniforms.shadowMatrix.value[ j ] = light.shadowMatrix;
-
-					uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
-					uniforms.shadowBias.value[ j ] = light.shadowBias;
-
-					j ++;
-
-				}
-
-			}
-
-		}
-
-	};
-
-	// Uniforms (load to GPU)
-
-	function loadUniformsMatrices ( uniforms, object ) {
-
-		renderer.uniformMatrix4fv( uniforms.modelViewMatrix, object._modelViewMatrix.elements );
-
-		if ( uniforms.normalMatrix ) {
-
-			renderer.uniformMatrix3fv( uniforms.normalMatrix, object._normalMatrix.elements );
-
-		}
-
-	};
-
-	function getTextureUnit() {
-
-		var textureUnit = _usedTextureUnits;
-
-		if ( textureUnit >= renderer.maxTextures ) {
-
-			console.warn( "WebGLRenderer: trying to use " + textureUnit + " texture units while this GPU supports only " + renderer.maxTextures );
-
-		}
-
-		_usedTextureUnits += 1;
-
-		return textureUnit;
-
-	};
-
-	function loadUniformsGeneric ( program, uniforms ) {
-
-		var uniform, value, type, location, texture, textureUnit, i, il, j, jl, offset;
-
-		for ( j = 0, jl = uniforms.length; j < jl; j ++ ) {
-
-			location = program.uniforms[ uniforms[ j ][ 1 ] ];
-			if ( !location ) continue;
-
-			uniform = uniforms[ j ][ 0 ];
-
-			type = uniform.type;
-			value = uniform.value;
-
-			if ( type === "i" ) { // single integer
-
-				renderer.uniform1i( location, value );
-
-			} else if ( type === "f" ) { // single float
-
-				renderer.uniform1f( location, value );
-
-			} else if ( type === "v2" ) { // single THREE.Vector2
-
-				renderer.uniform2f( location, value.x, value.y );
-
-			} else if ( type === "v3" ) { // single THREE.Vector3
-
-				renderer.uniform3f( location, value.x, value.y, value.z );
-
-			} else if ( type === "v4" ) { // single THREE.Vector4
-
-				renderer.uniform4f( location, value.x, value.y, value.z, value.w );
-
-			} else if ( type === "c" ) { // single THREE.Color
-
-				renderer.uniform3f( location, value.r, value.g, value.b );
-
-			} else if ( type === "iv1" ) { // flat array of integers (JS or typed array)
-
-				renderer.uniform1iv( location, value );
-
-			} else if ( type === "iv" ) { // flat array of integers with 3 x N size (JS or typed array)
-
-				renderer.uniform3iv( location, value );
-
-			} else if ( type === "fv1" ) { // flat array of floats (JS or typed array)
-
-				renderer.uniform1fv( location, value );
-
-			} else if ( type === "fv" ) { // flat array of floats with 3 x N size (JS or typed array)
-
-				renderer.uniform3fv( location, value );
-
-			} else if ( type === "v2v" ) { // array of THREE.Vector2
-
-				if ( uniform._array === undefined ) {
-
-					uniform._array = new Float32Array( 2 * value.length );
-
-				}
-
-				for ( i = 0, il = value.length; i < il; i ++ ) {
-
-					offset = i * 2;
-
-					uniform._array[ offset ] 	 = value[ i ].x;
-					uniform._array[ offset + 1 ] = value[ i ].y;
-
-				}
-
-				renderer.uniform2fv( location, uniform._array );
-
-			} else if ( type === "v3v" ) { // array of THREE.Vector3
-
-				if ( uniform._array === undefined ) {
-
-					uniform._array = new Float32Array( 3 * value.length );
-
-				}
-
-				for ( i = 0, il = value.length; i < il; i ++ ) {
-
-					offset = i * 3;
-
-					uniform._array[ offset ] 	 = value[ i ].x;
-					uniform._array[ offset + 1 ] = value[ i ].y;
-					uniform._array[ offset + 2 ] = value[ i ].z;
-
-				}
-
-				renderer.uniform3fv( location, uniform._array );
-
-			} else if ( type === "v4v" ) { // array of THREE.Vector4
-
-				if ( uniform._array === undefined ) {
-
-					uniform._array = new Float32Array( 4 * value.length );
-
-				}
-
-				for ( i = 0, il = value.length; i < il; i ++ ) {
-
-					offset = i * 4;
-
-					uniform._array[ offset ] 	 = value[ i ].x;
-					uniform._array[ offset + 1 ] = value[ i ].y;
-					uniform._array[ offset + 2 ] = value[ i ].z;
-					uniform._array[ offset + 3 ] = value[ i ].w;
-
-				}
-
-				renderer.uniform4fv( location, uniform._array );
-
-			} else if ( type === "m4") { // single THREE.Matrix4
-
-				if ( uniform._array === undefined ) {
-
-					uniform._array = new Float32Array( 16 );
-
-				}
-
-				value.flattenToArray( uniform._array );
-				renderer.uniformMatrix4fv( location, uniform._array );
-
-			} else if ( type === "m4v" ) { // array of THREE.Matrix4
-
-				if ( uniform._array === undefined ) {
-
-					uniform._array = new Float32Array( 16 * value.length );
-
-				}
-
-				for ( i = 0, il = value.length; i < il; i ++ ) {
-
-					value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
-
-				}
-
-				renderer.uniformMatrix4fv( location, uniform._array );
-
-			} else if ( type === "t" ) { // single THREE.Texture (2d or cube)
-
-				texture = value;
-				textureUnit = getTextureUnit();
-
-				renderer.uniform1i( location, textureUnit );
-
-				if ( !texture ) continue;
-
-				if ( texture.image instanceof Array && texture.image.length === 6 ) {
-
-					renderer.setCubeTexture( texture, textureUnit );
-
-				} else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
-
-					renderer.setCubeTextureDynamic( texture, textureUnit );
-
-				} else {
-
-					renderer.setTexture( texture, textureUnit );
-
-				}
-
-			} else if ( type === "tv" ) { // array of THREE.Texture (2d)
-
-				if ( uniform._array === undefined ) {
-
-					uniform._array = [];
-
-				}
-
-				for( i = 0, il = uniform.value.length; i < il; i ++ ) {
-
-					uniform._array[ i ] = getTextureUnit();
-
-				}
-
-				renderer.uniform1iv( location, uniform._array );
-
-				for( i = 0, il = uniform.value.length; i < il; i ++ ) {
-
-					texture = uniform.value[ i ];
-					textureUnit = uniform._array[ i ];
-
-					if ( !texture ) continue;
-
-					renderer.setTexture( texture, textureUnit );
-
-				}
-
-			}
-
-		}
-
-	};
-
-	function setupMatrices ( object, camera ) {
-
-		object._modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
-		object._normalMatrix.getNormalMatrix( object._modelViewMatrix );
-
-	};
-
-	//
-
-	function setColorGamma( array, offset, color, intensitySq ) {
-
-		array[ offset ]     = color.r * color.r * intensitySq;
-		array[ offset + 1 ] = color.g * color.g * intensitySq;
-		array[ offset + 2 ] = color.b * color.b * intensitySq;
-
-	};
-
-	function setColorLinear( array, offset, color, intensity ) {
-
-		array[ offset ]     = color.r * intensity;
-		array[ offset + 1 ] = color.g * intensity;
-		array[ offset + 2 ] = color.b * intensity;
-
-	};
-
-	function setupLights ( program, lights ) {
-
-		var l, ll, light, n,
-		r = 0, g = 0, b = 0,
-		color, skyColor, groundColor,
-		intensity,  intensitySq,
-		position,
-		distance,
-
-		zlights = _lights,
-
-		dirColors = zlights.directional.colors,
-		dirPositions = zlights.directional.positions,
-
-		pointColors = zlights.point.colors,
-		pointPositions = zlights.point.positions,
-		pointDistances = zlights.point.distances,
-
-		spotColors = zlights.spot.colors,
-		spotPositions = zlights.spot.positions,
-		spotDistances = zlights.spot.distances,
-		spotDirections = zlights.spot.directions,
-		spotAnglesCos = zlights.spot.anglesCos,
-		spotExponents = zlights.spot.exponents,
-
-		hemiSkyColors = zlights.hemi.skyColors,
-		hemiGroundColors = zlights.hemi.groundColors,
-		hemiPositions = zlights.hemi.positions,
-
-		dirLength = 0,
-		pointLength = 0,
-		spotLength = 0,
-		hemiLength = 0,
-
-		dirCount = 0,
-		pointCount = 0,
-		spotCount = 0,
-		hemiCount = 0,
-
-		dirOffset = 0,
-		pointOffset = 0,
-		spotOffset = 0,
-		hemiOffset = 0;
-
-		for ( l = 0, ll = lights.length; l < ll; l ++ ) {
-
-			light = lights[ l ];
-
-			if ( light.onlyShadow ) continue;
-
-			color = light.color;
-			intensity = light.intensity;
-			distance = light.distance;
-
-			if ( light instanceof THREE.AmbientLight ) {
-
-				if ( ! light.visible ) continue;
-
-				if ( _this.gammaInput ) {
-
-					r += color.r * color.r;
-					g += color.g * color.g;
-					b += color.b * color.b;
-
-				} else {
-
-					r += color.r;
-					g += color.g;
-					b += color.b;
-
-				}
-
-			} else if ( light instanceof THREE.DirectionalLight ) {
-
-				dirCount += 1;
-
-				if ( ! light.visible ) continue;
-
-				_direction.getPositionFromMatrix( light.matrixWorld );
-				_vector3.getPositionFromMatrix( light.target.matrixWorld );
-				_direction.sub( _vector3 );
-				_direction.normalize();
-
-				// skip lights with undefined direction
-				// these create troubles in OpenGL (making pixel black)
-
-				if ( _direction.x === 0 && _direction.y === 0 && _direction.z === 0 ) continue;
-
-				dirOffset = dirLength * 3;
-
-				dirPositions[ dirOffset ]     = _direction.x;
-				dirPositions[ dirOffset + 1 ] = _direction.y;
-				dirPositions[ dirOffset + 2 ] = _direction.z;
-
-				if ( _this.gammaInput ) {
-
-					setColorGamma( dirColors, dirOffset, color, intensity * intensity );
-
-				} else {
-
-					setColorLinear( dirColors, dirOffset, color, intensity );
-
-				}
-
-				dirLength += 1;
-
-			} else if ( light instanceof THREE.PointLight ) {
-
-				pointCount += 1;
-
-				if ( ! light.visible ) continue;
-
-				pointOffset = pointLength * 3;
-
-				if ( _this.gammaInput ) {
-
-					setColorGamma( pointColors, pointOffset, color, intensity * intensity );
-
-				} else {
-
-					setColorLinear( pointColors, pointOffset, color, intensity );
-
-				}
-
-				_vector3.getPositionFromMatrix( light.matrixWorld );
-
-				pointPositions[ pointOffset ]     = _vector3.x;
-				pointPositions[ pointOffset + 1 ] = _vector3.y;
-				pointPositions[ pointOffset + 2 ] = _vector3.z;
-
-				pointDistances[ pointLength ] = distance;
-
-				pointLength += 1;
-
-			} else if ( light instanceof THREE.SpotLight ) {
-
-				spotCount += 1;
-
-				if ( ! light.visible ) continue;
-
-				spotOffset = spotLength * 3;
-
-				if ( _this.gammaInput ) {
-
-					setColorGamma( spotColors, spotOffset, color, intensity * intensity );
-
-				} else {
-
-					setColorLinear( spotColors, spotOffset, color, intensity );
-
-				}
-
-				_vector3.getPositionFromMatrix( light.matrixWorld );
-
-				spotPositions[ spotOffset ]     = _vector3.x;
-				spotPositions[ spotOffset + 1 ] = _vector3.y;
-				spotPositions[ spotOffset + 2 ] = _vector3.z;
-
-				spotDistances[ spotLength ] = distance;
-
-				_direction.copy( _vector3 );
-				_vector3.getPositionFromMatrix( light.target.matrixWorld );
-				_direction.sub( _vector3 );
-				_direction.normalize();
-
-				spotDirections[ spotOffset ]     = _direction.x;
-				spotDirections[ spotOffset + 1 ] = _direction.y;
-				spotDirections[ spotOffset + 2 ] = _direction.z;
-
-				spotAnglesCos[ spotLength ] = Math.cos( light.angle );
-				spotExponents[ spotLength ] = light.exponent;
-
-				spotLength += 1;
-
-			} else if ( light instanceof THREE.HemisphereLight ) {
-
-				hemiCount += 1;
-
-				if ( ! light.visible ) continue;
-
-				_direction.getPositionFromMatrix( light.matrixWorld );
-				_direction.normalize();
-
-				// skip lights with undefined direction
-				// these create troubles in OpenGL (making pixel black)
-
-				if ( _direction.x === 0 && _direction.y === 0 && _direction.z === 0 ) continue;
-
-				hemiOffset = hemiLength * 3;
-
-				hemiPositions[ hemiOffset ]     = _direction.x;
-				hemiPositions[ hemiOffset + 1 ] = _direction.y;
-				hemiPositions[ hemiOffset + 2 ] = _direction.z;
-
-				skyColor = light.color;
-				groundColor = light.groundColor;
-
-				if ( _this.gammaInput ) {
-
-					intensitySq = intensity * intensity;
-
-					setColorGamma( hemiSkyColors, hemiOffset, skyColor, intensitySq );
-					setColorGamma( hemiGroundColors, hemiOffset, groundColor, intensitySq );
-
-				} else {
-
-					setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity );
-					setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity );
-
-				}
-
-				hemiLength += 1;
-
-			}
-
-		}
-
-		// null eventual remains from removed lights
-		// (this is to avoid if in shader)
-
-		for ( l = dirLength * 3, ll = Math.max( dirColors.length, dirCount * 3 ); l < ll; l ++ ) dirColors[ l ] = 0.0;
-		for ( l = pointLength * 3, ll = Math.max( pointColors.length, pointCount * 3 ); l < ll; l ++ ) pointColors[ l ] = 0.0;
-		for ( l = spotLength * 3, ll = Math.max( spotColors.length, spotCount * 3 ); l < ll; l ++ ) spotColors[ l ] = 0.0;
-		for ( l = hemiLength * 3, ll = Math.max( hemiSkyColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiSkyColors[ l ] = 0.0;
-		for ( l = hemiLength * 3, ll = Math.max( hemiGroundColors.length, hemiCount * 3 ); l < ll; l ++ ) hemiGroundColors[ l ] = 0.0;
-
-		zlights.directional.length = dirLength;
-		zlights.point.length = pointLength;
-		zlights.spot.length = spotLength;
-		zlights.hemi.length = hemiLength;
-
-		zlights.ambient[ 0 ] = r;
-		zlights.ambient[ 1 ] = g;
-		zlights.ambient[ 2 ] = b;
-
-	};
-
-	// Allocations
-
-	function allocateBones ( object ) {
-
-		if ( renderer.supportsBoneTextures && object && object.useVertexTexture ) {
-
-			return 1024;
-
-		} else {
-
-			// default for when object is not specified
-			// ( for example when prebuilding shader
-			//   to be used with multiple objects )
-			//
-			// 	- leave some extra space for other uniforms
-			//  - limit here is ANGLE's 254 max uniform vectors
-			//    (up to 54 should be safe)
-
-			var nVertexUniforms = renderer.maxVertexUniformVectors
-			var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
-
-			var maxBones = nVertexMatrices;
-
-			if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
-
-				maxBones = Math.min( object.bones.length, maxBones );
-
-				if ( maxBones < object.bones.length ) {
-
-					console.warn( "WebGLRenderer: too many bones - " + object.bones.length + ", this GPU supports just " + maxBones + " (try OpenGL instead of ANGLE)" );
-
-				}
-
-			}
-
-			return maxBones;
-
-		}
-
-	};
-
-	function allocateLights ( lights ) {
-
-		var l, ll, light, dirLights, pointLights, spotLights, hemiLights;
-
-		dirLights = pointLights = spotLights = hemiLights = 0;
-
-		for ( l = 0, ll = lights.length; l < ll; l ++ ) {
-
-			light = lights[ l ];
-
-			if ( light.onlyShadow ) continue;
-
-			if ( light instanceof THREE.DirectionalLight ) dirLights ++;
-			if ( light instanceof THREE.PointLight ) pointLights ++;
-			if ( light instanceof THREE.SpotLight ) spotLights ++;
-			if ( light instanceof THREE.HemisphereLight ) hemiLights ++;
-
-		}
-
-		return { 'directional' : dirLights, 'point' : pointLights, 'spot': spotLights, 'hemi': hemiLights };
-
-	};
-
-	function allocateShadows ( lights ) {
-
-		var l, ll, light, maxShadows = 0;
-
-		for ( l = 0, ll = lights.length; l < ll; l++ ) {
-
-			light = lights[ l ];
-
-			if ( ! light.castShadow ) continue;
-
-			if ( light instanceof THREE.SpotLight ) maxShadows ++;
-			if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
-
-		}
-
-		return maxShadows;
-
-	};
-
-	// default plugins (order is important)
-
-	this.shadowMapPlugin = new THREE.ShadowMapPlugin();
-	this.addPrePlugin( this.shadowMapPlugin );
-
-	this.addPostPlugin( new THREE.SpritePlugin() );
-	this.addPostPlugin( new THREE.LensFlarePlugin() );
-
-};

+ 0 - 1570
examples/js/renderers/WebGLRenderer2/webgl/LowLevelRenderer.js

@@ -1,1570 +0,0 @@
-
-/*global THREE:false */
-
-THREE.WebGLRenderer.LowLevelRenderer = function ( parameters ) {
-
-	parameters = parameters || {};
-
-	var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
-
-	_precision = parameters.precision !== undefined ? parameters.precision : 'highp',
-
-	_alpha = parameters.alpha !== undefined ? parameters.alpha : true,
-	_premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
-	_antialias = parameters.antialias !== undefined ? parameters.antialias : false,
-	_stencil = parameters.stencil !== undefined ? parameters.stencil : true,
-	_preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
-
-	_clearColor = parameters.clearColor !== undefined ? new THREE.Color( parameters.clearColor ) : new THREE.Color( 0x000000 ),
-	_clearAlpha = parameters.clearAlpha !== undefined ? parameters.clearAlpha : 0,
-	_autoScaleCubemaps = true;
-
-	this.devicePixelRatio = parameters.devicePixelRatio !== undefined ? parameters.devicePixelRatio : window.devicePixelRatio !== undefined ? window.devicePixelRatio : 1;
-
-	var _currentWidth = 0, _currentHeight = 0;
-
-	var _gl;
-
-	var _glExtensionTextureFloat;
-	var _glExtensionStandardDerivatives;
-	var _glExtensionTextureFilterAnisotropic;
-	var _glExtensionCompressedTextureS3TC;
-
-	initGL();
-
-	setDefaultGLState();
-
-	var _maxTextures = _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS );
-	var _maxVertexTextures = _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
-	var _maxTextureSize = _gl.getParameter( _gl.MAX_TEXTURE_SIZE );
-	var _maxCubemapSize = _gl.getParameter( _gl.MAX_CUBE_MAP_TEXTURE_SIZE );
-
-	var _maxAnisotropy = _glExtensionTextureFilterAnisotropic ? _gl.getParameter( _glExtensionTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT ) : 0;
-
-	var _supportsVertexTextures = ( _maxVertexTextures > 0 );
-	var _supportsBoneTextures = _supportsVertexTextures && _glExtensionTextureFloat;
-
-	var _compressedTextureFormats = _glExtensionCompressedTextureS3TC ? _gl.getParameter( _gl.COMPRESSED_TEXTURE_FORMATS ) : [];
-
-	var _vertexShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_FLOAT );
-	var _vertexShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_FLOAT );
-	var _vertexShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_FLOAT );
-
-	var _fragmentShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_FLOAT );
-	var _fragmentShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_FLOAT );
-	var _fragmentShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_FLOAT );
-
-	var _vertexShaderPrecisionHighpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_INT );
-	var _vertexShaderPrecisionMediumpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_INT );
-	var _vertexShaderPrecisionLowpInt = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_INT );
-
-	var _fragmentShaderPrecisionHighpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_INT );
-	var _fragmentShaderPrecisionMediumpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_INT );
-	var _fragmentShaderPrecisionLowpInt = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_INT );
-
-	// clamp precision to maximum available
-
-	var highpAvailable = _vertexShaderPrecisionHighpFloat.precision > 0 && _fragmentShaderPrecisionHighpFloat.precision > 0;
-	var mediumpAvailable = _vertexShaderPrecisionMediumpFloat.precision > 0 && _fragmentShaderPrecisionMediumpFloat.precision > 0;
-
-	if ( _precision === "highp" && ! highpAvailable ) {
-
-		if ( mediumpAvailable ) {
-
-			_precision = "mediump";
-			console.warn( "WebGLRenderer: highp not supported, using mediump" );
-
-		} else {
-
-			_precision = "lowp";
-			console.warn( "WebGLRenderer: highp and mediump not supported, using lowp" );
-
-		}
-
-	}
-
-	if ( _precision === "mediump" && ! mediumpAvailable ) {
-
-		_precision = "lowp";
-		console.warn( "WebGLRenderer: mediump not supported, using lowp" );
-
-	}
-
-	var _enabledAttributes = {},
-		_oldBlending,
-		_oldBlendEquation,
-		_oldBlendSrc,
-		_oldBlendDst,
-
-		_oldDoubleSided = -1,
-		_oldFlipSided = -1,
-
-		_oldDepthTest = -1,
-		_oldDepthWrite = -1,
-
-		_oldLineWidth = -1,
-
-		_viewportX = 0,
-		_viewportY = 0,
-		_viewportWidth = 0,
-		_viewportHeight = 0,
-			// GL state cache
-
-		_oldPolygonOffset = null,
-		_oldPolygonOffsetFactor = null,
-		_oldPolygonOffsetUnits = null,
-		_currentFramebuffer = null;
-
-	function initGL () {
-
-		try {
-
-			if ( ! ( _gl = _canvas.getContext( 'experimental-webgl', { alpha: _alpha, premultipliedAlpha: _premultipliedAlpha, antialias: _antialias, stencil: _stencil, preserveDrawingBuffer: _preserveDrawingBuffer } ) ) ) {
-
-				throw 'Error creating WebGL context.';
-
-			}
-
-		} catch ( error ) {
-
-			console.error( error );
-
-		}
-
-		_glExtensionTextureFloat = _gl.getExtension( 'OES_texture_float' );
-		_glExtensionStandardDerivatives = _gl.getExtension( 'OES_standard_derivatives' );
-
-		_glExtensionTextureFilterAnisotropic = _gl.getExtension( 'EXT_texture_filter_anisotropic' ) ||
-											   _gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) ||
-											   _gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
-
-
-		_glExtensionCompressedTextureS3TC = _gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) ||
-											_gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) ||
-											_gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
-
-		if ( ! _glExtensionTextureFloat ) {
-
-			console.log( 'THREE.WebGLRenderer: Float textures not supported.' );
-
-		}
-
-		if ( ! _glExtensionStandardDerivatives ) {
-
-			console.log( 'THREE.WebGLRenderer: Standard derivatives not supported.' );
-
-		}
-
-		if ( ! _glExtensionTextureFilterAnisotropic ) {
-
-			console.log( 'THREE.WebGLRenderer: Anisotropic texture filtering not supported.' );
-
-		}
-
-		if ( ! _glExtensionCompressedTextureS3TC ) {
-
-			console.log( 'THREE.WebGLRenderer: S3TC compressed textures not supported.' );
-
-		}
-
-		if ( _gl.getShaderPrecisionFormat === undefined ) {
-
-			_gl.getShaderPrecisionFormat = function() { 
-
-				return {
-					"rangeMin"  : 1,
-					"rangeMax"  : 1,
-					"precision" : 1
-				};
-
-			}
-
-		}
-
-	}
-
-	function setDefaultGLState () {
-
-		_gl.clearColor( 0, 0, 0, 1 );
-		_gl.clearDepth( 1 );
-		_gl.clearStencil( 0 );
-
-		_gl.enable( _gl.DEPTH_TEST );
-		_gl.depthFunc( _gl.LEQUAL );
-
-		_gl.frontFace( _gl.CCW );
-		_gl.cullFace( _gl.BACK );
-		_gl.enable( _gl.CULL_FACE );
-
-		_gl.enable( _gl.BLEND );
-		_gl.blendEquation( _gl.FUNC_ADD );
-		_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
-
-		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
-
-	}
-
-	// Fallback filters for non-power-of-2 textures
-
-	function filterFallback ( f ) {
-
-		if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
-
-			return _gl.NEAREST;
-
-		}
-
-		return _gl.LINEAR;
-
-	}
-
-	function getContext() {
-
-		return _gl;
-
-	}
-
-	function getDomElement(){
-
-		return _canvas;
-
-	}
-
-	function getPrecision() {
-
-		return _precision;
-
-	}
-
-	function getCurrentWidth(){
-
-		return _currentWidth;
-
-	}
-
-	function getCurrentHeight(){
-
-		return _currentHeight;
-
-	}
-
-	function supportsVertexTextures() {
-
-		return _supportsVertexTextures;
-
-	}
-
-	function supportsFloatTextures() {
-
-		return _glExtensionTextureFloat;
-
-	}
-
-	function supportsStandardDerivatives() {
-
-		return _glExtensionStandardDerivatives;
-
-	}
-
-	function supportsCompressedTextureS3TC() {
-
-		return _glExtensionCompressedTextureS3TC;
-
-	}
-
-	function getMaxAnisotropy() {
-
-		return _maxAnisotropy;
-
-	}
-
-	function setSize( width, height ) {
-
-		_canvas.width = width;
-		_canvas.height = height;
-
-		setViewport( 0, 0, _canvas.width, _canvas.height );
-
-	}
-
-	function setViewport( x, y, width, height ) {
-
-		_viewportX = x !== undefined ? x : 0;
-		_viewportY = y !== undefined ? y : 0;
-
-		_viewportWidth = width !== undefined ? width : _canvas.width;
-		_viewportHeight = height !== undefined ? height : _canvas.height;
-
-		_gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
-
-	}
-
-	function setScissor( x, y, width, height ) {
-
-		_gl.scissor( x, y, width, height );
-
-	}
-
-	function enableScissorTest( enable ) {
-
-		enable ? _gl.enable( _gl.SCISSOR_TEST ) : _gl.disable( _gl.SCISSOR_TEST );
-
-	}
-
-	// Clearing
-
-	function setClearColorHex( hex, alpha ) {
-
-		_clearColor.setHex( hex );
-		_clearAlpha = alpha;
-
-		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
-
-	}
-
-	function setClearColor( color, alpha ) {
-
-		_clearColor.copy( color );
-		_clearAlpha = alpha;
-
-		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
-
-	}
-
-	function getClearColor() {
-
-		return _clearColor;
-
-	}
-
-	function getClearAlpha() {
-
-		return _clearAlpha;
-
-	}
-
-	function clear( color, depth, stencil ) {
-
-		var bits = 0;
-
-		if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
-		if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
-		if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
-
-		_gl.clear( bits );
-
-	}
-
-	function clearTarget( renderTarget, color, depth, stencil ) {
-
-		setRenderTarget( renderTarget );
-		clear( color, depth, stencil );
-
-	}
-
-	function deleteBuffer(buffer){
-
-		_gl.deleteBuffer(buffer);
-
-	}
-
-	function deleteTexture(texture){
-
-		_gl.deleteTexture( texture );
-
-	}
-
-	function deleteFramebuffer(Framebuffer){
-
-		_gl.deleteFramebuffer(Framebuffer);
-
-	}
-
-	function deleteRenderbuffer(RenderBuffer){
-
-		_gl.deleteRenderbuffer(RenderBuffer);
-
-	}
-
-	function deleteProgram(RenderBuffer){
-
-		_gl.deleteProgram(RenderBuffer);
-
-	}
-
-	function createBuffer(){
-
-		return _gl.createBuffer();
-
-	}
-
-	function setStaticArrayBuffer(buffer,data){
-
-		bindArrayBuffer( buffer );
-		_gl.bufferData( _gl.ARRAY_BUFFER, data, _gl.STATIC_DRAW );
-
-	}
-
-	function setStaticIndexBuffer(buffer,data){
-
-		bindElementArrayBuffer( buffer );
-		_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, data, _gl.STATIC_DRAW );
-
-	}
-
-	function setDynamicArrayBuffer(buffer,data){
-
-		bindArrayBuffer( buffer );
-		_gl.bufferData( _gl.ARRAY_BUFFER, data, _gl.DYNAMIC_DRAW );
-
-	}
-
-	function setDynamicIndexBuffer(buffer,data){
-
-		bindElementArrayBuffer( buffer );
-		_gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, data, _gl.DYNAMIC_DRAW );
-
-	}
-
-	function drawTriangles(count){
-
-		_gl.drawArrays( _gl.TRIANGLES, 0, count );
-
-	}
-
-	function drawTriangleStrip(count){
-
-		_gl.drawArrays( _gl.TRIANGLE_STRIP, 0, count );
-
-	}
-
-	function drawLines(count){
-
-		_gl.drawArrays( _gl.LINES, 0, count );
-
-	}
-
-	function drawLineStrip(count){
-
-		_gl.drawArrays( _gl.LINE_STRIP, 0, count );
-
-	}
-
-	function drawPoints(count){
-
-		_gl.drawArrays( _gl.POINTS, 0, count );
-
-	}
-
-	function drawTriangleElements(buffer,count,offset){
-
-		bindElementArrayBuffer( buffer );
-		_gl.drawElements( _gl.TRIANGLES, count, _gl.UNSIGNED_SHORT, offset ); // 2 bytes per Uint16
-
-	}
-
-	function drawLineElements(buffer,count,offset){
-
-		bindElementArrayBuffer(  buffer );
-		_gl.drawElements( _gl.LINES, count, _gl.UNSIGNED_SHORT, offset ); // 2 bytes per Uint16
-
-	}
-
-	var _boundBuffer;
-
-	function bindArrayBuffer(buffer){
-
-		if (_boundBuffer != buffer){
-
-			_gl.bindBuffer( _gl.ARRAY_BUFFER, buffer );
-			_boundBuffer = buffer;
-
-		}
-
-	}
-
-	function bindElementArrayBuffer(buffer){
-
-		if (_boundBuffer != buffer){
-
-			_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, buffer );
-			_boundBuffer = buffer;
-
-		}
-
-	}
-
-	function enableAttribute( attribute ) {
-
-		if ( ! _enabledAttributes[ attribute ] ) {
-
-			_gl.enableVertexAttribArray( attribute );
-			_enabledAttributes[ attribute ] = true;
-
-		}
-
-	}
-
-	function disableAttributes() {
-
-		for ( var attribute in _enabledAttributes ) {
-
-			if ( _enabledAttributes[ attribute ] ) {
-
-				_gl.disableVertexAttribArray( attribute );
-				_enabledAttributes[ attribute ] = false;
-
-			}
-
-		}
-
-	}
-
-	function getAttribLocation( program, id ){
-
-		return _gl.getAttribLocation( program, id );
-
-	}
-
-	function setFloatAttribute(index,buffer,size,offset){
-
-		bindArrayBuffer( buffer );
-		enableAttribute( index );
-		_gl.vertexAttribPointer( index, size, _gl.FLOAT, false, 0, offset );
-
-	}
-
-	function getUniformLocation( program, id ){
-
-		return _gl.getUniformLocation( program, id );
-
-	}
-
-	function uniform1i(uniform,value){
-
-		_gl.uniform1i( uniform, value );
-
-	}
-
-	function uniform1f(uniform,value){
-
-		_gl.uniform1f( uniform, value );
-
-	}
-
-	function uniform2f(uniform,value1, value2){
-
-		_gl.uniform2f( uniform, value1, value2 );
-
-	}
-
-	function uniform3f(uniform, value1, value2, value3){
-
-		_gl.uniform3f( uniform, value1, value2, value3 );
-
-	}
-
-	function uniform4f(uniform, value1, value2, value3, value4){
-
-		_gl.uniform4f( uniform, value1, value2, value3, value4);
-
-	}
-
-	function uniform1iv(uniform,value){
-
-		_gl.uniform1iv( uniform, value );
-
-	}
-
-	function uniform2iv(uniform,value){
-
-		_gl.uniform2iv( uniform, value );
-
-	}
-
-	function uniform3iv(uniform,value){
-
-		_gl.uniform3iv( uniform, value );
-
-	}
-
-	function uniform1fv(uniform,value){
-
-		_gl.uniform1fv( uniform, value );
-
-	}
-
-	function uniform2fv(uniform,value){
-
-		_gl.uniform2fv( uniform, value );
-
-	}
-
-	function uniform3fv(uniform,value){
-
-		_gl.uniform3fv( uniform, value );
-
-	}
-
-	function uniform4fv(uniform,value){
-
-		_gl.uniform3fv( uniform, value );
-
-	}
-
-	function uniformMatrix3fv(location,value){
-
-		_gl.uniformMatrix3fv( location, false, value );
-
-	}
-
-	function uniformMatrix4fv(location,value){
-
-		_gl.uniformMatrix4fv( location, false, value );
-
-	}
-
-	function useProgram(program){
-
-		_gl.useProgram( program );
-
-	}
-
-	function setFaceCulling( cullFace, frontFaceDirection ) {
-
-		if ( cullFace === THREE.CullFaceNone ) {
-
-			_gl.disable( _gl.CULL_FACE );
-
-		} else {
-
-			if ( frontFaceDirection === THREE.FrontFaceDirectionCW ) {
-
-				_gl.frontFace( _gl.CW );
-
-			} else {
-
-				_gl.frontFace( _gl.CCW );
-
-			}
-
-			if ( cullFace === THREE.CullFaceBack ) {
-
-				_gl.cullFace( _gl.BACK );
-
-			} else if ( cullFace === THREE.CullFaceFront ) {
-
-				_gl.cullFace( _gl.FRONT );
-
-			} else {
-
-				_gl.cullFace( _gl.FRONT_AND_BACK );
-
-			}
-
-			_gl.enable( _gl.CULL_FACE );
-
-		}
-
-	}
-
-	function setMaterialFaces( material ) {
-
-		var doubleSided = material.side === THREE.DoubleSide;
-		var flipSided = material.side === THREE.BackSide;
-
-		if ( _oldDoubleSided !== doubleSided ) {
-
-			if ( doubleSided ) {
-
-				_gl.disable( _gl.CULL_FACE );
-
-			} else {
-
-				_gl.enable( _gl.CULL_FACE );
-
-			}
-
-			_oldDoubleSided = doubleSided;
-
-		}
-
-		if ( _oldFlipSided !== flipSided ) {
-
-			if ( flipSided ) {
-
-				_gl.frontFace( _gl.CW );
-
-			} else {
-
-				_gl.frontFace( _gl.CCW );
-
-			}
-
-			_oldFlipSided = flipSided;
-
-		}
-
-	}
-
-	function setPolygonOffset ( polygonoffset, factor, units ) {
-
-		if ( _oldPolygonOffset !== polygonoffset ) {
-
-			if ( polygonoffset ) {
-
-				_gl.enable( _gl.POLYGON_OFFSET_FILL );
-
-			} else {
-
-				_gl.disable( _gl.POLYGON_OFFSET_FILL );
-
-			}
-
-			_oldPolygonOffset = polygonoffset;
-
-		}
-
-		if ( polygonoffset && ( _oldPolygonOffsetFactor !== factor || _oldPolygonOffsetUnits !== units ) ) {
-
-			_gl.polygonOffset( factor, units );
-
-			_oldPolygonOffsetFactor = factor;
-			_oldPolygonOffsetUnits = units;
-
-		}
-
-	}
-
-	function setBlending( blending, blendEquation, blendSrc, blendDst ) {
-
-		if ( blending !== _oldBlending ) {
-
-			if ( blending === THREE.NoBlending ) {
-
-				_gl.disable( _gl.BLEND );
-
-			} else if ( blending === THREE.AdditiveBlending ) {
-
-				_gl.enable( _gl.BLEND );
-				_gl.blendEquation( _gl.FUNC_ADD );
-				_gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE );
-
-			} else if ( blending === THREE.SubtractiveBlending ) {
-
-				// TODO: Find blendFuncSeparate() combination
-				_gl.enable( _gl.BLEND );
-				_gl.blendEquation( _gl.FUNC_ADD );
-				_gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR );
-
-			} else if ( blending === THREE.MultiplyBlending ) {
-
-				// TODO: Find blendFuncSeparate() combination
-				_gl.enable( _gl.BLEND );
-				_gl.blendEquation( _gl.FUNC_ADD );
-				_gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR );
-
-			} else if ( blending === THREE.CustomBlending ) {
-
-				_gl.enable( _gl.BLEND );
-
-			} else {
-
-				_gl.enable( _gl.BLEND );
-				_gl.blendEquationSeparate( _gl.FUNC_ADD, _gl.FUNC_ADD );
-				_gl.blendFuncSeparate( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
-
-			}
-
-			_oldBlending = blending;
-
-		}
-
-		if ( blending === THREE.CustomBlending ) {
-
-			if ( blendEquation !== _oldBlendEquation ) {
-
-				_gl.blendEquation( paramThreeToGL( blendEquation ) );
-
-				_oldBlendEquation = blendEquation;
-
-			}
-
-			if ( blendSrc !== _oldBlendSrc || blendDst !== _oldBlendDst ) {
-
-				_gl.blendFunc( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ) );
-
-				_oldBlendSrc = blendSrc;
-				_oldBlendDst = blendDst;
-
-			}
-
-		} else {
-
-			_oldBlendEquation = null;
-			_oldBlendSrc = null;
-			_oldBlendDst = null;
-
-		}
-
-	}
-
-	function setDepthTest( depthTest ) {
-
-		if ( _oldDepthTest !== depthTest ) {
-
-			if ( depthTest ) {
-
-				_gl.enable( _gl.DEPTH_TEST );
-
-			} else {
-
-				_gl.disable( _gl.DEPTH_TEST );
-
-			}
-
-			_oldDepthTest = depthTest;
-
-		}
-
-	}
-
-	function setDepthWrite( depthWrite ) {
-
-		if ( _oldDepthWrite !== depthWrite ) {
-
-			_gl.depthMask( depthWrite );
-			_oldDepthWrite = depthWrite;
-
-		}
-
-	}
-
-	function setTexture( texture, slot ) {
-
-		if ( texture.needsUpdate ) {
-
-			if ( ! texture.__webglInit ) {
-
-				texture.__webglInit = true;
-
-				//texture.addEventListener( 'dispose', onTextureDispose );
-
-				texture.__webglTexture = _gl.createTexture();
-
-				//_this.info.memory.textures ++;
-
-			}
-
-			_gl.activeTexture( _gl.TEXTURE0 + slot );
-			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
-
-			_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
-			_gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
-			_gl.pixelStorei( _gl.UNPACK_ALIGNMENT, texture.unpackAlignment );
-
-			var image = texture.image,
-			isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
-			glFormat = paramThreeToGL( texture.format ),
-			glType = paramThreeToGL( texture.type );
-
-			setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
-
-			var mipmap, mipmaps = texture.mipmaps;
-
-			if ( texture instanceof THREE.DataTexture ) {
-
-				// use manually created mipmaps if available
-				// if there are no manual mipmaps
-				// set 0 level mipmap and then use GL to generate other mipmap levels
-
-				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
-
-					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
-
-						mipmap = mipmaps[ i ];
-						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, glFormat, glType, mipmap.data );
-
-					}
-
-					texture.generateMipmaps = false;
-
-				} else {
-
-					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
-
-				}
-
-			} else if ( texture instanceof THREE.CompressedTexture ) {
-
-				// compressed textures can only use manually created mipmaps
-				// WebGL can't generate mipmaps for DDS textures
-
-				for( var i = 0, il = mipmaps.length; i < il; i ++ ) {
-
-					mipmap = mipmaps[ i ];
-					_gl.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
-
-				}
-
-			} else { // regular Texture (image, video, canvas)
-
-				// use manually created mipmaps if available
-				// if there are no manual mipmaps
-				// set 0 level mipmap and then use GL to generate other mipmap levels
-
-				if ( mipmaps.length > 0 && isImagePowerOfTwo ) {
-
-					for ( var i = 0, il = mipmaps.length; i < il; i ++ ) {
-
-						mipmap = mipmaps[ i ];
-						_gl.texImage2D( _gl.TEXTURE_2D, i, glFormat, glFormat, glType, mipmap );
-
-					}
-
-					texture.generateMipmaps = false;
-
-				} else {
-
-					_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
-
-				}
-
-			}
-
-			if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
-
-			texture.needsUpdate = false;
-
-			if ( texture.onUpdate ) texture.onUpdate();
-
-		} else {
-
-			_gl.activeTexture( _gl.TEXTURE0 + slot );
-			_gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
-
-		}
-
-	}
-
-	function setCubeTexture ( texture, slot ) {
-
-		if ( texture.image.length === 6 ) {
-
-			if ( texture.needsUpdate ) {
-
-				if ( ! texture.image.__webglTextureCube ) {
-
-					texture.image.__webglTextureCube = _gl.createTexture();
-
-
-				}
-
-				_gl.activeTexture( _gl.TEXTURE0 + slot );
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
-
-				_gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
-
-				var isCompressed = texture instanceof THREE.CompressedTexture;
-
-				var cubeImage = [];
-
-				for ( var i = 0; i < 6; i ++ ) {
-
-					if ( _autoScaleCubemaps && ! isCompressed ) {
-
-						cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );
-
-					} else {
-
-						cubeImage[ i ] = texture.image[ i ];
-
-					}
-
-				}
-
-				var image = cubeImage[ 0 ],
-				isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
-				glFormat = paramThreeToGL( texture.format ),
-				glType = paramThreeToGL( texture.type );
-
-				setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );
-
-				for ( var i = 0; i < 6; i ++ ) {
-
-					if ( isCompressed ) {
-
-						var mipmap, mipmaps = cubeImage[ i ].mipmaps;
-
-						for( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
-
-							mipmap = mipmaps[ j ];
-							_gl.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
-
-						}
-
-					} else {
-
-						_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
-
-					}
-
-				}
-
-				if ( texture.generateMipmaps && isImagePowerOfTwo ) {
-
-					_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
-
-				}
-
-				texture.needsUpdate = false;
-
-				if ( texture.onUpdate ) texture.onUpdate();
-
-			} else {
-
-				_gl.activeTexture( _gl.TEXTURE0 + slot );
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
-
-			}
-
-		}
-
-	}
-
-	// Textures
-
-	function isPowerOfTwo ( value ) {
-
-		return ( value & ( value - 1 ) ) === 0;
-
-	}
-
-	function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
-
-		if ( isImagePowerOfTwo ) {
-
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
-
-			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
-			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
-
-		} else {
-
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
-			_gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
-
-			_gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
-			_gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
-
-		}
-
-		if ( _glExtensionTextureFilterAnisotropic && texture.type !== THREE.FloatType ) {
-
-			if ( texture.anisotropy > 1 || texture.__oldAnisotropy ) {
-
-				_gl.texParameterf( textureType, _glExtensionTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _maxAnisotropy ) );
-				texture.__oldAnisotropy = texture.anisotropy;
-
-			}
-
-		}
-
-	}
-
-	function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
-
-		_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
-		_gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
-
-	}
-
-	function setupRenderBuffer ( renderbuffer, renderTarget  ) {
-
-		_gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
-
-		if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
-
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
-			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
-
-		/* For some reason this is not working. Defaulting to RGBA4.
-		} else if( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
-
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
-			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
-		*/
-		} else if( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
-
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
-			_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
-
-		} else {
-
-			_gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
-
-		}
-
-	}
-
-	function setRenderTarget( renderTarget ) {
-
-		var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
-
-		if ( renderTarget && ! renderTarget.__webglFramebuffer ) {
-
-			if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
-			if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
-
-			//renderTarget.addEventListener( 'dispose', onRenderTargetDispose );
-
-			renderTarget.__webglTexture = _gl.createTexture();
-
-			//_this.info.memory.textures ++;
-
-			// Setup texture, create render and frame buffers
-
-			var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ),
-				glFormat = paramThreeToGL( renderTarget.format ),
-				glType = paramThreeToGL( renderTarget.type );
-
-			if ( isCube ) {
-
-				renderTarget.__webglFramebuffer = [];
-				renderTarget.__webglRenderbuffer = [];
-
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
-				setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
-
-				for ( var i = 0; i < 6; i ++ ) {
-
-					renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
-					renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
-
-					_gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
-
-					setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
-					setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );
-
-				}
-
-				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
-
-			} else {
-
-				renderTarget.__webglFramebuffer = _gl.createFramebuffer();
-
-				if ( renderTarget.shareDepthFrom ) {
-
-					renderTarget.__webglRenderbuffer = renderTarget.shareDepthFrom.__webglRenderbuffer;
-
-				} else {
-
-					renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
-
-				}
-
-				_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
-				setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
-
-				_gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
-
-				setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
-
-				if ( renderTarget.shareDepthFrom ) {
-
-					if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
-
-						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
-
-					} else if ( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
-
-						_gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderTarget.__webglRenderbuffer );
-
-					}
-
-				} else {
-
-					setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
-
-				}
-
-				if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
-
-			}
-
-			// Release everything
-
-			if ( isCube ) {
-
-				_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
-
-			} else {
-
-				_gl.bindTexture( _gl.TEXTURE_2D, null );
-
-			}
-
-			_gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
-			_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
-
-		}
-
-		var framebuffer, width, height, vx, vy;
-
-		if ( renderTarget ) {
-
-			if ( isCube ) {
-
-				framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
-
-			} else {
-
-				framebuffer = renderTarget.__webglFramebuffer;
-
-			}
-
-			width = renderTarget.width;
-			height = renderTarget.height;
-
-			vx = 0;
-			vy = 0;
-
-		} else {
-
-			framebuffer = null;
-
-			width = _viewportWidth;
-			height = _viewportHeight;
-
-			vx = _viewportX;
-			vy = _viewportY;
-
-		}
-
-		if ( framebuffer !== _currentFramebuffer ) {
-
-			_gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
-			_gl.viewport( vx, vy, width, height );
-
-			_currentFramebuffer = framebuffer;
-
-		}
-
-		_currentWidth = width;
-		_currentHeight = height;
-
-	}
-
-	function clampToMaxSize ( image, maxSize ) {
-
-		if ( image.width <= maxSize && image.height <= maxSize ) {
-
-			return image;
-
-		}
-
-		// Warning: Scaling through the canvas will only work with images that use
-		// premultiplied alpha.
-
-		var maxDimension = Math.max( image.width, image.height );
-		var newWidth = Math.floor( image.width * maxSize / maxDimension );
-		var newHeight = Math.floor( image.height * maxSize / maxDimension );
-
-		var canvas = document.createElement( 'canvas' );
-		canvas.width = newWidth;
-		canvas.height = newHeight;
-
-		var ctx = canvas.getContext( "2d" );
-		ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight );
-
-		return canvas;
-
-	}
-
-	function updateRenderTargetMipmap ( renderTarget ) {
-
-		if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
-
-			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
-			_gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
-			_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
-
-		} else {
-
-			_gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
-			_gl.generateMipmap( _gl.TEXTURE_2D );
-			_gl.bindTexture( _gl.TEXTURE_2D, null );
-
-		}
-
-	}
-
-	function setCubeTextureDynamic ( texture, slot ) {
-
-		_gl.activeTexture( _gl.TEXTURE0 + slot );
-		_gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
-
-	}
-
-	// Map three.js constants to WebGL constants
-	function paramThreeToGL ( p ) {
-
-		if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
-		if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
-		if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
-
-		if ( p === THREE.NearestFilter ) return _gl.NEAREST;
-		if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
-		if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
-
-		if ( p === THREE.LinearFilter ) return _gl.LINEAR;
-		if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
-		if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
-
-		if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
-		if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
-		if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
-		if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
-
-		if ( p === THREE.ByteType ) return _gl.BYTE;
-		if ( p === THREE.ShortType ) return _gl.SHORT;
-		if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
-		if ( p === THREE.IntType ) return _gl.INT;
-		if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
-		if ( p === THREE.FloatType ) return _gl.FLOAT;
-
-		if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
-		if ( p === THREE.RGBFormat ) return _gl.RGB;
-		if ( p === THREE.RGBAFormat ) return _gl.RGBA;
-		if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
-		if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
-
-		if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
-		if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
-		if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
-
-		if ( p === THREE.ZeroFactor ) return _gl.ZERO;
-		if ( p === THREE.OneFactor ) return _gl.ONE;
-		if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
-		if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
-		if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
-		if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
-		if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
-		if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
-
-		if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
-		if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
-		if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
-
-		if ( _glExtensionCompressedTextureS3TC !== undefined ) {
-
-			if ( p === THREE.RGB_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT;
-			if ( p === THREE.RGBA_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT;
-			if ( p === THREE.RGBA_S3TC_DXT3_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT;
-			if ( p === THREE.RGBA_S3TC_DXT5_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT;
-
-		}
-
-		return 0;
-
-	}
-
-	function compileShader(vertexShader, fragmentShader){
-
-		var program = _gl.createProgram();
-
-		var glFragmentShader = getShader( "fragment", fragmentShader );
-		var glVertexShader = getShader( "vertex", vertexShader );
-
-		_gl.attachShader( program, glVertexShader );
-		_gl.attachShader( program, glFragmentShader );
-
-		_gl.linkProgram( program );
-
-		if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
-
-			console.error( "Could not initialise shader\n" + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
-
-		}
-
-		// clean up
-
-		_gl.deleteShader( glFragmentShader );
-		_gl.deleteShader( glVertexShader );
-
-		return program;
-
-	}
-
-	function resetState(){
-
-		_oldBlending = -1;
-		_oldDepthTest = -1;
-		_oldDepthWrite = -1;
-		_oldDoubleSided = -1;
-		_oldFlipSided = -1;
-
-	}
-
-	function getShader ( type, string ) {
-
-		var shader;
-
-		if ( type === "fragment" ) {
-
-			shader = _gl.createShader( _gl.FRAGMENT_SHADER );
-
-		} else if ( type === "vertex" ) {
-
-			shader = _gl.createShader( _gl.VERTEX_SHADER );
-
-		}
-
-		_gl.shaderSource( shader, string );
-		_gl.compileShader( shader );
-
-		if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
-
-			console.error( _gl.getShaderInfoLog( shader ) );
-			console.error( addLineNumbers( string ) );
-			return null;
-
-		}
-
-		return shader;
-
-	}
-
-	function addLineNumbers ( string ) {
-
-		var chunks = string.split( "\n" );
-
-		for ( var i = 0, il = chunks.length; i < il; i ++ ) {
-
-			// Chrome reports shader errors on lines
-			// starting counting from 1
-
-			chunks[ i ] = ( i + 1 ) + ": " + chunks[ i ];
-
-		}
-
-		return chunks.join( "\n" );
-
-	}
-
-	function setLineWidth ( width ) {
-
-		if ( width !== _oldLineWidth ) {
-
-			_gl.lineWidth( width );
-
-			_oldLineWidth = width;
-
-		}
-
-	}
-
-	return {
-
-		context: _gl,
-
-		autoScaleCubemaps: _autoScaleCubemaps,
-		supportsBoneTextures: _supportsBoneTextures,
-		precision: _precision,
-		maxVertexUniformVectors: _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS ),
-
-		// Methods
-
-		getContext: getContext,
-		getDomElement: getDomElement,
-		getPrecision: getPrecision,
-		getCurrentWidth: getCurrentWidth,
-		getCurrentHeight: getCurrentHeight,
-		supportsVertexTextures: supportsVertexTextures,
-		supportsFloatTextures: supportsFloatTextures,
-		supportsStandardDerivatives: supportsStandardDerivatives,
-		supportsCompressedTextureS3TC: supportsCompressedTextureS3TC,
-		getMaxAnisotropy: getMaxAnisotropy,
-
-		setRenderTarget: setRenderTarget,
-		setSize: setSize,
-		setViewport: setViewport,
-		setScissor: setScissor,
-		enableScissorTest: enableScissorTest,
-
-		setClearColorHex: setClearColorHex,
-		setClearColor: setClearColor,
-		getClearColor: getClearColor,
-		getClearAlpha: getClearAlpha,
-		clear: clear,
-		clearTarget: clearTarget,
-
-		deleteBuffer: deleteBuffer,
-		deleteTexture: deleteTexture,
-		deleteFramebuffer: deleteFramebuffer,
-		deleteRenderbuffer: deleteRenderbuffer,
-		deleteProgram: deleteProgram,
-
-		createBuffer: createBuffer,
-		setStaticArrayBuffer: setStaticArrayBuffer,
-		setStaticIndexBuffer: setStaticIndexBuffer,
-		setDynamicArrayBuffer: setDynamicArrayBuffer,
-		setDynamicIndexBuffer: setDynamicIndexBuffer,
-
-		drawTriangles: drawTriangles,
-		drawTriangleStrip: drawTriangleStrip,
-		drawLines: drawLines,
-		drawLineStrip: drawLineStrip,
-		drawPoints: drawPoints,
-		drawTriangleElements: drawTriangleElements,
-		drawLineElements: drawLineElements,
-
-		bindArrayBuffer: bindArrayBuffer,
-		bindElementArrayBuffer: bindElementArrayBuffer,
-
-		enableAttribute: enableAttribute,
-		disableAttributes: disableAttributes,
-		getAttribLocation: getAttribLocation,
-		setFloatAttribute: setFloatAttribute,
-
-		getUniformLocation: getUniformLocation,
-
-		uniform1i: uniform1i,
-		uniform1f: uniform1f,
-		uniform2f: uniform2f,
-		uniform3f: uniform3f,
-		uniform4f: uniform4f,
-		uniform1iv: uniform1iv,
-		uniform2iv: uniform2iv,
-		uniform3iv: uniform3iv,
-		uniform1fv: uniform1fv,
-		uniform2fv: uniform2fv,
-		uniform3fv: uniform3fv,
-		uniform4fv: uniform4fv,
-		uniformMatrix3fv: uniformMatrix3fv,
-		uniformMatrix4fv: uniformMatrix4fv,
-
-		useProgram: useProgram,
-		compileShader: compileShader,
-
-		setFaceCulling: setFaceCulling,
-		setMaterialFaces: setMaterialFaces,
-		setPolygonOffset: setPolygonOffset,
-		setBlending: setBlending,
-		setDepthTest: setDepthTest,
-		setDepthWrite: setDepthWrite,
-
-		setTexture: setTexture,
-		setCubeTexture: setCubeTexture,
-		updateRenderTargetMipmap: updateRenderTargetMipmap,
-		setCubeTextureDynamic: setCubeTextureDynamic,
-
-		paramThreeToGL: paramThreeToGL,
-		setLineWidth: setLineWidth,
-		resetState: resetState
-
-	}
-
-};

+ 0 - 413
examples/js/renderers/WebGLRenderer2/webgl/ShaderBuilder.js

@@ -1,413 +0,0 @@
-
-THREE.WebGLRenderer.ShaderBuilder = function ( renderer, info ) {
-
-	this.renderer = renderer;
-	this.info = info;
-	this.programs = [],
-	this.programs_counter = 0;
-
-};
-
-THREE.extend( THREE.WebGLRenderer.ShaderBuilder.prototype, {
-
-	buildProgram: function ( shaderID, fragmentShader, vertexShader, uniforms, attributes, defines, parameters ) {
-
-		var renderer = this.renderer;
-		var p, pl, d, program, code;
-		var chunks = [];
-
-		// Generate code
-
-		if ( shaderID ) {
-
-			chunks.push( shaderID );
-
-		} else {
-
-			chunks.push( fragmentShader );
-			chunks.push( vertexShader );
-
-		}
-
-		for ( d in defines ) {
-
-			chunks.push( d );
-			chunks.push( defines[ d ] );
-
-		}
-
-		for ( p in parameters ) {
-
-			chunks.push( p );
-			chunks.push( parameters[ p ] );
-
-		}
-
-		code = chunks.join();
-
-		// Check if code has been already compiled
-
-		for ( p = 0, pl = this.programs.length; p < pl; p ++ ) {
-
-			var programInfo = this.programs[ p ];
-
-			if ( programInfo.code === code ) {
-
-				//console.log( "Code already compiled." /*: \n\n" + code*/ );
-
-				programInfo.usedTimes ++;
-
-				return programInfo.program;
-
-			}
-
-		}
-
-		var shadowMapTypeDefine = "SHADOWMAP_TYPE_BASIC";
-
-		if ( parameters.shadowMapType === THREE.PCFShadowMap ) {
-
-			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF";
-
-		} else if ( parameters.shadowMapType === THREE.PCFSoftShadowMap ) {
-
-			shadowMapTypeDefine = "SHADOWMAP_TYPE_PCF_SOFT";
-
-		}
-
-		//console.log( "building new program " );
-
-		//
-
-		var customDefines = this.generateDefines( defines );
-
-		//
-
-		var prefix_vertex = [
-
-			"precision " + renderer.precision + " float;",
-
-			customDefines,
-
-			renderer.supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
-
-			parameters.gammaInput ? "#define GAMMA_INPUT" : "",
-			parameters.gammaOutput ? "#define GAMMA_OUTPUT" : "",
-			parameters.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
-
-			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
-			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
-			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
-			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
-
-			"#define MAX_SHADOWS " + parameters.maxShadows,
-
-			"#define MAX_BONES " + parameters.maxBones,
-
-			parameters.map ? "#define USE_MAP" : "",
-			parameters.envMap ? "#define USE_ENVMAP" : "",
-			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
-			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
-			parameters.normalMap ? "#define USE_NORMALMAP" : "",
-			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
-			parameters.vertexColors ? "#define USE_COLOR" : "",
-
-			parameters.skinning ? "#define USE_SKINNING" : "",
-			parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
-			parameters.boneTextureWidth ? "#define N_BONE_PIXEL_X " + parameters.boneTextureWidth.toFixed( 1 ) : "",
-			parameters.boneTextureHeight ? "#define N_BONE_PIXEL_Y " + parameters.boneTextureHeight.toFixed( 1 ) : "",
-
-			parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
-			parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
-			parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
-			parameters.wrapAround ? "#define WRAP_AROUND" : "",
-			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
-			parameters.flipSided ? "#define FLIP_SIDED" : "",
-
-			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
-			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
-			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
-			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
-
-			parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
-
-			"uniform mat4 modelMatrix;",
-			"uniform mat4 modelViewMatrix;",
-			"uniform mat4 projectionMatrix;",
-			"uniform mat4 viewMatrix;",
-			"uniform mat3 normalMatrix;",
-			"uniform vec3 cameraPosition;",
-
-			"attribute vec3 position;",
-			"attribute vec3 normal;",
-			"attribute vec2 uv;",
-			"attribute vec2 uv2;",
-
-			"#ifdef USE_COLOR",
-
-				"attribute vec3 color;",
-
-			"#endif",
-
-			"#ifdef USE_MORPHTARGETS",
-
-				"attribute vec3 morphTarget0;",
-				"attribute vec3 morphTarget1;",
-				"attribute vec3 morphTarget2;",
-				"attribute vec3 morphTarget3;",
-
-				"#ifdef USE_MORPHNORMALS",
-
-					"attribute vec3 morphNormal0;",
-					"attribute vec3 morphNormal1;",
-					"attribute vec3 morphNormal2;",
-					"attribute vec3 morphNormal3;",
-
-				"#else",
-
-					"attribute vec3 morphTarget4;",
-					"attribute vec3 morphTarget5;",
-					"attribute vec3 morphTarget6;",
-					"attribute vec3 morphTarget7;",
-
-				"#endif",
-
-			"#endif",
-
-			"#ifdef USE_SKINNING",
-
-				"attribute vec4 skinIndex;",
-				"attribute vec4 skinWeight;",
-
-			"#endif",
-
-			""
-
-		].join("\n");
-
-		var prefix_fragment = [
-
-			"precision " + renderer.precision + " float;",
-
-			( parameters.bumpMap || parameters.normalMap ) ? "#extension GL_OES_standard_derivatives : enable" : "",
-
-			customDefines,
-
-			"#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
-			"#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
-			"#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
-			"#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
-
-			"#define MAX_SHADOWS " + parameters.maxShadows,
-
-			parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",
-
-			parameters.gammaInput ? "#define GAMMA_INPUT" : "",
-			parameters.gammaOutput ? "#define GAMMA_OUTPUT" : "",
-    		parameters.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
-
-			( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
-			( parameters.useFog && parameters.fogExp ) ? "#define FOG_EXP2" : "",
-
-			parameters.map ? "#define USE_MAP" : "",
-			parameters.envMap ? "#define USE_ENVMAP" : "",
-			parameters.lightMap ? "#define USE_LIGHTMAP" : "",
-			parameters.bumpMap ? "#define USE_BUMPMAP" : "",
-			parameters.normalMap ? "#define USE_NORMALMAP" : "",
-			parameters.specularMap ? "#define USE_SPECULARMAP" : "",
-			parameters.vertexColors ? "#define USE_COLOR" : "",
-
-			parameters.metal ? "#define METAL" : "",
-			parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
-			parameters.wrapAround ? "#define WRAP_AROUND" : "",
-			parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
-			parameters.flipSided ? "#define FLIP_SIDED" : "",
-
-			parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
-			parameters.shadowMapEnabled ? "#define " + shadowMapTypeDefine : "",
-			parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
-			parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
-
-			"uniform mat4 viewMatrix;",
-			"uniform vec3 cameraPosition;",
-			""
-
-		].join("\n");
-
-		program = renderer.compileShader(prefix_vertex + vertexShader, prefix_fragment + fragmentShader);
-
-		//console.log( prefix_fragment + fragmentShader );
-		//console.log( prefix_vertex + vertexShader );
-
-		program.uniforms = {};
-		program.attributes = {};
-
-		var identifiers, u, a, i;
-
-		// cache uniform locations
-
-		identifiers = [
-
-			'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition',
-			'morphTargetInfluences'
-
-		];
-
-		if ( parameters.useVertexTexture ) {
-
-			identifiers.push( 'boneTexture' );
-
-		} else {
-
-			identifiers.push( 'boneGlobalMatrices' );
-
-		}
-
-		for ( u in uniforms ) {
-
-			identifiers.push( u );
-
-		}
-
-		this.cacheUniformLocations( program, identifiers );
-
-		// cache attributes locations
-
-		identifiers = [
-
-			"position", "normal", "uv", "uv2", "tangent", "color",
-			"skinIndex", "skinWeight", "lineDistance"
-
-		];
-
-		for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
-
-			identifiers.push( "morphTarget" + i );
-
-		}
-
-		for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {
-
-			identifiers.push( "morphNormal" + i );
-
-		}
-
-		for ( a in attributes ) {
-
-			identifiers.push( a );
-
-		}
-
-		this.cacheAttributeLocations( program, identifiers );
-
-		program.id = this.programs_counter ++;
-
-		this.programs.push( { program: program, code: code, usedTimes: 1 } );
-
-		this.info.memory.programs = this.programs.length;
-
-		return program;
-
-	},
-
-	generateDefines: function ( defines ) {
-
-		var value, chunk, chunks = [];
-
-		for ( var d in defines ) {
-
-			value = defines[ d ];
-			if ( value === false ) continue;
-
-			chunk = "#define " + d + " " + value;
-			chunks.push( chunk );
-
-		}
-
-		return chunks.join( "\n" );
-
-	},
-
-	// Shader parameters cache
-
-	cacheUniformLocations: function ( program, identifiers ) {
-
-		var i, l, id, renderer = this.renderer;
-
-		for ( i = 0, l = identifiers.length; i < l; i ++ ) {
-
-			id = identifiers[ i ];
-			program.uniforms[ id ] = renderer.getUniformLocation( program, id );
-
-		}
-
-	},
-
-	cacheAttributeLocations: function ( program, identifiers ) {
-
-		var i, l, id, renderer = this.renderer;
-
-		for( i = 0, l = identifiers.length; i < l; i ++ ) {
-
-			id = identifiers[ i ];
-			program.attributes[ id ] = renderer.getAttribLocation( program, id );
-
-		}
-
-	},
-
-	removeProgram: function ( program ) {
-
-		var i, il, programInfo;
-		var deleteProgram = false;
-		var programs = this.programs;
-
-		for ( i = 0, il = programs.length; i < il; i ++ ) {
-
-			programInfo = programs[ i ];
-
-			if ( programInfo.program === program ) {
-
-				programInfo.usedTimes --;
-
-				if ( programInfo.usedTimes === 0 ) {
-
-					deleteProgram = true;
-
-				}
-
-				break;
-
-			}
-
-		}
-
-		if ( deleteProgram === true ) {
-
-			// avoid using array.splice, this is costlier than creating new array from scratch
-
-			var newPrograms = [];
-
-			for ( i = 0, il = programs.length; i < il; i ++ ) {
-
-				programInfo = programs[ i ];
-
-				if ( programInfo.program !== program ) {
-
-					newPrograms.push( programInfo );
-
-				}
-
-			}
-
-			this.programs = newPrograms;
-
-			this.renderer.deleteProgram( program );
-
-			this.info.memory.programs --;
-
-		}
-
-	}
-
-} );

+ 0 - 206
examples/js/renderers/WebGLRenderer2/webgl/objects/LineRenderer.js

@@ -1,206 +0,0 @@
-
-THREE.WebGLRenderer.LineRenderer = function ( lowlevelrenderer, info ) {
-
-	THREE.WebGLRenderer.Object3DRenderer.call( this, lowlevelrenderer, info );
-
-};
-
-THREE.WebGLRenderer.LineRenderer.prototype = Object.create( THREE.WebGLRenderer.Object3DRenderer.prototype );
-
-THREE.extend( THREE.WebGLRenderer.LineRenderer.prototype, {
-
-	createBuffers: function ( geometry ) {
-
-		var renderer = this.renderer;
-		geometry.__webglVertexBuffer = renderer.createBuffer();
-		geometry.__webglColorBuffer = renderer.createBuffer();
-		geometry.__webglLineDistanceBuffer = renderer.createBuffer();
-
-		this.info.memory.geometries ++;
-
-	},
-
-	initBuffers: function ( geometry, object ) {
-
-		var nvertices = geometry.vertices.length;
-
-		geometry.__vertexArray = new Float32Array( nvertices * 3 );
-		geometry.__colorArray = new Float32Array( nvertices * 3 );
-		geometry.__lineDistanceArray = new Float32Array( nvertices * 1 );
-
-		geometry.__webglLineCount = nvertices;
-
-		this.initCustomAttributes ( geometry, object );
-
-	},
-
-	setBuffers: function ( geometry, object ) {
-
-		var renderer = this.renderer;
-		var v, c, d, vertex, offset, color,
-
-		vertices = geometry.vertices,
-		colors = geometry.colors,
-		lineDistances = geometry.lineDistances,
-
-		vl = vertices.length,
-		cl = colors.length,
-		dl = lineDistances.length,
-
-		vertexArray = geometry.__vertexArray,
-		colorArray = geometry.__colorArray,
-		lineDistanceArray = geometry.__lineDistanceArray,
-
-		dirtyVertices = geometry.verticesNeedUpdate,
-		dirtyColors = geometry.colorsNeedUpdate,
-		dirtyLineDistances = geometry.lineDistancesNeedUpdate,
-
-		customAttributes = geometry.__webglCustomAttributesList,
-
-		i, il,
-		a, ca, cal, value,
-		customAttribute;
-
-		if ( dirtyVertices ) {
-
-			for ( v = 0; v < vl; v ++ ) {
-
-				vertex = vertices[ v ];
-
-				offset = v * 3;
-
-				vertexArray[ offset ]     = vertex.x;
-				vertexArray[ offset + 1 ] = vertex.y;
-				vertexArray[ offset + 2 ] = vertex.z;
-
-			}
-
-			renderer.setDynamicArrayBuffer(geometry.__webglVertexBuffer,vertexArray);
-
-		}
-
-		if ( dirtyColors ) {
-
-			for ( c = 0; c < cl; c ++ ) {
-
-				color = colors[ c ];
-
-				offset = c * 3;
-
-				colorArray[ offset ]     = color.r;
-				colorArray[ offset + 1 ] = color.g;
-				colorArray[ offset + 2 ] = color.b;
-
-			}
-
-			renderer.setDynamicArrayBuffer(geometry.__webglColorBuffer,colorArray);
-
-		}
-
-		if ( dirtyLineDistances ) {
-
-			for ( d = 0; d < dl; d ++ ) {
-
-				lineDistanceArray[ d ] = lineDistances[ d ];
-
-			}
-
-			renderer.setDynamicArrayBuffer( geometry.__webglLineDistanceBuffer,lineDistanceArray);
-
-		}
-
-		if ( customAttributes ) {
-
-			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-				customAttribute = customAttributes[ i ];
-
-				if ( customAttribute.needsUpdate &&
-					 ( customAttribute.boundTo === undefined ||
-					   customAttribute.boundTo === "vertices" ) ) {
-
-					offset = 0;
-
-					cal = customAttribute.value.length;
-
-					if ( customAttribute.size === 1 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							customAttribute.array[ ca ] = customAttribute.value[ ca ];
-
-						}
-
-					} else if ( customAttribute.size === 2 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							value = customAttribute.value[ ca ];
-
-							customAttribute.array[ offset ] 	= value.x;
-							customAttribute.array[ offset + 1 ] = value.y;
-
-							offset += 2;
-
-						}
-
-					} else if ( customAttribute.size === 3 ) {
-
-						if ( customAttribute.type === "c" ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.r;
-								customAttribute.array[ offset + 1 ] = value.g;
-								customAttribute.array[ offset + 2 ] = value.b;
-
-								offset += 3;
-
-							}
-
-						} else {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.x;
-								customAttribute.array[ offset + 1 ] = value.y;
-								customAttribute.array[ offset + 2 ] = value.z;
-
-								offset += 3;
-
-							}
-
-						}
-
-					} else if ( customAttribute.size === 4 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							value = customAttribute.value[ ca ];
-
-							customAttribute.array[ offset ] 	 = value.x;
-							customAttribute.array[ offset + 1  ] = value.y;
-							customAttribute.array[ offset + 2  ] = value.z;
-							customAttribute.array[ offset + 3  ] = value.w;
-
-							offset += 4;
-
-						}
-
-					}
-
-					renderer.setDynamicArrayBuffer( customAttribute.buffer,customAttribute.array);
-
-				}
-
-			}
-
-		}
-
-	}
-
-} );

+ 0 - 1618
examples/js/renderers/WebGLRenderer2/webgl/objects/MeshRenderer.js

@@ -1,1618 +0,0 @@
-
-THREE.WebGLRenderer.MeshRenderer = function ( lowlevelrenderer, info ) {
-
-	THREE.WebGLRenderer.Object3DRenderer.call( this, lowlevelrenderer, info );
-
-};
-
-THREE.WebGLRenderer.MeshRenderer.prototype = Object.create( THREE.WebGLRenderer.Object3DRenderer.prototype );
-
-THREE.extend( THREE.WebGLRenderer.MeshRenderer.prototype, {
-
-	createBuffers: function ( geometryGroup ) {
-
-		var renderer = this.renderer;
-		geometryGroup.__webglVertexBuffer = renderer.createBuffer();
-		geometryGroup.__webglNormalBuffer = renderer.createBuffer();
-		geometryGroup.__webglTangentBuffer = renderer.createBuffer();
-		geometryGroup.__webglColorBuffer = renderer.createBuffer();
-		geometryGroup.__webglUVBuffer = renderer.createBuffer();
-		geometryGroup.__webglUV2Buffer = renderer.createBuffer();
-
-		geometryGroup.__webglSkinIndicesBuffer = renderer.createBuffer();
-		geometryGroup.__webglSkinWeightsBuffer = renderer.createBuffer();
-
-		geometryGroup.__webglFaceBuffer = renderer.createBuffer();
-		geometryGroup.__webglLineBuffer = renderer.createBuffer();
-
-		var m, ml;
-
-		if ( geometryGroup.numMorphTargets ) {
-
-			geometryGroup.__webglMorphTargetsBuffers = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-				geometryGroup.__webglMorphTargetsBuffers.push( renderer.createBuffer() );
-
-			}
-
-		}
-
-		if ( geometryGroup.numMorphNormals ) {
-
-			geometryGroup.__webglMorphNormalsBuffers = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-				geometryGroup.__webglMorphNormalsBuffers.push( renderer.createBuffer() );
-
-			}
-
-		}
-
-		this.info.memory.geometries ++;
-
-	},
-
-	initBuffers: function ( geometryGroup, object ) {
-
-		var geometry = object.geometry,
-			faces3 = geometryGroup.faces3,
-			faces4 = geometryGroup.faces4,
-
-			nvertices = faces3.length * 3 + faces4.length * 4,
-			ntris     = faces3.length * 1 + faces4.length * 2,
-			nlines    = faces3.length * 3 + faces4.length * 4,
-
-			material = this.getBufferMaterial( object, geometryGroup ),
-
-			uvType = this.bufferGuessUVType( material ),
-			normalType = this.bufferGuessNormalType( material ),
-			vertexColorType = this.bufferGuessVertexColorType( material );
-
-		//console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
-
-		geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
-
-		if ( normalType ) {
-
-			geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
-
-		}
-
-		if ( geometry.hasTangents ) {
-
-			geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
-
-		}
-
-		if ( vertexColorType ) {
-
-			geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
-
-		}
-
-		if ( uvType ) {
-
-			if ( geometry.faceVertexUvs.length > 0 ) {
-
-				geometryGroup.__uvArray = new Float32Array( nvertices * 2 );
-
-			}
-
-			if ( geometry.faceVertexUvs.length > 1 ) {
-
-				geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );
-
-			}
-
-		}
-
-		if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {
-
-			geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
-			geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );
-
-		}
-
-		geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
-		geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
-
-		var m, ml;
-
-		if ( geometryGroup.numMorphTargets ) {
-
-			geometryGroup.__morphTargetsArrays = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
-
-				geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
-
-			}
-
-		}
-
-		if ( geometryGroup.numMorphNormals ) {
-
-			geometryGroup.__morphNormalsArrays = [];
-
-			for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
-
-				geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
-
-			}
-
-		}
-
-		geometryGroup.__webglFaceCount = ntris * 3;
-		geometryGroup.__webglLineCount = nlines * 2;
-
-
-		// custom attributes
-
-		if ( material.attributes ) {
-
-			if ( geometryGroup.__webglCustomAttributesList === undefined ) {
-
-				geometryGroup.__webglCustomAttributesList = [];
-
-			}
-
-			for ( var a in material.attributes ) {
-
-				// Do a shallow copy of the attribute object so different geometryGroup chunks use different
-				// attribute buffers which are correctly indexed in the setMeshBuffers function
-
-				var originalAttribute = material.attributes[ a ];
-
-				var attribute = {};
-
-				for ( var property in originalAttribute ) {
-
-					attribute[ property ] = originalAttribute[ property ];
-
-				}
-
-				if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
-
-					attribute.__webglInitialized = true;
-
-					var size = 1;		// "f" and "i"
-
-					if( attribute.type === "v2" ) size = 2;
-					else if( attribute.type === "v3" ) size = 3;
-					else if( attribute.type === "v4" ) size = 4;
-					else if( attribute.type === "c"  ) size = 3;
-
-					attribute.size = size;
-
-					attribute.array = new Float32Array( nvertices * size );
-
-					attribute.buffer = this.renderer.createBuffer();
-					attribute.buffer.belongsToAttribute = a;
-
-					originalAttribute.needsUpdate = true;
-					attribute.__original = originalAttribute;
-
-				}
-
-				geometryGroup.__webglCustomAttributesList.push( attribute );
-
-			}
-
-		}
-
-		geometryGroup.__inittedArrays = true;
-
-	},
-
-	setBuffers: function ( geometryGroup, object, dispose, material ) {
-
-		if ( ! geometryGroup.__inittedArrays ) {
-
-			return;
-
-		}
-
-		var renderer = this.renderer;
-		var normalType = this.bufferGuessNormalType( material ),
-		vertexColorType = this.bufferGuessVertexColorType( material ),
-		uvType = this.bufferGuessUVType( material ),
-
-		needsSmoothNormals = ( normalType === THREE.SmoothShading );
-
-		var f, fl, fi, face,
-		vertexNormals, faceNormal, normal,
-		vertexColors, faceColor,
-		vertexTangents,
-		uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
-		c1, c2, c3, c4,
-		sw1, sw2, sw3, sw4,
-		si1, si2, si3, si4,
-		sa1, sa2, sa3, sa4,
-		sb1, sb2, sb3, sb4,
-		m, ml, i, il,
-		vn, uvi, uv2i,
-		vk, vkl, vka,
-		nka, chf, faceVertexNormals,
-		a,
-
-		vertexIndex = 0,
-
-		offset = 0,
-		offset_uv = 0,
-		offset_uv2 = 0,
-		offset_face = 0,
-		offset_normal = 0,
-		offset_tangent = 0,
-		offset_line = 0,
-		offset_color = 0,
-		offset_skin = 0,
-		offset_morphTarget = 0,
-		offset_custom = 0,
-		offset_customSrc = 0,
-
-		value,
-
-		vertexArray = geometryGroup.__vertexArray,
-		uvArray = geometryGroup.__uvArray,
-		uv2Array = geometryGroup.__uv2Array,
-		normalArray = geometryGroup.__normalArray,
-		tangentArray = geometryGroup.__tangentArray,
-		colorArray = geometryGroup.__colorArray,
-
-		skinIndexArray = geometryGroup.__skinIndexArray,
-		skinWeightArray = geometryGroup.__skinWeightArray,
-
-		morphTargetsArrays = geometryGroup.__morphTargetsArrays,
-		morphNormalsArrays = geometryGroup.__morphNormalsArrays,
-
-		customAttributes = geometryGroup.__webglCustomAttributesList,
-		customAttribute,
-
-		faceArray = geometryGroup.__faceArray,
-		lineArray = geometryGroup.__lineArray,
-
-		geometry = object.geometry, // this is shared for all chunks
-
-		dirtyVertices = geometry.verticesNeedUpdate,
-		dirtyElements = geometry.elementsNeedUpdate,
-		dirtyUvs = geometry.uvsNeedUpdate,
-		dirtyNormals = geometry.normalsNeedUpdate,
-		dirtyTangents = geometry.tangentsNeedUpdate,
-		dirtyColors = geometry.colorsNeedUpdate,
-		dirtyMorphTargets = geometry.morphTargetsNeedUpdate,
-
-		vertices = geometry.vertices,
-		chunk_faces3 = geometryGroup.faces3,
-		chunk_faces4 = geometryGroup.faces4,
-		obj_faces = geometry.faces,
-
-		obj_uvs  = geometry.faceVertexUvs[ 0 ],
-		obj_uvs2 = geometry.faceVertexUvs[ 1 ],
-
-		obj_colors = geometry.colors,
-
-		obj_skinIndices = geometry.skinIndices,
-		obj_skinWeights = geometry.skinWeights,
-
-		morphTargets = geometry.morphTargets,
-		morphNormals = geometry.morphNormals;
-
-		if ( dirtyVertices ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ] ];
-
-				v1 = vertices[ face.a ];
-				v2 = vertices[ face.b ];
-				v3 = vertices[ face.c ];
-
-				vertexArray[ offset ]     = v1.x;
-				vertexArray[ offset + 1 ] = v1.y;
-				vertexArray[ offset + 2 ] = v1.z;
-
-				vertexArray[ offset + 3 ] = v2.x;
-				vertexArray[ offset + 4 ] = v2.y;
-				vertexArray[ offset + 5 ] = v2.z;
-
-				vertexArray[ offset + 6 ] = v3.x;
-				vertexArray[ offset + 7 ] = v3.y;
-				vertexArray[ offset + 8 ] = v3.z;
-
-				offset += 9;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				v1 = vertices[ face.a ];
-				v2 = vertices[ face.b ];
-				v3 = vertices[ face.c ];
-				v4 = vertices[ face.d ];
-
-				vertexArray[ offset ]     = v1.x;
-				vertexArray[ offset + 1 ] = v1.y;
-				vertexArray[ offset + 2 ] = v1.z;
-
-				vertexArray[ offset + 3 ] = v2.x;
-				vertexArray[ offset + 4 ] = v2.y;
-				vertexArray[ offset + 5 ] = v2.z;
-
-				vertexArray[ offset + 6 ] = v3.x;
-				vertexArray[ offset + 7 ] = v3.y;
-				vertexArray[ offset + 8 ] = v3.z;
-
-				vertexArray[ offset + 9 ]  = v4.x;
-				vertexArray[ offset + 10 ] = v4.y;
-				vertexArray[ offset + 11 ] = v4.z;
-
-				offset += 12;
-
-			}
-
-			renderer.setDynamicArrayBuffer( geometryGroup.__webglVertexBuffer, vertexArray);
-
-		}
-
-		if ( dirtyMorphTargets ) {
-
-			for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {
-
-				offset_morphTarget = 0;
-
-				for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-					chf = chunk_faces3[ f ];
-					face = obj_faces[ chf ];
-
-					// morph positions
-
-					v1 = morphTargets[ vk ].vertices[ face.a ];
-					v2 = morphTargets[ vk ].vertices[ face.b ];
-					v3 = morphTargets[ vk ].vertices[ face.c ];
-
-					vka = morphTargetsArrays[ vk ];
-
-					vka[ offset_morphTarget ] 	  = v1.x;
-					vka[ offset_morphTarget + 1 ] = v1.y;
-					vka[ offset_morphTarget + 2 ] = v1.z;
-
-					vka[ offset_morphTarget + 3 ] = v2.x;
-					vka[ offset_morphTarget + 4 ] = v2.y;
-					vka[ offset_morphTarget + 5 ] = v2.z;
-
-					vka[ offset_morphTarget + 6 ] = v3.x;
-					vka[ offset_morphTarget + 7 ] = v3.y;
-					vka[ offset_morphTarget + 8 ] = v3.z;
-
-					// morph normals
-
-					if ( material.morphNormals ) {
-
-						if ( needsSmoothNormals ) {
-
-							faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
-
-							n1 = faceVertexNormals.a;
-							n2 = faceVertexNormals.b;
-							n3 = faceVertexNormals.c;
-
-						} else {
-
-							n1 = morphNormals[ vk ].faceNormals[ chf ];
-							n2 = n1;
-							n3 = n1;
-
-						}
-
-						nka = morphNormalsArrays[ vk ];
-
-						nka[ offset_morphTarget ] 	  = n1.x;
-						nka[ offset_morphTarget + 1 ] = n1.y;
-						nka[ offset_morphTarget + 2 ] = n1.z;
-
-						nka[ offset_morphTarget + 3 ] = n2.x;
-						nka[ offset_morphTarget + 4 ] = n2.y;
-						nka[ offset_morphTarget + 5 ] = n2.z;
-
-						nka[ offset_morphTarget + 6 ] = n3.x;
-						nka[ offset_morphTarget + 7 ] = n3.y;
-						nka[ offset_morphTarget + 8 ] = n3.z;
-
-					}
-
-					//
-
-					offset_morphTarget += 9;
-
-				}
-
-				for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-					chf = chunk_faces4[ f ];
-					face = obj_faces[ chf ];
-
-					// morph positions
-
-					v1 = morphTargets[ vk ].vertices[ face.a ];
-					v2 = morphTargets[ vk ].vertices[ face.b ];
-					v3 = morphTargets[ vk ].vertices[ face.c ];
-					v4 = morphTargets[ vk ].vertices[ face.d ];
-
-					vka = morphTargetsArrays[ vk ];
-
-					vka[ offset_morphTarget ] 	  = v1.x;
-					vka[ offset_morphTarget + 1 ] = v1.y;
-					vka[ offset_morphTarget + 2 ] = v1.z;
-
-					vka[ offset_morphTarget + 3 ] = v2.x;
-					vka[ offset_morphTarget + 4 ] = v2.y;
-					vka[ offset_morphTarget + 5 ] = v2.z;
-
-					vka[ offset_morphTarget + 6 ] = v3.x;
-					vka[ offset_morphTarget + 7 ] = v3.y;
-					vka[ offset_morphTarget + 8 ] = v3.z;
-
-					vka[ offset_morphTarget + 9 ]  = v4.x;
-					vka[ offset_morphTarget + 10 ] = v4.y;
-					vka[ offset_morphTarget + 11 ] = v4.z;
-
-					// morph normals
-
-					if ( material.morphNormals ) {
-
-						if ( needsSmoothNormals ) {
-
-							faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
-
-							n1 = faceVertexNormals.a;
-							n2 = faceVertexNormals.b;
-							n3 = faceVertexNormals.c;
-							n4 = faceVertexNormals.d;
-
-						} else {
-
-							n1 = morphNormals[ vk ].faceNormals[ chf ];
-							n2 = n1;
-							n3 = n1;
-							n4 = n1;
-
-						}
-
-						nka = morphNormalsArrays[ vk ];
-
-						nka[ offset_morphTarget ] 	  = n1.x;
-						nka[ offset_morphTarget + 1 ] = n1.y;
-						nka[ offset_morphTarget + 2 ] = n1.z;
-
-						nka[ offset_morphTarget + 3 ] = n2.x;
-						nka[ offset_morphTarget + 4 ] = n2.y;
-						nka[ offset_morphTarget + 5 ] = n2.z;
-
-						nka[ offset_morphTarget + 6 ] = n3.x;
-						nka[ offset_morphTarget + 7 ] = n3.y;
-						nka[ offset_morphTarget + 8 ] = n3.z;
-
-						nka[ offset_morphTarget + 9 ]  = n4.x;
-						nka[ offset_morphTarget + 10 ] = n4.y;
-						nka[ offset_morphTarget + 11 ] = n4.z;
-
-					}
-
-					//
-
-					offset_morphTarget += 12;
-
-				}
-
-				this.renderer.setDynamicArrayBuffer( geometryGroup.__webglMorphTargetsBuffers[ vk ], morphTargetsArrays[ vk ]);
-
-				if ( material.morphNormals ) {
-
-					this.renderer.setDynamicArrayBuffer( geometryGroup.__webglMorphNormalsBuffers[ vk ], morphNormalsArrays[ vk ]);
-
-				}
-
-			}
-
-		}
-
-		if ( obj_skinWeights.length ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ]	];
-
-				// weights
-
-				sw1 = obj_skinWeights[ face.a ];
-				sw2 = obj_skinWeights[ face.b ];
-				sw3 = obj_skinWeights[ face.c ];
-
-				skinWeightArray[ offset_skin ]     = sw1.x;
-				skinWeightArray[ offset_skin + 1 ] = sw1.y;
-				skinWeightArray[ offset_skin + 2 ] = sw1.z;
-				skinWeightArray[ offset_skin + 3 ] = sw1.w;
-
-				skinWeightArray[ offset_skin + 4 ] = sw2.x;
-				skinWeightArray[ offset_skin + 5 ] = sw2.y;
-				skinWeightArray[ offset_skin + 6 ] = sw2.z;
-				skinWeightArray[ offset_skin + 7 ] = sw2.w;
-
-				skinWeightArray[ offset_skin + 8 ]  = sw3.x;
-				skinWeightArray[ offset_skin + 9 ]  = sw3.y;
-				skinWeightArray[ offset_skin + 10 ] = sw3.z;
-				skinWeightArray[ offset_skin + 11 ] = sw3.w;
-
-				// indices
-
-				si1 = obj_skinIndices[ face.a ];
-				si2 = obj_skinIndices[ face.b ];
-				si3 = obj_skinIndices[ face.c ];
-
-				skinIndexArray[ offset_skin ]     = si1.x;
-				skinIndexArray[ offset_skin + 1 ] = si1.y;
-				skinIndexArray[ offset_skin + 2 ] = si1.z;
-				skinIndexArray[ offset_skin + 3 ] = si1.w;
-
-				skinIndexArray[ offset_skin + 4 ] = si2.x;
-				skinIndexArray[ offset_skin + 5 ] = si2.y;
-				skinIndexArray[ offset_skin + 6 ] = si2.z;
-				skinIndexArray[ offset_skin + 7 ] = si2.w;
-
-				skinIndexArray[ offset_skin + 8 ]  = si3.x;
-				skinIndexArray[ offset_skin + 9 ]  = si3.y;
-				skinIndexArray[ offset_skin + 10 ] = si3.z;
-				skinIndexArray[ offset_skin + 11 ] = si3.w;
-
-				offset_skin += 12;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				// weights
-
-				sw1 = obj_skinWeights[ face.a ];
-				sw2 = obj_skinWeights[ face.b ];
-				sw3 = obj_skinWeights[ face.c ];
-				sw4 = obj_skinWeights[ face.d ];
-
-				skinWeightArray[ offset_skin ]     = sw1.x;
-				skinWeightArray[ offset_skin + 1 ] = sw1.y;
-				skinWeightArray[ offset_skin + 2 ] = sw1.z;
-				skinWeightArray[ offset_skin + 3 ] = sw1.w;
-
-				skinWeightArray[ offset_skin + 4 ] = sw2.x;
-				skinWeightArray[ offset_skin + 5 ] = sw2.y;
-				skinWeightArray[ offset_skin + 6 ] = sw2.z;
-				skinWeightArray[ offset_skin + 7 ] = sw2.w;
-
-				skinWeightArray[ offset_skin + 8 ]  = sw3.x;
-				skinWeightArray[ offset_skin + 9 ]  = sw3.y;
-				skinWeightArray[ offset_skin + 10 ] = sw3.z;
-				skinWeightArray[ offset_skin + 11 ] = sw3.w;
-
-				skinWeightArray[ offset_skin + 12 ] = sw4.x;
-				skinWeightArray[ offset_skin + 13 ] = sw4.y;
-				skinWeightArray[ offset_skin + 14 ] = sw4.z;
-				skinWeightArray[ offset_skin + 15 ] = sw4.w;
-
-				// indices
-
-				si1 = obj_skinIndices[ face.a ];
-				si2 = obj_skinIndices[ face.b ];
-				si3 = obj_skinIndices[ face.c ];
-				si4 = obj_skinIndices[ face.d ];
-
-				skinIndexArray[ offset_skin ]     = si1.x;
-				skinIndexArray[ offset_skin + 1 ] = si1.y;
-				skinIndexArray[ offset_skin + 2 ] = si1.z;
-				skinIndexArray[ offset_skin + 3 ] = si1.w;
-
-				skinIndexArray[ offset_skin + 4 ] = si2.x;
-				skinIndexArray[ offset_skin + 5 ] = si2.y;
-				skinIndexArray[ offset_skin + 6 ] = si2.z;
-				skinIndexArray[ offset_skin + 7 ] = si2.w;
-
-				skinIndexArray[ offset_skin + 8 ]  = si3.x;
-				skinIndexArray[ offset_skin + 9 ]  = si3.y;
-				skinIndexArray[ offset_skin + 10 ] = si3.z;
-				skinIndexArray[ offset_skin + 11 ] = si3.w;
-
-				skinIndexArray[ offset_skin + 12 ] = si4.x;
-				skinIndexArray[ offset_skin + 13 ] = si4.y;
-				skinIndexArray[ offset_skin + 14 ] = si4.z;
-				skinIndexArray[ offset_skin + 15 ] = si4.w;
-
-				offset_skin += 16;
-
-			}
-
-			if ( offset_skin > 0 ) {
-
-			renderer.setDynamicArrayBuffer( geometryGroup.__webglSkinIndicesBuffer, skinIndexArray);
-			renderer.setDynamicArrayBuffer( geometryGroup.__webglSkinWeightsBuffer, skinWeightArray);
-
-			}
-
-		}
-
-		if ( dirtyColors && vertexColorType ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ]	];
-
-				vertexColors = face.vertexColors;
-				faceColor = face.color;
-
-				if ( vertexColors.length === 3 && vertexColorType === THREE.VertexColors ) {
-
-					c1 = vertexColors[ 0 ];
-					c2 = vertexColors[ 1 ];
-					c3 = vertexColors[ 2 ];
-
-				} else {
-
-					c1 = faceColor;
-					c2 = faceColor;
-					c3 = faceColor;
-
-				}
-
-				colorArray[ offset_color ]     = c1.r;
-				colorArray[ offset_color + 1 ] = c1.g;
-				colorArray[ offset_color + 2 ] = c1.b;
-
-				colorArray[ offset_color + 3 ] = c2.r;
-				colorArray[ offset_color + 4 ] = c2.g;
-				colorArray[ offset_color + 5 ] = c2.b;
-
-				colorArray[ offset_color + 6 ] = c3.r;
-				colorArray[ offset_color + 7 ] = c3.g;
-				colorArray[ offset_color + 8 ] = c3.b;
-
-				offset_color += 9;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				vertexColors = face.vertexColors;
-				faceColor = face.color;
-
-				if ( vertexColors.length === 4 && vertexColorType === THREE.VertexColors ) {
-
-					c1 = vertexColors[ 0 ];
-					c2 = vertexColors[ 1 ];
-					c3 = vertexColors[ 2 ];
-					c4 = vertexColors[ 3 ];
-
-				} else {
-
-					c1 = faceColor;
-					c2 = faceColor;
-					c3 = faceColor;
-					c4 = faceColor;
-
-				}
-
-				colorArray[ offset_color ]     = c1.r;
-				colorArray[ offset_color + 1 ] = c1.g;
-				colorArray[ offset_color + 2 ] = c1.b;
-
-				colorArray[ offset_color + 3 ] = c2.r;
-				colorArray[ offset_color + 4 ] = c2.g;
-				colorArray[ offset_color + 5 ] = c2.b;
-
-				colorArray[ offset_color + 6 ] = c3.r;
-				colorArray[ offset_color + 7 ] = c3.g;
-				colorArray[ offset_color + 8 ] = c3.b;
-
-				colorArray[ offset_color + 9 ]  = c4.r;
-				colorArray[ offset_color + 10 ] = c4.g;
-				colorArray[ offset_color + 11 ] = c4.b;
-
-				offset_color += 12;
-
-			}
-
-			if ( offset_color > 0 ) {
-
-				renderer.setDynamicArrayBuffer( geometryGroup.__webglColorBuffer, colorArray);
-
-			}
-
-		}
-
-		if ( dirtyTangents && geometry.hasTangents ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ]	];
-
-				vertexTangents = face.vertexTangents;
-
-				t1 = vertexTangents[ 0 ];
-				t2 = vertexTangents[ 1 ];
-				t3 = vertexTangents[ 2 ];
-
-				tangentArray[ offset_tangent ]     = t1.x;
-				tangentArray[ offset_tangent + 1 ] = t1.y;
-				tangentArray[ offset_tangent + 2 ] = t1.z;
-				tangentArray[ offset_tangent + 3 ] = t1.w;
-
-				tangentArray[ offset_tangent + 4 ] = t2.x;
-				tangentArray[ offset_tangent + 5 ] = t2.y;
-				tangentArray[ offset_tangent + 6 ] = t2.z;
-				tangentArray[ offset_tangent + 7 ] = t2.w;
-
-				tangentArray[ offset_tangent + 8 ]  = t3.x;
-				tangentArray[ offset_tangent + 9 ]  = t3.y;
-				tangentArray[ offset_tangent + 10 ] = t3.z;
-				tangentArray[ offset_tangent + 11 ] = t3.w;
-
-				offset_tangent += 12;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				vertexTangents = face.vertexTangents;
-
-				t1 = vertexTangents[ 0 ];
-				t2 = vertexTangents[ 1 ];
-				t3 = vertexTangents[ 2 ];
-				t4 = vertexTangents[ 3 ];
-
-				tangentArray[ offset_tangent ]     = t1.x;
-				tangentArray[ offset_tangent + 1 ] = t1.y;
-				tangentArray[ offset_tangent + 2 ] = t1.z;
-				tangentArray[ offset_tangent + 3 ] = t1.w;
-
-				tangentArray[ offset_tangent + 4 ] = t2.x;
-				tangentArray[ offset_tangent + 5 ] = t2.y;
-				tangentArray[ offset_tangent + 6 ] = t2.z;
-				tangentArray[ offset_tangent + 7 ] = t2.w;
-
-				tangentArray[ offset_tangent + 8 ]  = t3.x;
-				tangentArray[ offset_tangent + 9 ]  = t3.y;
-				tangentArray[ offset_tangent + 10 ] = t3.z;
-				tangentArray[ offset_tangent + 11 ] = t3.w;
-
-				tangentArray[ offset_tangent + 12 ] = t4.x;
-				tangentArray[ offset_tangent + 13 ] = t4.y;
-				tangentArray[ offset_tangent + 14 ] = t4.z;
-				tangentArray[ offset_tangent + 15 ] = t4.w;
-
-				offset_tangent += 16;
-
-			}
-
-			renderer.setDynamicArrayBuffer( geometryGroup.__webglTangentBuffer, tangentArray);
-
-		}
-
-		if ( dirtyNormals && normalType ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces3[ f ]	];
-
-				vertexNormals = face.vertexNormals;
-				faceNormal = face.normal;
-
-				if ( vertexNormals.length === 3 && needsSmoothNormals ) {
-
-					for ( i = 0; i < 3; i ++ ) {
-
-						vn = vertexNormals[ i ];
-
-						normalArray[ offset_normal ]     = vn.x;
-						normalArray[ offset_normal + 1 ] = vn.y;
-						normalArray[ offset_normal + 2 ] = vn.z;
-
-						offset_normal += 3;
-
-					}
-
-				} else {
-
-					for ( i = 0; i < 3; i ++ ) {
-
-						normalArray[ offset_normal ]     = faceNormal.x;
-						normalArray[ offset_normal + 1 ] = faceNormal.y;
-						normalArray[ offset_normal + 2 ] = faceNormal.z;
-
-						offset_normal += 3;
-
-					}
-
-				}
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				face = obj_faces[ chunk_faces4[ f ] ];
-
-				vertexNormals = face.vertexNormals;
-				faceNormal = face.normal;
-
-				if ( vertexNormals.length === 4 && needsSmoothNormals ) {
-
-					for ( i = 0; i < 4; i ++ ) {
-
-						vn = vertexNormals[ i ];
-
-						normalArray[ offset_normal ]     = vn.x;
-						normalArray[ offset_normal + 1 ] = vn.y;
-						normalArray[ offset_normal + 2 ] = vn.z;
-
-						offset_normal += 3;
-
-					}
-
-				} else {
-
-					for ( i = 0; i < 4; i ++ ) {
-
-						normalArray[ offset_normal ]     = faceNormal.x;
-						normalArray[ offset_normal + 1 ] = faceNormal.y;
-						normalArray[ offset_normal + 2 ] = faceNormal.z;
-
-						offset_normal += 3;
-
-					}
-
-				}
-
-			}
-
-			renderer.setDynamicArrayBuffer( geometryGroup.__webglNormalBuffer, normalArray);
-
-		}
-
-		if ( dirtyUvs && obj_uvs && uvType ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				fi = chunk_faces3[ f ];
-
-				uv = obj_uvs[ fi ];
-
-				if ( uv === undefined ) continue;
-
-				for ( i = 0; i < 3; i ++ ) {
-
-					uvi = uv[ i ];
-
-					uvArray[ offset_uv ]     = uvi.x;
-					uvArray[ offset_uv + 1 ] = uvi.y;
-
-					offset_uv += 2;
-
-				}
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				fi = chunk_faces4[ f ];
-
-				uv = obj_uvs[ fi ];
-
-				if ( uv === undefined ) continue;
-
-				for ( i = 0; i < 4; i ++ ) {
-
-					uvi = uv[ i ];
-
-					uvArray[ offset_uv ]     = uvi.x;
-					uvArray[ offset_uv + 1 ] = uvi.y;
-
-					offset_uv += 2;
-
-				}
-
-			}
-
-			if ( offset_uv > 0 ) {
-
-				renderer.setDynamicArrayBuffer( geometryGroup.__webglUVBuffer, uvArray);
-
-			}
-
-		}
-
-		if ( dirtyUvs && obj_uvs2 && uvType ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				fi = chunk_faces3[ f ];
-
-				uv2 = obj_uvs2[ fi ];
-
-				if ( uv2 === undefined ) continue;
-
-				for ( i = 0; i < 3; i ++ ) {
-
-					uv2i = uv2[ i ];
-
-					uv2Array[ offset_uv2 ]     = uv2i.x;
-					uv2Array[ offset_uv2 + 1 ] = uv2i.y;
-
-					offset_uv2 += 2;
-
-				}
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				fi = chunk_faces4[ f ];
-
-				uv2 = obj_uvs2[ fi ];
-
-				if ( uv2 === undefined ) continue;
-
-				for ( i = 0; i < 4; i ++ ) {
-
-					uv2i = uv2[ i ];
-
-					uv2Array[ offset_uv2 ]     = uv2i.x;
-					uv2Array[ offset_uv2 + 1 ] = uv2i.y;
-
-					offset_uv2 += 2;
-
-				}
-
-			}
-
-			if ( offset_uv2 > 0 ) {
-
-				renderer.setDynamicArrayBuffer( geometryGroup.__webglUV2Buffer, uv2Array);
-
-			}
-
-		}
-
-		if ( dirtyElements ) {
-
-			for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-				faceArray[ offset_face ] 	 = vertexIndex;
-				faceArray[ offset_face + 1 ] = vertexIndex + 1;
-				faceArray[ offset_face + 2 ] = vertexIndex + 2;
-
-				offset_face += 3;
-
-				lineArray[ offset_line ]     = vertexIndex;
-				lineArray[ offset_line + 1 ] = vertexIndex + 1;
-
-				lineArray[ offset_line + 2 ] = vertexIndex;
-				lineArray[ offset_line + 3 ] = vertexIndex + 2;
-
-				lineArray[ offset_line + 4 ] = vertexIndex + 1;
-				lineArray[ offset_line + 5 ] = vertexIndex + 2;
-
-				offset_line += 6;
-
-				vertexIndex += 3;
-
-			}
-
-			for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-				faceArray[ offset_face ]     = vertexIndex;
-				faceArray[ offset_face + 1 ] = vertexIndex + 1;
-				faceArray[ offset_face + 2 ] = vertexIndex + 3;
-
-				faceArray[ offset_face + 3 ] = vertexIndex + 1;
-				faceArray[ offset_face + 4 ] = vertexIndex + 2;
-				faceArray[ offset_face + 5 ] = vertexIndex + 3;
-
-				offset_face += 6;
-
-				lineArray[ offset_line ]     = vertexIndex;
-				lineArray[ offset_line + 1 ] = vertexIndex + 1;
-
-				lineArray[ offset_line + 2 ] = vertexIndex;
-				lineArray[ offset_line + 3 ] = vertexIndex + 3;
-
-				lineArray[ offset_line + 4 ] = vertexIndex + 1;
-				lineArray[ offset_line + 5 ] = vertexIndex + 2;
-
-				lineArray[ offset_line + 6 ] = vertexIndex + 2;
-				lineArray[ offset_line + 7 ] = vertexIndex + 3;
-
-				offset_line += 8;
-
-				vertexIndex += 4;
-
-			}
-
-			renderer.setDynamicIndexBuffer( geometryGroup.__webglFaceBuffer, faceArray);
-			renderer.setDynamicIndexBuffer( geometryGroup.__webglLineBuffer, lineArray);
-
-		}
-
-		if ( customAttributes ) {
-
-			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-				customAttribute = customAttributes[ i ];
-
-				if ( ! customAttribute.__original.needsUpdate ) continue;
-
-				offset_custom = 0;
-				offset_customSrc = 0;
-
-				if ( customAttribute.size === 1 ) {
-
-					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces3[ f ]	];
-
-							customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
-							customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
-							customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
-
-							offset_custom += 3;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces4[ f ] ];
-
-							customAttribute.array[ offset_custom ] 	   = customAttribute.value[ face.a ];
-							customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
-							customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
-							customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ];
-
-							offset_custom += 4;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faces" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							customAttribute.array[ offset_custom ] 	   = value;
-							customAttribute.array[ offset_custom + 1 ] = value;
-							customAttribute.array[ offset_custom + 2 ] = value;
-
-							offset_custom += 3;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							customAttribute.array[ offset_custom ] 	   = value;
-							customAttribute.array[ offset_custom + 1 ] = value;
-							customAttribute.array[ offset_custom + 2 ] = value;
-							customAttribute.array[ offset_custom + 3 ] = value;
-
-							offset_custom += 4;
-
-						}
-
-					}
-
-				} else if ( customAttribute.size === 2 ) {
-
-					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces3[ f ]	];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-
-							customAttribute.array[ offset_custom ] 	   = v1.x;
-							customAttribute.array[ offset_custom + 1 ] = v1.y;
-
-							customAttribute.array[ offset_custom + 2 ] = v2.x;
-							customAttribute.array[ offset_custom + 3 ] = v2.y;
-
-							customAttribute.array[ offset_custom + 4 ] = v3.x;
-							customAttribute.array[ offset_custom + 5 ] = v3.y;
-
-							offset_custom += 6;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces4[ f ] ];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-							v4 = customAttribute.value[ face.d ];
-
-							customAttribute.array[ offset_custom ] 	   = v1.x;
-							customAttribute.array[ offset_custom + 1 ] = v1.y;
-
-							customAttribute.array[ offset_custom + 2 ] = v2.x;
-							customAttribute.array[ offset_custom + 3 ] = v2.y;
-
-							customAttribute.array[ offset_custom + 4 ] = v3.x;
-							customAttribute.array[ offset_custom + 5 ] = v3.y;
-
-							customAttribute.array[ offset_custom + 6 ] = v4.x;
-							customAttribute.array[ offset_custom + 7 ] = v4.y;
-
-							offset_custom += 8;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faces" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-
-							customAttribute.array[ offset_custom ] 	   = v1.x;
-							customAttribute.array[ offset_custom + 1 ] = v1.y;
-
-							customAttribute.array[ offset_custom + 2 ] = v2.x;
-							customAttribute.array[ offset_custom + 3 ] = v2.y;
-
-							customAttribute.array[ offset_custom + 4 ] = v3.x;
-							customAttribute.array[ offset_custom + 5 ] = v3.y;
-
-							offset_custom += 6;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-							v4 = value;
-
-							customAttribute.array[ offset_custom ] 	   = v1.x;
-							customAttribute.array[ offset_custom + 1 ] = v1.y;
-
-							customAttribute.array[ offset_custom + 2 ] = v2.x;
-							customAttribute.array[ offset_custom + 3 ] = v2.y;
-
-							customAttribute.array[ offset_custom + 4 ] = v3.x;
-							customAttribute.array[ offset_custom + 5 ] = v3.y;
-
-							customAttribute.array[ offset_custom + 6 ] = v4.x;
-							customAttribute.array[ offset_custom + 7 ] = v4.y;
-
-							offset_custom += 8;
-
-						}
-
-					}
-
-				} else if ( customAttribute.size === 3 ) {
-
-					var pp;
-
-					if ( customAttribute.type === "c" ) {
-
-						pp = [ "r", "g", "b" ];
-
-					} else {
-
-						pp = [ "x", "y", "z" ];
-
-					}
-
-					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces3[ f ]	];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-
-							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
-
-							offset_custom += 9;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces4[ f ] ];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-							v4 = customAttribute.value[ face.d ];
-
-							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
-
-							offset_custom += 12;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faces" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-
-							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
-
-							offset_custom += 9;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-							v4 = value;
-
-							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
-
-							offset_custom += 12;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faceVertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value[ 0 ];
-							v2 = value[ 1 ];
-							v3 = value[ 2 ];
-
-							customAttribute.array[ offset_custom ] 	   = v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
-
-							offset_custom += 9;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value[ 0 ];
-							v2 = value[ 1 ];
-							v3 = value[ 2 ];
-							v4 = value[ 3 ];
-
-							customAttribute.array[ offset_custom  ] 	= v1[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
-
-							customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
-							customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
-							customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
-
-							offset_custom += 12;
-
-						}
-
-					}
-
-				} else if ( customAttribute.size === 4 ) {
-
-					if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces3[ f ]	];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							offset_custom += 12;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							face = obj_faces[ chunk_faces4[ f ] ];
-
-							v1 = customAttribute.value[ face.a ];
-							v2 = customAttribute.value[ face.b ];
-							v3 = customAttribute.value[ face.c ];
-							v4 = customAttribute.value[ face.d ];
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							customAttribute.array[ offset_custom + 12 ] = v4.x;
-							customAttribute.array[ offset_custom + 13 ] = v4.y;
-							customAttribute.array[ offset_custom + 14 ] = v4.z;
-							customAttribute.array[ offset_custom + 15 ] = v4.w;
-
-							offset_custom += 16;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faces" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							offset_custom += 12;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value;
-							v2 = value;
-							v3 = value;
-							v4 = value;
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							customAttribute.array[ offset_custom + 12 ] = v4.x;
-							customAttribute.array[ offset_custom + 13 ] = v4.y;
-							customAttribute.array[ offset_custom + 14 ] = v4.z;
-							customAttribute.array[ offset_custom + 15 ] = v4.w;
-
-							offset_custom += 16;
-
-						}
-
-					} else if ( customAttribute.boundTo === "faceVertices" ) {
-
-						for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces3[ f ] ];
-
-							v1 = value[ 0 ];
-							v2 = value[ 1 ];
-							v3 = value[ 2 ];
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							offset_custom += 12;
-
-						}
-
-						for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
-
-							value = customAttribute.value[ chunk_faces4[ f ] ];
-
-							v1 = value[ 0 ];
-							v2 = value[ 1 ];
-							v3 = value[ 2 ];
-							v4 = value[ 3 ];
-
-							customAttribute.array[ offset_custom  ] 	= v1.x;
-							customAttribute.array[ offset_custom + 1  ] = v1.y;
-							customAttribute.array[ offset_custom + 2  ] = v1.z;
-							customAttribute.array[ offset_custom + 3  ] = v1.w;
-
-							customAttribute.array[ offset_custom + 4  ] = v2.x;
-							customAttribute.array[ offset_custom + 5  ] = v2.y;
-							customAttribute.array[ offset_custom + 6  ] = v2.z;
-							customAttribute.array[ offset_custom + 7  ] = v2.w;
-
-							customAttribute.array[ offset_custom + 8  ] = v3.x;
-							customAttribute.array[ offset_custom + 9  ] = v3.y;
-							customAttribute.array[ offset_custom + 10 ] = v3.z;
-							customAttribute.array[ offset_custom + 11 ] = v3.w;
-
-							customAttribute.array[ offset_custom + 12 ] = v4.x;
-							customAttribute.array[ offset_custom + 13 ] = v4.y;
-							customAttribute.array[ offset_custom + 14 ] = v4.z;
-							customAttribute.array[ offset_custom + 15 ] = v4.w;
-
-							offset_custom += 16;
-
-						}
-
-					}
-
-				}
-
-				renderer.setDynamicArrayBuffer( customAttribute.buffer, customAttribute.array);
-
-			}
-
-		}
-
-		if ( dispose ) {
-
-			delete geometryGroup.__inittedArrays;
-			delete geometryGroup.__colorArray;
-			delete geometryGroup.__normalArray;
-			delete geometryGroup.__tangentArray;
-			delete geometryGroup.__uvArray;
-			delete geometryGroup.__uv2Array;
-			delete geometryGroup.__faceArray;
-			delete geometryGroup.__vertexArray;
-			delete geometryGroup.__lineArray;
-			delete geometryGroup.__skinIndexArray;
-			delete geometryGroup.__skinWeightArray;
-
-		}
-
-	}
-
-} );

+ 0 - 127
examples/js/renderers/WebGLRenderer2/webgl/objects/Object3DRenderer.js

@@ -1,127 +0,0 @@
-
-THREE.WebGLRenderer.Object3DRenderer = function ( lowlevelrenderer, info ) {
-
-	this.renderer = lowlevelrenderer;
-	this.info = info;
-
-};
-
-THREE.extend( THREE.WebGLRenderer.Object3DRenderer.prototype, {
-
-	getBufferMaterial: function ( object, geometryGroup ) {
-
-		return object.material instanceof THREE.MeshFaceMaterial
-			? object.material.materials[ geometryGroup.materialIndex ]
-			: object.material;
-
-	},
-
-	bufferGuessUVType: function ( material ) {
-
-		// material must use some texture to require uvs
-
-		if ( material.map || material.lightMap || material.bumpMap || material.normalMap || material.specularMap || material instanceof THREE.ShaderMaterial ) {
-
-			return true;
-
-		}
-
-		return false;
-
-	},
-
-	bufferGuessNormalType: function ( material ) {
-
-		// only MeshBasicMaterial and MeshDepthMaterial don't need normals
-
-		if ( ( material instanceof THREE.MeshBasicMaterial && !material.envMap ) || material instanceof THREE.MeshDepthMaterial ) {
-
-			return false;
-
-		}
-
-		if ( this.materialNeedsSmoothNormals( material ) ) {
-
-			return THREE.SmoothShading;
-
-		} else {
-
-			return THREE.FlatShading;
-
-		}
-
-	},
-
-	materialNeedsSmoothNormals: function ( material ) {
-
-		return material && material.shading !== undefined && material.shading === THREE.SmoothShading;
-
-	},
-
-	bufferGuessVertexColorType: function ( material ) {
-
-		if ( material.vertexColors ) {
-
-			return material.vertexColors;
-
-		}
-
-		return false;
-
-	},
-
-	initCustomAttributes: function ( geometry, object ) {
-
-		var nvertices = geometry.vertices.length;
-
-		var material = object.material;
-
-		if ( material.attributes ) {
-
-			if ( geometry.__webglCustomAttributesList === undefined ) {
-
-				geometry.__webglCustomAttributesList = [];
-
-			}
-
-			for ( var a in material.attributes ) {
-
-				var attribute = material.attributes[ a ];
-
-				if ( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
-
-					attribute.__webglInitialized = true;
-
-					var size = 1;		// "f" and "i"
-
-					if ( attribute.type === "v2" ) size = 2;
-					else if ( attribute.type === "v3" ) size = 3;
-					else if ( attribute.type === "v4" ) size = 4;
-					else if ( attribute.type === "c"  ) size = 3;
-
-					attribute.size = size;
-
-					attribute.array = new Float32Array( nvertices * size );
-
-					attribute.buffer = this.renderer.createBuffer();
-					attribute.buffer.belongsToAttribute = a;
-
-					attribute.needsUpdate = true;
-
-				}
-
-				geometry.__webglCustomAttributesList.push( attribute );
-
-			}
-
-		}
-
-	},
-
-	numericalSort: function ( a, b ) {
-
-		return b[ 0 ] - a[ 0 ];
-
-	}
-
-} );

+ 0 - 360
examples/js/renderers/WebGLRenderer2/webgl/objects/ParticleRenderer.js

@@ -1,360 +0,0 @@
-
-THREE.WebGLRenderer.ParticleRenderer = function ( lowlevelrenderer, info ) {
-
-	THREE.WebGLRenderer.Object3DRenderer.call( this, lowlevelrenderer, info );
-
-};
-
-THREE.WebGLRenderer.ParticleRenderer.prototype = Object.create( THREE.WebGLRenderer.Object3DRenderer.prototype );
-
-THREE.extend( THREE.WebGLRenderer.ParticleRenderer.prototype, {
-
-	createBuffers: function ( geometry ) {
-
-		var renderer = this.renderer;
-		geometry.__webglVertexBuffer = renderer.createBuffer();
-		geometry.__webglColorBuffer = renderer.createBuffer();
-
-		this.info.memory.geometries ++;
-	},
-
-	initBuffers: function ( geometry, object ) {
-
-		var nvertices = geometry.vertices.length;
-
-		geometry.__vertexArray = new Float32Array( nvertices * 3 );
-		geometry.__colorArray = new Float32Array( nvertices * 3 );
-
-		geometry.__sortArray = [];
-
-		geometry.__webglParticleCount = nvertices;
-
-		this.initCustomAttributes ( geometry, object );
-
-	},
-
-	setBuffers: function ( geometry, object , projectionScreenMatrix ) {
-
-		var renderer = this.renderer;
-		var v, c, vertex, offset, index, color,
-
-		vertices = geometry.vertices,
-		vl = vertices.length,
-
-		colors = geometry.colors,
-		cl = colors.length,
-
-		vertexArray = geometry.__vertexArray,
-		colorArray = geometry.__colorArray,
-
-		sortArray = geometry.__sortArray,
-
-		dirtyVertices = geometry.verticesNeedUpdate,
-		dirtyElements = geometry.elementsNeedUpdate,
-		dirtyColors = geometry.colorsNeedUpdate,
-
-		customAttributes = geometry.__webglCustomAttributesList,
-		i, il,
-		a, ca, cal, value,
-		customAttribute;
-
-		var _projScreenMatrixPS = THREE.WebGLRenderer.ParticleRenderer._m1,
-			_vector3 = THREE.WebGLRenderer.ParticleRenderer._v1;
-
-		if ( object.sortParticles ) {
-
-			_projScreenMatrixPS.multiplyMatrices( projectionScreenMatrix, object.matrixWorld );
-
-			for ( v = 0; v < vl; v ++ ) {
-
-				vertex = vertices[ v ];
-
-				_vector3.copy( vertex );
-				_vector3.applyProjection(_projScreenMatrixPS);
-
-				sortArray[ v ] = [ _vector3.z, v ];
-
-			}
-
-			sortArray.sort( this.numericalSort );
-
-			for ( v = 0; v < vl; v ++ ) {
-
-				vertex = vertices[ sortArray[v][1] ];
-
-				offset = v * 3;
-
-				vertexArray[ offset ]     = vertex.x;
-				vertexArray[ offset + 1 ] = vertex.y;
-				vertexArray[ offset + 2 ] = vertex.z;
-
-			}
-
-			for ( c = 0; c < cl; c ++ ) {
-
-				offset = c * 3;
-
-				color = colors[ sortArray[c][1] ];
-
-				colorArray[ offset ]     = color.r;
-				colorArray[ offset + 1 ] = color.g;
-				colorArray[ offset + 2 ] = color.b;
-
-			}
-
-			if ( customAttributes ) {
-
-				for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-					customAttribute = customAttributes[ i ];
-
-					if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) ) continue;
-
-					offset = 0;
-
-					cal = customAttribute.value.length;
-
-					if ( customAttribute.size === 1 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							index = sortArray[ ca ][ 1 ];
-
-							customAttribute.array[ ca ] = customAttribute.value[ index ];
-
-						}
-
-					} else if ( customAttribute.size === 2 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							index = sortArray[ ca ][ 1 ];
-
-							value = customAttribute.value[ index ];
-
-							customAttribute.array[ offset ] 	= value.x;
-							customAttribute.array[ offset + 1 ] = value.y;
-
-							offset += 2;
-
-						}
-
-					} else if ( customAttribute.size === 3 ) {
-
-						if ( customAttribute.type === "c" ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								index = sortArray[ ca ][ 1 ];
-
-								value = customAttribute.value[ index ];
-
-								customAttribute.array[ offset ]     = value.r;
-								customAttribute.array[ offset + 1 ] = value.g;
-								customAttribute.array[ offset + 2 ] = value.b;
-
-								offset += 3;
-
-							}
-
-						} else {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								index = sortArray[ ca ][ 1 ];
-
-								value = customAttribute.value[ index ];
-
-								customAttribute.array[ offset ] 	= value.x;
-								customAttribute.array[ offset + 1 ] = value.y;
-								customAttribute.array[ offset + 2 ] = value.z;
-
-								offset += 3;
-
-							}
-
-						}
-
-					} else if ( customAttribute.size === 4 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							index = sortArray[ ca ][ 1 ];
-
-							value = customAttribute.value[ index ];
-
-							customAttribute.array[ offset ]      = value.x;
-							customAttribute.array[ offset + 1  ] = value.y;
-							customAttribute.array[ offset + 2  ] = value.z;
-							customAttribute.array[ offset + 3  ] = value.w;
-
-							offset += 4;
-
-						}
-
-					}
-
-				}
-
-			}
-
-		} else {
-
-			if ( dirtyVertices ) {
-
-				for ( v = 0; v < vl; v ++ ) {
-
-					vertex = vertices[ v ];
-
-					offset = v * 3;
-
-					vertexArray[ offset ]     = vertex.x;
-					vertexArray[ offset + 1 ] = vertex.y;
-					vertexArray[ offset + 2 ] = vertex.z;
-
-				}
-
-			}
-
-			if ( dirtyColors ) {
-
-				for ( c = 0; c < cl; c ++ ) {
-
-					color = colors[ c ];
-
-					offset = c * 3;
-
-					colorArray[ offset ]     = color.r;
-					colorArray[ offset + 1 ] = color.g;
-					colorArray[ offset + 2 ] = color.b;
-
-				}
-
-			}
-
-			if ( customAttributes ) {
-
-				for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-					customAttribute = customAttributes[ i ];
-
-					if ( customAttribute.needsUpdate &&
-						 ( customAttribute.boundTo === undefined ||
-						   customAttribute.boundTo === "vertices") ) {
-
-						cal = customAttribute.value.length;
-
-						offset = 0;
-
-						if ( customAttribute.size === 1 ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								customAttribute.array[ ca ] = customAttribute.value[ ca ];
-
-							}
-
-						} else if ( customAttribute.size === 2 ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.x;
-								customAttribute.array[ offset + 1 ] = value.y;
-
-								offset += 2;
-
-							}
-
-						} else if ( customAttribute.size === 3 ) {
-
-							if ( customAttribute.type === "c" ) {
-
-								for ( ca = 0; ca < cal; ca ++ ) {
-
-									value = customAttribute.value[ ca ];
-
-									customAttribute.array[ offset ] 	= value.r;
-									customAttribute.array[ offset + 1 ] = value.g;
-									customAttribute.array[ offset + 2 ] = value.b;
-
-									offset += 3;
-
-								}
-
-							} else {
-
-								for ( ca = 0; ca < cal; ca ++ ) {
-
-									value = customAttribute.value[ ca ];
-
-									customAttribute.array[ offset ] 	= value.x;
-									customAttribute.array[ offset + 1 ] = value.y;
-									customAttribute.array[ offset + 2 ] = value.z;
-
-									offset += 3;
-
-								}
-
-							}
-
-						} else if ( customAttribute.size === 4 ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ]      = value.x;
-								customAttribute.array[ offset + 1  ] = value.y;
-								customAttribute.array[ offset + 2  ] = value.z;
-								customAttribute.array[ offset + 3  ] = value.w;
-
-								offset += 4;
-
-							}
-
-						}
-
-					}
-
-				}
-
-			}
-
-		}
-
-		if ( dirtyVertices || object.sortParticles ) {
-
-			renderer.setDynamicArrayBuffer(geometry.__webglVertexBuffer,vertexArray);
-
-		}
-
-		if ( dirtyColors || object.sortParticles ) {
-
-			renderer.setDynamicArrayBuffer(geometry.__webglColorBuffer,colorArray);
-
-		}
-
-		if ( customAttributes ) {
-
-			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-				customAttribute = customAttributes[ i ];
-
-				if ( customAttribute.needsUpdate || object.sortParticles ) {
-
-					renderer.setDynamicArrayBuffer(customAttribute.buffer,customAttribute.array);
-
-				}
-
-			}
-
-		}
-
-	}
-
-} );
-
-THREE.WebGLRenderer.ParticleRenderer._m1 = new THREE.Matrix4();
-THREE.WebGLRenderer.ParticleRenderer._v1 = new THREE.Vector3();

+ 0 - 209
examples/js/renderers/WebGLRenderer2/webgl/objects/RibbonRenderer.js

@@ -1,209 +0,0 @@
-
-THREE.WebGLRenderer.RibbonRenderer = function ( lowlevelrenderer, info ) {
-
-	THREE.WebGLRenderer.Object3DRenderer.call( this, lowlevelrenderer, info );
-
-};
-
-THREE.WebGLRenderer.RibbonRenderer.prototype = Object.create( THREE.WebGLRenderer.Object3DRenderer.prototype );
-
-THREE.extend( THREE.WebGLRenderer.RibbonRenderer.prototype, {
-
-	createBuffers: function ( geometry ) {
-
-		var renderer = this.renderer;
-		geometry.__webglVertexBuffer = renderer.createBuffer();
-		geometry.__webglColorBuffer = renderer.createBuffer();
-		geometry.__webglNormalBuffer = renderer.createBuffer();
-
-		this.info.memory.geometries ++;
-	},
-
-	initBuffers: function ( geometry, object ) {
-
-		var nvertices = geometry.vertices.length;
-
-		geometry.__vertexArray = new Float32Array( nvertices * 3 );
-		geometry.__colorArray = new Float32Array( nvertices * 3 );
-		geometry.__normalArray = new Float32Array( nvertices * 3 );
-
-		geometry.__webglVertexCount = nvertices;
-
-		this.initCustomAttributes ( geometry, object );
-
-	},
-
-	setBuffers: function ( geometry, object , projectionScreenMatrix ) {
-
-		var renderer = this.renderer;
-		var v, c, n, vertex, offset, color, normal,
-
-		i, il, ca, cal, customAttribute, value,
-
-		vertices = geometry.vertices,
-		colors = geometry.colors,
-		normals = geometry.normals,
-
-		vl = vertices.length,
-		cl = colors.length,
-		nl = normals.length,
-
-		vertexArray = geometry.__vertexArray,
-		colorArray = geometry.__colorArray,
-		normalArray = geometry.__normalArray,
-
-		dirtyVertices = geometry.verticesNeedUpdate,
-		dirtyColors = geometry.colorsNeedUpdate,
-		dirtyNormals = geometry.normalsNeedUpdate,
-
-		customAttributes = geometry.__webglCustomAttributesList;
-
-		if ( dirtyVertices ) {
-
-			for ( v = 0; v < vl; v ++ ) {
-
-				vertex = vertices[ v ];
-
-				offset = v * 3;
-
-				vertexArray[ offset ]     = vertex.x;
-				vertexArray[ offset + 1 ] = vertex.y;
-				vertexArray[ offset + 2 ] = vertex.z;
-
-			}
-
-			renderer.setDynamicArrayBuffer( geometry.__webglVertexBuffer,vertexArray);
-
-		}
-
-		if ( dirtyColors ) {
-
-			for ( c = 0; c < cl; c ++ ) {
-
-				color = colors[ c ];
-
-				offset = c * 3;
-
-				colorArray[ offset ]     = color.r;
-				colorArray[ offset + 1 ] = color.g;
-				colorArray[ offset + 2 ] = color.b;
-
-			}
-
-			renderer.setDynamicArrayBuffer( geometry.__webglColorBuffer, colorArray);
-
-		}
-
-		if ( dirtyNormals ) {
-
-			for ( n = 0; n < nl; n ++ ) {
-
-				normal = normals[ n ];
-
-				offset = n * 3;
-
-				normalArray[ offset ]     = normal.x;
-				normalArray[ offset + 1 ] = normal.y;
-				normalArray[ offset + 2 ] = normal.z;
-
-			}
-
-			renderer.setDynamicArrayBuffer( geometry.__webglNormalBuffer, normalArray);
-
-		}
-
-		if ( customAttributes ) {
-
-			for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
-
-				customAttribute = customAttributes[ i ];
-
-				if ( customAttribute.needsUpdate &&
-					 ( customAttribute.boundTo === undefined ||
-					   customAttribute.boundTo === "vertices" ) ) {
-
-					offset = 0;
-
-					cal = customAttribute.value.length;
-
-					if ( customAttribute.size === 1 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							customAttribute.array[ ca ] = customAttribute.value[ ca ];
-
-						}
-
-					} else if ( customAttribute.size === 2 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							value = customAttribute.value[ ca ];
-
-							customAttribute.array[ offset ] 	= value.x;
-							customAttribute.array[ offset + 1 ] = value.y;
-
-							offset += 2;
-
-						}
-
-					} else if ( customAttribute.size === 3 ) {
-
-						if ( customAttribute.type === "c" ) {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.r;
-								customAttribute.array[ offset + 1 ] = value.g;
-								customAttribute.array[ offset + 2 ] = value.b;
-
-								offset += 3;
-
-							}
-
-						} else {
-
-							for ( ca = 0; ca < cal; ca ++ ) {
-
-								value = customAttribute.value[ ca ];
-
-								customAttribute.array[ offset ] 	= value.x;
-								customAttribute.array[ offset + 1 ] = value.y;
-								customAttribute.array[ offset + 2 ] = value.z;
-
-								offset += 3;
-
-							}
-
-						}
-
-					} else if ( customAttribute.size === 4 ) {
-
-						for ( ca = 0; ca < cal; ca ++ ) {
-
-							value = customAttribute.value[ ca ];
-
-							customAttribute.array[ offset ] 	 = value.x;
-							customAttribute.array[ offset + 1  ] = value.y;
-							customAttribute.array[ offset + 2  ] = value.z;
-							customAttribute.array[ offset + 3  ] = value.w;
-
-							offset += 4;
-
-						}
-
-					}
-
-					renderer.setDynamicArrayBuffer( customAttribute.buffer, customAttribute.array);
-
-				}
-
-			}
-
-		}
-
-	}
-
-} );

+ 2 - 2
examples/js/renderers/WebGLRenderer3.js

@@ -27,8 +27,8 @@ THREE.WebGLRenderer3 = function ( parameters ) {
 
 
 	var devicePixelRatio = parameters.devicePixelRatio !== undefined
 	var devicePixelRatio = parameters.devicePixelRatio !== undefined
 				? parameters.devicePixelRatio
 				? parameters.devicePixelRatio
-				: window.devicePixelRatio !== undefined
-					? window.devicePixelRatio
+				: self.devicePixelRatio !== undefined
+					? self.devicePixelRatio
 					: 1;
 					: 1;
 
 
 	var gl;
 	var gl;

+ 1 - 1
examples/misc_controls_fly.html

@@ -232,7 +232,7 @@
 
 
 				}
 				}
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.sortObjects = false;
 				renderer.sortObjects = false;
 
 

+ 43 - 27
examples/misc_controls_transform.html

@@ -26,7 +26,7 @@
 
 
 		<div id="info">
 		<div id="info">
 		"W" translate | "E" rotate | "R" scale | "+" increase size | "-" decrease size<br />
 		"W" translate | "E" rotate | "R" scale | "+" increase size | "-" decrease size<br />
-		Press "W/E/R" twice to toggle world/local space
+		Press "Q" twice to toggle world/local space
 		</div>
 		</div>
 
 
 		<script src="../build/three.min.js"></script>
 		<script src="../build/three.min.js"></script>
@@ -34,8 +34,7 @@
 
 
 		<script>
 		<script>
 
 
-			var camera, scene, renderer;
-			var controls = [];
+			var camera, scene, renderer, control;
 
 
 			init();
 			init();
 			render();
 			render();
@@ -50,40 +49,61 @@
 				//
 				//
 
 
 				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 3000 );
 				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 3000 );
-				camera.position.set( 1000, 1000, 1000 );
-				camera.lookAt( new THREE.Vector3( 0, 700, 0 ) );
+				camera.position.set( 1000, 500, 1000 );
+				camera.lookAt( new THREE.Vector3( 0, 200, 0 ) );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 				scene.add( new THREE.GridHelper( 500, 100 ) );
 				scene.add( new THREE.GridHelper( 500, 100 ) );
 
 
+				var light = new THREE.DirectionalLight( 0xffffff, 2 );
+				light.position.set( 1, 1, 1 );
+				scene.add( light );
+
+
 				var texture = THREE.ImageUtils.loadTexture( 'textures/crate.gif', new THREE.UVMapping(), render );
 				var texture = THREE.ImageUtils.loadTexture( 'textures/crate.gif', new THREE.UVMapping(), render );
 				texture.anisotropy = renderer.getMaxAnisotropy();
 				texture.anisotropy = renderer.getMaxAnisotropy();
 
 
 				var geometry = new THREE.CubeGeometry( 200, 200, 200 );
 				var geometry = new THREE.CubeGeometry( 200, 200, 200 );
-				var material = new THREE.MeshBasicMaterial( { map: texture } );
-
-				var parent = scene;
-
-				for ( var i = 0; i < 4; i ++ ) {
+				var material = new THREE.MeshLambertMaterial( { map: texture } );
 
 
-					var mesh = new THREE.Mesh( geometry, material );
-					mesh.position.y = i > 0 ? 350 : 100;
-					parent.add( mesh );
+				control = new THREE.TransformControls( camera, renderer.domElement );
 
 
-					var control = new THREE.TransformControls( camera, renderer.domElement );
-					control.addEventListener( 'change', render );
-					control.attach( mesh );
-					control.scale = 0.65;
-					scene.add( control.gizmo );
+				control.addEventListener( 'change', render );
 
 
-					controls.push( control );
+				var mesh = new THREE.Mesh( geometry, material );
+				scene.add( mesh );
 
 
-					parent = mesh;
-
-				}
+				control.attach( mesh );
+				scene.add( control );
 
 
 				window.addEventListener( 'resize', onWindowResize, false );
 				window.addEventListener( 'resize', onWindowResize, false );
 
 
+				window.addEventListener( 'keydown', function ( event ) {
+		            //console.log(event.which);
+		            switch ( event.keyCode ) {
+		              case 81: // Q
+		                control.setSpace( control.space == "local" ? "world" : "local" );
+		                break;
+		              case 87: // W
+		                control.setMode( "translate" );
+		                break;
+		              case 69: // E
+		                control.setMode( "rotate" );
+		                break;
+		              case 82: // R
+		                control.setMode( "scale" );
+		                break;
+					case 187:
+					case 107: // +,=,num+
+						control.setSize( control.size + 0.1 );
+						break;
+					case 189:
+					case 10: // -,_,num-
+						control.setSize( Math.max(control.size - 0.1, 0.1 ) );
+						break;
+		            }            
+        		});
+
 			}
 			}
 
 
 			function onWindowResize() {
 			function onWindowResize() {
@@ -99,11 +119,7 @@
 
 
 			function render() {
 			function render() {
 
 
-				for ( var i = 0, j = controls.length; i < j; i ++ ) {
-
-					controls[ i ].update();
-
-				}
+				control.update();
 
 
 				renderer.render( scene, camera );
 				renderer.render( scene, camera );
 
 

+ 1 - 1
examples/misc_sound.html

@@ -167,7 +167,7 @@
 
 
 				//
 				//
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: true } );
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				container.innerHTML = "";
 				container.innerHTML = "";

BIN
examples/textures/compressed/Mountains_argb_mip.dds


BIN
examples/textures/compressed/Mountains_argb_nomip.dds


BIN
examples/textures/compressed/disturb_argb_mip.dds


BIN
examples/textures/compressed/disturb_argb_nomip.dds


+ 2 - 1
examples/webgl3_performance.html

@@ -77,7 +77,8 @@
 
 
 				} );
 				} );
 
 
-				renderer = new THREE.WebGLRenderer3( { contextAttributes: { antialias: false } } );
+				renderer = new THREE.WebGLRenderer3( { contextAttributes: { antialias: false, alpha: false } } );
+				renderer.setClearColor( 0xffffff, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 

+ 2 - 2
examples/webgl_animation_skinning.html

@@ -99,9 +99,9 @@
 				floor.scale.set( 25, 25, 25 );
 				floor.scale.set( 25, 25, 25 );
 				scene.add( floor );
 				scene.add( floor );
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0xffffff, clearAlpha: 1, antialias: true } );
-				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
 				renderer.setClearColor( scene.fog.color, 1 );
 				renderer.setClearColor( scene.fog.color, 1 );
+				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.sortObjects = false;
 				renderer.sortObjects = false;
 
 
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 2 - 2
examples/webgl_buffergeometry.html

@@ -241,9 +241,9 @@
 
 
 				//
 				//
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x333333, clearAlpha: 1, alpha: false } );
-				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setClearColor( scene.fog.color, 1 );
 				renderer.setClearColor( scene.fog.color, 1 );
+				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				renderer.gammaInput = true;
 				renderer.gammaInput = true;
 				renderer.gammaOutput = true;
 				renderer.gammaOutput = true;

+ 1 - 1
examples/webgl_buffergeometry_custom_attributes_particles.html

@@ -187,7 +187,7 @@
 
 
 			scene.add( sphere );
 			scene.add( sphere );
 
 
-			renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+			renderer = new THREE.WebGLRenderer( { alpha: false } );
 			renderer.setSize( WIDTH, HEIGHT );
 			renderer.setSize( WIDTH, HEIGHT );
 
 
 			var container = document.getElementById( 'container' );
 			var container = document.getElementById( 'container' );

+ 1 - 1
examples/webgl_buffergeometry_lines.html

@@ -112,7 +112,7 @@
 
 
 				//
 				//
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x000000, clearAlpha: 0, alpha: true } );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				renderer.gammaInput = true;
 				renderer.gammaInput = true;

+ 2 - 3
examples/webgl_buffergeometry_particles.html

@@ -26,7 +26,6 @@
 
 
 				color: #0080ff;
 				color: #0080ff;
 			}
 			}
-
 		</style>
 		</style>
 	</head>
 	</head>
 	<body>
 	<body>
@@ -127,9 +126,9 @@
 
 
 				//
 				//
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x333333, clearAlpha: 1, alpha: false } );
-				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setClearColor( scene.fog.color, 1 );
 				renderer.setClearColor( scene.fog.color, 1 );
+				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 

+ 1 - 1
examples/webgl_camera.html

@@ -136,7 +136,7 @@
 				//
 				//
 
 
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: true, clearColor: 0x000000, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.domElement.style.position = "relative";
 				renderer.domElement.style.position = "relative";
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 2 - 1
examples/webgl_custom_attributes.html

@@ -149,7 +149,8 @@
 
 
 			scene.add( sphere );
 			scene.add( sphere );
 
 
-			renderer = new THREE.WebGLRenderer( { clearColor: 0x050505, clearAlpha: 1 } );
+			renderer = new THREE.WebGLRenderer( { alpha: false } );
+			renderer.setClearColor( 0x050505, 1 );
 			renderer.setSize( WIDTH, HEIGHT );
 			renderer.setSize( WIDTH, HEIGHT );
 
 
 			var container = document.getElementById( 'container' );
 			var container = document.getElementById( 'container' );

+ 2 - 1
examples/webgl_custom_attributes_lines.html

@@ -185,7 +185,8 @@
 
 
 			scene.add( object );
 			scene.add( object );
 
 
-			renderer = new THREE.WebGLRenderer( { clearColor: 0x050505, clearAlpha: 1, antialias: true } );
+			renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
+			renderer.setClearColor( 0x050505, 1 );
 			renderer.setSize( WIDTH, HEIGHT );
 			renderer.setSize( WIDTH, HEIGHT );
 
 
 			var container = document.getElementById( 'container' );
 			var container = document.getElementById( 'container' );

+ 1 - 1
examples/webgl_custom_attributes_particles.html

@@ -170,7 +170,7 @@
 
 
 			scene.add( sphere );
 			scene.add( sphere );
 
 
-			renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+			renderer = new THREE.WebGLRenderer( { alpha: false } );
 			renderer.setSize( WIDTH, HEIGHT );
 			renderer.setSize( WIDTH, HEIGHT );
 
 
 			var container = document.getElementById( 'container' );
 			var container = document.getElementById( 'container' );

+ 1 - 1
examples/webgl_custom_attributes_particles2.html

@@ -164,7 +164,7 @@
 
 
 			scene.add( sphere );
 			scene.add( sphere );
 
 
-			renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+			renderer = new THREE.WebGLRenderer( { alpha: false } );
 			renderer.setSize( WIDTH, HEIGHT );
 			renderer.setSize( WIDTH, HEIGHT );
 
 
 			var container = document.getElementById( 'container' );
 			var container = document.getElementById( 'container' );

+ 1 - 1
examples/webgl_custom_attributes_particles3.html

@@ -226,7 +226,7 @@
 
 
 			scene.add( object );
 			scene.add( object );
 
 
-			renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+			renderer = new THREE.WebGLRenderer( { alpha: false } );
 			renderer.setSize( WIDTH, HEIGHT );
 			renderer.setSize( WIDTH, HEIGHT );
 
 
 			var container = document.getElementById( 'container' );
 			var container = document.getElementById( 'container' );

+ 0 - 284
examples/webgl_custom_attributes_ribbons.html

@@ -1,284 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js webgl - custom attributes [ribbons]</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 {
-				background-color: #000000;
-				margin: 0px;
-				overflow: hidden;
-				font-family:Monospace;
-				font-size:13px;
-				text-align:center;
-				font-weight: bold;
-				text-align:center;
-			}
-
-			a {
-				color:#0078ff;
-			}
-
-			#info {
-				color:#fff;
-				position: absolute;
-				top: 0px; width: 100%;
-				padding: 5px;
-				z-index:100;
-			}
-		</style>
-	</head>
-
-	<body>
-
-		<script src="../build/three.min.js"></script>
-
-		<script src="js/Detector.js"></script>
-		<script src="js/libs/stats.min.js"></script>
-
-		<div id="info">
-			<a href="http://threejs.org" target="_blank">three.js</a> - webgl custom attributes example
-		</div>
-
-		<script type="x-shader/x-vertex" id="vertexShader">
-
-			uniform float ratio;
-
-			attribute vec3 position2;
-			attribute vec3 customColor;
-
-			varying vec3 vColor;
-
-			void main() {
-
-				vColor = customColor;
-
-				vec3 newPosition = mix( position, position2, ratio );
-				gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );
-
-			}
-
-		</script>
-
-		<script type="x-shader/x-fragment" id="fragmentShader">
-
-			uniform vec3 color;
-			varying vec3 vColor;
-
-			void main() {
-
-				gl_FragColor = vec4( color * vColor, 1.0 );
-
-			}
-
-		</script>
-
-		<script>
-
-			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
-
-			var container, stats;
-			var camera, scene, renderer;
-
-			var materials = [];
-
-			var mouseX = 0, mouseY = 0;
-
-			var windowHalfX = window.innerWidth / 2;
-			var windowHalfY = window.innerHeight / 2;
-
-			init();
-			animate();
-
-			function init() {
-
-				container = document.createElement( 'div' );
-				document.body.appendChild( container );
-
-				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 3000 );
-				camera.position.z = 1200;
-
-				scene = new THREE.Scene();
-				scene.fog = new THREE.FogExp2( 0x000000, 0.0016 );
-
-				//
-
-				var vertexShader = document.getElementById( 'vertexShader' ).textContent;
-				var fragmentShader = document.getElementById( 'fragmentShader' ).textContent;
-
-				var attributes = { customColor:  { type: 'c',  boundTo: 'vertices', value: [] },
-								   position2:    { type: 'v3', boundTo: 'vertices', value: [] }
-								  };
-
-				uniforms =  { ratio: { type: "f", value: 1.0 },
-							  color:     { type: "c", value: new THREE.Color( 0xffffff ) }
-							};
-
-				var material = new THREE.ShaderMaterial( { uniforms: uniforms, attributes: attributes, vertexShader: vertexShader, fragmentShader: fragmentShader, side: THREE.DoubleSide } );
-
-				var position2 = attributes.position2.value;
-				var colors = attributes.customColor.value;
-
-				//
-
-				var geometry = new THREE.Geometry();
-
-				var i, i2;
-				var x1, y1, z1;
-				var x2, y2, z2;
-				var color;
-
-				var n = 200;
-
-				for ( i = -n; i < n; i ++ ) {
-
-					i2 = i + n;
-
-					x1 = 10 * i;
-					y1 = - 50 + ( i2 % 2 ) * 100 - Math.cos( 4 * Math.PI * i/n ) * 50;
-					z1 = 0;
-
-					x2 = x1;
-					y2 = y1 + Math.cos( 4 * Math.PI * i/n ) * 100;
-					z2 = z1;
-
-					h = i2 % 2 ? 1 : 0.25;
-					if ( i2 % 4 <= 2 ) h -= 0.15;
-
-					color = new THREE.Color().setHSL( 0.1, 0.15, h );
-
-					position2[ geometry.vertices.length ] = new THREE.Vector3( x2, y2, z2 );
-					colors[ geometry.vertices.length ] = color;
-
-					geometry.vertices.push( new THREE.Vector3( x1, y1, z1 ) );
-
-				}
-
-				var ribbon = new THREE.Ribbon( geometry, material );
-				scene.add( ribbon );
-
-				materials.push( ribbon.material );
-
-				var ribbon = new THREE.Ribbon( geometry, material.clone() );
-				ribbon.position.y = 250;
-				ribbon.position.x = 250;
-				scene.add( ribbon );
-
-				ribbon.material.uniforms.color.value.setHSL( 0, 1, 0.5 );
-				materials.push( ribbon.material );
-
-				var ribbon = new THREE.Ribbon( geometry, material.clone() );
-				ribbon.position.y = -250;
-				ribbon.position.x = 250;
-				scene.add( ribbon );
-
-				ribbon.material.uniforms.color.value.setHSL( 0.1, 1, 0.5 );
-				materials.push( ribbon.material );
-
-				//
-
-				renderer = new THREE.WebGLRenderer( { antialias: true } );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.setClearColor( scene.fog.color, 1 );
-
-				container.appendChild( renderer.domElement );
-
-				//
-
-				stats = new Stats();
-				stats.domElement.style.position = 'absolute';
-				stats.domElement.style.top = '0px';
-				container.appendChild( stats.domElement );
-
-				//
-
-				document.addEventListener( 'mousemove', onDocumentMouseMove, 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 );
-
-			}
-
-			function onDocumentMouseMove( event ) {
-
-				mouseX = event.clientX - windowHalfX;
-				mouseY = event.clientY - windowHalfY;
-
-			}
-
-			function onDocumentTouchStart( event ) {
-
-				if ( event.touches.length === 1 ) {
-
-					event.preventDefault();
-
-					mouseX = event.touches[ 0 ].pageX - windowHalfX;
-					mouseY = event.touches[ 0 ].pageY - windowHalfY;
-
-				}
-
-			}
-
-			function onDocumentTouchMove( event ) {
-
-				if ( event.touches.length === 1 ) {
-
-					event.preventDefault();
-
-					mouseX = event.touches[ 0 ].pageX - windowHalfX;
-					mouseY = event.touches[ 0 ].pageY - windowHalfY;
-
-				}
-
-			}
-
-			//
-
-			function animate() {
-
-				requestAnimationFrame( animate );
-
-				render();
-				stats.update();
-
-			}
-
-			function render() {
-
-				var time = Date.now() * 0.0025;
-
-				//camera.position.x += ( mouseX - camera.position.x ) * 0.036;
-				//camera.position.y += ( - mouseY - camera.position.y ) * 0.036;
-
-				camera.lookAt( scene.position );
-
-				for ( var i = 0; i < materials.length; i ++ ) {
-
-					var uniforms = materials[ i ].uniforms;
-					uniforms.ratio.value = 0.5 * ( Math.sin( time ) + 1 );
-
-				}
-
-				renderer.render( scene, camera );
-
-			}
-
-		</script>
-	</body>
-</html>

+ 2 - 1
examples/webgl_geometry_dynamic.html

@@ -112,7 +112,8 @@
 				mesh = new THREE.Mesh( geometry, material );
 				mesh = new THREE.Mesh( geometry, material );
 				scene.add( mesh );
 				scene.add( mesh );
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0xaaccff, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
+				renderer.setClearColor( 0xaaccff, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				container.innerHTML = "";
 				container.innerHTML = "";

+ 2 - 1
examples/webgl_geometry_minecraft.html

@@ -195,7 +195,8 @@
 				directionalLight.position.set( 1, 1, 0.5 ).normalize();
 				directionalLight.position.set( 1, 1, 0.5 ).normalize();
 				scene.add( directionalLight );
 				scene.add( directionalLight );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
+				renderer.setClearColor( 0xbfd1e5, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				container.innerHTML = "";
 				container.innerHTML = "";

+ 2 - 1
examples/webgl_geometry_minecraft_ao.html

@@ -296,7 +296,8 @@
 				directionalLight.position.set( 1, 1, 0.5 ).normalize();
 				directionalLight.position.set( 1, 1, 0.5 ).normalize();
 				scene.add( directionalLight );
 				scene.add( directionalLight );
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0xffffff } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
+				renderer.setClearColor( 0xffffff );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				container.innerHTML = "";
 				container.innerHTML = "";

+ 2 - 2
examples/webgl_geometry_minecraft_oculusrift.html

@@ -196,9 +196,9 @@
 				directionalLight.position.set( 1, 1, 0.5 ).normalize();
 				directionalLight.position.set( 1, 1, 0.5 ).normalize();
 				scene.add( directionalLight );
 				scene.add( directionalLight );
 
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
+				renderer.setClearColor( 0xbfd1e5, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.setClearColor(new THREE.Color(0xbfd1e5));
 
 
 				// Here is the effect for the Oculus Rift
 				// Here is the effect for the Oculus Rift
 				// worldScale 100 means that 100 Units == 1m
 				// worldScale 100 means that 100 Units == 1m

+ 2 - 1
examples/webgl_geometry_terrain_fog.html

@@ -98,7 +98,8 @@
 				mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: texture } ) );
 				mesh = new THREE.Mesh( geometry, new THREE.MeshBasicMaterial( { map: texture } ) );
 				scene.add( mesh );
 				scene.add( mesh );
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0xefd1b5, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
+				renderer.setClearColor( 0xefd1b5 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				container.innerHTML = "";
 				container.innerHTML = "";

+ 2 - 1
examples/webgl_geometry_tessellation.html

@@ -228,7 +228,8 @@
 
 
 			scene.add( mesh );
 			scene.add( mesh );
 
 
-			renderer = new THREE.WebGLRenderer( { clearColor: 0x050505, clearAlpha: 1, antialias: true } );
+			renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
+			renderer.setClearColor( 0x050505, 1 );
 			renderer.setSize( WIDTH, HEIGHT );
 			renderer.setSize( WIDTH, HEIGHT );
 
 
 			var container = document.getElementById( 'container' );
 			var container = document.getElementById( 'container' );

+ 3 - 2
examples/webgl_interactive_cubes_gpu.html

@@ -170,9 +170,10 @@
 
 
 				projector = new THREE.Projector();
 				projector = new THREE.Projector();
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: true, clearColor: 0xffffff } );
-				renderer.sortObjects = false;
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
+				renderer.setClearColor( 0xffffff, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.sortObjects = false;
 
 
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 

+ 2 - 2
examples/webgl_lights_pointlights2.html

@@ -220,9 +220,9 @@
 
 
 				// RENDERER
 				// RENDERER
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x030303, clearAlpha: 1 } );
-				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setClearColor( scene.fog.color, 1 );
 				renderer.setClearColor( scene.fog.color, 1 );
+				renderer.setSize( window.innerWidth, window.innerHeight );
 
 
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 

+ 1 - 1
examples/webgl_lines_colors.html

@@ -87,7 +87,7 @@
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: false } );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.autoClear = false;
 				renderer.autoClear = false;
 
 

+ 2 - 1
examples/webgl_lines_dashed.html

@@ -94,7 +94,8 @@
 				objects.push( object );
 				objects.push( object );
 				scene.add( object );
 				scene.add( object );
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x111111, clearAlpha: 1, antialias: true } );
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
+				renderer.setClearColor( 0x111111, 1 );
 				renderer.setSize( WIDTH, HEIGHT );
 				renderer.setSize( WIDTH, HEIGHT );
 
 
 				var container = document.getElementById( 'container' );
 				var container = document.getElementById( 'container' );

+ 1 - 1
examples/webgl_loader_ctm_materials.html

@@ -146,7 +146,7 @@
 
 
 				// RENDERER
 				// RENDERER
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: true, clearColor: 0xffffff, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.domElement.style.position = "relative";
 				renderer.domElement.style.position = "relative";
 
 

+ 2 - 5
examples/webgl_loader_obj_mtl.html

@@ -76,15 +76,12 @@
 				// model
 				// model
 
 
 				var loader = new THREE.OBJMTLLoader();
 				var loader = new THREE.OBJMTLLoader();
-				loader.addEventListener( 'load', function ( event ) {
-
-					var object = event.content;
+				loader.load( 'obj/male02/male02.obj', 'obj/male02/male02_dds.mtl', function ( object ) {
 
 
 					object.position.y = - 80;
 					object.position.y = - 80;
 					scene.add( object );
 					scene.add( object );
 
 
-				});
-				loader.load( 'obj/male02/male02.obj', 'obj/male02/male02_dds.mtl' );
+				} );
 
 
 				//
 				//
 
 

+ 1 - 1
examples/webgl_lod.html

@@ -120,7 +120,7 @@
 				}
 				}
 
 
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.sortObjects = false;
 				renderer.sortObjects = false;
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 2 - 1
examples/webgl_marching_cubes.html

@@ -157,7 +157,8 @@
 
 
 			// RENDERER
 			// RENDERER
 
 
-			renderer = new THREE.WebGLRenderer( { clearColor: 0x050505, clearAlpha: 1, alpha: false } );
+			renderer = new THREE.WebGLRenderer( { alpha: false } );
+			renderer.setClearColor( 0x050505, 1 );
 			renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 			renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 
 			renderer.domElement.style.position = "absolute";
 			renderer.domElement.style.position = "absolute";

+ 2 - 1
examples/webgl_materials2.html

@@ -119,7 +119,8 @@
 
 
 				//
 				//
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x0a0a0a, clearAlpha: 1, antialias: true } );
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
+				renderer.setClearColor( 0x0a0a0a, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.sortObjects = true;
 				renderer.sortObjects = true;
 
 

+ 1 - 1
examples/webgl_materials_blending.html

@@ -117,7 +117,7 @@
 
 
 				// RENDERER
 				// RENDERER
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				document.body.appendChild( renderer.domElement );
 				document.body.appendChild( renderer.domElement );
 
 

+ 1 - 1
examples/webgl_materials_blending_custom.html

@@ -281,7 +281,7 @@
 
 
 				// RENDERER
 				// RENDERER
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 
 				renderer.domElement.style.position = "absolute";
 				renderer.domElement.style.position = "absolute";

+ 2 - 1
examples/webgl_materials_bumpmap.html

@@ -176,7 +176,8 @@
 
 
 				loader.load( "obj/leeperrysmith/LeePerrySmith.js", function( geometry ) { createScene( geometry, 100, material ) } );
 				loader.load( "obj/leeperrysmith/LeePerrySmith.js", function( geometry ) { createScene( geometry, 100, material ) } );
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x060708, clearAlpha: 1, alpha: false } );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
+				renderer.setClearColor( 0x060708, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 

+ 2 - 1
examples/webgl_materials_bumpmap_skin.html

@@ -179,7 +179,8 @@
 
 
 				//
 				//
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x060708, clearAlpha: 1, alpha: false } );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
+				renderer.setClearColor( 0x060708, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 

+ 2 - 3
examples/webgl_materials_cubemap_dynamic.html

@@ -193,10 +193,9 @@
 
 
 				// RENDERER
 				// RENDERER
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: false } );
-
-				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setClearColor( scene.fog.color, 1 );
 				renderer.setClearColor( scene.fog.color, 1 );
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 
 				renderer.domElement.style.position = "absolute";
 				renderer.domElement.style.position = "absolute";
 				renderer.domElement.style.top = MARGIN + "px";
 				renderer.domElement.style.top = MARGIN + "px";

+ 2 - 3
examples/webgl_materials_lightmap.html

@@ -134,13 +134,12 @@
 
 
 				// RENDERER
 				// RENDERER
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false, clearColor: 0xfafafa, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
+				renderer.setClearColor( scene.fog.color, 1 );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.domElement.style.position = "relative";
 				renderer.domElement.style.position = "relative";
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 
-				renderer.setClearColor( scene.fog.color, 1 );
-
 				renderer.gammaInput = true;
 				renderer.gammaInput = true;
 				renderer.gammaOutput = true;
 				renderer.gammaOutput = true;
 				renderer.physicallyBasedShading = true;
 				renderer.physicallyBasedShading = true;

+ 2 - 1
examples/webgl_materials_normalmap2.html

@@ -153,7 +153,8 @@
 
 
 				loader.load( "obj/leeperrysmith/LeePerrySmith.js", function( geometry ) { createScene( geometry, 100, material ) } );
 				loader.load( "obj/leeperrysmith/LeePerrySmith.js", function( geometry ) { createScene( geometry, 100, material ) } );
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0x111111, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
+				renderer.setClearColor( 0x111111, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 

+ 59 - 12
examples/webgl_materials_texture_compressed.html

@@ -68,56 +68,103 @@
 				DXT3 - RGBA - transparent textures with sharp alpha transitions
 				DXT3 - RGBA - transparent textures with sharp alpha transitions
 				DXT5 - RGBA - transparent textures with full alpha range
 				DXT5 - RGBA - transparent textures with full alpha range
 				*/
 				*/
-
-				var map1 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/disturb_dxt1_nomip.dds' );
+											
+				var map1 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/disturb_dxt1_nomip.dds' );
 				map1.minFilter = map1.magFilter = THREE.LinearFilter;
 				map1.minFilter = map1.magFilter = THREE.LinearFilter;
 				map1.anisotropy = 4;
 				map1.anisotropy = 4;
 
 
-				var map2 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/disturb_dxt1_mip.dds' );
+				var map2 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/disturb_dxt1_mip.dds' );
 				map2.anisotropy = 4;
 				map2.anisotropy = 4;
 
 
-				var map3 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/hepatica_dxt3_mip.dds' );
+				var map3 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/hepatica_dxt3_mip.dds' );
 				map3.anisotropy = 4;
 				map3.anisotropy = 4;
 
 
-				var map4 = THREE.ImageUtils.loadCompressedTexture( 'textures/compressed/explosion_dxt5_mip.dds' );
+				var map4 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/explosion_dxt5_mip.dds' );
 				map4.anisotropy = 4;
 				map4.anisotropy = 4;
 
 
-				var cubemap = THREE.ImageUtils.loadCompressedTextureCube( 'textures/compressed/Mountains.dds', new THREE.CubeReflectionMapping, function( cubemap ) {
+				var map5 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/disturb_argb_nomip.dds' );
+				map5.minFilter = map5.magFilter = THREE.LinearFilter;
+				map5.anisotropy = 4;
+
+				var map6 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/disturb_argb_mip.dds' );
+				map6.anisotropy = 4;
 
 
-					cubemap.magFilter = cubemap.minFilter = THREE.LinearFilter;
+				var cubemap1 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/Mountains.dds', new THREE.CubeReflectionMapping, function( cubemap ) {
+					cubemap1.magFilter = cubemap1.minFilter = THREE.LinearFilter;
 					material1.needsUpdate = true;
 					material1.needsUpdate = true;
 
 
 				} );
 				} );
 
 
-				var material1 = new THREE.MeshBasicMaterial( { map: map1, envMap: cubemap } );
+				var cubemap2 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/Mountains_argb_mip.dds', new THREE.CubeReflectionMapping, function( cubemap ) {
+					cubemap2.magFilter = cubemap2.minFilter = THREE.LinearFilter;
+					material5.needsUpdate = true;
+				} );
+
+				var cubemap3 = THREE.ImageUtils.loadDDSTexture( 'textures/compressed/Mountains_argb_nomip.dds', new THREE.CubeReflectionMapping, function( cubemap ) {
+					cubemap3.magFilter = cubemap3.minFilter = THREE.LinearFilter;
+					material6.needsUpdate = true;
+				} );
+
+
+				var material1 = new THREE.MeshBasicMaterial( { map: map1, envMap: cubemap1 } );
 				var material2 = new THREE.MeshBasicMaterial( { map: map2 } );
 				var material2 = new THREE.MeshBasicMaterial( { map: map2 } );
 				var material3 = new THREE.MeshBasicMaterial( { map: map3, alphaTest: 0.5, side: THREE.DoubleSide } );
 				var material3 = new THREE.MeshBasicMaterial( { map: map3, alphaTest: 0.5, side: THREE.DoubleSide } );
 				var material4 = new THREE.MeshBasicMaterial( { map: map4, side: THREE.DoubleSide, blending: THREE.AdditiveBlending, depthTest: false, transparent: true } );
 				var material4 = new THREE.MeshBasicMaterial( { map: map4, side: THREE.DoubleSide, blending: THREE.AdditiveBlending, depthTest: false, transparent: true } );
+				var material5 = new THREE.MeshBasicMaterial( { envMap: cubemap2 } );
+				var material6 = new THREE.MeshBasicMaterial( { envMap: cubemap3 } );
+				var material7 = new THREE.MeshBasicMaterial( { map: map5 } );
+				var material8 = new THREE.MeshBasicMaterial( { map: map6 } );
+				
 
 
 				var mesh = new THREE.Mesh( new THREE.TorusGeometry( 100, 50, 32, 16 ), material1 );
 				var mesh = new THREE.Mesh( new THREE.TorusGeometry( 100, 50, 32, 16 ), material1 );
-				mesh.position.x = -200;
+				mesh.position.x = -600;
 				mesh.position.y = -200;
 				mesh.position.y = -200;
 				scene.add( mesh );
 				scene.add( mesh );
 				meshes.push( mesh );
 				meshes.push( mesh );
 
 
 				mesh = new THREE.Mesh( geometry, material2 );
 				mesh = new THREE.Mesh( geometry, material2 );
-				mesh.position.x = 200;
+				mesh.position.x = -200;
 				mesh.position.y = -200;
 				mesh.position.y = -200;
 				scene.add( mesh );
 				scene.add( mesh );
 				meshes.push( mesh );
 				meshes.push( mesh );
 
 
 				mesh = new THREE.Mesh( geometry, material3 );
 				mesh = new THREE.Mesh( geometry, material3 );
-				mesh.position.x = 200;
+				mesh.position.x = -200;
 				mesh.position.y = 200;
 				mesh.position.y = 200;
 				scene.add( mesh );
 				scene.add( mesh );
 				meshes.push( mesh );
 				meshes.push( mesh );
 
 
 				mesh = new THREE.Mesh( geometry, material4 );
 				mesh = new THREE.Mesh( geometry, material4 );
-				mesh.position.x = -200;
+				mesh.position.x = -600;
+				mesh.position.y = 200;
+				scene.add( mesh );
+				meshes.push( mesh );
+
+				mesh = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200 ), material5 );
+				mesh.position.x = 200;
+				mesh.position.y = 200;
+				scene.add( mesh );
+				meshes.push( mesh );
+
+				mesh = new THREE.Mesh( new THREE.CubeGeometry( 200, 200, 200 ), material6 );
+				mesh.position.x = 200;
+				mesh.position.y = -200;
+				scene.add( mesh );
+				meshes.push( mesh );
+
+				mesh = new THREE.Mesh( geometry, material7 );
+				mesh.position.x = 600;
+				mesh.position.y = -200;
+				scene.add( mesh );
+				meshes.push( mesh );
+
+				mesh = new THREE.Mesh( geometry, material8 );
+				mesh.position.x = 600;
 				mesh.position.y = 200;
 				mesh.position.y = 200;
 				scene.add( mesh );
 				scene.add( mesh );
 				meshes.push( mesh );
 				meshes.push( mesh );
 
 
+
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				document.body.appendChild( renderer.domElement );
 				document.body.appendChild( renderer.domElement );

+ 215 - 0
examples/webgl_mirror.html

@@ -0,0 +1,215 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - mirror</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 {
+				color: #888888;
+				font-family:Monospace;
+				font-size:13px;
+
+				background-color: #000;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px;
+				width: 200px;
+				left: calc(50% - 100px);
+				text-align: center;
+			}
+
+			a {
+				color: #00f;
+			}
+		</style>
+	</head>
+	<body>
+
+		<div id="container"></div>
+		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - mirror
+		</div>
+
+		<script src="../build/three.min.js"></script>
+		<script src="js/Mirror.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
+
+		<script>
+
+			// scene size
+			var WIDTH = window.innerWidth;
+			var HEIGHT = window.innerHeight;
+
+			// camera
+			var VIEW_ANGLE = 45;
+			var ASPECT = WIDTH / HEIGHT;
+			var NEAR = 1;
+			var FAR = 500;
+
+			var camera, scane, renderer;
+
+			var cameraControls;
+
+			var verticalMirror, groundMirror;
+			var sphereGroup, smallSphere;
+
+			function init() {
+
+				// renderer
+				renderer = new THREE.WebGLRenderer();
+				renderer.setSize( WIDTH, HEIGHT );
+
+				renderer.autoClear = true;
+				renderer.setClearColor( 0x000000, 1 );
+
+				// scene
+				scene = new THREE.Scene();
+
+				// camera
+				camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
+				camera.position.set( 0, 75, 160 );
+
+				cameraControls = new THREE.OrbitControls(camera, renderer.domElement);
+				cameraControls.target.set( 0, 40, 0);
+				cameraControls.maxDistance = 400;
+				cameraControls.minDistance = 10;
+				cameraControls.update();
+
+				var container = document.getElementById( 'container' );
+				container.appendChild( renderer.domElement );
+
+			}
+
+			function fillScene() {
+
+				var planeGeo = new THREE.PlaneGeometry( 100.1, 100.1 );
+				
+			   //MIRORR planes
+				groundMirror = new THREE.Mirror( renderer, camera, { clipBias: 0.003, textureWidth: WIDTH, textureHeight: HEIGHT, color: 0x777777 } );
+				
+				var mirrorMesh = new THREE.Mesh( planeGeo, groundMirror.material );
+				mirrorMesh.add( groundMirror );
+				mirrorMesh.rotateX( - Math.PI / 2 );
+				scene.add( mirrorMesh );
+
+				verticalMirror = new THREE.Mirror( renderer, camera, { clipBias: 0.003, textureWidth: WIDTH, textureHeight: HEIGHT, color:0x889999 } );
+				
+				var verticalMirrorMesh = new THREE.Mesh( new THREE.PlaneGeometry( 60, 60 ), verticalMirror.material );
+				verticalMirrorMesh.add( verticalMirror );
+				verticalMirrorMesh.position.y = 35;
+				verticalMirrorMesh.position.z = -45;
+				scene.add( verticalMirrorMesh );
+
+				sphereGroup = new THREE.Object3D();
+				scene.add( sphereGroup );
+
+				var geometry = new THREE.CylinderGeometry( 0.1, 15 * Math.cos( Math.PI / 180 * 30 ), 0.1, 24, 1 );
+				var material = new THREE.MeshPhongMaterial( { color: 0xffffff, emissive: 0x444444 } );
+				var sphereCap = new THREE.Mesh( geometry, material );
+				sphereCap.position.y = -15 * Math.sin( Math.PI / 180 * 30 ) - 0.05;
+				sphereCap.rotateX(-Math.PI);
+				
+				var geometry = new THREE.SphereGeometry( 15, 24, 24, Math.PI / 2, Math.PI * 2, 0, Math.PI / 180 * 120 );
+				var halfSphere = new THREE.Mesh( geometry, material );
+				halfSphere.add( sphereCap );
+				halfSphere.rotateX( - Math.PI / 180 * 135 ); 
+				halfSphere.rotateZ( - Math.PI / 180 * 20 ); 
+				halfSphere.position.y = 7.5 + 15 * Math.sin( Math.PI / 180 * 30 );
+				
+				sphereGroup.add( halfSphere );
+				
+				var geometry = new THREE.IcosahedronGeometry( 5, 0 );
+				var material = new THREE.MeshLambertMaterial( { color: 0xffffff, emissive: 0x333333, shading: THREE.FlatShading } );
+				smallSphere = new THREE.Mesh( geometry, material );
+				scene.add(smallSphere);	
+				
+				// walls
+				var planeTop = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
+				planeTop.position.y = 100;
+				planeTop.rotateX( Math.PI / 2 );
+				scene.add( planeTop );
+				
+				var planeBack = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xffffff } ) );
+				planeBack.position.z = -50;
+				planeBack.position.y = 50;
+				scene.add( planeBack );
+				
+				var planeFront = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x7f7fff } ) );
+				planeFront.position.z = 50;
+				planeFront.position.y = 50;
+				planeFront.rotateY( Math.PI );
+				scene.add( planeFront );
+				
+				var planeRight = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0x00ff00 } ) );
+				planeRight.position.x = 50;
+				planeRight.position.y = 50;
+				planeRight.rotateY( - Math.PI / 2 );
+				scene.add( planeRight );
+				
+				var planeLeft = new THREE.Mesh( planeGeo, new THREE.MeshPhongMaterial( { color: 0xff0000 } ) );
+				planeLeft.position.x = -50;
+				planeLeft.position.y = 50;
+				planeLeft.rotateY( Math.PI / 2 );
+				scene.add( planeLeft );
+				
+				// lights
+				var mainLight = new THREE.PointLight( 0xcccccc, 1.5, 250 );
+				mainLight.position.y = 60;
+				scene.add( mainLight );
+
+				var greenLight = new THREE.PointLight( 0x00ff00, 0.25, 1000 );
+				greenLight.position.set( 550, 50, 0 );
+				scene.add( greenLight );
+
+				var redLight = new THREE.PointLight( 0xff0000, 0.25, 1000 );
+				redLight.position.set( - 550, 50, 0 );
+				scene.add( redLight );
+
+				var blueLight = new THREE.PointLight( 0x7f7fff, 0.25, 1000 );
+				blueLight.position.set( 0, 50, 550 );
+				scene.add( blueLight );
+
+			}
+
+			function render() {
+
+				// render (update) the mirrors
+				groundMirror.renderWithMirror( verticalMirror );
+				verticalMirror.renderWithMirror( groundMirror );
+				
+				renderer.render(scene, camera);
+
+			}
+
+			function update() {
+				
+				requestAnimationFrame( update );
+
+				var timer = Date.now() * 0.01;
+
+				sphereGroup.rotation.y -= 0.002;
+
+				smallSphere.position.set(
+					Math.cos( timer * 0.1 ) * 30,
+					Math.abs( Math.cos( timer * 0.2 ) ) * 20 + 5,
+					Math.sin( timer * 0.1 ) * 30
+				);
+				smallSphere.rotation.y = ( Math.PI / 2 ) - timer * 0.1;
+				smallSphere.rotation.z = timer * 0.8;
+
+				cameraControls.update();
+				
+				render();
+			}
+
+			init();
+			fillScene();
+			update();
+
+		</script>
+	</body>
+</html>

+ 2 - 1
examples/webgl_morphtargets.html

@@ -140,7 +140,8 @@
 
 
 				//
 				//
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x222222, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
+				renderer.setClearColor( 0x222222, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.sortObjects = false;
 				renderer.sortObjects = false;
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/webgl_particles_dynamic.html

@@ -139,7 +139,7 @@
 
 
 				//
 				//
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: false } );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.autoClear = false;
 				renderer.autoClear = false;
 				renderer.sortObjects = false;
 				renderer.sortObjects = false;

+ 2 - 1
examples/webgl_performance.html

@@ -76,7 +76,8 @@
 
 
 				} );
 				} );
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0xffffff } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
+				renderer.setClearColor( 0xffffff, 1 );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 

+ 2 - 1
examples/webgl_performance_doublesided.html

@@ -116,7 +116,8 @@
 
 
 				}
 				}
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x050505, clearAlpha: 1, antialias: FANCY } );
+				renderer = new THREE.WebGLRenderer( { antialias: FANCY, alpha: false } );
+				renderer.setClearColor( 0x050505, 1 );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 
 				renderer.gammaInput = true;
 				renderer.gammaInput = true;

+ 1 - 1
examples/webgl_postprocessing_dof2.html

@@ -105,7 +105,7 @@ Use WEBGL Depth buffer support?
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
-				renderer = new THREE.WebGLRenderer( { antialias: false, clearColor: 0xffffff } );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setSize( window.innerWidth, height );
 				renderer.setSize( window.innerWidth, height );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
 
 

+ 0 - 317
examples/webgl_ribbons.html

@@ -1,317 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js webgl - ribbons</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 {
-				background-color: #000000;
-				margin: 0px;
-				overflow: hidden;
-				font-family:Monospace;
-				font-size:13px;
-				text-align:center;
-				font-weight: bold;
-				text-align:center;
-			}
-
-			a {
-				color:#0078ff;
-			}
-
-			#info {
-				color:#fff;
-				position: absolute;
-				top: 0px; width: 100%;
-				padding: 5px;
-				z-index:100;
-			}
-		</style>
-	</head>
-
-	<body>
-
-		<script src="../build/three.min.js"></script>
-
-		<script src="js/shaders/ConvolutionShader.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
-
-		<script src="js/postprocessing/EffectComposer.js"></script>
-		<script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/postprocessing/RenderPass.js"></script>
-		<script src="js/postprocessing/ShaderPass.js"></script>
-		<script src="js/postprocessing/BloomPass.js"></script>
-
-		<script src="js/Detector.js"></script>
-		<script src="js/libs/stats.min.js"></script>
-
-		<div id="info">
-			<a href="http://threejs.org" target="_blank">three.js</a> - webgl ribbons example
-		</div>
-
-
-		<script>
-
-			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
-
-			var container, stats;
-			var camera, scene, renderer, ribbon, geometry, geometry2, ribbons = [],
-				parameters, i, i2, h, color, x, y, z, z2, s, n, n2, nribbons, grid;
-
-			var mouseX = 0, mouseY = 0;
-
-			var windowHalfX = window.innerWidth / 2;
-			var windowHalfY = window.innerHeight / 2;
-
-			var postprocessing = { enabled  : true };
-
-			var composer;
-
-			init();
-			animate();
-
-			function init() {
-
-				container = document.createElement( 'div' );
-				document.body.appendChild( container );
-
-				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 3000 );
-				camera.position.z = 1200;
-
-				scene = new THREE.Scene();
-				scene.fog = new THREE.FogExp2( 0x000000, 0.0016 );
-
-				geometry = new THREE.Geometry();
-				geometry2 = new THREE.Geometry();
-
-				n = 1000;
-				n2 = 2 * n;
-
-				for ( i = -n; i < n; i++ ) {
-
-					i2 = i + n;
-
-					x = i * 1.175;
-					y = ( i2 % 2 ) * 5;
-
-					if ( i2 % 2 )  {
-
-						z = 10 * Math.sin( i2 * 0.3 ) * Math.cos( i2 * 0.1 );
-
-					}
-
-					geometry.vertices.push( new THREE.Vector3( x, y, z ) );
-					geometry2.vertices.push( new THREE.Vector3( x, y, z ) );
-
-					h = i2 % 2 ? 1 : 0.15;
-					if( i2 % 4 <= 2 ) h -= 0.15;
-
-					color = new THREE.Color( 0xffffff );
-					color.setHSL( 0.1, 0, h );
-					geometry.colors.push( color );
-					geometry2.colors.push( color );
-
-				}
-
-				var tmpRot = new THREE.Matrix4();
-				tmpRot.makeRotationAxis( new THREE.Vector3( 1, 0, 0 ), Math.PI/2 );
-
-				xgrid = 34;
-				ygrid = 15;
-				nribbons = xgrid * ygrid;
-
-				c = 0;
-
-				var rotationMatrix = new THREE.Matrix4();
-
-				for ( i = 0; i < xgrid; i ++ ) {
-					for ( j = 0; j < ygrid; j ++ ) {
-
-						var material = new THREE.MeshBasicMaterial( { color: 0xffffff, vertexColors: true, side: THREE.DoubleSide } );
-
-						ribbon = new THREE.Ribbon( i % 2 ? geometry : geometry2, material );
-						ribbon.rotation.x = 0;
-						ribbon.rotation.y = Math.PI / 2;
-						ribbon.rotation.z = Math.PI;
-
-						x = 40 * ( i - xgrid/2 );
-						y = 40 * ( j - ygrid/2 );
-						z = 0;
-
-						ribbon.position.set( x, y, z );
-
-						ribbon.matrixAutoUpdate = false;
-
-						// manually create local matrix
-
-						ribbon.matrix.setPosition( ribbon.position );
-
-						rotationMatrix.makeRotationFromEuler( ribbon.rotation );
-
-						ribbon.matrix.elements[ 0 ] = rotationMatrix.elements[ 0 ];
-						ribbon.matrix.elements[ 4 ] = rotationMatrix.elements[ 4 ];
-						ribbon.matrix.elements[ 8 ] = rotationMatrix.elements[ 8 ];
-
-						ribbon.matrix.elements[ 1 ] = rotationMatrix.elements[ 1 ];
-						ribbon.matrix.elements[ 5 ] = rotationMatrix.elements[ 5 ];
-						ribbon.matrix.elements[ 9 ] = rotationMatrix.elements[ 9 ];
-
-						ribbon.matrix.elements[ 2 ] = rotationMatrix.elements[ 2 ];
-						ribbon.matrix.elements[ 6 ] = rotationMatrix.elements[ 6 ];
-						ribbon.matrix.elements[ 10 ] = rotationMatrix.elements[ 10 ];
-
-						ribbon.matrix.multiply( tmpRot );
-
-						ribbon.matrix.scale( ribbon.scale );
-
-						ribbons.push( ribbon );
-						scene.add( ribbon );
-
-						c ++;
-
-					}
-
-				}
-
-				scene.matrixAutoUpdate = false;
-
-				//
-
-				renderer = new THREE.WebGLRenderer( { antialias: false } );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.autoClear = false;
-				renderer.setClearColor( scene.fog.color, 1 );
-
-				container.appendChild( renderer.domElement );
-
-				//
-
-				stats = new Stats();
-				stats.domElement.style.position = 'absolute';
-				stats.domElement.style.top = '0px';
-				container.appendChild( stats.domElement );
-
-				//
-
-				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
-				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
-				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
-
-				//
-
-				var renderModel = new THREE.RenderPass( scene, camera );
-				var effectBloom = new THREE.BloomPass( 1.0 );
-				var effectCopy = new THREE.ShaderPass( THREE.CopyShader );
-
-				effectCopy.renderToScreen = true;
-
-				composer = new THREE.EffectComposer( renderer );
-
-				composer.addPass( renderModel );
-				composer.addPass( effectBloom );
-				composer.addPass( effectCopy );
-
-				//
-
-				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 );
-
-				composer.reset();
-
-			}
-
-			function onDocumentMouseMove( event ) {
-
-				mouseX = event.clientX - windowHalfX;
-				mouseY = event.clientY - windowHalfY;
-
-			}
-
-			function onDocumentTouchStart( event ) {
-
-				if ( event.touches.length === 1 ) {
-
-					event.preventDefault();
-
-					mouseX = event.touches[ 0 ].pageX - windowHalfX;
-					mouseY = event.touches[ 0 ].pageY - windowHalfY;
-
-				}
-
-			}
-
-			function onDocumentTouchMove( event ) {
-
-				if ( event.touches.length === 1 ) {
-
-					event.preventDefault();
-
-					mouseX = event.touches[ 0 ].pageX - windowHalfX;
-					mouseY = event.touches[ 0 ].pageY - windowHalfY;
-
-				}
-
-			}
-
-			//
-
-			function animate() {
-
-				requestAnimationFrame( animate );
-
-				render();
-				stats.update();
-
-			}
-
-			function render() {
-
-				var time = Date.now() * 0.00005;
-
-				camera.position.x += ( mouseX - camera.position.x ) * 0.036;
-				camera.position.y += ( - mouseY - camera.position.y ) * 0.036;
-
-				camera.lookAt( scene.position );
-
-				for ( i = -n; i < n; i ++ ) {
-
-					i2 = i + n;
-
-					z  =  10 * Math.sin( i2 * 0.1 + time*30 );
-					z2 =  20 * Math.cos( Math.sin( i2 * 0.1 + time * 20 ) );
-
-					geometry.vertices[ i2 ].z = z;
-					geometry2.vertices[ i2 ].z = z2;
-
-				}
-
-				geometry.verticesNeedUpdate = true;
-				geometry2.verticesNeedUpdate = true;
-
-				for ( i = 0; i < nribbons; i++ ) {
-
-					h = ( 360 * ( i / nribbons + time ) % 360 ) / 360;
-					ribbons[ i ].material.color.setHSL( h, ( i % 20 / 20 ) * 0.3 + 0.7, 0.6 );
-
-				}
-
-				renderer.clear();
-				composer.render( 0.1 );
-
-			}
-
-		</script>
-	</body>
-</html>

+ 1 - 1
examples/webgl_sandbox.html

@@ -138,7 +138,7 @@
 
 
 				}
 				}
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1 } );
+				renderer = new THREE.WebGLRenderer( { alpha: false } );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.sortObjects = false;
 				renderer.sortObjects = false;
 
 

+ 2 - 2
examples/webgl_shading_physical.html

@@ -334,9 +334,9 @@
 
 
 				// RENDERER
 				// RENDERER
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x00aaff, clearAlpha: 1, antialias: false } );
-				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setClearColor( scene.fog.color, 1 );
 				renderer.setClearColor( scene.fog.color, 1 );
+				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 
 				renderer.domElement.style.position = "absolute";
 				renderer.domElement.style.position = "absolute";
 				renderer.domElement.style.top = MARGIN + "px";
 				renderer.domElement.style.top = MARGIN + "px";

+ 1 - 1
examples/webgl_shadowmap.html

@@ -128,7 +128,7 @@
 
 
 				// RENDERER
 				// RENDERER
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: false } );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.domElement.style.position = "relative";
 				renderer.domElement.style.position = "relative";
 				renderer.domElement.style.top = MARGIN + 'px';
 				renderer.domElement.style.top = MARGIN + 'px';

+ 1 - 1
examples/webgl_shadowmap_performance.html

@@ -128,7 +128,7 @@
 
 
 				// RENDERER
 				// RENDERER
 
 
-				renderer = new THREE.WebGLRenderer( { clearColor: 0x000000, clearAlpha: 1, antialias: false } );
+				renderer = new THREE.WebGLRenderer( { antialias: false, alpha: false } );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.domElement.style.position = "relative";
 				renderer.domElement.style.position = "relative";
 				renderer.domElement.style.top = MARGIN + 'px';
 				renderer.domElement.style.top = MARGIN + 'px';

+ 1 - 1
index.html

@@ -93,7 +93,7 @@
 		</script>
 		</script>
 
 
 		<div id="panel">
 		<div id="panel">
-			<h1>three.js<span style="font-size: 50%; vertical-align: super;"> <a href="http://github.com/mrdoob/three.js/releases">r60</a></span></h1>
+			<h1>three.js<span style="font-size: 50%; vertical-align: super;"> <a href="http://github.com/mrdoob/three.js/releases">r61</a></span></h1>
 
 
 			<a href="examples/">examples</a><br /><br />
 			<a href="examples/">examples</a><br /><br />
 
 

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