浏览代码

Merge branch 'dev' into collada-exporter

Mr.doob 7 年之前
父节点
当前提交
c4a20fb3e7
共有 100 个文件被更改,包括 4316 次插入4834 次删除
  1. 2 2
      .github/CONTRIBUTING.md
  2. 2 2
      .github/ISSUE_TEMPLATE.md
  3. 86 42
      build/three.js
  4. 348 396
      build/three.min.js
  5. 86 42
      build/three.module.js
  6. 5 5
      docs/api/animation/PropertyMixer.html
  7. 1 1
      docs/api/cameras/Camera.html
  8. 1 1
      docs/api/cameras/StereoCamera.html
  9. 15 15
      docs/api/core/BufferAttribute.html
  10. 2 2
      docs/api/core/DirectGeometry.html
  11. 3 3
      docs/api/core/InterleavedBuffer.html
  12. 11 11
      docs/api/core/InterleavedBufferAttribute.html
  13. 1 1
      docs/api/core/Object3D.html
  14. 2 2
      docs/api/core/Raycaster.html
  15. 1 1
      docs/api/helpers/Box3Helper.html
  16. 1 1
      docs/api/helpers/PlaneHelper.html
  17. 16 14
      docs/api/lights/DirectionalLight.html
  18. 0 13
      docs/api/loaders/TextureLoader.html
  19. 0 4
      docs/api/loaders/managers/DefaultLoadingManager.html
  20. 2 2
      docs/api/materials/LineBasicMaterial.html
  21. 2 2
      docs/api/materials/LineDashedMaterial.html
  22. 1 2
      docs/api/materials/Material.html
  23. 3 2
      docs/api/materials/MeshBasicMaterial.html
  24. 3 2
      docs/api/materials/MeshDepthMaterial.html
  25. 4 3
      docs/api/materials/MeshLambertMaterial.html
  26. 3 2
      docs/api/materials/MeshNormalMaterial.html
  27. 3 2
      docs/api/materials/MeshPhongMaterial.html
  28. 3 2
      docs/api/materials/MeshStandardMaterial.html
  29. 1 1
      docs/api/materials/PointsMaterial.html
  30. 6 4
      docs/api/materials/ShaderMaterial.html
  31. 1 1
      docs/api/materials/SpriteMaterial.html
  32. 2 2
      docs/api/math/Box2.html
  33. 1 1
      docs/api/math/Cylindrical.html
  34. 7 2
      docs/api/math/Euler.html
  35. 1 6
      docs/api/math/Math.html
  36. 2 11
      docs/api/math/Matrix3.html
  37. 1 5
      docs/api/math/Matrix4.html
  38. 15 12
      docs/api/math/Quaternion.html
  39. 6 0
      docs/api/math/Vector2.html
  40. 4 0
      docs/api/objects/LOD.html
  41. 1 1
      docs/api/objects/Mesh.html
  42. 2 2
      docs/api/renderers/WebGLRenderer.html
  43. 0 39
      docs/api/renderers/webgl/plugins/SpritePlugin.html
  44. 3 3
      docs/api/textures/Texture.html
  45. 3 3
      docs/examples/controls/OrbitControls.html
  46. 4 2
      docs/examples/exporters/PLYExporter.html
  47. 1 1
      docs/examples/loaders/GLTFLoader.html
  48. 28 3
      docs/examples/loaders/SVGLoader.html
  49. 1 1
      docs/examples/renderers/SVGRenderer.html
  50. 2 0
      docs/index.html
  51. 0 4
      docs/list.js
  52. 6 6
      editor/css/dark.css
  53. 6 6
      editor/css/light.css
  54. 134 63
      editor/examples/arkanoid.app.json
  55. 106 43
      editor/examples/camera.app.json
  56. 53 17
      editor/examples/particles.app.json
  57. 74 39
      editor/examples/pong.app.json
  58. 8 7
      editor/examples/shaders.app.json
  59. 9 9
      editor/index.html
  60. 9 3
      editor/js/Toolbar.js
  61. 4 2
      editor/js/libs/app.js
  62. 1 1
      examples/canvas_ascii_effect.html
  63. 1 1
      examples/canvas_camera_orthographic.html
  64. 1 1
      examples/canvas_geometry_earth.html
  65. 1 1
      examples/canvas_geometry_hierarchy.html
  66. 1 1
      examples/canvas_geometry_panorama.html
  67. 7 5
      examples/canvas_geometry_panorama_fisheye.html
  68. 1 1
      examples/canvas_geometry_shapes.html
  69. 11 10
      examples/canvas_geometry_terrain.html
  70. 1 1
      examples/canvas_geometry_text.html
  71. 1 1
      examples/canvas_interactive_cubes.html
  72. 1 1
      examples/canvas_interactive_cubes_tween.html
  73. 1 1
      examples/canvas_interactive_voxelpainter.html
  74. 42 21
      examples/canvas_lines_colors.html
  75. 25 58
      examples/canvas_lines_dashed.html
  76. 23 20
      examples/canvas_lines_sphere.html
  77. 1 1
      examples/canvas_materials_video.html
  78. 1 1
      examples/canvas_performance.html
  79. 1 1
      examples/canvas_sandbox.html
  80. 4 0
      examples/files.js
  81. 2 4
      examples/index.html
  82. 13 0
      examples/js/Detector.js
  83. 769 752
      examples/js/MarchingCubes.js
  84. 1 1
      examples/js/controls/DragControls.js
  85. 10 8
      examples/js/controls/EditorControls.js
  86. 23 12
      examples/js/controls/MapControls.js
  87. 20 8
      examples/js/controls/OrbitControls.js
  88. 17 5
      examples/js/exporters/PLYExporter.js
  89. 79 16
      examples/js/loaders/ColladaLoader.js
  90. 1653 1565
      examples/js/loaders/FBXLoader.js
  91. 59 84
      examples/js/loaders/GLTFLoader.js
  92. 1 1
      examples/js/loaders/HDRCubeTextureLoader.js
  93. 74 405
      examples/js/loaders/NodeMaterialLoader.js
  94. 24 7
      examples/js/loaders/STLLoader.js
  95. 316 24
      examples/js/loaders/SVGLoader.js
  96. 8 0
      examples/js/loaders/TGALoader.js
  97. 0 774
      examples/js/modifiers/BufferSubdivisionModifier.js
  98. 14 0
      examples/js/modifiers/SubdivisionModifier.js
  99. 0 55
      examples/js/nodes/AttributeNode.js
  100. 0 110
      examples/js/nodes/ConstNode.js

+ 2 - 2
.github/CONTRIBUTING.md

@@ -1,6 +1,6 @@
 
 # Help 
-#### The issues section is for bug reports and feature requests only. If you need help, please use [stackoverflow](http://stackoverflow.com/questions/tagged/three.js).
+#### The issues section is for bug reports and feature requests only. If you need help, please use the [forum](http://discourse.threejs.org/) or [stackoverflow](http://stackoverflow.com/questions/tagged/three.js).
 ---
 # Bugs
 #### Before reporting a bug
@@ -14,7 +14,7 @@
 1. Specify the revision number of the three.js library where the bug occurred.
 2. Specify your browser version, operating system, and graphics card. (for example, Chrome 23.0.1271.95, Windows 7, Nvidia Quadro 2000M)
 3. Describe the problem in detail. Explain what happened, and what you expected would happen.
-4. Provide a small test-case (http://jsfiddle.net). [Here is a fiddle](http://jsfiddle.net/akmcv7Lh/) you can edit that runs the current version. [And here is a fiddle](http://jsfiddle.net/hw9rcLL8/) that uses the dev branch. If a test-case is not possible, provide a link to a live version of your application.
+4. Provide a small test-case (http://jsfiddle.net). [Here is a fiddle](https://jsfiddle.net/3foLr7sn/) you can edit that runs the current version. [And here is a fiddle](https://jsfiddle.net/qgu17w5o/) that uses the dev branch. If a test-case is not possible, provide a link to a live version of your application.
 5. If helpful, include a screenshot. Annotate the screenshot for clarity.
 
 ---

+ 2 - 2
.github/ISSUE_TEMPLATE.md

@@ -11,8 +11,8 @@ Always include a code snippet, screenshots, and any relevant models or textures
 
 Please also include a live example if possible. You can start from these templates:
 
-* [jsfiddle](https://jsfiddle.net/s3rjfcc3/) (latest release branch)
-* [jsfiddle](https://jsfiddle.net/ptgwhemb/) (dev branch)
+* [jsfiddle](https://jsfiddle.net/3foLr7sn/) (latest release branch)
+* [jsfiddle](https://jsfiddle.net/qgu17w5o/) (dev branch)
 * [codepen](https://codepen.io/anon/pen/aEBKxR) (latest release branch)
 * [codepen](https://codepen.io/anon/pen/BJWzaN) (dev branch)
 

文件差异内容过多而无法显示
+ 86 - 42
build/three.js


文件差异内容过多而无法显示
+ 348 - 396
build/three.min.js


文件差异内容过多而无法显示
+ 86 - 42
build/three.module.js


+ 5 - 5
docs/api/animation/PropertyMixer.html

@@ -18,7 +18,7 @@
 		<h2>Constructor</h2>
 
 
-		<h3>[name]( binding, typeName, valueSize )</h3>
+		<h3>[name]( [param:PropertyBinding binding], [param:String typeName], [param:Number valueSize] )</h3>
 		<p>
 			-- binding <br />
 			-- typeName <br />
@@ -29,12 +29,12 @@
 		<h2>Properties</h2>
 
 
-		<h3>[property:Number binding]</h3>
+		<h3>[property:PropertyBinding binding]</h3>
 		<p>
 
 		</p>
 
-		<h3>[property:Number buffer]</h3>
+		<h3>[property:TypedArray buffer]</h3>
 		<p>
 			Buffer with size [page:PropertyMixer valueSize] * 4. <br /><br />
 			This has the layout: [ incoming | accu0 | accu1 | orig ]<br /><br />
@@ -67,14 +67,14 @@
 		<h2>Methods</h2>
 
 
-		<h3>[method:null accumulate]( accuIndex, weight )</h3>
+		<h3>[method:null accumulate]( [param:Number accuIndex], [param:Number weight] )</h3>
 		<p>
 			Accumulate data in [page:PropertyMixer.buffer buffer][accuIndex] 'incoming' region into 'accu[i]'.<br />
 
 			If weight is *0* this does nothing.
 		</p>
 
-		<h3>[method:null apply]( accuIndex )</h3>
+		<h3>[method:null apply]( [param:Number accuIndex] )</h3>
 		<p>
 			Apply the state of [page:PropertyMixer.buffer buffer] 'accu[i]' to the binding when accus differ.
 		</p>

+ 1 - 1
docs/api/cameras/Camera.html

@@ -64,7 +64,7 @@
 			Return a new camera with the same properties as this one.
 		</p>
 
-		<h3>[method:Camera copy]( [param:Camera source] )</h3>
+		<h3>[method:Camera copy]( [param:Camera source], [param:Boolean recursive] )</h3>
 		<p>
 		Copy the properties from the source camera into this one.
 		</p>

+ 1 - 1
docs/api/cameras/StereoCamera.html

@@ -55,7 +55,7 @@
 
 		<h2>Methods</h2>
 
-		<h3>[method:null update]( camera )</h3>
+		<h3>[method:null update]( [param:PerspectiveCamera camera] )</h3>
 		<p>
 		Update the stereo cameras based on the camera passed in.
 		</p>

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

@@ -131,28 +131,28 @@
 		<h3>[method:null copyAt] ( [param:Integer index1], [param:BufferAttribute bufferAttribute], [param:Integer index2] ) </h3>
 		<p>Copy a vector from bufferAttribute[index2] to [page:BufferAttribute.array array][index1].</p>
 
-		<h3>[method:BufferAttribute copyColorsArray]( colors ) </h3>
+		<h3>[method:BufferAttribute copyColorsArray]( [param:Array colors] ) </h3>
 		<p>Copy an array representing RGB color values into [page:BufferAttribute.array array].</p>
 
-		<h3>[method:BufferAttribute copyVector2sArray]( vectors ) </h3>
+		<h3>[method:BufferAttribute copyVector2sArray]( [param:Array vectors] ) </h3>
 		<p>Copy an array representing [page:Vector2]s into [page:BufferAttribute.array array].</p>
 
-		<h3>[method:BufferAttribute copyVector3sArray]( vectors ) </h3>
+		<h3>[method:BufferAttribute copyVector3sArray]( [param:Array vectors] ) </h3>
 		<p>Copy an array representing [page:Vector3]s into [page:BufferAttribute.array array].</p>
 
-		<h3>[method:BufferAttribute copyVector4sArray]( vectors ) </h3>
+		<h3>[method:BufferAttribute copyVector4sArray]( [param:Array vectors] ) </h3>
 		<p>Copy an array representing [page:Vector4]s into [page:BufferAttribute.array array].</p>
 
-		<h3>[method:Number getX]( index ) </h3>
+		<h3>[method:Number getX]( [param:Integer index] ) </h3>
 		<p>Returns the x component of the vector at the given index.</p>
 
-		<h3>[method:Number getY]( index ) </h3>
+		<h3>[method:Number getY]( [param:Integer index] ) </h3>
 		<p>Returns the y component of the vector at the given index.</p>
 
-		<h3>[method:Number getZ]( index ) </h3>
+		<h3>[method:Number getZ]( [param:Integer index] ) </h3>
 		<p>Returns the z component of the vector at the given index.</p>
 
-		<h3>[method:Number getW]( index ) </h3>
+		<h3>[method:Number getW]( [param:Integer index] ) </h3>
 		<p>Returns the w component of the vector at the given index.</p>
 
 		<h3>[method:null onUpload]( [param:Function callback] ) </h3>
@@ -185,25 +185,25 @@
 		<h3>[method:BufferAttribute setDynamic] ( [param:Boolean value] ) </h3>
 		<p>Set [page:BufferAttribute.dynamic dynamic] to value.</p>
 
-		<h3>[method:BufferAttribute setX]( index, x ) </h3>
+		<h3>[method:BufferAttribute setX]( [param:Integer index], [param:Float x] ) </h3>
 		<p>Sets the x component of the vector at the given index.</p>
 
-		<h3>[method:BufferAttribute setY]( index, y ) </h3>
+		<h3>[method:BufferAttribute setY]( [param:Integer index], [param:Float y] ) </h3>
 		<p>Sets the y component of the vector at the given index.</p>
 
-		<h3>[method:BufferAttribute setZ]( index, z ) </h3>
+		<h3>[method:BufferAttribute setZ]( [param:Integer index], [param:Float z] ) </h3>
 		<p>Sets the z component of the vector at the given index.</p>
 
-		<h3>[method:BufferAttribute setW]( index, w ) </h3>
+		<h3>[method:BufferAttribute setW]( [param:Integer index], [param:Float w] ) </h3>
 		<p>Sets the w component of the vector at the given index.</p>
 
-		<h3>[method:BufferAttribute setXY]( index, x, y ) </h3>
+		<h3>[method:BufferAttribute setXY]( [param:Integer index], [param:Float x], [param:Float y] ) </h3>
 		<p>Sets the x and y components of the vector at the given index.</p>
 
-		<h3>[method:BufferAttribute setXYZ]( index, x, y, z ) </h3>
+		<h3>[method:BufferAttribute setXYZ]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z] ) </h3>
 		<p>Sets the x, y and z components of the vector at the given index.</p>
 
-		<h3>[method:BufferAttribute setXYZW]( index, x, y, z, w ) </h3>
+		<h3>[method:BufferAttribute setXYZW]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z], [param:Float w] ) </h3>
 		<p>Sets the x, y, z and w components of the vector at the given index.</p>
 
 

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

@@ -91,13 +91,13 @@
 
 		<h2>Methods</h2>
 
-		<h3>[property:null computeGroups]( [page:Geometry geometry] )</h3>
+		<h3>[property:null computeGroups]( [param:Geometry geometry] )</h3>
 		<p>
 			Compute the parts of the geometry that have different materialIndex.
 			See [page:BufferGeometry.groups].
 		</p>
 
-		<h3>[property:null fromGeometry]( [page:Geometry geometry] )</h3>
+		<h3>[property:null fromGeometry]( [param:Geometry geometry] )</h3>
 		<p>Pass in a [page:Geometry] instance for conversion.</p>
 
 

+ 3 - 3
docs/api/core/InterleavedBuffer.html

@@ -91,15 +91,15 @@
 			Set [page:InterleavedBuffer.dynamic dynamic] to value.
 		</p>
 
-		<h3>[method:InterleavedBuffer copy]( source ) </h3>
+		<h3>[method:InterleavedBuffer copy]( [param:InterleavedBuffer source] ) </h3>
 		<p>
 		 Copies another [name] to this [name].
 		</p>
 
-		<h3>[method:InterleavedBuffer copyAt]( index1, attribute, index2 ) </h3>
+		<h3>[method:InterleavedBuffer copyAt]( [param:Integer index1], [param:InterleavedBuffer attribute], [param:Integer index2] ) </h3>
 		<p>Copies data from attribute[index2] to [page:InterleavedBuffer.array array][index1].</p>
 
-		<h3>[method:InterleavedBuffer set]( value, offset ) </h3>
+		<h3>[method:InterleavedBuffer set]( [param:TypedArray value], [param:Integer offset] ) </h3>
 		<p>
 			value - The source (typed) array.<br/>
 			offset - The offset into the target array at which to begin writing values from the source array. Default is *0*.<br/><br />

+ 11 - 11
docs/api/core/InterleavedBufferAttribute.html

@@ -62,37 +62,37 @@
 
 		<h2>Methods</h2>
 
-		<h3>[method:Number getX]( index ) </h3>
+		<h3>[method:Number getX]( [param:Integer index] ) </h3>
 		<p>Returns the x component of the item at the given index.</p>
 
-		<h3>[method:Number getY]( index ) </h3>
+		<h3>[method:Number getY]( [param:Integer index] ) </h3>
 		<p>Returns the y component of the item at the given index.</p>
 
-		<h3>[method:Number getZ]( index ) </h3>
+		<h3>[method:Number getZ]( [param:Integer index] ) </h3>
 		<p>Returns the z component of the item at the given index.</p>
 
-		<h3>[method:Number getW]( index ) </h3>
+		<h3>[method:Number getW]( [param:Integer index] ) </h3>
 		<p>Returns the w component of the item at the given index.</p>
 
-		<h3>[method:null setX]( index, x ) </h3>
+		<h3>[method:null setX]( [param:Integer index], [param:Float x] ) </h3>
 		<p>Sets the x component of the item at the given index.</p>
 
-		<h3>[method:null setY]( index, y ) </h3>
+		<h3>[method:null setY]( [param:Integer index], [param:Float y] ) </h3>
 		<p>Sets the y component of the item at the given index.</p>
 
-		<h3>[method:null setZ]( index, z ) </h3>
+		<h3>[method:null setZ]( [param:Integer index], [param:Float z] ) </h3>
 		<p>Sets the z component of the item at the given index.</p>
 
-		<h3>[method:null setW]( index, w ) </h3>
+		<h3>[method:null setW]( [param:Integer index], [param:Float w] ) </h3>
 		<p>Sets the w component of the item at the given index.</p>
 
-		<h3>[method:null setXY]( index, x, y ) </h3>
+		<h3>[method:null setXY]( [param:Integer index], [param:Float x], [param:Float y] ) </h3>
 		<p>Sets the x and y components of the item at the given index.</p>
 
-		<h3>[method:null setXYZ]( index, x, y, z ) </h3>
+		<h3>[method:null setXYZ]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z] ) </h3>
 		<p>Sets the x, y and z components of the item at the given index.</p>
 
-		<h3>[method:null setXYZW]( index, x, y, z, w ) </h3>
+		<h3>[method:null setXYZW]( [param:Integer index], [param:Float x], [param:Float y], [param:Float z], [param:Float w] ) </h3>
 		<p>Sets the x, y, z and w components of the item at the given index.</p>
 
 

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

@@ -39,7 +39,7 @@
 		<h3>[property:Boolean frustumCulled]</h3>
 		<p>
 		When this is set, it checks every frame if the object is in the frustum of the camera before rendering the object.
-		Otherwise the object gets renderered every frame even if it isn't visible. Default is *true*.
+		Otherwise the object gets rendered every frame even if it isn't visible. Default is *true*.
 		</p>
 
 		<h3>[property:Integer id]</h3>

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

@@ -78,7 +78,7 @@
 		[page:Vector3 origin] — The origin vector where the ray casts from.<br />
 		[page:Vector3 direction] — The direction vector that gives direction to the ray. Should be normalized.<br />
 		[page:Float near] — All results returned are further away than near. Near can't be negative. Default value is 0.<br />
-		[page:Float far] — All results returned are closer then far. Far can't be lower then near . Default value is Infinity.
+		[page:Float far] — All results returned are closer than far. Far can't be lower than near. Default value is Infinity.
 		</p>
 		<p>
 		This creates a new raycaster object.<br />
@@ -144,7 +144,7 @@
 		Updates the ray with a new origin and direction.
 		</p>
 
-		<h3>[method:Array intersectObject]( [page:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
+		<h3>[method:Array intersectObject]( [param:Object3D object], [param:Boolean recursive], [param:Array optionalTarget] )</h3>
 		<p>
 		[page:Object3D object] — The object to check for intersection with the ray.<br />
 		[page:Boolean recursive] — If true, it also checks all descendants. Otherwise it only checks intersecton with the object. Default is false.<br />

+ 1 - 1
docs/api/helpers/Box3Helper.html

@@ -50,7 +50,7 @@
 		<p>See the base [page:LineSegments] class for common methods.</p>
 
 
-		<h3>[method:void updateMatrixWorld]( force )</h3>
+		<h3>[method:void updateMatrixWorld]( [param:Boolean force] )</h3>
 		<p>
 			This overrides the method in the base [page:Object3D] class so that it
 			also updates the wireframe box to the extent of the [page:Box3Helper.box .box]

+ 1 - 1
docs/api/helpers/PlaneHelper.html

@@ -51,7 +51,7 @@
 		<h2>Methods</h2>
 		<p>See the base [page:LineSegments] class for common methods.</p>
 
-		<h3>[method:void updateMatrixWorld]( force )</h3>
+		<h3>[method:void updateMatrixWorld]( [param:Boolean force] )</h3>
 		<p>
 			This overrides the method in the base [page:Object3D] class so that it also
 			updates the helper object according to the [page:PlaneHelper.plane .plane] and

+ 16 - 14
docs/api/lights/DirectionalLight.html

@@ -52,10 +52,10 @@
 		</p>
 
 		<code>
-// White directional light at half intensity shining from the top.
-var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
-scene.add( directionalLight );
-	</code>
+		// White directional light at half intensity shining from the top.
+		var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
+		scene.add( directionalLight );
+		</code>
 
 
 		<h2>Constructor</h2>
@@ -104,26 +104,28 @@ scene.add( directionalLight );
 
 			*Note*: For the target's position to be changed to anything other than the default,
 			it must be added to the [page:Scene scene] using
-			<code>
-				scene.add( light.target );
-			</code>
-
+		</p>
+		<code>
+		scene.add( light.target );
+		</code>
+		<p>
 			This is so that the target's [page:Object3D.matrixWorld matrixWorld] gets automatically
 			updated each frame.<br /><br />
 
 			It is also possible to set the target to be another object in the scene (anything with a
 			[page:Object3D.position position] property), like so:
-			<code>
-	var targetObject = new THREE.Object3D();
-	scene.add(targetObject);
+		</p>
+		<code>
+		var targetObject = new THREE.Object3D();
+		scene.add(targetObject);
 
-	light.target = targetObject;
-			</code>
+		light.target = targetObject;
+		</code>
+		<p>
 			The directionalLight will now track the target object.
 		</p>
 
 
-
 		<h2>Methods</h2>
 
 		See the base [page:Light Light] class for common methods.

+ 0 - 13
docs/api/loaders/TextureLoader.html

@@ -85,12 +85,6 @@
 		<p>The base path from which files will be loaded. See [page:.setPath]. Default is *undefined*.</p>
 
 
-		<h3>[property:String withCredentials]</h3>
-		<p>
-			Whether the XMLHttpRequest uses credentials - see [page:.setWithCredentials].
-			Default is *undefined*.
-		</p>
-
 		<h2>Methods</h2>
 
 		<h3>[method:Texture load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )</h3>
@@ -114,13 +108,6 @@
 			you are loading many models from the same directory.
 		</p>
 
-		<h3>[method:FileLoader setWithCredentials]( [param:Boolean value] )</h3>
-		<p>
-		Whether the XMLHttpRequest uses credentials such as cookies, authorization headers or
-		TLS client certificates. See
-		[link:https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials XMLHttpRequest.withCredentials].<br />
-		Note that this has no effect if you are loading files locally or from the same domain.
-		</p>
 
 		<h2>Source</h2>
 

+ 0 - 4
docs/api/loaders/managers/DefaultLoadingManager.html

@@ -19,10 +19,6 @@
 
 		<h2>Example</h2>
 
-		<p>
-			[example:webgl_loader_scene WebGL / loader / scene]<br />
-		</p>
-
 		<p>
 			You can optionally set the [page:LoadingManager.onStart onStart], [page:LoadingManager.onLoad onLoad],
 			[page:LoadingManager.onProgress onProgress], [page:LoadingManager.onStart onError] functions for the manager.

+ 2 - 2
docs/api/materials/LineBasicMaterial.html

@@ -75,8 +75,8 @@ var material = new THREE.LineBasicMaterial( {
 		<p>
 			Controls line thickness. Default is *1*.<br /><br />
 
-			Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-			with the [page:WebGLRenderer WebGL] renderer on Windows platforms linewidth will
+			Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+			with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
 			always be 1 regardless of the set value.
 		</p>
 

+ 2 - 2
docs/api/materials/LineDashedMaterial.html

@@ -70,8 +70,8 @@ var material = new THREE.LineDashedMaterial( {
 		<p>
 			Controls line thickness. Default is *1*.<br /><br />
 
-			Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-			with the [page:WebGLRenderer WebGL] renderer on Windows platforms linewidth will
+			Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+			with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
 			always be 1 regardless of the set value.
 		</p>
 

+ 1 - 2
docs/api/materials/Material.html

@@ -162,8 +162,7 @@
 
 		<h3>[property:Boolean needsUpdate]</h3>
 		<p>
-		Specifies that the material needs to be updated at the WebGL level.
-		Set it to true if you made changes that need to be reflected in WebGL.<br />
+		Specifies that the material needs to be recompiled.<br />
 		This property is automatically set to *true* when instancing a new material.
 		</p>
 

+ 3 - 2
docs/api/materials/MeshBasicMaterial.html

@@ -151,8 +151,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 
 		<h2>Methods</h2>

+ 3 - 2
docs/api/materials/MeshDepthMaterial.html

@@ -107,8 +107,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 
 		<h2>Methods</h2>

+ 4 - 3
docs/api/materials/MeshLambertMaterial.html

@@ -101,7 +101,7 @@
 
 		<h3>[property:Texture emissiveMap]</h3>
 		<p>
-		Set emisssive (glow) map. Default is null. The emissive map color is modulated by
+		Set emissive (glow) map. Default is null. The emissive map color is modulated by
 		the emissive color and the emissive intensity. If you have an emissive map, be sure to
 		set the emissive color to something other than black.
 		</p>
@@ -177,8 +177,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 
 		<h2>Methods</h2>

+ 3 - 2
docs/api/materials/MeshNormalMaterial.html

@@ -68,8 +68,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 
 		<h2>Methods</h2>

+ 3 - 2
docs/api/materials/MeshPhongMaterial.html

@@ -247,8 +247,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 
 		<h2>Methods</h2>

+ 3 - 2
docs/api/materials/MeshStandardMaterial.html

@@ -274,8 +274,9 @@
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 
 		<h2>Methods</h2>

+ 1 - 1
docs/api/materials/PointsMaterial.html

@@ -55,7 +55,7 @@ var starField = new THREE.Points( starsGeometry, starsMaterial );
 scene.add( starField );
 		</code>
 
-		<h3>[name]( [page:Object parameters] )</h3>
+		<h3>[name]( [param:Object parameters] )</h3>
 		<p>
 			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
 			Any property of the material (including any property inherited from [page:Material]) can be passed in here.<br /><br />

+ 6 - 4
docs/api/materials/ShaderMaterial.html

@@ -371,8 +371,9 @@ this.extensions = {
 		<h3>[property:Float linewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 
 
@@ -443,8 +444,9 @@ this.extensions = {
 		<h3>[property:Float wireframeLinewidth]</h3>
 		<p>Controls wireframe thickness. Default is 1.<br /><br />
 
-		Due to limitations in the [link:https://code.google.com/p/angleproject ANGLE layer],
-		on Windows platforms linewidth will always be 1 regardless of the set value.
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile)
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
 		</p>
 
 

+ 1 - 1
docs/api/materials/SpriteMaterial.html

@@ -37,7 +37,7 @@ scene.add( sprite );
 		</code>
 
 
-		<h3>[name]( [page:Object parameters] )</h3>
+		<h3>[name]( [param:Object parameters] )</h3>
 		<p>
 			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
 			Any property of the material (including any property inherited from [page:Material]) can be passed in here.<br /><br />

+ 2 - 2
docs/api/math/Box2.html

@@ -23,7 +23,7 @@
 		[page:Vector2 min] - (optional) [page:Vector2] representing the lower (x, y) boundary of the box.
 		Default is ( + Infinity, + Infinity ).<br>
 
-		[page:Vector2 max] - (optional) [page:Vector2] representing the lower upper (x, y) boundary of the box.
+		[page:Vector2 max] - (optional) [page:Vector2] representing the upper (x, y) boundary of the box.
 		Default is ( - Infinity, - Infinity ).<br /><br />
 
 		Creates a [name] bounded by min and max.
@@ -172,7 +172,7 @@
 		<h3>[method:Box2 set]( [param:Vector2 min], [param:Vector2 max] )</h3>
 		<p>
 			[page:Vector2 min] - (required ) [page:Vector2] representing the lower (x, y) boundary of the box. <br>
-			[page:Vector2 max]  - (required) [page:Vector2] representing the lower upper (x, y) boundary of the box. <br /><br />
+			[page:Vector2 max]  - (required) [page:Vector2] representing the upper (x, y) boundary of the box. <br /><br />
 
 			Sets the lower and upper (x, y) boundaries of this box.
 		</p>

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

@@ -50,7 +50,7 @@
 			and [page:.y y] properties to this cylindrical.
 		</p>
 
-		<h3>[method:Cylindrical set]( [param:Float radius], [param:Float phi], [param:Float theta] )</h3>
+		<h3>[method:Cylindrical set]( [param:Float radius], [param:Float theta], [param:Float y] )</h3>
 		<p>Sets values of this cylindrical's [page:.radius radius], [page:.theta theta]
 		and [page:.y y] properties.</p>
 

+ 7 - 2
docs/api/math/Euler.html

@@ -176,8 +176,13 @@
 		Returns an array of the form [[page:.x x], [page:.y y], [page:.z z], [page:.order order ]].
 		</p>
 
-		<h3>[method:Vector3 toVector3]()</h3>
-		<p>Returns the Euler's [page:.x x], [page:.y y] and [page:.z z] properties as a [page:Vector3].</p>
+		<h3>[method:Vector3 toVector3]( [param:Vector3 optionalResult] )</h3>
+		<p>
+			[page:Vector3 optionalResult] — (optional) If specified, the result will be copied into this Vector,
+			otherwise a new one will be created. <br /><br />
+
+			Returns the Euler's [page:.x x], [page:.y y] and [page:.z z] properties as a [page:Vector3].
+		</p>
 
 
 		<h2>Source</h2>

+ 1 - 6
docs/api/math/Math.html

@@ -54,12 +54,7 @@
 		and [page:Float t] = 1 will return [page:Float y].
 		</p>
 
-		<h3>[method:Float mapLinear](
-			[page:Float x],
-			[page:Float a1],
-			[page:Float a2],
-			[page:Float b1],
-			[page:Float b2] )</h3>
+		<h3>[method:Float mapLinear]( [param:Float x], [param:Float a1], [param:Float a2], [param:Float b1], [param:Float b2] )</h3>
 		<p>
 		[page:Float x] — Value to be mapped.<br />
 		[page:Float a1] — Minimum value for range A.<br />

+ 2 - 11
docs/api/math/Matrix3.html

@@ -144,12 +144,7 @@ m.elements = [ 11, 21, 31,
 		<h3>[method:this multiplyScalar]( [param:Float s] )</h3>
 		<p>Multiplies every component of the matrix by the scalar value *s*.</p>
 
-		<h3>
-			[method:this set](
-			[page:Float n11], [page:Float n12], [page:Float n13],
-			[page:Float n21], [page:Float n22], [page:Float n23],
-			[page:Float n31], [page:Float n32], [page:Float n33] )
-		</h3>
+		<h3>[method:this set]( [param:Float n11], [param:Float n12], [param:Float n13], [param:Float n21], [param:Float n22], [param:Float n23], [param:Float n31], [param:Float n32], [param:Float n33] )</h3>
 		<p>
 		[page:Float n11] - value to put in row 1, col 1.<br />
 		[page:Float n12] - value to put in row 1, col 2.<br />
@@ -169,11 +164,7 @@ m.elements = [ 11, 21, 31,
 		<h3>[method:this setFromMatrix4]( [param:Matrix4 m] )</h3>
 		<p>Set this matrx to the upper 3x3 matrix of the Matrix4 [page:Matrix4 m].</p>
 
-		<h3>
-			[method:this setUvTransform](
-			[page:Float tx], [page:Float ty], [page:Float sx], [page:Float sy],
-			[page:Float rotation], [page:Float cx], [page:Float cy] )
-		</h3>
+		<h3>[method:this setUvTransform]( [param:Float tx], [param:Float ty], [param:Float sx], [param:Float sy], [param:Float rotation], [param:Float cx], [param:Float cy] )</h3>
 		<p>
 		[page:Float tx] - offset x<br />
 		[page:Float ty] - offset y<br />

+ 1 - 5
docs/api/math/Matrix4.html

@@ -368,11 +368,7 @@ x, y, 1, 0,
 		<h3>[method:this scale]( [param:Vector3 v] )</h3>
 		<p>Multiplies the columns of this matrix by vector [page:Vector3 v].</p>
 
-		<h3>[method:this set](
-			[page:Float n11], [page:Float n12], [page:Float n13], [page:Float n14],
-			[page:Float n21], [page:Float n22], [page:Float n23], [page:Float n24],
-			[page:Float n31], [page:Float n32], [page:Float n33], [page:Float n34],
-			[page:Float n41], [page:Float n42], [page:Float n43], [page:Float n44] )</h3>
+		<h3>[method:this set]( [param:Float n11], [param:Float n12], [param:Float n13], [param:Float n14], [param:Float n21], [param:Float n22], [param:Float n23], [param:Float n24], [param:Float n31], [param:Float n32], [param:Float n33], [param:Float n34], [param:Float n41], [param:Float n42], [param:Float n43], [param:Float n44] )</h3>
 		<p>
 			Set the [page:.elements elements] of this matrix to the supplied row-major values [page:Float n11],
 			[page:Float n12], ... [page:Float n44].

+ 15 - 12
docs/api/math/Quaternion.html

@@ -59,13 +59,17 @@
 
 		<h2>Methods</h2>
 
+		<h3>[method:Float angleTo]( [param:Quaternion q] )</h3>
+		<p>
+			Returns the angle between this quaternion and quaternion [page:Quaternion q] in radians.
+		</p>
+
 		<h3>[method:Quaternion clone]()</h3>
 		<p>
 			Creates a new Quaternion with identical [page:.x x], [page:.y y],
 			[page:.z z] and [page:.w w] properties to this one.
 		</p>
 
-
 		<h3>[method:Quaternion conjugate]()</h3>
 		<p>
 		Returns the rotational conjugate of this quaternion. The conjugate of a quaternion
@@ -165,6 +169,15 @@
 		<h3>[method:Quaternion premultiply]( [param:Quaternion q] )</h3>
 		<p>Pre-multiplies this quaternion by [page:Quaternion q].</p>
 
+		<h3>[method:Quaternion rotateTowards]( [param:Quaternion q], [param:Float step] )</h3>
+		<p>
+			[page:Quaternion q] - The target quaternion.<br />
+			[page:float step] - The angular step in radians.<br /><br />
+
+			Rotates this quaternion by a given angular step to the defined quaternion *q*.
+			The method ensures that the final quaternion will not overshoot *q*.
+		</p>
+
 		<h3>[method:Quaternion slerp]( [param:Quaternion qb], [param:float t] )</h3>
 		<p>
 			[page:Quaternion qb] - The other quaternion rotation<br />
@@ -257,17 +270,7 @@ q.slerp( qb, t )
 		</p>
 
 
-		<h3>
-		[method:null slerpFlat](
-			[page:Array dst],
-			[page:Integer dstOffset],
-			[page:Array src0],
-			[page:Integer srcOffset0],
-			[page:Array src1],
-			[page:Integer srcOffset1],
-			[page:Float t]
-		)
-		</h3>
+		<h3>[method:null slerpFlat]( [param:Array dst], [param:Integer dstOffset], [param:Array src0], [param:Integer srcOffset0], [param:Array src1], [param:Integer srcOffset1], [param:Float t] )</h3>
 		<p>
 		[page:Array dst] - The output array.<br />
 		[page:Integer dstOffset] - An offset into the output array.<br />

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

@@ -176,6 +176,12 @@
 		Calculates the [link:https://en.wikipedia.org/wiki/Dot_product dot product] of this
 	  vector and [page:Vector2 v].
 		</p>
+        
+		<h3>[method:Float cross]( [param:Vector2 v] )</h3>
+		<p>
+		Calculates the [link:https://en.wikipedia.org/wiki/Cross_product cross product] of this
+	  vector and [page:Vector2 v]. Note that a 'cross-product' in 2D is not well-defined. This function computes a geometric cross-product often used in 2D graphics
+		</p>
 
 		<h3>[method:Boolean equals]( [param:Vector2 v] )</h3>
 		<p>Checks for strict equality of this vector and [page:Vector2 v].</p>

+ 4 - 0
docs/api/objects/LOD.html

@@ -21,6 +21,10 @@
 		</p>
 
 		<h2>Example</h2>
+		
+		<p>
+			[example:webgl_lod webgl / lod ]
+		</p>
 
 		<code>
 var lod = new THREE.LOD();

+ 1 - 1
docs/api/objects/Mesh.html

@@ -86,7 +86,7 @@
 		<h2>Methods</h2>
 		<p>See the base [page:Object3D] class for common methods.</p>
 
-		<h3>[method:null setDrawMode]()</h3>
+		<h3>[method:null setDrawMode]( [param:Integer value] )</h3>
 		<p>Set the value of [page:.drawMode drawMode].</p>
 
 		<h3>[method:Mesh clone]()</h3>

+ 2 - 2
docs/api/renderers/WebGLRenderer.html

@@ -211,7 +211,7 @@
 			Keep in mind that the standard materials only allow 4 MorphNormals.
 		</p>
 
-		<h3>[property:Integer physicallyCorrectLights]</h3>
+		<h3>[property:Boolean physicallyCorrectLights]</h3>
 		<p>
 		Whether to use physically correct lighting mode. Default is *false*.
 		See the [example:webgl_lights_physical lights / physical] example.
@@ -392,7 +392,7 @@
 			either the [page:WebGLRenderer.autoClearColor autoClearColor], [page:WebGLRenderer.autoClearStencil autoClearStencil] or [page:WebGLRenderer.autoClearDepth autoClearDepth] properties to false.
 		</p>
 
-		<h3>[method:null renderBufferDirect]( [param:Camera camera], [param:Array lights], [param:Fog fog], [param:Material material], [param:Object geometryGroup], [param:Object3D object] )</h3>
+		<h3>[method:null renderBufferDirect]( [param:Camera camera], [param:Fog fog], [param:Geometry geometry], [param:Material material], [param:Object3D object], [param:Object group] )</h3>
 		<p>Render a buffer geometry group using the camera and with the specified material.</p>
 
 		<h3>[method:null renderBufferImmediate]( [param:Object3D object], [param:shaderprogram program], [param:Material shading] )</h3>

+ 0 - 39
docs/api/renderers/webgl/plugins/SpritePlugin.html

@@ -1,39 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8" />
-		<base href="../../../../" />
-		<script src="list.js"></script>
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		<h1>[name]</h1>
-
-		<p class="desc">The Webglrenderer plugin class that allows Sprites to be rendered in the WebglRenderer. This plugin is automatically loaded in the Webglrenderer.</p>
-
-
-		<h2>Constructor</h2>
-
-		<h3>[name]()</h3>
-		<p>
-		Creates a new [name].
-		</p>
-
-
-		<h2>Methods</h2>
-
-		<h3>[method:null render]( [param:Scene scene], [param:Camera camera] )</h3>
-		<p>
-		scene -- The scene to render. <br />
-		camera -- The camera to render.
-		</p>
-		<p>
-		Renders the sprites defined in the scene. This gets automatically called as post-render function to draw the lensflares.
-		</p>
-
-		<h2>Source</h2>
-
-		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-	</body>
-</html>

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

@@ -234,12 +234,12 @@
 		[page:Texture.rotation .rotation], and [page:Texture.center .center].
 		</p>
 
-		<h3>[method:Texture clone]( [param:Texture texture] )</h3>
+		<h3>[method:Texture clone]()</h3>
 		<p>
 		Make copy of the texture. Note this is not a "deep copy", the image is shared.
 		</p>
 
-		<h3>[method:Texture toJSON]( meta )</h3>
+		<h3>[method:Texture toJSON]( [param:Object meta] )</h3>
 		<p>
 		meta -- optional object containing metadata.<br />
 		Convert the material to three.js JSON format.
@@ -250,7 +250,7 @@
 		Call [page:EventDispatcher EventDispatcher].dispatchEvent with a 'dispose' event type.
 		</p>
 
-		<h3>[method:null transformUv]( uv )</h3>
+		<h3>[method:null transformUv]( [param:Vector2 uv] )</h3>
 		<p>
 		Transform the uv based on the value of this texture's [page:Texture.offset .offset], [page:Texture.repeat .repeat],
 		[page:Texture.wrapS .wrapS], [page:Texture.wrapT .wrapT] and [page:Texture.flipY .flipY] properties.

+ 3 - 3
docs/examples/controls/OrbitControls.html

@@ -190,9 +190,9 @@ controls.keys = {
 			This object contains references to the mouse buttons used for the controls.
 			<code>
 controls.mouseButtons = {
-	ORBIT: THREE.MOUSE.LEFT,
-	ZOOM: THREE.MOUSE.MIDDLE,
-	PAN: THREE.MOUSE.RIGHT
+	LEFT: THREE.MOUSE.LEFT,
+	MIDDLE: THREE.MOUSE.MIDDLE,
+	RIGHT: THREE.MOUSE.RIGHT
 }
 			</code>
 		</p>

+ 4 - 2
docs/examples/exporters/PLYExporter.html

@@ -41,9 +41,10 @@
 
 		<h2>Methods</h2>
 
-		<h3>[method:ArrayBufferOrString parse]( [param:Object3D input], [param:Object options] )</h3>
+		<h3>[method:null parse]( [param:Object3D input], [param:Function onDone], [param:Object options] )</h3>
 		<p>
 		[page:Object input] — Object3D<br />
+		[page:Function onCompleted] — Will be called when the export completes. The argument will be the generated ply ascii or binary ArrayBuffer.<br />
 		[page:Options options] — Export options<br />
 		<ul>
 			<li>excludeAttributes - array. Which properties to explicitly exclude from the exported PLY file. Valid values are 'color', 'normal', 'uv', and 'index'. If triangle indices are excluded, then a point cloud is exported. Default is an empty array.</li>
@@ -51,7 +52,8 @@
 		</ul>
 		</p>
 		<p>
-		Generates ply file data as string or ArrayBuffer (ascii or binary) output from the input object.
+		Generates ply file data as string or ArrayBuffer (ascii or binary) output from the input object. The data that is returned is the same
+		that is passed into the "onCompleted" function.
 		If the object is composed of multiple children and geometry, they are merged into a single mesh in the file.
 		</p>
 

+ 1 - 1
docs/examples/loaders/GLTFLoader.html

@@ -31,7 +31,7 @@
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_unlit</li>
-			<li>KHR_lights (experimental)</li>
+			<li>KHR_lights_punctual (experimental)</li>
 		</ul>
 
 		<h2>Example</h2>

+ 28 - 3
docs/examples/loaders/SVGLoader.html

@@ -12,7 +12,7 @@
 		<h1>[name]</h1>
 
 		<p class="desc">A loader for loading a <em>.svg</em> resource.<br >
-		<a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics">Scalabe Vector Graphics</a> is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation.
+		<a href="https://en.wikipedia.org/wiki/Scalable_Vector_Graphics">Scalable Vector Graphics</a> is an XML-based vector image format for two-dimensional graphics with support for interactivity and animation.
 		</p>
 
 		<h2>Example</h2>
@@ -26,9 +26,34 @@
 			// resource URL
 			'data/svgSample.svg',
 			// called when the resource is loaded
-			function ( doc ) {
+			function ( paths ) {
 
-				scene.add( new THREE.SVGObject(doc) );
+				var group = new THREE.Group();
+
+				for ( var i = 0; i < paths.length; i ++ ) {
+
+					var path = paths[ i ];
+
+					var material = new THREE.MeshBasicMaterial( {
+						color: path.color,
+						side: THREE.DoubleSide,
+						depthWrite: false
+					} );
+
+					var shapes = path.toShapes( true );
+
+					for ( var j = 0; j < shapes.length; j ++ ) {
+
+						var shape = shapes[ j ];
+						var geometry = new THREE.ShapeBufferGeometry( shape );
+						var mesh = new THREE.Mesh( geometry, material );
+						group.add( mesh );
+
+					}
+
+				}
+
+				scene.add( group );
 
 			},
 			// called when loading is in progresses

+ 1 - 1
docs/examples/renderers/SVGRenderer.html

@@ -21,7 +21,7 @@
 				<li>Complex or animated user interfaces</li>
 			</ul>
 			<p>
-				[name] has various advantages. It produces crystal-clear and sharp output which is independet of the actual viewport resolution.<br />
+				[name] has various advantages. It produces crystal-clear and sharp output which is independent of the actual viewport resolution.<br />
 				SVG elements can be styled via CSS. And they have good accessibility since it's possible to add metadata like title or description (useful for search engines or screen readers).
 			</p>
 			<p>

+ 2 - 0
docs/index.html

@@ -93,6 +93,8 @@
 				link.setAttribute( 'target', 'viewer' );
 				link.addEventListener( 'click', function ( event ) {
 
+					if ( event.button !== 0 || event.ctrlKey || event.altKey || event.metaKey ) return;
+
 					window.location.hash = pageURL;
 					panel.classList.add( 'collapsed' );
 

+ 0 - 4
docs/list.js

@@ -416,10 +416,6 @@ var list = {
 			"WebGLProgram": "api/renderers/webgl/WebGLProgram",
 			"WebGLShader": "api/renderers/webgl/WebGLShader",
 			"WebGLState": "api/renderers/webgl/WebGLState"
-		},
-
-		"WebGLRenderer / Plugins": {
-			"SpritePlugin": "api/renderers/webgl/plugins/SpritePlugin"
 		}
 
 	}

+ 6 - 6
editor/css/dark.css

@@ -53,7 +53,7 @@ select {
 	top: 32px;
 	left: 0;
 	right: 300px;
-	bottom: 32px;
+	bottom: 0;
 }
 
 	#viewport #info {
@@ -66,7 +66,7 @@ select {
 	top: 32px;
 	left: 0;
 	right: 300px;
-	bottom: 32px;
+	bottom: 0;
 	opacity: 0.9;
 }
 
@@ -75,7 +75,7 @@ select {
 	top: 32px;
 	left: 0;
 	right: 300px;
-	bottom: 32px;
+	bottom: 0;
 }
 
 #menubar {
@@ -201,9 +201,9 @@ select {
 
 #toolbar {
 	position: absolute;
-	left: 0;
-	right: 300px;
-	bottom: 0;
+	left: calc(50% - 290px); /* ( ( 100% - 300px ) / 2.0 ) - 140px */
+	width: 280px;
+	bottom: 16px;
 	height: 32px;
 	background-color: #111;
 	color: #333;

+ 6 - 6
editor/css/light.css

@@ -49,7 +49,7 @@ select {
 	top: 32px;
 	left: 0;
 	right: 300px;
-	bottom: 32px;
+	bottom: 0;
 }
 
 	#viewport #info {
@@ -62,7 +62,7 @@ select {
 	top: 32px;
 	left: 0;
 	right: 300px;
-	bottom: 32px;
+	bottom: 0;
 	opacity: 0.9;
 }
 
@@ -71,7 +71,7 @@ select {
 	top: 32px;
 	left: 0;
 	right: 300px;
-	bottom: 32px;
+	bottom: 0;
 }
 
 #menubar {
@@ -194,9 +194,9 @@ select {
 
 #toolbar {
 	position: absolute;
-	left: 0;
-	right: 300px;
-	bottom: 0;
+	left: calc(50% - 290px); /* ( ( 100% - 300px ) / 2.0 ) - 140px */
+	width: 280px;
+	bottom: 16px;
 	height: 32px;
 	background: #eee;
 	color: #333;

+ 134 - 63
editor/examples/arkanoid.app.json

@@ -3,65 +3,72 @@
 		"type": "App"
 	},
 	"project": {
+		"gammaInput": true,
+		"gammaOutput": true,
 		"shadows": true,
 		"vr": false
 	},
 	"camera": {
 		"metadata": {
-			"version": 4.4,
+			"version": 4.5,
 			"type": "Object",
 			"generator": "Object3D.toJSON"
 		},
 		"object": {
-			"uuid": "E41E9F54-8B31-4D1F-8D09-AF5E802E9A22",
+			"uuid": "0C0DD0AD-3A7F-4ECD-A9FE-CECD97D5CBD9",
 			"type": "PerspectiveCamera",
 			"name": "Camera",
-			"matrix": [0.9392361044883728,-2.8092810300250903e-9,-0.3432718515396118,0,-0.14778217673301697,0.902585506439209,-0.404351145029068,0,0.3098321855068207,0.43051064014434814,0.847740888595581,0,142.32125854492188,202.75485229492188,389.40936279296875,1],
+			"layers": 1,
+			"matrix": [0.939236,0,-0.343272,0,-0.147782,0.902586,-0.404351,0,0.309832,0.430511,0.847741,0,11.713146,19.228675,40.388679,1],
 			"fov": 50,
-			"aspect": 1.536388140161725,
+			"zoom": 1,
 			"near": 0.1,
-			"far": 100000
+			"far": 100000,
+			"focus": 10,
+			"aspect": 1.428977,
+			"filmGauge": 35,
+			"filmOffset": 0
 		}
 	},
 	"scene": {
 		"metadata": {
-			"version": 4.4,
+			"version": 4.5,
 			"type": "Object",
 			"generator": "Object3D.toJSON"
 		},
 		"geometries": [
 			{
-				"uuid": "8F05A1F2-3877-478B-8DFC-F572AC61AB3A",
+				"uuid": "BBEE74D1-E43D-4C32-A9F3-4656E78C26F3",
 				"type": "PlaneGeometry",
-				"width": 300,
-				"height": 400,
+				"width": 30,
+				"height": 40,
 				"widthSegments": 1,
 				"heightSegments": 1
 			},
 			{
-				"uuid": "EEDF0A9A-D174-44E4-9C2F-A2F5BB8BE7F5",
-				"type": "CylinderGeometry",
-				"radiusTop": 5,
-				"radiusBottom": 5,
-				"height": 20,
-				"radialSegments": 32,
-				"heightSegments": 1,
-				"openEnded": false
-			},
-			{
-				"uuid": "7149652B-DBD7-4CB7-A600-27A9AC005C95",
+				"uuid": "C1722F5F-89AD-45D8-B78C-D1D34AF2A012",
 				"type": "BoxGeometry",
-				"width": 20,
-				"height": 10,
-				"depth": 10,
+				"width": 2,
+				"height": 1,
+				"depth": 1,
 				"widthSegments": 1,
 				"heightSegments": 1,
 				"depthSegments": 1
 			},
 			{
-				"uuid": "CABCC711-1331-4D4C-9FF6-409299F10C68",
+				"uuid": "327EFFCF-649C-4EF3-86D4-B422C5A86E89",
+				"type": "CylinderGeometry",
+				"radiusTop": 0.5,
+				"radiusBottom": 0.5,
+				"height": 2,
+				"radialSegments": 32,
+				"heightSegments": 1,
+				"openEnded": false
+			},
+			{
+				"uuid": "0791211B-BB02-4E57-82B5-64C05DE92B39",
 				"type": "SphereGeometry",
-				"radius": 5,
+				"radius": 0.5,
 				"widthSegments": 32,
 				"heightSegments": 16,
 				"phiStart": 0,
@@ -70,14 +77,24 @@
 				"thetaLength": 3.14
 			},
 			{
-				"uuid": "EFBF641D-F092-462E-B7FB-0BFAD1591EFC",
+				"uuid": "73F12A47-9EA7-47FD-BCF3-89B8219B2626",
 				"type": "BoxGeometry",
-				"width": 20,
-				"height": 10,
-				"depth": 10,
+				"width": 2,
+				"height": 1,
+				"depth": 1,
 				"widthSegments": 1,
 				"heightSegments": 1,
 				"depthSegments": 1
+			},
+			{
+				"uuid": "3BDEB9FB-BDD4-44AD-8A47-008BED1C8982",
+				"type": "CylinderGeometry",
+				"radiusTop": 0.5,
+				"radiusBottom": 0.5,
+				"height": 2,
+				"radialSegments": 32,
+				"heightSegments": 1,
+				"openEnded": false
 			}],
 		"materials": [
 			{
@@ -86,7 +103,19 @@
 				"color": 86015,
 				"emissive": 0,
 				"specular": 1118481,
-				"shininess": 30
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
+			},
+			{
+				"uuid": "D98FC4D1-169E-420A-92EA-20E55009A46D",
+				"type": "MeshBasicMaterial",
+				"color": 63744,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true,
+				"wireframe": true
 			},
 			{
 				"uuid": "3B9DE64D-E1C8-4C24-9F73-3A9E10E3E655",
@@ -94,13 +123,10 @@
 				"color": 16777215,
 				"emissive": 0,
 				"specular": 1118481,
-				"shininess": 30
-			},
-			{
-				"uuid": "D98FC4D1-169E-420A-92EA-20E55009A46D",
-				"type": "MeshBasicMaterial",
-				"wireframe": true,
-				"color": 63744
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			},
 			{
 				"uuid": "043B208C-1F83-42C6-802C-E0E35621C27C",
@@ -108,100 +134,145 @@
 				"color": 16777215,
 				"emissive": 0,
 				"specular": 1118481,
-				"shininess": 30
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			},
 			{
 				"uuid": "40EC9BDA-91C0-4671-937A-2BCB6DA7EEBB",
 				"type": "MeshBasicMaterial",
-				"wireframe": true,
-				"color": 63744
+				"color": 63744,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true,
+				"wireframe": true
 			}],
 		"object": {
 			"uuid": "31517222-A9A7-4EAF-B5F6-60751C0BABA3",
 			"type": "Scene",
 			"name": "Scene",
+			"layers": 1,
 			"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
 			"children": [
 				{
 					"uuid": "EBBB1E63-6318-4752-AE2E-440A4E0B3EF3",
 					"type": "Mesh",
 					"name": "Ground",
-					"matrix": [1,0,0,0,0,0.0007960614748299122,-0.9999997019767761,0,0,0.9999997019767761,0.0007960614748299122,0,0,0,0,1],
-					"geometry": "8F05A1F2-3877-478B-8DFC-F572AC61AB3A",
+					"layers": 1,
+					"matrix": [1,0,0,0,0,0.000796,-1,0,0,1,0.000796,0,0,0,0,1],
+					"geometry": "BBEE74D1-E43D-4C32-A9F3-4656E78C26F3",
 					"material": "2F69AF3A-DDF5-4BBA-87B5-80159F90DDBF"
 				},
 				{
 					"uuid": "6EE2E764-43E0-48E0-85F2-E0C8823C20DC",
 					"type": "DirectionalLight",
 					"name": "DirectionalLight 1",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,100,200,150,1],
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,10,20,15,1],
 					"color": 16777215,
-					"intensity": 1
+					"intensity": 1,
+					"shadow": {
+						"camera": {
+							"uuid": "3BC010F7-9766-4087-BA04-1D4FD7721ABA",
+							"type": "OrthographicCamera",
+							"layers": 1,
+							"zoom": 1,
+							"left": -5,
+							"right": 5,
+							"top": 5,
+							"bottom": -5,
+							"near": 0.5,
+							"far": 500
+						}
+					}
 				},
 				{
 					"uuid": "38219749-1E67-45F2-AB15-E64BA0940CAD",
 					"type": "Mesh",
 					"name": "Brick",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,5,0,1],
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0.5,0,1],
+					"geometry": "C1722F5F-89AD-45D8-B78C-D1D34AF2A012",
+					"material": "D98FC4D1-169E-420A-92EA-20E55009A46D",
 					"children": [
 						{
 							"uuid": "711A5955-8F17-4A8B-991A-7604D27E6FA0",
 							"type": "Mesh",
 							"name": "Cylinder",
-							"matrix": [0.0007962009985931218,0.0007962677045725286,0.9999995231628418,0,-0.9999997615814209,3.462185702574061e-7,0.0007962677045725286,0,2.210134084634774e-7,-0.9999997615814209,0.0007962008821777999,0,0,0,0,1],
-							"geometry": "EEDF0A9A-D174-44E4-9C2F-A2F5BB8BE7F5",
+							"layers": 1,
+							"matrix": [0.000795,0.000795,1,0,-1.000001,-0.000001,0.000795,0,0.000001,-1.000001,0.000795,0,0,0,0,1],
+							"geometry": "327EFFCF-649C-4EF3-86D4-B422C5A86E89",
 							"material": "3B9DE64D-E1C8-4C24-9F73-3A9E10E3E655"
-						}],
-					"geometry": "7149652B-DBD7-4CB7-A600-27A9AC005C95",
-					"material": "D98FC4D1-169E-420A-92EA-20E55009A46D"
+						}]
 				},
 				{
 					"uuid": "18FFA67C-F893-4E7A-8A76-8D996DEBE0C6",
 					"type": "Mesh",
 					"name": "Ball",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,5,35.54999923706055,1],
-					"geometry": "CABCC711-1331-4D4C-9FF6-409299F10C68",
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0.5,3.55,1],
+					"geometry": "0791211B-BB02-4E57-82B5-64C05DE92B39",
 					"material": "043B208C-1F83-42C6-802C-E0E35621C27C"
 				},
 				{
 					"uuid": "6D660D49-39B8-40C3-95F6-E4E007AA8D79",
 					"type": "Mesh",
 					"name": "Paddle",
-					"matrix": [2,0,0,0,0,1,0,0,0,0,1,0,0,5,159.5399932861328,1],
+					"layers": 1,
+					"matrix": [2,0,0,0,0,1,0,0,0,0,1,0,0,0.5,15.95,1],
+					"geometry": "73F12A47-9EA7-47FD-BCF3-89B8219B2626",
+					"material": "40EC9BDA-91C0-4671-937A-2BCB6DA7EEBB",
 					"children": [
 						{
 							"uuid": "4F5F884C-9E1B-45E6-8F1E-4D538A46D8CB",
 							"type": "Mesh",
 							"name": "Cylinder",
-							"matrix": [0.0007962009985931218,0.0007962677045725286,0.9999995231628418,0,-0.9999997615814209,3.462185702574061e-7,0.0007962677045725286,0,2.210134084634774e-7,-0.9999997615814209,0.0007962008821777999,0,0,0,0,1],
-							"geometry": "EEDF0A9A-D174-44E4-9C2F-A2F5BB8BE7F5",
+							"layers": 1,
+							"matrix": [0.000795,0.000795,1,0,-1.000001,-0.000001,0.000795,0,0.000001,-1.000001,0.000795,0,0,0,0,1],
+							"geometry": "3BDEB9FB-BDD4-44AD-8A47-008BED1C8982",
 							"material": "3B9DE64D-E1C8-4C24-9F73-3A9E10E3E655"
-						}],
-					"geometry": "EFBF641D-F092-462E-B7FB-0BFAD1591EFC",
-					"material": "40EC9BDA-91C0-4671-937A-2BCB6DA7EEBB"
+						}]
 				},
 				{
 					"uuid": "B0BEAF69-8B5D-4D87-ADCA-FDE83A02762D",
 					"type": "PointLight",
 					"name": "PointLight 2",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-116.54356384277344,69.48957061767578,-206.8248291015625,1],
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-11.65,6.949,-20.682,1],
 					"color": 16777215,
 					"intensity": 1,
 					"distance": 0,
-					"decay": 1
-				}]
+					"decay": 1,
+					"shadow": {
+						"camera": {
+							"uuid": "2F0DA21A-EFB8-4E9A-83C5-A601D6113780",
+							"type": "PerspectiveCamera",
+							"layers": 1,
+							"fov": 90,
+							"zoom": 1,
+							"near": 0.5,
+							"far": 500,
+							"focus": 10,
+							"aspect": 1,
+							"filmGauge": 35,
+							"filmOffset": 0
+						}
+					}
+				}],
+			"background": 11184810
 		}
 	},
 	"scripts": {
 		"6D660D49-39B8-40C3-95F6-E4E007AA8D79": [
 			{
 				"name": "User",
-				"source": "function mousemove( event ) {\n\n\tthis.position.x = ( event.clientX / player.width ) * 300 - 150;\n\n}\n\n// function update( event ) {}"
+				"source": "function mousemove( event ) {\n\n\tthis.position.x = ( event.clientX / player.width ) * 30 - 15;\n\n}\n\n// function update( event ) {}"
 			}],
 		"31517222-A9A7-4EAF-B5F6-60751C0BABA3": [
 			{
 				"name": "Game Logic",
-				"source": "var ball = this.getObjectByName( 'Ball' );\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = - 0.5;\ndirection.normalize();\n\nvar speed = new THREE.Vector3();\n\n//\n\nvar group = new THREE.Group();\nthis.add( group );\n\nvar paddle = this.getObjectByName( 'Paddle' );\npaddle.material.visible = false;\ngroup.add( paddle );\n\nvar brick = this.getObjectByName( 'Brick' );\n\nfor ( var j = 0; j < 8; j ++ ) {\n\n\tvar material = new THREE.MeshPhongMaterial( { color: Math.random() * 0xffffff } );\n\n\tfor ( var i = 0; i < 12; i ++ ) {\n\t\t\n\t\tvar object = brick.clone();\n\t\tobject.position.x = i * 22 - 120;\n\t\tobject.position.z = j * 14 - 120;\n\t\tgroup.add( object );\n\n\t\tvar cylinder = object.getObjectByName( 'Cylinder' );\n\t\tcylinder.material = material;\n\n\t}\n\t\n}\n\nbrick.visible = false;\nbrick.material.visible = false;\n\n//\n\nvar raycaster = new THREE.Raycaster();\n\nfunction update( event ) {\n\t\n\tif ( ball.position.x < - 150 || ball.position.x > 150 ) direction.x = - direction.x;\n\tif ( ball.position.z < - 200 || ball.position.z > 200 ) direction.z = - direction.z;\n\n\tball.position.x = Math.max( - 150, Math.min( 150, ball.position.x ) );\n\tball.position.z = Math.max( - 200, Math.min( 200, ball.position.z ) );\n\t\n\tball.position.add( speed.copy( direction ).multiplyScalar( event.delta / 4 ) );\n\t\n\traycaster.set( ball.position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( group.children );\n\t\n\tif ( intersections.length > 0 ) {\n\t\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 5 ) {\n\t\t\t\n\t\t\tif ( intersection.object !== paddle ) {\n\n\t\t\t\tgroup.remove( intersection.object );\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n}"
+				"source": "var ball = this.getObjectByName( 'Ball' );\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = - 0.5;\ndirection.normalize();\n\nvar speed = new THREE.Vector3();\n\n//\n\nvar group = new THREE.Group();\nthis.add( group );\n\nvar paddle = this.getObjectByName( 'Paddle' );\npaddle.material.visible = false;\ngroup.add( paddle );\n\nvar brick = this.getObjectByName( 'Brick' );\n\nfor ( var j = 0; j < 8; j ++ ) {\n\n\tvar material = new THREE.MeshPhongMaterial( { color: Math.random() * 0xffffff } );\n\n\tfor ( var i = 0; i < 12; i ++ ) {\n\t\t\n\t\tvar object = brick.clone();\n\t\tobject.position.x = i * 2.2 - 12;\n\t\tobject.position.z = j * 1.4 - 12;\n\t\tgroup.add( object );\n\n\t\tvar cylinder = object.getObjectByName( 'Cylinder' );\n\t\tcylinder.material = material;\n\n\t}\n\t\n}\n\nbrick.visible = false;\nbrick.material.visible = false;\n\n//\n\nvar raycaster = new THREE.Raycaster();\n\nfunction update( event ) {\n\t\n\tif ( ball.position.x < - 15 || ball.position.x > 15 ) direction.x = - direction.x;\n\tif ( ball.position.z < - 20 || ball.position.z > 20 ) direction.z = - direction.z;\n\n\tball.position.x = Math.max( - 15, Math.min( 15, ball.position.x ) );\n\tball.position.z = Math.max( - 20, Math.min( 20, ball.position.z ) );\n\t\n\tball.position.add( speed.copy( direction ).multiplyScalar( event.delta / 40 ) );\n\t\n\traycaster.set( ball.position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( group.children );\n\t\n\tif ( intersections.length > 0 ) {\n\t\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 0.5 ) {\n\t\t\t\n\t\t\tif ( intersection.object !== paddle ) {\n\n\t\t\t\tgroup.remove( intersection.object );\n\t\t\t\t\n\t\t\t}\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n}"
 			}]
 	}
 }

+ 106 - 43
editor/examples/camera.app.json

@@ -3,65 +3,72 @@
 		"type": "App"
 	},
 	"project": {
+		"gammaInput": true,
+		"gammaOutput": true,
 		"shadows": true,
 		"vr": false
 	},
 	"camera": {
 		"metadata": {
-			"version": 4.3,
+			"version": 4.5,
 			"type": "Object",
-			"generator": "ObjectExporter"
+			"generator": "Object3D.toJSON"
 		},
 		"object": {
-			"uuid": "C7FB195B-270E-47B4-95C9-1754652A9D11",
+			"uuid": "60EBAF60-53DA-47B0-A028-8FC031B708F6",
 			"type": "PerspectiveCamera",
 			"name": "Camera",
+			"layers": 1,
+			"matrix": [0.970041,0,-0.242943,0,-0.048226,0.980099,-0.192562,0,0.238108,0.198509,0.950736,0,1.548,1.29,6.18,1],
 			"fov": 50,
-			"aspect": 1.2252042007001167,
+			"zoom": 1,
 			"near": 0.1,
 			"far": 100000,
-			"matrix": [0.9700406789779663,-2.851828329042405e-9,-0.24294254183769226,0,-0.04822639003396034,0.9800989627838135,-0.1925622522830963,0,0.23810774087905884,0.19850945472717285,0.950735867023468,0,154.7735595703125,129.03408813476562,617.992431640625,1]
+			"focus": 10,
+			"aspect": 1.428977,
+			"filmGauge": 35,
+			"filmOffset": 0
 		}
 	},
 	"scene": {
 		"metadata": {
-			"version": 4.3,
+			"version": 4.5,
 			"type": "Object",
-			"generator": "ObjectExporter"
+			"generator": "Object3D.toJSON"
 		},
 		"geometries": [
 			{
-				"uuid": "51BB3E54-D2DF-4576-9953-FB8E940588B5",
+				"uuid": "6D90C4BE-EBA6-4E21-8F54-7CFDAA61F30B",
 				"type": "PlaneGeometry",
-				"width": 1000,
-				"height": 1000,
+				"width": 10,
+				"height": 10,
 				"widthSegments": 1,
 				"heightSegments": 1
 			},
 			{
-				"uuid": "D8E200D3-27BC-49F8-A5C5-7384206E70FE",
+				"uuid": "D3008B2A-ACDD-43CC-87F7-4F942607D21A",
 				"type": "BoxGeometry",
-				"width": 100,
-				"height": 100,
-				"depth": 100,
+				"width": 1,
+				"height": 1,
+				"depth": 1,
 				"widthSegments": 1,
 				"heightSegments": 1,
 				"depthSegments": 1
 			},
 			{
-				"uuid": "25BA32DB-8B02-4ABA-A77C-69868C464A1A",
+				"uuid": "F482ACD4-013A-49CF-AE0F-C9FF4ADAE409",
 				"type": "CylinderGeometry",
 				"radiusTop": 0,
-				"radiusBottom": 40,
-				"height": 75,
+				"radiusBottom": 0.4,
+				"height": 0.75,
 				"radialSegments": 4,
 				"heightSegments": 1,
 				"openEnded": false
 			},
 			{
-				"uuid": "4DECFAB5-6FD1-4D84-9A29-565807B074EA",
+				"uuid": "51CDDCED-BC71-4B1B-A485-725B6A48204B",
 				"type": "IcosahedronGeometry",
-				"radius": 40,
+				"radius": 0.4,
 				"detail": 2
 			}],
 		"materials": [
@@ -71,7 +78,10 @@
 				"color": 16777215,
 				"emissive": 0,
 				"specular": 1118481,
-				"shininess": 30
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			},
 			{
 				"uuid": "B5943856-E404-45D9-A427-4774202C2CD0",
@@ -79,7 +89,10 @@
 				"color": 37119,
 				"emissive": 0,
 				"specular": 1118481,
-				"shininess": 30
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			},
 			{
 				"uuid": "3F872310-2067-4BE4-9250-5B3F4E43797E",
@@ -87,7 +100,10 @@
 				"color": 15859456,
 				"emissive": 0,
 				"specular": 1118481,
-				"shininess": 30
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			},
 			{
 				"uuid": "E1826901-7922-4584-A25D-6D487E2C9BBD",
@@ -95,83 +111,130 @@
 				"color": 16711680,
 				"emissive": 0,
 				"specular": 1118481,
-				"shininess": 30
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			}],
 		"object": {
 			"uuid": "3741222A-BD8F-401C-A5D2-5A907E891896",
 			"type": "Scene",
 			"name": "Scene",
+			"layers": 1,
 			"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
 			"children": [
 				{
 					"uuid": "B7CBBC6F-EC26-49B5-8D0D-67D9C535924B",
 					"type": "Group",
 					"name": "Dummy",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,100,400,1],
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,1,4,1],
 					"children": [
 						{
 							"uuid": "60B69C58-4201-43FD-815E-AD2EDFBBD0CE",
 							"type": "PerspectiveCamera",
 							"name": "PerspectiveCamera",
+							"layers": 1,
+							"matrix": [-1,0,0,0,0,1,0,0,0,0,-1,0,0,0,0,1],
 							"fov": 50,
+							"zoom": 1,
+							"near": 0.1,
+							"far": 100,
+							"focus": 10,
 							"aspect": 1,
-							"near": 100,
-							"far": 10000,
-							"matrix": [-1,0,-1.2246468525851679e-16,0,0,1,0,0,1.2246468525851679e-16,0,-1,0,0,0,0,1]
+							"filmGauge": 35,
+							"filmOffset": 0
 						}]
 				},
 				{
 					"uuid": "A460C230-DC88-4A8F-A3FB-AA0FE735F3ED",
 					"type": "Mesh",
 					"name": "Plane",
-					"geometry": "51BB3E54-D2DF-4576-9953-FB8E940588B5",
-					"material": "4AE8130E-B6A8-47BC-ACCF-060973C74044",
-					"matrix": [1,0,0,0,0,0.040785226970911026,-0.9991679191589355,0,0,0.9991679191589355,0.040785226970911026,0,0,-50,0,1]
+					"layers": 1,
+					"matrix": [1,0,0,0,0,0.040785,-0.999168,0,0,0.999168,0.040785,0,0,-0.5,0,1],
+					"geometry": "6D90C4BE-EBA6-4E21-8F54-7CFDAA61F30B",
+					"material": "4AE8130E-B6A8-47BC-ACCF-060973C74044"
 				},
 				{
 					"uuid": "26DAAD69-725D-43B7-AF9D-990A99DEF8C5",
 					"type": "Mesh",
 					"name": "Box",
-					"geometry": "D8E200D3-27BC-49F8-A5C5-7384206E70FE",
-					"material": "B5943856-E404-45D9-A427-4774202C2CD0",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
+					"geometry": "D3008B2A-ACDD-43CC-87F7-4F942607D21A",
+					"material": "B5943856-E404-45D9-A427-4774202C2CD0"
 				},
 				{
 					"uuid": "AAAFF2D6-4725-4AFC-A9FE-26419B11011F",
 					"type": "Mesh",
 					"name": "Cylinder",
-					"geometry": "25BA32DB-8B02-4ABA-A77C-69868C464A1A",
-					"material": "3F872310-2067-4BE4-9250-5B3F4E43797E",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-130,-15,0,1]
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-1.3,-0.15,0,1],
+					"geometry": "F482ACD4-013A-49CF-AE0F-C9FF4ADAE409",
+					"material": "3F872310-2067-4BE4-9250-5B3F4E43797E"
 				},
 				{
 					"uuid": "B855E267-A266-4098-ACD6-6A1FDE7B88BA",
 					"type": "Mesh",
 					"name": "Icosahedron",
-					"geometry": "4DECFAB5-6FD1-4D84-9A29-565807B074EA",
-					"material": "E1826901-7922-4584-A25D-6D487E2C9BBD",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,130,-10,0,1]
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,1.3,-0.1,0,1],
+					"geometry": "51CDDCED-BC71-4B1B-A485-725B6A48204B",
+					"material": "E1826901-7922-4584-A25D-6D487E2C9BBD"
 				},
 				{
 					"uuid": "E2939A7B-5E40-438A-8C1B-32126FBC6892",
 					"type": "PointLight",
 					"name": "PointLight 1",
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-0.939,1.271,-1.143,1],
 					"color": 9474221,
 					"intensity": 0.75,
 					"distance": 0,
 					"decay": 1,
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-93.86000061035156,127.12999725341797,-114.30000305175781,1]
+					"shadow": {
+						"camera": {
+							"uuid": "EFF42F46-1E27-4B36-B9D9-CF7D879D258E",
+							"type": "PerspectiveCamera",
+							"layers": 1,
+							"fov": 90,
+							"zoom": 1,
+							"near": 0.5,
+							"far": 500,
+							"focus": 10,
+							"aspect": 1,
+							"filmGauge": 35,
+							"filmOffset": 0
+						}
+					}
 				},
 				{
 					"uuid": "3412781E-27CC-43C3-A5DB-54C0C8E42ED6",
 					"type": "PointLight",
 					"name": "PointLight 2",
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0.881,0.083,1.254,1],
 					"color": 12773063,
 					"intensity": 1,
 					"distance": 0,
 					"decay": 1,
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,88.12999725341797,8.3100004196167,125.44999694824219,1]
-				}]
+					"shadow": {
+						"camera": {
+							"uuid": "81E800FE-E8A7-4A9E-AFAA-4F04FD56AFE4",
+							"type": "PerspectiveCamera",
+							"layers": 1,
+							"fov": 90,
+							"zoom": 1,
+							"near": 0.5,
+							"far": 500,
+							"focus": 10,
+							"aspect": 1,
+							"filmGauge": 35,
+							"filmOffset": 0
+						}
+					}
+				}],
+			"background": 11184810
 		}
 	},
 	"scripts": {
@@ -183,7 +246,7 @@
 		"B7CBBC6F-EC26-49B5-8D0D-67D9C535924B": [
 			{
 				"name": "Orbit",
-				"source": "function update( event ) {\n\n\tvar time = event.time * 0.001;\n\n\tthis.position.x = Math.sin( time ) * 400;\n\tthis.position.z = Math.cos( time ) * 400;\n\tthis.lookAt( scene.position );\n\n}"
+				"source": "function update( event ) {\n\n\tvar time = event.time * 0.001;\n\n\tthis.position.x = Math.sin( time ) * 4;\n\tthis.position.z = Math.cos( time ) * 4;\n\tthis.lookAt( scene.position );\n\n}"
 			}]
 	}
 }

+ 53 - 17
editor/examples/particles.app.json

@@ -3,42 +3,45 @@
 		"type": "App"
 	},
 	"project": {
+		"gammaInput": true,
+		"gammaOutput": true,
 		"shadows": true,
 		"vr": false
 	},
 	"camera": {
 		"metadata": {
-			"version": 4.4,
+			"version": 4.5,
 			"type": "Object",
 			"generator": "Object3D.toJSON"
 		},
 		"object": {
-			"uuid": "763F3000-7D7C-4BE6-80B6-914DEEBD9AA2",
+			"uuid": "056199EB-6985-481B-97CC-A57FB7C87809",
 			"type": "PerspectiveCamera",
 			"name": "Camera",
-			"matrix": [0.7071067690849304,-3.398992198810902e-11,-0.7071068286895752,0,-0.2357022613286972,0.9428090453147888,-0.235702246427536,0,0.6666666865348816,0.3333333134651184,0.6666666269302368,0,41.824005126953125,20.912002563476562,41.824005126953125,1],
+			"layers": 1,
+			"matrix": [0.707107,0,-0.707107,0,-0.235702,0.942809,-0.235702,0,0.666667,0.333333,0.666667,0,4.182,2.091,4.182,1],
 			"fov": 50,
 			"zoom": 1,
 			"near": 0.1,
 			"far": 100000,
 			"focus": 10,
-			"aspect": 0.46657381615598886,
+			"aspect": 0.666193,
 			"filmGauge": 35,
 			"filmOffset": 0
 		}
 	},
 	"scene": {
 		"metadata": {
-			"version": 4.4,
+			"version": 4.5,
 			"type": "Object",
 			"generator": "Object3D.toJSON"
 		},
 		"geometries": [
 			{
-				"uuid": "E80D9EC5-D722-4812-8226-5F355EAC9B96",
+				"uuid": "C3C0CE7D-10B8-43FC-8F74-011CC6E57800",
 				"type": "PlaneGeometry",
-				"width": 1000,
-				"height": 1000,
+				"width": 100,
+				"height": 100,
 				"widthSegments": 1,
 				"heightSegments": 1
 			}],
@@ -49,51 +52,84 @@
 				"color": 5465019,
 				"roughness": 1,
 				"metalness": 0,
-				"emissive": 0
+				"emissive": 0,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			},
 			{
 				"uuid": "F5361474-F5F1-412F-8D99-3699B868092D",
 				"type": "SpriteMaterial",
-				"color": 16777215
+				"color": 16777215,
+				"transparent": true,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			}],
 		"object": {
 			"uuid": "3741222A-BD8F-401C-A5D2-5A907E891896",
 			"type": "Scene",
 			"name": "Scene",
+			"layers": 1,
 			"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
 			"children": [
 				{
 					"uuid": "05B57416-1BE5-4A96-BB05-9D9CD112D52B",
 					"type": "Mesh",
 					"name": "Ground",
-					"matrix": [1,0,0,0,0,0.0007959486683830619,-0.9999997019767761,0,0,0.9999997019767761,0.0007959486683830619,0,0,-0.5,0,1],
-					"geometry": "E80D9EC5-D722-4812-8226-5F355EAC9B96",
+					"layers": 1,
+					"matrix": [1,0,0,0,0,0.000796,-1,0,0,1,0.000796,0,0,-0.5,0,1],
+					"geometry": "C3C0CE7D-10B8-43FC-8F74-011CC6E57800",
 					"material": "3A9449D2-62DB-4BB4-ABBD-6F3F9D46DE1A"
 				},
 				{
 					"uuid": "0A3CB873-07E6-4EEB-830B-68192504111B",
 					"type": "Sprite",
 					"name": "Particle",
-					"matrix": [0.4000000059604645,0,0,0,0,0.4000000059604645,0,0,0,0,0.4000000059604645,0,0,0,0,1],
+					"layers": 1,
+					"matrix": [0.04,0,0,0,0,0.04,0,0,0,0,0.04,0,0,0,0,1],
 					"material": "F5361474-F5F1-412F-8D99-3699B868092D"
 				},
 				{
 					"uuid": "40E5CDA4-0E39-4265-9293-3E9EC3207F61",
 					"type": "PointLight",
 					"name": "PointLight",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,11.828879356384277,0,1],
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,1.183,0,1],
 					"color": 16777215,
 					"intensity": 1,
 					"distance": 0,
-					"decay": 1
-				}]
+					"decay": 1,
+					"shadow": {
+						"camera": {
+							"uuid": "B6D3493E-E5C9-4D65-9E26-BB788D127BE1",
+							"type": "PerspectiveCamera",
+							"layers": 1,
+							"fov": 90,
+							"zoom": 1,
+							"near": 0.5,
+							"far": 500,
+							"focus": 10,
+							"aspect": 1,
+							"filmGauge": 35,
+							"filmOffset": 0
+						}
+					}
+				}],
+			"background": 2171689,
+			"fog": {
+				"type": "Fog",
+				"color": 2171688,
+				"near": 1,
+				"far": 50
+			}
 		}
 	},
 	"scripts": {
 		"3741222A-BD8F-401C-A5D2-5A907E891896": [
 			{
 				"name": "Fountain",
-				"source": "var original = this.getObjectByName( 'Particle' );\n\nvar particles = [];\n\nfor ( var i = 0; i < 100; i ++ ) {\n\n\tvar particle = original.clone();\n\tparticle.userData.velocity = new THREE.Vector3();\n\tthis.add( particle );\n\n\tparticles.push( particle );\n\n}\n\nfunction update( event ) {\n\t\n\tvar particle = particles.shift();\n\tparticles.push( particle );\n\t\t\n\tvar velocity = particle.userData.velocity;\n\tvelocity.x = Math.random() - 0.5;\n\tvelocity.y = Math.random() + 1;\n\tvelocity.z = Math.random() - 0.5;\n\n\tfor ( var i = 0; i < particles.length; i ++ ) {\n\n\t\tvar particle = particles[ i ];\n\n\t\tvar velocity = particle.userData.velocity;\n\n\t\tvelocity.y -= 0.098;\n\n\t\tparticle.position.add( velocity );\n\n\t\tif ( particle.position.y < 0 ) {\n\n\t\t\tparticle.position.y = 0;\n\n\t\t\tvelocity.y = - velocity.y;\n\t\t\tvelocity.multiplyScalar( 0.6 );\n\n\t\t}\n\n\t}\n\n}"
+				"source": "var original = this.getObjectByName( 'Particle' );\n\nvar particles = [];\n\nfor ( var i = 0; i < 100; i ++ ) {\n\n\tvar particle = original.clone();\n\tparticle.userData.velocity = new THREE.Vector3();\n\tthis.add( particle );\n\n\tparticles.push( particle );\n\n}\n\nfunction update( event ) {\n\t\n\tvar particle = particles.shift();\n\tparticles.push( particle );\n\t\t\n\tvar velocity = particle.userData.velocity;\n\tvelocity.x = Math.random() * 0.1 - 0.05;\n\tvelocity.y = Math.random() * 0.1 + 0.1;\n\tvelocity.z = Math.random() * 0.1 - 0.05;\n\n\tfor ( var i = 0; i < particles.length; i ++ ) {\n\n\t\tvar particle = particles[ i ];\n\n\t\tvar velocity = particle.userData.velocity;\n\n\t\tvelocity.y -= 0.0098;\n\n\t\tparticle.position.add( velocity );\n\n\t\tif ( particle.position.y < 0 ) {\n\n\t\t\tparticle.position.y = 0;\n\n\t\t\tvelocity.y = - velocity.y;\n\t\t\tvelocity.multiplyScalar( 0.6 );\n\n\t\t}\n\n\t}\n\n}"
 			}]
 	}
 }

+ 74 - 39
editor/examples/pong.app.json

@@ -3,69 +3,74 @@
 		"type": "App"
 	},
 	"project": {
-		"shadows": false,
+		"gammaInput": true,
+		"gammaOutput": true,
+		"shadows": true,
 		"vr": false
 	},
 	"camera": {
 		"metadata": {
-			"version": 4.4,
+			"version": 4.5,
 			"type": "Object",
 			"generator": "Object3D.toJSON"
 		},
 		"object": {
-			"uuid": "B901700E-2B1B-4D74-9201-164193F8304E",
+			"uuid": "4AC7ADED-CC22-4B16-8218-2E0A0C38C8F8",
 			"type": "PerspectiveCamera",
 			"name": "Camera",
-			"matrix": [0.9522120356559753,4.608077919243669e-9,-0.3054378032684326,0,-0.17742955684661865,0.8139732480049133,-0.553142249584198,0,0.24861818552017212,0.5809023976325989,0.7750750780105591,0,18.645999908447266,43.56800079345703,58.13100051879883,1],
-			"focalLength": 10,
-			"zoom": 1,
+			"layers": 1,
+			"matrix": [0.952212,0,-0.305438,0,-0.17743,0.813973,-0.553142,0,0.248618,0.580902,0.775075,0,1.865,4.357,5.813,1],
 			"fov": 50,
-			"aspect": 1.3217270194986073,
+			"zoom": 1,
 			"near": 0.1,
-			"far": 100000
+			"far": 100000,
+			"focus": 10,
+			"aspect": 1.428977,
+			"filmGauge": 35,
+			"filmOffset": 0
 		}
 	},
 	"scene": {
 		"metadata": {
-			"version": 4.4,
+			"version": 4.5,
 			"type": "Object",
 			"generator": "Object3D.toJSON"
 		},
 		"geometries": [
 			{
-				"uuid": "713F75F5-5D04-4069-89CB-2035F5619AC3",
+				"uuid": "490CEBA3-6A25-4BE1-B517-C5FB11A5D18A",
 				"type": "PlaneGeometry",
-				"width": 60,
-				"height": 40,
+				"width": 6,
+				"height": 4,
 				"widthSegments": 1,
 				"heightSegments": 1
 			},
 			{
-				"uuid": "4537EA66-3CD6-43A1-97A9-EB59F3258BF9",
+				"uuid": "D9A92F2D-2F08-4851-99C7-12D8D1CA13C7",
 				"type": "BoxGeometry",
-				"width": 1,
-				"height": 1,
-				"depth": 1,
+				"width": 0.1,
+				"height": 0.1,
+				"depth": 0.1,
 				"widthSegments": 1,
 				"heightSegments": 1,
 				"depthSegments": 1
 			},
 			{
-				"uuid": "3C546CA4-FF0F-4BA1-9406-0CD0D560A396",
+				"uuid": "5E63B8CF-E225-4ABC-994A-4D06BD4E21EB",
 				"type": "BoxGeometry",
-				"width": 2,
-				"height": 2,
-				"depth": 10,
+				"width": 0.2,
+				"height": 0.2,
+				"depth": 1,
 				"widthSegments": 1,
 				"heightSegments": 1,
 				"depthSegments": 1
 			},
 			{
-				"uuid": "4628F4A7-D572-45C2-9A67-807D71FF19EC",
+				"uuid": "D61532B4-24C3-4BC4-B56B-7245E8163E09",
 				"type": "BoxGeometry",
-				"width": 2,
-				"height": 2,
-				"depth": 10,
+				"width": 0.2,
+				"height": 0.2,
+				"depth": 1,
 				"widthSegments": 1,
 				"heightSegments": 1,
 				"depthSegments": 1
@@ -77,7 +82,10 @@
 				"color": 16777215,
 				"emissive": 0,
 				"specular": 16777215,
-				"shininess": 30
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			},
 			{
 				"uuid": "B1CAF098-FE36-45E1-BEBE-8D6AC04821CC",
@@ -85,7 +93,10 @@
 				"color": 16711680,
 				"emissive": 0,
 				"specular": 1118481,
-				"shininess": 30
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			},
 			{
 				"uuid": "FBDBE66D-B613-4741-802D-5AE1DE07DE46",
@@ -93,61 +104,85 @@
 				"color": 2752767,
 				"emissive": 0,
 				"specular": 1118481,
-				"shininess": 30
+				"shininess": 30,
+				"depthFunc": 3,
+				"depthTest": true,
+				"depthWrite": true
 			}],
 		"object": {
 			"uuid": "31517222-A9A7-4EAF-B5F6-60751C0BABA3",
 			"type": "Scene",
 			"name": "Scene",
+			"layers": 1,
 			"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
 			"children": [
 				{
 					"uuid": "B47D0BFC-D63A-4CBB-985E-9C4DBDF086E4",
 					"type": "Mesh",
 					"name": "Ground",
-					"matrix": [1,0,0,0,0,0.0007960238144733012,-0.9999997019767761,0,0,0.9999997019767761,0.0007960238144733012,0,0,-1,0,1],
-					"geometry": "713F75F5-5D04-4069-89CB-2035F5619AC3",
+					"layers": 1,
+					"matrix": [1,0,0,0,0,0.000796,-1,0,0,1,0.000796,0,0,-0.1,0,1],
+					"geometry": "490CEBA3-6A25-4BE1-B517-C5FB11A5D18A",
 					"material": "7EDF7C08-6325-418A-BBAB-89341C694730"
 				},
 				{
 					"uuid": "CE13E58A-4E8B-4F72-9E2E-7DE57C58F989",
 					"type": "Mesh",
 					"name": "Ball",
+					"layers": 1,
 					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
-					"geometry": "4537EA66-3CD6-43A1-97A9-EB59F3258BF9",
+					"geometry": "D9A92F2D-2F08-4851-99C7-12D8D1CA13C7",
 					"material": "B1CAF098-FE36-45E1-BEBE-8D6AC04821CC"
 				},
 				{
 					"uuid": "2AAEA3AA-EC45-492B-B450-10473D1EC6C5",
 					"type": "Mesh",
 					"name": "Pad 1",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-24,0,0,1],
-					"geometry": "3C546CA4-FF0F-4BA1-9406-0CD0D560A396",
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,-2.4,0,0,1],
+					"geometry": "5E63B8CF-E225-4ABC-994A-4D06BD4E21EB",
 					"material": "FBDBE66D-B613-4741-802D-5AE1DE07DE46"
 				},
 				{
 					"uuid": "F1DD46A7-6584-4A37-BC76-852C3911077E",
 					"type": "Mesh",
 					"name": "Pad 2",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,24,0,0,1],
-					"geometry": "4628F4A7-D572-45C2-9A67-807D71FF19EC",
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,2.4,0,0,1],
+					"geometry": "D61532B4-24C3-4BC4-B56B-7245E8163E09",
 					"material": "FBDBE66D-B613-4741-802D-5AE1DE07DE46"
 				},
 				{
 					"uuid": "C62AAE9F-9E51-46A5-BD2B-71BA804FC0B3",
 					"type": "DirectionalLight",
-					"name": "DirectionalLight 3",
-					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,10,20,15,1],
+					"name": "DirectionalLight",
+					"layers": 1,
+					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,1,2,1.5,1],
 					"color": 16777215,
-					"intensity": 1
-				}]
+					"intensity": 1,
+					"shadow": {
+						"camera": {
+							"uuid": "2CF1F42A-8992-4E8D-8D94-7CC20979344C",
+							"type": "OrthographicCamera",
+							"layers": 1,
+							"zoom": 1,
+							"left": -5,
+							"right": 5,
+							"top": 5,
+							"bottom": -5,
+							"near": 0.5,
+							"far": 500
+						}
+					}
+				}],
+			"background": 11184810
 		}
 	},
 	"scripts": {
 		"31517222-A9A7-4EAF-B5F6-60751C0BABA3": [
 			{
 				"name": "Game logic",
-				"source": "var ball = this.getObjectByName( 'Ball' );\n\nvar position = ball.position;\n\nvar velocity = new THREE.Vector3();\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = Math.random() - 0.5;\ndirection.normalize();\n\nvar pad1 = this.getObjectByName( 'Pad 1' );\nvar pad2 = this.getObjectByName( 'Pad 2' );\n\nvar raycaster = new THREE.Raycaster();\nvar objects = [ pad1, pad2 ];\n\n//\n\nfunction mousemove( event ) {\n\n\tpad1.position.z = ( event.clientX / player.width ) * 30 - 15;\n\tpad2.position.z = - pad1.position.z;\n\n}\n\nfunction update( event ) {\n\t\n\tif ( position.x < -30 || position.x > 30 ) direction.x = - direction.x;\n\tif ( position.z < -20 || position.z > 20 ) direction.z = - direction.z;\n\t\n\tposition.x = Math.max( - 30, Math.min( 30, position.x ) );\n\tposition.z = Math.max( - 20, Math.min( 20, position.z ) );\n\t\n\traycaster.set( position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( objects );\n\t\n\tif ( intersections.length > 0 ) {\n\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 1 ) {\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n\tposition.add( velocity.copy( direction ).multiplyScalar( event.delta / 20 ) );\n\n}"
+				"source": "var ball = this.getObjectByName( 'Ball' );\n\nvar position = ball.position;\n\nvar velocity = new THREE.Vector3();\n\nvar direction = new THREE.Vector3();\ndirection.x = Math.random() - 0.5;\ndirection.z = Math.random() - 0.5;\ndirection.normalize().multiplyScalar( 0.1 );\n\nvar pad1 = this.getObjectByName( 'Pad 1' );\nvar pad2 = this.getObjectByName( 'Pad 2' );\n\nvar raycaster = new THREE.Raycaster();\nvar objects = [ pad1, pad2 ];\n\n//\n\nfunction mousemove( event ) {\n\n\tpad1.position.z = ( event.clientX / player.width ) * 3 - 1.5;\n\tpad2.position.z = - pad1.position.z;\n\n}\n\nfunction update( event ) {\n\t\n\tif ( position.x < -3 || position.x > 3 ) direction.x = - direction.x;\n\tif ( position.z < -2 || position.z > 2 ) direction.z = - direction.z;\n\t\n\tposition.x = Math.max( - 3, Math.min( 3, position.x ) );\n\tposition.z = Math.max( - 2, Math.min( 2, position.z ) );\n\t\n\traycaster.set( position, direction );\n\t\n\tvar intersections = raycaster.intersectObjects( objects );\n\t\n\tif ( intersections.length > 0 ) {\n\n\t\tvar intersection = intersections[ 0 ];\n\t\t\n\t\tif ( intersection.distance < 0.1 ) {\n\t\t\t\n\t\t\tdirection.reflect( intersection.face.normal );\n\t\t\t\n\t\t}\n\t\t\n\t}\n\n\tposition.add( velocity.copy( direction ).multiplyScalar( event.delta / 20 ) );\n\n}"
 			}]
 	}
 }

+ 8 - 7
editor/examples/shaders.app.json

@@ -10,28 +10,29 @@
 	},
 	"camera": {
 		"metadata": {
-			"version": 4.4,
+			"version": 4.5,
 			"type": "Object",
 			"generator": "Object3D.toJSON"
 		},
 		"object": {
-			"uuid": "FC3E973B-5A4A-4177-BD9C-A58E61E0593B",
+			"uuid": "4AC7ADED-CC22-4B16-8218-2E0A0C38C8F8",
 			"type": "PerspectiveCamera",
 			"name": "Camera",
+			"layers": 1,
 			"matrix": [0.605503,0,-0.795843,0,-0.261526,0.944464,-0.198978,0,0.751645,0.328615,0.571876,0,2.571484,1.124239,1.956469,1],
 			"fov": 50,
 			"zoom": 1,
 			"near": 0.1,
 			"far": 10000,
 			"focus": 10,
-			"aspect": 1.368715,
+			"aspect": 1.428977,
 			"filmGauge": 35,
 			"filmOffset": 0
 		}
 	},
 	"scene": {
 		"metadata": {
-			"version": 4.4,
+			"version": 4.5,
 			"type": "Object",
 			"generator": "Object3D.toJSON"
 		},
@@ -50,11 +51,9 @@
 				"depthTest": true,
 				"depthWrite": true,
 				"wireframe": true,
-				"skinning": false,
-				"morphTargets": false,
 				"uniforms": {
 					"time": {
-						"value": 0.0
+						"value": 0
 					}
 				},
 				"vertexShader": "uniform float time;\nvarying vec3 vPosition;\nvoid main() {\n\tvPosition = position;\n\tvPosition.x += sin( time + vPosition.z * 4.0 ) / 4.0;\n\tvPosition.y += cos( time + vPosition.z * 4.0 ) / 4.0;\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( vPosition, 1.0 );\n}",
@@ -64,12 +63,14 @@
 			"uuid": "5FC9ACA9-2A93-474D-AA32-FACC76551914",
 			"type": "Scene",
 			"name": "Scene",
+			"layers": 1,
 			"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
 			"children": [
 				{
 					"uuid": "FC7B6CF2-6386-4F47-9CE6-8ADB9FCA6E1F",
 					"type": "Mesh",
 					"name": "Icosahedron 1",
+					"layers": 1,
 					"matrix": [1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],
 					"geometry": "EA781333-F3AE-470D-9110-A9724FCB42AA",
 					"material": "50ED51F1-DEA4-4B61-8082-BF41609E8C27"

+ 9 - 9
editor/index.html

@@ -4,12 +4,12 @@
 		<title>three.js / editor</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<!-- Origin Trial Token, feature = WebVR (For Chrome M62+), origin = https://threejs.org, expires = 2018-07-25 -->
-		<meta http-equiv="origin-trial" data-feature="WebVR (For Chrome M62+)" data-expires="2018-07-25" content="AtW06hJFoVWUJTZf5gqymMIlrR60JJi5MsSe44qsHjrCmzDUNmvaTtAVg+K9O9jFpjJtn/W9jvG//hHHaq5HcQoAAABQeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUjEuMU02MiIsImV4cGlyeSI6MTUzMjUyNjI5OH0=">
-		<!-- Origin Trial Token, feature = WebXR Device API, origin = https://threejs.org, expires = 2018-07-21 -->
-		<meta http-equiv="origin-trial" data-feature="WebXR Device API" data-expires="2018-07-21" content="Anlf1R/bCOUxOEgGI/9TWuzHHNxBMfZSTUMDCN7cLwDj2gpLwgA1K0DPwOzO/O0Jwaur5bsHo7k9KXx+6g+82wIAAABQeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZSIsImV4cGlyeSI6MTUzMjE2NjIyNX0=">
-		<!-- Origin Trial Token, feature = WebXR Gamepad Support, origin = https://threejs.org, expires = 2018-07-21 -->
-		<meta http-equiv="origin-trial" data-feature="WebXR Gamepad Support" data-expires="2018-07-21" content="ArDsXbwATKHPmvQiPlEIWNCt4DlEjB7bLj9vOgoNmL8r38U+wQNYZyUvjQIqqzgACciUUuAnxluTIL7nNkI89gcAAABYeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkdhbWVwYWRTdXBwb3J0IiwiZXhwaXJ5IjoxNTMyMTY2MjI1fQ==">
+		<!-- Origin Trial Token, feature = WebVR (For Chrome M62+), origin = https://threejs.org, expires = 2018-08-30 -->
+		<meta http-equiv="origin-trial" data-feature="WebVR (For Chrome M62+)" data-expires="2018-08-30" content="Ag80lPFLAvRyqP2W5I5XBzACxrTAQTWa3cXebXzq+WzW66nlQa6lvejGg1gdAMrzYbY6jUWp8g08kEnzb6svVgcAAABQeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUjEuMU02MiIsImV4cGlyeSI6MTUzNTYzNjYxOX0=">
+		<!-- Origin Trial Token, feature = WebXR Device API, origin = https://threejs.org, expires = 2018-08-28 -->
+		<meta http-equiv="origin-trial" data-feature="WebXR Device API" data-expires="2018-08-28" content="Ag7nJS0Q6nBKfmRY1XLKHslnz73amLhaf8RoFpYz36MpMq0oa30AETLXer74BIwa3t8uDXlR0n4W9f/o674Rqw4AAABQeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZSIsImV4cGlyeSI6MTUzNTQxNDQwMH0=">
+		<!-- Origin Trial Token, feature = WebXR Gamepad Support, origin = https://threejs.org, expires = 2018-08-28 -->
+		<meta http-equiv="origin-trial" data-feature="WebXR Gamepad Support" data-expires="2018-08-28" content="AsflqqNG2L/Eepy8xSwCYwWH5U7w3nN7Ak137jGxMeBFz9lqQVcMBqMTcMw6ZkxThB7ZM2Cn7hgPqX++ZlgC9wMAAABYeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkdhbWVwYWRTdXBwb3J0IiwiZXhwaXJ5IjoxNTM1NDE0NDAwfQ==">
 	</head>
 	<body ontouchstart="">
 		<link href="css/main.css" rel="stylesheet" />
@@ -181,15 +181,15 @@
 			var viewport = new Viewport( editor );
 			document.body.appendChild( viewport.dom );
 
+			var toolbar = new Toolbar( editor );
+			document.body.appendChild( toolbar.dom );
+
 			var script = new Script( editor );
 			document.body.appendChild( script.dom );
 
 			var player = new Player( editor );
 			document.body.appendChild( player.dom );
 
-			var toolbar = new Toolbar( editor );
-			document.body.appendChild( toolbar.dom );
-
 			var menubar = new Menubar( editor );
 			document.body.appendChild( menubar.dom );
 

+ 9 - 3
editor/js/Toolbar.js

@@ -8,6 +8,7 @@ var Toolbar = function ( editor ) {
 
 	var container = new UI.Panel();
 	container.setId( 'toolbar' );
+	container.setDisplay( 'none' );
 
 	var buttons = new UI.Panel();
 	container.add( buttons );
@@ -15,7 +16,6 @@ var Toolbar = function ( editor ) {
 	// translate / rotate / scale
 
 	var translate = new UI.Button( 'translate' );
-	translate.dom.title = 'W';
 	translate.dom.className = 'Button selected';
 	translate.onClick( function () {
 
@@ -25,7 +25,6 @@ var Toolbar = function ( editor ) {
 	buttons.add( translate );
 
 	var rotate = new UI.Button( 'rotate' );
-	rotate.dom.title = 'E';
 	rotate.onClick( function () {
 
 		signals.transformModeChanged.dispatch( 'rotate' );
@@ -34,7 +33,6 @@ var Toolbar = function ( editor ) {
 	buttons.add( rotate );
 
 	var scale = new UI.Button( 'scale' );
-	scale.dom.title = 'R';
 	scale.onClick( function () {
 
 		signals.transformModeChanged.dispatch( 'scale' );
@@ -50,6 +48,14 @@ var Toolbar = function ( editor ) {
 	} );
 	buttons.add( local );
 
+	//
+
+	signals.objectSelected.add( function ( object ) {
+
+		container.setDisplay( object === null ? 'none' : '' );
+
+	} );
+
 	signals.transformModeChanged.add( function ( mode ) {
 
 		translate.dom.classList.remove( 'selected' );

+ 4 - 2
editor/js/libs/app.js

@@ -155,9 +155,11 @@ var APP = {
 
 		}
 
-		var prevTime;
+		var time, prevTime;
 
-		function animate( time ) {
+		function animate() {
+
+			time = performance.now();
 
 			try {
 

+ 1 - 1
examples/canvas_ascii_effect.html

@@ -72,7 +72,7 @@
 				light.position.set( - 500, - 500, - 500 );
 				scene.add( light );
 
-				sphere = new THREE.Mesh( new THREE.SphereGeometry( 200, 20, 10 ), new THREE.MeshLambertMaterial() );
+				sphere = new THREE.Mesh( new THREE.SphereBufferGeometry( 200, 20, 10 ), new THREE.MeshLambertMaterial() );
 				scene.add( sphere );
 
 				// Plane

+ 1 - 1
examples/canvas_camera_orthographic.html

@@ -58,7 +58,7 @@
 
 				// Cubes
 
-				var geometry = new THREE.BoxGeometry( 50, 50, 50 );
+				var geometry = new THREE.BoxBufferGeometry( 50, 50, 50 );
 				var material = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw: 0.5 } );
 
 				for ( var i = 0; i < 100; i ++ ) {

+ 1 - 1
examples/canvas_geometry_earth.html

@@ -72,7 +72,7 @@
 				var loader = new THREE.TextureLoader();
 				loader.load( 'textures/land_ocean_ice_cloud_2048.jpg', function ( texture ) {
 
-					var geometry = new THREE.SphereGeometry( 200, 20, 20 );
+					var geometry = new THREE.SphereBufferGeometry( 200, 20, 20 );
 
 					var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
 					var mesh = new THREE.Mesh( geometry, material );

+ 1 - 1
examples/canvas_geometry_hierarchy.html

@@ -52,7 +52,7 @@
 				scene = new THREE.Scene();
 				scene.background = new THREE.Color( 0xffffff );
 
-				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
+				var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
 				var material = new THREE.MeshNormalMaterial( { overdraw: 0.5 } );
 
 				group = new THREE.Group();

+ 1 - 1
examples/canvas_geometry_panorama.html

@@ -81,7 +81,7 @@
 
 				];
 
-				var geometry = new THREE.BoxGeometry( 300, 300, 300, 7, 7, 7 );
+				var geometry = new THREE.BoxBufferGeometry( 300, 300, 300, 7, 7, 7 );
 				geometry.scale( - 1, 1, 1 );
 
 				mesh = new THREE.Mesh( geometry, materials );

+ 7 - 5
examples/canvas_geometry_panorama_fisheye.html

@@ -81,18 +81,20 @@
 
 				];
 
-				var geometry = new THREE.BoxGeometry( 300, 300, 300, 7, 7, 7 );
+				var geometry = new THREE.BoxBufferGeometry( 300, 300, 300, 7, 7, 7 );
 				geometry.scale( - 1, 1, 1 );
 
 				mesh = new THREE.Mesh( geometry, materials );
 				scene.add( mesh );
 
-				for ( var i = 0, l = mesh.geometry.vertices.length; i < l; i ++ ) {
+				var vec = new THREE.Vector3();
+				var positions = mesh.geometry.attributes.position;
 
-					var vertex = mesh.geometry.vertices[ i ];
+				for ( var i = 0, l = positions.count; i < l; i ++ ) {
 
-					vertex.normalize();
-					vertex.multiplyScalar( 550 );
+					vec.fromBufferAttribute( positions, i );
+					vec.setLength( 550 );
+					positions.setXYZ( i, vec.x, vec.y, vec.z );
 
 				}
 

+ 1 - 1
examples/canvas_geometry_shapes.html

@@ -71,7 +71,7 @@
 
 					// flat shape
 
-					var geometry = new THREE.ShapeGeometry( shape );
+					var geometry = new THREE.ShapeBufferGeometry( shape );
 					var material = new THREE.MeshBasicMaterial( { color: color, overdraw: 0.5 } );
 
 					var mesh = new THREE.Mesh( geometry, material );

+ 11 - 10
examples/canvas_geometry_terrain.html

@@ -71,17 +71,19 @@
 
 				var data = generateHeight( 1024, 1024 );
 				var texture = new THREE.CanvasTexture( generateTexture( data, 1024, 1024 ) );
-				var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
+				var material = new THREE.MeshBasicMaterial( { map: texture, side: THREE.DoubleSide, overdraw: 0.5 } );
 
 				var quality = 16, step = 1024 / quality;
 
-				var geometry = new THREE.PlaneGeometry( 2000, 2000, quality - 1, quality - 1 );
+				var geometry = new THREE.PlaneBufferGeometry( 2000, 2000, quality - 1, quality - 1 );
 				geometry.rotateX( - Math.PI / 2 );
 
-				for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
+				var positions = geometry.attributes.position;
+
+				for ( var i = 0, l = positions.count; i < l; i ++ ) {
 
 					var x = i % quality, y = Math.floor( i / quality );
-					geometry.vertices[ i ].y = data[ ( x * step ) + ( y * step ) * 1024 ] * 2 - 128;
+					positions.setY( i, data[ ( x * step ) + ( y * step ) * 1024 ] * 2 - 128 );
 
 				}
 
@@ -122,7 +124,7 @@
 			function generateHeight( width, height ) {
 
 				var data = new Uint8Array( width * height ), perlin = new ImprovedNoise(),
-				size = width * height, quality = 2, z = Math.random() * 100;
+					size = width * height, quality = 2, z = Math.random() * 100;
 
 				for ( var j = 0; j < 4; j ++ ) {
 
@@ -130,7 +132,7 @@
 
 					for ( var i = 0; i < size; i ++ ) {
 
-						var x = i % width, y = ~~ ( i / width );
+						var x = i % width, y = ~ ~ ( i / width );
 						data[ i ] += Math.abs( perlin.noise( x / quality, y / quality, z ) * 0.5 ) * quality + 10;
 
 					}
@@ -144,7 +146,7 @@
 			function generateTexture( data, width, height ) {
 
 				var canvas, context, image, imageData,
-				level, diff, vector3, sun, shade;
+					level, diff, vector3, sun, shade;
 
 				vector3 = new THREE.Vector3( 0, 0, 0 );
 
@@ -162,7 +164,7 @@
 				image = context.getImageData( 0, 0, width, height );
 				imageData = image.data;
 
-				for ( var i = 0, j = 0, l = imageData.length; i < l; i += 4, j ++  ) {
+				for ( var i = 0, j = 0, l = imageData.length; i < l; i += 4, j ++ ) {
 
 					vector3.x = data[ j - 1 ] - data[ j + 1 ];
 					vector3.y = 2;
@@ -183,7 +185,7 @@
 
 			}
 
-			function onDocumentMouseMove(event) {
+			function onDocumentMouseMove( event ) {
 
 				mouseX = event.clientX - windowHalfX;
 				mouseY = event.clientY - windowHalfY;
@@ -211,7 +213,6 @@
 
 			}
 
-
 		</script>
 
 	</body>

+ 1 - 1
examples/canvas_geometry_text.html

@@ -80,7 +80,7 @@
 
 				}
 
-				var geometry = new THREE.TextGeometry( theText, {
+				var geometry = new THREE.TextBufferGeometry( theText, {
 
 					font: font,
 					size: 80,

+ 1 - 1
examples/canvas_interactive_cubes.html

@@ -55,7 +55,7 @@
 				scene = new THREE.Scene();
 				scene.background = new THREE.Color( 0xf0f0f0 );
 
-				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
+				var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
 
 				for ( var i = 0; i < 10; i ++ ) {
 

+ 1 - 1
examples/canvas_interactive_cubes_tween.html

@@ -54,7 +54,7 @@
 				scene = new THREE.Scene();
 				scene.background = new THREE.Color( 0xf0f0f0 );
 
-				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
+				var geometry = new THREE.BoxBufferGeometry( 100, 100, 100 );
 
 				for ( var i = 0; i < 20; i ++ ) {
 

+ 1 - 1
examples/canvas_interactive_voxelpainter.html

@@ -28,7 +28,7 @@
 
 			var mouse, raycaster, isShiftDown = false;
 
-			var cubeGeometry = new THREE.BoxGeometry( 50, 50, 50 );
+			var cubeGeometry = new THREE.BoxBufferGeometry( 50, 50, 50 );
 			var cubeMaterial = new THREE.MeshLambertMaterial( { color: 0x00ff80, overdraw: 0.5 } );
 
 			var objects = [];

+ 42 - 21
examples/canvas_lines_colors.html

@@ -49,14 +49,11 @@
 		<script src="js/renderers/Projector.js"></script>
 		<script src="js/renderers/CanvasRenderer.js"></script>
 
-		<script src="js/Detector.js"></script>
 		<script src="js/geometries/hilbert3D.js"></script>
 		<script src="js/geometries/hilbert2D.js"></script>
 
 		<script>
 
-			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
-
 			var mouseX = 0, mouseY = 0;
 
 			var windowHalfX = window.innerWidth / 2;
@@ -81,37 +78,61 @@
 
 				// 2d lines
 
-				var geometry2 = new THREE.Geometry(),
-					points = hilbert2D( new THREE.Vector3( 0, 0, 0 ), 400, 4 ),
-					colors2 = [];
+				var vertices = hilbert2D( new THREE.Vector3( 0, 0, 0 ), 400, 4 );
+				var numVertices = vertices.length;
 
-				for ( var i = 0; i < points.length; i ++ ) {
+				var geometry2 = new THREE.BufferGeometry();
 
-					geometry2.vertices.push( points[ i ] );
+				var positions = new Float32Array( numVertices * 3 );
+				var colors = new Float32Array( numVertices * 3 );
 
-					colors2[ i ] = new THREE.Color( 0xffffff );
-					colors2[ i ].setHSL( i / points.length, 1, 0.5 );
+				geometry2.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				geometry2.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
 
-				}
+				var color = new THREE.Color();
+
+				for ( var i = 0, index = 0, l = numVertices; i < l; i ++, index += 3 ) {
+
+					positions[ index ] = vertices[ i ].x;
+					positions[ index + 1 ] = vertices[ i ].y;
+					positions[ index + 2 ] = vertices[ i ].z;
 
-				geometry2.colors = colors2;
+					color.setHSL( i / l, 1.0, 0.5 );
+
+					colors[ index ] = color.r;
+					colors[ index + 1 ] = color.g;
+					colors[ index + 2 ] = color.b;
+
+				}
 
 				// 3d lines
 
-				var geometry3 = new THREE.Geometry(),
-					points = hilbert3D( new THREE.Vector3( 0, 0, 0 ), 200, 2, 0, 1, 2, 3, 4, 5, 6, 7 ),
-					colors3 = [];
+				var vertices = hilbert3D( new THREE.Vector3( 0, 0, 0 ), 200, 2, 0, 1, 2, 3, 4, 5, 6, 7 );
+				var numVertices = vertices.length;
 
-				for ( var i = 0; i < points.length; i ++ ) {
+				var geometry3 = new THREE.BufferGeometry();
 
-					geometry3.vertices.push( points[ i ] );
+				var positions = new Float32Array( numVertices * 3 );
+				var colors = new Float32Array( numVertices * 3 );
 
-					colors3[ i ] = new THREE.Color( 0xffffff );
-					colors3[ i ].setHSL( i / points.length, 1, 0.5 );
+				geometry3.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				geometry3.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
 
-				}
+				var color = new THREE.Color();
+
+				for ( var i = 0, index = 0, l = numVertices; i < l; i ++, index += 3 ) {
+
+					positions[ index ] = vertices[ i ].x;
+					positions[ index + 1 ] = vertices[ i ].y;
+					positions[ index + 2 ] = vertices[ i ].z;
 
-				geometry3.colors = colors3;
+					color.setHSL( i / l, 1.0, 0.5 );
+
+					colors[ index ] = color.r;
+					colors[ index + 1 ] = color.g;
+					colors[ index + 2 ] = color.b;
+
+				}
 
 				// lines
 

+ 25 - 58
examples/canvas_lines_dashed.html

@@ -38,17 +38,13 @@
 
 		<script src="js/geometries/hilbert3D.js"></script>
 
-		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 		<script>
 
-			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
-
 			var renderer, scene, camera, stats;
 			var objects = [];
 
-
 			var WIDTH = window.innerWidth, HEIGHT = window.innerHeight;
 
 			init();
@@ -62,23 +58,43 @@
 				scene = new THREE.Scene();
 				scene.background = new THREE.Color( 0x111111 );
 
-				var subdivisions = 6;
+				var subdivisions = 3;
 				var recursion = 1;
 
 				var points = hilbert3D( new THREE.Vector3( 0,0,0 ), 25.0, recursion, 0, 1, 2, 3, 4, 5, 6, 7 );
 				var spline = new THREE.CatmullRomCurve3( points );
 
 				var samples = spline.getPoints( points.length * subdivisions );
-				var geometrySpline = new THREE.Geometry().setFromPoints( samples );
+				var numSamples = samples.length;
+
+				var geometrySpline = new THREE.BufferGeometry();
+
+				var positions = new Float32Array( numSamples * 3 );
+
+				geometrySpline.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+
+				for ( var i = 0, index = 0, l = numSamples; i < l; i ++, index += 3 ) {
+
+					positions[ index ] = samples[ i ].x;
+					positions[ index + 1 ] = samples[ i ].y;
+					positions[ index + 2 ] = samples[ i ].z;
 
-				var geometryCube = cube( 50 );
+				}
+
+				var geometryCube = new THREE.EdgesGeometry( new THREE.BoxBufferGeometry( 50, 50, 50 ) );
 
-				var object = new THREE.Line( geometrySpline, new THREE.LineDashedMaterial( { color: 0xffffff, dashSize: 1, gapSize: 0.5 } ) );
+				var object = new THREE.Line(
+					geometrySpline,
+					new THREE.LineDashedMaterial( { color: 0xffffff, dashSize: 10, gapSize: 10, linewidth: 3 } )
+				);
 
 				objects.push( object );
 				scene.add( object );
 
-				var object = new THREE.LineSegments( geometryCube, new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 30, gapSize: 10, linewidth: 2 } ) );
+				var object = new THREE.LineSegments(
+					geometryCube,
+					new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 30, gapSize: 10, linewidth: 3 } )
+				);
 
 				objects.push( object );
 				scene.add( object );
@@ -99,55 +115,6 @@
 
 			}
 
-			function cube( size ) {
-
-				var h = size * 0.5;
-
-				var geometry = new THREE.Geometry();
-
-				geometry.vertices.push(
-					new THREE.Vector3( -h, -h, -h ),
-					new THREE.Vector3( -h, h, -h ),
-
-					new THREE.Vector3( -h, h, -h ),
-					new THREE.Vector3( h, h, -h ),
-
-					new THREE.Vector3( h, h, -h ),
-					new THREE.Vector3( h, -h, -h ),
-
-					new THREE.Vector3( h, -h, -h ),
-					new THREE.Vector3( -h, -h, -h ),
-
-
-					new THREE.Vector3( -h, -h, h ),
-					new THREE.Vector3( -h, h, h ),
-
-					new THREE.Vector3( -h, h, h ),
-					new THREE.Vector3( h, h, h ),
-
-					new THREE.Vector3( h, h, h ),
-					new THREE.Vector3( h, -h, h ),
-
-					new THREE.Vector3( h, -h, h ),
-					new THREE.Vector3( -h, -h, h ),
-
-					new THREE.Vector3( -h, -h, -h ),
-					new THREE.Vector3( -h, -h, h ),
-
-					new THREE.Vector3( -h, h, -h ),
-					new THREE.Vector3( -h, h, h ),
-
-					new THREE.Vector3( h, h, -h ),
-					new THREE.Vector3( h, h, h ),
-
-					new THREE.Vector3( h, -h, -h ),
-					new THREE.Vector3( h, -h, h )
-				 );
-
-				return geometry;
-
-			}
-
 			function onWindowResize() {
 
 				camera.aspect = window.innerWidth / window.innerHeight;

+ 23 - 20
examples/canvas_lines_sphere.html

@@ -26,29 +26,28 @@
 		<script>
 
 			var SCREEN_WIDTH = window.innerWidth,
-			SCREEN_HEIGHT = window.innerHeight,
+				SCREEN_HEIGHT = window.innerHeight,
 
-			mouseX = 0, mouseY = 0,
+				mouseX = 0, mouseY = 0,
 
-			windowHalfX = window.innerWidth / 2,
-			windowHalfY = window.innerHeight / 2,
+				windowHalfX = window.innerWidth / 2,
+				windowHalfY = window.innerHeight / 2,
 
-			SEPARATION = 200,
-			AMOUNTX = 10,
-			AMOUNTY = 10,
+				SEPARATION = 200,
+				AMOUNTX = 10,
+				AMOUNTY = 10,
 
-			camera, scene, renderer;
+				camera, scene, renderer;
 
 			init();
 			animate();
 
 			function init() {
 
-				var container, separation = 100, amountX = 50, amountY = 50,
-				particles, particle;
+				var container, separation = 100, amountX = 50, amountY = 50, particles, particle;
 
-				container = document.createElement('div');
-				document.body.appendChild(container);
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
 
 				camera = new THREE.PerspectiveCamera( 75, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
 				camera.position.z = 1000;
@@ -83,7 +82,7 @@
 					particle.position.y = Math.random() * 2 - 1;
 					particle.position.z = Math.random() * 2 - 1;
 					particle.position.normalize();
-					particle.position.multiplyScalar( Math.random() * 10 + 450 );
+					particle.position.multiplyScalar( 450 );
 					particle.scale.multiplyScalar( 2 );
 					scene.add( particle );
 
@@ -91,25 +90,28 @@
 
 				// lines
 
-				for (var i = 0; i < 300; i++) {
+				var vertices = [];
 
-					var geometry = new THREE.Geometry();
+				for ( var i = 0; i < 300; i ++ ) {
 
 					var vertex = new THREE.Vector3( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
 					vertex.normalize();
 					vertex.multiplyScalar( 450 );
 
-					geometry.vertices.push( vertex );
+					vertices.push( vertex );
 
 					var vertex2 = vertex.clone();
 					vertex2.multiplyScalar( Math.random() * 0.3 + 1 );
 
-					geometry.vertices.push( vertex2 );
+					vertices.push( vertex2 );
 
-					var line = new THREE.Line( geometry, new THREE.LineBasicMaterial( { color: 0xffffff, opacity: Math.random() } ) );
-					scene.add( line );
 				}
 
+				var geometry = new THREE.BufferGeometry().setFromPoints( vertices );
+
+				var line = new THREE.LineSegments( geometry, new THREE.LineBasicMaterial( { color: 0xffffff } ) );
+				scene.add( line );
+
 				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
 				document.addEventListener( 'touchstart', onDocumentTouchStart, false );
 				document.addEventListener( 'touchmove', onDocumentTouchMove, false );
@@ -134,10 +136,11 @@
 
 			//
 
-			function onDocumentMouseMove(event) {
+			function onDocumentMouseMove( event ) {
 
 				mouseX = event.clientX - windowHalfX;
 				mouseY = event.clientY - windowHalfY;
+
 			}
 
 			function onDocumentTouchStart( event ) {

+ 1 - 1
examples/canvas_materials_video.html

@@ -103,7 +103,7 @@
 
 				//
 
-				var plane = new THREE.PlaneGeometry( 480, 204, 4, 4 );
+				var plane = new THREE.PlaneBufferGeometry( 480, 204, 4, 4 );
 
 				mesh = new THREE.Mesh( plane, material );
 				mesh.scale.x = mesh.scale.y = mesh.scale.z = 1.5;

+ 1 - 1
examples/canvas_performance.html

@@ -53,7 +53,7 @@
 
 				// Spheres
 
-				var geometry = new THREE.SphereGeometry( 100, 26, 18 );
+				var geometry = new THREE.SphereBufferGeometry( 100, 26, 18 );
 				var material = new THREE.MeshLambertMaterial( { color: 0xffffff, overdraw: 0.5 } );
 
 				for ( var i = 0; i < 20; i ++ ) {

+ 1 - 1
examples/canvas_sandbox.html

@@ -56,7 +56,7 @@
 				group = new THREE.Group();
 				scene.add( group );
 
-				var geometry = new THREE.IcosahedronGeometry( 100, 1 );
+				var geometry = new THREE.IcosahedronBufferGeometry( 100, 1 );
 
 				var envMap = new THREE.TextureLoader().load( 'textures/metal.jpg' );
 				envMap.mapping = THREE.SphericalReflectionMapping;

+ 4 - 0
examples/files.js

@@ -183,6 +183,7 @@ var files = {
 		"webgl_materials_video",
 		"webgl_materials_video_webcam",
 		"webgl_materials_wireframe",
+		"webgl_math_orientation_transform",
 		"webgl_mirror",
 		"webgl_mirror_nodes",
 		"webgl_modifier_simplifier",
@@ -209,6 +210,7 @@ var files = {
 		"webgl_panorama_equirectangular",
 		"webgl_performance",
 		"webgl_performance_doublesided",
+		"webgl_performance_nodes",
 		"webgl_performance_static",
 		"webgl_physics_cloth",
 		"webgl_physics_convex_break",
@@ -232,6 +234,7 @@ var files = {
 		"webgl_postprocessing_ssaa",
 		"webgl_postprocessing_ssaa_unbiased",
 		"webgl_postprocessing_nodes",
+		"webgl_postprocessing_nodes_pass",
 		"webgl_postprocessing_outline",
 		"webgl_postprocessing_pixel",
 		"webgl_postprocessing_procedural",
@@ -241,6 +244,7 @@ var files = {
 		"webgl_postprocessing_ssao",
 		"webgl_postprocessing_taa",
 		"webgl_postprocessing_unreal_bloom",
+		"webgl_raycast_sprite",
 		"webgl_raycast_texture",
 		"webgl_read_float_buffer",
 		"webgl_refraction",

+ 2 - 4
examples/index.html

@@ -296,11 +296,9 @@
 			link.setAttribute( 'target', 'viewer' );
 			link.addEventListener( 'click', function ( event ) {
 
-				if ( event.button === 0 ) {
+				if ( event.button !== 0 || event.ctrlKey || event.altKey || event.metaKey ) return;
 
-					selectFile( file );
-
-				}
+				selectFile( file );
 
 			} );
 

+ 13 - 0
examples/js/Detector.js

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

+ 769 - 752
examples/js/MarchingCubes.js

@@ -4,548 +4,573 @@
  * Port of http://webglsamples.org/blob/blob.html
  */
 
-THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors ) {
+( function ( THREE ) {
 
-	THREE.ImmediateRenderObject.call( this, material );
+	THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors ) {
 
-	var scope = this;
+		THREE.ImmediateRenderObject.call( this, material );
 
-	// temp buffers used in polygonize
+		var scope = this;
 
-	var vlist = new Float32Array( 12 * 3 );
-	var nlist = new Float32Array( 12 * 3 );
+		var yd, zd;
+		var field, normal_cache;
 
-	this.enableUvs = enableUvs !== undefined ? enableUvs : false;
-	this.enableColors = enableColors !== undefined ? enableColors : false;
+		// temp buffers used in polygonize
 
-	// functions have to be object properties
-	// prototype functions kill performance
-	// (tested and it was 4x slower !!!)
+		var vlist = new Float32Array( 12 * 3 );
+		var nlist = new Float32Array( 12 * 3 );
 
-	this.init = function ( resolution ) {
+		this.enableUvs = enableUvs !== undefined ? enableUvs : false;
+		this.enableColors = enableColors !== undefined ? enableColors : false;
 
-		this.resolution = resolution;
+		// functions have to be object properties
+		// prototype functions kill performance
+		// (tested and it was 4x slower !!!)
 
-		// parameters
+		this.init = function ( resolution ) {
 
-		this.isolation = 80.0;
+			this.resolution = resolution;
 
-		// size of field, 32 is pushing it in Javascript :)
+			// parameters
 
-		this.size = resolution;
-		this.size2 = this.size * this.size;
-		this.size3 = this.size2 * this.size;
-		this.halfsize = this.size / 2.0;
+			this.isolation = 80.0;
 
-		// deltas
+			// size of field, 32 is pushing it in Javascript :)
 
-		this.delta = 2.0 / this.size;
-		this.yd = this.size;
-		this.zd = this.size2;
+			this.size = resolution;
+			this.size2 = this.size * this.size;
+			this.size3 = this.size2 * this.size;
+			this.halfsize = this.size / 2.0;
 
-		this.field = new Float32Array( this.size3 );
-		this.normal_cache = new Float32Array( this.size3 * 3 );
+			// deltas
 
-		// immediate render mode simulator
+			this.delta = 2.0 / this.size;
 
-		this.maxCount = 4096; // TODO: find the fastest size for this buffer
-		this.count = 0;
+			yd = this.size;
+			zd = this.size2;
 
-		this.hasPositions = false;
-		this.hasNormals = false;
-		this.hasColors = false;
-		this.hasUvs = false;
+			field = new Float32Array( this.size3 );
+			normal_cache = new Float32Array( this.size3 * 3 );
 
-		this.positionArray = new Float32Array( this.maxCount * 3 );
-		this.normalArray = new Float32Array( this.maxCount * 3 );
+			// immediate render mode simulator
 
-		if ( this.enableUvs ) {
+			this.maxCount = 4096; // TODO: find the fastest size for this buffer
+			this.count = 0;
 
-			this.uvArray = new Float32Array( this.maxCount * 2 );
+			this.hasPositions = false;
+			this.hasNormals = false;
+			this.hasColors = false;
+			this.hasUvs = false;
 
-		}
+			this.positionArray = new Float32Array( this.maxCount * 3 );
+			this.normalArray = new Float32Array( this.maxCount * 3 );
 
-		if ( this.enableColors ) {
+			if ( this.enableUvs ) {
 
-			this.colorArray = new Float32Array( this.maxCount * 3 );
+				this.uvArray = new Float32Array( this.maxCount * 2 );
 
-		}
+			}
 
-	};
+			if ( this.enableColors ) {
 
-	///////////////////////
-	// Polygonization
-	///////////////////////
+				this.colorArray = new Float32Array( this.maxCount * 3 );
 
-	function lerp( a, b, t ) {
+			}
 
-		return a + ( b - a ) * t;
+		};
 
-	}
+		///////////////////////
+		// Polygonization
+		///////////////////////
 
-	function VIntX( q, offset, isol, x, y, z, valp1, valp2 ) {
+		function lerp( a, b, t ) {
 
-		var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
-			nc = scope.normal_cache;
+			return a + ( b - a ) * t;
 
-		vlist[ offset + 0 ] = x + mu * scope.delta;
-		vlist[ offset + 1 ] = y;
-		vlist[ offset + 2 ] = z;
+		}
 
-		nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q + 3 ], mu );
-		nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q + 4 ], mu );
-		nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q + 5 ], mu );
+		function VIntX( q, offset, isol, x, y, z, valp1, valp2 ) {
 
-	}
+			var mu = ( isol - valp1 ) / ( valp2 - valp1 );
 
-	function VIntY( q, offset, isol, x, y, z, valp1, valp2 ) {
+			vlist[ offset + 0 ] = x + mu * scope.delta;
+			vlist[ offset + 1 ] = y;
+			vlist[ offset + 2 ] = z;
 
-		var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
-			nc = scope.normal_cache;
+			nlist[ offset + 0 ] = lerp( normal_cache[ q + 0 ], normal_cache[ q + 3 ], mu );
+			nlist[ offset + 1 ] = lerp( normal_cache[ q + 1 ], normal_cache[ q + 4 ], mu );
+			nlist[ offset + 2 ] = lerp( normal_cache[ q + 2 ], normal_cache[ q + 5 ], mu );
 
-		vlist[ offset + 0 ] = x;
-		vlist[ offset + 1 ] = y + mu * scope.delta;
-		vlist[ offset + 2 ] = z;
+		}
 
-		var q2 = q + scope.yd * 3;
+		function VIntY( q, offset, isol, x, y, z, valp1, valp2 ) {
 
-		nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu );
-		nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu );
-		nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu );
+			var mu = ( isol - valp1 ) / ( valp2 - valp1 );
 
-	}
+			vlist[ offset + 0 ] = x;
+			vlist[ offset + 1 ] = y + mu * scope.delta;
+			vlist[ offset + 2 ] = z;
 
-	function VIntZ( q, offset, isol, x, y, z, valp1, valp2 ) {
+			var q2 = q + yd * 3;
 
-		var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
-			nc = scope.normal_cache;
+			nlist[ offset + 0 ] = lerp( normal_cache[ q + 0 ], normal_cache[ q2 + 0 ], mu );
+			nlist[ offset + 1 ] = lerp( normal_cache[ q + 1 ], normal_cache[ q2 + 1 ], mu );
+			nlist[ offset + 2 ] = lerp( normal_cache[ q + 2 ], normal_cache[ q2 + 2 ], mu );
 
-		vlist[ offset + 0 ] = x;
-		vlist[ offset + 1 ] = y;
-		vlist[ offset + 2 ] = z + mu * scope.delta;
+		}
 
-		var q2 = q + scope.zd * 3;
+		function VIntZ( q, offset, isol, x, y, z, valp1, valp2 ) {
 
-		nlist[ offset + 0 ] = lerp( nc[ q + 0 ], nc[ q2 + 0 ], mu );
-		nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu );
-		nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu );
+			var mu = ( isol - valp1 ) / ( valp2 - valp1 );
 
-	}
+			vlist[ offset + 0 ] = x;
+			vlist[ offset + 1 ] = y;
+			vlist[ offset + 2 ] = z + mu * scope.delta;
 
-	function compNorm( q ) {
+			var q2 = q + zd * 3;
 
-		var q3 = q * 3;
+			nlist[ offset + 0 ] = lerp( normal_cache[ q + 0 ], normal_cache[ q2 + 0 ], mu );
+			nlist[ offset + 1 ] = lerp( normal_cache[ q + 1 ], normal_cache[ q2 + 1 ], mu );
+			nlist[ offset + 2 ] = lerp( normal_cache[ q + 2 ], normal_cache[ q2 + 2 ], mu );
 
-		if ( scope.normal_cache[ q3 ] === 0.0 ) {
+		}
 
-			scope.normal_cache[ q3 + 0 ] = scope.field[ q - 1 ] - scope.field[ q + 1 ];
-			scope.normal_cache[ q3 + 1 ] = scope.field[ q - scope.yd ] - scope.field[ q + scope.yd ];
-			scope.normal_cache[ q3 + 2 ] = scope.field[ q - scope.zd ] - scope.field[ q + scope.zd ];
+		function compNorm( q ) {
 
-		}
+			var q3 = q * 3;
 
-	}
+			if ( normal_cache[ q3 ] === 0.0 ) {
 
-	// Returns total number of triangles. Fills triangles.
-	// (this is where most of time is spent - it's inner work of O(n3) loop )
+				normal_cache[ q3 + 0 ] = field[ q - 1 ] - field[ q + 1 ];
+				normal_cache[ q3 + 1 ] = field[ q - yd ] - field[ q + yd ];
+				normal_cache[ q3 + 2 ] = field[ q - zd ] - field[ q + zd ];
 
-	function polygonize( fx, fy, fz, q, isol, renderCallback ) {
+			}
 
-		// cache indices
-		var q1 = q + 1,
-			qy = q + scope.yd,
-			qz = q + scope.zd,
-			q1y = q1 + scope.yd,
-			q1z = q1 + scope.zd,
-			qyz = q + scope.yd + scope.zd,
-			q1yz = q1 + scope.yd + scope.zd;
+		}
 
-		var cubeindex = 0,
-			field0 = scope.field[ q ],
-			field1 = scope.field[ q1 ],
-			field2 = scope.field[ qy ],
-			field3 = scope.field[ q1y ],
-			field4 = scope.field[ qz ],
-			field5 = scope.field[ q1z ],
-			field6 = scope.field[ qyz ],
-			field7 = scope.field[ q1yz ];
+		// Returns total number of triangles. Fills triangles.
+		// (this is where most of time is spent - it's inner work of O(n3) loop )
+
+		function polygonize( fx, fy, fz, q, isol, renderCallback ) {
+
+			// cache indices
+			var q1 = q + 1,
+				qy = q + yd,
+				qz = q + zd,
+				q1y = q1 + yd,
+				q1z = q1 + zd,
+				qyz = q + yd + zd,
+				q1yz = q1 + yd + zd;
+
+			var cubeindex = 0,
+				field0 = field[ q ],
+				field1 = field[ q1 ],
+				field2 = field[ qy ],
+				field3 = field[ q1y ],
+				field4 = field[ qz ],
+				field5 = field[ q1z ],
+				field6 = field[ qyz ],
+				field7 = field[ q1yz ];
+
+			if ( field0 < isol ) cubeindex |= 1;
+			if ( field1 < isol ) cubeindex |= 2;
+			if ( field2 < isol ) cubeindex |= 8;
+			if ( field3 < isol ) cubeindex |= 4;
+			if ( field4 < isol ) cubeindex |= 16;
+			if ( field5 < isol ) cubeindex |= 32;
+			if ( field6 < isol ) cubeindex |= 128;
+			if ( field7 < isol ) cubeindex |= 64;
+
+			// if cube is entirely in/out of the surface - bail, nothing to draw
+
+			var bits = EdgeTable[ cubeindex ];
+			if ( bits === 0 ) return 0;
+
+			var d = scope.delta,
+				fx2 = fx + d,
+				fy2 = fy + d,
+				fz2 = fz + d;
+
+			// top of the cube
+
+			if ( bits & 1 ) {
+
+				compNorm( q );
+				compNorm( q1 );
+				VIntX( q * 3, 0, isol, fx, fy, fz, field0, field1 );
 
-		if ( field0 < isol ) cubeindex |= 1;
-		if ( field1 < isol ) cubeindex |= 2;
-		if ( field2 < isol ) cubeindex |= 8;
-		if ( field3 < isol ) cubeindex |= 4;
-		if ( field4 < isol ) cubeindex |= 16;
-		if ( field5 < isol ) cubeindex |= 32;
-		if ( field6 < isol ) cubeindex |= 128;
-		if ( field7 < isol ) cubeindex |= 64;
+			}
 
-		// if cube is entirely in/out of the surface - bail, nothing to draw
+			if ( bits & 2 ) {
 
-		var bits = THREE.edgeTable[ cubeindex ];
-		if ( bits === 0 ) return 0;
+				compNorm( q1 );
+				compNorm( q1y );
+				VIntY( q1 * 3, 3, isol, fx2, fy, fz, field1, field3 );
 
-		var d = scope.delta,
-			fx2 = fx + d,
-			fy2 = fy + d,
-			fz2 = fz + d;
+			}
 
-		// top of the cube
+			if ( bits & 4 ) {
 
-		if ( bits & 1 ) {
+				compNorm( qy );
+				compNorm( q1y );
+				VIntX( qy * 3, 6, isol, fx, fy2, fz, field2, field3 );
 
-			compNorm( q );
-			compNorm( q1 );
-			VIntX( q * 3, 0, isol, fx, fy, fz, field0, field1 );
+			}
 
-		}
+			if ( bits & 8 ) {
 
-		if ( bits & 2 ) {
+				compNorm( q );
+				compNorm( qy );
+				VIntY( q * 3, 9, isol, fx, fy, fz, field0, field2 );
 
-			compNorm( q1 );
-			compNorm( q1y );
-			VIntY( q1 * 3, 3, isol, fx2, fy, fz, field1, field3 );
+			}
 
-		}
+			// bottom of the cube
 
-		if ( bits & 4 ) {
+			if ( bits & 16 ) {
 
-			compNorm( qy );
-			compNorm( q1y );
-			VIntX( qy * 3, 6, isol, fx, fy2, fz, field2, field3 );
+				compNorm( qz );
+				compNorm( q1z );
+				VIntX( qz * 3, 12, isol, fx, fy, fz2, field4, field5 );
 
-		}
+			}
 
-		if ( bits & 8 ) {
+			if ( bits & 32 ) {
 
-			compNorm( q );
-			compNorm( qy );
-			VIntY( q * 3, 9, isol, fx, fy, fz, field0, field2 );
+				compNorm( q1z );
+				compNorm( q1yz );
+				VIntY( q1z * 3, 15, isol, fx2, fy, fz2, field5, field7 );
 
-		}
+			}
 
-		// bottom of the cube
+			if ( bits & 64 ) {
 
-		if ( bits & 16 ) {
+				compNorm( qyz );
+				compNorm( q1yz );
+				VIntX( qyz * 3, 18, isol, fx, fy2, fz2, field6, field7 );
 
-			compNorm( qz );
-			compNorm( q1z );
-			VIntX( qz * 3, 12, isol, fx, fy, fz2, field4, field5 );
+			}
 
-		}
+			if ( bits & 128 ) {
 
-		if ( bits & 32 ) {
+				compNorm( qz );
+				compNorm( qyz );
+				VIntY( qz * 3, 21, isol, fx, fy, fz2, field4, field6 );
 
-			compNorm( q1z );
-			compNorm( q1yz );
-			VIntY( q1z * 3, 15, isol, fx2, fy, fz2, field5, field7 );
+			}
 
-		}
+			// vertical lines of the cube
 
-		if ( bits & 64 ) {
+			if ( bits & 256 ) {
 
-			compNorm( qyz );
-			compNorm( q1yz );
-			VIntX( qyz * 3, 18, isol, fx, fy2, fz2, field6, field7 );
+				compNorm( q );
+				compNorm( qz );
+				VIntZ( q * 3, 24, isol, fx, fy, fz, field0, field4 );
 
-		}
+			}
 
-		if ( bits & 128 ) {
+			if ( bits & 512 ) {
 
-			compNorm( qz );
-			compNorm( qyz );
-			VIntY( qz * 3, 21, isol, fx, fy, fz2, field4, field6 );
+				compNorm( q1 );
+				compNorm( q1z );
+				VIntZ( q1 * 3, 27, isol, fx2, fy, fz, field1, field5 );
 
-		}
+			}
 
-		// vertical lines of the cube
+			if ( bits & 1024 ) {
 
-		if ( bits & 256 ) {
+				compNorm( q1y );
+				compNorm( q1yz );
+				VIntZ( q1y * 3, 30, isol, fx2, fy2, fz, field3, field7 );
 
-			compNorm( q );
-			compNorm( qz );
-			VIntZ( q * 3, 24, isol, fx, fy, fz, field0, field4 );
+			}
 
-		}
+			if ( bits & 2048 ) {
 
-		if ( bits & 512 ) {
+				compNorm( qy );
+				compNorm( qyz );
+				VIntZ( qy * 3, 33, isol, fx, fy2, fz, field2, field6 );
 
-			compNorm( q1 );
-			compNorm( q1z );
-			VIntZ( q1 * 3, 27, isol, fx2, fy, fz, field1, field5 );
+			}
 
-		}
+			cubeindex <<= 4; // re-purpose cubeindex into an offset into triTable
 
-		if ( bits & 1024 ) {
+			var o1, o2, o3, numtris = 0, i = 0;
 
-			compNorm( q1y );
-			compNorm( q1yz );
-			VIntZ( q1y * 3, 30, isol, fx2, fy2, fz, field3, field7 );
+			// here is where triangles are created
 
-		}
+			while ( TriTable[ cubeindex + i ] != - 1 ) {
+
+				o1 = cubeindex + i;
+				o2 = o1 + 1;
+				o3 = o1 + 2;
 
-		if ( bits & 2048 ) {
+				posnormtriv( vlist, nlist,
+					3 * TriTable[ o1 ],
+					3 * TriTable[ o2 ],
+					3 * TriTable[ o3 ],
+					renderCallback );
 
-			compNorm( qy );
-			compNorm( qyz );
-			VIntZ( qy * 3, 33, isol, fx, fy2, fz, field2, field6 );
+				i += 3;
+				numtris ++;
+
+			}
+
+			return numtris;
 
 		}
 
-		cubeindex <<= 4; // re-purpose cubeindex into an offset into triTable
+		/////////////////////////////////////
+		// Immediate render mode simulator
+		/////////////////////////////////////
 
-		var o1, o2, o3, numtris = 0, i = 0;
+		function posnormtriv( pos, norm, o1, o2, o3, renderCallback ) {
 
-		// here is where triangles are created
+			var c = scope.count * 3;
 
-		while ( THREE.triTable[ cubeindex + i ] != - 1 ) {
+			// positions
 
-			o1 = cubeindex + i;
-			o2 = o1 + 1;
-			o3 = o1 + 2;
+			scope.positionArray[ c + 0 ] = pos[ o1 ];
+			scope.positionArray[ c + 1 ] = pos[ o1 + 1 ];
+			scope.positionArray[ c + 2 ] = pos[ o1 + 2 ];
 
-			posnormtriv( vlist, nlist,
-				3 * THREE.triTable[ o1 ],
-				3 * THREE.triTable[ o2 ],
-				3 * THREE.triTable[ o3 ],
-				renderCallback );
+			scope.positionArray[ c + 3 ] = pos[ o2 ];
+			scope.positionArray[ c + 4 ] = pos[ o2 + 1 ];
+			scope.positionArray[ c + 5 ] = pos[ o2 + 2 ];
 
-			i += 3;
-			numtris ++;
+			scope.positionArray[ c + 6 ] = pos[ o3 ];
+			scope.positionArray[ c + 7 ] = pos[ o3 + 1 ];
+			scope.positionArray[ c + 8 ] = pos[ o3 + 2 ];
 
-		}
+			// normals
 
-		return numtris;
+			if ( scope.material.flatShading === true ) {
 
-	}
+				var nx = ( norm[ o1 + 0 ] + norm[ o2 + 0 ] + norm[ o3 + 0 ] ) / 3;
+				var ny = ( norm[ o1 + 1 ] + norm[ o2 + 1 ] + norm[ o3 + 1 ] ) / 3;
+				var nz = ( norm[ o1 + 2 ] + norm[ o2 + 2 ] + norm[ o3 + 2 ] ) / 3;
 
-	/////////////////////////////////////
-	// Immediate render mode simulator
-	/////////////////////////////////////
+				scope.normalArray[ c + 0 ] = nx;
+				scope.normalArray[ c + 1 ] = ny;
+				scope.normalArray[ c + 2 ] = nz;
 
-	function posnormtriv( pos, norm, o1, o2, o3, renderCallback ) {
+				scope.normalArray[ c + 3 ] = nx;
+				scope.normalArray[ c + 4 ] = ny;
+				scope.normalArray[ c + 5 ] = nz;
 
-		var c = scope.count * 3;
+				scope.normalArray[ c + 6 ] = nx;
+				scope.normalArray[ c + 7 ] = ny;
+				scope.normalArray[ c + 8 ] = nz;
 
-		// positions
 
-		scope.positionArray[ c + 0 ] = pos[ o1 ];
-		scope.positionArray[ c + 1 ] = pos[ o1 + 1 ];
-		scope.positionArray[ c + 2 ] = pos[ o1 + 2 ];
+			} else {
 
-		scope.positionArray[ c + 3 ] = pos[ o2 ];
-		scope.positionArray[ c + 4 ] = pos[ o2 + 1 ];
-		scope.positionArray[ c + 5 ] = pos[ o2 + 2 ];
+				scope.normalArray[ c + 0 ] = norm[ o1 + 0 ];
+				scope.normalArray[ c + 1 ] = norm[ o1 + 1 ];
+				scope.normalArray[ c + 2 ] = norm[ o1 + 2 ];
 
-		scope.positionArray[ c + 6 ] = pos[ o3 ];
-		scope.positionArray[ c + 7 ] = pos[ o3 + 1 ];
-		scope.positionArray[ c + 8 ] = pos[ o3 + 2 ];
+				scope.normalArray[ c + 3 ] = norm[ o2 + 0 ];
+				scope.normalArray[ c + 4 ] = norm[ o2 + 1 ];
+				scope.normalArray[ c + 5 ] = norm[ o2 + 2 ];
 
-		// normals
+				scope.normalArray[ c + 6 ] = norm[ o3 + 0 ];
+				scope.normalArray[ c + 7 ] = norm[ o3 + 1 ];
+				scope.normalArray[ c + 8 ] = norm[ o3 + 2 ];
 
-		scope.normalArray[ c + 0 ] = norm[ o1 ];
-		scope.normalArray[ c + 1 ] = norm[ o1 + 1 ];
-		scope.normalArray[ c + 2 ] = norm[ o1 + 2 ];
+			}
 
-		scope.normalArray[ c + 3 ] = norm[ o2 ];
-		scope.normalArray[ c + 4 ] = norm[ o2 + 1 ];
-		scope.normalArray[ c + 5 ] = norm[ o2 + 2 ];
+			// uvs
 
-		scope.normalArray[ c + 6 ] = norm[ o3 ];
-		scope.normalArray[ c + 7 ] = norm[ o3 + 1 ];
-		scope.normalArray[ c + 8 ] = norm[ o3 + 2 ];
+			if ( scope.enableUvs ) {
 
-		// uvs
+				var d = scope.count * 2;
 
-		if ( scope.enableUvs ) {
+				scope.uvArray[ d + 0 ] = pos[ o1 + 0 ];
+				scope.uvArray[ d + 1 ] = pos[ o1 + 2 ];
 
-			var d = scope.count * 2;
+				scope.uvArray[ d + 2 ] = pos[ o2 + 0 ];
+				scope.uvArray[ d + 3 ] = pos[ o2 + 2 ];
 
-			scope.uvArray[ d + 0 ] = pos[ o1 ];
-			scope.uvArray[ d + 1 ] = pos[ o1 + 2 ];
+				scope.uvArray[ d + 4 ] = pos[ o3 + 0 ];
+				scope.uvArray[ d + 5 ] = pos[ o3 + 2 ];
 
-			scope.uvArray[ d + 2 ] = pos[ o2 ];
-			scope.uvArray[ d + 3 ] = pos[ o2 + 2 ];
+			}
 
-			scope.uvArray[ d + 4 ] = pos[ o3 ];
-			scope.uvArray[ d + 5 ] = pos[ o3 + 2 ];
+			// colors
 
-		}
+			if ( scope.enableColors ) {
 
-		// colors
+				scope.colorArray[ c + 0 ] = pos[ o1 + 0 ];
+				scope.colorArray[ c + 1 ] = pos[ o1 + 1 ];
+				scope.colorArray[ c + 2 ] = pos[ o1 + 2 ];
 
-		if ( scope.enableColors ) {
+				scope.colorArray[ c + 3 ] = pos[ o2 + 0 ];
+				scope.colorArray[ c + 4 ] = pos[ o2 + 1 ];
+				scope.colorArray[ c + 5 ] = pos[ o2 + 2 ];
 
-			scope.colorArray[ c + 0 ] = pos[ o1 ];
-			scope.colorArray[ c + 1 ] = pos[ o1 + 1 ];
-			scope.colorArray[ c + 2 ] = pos[ o1 + 2 ];
+				scope.colorArray[ c + 6 ] = pos[ o3 + 0 ];
+				scope.colorArray[ c + 7 ] = pos[ o3 + 1 ];
+				scope.colorArray[ c + 8 ] = pos[ o3 + 2 ];
 
-			scope.colorArray[ c + 3 ] = pos[ o2 ];
-			scope.colorArray[ c + 4 ] = pos[ o2 + 1 ];
-			scope.colorArray[ c + 5 ] = pos[ o2 + 2 ];
+			}
 
-			scope.colorArray[ c + 6 ] = pos[ o3 ];
-			scope.colorArray[ c + 7 ] = pos[ o3 + 1 ];
-			scope.colorArray[ c + 8 ] = pos[ o3 + 2 ];
+			scope.count += 3;
 
-		}
+			if ( scope.count >= scope.maxCount - 3 ) {
 
-		scope.count += 3;
+				scope.hasPositions = true;
+				scope.hasNormals = true;
 
-		if ( scope.count >= scope.maxCount - 3 ) {
+				if ( scope.enableUvs ) {
 
-			scope.hasPositions = true;
-			scope.hasNormals = true;
+					scope.hasUvs = true;
 
-			if ( scope.enableUvs ) {
+				}
 
-				scope.hasUvs = true;
+				if ( scope.enableColors ) {
 
-			}
+					scope.hasColors = true;
 
-			if ( scope.enableColors ) {
+				}
 
-				scope.hasColors = true;
+				renderCallback( scope );
 
 			}
 
-			renderCallback( scope );
-
 		}
 
-	}
+		function begin() {
 
-	this.begin = function () {
+			scope.count = 0;
 
-		this.count = 0;
+			scope.hasPositions = false;
+			scope.hasNormals = false;
+			scope.hasUvs = false;
+			scope.hasColors = false;
 
-		this.hasPositions = false;
-		this.hasNormals = false;
-		this.hasUvs = false;
-		this.hasColors = false;
+		}
 
-	};
+		function end( renderCallback ) {
 
-	this.end = function ( renderCallback ) {
+			if ( scope.count === 0 ) return;
 
-		if ( this.count === 0 ) return;
+			for ( var i = scope.count * 3; i < scope.positionArray.length; i ++ ) {
 
-		for ( var i = this.count * 3; i < this.positionArray.length; i ++ ) {
+				scope.positionArray[ i ] = 0.0;
 
-			this.positionArray[ i ] = 0.0;
+			}
 
-		}
+			scope.hasPositions = true;
+			scope.hasNormals = true;
 
-		this.hasPositions = true;
-		this.hasNormals = true;
+			if ( scope.enableUvs && scope.material.map ) {
 
-		if ( this.enableUvs ) {
+				scope.hasUvs = true;
 
-			this.hasUvs = true;
+			}
 
-		}
+			if ( scope.enableColors && scope.material.vertexColors !== THREE.NoColors ) {
 
-		if ( this.enableColors ) {
+				scope.hasColors = true;
 
-			this.hasColors = true;
+			}
 
-		}
+			renderCallback( scope );
 
-		renderCallback( this );
+		}
 
-	};
+		/////////////////////////////////////
+		// Metaballs
+		/////////////////////////////////////
 
-	/////////////////////////////////////
-	// Metaballs
-	/////////////////////////////////////
+		// Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after
+		// a fixed distance, determined by strength and subtract.
 
-	// Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after
-	// a fixed distance, determined by strength and subtract.
+		this.addBall = function ( ballx, bally, ballz, strength, subtract ) {
 
-	this.addBall = function ( ballx, bally, ballz, strength, subtract ) {
+			var sign = Math.sign( strength );
+			strength = Math.abs( strength );
 
-		var sign = Math.sign( strength );
-		strength = Math.abs( strength );
+			// Let's solve the equation to find the radius:
+			// 1.0 / (0.000001 + radius^2) * strength - subtract = 0
+			// strength / (radius^2) = subtract
+			// strength = subtract * radius^2
+			// radius^2 = strength / subtract
+			// radius = sqrt(strength / subtract)
 
-		// Let's solve the equation to find the radius:
-		// 1.0 / (0.000001 + radius^2) * strength - subtract = 0
-		// strength / (radius^2) = subtract
-		// strength = subtract * radius^2
-		// radius^2 = strength / subtract
-		// radius = sqrt(strength / subtract)
+			var radius = this.size * Math.sqrt( strength / subtract ),
+				zs = ballz * this.size,
+				ys = bally * this.size,
+				xs = ballx * this.size;
 
-		var radius = this.size * Math.sqrt( strength / subtract ),
-			zs = ballz * this.size,
-			ys = bally * this.size,
-			xs = ballx * this.size;
+			var min_z = Math.floor( zs - radius ); if ( min_z < 1 ) min_z = 1;
+			var max_z = Math.floor( zs + radius ); if ( max_z > this.size - 1 ) max_z = this.size - 1;
+			var min_y = Math.floor( ys - radius ); if ( min_y < 1 ) min_y = 1;
+			var max_y = Math.floor( ys + radius ); if ( max_y > this.size - 1 ) max_y = this.size - 1;
+			var min_x = Math.floor( xs - radius ); if ( min_x < 1 ) min_x = 1;
+			var max_x = Math.floor( xs + radius ); if ( max_x > this.size - 1 ) max_x = this.size - 1;
 
-		var min_z = Math.floor( zs - radius ); if ( min_z < 1 ) min_z = 1;
-		var max_z = Math.floor( zs + radius ); if ( max_z > this.size - 1 ) max_z = this.size - 1;
-		var min_y = Math.floor( ys - radius ); if ( min_y < 1 ) min_y = 1;
-		var max_y = Math.floor( ys + radius ); if ( max_y > this.size - 1 ) max_y = this.size - 1;
-		var min_x = Math.floor( xs - radius ); if ( min_x < 1 ) min_x = 1;
-		var max_x = Math.floor( xs + radius ); if ( max_x > this.size - 1 ) max_x = this.size - 1;
 
+			// Don't polygonize in the outer layer because normals aren't
+			// well-defined there.
 
-		// Don't polygonize in the outer layer because normals aren't
-		// well-defined there.
+			var x, y, z, y_offset, z_offset, fx, fy, fz, fz2, fy2, val;
 
-		var x, y, z, y_offset, z_offset, fx, fy, fz, fz2, fy2, val;
+			for ( z = min_z; z < max_z; z ++ ) {
 
-		for ( z = min_z; z < max_z; z ++ ) {
+				z_offset = this.size2 * z;
+				fz = z / this.size - ballz;
+				fz2 = fz * fz;
 
-			z_offset = this.size2 * z;
-			fz = z / this.size - ballz;
-			fz2 = fz * fz;
+				for ( y = min_y; y < max_y; y ++ ) {
 
-			for ( y = min_y; y < max_y; y ++ ) {
+					y_offset = z_offset + this.size * y;
+					fy = y / this.size - bally;
+					fy2 = fy * fy;
 
-				y_offset = z_offset + this.size * y;
-				fy = y / this.size - bally;
-				fy2 = fy * fy;
+					for ( x = min_x; x < max_x; x ++ ) {
 
-				for ( x = min_x; x < max_x; x ++ ) {
+						fx = x / this.size - ballx;
+						val = strength / ( 0.000001 + fx * fx + fy2 + fz2 ) - subtract;
+						if ( val > 0.0 ) field[ y_offset + x ] += val * sign;
 
-					fx = x / this.size - ballx;
-					val = strength / ( 0.000001 + fx * fx + fy2 + fz2 ) - subtract;
-					if ( val > 0.0 ) this.field[ y_offset + x ] += val * sign;
+					}
 
 				}
 
 			}
 
-		}
+		};
 
-	};
+		this.addPlaneX = function ( strength, subtract ) {
 
-	this.addPlaneX = function ( strength, subtract ) {
+			var x, y, z, xx, val, xdiv, cxy,
 
-		var x, y, z, xx, val, xdiv, cxy,
+				// cache attribute lookups
+				size = this.size,
 
-			// cache attribute lookups
-			size = this.size,
-			yd = this.yd,
-			zd = this.zd,
-			field = this.field,
+				dist = size * Math.sqrt( strength / subtract );
 
-			dist = size * Math.sqrt( strength / subtract );
+			if ( dist > size ) dist = size;
 
-		if ( dist > size ) dist = size;
+			for ( x = 0; x < dist; x ++ ) {
 
-		for ( x = 0; x < dist; x ++ ) {
+				xdiv = x / size;
+				xx = xdiv * xdiv;
+				val = strength / ( 0.0001 + xx ) - subtract;
 
-			xdiv = x / size;
-			xx = xdiv * xdiv;
-			val = strength / ( 0.0001 + xx ) - subtract;
+				if ( val > 0.0 ) {
 
-			if ( val > 0.0 ) {
+					for ( y = 0; y < size; y ++ ) {
 
-				for ( y = 0; y < size; y ++ ) {
+						cxy = x + y * yd;
 
-					cxy = x + y * yd;
+						for ( z = 0; z < size; z ++ ) {
 
-					for ( z = 0; z < size; z ++ ) {
+							field[ zd * z + cxy ] += val;
 
-						field[ zd * z + cxy ] += val;
+						}
 
 					}
 
@@ -553,492 +578,484 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			}
 
-		}
+		};
 
-	};
+		this.addPlaneY = function ( strength, subtract ) {
 
-	this.addPlaneY = function ( strength, subtract ) {
+			var x, y, z, yy, val, ydiv, cy, cxy,
 
-		var x, y, z, yy, val, ydiv, cy, cxy,
+				// cache attribute lookups
+				size = this.size,
 
-			// cache attribute lookups
-			size = this.size,
-			yd = this.yd,
-			zd = this.zd,
-			field = this.field,
+				dist = size * Math.sqrt( strength / subtract );
 
-			dist = size * Math.sqrt( strength / subtract );
+			if ( dist > size ) dist = size;
 
-		if ( dist > size ) dist = size;
+			for ( y = 0; y < dist; y ++ ) {
 
-		for ( y = 0; y < dist; y ++ ) {
+				ydiv = y / size;
+				yy = ydiv * ydiv;
+				val = strength / ( 0.0001 + yy ) - subtract;
 
-			ydiv = y / size;
-			yy = ydiv * ydiv;
-			val = strength / ( 0.0001 + yy ) - subtract;
+				if ( val > 0.0 ) {
 
-			if ( val > 0.0 ) {
+					cy = y * yd;
 
-				cy = y * yd;
+					for ( x = 0; x < size; x ++ ) {
 
-				for ( x = 0; x < size; x ++ ) {
+						cxy = cy + x;
 
-					cxy = cy + x;
+						for ( z = 0; z < size; z ++ )
+							field[ zd * z + cxy ] += val;
 
-					for ( z = 0; z < size; z ++ )
-						field[ zd * z + cxy ] += val;
+					}
 
 				}
 
 			}
 
-		}
+		};
 
-	};
+		this.addPlaneZ = function ( strength, subtract ) {
 
-	this.addPlaneZ = function ( strength, subtract ) {
+			var x, y, z, zz, val, zdiv, cz, cyz,
 
-		var x, y, z, zz, val, zdiv, cz, cyz,
+				// cache attribute lookups
+				size = this.size,
 
-			// cache attribute lookups
-			size = this.size,
-			yd = this.yd,
-			zd = this.zd,
-			field = this.field,
+				dist = size * Math.sqrt( strength / subtract );
 
-			dist = size * Math.sqrt( strength / subtract );
+			if ( dist > size ) dist = size;
 
-		if ( dist > size ) dist = size;
+			for ( z = 0; z < dist; z ++ ) {
 
-		for ( z = 0; z < dist; z ++ ) {
+				zdiv = z / size;
+				zz = zdiv * zdiv;
+				val = strength / ( 0.0001 + zz ) - subtract;
+				if ( val > 0.0 ) {
 
-			zdiv = z / size;
-			zz = zdiv * zdiv;
-			val = strength / ( 0.0001 + zz ) - subtract;
-			if ( val > 0.0 ) {
+					cz = zd * z;
 
-				cz = zd * z;
+					for ( y = 0; y < size; y ++ ) {
 
-				for ( y = 0; y < size; y ++ ) {
+						cyz = cz + y * yd;
 
-					cyz = cz + y * yd;
+						for ( x = 0; x < size; x ++ )
+							field[ cyz + x ] += val;
 
-					for ( x = 0; x < size; x ++ )
-						field[ cyz + x ] += val;
+					}
 
 				}
 
 			}
 
-		}
+		};
 
-	};
+		/////////////////////////////////////
+		// Updates
+		/////////////////////////////////////
 
-	/////////////////////////////////////
-	// Updates
-	/////////////////////////////////////
+		this.reset = function () {
 
-	this.reset = function () {
+			// wipe the normal cache
 
-		var i;
+			for ( var i = 0; i < this.size3; i ++ ) {
 
-		// wipe the normal cache
+				normal_cache[ i * 3 ] = 0.0;
+				field[ i ] = 0.0;
 
-		for ( i = 0; i < this.size3; i ++ ) {
+			}
 
-			this.normal_cache[ i * 3 ] = 0.0;
-			this.field[ i ] = 0.0;
+		};
 
-		}
+		this.render = function ( renderCallback ) {
 
-	};
+			begin();
 
-	this.render = function ( renderCallback ) {
+			// Triangulate. Yeah, this is slow.
 
-		this.begin();
+			var smin2 = this.size - 2;
 
-		// Triangulate. Yeah, this is slow.
+			for ( var z = 1; z < smin2; z ++ ) {
 
-		var smin2 = this.size - 2;
+				var z_offset = this.size2 * z;
+				var fz = ( z - this.halfsize ) / this.halfsize; //+ 1
 
-		for ( var z = 1; z < smin2; z ++ ) {
+				for ( var y = 1; y < smin2; y ++ ) {
 
-			var z_offset = this.size2 * z;
-			var fz = ( z - this.halfsize ) / this.halfsize; //+ 1
+					var y_offset = z_offset + this.size * y;
+					var fy = ( y - this.halfsize ) / this.halfsize; //+ 1
 
-			for ( var y = 1; y < smin2; y ++ ) {
+					for ( var x = 1; x < smin2; x ++ ) {
 
-				var y_offset = z_offset + this.size * y;
-				var fy = ( y - this.halfsize ) / this.halfsize; //+ 1
+						var fx = ( x - this.halfsize ) / this.halfsize; //+ 1
+						var q = y_offset + x;
 
-				for ( var x = 1; x < smin2; x ++ ) {
+						polygonize( fx, fy, fz, q, this.isolation, renderCallback );
 
-					var fx = ( x - this.halfsize ) / this.halfsize; //+ 1
-					var q = y_offset + x;
-
-					polygonize( fx, fy, fz, q, this.isolation, renderCallback );
+					}
 
 				}
 
 			}
 
-		}
+			end( renderCallback );
 
-		this.end( renderCallback );
+		};
 
-	};
+		this.generateGeometry = function () {
 
-	this.generateGeometry = function () {
+			console.warn( 'THREE.MarchingCubes: generateGeometry() now returns THREE.BufferGeometry' );
+			return this.generateBufferGeometry();
 
-		console.warn( 'THREE.MarchingCubes: generateGeometry() now returns THREE.BufferGeometry' );
-		return this.generateBufferGeometry();
+		};
 
-	};
+		function concatenate( a, b, length ) {
 
-	function concatenate( a, b, length ) {
+			var result = new Float32Array( a.length + length );
+			result.set( a, 0 );
+			result.set( b.slice( 0, length ), a.length );
+			return result;
 
-		var result = new Float32Array( a.length + length );
-		result.set( a, 0 );
-		result.set( b.slice( 0, length ), a.length );
-		return result;
+		}
 
-	}
+		this.generateBufferGeometry = function () {
 
-	this.generateBufferGeometry = function () {
+			var geo = new THREE.BufferGeometry();
+			var posArray = new Float32Array();
+			var normArray = new Float32Array();
+			var colorArray = new Float32Array();
+			var uvArray = new Float32Array();
+			var scope = this;
 
-		var geo = new THREE.BufferGeometry();
-		var posArray = new Float32Array();
-		var normArray = new Float32Array();
-		var colorArray = new Float32Array();
-		var uvArray = new Float32Array();
-		var scope = this;
+			var geo_callback = function ( object ) {
 
-		var geo_callback = function ( object ) {
+				if ( scope.hasPositions ) posArray = concatenate( posArray, object.positionArray, object.count * 3 );
+				if ( scope.hasNormals ) normArray = concatenate( normArray, object.normalArray, object.count * 3 );
+				if ( scope.hasColors ) colorArray = concatenate( colorArray, object.colorArray, object.count * 3 );
+				if ( scope.hasUvs ) uvArray = concatenate( uvArray, object.uvArray, object.count * 2 );
 
-			if ( scope.hasPositions ) posArray = concatenate( posArray, object.positionArray, object.count * 3 );
-			if ( scope.hasNormals ) normArray = concatenate( normArray, object.normalArray, object.count * 3 );
-			if ( scope.hasColors ) colorArray = concatenate( colorArray, object.colorArray, object.count * 3 );
-			if ( scope.hasUvs ) uvArray = concatenate( uvArray, object.uvArray, object.count * 2 );
+				object.count = 0;
 
-			object.count = 0;
+			};
 
-		};
+			this.render( geo_callback );
 
-		this.render( geo_callback );
+			if ( this.hasPositions ) geo.addAttribute( 'position', new THREE.BufferAttribute( posArray, 3 ) );
+			if ( this.hasNormals ) geo.addAttribute( 'normal', new THREE.BufferAttribute( normArray, 3 ) );
+			if ( this.hasColors ) geo.addAttribute( 'color', new THREE.BufferAttribute( colorArray, 3 ) );
+			if ( this.hasUvs ) geo.addAttribute( 'uv', new THREE.BufferAttribute( uvArray, 2 ) );
 
-		if ( this.hasPositions ) geo.addAttribute( 'position', new THREE.BufferAttribute( posArray, 3 ) );
-		if ( this.hasNormals ) geo.addAttribute( 'normal', new THREE.BufferAttribute( normArray, 3 ) );
-		if ( this.hasColors ) geo.addAttribute( 'color', new THREE.BufferAttribute( colorArray, 3 ) );
-		if ( this.hasUvs ) geo.addAttribute( 'uv', new THREE.BufferAttribute( uvArray, 2 ) );
+			return geo;
 
-		return geo;
+		};
+
+		this.init( resolution );
 
 	};
 
-	this.init( resolution );
-
-};
-
-THREE.MarchingCubes.prototype = Object.create( THREE.ImmediateRenderObject.prototype );
-THREE.MarchingCubes.prototype.constructor = THREE.MarchingCubes;
-
-
-/////////////////////////////////////
-// Marching cubes lookup tables
-/////////////////////////////////////
-
-// These tables are straight from Paul Bourke's page:
-// http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/
-// who in turn got them from Cory Gene Bloyd.
-
-THREE.edgeTable = new Int32Array( [
-	0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
-	0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
-	0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
-	0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
-	0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
-	0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
-	0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
-	0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
-	0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c,
-	0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
-	0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc,
-	0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
-	0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c,
-	0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
-	0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,
-	0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
-	0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
-	0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
-	0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
-	0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
-	0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
-	0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
-	0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
-	0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460,
-	0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
-	0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0,
-	0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
-	0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230,
-	0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
-	0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,
-	0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
-	0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ] );
-
-THREE.triTable = new Int32Array( [
-	- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 8, 3, 9, 8, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 8, 3, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 2, 10, 0, 2, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 8, 3, 2, 10, 8, 10, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 11, 2, 8, 11, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 9, 0, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 11, 2, 1, 9, 11, 9, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 10, 1, 11, 10, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 10, 1, 0, 8, 10, 8, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 9, 0, 3, 11, 9, 11, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 3, 0, 7, 3, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 1, 9, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 1, 9, 4, 7, 1, 7, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 2, 10, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 4, 7, 3, 0, 4, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 2, 10, 9, 0, 2, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
-	8, 4, 7, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	11, 4, 7, 11, 2, 4, 2, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 0, 1, 8, 4, 7, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, - 1, - 1, - 1, - 1,
-	3, 10, 1, 3, 11, 10, 7, 8, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, - 1, - 1, - 1, - 1,
-	4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
-	4, 7, 11, 4, 11, 9, 9, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 5, 4, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 5, 4, 1, 5, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	8, 5, 4, 8, 3, 5, 3, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 2, 10, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 0, 8, 1, 2, 10, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	5, 2, 10, 5, 4, 2, 4, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, - 1, - 1, - 1, - 1,
-	9, 5, 4, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 11, 2, 0, 8, 11, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 5, 4, 0, 1, 5, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, - 1, - 1, - 1, - 1,
-	10, 3, 11, 10, 1, 3, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, - 1, - 1, - 1, - 1,
-	5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
-	5, 4, 8, 5, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 7, 8, 5, 7, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 3, 0, 9, 5, 3, 5, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 7, 8, 0, 1, 7, 1, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 7, 8, 9, 5, 7, 10, 1, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, - 1, - 1, - 1, - 1,
-	8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, - 1, - 1, - 1, - 1,
-	2, 10, 5, 2, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	7, 9, 5, 7, 8, 9, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
-	2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, - 1, - 1, - 1, - 1,
-	11, 2, 1, 11, 1, 7, 7, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, - 1, - 1, - 1, - 1,
-	5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, - 1,
-	11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, - 1,
-	11, 10, 5, 7, 11, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 8, 3, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 0, 1, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 8, 3, 1, 9, 8, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 6, 5, 2, 6, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 6, 5, 1, 2, 6, 3, 0, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 6, 5, 9, 0, 6, 0, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, - 1, - 1, - 1, - 1,
-	2, 3, 11, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	11, 0, 8, 11, 2, 0, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 1, 9, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, - 1, - 1, - 1, - 1,
-	6, 3, 11, 6, 5, 3, 5, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
-	3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, - 1, - 1, - 1, - 1,
-	6, 5, 9, 6, 9, 11, 11, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	5, 10, 6, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 3, 0, 4, 7, 3, 6, 5, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 9, 0, 5, 10, 6, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
-	6, 1, 2, 6, 5, 1, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, - 1, - 1, - 1, - 1,
-	8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, - 1, - 1, - 1, - 1,
-	7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, - 1,
-	3, 11, 2, 7, 8, 4, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
-	0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1,
-	9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, - 1,
-	8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
-	5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, - 1,
-	0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, - 1,
-	6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, - 1, - 1, - 1, - 1,
-	10, 4, 9, 6, 4, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 10, 6, 4, 9, 10, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	10, 0, 1, 10, 6, 0, 6, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
-	1, 4, 9, 1, 2, 4, 2, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, - 1, - 1, - 1, - 1,
-	0, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	8, 3, 2, 8, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	10, 4, 9, 10, 6, 4, 11, 2, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, - 1, - 1, - 1, - 1,
-	3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
-	6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, - 1,
-	9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, - 1, - 1, - 1, - 1,
-	8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, - 1,
-	3, 11, 6, 3, 6, 0, 0, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	6, 4, 8, 11, 6, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	7, 10, 6, 7, 8, 10, 8, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, - 1, - 1, - 1, - 1,
-	10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, - 1, - 1, - 1, - 1,
-	10, 6, 7, 10, 7, 1, 1, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
-	2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, - 1,
-	7, 8, 0, 7, 0, 6, 6, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	7, 3, 2, 6, 7, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
-	2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, - 1,
-	1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, - 1,
-	11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, - 1, - 1, - 1, - 1,
-	8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, - 1,
-	0, 9, 1, 11, 6, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, - 1, - 1, - 1, - 1,
-	7, 11, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 0, 8, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 1, 9, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	8, 1, 9, 8, 3, 1, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	10, 1, 2, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 2, 10, 3, 0, 8, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 9, 0, 2, 10, 9, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, - 1, - 1, - 1, - 1,
-	7, 2, 3, 6, 2, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	7, 0, 8, 7, 6, 0, 6, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 7, 6, 2, 3, 7, 0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, - 1, - 1, - 1, - 1,
-	10, 7, 6, 10, 1, 7, 1, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, - 1, - 1, - 1, - 1,
-	0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, - 1, - 1, - 1, - 1,
-	7, 6, 10, 7, 10, 8, 8, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	6, 8, 4, 11, 8, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 6, 11, 3, 0, 6, 0, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	8, 6, 11, 8, 4, 6, 9, 0, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, - 1, - 1, - 1, - 1,
-	6, 8, 4, 6, 11, 8, 2, 10, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, - 1, - 1, - 1, - 1,
-	4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, - 1, - 1, - 1, - 1,
-	10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, - 1,
-	8, 2, 3, 8, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, - 1, - 1, - 1, - 1,
-	1, 9, 4, 1, 4, 2, 2, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, - 1, - 1, - 1, - 1,
-	10, 1, 0, 10, 0, 6, 6, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, - 1,
-	10, 9, 4, 6, 10, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 9, 5, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 8, 3, 4, 9, 5, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	5, 0, 1, 5, 4, 0, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, - 1, - 1, - 1, - 1,
-	9, 5, 4, 10, 1, 2, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, - 1, - 1, - 1, - 1,
-	7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, - 1, - 1, - 1, - 1,
-	3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, - 1,
-	7, 2, 3, 7, 6, 2, 5, 4, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, - 1, - 1, - 1, - 1,
-	3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, - 1, - 1, - 1, - 1,
-	6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, - 1,
-	9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, - 1, - 1, - 1, - 1,
-	1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, - 1,
-	4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, - 1,
-	7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, - 1, - 1, - 1, - 1,
-	6, 9, 5, 6, 11, 9, 11, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, - 1, - 1, - 1, - 1,
-	0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, - 1, - 1, - 1, - 1,
-	6, 11, 3, 6, 3, 5, 5, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, - 1, - 1, - 1, - 1,
-	0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, - 1,
-	11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, - 1,
-	6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, - 1, - 1, - 1, - 1,
-	5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, - 1, - 1, - 1, - 1,
-	9, 5, 6, 9, 6, 0, 0, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, - 1,
-	1, 5, 6, 2, 1, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, - 1,
-	10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, - 1, - 1, - 1, - 1,
-	0, 3, 8, 5, 6, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	10, 5, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	11, 5, 10, 7, 5, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	11, 5, 10, 11, 7, 5, 8, 3, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	5, 11, 7, 5, 10, 11, 1, 9, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, - 1, - 1, - 1, - 1,
-	11, 1, 2, 11, 7, 1, 7, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, - 1, - 1, - 1, - 1,
-	9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, - 1, - 1, - 1, - 1,
-	7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, - 1,
-	2, 5, 10, 2, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, - 1, - 1, - 1, - 1,
-	9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, - 1, - 1, - 1, - 1,
-	9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, - 1,
-	1, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 8, 7, 0, 7, 1, 1, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 0, 3, 9, 3, 5, 5, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 8, 7, 5, 9, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	5, 8, 4, 5, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, - 1, - 1, - 1, - 1,
-	0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, - 1, - 1, - 1, - 1,
-	10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, - 1,
-	2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, - 1, - 1, - 1, - 1,
-	0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, - 1,
-	0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, - 1,
-	9, 4, 5, 2, 11, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, - 1, - 1, - 1, - 1,
-	5, 10, 2, 5, 2, 4, 4, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, - 1,
-	5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, - 1, - 1, - 1, - 1,
-	8, 4, 5, 8, 5, 3, 3, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 4, 5, 1, 0, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, - 1, - 1, - 1, - 1,
-	9, 4, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 11, 7, 4, 9, 11, 9, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, - 1, - 1, - 1, - 1,
-	1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, - 1, - 1, - 1, - 1,
-	3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, - 1,
-	4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, - 1, - 1, - 1, - 1,
-	9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, - 1,
-	11, 7, 4, 11, 4, 2, 2, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, - 1, - 1, - 1, - 1,
-	2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, - 1, - 1, - 1, - 1,
-	9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, - 1,
-	3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, - 1,
-	1, 10, 2, 8, 7, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 9, 1, 4, 1, 7, 7, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, - 1, - 1, - 1, - 1,
-	4, 0, 3, 7, 4, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	4, 8, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 0, 9, 3, 9, 11, 11, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 1, 10, 0, 10, 8, 8, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 1, 10, 11, 3, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 2, 11, 1, 11, 9, 9, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, - 1, - 1, - 1, - 1,
-	0, 2, 11, 8, 0, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	3, 2, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 3, 8, 2, 8, 10, 10, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	9, 10, 2, 0, 9, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, - 1, - 1, - 1, - 1,
-	1, 10, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	1, 3, 8, 9, 1, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 9, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	0, 3, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
-	- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 ] );
+	THREE.MarchingCubes.prototype = Object.create( THREE.ImmediateRenderObject.prototype );
+	THREE.MarchingCubes.prototype.constructor = THREE.MarchingCubes;
+
+
+	/////////////////////////////////////
+	// Marching cubes lookup tables
+	/////////////////////////////////////
+
+	// These tables are straight from Paul Bourke's page:
+	// http://local.wasp.uwa.edu.au/~pbourke/geometry/polygonise/
+	// who in turn got them from Cory Gene Bloyd.
+
+	var EdgeTable = new Int32Array( [
+		0x0, 0x109, 0x203, 0x30a, 0x406, 0x50f, 0x605, 0x70c,
+		0x80c, 0x905, 0xa0f, 0xb06, 0xc0a, 0xd03, 0xe09, 0xf00,
+		0x190, 0x99, 0x393, 0x29a, 0x596, 0x49f, 0x795, 0x69c,
+		0x99c, 0x895, 0xb9f, 0xa96, 0xd9a, 0xc93, 0xf99, 0xe90,
+		0x230, 0x339, 0x33, 0x13a, 0x636, 0x73f, 0x435, 0x53c,
+		0xa3c, 0xb35, 0x83f, 0x936, 0xe3a, 0xf33, 0xc39, 0xd30,
+		0x3a0, 0x2a9, 0x1a3, 0xaa, 0x7a6, 0x6af, 0x5a5, 0x4ac,
+		0xbac, 0xaa5, 0x9af, 0x8a6, 0xfaa, 0xea3, 0xda9, 0xca0,
+		0x460, 0x569, 0x663, 0x76a, 0x66, 0x16f, 0x265, 0x36c,
+		0xc6c, 0xd65, 0xe6f, 0xf66, 0x86a, 0x963, 0xa69, 0xb60,
+		0x5f0, 0x4f9, 0x7f3, 0x6fa, 0x1f6, 0xff, 0x3f5, 0x2fc,
+		0xdfc, 0xcf5, 0xfff, 0xef6, 0x9fa, 0x8f3, 0xbf9, 0xaf0,
+		0x650, 0x759, 0x453, 0x55a, 0x256, 0x35f, 0x55, 0x15c,
+		0xe5c, 0xf55, 0xc5f, 0xd56, 0xa5a, 0xb53, 0x859, 0x950,
+		0x7c0, 0x6c9, 0x5c3, 0x4ca, 0x3c6, 0x2cf, 0x1c5, 0xcc,
+		0xfcc, 0xec5, 0xdcf, 0xcc6, 0xbca, 0xac3, 0x9c9, 0x8c0,
+		0x8c0, 0x9c9, 0xac3, 0xbca, 0xcc6, 0xdcf, 0xec5, 0xfcc,
+		0xcc, 0x1c5, 0x2cf, 0x3c6, 0x4ca, 0x5c3, 0x6c9, 0x7c0,
+		0x950, 0x859, 0xb53, 0xa5a, 0xd56, 0xc5f, 0xf55, 0xe5c,
+		0x15c, 0x55, 0x35f, 0x256, 0x55a, 0x453, 0x759, 0x650,
+		0xaf0, 0xbf9, 0x8f3, 0x9fa, 0xef6, 0xfff, 0xcf5, 0xdfc,
+		0x2fc, 0x3f5, 0xff, 0x1f6, 0x6fa, 0x7f3, 0x4f9, 0x5f0,
+		0xb60, 0xa69, 0x963, 0x86a, 0xf66, 0xe6f, 0xd65, 0xc6c,
+		0x36c, 0x265, 0x16f, 0x66, 0x76a, 0x663, 0x569, 0x460,
+		0xca0, 0xda9, 0xea3, 0xfaa, 0x8a6, 0x9af, 0xaa5, 0xbac,
+		0x4ac, 0x5a5, 0x6af, 0x7a6, 0xaa, 0x1a3, 0x2a9, 0x3a0,
+		0xd30, 0xc39, 0xf33, 0xe3a, 0x936, 0x83f, 0xb35, 0xa3c,
+		0x53c, 0x435, 0x73f, 0x636, 0x13a, 0x33, 0x339, 0x230,
+		0xe90, 0xf99, 0xc93, 0xd9a, 0xa96, 0xb9f, 0x895, 0x99c,
+		0x69c, 0x795, 0x49f, 0x596, 0x29a, 0x393, 0x99, 0x190,
+		0xf00, 0xe09, 0xd03, 0xc0a, 0xb06, 0xa0f, 0x905, 0x80c,
+		0x70c, 0x605, 0x50f, 0x406, 0x30a, 0x203, 0x109, 0x0 ] );
+
+	var TriTable = new Int32Array( [
+		- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 8, 3, 9, 8, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 8, 3, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 2, 10, 0, 2, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 8, 3, 2, 10, 8, 10, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 11, 2, 8, 11, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 9, 0, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 11, 2, 1, 9, 11, 9, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 10, 1, 11, 10, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 10, 1, 0, 8, 10, 8, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 9, 0, 3, 11, 9, 11, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 3, 0, 7, 3, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 1, 9, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 1, 9, 4, 7, 1, 7, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 2, 10, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 4, 7, 3, 0, 4, 1, 2, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 2, 10, 9, 0, 2, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 10, 9, 2, 9, 7, 2, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
+		8, 4, 7, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		11, 4, 7, 11, 2, 4, 2, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 0, 1, 8, 4, 7, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 7, 11, 9, 4, 11, 9, 11, 2, 9, 2, 1, - 1, - 1, - 1, - 1,
+		3, 10, 1, 3, 11, 10, 7, 8, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 11, 10, 1, 4, 11, 1, 0, 4, 7, 11, 4, - 1, - 1, - 1, - 1,
+		4, 7, 8, 9, 0, 11, 9, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
+		4, 7, 11, 4, 11, 9, 9, 11, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 5, 4, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 5, 4, 1, 5, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		8, 5, 4, 8, 3, 5, 3, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 2, 10, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 0, 8, 1, 2, 10, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		5, 2, 10, 5, 4, 2, 4, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 10, 5, 3, 2, 5, 3, 5, 4, 3, 4, 8, - 1, - 1, - 1, - 1,
+		9, 5, 4, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 11, 2, 0, 8, 11, 4, 9, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 5, 4, 0, 1, 5, 2, 3, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 1, 5, 2, 5, 8, 2, 8, 11, 4, 8, 5, - 1, - 1, - 1, - 1,
+		10, 3, 11, 10, 1, 3, 9, 5, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 9, 5, 0, 8, 1, 8, 10, 1, 8, 11, 10, - 1, - 1, - 1, - 1,
+		5, 4, 0, 5, 0, 11, 5, 11, 10, 11, 0, 3, - 1, - 1, - 1, - 1,
+		5, 4, 8, 5, 8, 10, 10, 8, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 7, 8, 5, 7, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 3, 0, 9, 5, 3, 5, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 7, 8, 0, 1, 7, 1, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 7, 8, 9, 5, 7, 10, 1, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		10, 1, 2, 9, 5, 0, 5, 3, 0, 5, 7, 3, - 1, - 1, - 1, - 1,
+		8, 0, 2, 8, 2, 5, 8, 5, 7, 10, 5, 2, - 1, - 1, - 1, - 1,
+		2, 10, 5, 2, 5, 3, 3, 5, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		7, 9, 5, 7, 8, 9, 3, 11, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 5, 7, 9, 7, 2, 9, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
+		2, 3, 11, 0, 1, 8, 1, 7, 8, 1, 5, 7, - 1, - 1, - 1, - 1,
+		11, 2, 1, 11, 1, 7, 7, 1, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 5, 8, 8, 5, 7, 10, 1, 3, 10, 3, 11, - 1, - 1, - 1, - 1,
+		5, 7, 0, 5, 0, 9, 7, 11, 0, 1, 0, 10, 11, 10, 0, - 1,
+		11, 10, 0, 11, 0, 3, 10, 5, 0, 8, 0, 7, 5, 7, 0, - 1,
+		11, 10, 5, 7, 11, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 8, 3, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 0, 1, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 8, 3, 1, 9, 8, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 6, 5, 2, 6, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 6, 5, 1, 2, 6, 3, 0, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 6, 5, 9, 0, 6, 0, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		5, 9, 8, 5, 8, 2, 5, 2, 6, 3, 2, 8, - 1, - 1, - 1, - 1,
+		2, 3, 11, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		11, 0, 8, 11, 2, 0, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 1, 9, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		5, 10, 6, 1, 9, 2, 9, 11, 2, 9, 8, 11, - 1, - 1, - 1, - 1,
+		6, 3, 11, 6, 5, 3, 5, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 8, 11, 0, 11, 5, 0, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
+		3, 11, 6, 0, 3, 6, 0, 6, 5, 0, 5, 9, - 1, - 1, - 1, - 1,
+		6, 5, 9, 6, 9, 11, 11, 9, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		5, 10, 6, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 3, 0, 4, 7, 3, 6, 5, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 9, 0, 5, 10, 6, 8, 4, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		10, 6, 5, 1, 9, 7, 1, 7, 3, 7, 9, 4, - 1, - 1, - 1, - 1,
+		6, 1, 2, 6, 5, 1, 4, 7, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 2, 5, 5, 2, 6, 3, 0, 4, 3, 4, 7, - 1, - 1, - 1, - 1,
+		8, 4, 7, 9, 0, 5, 0, 6, 5, 0, 2, 6, - 1, - 1, - 1, - 1,
+		7, 3, 9, 7, 9, 4, 3, 2, 9, 5, 9, 6, 2, 6, 9, - 1,
+		3, 11, 2, 7, 8, 4, 10, 6, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		5, 10, 6, 4, 7, 2, 4, 2, 0, 2, 7, 11, - 1, - 1, - 1, - 1,
+		0, 1, 9, 4, 7, 8, 2, 3, 11, 5, 10, 6, - 1, - 1, - 1, - 1,
+		9, 2, 1, 9, 11, 2, 9, 4, 11, 7, 11, 4, 5, 10, 6, - 1,
+		8, 4, 7, 3, 11, 5, 3, 5, 1, 5, 11, 6, - 1, - 1, - 1, - 1,
+		5, 1, 11, 5, 11, 6, 1, 0, 11, 7, 11, 4, 0, 4, 11, - 1,
+		0, 5, 9, 0, 6, 5, 0, 3, 6, 11, 6, 3, 8, 4, 7, - 1,
+		6, 5, 9, 6, 9, 11, 4, 7, 9, 7, 11, 9, - 1, - 1, - 1, - 1,
+		10, 4, 9, 6, 4, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 10, 6, 4, 9, 10, 0, 8, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		10, 0, 1, 10, 6, 0, 6, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		8, 3, 1, 8, 1, 6, 8, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
+		1, 4, 9, 1, 2, 4, 2, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 0, 8, 1, 2, 9, 2, 4, 9, 2, 6, 4, - 1, - 1, - 1, - 1,
+		0, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		8, 3, 2, 8, 2, 4, 4, 2, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		10, 4, 9, 10, 6, 4, 11, 2, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 8, 2, 2, 8, 11, 4, 9, 10, 4, 10, 6, - 1, - 1, - 1, - 1,
+		3, 11, 2, 0, 1, 6, 0, 6, 4, 6, 1, 10, - 1, - 1, - 1, - 1,
+		6, 4, 1, 6, 1, 10, 4, 8, 1, 2, 1, 11, 8, 11, 1, - 1,
+		9, 6, 4, 9, 3, 6, 9, 1, 3, 11, 6, 3, - 1, - 1, - 1, - 1,
+		8, 11, 1, 8, 1, 0, 11, 6, 1, 9, 1, 4, 6, 4, 1, - 1,
+		3, 11, 6, 3, 6, 0, 0, 6, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		6, 4, 8, 11, 6, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		7, 10, 6, 7, 8, 10, 8, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 7, 3, 0, 10, 7, 0, 9, 10, 6, 7, 10, - 1, - 1, - 1, - 1,
+		10, 6, 7, 1, 10, 7, 1, 7, 8, 1, 8, 0, - 1, - 1, - 1, - 1,
+		10, 6, 7, 10, 7, 1, 1, 7, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 2, 6, 1, 6, 8, 1, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
+		2, 6, 9, 2, 9, 1, 6, 7, 9, 0, 9, 3, 7, 3, 9, - 1,
+		7, 8, 0, 7, 0, 6, 6, 0, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		7, 3, 2, 6, 7, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 3, 11, 10, 6, 8, 10, 8, 9, 8, 6, 7, - 1, - 1, - 1, - 1,
+		2, 0, 7, 2, 7, 11, 0, 9, 7, 6, 7, 10, 9, 10, 7, - 1,
+		1, 8, 0, 1, 7, 8, 1, 10, 7, 6, 7, 10, 2, 3, 11, - 1,
+		11, 2, 1, 11, 1, 7, 10, 6, 1, 6, 7, 1, - 1, - 1, - 1, - 1,
+		8, 9, 6, 8, 6, 7, 9, 1, 6, 11, 6, 3, 1, 3, 6, - 1,
+		0, 9, 1, 11, 6, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		7, 8, 0, 7, 0, 6, 3, 11, 0, 11, 6, 0, - 1, - 1, - 1, - 1,
+		7, 11, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 0, 8, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 1, 9, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		8, 1, 9, 8, 3, 1, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		10, 1, 2, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 2, 10, 3, 0, 8, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 9, 0, 2, 10, 9, 6, 11, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		6, 11, 7, 2, 10, 3, 10, 8, 3, 10, 9, 8, - 1, - 1, - 1, - 1,
+		7, 2, 3, 6, 2, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		7, 0, 8, 7, 6, 0, 6, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 7, 6, 2, 3, 7, 0, 1, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 6, 2, 1, 8, 6, 1, 9, 8, 8, 7, 6, - 1, - 1, - 1, - 1,
+		10, 7, 6, 10, 1, 7, 1, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		10, 7, 6, 1, 7, 10, 1, 8, 7, 1, 0, 8, - 1, - 1, - 1, - 1,
+		0, 3, 7, 0, 7, 10, 0, 10, 9, 6, 10, 7, - 1, - 1, - 1, - 1,
+		7, 6, 10, 7, 10, 8, 8, 10, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		6, 8, 4, 11, 8, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 6, 11, 3, 0, 6, 0, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		8, 6, 11, 8, 4, 6, 9, 0, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 4, 6, 9, 6, 3, 9, 3, 1, 11, 3, 6, - 1, - 1, - 1, - 1,
+		6, 8, 4, 6, 11, 8, 2, 10, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 2, 10, 3, 0, 11, 0, 6, 11, 0, 4, 6, - 1, - 1, - 1, - 1,
+		4, 11, 8, 4, 6, 11, 0, 2, 9, 2, 10, 9, - 1, - 1, - 1, - 1,
+		10, 9, 3, 10, 3, 2, 9, 4, 3, 11, 3, 6, 4, 6, 3, - 1,
+		8, 2, 3, 8, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 4, 2, 4, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 9, 0, 2, 3, 4, 2, 4, 6, 4, 3, 8, - 1, - 1, - 1, - 1,
+		1, 9, 4, 1, 4, 2, 2, 4, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		8, 1, 3, 8, 6, 1, 8, 4, 6, 6, 10, 1, - 1, - 1, - 1, - 1,
+		10, 1, 0, 10, 0, 6, 6, 0, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 6, 3, 4, 3, 8, 6, 10, 3, 0, 3, 9, 10, 9, 3, - 1,
+		10, 9, 4, 6, 10, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 9, 5, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 8, 3, 4, 9, 5, 11, 7, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		5, 0, 1, 5, 4, 0, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		11, 7, 6, 8, 3, 4, 3, 5, 4, 3, 1, 5, - 1, - 1, - 1, - 1,
+		9, 5, 4, 10, 1, 2, 7, 6, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		6, 11, 7, 1, 2, 10, 0, 8, 3, 4, 9, 5, - 1, - 1, - 1, - 1,
+		7, 6, 11, 5, 4, 10, 4, 2, 10, 4, 0, 2, - 1, - 1, - 1, - 1,
+		3, 4, 8, 3, 5, 4, 3, 2, 5, 10, 5, 2, 11, 7, 6, - 1,
+		7, 2, 3, 7, 6, 2, 5, 4, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 5, 4, 0, 8, 6, 0, 6, 2, 6, 8, 7, - 1, - 1, - 1, - 1,
+		3, 6, 2, 3, 7, 6, 1, 5, 0, 5, 4, 0, - 1, - 1, - 1, - 1,
+		6, 2, 8, 6, 8, 7, 2, 1, 8, 4, 8, 5, 1, 5, 8, - 1,
+		9, 5, 4, 10, 1, 6, 1, 7, 6, 1, 3, 7, - 1, - 1, - 1, - 1,
+		1, 6, 10, 1, 7, 6, 1, 0, 7, 8, 7, 0, 9, 5, 4, - 1,
+		4, 0, 10, 4, 10, 5, 0, 3, 10, 6, 10, 7, 3, 7, 10, - 1,
+		7, 6, 10, 7, 10, 8, 5, 4, 10, 4, 8, 10, - 1, - 1, - 1, - 1,
+		6, 9, 5, 6, 11, 9, 11, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 6, 11, 0, 6, 3, 0, 5, 6, 0, 9, 5, - 1, - 1, - 1, - 1,
+		0, 11, 8, 0, 5, 11, 0, 1, 5, 5, 6, 11, - 1, - 1, - 1, - 1,
+		6, 11, 3, 6, 3, 5, 5, 3, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 2, 10, 9, 5, 11, 9, 11, 8, 11, 5, 6, - 1, - 1, - 1, - 1,
+		0, 11, 3, 0, 6, 11, 0, 9, 6, 5, 6, 9, 1, 2, 10, - 1,
+		11, 8, 5, 11, 5, 6, 8, 0, 5, 10, 5, 2, 0, 2, 5, - 1,
+		6, 11, 3, 6, 3, 5, 2, 10, 3, 10, 5, 3, - 1, - 1, - 1, - 1,
+		5, 8, 9, 5, 2, 8, 5, 6, 2, 3, 8, 2, - 1, - 1, - 1, - 1,
+		9, 5, 6, 9, 6, 0, 0, 6, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 5, 8, 1, 8, 0, 5, 6, 8, 3, 8, 2, 6, 2, 8, - 1,
+		1, 5, 6, 2, 1, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 3, 6, 1, 6, 10, 3, 8, 6, 5, 6, 9, 8, 9, 6, - 1,
+		10, 1, 0, 10, 0, 6, 9, 5, 0, 5, 6, 0, - 1, - 1, - 1, - 1,
+		0, 3, 8, 5, 6, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		10, 5, 6, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		11, 5, 10, 7, 5, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		11, 5, 10, 11, 7, 5, 8, 3, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		5, 11, 7, 5, 10, 11, 1, 9, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		10, 7, 5, 10, 11, 7, 9, 8, 1, 8, 3, 1, - 1, - 1, - 1, - 1,
+		11, 1, 2, 11, 7, 1, 7, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 8, 3, 1, 2, 7, 1, 7, 5, 7, 2, 11, - 1, - 1, - 1, - 1,
+		9, 7, 5, 9, 2, 7, 9, 0, 2, 2, 11, 7, - 1, - 1, - 1, - 1,
+		7, 5, 2, 7, 2, 11, 5, 9, 2, 3, 2, 8, 9, 8, 2, - 1,
+		2, 5, 10, 2, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		8, 2, 0, 8, 5, 2, 8, 7, 5, 10, 2, 5, - 1, - 1, - 1, - 1,
+		9, 0, 1, 5, 10, 3, 5, 3, 7, 3, 10, 2, - 1, - 1, - 1, - 1,
+		9, 8, 2, 9, 2, 1, 8, 7, 2, 10, 2, 5, 7, 5, 2, - 1,
+		1, 3, 5, 3, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 8, 7, 0, 7, 1, 1, 7, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 0, 3, 9, 3, 5, 5, 3, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 8, 7, 5, 9, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		5, 8, 4, 5, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		5, 0, 4, 5, 11, 0, 5, 10, 11, 11, 3, 0, - 1, - 1, - 1, - 1,
+		0, 1, 9, 8, 4, 10, 8, 10, 11, 10, 4, 5, - 1, - 1, - 1, - 1,
+		10, 11, 4, 10, 4, 5, 11, 3, 4, 9, 4, 1, 3, 1, 4, - 1,
+		2, 5, 1, 2, 8, 5, 2, 11, 8, 4, 5, 8, - 1, - 1, - 1, - 1,
+		0, 4, 11, 0, 11, 3, 4, 5, 11, 2, 11, 1, 5, 1, 11, - 1,
+		0, 2, 5, 0, 5, 9, 2, 11, 5, 4, 5, 8, 11, 8, 5, - 1,
+		9, 4, 5, 2, 11, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 5, 10, 3, 5, 2, 3, 4, 5, 3, 8, 4, - 1, - 1, - 1, - 1,
+		5, 10, 2, 5, 2, 4, 4, 2, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 10, 2, 3, 5, 10, 3, 8, 5, 4, 5, 8, 0, 1, 9, - 1,
+		5, 10, 2, 5, 2, 4, 1, 9, 2, 9, 4, 2, - 1, - 1, - 1, - 1,
+		8, 4, 5, 8, 5, 3, 3, 5, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 4, 5, 1, 0, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		8, 4, 5, 8, 5, 3, 9, 0, 5, 0, 3, 5, - 1, - 1, - 1, - 1,
+		9, 4, 5, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 11, 7, 4, 9, 11, 9, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 8, 3, 4, 9, 7, 9, 11, 7, 9, 10, 11, - 1, - 1, - 1, - 1,
+		1, 10, 11, 1, 11, 4, 1, 4, 0, 7, 4, 11, - 1, - 1, - 1, - 1,
+		3, 1, 4, 3, 4, 8, 1, 10, 4, 7, 4, 11, 10, 11, 4, - 1,
+		4, 11, 7, 9, 11, 4, 9, 2, 11, 9, 1, 2, - 1, - 1, - 1, - 1,
+		9, 7, 4, 9, 11, 7, 9, 1, 11, 2, 11, 1, 0, 8, 3, - 1,
+		11, 7, 4, 11, 4, 2, 2, 4, 0, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		11, 7, 4, 11, 4, 2, 8, 3, 4, 3, 2, 4, - 1, - 1, - 1, - 1,
+		2, 9, 10, 2, 7, 9, 2, 3, 7, 7, 4, 9, - 1, - 1, - 1, - 1,
+		9, 10, 7, 9, 7, 4, 10, 2, 7, 8, 7, 0, 2, 0, 7, - 1,
+		3, 7, 10, 3, 10, 2, 7, 4, 10, 1, 10, 0, 4, 0, 10, - 1,
+		1, 10, 2, 8, 7, 4, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 9, 1, 4, 1, 7, 7, 1, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 9, 1, 4, 1, 7, 0, 8, 1, 8, 7, 1, - 1, - 1, - 1, - 1,
+		4, 0, 3, 7, 4, 3, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		4, 8, 7, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 10, 8, 10, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 0, 9, 3, 9, 11, 11, 9, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 1, 10, 0, 10, 8, 8, 10, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 1, 10, 11, 3, 10, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 2, 11, 1, 11, 9, 9, 11, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 0, 9, 3, 9, 11, 1, 2, 9, 2, 11, 9, - 1, - 1, - 1, - 1,
+		0, 2, 11, 8, 0, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		3, 2, 11, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 3, 8, 2, 8, 10, 10, 8, 9, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		9, 10, 2, 0, 9, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		2, 3, 8, 2, 8, 10, 0, 1, 8, 1, 10, 8, - 1, - 1, - 1, - 1,
+		1, 10, 2, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		1, 3, 8, 9, 1, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 9, 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		0, 3, 8, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1,
+		- 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1, - 1 ] );
+
+} )( THREE )

+ 1 - 1
examples/js/controls/DragControls.js

@@ -154,7 +154,7 @@ THREE.DragControls = function ( _objects, _camera, _domElement ) {
 
 		}
 
-		_domElement.style.cursor = 'auto';
+		_domElement.style.cursor = _hovered ? 'pointer' : 'auto';
 
 	}
 

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

@@ -21,6 +21,8 @@ THREE.EditorControls = function ( object, domElement ) {
 
 	var scope = this;
 	var vector = new THREE.Vector3();
+	var delta = new THREE.Vector3();
+	var box = new THREE.Box3();
 
 	var STATE = { NONE: - 1, ROTATE: 0, ZOOM: 1, PAN: 2 };
 	var state = STATE.NONE;
@@ -37,10 +39,10 @@ THREE.EditorControls = function ( object, domElement ) {
 
 	this.focus = function ( target ) {
 
-		var box = new THREE.Box3().setFromObject( target );
-
 		var distance;
 
+		box.setFromObject( target );
+
 		if ( box.isEmpty() === false ) {
 
 			center.copy( box.getCenter() );
@@ -55,7 +57,7 @@ THREE.EditorControls = function ( object, domElement ) {
 
 		}
 
-		var delta = new THREE.Vector3( 0, 0, 1 );
+		delta.set( 0, 0, 1 );
 		delta.applyQuaternion( object.quaternion );
 		delta.multiplyScalar( distance * 4 );
 
@@ -156,15 +158,15 @@ THREE.EditorControls = function ( object, domElement ) {
 
 		if ( state === STATE.ROTATE ) {
 
-			scope.rotate( new THREE.Vector3( - movementX * scope.rotationSpeed, - movementY * scope.rotationSpeed, 0 ) );
+			scope.rotate( delta.set( - movementX * scope.rotationSpeed, - movementY * scope.rotationSpeed, 0 ) );
 
 		} else if ( state === STATE.ZOOM ) {
 
-			scope.zoom( new THREE.Vector3( 0, 0, movementY ) );
+			scope.zoom( delta.set( 0, 0, movementY ) );
 
 		} else if ( state === STATE.PAN ) {
 
-			scope.pan( new THREE.Vector3( - movementX, movementY, 0 ) );
+			scope.pan( delta.set( - movementX, movementY, 0 ) );
 
 		}
 
@@ -188,7 +190,7 @@ THREE.EditorControls = function ( object, domElement ) {
 		event.preventDefault();
 
 		// Normalize deltaY due to https://bugzilla.mozilla.org/show_bug.cgi?id=1392460
-		scope.zoom( new THREE.Vector3( 0, 0, event.deltaY > 0 ? 1 : - 1 ) );
+		scope.zoom( delta.set( 0, 0, event.deltaY > 0 ? 1 : - 1 ) );
 
 	}
 
@@ -283,7 +285,7 @@ THREE.EditorControls = function ( object, domElement ) {
 				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
 				touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 );
 				var distance = touches[ 0 ].distanceTo( touches[ 1 ] );
-				scope.zoom( new THREE.Vector3( 0, 0, prevDistance - distance ) );
+				scope.zoom( delta.set( 0, 0, prevDistance - distance ) );
 				prevDistance = distance;
 
 

+ 23 - 12
examples/js/controls/MapControls.js

@@ -11,11 +11,10 @@
 // Unlike TrackballControls, it maintains the "up" direction object.up (+Y by default).
 // This is very similar to OrbitControls, another set of touch behavior
 //
-//    Orbit - right mouse / touch: two-finger rotate
+//    Orbit - right mouse, or left mouse + ctrl/metaKey / touch: two-finger rotate
 //    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
 //    Pan - left mouse, or arrow keys / touch: one-finger move
 
-
 THREE.MapControls = function ( object, domElement ) {
 
 	this.object = object;
@@ -78,7 +77,7 @@ THREE.MapControls = function ( object, domElement ) {
 	this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
 
 	// Mouse buttons
-	this.mouseButtons = { ORBIT: THREE.MOUSE.RIGHT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.LEFT };
+	this.mouseButtons = { LEFT: THREE.MOUSE.LEFT, MIDDLE: THREE.MOUSE.MIDDLE, RIGHT: THREE.MOUSE.RIGHT };
 
 	// for reset
 	this.target0 = this.target.clone();
@@ -776,17 +775,29 @@ THREE.MapControls = function ( object, domElement ) {
 
 		switch ( event.button ) {
 
-			case scope.mouseButtons.ORBIT:
+			case scope.mouseButtons.LEFT:
 
-				if ( scope.enableRotate === false ) return;
+				if ( event.ctrlKey || event.metaKey ) {
 
-				handleMouseDownRotate( event );
+					if ( scope.enableRotate === false ) return;
 
-				state = STATE.ROTATE;
+					handleMouseDownRotate( event );
+
+					state = STATE.ROTATE;
+
+				} else {
+
+					if ( scope.enablePan === false ) return;
+
+					handleMouseDownPan( event );
+
+					state = STATE.PAN;
+
+				}
 
 				break;
 
-			case scope.mouseButtons.ZOOM:
+			case scope.mouseButtons.MIDDLE:
 
 				if ( scope.enableZoom === false ) return;
 
@@ -796,13 +807,13 @@ THREE.MapControls = function ( object, domElement ) {
 
 				break;
 
-			case scope.mouseButtons.PAN:
+			case scope.mouseButtons.RIGHT:
 
-				if ( scope.enablePan === false ) return;
+				if ( scope.enableRotate === false ) return;
 
-				handleMouseDownPan( event );
+				handleMouseDownRotate( event );
 
-				state = STATE.PAN;
+				state = STATE.ROTATE;
 
 				break;
 

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

@@ -11,7 +11,7 @@
 //
 //    Orbit - left mouse / touch: one-finger move
 //    Zoom - middle mouse, or mousewheel / touch: two-finger spread or squish
-//    Pan - right mouse, or arrow keys / touch: two-finger move
+//    Pan - right mouse, or left mouse + ctrl/metaKey, or arrow keys / touch: two-finger move
 
 THREE.OrbitControls = function ( object, domElement ) {
 
@@ -75,7 +75,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 	this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
 
 	// Mouse buttons
-	this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
+	this.mouseButtons = { LEFT: THREE.MOUSE.LEFT, MIDDLE: THREE.MOUSE.MIDDLE, RIGHT: THREE.MOUSE.RIGHT };
 
 	// for reset
 	this.target0 = this.target.clone();
@@ -677,17 +677,29 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 		switch ( event.button ) {
 
-			case scope.mouseButtons.ORBIT:
+			case scope.mouseButtons.LEFT:
 
-				if ( scope.enableRotate === false ) return;
+				if ( event.ctrlKey || event.metaKey ) {
+
+					if ( scope.enablePan === false ) return;
+
+					handleMouseDownPan( event );
+
+					state = STATE.PAN;
+
+				} else {
+
+					if ( scope.enableRotate === false ) return;
+
+					handleMouseDownRotate( event );
 
-				handleMouseDownRotate( event );
+					state = STATE.ROTATE;
 
-				state = STATE.ROTATE;
+				}
 
 				break;
 
-			case scope.mouseButtons.ZOOM:
+			case scope.mouseButtons.MIDDLE:
 
 				if ( scope.enableZoom === false ) return;
 
@@ -697,7 +709,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 				break;
 
-			case scope.mouseButtons.PAN:
+			case scope.mouseButtons.RIGHT:
 
 				if ( scope.enablePan === false ) return;
 

+ 17 - 5
examples/js/exporters/PLYExporter.js

@@ -6,10 +6,10 @@
  *  var exporter = new THREE.PLYExporter();
  *
  *  // second argument is a list of options
- *  var data = exporter.parse( mesh, { binary: true, excludeAttributes: [ 'color' ] } );
+ *  exporter.parse(mesh, data => console.log(data), { binary: true, excludeAttributes: [ 'color' ] });
  *
  * Format Definition:
- *  http://paulbourke.net/dataformats/ply/
+ * http://paulbourke.net/dataformats/ply/
  */
 
 THREE.PLYExporter = function () {};
@@ -18,7 +18,15 @@ THREE.PLYExporter.prototype = {
 
 	constructor: THREE.PLYExporter,
 
-	parse: function ( object, options ) {
+	parse: function ( object, onDone, options ) {
+
+		if ( onDone && typeof onDone === 'object' ) {
+
+			console.warn( 'THREE.PLYExporter: The options parameter is now the third argument to the "parse" function. See the documentation for the new API.' );
+			options = onDone;
+			onDone = undefined;
+
+		}
 
 		// Iterate over the valid meshes in the object
 		function traverseMeshes( cb ) {
@@ -208,6 +216,7 @@ THREE.PLYExporter.prototype = {
 		// Generate attribute data
 		var vertex = new THREE.Vector3();
 		var normalMatrixWorld = new THREE.Matrix3();
+		var result = null;
 
 		if ( options.binary === true ) {
 
@@ -399,7 +408,7 @@ THREE.PLYExporter.prototype = {
 
 			} );
 
-			return output;
+			result = output.buffer;
 
 		} else {
 
@@ -529,10 +538,13 @@ THREE.PLYExporter.prototype = {
 
 			} );
 
-			return `${ header }${vertexList}\n${ includeIndices ? `${faceList}\n` : '' }`;
+			result = `${ header }${vertexList}\n${ includeIndices ? `${faceList}\n` : '' }`;
 
 		}
 
+		if ( typeof onDone === 'function' ) requestAnimationFrame( () => onDone( result ) );
+		return result;
+
 	}
 
 };

+ 79 - 16
examples/js/loaders/ColladaLoader.js

@@ -969,11 +969,11 @@ THREE.ColladaLoader.prototype = {
 
 			if ( data.bindShapeMatrix ) {
 
-				build.bindMatrix = new THREE.Matrix4().fromArray( data.bindShapeMatrix ).transpose(); 
+				build.bindMatrix = new THREE.Matrix4().fromArray( data.bindShapeMatrix ).transpose();
 
 			} else {
 
-				build.bindMatrix = new THREE.Matrix4().transpose(); 
+				build.bindMatrix = new THREE.Matrix4().identity();
 
 			}
 
@@ -1449,6 +1449,28 @@ THREE.ColladaLoader.prototype = {
 
 		}
 
+		function getTextureLoader( image ) {
+
+			var loader;
+
+			var extension = image.slice( ( image.lastIndexOf( '.' ) - 1 >>> 0 ) + 2 ); // http://www.jstips.co/en/javascript/get-file-extension/
+			extension = extension.toLowerCase();
+
+			switch ( extension ) {
+
+				case 'tga':
+					loader = tgaLoader;
+					break;
+
+				default:
+					loader = textureLoader;
+
+			}
+
+			return loader;
+
+		}
+
 		function buildMaterial( data ) {
 
 			var effect = getEffect( data.url );
@@ -1499,28 +1521,40 @@ THREE.ColladaLoader.prototype = {
 
 				if ( image !== null ) {
 
-					var texture = textureLoader.load( image );
+					var loader = getTextureLoader( image );
+
+					if ( loader !== undefined ) {
+
+						var texture = loader.load( image );
+
+						var extra = textureObject.extra;
 
-					var extra = textureObject.extra;
+						if ( extra !== undefined && extra.technique !== undefined && isEmpty( extra.technique ) === false ) {
 
-					if ( extra !== undefined && extra.technique !== undefined && isEmpty( extra.technique ) === false ) {
+							var technique = extra.technique;
 
-						var technique = extra.technique;
+							texture.wrapS = technique.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
+							texture.wrapT = technique.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
 
-						texture.wrapS = technique.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
-						texture.wrapT = technique.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
+							texture.offset.set( technique.offsetU || 0, technique.offsetV || 0 );
+							texture.repeat.set( technique.repeatU || 1, technique.repeatV || 1 );
+
+						} else {
+
+							texture.wrapS = THREE.RepeatWrapping;
+							texture.wrapT = THREE.RepeatWrapping;
+
+						}
 
-						texture.offset.set( technique.offsetU || 0, technique.offsetV || 0 );
-						texture.repeat.set( technique.repeatU || 1, technique.repeatV || 1 );
+						return texture;
 
 					} else {
 
-						texture.wrapS = THREE.RepeatWrapping;
-						texture.wrapT = THREE.RepeatWrapping;
+						console.warn( 'THREE.ColladaLoader: Loader for texture %s not found.', image );
 
-					}
+						return null;
 
-					return texture;
+					}
 
 				} else {
 
@@ -3183,7 +3217,15 @@ THREE.ColladaLoader.prototype = {
 
 			}
 
-			library.nodes[ data.id ] = data;
+			if ( hasNode( data.id ) ) {
+
+				console.warn( 'THREE.ColladaLoader: There is already a node with ID %s. Exclude current node from further processing.', data.id );
+
+			} else {
+
+				library.nodes[ data.id ] = data;
+
+			}
 
 			return data;
 
@@ -3519,6 +3561,8 @@ THREE.ColladaLoader.prototype = {
 
 		}
 
+		var fallbackMaterial = new THREE.MeshBasicMaterial( { color: 0xff00ff } );
+
 		function resolveMaterialBinding( keys, instanceMaterials ) {
 
 			var materials = [];
@@ -3526,7 +3570,17 @@ THREE.ColladaLoader.prototype = {
 			for ( var i = 0, l = keys.length; i < l; i ++ ) {
 
 				var id = instanceMaterials[ keys[ i ] ];
-				materials.push( getMaterial( id ) );
+
+				if ( id === undefined ) {
+
+					console.warn( 'THREE.ColladaLoader: Material with key %s not found. Apply fallback material.', keys[ i ] );
+					materials.push( fallbackMaterial );
+
+				} else {
+
+					materials.push( getMaterial( id ) );
+
+				}
 
 			}
 
@@ -3749,6 +3803,15 @@ THREE.ColladaLoader.prototype = {
 		var textureLoader = new THREE.TextureLoader( this.manager );
 		textureLoader.setPath( path ).setCrossOrigin( this.crossOrigin );
 
+		var tgaLoader;
+
+		if ( THREE.TGALoader ) {
+
+			tgaLoader = new THREE.TGALoader( this.manager );
+			tgaLoader.setPath( path );
+
+		}
+
 		//
 
 		var animations = [];

文件差异内容过多而无法显示
+ 1653 - 1565
examples/js/loaders/FBXLoader.js


+ 59 - 84
examples/js/loaders/GLTFLoader.js

@@ -130,7 +130,7 @@ THREE.GLTFLoader = ( function () {
 
 					switch ( extensionName ) {
 
-						case EXTENSIONS.KHR_LIGHTS:
+						case EXTENSIONS.KHR_LIGHTS_PUNCTUAL:
 							extensions[ extensionName ] = new GLTFLightsExtension( json );
 							break;
 
@@ -237,7 +237,7 @@ THREE.GLTFLoader = ( function () {
 	var EXTENSIONS = {
 		KHR_BINARY_GLTF: 'KHR_binary_glTF',
 		KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
-		KHR_LIGHTS: 'KHR_lights',
+		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
 		MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
@@ -270,21 +270,24 @@ THREE.GLTFLoader = ( function () {
 	 */
 	function GLTFLightsExtension( json ) {
 
-		this.name = EXTENSIONS.KHR_LIGHTS;
+		this.name = EXTENSIONS.KHR_LIGHTS_PUNCTUAL;
 
-		this.lights = {};
+		this.lights = [];
 
-		var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_LIGHTS ] ) || {};
-		var lights = extension.lights || {};
+		var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ] ) || {};
+		var lightDefs = extension.lights || [];
 
-		for ( var lightId in lights ) {
+		for ( var i = 0; i < lightDefs.length; i ++ ) {
 
-			var light = lights[ lightId ];
+			var lightDef = lightDefs[ i ];
 			var lightNode;
 
-			var color = new THREE.Color().fromArray( light.color );
+			var color = new THREE.Color( 0xffffff );
+			if ( lightDef.color !== undefined ) color.fromArray( lightDef.color );
 
-			switch ( light.type ) {
+			var range = lightDef.range !== undefined ? lightDef.range : 0;
+
+			switch ( lightDef.type ) {
 
 				case 'directional':
 					lightNode = new THREE.DirectionalLight( color );
@@ -294,40 +297,34 @@ THREE.GLTFLoader = ( function () {
 
 				case 'point':
 					lightNode = new THREE.PointLight( color );
+					lightNode.distance = range;
 					break;
 
 				case 'spot':
 					lightNode = new THREE.SpotLight( color );
+					lightNode.distance = range;
 					// Handle spotlight properties.
-					light.spot = light.spot || {};
-					light.spot.innerConeAngle = light.spot.innerConeAngle !== undefined ? light.spot.innerConeAngle : 0;
-					light.spot.outerConeAngle = light.spot.outerConeAngle !== undefined ? light.spot.outerConeAngle : Math.PI / 4.0;
-					lightNode.angle = light.spot.outerConeAngle;
-					lightNode.penumbra = 1.0 - light.spot.innerConeAngle / light.spot.outerConeAngle;
+					lightDef.spot = lightDef.spot || {};
+					lightDef.spot.innerConeAngle = lightDef.spot.innerConeAngle !== undefined ? lightDef.spot.innerConeAngle : 0;
+					lightDef.spot.outerConeAngle = lightDef.spot.outerConeAngle !== undefined ? lightDef.spot.outerConeAngle : Math.PI / 4.0;
+					lightNode.angle = lightDef.spot.outerConeAngle;
+					lightNode.penumbra = 1.0 - lightDef.spot.innerConeAngle / lightDef.spot.outerConeAngle;
 					lightNode.target.position.set( 0, 0, 1 );
 					lightNode.add( lightNode.target );
 					break;
 
-				case 'ambient':
-					lightNode = new THREE.AmbientLight( color );
-					break;
+				default:
+					throw new Error( 'THREE.GLTFLoader: Unexpected light type, "' + lightDef.type + '".' );
 
 			}
 
-			if ( lightNode ) {
+			lightNode.decay = 2;
 
-				lightNode.decay = 2;
+			if ( lightDef.intensity !== undefined ) lightNode.intensity = lightDef.intensity;
 
-				if ( light.intensity !== undefined ) {
-
-					lightNode.intensity = light.intensity;
-
-				}
+			lightNode.name = lightDef.name || ( 'light_' + i );
 
-				lightNode.name = light.name || ( 'light_' + lightId );
-				this.lights[ lightId ] = lightNode;
-
-			}
+			this.lights.push( lightNode );
 
 		}
 
@@ -1019,21 +1016,6 @@ THREE.GLTFLoader = ( function () {
 		10497: THREE.RepeatWrapping
 	};
 
-	var WEBGL_TEXTURE_FORMATS = {
-		6406: THREE.AlphaFormat,
-		6407: THREE.RGBFormat,
-		6408: THREE.RGBAFormat,
-		6409: THREE.LuminanceFormat,
-		6410: THREE.LuminanceAlphaFormat
-	};
-
-	var WEBGL_TEXTURE_DATATYPES = {
-		5121: THREE.UnsignedByteType,
-		32819: THREE.UnsignedShort4444Type,
-		32820: THREE.UnsignedShort5551Type,
-		33635: THREE.UnsignedShort565Type
-	};
-
 	var WEBGL_SIDES = {
 		1028: THREE.BackSide, // Culling front
 		1029: THREE.FrontSide // Culling back
@@ -1188,6 +1170,28 @@ THREE.GLTFLoader = ( function () {
 
 	}
 
+	/**
+	 * @param {THREE.Object3D|THREE.Material|THREE.BufferGeometry} object
+	 * @param {GLTF.definition} def
+	 */
+	function assignExtrasToUserData( object, gltfDef ) {
+
+		if ( gltfDef.extras !== undefined ) {
+
+			if ( typeof gltfDef.extras === 'object' ) {
+
+				object.userData = gltfDef.extras;
+
+			} else {
+
+				console.warn( 'THREE.GLTFLoader: Ignoring primitive type .extras, ' + gltfDef.extras );
+
+			}
+
+		}
+
+	}
+
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#morph-targets
 	 *
@@ -2014,22 +2018,6 @@ THREE.GLTFLoader = ( function () {
 
 			if ( textureDef.name !== undefined ) texture.name = textureDef.name;
 
-			// .format of dds texture is set in DDSLoader
-			if ( ! textureExtensions[ EXTENSIONS.MSFT_TEXTURE_DDS ] ) {
-
-				texture.format = textureDef.format !== undefined ? WEBGL_TEXTURE_FORMATS[ textureDef.format ] : THREE.RGBAFormat;
-
-			}
-
-			if ( textureDef.internalFormat !== undefined && texture.format !== WEBGL_TEXTURE_FORMATS[ textureDef.internalFormat ] ) {
-
-				console.warn( 'THREE.GLTFLoader: Three.js does not support texture internalFormat which is different from texture format. ' +
-											'internalFormat will be forced to be the same value as format.' );
-
-			}
-
-			texture.type = textureDef.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ textureDef.type ] : THREE.UnsignedByteType;
-
 			var samplers = json.samplers || {};
 			var sampler = samplers[ textureDef.sampler ] || {};
 
@@ -2222,7 +2210,7 @@ THREE.GLTFLoader = ( function () {
 			if ( material.emissiveMap ) material.emissiveMap.encoding = THREE.sRGBEncoding;
 			if ( material.specularMap ) material.specularMap.encoding = THREE.sRGBEncoding;
 
-			if ( materialDef.extras ) material.userData = materialDef.extras;
+			assignExtrasToUserData( material, materialDef );
 
 			if ( materialDef.extensions ) addUnknownExtensionsToUserData( extensions, material, materialDef );
 
@@ -2266,11 +2254,7 @@ THREE.GLTFLoader = ( function () {
 
 		}
 
-		if ( primitiveDef.extras !== undefined ) {
-
-			geometry.userData = primitiveDef.extras;
-
-		}
+		assignExtrasToUserData( geometry, primitiveDef );
 
 	}
 
@@ -2539,7 +2523,7 @@ THREE.GLTFLoader = ( function () {
 
 					if ( geometries.length > 1 ) mesh.name += '_' + i;
 
-					if ( meshDef.extras !== undefined ) mesh.userData = meshDef.extras;
+					assignExtrasToUserData( mesh, meshDef );
 
 					meshes.push( mesh );
 
@@ -2707,7 +2691,8 @@ THREE.GLTFLoader = ( function () {
 		}
 
 		if ( cameraDef.name !== undefined ) camera.name = cameraDef.name;
-		if ( cameraDef.extras ) camera.userData = cameraDef.extras;
+
+		assignExtrasToUserData( camera, cameraDef );
 
 		return Promise.resolve( camera );
 
@@ -2956,11 +2941,11 @@ THREE.GLTFLoader = ( function () {
 				node = dependencies.cameras[ nodeDef.camera ];
 
 			} else if ( nodeDef.extensions
-					 && nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS ]
-					 && nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS ].light !== undefined ) {
+					 && nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ]
+					 && nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light !== undefined ) {
 
-				var lights = extensions[ EXTENSIONS.KHR_LIGHTS ].lights;
-				node = lights[ nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS ].light ];
+				var lights = extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].lights;
+				node = lights[ nodeDef.extensions[ EXTENSIONS.KHR_LIGHTS_PUNCTUAL ].light ];
 
 			} else {
 
@@ -2974,7 +2959,7 @@ THREE.GLTFLoader = ( function () {
 
 			}
 
-			if ( nodeDef.extras ) node.userData = nodeDef.extras;
+			assignExtrasToUserData( node, nodeDef );
 
 			if ( nodeDef.extensions ) addUnknownExtensionsToUserData( extensions, node, nodeDef );
 
@@ -3108,7 +3093,7 @@ THREE.GLTFLoader = ( function () {
 				var scene = new THREE.Scene();
 				if ( sceneDef.name !== undefined ) scene.name = sceneDef.name;
 
-				if ( sceneDef.extras ) scene.userData = sceneDef.extras;
+				assignExtrasToUserData( scene, sceneDef );
 
 				if ( sceneDef.extensions ) addUnknownExtensionsToUserData( extensions, scene, sceneDef );
 
@@ -3120,16 +3105,6 @@ THREE.GLTFLoader = ( function () {
 
 				}
 
-				// Ambient lighting, if present, is always attached to the scene root.
-				if ( sceneDef.extensions
-						 && sceneDef.extensions[ EXTENSIONS.KHR_LIGHTS ]
-						 && sceneDef.extensions[ EXTENSIONS.KHR_LIGHTS ].light !== undefined ) {
-
-					var lights = extensions[ EXTENSIONS.KHR_LIGHTS ].lights;
-					scene.add( lights[ sceneDef.extensions[ EXTENSIONS.KHR_LIGHTS ].light ] );
-
-				}
-
 				return scene;
 
 			} );

+ 1 - 1
examples/js/loaders/HDRCubeTextureLoader.js

@@ -108,7 +108,7 @@ THREE.HDRCubeTextureLoader.prototype.load = function ( type, urls, onLoad, onPro
 
 	function loadHDRData( i, onLoad, onProgress, onError ) {
 
-		var loader = new THREE.FileLoader( this.manager );
+		var loader = new THREE.FileLoader( scope.manager );
 		loader.setResponseType( 'arraybuffer' );
 		loader.load( urls[ i ], function ( buffer ) {
 

+ 74 - 405
examples/js/loaders/NodeMaterialLoader.js

@@ -91,7 +91,11 @@ Object.assign( THREE.NodeMaterialLoader.prototype, {
 
 	getObjectById: function ( uuid ) {
 
-		return this.library[ uuid ] || this.nodes[ uuid ] || this.names[ uuid ];
+		return this.library[ uuid ] || 
+			this.nodes[ uuid ] || 
+			this.materials[ uuid ] ||
+			this.passes[ uuid ] || 
+			this.names[ uuid ];
 
 	},
 
@@ -109,15 +113,62 @@ Object.assign( THREE.NodeMaterialLoader.prototype, {
 
 	},
 
-	parse: function ( json ) {
-
-		var uuid, node, object, prop, i;
+	resolve: function( json ) {
+		
+		switch( typeof json ) {
+			
+			case "boolean":
+			case "number":
+			
+				return json;
+			
+			case "string":
+			
+				if (/^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}$/i.test(json) || this.library[ json ]) {
+					
+					return this.getNode( json );
+					
+				}
+				
+				return json;
+
+			default:
+			
+				if ( Array.isArray( json ) ) {
+			
+					for(var i = 0; i < json.length; i++) {
+						
+						json[i] = this.resolve( json[i] );
+						
+					}
+					
+				} else {
+					
+					for ( var prop in json ) {
+						
+						if (prop === "uuid") continue;
+						
+						json[ prop ] = this.resolve( json[ prop ] );
+						
+					}
+					
+				}
+				
+		}
+		
+		return json;
+		
+	},
+	
+	declare: function( json ) {
+		
+		var uuid, node, object;
 
 		for ( uuid in json.nodes ) {
 
 			node = json.nodes[ uuid ];
 
-			object = new THREE[ node.type ]();
+			object = new THREE[ node.nodeType + "Node" ]();
 
 			if ( node.name ) {
 
@@ -125,15 +176,8 @@ Object.assign( THREE.NodeMaterialLoader.prototype, {
 
 				this.names[ object.name ] = object;
 
-			} else {
-
-				// ignore "uniform" shader input ( for optimization )
-				object.readonly = true;
-
 			}
 
-			if ( node.readonly !== undefined ) object.readonly = node.readonly;
-
 			this.nodes[ uuid ] = object;
 
 		}
@@ -174,410 +218,35 @@ Object.assign( THREE.NodeMaterialLoader.prototype, {
 
 		}
 
-		if ( json.material ) this.material = this.materials[ uuid ];
-		if ( json.pass ) this.pass = this.passes[ uuid ];
+		if ( json.material ) this.material = this.materials[ json.material ];
+		
+		if ( json.pass ) this.pass = this.passes[ json.pass ];
+		
+		return json;
+		
+	},
+	
+	parse: function ( json ) {
 
+		var uuid;
+	
+		json = this.resolve( this.declare( json ) );
+		
 		for ( uuid in json.nodes ) {
 
-			node = json.nodes[ uuid ];
-			object = this.nodes[ uuid ];
-
-			switch ( node.type ) {
-
-				case "IntNode":
-				case "FloatNode":
-
-					object.value = node.value;
-
-					break;
-
-				case "ColorNode":
-
-					object.value.copy( node );
-
-					break;
-
-				case "Vector2Node":
-
-					object.x = node.x;
-					object.y = node.y;
-
-					break;
-
-
-				case "Vector3Node":
-
-					object.x = node.x;
-					object.y = node.y;
-					object.z = node.z;
-
-					break;
-
-				case "Vector4Node":
-
-					object.x = node.x;
-					object.y = node.y;
-					object.z = node.z;
-					object.w = node.w;
-
-					break;
-
-				case "Matrix3Node":
-				case "Matrix4Node":
-
-					object.value.fromArray( node.elements );
-
-					break;
-
-				case "OperatorNode":
-
-					object.a = this.getNode( node.a );
-					object.b = this.getNode( node.b );
-					object.op = node.op;
-
-					break;
-
-				case "Math1Node":
-
-					object.a = this.getNode( node.a );
-					object.method = node.method;
-
-					break;
-
-				case "Math2Node":
-
-					object.a = this.getNode( node.a );
-					object.b = this.getNode( node.b );
-					object.method = node.method;
-
-					break;
-
-				case "Math3Node":
-
-					object.a = this.getNode( node.a );
-					object.b = this.getNode( node.b );
-					object.c = this.getNode( node.c );
-					object.method = node.method;
-
-					break;
-
-				case "UVNode":
-				case "ColorsNode":
-
-					object.index = node.index;
-
-					break;
-
-
-				case "LuminanceNode":
-
-					object.rgb = this.getNode( node.rgb );
-
-					break;
-
-				case "PositionNode":
-				case "NormalNode":
-				case "ReflectNode":
-				case "LightNode":
-
-					object.scope = node.scope;
-
-					break;
-
-				case "SwitchNode":
-
-					object.node = this.getNode( node.node );
-					object.components = node.components;
-
-					break;
-
-				case "JoinNode":
-
-					for ( prop in node.inputs ) {
-
-						object[ prop ] = this.getNode( node.inputs[ prop ] );
-
-					}
-
-					break;
-
-				case "CameraNode":
-
-					object.setScope( node.scope );
-
-					if ( node.camera ) object.setCamera( this.getNode( node.camera ) );
-
-					switch ( node.scope ) {
-
-						case THREE.CameraNode.DEPTH:
-
-							object.near.number = node.near;
-							object.far.number = node.far;
-
-							break;
-
-					}
-
-					break;
-
-				case "ColorAdjustmentNode":
-
-					object.rgb = this.getNode( node.rgb );
-					object.adjustment = this.getNode( node.adjustment );
-					object.method = node.method;
-
-					break;
-
-				case "UVTransformNode":
-
-					object.uv = this.getNode( node.uv );
-					object.transform = this.getNode( node.transform );
-
-					break;
-
-				case "BumpNode":
-
-					object.value = this.getNode( node.value );
-					object.coord = this.getNode( node.coord );
-					object.scale = this.getNode( node.scale );
-
-					break;
-
-				case "BlurNode":
-
-					object.value = this.getNode( node.value );
-					object.coord = this.getNode( node.coord );
-					object.scale = this.getNode( node.scale );
-
-					object.value = this.getNode( node.value );
-					object.coord = this.getNode( node.coord );
-					object.radius = this.getNode( node.radius );
-
-					if ( node.size !== undefined ) object.size = new THREE.Vector2( node.size.x, node.size.y );
-
-					object.blurX = node.blurX;
-					object.blurY = node.blurY;
-
-					break;
-
-				case "ResolutionNode":
-
-					object.renderer = this.getNode( node.renderer );
-
-					break;
-
-				case "ScreenUVNode":
-
-					object.resolution = this.getNode( node.resolution );
-
-					break;
-
-				case "VelocityNode":
-
-					if ( node.target ) object.setTarget( this.getNode( node.target ) );
-					object.setParams( node.params );
-
-					break;
-
-				case "TimerNode":
-
-					object.scope = node.scope;
-					object.scale = node.scale;
-
-					break;
-
-				case "ConstNode":
-
-					object.name = node.name;
-					object.type = node.out;
-					object.value = node.value;
-					object.useDefine = node.useDefine === true;
-
-					break;
-
-				case "AttributeNode":
-				case "VarNode":
-
-					object.type = node.out;
-
-					break;
-
-
-				case "ReflectorNode":
-
-					object.setMirror( this.getNode( node.mirror ) );
-
-					if ( node.offset ) object.offset = this.getNode( node.offset );
-
-					break;
-
-				case "NoiseNode":
-
-					object.coord = this.getNode( node.coord );
-
-					break;
-
-				case "FunctionNode":
-
-					object.isMethod = node.isMethod;
-					object.useKeywords = node.useKeywords;
-
-					object.extensions = node.extensions;
-					object.keywords = {};
-
-					for ( prop in node.keywords ) {
-
-						object.keywords[ prop ] = this.getNode( node.keywords[ prop ] );
-
-					}
-
-					if ( node.includes ) {
-
-						for ( i = 0; i < node.includes.length; i ++ ) {
-
-							object.includes.push( this.getNode( node.includes[ i ] ) );
-
-						}
-
-					}
-
-					object.eval( node.src, object.includes, object.extensions, object.keywords );
-
-					if ( ! object.isMethod ) object.type = node.out;
-
-					break;
-
-				case "FunctionCallNode":
-
-					for ( prop in node.inputs ) {
-
-						object.inputs[ prop ] = this.getNode( node.inputs[ prop ] );
-
-					}
-
-					object.value = this.getNode( node.value );
-
-					break;
-
-				case "TextureNode":
-				case "CubeTextureNode":
-				case "ScreenNode":
-
-					if ( node.value ) object.value = this.getNode( node.value );
-
-					object.coord = this.getNode( node.coord );
-
-					if ( node.bias ) object.bias = this.getNode( node.bias );
-					if ( object.project !== undefined ) object.project = node.project;
-
-					break;
-
-				case "RoughnessToBlinnExponentNode":
-					break;
-
-				case "RawNode":
-
-					object.value = this.getNode( node.value );
-
-					break;
-
-				case "StandardNode":
-				case "PhongNode":
-				case "SpriteNode":
-
-					object.color = this.getNode( node.color );
-
-					if ( node.alpha ) object.alpha = this.getNode( node.alpha );
-
-					if ( node.specular ) object.specular = this.getNode( node.specular );
-					if ( node.shininess ) object.shininess = this.getNode( node.shininess );
-
-					if ( node.roughness ) object.roughness = this.getNode( node.roughness );
-					if ( node.metalness ) object.metalness = this.getNode( node.metalness );
-
-					if ( node.reflectivity ) object.reflectivity = this.getNode( node.reflectivity );
-
-					if ( node.clearCoat ) object.clearCoat = this.getNode( node.clearCoat );
-					if ( node.clearCoatRoughness ) object.clearCoatRoughness = this.getNode( node.clearCoatRoughness );
-
-					if ( node.normal ) object.normal = this.getNode( node.normal );
-					if ( node.normalScale ) object.normalScale = this.getNode( node.normalScale );
-
-					if ( node.emissive ) object.emissive = this.getNode( node.emissive );
-					if ( node.ambient ) object.ambient = this.getNode( node.ambient );
-
-					if ( node.shadow ) object.shadow = this.getNode( node.shadow );
-					if ( node.light ) object.light = this.getNode( node.light );
-
-					if ( node.ao ) object.ao = this.getNode( node.ao );
-
-					if ( node.environment ) object.environment = this.getNode( node.environment );
-					if ( node.environmentAlpha ) object.environmentAlpha = this.getNode( node.environmentAlpha );
-
-					if ( node.transform ) object.transform = this.getNode( node.transform );
-
-					if ( node.spherical === false ) object.spherical = false;
-
-					break;
-
-				default:
-
-					console.warn( node.type, "not supported." );
-
-			}
+			this.nodes[ uuid ].copy( json.nodes[ uuid ] );
 
 		}
-
+		
 		for ( uuid in json.materials ) {
 
-			node = json.materials[ uuid ];
-			object = this.materials[ uuid ];
-
-			if ( node.name !== undefined ) object.name = node.name;
-
-			if ( node.blending !== undefined ) object.blending = node.blending;
-			if ( node.flatShading !== undefined ) object.flatShading = node.flatShading;
-			if ( node.side !== undefined ) object.side = node.side;
-
-			object.depthFunc = node.depthFunc;
-			object.depthTest = node.depthTest;
-			object.depthWrite = node.depthWrite;
-
-			if ( node.wireframe !== undefined ) object.wireframe = node.wireframe;
-			if ( node.wireframeLinewidth !== undefined ) object.wireframeLinewidth = node.wireframeLinewidth;
-			if ( node.wireframeLinecap !== undefined ) object.wireframeLinecap = node.wireframeLinecap;
-			if ( node.wireframeLinejoin !== undefined ) object.wireframeLinejoin = node.wireframeLinejoin;
-
-			if ( node.skinning !== undefined ) object.skinning = node.skinning;
-			if ( node.morphTargets !== undefined ) object.morphTargets = node.morphTargets;
-
-			if ( node.visible !== undefined ) object.visible = node.visible;
-			if ( node.userData !== undefined ) object.userData = node.userData;
-
-			object.vertex = this.getNode( node.vertex );
-			object.fragment = this.getNode( node.fragment );
-
-			if ( object.vertex === object.fragment ) {
-
-				// replace main node
-
-				object.node = object.vertex;
-
-			}
-
-			if ( node.fog !== undefined ) object.fog = node.fog;
-			if ( node.lights !== undefined ) object.lights = node.lights;
-
-			if ( node.transparent !== undefined ) object.transparent = node.transparent;
+			this.materials[ uuid ].copy( json.materials[ uuid ] );
 
 		}
-
+		
 		for ( uuid in json.passes ) {
 
-			node = json.passes[ uuid ];
-			object = this.passes[ uuid ];
-
-			object.value = this.getNode( node.value );
+			this.passes[ uuid ].copy( json.passes[ uuid ] );
 
 		}
 

+ 24 - 7
examples/js/loaders/STLLoader.js

@@ -86,22 +86,39 @@ THREE.STLLoader.prototype = {
 			// However, ASCII STLs lacking the SPACE after the 'd' are known to be
 			// plentiful.  So, check the first 5 bytes for 'solid'.
 
+			// Several encodings, such as UTF-8, precede the text with up to 5 bytes:
+			// https://en.wikipedia.org/wiki/Byte_order_mark#Byte_order_marks_by_encoding
+			// Search for "solid" to start anywhere after those prefixes.
+
 			// US-ASCII ordinal values for 's', 'o', 'l', 'i', 'd'
 
 			var solid = [ 115, 111, 108, 105, 100 ];
 
-			for ( var i = 0; i < 5; i ++ ) {
+			for ( var off = 0; off < 5; off ++ ) {
+
+				// If "solid" text is matched to the current offset, declare it to be an ASCII STL.
+
+				if ( matchDataViewAt ( solid, reader, off ) ) return false;
 
-				// If solid[ i ] does not match the i-th byte, then it is not an
-				// ASCII STL; hence, it is binary and return true.
+			}
+
+			// Couldn't find "solid" text at the beginning; it is binary STL.
 
-				if ( solid[ i ] != reader.getUint8( i, false ) ) return true;
+			return true;
 
- 			}
+		}
 
-			// First 5 bytes read "solid"; declare it to be an ASCII STL
+		function matchDataViewAt( query, reader, offset ) {
+
+			// Check if each byte in query matches the corresponding byte from the current offset
+
+			for ( var i = 0, il = query.length; i < il; i ++ ) {
+
+				if ( query[ i ] !== reader.getUint8( offset + i, false ) ) return false;
+
+			}
 
-			return false;
+			return true;
 
 		}
 

+ 316 - 24
examples/js/loaders/SVGLoader.js

@@ -1,6 +1,7 @@
 /**
  * @author mrdoob / http://mrdoob.com/
  * @author zz85 / http://joshuakoo.com/
+ * @author yomboprime / https://yombo.org
  */
 
 THREE.SVGLoader = function ( manager ) {
@@ -32,6 +33,10 @@ THREE.SVGLoader.prototype = {
 
 			if ( node.nodeType !== 1 ) return;
 
+			var transform = getNodeTransform( node );
+
+			var path = null;
+
 			switch ( node.nodeName ) {
 
 				case 'svg':
@@ -43,37 +48,37 @@ THREE.SVGLoader.prototype = {
 
 				case 'path':
 					style = parseStyle( node, style );
-					if ( node.hasAttribute( 'd' ) && isVisible( style ) ) paths.push( parsePathNode( node, style ) );
+					if ( node.hasAttribute( 'd' ) && isVisible( style ) ) path = parsePathNode( node, style );
 					break;
 
 				case 'rect':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseRectNode( node, style ) );
+					if ( isVisible( style ) ) path = parseRectNode( node, style );
 					break;
 
 				case 'polygon':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parsePolygonNode( node, style ) );
+					if ( isVisible( style ) ) path = parsePolygonNode( node, style );
 					break;
 
 				case 'polyline':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parsePolylineNode( node, style ) );
+					if ( isVisible( style ) ) path = parsePolylineNode( node, style );
 					break;
 
 				case 'circle':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseCircleNode( node, style ) );
+					if ( isVisible( style ) ) path = parseCircleNode( node, style );
 					break;
 
 				case 'ellipse':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseEllipseNode( node, style ) );
+					if ( isVisible( style ) ) path = parseEllipseNode( node, style );
 					break;
 
 				case 'line':
 					style = parseStyle( node, style );
-					if ( isVisible( style ) ) paths.push( parseLineNode( node, style ) );
+					if ( isVisible( style ) ) path = parseLineNode( node, style );
 					break;
 
 				default:
@@ -81,6 +86,14 @@ THREE.SVGLoader.prototype = {
 
 			}
 
+			if ( path ) {
+
+				transformPath( path, currentTransform );
+
+				paths.push( path );
+
+			}
+
 			var nodes = node.childNodes;
 
 			for ( var i = 0; i < nodes.length; i ++ ) {
@@ -89,6 +102,12 @@ THREE.SVGLoader.prototype = {
 
 			}
 
+			if ( transform ) {
+
+				currentTransform.copy( transformStack.pop() );
+
+			}
+
 		}
 
 		function parsePathNode( node, style ) {
@@ -99,6 +118,10 @@ THREE.SVGLoader.prototype = {
 			var point = new THREE.Vector2();
 			var control = new THREE.Vector2();
 
+			var firstPoint = new THREE.Vector2();
+			var isFirstPoint = true;
+			var doSetFirstPoint = false;
+
 			var d = node.getAttribute( 'd' );
 
 			// console.log( d );
@@ -112,6 +135,11 @@ THREE.SVGLoader.prototype = {
 				var type = command.charAt( 0 );
 				var data = command.substr( 1 ).trim();
 
+				if ( isFirstPoint ) {
+					doSetFirstPoint = true;
+				}
+				isFirstPoint = false;
+
 				switch ( type ) {
 
 					case 'M':
@@ -121,7 +149,11 @@ THREE.SVGLoader.prototype = {
 							point.y = numbers[ j + 1 ];
 							control.x = point.x;
 							control.y = point.y;
-							path.moveTo( point.x, point.y );
+							if ( j === 0 ) {
+								path.moveTo( point.x, point.y );
+							} else {
+								path.lineTo( point.x, point.y );
+							}
 						}
 						break;
 
@@ -249,7 +281,11 @@ THREE.SVGLoader.prototype = {
 							point.y += numbers[ j + 1 ];
 							control.x = point.x;
 							control.y = point.y;
-							path.moveTo( point.x, point.y );
+							if ( j === 0 ) {
+								path.moveTo( point.x, point.y );
+							} else {
+								path.lineTo( point.x, point.y );
+							}
 						}
 						break;
 
@@ -375,21 +411,9 @@ THREE.SVGLoader.prototype = {
 						path.currentPath.autoClose = true;
 						if ( path.currentPath.curves.length > 0 ) {
 							// Reset point to beginning of Path
-							var curve = path.currentPath.curves[ 0 ];
-							if ( curve.isLineCurve ) {
-								point.x = curve.v1.x;
-								point.y = curve.v1.y;
-							} else if ( curve.isEllipseCurve || curve.isArcCurve ) {
-								point.x = curve.aX;
-								point.y = curve.aY;
-							} else if ( curve.isCubicBezierCurve || curve.isQuadraticBezierCurve ) {
-								point.x = curve.v0.x;
-								point.y = curve.v0.y;
-							} else if ( curve.isSplineCurve ) {
-								point.x = curve.points[ 0 ].x;
-								point.y = curve.points[ 0 ].y;
-							}
+							point.copy( firstPoint );
 							path.currentPath.currentPoint.copy( point );
+							isFirstPoint = true;
 						}
 						break;
 
@@ -400,6 +424,13 @@ THREE.SVGLoader.prototype = {
 
 				// console.log( type, parseFloats( data ), parseFloats( data ).length  )
 
+				if ( doSetFirstPoint ) {
+
+					firstPoint.copy( point );
+
+					doSetFirstPoint = false;
+
+				}
 			}
 
 			return path;
@@ -503,7 +534,13 @@ THREE.SVGLoader.prototype = {
 			if ( rx !== 0 || ry !== 0 ) {
 
 				path.bezierCurveTo( x, y + h, x, y + h, x, y + h - 2 * ry );
-				path.lineTo( x, y + 2 * ry );
+
+			}
+
+			path.lineTo( x, y + 2 * ry );
+
+			if ( rx !== 0 || ry !== 0 ) {
+
 				path.bezierCurveTo( x, y, x, y, x + 2 * rx, y );
 
 			}
@@ -683,6 +720,252 @@ THREE.SVGLoader.prototype = {
 
 			return array;
 
+
+		}
+
+		function getNodeTransform( node ) {
+
+			if ( ! node.hasAttribute( 'transform' ) ) {
+				return null;
+			}
+
+			var transform = parseTransformNode( node );
+
+			if ( transform ) {
+
+				if ( transformStack.length > 0 ) {
+					transform.premultiply( transformStack[ transformStack.length - 1 ] );
+				}
+
+				currentTransform.copy( transform );
+				transformStack.push( transform );
+
+			}
+
+			return transform;
+
+		}
+
+		function parseTransformNode( node ) {
+
+			var transformAttr = node.getAttribute( 'transform' );
+			var transform = null;
+			var openParPos = transformAttr.indexOf( "(" );
+			var closeParPos = transformAttr.indexOf( ")" );
+
+			if ( openParPos > 0 && openParPos < closeParPos ) {
+
+				var transformType = transformAttr.substr( 0, openParPos );
+
+				var array = parseFloats( transformAttr.substr( openParPos + 1, closeParPos - openParPos - 1 ) );
+
+				switch ( transformType ) {
+
+					case "translate":
+
+						if ( array.length >= 1 ) {
+
+							transform = new THREE.Matrix3();
+
+							var tx = array[ 0 ];
+							var ty = tx;
+
+							if ( array.length >= 2 ) {
+
+								ty = array[ 1 ];
+
+							}
+
+							transform.translate( tx, ty );
+
+						}
+
+						break;
+
+					case "rotate":
+
+						if ( array.length >= 1 ) {
+
+							var angle = 0;
+							var cx = 0;
+							var cy = 0;
+
+							transform = new THREE.Matrix3();
+
+							// Angle
+							angle = - array[ 0 ] * Math.PI / 180;
+
+							if ( array.length >= 3 ) {
+
+								// Center x, y
+								cx = array[ 1 ];
+								cy = array[ 2 ];
+
+							}
+
+							// Rotate around center (cx, cy)
+							tempTransform1.identity().translate( -cx, -cy );
+							tempTransform2.identity().rotate( angle );
+							tempTransform3.multiplyMatrices( tempTransform2, tempTransform1 );
+							tempTransform1.identity().translate( cx, cy );
+							transform.multiplyMatrices( tempTransform1, tempTransform3 );
+
+						}
+
+						break;
+
+					case "scale":
+
+						if ( array.length >= 1 ) {
+
+							transform = new THREE.Matrix3();
+
+							var scaleX = array[ 0 ];
+							var scaleY = scaleX;
+
+							if ( array.length >= 2 ) {
+								scaleY = array[ 1 ];
+							}
+
+							transform.scale( scaleX, scaleY );
+
+						}
+
+						break;
+
+					case "skewX":
+
+						if ( array.length === 1 ) {
+
+							transform = new THREE.Matrix3();
+
+							transform.set(
+								1, Math.tan( array[ 0 ] * Math.PI / 180 ), 0,
+								0, 1, 0,
+								0, 0, 1
+							);
+
+						}
+
+						break;
+
+					case "skewY":
+
+						if ( array.length === 1 ) {
+
+							transform = new THREE.Matrix3();
+
+							transform.set(
+								1, 0, 0,
+								Math.tan( array[ 0 ] * Math.PI / 180 ), 1, 0,
+								0, 0, 1
+							);
+
+						}
+
+						break;
+
+					case "matrix":
+
+						if ( array.length === 6 ) {
+
+							transform = new THREE.Matrix3();
+
+							transform.set(
+								array[ 0 ], array[ 2 ], array[ 4 ],
+								array[ 1 ], array[ 3 ], array[ 5 ],
+								0, 0, 1
+							);
+
+						}
+
+						break;
+				}
+
+			}
+
+			return transform;
+
+		}
+
+		function transformPath( path, m ) {
+
+			function transfVec2( v2 ) {
+
+				tempV3.set( v2.x, v2.y, 1 ).applyMatrix3( m );
+
+				v2.set( tempV3.x, tempV3.y );
+
+			}
+
+			var isRotated = isTransformRotated( m );
+
+			var tempV2 = new THREE.Vector2();
+			var tempV3 = new THREE.Vector3();
+
+			var subPaths = path.subPaths;
+
+			for ( var i = 0, n = subPaths.length; i < n; i++ ) {
+
+				var subPath = subPaths[ i ];
+				var curves = subPath.curves;
+
+				for ( var j = 0; j < curves.length; j++ ) {
+
+					var curve = curves[ j ];
+
+					if ( curve.isLineCurve ) {
+
+						transfVec2( curve.v1 );
+						transfVec2( curve.v2 );
+
+					} else if ( curve.isCubicBezierCurve ) {
+
+						transfVec2( curve.v0 );
+						transfVec2( curve.v1 );
+						transfVec2( curve.v2 );
+						transfVec2( curve.v3 );
+
+					} else if ( curve.isQuadraticBezierCurve ) {
+
+						transfVec2( curve.v0 );
+						transfVec2( curve.v1 );
+						transfVec2( curve.v2 );
+
+					} else if ( curve.isEllipseCurve ) {
+
+						if ( isRotated ) {
+							console.warn( "SVGLoader: Elliptic arc or ellipse rotation or skewing is not implemented." );
+						}
+
+						tempV2.set( curve.aX, curve.aY );
+						transfVec2( tempV2 );
+						curve.aX = tempV2.x;
+						curve.aY = tempV2.y;
+
+						curve.xRadius *= getTransformScaleX( m );
+						curve.yRadius *= getTransformScaleY( m );
+
+					}
+
+				}
+
+			}
+
+		}
+
+		function isTransformRotated( m ) {
+			return m.elements[ 1 ] !== 0 || m.elements[ 3 ] !== 0;
+		}
+
+		function getTransformScaleX( m ) {
+			var te = m.elements;
+			return Math.sqrt( te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] )
+		}
+
+		function getTransformScaleY( m ) {
+			var te = m.elements;
+			return Math.sqrt( te[ 3 ] * te[ 3 ] + te[ 4 ] * te[ 4 ] )
 		}
 
 		//
@@ -691,6 +974,14 @@ THREE.SVGLoader.prototype = {
 
 		var paths = [];
 
+		var transformStack = [];
+
+		var tempTransform1 = new THREE.Matrix3();
+		var tempTransform2 = new THREE.Matrix3();
+		var tempTransform3 = new THREE.Matrix3();
+
+		var currentTransform = new THREE.Matrix3();
+
 		console.time( 'THREE.SVGLoader: DOMParser' );
 
 		var xml = new DOMParser().parseFromString( text, 'image/svg+xml' ); // application/xml
@@ -703,6 +994,7 @@ THREE.SVGLoader.prototype = {
 
 		// console.log( paths );
 
+
 		console.timeEnd( 'THREE.SVGLoader: Parse' );
 
 		return paths;

+ 8 - 0
examples/js/loaders/TGALoader.js

@@ -22,6 +22,7 @@ THREE.TGALoader.prototype = {
 
 		var loader = new THREE.FileLoader( this.manager );
 		loader.setResponseType( 'arraybuffer' );
+		loader.setPath( this.path );
 
 		loader.load( url, function ( buffer ) {
 
@@ -535,6 +536,13 @@ THREE.TGALoader.prototype = {
 
 		return canvas;
 
+	},
+
+	setPath: function ( value ) {
+
+		this.path = value;
+		return this;
+
 	}
 
 };

+ 0 - 774
examples/js/modifiers/BufferSubdivisionModifier.js

@@ -1,774 +0,0 @@
-/*
- * @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
- * @author Matthew Adams / http://www.centerionware.com - added UV support and rewrote to use buffergeometry.
- *
- * Subdivision Geometry Modifier using Loop Subdivision Scheme for Geometry / BufferGeometry
- *
- * References:
- *	http://graphics.stanford.edu/~mdfisher/subdivision.html
- *	http://www.holmes3d.net/graphics/subdivision/
- *	http://www.cs.rutgers.edu/~decarlo/readings/subdiv-sg00c.pdf
- *
- * Known Issues:
- *	- currently doesn't handle "Sharp Edges"
- *	- no checks to prevent breaking when uv's don't exist.
- *	- vertex colors are unsupported.
- *	**DDS Images when using corrected uv's passed to subdivision modifier will have their uv's flipy'd within the correct uv set
- *	**Either flipy the DDS image, or use shaders. Don't try correcting the uv's before passing into subdiv (eg: v=1-v).
- *
- * @input THREE.Geometry, or index'd THREE.BufferGeometry with faceUV's (Not vertex uv's)
- * @output non-indexed vertex points, uv's, normals.
- *
- * The TypedArrayHelper class is designed to assist managing typed arrays, and to allow the removal of all 'new Vector3, new Face3, new Vector2'.
- *
- * It will automatically resize them if trying to push a new element to an array that isn't long enough
- * It provides 'registers' that the units can be mapped to. This allows a small set of objects
- * (ex: vector3's, face3's, vector2's) to be allocated then used, to eliminate any need to rewrite all
- * the features those classes offer while not requiring some_huge_number to be allocated.
- * It should be moved into it's own file honestly, then included before the BufferSubdivisionModifier - maybe in three's core?
- *
- */
-
-THREE.Face3.prototype.set = function( a, b, c ) {
-
-	this.a = a;
-	this.b = b;
-	this.c = c;
-
-};
-
-var TypedArrayHelper = function( size, registers, register_type, array_type, unit_size, accessors ) {
-
-	this.array_type = array_type;
-	this.register_type = register_type;
-	this.unit_size = unit_size;
-	this.accessors = accessors;
-	this.buffer = new array_type( size * unit_size );
-	this.register = [];
-	this.length = 0;
-	this.real_length = size;
-	this.available_registers = registers;
-
-	for ( var i = 0; i < registers; i++ ) {
-
-		this.register.push( new register_type() );
-
-	}
-
-};
-
-TypedArrayHelper.prototype = {
-
-	constructor: TypedArrayHelper,
-
-	index_to_register: function( index, register, isLoop ) {
-
-		var base = index * this.unit_size;
-
-		if ( register >= this.available_registers ) {
-
-			throw new Error( 'THREE.BufferSubdivisionModifier: Not enough registers in TypedArrayHelper.' );
-
-		}
-
-		if ( index > this.length ) {
-
-			throw new Error( 'THREE.BufferSubdivisionModifier: Index is out of range in TypedArrayHelper.' );
-
-		}
-
-		for ( var i = 0; i < this.unit_size; i++ ) {
-
-			( this.register[ register ] )[ this.accessors[ i ] ] = this.buffer[ base + i ];
-
-		}
-
-	},
-
-	resize: function( new_size ) {
-
-		if ( new_size === 0 ) {
-
-			new_size = 8;
-
-		}
-
-		if ( new_size < this.length ) {
-
-			this.buffer = this.buffer.subarray( 0, this.length * this.unit_size );
-
-		} else {
-
-			var nBuffer;
-
-			if ( this.buffer.length < new_size * this.unit_size ) {
-
-				nBuffer = new this.array_type( new_size * this.unit_size );
-				nBuffer.set( this.buffer );
-				this.buffer = nBuffer;
-				this.real_length = new_size;
-
-			} else {
-
-				nBuffer = new this.array_type( new_size * this.unit_size );
-				nBuffer.set( this.buffer.subarray( 0, this.length * this.unit_size ) );
-				this.buffer = nBuffer;
-				this.real_length = new_size;
-
-			}
-
-		}
-
-	},
-
-	from_existing: function( oldArray ) {
-
-		var new_size = oldArray.length;
-		this.buffer = new this.array_type( new_size );
-		this.buffer.set( oldArray );
-		this.length = oldArray.length / this.unit_size;
-		this.real_length = this.length;
-
-	},
-
-	push_element: function( vector ) {
-
-		if ( this.length + 1 > this.real_length ) {
-
-			this.resize( this.real_length * 2 );
-
-		}
-
-		var bpos = this.length * this.unit_size;
-
-		for ( var i = 0; i < this.unit_size; i++ ) {
-
-			this.buffer[ bpos + i ] = vector[ this.accessors[ i ] ];
-
-		}
-
-		this.length++;
-
-	},
-
-	trim_size: function() {
-
-		if ( this.length < this.real_length ) {
-
-			this.resize( this.length );
-
-		}
-
-	}
-
-};
-
-
-function convertGeometryToIndexedBuffer( geometry ) {
-
-	var BGeom = new THREE.BufferGeometry();
-
-	// create a new typed array
-	var vertArray = new TypedArrayHelper( geometry.vertices.length, 0, THREE.Vector3, Float32Array, 3, [ 'x', 'y', 'z' ] );
-	var indexArray = new TypedArrayHelper( geometry.faces.length, 0, THREE.Face3, Uint32Array, 3, [ 'a', 'b', 'c' ] );
-	var uvArray = new TypedArrayHelper( geometry.faceVertexUvs[0].length * 3 * 3, 0, THREE.Vector2, Float32Array, 2, [ 'x', 'y' ] );
-
-	for ( var i = 0, il = geometry.vertices.length; i < il; i++ ) {
-
-		vertArray.push_element( geometry.vertices[ i ] );
-
-	}
-
-	for ( var i = 0, il = geometry.faces.length; i < il; i++ ) {
-
-		indexArray.push_element( geometry.faces[ i ] );
-
-	}
-
-	for ( var i = 0, il = geometry.faceVertexUvs[ 0 ].length; i < il; i++ ) {
-
-		uvArray.push_element( geometry.faceVertexUvs[ 0 ][ i ][ 0 ] );
-		uvArray.push_element( geometry.faceVertexUvs[ 0 ][ i ][ 1 ] );
-		uvArray.push_element( geometry.faceVertexUvs[ 0 ][ i ][ 2 ] );
-
-	}
-
-	indexArray.trim_size();
-	vertArray.trim_size();
-	uvArray.trim_size();
-
-	BGeom.setIndex( new THREE.BufferAttribute( indexArray.buffer, 3 ) );
-	BGeom.addAttribute( 'position', new THREE.BufferAttribute( vertArray.buffer, 3 ) );
-	BGeom.addAttribute( 'uv', new THREE.BufferAttribute( uvArray.buffer, 2 ) );
-
-	return BGeom;
-
-}
-
-function compute_vertex_normals( geometry ) {
-
-	var ABC = [ 'a', 'b', 'c' ];
-	var XYZ = [ 'x', 'y', 'z' ];
-	var XY = [ 'x', 'y' ];
-
-	var oldVertices = new TypedArrayHelper( 0, 5, THREE.Vector3, Float32Array, 3, XYZ );
-	var oldFaces = new TypedArrayHelper( 0, 3, THREE.Face3, Uint32Array, 3, ABC );
-	oldVertices.from_existing( geometry.getAttribute( 'position' ).array );
-	var newNormals = new TypedArrayHelper( oldVertices.length * 3, 4, THREE.Vector3, Float32Array, 3, XYZ );
-	var newNormalFaces = new TypedArrayHelper( oldVertices.length, 1, function () { this.x = 0; }, Float32Array, 1, [ 'x' ] );
-
-	newNormals.length = oldVertices.length;
-	oldFaces.from_existing( geometry.index.array );
-	var a, b, c;
-	var my_weight;
-	var full_weights = [ 0.0, 0.0, 0.0 ];
-
-	for ( var i = 0, il = oldFaces.length; i < il; i++ ) {
-
-		oldFaces.index_to_register( i, 0 );
-
-		oldVertices.index_to_register( oldFaces.register[ 0 ].a, 0 );
-		oldVertices.index_to_register( oldFaces.register[ 0 ].b, 1 );
-		oldVertices.index_to_register( oldFaces.register[ 0 ].c, 2 );
-
-		newNormals.register[ 0 ].subVectors( oldVertices.register[ 1 ], oldVertices.register[ 0 ] );
-		newNormals.register[ 1 ].subVectors( oldVertices.register[ 2 ], oldVertices.register[ 1 ] );
-		newNormals.register[ 0 ].cross( newNormals.register[ 1 ] );
-		my_weight = Math.abs( newNormals.register[ 0 ].length() );
-
-		newNormalFaces.buffer[ oldFaces.register[ 0 ].a ] += my_weight;
-		newNormalFaces.buffer[ oldFaces.register[ 0 ].b ] += my_weight;
-		newNormalFaces.buffer[ oldFaces.register[ 0 ].c ] += my_weight;
-
-	}
-
-	var t_len;
-
-	for ( var i = 0, il = oldFaces.length; i < il; i++ ) {
-
-		oldFaces.index_to_register( i, 0 );
-		oldVertices.index_to_register( oldFaces.register[ 0 ].a, 0 );
-		oldVertices.index_to_register( oldFaces.register[ 0 ].b, 1 );
-		oldVertices.index_to_register( oldFaces.register[ 0 ].c, 2 );
-
-		newNormals.register[ 0 ].subVectors( oldVertices.register[ 1 ], oldVertices.register[ 0 ] );
-		newNormals.register[ 1 ].subVectors( oldVertices.register[ 2 ], oldVertices.register[ 0 ] );
-
-		newNormals.register[ 3 ].set( 0, 0, 0 );
-		newNormals.register[ 3 ].x = ( newNormals.register[ 0 ].y * newNormals.register[ 1 ].z ) - ( newNormals.register[ 0 ].z * newNormals.register[ 1 ].y );
-		newNormals.register[ 3 ].y = ( newNormals.register[ 0 ].z * newNormals.register[ 1 ].x ) - ( newNormals.register[ 0 ].x * newNormals.register[ 1 ].z );
-		newNormals.register[ 3 ].z = ( newNormals.register[ 0 ].x * newNormals.register[ 1 ].y ) - ( newNormals.register[ 0 ].y * newNormals.register[ 1 ].x );
-
-		newNormals.register[ 0 ].cross( newNormals.register[ 1 ] );
-
-		my_weight = Math.abs( newNormals.register[ 0 ].length() );
-
-		full_weights[ 0 ] = ( my_weight / newNormalFaces.buffer[ oldFaces.register[ 0 ].a ] );
-		full_weights[ 1 ] = ( my_weight / newNormalFaces.buffer[ oldFaces.register[ 0 ].b ] );
-		full_weights[ 2 ] = ( my_weight / newNormalFaces.buffer[ oldFaces.register[ 0 ].c ] );
-
-		newNormals.buffer[ ( oldFaces.register[ 0 ].a * 3 ) + 0 ] += newNormals.register[ 3 ].x * full_weights[ 0 ];
-		newNormals.buffer[ ( oldFaces.register[ 0 ].a * 3 ) + 1 ] += newNormals.register[ 3 ].y * full_weights[ 0 ];
-		newNormals.buffer[ ( oldFaces.register[ 0 ].a * 3 ) + 2 ] += newNormals.register[ 3 ].z * full_weights[ 0 ];
-
-		newNormals.buffer[ ( oldFaces.register[ 0 ].b * 3 ) + 0 ] += newNormals.register[ 3 ].x * full_weights[ 1 ];
-		newNormals.buffer[ ( oldFaces.register[ 0 ].b * 3 ) + 1 ] += newNormals.register[ 3 ].y * full_weights[ 1 ];
-		newNormals.buffer[ ( oldFaces.register[ 0 ].b * 3 ) + 2 ] += newNormals.register[ 3 ].z * full_weights[ 1 ];
-
-		newNormals.buffer[ ( oldFaces.register[ 0 ].c * 3 ) + 0 ] += newNormals.register[ 3 ].x * full_weights[ 2 ];
-		newNormals.buffer[ ( oldFaces.register[ 0 ].c * 3 ) + 1 ] += newNormals.register[ 3 ].y * full_weights[ 2 ];
-		newNormals.buffer[ ( oldFaces.register[ 0 ].c * 3 ) + 2 ] += newNormals.register[ 3 ].z * full_weights[ 2 ];
-
-	}
-
-	newNormals.trim_size();
-	geometry.addAttribute( 'normal', new THREE.BufferAttribute( newNormals.buffer, 3 ) );
-
-}
-
-function unIndexIndexedGeometry( geometry ) {
-
-	var ABC = [ 'a', 'b', 'c' ];
-	var XYZ = [ 'x', 'y', 'z' ];
-	var XY = [ 'x', 'y' ];
-
-	var oldVertices = new TypedArrayHelper( 0, 3, THREE.Vector3, Float32Array, 3, XYZ );
-	var oldFaces = new TypedArrayHelper( 0, 3, THREE.Face3, Uint32Array, 3, ABC );
-	var oldUvs = new TypedArrayHelper( 0, 3, THREE.Vector2, Float32Array, 2, XY );
-	var oldNormals = new TypedArrayHelper( 0, 3, THREE.Vector3, Float32Array, 3, XYZ );
-
-	oldVertices.from_existing( geometry.getAttribute( 'position' ).array );
-	oldFaces.from_existing( geometry.index.array );
-	oldUvs.from_existing( geometry.getAttribute( 'uv' ).array );
-
-	compute_vertex_normals( geometry );
-	oldNormals.from_existing( geometry.getAttribute( 'normal' ).array );
-
-	var newVertices = new TypedArrayHelper( oldFaces.length * 3, 3, THREE.Vector3, Float32Array, 3, XYZ );
-	var newNormals = new TypedArrayHelper( oldFaces.length * 3, 3, THREE.Vector3, Float32Array, 3, XYZ );
-	var newUvs = new TypedArrayHelper( oldFaces.length * 3, 3, THREE.Vector2, Float32Array, 2, XY );
-	var v, w;
-
-	for ( var i = 0, il = oldFaces.length; i < il; i++ ) {
-
-		oldFaces.index_to_register( i, 0 );
-
-		oldVertices.index_to_register( oldFaces.register[ 0 ].a, 0 );
-		oldVertices.index_to_register( oldFaces.register[ 0 ].b, 1 );
-		oldVertices.index_to_register( oldFaces.register[ 0 ].c, 2 );
-
-		newVertices.push_element( oldVertices.register[ 0 ] );
-		newVertices.push_element( oldVertices.register[ 1 ] );
-		newVertices.push_element( oldVertices.register[ 2 ] );
-
-			if ( oldUvs.length !== 0 ) {
-
-				oldUvs.index_to_register( ( i * 3 ) + 0, 0 );
-				oldUvs.index_to_register( ( i * 3 ) + 1, 1 );
-				oldUvs.index_to_register( ( i * 3 ) + 2, 2 );
-
-				newUvs.push_element( oldUvs.register[ 0 ] );
-				newUvs.push_element( oldUvs.register[ 1 ] );
-				newUvs.push_element( oldUvs.register[ 2 ] );
-
-			}
-
-		oldNormals.index_to_register( oldFaces.register[ 0 ].a, 0 );
-		oldNormals.index_to_register( oldFaces.register[ 0 ].b, 1 );
-		oldNormals.index_to_register( oldFaces.register[ 0 ].c, 2 );
-
-		newNormals.push_element( oldNormals.register[ 0 ] );
-		newNormals.push_element( oldNormals.register[ 1 ] );
-		newNormals.push_element( oldNormals.register[ 2 ] );
-
-	}
-
-	newVertices.trim_size();
-	newUvs.trim_size();
-	newNormals.trim_size();
-
-	geometry.index = null;
-
-	geometry.addAttribute( 'position', new THREE.BufferAttribute( newVertices.buffer, 3 ) );
-	geometry.addAttribute( 'normal', new THREE.BufferAttribute( newNormals.buffer, 3 ) );
-
-	if ( newUvs.length !== 0 ) {
-
-		geometry.addAttribute( 'uv', new THREE.BufferAttribute( newUvs.buffer, 2 ) );
-
-	}
-
-	return geometry;
-
-}
-
-THREE.BufferSubdivisionModifier = function( subdivisions ) {
-
-	this.subdivisions = ( subdivisions === undefined ) ? 1 : subdivisions;
-
-};
-
-THREE.BufferSubdivisionModifier.prototype.modify = function( geometry ) {
-
-	if ( geometry instanceof THREE.Geometry ) {
-
-		geometry.mergeVertices();
-
-		if ( typeof geometry.normals === 'undefined' ) {
-
-			geometry.normals = [];
-
-		}
-
-		geometry = convertGeometryToIndexedBuffer( geometry );
-
-	} else if ( !( geometry instanceof THREE.BufferGeometry ) ) {
-
-		console.error( 'THREE.BufferSubdivisionModifier: Geometry is not an instance of THREE.BufferGeometry or THREE.Geometry' );
-
-	}
-
-	var repeats = this.subdivisions;
-
-	while ( repeats -- > 0 ) {
-
-		this.smooth( geometry );
-
-	}
-
-	return unIndexIndexedGeometry( geometry );
-
-};
-
-var edge_type = function ( a, b ) {
-
-	this.a = a;
-	this.b = b;
-	this.faces = [];
-	this.newEdge = null;
-
-};
-
-( function () {
-
-	// Some constants
-	var ABC = [ 'a', 'b', 'c' ];
-	var XYZ = [ 'x', 'y', 'z' ];
-	var XY = [ 'x', 'y' ];
-
-	function getEdge( a, b, map ) {
-
-		var key = Math.min( a, b ) + '_' + Math.max( a, b );
-		return map[ key ];
-
-	}
-
-
-	function processEdge( a, b, vertices, map, face, metaVertices ) {
-
-		var vertexIndexA = Math.min( a, b );
-		var vertexIndexB = Math.max( a, b );
-
-		var key = vertexIndexA + '_' + vertexIndexB;
-
-		var edge;
-
-		if ( key in map ) {
-
-			edge = map[ key ];
-
-		} else {
-
-			edge = new edge_type( vertexIndexA,vertexIndexB );
-			map[key] = edge;
-
-		}
-
-		edge.faces.push( face );
-
-		metaVertices[ a ].edges.push( edge );
-		metaVertices[ b ].edges.push( edge );
-
-	}
-
-	function generateLookups( vertices, faces, metaVertices, edges ) {
-
-		var i, il, face, edge;
-
-		for ( i = 0, il = vertices.length; i < il; i++ ) {
-
-			metaVertices[ i ] = { edges: [] };
-
-		}
-
-		for ( i = 0, il = faces.length; i < il; i++ ) {
-
-			faces.index_to_register( i, 0 );
-			face = faces.register[ 0 ]; // Faces is now a TypedArrayHelper class, not a face3.
-
-			processEdge( face.a, face.b, vertices, edges, i, metaVertices );
-			processEdge( face.b, face.c, vertices, edges, i, metaVertices );
-			processEdge( face.c, face.a, vertices, edges, i, metaVertices );
-
-		}
-
-	}
-
-	function newFace( newFaces, face ) {
-
-		newFaces.push_element( face );
-
-	}
-
-	function midpoint( a, b ) {
-
-		return ( Math.abs( b - a ) / 2 ) + Math.min( a, b );
-
-	}
-
-	function newUv( newUvs, a, b, c ) {
-
-		newUvs.push_element( a );
-		newUvs.push_element( b );
-		newUvs.push_element( c );
-
-	}
-
-	/////////////////////////////
-
-	// Performs one iteration of Subdivision
-
-	THREE.BufferSubdivisionModifier.prototype.smooth = function ( geometry ) {
-
-		var oldVertices, oldFaces, oldUvs;
-		var newVertices, newFaces, newUVs;
-
-		var n, l, i, il, j, k;
-		var metaVertices, sourceEdges;
-
-		oldVertices = new TypedArrayHelper( 0, 3, THREE.Vector3, Float32Array, 3, XYZ );
-		oldFaces = new TypedArrayHelper( 0, 3, THREE.Face3, Uint32Array, 3, ABC );
-		oldUvs = new TypedArrayHelper( 0, 3, THREE.Vector2, Float32Array, 2, XY );
-		oldVertices.from_existing( geometry.getAttribute( 'position' ).array );
-		oldFaces.from_existing( geometry.index.array );
-		oldUvs.from_existing( geometry.getAttribute( 'uv' ).array );
-
-		var doUvs = false;
-
-		if ( typeof oldUvs !== 'undefined' && oldUvs.length !== 0 ) {
-
-			doUvs = true;
-
-		}
-		/******************************************************
-		*
-		* Step 0: Preprocess Geometry to Generate edges Lookup
-		*
-		*******************************************************/
-
-		metaVertices = new Array( oldVertices.length );
-		sourceEdges = {}; // Edge => { oldVertex1, oldVertex2, faces[]  }
-
-		generateLookups( oldVertices, oldFaces, metaVertices, sourceEdges );
-
-
-		/******************************************************
-		*
-		*	Step 1.
-		*	For each edge, create a new Edge Vertex,
-		*	then position it.
-		*
-		*******************************************************/
-
-		newVertices = new TypedArrayHelper( ( geometry.getAttribute( 'position' ).array.length * 2 ) / 3, 2, THREE.Vector3, Float32Array, 3, XYZ );
-		var other, currentEdge, newEdge, face;
-		var edgeVertexWeight, adjacentVertexWeight, connectedFaces;
-
-		var tmp = newVertices.register[ 1 ];
-		for ( i in sourceEdges ) {
-
-		currentEdge = sourceEdges[ i ];
-		newEdge = newVertices.register[ 0 ];
-
-		edgeVertexWeight = 3 / 8;
-		adjacentVertexWeight = 1 / 8;
-
-		connectedFaces = currentEdge.faces.length;
-
-		// check how many linked faces. 2 should be correct.
-		if ( connectedFaces !== 2 ) {
-
-			// if length is not 2, handle condition
-			edgeVertexWeight = 0.5;
-			adjacentVertexWeight = 0;
-
-		}
-
-		oldVertices.index_to_register( currentEdge.a, 0 );
-		oldVertices.index_to_register( currentEdge.b, 1 );
-		newEdge.addVectors( oldVertices.register[ 0 ], oldVertices.register[ 1 ] ).multiplyScalar( edgeVertexWeight );
-
-		tmp.set( 0, 0, 0 );
-
-		for ( j = 0; j < connectedFaces; j++ ) {
-
-			oldFaces.index_to_register( currentEdge.faces[ j ], 0 );
-			face = oldFaces.register[ 0 ];
-
-			for ( k = 0; k < 3; k++ ) {
-
-				oldVertices.index_to_register( face[ ABC[ k ] ], 2 );
-				other = oldVertices.register[ 2 ];
-
-				if ( face[ ABC[ k ] ] !== currentEdge.a && face[ ABC[ k ] ] !== currentEdge.b) {
-
-					break;
-
-				}
-
-		}
-
-		tmp.add( other );
-
-		}
-
-		tmp.multiplyScalar( adjacentVertexWeight );
-		newEdge.add( tmp );
-
-		currentEdge.newEdge = newVertices.length;
-		newVertices.push_element( newEdge );
-
-		}
-
-		var edgeLength = newVertices.length;
-		/******************************************************
-		*
-		*	Step 2.
-		*	Reposition each source vertices.
-		*
-		*******************************************************/
-
-		var beta, sourceVertexWeight, connectingVertexWeight;
-		var connectingEdge, connectingEdges, oldVertex, newSourceVertex;
-
-		for ( i = 0, il = oldVertices.length; i < il; i++ ) {
-
-			oldVertices.index_to_register( i, 0, XYZ );
-			oldVertex = oldVertices.register[ 0 ];
-
-			// find all connecting edges (using lookupTable)
-			connectingEdges = metaVertices[ i ].edges;
-			n = connectingEdges.length;
-
-			if ( n === 3 ) {
-
-				beta = 3 / 16;
-
-			} else if (n > 3) {
-
-				beta = 3 / (8 * n); // Warren's modified formula
-
-			}
-
-			// Loop's original beta formula
-			// beta = 1 / n * ( 5/8 - Math.pow( 3/8 + 1/4 * Math.cos( 2 * Math. PI / n ), 2) );
-
-			sourceVertexWeight = 1 - n * beta;
-			connectingVertexWeight = beta;
-
-			if ( n <= 2 ) {
-
-				// crease and boundary rules
-
-				if ( n === 2 ) {
-
-					sourceVertexWeight = 3 / 4;
-					connectingVertexWeight = 1 / 8;
-
-				}
-
-			}
-
-			newSourceVertex = oldVertex.multiplyScalar( sourceVertexWeight );
-
-			tmp.set( 0, 0, 0 );
-
-			for ( j = 0; j < n; j++ ) {
-
-				connectingEdge = connectingEdges[ j ];
-				other = connectingEdge.a !== i ? connectingEdge.a : connectingEdge.b;
-				oldVertices.index_to_register( other, 1, XYZ );
-				tmp.add( oldVertices.register[ 1 ] );
-
-			}
-
-			tmp.multiplyScalar( connectingVertexWeight );
-			newSourceVertex.add( tmp );
-
-			newVertices.push_element( newSourceVertex,XYZ );
-
-		}
-
-
-		/******************************************************
-		*
-		*	Step 3.
-		*	Generate faces between source vertices and edge vertices.
-		*
-		*******************************************************/
-
-
-		var edge1, edge2, edge3;
-		newFaces = new TypedArrayHelper( ( geometry.index.array.length * 4 ) / 3, 1, THREE.Face3, Float32Array, 3, ABC );
-		newUVs = new TypedArrayHelper( ( geometry.getAttribute( 'uv' ).array.length * 4 ) / 2, 3, THREE.Vector2, Float32Array, 2, XY );
-		var x3 = newUVs.register[ 0 ];
-		var x4 = newUVs.register[ 1 ];
-		var x5 = newUVs.register[ 2 ];
-		var tFace = newFaces.register[ 0 ];
-
-		for ( i = 0, il = oldFaces.length; i < il; i++ ) {
-
-			oldFaces.index_to_register( i, 0 );
-			face = oldFaces.register[ 0 ];
-
-			// find the 3 new edges vertex of each old face
-			// The new source verts are added after the new edge verts now..
-
-			edge1 = getEdge( face.a, face.b, sourceEdges ).newEdge;
-			edge2 = getEdge( face.b, face.c, sourceEdges ).newEdge;
-			edge3 = getEdge( face.c, face.a, sourceEdges ).newEdge;
-
-			// create 4 faces.
-			tFace.set( edge1, edge2, edge3 );
-			newFace( newFaces, tFace );
-			tFace.set( face.a + edgeLength, edge1, edge3 );
-			newFace( newFaces, tFace );
-			tFace.set( face.b + edgeLength, edge2, edge1 );
-			newFace( newFaces, tFace );
-			tFace.set( face.c + edgeLength, edge3, edge2 );
-			newFace( newFaces, tFace );
-
-
-			/*
-				0________C_______2
-				 \      /\      /
-				  \ F2 /  \ F4 /
-				   \  / F1 \  /
-				    \/______\/
-				   A \      / B
-				      \ F3 /
-				       \  /
-				        \/
-				         1
-
-				Draw orders:
-				F1: ABC x3,x4,x5
-				F2: 0AC x0,x3,x5
-				F3: 1BA x1,x4,x3
-				F4: 2CB x2,x5,x4
-
-				0: x0
-				1: x1
-				2: x2
-				A: x3
-				B: x4
-				C: x5
-			*/
-
-			if ( doUvs === true ) {
-
-				oldUvs.index_to_register( ( i * 3 ) + 0, 0 );
-				oldUvs.index_to_register( ( i * 3 ) + 1, 1 );
-				oldUvs.index_to_register( ( i * 3 ) + 2, 2 );
-
-				var x0 = oldUvs.register[ 0 ]; // uv[0];
-				var x1 = oldUvs.register[ 1 ]; // uv[1];
-				var x2 = oldUvs.register[ 2 ]; // uv[2];
-
-				x3.set( midpoint( x0.x, x1.x ), midpoint( x0.y, x1.y ) );
-				x4.set( midpoint( x1.x, x2.x ), midpoint( x1.y, x2.y ) );
-				x5.set( midpoint( x0.x, x2.x ), midpoint( x0.y, x2.y ) );
-
-				newUv( newUVs, x3, x4, x5 );
-				newUv( newUVs, x0, x3, x5 );
-
-				newUv( newUVs, x1, x4, x3 );
-				newUv( newUVs, x2, x5, x4 );
-
-			}
-
-		}
-
-		// Overwrite old arrays
-
-		newFaces.trim_size();
-		newVertices.trim_size();
-		newUVs.trim_size();
-
-		geometry.setIndex( new THREE.BufferAttribute( newFaces.buffer ,3 ) );
-		geometry.addAttribute( 'position', new THREE.BufferAttribute( newVertices.buffer, 3 ) );
-		geometry.addAttribute( 'uv', new THREE.BufferAttribute( newUVs.buffer, 2 ) );
-
-	};
-
-} ) ();

+ 14 - 0
examples/js/modifiers/SubdivisionModifier.js

@@ -23,6 +23,18 @@ THREE.SubdivisionModifier = function ( subdivisions ) {
 // Applies the "modify" pattern
 THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
 
+	if ( geometry.isBufferGeometry ) {
+
+		geometry = new THREE.Geometry().fromBufferGeometry( geometry );
+
+	} else {
+
+		geometry = geometry.clone();
+
+	}
+
+	geometry.mergeVertices();
+
 	var repeats = this.subdivisions;
 
 	while ( repeats -- > 0 ) {
@@ -34,6 +46,8 @@ THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
 	geometry.computeFaceNormals();
 	geometry.computeVertexNormals();
 
+	return geometry;
+
 };
 
 ( function () {

+ 0 - 55
examples/js/nodes/AttributeNode.js

@@ -1,55 +0,0 @@
-/**
- * @author sunag / http://www.sunag.com.br/
- */
-
-THREE.AttributeNode = function ( name, type ) {
-
-	THREE.GLNode.call( this, type );
-
-	this.name = name;
-
-};
-
-THREE.AttributeNode.prototype = Object.create( THREE.GLNode.prototype );
-THREE.AttributeNode.prototype.constructor = THREE.AttributeNode;
-THREE.AttributeNode.prototype.nodeType = "Attribute";
-
-THREE.AttributeNode.prototype.getAttributeType = function ( builder ) {
-
-	return typeof this.type === 'number' ? builder.getConstructorFromLength( this.type ) : this.type;
-
-};
-
-THREE.AttributeNode.prototype.getType = function ( builder ) {
-
-	var type = this.getAttributeType( builder );
-
-	return builder.getTypeByFormat( type );
-
-};
-
-THREE.AttributeNode.prototype.generate = function ( builder, output ) {
-
-	var type = this.getAttributeType( builder );
-
-	var attribute = builder.material.getAttribute( this.name, type );
-
-	return builder.format( builder.isShader( 'vertex' ) ? this.name : attribute.varying.name, this.getType( builder ), output );
-
-};
-
-THREE.AttributeNode.prototype.toJSON = function ( meta ) {
-
-	var data = this.getJSONNode( meta );
-
-	if ( ! data ) {
-
-		data = this.createJSONNode( meta );
-
-		data.out = this.type;
-
-	}
-
-	return data;
-
-};

+ 0 - 110
examples/js/nodes/ConstNode.js

@@ -1,110 +0,0 @@
-/**
- * @author sunag / http://www.sunag.com.br/
- */
-
-THREE.ConstNode = function ( src, useDefine ) {
-
-	THREE.TempNode.call( this );
-
-	this.eval( src || THREE.ConstNode.PI, useDefine );
-
-};
-
-THREE.ConstNode.PI = 'PI';
-THREE.ConstNode.PI2 = 'PI2';
-THREE.ConstNode.RECIPROCAL_PI = 'RECIPROCAL_PI';
-THREE.ConstNode.RECIPROCAL_PI2 = 'RECIPROCAL_PI2';
-THREE.ConstNode.LOG2 = 'LOG2';
-THREE.ConstNode.EPSILON = 'EPSILON';
-
-THREE.ConstNode.prototype = Object.create( THREE.TempNode.prototype );
-THREE.ConstNode.prototype.constructor = THREE.ConstNode;
-THREE.ConstNode.prototype.nodeType = "Const";
-
-THREE.ConstNode.prototype.getType = function ( builder ) {
-
-	return builder.getTypeByFormat( this.type );
-
-};
-
-THREE.ConstNode.prototype.eval = function ( src, useDefine ) {
-
-	src = ( src || '' ).trim();
-
-	var name, type, value = "";
-
-	var rDeclaration = /^([a-z_0-9]+)\s([a-z_0-9]+)\s?\=?\s?(.*?)(\;|$)/i;
-	var match = src.match( rDeclaration );
-
-	this.useDefine = useDefine;
-
-	if ( match && match.length > 1 ) {
-
-		type = match[ 1 ];
-		name = match[ 2 ];
-		value = match[ 3 ];
-
-	} else {
-
-		name = src;
-		type = 'fv1';
-
-	}
-
-	this.name = name;
-	this.type = type;
-	this.value = value;
-
-};
-
-THREE.ConstNode.prototype.build = function ( builder, output ) {
-
-	if ( output === 'source' ) {
-
-		if ( this.value ) {
-
-			if ( this.useDefine ) {
-
-				return '#define ' + this.name + ' ' + this.value;
-
-			}
-
-			return 'const ' + this.type + ' ' + this.name + ' = ' + this.value + ';';
-
-		}
-
-	} else {
-
-		builder.include( this );
-
-		return builder.format( this.name, this.getType( builder ), output );
-
-	}
-
-};
-
-THREE.ConstNode.prototype.generate = function ( builder, output ) {
-
-	return builder.format( this.name, this.getType( builder ), output );
-
-};
-
-THREE.ConstNode.prototype.toJSON = function ( meta ) {
-
-	var data = this.getJSONNode( meta );
-
-	if ( ! data ) {
-
-		data = this.createJSONNode( meta );
-
-		data.name = this.name;
-		data.out = this.type;
-
-		if ( this.value ) data.value = this.value;
-		if ( data.useDefine === true ) data.useDefine = true;
-
-	}
-
-	return data;
-
-};

部分文件因为文件数量过多而无法显示