aardgoose 6 years ago
parent
commit
b5eacca97e
100 changed files with 6585 additions and 1942 deletions
  1. 0 0
      build/three.js
  2. 320 320
      build/three.min.js
  3. 0 0
      build/three.module.js
  4. 1 1
      docs/api/en/animation/KeyframeTrack.html
  5. 2 2
      docs/api/en/core/Clock.html
  6. 1 0
      docs/api/en/renderers/WebGLRenderer.html
  7. 1 1
      docs/api/zh/animation/KeyframeTrack.html
  8. 2 2
      docs/api/zh/core/Clock.html
  9. 18 18
      docs/examples/math/convexhull/ConvexHull.html
  10. 2 2
      docs/examples/math/convexhull/Face.html
  11. 2 2
      docs/examples/math/convexhull/HalfEdge.html
  12. 2 2
      docs/examples/math/convexhull/VertexList.html
  13. 2 2
      docs/examples/math/convexhull/VertexNode.html
  14. 7 0
      docs/examples/renderers/SVGRenderer.html
  15. 6 6
      docs/list.js
  16. 1 1
      docs/manual/en/introduction/Drawing-lines.html
  17. 0 2
      docs/manual/en/introduction/How-to-update-things.html
  18. 41 0
      docs/manual/en/introduction/Import-via-modules.html
  19. 1 4
      docs/manual/en/introduction/Useful-links.html
  20. 8 1
      docs/page.css
  21. 1 1
      docs/scenes/geometry-browser.html
  22. 1 0
      examples/files.js
  23. 0 71
      examples/js/ImprovedNoise.js
  24. 0 23
      examples/js/PRNG.js
  25. 0 324
      examples/js/SimplexNoise.js
  26. 0 0
      examples/js/animation/AnimationClipCreator.js
  27. 21 27
      examples/js/animation/TimelinerController.js
  28. 0 39
      examples/js/crossfade/gui.js
  29. 0 119
      examples/js/crossfade/scenes.js
  30. 0 168
      examples/js/crossfade/transition.js
  31. 6 0
      examples/js/effects/AsciiEffect.js
  32. 11 14
      examples/js/effects/OutlineEffect.js
  33. 13 13
      examples/js/geometries/BoxLineGeometry.js
  34. 36 47
      examples/js/geometries/ConvexGeometry.js
  35. 202 210
      examples/js/geometries/DecalGeometry.js
  36. 0 157
      examples/js/geometries/Hilbert.js
  37. 3 3
      examples/js/geometries/LightningStrike.js
  38. 0 0
      examples/js/geometries/ParametricGeometries.js
  39. 1 4
      examples/js/geometries/TeapotBufferGeometry.js
  40. 27 132
      examples/js/loaders/AssimpLoader.js
  41. 0 2
      examples/js/loaders/BasisTextureLoader.js
  42. 10 2
      examples/js/loaders/LDrawLoader.js
  43. 7 7
      examples/js/loaders/SVGLoader.js
  44. 15 3
      examples/js/loaders/VTKLoader.js
  45. 6 9
      examples/js/math/ConvexHull.js
  46. 72 0
      examples/js/math/ImprovedNoise.js
  47. 0 15
      examples/js/math/Lut.js
  48. 405 0
      examples/js/math/SimplexNoise.js
  49. 4 5
      examples/js/modifiers/SubdivisionModifier.js
  50. 2 2
      examples/js/modifiers/TessellateModifier.js
  51. 4 0
      examples/js/objects/ReflectorRTT.js
  52. 10 10
      examples/js/objects/ShadowMesh.js
  53. 2 4
      examples/js/postprocessing/EffectComposer.js
  54. 2 2
      examples/js/postprocessing/SSAOPass.js
  55. 28 0
      examples/js/renderers/SVGRenderer.js
  56. 8 8
      examples/js/renderers/WebGLDeferredRenderer.js
  57. 148 0
      examples/js/utils/GeometryUtils.js
  58. 3 11
      examples/js/vr/WebVR.js
  59. 16 0
      examples/jsm/effects/AnaglyphEffect.d.ts
  60. 181 0
      examples/jsm/effects/AnaglyphEffect.js
  61. 22 0
      examples/jsm/effects/AsciiEffect.d.ts
  62. 293 0
      examples/jsm/effects/AsciiEffect.js
  63. 36 0
      examples/jsm/effects/OutlineEffect.d.ts
  64. 586 0
      examples/jsm/effects/OutlineEffect.js
  65. 12 0
      examples/jsm/effects/ParallaxBarrierEffect.d.ts
  66. 118 0
      examples/jsm/effects/ParallaxBarrierEffect.js
  67. 14 0
      examples/jsm/effects/PeppersGhostEffect.d.ts
  68. 151 0
      examples/jsm/effects/PeppersGhostEffect.js
  69. 13 0
      examples/jsm/effects/StereoEffect.d.ts
  70. 58 0
      examples/jsm/effects/StereoEffect.js
  71. 7 0
      examples/jsm/geometries/BoxLineGeometry.d.ts
  72. 74 0
      examples/jsm/geometries/BoxLineGeometry.js
  73. 15 0
      examples/jsm/geometries/DecalGeometry.d.ts
  74. 358 0
      examples/jsm/geometries/DecalGeometry.js
  75. 27 0
      examples/jsm/geometries/ParametricGeometries.d.ts
  76. 274 0
      examples/jsm/geometries/ParametricGeometries.js
  77. 7 0
      examples/jsm/geometries/TeapotBufferGeometry.d.ts
  78. 725 0
      examples/jsm/geometries/TeapotBufferGeometry.js
  79. 28 135
      examples/jsm/loaders/AssimpLoader.js
  80. 1 1
      examples/jsm/loaders/ColladaLoader.d.ts
  81. 1 1
      examples/jsm/loaders/GCodeLoader.d.ts
  82. 7 7
      examples/jsm/loaders/SVGLoader.js
  83. 25 0
      examples/jsm/math/ColorConverter.d.ts
  84. 94 0
      examples/jsm/math/ColorConverter.js
  85. 4 0
      examples/jsm/math/ImprovedNoise.d.ts
  86. 74 0
      examples/jsm/math/ImprovedNoise.js
  87. 29 0
      examples/jsm/math/Lut.d.ts
  88. 191 0
      examples/jsm/math/Lut.js
  89. 9 0
      examples/jsm/math/SimplexNoise.d.ts
  90. 407 0
      examples/jsm/math/SimplexNoise.js
  91. 8 0
      examples/jsm/modifiers/ExplodeModifier.d.ts
  92. 46 0
      examples/jsm/modifiers/ExplodeModifier.js
  93. 9 0
      examples/jsm/modifiers/SimplifyModifier.d.ts
  94. 503 0
      examples/jsm/modifiers/SimplifyModifier.js
  95. 12 0
      examples/jsm/modifiers/SubdivisionModifier.d.ts
  96. 409 0
      examples/jsm/modifiers/SubdivisionModifier.js
  97. 10 0
      examples/jsm/modifiers/TessellateModifier.d.ts
  98. 242 0
      examples/jsm/modifiers/TessellateModifier.js
  99. 6 0
      examples/jsm/objects/ReflectorRTT.d.ts
  100. 18 0
      examples/jsm/objects/ReflectorRTT.js

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


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


File diff suppressed because it is too large
+ 0 - 0
build/three.module.js


+ 1 - 1
docs/api/en/animation/KeyframeTrack.html

@@ -58,7 +58,7 @@
 
 		<p>
 			Some examples of how to manually create [page:AnimationClip AnimationClips] with different sorts
-			of KeyframeTracks can be found in the [link:https://threejs.org/examples/js/AnimationClipCreator.js]
+			of KeyframeTracks can be found in the [link:https://threejs.org/examples/js/animation/AnimationClipCreator.js AnimationClipCreator]
 			file.
 		</p>
 

+ 2 - 2
docs/api/en/core/Clock.html

@@ -11,8 +11,8 @@
 		<h1>[name]</h1>
 
 		<p class="desc">
-		Object for keeping track of time. This uses <a href="https://developer.mozilla.org/en-US/docs/Web/API/Performance/now">performance.now()</a>
-		if it is available, otherwise it reverts to the less accurate <a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now">Date.now()</a>.
+		Object for keeping track of time. This uses [link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now]
+		if it is available, otherwise it reverts to the less accurate [link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now].
 		</p>
 
 

+ 1 - 0
docs/api/en/renderers/WebGLRenderer.html

@@ -113,6 +113,7 @@
 		- [page:Boolean floatVertexTextures]: *true* if [page:Boolean floatFragmentTextures] and [page:Boolean vertexTextures] are both true.<br />
 		- [page:Method getMaxAnisotropy](): Returns the maximum available anisotropy.<br />
 		- [page:Method getMaxPrecision](): Returns the maximum available precision for vertex and fragment shaders. <br />
+		- [page:Boolean isWebGL2: *true* if the context in use is a WebGL2RenderingContext object.<br />
 		- [page:Boolean logarithmicDepthBuffer]: *true* if the [page:parameter logarithmicDepthBuffer] was set to true in the constructor and
 		the context supports the [link:https://developer.mozilla.org/en-US/docs/Web/API/EXT_frag_depth EXT_frag_depth] extension.
 			According to [link:https://webglstats.com/ WebGLStats], as of February 2016 around 66% of WebGL enabled devices support this.<br />

+ 1 - 1
docs/api/zh/animation/KeyframeTrack.html

@@ -49,7 +49,7 @@
 		</ul>
 
 		<p>
-            可以在[link:https://threejs.org/examples/js/AnimationClipCreator.js]文件中找到用不同类型的关键帧轨道创建动画剪辑([page:AnimationClip AnimationClips])的示例。
+            可以在[link:https://threejs.org/examples/js/animation/AnimationClipCreator.js AnimationClipCreator]文件中找到用不同类型的关键帧轨道创建动画剪辑([page:AnimationClip AnimationClips])的示例。
 		</p>
 
 		<p>

+ 2 - 2
docs/api/zh/core/Clock.html

@@ -10,8 +10,8 @@
 	<body>
 		<h1>[name]</h1>
 		<p class="desc">
-			该对象用于跟踪时间。如果<a href="https://developer.mozilla.org/en-US/docs/Web/API/Performance/now">performance.now()</a>可用,则
-			Clock 对象通过该方法实现,否则通过歉精准的<a href="https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now">Date.now()</a>实现。
+			该对象用于跟踪时间。如果[link:https://developer.mozilla.org/en-US/docs/Web/API/Performance/now performance.now]可用,则
+			Clock 对象通过该方法实现,否则通过歉精准的[link:https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Date/now Date.now]实现。
 		</p>
 
 

+ 18 - 18
docs/examples/quickhull/QuickHull.html → docs/examples/math/convexhull/ConvexHull.html

@@ -2,7 +2,7 @@
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
-		<base href="../../" />
+		<base href="../../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
 		<link type="text/css" rel="stylesheet" href="page.css" />
@@ -11,7 +11,7 @@
 		<h1>[name]</h1>
 
 		<p class="desc">
-			General information about the Quickhull algorithm: Dirk Gregorius. March 2014, Game Developers Conference: [link:http://media.steampowered.com/apps/valve/2014/DirkGregorius_ImplementingQuickHull.pdf Implementing QuickHull].
+			A convex hull class. Implements the Quickhull algorithm by: Dirk Gregorius. March 2014, Game Developers Conference: [link:http://media.steampowered.com/apps/valve/2014/DirkGregorius_ImplementingQuickHull.pdf Implementing QuickHull].
 		</p>
 
 
@@ -63,19 +63,19 @@
 		<p>Creates a face with the vertices 'eyeVertex.point', 'horizonEdge.tail' and 'horizonEdge.head' in CCW order.
 			All the half edges are created in CCW order thus the face is always pointing outside the hull</p>
 
-		<h3>[method:QuickHull addNewFaces]( [param:VertexNode eyeVertex], [param:HalfEdge horizonEdge] )</h3>
+		<h3>[method:ConvexHull addNewFaces]( [param:VertexNode eyeVertex], [param:HalfEdge horizonEdge] )</h3>
 		[page:VertexNode eyeVertex] - The vertex that is added to the hull.<br /><br />
 		[page:HalfEdge horizon] - An array of half-edges that form the horizon.<br /><br />
 
 		<p>Adds 'horizon.length' faces to the hull, each face will be linked with the horizon opposite face and the face on the left/right.</p>
 
-		<h3>[method:QuickHull addVertexToFace]( [param:VertexNode vertex], [param:Face face]	)</h3>
+		<h3>[method:ConvexHull addVertexToFace]( [param:VertexNode vertex], [param:Face face]	)</h3>
 		[page:VertexNodeNode vertex] - The vertex to add.<br /><br />
 		[page:Face face] - The target face.<br /><br />
 
 		<p>Adds a vertex to the 'assigned' list of vertices and assigns it to the given face.</p>
 
-		<h3>[method:QuickHull addVertexToHull]( [param:VertexNode eyeVertex] )</h3>
+		<h3>[method:ConvexHull addVertexToHull]( [param:VertexNode eyeVertex] )</h3>
 		[page:VertexNode eyeVertex] - The vertex that is added to the hull.<br /><br />
 
 		<p>Adds a vertex to the hull with the following algorithm
@@ -87,11 +87,11 @@
 			</ul>
 		</p>
 
-		<h3>[method:QuickHull cleanup]()</h3>
+		<h3>[method:ConvexHull cleanup]()</h3>
 
 		<p>Cleans up internal properties after computing the convex hull.</p>
 
-		<h3>[method:QuickHull compute]()</h3>
+		<h3>[method:ConvexHull compute]()</h3>
 
 		<p>Starts the execution of the quick hull algorithm.</p>
 
@@ -99,7 +99,7 @@
 
 		<p>Computes the extremes values (min/max vectors) which will be used to compute the inital hull.</p>
 
-		<h3>[method:QuickHull computeHorizon]( [param:Vector3 eyePoint], [param:HalfEdge crossEdge], [param:Face face], [param:Array horizon]	)</h3>
+		<h3>[method:ConvexHull computeHorizon]( [param:Vector3 eyePoint], [param:HalfEdge crossEdge], [param:Face face], [param:Array horizon]	)</h3>
 		[page:Vector3 eyePoint] - The 3D-coordinates of a point.<br /><br />
 		[page:HalfEdge crossEdge] - The edge used to jump to the current face.<br /><br />
 		[page:Face face] - The current face being tested.<br /><br />
@@ -107,16 +107,16 @@
 
 		<p>Computes a chain of half edges in CCW order called the 'horizon'. For an edge to be part of the horizon it must join a face that can see 'eyePoint' and a face that cannot see 'eyePoint'.</p>
 
-		<h3>[method:QuickHull computeInitialHull]()</h3>
+		<h3>[method:ConvexHull computeInitialHull]()</h3>
 
 		<p>Computes the initial simplex assigning to its faces all the points that are candidates to form part of the hull.</p>
 
-		<h3>[method:QuickHull containsPoint]( [param:Vector3 point] )</h3>
+		<h3>[method:ConvexHull containsPoint]( [param:Vector3 point] )</h3>
 		[page:Vector3 point] - A point in 3D space.<br /><br />
 
 		<p>Returns *true* if the given point is inside this convex hull.</p>
 
-		<h3>[method:QuickHull deleteFaceVertices]( [param:Face face], [param:Face absorbingFace]	)</h3>
+		<h3>[method:ConvexHull deleteFaceVertices]( [param:Face face], [param:Face absorbingFace]	)</h3>
 		[page:Face face] - The given face.<br /><br />
 		[page:Face absorbingFace] - An optional face that tries to absorb the vertices of the first face.<br /><br />
 
@@ -139,7 +139,7 @@
 
 		<p>Returns *true* if the given ray intersects with this convex hull.</p>
 
-		<h3>[method:QuickHull makeEmpty]()</h3>
+		<h3>[method:ConvexHull makeEmpty]()</h3>
 
 		<p>Makes this convex hull empty.</p>
 
@@ -153,7 +153,7 @@
 			</ul>
 		</p>
 
-		<h3>[method:QuickHull reindexFaces]()</h3>
+		<h3>[method:ConvexHull reindexFaces]()</h3>
 
 		<p>Removes inactive (e.g. deleted) faces from the internal face list.</p>
 
@@ -162,30 +162,30 @@
 
 		<p>Removes all the visible vertices that a given face is able to see which are stored in the 'assigned' vertext list.</p>
 
-		<h3>[method:QuickHull removeVertexFromFace]( [param:VertexNode vertex], [param:Face face]	)</h3>
+		<h3>[method:ConvexHull removeVertexFromFace]( [param:VertexNode vertex], [param:Face face]	)</h3>
 		[page:VertexNode vertex] - The vertex to remove.<br /><br />
 		[page:Face face] - The target face.<br /><br />
 
 		<p>Removes a vertex from the 'assigned' list of vertices and from the given face. It also makes sure that the link from 'face' to the first vertex it sees in 'assigned' is linked correctly after the removal.</p>
 
-		<h3>[method:QuickHull resolveUnassignedPoints]( [param:Array newFaces]	)</h3>
+		<h3>[method:ConvexHull resolveUnassignedPoints]( [param:Array newFaces]	)</h3>
 		[page:Face newFaces] - An array of new faces.<br /><br />
 
 		<p>Reassigns as many vertices as possible from the unassigned list to the new faces.</p>
 
-		<h3>[method:QuickHull setFromObject]( [param:Object3D object] )</h3>
+		<h3>[method:ConvexHull setFromObject]( [param:Object3D object] )</h3>
 		[page:Object3D object] - [page:Object3D] to compute the convex hull of.<br /><br />
 
 		<p>Computes the convex hull of an [page:Object3D] (including its children),
 		accounting for the world transforms of both the object and its childrens.</p>
 
-		<h3>[method:QuickHull setFromPoints]( [param:Array points] )</h3>
+		<h3>[method:ConvexHull setFromPoints]( [param:Array points] )</h3>
 		[page:Array points] - Array of [page:Vector3 Vector3s] that the resulting convex hull will contain.<br /><br />
 
 		<p>Computes to convex hull for the given array of points.</p>
 
 		<h2>Source</h2>
 
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/QuickHull.js examples/js/QuickHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/math/ConvexHull.js examples/js/ConvexHull.js]
 	</body>
 </html>

+ 2 - 2
docs/examples/quickhull/Face.html → docs/examples/math/convexhull/Face.html

@@ -2,7 +2,7 @@
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
-		<base href="../../" />
+		<base href="../../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
 		<link type="text/css" rel="stylesheet" href="page.css" />
@@ -84,6 +84,6 @@
 
 		<h2>Source</h2>
 
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/QuickHull.js examples/js/QuickHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/math/ConvexHull.js examples/js/math/ConvexHull.js]
 	</body>
 </html>

+ 2 - 2
docs/examples/quickhull/HalfEdge.html → docs/examples/math/convexhull/HalfEdge.html

@@ -2,7 +2,7 @@
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
-		<base href="../../" />
+		<base href="../../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
 		<link type="text/css" rel="stylesheet" href="page.css" />
@@ -74,6 +74,6 @@
 
 		<h2>Source</h2>
 
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/QuickHull.js examples/js/QuickHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/math/ConvexHull.js examples/js/math/ConvexHull.js]
 	</body>
 </html>

+ 2 - 2
docs/examples/quickhull/VertexList.html → docs/examples/math/convexhull/VertexList.html

@@ -2,7 +2,7 @@
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
-		<base href="../../" />
+		<base href="../../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
 		<link type="text/css" rel="stylesheet" href="page.css" />
@@ -86,6 +86,6 @@
 
 		<h2>Source</h2>
 
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/QuickHull.js examples/js/QuickHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/math/ConvexHull.js examples/js/math/ConvexHull.js]
 	</body>
 </html>

+ 2 - 2
docs/examples/quickhull/VertexNode.html → docs/examples/math/convexhull/VertexNode.html

@@ -2,7 +2,7 @@
 <html lang="en">
 	<head>
 		<meta charset="utf-8" />
-		<base href="../../" />
+		<base href="../../../" />
 		<script src="list.js"></script>
 		<script src="page.js"></script>
 		<link type="text/css" rel="stylesheet" href="page.css" />
@@ -47,6 +47,6 @@
 
 		<h2>Source</h2>
 
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/QuickHull.js examples/js/QuickHull.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/math/ConvexHull.js examples/js/math/ConvexHull.js]
 	</body>
 </html>

+ 7 - 0
docs/examples/renderers/SVGRenderer.html

@@ -61,6 +61,13 @@
 
 		<h3>[name]()</h3>
 
+		<h2>Properties</h2>
+
+		<h3>[property:Number overdraw]</h3>
+		<p>
+		Number of fractional pixels to enlarge polygons in order to prevent anti-aliasing gaps. Range is [0..1]. Default is *0.5*.
+		</p>
+
 		<h2>Methods</h2>
 
 		<h3>[method:null clear]()</h3>

+ 6 - 6
docs/list.js

@@ -393,12 +393,12 @@ var list = {
 				"LookupTable": "examples/Lut",
 			},
 
-			"QuickHull": {
-				"Face": "examples/quickhull/Face",
-				"HalfEdge": "examples/quickhull/HalfEdge",
-				"QuickHull": "examples/quickhull/QuickHull",
-				"VertexNode": "examples/quickhull/VertexNode",
-				"VertexList": "examples/quickhull/VertexList"
+			"ConvexHull": {
+				"Face": "examples/math/convexhull/Face",
+				"HalfEdge": "examples/math/convexhull/HalfEdge",
+				"ConvexHull": "examples/math/convexhull/ConvexHull",
+				"VertexNode": "examples/math/convexhull/VertexNode",
+				"VertexList": "examples/math/convexhull/VertexList"
 			},
 
 			"Renderers": {

+ 1 - 1
docs/manual/en/introduction/Drawing-lines.html

@@ -12,7 +12,7 @@
 		<div>
 			<p>
 				Let's say you want to draw a line or a circle, not a wireframe [page:Mesh].
-				First we need to setup the [page:WebGLRenderer renderer], [page:Scene scene] and camera (see the Creating a scene page).
+				First we need to set up the [page:WebGLRenderer renderer], [page:Scene scene] and camera (see the Creating a scene page).
 			</p>
 
 			<p>Here is the code that we will use:</p>

+ 0 - 2
docs/manual/en/introduction/How-to-update-things.html

@@ -178,8 +178,6 @@ geometry.tangentsNeedUpdate = true;
 
 			<p>Also GLstate related parameters can change any time (depthTest, blending, polygonOffset, etc).</p>
 
-			<p>Flat / smooth shading is baked into normals. You need to reset normals buffer (see above).</p>
-
 			<p>The following properties can't be easily changed at runtime (once the material is rendered at least once):</p>
 			<ul>
 				<li>numbers and types of uniforms</li>

+ 41 - 0
docs/manual/en/introduction/Import-via-modules.html

@@ -103,6 +103,16 @@
 						<li>NURBSUtils</li>
 					</ul>
 				</li>
+				<li>effects
+					<ul>
+						<li>AnaglyphEffect</li>
+						<li>AsciiEffect</li>
+						<li>OutlineEffect</li>
+						<li>ParallaxBarrierEffect</li>
+						<li>PeppersGhostEffect</li>
+						<li>StereoEffect</li>
+					</ul>
+				</li>
 				<li>exporters
 					<ul>
 						<li>ColladaExporter</li>
@@ -114,6 +124,14 @@
 						<li>TypedGeometryExporter</li>
 					</ul>
 				</li>
+				<li>geometries
+					<ul>
+						<li>BoxLineGeometry</li>
+						<li>DecalGeometry</li>
+						<li>ParametricGeometries</li>
+						<li>TeapotBufferGeometry</li>
+					</ul>
+				</li>
 				<li>loaders
 					<ul>
 						<li>3MFLoader</li>
@@ -143,11 +161,32 @@
 						<li>VRMLLoader</li>
 					</ul>
 				</li>
+				<li>math
+					<ul>
+						<li>ColorConverter</li>
+						<li>ImprovedNoise</li>
+						<li>Lut</li>
+						<li>SimplexNoise</li>
+					</ul>
+				</li>
+				<li>modifiers
+					<ul>
+						<li>ExplodeModifier</li>
+						<li>SimplifyModifier</li>
+						<li>SubdivisionModifier</li>
+						<li>TessellateModifier</li>
+					</ul>
+				</li>
 				<li>objects
 					<ul>
 						<li>Lensflare</li>
 						<li>Reflector</li>
 						<li>Refractor</li>
+						<li>ReflectorRTT</li>
+						<li>ShadowMesh</li>
+						<li>Sky</li>
+						<li>Water</li>
+						<li>Water2</li>
 					</ul>
 				</li>
 				<li>pmrem
@@ -177,6 +216,7 @@
 						<li>ShaderPass</li>
 						<li>SMAAPass</li>
 						<li>SSAARenderPass</li>
+						<li>SSAOPass</li>
 						<li>TAARenderPass</li>
 						<li>TexturePass</li>
 						<li>UnrealBloomPass</li>
@@ -190,6 +230,7 @@
 						<li>SoftwareRenderer</li>
 						<li>SVGRenderer</li>
 						<li>RaytracingRenderer</li>
+						<li>WebGLDeferredRenderer</li>
 					</ul>
 				</li>
 				<li>shaders

+ 1 - 4
docs/manual/en/introduction/Useful-links.html

@@ -17,10 +17,7 @@
 
 			Note also that as three.js is under rapid development, a lot of these links will contain information that is
 			out of date - if something isn't working as you'd expect or as one of these links says it should,
-			check the browser console for warnings or errors, the relevant docs pages and especially the [page:DeprecatedList].<br /><br />
-
-			In addition to this page, mrdoob maintains a collection of links related to three.js over on Google+.
-			Check them out <a href="https://plus.google.com/+ThreejsOrg">here</a>.
+			check the browser console for warnings or errors, the relevant docs pages and especially the [page:DeprecatedList].
 		</p>
 
 		<h2>Help forums</h2>

+ 8 - 1
docs/page.css

@@ -92,7 +92,7 @@ body {
 
 table,
 pre,
-code {
+code:not(.inline) {
 	margin-left: -24px;
 	margin-right: -24px;
 	margin-top: 20px;
@@ -133,6 +133,13 @@ code {
 	box-sizing: border-box;
 }
 
+code.inline {
+	display: inline-block;
+	vertical-align: middle;
+	border-radius: 4px;
+	padding: 2px 5px;
+}
+
 iframe {
 	width: 100%;
 	height: 420px;

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

@@ -24,7 +24,7 @@
 		<script src="../../build/three.min.js"></script>
 		<script src='../../examples/js/libs/dat.gui.min.js'></script>
 		<script src="../../examples/js/controls/OrbitControls.js"></script>
-		<script src="../../examples/js/ParametricGeometries.js"></script>
+		<script src="../../examples/js/geometries/ParametricGeometries.js"></script>
 
 		<script src='js/geometry.js'></script>
 

+ 1 - 0
examples/files.js

@@ -126,6 +126,7 @@ var files = {
 		"webgl_loader_sea3d_sound",
 		"webgl_loader_stl",
 		"webgl_loader_svg",
+		"webgl_loader_texture_basis",
 		"webgl_loader_texture_dds",
 		"webgl_loader_texture_exr",
 		"webgl_loader_texture_hdr",

+ 0 - 71
examples/js/ImprovedNoise.js

@@ -1,71 +0,0 @@
-// http://mrl.nyu.edu/~perlin/noise/
-
-var ImprovedNoise = function () {
-
-	var p = [ 151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,
-		 23,190,6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,
-		 174,20,125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231,83,111,229,122,60,211,
-		 133,230,220,105,92,41,55,46,245,40,244,102,143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,
-		 89,18,169,200,196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226,250,124,123,5,
-		 202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,223,183,170,213,119,
-		 248,152,2,44,154,163,70,221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113,224,232,
-		 178,185,112,104,218,246,97,228,251,34,242,193,238,210,144,12,191,179,162,241,81,51,145,235,249,
-		 14,239,107,49,192,214,31,181,199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236,205,
-		 93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180 ];
-
-	for (var i = 0; i < 256 ; i ++) {
-
-		p[256 + i] = p[i];
-
-	}
-
-	function fade(t) {
-
-		return t * t * t * (t * (t * 6 - 15) + 10);
-
-	}
-
-	function lerp(t, a, b) {
-
-		return a + t * (b - a);
-
-	}
-
-	function grad(hash, x, y, z) {
-
-		var h = hash & 15;
-		var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
-		return ((h&1) == 0 ? u : -u) + ((h&2) == 0 ? v : -v);
-
-	}
-
-	return {
-
-		noise: function (x, y, z) {
-
-			var floorX = Math.floor(x), floorY = Math.floor(y), floorZ = Math.floor(z);
-
-			var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255;
-
-			x -= floorX;
-			y -= floorY;
-			z -= floorZ;
-
-			var xMinus1 = x - 1, yMinus1 = y - 1, zMinus1 = z - 1;
-
-			var u = fade(x), v = fade(y), w = fade(z);
-
-			var A = p[X] + Y, AA = p[A] + Z, AB = p[A + 1] + Z, B = p[X + 1] + Y, BA = p[B] + Z, BB = p[B + 1] + Z;
-
-			return lerp(w, lerp(v, lerp(u, grad(p[AA], x, y, z),
-							grad(p[BA], xMinus1, y, z)),
-						lerp(u, grad(p[AB], x, yMinus1, z),
-							grad(p[BB], xMinus1, yMinus1, z))),
-					lerp(v, lerp(u, grad(p[AA + 1], x, y, zMinus1),
-							grad(p[BA + 1], xMinus1, y, z - 1)),
-						lerp(u, grad(p[AB + 1], x, yMinus1, zMinus1),
-							grad(p[BB + 1], xMinus1, yMinus1, zMinus1))));
-
-		}
-	}
-};

+ 0 - 23
examples/js/PRNG.js

@@ -1,23 +0,0 @@
-// Park-Miller-Carta Pseudo-Random Number Generator
-// https://github.com/pnitsch/BitmapData.js/blob/master/js/BitmapData.js
-
-var PRNG = function () {
-
-	this.seed = 1;
-	this.next = function() {
-
-		return ( this.gen() / 2147483647 );
-
-	};
-	this.nextRange = function( min, max )	{
-
-		return min + ( ( max - min ) * this.next() )
-
-	};
-	this.gen = function() {
-
-		return this.seed = ( this.seed * 16807 ) % 2147483647;
-
-	};
-
-};

+ 0 - 324
examples/js/SimplexNoise.js

@@ -1,324 +0,0 @@
-// Ported from Stefan Gustavson's java implementation
-// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
-// Read Stefan's excellent paper for details on how this code works.
-//
-// Sean McCullough [email protected]
-//
-// Added 4D noise
-// Joshua Koo [email protected] 
-
-/**
- * You can pass in a random number generator object if you like.
- * It is assumed to have a random() method.
- */
-var SimplexNoise = function(r) {
-	if (r == undefined) r = Math;
-	this.grad3 = [[ 1,1,0 ],[ -1,1,0 ],[ 1,-1,0 ],[ -1,-1,0 ], 
-                                 [ 1,0,1 ],[ -1,0,1 ],[ 1,0,-1 ],[ -1,0,-1 ], 
-                                 [ 0,1,1 ],[ 0,-1,1 ],[ 0,1,-1 ],[ 0,-1,-1 ]]; 
-
-	this.grad4 = [[ 0,1,1,1 ], [ 0,1,1,-1 ], [ 0,1,-1,1 ], [ 0,1,-1,-1 ],
-	     [ 0,-1,1,1 ], [ 0,-1,1,-1 ], [ 0,-1,-1,1 ], [ 0,-1,-1,-1 ],
-	     [ 1,0,1,1 ], [ 1,0,1,-1 ], [ 1,0,-1,1 ], [ 1,0,-1,-1 ],
-	     [ -1,0,1,1 ], [ -1,0,1,-1 ], [ -1,0,-1,1 ], [ -1,0,-1,-1 ],
-	     [ 1,1,0,1 ], [ 1,1,0,-1 ], [ 1,-1,0,1 ], [ 1,-1,0,-1 ],
-	     [ -1,1,0,1 ], [ -1,1,0,-1 ], [ -1,-1,0,1 ], [ -1,-1,0,-1 ],
-	     [ 1,1,1,0 ], [ 1,1,-1,0 ], [ 1,-1,1,0 ], [ 1,-1,-1,0 ],
-	     [ -1,1,1,0 ], [ -1,1,-1,0 ], [ -1,-1,1,0 ], [ -1,-1,-1,0 ]];
-
-	this.p = [];
-	for (var i = 0; i < 256; i ++) {
-		this.p[i] = Math.floor(r.random() * 256);
-	}
-  // To remove the need for index wrapping, double the permutation table length 
-	this.perm = []; 
-	for (var i = 0; i < 512; i ++) {
-		this.perm[i] = this.p[i & 255];
-	} 
-
-  // A lookup table to traverse the simplex around a given point in 4D. 
-  // Details can be found where this table is used, in the 4D noise method. 
-	this.simplex = [ 
-    [ 0,1,2,3 ],[ 0,1,3,2 ],[ 0,0,0,0 ],[ 0,2,3,1 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 1,2,3,0 ], 
-    [ 0,2,1,3 ],[ 0,0,0,0 ],[ 0,3,1,2 ],[ 0,3,2,1 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 1,3,2,0 ], 
-    [ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ], 
-    [ 1,2,0,3 ],[ 0,0,0,0 ],[ 1,3,0,2 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 2,3,0,1 ],[ 2,3,1,0 ], 
-    [ 1,0,2,3 ],[ 1,0,3,2 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 2,0,3,1 ],[ 0,0,0,0 ],[ 2,1,3,0 ], 
-    [ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ], 
-    [ 2,0,1,3 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 3,0,1,2 ],[ 3,0,2,1 ],[ 0,0,0,0 ],[ 3,1,2,0 ], 
-    [ 2,1,0,3 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 0,0,0,0 ],[ 3,1,0,2 ],[ 0,0,0,0 ],[ 3,2,0,1 ],[ 3,2,1,0 ]]; 
-};
-
-SimplexNoise.prototype.dot = function(g, x, y) { 
-	return g[0] * x + g[1] * y;
-};
-
-SimplexNoise.prototype.dot3 = function(g, x, y, z) {
-	return g[0] * x + g[1] * y + g[2] * z; 
-};
-
-SimplexNoise.prototype.dot4 = function(g, x, y, z, w) {
-	return g[0] * x + g[1] * y + g[2] * z + g[3] * w;
-};
-
-SimplexNoise.prototype.noise = function(xin, yin) { 
-	var n0, n1, n2; // Noise contributions from the three corners 
-  // Skew the input space to determine which simplex cell we're in 
-	var F2 = 0.5 * (Math.sqrt(3.0) - 1.0); 
-	var s = (xin + yin) * F2; // Hairy factor for 2D 
-	var i = Math.floor(xin + s); 
-	var j = Math.floor(yin + s); 
-	var G2 = (3.0 - Math.sqrt(3.0)) / 6.0; 
-	var t = (i + j) * G2; 
-	var X0 = i - t; // Unskew the cell origin back to (x,y) space 
-	var Y0 = j - t; 
-	var x0 = xin - X0; // The x,y distances from the cell origin 
-	var y0 = yin - Y0; 
-  // For the 2D case, the simplex shape is an equilateral triangle. 
-  // Determine which simplex we are in. 
-	var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords 
-	if (x0 > y0) {i1 = 1; j1 = 0;} // lower triangle, XY order: (0,0)->(1,0)->(1,1) 
-	else {i1 = 0; j1 = 1;}      // upper triangle, YX order: (0,0)->(0,1)->(1,1) 
-  // A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and 
-  // a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where 
-  // c = (3-sqrt(3))/6 
-	var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords 
-	var y1 = y0 - j1 + G2; 
-	var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords 
-	var y2 = y0 - 1.0 + 2.0 * G2; 
-  // Work out the hashed gradient indices of the three simplex corners 
-	var ii = i & 255; 
-	var jj = j & 255; 
-	var gi0 = this.perm[ii + this.perm[jj]] % 12; 
-	var gi1 = this.perm[ii + i1 + this.perm[jj + j1]] % 12; 
-	var gi2 = this.perm[ii + 1 + this.perm[jj + 1]] % 12; 
-  // Calculate the contribution from the three corners 
-	var t0 = 0.5 - x0 * x0 - y0 * y0; 
-	if (t0 < 0) n0 = 0.0; 
-	else { 
-		t0 *= t0; 
-		n0 = t0 * t0 * this.dot(this.grad3[gi0], x0, y0);  // (x,y) of grad3 used for 2D gradient 
-	} 
-	var t1 = 0.5 - x1 * x1 - y1 * y1; 
-	if (t1 < 0) n1 = 0.0; 
-	else { 
-		t1 *= t1; 
-		n1 = t1 * t1 * this.dot(this.grad3[gi1], x1, y1); 
-	}
-	var t2 = 0.5 - x2 * x2 - y2 * y2; 
-	if (t2 < 0) n2 = 0.0; 
-	else { 
-		t2 *= t2; 
-		n2 = t2 * t2 * this.dot(this.grad3[gi2], x2, y2); 
-	} 
-  // Add contributions from each corner to get the final noise value. 
-  // The result is scaled to return values in the interval [-1,1]. 
-	return 70.0 * (n0 + n1 + n2); 
-};
-
-// 3D simplex noise 
-SimplexNoise.prototype.noise3d = function(xin, yin, zin) { 
-	var n0, n1, n2, n3; // Noise contributions from the four corners 
-  // Skew the input space to determine which simplex cell we're in 
-	var F3 = 1.0 / 3.0; 
-	var s = (xin + yin + zin) * F3; // Very nice and simple skew factor for 3D 
-	var i = Math.floor(xin + s); 
-	var j = Math.floor(yin + s); 
-	var k = Math.floor(zin + s); 
-	var G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too 
-	var t = (i + j + k) * G3; 
-	var X0 = i - t; // Unskew the cell origin back to (x,y,z) space 
-	var Y0 = j - t; 
-	var Z0 = k - t; 
-	var x0 = xin - X0; // The x,y,z distances from the cell origin 
-	var y0 = yin - Y0; 
-	var z0 = zin - Z0; 
-  // For the 3D case, the simplex shape is a slightly irregular tetrahedron. 
-  // Determine which simplex we are in. 
-	var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords 
-	var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords 
-	if (x0 >= y0) { 
-		if (y0 >= z0) 
-      { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // X Y Z order 
-      else if (x0 >= z0) { i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1; } // X Z Y order 
-		else { i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1; } // Z X Y order 
-	} 
-	else { // x0<y0 
-		if (y0 < z0) { i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1; } // Z Y X order 
-    else if (x0 < z0) { i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1; } // Y Z X order 
-		else { i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0; } // Y X Z order 
-	} 
-  // A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z), 
-  // a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and 
-  // a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where 
-  // c = 1/6.
-	var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords 
-	var y1 = y0 - j1 + G3; 
-	var z1 = z0 - k1 + G3; 
-	var x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords 
-	var y2 = y0 - j2 + 2.0 * G3; 
-	var z2 = z0 - k2 + 2.0 * G3; 
-	var x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords 
-	var y3 = y0 - 1.0 + 3.0 * G3; 
-	var z3 = z0 - 1.0 + 3.0 * G3; 
-  // Work out the hashed gradient indices of the four simplex corners 
-	var ii = i & 255; 
-	var jj = j & 255; 
-	var kk = k & 255; 
-	var gi0 = this.perm[ii + this.perm[jj + this.perm[kk]]] % 12; 
-	var gi1 = this.perm[ii + i1 + this.perm[jj + j1 + this.perm[kk + k1]]] % 12; 
-	var gi2 = this.perm[ii + i2 + this.perm[jj + j2 + this.perm[kk + k2]]] % 12; 
-	var gi3 = this.perm[ii + 1 + this.perm[jj + 1 + this.perm[kk + 1]]] % 12; 
-  // Calculate the contribution from the four corners 
-	var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0; 
-	if (t0 < 0) n0 = 0.0; 
-	else { 
-		t0 *= t0; 
-		n0 = t0 * t0 * this.dot3(this.grad3[gi0], x0, y0, z0); 
-	}
-	var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1; 
-	if (t1 < 0) n1 = 0.0; 
-	else { 
-		t1 *= t1; 
-		n1 = t1 * t1 * this.dot3(this.grad3[gi1], x1, y1, z1); 
-	} 
-	var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2; 
-	if (t2 < 0) n2 = 0.0; 
-	else { 
-		t2 *= t2; 
-		n2 = t2 * t2 * this.dot3(this.grad3[gi2], x2, y2, z2); 
-	} 
-	var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3; 
-	if (t3 < 0) n3 = 0.0; 
-	else { 
-		t3 *= t3; 
-		n3 = t3 * t3 * this.dot3(this.grad3[gi3], x3, y3, z3); 
-	} 
-  // Add contributions from each corner to get the final noise value. 
-  // The result is scaled to stay just inside [-1,1] 
-	return 32.0 * (n0 + n1 + n2 + n3); 
-};
-
-// 4D simplex noise
-SimplexNoise.prototype.noise4d = function( x, y, z, w ) {
-	// For faster and easier lookups
-	var grad4 = this.grad4;
-	var simplex = this.simplex;
-	var perm = this.perm;
-	
-   // The skewing and unskewing factors are hairy again for the 4D case
-	var F4 = (Math.sqrt(5.0) - 1.0) / 4.0;
-	var G4 = (5.0 - Math.sqrt(5.0)) / 20.0;
-	var n0, n1, n2, n3, n4; // Noise contributions from the five corners
-   // Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
-	var s = (x + y + z + w) * F4; // Factor for 4D skewing
-	var i = Math.floor(x + s);
-	var j = Math.floor(y + s);
-	var k = Math.floor(z + s);
-	var l = Math.floor(w + s);
-	var t = (i + j + k + l) * G4; // Factor for 4D unskewing
-	var X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
-	var Y0 = j - t;
-	var Z0 = k - t;
-	var W0 = l - t;
-	var x0 = x - X0;  // The x,y,z,w distances from the cell origin
-	var y0 = y - Y0;
-	var z0 = z - Z0;
-	var w0 = w - W0;
-
-   // For the 4D case, the simplex is a 4D shape I won't even try to describe.
-   // To find out which of the 24 possible simplices we're in, we need to
-   // determine the magnitude ordering of x0, y0, z0 and w0.
-   // The method below is a good way of finding the ordering of x,y,z,w and
-   // then find the correct traversal order for the simplex we’re in.
-   // First, six pair-wise comparisons are performed between each possible pair
-   // of the four coordinates, and the results are used to add up binary bits
-   // for an integer index.
-	var c1 = (x0 > y0) ? 32 : 0;
-	var c2 = (x0 > z0) ? 16 : 0;
-	var c3 = (y0 > z0) ? 8 : 0;
-	var c4 = (x0 > w0) ? 4 : 0;
-	var c5 = (y0 > w0) ? 2 : 0;
-	var c6 = (z0 > w0) ? 1 : 0;
-	var c = c1 + c2 + c3 + c4 + c5 + c6;
-	var i1, j1, k1, l1; // The integer offsets for the second simplex corner
-	var i2, j2, k2, l2; // The integer offsets for the third simplex corner
-	var i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
-   // simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
-   // Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
-   // impossible. Only the 24 indices which have non-zero entries make any sense.
-   // We use a thresholding to set the coordinates in turn from the largest magnitude.
-   // The number 3 in the "simplex" array is at the position of the largest coordinate.
-	i1 = simplex[c][0] >= 3 ? 1 : 0;
-	j1 = simplex[c][1] >= 3 ? 1 : 0;
-	k1 = simplex[c][2] >= 3 ? 1 : 0;
-	l1 = simplex[c][3] >= 3 ? 1 : 0;
-   // The number 2 in the "simplex" array is at the second largest coordinate.
-	i2 = simplex[c][0] >= 2 ? 1 : 0;
-	j2 = simplex[c][1] >= 2 ? 1 : 0;    k2 = simplex[c][2] >= 2 ? 1 : 0;
-	l2 = simplex[c][3] >= 2 ? 1 : 0;
-   // The number 1 in the "simplex" array is at the second smallest coordinate.
-	i3 = simplex[c][0] >= 1 ? 1 : 0;
-	j3 = simplex[c][1] >= 1 ? 1 : 0;
-	k3 = simplex[c][2] >= 1 ? 1 : 0;
-	l3 = simplex[c][3] >= 1 ? 1 : 0;
-   // The fifth corner has all coordinate offsets = 1, so no need to look that up.
-	var x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
-	var y1 = y0 - j1 + G4;
-	var z1 = z0 - k1 + G4;
-	var w1 = w0 - l1 + G4;
-	var x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords
-	var y2 = y0 - j2 + 2.0 * G4;
-	var z2 = z0 - k2 + 2.0 * G4;
-	var w2 = w0 - l2 + 2.0 * G4;
-	var x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords
-	var y3 = y0 - j3 + 3.0 * G4;
-	var z3 = z0 - k3 + 3.0 * G4;
-	var w3 = w0 - l3 + 3.0 * G4;
-	var x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords
-	var y4 = y0 - 1.0 + 4.0 * G4;
-	var z4 = z0 - 1.0 + 4.0 * G4;
-	var w4 = w0 - 1.0 + 4.0 * G4;
-   // Work out the hashed gradient indices of the five simplex corners
-	var ii = i & 255;
-	var jj = j & 255;
-	var kk = k & 255;
-	var ll = l & 255;
-	var gi0 = perm[ii + perm[jj + perm[kk + perm[ll]]]] % 32;
-	var gi1 = perm[ii + i1 + perm[jj + j1 + perm[kk + k1 + perm[ll + l1]]]] % 32;
-	var gi2 = perm[ii + i2 + perm[jj + j2 + perm[kk + k2 + perm[ll + l2]]]] % 32;
-	var gi3 = perm[ii + i3 + perm[jj + j3 + perm[kk + k3 + perm[ll + l3]]]] % 32;
-	var gi4 = perm[ii + 1 + perm[jj + 1 + perm[kk + 1 + perm[ll + 1]]]] % 32;
-   // Calculate the contribution from the five corners
-	var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
-	if (t0 < 0) n0 = 0.0;
-	else {
-		t0 *= t0;
-		n0 = t0 * t0 * this.dot4(grad4[gi0], x0, y0, z0, w0);
-	}
-	var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
-	if (t1 < 0) n1 = 0.0;
-	else {
-		t1 *= t1;
-		n1 = t1 * t1 * this.dot4(grad4[gi1], x1, y1, z1, w1);
-	}
-	var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
-	if (t2 < 0) n2 = 0.0;
-	else {
-		t2 *= t2;
-		n2 = t2 * t2 * this.dot4(grad4[gi2], x2, y2, z2, w2);
-	}   var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
-	if (t3 < 0) n3 = 0.0;
-	else {
-		t3 *= t3;
-		n3 = t3 * t3 * this.dot4(grad4[gi3], x3, y3, z3, w3);
-	}
-	var t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
-	if (t4 < 0) n4 = 0.0;
-	else {
-		t4 *= t4;
-		n4 = t4 * t4 * this.dot4(grad4[gi4], x4, y4, z4, w4);
-	}
-   // Sum up and scale the result to cover the range [-1,1]
-	return 27.0 * (n0 + n1 + n2 + n3 + n4);
-};

+ 0 - 0
examples/js/AnimationClipCreator.js → examples/js/animation/AnimationClipCreator.js


+ 21 - 27
examples/js/TimelinerController.js → examples/js/animation/TimelinerController.js

@@ -3,7 +3,7 @@
  *
  * Timeliner GUI library (required to use this class):
  *
- * 		./libs/timeliner_gui.min.js
+ * 		../libs/timeliner_gui.min.js
  *
  * Source code:
  *
@@ -35,7 +35,7 @@ THREE.TimelinerController.prototype = {
 
 	constructor: THREE.TimelinerController,
 
-	init: function( timeliner ) {
+	init: function () {
 
 		var tracks = [],
 			trackInfo = this._trackInfo;
@@ -44,9 +44,8 @@ THREE.TimelinerController.prototype = {
 
 			var spec = trackInfo[ i ];
 
-			tracks.push( this._addTrack(
-					spec.type, spec.propertyPath,
-					spec.initialValue, spec.interpolation ) );
+			tracks.push( this._addTrack( spec.type, spec.propertyPath, spec.initialValue, spec.interpolation ) );
+
 		}
 
 		this._clip = new THREE.AnimationClip( 'editclip', 0, tracks );
@@ -54,7 +53,7 @@ THREE.TimelinerController.prototype = {
 
 	},
 
-	setDisplayTime: function( time ) {
+	setDisplayTime: function ( time ) {
 
 		this._action.time = time;
 		this._mixer.update( 0 );
@@ -63,25 +62,25 @@ THREE.TimelinerController.prototype = {
 
 	},
 
-	setDuration: function( duration ) {
+	setDuration: function ( duration ) {
 
 		this._clip.duration = duration;
 
 	},
 
-	getChannelNames: function() {
+	getChannelNames: function () {
 
 		return this._channelNames;
 
 	},
 
-	getChannelKeyTimes: function( channelName ) {
+	getChannelKeyTimes: function ( channelName ) {
 
 		return this._tracks[ channelName ].times;
 
 	},
 
-	setKeyframe: function( channelName, time ) {
+	setKeyframe: function ( channelName, time ) {
 
 		var track = this._tracks[ channelName ],
 			times = track.times,
@@ -106,8 +105,7 @@ THREE.TimelinerController.prototype = {
 
 			}
 
-			for ( var i = nValues - 1,
-					e = offset + stride - 1; i !== e; -- i ) {
+			for ( var i = nValues - 1, e = offset + stride - 1; i !== e; -- i ) {
 
 				values[ i ] = values[ i - stride ];
 
@@ -120,7 +118,7 @@ THREE.TimelinerController.prototype = {
 
 	},
 
-	delKeyframe: function( channelName, time ) {
+	delKeyframe: function ( channelName, time ) {
 
 		var track = this._tracks[ channelName ],
 			times = track.times,
@@ -159,7 +157,7 @@ THREE.TimelinerController.prototype = {
 
 	},
 
-	moveKeyframe: function( channelName, time, delta, moveRemaining ) {
+	moveKeyframe: function ( channelName, time, delta, moveRemaining ) {
 
 		var track = this._tracks[ channelName ],
 			times = track.times,
@@ -179,7 +177,7 @@ THREE.TimelinerController.prototype = {
 
 	},
 
-	serialize: function() {
+	serialize: function () {
 
 		var result = {
 				duration: this._clip.duration,
@@ -209,7 +207,7 @@ THREE.TimelinerController.prototype = {
 
 	},
 
-	deserialize: function( structs ) {
+	deserialize: function ( structs ) {
 
 		var names = this._channelNames,
 			tracks = this._tracks,
@@ -234,33 +232,29 @@ THREE.TimelinerController.prototype = {
 
 	},
 
-	_sort: function( track ) {
+	_sort: function ( track ) {
 
-		var times = track.times,
-			order = THREE.AnimationUtils.getKeyframeOrder( times );
+		var times = track.times, order = THREE.AnimationUtils.getKeyframeOrder( times );
 
-		this._setArray( times,
-				THREE.AnimationUtils.sortedArray( times, 1, order ) );
+		this._setArray( times, THREE.AnimationUtils.sortedArray( times, 1, order ) );
 
 		var values = track.values,
 			stride = track.getValueSize();
 
-		this._setArray( values,
-				THREE.AnimationUtils.sortedArray( values, stride, order ) );
+		this._setArray( values, THREE.AnimationUtils.sortedArray( values, stride, order ) );
 
 	},
 
-	_setArray: function( dst, src ) {
+	_setArray: function ( dst, src ) {
 
 		dst.length = 0;
 		dst.push.apply( dst, src );
 
 	},
 
-	_addTrack: function( type, prop, initialValue, interpolation ) {
+	_addTrack: function ( type, prop, initialValue, interpolation ) {
 
-		var track = new type(
-				prop, [ 0 ], initialValue, interpolation );
+		var track = new type( prop, [ 0 ], initialValue, interpolation );
 
 		// data must be in JS arrays so it can be resized
 		track.times = Array.prototype.slice.call( track.times );

+ 0 - 39
examples/js/crossfade/gui.js

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

+ 0 - 119
examples/js/crossfade/scenes.js

@@ -1,119 +0,0 @@
-function generateGeometry( objectType, numObjects ) {
-
-	function applyVertexColors( geometry, color ) {
-
-		var position = geometry.attributes.position;
-		var colors = [];
-
-		for ( var i = 0; i < position.count; i ++ ) {
-
-			colors.push( color.r, color.g, color.b );
-
-		}
-
-		geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
-
-	}
-
-	var geometries = [];
-
-	var matrix = new THREE.Matrix4();
-	var position = new THREE.Vector3();
-	var rotation = new THREE.Euler();
-	var quaternion = new THREE.Quaternion();
-	var scale = new THREE.Vector3();
-	var color = new THREE.Color();
-
-	for ( var i = 0; i < numObjects; i ++ ) {
-
-		position.x = Math.random() * 10000 - 5000;
-		position.y = Math.random() * 6000 - 3000;
-		position.z = Math.random() * 8000 - 4000;
-
-		rotation.x = Math.random() * 2 * Math.PI;
-		rotation.y = Math.random() * 2 * Math.PI;
-		rotation.z = Math.random() * 2 * Math.PI;
-		quaternion.setFromEuler( rotation, false );
-
-		scale.x = Math.random() * 200 + 100;
-
-		var geometry;
-
-		if ( objectType === 'cube' ) {
-
-			geometry = new THREE.BoxBufferGeometry( 1, 1, 1 );
-			geometry = geometry.toNonIndexed(); // merging needs consistent buffer geometries
-			scale.y = Math.random() * 200 + 100;
-			scale.z = Math.random() * 200 + 100;
-			color.setRGB( 0, 0, 0.1 + 0.9 * Math.random() );
-
-		} else if ( objectType === 'sphere' ) {
-
-			geometry = new THREE.IcosahedronBufferGeometry( 1, 1 );
-			scale.y = scale.z = scale.x;
-			color.setRGB( 0.1 + 0.9 * Math.random(), 0, 0 );
-
-		}
-
-		// give the geom's vertices a random color, to be displayed
-		applyVertexColors( geometry, color );
-
-		matrix.compose( position, quaternion, scale );
-		geometry.applyMatrix( matrix );
-
-		geometries.push( geometry );
-
-	}
-
-	return THREE.BufferGeometryUtils.mergeBufferGeometries( geometries );
-
-}
-
-function Scene( type, numObjects, cameraZ, fov, rotationSpeed, clearColor ) {
-
-	this.clearColor = clearColor;
-
-	this.camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 10000 );
-	this.camera.position.z = cameraZ;
-
-	// Setup scene
-	this.scene = new THREE.Scene();
-	this.scene.add( new THREE.AmbientLight( 0x555555 ) );
-
-	var light = new THREE.SpotLight( 0xffffff, 1.5 );
-	light.position.set( 0, 500, 2000 );
-	this.scene.add( light );
-
-	this.rotationSpeed = rotationSpeed;
-
-	var defaultMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true, vertexColors: THREE.VertexColors } );
-	this.mesh = new THREE.Mesh( generateGeometry( type, numObjects ), defaultMaterial );
-	this.scene.add( this.mesh );
-
-	var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
-	this.fbo = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, renderTargetParameters );
-
-	this.render = function ( delta, rtt ) {
-
-		this.mesh.rotation.x += delta * this.rotationSpeed.x;
-		this.mesh.rotation.y += delta * this.rotationSpeed.y;
-		this.mesh.rotation.z += delta * this.rotationSpeed.z;
-
-		renderer.setClearColor( this.clearColor );
-
-		if ( rtt ) {
-
-			renderer.setRenderTarget( this.fbo );
-			renderer.clear();
-			renderer.render( this.scene, this.camera );
-
-		} else {
-
-			renderer.setRenderTarget( null );
-			renderer.render( this.scene, this.camera );
-
-		}
-
-	};
-
-}

+ 0 - 168
examples/js/crossfade/transition.js

@@ -1,168 +0,0 @@
-function Transition( sceneA, sceneB ) {
-
-	this.scene = new THREE.Scene();
-
-	this.cameraOrtho = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 10, 10 );
-
-	this.textures = [];
-
-	var loader = new THREE.TextureLoader();
-
-	for ( var i = 0; i < 6; i ++ )
-		this.textures[ i ] = loader.load( 'textures/transition/transition' + ( i + 1 ) + '.png' );
-
-	this.quadmaterial = new THREE.ShaderMaterial( {
-
-		uniforms: {
-
-			tDiffuse1: {
-				value: null
-			},
-			tDiffuse2: {
-				value: null
-			},
-			mixRatio: {
-				value: 0.0
-			},
-			threshold: {
-				value: 0.1
-			},
-			useTexture: {
-				value: 1
-			},
-			tMixTexture: {
-				value: this.textures[ 0 ]
-			}
-		},
-		vertexShader: [
-
-			"varying vec2 vUv;",
-
-			"void main() {",
-
-			"vUv = vec2( uv.x, uv.y );",
-			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
-
-			"}"
-
-		].join( "\n" ),
-		fragmentShader: [
-
-			"uniform float mixRatio;",
-
-			"uniform sampler2D tDiffuse1;",
-			"uniform sampler2D tDiffuse2;",
-			"uniform sampler2D tMixTexture;",
-
-			"uniform int useTexture;",
-			"uniform float threshold;",
-
-			"varying vec2 vUv;",
-
-			"void main() {",
-
-			"	vec4 texel1 = texture2D( tDiffuse1, vUv );",
-			"	vec4 texel2 = texture2D( tDiffuse2, vUv );",
-
-			"	if (useTexture==1) {",
-
-			"		vec4 transitionTexel = texture2D( tMixTexture, vUv );",
-			"		float r = mixRatio * (1.0 + threshold * 2.0) - threshold;",
-			"		float mixf=clamp((transitionTexel.r - r)*(1.0/threshold), 0.0, 1.0);",
-
-			"		gl_FragColor = mix( texel1, texel2, mixf );",
-
-			"	} else {",
-
-			"		gl_FragColor = mix( texel2, texel1, mixRatio );",
-
-			"	}",
-
-			"}"
-
-		].join( "\n" )
-
-	} );
-
-	var quadgeometry = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
-
-	this.quad = new THREE.Mesh( quadgeometry, this.quadmaterial );
-	this.scene.add( this.quad );
-
-	// Link both scenes and their FBOs
-	this.sceneA = sceneA;
-	this.sceneB = sceneB;
-
-	this.quadmaterial.uniforms.tDiffuse1.value = sceneA.fbo.texture;
-	this.quadmaterial.uniforms.tDiffuse2.value = sceneB.fbo.texture;
-
-	this.needChange = false;
-
-	this.setTextureThreshold = function ( value ) {
-
-		this.quadmaterial.uniforms.threshold.value = value;
-
-	};
-
-	this.useTexture = function ( value ) {
-
-		this.quadmaterial.uniforms.useTexture.value = value ? 1 : 0;
-
-	};
-
-	this.setTexture = function ( i ) {
-
-		this.quadmaterial.uniforms.tMixTexture.value = this.textures[ i ];
-
-	};
-
-	this.render = function ( delta ) {
-
-		// Transition animation
-		if ( transitionParams.animateTransition ) {
-
-			var t = ( 1 + Math.sin( transitionParams.transitionSpeed * clock.getElapsedTime() / Math.PI ) ) / 2;
-			transitionParams.transition = THREE.Math.smoothstep( t, 0.3, 0.7 );
-
-			// Change the current alpha texture after each transition
-			if ( transitionParams.loopTexture && ( transitionParams.transition == 0 || transitionParams.transition == 1 ) ) {
-
-				if ( this.needChange ) {
-
-					transitionParams.texture = ( transitionParams.texture + 1 ) % this.textures.length;
-					this.quadmaterial.uniforms.tMixTexture.value = this.textures[ transitionParams.texture ];
-					this.needChange = false;
-
-				}
-
-			} else
-				this.needChange = true;
-
-		}
-
-		this.quadmaterial.uniforms.mixRatio.value = transitionParams.transition;
-
-		// Prevent render both scenes when it's not necessary
-		if ( transitionParams.transition == 0 ) {
-
-			this.sceneB.render( delta, false );
-
-		} else if ( transitionParams.transition == 1 ) {
-
-			this.sceneA.render( delta, false );
-
-		} else {
-
-			// When 0<transition<1 render transition between two scenes
-
-			this.sceneA.render( delta, true );
-			this.sceneB.render( delta, true );
-			renderer.setRenderTarget( null );
-			renderer.clear();
-			renderer.render( this.scene, this.cameraOrtho );
-
-		}
-
-	};
-
-}

+ 6 - 0
examples/js/effects/AsciiEffect.js

@@ -159,11 +159,13 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 	if ( strResolution == "low" ) {
 
 		switch ( iScale ) {
+
 			case 1 : fLetterSpacing = - 1; break;
 			case 2 :
 			case 3 : fLetterSpacing = - 2.1; break;
 			case 4 : fLetterSpacing = - 3.1; break;
 			case 5 : fLetterSpacing = - 4.15; break;
+
 		}
 
 	}
@@ -171,11 +173,13 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 	if ( strResolution == "medium" ) {
 
 		switch ( iScale ) {
+
 			case 1 : fLetterSpacing = 0; break;
 			case 2 : fLetterSpacing = - 1; break;
 			case 3 : fLetterSpacing = - 1.04; break;
 			case 4 :
 			case 5 : fLetterSpacing = - 2.1; break;
+
 		}
 
 	}
@@ -183,11 +187,13 @@ THREE.AsciiEffect = function ( renderer, charSet, options ) {
 	if ( strResolution == "high" ) {
 
 		switch ( iScale ) {
+
 			case 1 :
 			case 2 : fLetterSpacing = 0; break;
 			case 3 :
 			case 4 :
 			case 5 : fLetterSpacing = - 1; break;
+
 		}
 
 	}

+ 11 - 14
examples/js/effects/OutlineEffect.js

@@ -108,8 +108,6 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 	var vertexShaderChunk = [
 
-		"#include <fog_pars_vertex>",
-
 		"uniform float outlineThickness;",
 
 		"vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {",
@@ -175,7 +173,6 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 		var shaderID = shaderIDs[ originalMaterial.type ];
 		var originalUniforms, originalVertexShader;
-		var outlineParameters = originalMaterial.userData.outlineParameters;
 
 		if ( shaderID !== undefined ) {
 
@@ -212,15 +209,15 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 		var uniforms = Object.assign( {}, originalUniforms, uniformsChunk );
 
 		var vertexShader = originalVertexShader
-					// put vertexShaderChunk right before "void main() {...}"
-					.replace( /void\s+main\s*\(\s*\)/, vertexShaderChunk + '\nvoid main()' )
-					// put vertexShaderChunk2 the end of "void main() {...}"
-					// Note: here assums originalVertexShader ends with "}" of "void main() {...}"
-					.replace( /\}\s*$/, vertexShaderChunk2 + '\n}' )
-					// remove any light related lines
-					// Note: here is very sensitive to originalVertexShader
-					// TODO: consider safer way
-					.replace( /#include\s+<[\w_]*light[\w_]*>/g, '' );
+			// put vertexShaderChunk right before "void main() {...}"
+			.replace( /void\s+main\s*\(\s*\)/, vertexShaderChunk + '\nvoid main()' )
+			// put vertexShaderChunk2 the end of "void main() {...}"
+			// Note: here assums originalVertexShader ends with "}" of "void main() {...}"
+			.replace( /\}\s*$/, vertexShaderChunk2 + '\n}' )
+			// remove any light related lines
+			// Note: here is very sensitive to originalVertexShader
+			// TODO: consider safer way
+			.replace( /#include\s+<[\w_]*light[\w_]*>/g, '' );
 
 		var defines = {};
 
@@ -322,7 +319,7 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 	}
 
-	function onBeforeRender( renderer, scene, camera, geometry, material, group ) {
+	function onBeforeRender( renderer, scene, camera, geometry, material ) {
 
 		var originalMaterial = originalMaterials[ material.uuid ];
 
@@ -418,7 +415,7 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 			if ( cache[ key ].used === false ) {
 
-				cache[ key ].count++;
+				cache[ key ].count ++;
 
 				if ( cache[ key ].keepAlive === false && cache[ key ].count > removeThresholdCount ) {
 

+ 13 - 13
examples/js/geometries/BoxLineGeometry.js

@@ -28,10 +28,10 @@ THREE.BoxLineGeometry = function ( width, height, depth, widthSegments, heightSe
 
 	for ( var i = 0; i <= widthSegments; i ++ ) {
 
-		vertices.push( x, - heightHalf, - depthHalf, x,   heightHalf, - depthHalf );
-		vertices.push( x,   heightHalf, - depthHalf, x,   heightHalf,   depthHalf );
-		vertices.push( x,   heightHalf,   depthHalf, x, - heightHalf,   depthHalf );
-		vertices.push( x, - heightHalf,   depthHalf, x, - heightHalf, - depthHalf );
+		vertices.push( x, - heightHalf, - depthHalf, x, heightHalf, - depthHalf );
+		vertices.push( x, heightHalf, - depthHalf, x, heightHalf, depthHalf );
+		vertices.push( x, heightHalf, depthHalf, x, - heightHalf, depthHalf );
+		vertices.push( x, - heightHalf, depthHalf, x, - heightHalf, - depthHalf );
 
 		x += segmentWidth;
 
@@ -39,10 +39,10 @@ THREE.BoxLineGeometry = function ( width, height, depth, widthSegments, heightSe
 
 	for ( var i = 0; i <= heightSegments; i ++ ) {
 
-		vertices.push( - widthHalf, y, - depthHalf,   widthHalf, y, - depthHalf );
-		vertices.push(   widthHalf, y, - depthHalf,   widthHalf, y,   depthHalf );
-		vertices.push(   widthHalf, y,   depthHalf, - widthHalf, y,   depthHalf );
-		vertices.push( - widthHalf, y,   depthHalf, - widthHalf, y, - depthHalf );
+		vertices.push( - widthHalf, y, - depthHalf, widthHalf, y, - depthHalf );
+		vertices.push( widthHalf, y, - depthHalf, widthHalf, y, depthHalf );
+		vertices.push( widthHalf, y, depthHalf, - widthHalf, y, depthHalf );
+		vertices.push( - widthHalf, y, depthHalf, - widthHalf, y, - depthHalf );
 
 		y += segmentHeight;
 
@@ -50,10 +50,10 @@ THREE.BoxLineGeometry = function ( width, height, depth, widthSegments, heightSe
 
 	for ( var i = 0; i <= depthSegments; i ++ ) {
 
-		vertices.push( - widthHalf, - heightHalf, z, - widthHalf,   heightHalf, z );
-		vertices.push( - widthHalf,   heightHalf, z,   widthHalf,   heightHalf, z );
-		vertices.push(   widthHalf,   heightHalf, z,   widthHalf, - heightHalf, z );
-		vertices.push(   widthHalf, - heightHalf, z, - widthHalf, - heightHalf, z );
+		vertices.push( - widthHalf, - heightHalf, z, - widthHalf, heightHalf, z );
+		vertices.push( - widthHalf, heightHalf, z, widthHalf, heightHalf, z );
+		vertices.push( widthHalf, heightHalf, z, widthHalf, - heightHalf, z );
+		vertices.push( widthHalf, - heightHalf, z, - widthHalf, - heightHalf, z );
 
 		z += segmentDepth;
 
@@ -61,7 +61,7 @@ THREE.BoxLineGeometry = function ( width, height, depth, widthSegments, heightSe
 
 	this.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
 
-}
+};
 
 THREE.BoxLineGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
 THREE.BoxLineGeometry.prototype.constructor = THREE.BoxLineGeometry;

+ 36 - 47
examples/js/geometries/ConvexGeometry.js

@@ -2,80 +2,69 @@
  * @author Mugen87 / https://github.com/Mugen87
  */
 
-( function () {
+// ConvexGeometry
 
-	// ConvexGeometry
+THREE.ConvexGeometry = function ( points ) {
 
-	function ConvexGeometry( points ) {
+	THREE.Geometry.call( this );
 
-		THREE.Geometry.call( this );
+	this.fromBufferGeometry( new THREE.ConvexBufferGeometry( points ) );
+	this.mergeVertices();
 
-		this.fromBufferGeometry( new ConvexBufferGeometry( points ) );
-		this.mergeVertices();
+};
 
-	}
-
-	ConvexGeometry.prototype = Object.create( THREE.Geometry.prototype );
-	ConvexGeometry.prototype.constructor = ConvexGeometry;
-
-	// ConvexBufferGeometry
-
-	function ConvexBufferGeometry( points ) {
+THREE.ConvexGeometry.prototype = Object.create( THREE.Geometry.prototype );
+THREE.ConvexGeometry.prototype.constructor = THREE.ConvexGeometry;
 
-		THREE.BufferGeometry.call( this );
+// ConvexBufferGeometry
 
-		// buffers
+THREE.ConvexBufferGeometry = function ( points ) {
 
-		var vertices = [];
-		var normals = [];
+	THREE.BufferGeometry.call( this );
 
-		// execute QuickHull
+	// buffers
 
-		if ( THREE.QuickHull === undefined ) {
+	var vertices = [];
+	var normals = [];
 
-			console.error( 'THREE.ConvexBufferGeometry: ConvexBufferGeometry relies on THREE.QuickHull' );
+	if ( THREE.ConvexHull === undefined ) {
 
-		}
+		console.error( 'THREE.ConvexBufferGeometry: ConvexBufferGeometry relies on THREE.ConvexHull' );
 
-		var quickHull = new THREE.QuickHull().setFromPoints( points );
-
-		// generate vertices and normals
-
-		var faces = quickHull.faces;
+	}
 
-		for ( var i = 0; i < faces.length; i ++ ) {
+	var convexHull = new THREE.ConvexHull().setFromPoints( points );
 
-			var face = faces[ i ];
-			var edge = face.edge;
+	// generate vertices and normals
 
-			// we move along a doubly-connected edge list to access all face points (see HalfEdge docs)
+	var faces = convexHull.faces;
 
-			do {
+	for ( var i = 0; i < faces.length; i ++ ) {
 
-				var point = edge.head().point;
+		var face = faces[ i ];
+		var edge = face.edge;
 
-				vertices.push( point.x, point.y, point.z );
-				normals.push( face.normal.x, face.normal.y, face.normal.z );
+		// we move along a doubly-connected edge list to access all face points (see HalfEdge docs)
 
-				edge = edge.next;
+		do {
 
-			} while ( edge !== face.edge );
+			var point = edge.head().point;
 
-		}
+			vertices.push( point.x, point.y, point.z );
+			normals.push( face.normal.x, face.normal.y, face.normal.z );
 
-		// build geometry
+			edge = edge.next;
 
-		this.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
-		this.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
+		} while ( edge !== face.edge );
 
 	}
 
-	ConvexBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
-	ConvexBufferGeometry.prototype.constructor = ConvexBufferGeometry;
+	// build geometry
 
-	// export
+	this.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
+	this.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
 
-	THREE.ConvexGeometry = ConvexGeometry;
-	THREE.ConvexBufferGeometry = ConvexBufferGeometry;
+};
 
-} )();
+THREE.ConvexBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
+THREE.ConvexBufferGeometry.prototype.constructor = THREE.ConvexBufferGeometry;

+ 202 - 210
examples/js/geometries/DecalGeometry.js

@@ -16,342 +16,334 @@
  *
  */
 
-( function () {
+THREE.DecalGeometry = function ( mesh, position, orientation, size ) {
 
-	function DecalGeometry( mesh, position, orientation, size ) {
+	THREE.BufferGeometry.call( this );
 
-		THREE.BufferGeometry.call( this );
+	// buffers
 
-		// buffers
+	var vertices = [];
+	var normals = [];
+	var uvs = [];
 
-		var vertices = [];
-		var normals = [];
-		var uvs = [];
+	// helpers
 
-		// helpers
+	var plane = new THREE.Vector3();
 
-		var plane = new THREE.Vector3();
+	// this matrix represents the transformation of the decal projector
 
-		// this matrix represents the transformation of the decal projector
+	var projectorMatrix = new THREE.Matrix4();
+	projectorMatrix.makeRotationFromEuler( orientation );
+	projectorMatrix.setPosition( position );
 
-		var projectorMatrix = new THREE.Matrix4();
-		projectorMatrix.makeRotationFromEuler( orientation );
-		projectorMatrix.setPosition( position );
+	var projectorMatrixInverse = new THREE.Matrix4().getInverse( projectorMatrix );
 
-		var projectorMatrixInverse = new THREE.Matrix4().getInverse( projectorMatrix );
+	// generate buffers
 
-		// generate buffers
+	generate();
 
-		generate();
+	// build geometry
 
-		// build geometry
+	this.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
+	this.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
+	this.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
 
-		this.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
-		this.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
-		this.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
+	function generate() {
 
-		function generate() {
+		var i;
+		var geometry = new THREE.BufferGeometry();
+		var decalVertices = [];
 
-			var i;
-			var geometry = new THREE.BufferGeometry();
-			var decalVertices = [];
+		var vertex = new THREE.Vector3();
+		var normal = new THREE.Vector3();
 
-			var vertex = new THREE.Vector3();
-			var normal = new THREE.Vector3();
+		// handle different geometry types
 
-			// handle different geometry types
+		if ( mesh.geometry.isGeometry ) {
 
-			if ( mesh.geometry.isGeometry ) {
+			geometry.fromGeometry( mesh.geometry );
 
-				geometry.fromGeometry( mesh.geometry );
+		} else {
 
-			} else {
+			geometry.copy( mesh.geometry );
 
-				geometry.copy( mesh.geometry );
-
-			}
+		}
 
-			var positionAttribute = geometry.attributes.position;
-			var normalAttribute = geometry.attributes.normal;
+		var positionAttribute = geometry.attributes.position;
+		var normalAttribute = geometry.attributes.normal;
 
-			// first, create an array of 'DecalVertex' objects
-			// three consecutive 'DecalVertex' objects represent a single face
-			//
-			// this data structure will be later used to perform the clipping
+		// first, create an array of 'DecalVertex' objects
+		// three consecutive 'DecalVertex' objects represent a single face
+		//
+		// this data structure will be later used to perform the clipping
 
-			if ( geometry.index !== null ) {
+		if ( geometry.index !== null ) {
 
-				// indexed BufferGeometry
+			// indexed BufferGeometry
 
-				var index = geometry.index;
+			var index = geometry.index;
 
-				for ( i = 0; i < index.count; i ++ ) {
+			for ( i = 0; i < index.count; i ++ ) {
 
-					vertex.fromBufferAttribute( positionAttribute, index.getX( i ) );
-					normal.fromBufferAttribute( normalAttribute, index.getX( i ) );
+				vertex.fromBufferAttribute( positionAttribute, index.getX( i ) );
+				normal.fromBufferAttribute( normalAttribute, index.getX( i ) );
 
-					pushDecalVertex( decalVertices, vertex, normal );
+				pushDecalVertex( decalVertices, vertex, normal );
 
-				}
-
-			} else {
+			}
 
-				// non-indexed BufferGeometry
+		} else {
 
-				for ( i = 0; i < positionAttribute.count; i ++ ) {
+			// non-indexed BufferGeometry
 
-					vertex.fromBufferAttribute( positionAttribute, i );
-					normal.fromBufferAttribute( normalAttribute, i );
+			for ( i = 0; i < positionAttribute.count; i ++ ) {
 
-					pushDecalVertex( decalVertices, vertex, normal );
+				vertex.fromBufferAttribute( positionAttribute, i );
+				normal.fromBufferAttribute( normalAttribute, i );
 
-				}
+				pushDecalVertex( decalVertices, vertex, normal );
 
 			}
 
-			// second, clip the geometry so that it doesn't extend out from the projector
-
-			decalVertices = clipGeometry( decalVertices, plane.set( 1, 0, 0 ) );
-			decalVertices = clipGeometry( decalVertices, plane.set( - 1, 0, 0 ) );
-			decalVertices = clipGeometry( decalVertices, plane.set( 0, 1, 0 ) );
-			decalVertices = clipGeometry( decalVertices, plane.set( 0, - 1, 0 ) );
-			decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, 1 ) );
-			decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, - 1 ) );
-
-			// third, generate final vertices, normals and uvs
-
-			for ( i = 0; i < decalVertices.length; i ++ ) {
-
-				var decalVertex = decalVertices[ i ];
-
-				// create texture coordinates (we are still in projector space)
+		}
 
-				uvs.push(
-					0.5 + ( decalVertex.position.x / size.x ),
-					0.5 + ( decalVertex.position.y / size.y )
-				);
+		// second, clip the geometry so that it doesn't extend out from the projector
 
-				// transform the vertex back to world space
+		decalVertices = clipGeometry( decalVertices, plane.set( 1, 0, 0 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( - 1, 0, 0 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( 0, 1, 0 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( 0, - 1, 0 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, 1 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, - 1 ) );
 
-				decalVertex.position.applyMatrix4( projectorMatrix );
+		// third, generate final vertices, normals and uvs
 
-				// now create vertex and normal buffer data
+		for ( i = 0; i < decalVertices.length; i ++ ) {
 
-				vertices.push( decalVertex.position.x, decalVertex.position.y, decalVertex.position.z );
-				normals.push( decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z );
+			var decalVertex = decalVertices[ i ];
 
-			}
+			// create texture coordinates (we are still in projector space)
 
-		}
+			uvs.push(
+				0.5 + ( decalVertex.position.x / size.x ),
+				0.5 + ( decalVertex.position.y / size.y )
+			);
 
-		function pushDecalVertex( decalVertices, vertex, normal ) {
+			// transform the vertex back to world space
 
-			// transform the vertex to world space, then to projector space
+			decalVertex.position.applyMatrix4( projectorMatrix );
 
-			vertex.applyMatrix4( mesh.matrixWorld );
-			vertex.applyMatrix4( projectorMatrixInverse );
+			// now create vertex and normal buffer data
 
-			decalVertices.push( new DecalVertex( vertex.clone(), normal.clone() ) );
+			vertices.push( decalVertex.position.x, decalVertex.position.y, decalVertex.position.z );
+			normals.push( decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z );
 
 		}
 
-		function clipGeometry( inVertices, plane ) {
+	}
 
-			var outVertices = [];
+	function pushDecalVertex( decalVertices, vertex, normal ) {
 
-			var s = 0.5 * Math.abs( size.dot( plane ) );
+		// transform the vertex to world space, then to projector space
 
-			// a single iteration clips one face,
-			// which consists of three consecutive 'DecalVertex' objects
+		vertex.applyMatrix4( mesh.matrixWorld );
+		vertex.applyMatrix4( projectorMatrixInverse );
 
-			for ( var i = 0; i < inVertices.length; i += 3 ) {
+		decalVertices.push( new THREE.DecalVertex( vertex.clone(), normal.clone() ) );
 
-				var v1Out, v2Out, v3Out, total = 0;
-				var nV1, nV2, nV3, nV4;
+	}
 
-				var d1 = inVertices[ i + 0 ].position.dot( plane ) - s;
-				var d2 = inVertices[ i + 1 ].position.dot( plane ) - s;
-				var d3 = inVertices[ i + 2 ].position.dot( plane ) - s;
+	function clipGeometry( inVertices, plane ) {
 
-				v1Out = d1 > 0;
-				v2Out = d2 > 0;
-				v3Out = d3 > 0;
+		var outVertices = [];
 
-				// calculate, how many vertices of the face lie outside of the clipping plane
+		var s = 0.5 * Math.abs( size.dot( plane ) );
 
-				total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 );
+		// a single iteration clips one face,
+		// which consists of three consecutive 'DecalVertex' objects
 
-				switch ( total ) {
+		for ( var i = 0; i < inVertices.length; i += 3 ) {
 
-					case 0: {
+			var v1Out, v2Out, v3Out, total = 0;
+			var nV1, nV2, nV3, nV4;
 
-						// the entire face lies inside of the plane, no clipping needed
+			var d1 = inVertices[ i + 0 ].position.dot( plane ) - s;
+			var d2 = inVertices[ i + 1 ].position.dot( plane ) - s;
+			var d3 = inVertices[ i + 2 ].position.dot( plane ) - s;
 
-						outVertices.push( inVertices[ i ] );
-						outVertices.push( inVertices[ i + 1 ] );
-						outVertices.push( inVertices[ i + 2 ] );
-						break;
+			v1Out = d1 > 0;
+			v2Out = d2 > 0;
+			v3Out = d3 > 0;
 
-					}
+			// calculate, how many vertices of the face lie outside of the clipping plane
 
-					case 1: {
+			total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 );
 
-						// one vertex lies outside of the plane, perform clipping
+			switch ( total ) {
 
-						if ( v1Out ) {
+				case 0: {
 
-							nV1 = inVertices[ i + 1 ];
-							nV2 = inVertices[ i + 2 ];
-							nV3 = clip( inVertices[ i ], nV1, plane, s );
-							nV4 = clip( inVertices[ i ], nV2, plane, s );
+					// the entire face lies inside of the plane, no clipping needed
 
-						}
+					outVertices.push( inVertices[ i ] );
+					outVertices.push( inVertices[ i + 1 ] );
+					outVertices.push( inVertices[ i + 2 ] );
+					break;
 
-						if ( v2Out ) {
+				}
 
-							nV1 = inVertices[ i ];
-							nV2 = inVertices[ i + 2 ];
-							nV3 = clip( inVertices[ i + 1 ], nV1, plane, s );
-							nV4 = clip( inVertices[ i + 1 ], nV2, plane, s );
+				case 1: {
 
-							outVertices.push( nV3 );
-							outVertices.push( nV2.clone() );
-							outVertices.push( nV1.clone() );
+					// one vertex lies outside of the plane, perform clipping
 
-							outVertices.push( nV2.clone() );
-							outVertices.push( nV3.clone() );
-							outVertices.push( nV4 );
-							break;
+					if ( v1Out ) {
 
-						}
+						nV1 = inVertices[ i + 1 ];
+						nV2 = inVertices[ i + 2 ];
+						nV3 = clip( inVertices[ i ], nV1, plane, s );
+						nV4 = clip( inVertices[ i ], nV2, plane, s );
 
-						if ( v3Out ) {
+					}
 
-							nV1 = inVertices[ i ];
-							nV2 = inVertices[ i + 1 ];
-							nV3 = clip( inVertices[ i + 2 ], nV1, plane, s );
-							nV4 = clip( inVertices[ i + 2 ], nV2, plane, s );
+					if ( v2Out ) {
 
-						}
+						nV1 = inVertices[ i ];
+						nV2 = inVertices[ i + 2 ];
+						nV3 = clip( inVertices[ i + 1 ], nV1, plane, s );
+						nV4 = clip( inVertices[ i + 1 ], nV2, plane, s );
 
-						outVertices.push( nV1.clone() );
-						outVertices.push( nV2.clone() );
 						outVertices.push( nV3 );
-
-						outVertices.push( nV4 );
-						outVertices.push( nV3.clone() );
 						outVertices.push( nV2.clone() );
+						outVertices.push( nV1.clone() );
 
+						outVertices.push( nV2.clone() );
+						outVertices.push( nV3.clone() );
+						outVertices.push( nV4 );
 						break;
 
 					}
 
-					case 2: {
+					if ( v3Out ) {
 
-						// two vertices lies outside of the plane, perform clipping
+						nV1 = inVertices[ i ];
+						nV2 = inVertices[ i + 1 ];
+						nV3 = clip( inVertices[ i + 2 ], nV1, plane, s );
+						nV4 = clip( inVertices[ i + 2 ], nV2, plane, s );
 
-						if ( ! v1Out ) {
-
-							nV1 = inVertices[ i ].clone();
-							nV2 = clip( nV1, inVertices[ i + 1 ], plane, s );
-							nV3 = clip( nV1, inVertices[ i + 2 ], plane, s );
-							outVertices.push( nV1 );
-							outVertices.push( nV2 );
-							outVertices.push( nV3 );
+					}
 
-						}
+					outVertices.push( nV1.clone() );
+					outVertices.push( nV2.clone() );
+					outVertices.push( nV3 );
 
-						if ( ! v2Out ) {
+					outVertices.push( nV4 );
+					outVertices.push( nV3.clone() );
+					outVertices.push( nV2.clone() );
 
-							nV1 = inVertices[ i + 1 ].clone();
-							nV2 = clip( nV1, inVertices[ i + 2 ], plane, s );
-							nV3 = clip( nV1, inVertices[ i ], plane, s );
-							outVertices.push( nV1 );
-							outVertices.push( nV2 );
-							outVertices.push( nV3 );
+					break;
 
-						}
+				}
 
-						if ( ! v3Out ) {
+				case 2: {
 
-							nV1 = inVertices[ i + 2 ].clone();
-							nV2 = clip( nV1, inVertices[ i ], plane, s );
-							nV3 = clip( nV1, inVertices[ i + 1 ], plane, s );
-							outVertices.push( nV1 );
-							outVertices.push( nV2 );
-							outVertices.push( nV3 );
+					// two vertices lies outside of the plane, perform clipping
 
-						}
+					if ( ! v1Out ) {
 
-						break;
+						nV1 = inVertices[ i ].clone();
+						nV2 = clip( nV1, inVertices[ i + 1 ], plane, s );
+						nV3 = clip( nV1, inVertices[ i + 2 ], plane, s );
+						outVertices.push( nV1 );
+						outVertices.push( nV2 );
+						outVertices.push( nV3 );
 
 					}
 
-					case 3: {
+					if ( ! v2Out ) {
 
-						// the entire face lies outside of the plane, so let's discard the corresponding vertices
-
-						break;
+						nV1 = inVertices[ i + 1 ].clone();
+						nV2 = clip( nV1, inVertices[ i + 2 ], plane, s );
+						nV3 = clip( nV1, inVertices[ i ], plane, s );
+						outVertices.push( nV1 );
+						outVertices.push( nV2 );
+						outVertices.push( nV3 );
 
 					}
 
-				}
+					if ( ! v3Out ) {
 
-			}
+						nV1 = inVertices[ i + 2 ].clone();
+						nV2 = clip( nV1, inVertices[ i ], plane, s );
+						nV3 = clip( nV1, inVertices[ i + 1 ], plane, s );
+						outVertices.push( nV1 );
+						outVertices.push( nV2 );
+						outVertices.push( nV3 );
 
-			return outVertices;
+					}
 
-		}
+					break;
 
-		function clip( v0, v1, p, s ) {
+				}
 
-			var d0 = v0.position.dot( p ) - s;
-			var d1 = v1.position.dot( p ) - s;
+				case 3: {
 
-			var s0 = d0 / ( d0 - d1 );
+					// the entire face lies outside of the plane, so let's discard the corresponding vertices
 
-			var v = new DecalVertex(
-				new THREE.Vector3(
-					v0.position.x + s0 * ( v1.position.x - v0.position.x ),
-					v0.position.y + s0 * ( v1.position.y - v0.position.y ),
-					v0.position.z + s0 * ( v1.position.z - v0.position.z )
-				),
-				new THREE.Vector3(
-					v0.normal.x + s0 * ( v1.normal.x - v0.normal.x ),
-					v0.normal.y + s0 * ( v1.normal.y - v0.normal.y ),
-					v0.normal.z + s0 * ( v1.normal.z - v0.normal.z )
-				)
-			);
+					break;
 
-			// need to clip more values (texture coordinates)? do it this way:
-			// intersectpoint.value = a.value + s * ( b.value - a.value );
+				}
 
-			return v;
+			}
 
 		}
 
+		return outVertices;
+
 	}
 
-	DecalGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
-	DecalGeometry.prototype.constructor = DecalGeometry;
+	function clip( v0, v1, p, s ) {
+
+		var d0 = v0.position.dot( p ) - s;
+		var d1 = v1.position.dot( p ) - s;
+
+		var s0 = d0 / ( d0 - d1 );
 
-	// helper
+		var v = new THREE.DecalVertex(
+			new THREE.Vector3(
+				v0.position.x + s0 * ( v1.position.x - v0.position.x ),
+				v0.position.y + s0 * ( v1.position.y - v0.position.y ),
+				v0.position.z + s0 * ( v1.position.z - v0.position.z )
+			),
+			new THREE.Vector3(
+				v0.normal.x + s0 * ( v1.normal.x - v0.normal.x ),
+				v0.normal.y + s0 * ( v1.normal.y - v0.normal.y ),
+				v0.normal.z + s0 * ( v1.normal.z - v0.normal.z )
+			)
+		);
 
-	function DecalVertex( position, normal ) {
+		// need to clip more values (texture coordinates)? do it this way:
+		// intersectpoint.value = a.value + s * ( b.value - a.value );
 
-		this.position = position;
-		this.normal = normal;
+		return v;
 
 	}
 
-	DecalVertex.prototype.clone = function () {
+};
+
+THREE.DecalGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
+THREE.DecalGeometry.prototype.constructor = THREE.DecalGeometry;
+
+// helper
+
+THREE.DecalVertex = function ( position, normal ) {
 
-		return new DecalVertex( this.position.clone(), this.normal.clone() );
+	this.position = position;
+	this.normal = normal;
 
-	};
+};
 
-	// export
+THREE.DecalVertex.prototype.clone = function () {
 
-	THREE.DecalGeometry = DecalGeometry;
+	return new this.constructor( this.position.clone(), this.normal.clone() );
 
-} )();
+};

+ 0 - 157
examples/js/geometries/Hilbert.js

@@ -1,157 +0,0 @@
-/**
- * Hilbert Curves.
- *
- * @author Dylan Grafmyre
- */
-
-THREE.Hilbert = {
-
-	/**
-	 * Generates 2D-Coordinates in a very fast way.
-	 *
-	 * @author Dylan Grafmyre
-	 *
-	 * Based on work by:
-	 * @author Thomas Diewald
-	 * @link http://www.openprocessing.org/sketch/15493
-	 *
-	 * @param center     Center of Hilbert curve.
-	 * @param size       Total width of Hilbert curve.
-	 * @param iterations Number of subdivisions.
-	 * @param v0         Corner index -X, -Z.
-	 * @param v1         Corner index -X, +Z.
-	 * @param v2         Corner index +X, +Z.
-	 * @param v3         Corner index +X, -Z.
-	 */
-	generate2D( center, size, iterations, v0, v1, v2, v3 ) {
-
-		// Default Vars
-		var center = center !== undefined ? center : new THREE.Vector3( 0, 0, 0 ),
-			size = size !== undefined ? size : 10,
-			half = size / 2,
-			iterations = iterations !== undefined ? iterations : 1,
-			v0 = v0 !== undefined ? v0 : 0,
-			v1 = v1 !== undefined ? v1 : 1,
-			v2 = v2 !== undefined ? v2 : 2,
-			v3 = v3 !== undefined ? v3 : 3
-		;
-
-		var vec_s = [
-			new THREE.Vector3( center.x - half, center.y, center.z - half ),
-			new THREE.Vector3( center.x - half, center.y, center.z + half ),
-			new THREE.Vector3( center.x + half, center.y, center.z + half ),
-			new THREE.Vector3( center.x + half, center.y, center.z - half )
-		];
-
-		var vec = [
-			vec_s[ v0 ],
-			vec_s[ v1 ],
-			vec_s[ v2 ],
-			vec_s[ v3 ]
-		];
-
-		// Recurse iterations
-		if ( 0 <= -- iterations ) {
-
-			var tmp = [];
-
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate2D( vec[ 0 ], half, iterations, v0, v3, v2, v1 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate2D( vec[ 1 ], half, iterations, v0, v1, v2, v3 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate2D( vec[ 2 ], half, iterations, v0, v1, v2, v3 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate2D( vec[ 3 ], half, iterations, v2, v1, v0, v3 ) );
-
-			// Return recursive call
-			return tmp;
-
-		}
-
-		// Return complete Hilbert Curve.
-		return vec;
-
-	},
-
-	/**
-	 * Generates 3D-Coordinates in a very fast way.
-	 *
-	 * @author Dylan Grafmyre
-	 *
-	 * Based on work by:
-	 * @author Thomas Diewald
-	 * @link http://www.openprocessing.org/visuals/?visualID=15599
-	 *
-	 * @param center     Center of Hilbert curve.
-	 * @param size       Total width of Hilbert curve.
-	 * @param iterations Number of subdivisions.
-	 * @param v0         Corner index -X, +Y, -Z.
-	 * @param v1         Corner index -X, +Y, +Z.
-	 * @param v2         Corner index -X, -Y, +Z.
-	 * @param v3         Corner index -X, -Y, -Z.
-	 * @param v4         Corner index +X, -Y, -Z.
-	 * @param v5         Corner index +X, -Y, +Z.
-	 * @param v6         Corner index +X, +Y, +Z.
-	 * @param v7         Corner index +X, +Y, -Z.
-	 */
-	generate3D( center, size, iterations, v0, v1, v2, v3, v4, v5, v6, v7 ) {
-
-		// Default Vars
-		var center = center !== undefined ? center : new THREE.Vector3( 0, 0, 0 ),
-			size = size !== undefined ? size : 10,
-			half = size / 2,
-			iterations = iterations !== undefined ? iterations : 1,
-			v0 = v0 !== undefined ? v0 : 0,
-			v1 = v1 !== undefined ? v1 : 1,
-			v2 = v2 !== undefined ? v2 : 2,
-			v3 = v3 !== undefined ? v3 : 3,
-			v4 = v4 !== undefined ? v4 : 4,
-			v5 = v5 !== undefined ? v5 : 5,
-			v6 = v6 !== undefined ? v6 : 6,
-			v7 = v7 !== undefined ? v7 : 7
-		;
-
-		var vec_s = [
-			new THREE.Vector3( center.x - half, center.y + half, center.z - half ),
-			new THREE.Vector3( center.x - half, center.y + half, center.z + half ),
-			new THREE.Vector3( center.x - half, center.y - half, center.z + half ),
-			new THREE.Vector3( center.x - half, center.y - half, center.z - half ),
-			new THREE.Vector3( center.x + half, center.y - half, center.z - half ),
-			new THREE.Vector3( center.x + half, center.y - half, center.z + half ),
-			new THREE.Vector3( center.x + half, center.y + half, center.z + half ),
-			new THREE.Vector3( center.x + half, center.y + half, center.z - half )
-		];
-
-		var vec = [
-			vec_s[ v0 ],
-			vec_s[ v1 ],
-			vec_s[ v2 ],
-			vec_s[ v3 ],
-			vec_s[ v4 ],
-			vec_s[ v5 ],
-			vec_s[ v6 ],
-			vec_s[ v7 ]
-		];
-
-		// Recurse iterations
-		if ( -- iterations >= 0 ) {
-
-			var tmp = [];
-
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate3D( vec[ 0 ], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate3D( vec[ 1 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate3D( vec[ 2 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate3D( vec[ 3 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate3D( vec[ 4 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate3D( vec[ 5 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate3D( vec[ 6 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
-			Array.prototype.push.apply( tmp, THREE.Hilbert.generate3D( vec[ 7 ], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7 ) );
-
-			// Return recursive call
-			return tmp;
-
-		}
-
-		// Return complete Hilbert Curve.
-		return vec;
-
-	}
-
-};

+ 3 - 3
examples/js/geometries/LightningStrike.js

@@ -381,9 +381,9 @@ THREE.LightningStrike.prototype.init = function ( rayParameters ) {
 	this.positionAttribute = null;
 	this.uvsAttribute = null;
 
-	this.simplexX = new SimplexNoise( this.seedGenerator );
-	this.simplexY = new SimplexNoise( this.seedGenerator );
-	this.simplexZ = new SimplexNoise( this.seedGenerator );
+	this.simplexX = new THREE.SimplexNoise( this.seedGenerator );
+	this.simplexY = new THREE.SimplexNoise( this.seedGenerator );
+	this.simplexZ = new THREE.SimplexNoise( this.seedGenerator );
 
 	// Temp vectors
 	this.forwards = new THREE.Vector3();

+ 0 - 0
examples/js/ParametricGeometries.js → examples/js/geometries/ParametricGeometries.js


+ 1 - 4
examples/js/geometries/TeapotBufferGeometry.js

@@ -3,9 +3,7 @@
  *
  * Tessellates the famous Utah teapot database by Martin Newell into triangles.
  *
- * THREE.TeapotBufferGeometry = function ( size, segments, bottom, lid, body, fitLid, blinn )
- *
- * defaults: size = 50, segments = 10, bottom = true, lid = true, body = true,
+ * Parameters: size = 50, segments = 10, bottom = true, lid = true, body = true,
  *   fitLid = false, blinn = true
  *
  * size is a relative scale: I've scaled the teapot to fit vertically between -1 and 1.
@@ -50,7 +48,6 @@
  * See https://en.wikipedia.org/wiki/Utah_teapot for the history of the teapot
  *
  */
-/*global THREE */
 
 THREE.TeapotBufferGeometry = function ( size, segments, bottom, lid, body, fitLid, blinn ) {
 

+ 27 - 132
examples/js/loaders/AssimpLoader.js

@@ -359,7 +359,7 @@ THREE.AssimpLoader.prototype = {
 		var ASSBIN_MESH_HAS_COLOR_BASE = 0x10000;
 		var AI_MAX_NUMBER_OF_COLOR_SETS = 1;
 		var AI_MAX_NUMBER_OF_TEXTURECOORDS = 4;
-		var aiLightSource_UNDEFINED = 0x0;
+		//var aiLightSource_UNDEFINED = 0x0;
 		//! A directional light source has a well-defined direction
 		//! but is infinitely far away. That's quite a good
 		//! approximation for sun light.
@@ -367,7 +367,7 @@ THREE.AssimpLoader.prototype = {
 		//! A point light source has a well-defined position
 		//! in space but no direction - it emits light in all
 		//! directions. A normal bulb is a point light.
-		var aiLightSource_POINT = 0x2;
+		//var aiLightSource_POINT = 0x2;
 		//! A spot light source emits light in a specific
 		//! angle. It has a position and a direction it is pointing to.
 		//! A good example for a spot light is a light spot in
@@ -378,49 +378,49 @@ THREE.AssimpLoader.prototype = {
 		//! Typically, there's at most one ambient light in a scene.
 		//! This light type doesn't have a valid position, direction, or
 		//! other properties, just a color.
-		var aiLightSource_AMBIENT = 0x4;
+		//var aiLightSource_AMBIENT = 0x4;
 		/** Flat shading. Shading is done on per-face base,
 		 *  diffuse only. Also known as 'faceted shading'.
 		 */
-		var aiShadingMode_Flat = 0x1;
+		//var aiShadingMode_Flat = 0x1;
 		/** Simple Gouraud shading.
 		 */
-		var aiShadingMode_Gouraud = 0x2;
+		//var aiShadingMode_Gouraud = 0x2;
 		/** Phong-Shading -
 		 */
-		var aiShadingMode_Phong = 0x3;
+		//var aiShadingMode_Phong = 0x3;
 		/** Phong-Blinn-Shading
 		 */
-		var aiShadingMode_Blinn = 0x4;
+		//var aiShadingMode_Blinn = 0x4;
 		/** Toon-Shading per pixel
 		 *
 		 *  Also known as 'comic' shader.
 		 */
-		var aiShadingMode_Toon = 0x5;
+		//var aiShadingMode_Toon = 0x5;
 		/** OrenNayar-Shading per pixel
 		 *
 		 *  Extension to standard Lambertian shading, taking the
 		 *  roughness of the material into account
 		 */
-		var aiShadingMode_OrenNayar = 0x6;
+		//var aiShadingMode_OrenNayar = 0x6;
 		/** Minnaert-Shading per pixel
 		 *
 		 *  Extension to standard Lambertian shading, taking the
 		 *  "darkness" of the material into account
 		 */
-		var aiShadingMode_Minnaert = 0x7;
+		//var aiShadingMode_Minnaert = 0x7;
 		/** CookTorrance-Shading per pixel
 		 *
 		 *  Special shader for metallic surfaces.
 		 */
-		var aiShadingMode_CookTorrance = 0x8;
+		//var aiShadingMode_CookTorrance = 0x8;
 		/** No shading at all. Constant light influence of 1.0.
 		 */
-		var aiShadingMode_NoShading = 0x9;
+		//var aiShadingMode_NoShading = 0x9;
 		/** Fresnel shading
 		 */
-		var aiShadingMode_Fresnel = 0xa;
-		var aiTextureType_NONE = 0x0;
+		//var aiShadingMode_Fresnel = 0xa;
+		//var aiTextureType_NONE = 0x0;
 		/** The texture is combined with the result of the diffuse
 		 *  lighting equation.
 		 */
@@ -428,21 +428,21 @@ THREE.AssimpLoader.prototype = {
 		/** The texture is combined with the result of the specular
 		 *  lighting equation.
 		 */
-		var aiTextureType_SPECULAR = 0x2;
+		//var aiTextureType_SPECULAR = 0x2;
 		/** The texture is combined with the result of the ambient
 		 *  lighting equation.
 		 */
-		var aiTextureType_AMBIENT = 0x3;
+		//var aiTextureType_AMBIENT = 0x3;
 		/** The texture is added to the result of the lighting
 		 *  calculation. It isn't influenced by incoming light.
 		 */
-		var aiTextureType_EMISSIVE = 0x4;
+		//var aiTextureType_EMISSIVE = 0x4;
 		/** The texture is a height map.
 		 *
 		 *  By convention, higher gray-scale values stand for
 		 *  higher elevations from the base height.
 		 */
-		var aiTextureType_HEIGHT = 0x5;
+		//var aiTextureType_HEIGHT = 0x5;
 		/** The texture is a (tangent space) normal-map.
 		 *
 		 *  Again, there are several conventions for tangent-space
@@ -457,7 +457,7 @@ THREE.AssimpLoader.prototype = {
 		 *  function defined to map the linear color values in the
 		 *  texture to a suitable exponent. Have fun.
 		 */
-		var aiTextureType_SHININESS = 0x7;
+		//var aiTextureType_SHININESS = 0x7;
 		/** The texture defines per-pixel opacity.
 		 *
 		 *  Usually 'white' means opaque and 'black' means
@@ -469,7 +469,7 @@ THREE.AssimpLoader.prototype = {
 		 *  The exact purpose and format is application-dependent.
 		 *  Higher color values stand for higher vertex displacements.
 		 */
-		var aiTextureType_DISPLACEMENT = 0x9;
+		//var aiTextureType_DISPLACEMENT = 0x9;
 		/** Lightmap texture (aka Ambient Occlusion)
 		 *
 		 *  Both 'Lightmaps' and dedicated 'ambient occlusion maps' are
@@ -483,14 +483,14 @@ THREE.AssimpLoader.prototype = {
 		 * Contains the color of a perfect mirror reflection.
 		 * Rarely used, almost never for real-time applications.
 		 */
-		var aiTextureType_REFLECTION = 0xB;
+		//var aiTextureType_REFLECTION = 0xB;
 		/** Unknown texture
 		 *
 		 *  A texture reference that does not match any of the definitions
 		 *  above is considered to be 'unknown'. It is still imported,
 		 *  but is excluded from any further postprocessing.
 		 */
-		var aiTextureType_UNKNOWN = 0xC;
+		//var aiTextureType_UNKNOWN = 0xC;
 		var BONESPERVERT = 4;
 
 		function ASSBIN_MESH_HAS_TEXCOORD( n ) {
@@ -634,7 +634,7 @@ THREE.AssimpLoader.prototype = {
 			];
 			this.mFaces = [];
 			this.mBones = [];
-			this.hookupSkeletons = function ( scene, threeScene ) {
+			this.hookupSkeletons = function ( scene ) {
 
 				if ( this.mBones.length == 0 ) return;
 
@@ -668,7 +668,6 @@ THREE.AssimpLoader.prototype = {
 						var skeletonRoot = scene.findNode( this.mBones[ i ].mName );
 						if ( ! skeletonRoot ) return;
 						var threeSkeletonRoot = skeletonRoot.toTHREE( scene );
-						var threeSkeletonRootParent = threeSkeletonRoot.parent;
 						var threeSkeletonRootBone = cloneTreeToBones( threeSkeletonRoot, scene );
 						this.threeNode.add( threeSkeletonRootBone );
 						var bone = findMatchingBone( threeSkeletonRootBone, this.mBones[ i ].mName );
@@ -808,46 +807,6 @@ THREE.AssimpLoader.prototype = {
 
 		}
 
-		function aiVector2D() {
-
-			this.x = 0;
-			this.y = 0;
-			this.toTHREE = function () {
-
-				return new THREE.Vector2( this.x, this.y );
-
-			};
-
-		}
-
-		function aiVector4D() {
-
-			this.w = 0;
-			this.x = 0;
-			this.y = 0;
-			this.z = 0;
-			this.toTHREE = function () {
-
-				return new THREE.Vector4( this.w, this.x, this.y, this.z );
-
-			};
-
-		}
-
-		function aiColor4D() {
-
-			this.r = 0;
-			this.g = 0;
-			this.b = 0;
-			this.a = 0;
-			this.toTHREE = function () {
-
-				return new THREE.Color( this.r, this.g, this.b, this.a );
-
-			};
-
-		}
-
 		function aiColor3D() {
 
 			this.r = 0;
@@ -856,7 +815,7 @@ THREE.AssimpLoader.prototype = {
 			this.a = 0;
 			this.toTHREE = function () {
 
-				return new THREE.Color( this.r, this.g, this.b, 1 );
+				return new THREE.Color( this.r, this.g, this.b );
 
 			};
 
@@ -1065,9 +1024,8 @@ THREE.AssimpLoader.prototype = {
 			this.mNumAllocated = 0;
 			this.mNumProperties = 0;
 			this.mProperties = [];
-			this.toTHREE = function ( scene ) {
+			this.toTHREE = function () {
 
-				var name = this.mProperties[ 0 ].dataAsString();
 				var mat = new THREE.MeshPhongMaterial();
 
 				for ( var i = 0; i < this.mProperties.length; i ++ ) {
@@ -1238,7 +1196,7 @@ THREE.AssimpLoader.prototype = {
 
 			};
 
-			this.toTHREE = function ( o, tps ) {
+			this.toTHREE = function ( o ) {
 
 				this.sortKeys();
 				var length = this.getLength();
@@ -1404,7 +1362,7 @@ THREE.AssimpLoader.prototype = {
 				var o = this.mRootNode.toTHREE( this );
 
 				for ( var i in this.mMeshes )
-					this.mMeshes[ i ].hookupSkeletons( this, o );
+					this.mMeshes[ i ].hookupSkeletons( this );
 
 				if ( this.mAnimations.length > 0 ) {
 
@@ -1506,26 +1464,6 @@ THREE.AssimpLoader.prototype = {
 
 		}
 
-		function Read_aiVector2D( stream ) {
-
-			var v = new aiVector2D();
-			v.x = readFloat( stream );
-			v.y = readFloat( stream );
-			return v;
-
-		}
-
-		function Read_aiVector4D( stream ) {
-
-			var v = new aiVector4D();
-			v.w = readFloat( stream );
-			v.x = readFloat( stream );
-			v.y = readFloat( stream );
-			v.z = readFloat( stream );
-			return v;
-
-		}
-
 		function Read_aiColor3D( stream ) {
 
 			var c = new aiColor3D();
@@ -1536,17 +1474,6 @@ THREE.AssimpLoader.prototype = {
 
 		}
 
-		function Read_aiColor4D( stream ) {
-
-			var c = new aiColor4D();
-			c.r = readFloat( stream );
-			c.g = readFloat( stream );
-			c.b = readFloat( stream );
-			c.a = readFloat( stream );
-			return c;
-
-		}
-
 		function Read_aiQuaternion( stream ) {
 
 			var v = new aiQuaternion();
@@ -1612,42 +1539,12 @@ THREE.AssimpLoader.prototype = {
 
 		}
 
-		function ReadArray( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read( stream );
-
-		}
-
-		function ReadArray_aiVector2D( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVector2D( stream );
-
-		}
-
-		function ReadArray_aiVector3D( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVector3D( stream );
-
-		}
-
-		function ReadArray_aiVector4D( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVector4D( stream );
-
-		}
-
 		function ReadArray_aiVertexWeight( stream, data, size ) {
 
 			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVertexWeight( stream );
 
 		}
 
-		function ReadArray_aiColor4D( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiColor4D( stream );
-
-		}
-
 		function ReadArray_aiVectorKey( stream, data, size ) {
 
 			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVectorKey( stream );
@@ -1886,8 +1783,6 @@ THREE.AssimpLoader.prototype = {
 
 				// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
 				mesh.mFaces = [];
-
-				var indexCounter = 0;
 				mesh.mIndexArray = [];
 
 				for ( var i = 0; i < mesh.mNumFaces; ++ i ) {

+ 0 - 2
examples/js/loaders/BasisTextureLoader.js

@@ -143,9 +143,7 @@ THREE.BasisTextureLoader = class BasisTextureLoader {
 
 				texture.minFilter = THREE.LinearMipMapLinearFilter;
 				texture.magFilter = THREE.LinearFilter;
-				texture.encoding = THREE.sRGBEncoding;
 				texture.generateMipmaps = false;
-				texture.flipY = false;
 				texture.needsUpdate = true;
 
 				return texture;

+ 10 - 2
examples/js/loaders/LDrawLoader.js

@@ -1273,6 +1273,7 @@ THREE.LDrawLoader = ( function () {
 			material.transparent = isTransparent;
 			material.premultipliedAlpha = true;
 			material.opacity = alpha;
+			material.depthWrite = ! isTransparent;
 
 			material.polygonOffset = true;
 			material.polygonOffsetFactor = 1;
@@ -1288,7 +1289,12 @@ THREE.LDrawLoader = ( function () {
 			if ( ! edgeMaterial ) {
 
 				// This is the material used for edges
-				edgeMaterial = new THREE.LineBasicMaterial( { color: edgeColour } );
+				edgeMaterial = new THREE.LineBasicMaterial( {
+					color: edgeColour,
+					transparent: isTransparent,
+					opacity: alpha,
+					depthWrite: ! isTransparent
+				} );
 				edgeMaterial.userData.code = code;
 				edgeMaterial.name = name + " - Edge";
 				edgeMaterial.userData.canHaveEnvMap = false;
@@ -1304,7 +1310,9 @@ THREE.LDrawLoader = ( function () {
 						opacity: {
 							value: alpha
 						}
-					}
+					},
+					transparent: isTransparent,
+					depthWrite: ! isTransparent
 				} );
 				edgeMaterial.userData.conditionalEdgeMaterial.userData.canHaveEnvMap = false;
 

+ 7 - 7
examples/js/loaders/SVGLoader.js

@@ -56,37 +56,37 @@ THREE.SVGLoader.prototype = {
 
 				case 'path':
 					style = parseStyle( node, style );
-					if ( node.hasAttribute( 'd' ) ) path = parsePathNode( node, style );
+					if ( node.hasAttribute( 'd' ) ) path = parsePathNode( node );
 					break;
 
 				case 'rect':
 					style = parseStyle( node, style );
-					path = parseRectNode( node, style );
+					path = parseRectNode( node );
 					break;
 
 				case 'polygon':
 					style = parseStyle( node, style );
-					path = parsePolygonNode( node, style );
+					path = parsePolygonNode( node );
 					break;
 
 				case 'polyline':
 					style = parseStyle( node, style );
-					path = parsePolylineNode( node, style );
+					path = parsePolylineNode( node );
 					break;
 
 				case 'circle':
 					style = parseStyle( node, style );
-					path = parseCircleNode( node, style );
+					path = parseCircleNode( node );
 					break;
 
 				case 'ellipse':
 					style = parseStyle( node, style );
-					path = parseEllipseNode( node, style );
+					path = parseEllipseNode( node );
 					break;
 
 				case 'line':
 					style = parseStyle( node, style );
-					path = parseLineNode( node, style );
+					path = parseLineNode( node );
 					break;
 
 				default:

+ 15 - 3
examples/js/loaders/VTKLoader.js

@@ -99,7 +99,13 @@ Object.assign( THREE.VTKLoader.prototype, THREE.EventDispatcher.prototype, {
 
 				var line = lines[ i ];
 
-				if ( inPointsSection ) {
+				if ( line.indexOf( 'DATASET' ) === 0 ) {
+
+					var dataset = line.split( ' ' )[ 1 ];
+
+					if ( dataset !== 'POLYDATA' ) throw new Error( 'Unsupported DATASET type: ' + dataset );
+
+				} else if ( inPointsSection ) {
 
 					// get the vertices
 					while ( ( result = pat3Floats.exec( line ) ) !== null ) {
@@ -354,7 +360,13 @@ Object.assign( THREE.VTKLoader.prototype, THREE.EventDispatcher.prototype, {
 				state = findString( buffer, index );
 				line = state.parsedString;
 
-				if ( line.indexOf( 'POINTS' ) === 0 ) {
+				if ( line.indexOf( 'DATASET' ) === 0 ) {
+
+					var dataset = line.split( ' ' )[ 1 ];
+
+					if ( dataset !== 'POLYDATA' ) throw new Error( 'Unsupported DATASET type: ' + dataset );
+
+				} else if ( line.indexOf( 'POINTS' ) === 0 ) {
 
 					vtk.push( line );
 					// Add the points
@@ -1117,7 +1129,7 @@ Object.assign( THREE.VTKLoader.prototype, THREE.EventDispatcher.prototype, {
 
 			} else {
 
-				// TODO for vtu,vti,and other xml formats
+				throw new Error( 'Unsupported DATASET type' );
 
 			}
 

+ 6 - 9
examples/js/QuickHull.js → examples/js/math/ConvexHull.js

@@ -5,14 +5,14 @@
  *
  */
 
-( function () {
+THREE.ConvexHull = ( function () {
 
 	var Visible = 0;
 	var Deleted = 1;
 
 	var v1 = new THREE.Vector3();
 
-	function QuickHull() {
+	function ConvexHull() {
 
 		this.tolerance = - 1;
 
@@ -36,19 +36,19 @@
 
 	}
 
-	Object.assign( QuickHull.prototype, {
+	Object.assign( ConvexHull.prototype, {
 
 		setFromPoints: function ( points ) {
 
 			if ( Array.isArray( points ) !== true ) {
 
-				console.error( 'THREE.QuickHull: Points parameter is not an array.' );
+				console.error( 'THREE.ConvexHull: Points parameter is not an array.' );
 
 			}
 
 			if ( points.length < 4 ) {
 
-				console.error( 'THREE.QuickHull: The algorithm needs at least four points.' );
+				console.error( 'THREE.ConvexHull: The algorithm needs at least four points.' );
 
 			}
 
@@ -1311,9 +1311,6 @@
 
 	} );
 
-	// export
-
-	THREE.QuickHull = QuickHull;
-
+	return ConvexHull;
 
 } )();

+ 72 - 0
examples/js/math/ImprovedNoise.js

@@ -0,0 +1,72 @@
+// http://mrl.nyu.edu/~perlin/noise/
+
+THREE.ImprovedNoise = function () {
+
+	var p = [ 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10,
+		 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87,
+		 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211,
+		 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208,
+		 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5,
+		 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119,
+		 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232,
+		 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249,
+		 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205,
+		 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 ];
+
+	for ( var i = 0; i < 256; i ++ ) {
+
+		p[ 256 + i ] = p[ i ];
+
+	}
+
+	function fade( t ) {
+
+		return t * t * t * ( t * ( t * 6 - 15 ) + 10 );
+
+	}
+
+	function lerp( t, a, b ) {
+
+		return a + t * ( b - a );
+
+	}
+
+	function grad( hash, x, y, z ) {
+
+		var h = hash & 15;
+		var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+		return ( ( h & 1 ) == 0 ? u : - u ) + ( ( h & 2 ) == 0 ? v : - v );
+
+	}
+
+	return {
+
+		noise: function ( x, y, z ) {
+
+			var floorX = Math.floor( x ), floorY = Math.floor( y ), floorZ = Math.floor( z );
+
+			var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255;
+
+			x -= floorX;
+			y -= floorY;
+			z -= floorZ;
+
+			var xMinus1 = x - 1, yMinus1 = y - 1, zMinus1 = z - 1;
+
+			var u = fade( x ), v = fade( y ), w = fade( z );
+
+			var A = p[ X ] + Y, AA = p[ A ] + Z, AB = p[ A + 1 ] + Z, B = p[ X + 1 ] + Y, BA = p[ B ] + Z, BB = p[ B + 1 ] + Z;
+
+			return lerp( w, lerp( v, lerp( u, grad( p[ AA ], x, y, z ),
+				grad( p[ BA ], xMinus1, y, z ) ),
+			lerp( u, grad( p[ AB ], x, yMinus1, z ),
+				grad( p[ BB ], xMinus1, yMinus1, z ) ) ),
+			lerp( v, lerp( u, grad( p[ AA + 1 ], x, y, zMinus1 ),
+				grad( p[ BA + 1 ], xMinus1, y, z - 1 ) ),
+			lerp( u, grad( p[ AB + 1 ], x, yMinus1, zMinus1 ),
+				grad( p[ BB + 1 ], xMinus1, yMinus1, zMinus1 ) ) ) );
+
+		}
+	};
+
+};

+ 0 - 15
examples/js/math/Lut.js

@@ -10,20 +10,6 @@ THREE.Lut = function ( colormap, numberofcolors ) {
 
 };
 
-var defaultLabelParameters = {
-	fontsize: 24,
-	fontface: 'Arial',
-	title: '',
-	um: '',
-	ticks: 0,
-	decimal: 2,
-	notation: 'standard'
-};
-
-var defaultBackgroundColor = { r: 255, g: 100, b: 100, a: 0.8 };
-var defaultBorderColor = { r: 255, g: 0, b: 0, a: 1.0 };
-var defaultBorderThickness = 4;
-
 THREE.Lut.prototype = {
 
 	constructor: THREE.Lut,
@@ -189,7 +175,6 @@ THREE.Lut.prototype = {
 	}
 };
 
-
 THREE.ColorMapKeywords = {
 
 	"rainbow": [[ 0.0, 0x0000FF ], [ 0.2, 0x00FFFF ], [ 0.5, 0x00FF00 ], [ 0.8, 0xFFFF00 ], [ 1.0, 0xFF0000 ]],

+ 405 - 0
examples/js/math/SimplexNoise.js

@@ -0,0 +1,405 @@
+// Ported from Stefan Gustavson's java implementation
+// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
+// Read Stefan's excellent paper for details on how this code works.
+//
+// Sean McCullough [email protected]
+//
+// Added 4D noise
+// Joshua Koo [email protected]
+
+/**
+ * You can pass in a random number generator object if you like.
+ * It is assumed to have a random() method.
+ */
+THREE.SimplexNoise = function ( r ) {
+
+	if ( r == undefined ) r = Math;
+	this.grad3 = [[ 1, 1, 0 ], [ - 1, 1, 0 ], [ 1, - 1, 0 ], [ - 1, - 1, 0 ],
+		[ 1, 0, 1 ], [ - 1, 0, 1 ], [ 1, 0, - 1 ], [ - 1, 0, - 1 ],
+		[ 0, 1, 1 ], [ 0, - 1, 1 ], [ 0, 1, - 1 ], [ 0, - 1, - 1 ]];
+
+	this.grad4 = [[ 0, 1, 1, 1 ], [ 0, 1, 1, - 1 ], [ 0, 1, - 1, 1 ], [ 0, 1, - 1, - 1 ],
+	     [ 0, - 1, 1, 1 ], [ 0, - 1, 1, - 1 ], [ 0, - 1, - 1, 1 ], [ 0, - 1, - 1, - 1 ],
+	     [ 1, 0, 1, 1 ], [ 1, 0, 1, - 1 ], [ 1, 0, - 1, 1 ], [ 1, 0, - 1, - 1 ],
+	     [ - 1, 0, 1, 1 ], [ - 1, 0, 1, - 1 ], [ - 1, 0, - 1, 1 ], [ - 1, 0, - 1, - 1 ],
+	     [ 1, 1, 0, 1 ], [ 1, 1, 0, - 1 ], [ 1, - 1, 0, 1 ], [ 1, - 1, 0, - 1 ],
+	     [ - 1, 1, 0, 1 ], [ - 1, 1, 0, - 1 ], [ - 1, - 1, 0, 1 ], [ - 1, - 1, 0, - 1 ],
+	     [ 1, 1, 1, 0 ], [ 1, 1, - 1, 0 ], [ 1, - 1, 1, 0 ], [ 1, - 1, - 1, 0 ],
+	     [ - 1, 1, 1, 0 ], [ - 1, 1, - 1, 0 ], [ - 1, - 1, 1, 0 ], [ - 1, - 1, - 1, 0 ]];
+
+	this.p = [];
+	for ( var i = 0; i < 256; i ++ ) {
+
+		this.p[ i ] = Math.floor( r.random() * 256 );
+
+	}
+	// To remove the need for index wrapping, double the permutation table length
+	this.perm = [];
+	for ( var i = 0; i < 512; i ++ ) {
+
+		this.perm[ i ] = this.p[ i & 255 ];
+
+	}
+
+	// A lookup table to traverse the simplex around a given point in 4D.
+	// Details can be found where this table is used, in the 4D noise method.
+	this.simplex = [
+		[ 0, 1, 2, 3 ], [ 0, 1, 3, 2 ], [ 0, 0, 0, 0 ], [ 0, 2, 3, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 1, 2, 3, 0 ],
+		[ 0, 2, 1, 3 ], [ 0, 0, 0, 0 ], [ 0, 3, 1, 2 ], [ 0, 3, 2, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 1, 3, 2, 0 ],
+		[ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ],
+		[ 1, 2, 0, 3 ], [ 0, 0, 0, 0 ], [ 1, 3, 0, 2 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 2, 3, 0, 1 ], [ 2, 3, 1, 0 ],
+		[ 1, 0, 2, 3 ], [ 1, 0, 3, 2 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 2, 0, 3, 1 ], [ 0, 0, 0, 0 ], [ 2, 1, 3, 0 ],
+		[ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ],
+		[ 2, 0, 1, 3 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 3, 0, 1, 2 ], [ 3, 0, 2, 1 ], [ 0, 0, 0, 0 ], [ 3, 1, 2, 0 ],
+		[ 2, 1, 0, 3 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 3, 1, 0, 2 ], [ 0, 0, 0, 0 ], [ 3, 2, 0, 1 ], [ 3, 2, 1, 0 ]];
+
+};
+
+THREE.SimplexNoise.prototype.dot = function ( g, x, y ) {
+
+	return g[ 0 ] * x + g[ 1 ] * y;
+
+};
+
+THREE.SimplexNoise.prototype.dot3 = function ( g, x, y, z ) {
+
+	return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z;
+
+};
+
+THREE.SimplexNoise.prototype.dot4 = function ( g, x, y, z, w ) {
+
+	return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z + g[ 3 ] * w;
+
+};
+
+THREE.SimplexNoise.prototype.noise = function ( xin, yin ) {
+
+	var n0, n1, n2; // Noise contributions from the three corners
+	// Skew the input space to determine which simplex cell we're in
+	var F2 = 0.5 * ( Math.sqrt( 3.0 ) - 1.0 );
+	var s = ( xin + yin ) * F2; // Hairy factor for 2D
+	var i = Math.floor( xin + s );
+	var j = Math.floor( yin + s );
+	var G2 = ( 3.0 - Math.sqrt( 3.0 ) ) / 6.0;
+	var t = ( i + j ) * G2;
+	var X0 = i - t; // Unskew the cell origin back to (x,y) space
+	var Y0 = j - t;
+	var x0 = xin - X0; // The x,y distances from the cell origin
+	var y0 = yin - Y0;
+	// For the 2D case, the simplex shape is an equilateral triangle.
+	// Determine which simplex we are in.
+	var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
+	if ( x0 > y0 ) {
+
+		i1 = 1; j1 = 0;
+
+		// lower triangle, XY order: (0,0)->(1,0)->(1,1)
+
+	}	else {
+
+		i1 = 0; j1 = 1;
+
+	} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
+	// A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
+	// a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
+	// c = (3-sqrt(3))/6
+	var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
+	var y1 = y0 - j1 + G2;
+	var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
+	var y2 = y0 - 1.0 + 2.0 * G2;
+	// Work out the hashed gradient indices of the three simplex corners
+	var ii = i & 255;
+	var jj = j & 255;
+	var gi0 = this.perm[ ii + this.perm[ jj ] ] % 12;
+	var gi1 = this.perm[ ii + i1 + this.perm[ jj + j1 ] ] % 12;
+	var gi2 = this.perm[ ii + 1 + this.perm[ jj + 1 ] ] % 12;
+	// Calculate the contribution from the three corners
+	var t0 = 0.5 - x0 * x0 - y0 * y0;
+	if ( t0 < 0 ) n0 = 0.0;
+	else {
+
+		t0 *= t0;
+		n0 = t0 * t0 * this.dot( this.grad3[ gi0 ], x0, y0 ); // (x,y) of grad3 used for 2D gradient
+
+	}
+	var t1 = 0.5 - x1 * x1 - y1 * y1;
+	if ( t1 < 0 ) n1 = 0.0;
+	else {
+
+		t1 *= t1;
+		n1 = t1 * t1 * this.dot( this.grad3[ gi1 ], x1, y1 );
+
+	}
+	var t2 = 0.5 - x2 * x2 - y2 * y2;
+	if ( t2 < 0 ) n2 = 0.0;
+	else {
+
+		t2 *= t2;
+		n2 = t2 * t2 * this.dot( this.grad3[ gi2 ], x2, y2 );
+
+	}
+	// Add contributions from each corner to get the final noise value.
+	// The result is scaled to return values in the interval [-1,1].
+	return 70.0 * ( n0 + n1 + n2 );
+
+};
+
+// 3D simplex noise
+THREE.SimplexNoise.prototype.noise3d = function ( xin, yin, zin ) {
+
+	var n0, n1, n2, n3; // Noise contributions from the four corners
+	// Skew the input space to determine which simplex cell we're in
+	var F3 = 1.0 / 3.0;
+	var s = ( xin + yin + zin ) * F3; // Very nice and simple skew factor for 3D
+	var i = Math.floor( xin + s );
+	var j = Math.floor( yin + s );
+	var k = Math.floor( zin + s );
+	var G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too
+	var t = ( i + j + k ) * G3;
+	var X0 = i - t; // Unskew the cell origin back to (x,y,z) space
+	var Y0 = j - t;
+	var Z0 = k - t;
+	var x0 = xin - X0; // The x,y,z distances from the cell origin
+	var y0 = yin - Y0;
+	var z0 = zin - Z0;
+	// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
+	// Determine which simplex we are in.
+	var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
+	var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
+	if ( x0 >= y0 ) {
+
+		if ( y0 >= z0 ) {
+
+			i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0;
+
+			// X Y Z order
+
+		} else if ( x0 >= z0 ) {
+
+			i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1;
+
+			// X Z Y order
+
+		} else {
+
+			i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1;
+
+		} // Z X Y order
+
+	} else { // x0<y0
+
+		if ( y0 < z0 ) {
+
+			i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1;
+
+			// Z Y X order
+
+		} else if ( x0 < z0 ) {
+
+			i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1;
+
+			// Y Z X order
+
+		} else {
+
+			i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0;
+
+		} // Y X Z order
+
+	}
+	// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
+	// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
+	// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
+	// c = 1/6.
+	var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
+	var y1 = y0 - j1 + G3;
+	var z1 = z0 - k1 + G3;
+	var x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
+	var y2 = y0 - j2 + 2.0 * G3;
+	var z2 = z0 - k2 + 2.0 * G3;
+	var x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
+	var y3 = y0 - 1.0 + 3.0 * G3;
+	var z3 = z0 - 1.0 + 3.0 * G3;
+	// Work out the hashed gradient indices of the four simplex corners
+	var ii = i & 255;
+	var jj = j & 255;
+	var kk = k & 255;
+	var gi0 = this.perm[ ii + this.perm[ jj + this.perm[ kk ] ] ] % 12;
+	var gi1 = this.perm[ ii + i1 + this.perm[ jj + j1 + this.perm[ kk + k1 ] ] ] % 12;
+	var gi2 = this.perm[ ii + i2 + this.perm[ jj + j2 + this.perm[ kk + k2 ] ] ] % 12;
+	var gi3 = this.perm[ ii + 1 + this.perm[ jj + 1 + this.perm[ kk + 1 ] ] ] % 12;
+	// Calculate the contribution from the four corners
+	var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
+	if ( t0 < 0 ) n0 = 0.0;
+	else {
+
+		t0 *= t0;
+		n0 = t0 * t0 * this.dot3( this.grad3[ gi0 ], x0, y0, z0 );
+
+	}
+	var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
+	if ( t1 < 0 ) n1 = 0.0;
+	else {
+
+		t1 *= t1;
+		n1 = t1 * t1 * this.dot3( this.grad3[ gi1 ], x1, y1, z1 );
+
+	}
+	var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
+	if ( t2 < 0 ) n2 = 0.0;
+	else {
+
+		t2 *= t2;
+		n2 = t2 * t2 * this.dot3( this.grad3[ gi2 ], x2, y2, z2 );
+
+	}
+	var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
+	if ( t3 < 0 ) n3 = 0.0;
+	else {
+
+		t3 *= t3;
+		n3 = t3 * t3 * this.dot3( this.grad3[ gi3 ], x3, y3, z3 );
+
+	}
+	// Add contributions from each corner to get the final noise value.
+	// The result is scaled to stay just inside [-1,1]
+	return 32.0 * ( n0 + n1 + n2 + n3 );
+
+};
+
+// 4D simplex noise
+THREE.SimplexNoise.prototype.noise4d = function ( x, y, z, w ) {
+
+	// For faster and easier lookups
+	var grad4 = this.grad4;
+	var simplex = this.simplex;
+	var perm = this.perm;
+
+	// The skewing and unskewing factors are hairy again for the 4D case
+	var F4 = ( Math.sqrt( 5.0 ) - 1.0 ) / 4.0;
+	var G4 = ( 5.0 - Math.sqrt( 5.0 ) ) / 20.0;
+	var n0, n1, n2, n3, n4; // Noise contributions from the five corners
+	// Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
+	var s = ( x + y + z + w ) * F4; // Factor for 4D skewing
+	var i = Math.floor( x + s );
+	var j = Math.floor( y + s );
+	var k = Math.floor( z + s );
+	var l = Math.floor( w + s );
+	var t = ( i + j + k + l ) * G4; // Factor for 4D unskewing
+	var X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
+	var Y0 = j - t;
+	var Z0 = k - t;
+	var W0 = l - t;
+	var x0 = x - X0; // The x,y,z,w distances from the cell origin
+	var y0 = y - Y0;
+	var z0 = z - Z0;
+	var w0 = w - W0;
+
+	// For the 4D case, the simplex is a 4D shape I won't even try to describe.
+	// To find out which of the 24 possible simplices we're in, we need to
+	// determine the magnitude ordering of x0, y0, z0 and w0.
+	// The method below is a good way of finding the ordering of x,y,z,w and
+	// then find the correct traversal order for the simplex we’re in.
+	// First, six pair-wise comparisons are performed between each possible pair
+	// of the four coordinates, and the results are used to add up binary bits
+	// for an integer index.
+	var c1 = ( x0 > y0 ) ? 32 : 0;
+	var c2 = ( x0 > z0 ) ? 16 : 0;
+	var c3 = ( y0 > z0 ) ? 8 : 0;
+	var c4 = ( x0 > w0 ) ? 4 : 0;
+	var c5 = ( y0 > w0 ) ? 2 : 0;
+	var c6 = ( z0 > w0 ) ? 1 : 0;
+	var c = c1 + c2 + c3 + c4 + c5 + c6;
+	var i1, j1, k1, l1; // The integer offsets for the second simplex corner
+	var i2, j2, k2, l2; // The integer offsets for the third simplex corner
+	var i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
+	// simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
+	// Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
+	// impossible. Only the 24 indices which have non-zero entries make any sense.
+	// We use a thresholding to set the coordinates in turn from the largest magnitude.
+	// The number 3 in the "simplex" array is at the position of the largest coordinate.
+	i1 = simplex[ c ][ 0 ] >= 3 ? 1 : 0;
+	j1 = simplex[ c ][ 1 ] >= 3 ? 1 : 0;
+	k1 = simplex[ c ][ 2 ] >= 3 ? 1 : 0;
+	l1 = simplex[ c ][ 3 ] >= 3 ? 1 : 0;
+	// The number 2 in the "simplex" array is at the second largest coordinate.
+	i2 = simplex[ c ][ 0 ] >= 2 ? 1 : 0;
+	j2 = simplex[ c ][ 1 ] >= 2 ? 1 : 0; k2 = simplex[ c ][ 2 ] >= 2 ? 1 : 0;
+	l2 = simplex[ c ][ 3 ] >= 2 ? 1 : 0;
+	// The number 1 in the "simplex" array is at the second smallest coordinate.
+	i3 = simplex[ c ][ 0 ] >= 1 ? 1 : 0;
+	j3 = simplex[ c ][ 1 ] >= 1 ? 1 : 0;
+	k3 = simplex[ c ][ 2 ] >= 1 ? 1 : 0;
+	l3 = simplex[ c ][ 3 ] >= 1 ? 1 : 0;
+	// The fifth corner has all coordinate offsets = 1, so no need to look that up.
+	var x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
+	var y1 = y0 - j1 + G4;
+	var z1 = z0 - k1 + G4;
+	var w1 = w0 - l1 + G4;
+	var x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords
+	var y2 = y0 - j2 + 2.0 * G4;
+	var z2 = z0 - k2 + 2.0 * G4;
+	var w2 = w0 - l2 + 2.0 * G4;
+	var x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords
+	var y3 = y0 - j3 + 3.0 * G4;
+	var z3 = z0 - k3 + 3.0 * G4;
+	var w3 = w0 - l3 + 3.0 * G4;
+	var x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords
+	var y4 = y0 - 1.0 + 4.0 * G4;
+	var z4 = z0 - 1.0 + 4.0 * G4;
+	var w4 = w0 - 1.0 + 4.0 * G4;
+	// Work out the hashed gradient indices of the five simplex corners
+	var ii = i & 255;
+	var jj = j & 255;
+	var kk = k & 255;
+	var ll = l & 255;
+	var gi0 = perm[ ii + perm[ jj + perm[ kk + perm[ ll ] ] ] ] % 32;
+	var gi1 = perm[ ii + i1 + perm[ jj + j1 + perm[ kk + k1 + perm[ ll + l1 ] ] ] ] % 32;
+	var gi2 = perm[ ii + i2 + perm[ jj + j2 + perm[ kk + k2 + perm[ ll + l2 ] ] ] ] % 32;
+	var gi3 = perm[ ii + i3 + perm[ jj + j3 + perm[ kk + k3 + perm[ ll + l3 ] ] ] ] % 32;
+	var gi4 = perm[ ii + 1 + perm[ jj + 1 + perm[ kk + 1 + perm[ ll + 1 ] ] ] ] % 32;
+	// Calculate the contribution from the five corners
+	var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
+	if ( t0 < 0 ) n0 = 0.0;
+	else {
+
+		t0 *= t0;
+		n0 = t0 * t0 * this.dot4( grad4[ gi0 ], x0, y0, z0, w0 );
+
+	}
+	var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
+	if ( t1 < 0 ) n1 = 0.0;
+	else {
+
+		t1 *= t1;
+		n1 = t1 * t1 * this.dot4( grad4[ gi1 ], x1, y1, z1, w1 );
+
+	}
+	var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
+	if ( t2 < 0 ) n2 = 0.0;
+	else {
+
+		t2 *= t2;
+		n2 = t2 * t2 * this.dot4( grad4[ gi2 ], x2, y2, z2, w2 );
+
+	} var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
+	if ( t3 < 0 ) n3 = 0.0;
+	else {
+
+		t3 *= t3;
+		n3 = t3 * t3 * this.dot4( grad4[ gi3 ], x3, y3, z3, w3 );
+
+	}
+	var t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
+	if ( t4 < 0 ) n4 = 0.0;
+	else {
+
+		t4 *= t4;
+		n4 = t4 * t4 * this.dot4( grad4[ gi4 ], x4, y4, z4, w4 );
+
+	}
+	// Sum up and scale the result to cover the range [-1,1]
+	return 27.0 * ( n0 + n1 + n2 + n3 + n4 );
+
+};

+ 4 - 5
examples/js/modifiers/SubdivisionModifier.js

@@ -53,7 +53,6 @@ THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
 ( function () {
 
 	// Some constants
-	var WARNINGS = ! true; // Set to true for development
 	var ABC = [ 'a', 'b', 'c' ];
 
 
@@ -215,7 +214,7 @@ THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
 
 				if ( connectedFaces != 1 ) {
 
-					if ( WARNINGS ) console.warn( 'Subdivision Modifier: Number of connected faces != 2, is: ', connectedFaces, currentEdge );
+					// console.warn( 'Subdivision Modifier: Number of connected faces != 2, is: ', connectedFaces, currentEdge );
 
 				}
 
@@ -292,7 +291,7 @@ THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
 
 				if ( n == 2 ) {
 
-					if ( WARNINGS ) console.warn( '2 connecting edges', connectingEdges );
+					// console.warn( '2 connecting edges', connectingEdges );
 					sourceVertexWeight = 3 / 4;
 					connectingVertexWeight = 1 / 8;
 
@@ -301,11 +300,11 @@ THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
 
 				} else if ( n == 1 ) {
 
-					if ( WARNINGS ) console.warn( 'only 1 connecting edge' );
+					// console.warn( 'only 1 connecting edge' );
 
 				} else if ( n == 0 ) {
 
-					if ( WARNINGS ) console.warn( '0 connecting edges' );
+					// console.warn( '0 connecting edges' );
 
 				}
 

+ 2 - 2
examples/js/modifiers/TessellateModifier.js

@@ -186,7 +186,7 @@ THREE.TessellateModifier.prototype.modify = function ( geometry ) {
 							var uvsTriA = [ uvA.clone(), uvM.clone(), uvC.clone() ];
 							var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
 
-						// BC
+							// BC
 
 						} else if ( edge === 1 ) {
 
@@ -196,7 +196,7 @@ THREE.TessellateModifier.prototype.modify = function ( geometry ) {
 							var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
 							var uvsTriB = [ uvM.clone(), uvC.clone(), uvA.clone() ];
 
-						// AC
+							// AC
 
 						} else {
 

+ 4 - 0
examples/js/objects/ReflectorRTT.js

@@ -1,3 +1,7 @@
+/**
+ * RTT version
+ */
+
 THREE.ReflectorRTT = function ( geometry, options ) {
 
 	THREE.Reflector.call( this, geometry, options );

+ 10 - 10
examples/js/objects/ShadowMesh.js

@@ -42,23 +42,23 @@ THREE.ShadowMesh.prototype.update = function () {
 
 		var sme = shadowMatrix.elements;
 
-		sme[ 0 ]  = dot - lightPosition4D.x * plane.normal.x;
-		sme[ 4 ]  = - lightPosition4D.x * plane.normal.y;
-		sme[ 8 ]  = - lightPosition4D.x * plane.normal.z;
+		sme[ 0 ] = dot - lightPosition4D.x * plane.normal.x;
+		sme[ 4 ] = - lightPosition4D.x * plane.normal.y;
+		sme[ 8 ] = - lightPosition4D.x * plane.normal.z;
 		sme[ 12 ] = - lightPosition4D.x * - plane.constant;
 
-		sme[ 1 ]  = - lightPosition4D.y * plane.normal.x;
-		sme[ 5 ]  = dot - lightPosition4D.y * plane.normal.y;
-		sme[ 9 ]  = - lightPosition4D.y * plane.normal.z;
+		sme[ 1 ] = - lightPosition4D.y * plane.normal.x;
+		sme[ 5 ] = dot - lightPosition4D.y * plane.normal.y;
+		sme[ 9 ] = - lightPosition4D.y * plane.normal.z;
 		sme[ 13 ] = - lightPosition4D.y * - plane.constant;
 
-		sme[ 2 ]  = - lightPosition4D.z * plane.normal.x;
-		sme[ 6 ]  = - lightPosition4D.z * plane.normal.y;
+		sme[ 2 ] = - lightPosition4D.z * plane.normal.x;
+		sme[ 6 ] = - lightPosition4D.z * plane.normal.y;
 		sme[ 10 ] = dot - lightPosition4D.z * plane.normal.z;
 		sme[ 14 ] = - lightPosition4D.z * - plane.constant;
 
-		sme[ 3 ]  = - lightPosition4D.w * plane.normal.x;
-		sme[ 7 ]  = - lightPosition4D.w * plane.normal.y;
+		sme[ 3 ] = - lightPosition4D.w * plane.normal.x;
+		sme[ 7 ] = - lightPosition4D.w * plane.normal.y;
 		sme[ 11 ] = - lightPosition4D.w * plane.normal.z;
 		sme[ 15 ] = dot - lightPosition4D.w * - plane.constant;
 

+ 2 - 4
examples/js/postprocessing/EffectComposer.js

@@ -58,7 +58,7 @@ THREE.EffectComposer = function ( renderer, renderTarget ) {
 
 	this.copyPass = new THREE.ShaderPass( THREE.CopyShader );
 
-	this._previousFrameTime = Date.now();
+	this.clock = new THREE.Clock();
 
 };
 
@@ -109,12 +109,10 @@ Object.assign( THREE.EffectComposer.prototype, {
 
 		if ( deltaTime === undefined ) {
 
-			deltaTime = ( Date.now() - this._previousFrameTime ) * 0.001;
+			deltaTime = this.clock.getDelta();
 
 		}
 
-		this._previousFrameTime = Date.now();
-
 		var currentRenderTarget = this.renderer.getRenderTarget();
 
 		var maskActive = false;

+ 2 - 2
examples/js/postprocessing/SSAOPass.js

@@ -357,13 +357,13 @@ THREE.SSAOPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ),
 
 		var width = 4, height = 4;
 
-		if ( SimplexNoise === undefined ) {
+		if ( THREE.SimplexNoise === undefined ) {
 
 			console.error( 'THREE.SSAOPass: The pass relies on THREE.SimplexNoise.' );
 
 		}
 
-		var simplex = new SimplexNoise();
+		var simplex = new THREE.SimplexNoise();
 
 		var size = width * height;
 		var data = new Float32Array( size * 4 );

+ 28 - 0
examples/js/renderers/SVGRenderer.js

@@ -57,6 +57,8 @@ THREE.SVGRenderer = function () {
 	this.sortObjects = true;
 	this.sortElements = true;
 
+	this.overdraw = 0.5;
+
 	this.info = {
 
 		render: {
@@ -227,6 +229,14 @@ THREE.SVGRenderer = function () {
 				_v2.positionScreen.x *= _svgWidthHalf; _v2.positionScreen.y *= - _svgHeightHalf;
 				_v3.positionScreen.x *= _svgWidthHalf; _v3.positionScreen.y *= - _svgHeightHalf;
 
+				if ( this.overdraw > 0 ) {
+
+					expand( _v1.positionScreen, _v2.positionScreen, this.overdraw );
+					expand( _v2.positionScreen, _v3.positionScreen, this.overdraw );
+					expand( _v3.positionScreen, _v1.positionScreen, this.overdraw );
+
+				}
+
 				_elemBox.setFromPoints( [
 					_v1.positionScreen,
 					_v2.positionScreen,
@@ -451,6 +461,24 @@ THREE.SVGRenderer = function () {
 
 	}
 
+	// Hide anti-alias gaps
+
+	function expand( v1, v2, pixels ) {
+
+		var x = v2.x - v1.x, y = v2.y - v1.y,
+			det = x * x + y * y, idet;
+
+		if ( det === 0 ) return;
+
+		idet = pixels / Math.sqrt( det );
+
+		x *= idet; y *= idet;
+
+		v2.x += x; v2.y += y;
+		v1.x -= x; v1.y -= y;
+
+	}
+
 	function addPath( style, path ) {
 
 		if ( _currentStyle === style ) {

+ 8 - 8
examples/js/renderers/WebGLDeferredRenderer.js

@@ -418,7 +418,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 	}
 
-	function createDeferredNormalDepthMaterial( originalMaterial ) {
+	function createDeferredNormalDepthMaterial() {
 
 		var shader = ( _lightPrePass ) ? THREE.ShaderDeferred[ 'normalDepthShininess' ] : THREE.ShaderDeferred[ 'normalDepth' ];
 
@@ -448,7 +448,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 	}
 
-	function updateDeferredNormalDepthUniforms( renderer, scene, camera, geometry, material, group ) {
+	function updateDeferredNormalDepthUniforms( renderer, scene, camera, geometry, material ) {
 
 		if ( ! _lightPrePass ) return;
 
@@ -512,7 +512,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 	}
 
-	function updateDeferredColorUniforms( renderer, scene, camera, geometry, material, group ) {
+	function updateDeferredColorUniforms( renderer, scene, camera, geometry, material ) {
 
 		var originalMaterial = _originalMaterialsTable[ material.uuid ];
 		var uniforms = material.uniforms;
@@ -606,7 +606,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 		}
 
-		updateDeferredColorUniforms( renderer, scene, camera, geometry, material, group );
+		updateDeferredColorUniforms( renderer, scene, camera, geometry, material );
 
 		material.uniforms.samplerLight.value = _compLight.renderTarget2.texture;
 
@@ -677,7 +677,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 		var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
 		var mesh = new THREE.Mesh( geometry, material );
 
-		mesh.onBeforeRender = function ( renderer, scene, camera, geometry, material, group ) {
+		mesh.onBeforeRender = function ( renderer, scene, camera, geometry, material ) {
 
 			material.uniforms.samplerColor.value = _compColor.renderTarget2.texture;
 
@@ -840,7 +840,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 	}
 
-	function updateDeferredPointLightUniforms( renderer, scene, camera, geometry, material, group ) {
+	function updateDeferredPointLightUniforms( renderer, scene, camera, geometry, material ) {
 
 		var light = this;
 
@@ -886,7 +886,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 	}
 
-	function updateDeferredSpotLightUniforms( renderer, scene, camera, geometry, material, group ) {
+	function updateDeferredSpotLightUniforms() {
 
 		var light = this;
 
@@ -929,7 +929,7 @@ THREE.WebGLDeferredRenderer = function ( parameters ) {
 
 	}
 
-	function updateDeferredDirectionalLightUniforms( renderer, scene, camera, geometry, material, group ) {
+	function updateDeferredDirectionalLightUniforms() {
 
 		var light = this;
 

+ 148 - 0
examples/js/utils/GeometryUtils.js

@@ -295,6 +295,154 @@ THREE.GeometryUtils = {
 		console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
 		return geometry.center();
 
+	},
+
+	/**
+	 * Generates 2D-Coordinates in a very fast way.
+	 *
+	 * @author Dylan Grafmyre
+	 *
+	 * Based on work by:
+	 * @author Thomas Diewald
+	 * @link http://www.openprocessing.org/sketch/15493
+	 *
+	 * @param center     Center of Hilbert curve.
+	 * @param size       Total width of Hilbert curve.
+	 * @param iterations Number of subdivisions.
+	 * @param v0         Corner index -X, -Z.
+	 * @param v1         Corner index -X, +Z.
+	 * @param v2         Corner index +X, +Z.
+	 * @param v3         Corner index +X, -Z.
+	 */
+	hilbert2D: function ( center, size, iterations, v0, v1, v2, v3 ) {
+
+		// Default Vars
+		var center = center !== undefined ? center : new THREE.Vector3( 0, 0, 0 ),
+			size = size !== undefined ? size : 10,
+			half = size / 2,
+			iterations = iterations !== undefined ? iterations : 1,
+			v0 = v0 !== undefined ? v0 : 0,
+			v1 = v1 !== undefined ? v1 : 1,
+			v2 = v2 !== undefined ? v2 : 2,
+			v3 = v3 !== undefined ? v3 : 3
+		;
+
+		var vec_s = [
+			new THREE.Vector3( center.x - half, center.y, center.z - half ),
+			new THREE.Vector3( center.x - half, center.y, center.z + half ),
+			new THREE.Vector3( center.x + half, center.y, center.z + half ),
+			new THREE.Vector3( center.x + half, center.y, center.z - half )
+		];
+
+		var vec = [
+			vec_s[ v0 ],
+			vec_s[ v1 ],
+			vec_s[ v2 ],
+			vec_s[ v3 ]
+		];
+
+		// Recurse iterations
+		if ( 0 <= -- iterations ) {
+
+			var tmp = [];
+
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert2D( vec[ 0 ], half, iterations, v0, v3, v2, v1 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert2D( vec[ 1 ], half, iterations, v0, v1, v2, v3 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert2D( vec[ 2 ], half, iterations, v0, v1, v2, v3 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert2D( vec[ 3 ], half, iterations, v2, v1, v0, v3 ) );
+
+			// Return recursive call
+			return tmp;
+
+		}
+
+		// Return complete Hilbert Curve.
+		return vec;
+
+	},
+
+	/**
+	 * Generates 3D-Coordinates in a very fast way.
+	 *
+	 * @author Dylan Grafmyre
+	 *
+	 * Based on work by:
+	 * @author Thomas Diewald
+	 * @link http://www.openprocessing.org/visuals/?visualID=15599
+	 *
+	 * @param center     Center of Hilbert curve.
+	 * @param size       Total width of Hilbert curve.
+	 * @param iterations Number of subdivisions.
+	 * @param v0         Corner index -X, +Y, -Z.
+	 * @param v1         Corner index -X, +Y, +Z.
+	 * @param v2         Corner index -X, -Y, +Z.
+	 * @param v3         Corner index -X, -Y, -Z.
+	 * @param v4         Corner index +X, -Y, -Z.
+	 * @param v5         Corner index +X, -Y, +Z.
+	 * @param v6         Corner index +X, +Y, +Z.
+	 * @param v7         Corner index +X, +Y, -Z.
+	 */
+	hilbert3D: function ( center, size, iterations, v0, v1, v2, v3, v4, v5, v6, v7 ) {
+
+		// Default Vars
+		var center = center !== undefined ? center : new THREE.Vector3( 0, 0, 0 ),
+			size = size !== undefined ? size : 10,
+			half = size / 2,
+			iterations = iterations !== undefined ? iterations : 1,
+			v0 = v0 !== undefined ? v0 : 0,
+			v1 = v1 !== undefined ? v1 : 1,
+			v2 = v2 !== undefined ? v2 : 2,
+			v3 = v3 !== undefined ? v3 : 3,
+			v4 = v4 !== undefined ? v4 : 4,
+			v5 = v5 !== undefined ? v5 : 5,
+			v6 = v6 !== undefined ? v6 : 6,
+			v7 = v7 !== undefined ? v7 : 7
+		;
+
+		var vec_s = [
+			new THREE.Vector3( center.x - half, center.y + half, center.z - half ),
+			new THREE.Vector3( center.x - half, center.y + half, center.z + half ),
+			new THREE.Vector3( center.x - half, center.y - half, center.z + half ),
+			new THREE.Vector3( center.x - half, center.y - half, center.z - half ),
+			new THREE.Vector3( center.x + half, center.y - half, center.z - half ),
+			new THREE.Vector3( center.x + half, center.y - half, center.z + half ),
+			new THREE.Vector3( center.x + half, center.y + half, center.z + half ),
+			new THREE.Vector3( center.x + half, center.y + half, center.z - half )
+		];
+
+		var vec = [
+			vec_s[ v0 ],
+			vec_s[ v1 ],
+			vec_s[ v2 ],
+			vec_s[ v3 ],
+			vec_s[ v4 ],
+			vec_s[ v5 ],
+			vec_s[ v6 ],
+			vec_s[ v7 ]
+		];
+
+		// Recurse iterations
+		if ( -- iterations >= 0 ) {
+
+			var tmp = [];
+
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 0 ], half, iterations, v0, v3, v4, v7, v6, v5, v2, v1 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 1 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 2 ], half, iterations, v0, v7, v6, v1, v2, v5, v4, v3 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 3 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 4 ], half, iterations, v2, v3, v0, v1, v6, v7, v4, v5 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 5 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 6 ], half, iterations, v4, v3, v2, v5, v6, v1, v0, v7 ) );
+			Array.prototype.push.apply( tmp, THREE.GeometryUtils.hilbert3D( vec[ 7 ], half, iterations, v6, v5, v2, v1, v0, v3, v4, v7 ) );
+
+			// Return recursive call
+			return tmp;
+
+		}
+
+		// Return complete Hilbert Curve.
+		return vec;
+
 	}
 
 };

+ 3 - 11
examples/js/vr/WebVR.js

@@ -81,7 +81,7 @@ var WEBVR = {
 
 				if ( currentSession === null ) {
 
-					device.requestSession( { immersive: true, exclusive: true /* DEPRECATED */ } ).then( onSessionStarted );
+					navigator.xr.requestSession( 'immersive-vr' ).then( onSessionStarted );
 
 				} else {
 
@@ -91,8 +91,6 @@ var WEBVR = {
 
 			};
 
-			renderer.vr.setDevice( device );
-
 		}
 
 		function showVRNotFound() {
@@ -131,20 +129,14 @@ var WEBVR = {
 
 		}
 
-		if ( 'xr' in navigator && 'requestDevice' in navigator.xr ) {
+		if ( 'xr' in navigator && 'supportsSession' in navigator.xr ) {
 
 			var button = document.createElement( 'button' );
 			button.style.display = 'none';
 
 			stylizeElement( button );
 
-			navigator.xr.requestDevice().then( function ( device ) {
-
-				device.supportsSession( { immersive: true, exclusive: true /* DEPRECATED */ } )
-					.then( function () { showEnterXR( device ); } )
-					.catch( showVRNotFound );
-
-			} ).catch( showVRNotFound );
+			navigator.xr.supportsSession( 'immersive-vr' ).then( showEnterXR );
 
 			return button;
 

+ 16 - 0
examples/jsm/effects/AnaglyphEffect.d.ts

@@ -0,0 +1,16 @@
+import {
+  Camera,
+  Matrix3,
+  Scene,
+  WebGLRenderer
+} from '../../../src/Three';
+
+export class AnaglyphEffect {
+  constructor(renderer: WebGLRenderer, width?: number, height?: number);
+  colorMatrixLeft: Matrix3;
+  colorMatrixRight: Matrix3;
+
+  dispose(): void;
+  render(scene: Scene, camera: Camera): void;
+  setSize(width: number, height: number): void;
+}

+ 181 - 0
examples/jsm/effects/AnaglyphEffect.js

@@ -0,0 +1,181 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author marklundin / http://mark-lundin.com/
+ * @author alteredq / http://alteredqualia.com/
+ * @author tschw
+ */
+
+import {
+	LinearFilter,
+	Matrix3,
+	Mesh,
+	NearestFilter,
+	OrthographicCamera,
+	PlaneBufferGeometry,
+	RGBAFormat,
+	Scene,
+	ShaderMaterial,
+	StereoCamera,
+	WebGLRenderTarget
+} from "../../../build/three.module.js";
+
+var AnaglyphEffect = function ( renderer, width, height ) {
+
+	// Matrices generated with angler.js https://github.com/tschw/angler.js/
+	// (in column-major element order, as accepted by WebGL)
+
+	this.colorMatrixLeft = new Matrix3().fromArray( [
+
+		1.0671679973602295, - 0.0016435992438346148, 0.0001777536963345483, // r out
+		- 0.028107794001698494, - 0.00019593400065787137, - 0.0002875397040043026, // g out
+		- 0.04279090091586113, 0.000015809757314855233, - 0.00024287120322696865 // b out
+
+	] );
+
+	//		red						green 						blue  						in
+
+	this.colorMatrixRight = new Matrix3().fromArray( [
+
+		- 0.0355340838432312, - 0.06440307199954987, 0.018319187685847282, // r out
+		- 0.10269022732973099, 0.8079727292060852, - 0.04835830628871918, // g out
+		0.0001224992738571018, - 0.009558862075209618, 0.567823588848114 // b out
+
+	] );
+
+	var _camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
+
+	var _scene = new Scene();
+
+	var _stereo = new StereoCamera();
+
+	var _params = { minFilter: LinearFilter, magFilter: NearestFilter, format: RGBAFormat };
+
+	if ( width === undefined ) width = 512;
+	if ( height === undefined ) height = 512;
+
+	var _renderTargetL = new WebGLRenderTarget( width, height, _params );
+	var _renderTargetR = new WebGLRenderTarget( width, height, _params );
+
+	var _material = new ShaderMaterial( {
+
+		uniforms: {
+
+			"mapLeft": { value: _renderTargetL.texture },
+			"mapRight": { value: _renderTargetR.texture },
+
+			"colorMatrixLeft": { value: this.colorMatrixLeft },
+			"colorMatrixRight": { value: this.colorMatrixRight }
+
+		},
+
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+			"	vUv = vec2( uv.x, uv.y );",
+			"	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"uniform sampler2D mapLeft;",
+			"uniform sampler2D mapRight;",
+			"varying vec2 vUv;",
+
+			"uniform mat3 colorMatrixLeft;",
+			"uniform mat3 colorMatrixRight;",
+
+			// These functions implement sRGB linearization and gamma correction
+
+			"float lin( float c ) {",
+			"	return c <= 0.04045 ? c * 0.0773993808 :",
+			"			pow( c * 0.9478672986 + 0.0521327014, 2.4 );",
+			"}",
+
+			"vec4 lin( vec4 c ) {",
+			"	return vec4( lin( c.r ), lin( c.g ), lin( c.b ), c.a );",
+			"}",
+
+			"float dev( float c ) {",
+			"	return c <= 0.0031308 ? c * 12.92",
+			"			: pow( c, 0.41666 ) * 1.055 - 0.055;",
+			"}",
+
+
+			"void main() {",
+
+			"	vec2 uv = vUv;",
+
+			"	vec4 colorL = lin( texture2D( mapLeft, uv ) );",
+			"	vec4 colorR = lin( texture2D( mapRight, uv ) );",
+
+			"	vec3 color = clamp(",
+			"			colorMatrixLeft * colorL.rgb +",
+			"			colorMatrixRight * colorR.rgb, 0., 1. );",
+
+			"	gl_FragColor = vec4(",
+			"			dev( color.r ), dev( color.g ), dev( color.b ),",
+			"			max( colorL.a, colorR.a ) );",
+
+			"}"
+
+		].join( "\n" )
+
+	} );
+
+	var _mesh = new Mesh( new PlaneBufferGeometry( 2, 2 ), _material );
+	_scene.add( _mesh );
+
+	this.setSize = function ( width, height ) {
+
+		renderer.setSize( width, height );
+
+		var pixelRatio = renderer.getPixelRatio();
+
+		_renderTargetL.setSize( width * pixelRatio, height * pixelRatio );
+		_renderTargetR.setSize( width * pixelRatio, height * pixelRatio );
+
+	};
+
+	this.render = function ( scene, camera ) {
+
+		var currentRenderTarget = renderer.getRenderTarget();
+
+		scene.updateMatrixWorld();
+
+		if ( camera.parent === null ) camera.updateMatrixWorld();
+
+		_stereo.update( camera );
+
+		renderer.setRenderTarget( _renderTargetL );
+		renderer.clear();
+		renderer.render( scene, _stereo.cameraL );
+
+		renderer.setRenderTarget( _renderTargetR );
+		renderer.clear();
+		renderer.render( scene, _stereo.cameraR );
+
+		renderer.setRenderTarget( null );
+		renderer.render( _scene, _camera );
+
+		renderer.setRenderTarget( currentRenderTarget );
+
+	};
+
+	this.dispose = function () {
+
+		if ( _renderTargetL ) _renderTargetL.dispose();
+		if ( _renderTargetR ) _renderTargetR.dispose();
+		if ( _mesh ) _mesh.geometry.dispose();
+		if ( _material ) _material.dispose();
+
+	};
+
+};
+
+export { AnaglyphEffect };

+ 22 - 0
examples/jsm/effects/AsciiEffect.d.ts

@@ -0,0 +1,22 @@
+import {
+  Camera,
+  Scene,
+  WebGLRenderer
+} from '../../../src/Three';
+
+export interface AsciiEffectOptions {
+  resolution?: number;
+  scale?: number;
+  color?: boolean;
+  alpha?: boolean;
+  block?: boolean;
+  invert?: boolean;
+}
+
+export class AsciiEffect {
+  constructor(renderer: WebGLRenderer, charSet?: string, options?: AsciiEffectOptions);
+  domElement: HTMLElement;
+
+  render(scene: Scene, camera: Camera): void;
+  setSize(width: number, height: number): void;
+}

+ 293 - 0
examples/jsm/effects/AsciiEffect.js

@@ -0,0 +1,293 @@
+/*
+ * @author zz85 / https://github.com/zz85
+ *
+ * Ascii generation is based on http://www.nihilogic.dk/labs/jsascii/
+ * Maybe more about this later with a blog post at http://lab4games.net/zz85/blog
+ *
+ * 16 April 2012 - @blurspline
+ */
+
+
+
+var AsciiEffect = function ( renderer, charSet, options ) {
+
+	// its fun to create one your own!
+
+	charSet = ( charSet === undefined ) ? ' .:-=+*#%@' : charSet;
+
+	// ' .,:;=|iI+hHOE#`$';
+	// darker bolder character set from https://github.com/saw/Canvas-ASCII-Art/
+	// ' .\'`^",:;Il!i~+_-?][}{1)(|/tfjrxnuvczXYUJCLQ0OZmwqpdbkhao*#MW&8%B@$'.split('');
+
+	if ( ! options ) options = {};
+
+	// Some ASCII settings
+
+	var bResolution = ! options[ 'resolution' ] ? 0.15 : options[ 'resolution' ]; // Higher for more details
+	var iScale = ! options[ 'scale' ] ? 1 : options[ 'scale' ];
+	var bColor = ! options[ 'color' ] ? false : options[ 'color' ]; // nice but slows down rendering!
+	var bAlpha = ! options[ 'alpha' ] ? false : options[ 'alpha' ]; // Transparency
+	var bBlock = ! options[ 'block' ] ? false : options[ 'block' ]; // blocked characters. like good O dos
+	var bInvert = ! options[ 'invert' ] ? false : options[ 'invert' ]; // black is white, white is black
+
+	var strResolution = 'low';
+
+	var width, height;
+
+	var domElement = document.createElement( 'div' );
+	domElement.style.cursor = 'default';
+
+	var oAscii = document.createElement( "table" );
+	domElement.appendChild( oAscii );
+
+	var iWidth, iHeight;
+	var oImg;
+
+	this.setSize = function ( w, h ) {
+
+		width = w;
+		height = h;
+
+		renderer.setSize( w, h );
+
+		initAsciiSize();
+
+	};
+
+
+	this.render = function ( scene, camera ) {
+
+		renderer.render( scene, camera );
+		asciifyImage( renderer, oAscii );
+
+	};
+
+	this.domElement = domElement;
+
+
+	// Throw in ascii library from http://www.nihilogic.dk/labs/jsascii/jsascii.js
+
+	/*
+	* jsAscii 0.1
+	* Copyright (c) 2008 Jacob Seidelin, [email protected], http://blog.nihilogic.dk/
+	* MIT License [http://www.nihilogic.dk/licenses/mit-license.txt]
+	*/
+
+	function initAsciiSize() {
+
+		iWidth = Math.round( width * fResolution );
+		iHeight = Math.round( height * fResolution );
+
+		oCanvas.width = iWidth;
+		oCanvas.height = iHeight;
+		// oCanvas.style.display = "none";
+		// oCanvas.style.width = iWidth;
+		// oCanvas.style.height = iHeight;
+
+		oImg = renderer.domElement;
+
+		if ( oImg.style.backgroundColor ) {
+
+			oAscii.rows[ 0 ].cells[ 0 ].style.backgroundColor = oImg.style.backgroundColor;
+			oAscii.rows[ 0 ].cells[ 0 ].style.color = oImg.style.color;
+
+		}
+
+		oAscii.cellSpacing = 0;
+		oAscii.cellPadding = 0;
+
+		var oStyle = oAscii.style;
+		oStyle.display = "inline";
+		oStyle.width = Math.round( iWidth / fResolution * iScale ) + "px";
+		oStyle.height = Math.round( iHeight / fResolution * iScale ) + "px";
+		oStyle.whiteSpace = "pre";
+		oStyle.margin = "0px";
+		oStyle.padding = "0px";
+		oStyle.letterSpacing = fLetterSpacing + "px";
+		oStyle.fontFamily = strFont;
+		oStyle.fontSize = fFontSize + "px";
+		oStyle.lineHeight = fLineHeight + "px";
+		oStyle.textAlign = "left";
+		oStyle.textDecoration = "none";
+
+	}
+
+
+	var aDefaultCharList = ( " .,:;i1tfLCG08@" ).split( "" );
+	var aDefaultColorCharList = ( " CGO08@" ).split( "" );
+	var strFont = "courier new, monospace";
+
+	var oCanvasImg = renderer.domElement;
+
+	var oCanvas = document.createElement( "canvas" );
+	if ( ! oCanvas.getContext ) {
+
+		return;
+
+	}
+
+	var oCtx = oCanvas.getContext( "2d" );
+	if ( ! oCtx.getImageData ) {
+
+		return;
+
+	}
+
+	var aCharList = ( bColor ? aDefaultColorCharList : aDefaultCharList );
+
+	if ( charSet ) aCharList = charSet;
+
+	var fResolution = 0.5;
+
+	switch ( strResolution ) {
+
+		case "low" : 	fResolution = 0.25; break;
+		case "medium" : fResolution = 0.5; break;
+		case "high" : 	fResolution = 1; break;
+
+	}
+
+	if ( bResolution ) fResolution = bResolution;
+
+	// Setup dom
+
+	var fFontSize = ( 2 / fResolution ) * iScale;
+	var fLineHeight = ( 2 / fResolution ) * iScale;
+
+	// adjust letter-spacing for all combinations of scale and resolution to get it to fit the image width.
+
+	var fLetterSpacing = 0;
+
+	if ( strResolution == "low" ) {
+
+		switch ( iScale ) {
+
+			case 1 : fLetterSpacing = - 1; break;
+			case 2 :
+			case 3 : fLetterSpacing = - 2.1; break;
+			case 4 : fLetterSpacing = - 3.1; break;
+			case 5 : fLetterSpacing = - 4.15; break;
+
+		}
+
+	}
+
+	if ( strResolution == "medium" ) {
+
+		switch ( iScale ) {
+
+			case 1 : fLetterSpacing = 0; break;
+			case 2 : fLetterSpacing = - 1; break;
+			case 3 : fLetterSpacing = - 1.04; break;
+			case 4 :
+			case 5 : fLetterSpacing = - 2.1; break;
+
+		}
+
+	}
+
+	if ( strResolution == "high" ) {
+
+		switch ( iScale ) {
+
+			case 1 :
+			case 2 : fLetterSpacing = 0; break;
+			case 3 :
+			case 4 :
+			case 5 : fLetterSpacing = - 1; break;
+
+		}
+
+	}
+
+
+	// can't get a span or div to flow like an img element, but a table works?
+
+
+	// convert img element to ascii
+
+	function asciifyImage( canvasRenderer, oAscii ) {
+
+		oCtx.clearRect( 0, 0, iWidth, iHeight );
+		oCtx.drawImage( oCanvasImg, 0, 0, iWidth, iHeight );
+		var oImgData = oCtx.getImageData( 0, 0, iWidth, iHeight ).data;
+
+		// Coloring loop starts now
+		var strChars = "";
+
+		// console.time('rendering');
+
+		for ( var y = 0; y < iHeight; y += 2 ) {
+
+			for ( var x = 0; x < iWidth; x ++ ) {
+
+				var iOffset = ( y * iWidth + x ) * 4;
+
+				var iRed = oImgData[ iOffset ];
+				var iGreen = oImgData[ iOffset + 1 ];
+				var iBlue = oImgData[ iOffset + 2 ];
+				var iAlpha = oImgData[ iOffset + 3 ];
+				var iCharIdx;
+
+				var fBrightness;
+
+				fBrightness = ( 0.3 * iRed + 0.59 * iGreen + 0.11 * iBlue ) / 255;
+				// fBrightness = (0.3*iRed + 0.5*iGreen + 0.3*iBlue) / 255;
+
+				if ( iAlpha == 0 ) {
+
+					// should calculate alpha instead, but quick hack :)
+					//fBrightness *= (iAlpha / 255);
+					fBrightness = 1;
+
+				}
+
+				iCharIdx = Math.floor( ( 1 - fBrightness ) * ( aCharList.length - 1 ) );
+
+				if ( bInvert ) {
+
+					iCharIdx = aCharList.length - iCharIdx - 1;
+
+				}
+
+				// good for debugging
+				//fBrightness = Math.floor(fBrightness * 10);
+				//strThisChar = fBrightness;
+
+				var strThisChar = aCharList[ iCharIdx ];
+
+				if ( strThisChar === undefined || strThisChar == " " )
+					strThisChar = "&nbsp;";
+
+				if ( bColor ) {
+
+					strChars += "<span style='"
+						+ "color:rgb(" + iRed + "," + iGreen + "," + iBlue + ");"
+						+ ( bBlock ? "background-color:rgb(" + iRed + "," + iGreen + "," + iBlue + ");" : "" )
+						+ ( bAlpha ? "opacity:" + ( iAlpha / 255 ) + ";" : "" )
+						+ "'>" + strThisChar + "</span>";
+
+				} else {
+
+					strChars += strThisChar;
+
+				}
+
+			}
+			strChars += "<br/>";
+
+		}
+
+		oAscii.innerHTML = "<tr><td>" + strChars + "</td></tr>";
+
+		// console.timeEnd('rendering');
+
+		// return oAscii;
+
+	}
+
+	// end modified asciifyImage block
+
+};
+
+export { AsciiEffect };

+ 36 - 0
examples/jsm/effects/OutlineEffect.d.ts

@@ -0,0 +1,36 @@
+import {
+  Camera,
+  Scene,
+  Vector2,
+  Vector4,
+  WebGLRenderer,
+  WebGLRenderTarget,
+  WebGLShadowMap
+} from '../../../src/Three';
+
+export interface OutlineEffectParameters {
+  defaultThickness?: number;
+  defaultColor?: number[];
+  defaultAlpha?: number;
+  defaultKeepAlive?: boolean;
+}
+
+export class OutlineEffect {
+  constructor(renderer: WebGLRenderer, parameters: OutlineEffectParameters);
+  enabled: boolean;
+  autoClear: boolean;
+  domElement: HTMLElement;
+  shadowMap: WebGLShadowMap;
+
+  clear(color?: boolean, depth?: boolean, stencil?: boolean): void;
+  getPixelRatio(): number;
+  getSize(target: Vector2): Vector2;
+  render(scene: Scene, camera: Camera): void;
+  renderOutline(scene: Scene, camera: Camera): void;
+  setRenderTarget(renderTarget: WebGLRenderTarget | null): void;
+  setPixelRatio(value: number): void;
+  setScissor(x: Vector4 | number, y?: number, width?: number, height?: number): void;
+  setScissorTest(enable: boolean): void;
+  setSize(width: number, height: number, updateStyle?: boolean): void;
+  setViewport(x: Vector4 | number, y?: number, width?: number, height?: number): void;
+}

+ 586 - 0
examples/jsm/effects/OutlineEffect.js

@@ -0,0 +1,586 @@
+/**
+ * @author takahirox / http://github.com/takahirox/
+ *
+ * Reference: https://en.wikipedia.org/wiki/Cel_shading
+ *
+ * API
+ *
+ * 1. Traditional
+ *
+ * var effect = new OutlineEffect( renderer );
+ *
+ * function render() {
+ *
+ * 	effect.render( scene, camera );
+ *
+ * }
+ *
+ * 2. VR compatible
+ *
+ * var effect = new OutlineEffect( renderer );
+ * var renderingOutline = false;
+ *
+ * scene.onAfterRender = function () {
+ *
+ * 	if ( renderingOutline ) return;
+ *
+ * 	renderingOutline = true;
+ *
+ * 	effect.renderOutline( scene, camera );
+ *
+ * 	renderingOutline = false;
+ *
+ * };
+ *
+ * function render() {
+ *
+ * 	renderer.render( scene, camera );
+ *
+ * }
+ *
+ * // How to set default outline parameters
+ * new OutlineEffect( renderer, {
+ * 	defaultThickness: 0.01,
+ * 	defaultColor: [ 0, 0, 0 ],
+ * 	defaultAlpha: 0.8,
+ * 	defaultKeepAlive: true // keeps outline material in cache even if material is removed from scene
+ * } );
+ *
+ * // How to set outline parameters for each material
+ * material.userData.outlineParameters = {
+ * 	thickness: 0.01,
+ * 	color: [ 0, 0, 0 ]
+ * 	alpha: 0.8,
+ * 	visible: true,
+ * 	keepAlive: true
+ * };
+ *
+ * TODO
+ *  - support shader material without objectNormal in its vertexShader
+ */
+
+import {
+	BackSide,
+	Color,
+	ShaderLib,
+	ShaderMaterial
+} from "../../../build/three.module.js";
+
+var OutlineEffect = function ( renderer, parameters ) {
+
+	parameters = parameters || {};
+
+	this.enabled = true;
+
+	var defaultThickness = parameters.defaultThickness !== undefined ? parameters.defaultThickness : 0.003;
+	var defaultColor = new Color().fromArray( parameters.defaultColor !== undefined ? parameters.defaultColor : [ 0, 0, 0 ] );
+	var defaultAlpha = parameters.defaultAlpha !== undefined ? parameters.defaultAlpha : 1.0;
+	var defaultKeepAlive = parameters.defaultKeepAlive !== undefined ? parameters.defaultKeepAlive : false;
+
+	// object.material.uuid -> outlineMaterial or
+	// object.material[ n ].uuid -> outlineMaterial
+	// save at the outline material creation and release
+	// if it's unused removeThresholdCount frames
+	// unless keepAlive is true.
+	var cache = {};
+
+	var removeThresholdCount = 60;
+
+	// outlineMaterial.uuid -> object.material or
+	// outlineMaterial.uuid -> object.material[ n ]
+	// save before render and release after render.
+	var originalMaterials = {};
+
+	// object.uuid -> originalOnBeforeRender
+	// save before render and release after render.
+	var originalOnBeforeRenders = {};
+
+	//this.cache = cache;  // for debug
+
+	// copied from WebGLPrograms and removed some materials
+	var shaderIDs = {
+		MeshBasicMaterial: 'basic',
+		MeshLambertMaterial: 'lambert',
+		MeshPhongMaterial: 'phong',
+		MeshToonMaterial: 'phong',
+		MeshStandardMaterial: 'physical',
+		MeshPhysicalMaterial: 'physical'
+	};
+
+	var uniformsChunk = {
+		outlineThickness: { value: defaultThickness },
+		outlineColor: { value: defaultColor },
+		outlineAlpha: { value: defaultAlpha }
+	};
+
+	var vertexShaderChunk = [
+
+		"uniform float outlineThickness;",
+
+		"vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {",
+
+		"	float thickness = outlineThickness;",
+		"	const float ratio = 1.0;", // TODO: support outline thickness ratio for each vertex
+		"	vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );",
+		// NOTE: subtract pos2 from pos because BackSide objectNormal is negative
+		"	vec4 norm = normalize( pos - pos2 );",
+		"	return pos + norm * thickness * pos.w * ratio;",
+
+		"}"
+
+	].join( "\n" );
+
+	var vertexShaderChunk2 = [
+
+		"#if ! defined( LAMBERT ) && ! defined( PHONG ) && ! defined( TOON ) && ! defined( PHYSICAL )",
+		"	#ifndef USE_ENVMAP",
+		"		vec3 objectNormal = normalize( normal );",
+		"	#endif",
+		"#endif",
+
+		"#ifdef FLIP_SIDED",
+		"	objectNormal = -objectNormal;",
+		"#endif",
+
+		"#ifdef DECLARE_TRANSFORMED",
+		"	vec3 transformed = vec3( position );",
+		"#endif",
+
+		"gl_Position = calculateOutline( gl_Position, objectNormal, vec4( transformed, 1.0 ) );",
+
+		"#include <fog_vertex>"
+
+	].join( "\n" );
+
+	var fragmentShader = [
+
+		"#include <common>",
+		"#include <fog_pars_fragment>",
+
+		"uniform vec3 outlineColor;",
+		"uniform float outlineAlpha;",
+
+		"void main() {",
+
+		"	gl_FragColor = vec4( outlineColor, outlineAlpha );",
+
+		"	#include <fog_fragment>",
+
+		"}"
+
+	].join( "\n" );
+
+	function createInvisibleMaterial() {
+
+		return new ShaderMaterial( { name: 'invisible', visible: false } );
+
+	}
+
+	function createMaterial( originalMaterial ) {
+
+		var shaderID = shaderIDs[ originalMaterial.type ];
+		var originalUniforms, originalVertexShader;
+
+		if ( shaderID !== undefined ) {
+
+			var shader = ShaderLib[ shaderID ];
+			originalUniforms = shader.uniforms;
+			originalVertexShader = shader.vertexShader;
+
+		} else if ( originalMaterial.isRawShaderMaterial === true ) {
+
+			originalUniforms = originalMaterial.uniforms;
+			originalVertexShader = originalMaterial.vertexShader;
+
+			if ( ! /attribute\s+vec3\s+position\s*;/.test( originalVertexShader ) ||
+			     ! /attribute\s+vec3\s+normal\s*;/.test( originalVertexShader ) ) {
+
+				console.warn( 'THREE.OutlineEffect requires both vec3 position and normal attributes in vertex shader, ' +
+				              'does not draw outline for ' + originalMaterial.name + '(uuid:' + originalMaterial.uuid + ') material.' );
+
+				return createInvisibleMaterial();
+
+			}
+
+		} else if ( originalMaterial.isShaderMaterial === true ) {
+
+			originalUniforms = originalMaterial.uniforms;
+			originalVertexShader = originalMaterial.vertexShader;
+
+		} else {
+
+			return createInvisibleMaterial();
+
+		}
+
+		var uniforms = Object.assign( {}, originalUniforms, uniformsChunk );
+
+		var vertexShader = originalVertexShader
+			// put vertexShaderChunk right before "void main() {...}"
+			.replace( /void\s+main\s*\(\s*\)/, vertexShaderChunk + '\nvoid main()' )
+			// put vertexShaderChunk2 the end of "void main() {...}"
+			// Note: here assums originalVertexShader ends with "}" of "void main() {...}"
+			.replace( /\}\s*$/, vertexShaderChunk2 + '\n}' )
+			// remove any light related lines
+			// Note: here is very sensitive to originalVertexShader
+			// TODO: consider safer way
+			.replace( /#include\s+<[\w_]*light[\w_]*>/g, '' );
+
+		var defines = {};
+
+		if ( ! /vec3\s+transformed\s*=/.test( originalVertexShader ) &&
+		     ! /#include\s+<begin_vertex>/.test( originalVertexShader ) ) defines.DECLARE_TRANSFORMED = true;
+
+		return new ShaderMaterial( {
+			defines: defines,
+			uniforms: uniforms,
+			vertexShader: vertexShader,
+			fragmentShader: fragmentShader,
+			side: BackSide,
+			//wireframe: true,
+			skinning: false,
+			morphTargets: false,
+			morphNormals: false,
+			fog: false
+		} );
+
+	}
+
+	function getOutlineMaterialFromCache( originalMaterial ) {
+
+		var data = cache[ originalMaterial.uuid ];
+
+		if ( data === undefined ) {
+
+			data = {
+				material: createMaterial( originalMaterial ),
+				used: true,
+				keepAlive: defaultKeepAlive,
+				count: 0
+			};
+
+			cache[ originalMaterial.uuid ] = data;
+
+		}
+
+		data.used = true;
+
+		return data.material;
+
+	}
+
+	function getOutlineMaterial( originalMaterial ) {
+
+		var outlineMaterial = getOutlineMaterialFromCache( originalMaterial );
+
+		originalMaterials[ outlineMaterial.uuid ] = originalMaterial;
+
+		updateOutlineMaterial( outlineMaterial, originalMaterial );
+
+		return outlineMaterial;
+
+	}
+
+	function setOutlineMaterial( object ) {
+
+		if ( object.material === undefined ) return;
+
+		if ( Array.isArray( object.material ) ) {
+
+			for ( var i = 0, il = object.material.length; i < il; i ++ ) {
+
+				object.material[ i ] = getOutlineMaterial( object.material[ i ] );
+
+			}
+
+		} else {
+
+			object.material = getOutlineMaterial( object.material );
+
+		}
+
+		originalOnBeforeRenders[ object.uuid ] = object.onBeforeRender;
+		object.onBeforeRender = onBeforeRender;
+
+	}
+
+	function restoreOriginalMaterial( object ) {
+
+		if ( object.material === undefined ) return;
+
+		if ( Array.isArray( object.material ) ) {
+
+			for ( var i = 0, il = object.material.length; i < il; i ++ ) {
+
+				object.material[ i ] = originalMaterials[ object.material[ i ].uuid ];
+
+			}
+
+		} else {
+
+			object.material = originalMaterials[ object.material.uuid ];
+
+		}
+
+		object.onBeforeRender = originalOnBeforeRenders[ object.uuid ];
+
+	}
+
+	function onBeforeRender( renderer, scene, camera, geometry, material ) {
+
+		var originalMaterial = originalMaterials[ material.uuid ];
+
+		// just in case
+		if ( originalMaterial === undefined ) return;
+
+		updateUniforms( material, originalMaterial );
+
+	}
+
+	function updateUniforms( material, originalMaterial ) {
+
+		var outlineParameters = originalMaterial.userData.outlineParameters;
+
+		material.uniforms.outlineAlpha.value = originalMaterial.opacity;
+
+		if ( outlineParameters !== undefined ) {
+
+			if ( outlineParameters.thickness !== undefined ) material.uniforms.outlineThickness.value = outlineParameters.thickness;
+			if ( outlineParameters.color !== undefined ) material.uniforms.outlineColor.value.fromArray( outlineParameters.color );
+			if ( outlineParameters.alpha !== undefined ) material.uniforms.outlineAlpha.value = outlineParameters.alpha;
+
+		}
+
+	}
+
+	function updateOutlineMaterial( material, originalMaterial ) {
+
+		if ( material.name === 'invisible' ) return;
+
+		var outlineParameters = originalMaterial.userData.outlineParameters;
+
+		material.skinning = originalMaterial.skinning;
+		material.morphTargets = originalMaterial.morphTargets;
+		material.morphNormals = originalMaterial.morphNormals;
+		material.fog = originalMaterial.fog;
+
+		if ( outlineParameters !== undefined ) {
+
+			if ( originalMaterial.visible === false ) {
+
+				material.visible = false;
+
+			} else {
+
+				material.visible = ( outlineParameters.visible !== undefined ) ? outlineParameters.visible : true;
+
+			}
+
+			material.transparent = ( outlineParameters.alpha !== undefined && outlineParameters.alpha < 1.0 ) ? true : originalMaterial.transparent;
+
+			if ( outlineParameters.keepAlive !== undefined ) cache[ originalMaterial.uuid ].keepAlive = outlineParameters.keepAlive;
+
+		} else {
+
+			material.transparent = originalMaterial.transparent;
+			material.visible = originalMaterial.visible;
+
+		}
+
+		if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false;
+
+	}
+
+	function cleanupCache() {
+
+		var keys;
+
+		// clear originialMaterials
+		keys = Object.keys( originalMaterials );
+
+		for ( var i = 0, il = keys.length; i < il; i ++ ) {
+
+			originalMaterials[ keys[ i ] ] = undefined;
+
+		}
+
+		// clear originalOnBeforeRenders
+		keys = Object.keys( originalOnBeforeRenders );
+
+		for ( var i = 0, il = keys.length; i < il; i ++ ) {
+
+			originalOnBeforeRenders[ keys[ i ] ] = undefined;
+
+		}
+
+		// remove unused outlineMaterial from cache
+		keys = Object.keys( cache );
+
+		for ( var i = 0, il = keys.length; i < il; i ++ ) {
+
+			var key = keys[ i ];
+
+			if ( cache[ key ].used === false ) {
+
+				cache[ key ].count ++;
+
+				if ( cache[ key ].keepAlive === false && cache[ key ].count > removeThresholdCount ) {
+
+					delete cache[ key ];
+
+				}
+
+			} else {
+
+				cache[ key ].used = false;
+				cache[ key ].count = 0;
+
+			}
+
+		}
+
+	}
+
+	this.render = function ( scene, camera ) {
+
+		var renderTarget;
+		var forceClear = false;
+
+		if ( arguments[ 2 ] !== undefined ) {
+
+			console.warn( 'THREE.OutlineEffect.render(): the renderTarget argument has been removed. Use .setRenderTarget() instead.' );
+			renderTarget = arguments[ 2 ];
+
+		}
+
+		if ( arguments[ 3 ] !== undefined ) {
+
+			console.warn( 'THREE.OutlineEffect.render(): the forceClear argument has been removed. Use .clear() instead.' );
+			forceClear = arguments[ 3 ];
+
+		}
+
+		if ( renderTarget !== undefined ) renderer.setRenderTarget( renderTarget );
+
+		if ( forceClear ) renderer.clear();
+
+		if ( this.enabled === false ) {
+
+			renderer.render( scene, camera );
+			return;
+
+		}
+
+		var currentAutoClear = renderer.autoClear;
+		renderer.autoClear = this.autoClear;
+
+		renderer.render( scene, camera );
+
+		renderer.autoClear = currentAutoClear;
+
+		this.renderOutline( scene, camera );
+
+	};
+
+	this.renderOutline = function ( scene, camera ) {
+
+		var currentAutoClear = renderer.autoClear;
+		var currentSceneAutoUpdate = scene.autoUpdate;
+		var currentSceneBackground = scene.background;
+		var currentShadowMapEnabled = renderer.shadowMap.enabled;
+
+		scene.autoUpdate = false;
+		scene.background = null;
+		renderer.autoClear = false;
+		renderer.shadowMap.enabled = false;
+
+		scene.traverse( setOutlineMaterial );
+
+		renderer.render( scene, camera );
+
+		scene.traverse( restoreOriginalMaterial );
+
+		cleanupCache();
+
+		scene.autoUpdate = currentSceneAutoUpdate;
+		scene.background = currentSceneBackground;
+		renderer.autoClear = currentAutoClear;
+		renderer.shadowMap.enabled = currentShadowMapEnabled;
+
+	};
+
+	/*
+	 * See #9918
+	 *
+	 * The following property copies and wrapper methods enable
+	 * OutlineEffect to be called from other *Effect, like
+	 *
+	 * effect = new StereoEffect( new OutlineEffect( renderer ) );
+	 *
+	 * function render () {
+	 *
+ 	 * 	effect.render( scene, camera );
+	 *
+	 * }
+	 */
+	this.autoClear = renderer.autoClear;
+	this.domElement = renderer.domElement;
+	this.shadowMap = renderer.shadowMap;
+
+	this.clear = function ( color, depth, stencil ) {
+
+		renderer.clear( color, depth, stencil );
+
+	};
+
+	this.getPixelRatio = function () {
+
+		return renderer.getPixelRatio();
+
+	};
+
+	this.setPixelRatio = function ( value ) {
+
+		renderer.setPixelRatio( value );
+
+	};
+
+	this.getSize = function ( target ) {
+
+		return renderer.getSize( target );
+
+	};
+
+	this.setSize = function ( width, height, updateStyle ) {
+
+		renderer.setSize( width, height, updateStyle );
+
+	};
+
+	this.setViewport = function ( x, y, width, height ) {
+
+		renderer.setViewport( x, y, width, height );
+
+	};
+
+	this.setScissor = function ( x, y, width, height ) {
+
+		renderer.setScissor( x, y, width, height );
+
+	};
+
+	this.setScissorTest = function ( boolean ) {
+
+		renderer.setScissorTest( boolean );
+
+	};
+
+	this.setRenderTarget = function ( renderTarget ) {
+
+		renderer.setRenderTarget( renderTarget );
+
+	};
+
+};
+
+export { OutlineEffect };

+ 12 - 0
examples/jsm/effects/ParallaxBarrierEffect.d.ts

@@ -0,0 +1,12 @@
+import {
+  Camera,
+  Scene,
+  WebGLRenderer
+} from '../../../src/Three';
+
+export class ParallaxBarrierEffect {
+  constructor(renderer: WebGLRenderer);
+
+  render(scene: Scene, camera: Camera): void;
+  setSize(width: number, height: number): void;
+}

+ 118 - 0
examples/jsm/effects/ParallaxBarrierEffect.js

@@ -0,0 +1,118 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author marklundin / http://mark-lundin.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+import {
+	LinearFilter,
+	Mesh,
+	NearestFilter,
+	OrthographicCamera,
+	PlaneBufferGeometry,
+	RGBAFormat,
+	Scene,
+	ShaderMaterial,
+	StereoCamera,
+	WebGLRenderTarget
+} from "../../../build/three.module.js";
+
+var ParallaxBarrierEffect = function ( renderer ) {
+
+	var _camera = new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 );
+
+	var _scene = new Scene();
+
+	var _stereo = new StereoCamera();
+
+	var _params = { minFilter: LinearFilter, magFilter: NearestFilter, format: RGBAFormat };
+
+	var _renderTargetL = new WebGLRenderTarget( 512, 512, _params );
+	var _renderTargetR = new WebGLRenderTarget( 512, 512, _params );
+
+	var _material = new ShaderMaterial( {
+
+		uniforms: {
+
+			"mapLeft": { value: _renderTargetL.texture },
+			"mapRight": { value: _renderTargetR.texture }
+
+		},
+
+		vertexShader: [
+
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+			"	vUv = vec2( uv.x, uv.y );",
+			"	gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+			"}"
+
+		].join( "\n" ),
+
+		fragmentShader: [
+
+			"uniform sampler2D mapLeft;",
+			"uniform sampler2D mapRight;",
+			"varying vec2 vUv;",
+
+			"void main() {",
+
+			"	vec2 uv = vUv;",
+
+			"	if ( ( mod( gl_FragCoord.y, 2.0 ) ) > 1.00 ) {",
+
+			"		gl_FragColor = texture2D( mapLeft, uv );",
+
+			"	} else {",
+
+			"		gl_FragColor = texture2D( mapRight, uv );",
+
+			"	}",
+
+			"}"
+
+		].join( "\n" )
+
+	} );
+
+	var mesh = new Mesh( new PlaneBufferGeometry( 2, 2 ), _material );
+	_scene.add( mesh );
+
+	this.setSize = function ( width, height ) {
+
+		renderer.setSize( width, height );
+
+		var pixelRatio = renderer.getPixelRatio();
+
+		_renderTargetL.setSize( width * pixelRatio, height * pixelRatio );
+		_renderTargetR.setSize( width * pixelRatio, height * pixelRatio );
+
+	};
+
+	this.render = function ( scene, camera ) {
+
+		scene.updateMatrixWorld();
+
+		if ( camera.parent === null ) camera.updateMatrixWorld();
+
+		_stereo.update( camera );
+
+		renderer.setRenderTarget( _renderTargetL );
+		renderer.clear();
+		renderer.render( scene, _stereo.cameraL );
+
+		renderer.setRenderTarget( _renderTargetR );
+		renderer.clear();
+		renderer.render( scene, _stereo.cameraR );
+
+		renderer.setRenderTarget( null );
+		renderer.render( _scene, _camera );
+
+	};
+
+};
+
+export { ParallaxBarrierEffect };

+ 14 - 0
examples/jsm/effects/PeppersGhostEffect.d.ts

@@ -0,0 +1,14 @@
+import {
+  Camera,
+  Scene,
+  WebGLRenderer
+} from '../../../src/Three';
+
+export class PeppersGhostEffect {
+  constructor(renderer: WebGLRenderer);
+  cameraDistance: number;
+  reflectFromAbove: boolean;
+
+  render(scene: Scene, camera: Camera): void;
+  setSize(width: number, height: number): void;
+}

+ 151 - 0
examples/jsm/effects/PeppersGhostEffect.js

@@ -0,0 +1,151 @@
+/**
+ * Created by tpowellmeto on 29/10/2015.
+ *
+ * peppers ghost effect based on http://www.instructables.com/id/Reflective-Prism/?ALLSTEPS
+ */
+
+import {
+	PerspectiveCamera,
+	Quaternion,
+	Vector3
+} from "../../../build/three.module.js";
+
+var PeppersGhostEffect = function ( renderer ) {
+
+	var scope = this;
+
+	scope.cameraDistance = 15;
+	scope.reflectFromAbove = false;
+
+	// Internals
+	var _halfWidth, _width, _height;
+
+	var _cameraF = new PerspectiveCamera(); //front
+	var _cameraB = new PerspectiveCamera(); //back
+	var _cameraL = new PerspectiveCamera(); //left
+	var _cameraR = new PerspectiveCamera(); //right
+
+	var _position = new Vector3();
+	var _quaternion = new Quaternion();
+	var _scale = new Vector3();
+
+	// Initialization
+	renderer.autoClear = false;
+
+	this.setSize = function ( width, height ) {
+
+		_halfWidth = width / 2;
+		if ( width < height ) {
+
+			_width = width / 3;
+			_height = width / 3;
+
+		} else {
+
+			_width = height / 3;
+			_height = height / 3;
+
+		}
+		renderer.setSize( width, height );
+
+	};
+
+	this.render = function ( scene, camera ) {
+
+		scene.updateMatrixWorld();
+
+		if ( camera.parent === null ) camera.updateMatrixWorld();
+
+		camera.matrixWorld.decompose( _position, _quaternion, _scale );
+
+		// front
+		_cameraF.position.copy( _position );
+		_cameraF.quaternion.copy( _quaternion );
+		_cameraF.translateZ( scope.cameraDistance );
+		_cameraF.lookAt( scene.position );
+
+		// back
+		_cameraB.position.copy( _position );
+		_cameraB.quaternion.copy( _quaternion );
+		_cameraB.translateZ( - ( scope.cameraDistance ) );
+		_cameraB.lookAt( scene.position );
+		_cameraB.rotation.z += 180 * ( Math.PI / 180 );
+
+		// left
+		_cameraL.position.copy( _position );
+		_cameraL.quaternion.copy( _quaternion );
+		_cameraL.translateX( - ( scope.cameraDistance ) );
+		_cameraL.lookAt( scene.position );
+		_cameraL.rotation.x += 90 * ( Math.PI / 180 );
+
+		// right
+		_cameraR.position.copy( _position );
+		_cameraR.quaternion.copy( _quaternion );
+		_cameraR.translateX( scope.cameraDistance );
+		_cameraR.lookAt( scene.position );
+		_cameraR.rotation.x += 90 * ( Math.PI / 180 );
+
+
+		renderer.clear();
+		renderer.setScissorTest( true );
+
+		renderer.setScissor( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height );
+		renderer.setViewport( _halfWidth - ( _width / 2 ), ( _height * 2 ), _width, _height );
+
+		if ( scope.reflectFromAbove ) {
+
+			renderer.render( scene, _cameraB );
+
+		} else {
+
+			renderer.render( scene, _cameraF );
+
+		}
+
+		renderer.setScissor( _halfWidth - ( _width / 2 ), 0, _width, _height );
+		renderer.setViewport( _halfWidth - ( _width / 2 ), 0, _width, _height );
+
+		if ( scope.reflectFromAbove ) {
+
+			renderer.render( scene, _cameraF );
+
+		} else {
+
+			renderer.render( scene, _cameraB );
+
+		}
+
+		renderer.setScissor( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height );
+		renderer.setViewport( _halfWidth - ( _width / 2 ) - _width, _height, _width, _height );
+
+		if ( scope.reflectFromAbove ) {
+
+			renderer.render( scene, _cameraR );
+
+		} else {
+
+			renderer.render( scene, _cameraL );
+
+		}
+
+		renderer.setScissor( _halfWidth + ( _width / 2 ), _height, _width, _height );
+		renderer.setViewport( _halfWidth + ( _width / 2 ), _height, _width, _height );
+
+		if ( scope.reflectFromAbove ) {
+
+			renderer.render( scene, _cameraL );
+
+		} else {
+
+			renderer.render( scene, _cameraR );
+
+		}
+
+		renderer.setScissorTest( false );
+
+	};
+
+
+};
+
+export { PeppersGhostEffect };

+ 13 - 0
examples/jsm/effects/StereoEffect.d.ts

@@ -0,0 +1,13 @@
+import {
+  Camera,
+  Scene,
+  WebGLRenderer
+} from '../../../src/Three';
+
+export class StereoEffect {
+  constructor(renderer: WebGLRenderer);
+
+  setEyeSeparation(eyeSep: number): void;
+  render(scene: Scene, camera: Camera): void;
+  setSize(width: number, height: number): void;
+}

+ 58 - 0
examples/jsm/effects/StereoEffect.js

@@ -0,0 +1,58 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ * @authod mrdoob / http://mrdoob.com/
+ * @authod arodic / http://aleksandarrodic.com/
+ * @authod fonserbc / http://fonserbc.github.io/
+*/
+
+import {
+	StereoCamera,
+	Vector2
+} from "../../../build/three.module.js";
+
+var StereoEffect = function ( renderer ) {
+
+	var _stereo = new StereoCamera();
+	_stereo.aspect = 0.5;
+	var size = new Vector2();
+
+	this.setEyeSeparation = function ( eyeSep ) {
+
+		_stereo.eyeSep = eyeSep;
+
+	};
+
+	this.setSize = function ( width, height ) {
+
+		renderer.setSize( width, height );
+
+	};
+
+	this.render = function ( scene, camera ) {
+
+		scene.updateMatrixWorld();
+
+		if ( camera.parent === null ) camera.updateMatrixWorld();
+
+		_stereo.update( camera );
+
+		renderer.getSize( size );
+
+		if ( renderer.autoClear ) renderer.clear();
+		renderer.setScissorTest( true );
+
+		renderer.setScissor( 0, 0, size.width / 2, size.height );
+		renderer.setViewport( 0, 0, size.width / 2, size.height );
+		renderer.render( scene, _stereo.cameraL );
+
+		renderer.setScissor( size.width / 2, 0, size.width / 2, size.height );
+		renderer.setViewport( size.width / 2, 0, size.width / 2, size.height );
+		renderer.render( scene, _stereo.cameraR );
+
+		renderer.setScissorTest( false );
+
+	};
+
+};
+
+export { StereoEffect };

+ 7 - 0
examples/jsm/geometries/BoxLineGeometry.d.ts

@@ -0,0 +1,7 @@
+import {
+  BufferGeometry
+} from '../../../src/Three';
+
+export class BoxLineGeometry extends BufferGeometry {
+  constructor(width?: number, height?: number, depth?: number, widthSegments?: number, heightSegments?: number, depthSegments?: number);
+}

+ 74 - 0
examples/jsm/geometries/BoxLineGeometry.js

@@ -0,0 +1,74 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+import {
+	BufferGeometry,
+	Float32BufferAttribute
+} from "../../../build/three.module.js";
+
+var BoxLineGeometry = function ( width, height, depth, widthSegments, heightSegments, depthSegments ) {
+
+	BufferGeometry.call( this );
+
+	width = width || 1;
+	height = height || 1;
+	depth = depth || 1;
+
+	widthSegments = Math.floor( widthSegments ) || 1;
+	heightSegments = Math.floor( heightSegments ) || 1;
+	depthSegments = Math.floor( depthSegments ) || 1;
+
+	var widthHalf = width / 2;
+	var heightHalf = height / 2;
+	var depthHalf = depth / 2;
+
+	var segmentWidth = width / widthSegments;
+	var segmentHeight = height / heightSegments;
+	var segmentDepth = depth / depthSegments;
+
+	var vertices = [];
+
+	var x = - widthHalf, y = - heightHalf, z = - depthHalf;
+
+	for ( var i = 0; i <= widthSegments; i ++ ) {
+
+		vertices.push( x, - heightHalf, - depthHalf, x, heightHalf, - depthHalf );
+		vertices.push( x, heightHalf, - depthHalf, x, heightHalf, depthHalf );
+		vertices.push( x, heightHalf, depthHalf, x, - heightHalf, depthHalf );
+		vertices.push( x, - heightHalf, depthHalf, x, - heightHalf, - depthHalf );
+
+		x += segmentWidth;
+
+	}
+
+	for ( var i = 0; i <= heightSegments; i ++ ) {
+
+		vertices.push( - widthHalf, y, - depthHalf, widthHalf, y, - depthHalf );
+		vertices.push( widthHalf, y, - depthHalf, widthHalf, y, depthHalf );
+		vertices.push( widthHalf, y, depthHalf, - widthHalf, y, depthHalf );
+		vertices.push( - widthHalf, y, depthHalf, - widthHalf, y, - depthHalf );
+
+		y += segmentHeight;
+
+	}
+
+	for ( var i = 0; i <= depthSegments; i ++ ) {
+
+		vertices.push( - widthHalf, - heightHalf, z, - widthHalf, heightHalf, z );
+		vertices.push( - widthHalf, heightHalf, z, widthHalf, heightHalf, z );
+		vertices.push( widthHalf, heightHalf, z, widthHalf, - heightHalf, z );
+		vertices.push( widthHalf, - heightHalf, z, - widthHalf, - heightHalf, z );
+
+		z += segmentDepth;
+
+	}
+
+	this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
+
+};
+
+BoxLineGeometry.prototype = Object.create( BufferGeometry.prototype );
+BoxLineGeometry.prototype.constructor = BoxLineGeometry;
+
+export { BoxLineGeometry };

+ 15 - 0
examples/jsm/geometries/DecalGeometry.d.ts

@@ -0,0 +1,15 @@
+import {
+  BufferGeometry,
+  Euler,
+  Mesh,
+  Vector3
+} from '../../../src/Three';
+
+export class DecalGeometry extends BufferGeometry {
+  constructor(mesh: Mesh, position: Vector3, orientation: Euler, size: Vector3);
+}
+
+export class DecalVertex {
+  constructor(position: Vector3, normal: Vector3);
+  clone(): DecalVertex;
+}

+ 358 - 0
examples/jsm/geometries/DecalGeometry.js

@@ -0,0 +1,358 @@
+/**
+ * @author Mugen87 / https://github.com/Mugen87
+ * @author spite / https://github.com/spite
+ *
+ * You can use this geometry to create a decal mesh, that serves different kinds of purposes.
+ * e.g. adding unique details to models, performing dynamic visual environmental changes or covering seams.
+ *
+ * Constructor parameter:
+ *
+ * mesh — Any mesh object
+ * position — Position of the decal projector
+ * orientation — Orientation of the decal projector
+ * size — Size of the decal projector
+ *
+ * reference: http://blog.wolfire.com/2009/06/how-to-project-decals/
+ *
+ */
+
+import {
+	BufferGeometry,
+	Float32BufferAttribute,
+	Matrix4,
+	Vector3
+} from "../../../build/three.module.js";
+
+var DecalGeometry = function ( mesh, position, orientation, size ) {
+
+	BufferGeometry.call( this );
+
+	// buffers
+
+	var vertices = [];
+	var normals = [];
+	var uvs = [];
+
+	// helpers
+
+	var plane = new Vector3();
+
+	// this matrix represents the transformation of the decal projector
+
+	var projectorMatrix = new Matrix4();
+	projectorMatrix.makeRotationFromEuler( orientation );
+	projectorMatrix.setPosition( position );
+
+	var projectorMatrixInverse = new Matrix4().getInverse( projectorMatrix );
+
+	// generate buffers
+
+	generate();
+
+	// build geometry
+
+	this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
+	this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
+	this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
+
+	function generate() {
+
+		var i;
+		var geometry = new BufferGeometry();
+		var decalVertices = [];
+
+		var vertex = new Vector3();
+		var normal = new Vector3();
+
+		// handle different geometry types
+
+		if ( mesh.geometry.isGeometry ) {
+
+			geometry.fromGeometry( mesh.geometry );
+
+		} else {
+
+			geometry.copy( mesh.geometry );
+
+		}
+
+		var positionAttribute = geometry.attributes.position;
+		var normalAttribute = geometry.attributes.normal;
+
+		// first, create an array of 'DecalVertex' objects
+		// three consecutive 'DecalVertex' objects represent a single face
+		//
+		// this data structure will be later used to perform the clipping
+
+		if ( geometry.index !== null ) {
+
+			// indexed BufferGeometry
+
+			var index = geometry.index;
+
+			for ( i = 0; i < index.count; i ++ ) {
+
+				vertex.fromBufferAttribute( positionAttribute, index.getX( i ) );
+				normal.fromBufferAttribute( normalAttribute, index.getX( i ) );
+
+				pushDecalVertex( decalVertices, vertex, normal );
+
+			}
+
+		} else {
+
+			// non-indexed BufferGeometry
+
+			for ( i = 0; i < positionAttribute.count; i ++ ) {
+
+				vertex.fromBufferAttribute( positionAttribute, i );
+				normal.fromBufferAttribute( normalAttribute, i );
+
+				pushDecalVertex( decalVertices, vertex, normal );
+
+			}
+
+		}
+
+		// second, clip the geometry so that it doesn't extend out from the projector
+
+		decalVertices = clipGeometry( decalVertices, plane.set( 1, 0, 0 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( - 1, 0, 0 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( 0, 1, 0 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( 0, - 1, 0 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, 1 ) );
+		decalVertices = clipGeometry( decalVertices, plane.set( 0, 0, - 1 ) );
+
+		// third, generate final vertices, normals and uvs
+
+		for ( i = 0; i < decalVertices.length; i ++ ) {
+
+			var decalVertex = decalVertices[ i ];
+
+			// create texture coordinates (we are still in projector space)
+
+			uvs.push(
+				0.5 + ( decalVertex.position.x / size.x ),
+				0.5 + ( decalVertex.position.y / size.y )
+			);
+
+			// transform the vertex back to world space
+
+			decalVertex.position.applyMatrix4( projectorMatrix );
+
+			// now create vertex and normal buffer data
+
+			vertices.push( decalVertex.position.x, decalVertex.position.y, decalVertex.position.z );
+			normals.push( decalVertex.normal.x, decalVertex.normal.y, decalVertex.normal.z );
+
+		}
+
+	}
+
+	function pushDecalVertex( decalVertices, vertex, normal ) {
+
+		// transform the vertex to world space, then to projector space
+
+		vertex.applyMatrix4( mesh.matrixWorld );
+		vertex.applyMatrix4( projectorMatrixInverse );
+
+		decalVertices.push( new DecalVertex( vertex.clone(), normal.clone() ) );
+
+	}
+
+	function clipGeometry( inVertices, plane ) {
+
+		var outVertices = [];
+
+		var s = 0.5 * Math.abs( size.dot( plane ) );
+
+		// a single iteration clips one face,
+		// which consists of three consecutive 'DecalVertex' objects
+
+		for ( var i = 0; i < inVertices.length; i += 3 ) {
+
+			var v1Out, v2Out, v3Out, total = 0;
+			var nV1, nV2, nV3, nV4;
+
+			var d1 = inVertices[ i + 0 ].position.dot( plane ) - s;
+			var d2 = inVertices[ i + 1 ].position.dot( plane ) - s;
+			var d3 = inVertices[ i + 2 ].position.dot( plane ) - s;
+
+			v1Out = d1 > 0;
+			v2Out = d2 > 0;
+			v3Out = d3 > 0;
+
+			// calculate, how many vertices of the face lie outside of the clipping plane
+
+			total = ( v1Out ? 1 : 0 ) + ( v2Out ? 1 : 0 ) + ( v3Out ? 1 : 0 );
+
+			switch ( total ) {
+
+				case 0: {
+
+					// the entire face lies inside of the plane, no clipping needed
+
+					outVertices.push( inVertices[ i ] );
+					outVertices.push( inVertices[ i + 1 ] );
+					outVertices.push( inVertices[ i + 2 ] );
+					break;
+
+				}
+
+				case 1: {
+
+					// one vertex lies outside of the plane, perform clipping
+
+					if ( v1Out ) {
+
+						nV1 = inVertices[ i + 1 ];
+						nV2 = inVertices[ i + 2 ];
+						nV3 = clip( inVertices[ i ], nV1, plane, s );
+						nV4 = clip( inVertices[ i ], nV2, plane, s );
+
+					}
+
+					if ( v2Out ) {
+
+						nV1 = inVertices[ i ];
+						nV2 = inVertices[ i + 2 ];
+						nV3 = clip( inVertices[ i + 1 ], nV1, plane, s );
+						nV4 = clip( inVertices[ i + 1 ], nV2, plane, s );
+
+						outVertices.push( nV3 );
+						outVertices.push( nV2.clone() );
+						outVertices.push( nV1.clone() );
+
+						outVertices.push( nV2.clone() );
+						outVertices.push( nV3.clone() );
+						outVertices.push( nV4 );
+						break;
+
+					}
+
+					if ( v3Out ) {
+
+						nV1 = inVertices[ i ];
+						nV2 = inVertices[ i + 1 ];
+						nV3 = clip( inVertices[ i + 2 ], nV1, plane, s );
+						nV4 = clip( inVertices[ i + 2 ], nV2, plane, s );
+
+					}
+
+					outVertices.push( nV1.clone() );
+					outVertices.push( nV2.clone() );
+					outVertices.push( nV3 );
+
+					outVertices.push( nV4 );
+					outVertices.push( nV3.clone() );
+					outVertices.push( nV2.clone() );
+
+					break;
+
+				}
+
+				case 2: {
+
+					// two vertices lies outside of the plane, perform clipping
+
+					if ( ! v1Out ) {
+
+						nV1 = inVertices[ i ].clone();
+						nV2 = clip( nV1, inVertices[ i + 1 ], plane, s );
+						nV3 = clip( nV1, inVertices[ i + 2 ], plane, s );
+						outVertices.push( nV1 );
+						outVertices.push( nV2 );
+						outVertices.push( nV3 );
+
+					}
+
+					if ( ! v2Out ) {
+
+						nV1 = inVertices[ i + 1 ].clone();
+						nV2 = clip( nV1, inVertices[ i + 2 ], plane, s );
+						nV3 = clip( nV1, inVertices[ i ], plane, s );
+						outVertices.push( nV1 );
+						outVertices.push( nV2 );
+						outVertices.push( nV3 );
+
+					}
+
+					if ( ! v3Out ) {
+
+						nV1 = inVertices[ i + 2 ].clone();
+						nV2 = clip( nV1, inVertices[ i ], plane, s );
+						nV3 = clip( nV1, inVertices[ i + 1 ], plane, s );
+						outVertices.push( nV1 );
+						outVertices.push( nV2 );
+						outVertices.push( nV3 );
+
+					}
+
+					break;
+
+				}
+
+				case 3: {
+
+					// the entire face lies outside of the plane, so let's discard the corresponding vertices
+
+					break;
+
+				}
+
+			}
+
+		}
+
+		return outVertices;
+
+	}
+
+	function clip( v0, v1, p, s ) {
+
+		var d0 = v0.position.dot( p ) - s;
+		var d1 = v1.position.dot( p ) - s;
+
+		var s0 = d0 / ( d0 - d1 );
+
+		var v = new DecalVertex(
+			new Vector3(
+				v0.position.x + s0 * ( v1.position.x - v0.position.x ),
+				v0.position.y + s0 * ( v1.position.y - v0.position.y ),
+				v0.position.z + s0 * ( v1.position.z - v0.position.z )
+			),
+			new Vector3(
+				v0.normal.x + s0 * ( v1.normal.x - v0.normal.x ),
+				v0.normal.y + s0 * ( v1.normal.y - v0.normal.y ),
+				v0.normal.z + s0 * ( v1.normal.z - v0.normal.z )
+			)
+		);
+
+		// need to clip more values (texture coordinates)? do it this way:
+		// intersectpoint.value = a.value + s * ( b.value - a.value );
+
+		return v;
+
+	}
+
+};
+
+DecalGeometry.prototype = Object.create( BufferGeometry.prototype );
+DecalGeometry.prototype.constructor = DecalGeometry;
+
+// helper
+
+var DecalVertex = function ( position, normal ) {
+
+	this.position = position;
+	this.normal = normal;
+
+};
+
+DecalVertex.prototype.clone = function () {
+
+	return new this.constructor( this.position.clone(), this.normal.clone() );
+
+};
+
+export { DecalGeometry, DecalVertex };

+ 27 - 0
examples/jsm/geometries/ParametricGeometries.d.ts

@@ -0,0 +1,27 @@
+import {
+  Curve,
+  Vector3
+} from '../../../src/Three';
+
+export namespace ParametricGeometries  {
+  export function klein(v: number, u: number, target: Vector3): Vector3;
+  export function plane(width: number, height: number, target: Vector3): Vector3;
+  export function mobius(u: number, t: number, target: Vector3): Vector3;
+  export function mobius3d(u: number, t: number, target: Vector3): Vector3;
+
+  export class TubeGeometry {
+    constructor(path: Curve<Vector3>, segments?: number, radius?: number, segmentsRadius?: number, closed?: boolean, debug?: boolean);
+  }
+
+  export class TorusKnotGeometry {
+    constructor(radius?: number, tube?: number, segmentsT?: number, segmentsR?: number, p?: number, q?: number);
+  }
+
+  export class SphereGeometry {
+    constructor(size: number, u: number, v): number;
+  }
+
+  export class PlaneGeometry {
+    constructor(width: number, depth: number, segmentsWidth: number, segmentsDepth: number);
+  }
+}

+ 274 - 0
examples/jsm/geometries/ParametricGeometries.js

@@ -0,0 +1,274 @@
+/*
+ * @author zz85
+ *
+ * Experimenting of primitive geometry creation using Surface Parametric equations
+ *
+ */
+
+import {
+	ArrowHelper,
+	Curve,
+	Geometry,
+	Object3D,
+	ParametricGeometry,
+	Vector3
+} from "../../../build/three.module.js";
+
+var ParametricGeometries = {
+
+	klein: function ( v, u, target ) {
+
+		u *= Math.PI;
+		v *= 2 * Math.PI;
+
+		u = u * 2;
+		var x, y, z;
+		if ( u < Math.PI ) {
+
+			x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( u ) * Math.cos( v );
+			z = - 8 * Math.sin( u ) - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( u ) * Math.cos( v );
+
+		} else {
+
+			x = 3 * Math.cos( u ) * ( 1 + Math.sin( u ) ) + ( 2 * ( 1 - Math.cos( u ) / 2 ) ) * Math.cos( v + Math.PI );
+			z = - 8 * Math.sin( u );
+
+		}
+
+		y = - 2 * ( 1 - Math.cos( u ) / 2 ) * Math.sin( v );
+
+		target.set( x, y, z );
+
+	},
+
+	plane: function ( width, height ) {
+
+		return function ( u, v, target ) {
+
+			var x = u * width;
+			var y = 0;
+			var z = v * height;
+
+			target.set( x, y, z );
+
+		};
+
+	},
+
+	mobius: function ( u, t, target ) {
+
+		// flat mobius strip
+		// http://www.wolframalpha.com/input/?i=M%C3%B6bius+strip+parametric+equations&lk=1&a=ClashPrefs_*Surface.MoebiusStrip.SurfaceProperty.ParametricEquations-
+		u = u - 0.5;
+		var v = 2 * Math.PI * t;
+
+		var x, y, z;
+
+		var a = 2;
+
+		x = Math.cos( v ) * ( a + u * Math.cos( v / 2 ) );
+		y = Math.sin( v ) * ( a + u * Math.cos( v / 2 ) );
+		z = u * Math.sin( v / 2 );
+
+		target.set( x, y, z );
+
+	},
+
+	mobius3d: function ( u, t, target ) {
+
+		// volumetric mobius strip
+
+		u *= Math.PI;
+		t *= 2 * Math.PI;
+
+		u = u * 2;
+		var phi = u / 2;
+		var major = 2.25, a = 0.125, b = 0.65;
+
+		var x, y, z;
+
+		x = a * Math.cos( t ) * Math.cos( phi ) - b * Math.sin( t ) * Math.sin( phi );
+		z = a * Math.cos( t ) * Math.sin( phi ) + b * Math.sin( t ) * Math.cos( phi );
+		y = ( major + x ) * Math.sin( u );
+		x = ( major + x ) * Math.cos( u );
+
+		target.set( x, y, z );
+
+	}
+
+};
+
+
+/*********************************************
+ *
+ * Parametric Replacement for TubeGeometry
+ *
+ *********************************************/
+
+ParametricGeometries.TubeGeometry = function ( path, segments, radius, segmentsRadius, closed, debug ) {
+
+	this.path = path;
+	this.segments = segments || 64;
+	this.radius = radius || 1;
+	this.segmentsRadius = segmentsRadius || 8;
+	this.closed = closed || false;
+	if ( debug ) this.debug = new Object3D();
+
+	var scope = this, numpoints = this.segments + 1;
+
+	var frames = path.computeFrenetFrames( segments, closed ),
+		tangents = frames.tangents,
+		normals = frames.normals,
+		binormals = frames.binormals;
+
+	// proxy internals
+
+	this.tangents = tangents;
+	this.normals = normals;
+	this.binormals = binormals;
+
+	var ParametricTube = function ( u, v, target ) {
+
+		v *= 2 * Math.PI;
+
+		var i = u * ( numpoints - 1 );
+		i = Math.floor( i );
+
+		var pos = path.getPointAt( u );
+
+		var tangent = tangents[ i ];
+		var normal = normals[ i ];
+		var binormal = binormals[ i ];
+
+		if ( scope.debug ) {
+
+			scope.debug.add( new ArrowHelper( tangent, pos, radius, 0x0000ff ) );
+			scope.debug.add( new ArrowHelper( normal, pos, radius, 0xff0000 ) );
+			scope.debug.add( new ArrowHelper( binormal, pos, radius, 0x00ff00 ) );
+
+		}
+
+		var cx = - scope.radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
+		var cy = scope.radius * Math.sin( v );
+
+		pos.x += cx * normal.x + cy * binormal.x;
+		pos.y += cx * normal.y + cy * binormal.y;
+		pos.z += cx * normal.z + cy * binormal.z;
+
+		target.copy( pos );
+
+	};
+
+	ParametricGeometry.call( this, ParametricTube, segments, segmentsRadius );
+
+};
+
+ParametricGeometries.TubeGeometry.prototype = Object.create( Geometry.prototype );
+ParametricGeometries.TubeGeometry.prototype.constructor = ParametricGeometries.TubeGeometry;
+
+
+/*********************************************
+  *
+  * Parametric Replacement for TorusKnotGeometry
+  *
+  *********************************************/
+ParametricGeometries.TorusKnotGeometry = function ( radius, tube, segmentsT, segmentsR, p, q ) {
+
+	this.radius = radius || 200;
+	this.tube = tube || 40;
+	this.segmentsT = segmentsT || 64;
+	this.segmentsR = segmentsR || 8;
+	this.p = p || 2;
+	this.q = q || 3;
+
+	function TorusKnotCurve() {
+
+		Curve.call( this );
+
+	}
+
+	TorusKnotCurve.prototype = Object.create( Curve.prototype );
+	TorusKnotCurve.prototype.constructor = TorusKnotCurve;
+
+	TorusKnotCurve.prototype.getPoint = function ( t, optionalTarget ) {
+
+		var point = optionalTarget || new Vector3();
+
+		t *= Math.PI * 2;
+
+		var r = 0.5;
+
+		var x = ( 1 + r * Math.cos( q * t ) ) * Math.cos( p * t );
+		var y = ( 1 + r * Math.cos( q * t ) ) * Math.sin( p * t );
+		var z = r * Math.sin( q * t );
+
+		return point.set( x, y, z ).multiplyScalar( radius );
+
+	};
+
+	var segments = segmentsT;
+	var radiusSegments = segmentsR;
+	var extrudePath = new TorusKnotCurve();
+
+	ParametricGeometries.TubeGeometry.call( this, extrudePath, segments, tube, radiusSegments, true, false );
+
+};
+
+ParametricGeometries.TorusKnotGeometry.prototype = Object.create( Geometry.prototype );
+ParametricGeometries.TorusKnotGeometry.prototype.constructor = ParametricGeometries.TorusKnotGeometry;
+
+
+/*********************************************
+  *
+  * Parametric Replacement for SphereGeometry
+  *
+  *********************************************/
+ParametricGeometries.SphereGeometry = function ( size, u, v ) {
+
+	function sphere( u, v, target ) {
+
+		u *= Math.PI;
+		v *= 2 * Math.PI;
+
+		var x = size * Math.sin( u ) * Math.cos( v );
+		var y = size * Math.sin( u ) * Math.sin( v );
+		var z = size * Math.cos( u );
+
+		target.set( x, y, z );
+
+	}
+
+	ParametricGeometry.call( this, sphere, u, v );
+
+};
+
+ParametricGeometries.SphereGeometry.prototype = Object.create( Geometry.prototype );
+ParametricGeometries.SphereGeometry.prototype.constructor = ParametricGeometries.SphereGeometry;
+
+
+/*********************************************
+  *
+  * Parametric Replacement for PlaneGeometry
+  *
+  *********************************************/
+
+ParametricGeometries.PlaneGeometry = function ( width, depth, segmentsWidth, segmentsDepth ) {
+
+	function plane( u, v, target ) {
+
+		var x = u * width;
+		var y = 0;
+		var z = v * depth;
+
+		target.set( x, y, z );
+
+	}
+
+	ParametricGeometry.call( this, plane, segmentsWidth, segmentsDepth );
+
+};
+
+ParametricGeometries.PlaneGeometry.prototype = Object.create( Geometry.prototype );
+ParametricGeometries.PlaneGeometry.prototype.constructor = ParametricGeometries.PlaneGeometry;
+
+export { ParametricGeometries };

+ 7 - 0
examples/jsm/geometries/TeapotBufferGeometry.d.ts

@@ -0,0 +1,7 @@
+import {
+  BufferGeometry
+} from '../../../src/Three';
+
+export class TeapotBufferGeometry extends BufferGeometry {
+  constructor(size?: number, segments?: number, bottom?: boolean, lid?: boolean, body?: boolean, fitLid?: boolean, blinn?: number);
+}

+ 725 - 0
examples/jsm/geometries/TeapotBufferGeometry.js

@@ -0,0 +1,725 @@
+/**
+ * @author Eric Haines / http://erichaines.com/
+ *
+ * Tessellates the famous Utah teapot database by Martin Newell into triangles.
+ *
+ * Parameters: size = 50, segments = 10, bottom = true, lid = true, body = true,
+ *   fitLid = false, blinn = true
+ *
+ * size is a relative scale: I've scaled the teapot to fit vertically between -1 and 1.
+ * Think of it as a "radius".
+ * segments - number of line segments to subdivide each patch edge;
+ *   1 is possible but gives degenerates, so two is the real minimum.
+ * bottom - boolean, if true (default) then the bottom patches are added. Some consider
+ *   adding the bottom heresy, so set this to "false" to adhere to the One True Way.
+ * lid - to remove the lid and look inside, set to true.
+ * body - to remove the body and leave the lid, set this and "bottom" to false.
+ * fitLid - the lid is a tad small in the original. This stretches it a bit so you can't
+ *   see the teapot's insides through the gap.
+ * blinn - Jim Blinn scaled the original data vertically by dividing by about 1.3 to look
+ *   nicer. If you want to see the original teapot, similar to the real-world model, set
+ *   this to false. True by default.
+ *   See http://en.wikipedia.org/wiki/File:Original_Utah_Teapot.jpg for the original
+ *   real-world teapot (from http://en.wikipedia.org/wiki/Utah_teapot).
+ *
+ * Note that the bottom (the last four patches) is not flat - blame Frank Crow, not me.
+ *
+ * The teapot should normally be rendered as a double sided object, since for some
+ * patches both sides can be seen, e.g., the gap around the lid and inside the spout.
+ *
+ * Segments 'n' determines the number of triangles output.
+ *   Total triangles = 32*2*n*n - 8*n    [degenerates at the top and bottom cusps are deleted]
+ *
+ *   size_factor   # triangles
+ *       1          56
+ *       2         240
+ *       3         552
+ *       4         992
+ *
+ *      10        6320
+ *      20       25440
+ *      30       57360
+ *
+ * Code converted from my ancient SPD software, http://tog.acm.org/resources/SPD/
+ * Created for the Udacity course "Interactive Rendering", http://bit.ly/ericity
+ * Lesson: https://www.udacity.com/course/viewer#!/c-cs291/l-68866048/m-106482448
+ * YouTube video on teapot history: https://www.youtube.com/watch?v=DxMfblPzFNc
+ *
+ * See https://en.wikipedia.org/wiki/Utah_teapot for the history of the teapot
+ *
+ */
+
+import {
+	BufferAttribute,
+	BufferGeometry,
+	Matrix4,
+	Vector3,
+	Vector4
+} from "../../../build/three.module.js";
+
+var TeapotBufferGeometry = function ( size, segments, bottom, lid, body, fitLid, blinn ) {
+
+	// 32 * 4 * 4 Bezier spline patches
+	var teapotPatches = [
+		/*rim*/
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+		3, 16, 17, 18, 7, 19, 20, 21, 11, 22, 23, 24, 15, 25, 26, 27,
+		18, 28, 29, 30, 21, 31, 32, 33, 24, 34, 35, 36, 27, 37, 38, 39,
+		30, 40, 41, 0, 33, 42, 43, 4, 36, 44, 45, 8, 39, 46, 47, 12,
+		/*body*/
+		12, 13, 14, 15, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
+		15, 25, 26, 27, 51, 60, 61, 62, 55, 63, 64, 65, 59, 66, 67, 68,
+		27, 37, 38, 39, 62, 69, 70, 71, 65, 72, 73, 74, 68, 75, 76, 77,
+		39, 46, 47, 12, 71, 78, 79, 48, 74, 80, 81, 52, 77, 82, 83, 56,
+		56, 57, 58, 59, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
+		59, 66, 67, 68, 87, 96, 97, 98, 91, 99, 100, 101, 95, 102, 103, 104,
+		68, 75, 76, 77, 98, 105, 106, 107, 101, 108, 109, 110, 104, 111, 112, 113,
+		77, 82, 83, 56, 107, 114, 115, 84, 110, 116, 117, 88, 113, 118, 119, 92,
+		/*handle*/
+		120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135,
+		123, 136, 137, 120, 127, 138, 139, 124, 131, 140, 141, 128, 135, 142, 143, 132,
+		132, 133, 134, 135, 144, 145, 146, 147, 148, 149, 150, 151, 68, 152, 153, 154,
+		135, 142, 143, 132, 147, 155, 156, 144, 151, 157, 158, 148, 154, 159, 160, 68,
+		/*spout*/
+		161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
+		164, 177, 178, 161, 168, 179, 180, 165, 172, 181, 182, 169, 176, 183, 184, 173,
+		173, 174, 175, 176, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196,
+		176, 183, 184, 173, 188, 197, 198, 185, 192, 199, 200, 189, 196, 201, 202, 193,
+		/*lid*/
+		203, 203, 203, 203, 204, 205, 206, 207, 208, 208, 208, 208, 209, 210, 211, 212,
+		203, 203, 203, 203, 207, 213, 214, 215, 208, 208, 208, 208, 212, 216, 217, 218,
+		203, 203, 203, 203, 215, 219, 220, 221, 208, 208, 208, 208, 218, 222, 223, 224,
+		203, 203, 203, 203, 221, 225, 226, 204, 208, 208, 208, 208, 224, 227, 228, 209,
+		209, 210, 211, 212, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
+		212, 216, 217, 218, 232, 241, 242, 243, 236, 244, 245, 246, 240, 247, 248, 249,
+		218, 222, 223, 224, 243, 250, 251, 252, 246, 253, 254, 255, 249, 256, 257, 258,
+		224, 227, 228, 209, 252, 259, 260, 229, 255, 261, 262, 233, 258, 263, 264, 237,
+		/*bottom*/
+		265, 265, 265, 265, 266, 267, 268, 269, 270, 271, 272, 273, 92, 119, 118, 113,
+		265, 265, 265, 265, 269, 274, 275, 276, 273, 277, 278, 279, 113, 112, 111, 104,
+		265, 265, 265, 265, 276, 280, 281, 282, 279, 283, 284, 285, 104, 103, 102, 95,
+		265, 265, 265, 265, 282, 286, 287, 266, 285, 288, 289, 270, 95, 94, 93, 92
+	];
+
+	var teapotVertices = [
+		1.4, 0, 2.4,
+		1.4, - 0.784, 2.4,
+		0.784, - 1.4, 2.4,
+		0, - 1.4, 2.4,
+		1.3375, 0, 2.53125,
+		1.3375, - 0.749, 2.53125,
+		0.749, - 1.3375, 2.53125,
+		0, - 1.3375, 2.53125,
+		1.4375, 0, 2.53125,
+		1.4375, - 0.805, 2.53125,
+		0.805, - 1.4375, 2.53125,
+		0, - 1.4375, 2.53125,
+		1.5, 0, 2.4,
+		1.5, - 0.84, 2.4,
+		0.84, - 1.5, 2.4,
+		0, - 1.5, 2.4,
+		- 0.784, - 1.4, 2.4,
+		- 1.4, - 0.784, 2.4,
+		- 1.4, 0, 2.4,
+		- 0.749, - 1.3375, 2.53125,
+		- 1.3375, - 0.749, 2.53125,
+		- 1.3375, 0, 2.53125,
+		- 0.805, - 1.4375, 2.53125,
+		- 1.4375, - 0.805, 2.53125,
+		- 1.4375, 0, 2.53125,
+		- 0.84, - 1.5, 2.4,
+		- 1.5, - 0.84, 2.4,
+		- 1.5, 0, 2.4,
+		- 1.4, 0.784, 2.4,
+		- 0.784, 1.4, 2.4,
+		0, 1.4, 2.4,
+		- 1.3375, 0.749, 2.53125,
+		- 0.749, 1.3375, 2.53125,
+		0, 1.3375, 2.53125,
+		- 1.4375, 0.805, 2.53125,
+		- 0.805, 1.4375, 2.53125,
+		0, 1.4375, 2.53125,
+		- 1.5, 0.84, 2.4,
+		- 0.84, 1.5, 2.4,
+		0, 1.5, 2.4,
+		0.784, 1.4, 2.4,
+		1.4, 0.784, 2.4,
+		0.749, 1.3375, 2.53125,
+		1.3375, 0.749, 2.53125,
+		0.805, 1.4375, 2.53125,
+		1.4375, 0.805, 2.53125,
+		0.84, 1.5, 2.4,
+		1.5, 0.84, 2.4,
+		1.75, 0, 1.875,
+		1.75, - 0.98, 1.875,
+		0.98, - 1.75, 1.875,
+		0, - 1.75, 1.875,
+		2, 0, 1.35,
+		2, - 1.12, 1.35,
+		1.12, - 2, 1.35,
+		0, - 2, 1.35,
+		2, 0, 0.9,
+		2, - 1.12, 0.9,
+		1.12, - 2, 0.9,
+		0, - 2, 0.9,
+		- 0.98, - 1.75, 1.875,
+		- 1.75, - 0.98, 1.875,
+		- 1.75, 0, 1.875,
+		- 1.12, - 2, 1.35,
+		- 2, - 1.12, 1.35,
+		- 2, 0, 1.35,
+		- 1.12, - 2, 0.9,
+		- 2, - 1.12, 0.9,
+		- 2, 0, 0.9,
+		- 1.75, 0.98, 1.875,
+		- 0.98, 1.75, 1.875,
+		0, 1.75, 1.875,
+		- 2, 1.12, 1.35,
+		- 1.12, 2, 1.35,
+		0, 2, 1.35,
+		- 2, 1.12, 0.9,
+		- 1.12, 2, 0.9,
+		0, 2, 0.9,
+		0.98, 1.75, 1.875,
+		1.75, 0.98, 1.875,
+		1.12, 2, 1.35,
+		2, 1.12, 1.35,
+		1.12, 2, 0.9,
+		2, 1.12, 0.9,
+		2, 0, 0.45,
+		2, - 1.12, 0.45,
+		1.12, - 2, 0.45,
+		0, - 2, 0.45,
+		1.5, 0, 0.225,
+		1.5, - 0.84, 0.225,
+		0.84, - 1.5, 0.225,
+		0, - 1.5, 0.225,
+		1.5, 0, 0.15,
+		1.5, - 0.84, 0.15,
+		0.84, - 1.5, 0.15,
+		0, - 1.5, 0.15,
+		- 1.12, - 2, 0.45,
+		- 2, - 1.12, 0.45,
+		- 2, 0, 0.45,
+		- 0.84, - 1.5, 0.225,
+		- 1.5, - 0.84, 0.225,
+		- 1.5, 0, 0.225,
+		- 0.84, - 1.5, 0.15,
+		- 1.5, - 0.84, 0.15,
+		- 1.5, 0, 0.15,
+		- 2, 1.12, 0.45,
+		- 1.12, 2, 0.45,
+		0, 2, 0.45,
+		- 1.5, 0.84, 0.225,
+		- 0.84, 1.5, 0.225,
+		0, 1.5, 0.225,
+		- 1.5, 0.84, 0.15,
+		- 0.84, 1.5, 0.15,
+		0, 1.5, 0.15,
+		1.12, 2, 0.45,
+		2, 1.12, 0.45,
+		0.84, 1.5, 0.225,
+		1.5, 0.84, 0.225,
+		0.84, 1.5, 0.15,
+		1.5, 0.84, 0.15,
+		- 1.6, 0, 2.025,
+		- 1.6, - 0.3, 2.025,
+		- 1.5, - 0.3, 2.25,
+		- 1.5, 0, 2.25,
+		- 2.3, 0, 2.025,
+		- 2.3, - 0.3, 2.025,
+		- 2.5, - 0.3, 2.25,
+		- 2.5, 0, 2.25,
+		- 2.7, 0, 2.025,
+		- 2.7, - 0.3, 2.025,
+		- 3, - 0.3, 2.25,
+		- 3, 0, 2.25,
+		- 2.7, 0, 1.8,
+		- 2.7, - 0.3, 1.8,
+		- 3, - 0.3, 1.8,
+		- 3, 0, 1.8,
+		- 1.5, 0.3, 2.25,
+		- 1.6, 0.3, 2.025,
+		- 2.5, 0.3, 2.25,
+		- 2.3, 0.3, 2.025,
+		- 3, 0.3, 2.25,
+		- 2.7, 0.3, 2.025,
+		- 3, 0.3, 1.8,
+		- 2.7, 0.3, 1.8,
+		- 2.7, 0, 1.575,
+		- 2.7, - 0.3, 1.575,
+		- 3, - 0.3, 1.35,
+		- 3, 0, 1.35,
+		- 2.5, 0, 1.125,
+		- 2.5, - 0.3, 1.125,
+		- 2.65, - 0.3, 0.9375,
+		- 2.65, 0, 0.9375,
+		- 2, - 0.3, 0.9,
+		- 1.9, - 0.3, 0.6,
+		- 1.9, 0, 0.6,
+		- 3, 0.3, 1.35,
+		- 2.7, 0.3, 1.575,
+		- 2.65, 0.3, 0.9375,
+		- 2.5, 0.3, 1.125,
+		- 1.9, 0.3, 0.6,
+		- 2, 0.3, 0.9,
+		1.7, 0, 1.425,
+		1.7, - 0.66, 1.425,
+		1.7, - 0.66, 0.6,
+		1.7, 0, 0.6,
+		2.6, 0, 1.425,
+		2.6, - 0.66, 1.425,
+		3.1, - 0.66, 0.825,
+		3.1, 0, 0.825,
+		2.3, 0, 2.1,
+		2.3, - 0.25, 2.1,
+		2.4, - 0.25, 2.025,
+		2.4, 0, 2.025,
+		2.7, 0, 2.4,
+		2.7, - 0.25, 2.4,
+		3.3, - 0.25, 2.4,
+		3.3, 0, 2.4,
+		1.7, 0.66, 0.6,
+		1.7, 0.66, 1.425,
+		3.1, 0.66, 0.825,
+		2.6, 0.66, 1.425,
+		2.4, 0.25, 2.025,
+		2.3, 0.25, 2.1,
+		3.3, 0.25, 2.4,
+		2.7, 0.25, 2.4,
+		2.8, 0, 2.475,
+		2.8, - 0.25, 2.475,
+		3.525, - 0.25, 2.49375,
+		3.525, 0, 2.49375,
+		2.9, 0, 2.475,
+		2.9, - 0.15, 2.475,
+		3.45, - 0.15, 2.5125,
+		3.45, 0, 2.5125,
+		2.8, 0, 2.4,
+		2.8, - 0.15, 2.4,
+		3.2, - 0.15, 2.4,
+		3.2, 0, 2.4,
+		3.525, 0.25, 2.49375,
+		2.8, 0.25, 2.475,
+		3.45, 0.15, 2.5125,
+		2.9, 0.15, 2.475,
+		3.2, 0.15, 2.4,
+		2.8, 0.15, 2.4,
+		0, 0, 3.15,
+		0.8, 0, 3.15,
+		0.8, - 0.45, 3.15,
+		0.45, - 0.8, 3.15,
+		0, - 0.8, 3.15,
+		0, 0, 2.85,
+		0.2, 0, 2.7,
+		0.2, - 0.112, 2.7,
+		0.112, - 0.2, 2.7,
+		0, - 0.2, 2.7,
+		- 0.45, - 0.8, 3.15,
+		- 0.8, - 0.45, 3.15,
+		- 0.8, 0, 3.15,
+		- 0.112, - 0.2, 2.7,
+		- 0.2, - 0.112, 2.7,
+		- 0.2, 0, 2.7,
+		- 0.8, 0.45, 3.15,
+		- 0.45, 0.8, 3.15,
+		0, 0.8, 3.15,
+		- 0.2, 0.112, 2.7,
+		- 0.112, 0.2, 2.7,
+		0, 0.2, 2.7,
+		0.45, 0.8, 3.15,
+		0.8, 0.45, 3.15,
+		0.112, 0.2, 2.7,
+		0.2, 0.112, 2.7,
+		0.4, 0, 2.55,
+		0.4, - 0.224, 2.55,
+		0.224, - 0.4, 2.55,
+		0, - 0.4, 2.55,
+		1.3, 0, 2.55,
+		1.3, - 0.728, 2.55,
+		0.728, - 1.3, 2.55,
+		0, - 1.3, 2.55,
+		1.3, 0, 2.4,
+		1.3, - 0.728, 2.4,
+		0.728, - 1.3, 2.4,
+		0, - 1.3, 2.4,
+		- 0.224, - 0.4, 2.55,
+		- 0.4, - 0.224, 2.55,
+		- 0.4, 0, 2.55,
+		- 0.728, - 1.3, 2.55,
+		- 1.3, - 0.728, 2.55,
+		- 1.3, 0, 2.55,
+		- 0.728, - 1.3, 2.4,
+		- 1.3, - 0.728, 2.4,
+		- 1.3, 0, 2.4,
+		- 0.4, 0.224, 2.55,
+		- 0.224, 0.4, 2.55,
+		0, 0.4, 2.55,
+		- 1.3, 0.728, 2.55,
+		- 0.728, 1.3, 2.55,
+		0, 1.3, 2.55,
+		- 1.3, 0.728, 2.4,
+		- 0.728, 1.3, 2.4,
+		0, 1.3, 2.4,
+		0.224, 0.4, 2.55,
+		0.4, 0.224, 2.55,
+		0.728, 1.3, 2.55,
+		1.3, 0.728, 2.55,
+		0.728, 1.3, 2.4,
+		1.3, 0.728, 2.4,
+		0, 0, 0,
+		1.425, 0, 0,
+		1.425, 0.798, 0,
+		0.798, 1.425, 0,
+		0, 1.425, 0,
+		1.5, 0, 0.075,
+		1.5, 0.84, 0.075,
+		0.84, 1.5, 0.075,
+		0, 1.5, 0.075,
+		- 0.798, 1.425, 0,
+		- 1.425, 0.798, 0,
+		- 1.425, 0, 0,
+		- 0.84, 1.5, 0.075,
+		- 1.5, 0.84, 0.075,
+		- 1.5, 0, 0.075,
+		- 1.425, - 0.798, 0,
+		- 0.798, - 1.425, 0,
+		0, - 1.425, 0,
+		- 1.5, - 0.84, 0.075,
+		- 0.84, - 1.5, 0.075,
+		0, - 1.5, 0.075,
+		0.798, - 1.425, 0,
+		1.425, - 0.798, 0,
+		0.84, - 1.5, 0.075,
+		1.5, - 0.84, 0.075
+	];
+
+	BufferGeometry.call( this );
+
+	size = size || 50;
+
+	// number of segments per patch
+	segments = segments !== undefined ? Math.max( 2, Math.floor( segments ) || 10 ) : 10;
+
+	// which parts should be visible
+	bottom = bottom === undefined ? true : bottom;
+	lid = lid === undefined ? true : lid;
+	body = body === undefined ? true : body;
+
+	// Should the lid be snug? It's not traditional, but we make it snug by default
+	fitLid = fitLid === undefined ? true : fitLid;
+
+	// Jim Blinn scaled the teapot down in size by about 1.3 for
+	// some rendering tests. He liked the new proportions that he kept
+	// the data in this form. The model was distributed with these new
+	// proportions and became the norm. Trivia: comparing images of the
+	// real teapot and the computer model, the ratio for the bowl of the
+	// real teapot is more like 1.25, but since 1.3 is the traditional
+	// value given, we use it here.
+	var blinnScale = 1.3;
+	blinn = blinn === undefined ? true : blinn;
+
+	// scale the size to be the real scaling factor
+	var maxHeight = 3.15 * ( blinn ? 1 : blinnScale );
+
+	var maxHeight2 = maxHeight / 2;
+	var trueSize = size / maxHeight2;
+
+	// Number of elements depends on what is needed. Subtract degenerate
+	// triangles at tip of bottom and lid out in advance.
+	var numTriangles = bottom ? ( 8 * segments - 4 ) * segments : 0;
+	numTriangles += lid ? ( 16 * segments - 4 ) * segments : 0;
+	numTriangles += body ? 40 * segments * segments : 0;
+
+	var indices = new Uint32Array( numTriangles * 3 );
+
+	var numVertices = bottom ? 4 : 0;
+	numVertices += lid ? 8 : 0;
+	numVertices += body ? 20 : 0;
+	numVertices *= ( segments + 1 ) * ( segments + 1 );
+
+	var vertices = new Float32Array( numVertices * 3 );
+	var normals = new Float32Array( numVertices * 3 );
+	var uvs = new Float32Array( numVertices * 2 );
+
+	// Bezier form
+	var ms = new Matrix4();
+	ms.set(
+		- 1.0, 3.0, - 3.0, 1.0,
+		3.0, - 6.0, 3.0, 0.0,
+		- 3.0, 3.0, 0.0, 0.0,
+		1.0, 0.0, 0.0, 0.0 );
+
+	var g = [];
+	var i, r, c;
+
+	var sp = [];
+	var tp = [];
+	var dsp = [];
+	var dtp = [];
+
+	// M * G * M matrix, sort of see
+	// http://www.cs.helsinki.fi/group/goa/mallinnus/curves/surfaces.html
+	var mgm = [];
+
+	var vert = [];
+	var sdir = [];
+	var tdir = [];
+
+	var norm = new Vector3();
+
+	var tcoord;
+
+	var sstep, tstep;
+	var vertPerRow;
+
+	var s, t, sval, tval, p;
+	var dsval = 0;
+	var dtval = 0;
+
+	var normOut = new Vector3();
+	var v1, v2, v3, v4;
+
+	var gmx = new Matrix4();
+	var tmtx = new Matrix4();
+
+	var vsp = new Vector4();
+	var vtp = new Vector4();
+	var vdsp = new Vector4();
+	var vdtp = new Vector4();
+
+	var vsdir = new Vector3();
+	var vtdir = new Vector3();
+
+	var mst = ms.clone();
+	mst.transpose();
+
+	// internal function: test if triangle has any matching vertices;
+	// if so, don't save triangle, since it won't display anything.
+	var notDegenerate = function ( vtx1, vtx2, vtx3 ) {
+
+		// if any vertex matches, return false
+		return ! ( ( ( vertices[ vtx1 * 3 ] === vertices[ vtx2 * 3 ] ) &&
+					 ( vertices[ vtx1 * 3 + 1 ] === vertices[ vtx2 * 3 + 1 ] ) &&
+					 ( vertices[ vtx1 * 3 + 2 ] === vertices[ vtx2 * 3 + 2 ] ) ) ||
+				   ( ( vertices[ vtx1 * 3 ] === vertices[ vtx3 * 3 ] ) &&
+					 ( vertices[ vtx1 * 3 + 1 ] === vertices[ vtx3 * 3 + 1 ] ) &&
+					 ( vertices[ vtx1 * 3 + 2 ] === vertices[ vtx3 * 3 + 2 ] ) ) ||
+				   ( ( vertices[ vtx2 * 3 ] === vertices[ vtx3 * 3 ] ) &&
+					 ( vertices[ vtx2 * 3 + 1 ] === vertices[ vtx3 * 3 + 1 ] ) &&
+					 ( vertices[ vtx2 * 3 + 2 ] === vertices[ vtx3 * 3 + 2 ] ) ) );
+
+	};
+
+
+	for ( i = 0; i < 3; i ++ ) {
+
+		mgm[ i ] = new Matrix4();
+
+	}
+
+	var minPatches = body ? 0 : 20;
+	var maxPatches = bottom ? 32 : 28;
+
+	vertPerRow = segments + 1;
+
+	var surfCount = 0;
+
+	var vertCount = 0;
+	var normCount = 0;
+	var uvCount = 0;
+
+	var indexCount = 0;
+
+	for ( var surf = minPatches; surf < maxPatches; surf ++ ) {
+
+		// lid is in the middle of the data, patches 20-27,
+		// so ignore it for this part of the loop if the lid is not desired
+		if ( lid || ( surf < 20 || surf >= 28 ) ) {
+
+			// get M * G * M matrix for x,y,z
+			for ( i = 0; i < 3; i ++ ) {
+
+				// get control patches
+				for ( r = 0; r < 4; r ++ ) {
+
+					for ( c = 0; c < 4; c ++ ) {
+
+						// transposed
+						g[ c * 4 + r ] = teapotVertices[ teapotPatches[ surf * 16 + r * 4 + c ] * 3 + i ];
+
+						// is the lid to be made larger, and is this a point on the lid
+						// that is X or Y?
+						if ( fitLid && ( surf >= 20 && surf < 28 ) && ( i !== 2 ) ) {
+
+							// increase XY size by 7.7%, found empirically. I don't
+							// increase Z so that the teapot will continue to fit in the
+							// space -1 to 1 for Y (Y is up for the final model).
+							g[ c * 4 + r ] *= 1.077;
+
+						}
+
+						// Blinn "fixed" the teapot by dividing Z by blinnScale, and that's the
+						// data we now use. The original teapot is taller. Fix it:
+						if ( ! blinn && ( i === 2 ) ) {
+
+							g[ c * 4 + r ] *= blinnScale;
+
+						}
+
+					}
+
+				}
+
+				gmx.set( g[ 0 ], g[ 1 ], g[ 2 ], g[ 3 ], g[ 4 ], g[ 5 ], g[ 6 ], g[ 7 ], g[ 8 ], g[ 9 ], g[ 10 ], g[ 11 ], g[ 12 ], g[ 13 ], g[ 14 ], g[ 15 ] );
+
+				tmtx.multiplyMatrices( gmx, ms );
+				mgm[ i ].multiplyMatrices( mst, tmtx );
+
+			}
+
+			// step along, get points, and output
+			for ( sstep = 0; sstep <= segments; sstep ++ ) {
+
+				s = sstep / segments;
+
+				for ( tstep = 0; tstep <= segments; tstep ++ ) {
+
+					t = tstep / segments;
+
+					// point from basis
+					// get power vectors and their derivatives
+					for ( p = 4, sval = tval = 1.0; p --; ) {
+
+						sp[ p ] = sval;
+						tp[ p ] = tval;
+						sval *= s;
+						tval *= t;
+
+						if ( p === 3 ) {
+
+							dsp[ p ] = dtp[ p ] = 0.0;
+							dsval = dtval = 1.0;
+
+						} else {
+
+							dsp[ p ] = dsval * ( 3 - p );
+							dtp[ p ] = dtval * ( 3 - p );
+							dsval *= s;
+							dtval *= t;
+
+						}
+
+					}
+
+					vsp.fromArray( sp );
+					vtp.fromArray( tp );
+					vdsp.fromArray( dsp );
+					vdtp.fromArray( dtp );
+
+					// do for x,y,z
+					for ( i = 0; i < 3; i ++ ) {
+
+						// multiply power vectors times matrix to get value
+						tcoord = vsp.clone();
+						tcoord.applyMatrix4( mgm[ i ] );
+						vert[ i ] = tcoord.dot( vtp );
+
+						// get s and t tangent vectors
+						tcoord = vdsp.clone();
+						tcoord.applyMatrix4( mgm[ i ] );
+						sdir[ i ] = tcoord.dot( vtp );
+
+						tcoord = vsp.clone();
+						tcoord.applyMatrix4( mgm[ i ] );
+						tdir[ i ] = tcoord.dot( vdtp );
+
+					}
+
+					// find normal
+					vsdir.fromArray( sdir );
+					vtdir.fromArray( tdir );
+					norm.crossVectors( vtdir, vsdir );
+					norm.normalize();
+
+					// if X and Z length is 0, at the cusp, so point the normal up or down, depending on patch number
+					if ( vert[ 0 ] === 0 && vert[ 1 ] === 0 ) {
+
+						// if above the middle of the teapot, normal points up, else down
+						normOut.set( 0, vert[ 2 ] > maxHeight2 ? 1 : - 1, 0 );
+
+					} else {
+
+						// standard output: rotate on X axis
+						normOut.set( norm.x, norm.z, - norm.y );
+
+					}
+
+					// store it all
+					vertices[ vertCount ++ ] = trueSize * vert[ 0 ];
+					vertices[ vertCount ++ ] = trueSize * ( vert[ 2 ] - maxHeight2 );
+					vertices[ vertCount ++ ] = - trueSize * vert[ 1 ];
+
+					normals[ normCount ++ ] = normOut.x;
+					normals[ normCount ++ ] = normOut.y;
+					normals[ normCount ++ ] = normOut.z;
+
+					uvs[ uvCount ++ ] = 1 - t;
+					uvs[ uvCount ++ ] = 1 - s;
+
+				}
+
+			}
+
+			// save the faces
+			for ( sstep = 0; sstep < segments; sstep ++ ) {
+
+				for ( tstep = 0; tstep < segments; tstep ++ ) {
+
+					v1 = surfCount * vertPerRow * vertPerRow + sstep * vertPerRow + tstep;
+					v2 = v1 + 1;
+					v3 = v2 + vertPerRow;
+					v4 = v1 + vertPerRow;
+
+					// Normals and UVs cannot be shared. Without clone(), you can see the consequences
+					// of sharing if you call geometry.applyMatrix( matrix ).
+					if ( notDegenerate( v1, v2, v3 ) ) {
+
+						indices[ indexCount ++ ] = v1;
+						indices[ indexCount ++ ] = v2;
+						indices[ indexCount ++ ] = v3;
+
+					}
+					if ( notDegenerate( v1, v3, v4 ) ) {
+
+						indices[ indexCount ++ ] = v1;
+						indices[ indexCount ++ ] = v3;
+						indices[ indexCount ++ ] = v4;
+
+					}
+
+				}
+
+			}
+
+			// increment only if a surface was used
+			surfCount ++;
+
+		}
+
+	}
+
+	this.setIndex( new BufferAttribute( indices, 1 ) );
+	this.addAttribute( 'position', new BufferAttribute( vertices, 3 ) );
+	this.addAttribute( 'normal', new BufferAttribute( normals, 3 ) );
+	this.addAttribute( 'uv', new BufferAttribute( uvs, 2 ) );
+
+	this.computeBoundingSphere();
+
+};
+
+
+TeapotBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
+TeapotBufferGeometry.prototype.constructor = TeapotBufferGeometry;
+
+export { TeapotBufferGeometry };

+ 28 - 135
examples/jsm/loaders/AssimpLoader.js

@@ -19,9 +19,7 @@ import {
 	Skeleton,
 	SkinnedMesh,
 	TextureLoader,
-	Vector2,
-	Vector3,
-	Vector4
+	Vector3
 } from "../../../build/three.module.js";
 
 var AssimpLoader = function ( manager ) {
@@ -381,7 +379,7 @@ AssimpLoader.prototype = {
 		var ASSBIN_MESH_HAS_COLOR_BASE = 0x10000;
 		var AI_MAX_NUMBER_OF_COLOR_SETS = 1;
 		var AI_MAX_NUMBER_OF_TEXTURECOORDS = 4;
-		var aiLightSource_UNDEFINED = 0x0;
+		//var aiLightSource_UNDEFINED = 0x0;
 		//! A directional light source has a well-defined direction
 		//! but is infinitely far away. That's quite a good
 		//! approximation for sun light.
@@ -389,7 +387,7 @@ AssimpLoader.prototype = {
 		//! A point light source has a well-defined position
 		//! in space but no direction - it emits light in all
 		//! directions. A normal bulb is a point light.
-		var aiLightSource_POINT = 0x2;
+		//var aiLightSource_POINT = 0x2;
 		//! A spot light source emits light in a specific
 		//! angle. It has a position and a direction it is pointing to.
 		//! A good example for a spot light is a light spot in
@@ -400,49 +398,49 @@ AssimpLoader.prototype = {
 		//! Typically, there's at most one ambient light in a scene.
 		//! This light type doesn't have a valid position, direction, or
 		//! other properties, just a color.
-		var aiLightSource_AMBIENT = 0x4;
+		//var aiLightSource_AMBIENT = 0x4;
 		/** Flat shading. Shading is done on per-face base,
 		 *  diffuse only. Also known as 'faceted shading'.
 		 */
-		var aiShadingMode_Flat = 0x1;
+		//var aiShadingMode_Flat = 0x1;
 		/** Simple Gouraud shading.
 		 */
-		var aiShadingMode_Gouraud = 0x2;
+		//var aiShadingMode_Gouraud = 0x2;
 		/** Phong-Shading -
 		 */
-		var aiShadingMode_Phong = 0x3;
+		//var aiShadingMode_Phong = 0x3;
 		/** Phong-Blinn-Shading
 		 */
-		var aiShadingMode_Blinn = 0x4;
+		//var aiShadingMode_Blinn = 0x4;
 		/** Toon-Shading per pixel
 		 *
 		 *  Also known as 'comic' shader.
 		 */
-		var aiShadingMode_Toon = 0x5;
+		//var aiShadingMode_Toon = 0x5;
 		/** OrenNayar-Shading per pixel
 		 *
 		 *  Extension to standard Lambertian shading, taking the
 		 *  roughness of the material into account
 		 */
-		var aiShadingMode_OrenNayar = 0x6;
+		//var aiShadingMode_OrenNayar = 0x6;
 		/** Minnaert-Shading per pixel
 		 *
 		 *  Extension to standard Lambertian shading, taking the
 		 *  "darkness" of the material into account
 		 */
-		var aiShadingMode_Minnaert = 0x7;
+		//var aiShadingMode_Minnaert = 0x7;
 		/** CookTorrance-Shading per pixel
 		 *
 		 *  Special shader for metallic surfaces.
 		 */
-		var aiShadingMode_CookTorrance = 0x8;
+		//var aiShadingMode_CookTorrance = 0x8;
 		/** No shading at all. Constant light influence of 1.0.
 		 */
-		var aiShadingMode_NoShading = 0x9;
+		//var aiShadingMode_NoShading = 0x9;
 		/** Fresnel shading
 		 */
-		var aiShadingMode_Fresnel = 0xa;
-		var aiTextureType_NONE = 0x0;
+		//var aiShadingMode_Fresnel = 0xa;
+		//var aiTextureType_NONE = 0x0;
 		/** The texture is combined with the result of the diffuse
 		 *  lighting equation.
 		 */
@@ -450,21 +448,21 @@ AssimpLoader.prototype = {
 		/** The texture is combined with the result of the specular
 		 *  lighting equation.
 		 */
-		var aiTextureType_SPECULAR = 0x2;
+		//var aiTextureType_SPECULAR = 0x2;
 		/** The texture is combined with the result of the ambient
 		 *  lighting equation.
 		 */
-		var aiTextureType_AMBIENT = 0x3;
+		//var aiTextureType_AMBIENT = 0x3;
 		/** The texture is added to the result of the lighting
 		 *  calculation. It isn't influenced by incoming light.
 		 */
-		var aiTextureType_EMISSIVE = 0x4;
+		//var aiTextureType_EMISSIVE = 0x4;
 		/** The texture is a height map.
 		 *
 		 *  By convention, higher gray-scale values stand for
 		 *  higher elevations from the base height.
 		 */
-		var aiTextureType_HEIGHT = 0x5;
+		//var aiTextureType_HEIGHT = 0x5;
 		/** The texture is a (tangent space) normal-map.
 		 *
 		 *  Again, there are several conventions for tangent-space
@@ -479,7 +477,7 @@ AssimpLoader.prototype = {
 		 *  function defined to map the linear color values in the
 		 *  texture to a suitable exponent. Have fun.
 		 */
-		var aiTextureType_SHININESS = 0x7;
+		//var aiTextureType_SHININESS = 0x7;
 		/** The texture defines per-pixel opacity.
 		 *
 		 *  Usually 'white' means opaque and 'black' means
@@ -491,7 +489,7 @@ AssimpLoader.prototype = {
 		 *  The exact purpose and format is application-dependent.
 		 *  Higher color values stand for higher vertex displacements.
 		 */
-		var aiTextureType_DISPLACEMENT = 0x9;
+		//var aiTextureType_DISPLACEMENT = 0x9;
 		/** Lightmap texture (aka Ambient Occlusion)
 		 *
 		 *  Both 'Lightmaps' and dedicated 'ambient occlusion maps' are
@@ -505,14 +503,14 @@ AssimpLoader.prototype = {
 		 * Contains the color of a perfect mirror reflection.
 		 * Rarely used, almost never for real-time applications.
 		 */
-		var aiTextureType_REFLECTION = 0xB;
+		//var aiTextureType_REFLECTION = 0xB;
 		/** Unknown texture
 		 *
 		 *  A texture reference that does not match any of the definitions
 		 *  above is considered to be 'unknown'. It is still imported,
 		 *  but is excluded from any further postprocessing.
 		 */
-		var aiTextureType_UNKNOWN = 0xC;
+		//var aiTextureType_UNKNOWN = 0xC;
 		var BONESPERVERT = 4;
 
 		function ASSBIN_MESH_HAS_TEXCOORD( n ) {
@@ -656,7 +654,7 @@ AssimpLoader.prototype = {
 			];
 			this.mFaces = [];
 			this.mBones = [];
-			this.hookupSkeletons = function ( scene, threeScene ) {
+			this.hookupSkeletons = function ( scene ) {
 
 				if ( this.mBones.length == 0 ) return;
 
@@ -690,7 +688,6 @@ AssimpLoader.prototype = {
 						var skeletonRoot = scene.findNode( this.mBones[ i ].mName );
 						if ( ! skeletonRoot ) return;
 						var threeSkeletonRoot = skeletonRoot.toTHREE( scene );
-						var threeSkeletonRootParent = threeSkeletonRoot.parent;
 						var threeSkeletonRootBone = cloneTreeToBones( threeSkeletonRoot, scene );
 						this.threeNode.add( threeSkeletonRootBone );
 						var bone = findMatchingBone( threeSkeletonRootBone, this.mBones[ i ].mName );
@@ -830,46 +827,6 @@ AssimpLoader.prototype = {
 
 		}
 
-		function aiVector2D() {
-
-			this.x = 0;
-			this.y = 0;
-			this.toTHREE = function () {
-
-				return new Vector2( this.x, this.y );
-
-			};
-
-		}
-
-		function aiVector4D() {
-
-			this.w = 0;
-			this.x = 0;
-			this.y = 0;
-			this.z = 0;
-			this.toTHREE = function () {
-
-				return new Vector4( this.w, this.x, this.y, this.z );
-
-			};
-
-		}
-
-		function aiColor4D() {
-
-			this.r = 0;
-			this.g = 0;
-			this.b = 0;
-			this.a = 0;
-			this.toTHREE = function () {
-
-				return new Color( this.r, this.g, this.b, this.a );
-
-			};
-
-		}
-
 		function aiColor3D() {
 
 			this.r = 0;
@@ -878,7 +835,7 @@ AssimpLoader.prototype = {
 			this.a = 0;
 			this.toTHREE = function () {
 
-				return new Color( this.r, this.g, this.b, 1 );
+				return new Color( this.r, this.g, this.b );
 
 			};
 
@@ -1087,9 +1044,8 @@ AssimpLoader.prototype = {
 			this.mNumAllocated = 0;
 			this.mNumProperties = 0;
 			this.mProperties = [];
-			this.toTHREE = function ( scene ) {
+			this.toTHREE = function () {
 
-				var name = this.mProperties[ 0 ].dataAsString();
 				var mat = new MeshPhongMaterial();
 
 				for ( var i = 0; i < this.mProperties.length; i ++ ) {
@@ -1260,7 +1216,7 @@ AssimpLoader.prototype = {
 
 			};
 
-			this.toTHREE = function ( o, tps ) {
+			this.toTHREE = function ( o ) {
 
 				this.sortKeys();
 				var length = this.getLength();
@@ -1426,7 +1382,7 @@ AssimpLoader.prototype = {
 				var o = this.mRootNode.toTHREE( this );
 
 				for ( var i in this.mMeshes )
-					this.mMeshes[ i ].hookupSkeletons( this, o );
+					this.mMeshes[ i ].hookupSkeletons( this );
 
 				if ( this.mAnimations.length > 0 ) {
 
@@ -1528,26 +1484,6 @@ AssimpLoader.prototype = {
 
 		}
 
-		function Read_aiVector2D( stream ) {
-
-			var v = new aiVector2D();
-			v.x = readFloat( stream );
-			v.y = readFloat( stream );
-			return v;
-
-		}
-
-		function Read_aiVector4D( stream ) {
-
-			var v = new aiVector4D();
-			v.w = readFloat( stream );
-			v.x = readFloat( stream );
-			v.y = readFloat( stream );
-			v.z = readFloat( stream );
-			return v;
-
-		}
-
 		function Read_aiColor3D( stream ) {
 
 			var c = new aiColor3D();
@@ -1558,17 +1494,6 @@ AssimpLoader.prototype = {
 
 		}
 
-		function Read_aiColor4D( stream ) {
-
-			var c = new aiColor4D();
-			c.r = readFloat( stream );
-			c.g = readFloat( stream );
-			c.b = readFloat( stream );
-			c.a = readFloat( stream );
-			return c;
-
-		}
-
 		function Read_aiQuaternion( stream ) {
 
 			var v = new aiQuaternion();
@@ -1634,42 +1559,12 @@ AssimpLoader.prototype = {
 
 		}
 
-		function ReadArray( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read( stream );
-
-		}
-
-		function ReadArray_aiVector2D( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVector2D( stream );
-
-		}
-
-		function ReadArray_aiVector3D( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVector3D( stream );
-
-		}
-
-		function ReadArray_aiVector4D( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVector4D( stream );
-
-		}
-
 		function ReadArray_aiVertexWeight( stream, data, size ) {
 
 			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVertexWeight( stream );
 
 		}
 
-		function ReadArray_aiColor4D( stream, data, size ) {
-
-			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiColor4D( stream );
-
-		}
-
 		function ReadArray_aiVectorKey( stream, data, size ) {
 
 			for ( var i = 0; i < size; i ++ ) data[ i ] = Read_aiVectorKey( stream );
@@ -1908,8 +1803,6 @@ AssimpLoader.prototype = {
 
 				// if there are less than 2^16 vertices, we can simply use 16 bit integers ...
 				mesh.mFaces = [];
-
-				var indexCounter = 0;
 				mesh.mIndexArray = [];
 
 				for ( var i = 0; i < mesh.mNumFaces; ++ i ) {

+ 1 - 1
examples/jsm/loaders/ColladaLoader.d.ts

@@ -12,7 +12,7 @@ export interface Collada {
   scene: Scene;
 }
 
-export class Collada {
+export class ColladaLoader {
   constructor(manager?: LoadingManager);
   manager: LoadingManager;
   crossOrigin: string;

+ 1 - 1
examples/jsm/loaders/GCodeLoader.d.ts

@@ -1,5 +1,5 @@
 import {
-  Group
+  Group,
   LoadingManager
 } from '../../../src/Three';
 

+ 7 - 7
examples/jsm/loaders/SVGLoader.js

@@ -69,37 +69,37 @@ SVGLoader.prototype = {
 
 				case 'path':
 					style = parseStyle( node, style );
-					if ( node.hasAttribute( 'd' ) ) path = parsePathNode( node, style );
+					if ( node.hasAttribute( 'd' ) ) path = parsePathNode( node );
 					break;
 
 				case 'rect':
 					style = parseStyle( node, style );
-					path = parseRectNode( node, style );
+					path = parseRectNode( node );
 					break;
 
 				case 'polygon':
 					style = parseStyle( node, style );
-					path = parsePolygonNode( node, style );
+					path = parsePolygonNode( node );
 					break;
 
 				case 'polyline':
 					style = parseStyle( node, style );
-					path = parsePolylineNode( node, style );
+					path = parsePolylineNode( node );
 					break;
 
 				case 'circle':
 					style = parseStyle( node, style );
-					path = parseCircleNode( node, style );
+					path = parseCircleNode( node );
 					break;
 
 				case 'ellipse':
 					style = parseStyle( node, style );
-					path = parseEllipseNode( node, style );
+					path = parseEllipseNode( node );
 					break;
 
 				case 'line':
 					style = parseStyle( node, style );
-					path = parseLineNode( node, style );
+					path = parseLineNode( node );
 					break;
 
 				default:

+ 25 - 0
examples/jsm/math/ColorConverter.d.ts

@@ -0,0 +1,25 @@
+import {
+  Color
+} from '../../../src/Three';
+
+export interface HSL {
+  h: number;
+  s: number;
+  l: number;
+}
+
+export interface CMYK {
+  c: number;
+  m: number;
+  y: number;
+  k: number;
+}
+
+export namespace ColorConverter {
+
+  export function setHSV(color: Color, h: number, s: number, v: number): Color;
+  export function getHSV(color: Color, target: HSL): HSL;
+  export function setCMYK(color: Color, c: number, m: number, y: number, k: number): Color;
+  export function getCMYK(color: Color, target: CMYK): CMYK;
+
+}

+ 94 - 0
examples/jsm/math/ColorConverter.js

@@ -0,0 +1,94 @@
+/**
+ * @author bhouston / http://exocortex.com/
+ * @author zz85 / http://github.com/zz85
+ */
+
+import {
+	Math as _Math
+} from "../../../build/three.module.js";
+
+var ColorConverter = {
+
+	setHSV: function ( color, h, s, v ) {
+
+		// https://gist.github.com/xpansive/1337890#file-index-js
+
+		h = _Math.euclideanModulo( h, 1 );
+		s = _Math.clamp( s, 0, 1 );
+		v = _Math.clamp( v, 0, 1 );
+
+		return color.setHSL( h, ( s * v ) / ( ( h = ( 2 - s ) * v ) < 1 ? h : ( 2 - h ) ), h * 0.5 );
+
+	},
+
+	getHSV: function () {
+
+		var hsl = {};
+
+		return function getHSV( color, target ) {
+
+			if ( target === undefined ) {
+
+				console.warn( 'THREE.ColorConverter: .getHSV() target is now required' );
+				target = { h: 0, s: 0, l: 0 };
+
+			}
+
+			color.getHSL( hsl );
+
+			// based on https://gist.github.com/xpansive/1337890#file-index-js
+			hsl.s *= ( hsl.l < 0.5 ) ? hsl.l : ( 1 - hsl.l );
+
+			target.h = hsl.h;
+			target.s = 2 * hsl.s / ( hsl.l + hsl.s );
+			target.v = hsl.l + hsl.s;
+
+			return target;
+
+		};
+
+	}(),
+
+	// where c, m, y, k is between 0 and 1
+
+	setCMYK: function ( color, c, m, y, k ) {
+
+		var r = ( 1 - c ) * ( 1 - k );
+		var g = ( 1 - m ) * ( 1 - k );
+		var b = ( 1 - y ) * ( 1 - k );
+
+		return color.setRGB( r, g, b );
+
+	},
+
+	getCMYK: function ( color, target ) {
+
+		if ( target === undefined ) {
+
+			console.warn( 'THREE.ColorConverter: .getCMYK() target is now required' );
+			target = { c: 0, m: 0, y: 0, k: 0 };
+
+		}
+
+		var r = color.r;
+		var g = color.g;
+		var b = color.b;
+
+		var k = 1 - Math.max( r, g, b );
+		var c = ( 1 - r - k ) / ( 1 - k );
+		var m = ( 1 - g - k ) / ( 1 - k );
+		var y = ( 1 - b - k ) / ( 1 - k );
+
+		target.c = c;
+		target.m = m;
+		target.y = y;
+		target.k = k;
+
+		return target;
+
+	}
+
+
+};
+
+export { ColorConverter };

+ 4 - 0
examples/jsm/math/ImprovedNoise.d.ts

@@ -0,0 +1,4 @@
+export class ImprovedNoise {
+  constructor();
+  noise(x: number, y: number, z: number): number;
+}

+ 74 - 0
examples/jsm/math/ImprovedNoise.js

@@ -0,0 +1,74 @@
+// http://mrl.nyu.edu/~perlin/noise/
+
+var ImprovedNoise = function () {
+
+	var p = [ 151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10,
+		 23, 190, 6, 148, 247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33, 88, 237, 149, 56, 87,
+		 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211,
+		 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208,
+		 89, 18, 169, 200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250, 124, 123, 5,
+		 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119,
+		 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232,
+		 178, 185, 112, 104, 218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249,
+		 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205,
+		 93, 222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180 ];
+
+	for ( var i = 0; i < 256; i ++ ) {
+
+		p[ 256 + i ] = p[ i ];
+
+	}
+
+	function fade( t ) {
+
+		return t * t * t * ( t * ( t * 6 - 15 ) + 10 );
+
+	}
+
+	function lerp( t, a, b ) {
+
+		return a + t * ( b - a );
+
+	}
+
+	function grad( hash, x, y, z ) {
+
+		var h = hash & 15;
+		var u = h < 8 ? x : y, v = h < 4 ? y : h == 12 || h == 14 ? x : z;
+		return ( ( h & 1 ) == 0 ? u : - u ) + ( ( h & 2 ) == 0 ? v : - v );
+
+	}
+
+	return {
+
+		noise: function ( x, y, z ) {
+
+			var floorX = Math.floor( x ), floorY = Math.floor( y ), floorZ = Math.floor( z );
+
+			var X = floorX & 255, Y = floorY & 255, Z = floorZ & 255;
+
+			x -= floorX;
+			y -= floorY;
+			z -= floorZ;
+
+			var xMinus1 = x - 1, yMinus1 = y - 1, zMinus1 = z - 1;
+
+			var u = fade( x ), v = fade( y ), w = fade( z );
+
+			var A = p[ X ] + Y, AA = p[ A ] + Z, AB = p[ A + 1 ] + Z, B = p[ X + 1 ] + Y, BA = p[ B ] + Z, BB = p[ B + 1 ] + Z;
+
+			return lerp( w, lerp( v, lerp( u, grad( p[ AA ], x, y, z ),
+				grad( p[ BA ], xMinus1, y, z ) ),
+			lerp( u, grad( p[ AB ], x, yMinus1, z ),
+				grad( p[ BB ], xMinus1, yMinus1, z ) ) ),
+			lerp( v, lerp( u, grad( p[ AA + 1 ], x, y, zMinus1 ),
+				grad( p[ BA + 1 ], xMinus1, y, z - 1 ) ),
+			lerp( u, grad( p[ AB + 1 ], x, yMinus1, zMinus1 ),
+				grad( p[ BB + 1 ], xMinus1, yMinus1, zMinus1 ) ) ) );
+
+		}
+	};
+
+};
+
+export { ImprovedNoise };

+ 29 - 0
examples/jsm/math/Lut.d.ts

@@ -0,0 +1,29 @@
+import {
+  Color
+} from '../../../src/Three';
+
+export class Lut {
+  constructor(colormap?: string, numberofcolors?: number);
+  lut: Color[];
+  map: object[];
+  n: number;
+  minV: number;
+  maxV: number;
+
+  set(value: Lut): this;
+  setMin(min: number): this;
+  setMax(max: number): this;
+  setColorMap(colormap?: string, numberofcolors?: number): this;
+  copy(lut: Lut): this;
+  getColor(alpha: number): Color;
+  addColorMap(colormapName: string, arrayOfColors: number[][]): void;
+  createCanvas(): HTMLCanvasElement;
+  updateCanvas(canvas: HTMLCanvasElement): HTMLCanvasElement;
+}
+
+export interface ColorMapKeywords {
+  rainbow: number[][];
+  cooltowarm: number[][];
+  blackbody: number[][];
+  grayscale: number[][];
+}

+ 191 - 0
examples/jsm/math/Lut.js

@@ -0,0 +1,191 @@
+/**
+ * @author daron1337 / http://daron1337.github.io/
+ */
+
+import {
+	Color
+} from "../../../build/three.module.js";
+
+var Lut = function ( colormap, numberofcolors ) {
+
+	this.lut = [];
+	this.setColorMap( colormap, numberofcolors );
+	return this;
+
+};
+
+Lut.prototype = {
+
+	constructor: Lut,
+
+	lut: [], map: [], n: 256, minV: 0, maxV: 1,
+
+	set: function ( value ) {
+
+		if ( value instanceof Lut ) {
+
+			this.copy( value );
+
+		}
+
+		return this;
+
+	},
+
+	setMin: function ( min ) {
+
+		this.minV = min;
+
+		return this;
+
+	},
+
+	setMax: function ( max ) {
+
+		this.maxV = max;
+
+		return this;
+
+	},
+
+	setColorMap: function ( colormap, numberofcolors ) {
+
+		this.map = ColorMapKeywords[ colormap ] || ColorMapKeywords.rainbow;
+		this.n = numberofcolors || 32;
+
+		var step = 1.0 / this.n;
+
+		this.lut.length = 0;
+		for ( var i = 0; i <= 1; i += step ) {
+
+			for ( var j = 0; j < this.map.length - 1; j ++ ) {
+
+				if ( i >= this.map[ j ][ 0 ] && i < this.map[ j + 1 ][ 0 ] ) {
+
+					var min = this.map[ j ][ 0 ];
+					var max = this.map[ j + 1 ][ 0 ];
+
+					var minColor = new Color( this.map[ j ][ 1 ] );
+					var maxColor = new Color( this.map[ j + 1 ][ 1 ] );
+
+					var color = minColor.lerp( maxColor, ( i - min ) / ( max - min ) );
+
+					this.lut.push( color );
+
+				}
+
+			}
+
+		}
+
+		return this;
+
+	},
+
+	copy: function ( lut ) {
+
+		this.lut = lut.lut;
+		this.map = lut.map;
+		this.n = lut.n;
+		this.minV = lut.minV;
+		this.maxV = lut.maxV;
+
+		return this;
+
+	},
+
+	getColor: function ( alpha ) {
+
+		if ( alpha <= this.minV ) {
+
+			alpha = this.minV;
+
+		} else if ( alpha >= this.maxV ) {
+
+			alpha = this.maxV;
+
+		}
+
+		alpha = ( alpha - this.minV ) / ( this.maxV - this.minV );
+
+		var colorPosition = Math.round( alpha * this.n );
+		colorPosition == this.n ? colorPosition -= 1 : colorPosition;
+
+		return this.lut[ colorPosition ];
+
+	},
+
+	addColorMap: function ( colormapName, arrayOfColors ) {
+
+		ColorMapKeywords[ colormapName ] = arrayOfColors;
+
+	},
+
+	createCanvas: function () {
+
+		var canvas = document.createElement( 'canvas' );
+		canvas.width = 1;
+		canvas.height = this.n;
+
+		this.updateCanvas( canvas );
+
+		return canvas;
+
+	},
+
+	updateCanvas: function ( canvas ) {
+
+		var ctx = canvas.getContext( '2d', { alpha: false } );
+
+		var imageData = ctx.getImageData( 0, 0, 1, this.n );
+
+		var data = imageData.data;
+
+		var k = 0;
+
+		var step = 1.0 / this.n;
+
+		for ( var i = 1; i >= 0; i -= step ) {
+
+			for ( var j = this.map.length - 1; j >= 0; j -- ) {
+
+				if ( i < this.map[ j ][ 0 ] && i >= this.map[ j - 1 ][ 0 ] ) {
+
+					var min = this.map[ j - 1 ][ 0 ];
+					var max = this.map[ j ][ 0 ];
+
+					var minColor = new Color( this.map[ j - 1 ][ 1 ] );
+					var maxColor = new Color( this.map[ j ][ 1 ] );
+
+					var color = minColor.lerp( maxColor, ( i - min ) / ( max - min ) );
+
+					data[ k * 4 ] = Math.round( color.r * 255 );
+					data[ k * 4 + 1 ] = Math.round( color.g * 255 );
+					data[ k * 4 + 2 ] = Math.round( color.b * 255 );
+					data[ k * 4 + 3 ] = 255;
+
+					k += 1;
+
+				}
+
+			}
+
+		}
+
+		ctx.putImageData( imageData, 0, 0 );
+
+		return canvas;
+
+	}
+};
+
+var ColorMapKeywords = {
+
+	"rainbow": [[ 0.0, 0x0000FF ], [ 0.2, 0x00FFFF ], [ 0.5, 0x00FF00 ], [ 0.8, 0xFFFF00 ], [ 1.0, 0xFF0000 ]],
+	"cooltowarm": [[ 0.0, 0x3C4EC2 ], [ 0.2, 0x9BBCFF ], [ 0.5, 0xDCDCDC ], [ 0.8, 0xF6A385 ], [ 1.0, 0xB40426 ]],
+	"blackbody": [[ 0.0, 0x000000 ], [ 0.2, 0x780000 ], [ 0.5, 0xE63200 ], [ 0.8, 0xFFFF00 ], [ 1.0, 0xFFFFFF ]],
+	"grayscale": [[ 0.0, 0x000000 ], [ 0.2, 0x404040 ], [ 0.5, 0x7F7F80 ], [ 0.8, 0xBFBFBF ], [ 1.0, 0xFFFFFF ]]
+
+};
+
+export { Lut, ColorMapKeywords };

+ 9 - 0
examples/jsm/math/SimplexNoise.d.ts

@@ -0,0 +1,9 @@
+export class SimplexNoise {
+  constructor(r?: object);
+  dot(g: number[], x: number, y: number): number;
+  dot3(g: number[], x: number, y: number, z: number): number;
+  dot4(g: number[], x: number, y: number, z: number, w: number): number;
+  noise(xin: number, yin: number): number;
+  noise3d(xin: number, yin: number, zin: number): number;
+  noise4d(x: number, y: number, z: number, w: number): number;
+}

+ 407 - 0
examples/jsm/math/SimplexNoise.js

@@ -0,0 +1,407 @@
+// Ported from Stefan Gustavson's java implementation
+// http://staffwww.itn.liu.se/~stegu/simplexnoise/simplexnoise.pdf
+// Read Stefan's excellent paper for details on how this code works.
+//
+// Sean McCullough [email protected]
+//
+// Added 4D noise
+// Joshua Koo [email protected]
+
+/**
+ * You can pass in a random number generator object if you like.
+ * It is assumed to have a random() method.
+ */
+var SimplexNoise = function ( r ) {
+
+	if ( r == undefined ) r = Math;
+	this.grad3 = [[ 1, 1, 0 ], [ - 1, 1, 0 ], [ 1, - 1, 0 ], [ - 1, - 1, 0 ],
+		[ 1, 0, 1 ], [ - 1, 0, 1 ], [ 1, 0, - 1 ], [ - 1, 0, - 1 ],
+		[ 0, 1, 1 ], [ 0, - 1, 1 ], [ 0, 1, - 1 ], [ 0, - 1, - 1 ]];
+
+	this.grad4 = [[ 0, 1, 1, 1 ], [ 0, 1, 1, - 1 ], [ 0, 1, - 1, 1 ], [ 0, 1, - 1, - 1 ],
+	     [ 0, - 1, 1, 1 ], [ 0, - 1, 1, - 1 ], [ 0, - 1, - 1, 1 ], [ 0, - 1, - 1, - 1 ],
+	     [ 1, 0, 1, 1 ], [ 1, 0, 1, - 1 ], [ 1, 0, - 1, 1 ], [ 1, 0, - 1, - 1 ],
+	     [ - 1, 0, 1, 1 ], [ - 1, 0, 1, - 1 ], [ - 1, 0, - 1, 1 ], [ - 1, 0, - 1, - 1 ],
+	     [ 1, 1, 0, 1 ], [ 1, 1, 0, - 1 ], [ 1, - 1, 0, 1 ], [ 1, - 1, 0, - 1 ],
+	     [ - 1, 1, 0, 1 ], [ - 1, 1, 0, - 1 ], [ - 1, - 1, 0, 1 ], [ - 1, - 1, 0, - 1 ],
+	     [ 1, 1, 1, 0 ], [ 1, 1, - 1, 0 ], [ 1, - 1, 1, 0 ], [ 1, - 1, - 1, 0 ],
+	     [ - 1, 1, 1, 0 ], [ - 1, 1, - 1, 0 ], [ - 1, - 1, 1, 0 ], [ - 1, - 1, - 1, 0 ]];
+
+	this.p = [];
+	for ( var i = 0; i < 256; i ++ ) {
+
+		this.p[ i ] = Math.floor( r.random() * 256 );
+
+	}
+	// To remove the need for index wrapping, double the permutation table length
+	this.perm = [];
+	for ( var i = 0; i < 512; i ++ ) {
+
+		this.perm[ i ] = this.p[ i & 255 ];
+
+	}
+
+	// A lookup table to traverse the simplex around a given point in 4D.
+	// Details can be found where this table is used, in the 4D noise method.
+	this.simplex = [
+		[ 0, 1, 2, 3 ], [ 0, 1, 3, 2 ], [ 0, 0, 0, 0 ], [ 0, 2, 3, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 1, 2, 3, 0 ],
+		[ 0, 2, 1, 3 ], [ 0, 0, 0, 0 ], [ 0, 3, 1, 2 ], [ 0, 3, 2, 1 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 1, 3, 2, 0 ],
+		[ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ],
+		[ 1, 2, 0, 3 ], [ 0, 0, 0, 0 ], [ 1, 3, 0, 2 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 2, 3, 0, 1 ], [ 2, 3, 1, 0 ],
+		[ 1, 0, 2, 3 ], [ 1, 0, 3, 2 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 2, 0, 3, 1 ], [ 0, 0, 0, 0 ], [ 2, 1, 3, 0 ],
+		[ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ],
+		[ 2, 0, 1, 3 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 3, 0, 1, 2 ], [ 3, 0, 2, 1 ], [ 0, 0, 0, 0 ], [ 3, 1, 2, 0 ],
+		[ 2, 1, 0, 3 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 0, 0, 0, 0 ], [ 3, 1, 0, 2 ], [ 0, 0, 0, 0 ], [ 3, 2, 0, 1 ], [ 3, 2, 1, 0 ]];
+
+};
+
+SimplexNoise.prototype.dot = function ( g, x, y ) {
+
+	return g[ 0 ] * x + g[ 1 ] * y;
+
+};
+
+SimplexNoise.prototype.dot3 = function ( g, x, y, z ) {
+
+	return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z;
+
+};
+
+SimplexNoise.prototype.dot4 = function ( g, x, y, z, w ) {
+
+	return g[ 0 ] * x + g[ 1 ] * y + g[ 2 ] * z + g[ 3 ] * w;
+
+};
+
+SimplexNoise.prototype.noise = function ( xin, yin ) {
+
+	var n0, n1, n2; // Noise contributions from the three corners
+	// Skew the input space to determine which simplex cell we're in
+	var F2 = 0.5 * ( Math.sqrt( 3.0 ) - 1.0 );
+	var s = ( xin + yin ) * F2; // Hairy factor for 2D
+	var i = Math.floor( xin + s );
+	var j = Math.floor( yin + s );
+	var G2 = ( 3.0 - Math.sqrt( 3.0 ) ) / 6.0;
+	var t = ( i + j ) * G2;
+	var X0 = i - t; // Unskew the cell origin back to (x,y) space
+	var Y0 = j - t;
+	var x0 = xin - X0; // The x,y distances from the cell origin
+	var y0 = yin - Y0;
+	// For the 2D case, the simplex shape is an equilateral triangle.
+	// Determine which simplex we are in.
+	var i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
+	if ( x0 > y0 ) {
+
+		i1 = 1; j1 = 0;
+
+		// lower triangle, XY order: (0,0)->(1,0)->(1,1)
+
+	}	else {
+
+		i1 = 0; j1 = 1;
+
+	} // upper triangle, YX order: (0,0)->(0,1)->(1,1)
+	// A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
+	// a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
+	// c = (3-sqrt(3))/6
+	var x1 = x0 - i1 + G2; // Offsets for middle corner in (x,y) unskewed coords
+	var y1 = y0 - j1 + G2;
+	var x2 = x0 - 1.0 + 2.0 * G2; // Offsets for last corner in (x,y) unskewed coords
+	var y2 = y0 - 1.0 + 2.0 * G2;
+	// Work out the hashed gradient indices of the three simplex corners
+	var ii = i & 255;
+	var jj = j & 255;
+	var gi0 = this.perm[ ii + this.perm[ jj ] ] % 12;
+	var gi1 = this.perm[ ii + i1 + this.perm[ jj + j1 ] ] % 12;
+	var gi2 = this.perm[ ii + 1 + this.perm[ jj + 1 ] ] % 12;
+	// Calculate the contribution from the three corners
+	var t0 = 0.5 - x0 * x0 - y0 * y0;
+	if ( t0 < 0 ) n0 = 0.0;
+	else {
+
+		t0 *= t0;
+		n0 = t0 * t0 * this.dot( this.grad3[ gi0 ], x0, y0 ); // (x,y) of grad3 used for 2D gradient
+
+	}
+	var t1 = 0.5 - x1 * x1 - y1 * y1;
+	if ( t1 < 0 ) n1 = 0.0;
+	else {
+
+		t1 *= t1;
+		n1 = t1 * t1 * this.dot( this.grad3[ gi1 ], x1, y1 );
+
+	}
+	var t2 = 0.5 - x2 * x2 - y2 * y2;
+	if ( t2 < 0 ) n2 = 0.0;
+	else {
+
+		t2 *= t2;
+		n2 = t2 * t2 * this.dot( this.grad3[ gi2 ], x2, y2 );
+
+	}
+	// Add contributions from each corner to get the final noise value.
+	// The result is scaled to return values in the interval [-1,1].
+	return 70.0 * ( n0 + n1 + n2 );
+
+};
+
+// 3D simplex noise
+SimplexNoise.prototype.noise3d = function ( xin, yin, zin ) {
+
+	var n0, n1, n2, n3; // Noise contributions from the four corners
+	// Skew the input space to determine which simplex cell we're in
+	var F3 = 1.0 / 3.0;
+	var s = ( xin + yin + zin ) * F3; // Very nice and simple skew factor for 3D
+	var i = Math.floor( xin + s );
+	var j = Math.floor( yin + s );
+	var k = Math.floor( zin + s );
+	var G3 = 1.0 / 6.0; // Very nice and simple unskew factor, too
+	var t = ( i + j + k ) * G3;
+	var X0 = i - t; // Unskew the cell origin back to (x,y,z) space
+	var Y0 = j - t;
+	var Z0 = k - t;
+	var x0 = xin - X0; // The x,y,z distances from the cell origin
+	var y0 = yin - Y0;
+	var z0 = zin - Z0;
+	// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
+	// Determine which simplex we are in.
+	var i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
+	var i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
+	if ( x0 >= y0 ) {
+
+		if ( y0 >= z0 ) {
+
+			i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 1; k2 = 0;
+
+			// X Y Z order
+
+		} else if ( x0 >= z0 ) {
+
+			i1 = 1; j1 = 0; k1 = 0; i2 = 1; j2 = 0; k2 = 1;
+
+			// X Z Y order
+
+		} else {
+
+			i1 = 0; j1 = 0; k1 = 1; i2 = 1; j2 = 0; k2 = 1;
+
+		} // Z X Y order
+
+	} else { // x0<y0
+
+		if ( y0 < z0 ) {
+
+			i1 = 0; j1 = 0; k1 = 1; i2 = 0; j2 = 1; k2 = 1;
+
+			// Z Y X order
+
+		} else if ( x0 < z0 ) {
+
+			i1 = 0; j1 = 1; k1 = 0; i2 = 0; j2 = 1; k2 = 1;
+
+			// Y Z X order
+
+		} else {
+
+			i1 = 0; j1 = 1; k1 = 0; i2 = 1; j2 = 1; k2 = 0;
+
+		} // Y X Z order
+
+	}
+	// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
+	// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
+	// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
+	// c = 1/6.
+	var x1 = x0 - i1 + G3; // Offsets for second corner in (x,y,z) coords
+	var y1 = y0 - j1 + G3;
+	var z1 = z0 - k1 + G3;
+	var x2 = x0 - i2 + 2.0 * G3; // Offsets for third corner in (x,y,z) coords
+	var y2 = y0 - j2 + 2.0 * G3;
+	var z2 = z0 - k2 + 2.0 * G3;
+	var x3 = x0 - 1.0 + 3.0 * G3; // Offsets for last corner in (x,y,z) coords
+	var y3 = y0 - 1.0 + 3.0 * G3;
+	var z3 = z0 - 1.0 + 3.0 * G3;
+	// Work out the hashed gradient indices of the four simplex corners
+	var ii = i & 255;
+	var jj = j & 255;
+	var kk = k & 255;
+	var gi0 = this.perm[ ii + this.perm[ jj + this.perm[ kk ] ] ] % 12;
+	var gi1 = this.perm[ ii + i1 + this.perm[ jj + j1 + this.perm[ kk + k1 ] ] ] % 12;
+	var gi2 = this.perm[ ii + i2 + this.perm[ jj + j2 + this.perm[ kk + k2 ] ] ] % 12;
+	var gi3 = this.perm[ ii + 1 + this.perm[ jj + 1 + this.perm[ kk + 1 ] ] ] % 12;
+	// Calculate the contribution from the four corners
+	var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
+	if ( t0 < 0 ) n0 = 0.0;
+	else {
+
+		t0 *= t0;
+		n0 = t0 * t0 * this.dot3( this.grad3[ gi0 ], x0, y0, z0 );
+
+	}
+	var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
+	if ( t1 < 0 ) n1 = 0.0;
+	else {
+
+		t1 *= t1;
+		n1 = t1 * t1 * this.dot3( this.grad3[ gi1 ], x1, y1, z1 );
+
+	}
+	var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
+	if ( t2 < 0 ) n2 = 0.0;
+	else {
+
+		t2 *= t2;
+		n2 = t2 * t2 * this.dot3( this.grad3[ gi2 ], x2, y2, z2 );
+
+	}
+	var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
+	if ( t3 < 0 ) n3 = 0.0;
+	else {
+
+		t3 *= t3;
+		n3 = t3 * t3 * this.dot3( this.grad3[ gi3 ], x3, y3, z3 );
+
+	}
+	// Add contributions from each corner to get the final noise value.
+	// The result is scaled to stay just inside [-1,1]
+	return 32.0 * ( n0 + n1 + n2 + n3 );
+
+};
+
+// 4D simplex noise
+SimplexNoise.prototype.noise4d = function ( x, y, z, w ) {
+
+	// For faster and easier lookups
+	var grad4 = this.grad4;
+	var simplex = this.simplex;
+	var perm = this.perm;
+
+	// The skewing and unskewing factors are hairy again for the 4D case
+	var F4 = ( Math.sqrt( 5.0 ) - 1.0 ) / 4.0;
+	var G4 = ( 5.0 - Math.sqrt( 5.0 ) ) / 20.0;
+	var n0, n1, n2, n3, n4; // Noise contributions from the five corners
+	// Skew the (x,y,z,w) space to determine which cell of 24 simplices we're in
+	var s = ( x + y + z + w ) * F4; // Factor for 4D skewing
+	var i = Math.floor( x + s );
+	var j = Math.floor( y + s );
+	var k = Math.floor( z + s );
+	var l = Math.floor( w + s );
+	var t = ( i + j + k + l ) * G4; // Factor for 4D unskewing
+	var X0 = i - t; // Unskew the cell origin back to (x,y,z,w) space
+	var Y0 = j - t;
+	var Z0 = k - t;
+	var W0 = l - t;
+	var x0 = x - X0; // The x,y,z,w distances from the cell origin
+	var y0 = y - Y0;
+	var z0 = z - Z0;
+	var w0 = w - W0;
+
+	// For the 4D case, the simplex is a 4D shape I won't even try to describe.
+	// To find out which of the 24 possible simplices we're in, we need to
+	// determine the magnitude ordering of x0, y0, z0 and w0.
+	// The method below is a good way of finding the ordering of x,y,z,w and
+	// then find the correct traversal order for the simplex we’re in.
+	// First, six pair-wise comparisons are performed between each possible pair
+	// of the four coordinates, and the results are used to add up binary bits
+	// for an integer index.
+	var c1 = ( x0 > y0 ) ? 32 : 0;
+	var c2 = ( x0 > z0 ) ? 16 : 0;
+	var c3 = ( y0 > z0 ) ? 8 : 0;
+	var c4 = ( x0 > w0 ) ? 4 : 0;
+	var c5 = ( y0 > w0 ) ? 2 : 0;
+	var c6 = ( z0 > w0 ) ? 1 : 0;
+	var c = c1 + c2 + c3 + c4 + c5 + c6;
+	var i1, j1, k1, l1; // The integer offsets for the second simplex corner
+	var i2, j2, k2, l2; // The integer offsets for the third simplex corner
+	var i3, j3, k3, l3; // The integer offsets for the fourth simplex corner
+	// simplex[c] is a 4-vector with the numbers 0, 1, 2 and 3 in some order.
+	// Many values of c will never occur, since e.g. x>y>z>w makes x<z, y<w and x<w
+	// impossible. Only the 24 indices which have non-zero entries make any sense.
+	// We use a thresholding to set the coordinates in turn from the largest magnitude.
+	// The number 3 in the "simplex" array is at the position of the largest coordinate.
+	i1 = simplex[ c ][ 0 ] >= 3 ? 1 : 0;
+	j1 = simplex[ c ][ 1 ] >= 3 ? 1 : 0;
+	k1 = simplex[ c ][ 2 ] >= 3 ? 1 : 0;
+	l1 = simplex[ c ][ 3 ] >= 3 ? 1 : 0;
+	// The number 2 in the "simplex" array is at the second largest coordinate.
+	i2 = simplex[ c ][ 0 ] >= 2 ? 1 : 0;
+	j2 = simplex[ c ][ 1 ] >= 2 ? 1 : 0; k2 = simplex[ c ][ 2 ] >= 2 ? 1 : 0;
+	l2 = simplex[ c ][ 3 ] >= 2 ? 1 : 0;
+	// The number 1 in the "simplex" array is at the second smallest coordinate.
+	i3 = simplex[ c ][ 0 ] >= 1 ? 1 : 0;
+	j3 = simplex[ c ][ 1 ] >= 1 ? 1 : 0;
+	k3 = simplex[ c ][ 2 ] >= 1 ? 1 : 0;
+	l3 = simplex[ c ][ 3 ] >= 1 ? 1 : 0;
+	// The fifth corner has all coordinate offsets = 1, so no need to look that up.
+	var x1 = x0 - i1 + G4; // Offsets for second corner in (x,y,z,w) coords
+	var y1 = y0 - j1 + G4;
+	var z1 = z0 - k1 + G4;
+	var w1 = w0 - l1 + G4;
+	var x2 = x0 - i2 + 2.0 * G4; // Offsets for third corner in (x,y,z,w) coords
+	var y2 = y0 - j2 + 2.0 * G4;
+	var z2 = z0 - k2 + 2.0 * G4;
+	var w2 = w0 - l2 + 2.0 * G4;
+	var x3 = x0 - i3 + 3.0 * G4; // Offsets for fourth corner in (x,y,z,w) coords
+	var y3 = y0 - j3 + 3.0 * G4;
+	var z3 = z0 - k3 + 3.0 * G4;
+	var w3 = w0 - l3 + 3.0 * G4;
+	var x4 = x0 - 1.0 + 4.0 * G4; // Offsets for last corner in (x,y,z,w) coords
+	var y4 = y0 - 1.0 + 4.0 * G4;
+	var z4 = z0 - 1.0 + 4.0 * G4;
+	var w4 = w0 - 1.0 + 4.0 * G4;
+	// Work out the hashed gradient indices of the five simplex corners
+	var ii = i & 255;
+	var jj = j & 255;
+	var kk = k & 255;
+	var ll = l & 255;
+	var gi0 = perm[ ii + perm[ jj + perm[ kk + perm[ ll ] ] ] ] % 32;
+	var gi1 = perm[ ii + i1 + perm[ jj + j1 + perm[ kk + k1 + perm[ ll + l1 ] ] ] ] % 32;
+	var gi2 = perm[ ii + i2 + perm[ jj + j2 + perm[ kk + k2 + perm[ ll + l2 ] ] ] ] % 32;
+	var gi3 = perm[ ii + i3 + perm[ jj + j3 + perm[ kk + k3 + perm[ ll + l3 ] ] ] ] % 32;
+	var gi4 = perm[ ii + 1 + perm[ jj + 1 + perm[ kk + 1 + perm[ ll + 1 ] ] ] ] % 32;
+	// Calculate the contribution from the five corners
+	var t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0 - w0 * w0;
+	if ( t0 < 0 ) n0 = 0.0;
+	else {
+
+		t0 *= t0;
+		n0 = t0 * t0 * this.dot4( grad4[ gi0 ], x0, y0, z0, w0 );
+
+	}
+	var t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1 - w1 * w1;
+	if ( t1 < 0 ) n1 = 0.0;
+	else {
+
+		t1 *= t1;
+		n1 = t1 * t1 * this.dot4( grad4[ gi1 ], x1, y1, z1, w1 );
+
+	}
+	var t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2 - w2 * w2;
+	if ( t2 < 0 ) n2 = 0.0;
+	else {
+
+		t2 *= t2;
+		n2 = t2 * t2 * this.dot4( grad4[ gi2 ], x2, y2, z2, w2 );
+
+	} var t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3 - w3 * w3;
+	if ( t3 < 0 ) n3 = 0.0;
+	else {
+
+		t3 *= t3;
+		n3 = t3 * t3 * this.dot4( grad4[ gi3 ], x3, y3, z3, w3 );
+
+	}
+	var t4 = 0.6 - x4 * x4 - y4 * y4 - z4 * z4 - w4 * w4;
+	if ( t4 < 0 ) n4 = 0.0;
+	else {
+
+		t4 *= t4;
+		n4 = t4 * t4 * this.dot4( grad4[ gi4 ], x4, y4, z4, w4 );
+
+	}
+	// Sum up and scale the result to cover the range [-1,1]
+	return 27.0 * ( n0 + n1 + n2 + n3 + n4 );
+
+};
+
+export { SimplexNoise };

+ 8 - 0
examples/jsm/modifiers/ExplodeModifier.d.ts

@@ -0,0 +1,8 @@
+import {
+  Geometry
+} from '../../../src/Three';
+
+export class ExplodeModifier {
+  constructor();
+  modify(geometry: Geometry): void;
+}

+ 46 - 0
examples/jsm/modifiers/ExplodeModifier.js

@@ -0,0 +1,46 @@
+/**
+ * Make all faces use unique vertices
+ * so that each face can be separated from others
+ *
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+
+
+var ExplodeModifier = function () {
+
+};
+
+ExplodeModifier.prototype.modify = function ( geometry ) {
+
+	var vertices = [];
+
+	for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {
+
+		var n = vertices.length;
+
+		var face = geometry.faces[ i ];
+
+		var a = face.a;
+		var b = face.b;
+		var c = face.c;
+
+		var va = geometry.vertices[ a ];
+		var vb = geometry.vertices[ b ];
+		var vc = geometry.vertices[ c ];
+
+		vertices.push( va.clone() );
+		vertices.push( vb.clone() );
+		vertices.push( vc.clone() );
+
+		face.a = n;
+		face.b = n + 1;
+		face.c = n + 2;
+
+	}
+
+	geometry.vertices = vertices;
+
+};
+
+export { ExplodeModifier };

+ 9 - 0
examples/jsm/modifiers/SimplifyModifier.d.ts

@@ -0,0 +1,9 @@
+import {
+  BufferGeometry,
+  Geometry
+} from '../../../src/Three';
+
+export class SimplifyModifier {
+  constructor();
+  modify(geometry: BufferGeometry | Geometry, count: number): BufferGeometry;
+}

+ 503 - 0
examples/jsm/modifiers/SimplifyModifier.js

@@ -0,0 +1,503 @@
+/*
+ *	@author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
+ *
+ *	Simplification Geometry Modifier
+ *    - based on code and technique
+ *	  - by Stan Melax in 1998
+ *	  - Progressive Mesh type Polygon Reduction Algorithm
+ *    - http://www.melax.com/polychop/
+ */
+
+import {
+	BufferGeometry,
+	Float32BufferAttribute,
+	Geometry,
+	Vector3
+} from "../../../build/three.module.js";
+
+var SimplifyModifier = function () {};
+
+( function () {
+
+	var cb = new Vector3(), ab = new Vector3();
+
+	function pushIfUnique( array, object ) {
+
+		if ( array.indexOf( object ) === - 1 ) array.push( object );
+
+	}
+
+	function removeFromArray( array, object ) {
+
+		var k = array.indexOf( object );
+		if ( k > - 1 ) array.splice( k, 1 );
+
+	}
+
+	function computeEdgeCollapseCost( u, v ) {
+
+		// if we collapse edge uv by moving u to v then how
+		// much different will the model change, i.e. the "error".
+
+		var edgelength = v.position.distanceTo( u.position );
+		var curvature = 0;
+
+		var sideFaces = [];
+		var i, il = u.faces.length, face, sideFace;
+
+		// find the "sides" triangles that are on the edge uv
+		for ( i = 0; i < il; i ++ ) {
+
+			face = u.faces[ i ];
+
+			if ( face.hasVertex( v ) ) {
+
+				sideFaces.push( face );
+
+			}
+
+		}
+
+		// use the triangle facing most away from the sides
+		// to determine our curvature term
+		for ( i = 0; i < il; i ++ ) {
+
+			var minCurvature = 1;
+			face = u.faces[ i ];
+
+			for ( var j = 0; j < sideFaces.length; j ++ ) {
+
+				sideFace = sideFaces[ j ];
+				// use dot product of face normals.
+				var dotProd = face.normal.dot( sideFace.normal );
+				minCurvature = Math.min( minCurvature, ( 1.001 - dotProd ) / 2 );
+
+			}
+
+			curvature = Math.max( curvature, minCurvature );
+
+		}
+
+		// crude approach in attempt to preserve borders
+		// though it seems not to be totally correct
+		var borders = 0;
+		if ( sideFaces.length < 2 ) {
+
+			// we add some arbitrary cost for borders,
+			// borders += 10;
+			curvature = 1;
+
+		}
+
+		var amt = edgelength * curvature + borders;
+
+		return amt;
+
+	}
+
+	function computeEdgeCostAtVertex( v ) {
+
+		// compute the edge collapse cost for all edges that start
+		// from vertex v.  Since we are only interested in reducing
+		// the object by selecting the min cost edge at each step, we
+		// only cache the cost of the least cost edge at this vertex
+		// (in member variable collapse) as well as the value of the
+		// cost (in member variable collapseCost).
+
+		if ( v.neighbors.length === 0 ) {
+
+			// collapse if no neighbors.
+			v.collapseNeighbor = null;
+			v.collapseCost = - 0.01;
+
+			return;
+
+		}
+
+		v.collapseCost = 100000;
+		v.collapseNeighbor = null;
+
+		// search all neighboring edges for "least cost" edge
+		for ( var i = 0; i < v.neighbors.length; i ++ ) {
+
+			var collapseCost = computeEdgeCollapseCost( v, v.neighbors[ i ] );
+
+			if ( ! v.collapseNeighbor ) {
+
+				v.collapseNeighbor = v.neighbors[ i ];
+				v.collapseCost = collapseCost;
+				v.minCost = collapseCost;
+				v.totalCost = 0;
+				v.costCount = 0;
+
+			}
+
+			v.costCount ++;
+			v.totalCost += collapseCost;
+
+			if ( collapseCost < v.minCost ) {
+
+				v.collapseNeighbor = v.neighbors[ i ];
+				v.minCost = collapseCost;
+
+			}
+
+		}
+
+		// we average the cost of collapsing at this vertex
+		v.collapseCost = v.totalCost / v.costCount;
+		// v.collapseCost = v.minCost;
+
+	}
+
+	function removeVertex( v, vertices ) {
+
+		console.assert( v.faces.length === 0 );
+
+		while ( v.neighbors.length ) {
+
+			var n = v.neighbors.pop();
+			removeFromArray( n.neighbors, v );
+
+		}
+
+		removeFromArray( vertices, v );
+
+	}
+
+	function removeFace( f, faces ) {
+
+		removeFromArray( faces, f );
+
+		if ( f.v1 ) removeFromArray( f.v1.faces, f );
+		if ( f.v2 ) removeFromArray( f.v2.faces, f );
+		if ( f.v3 ) removeFromArray( f.v3.faces, f );
+
+		// TODO optimize this!
+		var vs = [ f.v1, f.v2, f.v3 ];
+		var v1, v2;
+
+		for ( var i = 0; i < 3; i ++ ) {
+
+			v1 = vs[ i ];
+			v2 = vs[ ( i + 1 ) % 3 ];
+
+			if ( ! v1 || ! v2 ) continue;
+
+			v1.removeIfNonNeighbor( v2 );
+			v2.removeIfNonNeighbor( v1 );
+
+		}
+
+	}
+
+	function collapse( vertices, faces, u, v ) { // u and v are pointers to vertices of an edge
+
+		// Collapse the edge uv by moving vertex u onto v
+
+		if ( ! v ) {
+
+			// u is a vertex all by itself so just delete it..
+			removeVertex( u, vertices );
+			return;
+
+		}
+
+		var i;
+		var tmpVertices = [];
+
+		for ( i = 0; i < u.neighbors.length; i ++ ) {
+
+			tmpVertices.push( u.neighbors[ i ] );
+
+		}
+
+
+		// delete triangles on edge uv:
+		for ( i = u.faces.length - 1; i >= 0; i -- ) {
+
+			if ( u.faces[ i ].hasVertex( v ) ) {
+
+				removeFace( u.faces[ i ], faces );
+
+			}
+
+		}
+
+		// update remaining triangles to have v instead of u
+		for ( i = u.faces.length - 1; i >= 0; i -- ) {
+
+			u.faces[ i ].replaceVertex( u, v );
+
+		}
+
+
+		removeVertex( u, vertices );
+
+		// recompute the edge collapse costs in neighborhood
+		for ( i = 0; i < tmpVertices.length; i ++ ) {
+
+			computeEdgeCostAtVertex( tmpVertices[ i ] );
+
+		}
+
+	}
+
+
+
+	function minimumCostEdge( vertices ) {
+
+		// O(n * n) approach. TODO optimize this
+
+		var least = vertices[ 0 ];
+
+		for ( var i = 0; i < vertices.length; i ++ ) {
+
+			if ( vertices[ i ].collapseCost < least.collapseCost ) {
+
+				least = vertices[ i ];
+
+			}
+
+		}
+
+		return least;
+
+	}
+
+	// we use a triangle class to represent structure of face slightly differently
+
+	function Triangle( v1, v2, v3, a, b, c ) {
+
+		this.a = a;
+		this.b = b;
+		this.c = c;
+
+		this.v1 = v1;
+		this.v2 = v2;
+		this.v3 = v3;
+
+		this.normal = new Vector3();
+
+		this.computeNormal();
+
+		v1.faces.push( this );
+		v1.addUniqueNeighbor( v2 );
+		v1.addUniqueNeighbor( v3 );
+
+		v2.faces.push( this );
+		v2.addUniqueNeighbor( v1 );
+		v2.addUniqueNeighbor( v3 );
+
+
+		v3.faces.push( this );
+		v3.addUniqueNeighbor( v1 );
+		v3.addUniqueNeighbor( v2 );
+
+	}
+
+	Triangle.prototype.computeNormal = function () {
+
+		var vA = this.v1.position;
+		var vB = this.v2.position;
+		var vC = this.v3.position;
+
+		cb.subVectors( vC, vB );
+		ab.subVectors( vA, vB );
+		cb.cross( ab ).normalize();
+
+		this.normal.copy( cb );
+
+	};
+
+	Triangle.prototype.hasVertex = function ( v ) {
+
+		return v === this.v1 || v === this.v2 || v === this.v3;
+
+	};
+
+	Triangle.prototype.replaceVertex = function ( oldv, newv ) {
+
+		if ( oldv === this.v1 ) this.v1 = newv;
+		else if ( oldv === this.v2 ) this.v2 = newv;
+		else if ( oldv === this.v3 ) this.v3 = newv;
+
+		removeFromArray( oldv.faces, this );
+		newv.faces.push( this );
+
+
+		oldv.removeIfNonNeighbor( this.v1 );
+		this.v1.removeIfNonNeighbor( oldv );
+
+		oldv.removeIfNonNeighbor( this.v2 );
+		this.v2.removeIfNonNeighbor( oldv );
+
+		oldv.removeIfNonNeighbor( this.v3 );
+		this.v3.removeIfNonNeighbor( oldv );
+
+		this.v1.addUniqueNeighbor( this.v2 );
+		this.v1.addUniqueNeighbor( this.v3 );
+
+		this.v2.addUniqueNeighbor( this.v1 );
+		this.v2.addUniqueNeighbor( this.v3 );
+
+		this.v3.addUniqueNeighbor( this.v1 );
+		this.v3.addUniqueNeighbor( this.v2 );
+
+		this.computeNormal();
+
+	};
+
+	function Vertex( v, id ) {
+
+		this.position = v;
+
+		this.id = id; // old index id
+
+		this.faces = []; // faces vertex is connected
+		this.neighbors = []; // neighbouring vertices aka "adjacentVertices"
+
+		// these will be computed in computeEdgeCostAtVertex()
+		this.collapseCost = 0; // cost of collapsing this vertex, the less the better. aka objdist
+		this.collapseNeighbor = null; // best candinate for collapsing
+
+	}
+
+	Vertex.prototype.addUniqueNeighbor = function ( vertex ) {
+
+		pushIfUnique( this.neighbors, vertex );
+
+	};
+
+	Vertex.prototype.removeIfNonNeighbor = function ( n ) {
+
+		var neighbors = this.neighbors;
+		var faces = this.faces;
+
+		var offset = neighbors.indexOf( n );
+		if ( offset === - 1 ) return;
+		for ( var i = 0; i < faces.length; i ++ ) {
+
+			if ( faces[ i ].hasVertex( n ) ) return;
+
+		}
+
+		neighbors.splice( offset, 1 );
+
+	};
+
+	SimplifyModifier.prototype.modify = function ( geometry, count ) {
+
+		if ( geometry.isBufferGeometry ) {
+
+			geometry = new Geometry().fromBufferGeometry( geometry );
+
+		}
+
+		geometry.mergeVertices();
+
+		var oldVertices = geometry.vertices; // Three Position
+		var oldFaces = geometry.faces; // Three Face
+
+		// conversion
+		var vertices = [];
+		var faces = [];
+
+		var i, il;
+
+		//
+		// put data of original geometry in different data structures
+		//
+
+		// add vertices
+
+		for ( i = 0, il = oldVertices.length; i < il; i ++ ) {
+
+			var vertex = new Vertex( oldVertices[ i ], i );
+			vertices.push( vertex );
+
+		}
+
+		// add faces
+
+		for ( i = 0, il = oldFaces.length; i < il; i ++ ) {
+
+			var face = oldFaces[ i ];
+
+			var a = face.a;
+			var b = face.b;
+			var c = face.c;
+
+			var triangle = new Triangle( vertices[ a ], vertices[ b ], vertices[ c ], a, b, c );
+			faces.push( triangle );
+
+		}
+
+		// compute all edge collapse costs
+
+		for ( i = 0, il = vertices.length; i < il; i ++ ) {
+
+			computeEdgeCostAtVertex( vertices[ i ] );
+
+		}
+
+		var nextVertex;
+
+		var z = count;
+
+		while ( z -- ) {
+
+			nextVertex = minimumCostEdge( vertices );
+
+			if ( ! nextVertex ) {
+
+				console.log( 'THREE.SimplifyModifier: No next vertex' );
+				break;
+
+			}
+
+			collapse( vertices, faces, nextVertex, nextVertex.collapseNeighbor );
+
+		}
+
+		//
+
+		var simplifiedGeometry = new BufferGeometry();
+		var position = [];
+		var index = [];
+
+		//
+
+		for ( i = 0; i < vertices.length; i ++ ) {
+
+			var vertex = vertices[ i ].position;
+			position.push( vertex.x, vertex.y, vertex.z );
+
+		}
+
+		//
+
+		for ( i = 0; i < faces.length; i ++ ) {
+
+			var face = faces[ i ];
+
+			var a = vertices.indexOf( face.v1 );
+			var b = vertices.indexOf( face.v2 );
+			var c = vertices.indexOf( face.v3 );
+
+			index.push( a, b, c );
+
+		}
+
+		//
+
+		simplifiedGeometry.addAttribute( 'position', new Float32BufferAttribute( position, 3 ) );
+		simplifiedGeometry.setIndex( index );
+
+		return simplifiedGeometry;
+
+	};
+
+} )();
+
+export { SimplifyModifier };

+ 12 - 0
examples/jsm/modifiers/SubdivisionModifier.d.ts

@@ -0,0 +1,12 @@
+import {
+  BufferGeometry,
+  Geometry
+} from '../../../src/Three';
+
+export class SubdivisionModifier {
+  constructor(subdivisions?: number);
+  subdivisions: number;
+  
+  modify(geometry: BufferGeometry | Geometry): Geometry;
+  smooth(geometry: Geometry): void;
+}

+ 409 - 0
examples/jsm/modifiers/SubdivisionModifier.js

@@ -0,0 +1,409 @@
+/*
+ *	@author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
+ *	@author centerionware / http://www.centerionware.com
+ *
+ *	Subdivision Geometry Modifier
+ *		using Loop Subdivision Scheme
+ *
+ *	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"
+ */
+
+import {
+	Face3,
+	Geometry,
+	Vector2,
+	Vector3
+} from "../../../build/three.module.js";
+
+var SubdivisionModifier = function ( subdivisions ) {
+
+	this.subdivisions = ( subdivisions === undefined ) ? 1 : subdivisions;
+
+};
+
+// Applies the "modify" pattern
+SubdivisionModifier.prototype.modify = function ( geometry ) {
+
+	if ( geometry.isBufferGeometry ) {
+
+		geometry = new Geometry().fromBufferGeometry( geometry );
+
+	} else {
+
+		geometry = geometry.clone();
+
+	}
+
+	geometry.mergeVertices();
+
+	var repeats = this.subdivisions;
+
+	while ( repeats -- > 0 ) {
+
+		this.smooth( geometry );
+
+	}
+
+	geometry.computeFaceNormals();
+	geometry.computeVertexNormals();
+
+	return geometry;
+
+};
+
+( function () {
+
+	// Some constants
+	var ABC = [ 'a', 'b', 'c' ];
+
+
+	function getEdge( a, b, map ) {
+
+		var vertexIndexA = Math.min( a, b );
+		var vertexIndexB = Math.max( a, b );
+
+		var key = vertexIndexA + "_" + vertexIndexB;
+
+		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 {
+
+			var vertexA = vertices[ vertexIndexA ];
+			var vertexB = vertices[ vertexIndexB ];
+
+			edge = {
+
+				a: vertexA, // pointer reference
+				b: vertexB,
+				newEdge: null,
+				// aIndex: a, // numbered reference
+				// bIndex: b,
+				faces: [] // pointers to face
+
+			};
+
+			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;
+
+		for ( i = 0, il = vertices.length; i < il; i ++ ) {
+
+			metaVertices[ i ] = { edges: [] };
+
+		}
+
+		for ( i = 0, il = faces.length; i < il; i ++ ) {
+
+			face = faces[ i ];
+
+			processEdge( face.a, face.b, vertices, edges, face, metaVertices );
+			processEdge( face.b, face.c, vertices, edges, face, metaVertices );
+			processEdge( face.c, face.a, vertices, edges, face, metaVertices );
+
+		}
+
+	}
+
+	function newFace( newFaces, a, b, c, materialIndex ) {
+
+		newFaces.push( new Face3( a, b, c, undefined, undefined, materialIndex ) );
+
+	}
+
+	function midpoint( a, b ) {
+
+		return ( Math.abs( b - a ) / 2 ) + Math.min( a, b );
+
+	}
+
+	function newUv( newUvs, a, b, c ) {
+
+		newUvs.push( [ a.clone(), b.clone(), c.clone() ] );
+
+	}
+
+	/////////////////////////////
+
+	// Performs one iteration of Subdivision
+	SubdivisionModifier.prototype.smooth = function ( geometry ) {
+
+		var tmp = new Vector3();
+
+		var oldVertices, oldFaces, oldUvs;
+		var newVertices, newFaces, newUVs = [];
+
+		var n, i, il, j, k;
+		var metaVertices, sourceEdges;
+
+		// new stuff.
+		var sourceEdges, newEdgeVertices, newSourceVertices;
+
+		oldVertices = geometry.vertices; // { x, y, z}
+		oldFaces = geometry.faces; // { a: oldVertex1, b: oldVertex2, c: oldVertex3 }
+		oldUvs = geometry.faceVertexUvs[ 0 ];
+
+		var hasUvs = oldUvs !== undefined && oldUvs.length > 0;
+
+		/******************************************************
+		 *
+		 * 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.
+		 *
+		 *******************************************************/
+
+		newEdgeVertices = [];
+		var other, currentEdge, newEdge, face;
+		var edgeVertexWeight, adjacentVertexWeight, connectedFaces;
+
+		for ( i in sourceEdges ) {
+
+			currentEdge = sourceEdges[ i ];
+			newEdge = new Vector3();
+
+			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;
+
+				if ( connectedFaces != 1 ) {
+
+					// console.warn( 'Subdivision Modifier: Number of connected faces != 2, is: ', connectedFaces, currentEdge );
+
+				}
+
+			}
+
+			newEdge.addVectors( currentEdge.a, currentEdge.b ).multiplyScalar( edgeVertexWeight );
+
+			tmp.set( 0, 0, 0 );
+
+			for ( j = 0; j < connectedFaces; j ++ ) {
+
+				face = currentEdge.faces[ j ];
+
+				for ( k = 0; k < 3; k ++ ) {
+
+					other = oldVertices[ face[ ABC[ k ] ] ];
+					if ( other !== currentEdge.a && other !== currentEdge.b ) break;
+
+				}
+
+				tmp.add( other );
+
+			}
+
+			tmp.multiplyScalar( adjacentVertexWeight );
+			newEdge.add( tmp );
+
+			currentEdge.newEdge = newEdgeVertices.length;
+			newEdgeVertices.push( newEdge );
+
+			// console.log(currentEdge, newEdge);
+
+		}
+
+		/******************************************************
+		 *
+		 *	Step 2.
+		 *	Reposition each source vertices.
+		 *
+		 *******************************************************/
+
+		var beta, sourceVertexWeight, connectingVertexWeight;
+		var connectingEdge, connectingEdges, oldVertex, newSourceVertex;
+		newSourceVertices = [];
+
+		for ( i = 0, il = oldVertices.length; i < il; i ++ ) {
+
+			oldVertex = oldVertices[ i ];
+
+			// 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
+				// console.warn('crease and boundary rules');
+
+				if ( n == 2 ) {
+
+					// console.warn( '2 connecting edges', connectingEdges );
+					sourceVertexWeight = 3 / 4;
+					connectingVertexWeight = 1 / 8;
+
+					// sourceVertexWeight = 1;
+					// connectingVertexWeight = 0;
+
+				} else if ( n == 1 ) {
+
+					// console.warn( 'only 1 connecting edge' );
+
+				} else if ( n == 0 ) {
+
+					// console.warn( '0 connecting edges' );
+
+				}
+
+			}
+
+			newSourceVertex = oldVertex.clone().multiplyScalar( sourceVertexWeight );
+
+			tmp.set( 0, 0, 0 );
+
+			for ( j = 0; j < n; j ++ ) {
+
+				connectingEdge = connectingEdges[ j ];
+				other = connectingEdge.a !== oldVertex ? connectingEdge.a : connectingEdge.b;
+				tmp.add( other );
+
+			}
+
+			tmp.multiplyScalar( connectingVertexWeight );
+			newSourceVertex.add( tmp );
+
+			newSourceVertices.push( newSourceVertex );
+
+		}
+
+
+		/******************************************************
+		 *
+		 *	Step 3.
+		 *	Generate Faces between source vertices
+		 *	and edge vertices.
+		 *
+		 *******************************************************/
+
+		newVertices = newSourceVertices.concat( newEdgeVertices );
+		var sl = newSourceVertices.length, edge1, edge2, edge3;
+		newFaces = [];
+
+		var uv, x0, x1, x2;
+		var x3 = new Vector2();
+		var x4 = new Vector2();
+		var x5 = new Vector2();
+
+		for ( i = 0, il = oldFaces.length; i < il; i ++ ) {
+
+			face = oldFaces[ i ];
+
+			// find the 3 new edges vertex of each old face
+
+			edge1 = getEdge( face.a, face.b, sourceEdges ).newEdge + sl;
+			edge2 = getEdge( face.b, face.c, sourceEdges ).newEdge + sl;
+			edge3 = getEdge( face.c, face.a, sourceEdges ).newEdge + sl;
+
+			// create 4 faces.
+
+			newFace( newFaces, edge1, edge2, edge3, face.materialIndex );
+			newFace( newFaces, face.a, edge1, edge3, face.materialIndex );
+			newFace( newFaces, face.b, edge2, edge1, face.materialIndex );
+			newFace( newFaces, face.c, edge3, edge2, face.materialIndex );
+
+			// create 4 new uv's
+
+			if ( hasUvs ) {
+
+				uv = oldUvs[ i ];
+
+				x0 = uv[ 0 ];
+				x1 = uv[ 1 ];
+				x2 = 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
+		geometry.vertices = newVertices;
+		geometry.faces = newFaces;
+		if ( hasUvs ) geometry.faceVertexUvs[ 0 ] = newUVs;
+
+		// console.log('done');
+
+	};
+
+} )();
+
+export { SubdivisionModifier };

+ 10 - 0
examples/jsm/modifiers/TessellateModifier.d.ts

@@ -0,0 +1,10 @@
+import {
+  Geometry
+} from '../../../src/Three';
+
+export class SubdivisionModifier {
+  constructor(maxEdgeLength: number);
+  maxEdgeLength: number;
+
+  modify(geometry: Geometry): void;
+}

+ 242 - 0
examples/jsm/modifiers/TessellateModifier.js

@@ -0,0 +1,242 @@
+/**
+ * Break faces with edges longer than maxEdgeLength
+ * - not recursive
+ *
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+import {
+	Face3
+} from "../../../build/three.module.js";
+
+var TessellateModifier = function ( maxEdgeLength ) {
+
+	this.maxEdgeLength = maxEdgeLength;
+
+};
+
+TessellateModifier.prototype.modify = function ( geometry ) {
+
+	var edge;
+
+	var faces = [];
+	var faceVertexUvs = [];
+	var maxEdgeLengthSquared = this.maxEdgeLength * this.maxEdgeLength;
+
+	for ( var i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
+
+		faceVertexUvs[ i ] = [];
+
+	}
+
+	for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {
+
+		var face = geometry.faces[ i ];
+
+		if ( face instanceof Face3 ) {
+
+			var a = face.a;
+			var b = face.b;
+			var c = face.c;
+
+			var va = geometry.vertices[ a ];
+			var vb = geometry.vertices[ b ];
+			var vc = geometry.vertices[ c ];
+
+			var dab = va.distanceToSquared( vb );
+			var dbc = vb.distanceToSquared( vc );
+			var dac = va.distanceToSquared( vc );
+
+			if ( dab > maxEdgeLengthSquared || dbc > maxEdgeLengthSquared || dac > maxEdgeLengthSquared ) {
+
+				var m = geometry.vertices.length;
+
+				var triA = face.clone();
+				var triB = face.clone();
+
+				if ( dab >= dbc && dab >= dac ) {
+
+					var vm = va.clone();
+					vm.lerp( vb, 0.5 );
+
+					triA.a = a;
+					triA.b = m;
+					triA.c = c;
+
+					triB.a = m;
+					triB.b = b;
+					triB.c = c;
+
+					if ( face.vertexNormals.length === 3 ) {
+
+						var vnm = face.vertexNormals[ 0 ].clone();
+						vnm.lerp( face.vertexNormals[ 1 ], 0.5 );
+
+						triA.vertexNormals[ 1 ].copy( vnm );
+						triB.vertexNormals[ 0 ].copy( vnm );
+
+					}
+
+					if ( face.vertexColors.length === 3 ) {
+
+						var vcm = face.vertexColors[ 0 ].clone();
+						vcm.lerp( face.vertexColors[ 1 ], 0.5 );
+
+						triA.vertexColors[ 1 ].copy( vcm );
+						triB.vertexColors[ 0 ].copy( vcm );
+
+					}
+
+					edge = 0;
+
+				} else if ( dbc >= dab && dbc >= dac ) {
+
+					var vm = vb.clone();
+					vm.lerp( vc, 0.5 );
+
+					triA.a = a;
+					triA.b = b;
+					triA.c = m;
+
+					triB.a = m;
+					triB.b = c;
+					triB.c = a;
+
+					if ( face.vertexNormals.length === 3 ) {
+
+						var vnm = face.vertexNormals[ 1 ].clone();
+						vnm.lerp( face.vertexNormals[ 2 ], 0.5 );
+
+						triA.vertexNormals[ 2 ].copy( vnm );
+
+						triB.vertexNormals[ 0 ].copy( vnm );
+						triB.vertexNormals[ 1 ].copy( face.vertexNormals[ 2 ] );
+						triB.vertexNormals[ 2 ].copy( face.vertexNormals[ 0 ] );
+
+					}
+
+					if ( face.vertexColors.length === 3 ) {
+
+						var vcm = face.vertexColors[ 1 ].clone();
+						vcm.lerp( face.vertexColors[ 2 ], 0.5 );
+
+						triA.vertexColors[ 2 ].copy( vcm );
+
+						triB.vertexColors[ 0 ].copy( vcm );
+						triB.vertexColors[ 1 ].copy( face.vertexColors[ 2 ] );
+						triB.vertexColors[ 2 ].copy( face.vertexColors[ 0 ] );
+
+					}
+
+					edge = 1;
+
+				} else {
+
+					var vm = va.clone();
+					vm.lerp( vc, 0.5 );
+
+					triA.a = a;
+					triA.b = b;
+					triA.c = m;
+
+					triB.a = m;
+					triB.b = b;
+					triB.c = c;
+
+					if ( face.vertexNormals.length === 3 ) {
+
+						var vnm = face.vertexNormals[ 0 ].clone();
+						vnm.lerp( face.vertexNormals[ 2 ], 0.5 );
+
+						triA.vertexNormals[ 2 ].copy( vnm );
+						triB.vertexNormals[ 0 ].copy( vnm );
+
+					}
+
+					if ( face.vertexColors.length === 3 ) {
+
+						var vcm = face.vertexColors[ 0 ].clone();
+						vcm.lerp( face.vertexColors[ 2 ], 0.5 );
+
+						triA.vertexColors[ 2 ].copy( vcm );
+						triB.vertexColors[ 0 ].copy( vcm );
+
+					}
+
+					edge = 2;
+
+				}
+
+				faces.push( triA, triB );
+				geometry.vertices.push( vm );
+
+				for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
+
+					if ( geometry.faceVertexUvs[ j ].length ) {
+
+						var uvs = geometry.faceVertexUvs[ j ][ i ];
+
+						var uvA = uvs[ 0 ];
+						var uvB = uvs[ 1 ];
+						var uvC = uvs[ 2 ];
+
+						// AB
+
+						if ( edge === 0 ) {
+
+							var uvM = uvA.clone();
+							uvM.lerp( uvB, 0.5 );
+
+							var uvsTriA = [ uvA.clone(), uvM.clone(), uvC.clone() ];
+							var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
+
+							// BC
+
+						} else if ( edge === 1 ) {
+
+							var uvM = uvB.clone();
+							uvM.lerp( uvC, 0.5 );
+
+							var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
+							var uvsTriB = [ uvM.clone(), uvC.clone(), uvA.clone() ];
+
+							// AC
+
+						} else {
+
+							var uvM = uvA.clone();
+							uvM.lerp( uvC, 0.5 );
+
+							var uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
+							var uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
+
+						}
+
+						faceVertexUvs[ j ].push( uvsTriA, uvsTriB );
+
+					}
+
+				}
+
+			} else {
+
+				faces.push( face );
+
+				for ( var j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
+
+					faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] );
+
+				}
+
+			}
+
+		}
+
+	}
+
+	geometry.faces = faces;
+	geometry.faceVertexUvs = faceVertexUvs;
+
+};
+
+export { TessellateModifier };

+ 6 - 0
examples/jsm/objects/ReflectorRTT.d.ts

@@ -0,0 +1,6 @@
+import { BufferGeometry } from '../../../src/Three';
+import { Reflector, ReflectorOptions } from './Reflector';
+
+export class ReflectorRTT extends Reflector {
+  constructor(geometry?: BufferGeometry, options?: ReflectorOptions);
+}

+ 18 - 0
examples/jsm/objects/ReflectorRTT.js

@@ -0,0 +1,18 @@
+/**
+ * RTT version
+ */
+
+
+import { Reflector } from "../objects/Reflector.js";
+
+var ReflectorRTT = function ( geometry, options ) {
+
+	Reflector.call( this, geometry, options );
+
+	this.geometry.setDrawRange( 0, 0 ); // avoid rendering geometry
+
+};
+
+ReflectorRTT.prototype = Object.create( Reflector.prototype );
+
+export { ReflectorRTT };

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