Pārlūkot izejas kodu

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

David Pritchard 5 gadi atpakaļ
vecāks
revīzija
c378961f38
100 mainītis faili ar 2702 papildinājumiem un 2447 dzēšanām
  1. 1 1
      .github/ISSUE_TEMPLATE.md
  2. 99 46
      build/three.js
  3. 524 522
      build/three.min.js
  4. 98 45
      build/three.module.js
  5. 0 79
      docs/api/en/constants/DrawModes.html
  6. 12 0
      docs/api/en/core/BufferAttribute.html
  7. 4 4
      docs/api/en/extras/core/Path.html
  8. 7 8
      docs/api/en/helpers/SkeletonHelper.html
  9. 168 20
      docs/api/en/materials/MeshToonMaterial.html
  10. 0 15
      docs/api/en/objects/Mesh.html
  11. 11 1
      docs/api/en/renderers/WebGLRenderer.html
  12. 0 79
      docs/api/zh/constants/DrawModes.html
  13. 4 4
      docs/api/zh/extras/core/Path.html
  14. 7 6
      docs/api/zh/helpers/SkeletonHelper.html
  15. 176 24
      docs/api/zh/materials/MeshToonMaterial.html
  16. 0 14
      docs/api/zh/objects/Mesh.html
  17. 11 1
      docs/api/zh/renderers/WebGLRenderer.html
  18. 0 0
      docs/examples/en/math/Lut.html
  19. 86 0
      docs/examples/en/math/MeshSurfaceSampler.html
  20. 10 0
      docs/examples/en/utils/BufferGeometryUtils.html
  21. 0 0
      docs/examples/zh/math/Lut.html
  22. 86 0
      docs/examples/zh/math/MeshSurfaceSampler.html
  23. 10 0
      docs/examples/zh/utils/BufferGeometryUtils.html
  24. 6 6
      docs/list.js
  25. 3 3
      docs/manual/en/introduction/How-to-create-VR-content.html
  26. 3 3
      docs/manual/zh/introduction/How-to-create-VR-content.html
  27. 0 2
      editor/index.html
  28. 2 2
      editor/js/libs/app.js
  29. 1 1
      editor/sw.js
  30. 16 2
      examples/css3d_panorama_deviceorientation.html
  31. 7 6
      examples/files.js
  32. 1 14
      examples/js/exporters/GLTFExporter.js
  33. 10 25
      examples/js/exporters/PLYExporter.js
  34. 1 1
      examples/js/loaders/EXRLoader.js
  35. 97 2
      examples/js/loaders/GLTFLoader.js
  36. 0 305
      examples/js/misc/CarControls.js
  37. 27 13
      examples/js/modifiers/SubdivisionModifier.js
  38. 3 3
      examples/js/objects/Fire.js
  39. 3 3
      examples/js/objects/Reflector.js
  40. 3 3
      examples/js/objects/Refractor.js
  41. 3 3
      examples/js/objects/Water.js
  42. 0 233
      examples/js/pmrem/PMREMCubeUVPacker.js
  43. 706 224
      examples/js/pmrem/PMREMGenerator.js
  44. 2 2
      examples/js/postprocessing/CubeTexturePass.js
  45. 9 3
      examples/js/postprocessing/UnrealBloomPass.js
  46. 111 0
      examples/js/utils/BufferGeometryUtils.js
  47. 0 292
      examples/js/utils/GeometryUtils.js
  48. 5 5
      examples/js/vr/WebVR.js
  49. 1 16
      examples/jsm/exporters/GLTFExporter.js
  50. 10 25
      examples/jsm/exporters/PLYExporter.js
  51. 24 0
      examples/jsm/libs/stats.module.d.ts
  52. 1 1
      examples/jsm/loaders/EXRLoader.js
  53. 19 1
      examples/jsm/loaders/GLTFLoader.d.ts
  54. 97 2
      examples/jsm/loaders/GLTFLoader.js
  55. 187 0
      examples/jsm/math/MeshSurfaceSampler.js
  56. 0 22
      examples/jsm/misc/CarControls.d.ts
  57. 0 314
      examples/jsm/misc/CarControls.js
  58. 16 0
      examples/jsm/misc/TubePainter.d.ts
  59. 7 0
      examples/jsm/misc/TubePainter.js
  60. 0 1
      examples/jsm/nodes/accessors/CameraNode.d.ts
  61. 0 1
      examples/jsm/nodes/accessors/ColorsNode.d.ts
  62. 0 1
      examples/jsm/nodes/accessors/LightNode.d.ts
  63. 0 1
      examples/jsm/nodes/accessors/NormalNode.d.ts
  64. 0 1
      examples/jsm/nodes/accessors/PositionNode.d.ts
  65. 0 2
      examples/jsm/nodes/accessors/ReflectNode.d.ts
  66. 0 1
      examples/jsm/nodes/accessors/ScreenUVNode.d.ts
  67. 0 1
      examples/jsm/nodes/accessors/UVNode.d.ts
  68. 0 1
      examples/jsm/nodes/core/AttributeNode.d.ts
  69. 0 1
      examples/jsm/nodes/core/ConstNode.d.ts
  70. 0 1
      examples/jsm/nodes/core/FunctionCallNode.d.ts
  71. 0 1
      examples/jsm/nodes/core/FunctionNode.d.ts
  72. 0 1
      examples/jsm/nodes/core/InputNode.d.ts
  73. 1 0
      examples/jsm/nodes/core/Node.d.ts
  74. 6 0
      examples/jsm/nodes/core/Node.js
  75. 0 1
      examples/jsm/nodes/core/StructNode.d.ts
  76. 0 1
      examples/jsm/nodes/core/TempNode.d.ts
  77. 0 1
      examples/jsm/nodes/core/VarNode.d.ts
  78. 0 1
      examples/jsm/nodes/effects/BlurNode.d.ts
  79. 0 1
      examples/jsm/nodes/effects/ColorAdjustmentNode.d.ts
  80. 0 1
      examples/jsm/nodes/effects/LuminanceNode.d.ts
  81. 0 1
      examples/jsm/nodes/inputs/CubeTextureNode.d.ts
  82. 0 1
      examples/jsm/nodes/inputs/ReflectorNode.d.ts
  83. 0 1
      examples/jsm/nodes/inputs/TextureNode.d.ts
  84. 0 1
      examples/jsm/nodes/materials/nodes/RawNode.d.ts
  85. 0 1
      examples/jsm/nodes/math/CondNode.d.ts
  86. 0 1
      examples/jsm/nodes/math/MathNode.d.ts
  87. 0 1
      examples/jsm/nodes/math/OperatorNode.d.ts
  88. 0 1
      examples/jsm/nodes/misc/BumpMapNode.d.ts
  89. 0 1
      examples/jsm/nodes/misc/NormalMapNode.d.ts
  90. 0 1
      examples/jsm/nodes/misc/TextureCubeNode.d.ts
  91. 0 2
      examples/jsm/nodes/misc/TextureCubeUVNode.d.ts
  92. 0 1
      examples/jsm/nodes/procedural/CheckerNode.d.ts
  93. 0 1
      examples/jsm/nodes/procedural/NoiseNode.d.ts
  94. 0 1
      examples/jsm/nodes/utils/BypassNode.d.ts
  95. 0 1
      examples/jsm/nodes/utils/ColorSpaceNode.d.ts
  96. 0 1
      examples/jsm/nodes/utils/JoinNode.d.ts
  97. 0 1
      examples/jsm/nodes/utils/SpecularMIPLevelNode.d.ts
  98. 0 1
      examples/jsm/nodes/utils/SubSlot.d.ts
  99. 0 1
      examples/jsm/nodes/utils/SwitchNode.d.ts
  100. 0 1
      examples/jsm/nodes/utils/UVTransformNode.d.ts

+ 1 - 1
.github/ISSUE_TEMPLATE.md

@@ -17,7 +17,7 @@ Please also include a live example if possible. You can start from these templat
 ##### Three.js version
 
 - [ ] Dev
-- [ ] r110
+- [ ] r111
 - [ ] ...
 
 ##### Browser

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 99 - 46
build/three.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 524 - 522
build/three.min.js


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 98 - 45
build/three.module.js


+ 0 - 79
docs/api/en/constants/DrawModes.html

@@ -1,79 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8" />
-		<base href="../../../" />
-		<script src="list.js"></script>
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		<h1>Draw Mode Constants</h1>
-
-		<p class="desc">
-			These are valid values for [page:Mesh.drawMode], and control how the list of vertices is interpeted once sent to the GPU.
-		</p>
-
-		<h2>Draw Modes</h2>
-
-		<code>
-			THREE.TrianglesDrawMode
-		</code>
-		<p>
-			This is the default, and results in every three consecutive vertices (v0, v1, v2), (v3, v4, v5), ...
-			being interpreted as a separate triangle. <br />
-			If the number of vertices is not a multiple of 3, excess vertices are ignored.
-		</p>
-
-		<code>
-			THREE.TriangleStripDrawMode
-		</code>
-		<p>
-			This will result in a series of triangles connected in a strip, given by (v0, v1, v2), (v2, v1, v3), (v2, v3, v4), ...
-			so that every subsequent triangle shares two vertices with the previous triangle.
-		</p>
-
-		<code>
-			THREE.TriangleFanDrawMode
-		</code>
-		<p>
-			This will result in a series of triangles each sharing the first vertex (like a fan),
-			given by (v0, v1, v2), (v0, v2, v3), (v0, v3, v4), ... <br /><br />
-
-			<em>Note:</em> As of [link:https://en.wikipedia.org/wiki/DirectX#DirectX_10 DirectX10], this mode is not supported. As Chrome and Firefox
-			render WebGL using [link:https://en.wikipedia.org/wiki/ANGLE_(software) ANGLE] on Windows,
-			internally this mode will be converted to a supported mode, which will likely lead to lowered
-			performance on those browsers.
-		</p>
-
-
-		<h2>Usage</h2>
-
-		<code>
-		var geometry = new THREE.BufferGeometry();
-
-		var vertices = [];
-
-		vertices.push( -10,  10, 0 );
-		vertices.push( -10, -10, 0 );
-		vertices.push(  10, -10, 0 );
-
-		// ...
-
-		geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
-
-		var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
-
-		var mesh = new THREE.Mesh( geometry, material );
-		mesh.drawMode = THREE.TrianglesDrawMode; //default
-
-		scene.add( mesh );
-		</code>
-
-		<h2>Source</h2>
-
-		<p>
-			[link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js]
-		</p>
-	</body>
-</html>

+ 12 - 0
docs/api/en/core/BufferAttribute.html

@@ -113,6 +113,18 @@
 
 		<h2>Methods</h2>
 
+		<h3>[method:this applyMatrix3]( [param:Matrix3 m] )</h3>
+		<p>Applies matrix [page:Matrix3 m] to every Vector3 element of this BufferAttribute.</p>
+
+		<h3>[method:this applyMatrix4]( [param:Matrix4 m] )</h3>
+		<p>Applies matrix [page:Matrix4 m] to every Vector3 element of this BufferAttribute.</p>
+
+		<h3>[method:this applyNormalMatrix]( [param:Matrix3 m] )</h3>
+		<p>Applies normal matrix [page:Matrix3 m] to every Vector3 element of this BufferAttribute.</p>
+
+		<h3>[method:this transformDirection]( [param:Matrix4 m] )</h3>
+		<p>Applies matrix [page:Matrix4 m] to every Vector3 element of this BufferAttribute, interpreting the elements as a direction vectors.</p>
+
 		<h3>[method:BufferAttribute clone]() </h3>
 		<p>Return a copy of this bufferAttribute.</p>
 

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

@@ -60,7 +60,7 @@
 		<h2>Methods</h2>
 		<p>See the base [page:CurvePath] class for common methods.</p>
 
-		<h3>[method:this absarc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Float clockwise] )</h3>
+		<h3>[method:this absarc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise] )</h3>
 		<p>
 			x, y -- The absolute center of the arc.<br />
 			radius -- The radius of the arc.<br />
@@ -71,7 +71,7 @@
 			Adds an absolutely positioned [page:EllipseCurve EllipseCurve] to the path.
 		</p>
 
-		<h3>[method:this absellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Float clockwise], [param:Float rotation] )</h3>
+		<h3>[method:this absellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise], [param:Float rotation] )</h3>
 		<p>
 			x, y -- The absolute center of the ellipse.<br />
 			xRadius -- The radius of the ellipse in the x axis.<br />
@@ -84,7 +84,7 @@
 			Adds an absolutely positioned [page:EllipseCurve EllipseCurve] to the path.
 		</p>
 
-		<h3>[method:this arc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Float clockwise] )</h3>
+		<h3>[method:this arc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise] )</h3>
 		<p>
 		x, y -- The center of the arc offset from the last call.<br />
 		radius -- The radius of the arc.<br />
@@ -99,7 +99,7 @@
 		<h3>[method:this bezierCurveTo]( [param:Float cp1X], [param:Float cp1Y], [param:Float cp2X], [param:Float cp2Y], [param:Float x], [param:Float y] )</h3>
 		<p>This creates a bezier curve from [page:.currentPoint] with (cp1X, cp1Y) and (cp2X, cp2Y) as control points and updates [page:.currentPoint] to x and y.</p>
 
-		<h3>[method:this ellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Float clockwise], [param:Float rotation] )</h3>
+		<h3>[method:this ellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise], [param:Float rotation] )</h3>
 		<p>
 			x, y -- The center of the ellipse offset from the last call.<br />
 			xRadius -- The radius of the ellipse in the x axis.<br />

+ 7 - 8
docs/api/en/helpers/SkeletonHelper.html

@@ -20,13 +20,14 @@
 
 		<h2>Example</h2>
 
+		<p>
 		[example:webgl_animation_skinning_blending animation / skinning / blending]<br />
 		[example:webgl_animation_skinning_morph animation / skinning / morph]<br />
 		[example:webgl_loader_bvh loader / bvh ]
+		</p>
 
 		<code>
-var helper = new THREE.SkeletonHelper( mesh );
-helper.material.linewidth = 3;
+var helper = new THREE.SkeletonHelper( skinnedMesh );
 scene.add( helper );
 		</code>
 
@@ -35,13 +36,12 @@ scene.add( helper );
 		<h2>Constructor</h2>
 
 
-		<h3>[name]( object )</h3>
+		<h3>[name]( [param:Object3D object] )</h3>
 		<p>
-		object -- can be any object that has an array of [page:Bone Bone]s as a sub object. <br />
-		For example, a [page:Skeleton Skeleton] or a [page:SkinnedMesh SkinnedMesh].
+		object -- Usually an instance of [page:SkinnedMesh]. However, any instance of [page:Object3D] can be used if it represents
+		a hierarchy of [page:Bone Bone]s (via [page:Object3D.children]).
 		</p>
 
-
 		<h2>Properties</h2>
 
 		<h3>[property:Array bones]</h3>
@@ -49,12 +49,11 @@ scene.add( helper );
 		The list of bones that the helper renders as [page:Line Lines].
 		</p>
 
-		<h3>[property:Object root]</h3>
+		<h3>[property:Object3D root]</h3>
 		<p>
 		The object passed in the constructor.
 		</p>
 
-
 		<h2>Source</h2>
 
 		<p>

+ 168 - 20
docs/api/en/materials/MeshToonMaterial.html

@@ -8,11 +8,11 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body>
-		[page:Material] &rarr; [page:MeshPhongMaterial] &rarr;
+		[page:Material] &rarr;
 
 		<h1>[name]</h1>
 
-		<div class="desc">An extension of the [page:MeshPhongMaterial] with toon shading.</div>
+		<div class="desc">A material implementing toon shading.</div>
 
 		<iframe id="scene" src="scenes/material-browser.html#MeshToonMaterial"></iframe>
 
@@ -33,46 +33,194 @@
 		</script>
 
 		<h2>Examples</h2>
-		[example:webgl_materials_variations_toon materials / variations / toon]<br />
+		<p>
+			[example:webgl_materials_variations_toon materials / variations / toon]
+		</p>
 
 		<h2>Constructor</h2>
 
 		<h3>[name]( [param:Object parameters] )</h3>
 		<p>
-		[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
-		Any property of the material (including any property inherited from [page:Material] and [page:MeshStandardMaterial]) can be passed in here.<br /><br />
+			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
+			Any property of the material (including any property inherited from [page:Material]) can be passed in here.<br /><br />
 
-		The exception is the property [page:Hexadecimal color], which can be passed in as a hexadecimal
-		string and is *0xffffff* (white) by default. [page:Color.set]( color ) is called internally.
+			The exception is the property [page:Hexadecimal color], which can be passed in as a hexadecimal
+			string and is *0xffffff* (white) by default. [page:Color.set]( color ) is called internally.
 		</p>
 
-
 		<h2>Properties</h2>
-		<p>See the base [page:Material] and [page:MeshPhongMaterial] classes for common properties.</p>
+		<p>See the base [page:Material] class for common properties.</p>
 
-		<h3>[property:Texture gradientMap]</h3>
-		<p>Gradient map for the toon shading. Default is *null*.</p>
+		<h3>[property:Texture alphaMap]</h3>
+		<p>The alpha map is a grayscale texture that controls the opacity across the surface
+			(black: fully transparent; white: fully opaque). Default is null.<br /><br />
+
+			Only the color of the texture is used, ignoring the alpha channel if one exists.
+			For RGB and RGBA textures, the [page:WebGLRenderer WebGL] renderer will use the
+			green channel when sampling this texture due to the extra bit of precision provided
+			for green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
+			luminance/alpha textures will also still work as expected.
+		</p>
+
+		<h3>[property:Texture aoMap]</h3>
+		<p>The red channel of this texture is used as the ambient occlusion map. Default is null.
+		The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat]
+		and [page:Texture offset] Texture properties.</p>
+
+		<h3>[property:Float aoMapIntensity]</h3>
+		<p>Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.</p>
+
+		<h3>[property:Texture bumpMap]</h3>
+		<p>
+			The texture to create a bump map. The black and white values map to the perceived depth in relation to the lights.
+			Bump doesn't actually affect the geometry of the object, only the lighting. If a normal map is defined this will
+			be ignored.
+		</p>
+
+		<h3>[property:Float bumpScale]</h3>
+		<p>How much the bump map affects the material. Typical ranges are 0-1. Default is 1.</p>
+
+
+		<h3>[property:Color color]</h3>
+		<p>[page:Color] of the material, by default set to white (0xffffff).</p>
+
+		<h3>[property:Texture displacementMap]</h3>
+		<p>
+			The displacement map affects the position of the mesh's vertices. Unlike other maps
+			which only affect the light and shade of the material the displaced vertices can cast shadows,
+			block other objects, and otherwise act as real geometry. The displacement texture is
+			an image where the value of each pixel (white being the highest) is mapped against,
+			and repositions, the vertices of the mesh.
+		</p>
+
+		<h3>[property:Float displacementScale]</h3>
+		<p>
+			How much the displacement map affects the mesh (where black is no displacement,
+			and white is maximum displacement). Without a displacement map set, this value is not applied.
+			 Default is 1.
+		</p>
+
+		<h3>[property:Float displacementBias]</h3>
+		<p>
+			The offset of the displacement map's values on the mesh's vertices.
+			Without a displacement map set, this value is not applied. Default is 0.
+		</p>
+
+		<h3>[property:Color emissive]</h3>
+		<p>
+		Emissive (light) color of the material, essentially a solid color unaffected by other lighting.
+		Default is black.
+		</p>
+
+		<h3>[property:Texture emissiveMap]</h3>
+		<p>
+		Set emisssive (glow) map. Default is null. The emissive map color is modulated by
+		the emissive color and the emissive intensity. If you have an emissive map, be sure to
+		set the emissive color to something other than black.
+		</p>
+
+		<h3>[property:Float emissiveIntensity]</h3>
+		<p>Intensity of the emissive light. Modulates the emissive color. Default is 1.</p>
 
 		<h3>[property:Boolean isMeshToonMaterial]</h3>
 		<p>
-			Used to check whether this or derived classes are mesh toon materials. Default is *true*.<br /><br />
+			Used to check whether this or derived classes are [name]. Default is *true*.<br /><br />
 
 			You should not change this, as it used internally for optimisation.
 		</p>
 
-		<h3>[property:Object defines]</h3>
-		<p>An object of the form:
-			<code>
-				{ 'TOON': '' };
-			</code>
+		<h3>[property:Texture gradientMap]</h3>
+		<p>Gradient map for toon shading. It's required to set [page:Texture.minFilter] and [page:Texture.magFilter] to
+			[page:Textures THREE.NearestFilter] when using this type of texture. Default is *null*.</p>
+
+		<h3>[property:Texture lightMap]</h3>
+		<p>The light map. Default is null. The lightMap requires a second set of UVs,
+		and consequently will ignore the [page:Texture repeat] and [page:Texture offset]
+		Texture properties.</p>
+
+		<h3>[property:Float lightMapIntensity]</h3>
+		<p>Intensity of the baked light. Default is 1.</p>
+
+		<h3>[property:Texture map]</h3>
+		<p>The color map. Default is null. The texture map color is modulated by the diffuse [page:.color].</p>
+
+		<h3>[property:boolean morphNormals]</h3>
+		<p>
+			Defines whether the material uses morphNormals. Set as true to pass morphNormal
+			attributes from the [page:Geometry]	to the shader. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean morphTargets]</h3>
+		<p>Define whether the material uses morphTargets. Default is false.</p>
 
-			This is used by the [page:WebGLRenderer] for selecting shaders.
+		<h3>[property:Texture normalMap]</h3>
+		<p>
+			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
+			the way the color is lit. Normal maps do not change the actual shape of the surface, only the lighting.
 		</p>
 
+		<h3>[property:Integer normalMapType]</h3>
+		<p>
+			The type of normal map.<br /><br />
 
-		<h2>Methods</h2>
-		<p>See the base [page:Material] and [page:MeshPhongMaterial] classes for common methods.</p>
+			Options are [page:constant THREE.TangentSpaceNormalMap] (default), and [page:constant THREE.ObjectSpaceNormalMap].
+		</p>
+
+		<h3>[property:Vector2 normalScale]</h3>
+		<p>
+			How much the normal map affects the material. Typical ranges are 0-1.
+			Default is a [page:Vector2] set to (1,1).
+		</p>
+
+		<h3>[property:Float shininess]</h3>
+		<p>How shiny the [page:.specular] highlight is; a higher value gives a sharper highlight. Default is *30*.</p>
+
+
+		<h3>[property:Boolean skinning]</h3>
+		<p>Define whether the material uses skinning. Default is false.</p>
+
+		<h3>[property:Color specular]</h3>
+		<p>
+			Specular color of the material. Default is a [page:Color] set to *0x111111* (very dark grey).<br /><br />
+
+			This defines how shiny the material is and the color of its shine.
+		</p>
+
+		<h3>[property:Texture specularMap]</h3>
+		<p>
+			The specular map value affects both how much the specular surface highlight
+			contributes and how much of the environment map affects the surface. Default is null.
+		</p>
+
+		<h3>[property:Boolean wireframe]</h3>
+		<p>Render geometry as wireframe. Default is *false* (i.e. render as flat polygons).</p>
+
+		<h3>[property:String wireframeLinecap]</h3>
+		<p>
+			Define appearance of line ends. Possible values are "butt", "round" and "square". Default is 'round'.<br /><br />
+
+			This corresponds to the [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap]
+			property and it is ignored by the [page:WebGLRenderer WebGL] renderer.
+		</p>
 
+		<h3>[property:String wireframeLinejoin]</h3>
+		<p>
+			Define appearance of line joints. Possible values are "round", "bevel" and "miter". Default is 'round'.<br /><br />
+
+			This corresponds to the [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin]
+			property and it is ignored by the [page:WebGLRenderer WebGL] renderer.
+		</p>
+
+		<h3>[property:Float wireframeLinewidth]</h3>
+		<p>Controls wireframe thickness. Default is 1.<br /><br />
+
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
+		</p>
+
+		<h2>Methods</h2>
+		<p>See the base [page:Material] class for common methods.</p>
 
 		<h2>Source</h2>
 

+ 0 - 15
docs/api/en/objects/Mesh.html

@@ -41,18 +41,6 @@
 		<h2>Properties</h2>
 		<p>See the base [page:Object3D] class for common properties.</p>
 
-		<h3>[property:Integer drawMode]</h3>
-		<p>
-			Determines how the mesh triangles are constructed from the vertices.
-			See the draw mode [page:DrawModes constants] for all possible values.
-			Default is [page:DrawModes TrianglesDrawMode].
-		</p>
-		<p>
-			A sensible usage of this property is only possible when [page:Mesh.geometry] is of type [page:BufferGeometry BufferGeometry]
-			since the engine always assumes *THREE.TrianglesDrawMode* for [page:Geometry Geometry].
-		</p>
-
-
 		<h3>[property:Boolean isMesh]</h3>
 		<p>
 			Used to check whether this or derived classes are meshes. Default is *true*.<br /><br />
@@ -90,9 +78,6 @@
 		<h2>Methods</h2>
 		<p>See the base [page:Object3D] class for common methods.</p>
 
-		<h3>[method:null setDrawMode]( [param:Integer value] )</h3>
-		<p>Set the value of [page:.drawMode drawMode].</p>
-
 		<h3>[method:Mesh clone]()</h3>
 		<p>Returns a clone of this [name] object and its descendants.</p>
 

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

@@ -283,6 +283,16 @@
 		Tone mapping white point. Default is *1*.
 		</p>
 
+		<h3>[property:Object xr]</h3>
+		<p>
+		Provides access to the WebXR related interface of the renderer.
+		</p>
+
+		<h3>[property:Boolean xr.enabled]</h3>
+		<p>
+		Whether the renderer should enable XR rendering or not. Default is *false*.
+		</p>
+
 		<h2>Methods</h2>
 
 		<h3>[method:null clear]( [param:Boolean color], [param:Boolean depth], [param:Boolean stencil] )</h3>
@@ -431,7 +441,7 @@
 
 		<h3>[method:null setAnimationLoop]( [param:Function callback] )</h3>
 		<p>[page:Function callback] — The function will be called every available frame. If `null` is passed it will stop any already ongoing animation.</p>
-		<p>A built in function that can be used instead of [link:https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame requestAnimationFrame]. For WebVR projects this function must be used.</p>
+		<p>A built in function that can be used instead of [link:https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame requestAnimationFrame]. For WebXR projects this function must be used.</p>
 
 		<h3>[method:null setClearAlpha]( [param:Float alpha] )</h3>
 		<p>Sets the clear alpha. Valid input is a float between *0.0* and *1.0*.</p>

+ 0 - 79
docs/api/zh/constants/DrawModes.html

@@ -1,79 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8" />
-		<base href="../../../" />
-		<script src="list.js"></script>
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body>
-		<h1>绘图模式常量(Draw Mode Constants)</h1>
-
-		<p class="desc">
-			这些是[page:Mesh.drawMode]的有效值,控制着顶点列表一旦被发送到GPU中将如何被解释。
-		</p>
-
-
-		<h2>绘图模式</h2>
-
-		<code>
-			THREE.TrianglesDrawMode
-		</code>
-		<p>
-			这是默认值,这将使得每三个连续顶点(v0, v1, v2),(v3, v4, v5),……被解释为一个单独的三角形。
-			<br />
-			如果顶点的数量不是3的倍数,那么将会忽略多余的顶点。
-		</p>
-
-		<code>
-			THREE.TriangleStripDrawMode
-		</code>
-		<p>
-			这将使得一系列的三角形(由(v0, v1, v2),(v2, v1, v3),(v2, v3, v4),……给定)一个一个地连在一起,每一个连续的三角形将和前一个三角形共享两个顶点。
-		</p>
-
-		<code>
-			THREE.TriangleFanDrawMode
-		</code>
-		<p>
-这将会使得一个序列中的每一个三角形(由(v0, v1, v2),(v0, v2, v3),(v0, v3, v4),……给定)共享它们的第一个顶点(就像风扇一样)。<br /><br />
-
-			<em>注意:</em>截至[link:https://en.wikipedia.org/wiki/DirectX#DirectX_10 DirectX10]这个模式还没有被支持。
-			由于Chorme和Firefox在Windows上是使用[link:https://en.wikipedia.org/wiki/ANGLE_(software) ANGLE]来渲染WebGL的,所以这种模式将会在内部转换为受支持的模式,
-			但可能会导致这些浏览器在性能上降低一些。
-		</p>
-
-
-		<h2>用法</h2>
-
-		<code>
-		var geometry = new THREE.BufferGeometry();
-
-		var vertices = [];
-	
-		vertices.push( -10,  10, 0 );
-		vertices.push( -10, -10, 0 );
-		vertices.push(  10, -10, 0 );
-	
-		// ...
-	
-		geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
-	
-		var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
-
-		var mesh = new THREE.Mesh( geometry, material );
-		mesh.drawMode = THREE.TrianglesDrawMode; //default
-
-		scene.add( mesh );
-		</code>
-
-
-
-		<h2>源代码</h2>
-
-		<p>
-			[link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js]
-		</p>
-	</body>
-</html>

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

@@ -59,7 +59,7 @@
 		<h2>方法</h2>
 		<p>共有方法请参见其基类[page:CurvePath]。</p>
 
-		<h3>[method:this absarc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Float clockwise] )</h3>
+		<h3>[method:this absarc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise] )</h3>
 		<p>
 			x, y -- 弧线的绝对中心。<br />
 			radius -- 弧线的半径。<br />
@@ -70,7 +70,7 @@
 			添加一条绝对定位的[page:EllipseCurve EllipseCurve]到路径中。
 		</p>
 
-		<h3>[method:this absellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Float clockwise], [param:Float rotation] )</h3>
+		<h3>[method:this absellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise], [param:Float rotation] )</h3>
 		<p>
 			x, y -- 椭圆的绝对中心。<br />
 			xRadius -- 椭圆x轴方向的半径。<br />
@@ -83,7 +83,7 @@
 			添加一条绝对定位的[page:EllipseCurve EllipseCurve]到路径中。
 		</p>
 
-		<h3>[method:this arc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Float clockwise] )</h3>
+		<h3>[method:this arc]( [param:Float x], [param:Float y], [param:Float radius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise] )</h3>
 		<p>
 			x, y -- 弧线的中心来自上次调用后的偏移量。<br />
 			radius -- 弧线的半径。<br />
@@ -98,7 +98,7 @@
 		<h3>[method:this bezierCurveTo]( [param:Float cp1X], [param:Float cp1Y], [param:Float cp2X], [param:Float cp2Y], [param:Float x], [param:Float y] )</h3>
 		<p>从[page:.currentPoint]创建一条贝塞尔曲线,以(cp1X, cp1Y)和(cp2X, cp2Y)作为控制点,并将[page:.currentPoint]更新到x,y。</p>
 
-		<h3>[method:this ellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Float clockwise], [param:Float rotation] )</h3>
+		<h3>[method:this ellipse]( [param:Float x], [param:Float y], [param:Float xRadius], [param:Float yRadius], [param:Float startAngle], [param:Float endAngle], [param:Boolean clockwise], [param:Float rotation] )</h3>
 		<p>
 			x, y -- 椭圆的中心来自上次调用后的偏移量。The center of the ellipse offset from the last call.<br />
 			xRadius -- 椭圆x轴方向的半径。<br />

+ 7 - 6
docs/api/zh/helpers/SkeletonHelper.html

@@ -20,13 +20,14 @@
 
 		<h2>例子</h2>
 
+		<p>
 		[example:webgl_animation_skinning_blending animation / skinning / blending]<br />
 		[example:webgl_animation_skinning_morph animation / skinning / morph]<br />
 		[example:webgl_loader_bvh loader / bvh ]
+		</p>
 
 		<code>
-var helper = new THREE.SkeletonHelper( mesh );
-helper.material.linewidth = 3;
+var helper = new THREE.SkeletonHelper( skinnedMesh );
 scene.add( helper );
 		</code>
 
@@ -35,10 +36,10 @@ scene.add( helper );
 		<h2>构造函数</h2>
 
 
-		<h3>[name]( object )</h3>
+		<h3>[name]( [param:Object3D object] )</h3>
 		<p>
-		object -- 可以是任何拥有一组骨 [page:Bone Bone] 作为子对象的对象. <br />
-		比如, 一个骨骼 [page:Skeleton Skeleton] 或 一个蒙皮网格 [page:SkinnedMesh SkinnedMesh].
+		object -- Usually an instance of [page:SkinnedMesh]. However, any instance of [page:Object3D] can be used if it represents
+		a hierarchy of [page:Bone Bone]s (via [page:Object3D.children]).
 		</p>
 
 
@@ -49,7 +50,7 @@ scene.add( helper );
 		辅助对象使用 [page:Line Lines] 渲染的骨数组.
 		</p>
 
-		<h3>[property:Object root]</h3>
+		<h3>[property:Object3D root]</h3>
 		<p>
 		构造函数传入的对象.
 		</p>

+ 176 - 24
docs/api/zh/materials/MeshToonMaterial.html

@@ -8,11 +8,11 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body>
-		[page:Material] &rarr; [page:MeshPhongMaterial] &rarr;
+		[page:Material] &rarr;
 
-		<h1>卡通网格材质([name])</h1>
+		<h1>[name]</h1>
 
-		<div class="desc">[page:MeshPhongMaterial]卡通着色的扩展。</div>
+		<div class="desc">A material implementing toon shading.</div>
 
 		<iframe id="scene" src="scenes/material-browser.html#MeshToonMaterial"></iframe>
 
@@ -32,45 +32,197 @@
 
 		</script>
 
-		<h2>例子(Examples)</h2>
-		[example:webgl_materials_variations_toon materials / variations / toon]<br />
+		<h2>Examples</h2>
+		<p>
+			[example:webgl_materials_variations_toon materials / variations / toon]
+		</p>
 
-		<h2>构造函数(Constructor)</h2>
+		<h2>Constructor</h2>
 
 		<h3>[name]( [param:Object parameters] )</h3>
-		<p> [page:Object parameters] - (可选)用于定义材质外观的对象,具有一个或多个属性。
-			材质的任何属性都可以从此处传入(包括从[page:Material]和[page:MeshStandardMaterial]继承的任何属性)。<br /><br />
-			属性[page:Hexadecimal color]例外,其可以作为十六进制字符串传递,默认情况下为 *0xffffff*(白色),内部调用[page:Color.set](color)。
+		<p>
+			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
+			Any property of the material (including any property inherited from [page:Material]) can be passed in here.<br /><br />
+
+			The exception is the property [page:Hexadecimal color], which can be passed in as a hexadecimal
+			string and is *0xffffff* (white) by default. [page:Color.set]( color ) is called internally.
 		</p>
 
+		<h2>Properties</h2>
+		<p>See the base [page:Material] class for common properties.</p>
 
-		<h2>属性(Properties)</h2>
-		<p>共有属性请参见其基类[page:Material]和[page:MeshPhongMaterial]。</p>
+		<h3>[property:Texture alphaMap]</h3>
+		<p>The alpha map is a grayscale texture that controls the opacity across the surface
+			(black: fully transparent; white: fully opaque). Default is null.<br /><br />
 
-		<h3>[property:Texture gradientMap]</h3>
-		<p> 卡通着色的渐变贴图,默认值为*null*。</p>
+			Only the color of the texture is used, ignoring the alpha channel if one exists.
+			For RGB and RGBA textures, the [page:WebGLRenderer WebGL] renderer will use the
+			green channel when sampling this texture due to the extra bit of precision provided
+			for green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
+			luminance/alpha textures will also still work as expected.
+		</p>
+
+		<h3>[property:Texture aoMap]</h3>
+		<p>The red channel of this texture is used as the ambient occlusion map. Default is null.
+		The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat]
+		and [page:Texture offset] Texture properties.</p>
+
+		<h3>[property:Float aoMapIntensity]</h3>
+		<p>Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.</p>
+
+		<h3>[property:Texture bumpMap]</h3>
+		<p>
+			The texture to create a bump map. The black and white values map to the perceived depth in relation to the lights.
+			Bump doesn't actually affect the geometry of the object, only the lighting. If a normal map is defined this will
+			be ignored.
+		</p>
+
+		<h3>[property:Float bumpScale]</h3>
+		<p>How much the bump map affects the material. Typical ranges are 0-1. Default is 1.</p>
+
+
+		<h3>[property:Color color]</h3>
+		<p>[page:Color] of the material, by default set to white (0xffffff).</p>
+
+		<h3>[property:Texture displacementMap]</h3>
+		<p>
+			The displacement map affects the position of the mesh's vertices. Unlike other maps
+			which only affect the light and shade of the material the displaced vertices can cast shadows,
+			block other objects, and otherwise act as real geometry. The displacement texture is
+			an image where the value of each pixel (white being the highest) is mapped against,
+			and repositions, the vertices of the mesh.
+		</p>
+
+		<h3>[property:Float displacementScale]</h3>
+		<p>
+			How much the displacement map affects the mesh (where black is no displacement,
+			and white is maximum displacement). Without a displacement map set, this value is not applied.
+			 Default is 1.
+		</p>
+
+		<h3>[property:Float displacementBias]</h3>
+		<p>
+			The offset of the displacement map's values on the mesh's vertices.
+			Without a displacement map set, this value is not applied. Default is 0.
+		</p>
+
+		<h3>[property:Color emissive]</h3>
+		<p>
+		Emissive (light) color of the material, essentially a solid color unaffected by other lighting.
+		Default is black.
+		</p>
+
+		<h3>[property:Texture emissiveMap]</h3>
+		<p>
+		Set emisssive (glow) map. Default is null. The emissive map color is modulated by
+		the emissive color and the emissive intensity. If you have an emissive map, be sure to
+		set the emissive color to something other than black.
+		</p>
+
+		<h3>[property:Float emissiveIntensity]</h3>
+		<p>Intensity of the emissive light. Modulates the emissive color. Default is 1.</p>
 
 		<h3>[property:Boolean isMeshToonMaterial]</h3>
-		<p> 用于检查此类或派生类是否为卡通网格材质。默认值为 *true*。<br /><br />
+		<p>
+			Used to check whether this or derived classes are [name]. Default is *true*.<br /><br />
 
-			因为其通常用在内部优化,所以不应该更改该属性值。
+			You should not change this, as it used internally for optimisation.
 		</p>
 
-		<h3>[property:Object defines]</h3>
-		<p>如下形式的对象:
-			<code>
-				{ 'TOON': '' };
-			</code>
+		<h3>[property:Texture gradientMap]</h3>
+		<p>Gradient map for toon shading. It's required to set [page:Texture.minFilter] and [page:Texture.magFilter] to
+			[page:Textures THREE.NearestFilter] when using this type of texture. Default is *null*.</p>
+
+		<h3>[property:Texture lightMap]</h3>
+		<p>The light map. Default is null. The lightMap requires a second set of UVs,
+		and consequently will ignore the [page:Texture repeat] and [page:Texture offset]
+		Texture properties.</p>
+
+		<h3>[property:Float lightMapIntensity]</h3>
+		<p>Intensity of the baked light. Default is 1.</p>
 
-			[page:WebGLRenderer]使用它来选择shaders。
+		<h3>[property:Texture map]</h3>
+		<p>The color map. Default is null. The texture map color is modulated by the diffuse [page:.color].</p>
+
+		<h3>[property:boolean morphNormals]</h3>
+		<p>
+			Defines whether the material uses morphNormals. Set as true to pass morphNormal
+			attributes from the [page:Geometry]	to the shader. Default is *false*.
 		</p>
 
+		<h3>[property:Boolean morphTargets]</h3>
+		<p>Define whether the material uses morphTargets. Default is false.</p>
+
+		<h3>[property:Texture normalMap]</h3>
+		<p>
+			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
+			the way the color is lit. Normal maps do not change the actual shape of the surface, only the lighting.
+		</p>
+
+		<h3>[property:Integer normalMapType]</h3>
+		<p>
+			The type of normal map.<br /><br />
+
+			Options are [page:constant THREE.TangentSpaceNormalMap] (default), and [page:constant THREE.ObjectSpaceNormalMap].
+		</p>
+
+		<h3>[property:Vector2 normalScale]</h3>
+		<p>
+			How much the normal map affects the material. Typical ranges are 0-1.
+			Default is a [page:Vector2] set to (1,1).
+		</p>
+
+		<h3>[property:Float shininess]</h3>
+		<p>How shiny the [page:.specular] highlight is; a higher value gives a sharper highlight. Default is *30*.</p>
+
+
+		<h3>[property:Boolean skinning]</h3>
+		<p>Define whether the material uses skinning. Default is false.</p>
+
+		<h3>[property:Color specular]</h3>
+		<p>
+			Specular color of the material. Default is a [page:Color] set to *0x111111* (very dark grey).<br /><br />
 
-		<h2>方法(Methods)</h2>
-		<p>共有方法请参见其基类[page:Material]和[page:MeshPhongMaterial]。</p>
+			This defines how shiny the material is and the color of its shine.
+		</p>
+
+		<h3>[property:Texture specularMap]</h3>
+		<p>
+			The specular map value affects both how much the specular surface highlight
+			contributes and how much of the environment map affects the surface. Default is null.
+		</p>
+
+		<h3>[property:Boolean wireframe]</h3>
+		<p>Render geometry as wireframe. Default is *false* (i.e. render as flat polygons).</p>
+
+		<h3>[property:String wireframeLinecap]</h3>
+		<p>
+			Define appearance of line ends. Possible values are "butt", "round" and "square". Default is 'round'.<br /><br />
+
+			This corresponds to the [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineCap 2D Canvas lineCap]
+			property and it is ignored by the [page:WebGLRenderer WebGL] renderer.
+		</p>
+
+		<h3>[property:String wireframeLinejoin]</h3>
+		<p>
+			Define appearance of line joints. Possible values are "round", "bevel" and "miter". Default is 'round'.<br /><br />
+
+			This corresponds to the [link:https://developer.mozilla.org/en/docs/Web/API/CanvasRenderingContext2D/lineJoin 2D Canvas lineJoin]
+			property and it is ignored by the [page:WebGLRenderer WebGL] renderer.
+		</p>
+
+		<h3>[property:Float wireframeLinewidth]</h3>
+		<p>Controls wireframe thickness. Default is 1.<br /><br />
+
+		Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]
+		with the [page:WebGLRenderer WebGL] renderer on most platforms linewidth will
+		always be 1 regardless of the set value.
+		</p>
 
+		<h2>Methods</h2>
+		<p>See the base [page:Material] class for common methods.</p>
 
-		<h2>源码(Source)</h2>
+		<h2>Source</h2>
 
 		<p>
 			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 0 - 14
docs/api/zh/objects/Mesh.html

@@ -40,17 +40,6 @@
 		<h2>属性</h2>
 		<p>共有属性请参见其基类[page:Object3D]。</p>
 
-		<h3>[property:Integer drawMode]</h3>
-		<p>
-			决定了网格中的三角形将如何从顶点来构造。
-			请参阅draw mode [page:DrawModes constants](绘图模式常量)来查看其所有可能的值。
-			其默认值是[page:DrawModes TrianglesDrawMode]。
-		</p>
-		<p>
-			A sensible usage of this property is only possible when [page:Mesh.geometry] is of type [page:BufferGeometry BufferGeometry]
-			since the engine always assumes *THREE.TrianglesDrawMode* for [page:Geometry Geometry].
-		</p>
-
 		<h3>[property:Boolean isMesh]</h3>
 		<p>
 			用于检查这个类或者其派生类是否为网格,默认值为*true*。<br /><br />
@@ -85,9 +74,6 @@
 		<h2>方法</h2>
 		<p>共有方法请参见其基类[page:Object3D]。</p>
 
-		<h3>[method:null setDrawMode]( [param:Integer value] )</h3>
-		<p>设置[page:.drawMode drawMode]的值。</p>
-
 		<h3>[method:Mesh clone]()</h3>
 		<p>返回这个[name]对象及其子级的克隆。</p>
 

+ 11 - 1
docs/api/zh/renderers/WebGLRenderer.html

@@ -260,6 +260,16 @@
 		色调映射的白点。默认是*1*
 		</p>
 
+		<h3>[property:Object xr]</h3>
+		<p>
+		Provides access to the WebXR related interface of the renderer.
+		</p>
+
+		<h3>[property:Boolean xr.enabled]</h3>
+		<p>
+		Whether the renderer should enable XR rendering or not. Default is *false*.
+		</p>
+
 		<h2>方法</h2>
 
 		<h3>[method:null clear]( [param:Boolean color], [param:Boolean depth], [param:Boolean stencil] )</h3>
@@ -388,7 +398,7 @@
 
 		<h3>[method:null setAnimationLoop]( [param:Function callback] )</h3>
 		<p>[page:Function callback] — 每个可用帧都会调用的函数。 如果传入‘null’,所有正在进行的动画都会停止。</p>
-		<p>可用来代替[link:https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame requestAnimationFrame]的内置函数. 对于WebVR项目,必须使用此函数。</p>
+		<p>可用来代替[link:https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame requestAnimationFrame]的内置函数. 对于WebXR项目,必须使用此函数。</p>
 
 		<h3>[method:null setClearAlpha]( [param:Float alpha] )</h3>
 		<p>设置alpha。合法参数是一个*0.0*到 *1.0*之间的浮点数</p>

+ 0 - 0
docs/examples/en/Lut.html → docs/examples/en/math/Lut.html


+ 86 - 0
docs/examples/en/math/MeshSurfaceSampler.html

@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		<h1>[name]</h1>
+
+		<p class="desc">Utility class for sampling weighted random points on the surface of a mesh.</p>
+
+		<p>Weighted sampling is useful for effects like heavier foliage growth in certain areas of terrain, or concentrated particle emissions from specific parts of a mesh. Vertex weights may be written programmatically, or painted by hand as vertex colors in 3D tools like Blender.</p>
+
+		<h2>Example</h2>
+
+		<code>
+		// Create a sampler for a BufferGeometry surface.
+		var sampler = new THREE.MeshSurfaceSampler( surfaceGeometry )
+			.setWeightAttribute( 'color' )
+			.build();
+
+		var sampleMesh = new THREE.InstancedMesh( sampleGeometry, sampleMaterial, 100 );
+
+		var _position = new THREE.Vector3();
+		var _normal = new THREE.Vector3();
+		var _matrix = new THREE.Matrix4();
+
+		// Sample randomly from the surface, creating an instance of the sample
+		// geometry at each sample point.
+		for ( var i = 0; i < 100; i ++ ) {
+
+			sampler.sample( _position, _normal );
+
+			_matrix.makeTranslation( _position.x, _position.y, _position.z );
+
+			mesh.setMatrixAt( i, _matrix );
+
+		}
+
+		mesh.instanceMatrix.needsUpdate = true;
+
+		scene.add( mesh );
+		</code>
+
+		[example:webgl_instancing_scatter]
+
+		<br>
+		<hr>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:BufferGeometry geometry] )</h3>
+		<p>
+		[page:BufferGeometry geometry] — Surface geometry from which to sample.
+		</p>
+		<p>
+		Creates a new [name]. If the input geometry is indexed, a non-indexed copy is made. After construction, the sampler is not able to return samples until [page:MeshSurfaceSampler.build build] is called.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:this setWeightAttribute]( [param:String name] )</h3>
+		<p>
+		Specifies a vertex attribute to be used as a weight when sampling from the surface. Faces with higher weights are more likely to be sampled, and those with weights of zero will not be sampled at all. For vector attributes, only <i>.x</i> is used in sampling.
+		</p>
+		<p>If no weight attribute is selected, sampling is randomly distributed by area.</p>
+
+		<h3>[method:this build]()</h3>
+		<p>
+		Processes the input geometry and prepares to return samples. Any configuration of the geometry or sampler must occur before this method is called. Time complexity is <i>O(n)</i> for a surface with <i>n</i> faces.
+		</p>
+
+		<h3>[method:this sample]( [param:Vector3 targetPosition], [param:Vector3 targetNormal] )</h3>
+		<p>
+		Selects a random point on the surface of the input geometry, returning the position and normal vector at that point. Time complexity is <i>O(log n)</i> for a surface with <i>n</i> faces.</i></p>
+
+		<h2>Source</h2>
+
+		<p>
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/math/MeshSurfaceSampler.js examples/js/math/MeshSurfaceSampler.js]
+		</p>
+	</body>
+</html>

+ 10 - 0
docs/examples/en/utils/BufferGeometryUtils.html

@@ -73,6 +73,16 @@
 
 		</p>
 
+		<h3>[method:BufferGeometry toTrianglesDrawMode]( [param:BufferGeometry geometry], [param:TrianglesDrawMode drawMode] )</h3>
+		<p>
+		geometry -- Instance of [page:BufferGeometry BufferGeometry].<br />
+		drawMode -- The draw mode of the given geometry.<br /><br />
+
+		Returns a new indexed [page:BufferGeometry BufferGeometry] based on the [page:DrawModes THREE.TrianglesDrawMode] draw mode. This mode
+		corresponds to the *gl.TRIANGLES* WebGL primitive.
+
+		</p>
+
 		<h2>Source</h2>
 
 		<p>

+ 0 - 0
docs/examples/zh/Lut.html → docs/examples/zh/math/Lut.html


+ 86 - 0
docs/examples/zh/math/MeshSurfaceSampler.html

@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		<h1>[name]</h1>
+
+		<p class="desc">Utility class for sampling weighted random points on the surface of a mesh.</p>
+
+		<p>Weighted sampling is useful for effects like heavier foliage growth in certain areas of terrain, or concentrated particle emissions from specific parts of a mesh. Vertex weights may be written programmatically, or painted by hand as vertex colors in 3D tools like Blender.</p>
+
+		<h2>Example</h2>
+
+		<code>
+		// Create a sampler for a BufferGeometry surface.
+		var sampler = new THREE.MeshSurfaceSampler( surfaceGeometry )
+			.setWeightAttribute( 'color' )
+			.build();
+
+		var sampleMesh = new THREE.InstancedMesh( sampleGeometry, sampleMaterial, 100 );
+
+		var _position = new THREE.Vector3();
+		var _normal = new THREE.Vector3();
+		var _matrix = new THREE.Matrix4();
+
+		// Sample randomly from the surface, creating an instance of the sample
+		// geometry at each sample point.
+		for ( var i = 0; i < 100; i ++ ) {
+
+			sampler.sample( _position, _normal );
+
+			_matrix.makeTranslation( _position.x, _position.y, _position.z );
+
+			mesh.setMatrixAt( i, _matrix );
+
+		}
+
+		mesh.instanceMatrix.needsUpdate = true;
+
+		scene.add( mesh );
+		</code>
+
+		[example:webgl_instancing_scatter]
+
+		<br>
+		<hr>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:BufferGeometry geometry] )</h3>
+		<p>
+		[page:BufferGeometry geometry] — Surface geometry from which to sample.
+		</p>
+		<p>
+		Creates a new [name]. If the input geometry is indexed, a non-indexed copy is made. After construction, the sampler is not able to return samples until [page:MeshSurfaceSampler.build build] is called.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:this setWeightAttribute]( [param:String name] )</h3>
+		<p>
+		Specifies a vertex attribute to be used as a weight when sampling from the surface. Faces with higher weights are more likely to be sampled, and those with weights of zero will not be sampled at all. For vector attributes, only <i>.x</i> is used in sampling.
+		</p>
+		<p>If no weight attribute is selected, sampling is randomly distributed by area.</p>
+
+		<h3>[method:this build]()</h3>
+		<p>
+		Processes the input geometry and prepares to return samples. Any configuration of the geometry or sampler must occur before this method is called. Time complexity is <i>O(n)</i> for a surface with <i>n</i> faces.
+		</p>
+
+		<h3>[method:this sample]( [param:Vector3 targetPosition], [param:Vector3 targetNormal] )</h3>
+		<p>
+		Selects a random point on the surface of the input geometry, returning the position and normal vector at that point. Time complexity is <i>O(log n)</i> for a surface with <i>n</i> faces.</i></p>
+
+		<h2>Source</h2>
+
+		<p>
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/math/MeshSurfaceSampler.js examples/js/math/MeshSurfaceSampler.js]
+		</p>
+	</body>
+</html>

+ 10 - 0
docs/examples/zh/utils/BufferGeometryUtils.html

@@ -73,6 +73,16 @@
 
 		</p>
 
+		<h3>[method:BufferGeometry toTrianglesDrawMode]( [param:BufferGeometry geometry], [param:TrianglesDrawMode drawMode] )</h3>
+		<p>
+		geometry -- Instance of [page:BufferGeometry BufferGeometry].<br />
+		drawMode -- The draw mode of the given geometry.<br /><br />
+
+		Returns a new indexed [page:BufferGeometry BufferGeometry] based on the [page:DrawModes THREE.TrianglesDrawMode] draw mode. This mode
+		corresponds to the *gl.TRIANGLES* WebGL primitive.
+
+		</p>
+
 		<h2>Source</h2>
 
 		<p>

+ 6 - 6
docs/list.js

@@ -76,7 +76,6 @@ var list = {
 				"Animation": "api/en/constants/Animation",
 				"Core": "api/en/constants/Core",
 				"CustomBlendingEquation": "api/en/constants/CustomBlendingEquations",
-				"DrawModes": "api/en/constants/DrawModes",
 				"Materials": "api/en/constants/Materials",
 				"Renderer": "api/en/constants/Renderer",
 				"Textures": "api/en/constants/Textures"
@@ -401,8 +400,9 @@ var list = {
 				"ColladaExporter": "examples/en/exporters/ColladaExporter"
 			},
 
-			"Plugins": {
-				"LookupTable": "examples/en/Lut",
+			"Math": {
+				"LookupTable": "examples/en/math/Lut",
+				"MeshSurfaceSampler": "examples/en/math/MeshSurfaceSampler",
 			},
 
 			"ConvexHull": {
@@ -520,7 +520,6 @@ var list = {
 				"Animation": "api/zh/constants/Animation",
 				"Core": "api/zh/constants/Core",
 				"CustomBlendingEquation": "api/zh/constants/CustomBlendingEquations",
-				"DrawModes": "api/zh/constants/DrawModes",
 				"Materials": "api/zh/constants/Materials",
 				"Renderer": "api/zh/constants/Renderer",
 				"Textures": "api/zh/constants/Textures"
@@ -844,8 +843,9 @@ var list = {
 				"ColladaExporter": "examples/zh/exporters/ColladaExporter"
 			},
 
-			"插件": {
-				"LookupTable": "examples/zh/Lut",
+			"数学库": {
+				"LookupTable": "examples/zh/math/Lut",
+				"MeshSurfaceSampler": "examples/zh/math/MeshSurfaceSampler",
 			},
 
 			"QuickHull": {

+ 3 - 3
docs/manual/en/introduction/How-to-create-VR-content.html

@@ -39,11 +39,11 @@ document.body.appendChild( VRButton.createButton( renderer ) );
 	</code>
 
 	<p>
-		Next, you have to tell your instance of *WebGLRenderer* to enable VR rendering.
+		Next, you have to tell your instance of *WebGLRenderer* to enable XR rendering.
 	</p>
 
 	<code>
-renderer.vr.enabled = true;
+renderer.xr.enabled = true;
 	</code>
 
 	<p>
@@ -65,7 +65,7 @@ renderer.setAnimationLoop( function () {
 	<p>
 		Have a look at one of the official WebVR examples to see this workflow in action.<br /><br />
 
-		[example:webxr_vr_ballshooter WebXR / VR / ballshoter]<br />
+		[example:webxr_vr_ballshooter WebXR / VR / ballshooter]<br />
 		[example:webxr_vr_cubes WebXR / VR / cubes]<br />
 		[example:webxr_vr_dragging WebXR / VR / dragging]<br />
 		[example:webxr_vr_lorenzattractor WebXR / VR / lorenzattractor]<br />

+ 3 - 3
docs/manual/zh/introduction/How-to-create-VR-content.html

@@ -37,11 +37,11 @@ document.body.appendChild( VRButton.createButton( renderer ) );
 	</code>
 
 	<p>
-		接下来,你需要告诉你的*WebGLRenderer*实例来启用VR渲染。
+		接下来,你需要告诉你的*WebGLRenderer*实例来启用XR渲染。
 	</p>
 
 	<code>
-renderer.vr.enabled = true;
+renderer.xr.enabled = true;
 	</code>
 
 	<p>
@@ -65,7 +65,7 @@ renderer.setAnimationLoop( function () {
 		请查看官方示例中与WebVR相关的示例,了解这一工作流程的实际使用、运行情况。
 		<br /><br />
 
-		[example:webxr_vr_ballshooter WebXR / VR / ballshoter]<br />
+		[example:webxr_vr_ballshooter WebXR / VR / ballshooter]<br />
 		[example:webxr_vr_cubes WebXR / VR / cubes]<br />
 		[example:webxr_vr_dragging WebXR / VR / dragging]<br />
 		[example:webxr_vr_lorenzattractor WebXR / VR / lorenzattractor]<br />

+ 0 - 2
editor/index.html

@@ -7,8 +7,6 @@
 		<link rel="apple-touch-icon" href="images/icon.png">
 		<link rel="manifest" href="manifest.json">
 		<link rel="shortcut icon" href="../files/favicon.ico" />
-		<!-- WebXR Device API (For Chrome M76+), expires 12/04/2019 -->
-		<meta http-equiv="origin-trial" content="Aq9LklhCLNUveuCr7QTpGpqwCPG817cYHdVyQuJPOZYk47iRB390lUKa5edVmgS1pZSl8HPspElEC/91Fz55dwIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3NTQxNzU5OX0=">
 	</head>
 	<body ontouchstart="">
 		<link rel="stylesheet" href="css/main.css">

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

@@ -28,7 +28,7 @@ var APP = {
 			var project = json.project;
 
 			if ( project.shadows ) renderer.shadowMap.enabled = true;
-			if ( project.vr ) renderer.vr.enabled = true;
+			if ( project.vr ) renderer.xr.enabled = true;
 
 			dom.appendChild( renderer.domElement );
 
@@ -110,7 +110,7 @@ var APP = {
 			camera.aspect = this.width / this.height;
 			camera.updateProjectionMatrix();
 
-			if ( renderer.vr.enabled ) {
+			if ( renderer.xr.enabled ) {
 
 				dom.appendChild( THREE.WEBVR.createButton( renderer ) );
 

+ 1 - 1
editor/sw.js

@@ -1,4 +1,4 @@
-// r110
+// r111
 
 const assets = [
 	'./',

+ 16 - 2
examples/css3d_panorama_deviceorientation.html

@@ -7,6 +7,12 @@
 		<link type="text/css" rel="stylesheet" href="main.css">
 	</head>
 	<body>
+		<div id="overlay">
+			<div>
+				<button id="startButton">Start Demo</button>
+				<p>Using device orientation might require a user interaction.</p>
+			</div>
+		</div>
 		<div id="info"><a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> css3d - panorama - device orientation.<br/>cubemap by <a href="http://www.humus.name/index.php?page=Textures" target="_blank" rel="noopener">Humus</a>.</div>
 
 		<script type="module">
@@ -19,11 +25,19 @@
 			var camera, scene, renderer;
 			var controls;
 
-			init();
-			animate();
+			var startButton = document.getElementById( 'startButton' );
+			startButton.addEventListener( 'click', function () {
+
+				init();
+				animate();
+
+			}, false );
 
 			function init() {
 
+				var overlay = document.getElementById( 'overlay' );
+				overlay.remove();
+
 				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 1000 );
 
 				controls = new DeviceOrientationControls( camera );

+ 7 - 6
examples/files.js

@@ -47,12 +47,13 @@ var files = {
 		"webgl_geometry_text_shapes",
 		"webgl_geometry_text_stroke",
 		"webgl_helpers",
-		"webgl_instancing_suzanne",
+		"webgl_instancing_dynamic",
+		"webgl_instancing_interactive",
 		"webgl_instancing_raycast",
+		"webgl_instancing_scatter",
 		"webgl_interactive_buffergeometry",
 		"webgl_interactive_cubes",
 		"webgl_interactive_cubes_gpu",
-		"webgl_interactive_instances_gpu",
 		"webgl_interactive_cubes_ortho",
 		"webgl_interactive_lines",
 		"webgl_interactive_points",
@@ -131,7 +132,7 @@ var files = {
 		"webgl_materials_blending_custom",
 		"webgl_materials_bumpmap",
 		"webgl_materials_bumpmap_skin",
-		"webgl_materials_cars",
+		"webgl_materials_car",
 		"webgl_materials_channels",
 		"webgl_materials_cubemap",
 		"webgl_materials_cubemap_balls_reflection",
@@ -278,10 +279,8 @@ var files = {
 		"webgl_buffergeometry_drawrange",
 		"webgl_buffergeometry_indexed",
 		"webgl_buffergeometry_instancing",
-		"webgl_buffergeometry_instancing2",
 		"webgl_buffergeometry_instancing_billboards",
-		"webgl_buffergeometry_instancing_dynamic",
-		"webgl_buffergeometry_instancing_interleaved_dynamic",
+		"webgl_buffergeometry_instancing_interleaved",
 		"webgl_buffergeometry_instancing_lambert",
 		"webgl_buffergeometry_lines",
 		"webgl_buffergeometry_lines_indexed",
@@ -323,6 +322,7 @@ var files = {
 		"webaudio_visualizer"
 	],
 	"webxr": [
+		"webxr_ar_paint",
 		"webxr_vr_ballshooter",
 		"webxr_vr_cubes",
 		"webxr_vr_dragging",
@@ -360,6 +360,7 @@ var files = {
 		"misc_exporter_draco",
 		"misc_exporter_gltf",
 		"misc_exporter_obj",
+		"misc_exporter_ply",
 		"misc_exporter_stl",
 		"misc_lookat",
 	],

+ 1 - 14
examples/js/exporters/GLTFExporter.js

@@ -1175,20 +1175,7 @@ THREE.GLTFExporter.prototype = {
 
 				}
 
-				if ( mesh.drawMode === THREE.TriangleFanDrawMode ) {
-
-					console.warn( 'GLTFExporter: TriangleFanDrawMode and wireframe incompatible.' );
-					mode = WEBGL_CONSTANTS.TRIANGLE_FAN;
-
-				} else if ( mesh.drawMode === THREE.TriangleStripDrawMode ) {
-
-					mode = mesh.material.wireframe ? WEBGL_CONSTANTS.LINE_STRIP : WEBGL_CONSTANTS.TRIANGLE_STRIP;
-
-				} else {
-
-					mode = mesh.material.wireframe ? WEBGL_CONSTANTS.LINES : WEBGL_CONSTANTS.TRIANGLES;
-
-				}
+				mode = mesh.material.wireframe ? WEBGL_CONSTANTS.LINES : WEBGL_CONSTANTS.TRIANGLES;
 
 			}
 

+ 10 - 25
examples/js/exporters/PLYExporter.js

@@ -144,22 +144,7 @@ THREE.PLYExporter.prototype = {
 
 		}
 
-		// get how many bytes will be needed to save out the faces
-		// so we can use a minimal amount of memory / data
-		var indexByteCount = 1;
-
-		if ( vertexCount > 256 ) { // 2^8 bits
-
-			indexByteCount = 2;
-
-		}
-
-		if ( vertexCount > 65536 ) { // 2^16 bits
-
-			indexByteCount = 4;
-
-		}
-
+		var indexByteCount = 4;
 
 		var header =
 			'ply\n' +
@@ -205,7 +190,7 @@ THREE.PLYExporter.prototype = {
 			// faces
 			header +=
 				`element face ${faceCount}\n` +
-				`property list uchar uint${ indexByteCount * 8 } vertex_index\n`;
+				`property list uchar int vertex_index\n`;
 
 		}
 
@@ -359,7 +344,7 @@ THREE.PLYExporter.prototype = {
 				if ( includeIndices === true ) {
 
 					// Create the face list
-					var faceIndexFunc = `setUint${indexByteCount * 8}`;
+
 					if ( indices !== null ) {
 
 						for ( var i = 0, l = indices.count; i < l; i += 3 ) {
@@ -367,13 +352,13 @@ THREE.PLYExporter.prototype = {
 							output.setUint8( fOffset, 3 );
 							fOffset += 1;
 
-							output[ faceIndexFunc ]( fOffset, indices.getX( i + 0 ) + writtenVertices );
+							output.setUint32( fOffset, indices.getX( i + 0 ) + writtenVertices );
 							fOffset += indexByteCount;
 
-							output[ faceIndexFunc ]( fOffset, indices.getX( i + 1 ) + writtenVertices );
+							output.setUint32( fOffset, indices.getX( i + 1 ) + writtenVertices );
 							fOffset += indexByteCount;
 
-							output[ faceIndexFunc ]( fOffset, indices.getX( i + 2 ) + writtenVertices );
+							output.setUint32( fOffset, indices.getX( i + 2 ) + writtenVertices );
 							fOffset += indexByteCount;
 
 						}
@@ -385,13 +370,13 @@ THREE.PLYExporter.prototype = {
 							output.setUint8( fOffset, 3 );
 							fOffset += 1;
 
-							output[ faceIndexFunc ]( fOffset, writtenVertices + i );
+							output.setUint32( fOffset, writtenVertices + i );
 							fOffset += indexByteCount;
 
-							output[ faceIndexFunc ]( fOffset, writtenVertices + i + 1 );
+							output.setUint32( fOffset, writtenVertices + i + 1 );
 							fOffset += indexByteCount;
 
-							output[ faceIndexFunc ]( fOffset, writtenVertices + i + 2 );
+							output.setUint32( fOffset, writtenVertices + i + 2 );
 							fOffset += indexByteCount;
 
 						}
@@ -537,7 +522,7 @@ THREE.PLYExporter.prototype = {
 
 			} );
 
-			result = `${ header }${vertexList}\n${ includeIndices ? `${faceList}\n` : '' }`;
+			result = `${ header }${vertexList}${ includeIndices ? `${faceList}\n` : '\n' }`;
 
 		}
 

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

@@ -1125,7 +1125,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 		function parseValue( dataView, buffer, offset, type, size ) {
 
-			if ( type === 'string' || type === 'iccProfile' ) {
+			if ( type === 'string' || type === 'stringvector' || type === 'iccProfile' ) {
 
 				return parseFixedLengthString( buffer, offset, size );
 

+ 97 - 2
examples/js/loaders/GLTFLoader.js

@@ -490,6 +490,7 @@ THREE.GLTFLoader = ( function () {
 		this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
 		this.json = json;
 		this.dracoLoader = dracoLoader;
+		this.dracoLoader.preload();
 
 	}
 
@@ -2394,6 +2395,100 @@ THREE.GLTFLoader = ( function () {
 
 	}
 
+	/**
+	 * @param {THREE.BufferGeometry} geometry
+	 * @param {Number} drawMode
+	 * @return {THREE.BufferGeometry}
+	 */
+	function toTrianglesDrawMode( geometry, drawMode ) {
+
+		var index = geometry.getIndex();
+
+		// generate index if not present
+
+		if ( index === null ) {
+
+			var indices = [];
+
+			var position = geometry.getAttribute( 'position' );
+
+			if ( position !== undefined ) {
+
+				for ( var i = 0; i < position.count; i ++ ) {
+
+					indices.push( i );
+
+				}
+
+				geometry.setIndex( indices );
+				index = geometry.getIndex();
+
+			} else {
+
+				console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );
+				return geometry;
+
+			}
+
+		}
+
+		//
+
+		var numberOfTriangles = index.count - 2;
+		var newIndices = [];
+
+		if ( drawMode === THREE.TriangleFanDrawMode ) {
+
+			// gl.TRIANGLE_FAN
+
+			for ( var i = 1; i <= numberOfTriangles; i ++ ) {
+
+				newIndices.push( index.getX( 0 ) );
+				newIndices.push( index.getX( i ) );
+				newIndices.push( index.getX( i + 1 ) );
+
+			}
+
+		} else {
+
+			// gl.TRIANGLE_STRIP
+
+			for ( var i = 0; i < numberOfTriangles; i ++ ) {
+
+				if ( i % 2 === 0 ) {
+
+					newIndices.push( index.getX( i ) );
+					newIndices.push( index.getX( i + 1 ) );
+					newIndices.push( index.getX( i + 2 ) );
+
+
+				} else {
+
+					newIndices.push( index.getX( i + 2 ) );
+					newIndices.push( index.getX( i + 1 ) );
+					newIndices.push( index.getX( i ) );
+
+				}
+
+			}
+
+		}
+
+		if ( ( newIndices.length / 3 ) !== numberOfTriangles ) {
+
+			console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );
+
+		}
+
+		// build final geometry
+
+		var newGeometry = geometry.clone();
+		newGeometry.setIndex( newIndices );
+
+		return newGeometry;
+
+	}
+
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry
 	 *
@@ -2526,11 +2621,11 @@ THREE.GLTFLoader = ( function () {
 
 						if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
 
-							mesh.drawMode = THREE.TriangleStripDrawMode;
+							mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleStripDrawMode );
 
 						} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
 
-							mesh.drawMode = THREE.TriangleFanDrawMode;
+							mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleFanDrawMode );
 
 						}
 

+ 0 - 305
examples/js/misc/CarControls.js

@@ -1,305 +0,0 @@
-/**
- * @author alteredq / http://alteredqualia.com/
- * @author Lewy Blue https://github.com/looeee
- *
- * The model is expected to follow real world car proportions. You can try unusual car types
- * but your results may be unexpected. Scaled models are also not supported.
- *
- * Defaults are rough estimates for a real world scale car model
- *
- */
-
-THREE.CarControls = ( function ( ) {
-
-	// private variables
-	var steeringWheelSpeed = 1.5;
-	var maxSteeringRotation = 0.6;
-
-	var acceleration = 0;
-
-	var maxSpeedReverse, accelerationReverse, deceleration;
-
-	var controlKeys = { LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, BRAKE: 32 };
-
-	var wheelOrientation = 0;
-	var carOrientation = 0;
-
-	var root = null;
-
-	var frontLeftWheelRoot = null;
-	var frontRightWheelRoot = null;
-
-	var frontLeftWheel = new THREE.Group();
-	var frontRightWheel = new THREE.Group();
-	var backLeftWheel = null;
-	var backRightWheel = null;
-
-	var steeringWheel = null;
-
-	var wheelDiameter = 1;
-	var length = 1;
-
-	var loaded = false;
-
-	var controls = {
-
-		brake: false,
-		moveForward: false,
-		moveBackward: false,
-		moveLeft: false,
-		moveRight: false
-
-	};
-
-	function CarControls( maxSpeed, acceleration, brakePower, turningRadius, keys ) {
-
-		this.enabled = true;
-
-		this.elemNames = {
-			flWheel: 'wheel_fl',
-			frWheel: 'wheel_fr',
-			rlWheel: 'wheel_rl',
-			rrWheel: 'wheel_rr',
-			steeringWheel: 'steering_wheel', // set to null to disable
-		};
-
-		// km/hr
-		this.maxSpeed = maxSpeed || 180;
-		maxSpeedReverse = - this.maxSpeed * 0.25;
-
-		// m/s
-		this.acceleration = acceleration || 10;
-		accelerationReverse = this.acceleration * 0.5;
-
-		// metres
-		this.turningRadius = turningRadius || 6;
-
-		// m/s
-		deceleration = this.acceleration * 2;
-
-		// multiplied with deceleration, so breaking deceleration = ( acceleration * 2 * brakePower ) m/s
-		this.brakePower = brakePower || 10;
-
-		// exposed so that a user can use this for various effect, e.g blur
-		this.speed = 0;
-
-		// keys used to control car - by default the arrow keys and space to brake
-		controlKeys = keys || controlKeys;
-
-		// local axes of rotation - these are likely to vary between models
-		this.wheelRotationAxis = 'x';
-		this.wheelTurnAxis = 'z';
-		this.steeringWheelTurnAxis = 'y';
-
-		document.addEventListener( 'keydown', this.onKeyDown, false );
-		document.addEventListener( 'keyup', this.onKeyUp, false );
-
-	}
-
-	CarControls.prototype = {
-
-		constructor: CarControls,
-
-		onKeyDown: function ( event ) {
-
-			switch ( event.keyCode ) {
-
-				case controlKeys.BRAKE:
-					controls.brake = true;
-					controls.moveForward = false;
-					controls.moveBackward = false;
-					break;
-
-				case controlKeys.UP: controls.moveForward = true; break;
-
-				case controlKeys.DOWN: controls.moveBackward = true; break;
-
-				case controlKeys.LEFT: controls.moveLeft = true; break;
-
-				case controlKeys.RIGHT: controls.moveRight = true; break;
-
-			}
-
-		},
-
-		onKeyUp: function ( event ) {
-
-			switch ( event.keyCode ) {
-
-				case controlKeys.BRAKE: controls.brake = false; break;
-
-				case controlKeys.UP: controls.moveForward = false; break;
-
-				case controlKeys.DOWN: controls.moveBackward = false; break;
-
-				case controlKeys.LEFT: controls.moveLeft = false; break;
-
-				case controlKeys.RIGHT: controls.moveRight = false; break;
-
-			}
-
-		},
-
-		dispose: function () {
-
-			document.removeEventListener( 'keydown', this.onKeyDown, false );
-			document.removeEventListener( 'keyup', this.onKeyUp, false );
-
-		},
-
-		update: function ( delta ) {
-
-			if ( ! loaded || ! this.enabled ) return;
-
-			var brakingDeceleration = 1;
-
-			if ( controls.brake ) brakingDeceleration = this.brakePower;
-
-			if ( controls.moveForward ) {
-
-				this.speed = THREE.Math.clamp( this.speed + delta * this.acceleration, maxSpeedReverse, this.maxSpeed );
-				acceleration = THREE.Math.clamp( acceleration + delta, - 1, 1 );
-
-			}
-
-			if ( controls.moveBackward ) {
-
-				this.speed = THREE.Math.clamp( this.speed - delta * accelerationReverse, maxSpeedReverse, this.maxSpeed );
-				acceleration = THREE.Math.clamp( acceleration - delta, - 1, 1 );
-
-			}
-
-			if ( controls.moveLeft ) {
-
-				wheelOrientation = THREE.Math.clamp( wheelOrientation + delta * steeringWheelSpeed, - maxSteeringRotation, maxSteeringRotation );
-
-			}
-
-			if ( controls.moveRight ) {
-
-				wheelOrientation = THREE.Math.clamp( wheelOrientation - delta * steeringWheelSpeed, - maxSteeringRotation, maxSteeringRotation );
-
-			}
-
-			// this.speed decay
-			if ( ! ( controls.moveForward || controls.moveBackward ) ) {
-
-				if ( this.speed > 0 ) {
-
-					var k = exponentialEaseOut( this.speed / this.maxSpeed );
-
-					this.speed = THREE.Math.clamp( this.speed - k * delta * deceleration * brakingDeceleration, 0, this.maxSpeed );
-					acceleration = THREE.Math.clamp( acceleration - k * delta, 0, 1 );
-
-				} else {
-
-					var k = exponentialEaseOut( this.speed / maxSpeedReverse );
-
-					this.speed = THREE.Math.clamp( this.speed + k * delta * accelerationReverse * brakingDeceleration, maxSpeedReverse, 0 );
-					acceleration = THREE.Math.clamp( acceleration + k * delta, - 1, 0 );
-
-				}
-
-			}
-
-			// steering decay
-			if ( ! ( controls.moveLeft || controls.moveRight ) ) {
-
-				if ( wheelOrientation > 0 ) {
-
-					wheelOrientation = THREE.Math.clamp( wheelOrientation - delta * steeringWheelSpeed, 0, maxSteeringRotation );
-
-				} else {
-
-					wheelOrientation = THREE.Math.clamp( wheelOrientation + delta * steeringWheelSpeed, - maxSteeringRotation, 0 );
-
-				}
-
-			}
-
-			var forwardDelta = - this.speed * delta;
-
-			carOrientation -= ( forwardDelta * this.turningRadius * 0.02 ) * wheelOrientation;
-
-			// movement of car
-			root.position.x += Math.sin( carOrientation ) * forwardDelta * length;
-			root.position.z += Math.cos( carOrientation ) * forwardDelta * length;
-
-			// angle of car
-			root.rotation.y = carOrientation;
-
-			// wheels rolling
-			var angularSpeedRatio = - 2 / wheelDiameter;
-
-			var wheelDelta = forwardDelta * angularSpeedRatio * length;
-
-			frontLeftWheel.rotation[ this.wheelRotationAxis ] -= wheelDelta;
-			frontRightWheel.rotation[ this.wheelRotationAxis ] -= wheelDelta;
-			backLeftWheel.rotation[ this.wheelRotationAxis ] -= wheelDelta;
-			backRightWheel.rotation[ this.wheelRotationAxis ] -= wheelDelta;
-
-			// rotation while steering
-			frontLeftWheelRoot.rotation[ this.wheelTurnAxis ] = wheelOrientation;
-			frontRightWheelRoot.rotation[ this.wheelTurnAxis ] = wheelOrientation;
-
-			steeringWheel.rotation[ this.steeringWheelTurnAxis ] = - wheelOrientation * 6;
-
-		},
-
-		setModel: function ( model, elemNames ) {
-
-			if ( elemNames ) this.elemNames = elemNames;
-
-			root = model;
-
-			this.setupWheels();
-			this.computeDimensions();
-
-			loaded = true;
-
-		},
-
-		setupWheels: function () {
-
-			frontLeftWheelRoot = root.getObjectByName( this.elemNames.flWheel );
-			frontRightWheelRoot = root.getObjectByName( this.elemNames.frWheel );
-			backLeftWheel = root.getObjectByName( this.elemNames.rlWheel );
-			backRightWheel = root.getObjectByName( this.elemNames.rrWheel );
-
-			if ( this.elemNames.steeringWheel !== null ) steeringWheel = root.getObjectByName( this.elemNames.steeringWheel );
-
-			while ( frontLeftWheelRoot.children.length > 0 ) frontLeftWheel.add( frontLeftWheelRoot.children[ 0 ] );
-			while ( frontRightWheelRoot.children.length > 0 ) frontRightWheel.add( frontRightWheelRoot.children[ 0 ] );
-
-			frontLeftWheelRoot.add( frontLeftWheel );
-			frontRightWheelRoot.add( frontRightWheel );
-
-		},
-
-		computeDimensions: function () {
-
-			var bb = new THREE.Box3().setFromObject( frontLeftWheelRoot );
-
-			var size = new THREE.Vector3();
-			bb.getSize( size );
-
-			wheelDiameter = Math.max( size.x, size.y, size.z );
-
-			bb.setFromObject( root );
-
-			size = bb.getSize( size );
-			length = Math.max( size.x, size.y, size.z );
-
-		}
-
-	};
-
-	function exponentialEaseOut( k ) {
-
-		return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
-
-	}
-
-	return CarControls;
-
-} )();

+ 27 - 13
examples/js/modifiers/SubdivisionModifier.js

@@ -167,10 +167,20 @@ THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
 
 		oldVertices = geometry.vertices; // { x, y, z}
 		oldFaces = geometry.faces; // { a: oldVertex1, b: oldVertex2, c: oldVertex3 }
-		oldUvs = geometry.faceVertexUvs[ 0 ];
+		oldUvs = geometry.faceVertexUvs;
 
 		var hasUvs = oldUvs !== undefined && oldUvs.length > 0;
 
+		if ( hasUvs ) {
+
+			for ( var j = 0; j < oldUvs.length; j ++ ) {
+
+				newUVs.push( [] );
+
+			}
+
+		}
+
 		/******************************************************
 		 *
 		 * Step 0: Preprocess Geometry to Generate edges Lookup
@@ -368,21 +378,25 @@ THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
 
 			if ( hasUvs ) {
 
-				uv = oldUvs[ i ];
+				for ( var j = 0; j < oldUvs.length; j ++ ) {
+
+					uv = oldUvs[ j ][ i ];
 
-				x0 = uv[ 0 ];
-				x1 = uv[ 1 ];
-				x2 = uv[ 2 ];
+					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 ) );
+					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[ j ], x3, x4, x5 );
+					newUv( newUVs[ j ], x0, x3, x5 );
 
-				newUv( newUVs, x1, x4, x3 );
-				newUv( newUVs, x2, x5, x4 );
+					newUv( newUVs[ j ], x1, x4, x3 );
+					newUv( newUVs[ j ], x2, x5, x4 );
+
+				}
 
 			}
 
@@ -391,7 +405,7 @@ THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
 		// Overwrite old arrays
 		geometry.vertices = newVertices;
 		geometry.faces = newFaces;
-		if ( hasUvs ) geometry.faceVertexUvs[ 0 ] = newUVs;
+		if ( hasUvs ) geometry.faceVertexUvs = newUVs;
 
 		// console.log('done');
 

+ 3 - 3
examples/js/objects/Fire.js

@@ -319,7 +319,7 @@ THREE.Fire = function ( geometry, options ) {
 	this.saveRenderState = function ( renderer ) {
 
 		this.savedRenderTarget = renderer.getRenderTarget();
-		this.savedVrEnabled = renderer.vr.enabled;
+		this.savedXrEnabled = renderer.xr.enabled;
 		this.savedShadowAutoUpdate = renderer.shadowMap.autoUpdate;
 		this.savedAntialias = renderer.antialias;
 		this.savedToneMapping = renderer.toneMapping;
@@ -328,7 +328,7 @@ THREE.Fire = function ( geometry, options ) {
 
 	this.restoreRenderState = function ( renderer ) {
 
-		renderer.vr.enabled = this.savedVrEnabled;
+		renderer.xr.enabled = this.savedXrEnabled;
 		renderer.shadowMap.autoUpdate = this.savedShadowAutoUpdate;
 		renderer.setRenderTarget( this.savedRenderTarget );
 		renderer.antialias = this.savedAntialias;
@@ -445,7 +445,7 @@ THREE.Fire = function ( geometry, options ) {
 
 		this.saveRenderState( renderer );
 
-		renderer.vr.enabled = false; // Avoid camera modification and recursion
+		renderer.xr.enabled = false; // Avoid camera modification and recursion
 		renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
 		renderer.antialias = false;
 		renderer.toneMapping = THREE.NoToneMapping;

+ 3 - 3
examples/js/objects/Reflector.js

@@ -153,17 +153,17 @@ THREE.Reflector = function ( geometry, options ) {
 
 		var currentRenderTarget = renderer.getRenderTarget();
 
-		var currentVrEnabled = renderer.vr.enabled;
+		var currentXrEnabled = renderer.xr.enabled;
 		var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
 
-		renderer.vr.enabled = false; // Avoid camera modification and recursion
+		renderer.xr.enabled = false; // Avoid camera modification and recursion
 		renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
 
 		renderer.setRenderTarget( renderTarget );
 		renderer.clear();
 		renderer.render( scene, virtualCamera );
 
-		renderer.vr.enabled = currentVrEnabled;
+		renderer.xr.enabled = currentXrEnabled;
 		renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
 
 		renderer.setRenderTarget( currentRenderTarget );

+ 3 - 3
examples/js/objects/Refractor.js

@@ -189,17 +189,17 @@ THREE.Refractor = function ( geometry, options ) {
 		scope.visible = false;
 
 		var currentRenderTarget = renderer.getRenderTarget();
-		var currentVrEnabled = renderer.vr.enabled;
+		var currentXrEnabled = renderer.xr.enabled;
 		var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
 
-		renderer.vr.enabled = false; // avoid camera modification
+		renderer.xr.enabled = false; // avoid camera modification
 		renderer.shadowMap.autoUpdate = false; // avoid re-computing shadows
 
 		renderer.setRenderTarget( renderTarget );
 		renderer.clear();
 		renderer.render( scene, virtualCamera );
 
-		renderer.vr.enabled = currentVrEnabled;
+		renderer.xr.enabled = currentXrEnabled;
 		renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
 		renderer.setRenderTarget( currentRenderTarget );
 

+ 3 - 3
examples/js/objects/Water.js

@@ -283,12 +283,12 @@ THREE.Water = function ( geometry, options ) {
 
 		var currentRenderTarget = renderer.getRenderTarget();
 
-		var currentVrEnabled = renderer.vr.enabled;
+		var currentXrEnabled = renderer.xr.enabled;
 		var currentShadowAutoUpdate = renderer.shadowMap.autoUpdate;
 
 		scope.visible = false;
 
-		renderer.vr.enabled = false; // Avoid camera modification and recursion
+		renderer.xr.enabled = false; // Avoid camera modification and recursion
 		renderer.shadowMap.autoUpdate = false; // Avoid re-computing shadows
 
 		renderer.setRenderTarget( renderTarget );
@@ -297,7 +297,7 @@ THREE.Water = function ( geometry, options ) {
 
 		scope.visible = true;
 
-		renderer.vr.enabled = currentVrEnabled;
+		renderer.xr.enabled = currentXrEnabled;
 		renderer.shadowMap.autoUpdate = currentShadowAutoUpdate;
 
 		renderer.setRenderTarget( currentRenderTarget );

+ 0 - 233
examples/js/pmrem/PMREMCubeUVPacker.js

@@ -1,233 +0,0 @@
-/**
- * @author Prashant Sharma / spidersharma03
- * @author Ben Houston / bhouston, https://clara.io
- *
- * This class takes the cube lods(corresponding to different roughness values), and creates a single cubeUV
- * Texture. The format for a given roughness set of faces is simply::
- * +X+Y+Z
- * -X-Y-Z
- * For every roughness a mip map chain is also saved, which is essential to remove the texture artifacts due to
- * minification.
- * Right now for every face a PlaneMesh is drawn, which leads to a lot of geometry draw calls, but can be replaced
- * later by drawing a single buffer and by sending the appropriate faceIndex via vertex attributes.
- * The arrangement of the faces is fixed, as assuming this arrangement, the sampling function has been written.
- */
-
-THREE.PMREMCubeUVPacker = ( function () {
-
-	var camera = new THREE.OrthographicCamera();
-	var scene = new THREE.Scene();
-	var shader = getShader();
-
-	var PMREMCubeUVPacker = function ( cubeTextureLods ) {
-
-		this.cubeLods = cubeTextureLods;
-		var size = cubeTextureLods[ 0 ].width * 4;
-
-		var sourceTexture = cubeTextureLods[ 0 ].texture;
-		var params = {
-			format: sourceTexture.format,
-			magFilter: sourceTexture.magFilter,
-			minFilter: sourceTexture.minFilter,
-			type: sourceTexture.type,
-			generateMipmaps: sourceTexture.generateMipmaps,
-			anisotropy: sourceTexture.anisotropy,
-			encoding: ( sourceTexture.encoding === THREE.RGBEEncoding ) ? THREE.RGBM16Encoding : sourceTexture.encoding
-		};
-
-		if ( params.encoding === THREE.RGBM16Encoding ) {
-
-			params.magFilter = THREE.LinearFilter;
-			params.minFilter = THREE.LinearFilter;
-
-		}
-
-		this.CubeUVRenderTarget = new THREE.WebGLRenderTarget( size, size, params );
-		this.CubeUVRenderTarget.texture.name = "PMREMCubeUVPacker.cubeUv";
-		this.CubeUVRenderTarget.texture.mapping = THREE.CubeUVReflectionMapping;
-
-		this.objects = [];
-
-		var geometry = new THREE.PlaneBufferGeometry( 1, 1 );
-
-		var faceOffsets = [];
-		faceOffsets.push( new THREE.Vector2( 0, 0 ) );
-		faceOffsets.push( new THREE.Vector2( 1, 0 ) );
-		faceOffsets.push( new THREE.Vector2( 2, 0 ) );
-		faceOffsets.push( new THREE.Vector2( 0, 1 ) );
-		faceOffsets.push( new THREE.Vector2( 1, 1 ) );
-		faceOffsets.push( new THREE.Vector2( 2, 1 ) );
-
-		var textureResolution = size;
-		size = cubeTextureLods[ 0 ].width;
-
-		var offset2 = 0;
-		var c = 4.0;
-		this.numLods = Math.log( cubeTextureLods[ 0 ].width ) / Math.log( 2 ) - 2; // IE11 doesn't support Math.log2
-		for ( var i = 0; i < this.numLods; i ++ ) {
-
-			var offset1 = ( textureResolution - textureResolution / c ) * 0.5;
-			if ( size > 16 ) c *= 2;
-			var nMips = size > 16 ? 6 : 1;
-			var mipOffsetX = 0;
-			var mipOffsetY = 0;
-			var mipSize = size;
-
-			for ( var j = 0; j < nMips; j ++ ) {
-
-				// Mip Maps
-				for ( var k = 0; k < 6; k ++ ) {
-
-					// 6 Cube Faces
-					var material = shader.clone();
-					material.uniforms[ 'envMap' ].value = this.cubeLods[ i ].texture;
-					material.envMap = this.cubeLods[ i ].texture;
-					material.uniforms[ 'faceIndex' ].value = k;
-					material.uniforms[ 'mapSize' ].value = mipSize;
-
-					var planeMesh = new THREE.Mesh( geometry, material );
-					planeMesh.position.x = faceOffsets[ k ].x * mipSize - offset1 + mipOffsetX;
-					planeMesh.position.y = faceOffsets[ k ].y * mipSize - offset1 + offset2 + mipOffsetY;
-					planeMesh.material.side = THREE.BackSide;
-					planeMesh.scale.setScalar( mipSize );
-					this.objects.push( planeMesh );
-
-				}
-				mipOffsetY += 1.75 * mipSize;
-				mipOffsetX += 1.25 * mipSize;
-				mipSize /= 2;
-
-			}
-			offset2 += 2 * size;
-			if ( size > 16 ) size /= 2;
-
-		}
-
-	};
-
-	PMREMCubeUVPacker.prototype = {
-
-		constructor: PMREMCubeUVPacker,
-
-		update: function ( renderer ) {
-
-			var size = this.cubeLods[ 0 ].width * 4;
-			// top and bottom are swapped for some reason?
-			camera.left = - size * 0.5;
-			camera.right = size * 0.5;
-			camera.top = - size * 0.5;
-			camera.bottom = size * 0.5;
-			camera.near = 0;
-			camera.far = 1;
-			camera.updateProjectionMatrix();
-
-			for ( var i = 0; i < this.objects.length; i ++ ) {
-
-				scene.add( this.objects[ i ] );
-
-			}
-
-			var gammaInput = renderer.gammaInput;
-			var gammaOutput = renderer.gammaOutput;
-			var toneMapping = renderer.toneMapping;
-			var toneMappingExposure = renderer.toneMappingExposure;
-			var currentRenderTarget = renderer.getRenderTarget();
-
-			renderer.gammaInput = false;
-			renderer.gammaOutput = false;
-			renderer.toneMapping = THREE.LinearToneMapping;
-			renderer.toneMappingExposure = 1.0;
-			renderer.setRenderTarget( this.CubeUVRenderTarget );
-			renderer.render( scene, camera );
-
-			renderer.setRenderTarget( currentRenderTarget );
-			renderer.toneMapping = toneMapping;
-			renderer.toneMappingExposure = toneMappingExposure;
-			renderer.gammaInput = gammaInput;
-			renderer.gammaOutput = gammaOutput;
-
-			for ( var i = 0; i < this.objects.length; i ++ ) {
-
-				scene.remove( this.objects[ i ] );
-
-			}
-
-		},
-
-		dispose: function () {
-
-			for ( var i = 0, l = this.objects.length; i < l; i ++ ) {
-
-				this.objects[ i ].material.dispose();
-
-			}
-
-			this.objects[ 0 ].geometry.dispose();
-
-		}
-
-	};
-
-	function getShader() {
-
-		var shaderMaterial = new THREE.ShaderMaterial( {
-
-			uniforms: {
-				"faceIndex": { value: 0 },
-				"mapSize": { value: 0 },
-				"envMap": { value: null },
-				"testColor": { value: new THREE.Vector3( 1, 1, 1 ) }
-			},
-
-			vertexShader:
-        "precision highp float;\
-        varying vec2 vUv;\
-        void main() {\
-          vUv = uv;\
-          gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\
-        }",
-
-			fragmentShader:
-        "precision highp float;\
-        varying vec2 vUv;\
-        uniform samplerCube envMap;\
-        uniform float mapSize;\
-        uniform vec3 testColor;\
-        uniform int faceIndex;\
-        \
-        void main() {\
-          vec3 sampleDirection;\
-          vec2 uv = vUv;\
-          uv = uv * 2.0 - 1.0;\
-          uv.y *= -1.0;\
-          if(faceIndex == 0) {\
-            sampleDirection = normalize(vec3(1.0, uv.y, -uv.x));\
-          } else if(faceIndex == 1) {\
-            sampleDirection = normalize(vec3(uv.x, 1.0, uv.y));\
-          } else if(faceIndex == 2) {\
-            sampleDirection = normalize(vec3(uv.x, uv.y, 1.0));\
-          } else if(faceIndex == 3) {\
-            sampleDirection = normalize(vec3(-1.0, uv.y, uv.x));\
-          } else if(faceIndex == 4) {\
-            sampleDirection = normalize(vec3(uv.x, -1.0, -uv.y));\
-          } else {\
-            sampleDirection = normalize(vec3(-uv.x, uv.y, -1.0));\
-          }\
-          vec4 color = envMapTexelToLinear( textureCube( envMap, sampleDirection ) );\
-          gl_FragColor = linearToOutputTexel( color );\
-        }",
-
-			blending: THREE.NoBlending
-
-		} );
-
-		shaderMaterial.type = 'PMREMCubeUVPacker';
-
-		return shaderMaterial;
-
-	}
-
-
-	return PMREMCubeUVPacker;
-
-} )();

+ 706 - 224
examples/js/pmrem/PMREMGenerator.js

@@ -1,293 +1,775 @@
 /**
- * @author Prashant Sharma / spidersharma03
- * @author Ben Houston / bhouston, https://clara.io
+ * @author Emmett Lalish / elalish
  *
- * To avoid cube map seams, I create an extra pixel around each face. This way when the cube map is
- * sampled by an application later(with a little care by sampling the centre of the texel), the extra 1 border
- *	of pixels makes sure that there is no seams artifacts present. This works perfectly for cubeUV format as
- *	well where the 6 faces can be arranged in any manner whatsoever.
- * Code in the beginning of fragment shader's main function does this job for a given resolution.
- *	Run Scene_PMREM_Test.html in the examples directory to see the sampling from the cube lods generated
- *	by this class.
+ * This class generates a Prefiltered, Mipmapped Radiance Environment Map
+ * (PMREM) from a cubeMap environment texture. This allows different levels of
+ * blur to be quickly accessed based on material roughness. It is packed into a
+ * special CubeUV format that allows us to perform custom interpolation so that
+ * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap
+ * chain, it only goes down to the LOD_MIN level (above), and then creates extra
+ * even more filtered 'mips' at the same LOD_MIN resolution, associated with
+ * higher roughness levels. In this way we maintain resolution to smoothly
+ * interpolate diffuse lighting while limiting sampling computation.
  */
 
 THREE.PMREMGenerator = ( function () {
 
-	var shader = getShader();
-	var camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0.0, 1000 );
-	var scene = new THREE.Scene();
-	var planeMesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2, 0 ), shader );
-	planeMesh.material.side = THREE.DoubleSide;
-	scene.add( planeMesh );
-	scene.add( camera );
+	var LOD_MIN = 4;
+	var LOD_MAX = 8;
+	var SIZE_MAX = Math.pow( 2, LOD_MAX );
+	// The standard deviations (radians) associated with the extra mips. These are
+	// chosen to approximate a Trowbridge-Reitz distribution function times the
+	// geometric shadowing function. These sigma values squared must match the
+	// variance #defines in cube_uv_reflection_fragment.glsl.js.
+	var EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ];
+	var TOTAL_LODS = LOD_MAX - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length;
+	// The maximum length of the blur for loop. Smaller sigmas will use fewer
+	// samples and exit early, but not recompile the shader.
+	var MAX_SAMPLES = 20;
+	var ENCODINGS = {
+		[ THREE.LinearEncoding ]: 0,
+		[ THREE.sRGBEncoding ]: 1,
+		[ THREE.RGBEEncoding ]: 2,
+		[ THREE.RGBM7Encoding ]: 3,
+		[ THREE.RGBM16Encoding ]: 4,
+		[ THREE.RGBDEncoding ]: 5,
+		[ THREE.GammaEncoding ]: 6
+	  };
+
+	var _flatCamera = new THREE.OrthographicCamera();
+	var _blurMaterial = _getBlurShader( MAX_SAMPLES );
+	var _equirectShader = null;
+	var _cubemapShader = null;
+
+	var { _lodPlanes, _sizeLods, _sigmas } = _createPlanes();
+	var _pingPongRenderTarget = null;
+	var _renderer = null;
+
+	// Golden Ratio
+	var PHI = ( 1 + Math.sqrt( 5 ) ) / 2;
+	var INV_PHI = 1 / PHI;
+	// Vertices of a dodecahedron (except the opposites, which represent the
+	// same axis), used as axis directions evenly spread on a sphere.
+	var _axisDirections = [
+		new THREE.Vector3( 1, 1, 1 ),
+		new THREE.Vector3( - 1, 1, 1 ),
+		new THREE.Vector3( 1, 1, - 1 ),
+		new THREE.Vector3( - 1, 1, - 1 ),
+		new THREE.Vector3( 0, PHI, INV_PHI ),
+		new THREE.Vector3( 0, PHI, - INV_PHI ),
+		new THREE.Vector3( INV_PHI, 0, PHI ),
+		new THREE.Vector3( - INV_PHI, 0, PHI ),
+		new THREE.Vector3( PHI, INV_PHI, 0 ),
+		new THREE.Vector3( - PHI, INV_PHI, 0 ) ];
+
+	var PMREMGenerator = function ( renderer ) {
+
+		_renderer = renderer;
 
-	var PMREMGenerator = function ( sourceTexture, samplesPerLevel, resolution ) {
+	};
+
+	PMREMGenerator.prototype = {
+
+		constructor: PMREMGenerator,
+
+		/**
+		 * Generates a PMREM from a supplied Scene, which can be faster than using an
+		 * image if networking bandwidth is low. Optional sigma specifies a blur radius
+		 * in radians to be applied to the scene before PMREM generation. Optional near
+		 * and far planes ensure the scene is rendered in its entirety (the cubeCamera
+		 * is placed at the origin).
+		 */
+		fromScene: function ( scene, sigma = 0, near = 0.1, far = 100 ) {
+
+			var cubeUVRenderTarget = _allocateTargets();
+			_sceneToCubeUV( scene, near, far, cubeUVRenderTarget );
+			if ( sigma > 0 ) {
+
+				_blur( cubeUVRenderTarget, 0, 0, sigma );
+
+			}
+			_applyPMREM( cubeUVRenderTarget );
+			_cleanup();
+			cubeUVRenderTarget.scissorTest = false;
+
+			return cubeUVRenderTarget;
+
+		},
+
+		/**
+		 * Generates a PMREM from an equirectangular texture, which can be either LDR
+		 * (RGBFormat) or HDR (RGBEFormat). The ideal input image size is 1k (1024 x 512),
+		 * as this matches best with the 256 x 256 cubemap output.
+		 */
+		fromEquirectangular: function ( equirectangular ) {
+
+			equirectangular.magFilter = THREE.NearestFilter;
+			equirectangular.minFilter = THREE.NearestFilter;
+			equirectangular.generateMipmaps = false;
+
+			return this.fromCubemap( equirectangular );
+
+		},
+
+		/**
+		 * Generates a PMREM from an cubemap texture, which can be either LDR
+		 * (RGBFormat) or HDR (RGBEFormat). The ideal input cube size is 256 x 256,
+		 * as this matches best with the 256 x 256 cubemap output.
+		 */
+		fromCubemap: function ( cubemap ) {
+
+			var cubeUVRenderTarget = _allocateTargets( cubemap );
+			_textureToCubeUV( cubemap, cubeUVRenderTarget );
+			_applyPMREM( cubeUVRenderTarget );
+			_cleanup();
+			cubeUVRenderTarget.scissorTest = false;
+
+			return cubeUVRenderTarget;
+
+		},
+
+		/**
+		 * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class,
+		 * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on
+		 * one of them will cause any others to also become unusable.
+		 */
+		dispose: function () {
+
+			_blurMaterial.dispose();
+			if ( _cubemapShader != null ) _cubemapShader.dispose();
+			if ( _equirectShader != null ) _equirectShader.dispose();
+			var plane;
+			for ( plane of _lodPlanes ) {
+
+				plane.dispose();
+
+			}
+
+		},
+
+	};
+
+	function _createPlanes() {
+
+		var _lodPlanes = [];
+		var _sizeLods = [];
+		var _sigmas = [];
 
-		this.sourceTexture = sourceTexture;
-		this.resolution = ( resolution !== undefined ) ? resolution : 256; // NODE: 256 is currently hard coded in the glsl code for performance reasons
-		this.samplesPerLevel = ( samplesPerLevel !== undefined ) ? samplesPerLevel : 32;
+		var lod = LOD_MAX;
+		for ( var i = 0; i < TOTAL_LODS; i ++ ) {
 
-		var monotonicEncoding = ( this.sourceTexture.encoding === THREE.LinearEncoding ) ||
-			( this.sourceTexture.encoding === THREE.GammaEncoding ) || ( this.sourceTexture.encoding === THREE.sRGBEncoding );
+			var sizeLod = Math.pow( 2, lod );
+			_sizeLods.push( sizeLod );
+			var sigma = 1.0 / sizeLod;
+			if ( i > LOD_MAX - LOD_MIN ) {
 
-		this.sourceTexture.minFilter = ( monotonicEncoding ) ? THREE.LinearFilter : THREE.NearestFilter;
-		this.sourceTexture.magFilter = ( monotonicEncoding ) ? THREE.LinearFilter : THREE.NearestFilter;
-		this.sourceTexture.generateMipmaps = this.sourceTexture.generateMipmaps && monotonicEncoding;
+				sigma = EXTRA_LOD_SIGMA[ i - LOD_MAX + LOD_MIN - 1 ];
 
-		this.cubeLods = [];
+			} else if ( i == 0 ) {
+
+				sigma = 0;
+
+			}
+			_sigmas.push( sigma );
+
+			var texelSize = 1.0 / ( sizeLod - 1 );
+			var min = - texelSize / 2;
+			var max = 1 + texelSize / 2;
+			var uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ];
+
+			var cubeFaces = 6;
+			var vertices = 6;
+			var positionSize = 3;
+			var uvSize = 2;
+			var faceIndexSize = 1;
+
+			var position = new Float32Array( positionSize * vertices * cubeFaces );
+			var uv = new Float32Array( uvSize * vertices * cubeFaces );
+			var faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces );
+
+			for ( var face = 0; face < cubeFaces; face ++ ) {
+
+				var x = ( face % 3 ) * 2 / 3 - 1;
+				var y = face > 2 ? 0 : - 1;
+				var coordinates = [
+					[ x, y, 0 ],
+					[ x + 2 / 3, y, 0 ],
+					[ x + 2 / 3, y + 1, 0 ],
+					[ x, y, 0 ],
+					[ x + 2 / 3, y + 1, 0 ],
+					[ x, y + 1, 0 ]
+				];
+				position.set( [].concat( ...coordinates ),
+					positionSize * vertices * face );
+				uv.set( uv1, uvSize * vertices * face );
+				var fill = [ face, face, face, face, face, face ];
+				faceIndex.set( fill, faceIndexSize * vertices * face );
+
+			}
+			var planes = new THREE.BufferGeometry();
+			planes.setAttribute(
+				'position', new THREE.BufferAttribute( position, positionSize ) );
+			planes.setAttribute( 'uv', new THREE.BufferAttribute( uv, uvSize ) );
+			planes.setAttribute(
+				'faceIndex', new THREE.BufferAttribute( faceIndex, faceIndexSize ) );
+			_lodPlanes.push( planes );
+
+			if ( lod > LOD_MIN ) {
+
+				lod --;
+
+			}
+
+		}
+		return { _lodPlanes, _sizeLods, _sigmas };
+
+	}
+
+	function _allocateTargets( equirectangular ) {
 
-		var size = this.resolution;
 		var params = {
-			format: this.sourceTexture.format,
-			magFilter: this.sourceTexture.magFilter,
-			minFilter: this.sourceTexture.minFilter,
-			type: this.sourceTexture.type,
-			generateMipmaps: this.sourceTexture.generateMipmaps,
-			anisotropy: this.sourceTexture.anisotropy,
-			encoding: this.sourceTexture.encoding
+		  magFilter: THREE.NearestFilter,
+		  minFilter: THREE.NearestFilter,
+		  generateMipmaps: false,
+		  type: equirectangular ? equirectangular.type : THREE.UnsignedByteType,
+		  format: equirectangular ? equirectangular.format : THREE.RGBEFormat,
+		  encoding: equirectangular ? equirectangular.encoding : THREE.RGBEEncoding,
+		  depthBuffer: false,
+		  stencilBuffer: false
 		};
+		var cubeUVRenderTarget = _createRenderTarget(
+			{ ...params, depthBuffer: ( equirectangular ? false : true ) } );
+		_pingPongRenderTarget = _createRenderTarget( params );
+		return cubeUVRenderTarget;
+
+	}
+
+	function _cleanup() {
 
-		// how many LODs fit in the given CubeUV Texture.
-		this.numLods = Math.log( size ) / Math.log( 2 ) - 2; // IE11 doesn't support Math.log2
+		_pingPongRenderTarget.dispose();
+		_renderer.setRenderTarget( null );
+		var size = _renderer.getSize( new THREE.Vector2() );
+		_renderer.setViewport( 0, 0, size.x, size.y );
 
-		for ( var i = 0; i < this.numLods; i ++ ) {
+	}
 
-			var renderTarget = new THREE.WebGLRenderTargetCube( size, size, params );
-			renderTarget.texture.name = "PMREMGenerator.cube" + i;
-			this.cubeLods.push( renderTarget );
-			size = Math.max( 16, size / 2 );
+	function _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) {
+
+		var fov = 90;
+		var aspect = 1;
+		var cubeCamera = new THREE.PerspectiveCamera( fov, aspect, near, far );
+		var upSign = [ 1, 1, 1, 1, - 1, 1 ];
+		var forwardSign = [ 1, 1, - 1, - 1, - 1, 1 ];
+
+		var gammaOutput = _renderer.gammaOutput;
+		var toneMapping = _renderer.toneMapping;
+		var toneMappingExposure = _renderer.toneMappingExposure;
+		var clearColor = _renderer.getClearColor();
+		var clearAlpha = _renderer.getClearAlpha();
+
+		_renderer.toneMapping = THREE.LinearToneMapping;
+		_renderer.toneMappingExposure = 1.0;
+		_renderer.gammaOutput = false;
+		scene.scale.z *= - 1;
+
+		var background = scene.background;
+		if ( background && background.isColor ) {
+
+			background.convertSRGBToLinear();
+			// Convert linear to RGBE
+			var maxComponent = Math.max( background.r, background.g, background.b );
+			var fExp = Math.min( Math.max( Math.ceil( Math.log2( maxComponent ) ), - 128.0 ), 127.0 );
+			background = background.multiplyScalar( Math.pow( 2.0, - fExp ) );
+			var alpha = ( fExp + 128.0 ) / 255.0;
+			_renderer.setClearColor( background, alpha );
+			scene.background = null;
 
 		}
 
-	};
+		_renderer.setRenderTarget( cubeUVRenderTarget );
+		for ( var i = 0; i < 6; i ++ ) {
 
-	PMREMGenerator.prototype = {
+			var col = i % 3;
+			if ( col == 0 ) {
 
-		constructor: PMREMGenerator,
+				cubeCamera.up.set( 0, upSign[ i ], 0 );
+				cubeCamera.lookAt( forwardSign[ i ], 0, 0 );
 
-		/*
-		 * Prashant Sharma / spidersharma03: More thought and work is needed here.
-		 * Right now it's a kind of a hack to use the previously convolved map to convolve the current one.
-		 * I tried to use the original map to convolve all the lods, but for many textures(specially the high frequency)
-		 * even a high number of samples(1024) dosen't lead to satisfactory results.
-		 * By using the previous convolved maps, a lower number of samples are generally sufficient(right now 32, which
-		 * gives okay results unless we see the reflection very carefully, or zoom in too much), however the math
-		 * goes wrong as the distribution function tries to sample a larger area than what it should be. So I simply scaled
-		 * the roughness by 0.9(totally empirical) to try to visually match the original result.
-		 * The condition "if(i <5)" is also an attemt to make the result match the original result.
-		 * This method requires the most amount of thinking I guess. Here is a paper which we could try to implement in future::
-		 * https://developer.nvidia.com/gpugems/GPUGems3/gpugems3_ch20.html
-		 */
-		update: function ( renderer ) {
+			} else if ( col == 1 ) {
+
+				cubeCamera.up.set( 0, 0, upSign[ i ] );
+				cubeCamera.lookAt( 0, forwardSign[ i ], 0 );
 
-			// Texture should only be flipped for CubeTexture, not for
-			// a Texture created via THREE.WebGLRenderTargetCube.
-			var tFlip = ( this.sourceTexture.isCubeTexture ) ? - 1 : 1;
+			} else {
 
-			shader.defines[ 'SAMPLES_PER_LEVEL' ] = this.samplesPerLevel;
-			shader.uniforms[ 'faceIndex' ].value = 0;
-			shader.uniforms[ 'envMap' ].value = this.sourceTexture;
-			shader.envMap = this.sourceTexture;
-			shader.needsUpdate = true;
+				cubeCamera.up.set( 0, upSign[ i ], 0 );
+				cubeCamera.lookAt( 0, 0, forwardSign[ i ] );
+
+			}
+			_setViewport(
+				col * SIZE_MAX, i > 2 ? SIZE_MAX : 0, SIZE_MAX, SIZE_MAX );
+			_renderer.render( scene, cubeCamera );
 
-			var gammaInput = renderer.gammaInput;
-			var gammaOutput = renderer.gammaOutput;
-			var toneMapping = renderer.toneMapping;
-			var toneMappingExposure = renderer.toneMappingExposure;
-			var currentRenderTarget = renderer.getRenderTarget();
+		}
 
-			renderer.toneMapping = THREE.LinearToneMapping;
-			renderer.toneMappingExposure = 1.0;
-			renderer.gammaInput = false;
-			renderer.gammaOutput = false;
+		_renderer.toneMapping = toneMapping;
+		_renderer.toneMappingExposure = toneMappingExposure;
+		_renderer.gammaOutput = gammaOutput;
+		_renderer.setClearColor( clearColor, clearAlpha );
+		scene.scale.z *= - 1;
 
-			for ( var i = 0; i < this.numLods; i ++ ) {
+	}
 
-				var r = i / ( this.numLods - 1 );
-				shader.uniforms[ 'roughness' ].value = r * 0.9; // see comment above, pragmatic choice
-				// Only apply the tFlip for the first LOD
-				shader.uniforms[ 'tFlip' ].value = ( i == 0 ) ? tFlip : 1;
-				var size = this.cubeLods[ i ].width;
-				shader.uniforms[ 'mapSize' ].value = size;
-				this.renderToCubeMapTarget( renderer, this.cubeLods[ i ] );
+	function _textureToCubeUV( texture, cubeUVRenderTarget ) {
 
-				if ( i < 5 ) shader.uniforms[ 'envMap' ].value = this.cubeLods[ i ].texture;
+		var scene = new THREE.Scene();
+		if ( texture.isCubeTexture ) {
 
-			}
+			if ( _cubemapShader == null ) {
 
-			renderer.setRenderTarget( currentRenderTarget );
-			renderer.toneMapping = toneMapping;
-			renderer.toneMappingExposure = toneMappingExposure;
-			renderer.gammaInput = gammaInput;
-			renderer.gammaOutput = gammaOutput;
+				_cubemapShader = _getCubemapShader();
 
-		},
+			}
 
-		renderToCubeMapTarget: function ( renderer, renderTarget ) {
+		} else {
 
-			for ( var i = 0; i < 6; i ++ ) {
+			if ( _equirectShader == null ) {
 
-				this.renderToCubeMapTargetFace( renderer, renderTarget, i );
+				_equirectShader = _getEquirectShader();
 
 			}
 
-		},
+		}
+		var material = texture.isCubeTexture ? _cubemapShader : _equirectShader;
+		scene.add( new THREE.Mesh( _lodPlanes[ 0 ], material ) );
+		var uniforms = material.uniforms;
 
-		renderToCubeMapTargetFace: function ( renderer, renderTarget, faceIndex ) {
+		uniforms[ 'envMap' ].value = texture;
+		if ( ! texture.isCubeTexture ) {
 
-			shader.uniforms[ 'faceIndex' ].value = faceIndex;
-			renderer.setRenderTarget( renderTarget, faceIndex );
-			renderer.clear();
-			renderer.render( scene, camera );
+			uniforms[ 'texelSize' ].value.set( 1.0 / texture.image.width, 1.0 / texture.image.height );
 
-		},
+		}
+		uniforms[ 'inputEncoding' ].value = ENCODINGS[ texture.encoding ];
+		uniforms[ 'outputEncoding' ].value = ENCODINGS[ texture.encoding ];
 
-		dispose: function () {
+		_renderer.setRenderTarget( cubeUVRenderTarget );
+		_setViewport( 0, 0, 3 * SIZE_MAX, 2 * SIZE_MAX );
+		_renderer.render( scene, _flatCamera );
+
+	}
+
+	function _createRenderTarget( params ) {
+
+		var cubeUVRenderTarget =
+		new THREE.WebGLRenderTarget( 3 * SIZE_MAX, 3 * SIZE_MAX, params );
+		cubeUVRenderTarget.texture.mapping = THREE.CubeUVReflectionMapping;
+		cubeUVRenderTarget.texture.name = 'PMREM.cubeUv';
+		cubeUVRenderTarget.scissorTest = true;
+		return cubeUVRenderTarget;
 
-			for ( var i = 0, l = this.cubeLods.length; i < l; i ++ ) {
+	}
+
+	function _setViewport( x, y, width, height ) {
+
+		var invDpr = 1.0 / _renderer.getPixelRatio();
+		x *= invDpr;
+		y *= invDpr;
+		width *= invDpr;
+		height *= invDpr;
+		_renderer.setViewport( x, y, width, height );
+		_renderer.setScissor( x, y, width, height );
+
+	}
+
+	function _applyPMREM( cubeUVRenderTarget ) {
+
+		var autoClear = _renderer.autoClear;
+		_renderer.autoClear = false;
+
+	  	for ( var i = 1; i < TOTAL_LODS; i ++ ) {
+
+			var sigma = Math.sqrt(
+				_sigmas[ i ] * _sigmas[ i ] -
+			_sigmas[ i - 1 ] * _sigmas[ i - 1 ] );
+			var poleAxis =
+			_axisDirections[ ( i - 1 ) % _axisDirections.length ];
+			_blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis );
+
+		}
+
+		_renderer.autoClear = autoClear;
+
+	}
+
+	/**
+   * This is a two-pass Gaussian blur for a cubemap. Normally this is done
+   * vertically and horizontally, but this breaks down on a cube. Here we apply
+   * the blur latitudinally (around the poles), and then longitudinally (towards
+   * the poles) to approximate the orthogonally-separable blur. It is least
+   * accurate at the poles, but still does a decent job.
+   */
+	function _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) {
+
+		_halfBlur(
+			cubeUVRenderTarget,
+			_pingPongRenderTarget,
+			lodIn,
+			lodOut,
+			sigma,
+			'latitudinal',
+			poleAxis );
+
+		_halfBlur(
+			_pingPongRenderTarget,
+			cubeUVRenderTarget,
+			lodOut,
+			lodOut,
+			sigma,
+			'longitudinal',
+			poleAxis );
 
-				this.cubeLods[ i ].dispose();
+	}
+
+	function _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) {
+
+		if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) {
+
+			console.error(
+				'blur direction must be either latitudinal or longitudinal!' );
+
+		}
+
+		// Number of standard deviations at which to cut off the discrete approximation.
+		var STANDARD_DEVIATIONS = 3;
+
+		var blurScene = new THREE.Scene();
+		blurScene.add( new THREE.Mesh( _lodPlanes[ lodOut ], _blurMaterial ) );
+		var blurUniforms = _blurMaterial.uniforms;
+
+		var pixels = _sizeLods[ lodIn ] - 1;
+		var radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 );
+		var sigmaPixels = sigmaRadians / radiansPerPixel;
+		var samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES;
+
+		if ( samples > MAX_SAMPLES ) {
+
+			console.warn( `sigmaRadians, ${
+				sigmaRadians}, is too large and will clip, as it requested ${
+				samples} samples when the maximum is set to ${MAX_SAMPLES}` );
+
+		}
+
+		var weights = [];
+		var sum = 0;
+		for ( var i = 0; i < MAX_SAMPLES; ++ i ) {
+
+			var x = i / sigmaPixels;
+			var weight = Math.exp( - x * x / 2 );
+			weights.push( weight );
+			if ( i == 0 ) {
+
+	  			 sum += weight;
+
+			} else if ( i < samples ) {
+
+	  			sum += 2 * weight;
 
 			}
 
-			shader.dispose();
+		}
+		weights = weights.map( w => w / sum );
 
-		},
+		blurUniforms[ 'envMap' ].value = targetIn.texture;
+		blurUniforms[ 'samples' ].value = samples;
+		blurUniforms[ 'weights' ].value = weights;
+		blurUniforms[ 'latitudinal' ].value = direction === 'latitudinal';
+		if ( poleAxis ) {
 
-	};
+			blurUniforms[ 'poleAxis' ].value = poleAxis;
+
+		}
+		blurUniforms[ 'dTheta' ].value = radiansPerPixel;
+		blurUniforms[ 'mipInt' ].value = LOD_MAX - lodIn;
+		blurUniforms[ 'inputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
+		blurUniforms[ 'outputEncoding' ].value = ENCODINGS[ targetIn.texture.encoding ];
+
+		var outputSize = _sizeLods[ lodOut ];
+		var x = 3 * Math.max( 0, SIZE_MAX - 2 * outputSize );
+		var y = ( lodOut === 0 ? 0 : 2 * SIZE_MAX ) +
+	  2 * outputSize *
+		  ( lodOut > LOD_MAX - LOD_MIN ? lodOut - LOD_MAX + LOD_MIN : 0 );
 
-	function getShader() {
+		_renderer.setRenderTarget( targetOut );
+		_setViewport( x, y, 3 * outputSize, 2 * outputSize );
+		_renderer.render( blurScene, _flatCamera );
 
-		var shaderMaterial = new THREE.ShaderMaterial( {
+	}
+
+	function _getBlurShader( maxSamples ) {
+
+		var weights = new Float32Array( maxSamples );
+		var poleAxis = new THREE.Vector3( 0, 1, 0 );
+		var shaderMaterial = new THREE.RawShaderMaterial( {
 
-			defines: {
-				"SAMPLES_PER_LEVEL": 20,
+			defines: { 'n': maxSamples },
+
+			uniforms: {
+				'envMap': { value: null },
+				'samples': { value: 1 },
+				'weights': { value: weights },
+				'latitudinal': { value: false },
+				'dTheta': { value: 0 },
+				'mipInt': { value: 0 },
+				'poleAxis': { value: poleAxis },
+				'inputEncoding': { value: ENCODINGS[ THREE.LinearEncoding ] },
+				'outputEncoding': { value: ENCODINGS[ THREE.LinearEncoding ] }
 			},
 
+			vertexShader: _getCommonVertexShader(),
+
+			fragmentShader: `
+precision mediump float;
+precision mediump int;
+varying vec3 vOutputDirection;
+uniform sampler2D envMap;
+uniform int samples;
+uniform float weights[n];
+uniform bool latitudinal;
+uniform float dTheta;
+uniform float mipInt;
+uniform vec3 poleAxis;
+
+${_getEncodings()}
+
+#define ENVMAP_TYPE_CUBE_UV
+#include <cube_uv_reflection_fragment>
+
+void main() {
+	gl_FragColor = vec4(0.0);
+    for (int i = 0; i < n; i++) {
+      if (i >= samples)
+        break;
+      for (int dir = -1; dir < 2; dir += 2) {
+        if (i == 0 && dir == 1)
+          continue;
+        vec3 axis = latitudinal ? poleAxis : cross(poleAxis, vOutputDirection);
+        if (all(equal(axis, vec3(0.0))))
+          axis = cross(vec3(0.0, 1.0, 0.0), vOutputDirection);
+        axis = normalize(axis);
+        float theta = dTheta * float(dir * i);
+        float cosTheta = cos(theta);
+        // Rodrigues' axis-angle rotation
+        vec3 sampleDirection = vOutputDirection * cosTheta 
+            + cross(axis, vOutputDirection) * sin(theta) 
+            + axis * dot(axis, vOutputDirection) * (1.0 - cosTheta);
+        gl_FragColor.rgb +=
+            weights[i] * bilinearCubeUV(envMap, sampleDirection, mipInt);
+      }
+    }
+  	gl_FragColor = linearToOutputTexel(gl_FragColor);
+}
+     		`,
+
+			blending: THREE.NoBlending,
+			depthTest: false,
+	   		depthWrite: false
+
+		} );
+
+		shaderMaterial.type = 'SphericalGaussianBlur';
+
+		return shaderMaterial;
+
+	}
+
+	function _getEquirectShader() {
+
+		var texelSize = new THREE.Vector2( 1, 1 );
+		var shaderMaterial = new THREE.RawShaderMaterial( {
+
 			uniforms: {
-				"faceIndex": { value: 0 },
-				"roughness": { value: 0.5 },
-				"mapSize": { value: 0.5 },
-				"envMap": { value: null },
-				"tFlip": { value: - 1 },
+				'envMap': { value: null },
+				'texelSize': { value: texelSize },
+				'inputEncoding': { value: ENCODINGS[ THREE.LinearEncoding ] },
+				'outputEncoding': { value: ENCODINGS[ THREE.LinearEncoding ] }
 			},
 
-			vertexShader:
-				"varying vec2 vUv;\n\
-				void main() {\n\
-					vUv = uv;\n\
-					gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\
-				}",
-
-			fragmentShader:
-				"#include <common>\n\
-				varying vec2 vUv;\n\
-				uniform int faceIndex;\n\
-				uniform float roughness;\n\
-				uniform samplerCube envMap;\n\
-				uniform float mapSize;\n\
-				uniform float tFlip;\n\
-				\n\
-				float GGXRoughnessToBlinnExponent( const in float ggxRoughness ) {\n\
-					float a = ggxRoughness + 0.0001;\n\
-					a *= a;\n\
-					return ( 2.0 / a - 2.0 );\n\
-				}\n\
-				vec3 ImportanceSamplePhong(vec2 uv, mat3 vecSpace, float specPow) {\n\
-					float phi = uv.y * 2.0 * PI;\n\
-					float cosTheta = pow(1.0 - uv.x, 1.0 / (specPow + 1.0));\n\
-					float sinTheta = sqrt(1.0 - cosTheta * cosTheta);\n\
-					vec3 sampleDir = vec3(cos(phi) * sinTheta, sin(phi) * sinTheta, cosTheta);\n\
-					return vecSpace * sampleDir;\n\
-				}\n\
-				vec3 ImportanceSampleGGX( vec2 uv, mat3 vecSpace, float Roughness )\n\
-				{\n\
-					float a = Roughness * Roughness;\n\
-					float Phi = 2.0 * PI * uv.x;\n\
-					float CosTheta = sqrt( (1.0 - uv.y) / ( 1.0 + (a*a - 1.0) * uv.y ) );\n\
-					float SinTheta = sqrt( 1.0 - CosTheta * CosTheta );\n\
-					return vecSpace * vec3(SinTheta * cos( Phi ), SinTheta * sin( Phi ), CosTheta);\n\
-				}\n\
-				mat3 matrixFromVector(vec3 n) {\n\
-					float a = 1.0 / (1.0 + n.z);\n\
-					float b = -n.x * n.y * a;\n\
-					vec3 b1 = vec3(1.0 - n.x * n.x * a, b, -n.x);\n\
-					vec3 b2 = vec3(b, 1.0 - n.y * n.y * a, -n.y);\n\
-					return mat3(b1, b2, n);\n\
-				}\n\
-				\n\
-				vec4 testColorMap(float Roughness) {\n\
-					vec4 color;\n\
-					if(faceIndex == 0)\n\
-						color = vec4(1.0,0.0,0.0,1.0);\n\
-					else if(faceIndex == 1)\n\
-						color = vec4(0.0,1.0,0.0,1.0);\n\
-					else if(faceIndex == 2)\n\
-						color = vec4(0.0,0.0,1.0,1.0);\n\
-					else if(faceIndex == 3)\n\
-						color = vec4(1.0,1.0,0.0,1.0);\n\
-					else if(faceIndex == 4)\n\
-						color = vec4(0.0,1.0,1.0,1.0);\n\
-					else\n\
-						color = vec4(1.0,0.0,1.0,1.0);\n\
-					color *= ( 1.0 - Roughness );\n\
-					return color;\n\
-				}\n\
-				void main() {\n\
-					vec3 sampleDirection;\n\
-					vec2 uv = vUv*2.0 - 1.0;\n\
-					float offset = -1.0/mapSize;\n\
-					const float a = -1.0;\n\
-					const float b = 1.0;\n\
-					float c = -1.0 + offset;\n\
-					float d = 1.0 - offset;\n\
-					float bminusa = b - a;\n\
-					uv.x = (uv.x - a)/bminusa * d - (uv.x - b)/bminusa * c;\n\
-					uv.y = (uv.y - a)/bminusa * d - (uv.y - b)/bminusa * c;\n\
-					if (faceIndex==0) {\n\
-						sampleDirection = vec3(1.0, -uv.y, -uv.x);\n\
-					} else if (faceIndex==1) {\n\
-						sampleDirection = vec3(-1.0, -uv.y, uv.x);\n\
-					} else if (faceIndex==2) {\n\
-						sampleDirection = vec3(uv.x, 1.0, uv.y);\n\
-					} else if (faceIndex==3) {\n\
-						sampleDirection = vec3(uv.x, -1.0, -uv.y);\n\
-					} else if (faceIndex==4) {\n\
-						sampleDirection = vec3(uv.x, -uv.y, 1.0);\n\
-					} else {\n\
-						sampleDirection = vec3(-uv.x, -uv.y, -1.0);\n\
-					}\n\
-					vec3 correctedDirection = vec3( tFlip * sampleDirection.x, sampleDirection.yz );\n\
-					mat3 vecSpace = matrixFromVector( normalize( correctedDirection ) );\n\
-					vec3 rgbColor = vec3(0.0);\n\
-					const int NumSamples = SAMPLES_PER_LEVEL;\n\
-					vec3 vect;\n\
-					float weight = 0.0;\n\
-					for( int i = 0; i < NumSamples; i ++ ) {\n\
-						float sini = sin(float(i));\n\
-						float cosi = cos(float(i));\n\
-						float r = rand(vec2(sini, cosi));\n\
-						vect = ImportanceSampleGGX(vec2(float(i) / float(NumSamples), r), vecSpace, roughness);\n\
-						float dotProd = dot(vect, normalize(sampleDirection));\n\
-						weight += dotProd;\n\
-						vec3 color = envMapTexelToLinear(textureCube(envMap, vect)).rgb;\n\
-						rgbColor.rgb += color;\n\
-					}\n\
-					rgbColor /= float(NumSamples);\n\
-					//rgbColor = testColorMap( roughness ).rgb;\n\
-					gl_FragColor = linearToOutputTexel( vec4( rgbColor, 1.0 ) );\n\
-				}",
-
-			blending: THREE.NoBlending
+			vertexShader: _getCommonVertexShader(),
+
+			fragmentShader: `
+precision mediump float;
+precision mediump int;
+varying vec3 vOutputDirection;
+uniform sampler2D envMap;
+uniform vec2 texelSize;
+
+${_getEncodings()}
+
+#define RECIPROCAL_PI 0.31830988618
+#define RECIPROCAL_PI2 0.15915494
+
+void main() {
+	gl_FragColor = vec4(0.0);
+	vec3 outputDirection = normalize(vOutputDirection);
+	vec2 uv;
+	uv.y = asin(clamp(outputDirection.y, -1.0, 1.0)) * RECIPROCAL_PI + 0.5;
+	uv.x = atan(outputDirection.z, outputDirection.x) * RECIPROCAL_PI2 + 0.5;
+	vec2 f = fract(uv / texelSize - 0.5);
+	uv -= f * texelSize;
+	vec3 tl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;
+	uv.x += texelSize.x;
+	vec3 tr = envMapTexelToLinear(texture2D(envMap, uv)).rgb;
+	uv.y += texelSize.y;
+	vec3 br = envMapTexelToLinear(texture2D(envMap, uv)).rgb;
+	uv.x -= texelSize.x;
+	vec3 bl = envMapTexelToLinear(texture2D(envMap, uv)).rgb;
+	vec3 tm = mix(tl, tr, f.x);
+	vec3 bm = mix(bl, br, f.x);
+	gl_FragColor.rgb = mix(tm, bm, f.y);
+  	gl_FragColor = linearToOutputTexel(gl_FragColor);
+}
+     		`,
+
+			blending: THREE.NoBlending,
+			depthTest: false,
+	   		depthWrite: false
 
 		} );
 
-		shaderMaterial.type = 'PMREMGenerator';
+		shaderMaterial.type = 'EquirectangularToCubeUV';
 
 		return shaderMaterial;
 
 	}
 
+	function _getCubemapShader() {
+
+		var shaderMaterial = new THREE.RawShaderMaterial( {
+
+			uniforms: {
+				'envMap': { value: null },
+				'inputEncoding': { value: ENCODINGS[ THREE.LinearEncoding ] },
+				'outputEncoding': { value: ENCODINGS[ THREE.LinearEncoding ] }
+			},
+
+			vertexShader: _getCommonVertexShader(),
+
+			fragmentShader: `
+precision mediump float;
+precision mediump int;
+varying vec3 vOutputDirection;
+uniform samplerCube envMap;
+
+${_getEncodings()}
+
+void main() {
+	gl_FragColor = vec4(0.0);
+	gl_FragColor.rgb = envMapTexelToLinear(textureCube(envMap, vec3( - vOutputDirection.x, vOutputDirection.yz ))).rgb;
+  	gl_FragColor = linearToOutputTexel(gl_FragColor);
+}
+     		`,
+
+			blending: THREE.NoBlending,
+			depthTest: false,
+	   		depthWrite: false
+
+		} );
+
+		shaderMaterial.type = 'CubemapToCubeUV';
+
+		return shaderMaterial;
+
+	}
+
+	function _getCommonVertexShader() {
+
+		return `
+precision mediump float;
+precision mediump int;
+attribute vec3 position;
+attribute vec2 uv;
+attribute float faceIndex;
+varying vec3 vOutputDirection;
+vec3 getDirection(vec2 uv, float face) {
+	uv = 2.0 * uv - 1.0;
+	vec3 direction = vec3(uv, 1.0);
+	if (face == 0.0) {
+		direction = direction.zyx;
+		direction.z *= -1.0;
+	} else if (face == 1.0) {
+		direction = direction.xzy;
+		direction.z *= -1.0;
+	} else if (face == 3.0) {
+		direction = direction.zyx;
+		direction.x *= -1.0;
+	} else if (face == 4.0) {
+		direction = direction.xzy;
+		direction.y *= -1.0;
+	} else if (face == 5.0) {
+		direction.xz *= -1.0;
+	}
+	return direction;
+}
+void main() {
+	vOutputDirection = getDirection(uv, faceIndex);
+	gl_Position = vec4( position, 1.0 );
+}
+		`;
+
+	}
+
+	function _getEncodings() {
+
+		return `
+uniform int inputEncoding;
+uniform int outputEncoding;
+
+#include <encodings_pars_fragment>
+
+vec4 inputTexelToLinear(vec4 value){
+    if(inputEncoding == 0){
+        return value;
+    }else if(inputEncoding == 1){
+        return sRGBToLinear(value);
+    }else if(inputEncoding == 2){
+        return RGBEToLinear(value);
+    }else if(inputEncoding == 3){
+        return RGBMToLinear(value, 7.0);
+    }else if(inputEncoding == 4){
+        return RGBMToLinear(value, 16.0);
+    }else if(inputEncoding == 5){
+        return RGBDToLinear(value, 256.0);
+    }else{
+        return GammaToLinear(value, 2.2);
+    }
+}
+
+vec4 linearToOutputTexel(vec4 value){
+    if(outputEncoding == 0){
+        return value;
+    }else if(outputEncoding == 1){
+        return LinearTosRGB(value);
+    }else if(outputEncoding == 2){
+        return LinearToRGBE(value);
+    }else if(outputEncoding == 3){
+        return LinearToRGBM(value, 7.0);
+    }else if(outputEncoding == 4){
+        return LinearToRGBM(value, 16.0);
+    }else if(outputEncoding == 5){
+        return LinearToRGBD(value, 256.0);
+    }else{
+        return LinearToGamma(value, 2.2);
+    }
+}
+
+vec4 envMapTexelToLinear(vec4 color) {
+  return inputTexelToLinear(color);
+}
+		`;
+
+	}
+
 	return PMREMGenerator;
 
 } )();

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

@@ -44,8 +44,8 @@ THREE.CubeTexturePass.prototype = Object.assign( Object.create( THREE.Pass.proto
 		this.cubeCamera.projectionMatrix.copy( this.camera.projectionMatrix );
 		this.cubeCamera.quaternion.setFromRotationMatrix( this.camera.matrixWorld );
 
-		this.cubeMesh.material.uniforms[ "tCube" ].value = this.envMap;
-		this.cubeMesh.material.uniforms[ "opacity" ].value = this.opacity;
+		this.cubeMesh.material.envMap = this.envMap;
+		this.cubeMesh.material.opacity = this.opacity;
 		this.cubeMesh.material.transparent = ( this.opacity < 1.0 );
 
 		renderer.setRenderTarget( this.renderToScreen ? null : readBuffer );

+ 9 - 3
examples/js/postprocessing/UnrealBloomPass.js

@@ -1,10 +1,16 @@
 /**
  * @author spidersharma / http://eduperiment.com/
- *
- * Inspired from Unreal Engine
- * https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/
  */
 
+/**
+ * UnrealBloomPass is inspired by the bloom pass of Unreal Engine. It creates a
+ * mip map chain of bloom textures and blurs them with different radii. Because
+ * of the weighted combination of mips, and because larger blurs are done on
+ * higher mips, this effect provides good quality and performance.
+ *
+ * Reference:
+ * - https://docs.unrealengine.com/latest/INT/Engine/Rendering/PostProcessEffects/Bloom/
+ */
 THREE.UnrealBloomPass = function ( resolution, strength, radius, threshold ) {
 
 	THREE.Pass.call( this );

+ 111 - 0
examples/js/utils/BufferGeometryUtils.js

@@ -622,6 +622,117 @@ THREE.BufferGeometryUtils = {
 
 		return result;
 
+	},
+
+	/**
+	 * @param {THREE.BufferGeometry} geometry
+	 * @param {number} drawMode
+	 * @return {THREE.BufferGeometry>}
+	 */
+	toTrianglesDrawMode: function ( geometry, drawMode ) {
+
+		if ( drawMode === THREE.TrianglesDrawMode ) {
+
+			console.warn( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Geometry already defined as triangles.' );
+			return geometry;
+
+		}
+
+		if ( drawMode === THREE.TriangleFanDrawMode || drawMode === THREE.TriangleStripDrawMode ) {
+
+			var index = geometry.getIndex();
+
+			// generate index if not present
+
+			if ( index === null ) {
+
+				var indices = [];
+
+				var position = geometry.getAttribute( 'position' );
+
+				if ( position !== undefined ) {
+
+					for ( var i = 0; i < position.count; i ++ ) {
+
+						indices.push( i );
+
+					}
+
+					geometry.setIndex( indices );
+					index = geometry.getIndex();
+
+				} else {
+
+					console.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );
+					return geometry;
+
+				}
+
+			}
+
+			//
+
+			var numberOfTriangles = index.count - 2;
+			var newIndices = [];
+
+			if ( drawMode === THREE.TriangleFanDrawMode ) {
+
+				// gl.TRIANGLE_FAN
+
+				for ( var i = 1; i <= numberOfTriangles; i ++ ) {
+
+					newIndices.push( index.getX( 0 ) );
+					newIndices.push( index.getX( i ) );
+					newIndices.push( index.getX( i + 1 ) );
+
+				}
+
+			} else {
+
+				// gl.TRIANGLE_STRIP
+
+				for ( var i = 0; i < numberOfTriangles; i ++ ) {
+
+					if ( i % 2 === 0 ) {
+
+						newIndices.push( index.getX( i ) );
+						newIndices.push( index.getX( i + 1 ) );
+						newIndices.push( index.getX( i + 2 ) );
+
+
+					} else {
+
+						newIndices.push( index.getX( i + 2 ) );
+						newIndices.push( index.getX( i + 1 ) );
+						newIndices.push( index.getX( i ) );
+
+					}
+
+				}
+
+			}
+
+			if ( ( newIndices.length / 3 ) !== numberOfTriangles ) {
+
+				console.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );
+
+			}
+
+			// build final geometry
+
+			var newGeometry = geometry.clone();
+			newGeometry.setIndex( newIndices );
+			newGeometry.clearGroups();
+
+			return newGeometry;
+
+		} else {
+
+			console.error( 'THREE.BufferGeometryUtils.toTrianglesDrawMode(): Unknown draw mode:', drawMode );
+			return geometry;
+
+		}
+
 	}
 
 };

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

@@ -5,298 +5,6 @@
 
 THREE.GeometryUtils = {
 
-	// Merge two geometries or geometry and geometry from object (using object's transform)
-
-	merge: function ( geometry1, geometry2, materialIndexOffset ) {
-
-		console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
-
-		var matrix;
-
-		if ( geometry2 instanceof THREE.Mesh ) {
-
-			geometry2.matrixAutoUpdate && geometry2.updateMatrix();
-
-			matrix = geometry2.matrix;
-			geometry2 = geometry2.geometry;
-
-		}
-
-		geometry1.merge( geometry2, matrix, materialIndexOffset );
-
-	},
-
-	// Get random point in triangle (via barycentric coordinates)
-	// 	(uniform distribution)
-	// 	http://www.cgafaq.info/wiki/Random_Point_In_Triangle
-
-	randomPointInTriangle: function () {
-
-		var vector = new THREE.Vector3();
-
-		return function ( vectorA, vectorB, vectorC ) {
-
-			var point = new THREE.Vector3();
-
-			var a = Math.random();
-			var b = Math.random();
-
-			if ( ( a + b ) > 1 ) {
-
-				a = 1 - a;
-				b = 1 - b;
-
-			}
-
-			var c = 1 - a - b;
-
-			point.copy( vectorA );
-			point.multiplyScalar( a );
-
-			vector.copy( vectorB );
-			vector.multiplyScalar( b );
-
-			point.add( vector );
-
-			vector.copy( vectorC );
-			vector.multiplyScalar( c );
-
-			point.add( vector );
-
-			return point;
-
-		};
-
-	}(),
-
-	// Get random point in face (triangle)
-	// (uniform distribution)
-
-	randomPointInFace: function ( face, geometry ) {
-
-		var vA, vB, vC;
-
-		vA = geometry.vertices[ face.a ];
-		vB = geometry.vertices[ face.b ];
-		vC = geometry.vertices[ face.c ];
-
-		return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
-
-	},
-
-	// Get uniformly distributed random points in mesh
-	// 	- create array with cumulative sums of face areas
-	//  - pick random number from 0 to total area
-	//  - find corresponding place in area array by binary search
-	//	- get random point in face
-
-	randomPointsInGeometry: function ( geometry, n ) {
-
-		var face, i,
-			faces = geometry.faces,
-			vertices = geometry.vertices,
-			il = faces.length,
-			totalArea = 0,
-			cumulativeAreas = [],
-			vA, vB, vC;
-
-		// precompute face areas
-
-		for ( i = 0; i < il; i ++ ) {
-
-			face = faces[ i ];
-
-			vA = vertices[ face.a ];
-			vB = vertices[ face.b ];
-			vC = vertices[ face.c ];
-
-			face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC );
-
-			totalArea += face._area;
-
-			cumulativeAreas[ i ] = totalArea;
-
-		}
-
-		// binary search cumulative areas array
-
-		function binarySearchIndices( value ) {
-
-			function binarySearch( start, end ) {
-
-				// return closest larger index
-				// if exact number is not found
-
-				if ( end < start )
-					return start;
-
-				var mid = start + Math.floor( ( end - start ) / 2 );
-
-				if ( cumulativeAreas[ mid ] > value ) {
-
-					return binarySearch( start, mid - 1 );
-
-				} else if ( cumulativeAreas[ mid ] < value ) {
-
-					return binarySearch( mid + 1, end );
-
-				} else {
-
-					return mid;
-
-				}
-
-			}
-
-			var result = binarySearch( 0, cumulativeAreas.length - 1 );
-			return result;
-
-		}
-
-		// pick random face weighted by face area
-
-		var r, index,
-			result = [];
-
-		var stats = {};
-
-		for ( i = 0; i < n; i ++ ) {
-
-			r = Math.random() * totalArea;
-
-			index = binarySearchIndices( r );
-
-			result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry );
-
-			if ( ! stats[ index ] ) {
-
-				stats[ index ] = 1;
-
-			} else {
-
-				stats[ index ] += 1;
-
-			}
-
-		}
-
-		return result;
-
-	},
-
-	randomPointsInBufferGeometry: function ( geometry, n ) {
-
-		var i,
-			vertices = geometry.attributes.position.array,
-			totalArea = 0,
-			cumulativeAreas = [],
-			vA, vB, vC;
-
-		// precompute face areas
-		vA = new THREE.Vector3();
-		vB = new THREE.Vector3();
-		vC = new THREE.Vector3();
-
-		// geometry._areas = [];
-		var il = vertices.length / 9;
-
-		for ( i = 0; i < il; i ++ ) {
-
-			vA.set( vertices[ i * 9 + 0 ], vertices[ i * 9 + 1 ], vertices[ i * 9 + 2 ] );
-			vB.set( vertices[ i * 9 + 3 ], vertices[ i * 9 + 4 ], vertices[ i * 9 + 5 ] );
-			vC.set( vertices[ i * 9 + 6 ], vertices[ i * 9 + 7 ], vertices[ i * 9 + 8 ] );
-
-			totalArea += THREE.GeometryUtils.triangleArea( vA, vB, vC );
-
-			cumulativeAreas.push( totalArea );
-
-		}
-
-		// binary search cumulative areas array
-
-		function binarySearchIndices( value ) {
-
-			function binarySearch( start, end ) {
-
-				// return closest larger index
-				// if exact number is not found
-
-				if ( end < start )
-					return start;
-
-				var mid = start + Math.floor( ( end - start ) / 2 );
-
-				if ( cumulativeAreas[ mid ] > value ) {
-
-					return binarySearch( start, mid - 1 );
-
-				} else if ( cumulativeAreas[ mid ] < value ) {
-
-					return binarySearch( mid + 1, end );
-
-				} else {
-
-					return mid;
-
-				}
-
-			}
-
-			var result = binarySearch( 0, cumulativeAreas.length - 1 );
-			return result;
-
-		}
-
-		// pick random face weighted by face area
-
-		var r, index,
-			result = [];
-
-		for ( i = 0; i < n; i ++ ) {
-
-			r = Math.random() * totalArea;
-
-			index = binarySearchIndices( r );
-
-			// result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );
-			vA.set( vertices[ index * 9 + 0 ], vertices[ index * 9 + 1 ], vertices[ index * 9 + 2 ] );
-			vB.set( vertices[ index * 9 + 3 ], vertices[ index * 9 + 4 ], vertices[ index * 9 + 5 ] );
-			vC.set( vertices[ index * 9 + 6 ], vertices[ index * 9 + 7 ], vertices[ index * 9 + 8 ] );
-			result[ i ] = THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
-
-		}
-
-		return result;
-
-	},
-
-	// Get triangle area (half of parallelogram)
-	// http://mathworld.wolfram.com/TriangleArea.html
-
-	triangleArea: function () {
-
-		var vector1 = new THREE.Vector3();
-		var vector2 = new THREE.Vector3();
-
-		return function ( vectorA, vectorB, vectorC ) {
-
-			vector1.subVectors( vectorB, vectorA );
-			vector2.subVectors( vectorC, vectorA );
-			vector1.cross( vector2 );
-
-			return 0.5 * vector1.length();
-
-		};
-
-	}(),
-
-	center: function ( geometry ) {
-
-		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.
 	 *

+ 5 - 5
examples/js/vr/WebVR.js

@@ -13,7 +13,7 @@ THREE.WEBVR = {
 
 		if ( options && options.referenceSpaceType ) {
 
-			renderer.vr.setReferenceSpaceType( options.referenceSpaceType );
+			renderer.xr.setReferenceSpaceType( options.referenceSpaceType );
 
 		}
 
@@ -45,7 +45,7 @@ THREE.WEBVR = {
 
 			};
 
-			renderer.vr.setDevice( device );
+			renderer.xr.setDevice( device );
 
 		}
 
@@ -57,7 +57,7 @@ THREE.WEBVR = {
 
 				session.addEventListener( 'end', onSessionEnded );
 
-				renderer.vr.setSession( session );
+				renderer.xr.setSession( session );
 				button.textContent = 'EXIT XR';
 
 				currentSession = session;
@@ -68,7 +68,7 @@ THREE.WEBVR = {
 
 				currentSession.removeEventListener( 'end', onSessionEnded );
 
-				renderer.vr.setSession( null );
+				renderer.xr.setSession( null );
 				button.textContent = 'ENTER XR';
 
 				currentSession = null;
@@ -142,7 +142,7 @@ THREE.WEBVR = {
 
 			button.textContent = 'VR NOT FOUND';
 
-			renderer.vr.setDevice( null );
+			renderer.xr.setDevice( null );
 
 		}
 

+ 1 - 16
examples/jsm/exporters/GLTFExporter.js

@@ -23,8 +23,6 @@ import {
 	RGBAFormat,
 	RepeatWrapping,
 	Scene,
-	TriangleFanDrawMode,
-	TriangleStripDrawMode,
 	Vector3
 } from "../../../build/three.module.js";
 
@@ -1199,20 +1197,7 @@ GLTFExporter.prototype = {
 
 				}
 
-				if ( mesh.drawMode === TriangleFanDrawMode ) {
-
-					console.warn( 'GLTFExporter: TriangleFanDrawMode and wireframe incompatible.' );
-					mode = WEBGL_CONSTANTS.TRIANGLE_FAN;
-
-				} else if ( mesh.drawMode === TriangleStripDrawMode ) {
-
-					mode = mesh.material.wireframe ? WEBGL_CONSTANTS.LINE_STRIP : WEBGL_CONSTANTS.TRIANGLE_STRIP;
-
-				} else {
-
-					mode = mesh.material.wireframe ? WEBGL_CONSTANTS.LINES : WEBGL_CONSTANTS.TRIANGLES;
-
-				}
+				mode = mesh.material.wireframe ? WEBGL_CONSTANTS.LINES : WEBGL_CONSTANTS.TRIANGLES;
 
 			}
 

+ 10 - 25
examples/jsm/exporters/PLYExporter.js

@@ -150,22 +150,7 @@ PLYExporter.prototype = {
 
 		}
 
-		// get how many bytes will be needed to save out the faces
-		// so we can use a minimal amount of memory / data
-		var indexByteCount = 1;
-
-		if ( vertexCount > 256 ) { // 2^8 bits
-
-			indexByteCount = 2;
-
-		}
-
-		if ( vertexCount > 65536 ) { // 2^16 bits
-
-			indexByteCount = 4;
-
-		}
-
+		var indexByteCount = 4;
 
 		var header =
 			'ply\n' +
@@ -211,7 +196,7 @@ PLYExporter.prototype = {
 			// faces
 			header +=
 				`element face ${faceCount}\n` +
-				`property list uchar uint${ indexByteCount * 8 } vertex_index\n`;
+				`property list uchar int vertex_index\n`;
 
 		}
 
@@ -365,7 +350,7 @@ PLYExporter.prototype = {
 				if ( includeIndices === true ) {
 
 					// Create the face list
-					var faceIndexFunc = `setUint${indexByteCount * 8}`;
+
 					if ( indices !== null ) {
 
 						for ( var i = 0, l = indices.count; i < l; i += 3 ) {
@@ -373,13 +358,13 @@ PLYExporter.prototype = {
 							output.setUint8( fOffset, 3 );
 							fOffset += 1;
 
-							output[ faceIndexFunc ]( fOffset, indices.getX( i + 0 ) + writtenVertices );
+							output.setUint32( fOffset, indices.getX( i + 0 ) + writtenVertices );
 							fOffset += indexByteCount;
 
-							output[ faceIndexFunc ]( fOffset, indices.getX( i + 1 ) + writtenVertices );
+							output.setUint32( fOffset, indices.getX( i + 1 ) + writtenVertices );
 							fOffset += indexByteCount;
 
-							output[ faceIndexFunc ]( fOffset, indices.getX( i + 2 ) + writtenVertices );
+							output.setUint32( fOffset, indices.getX( i + 2 ) + writtenVertices );
 							fOffset += indexByteCount;
 
 						}
@@ -391,13 +376,13 @@ PLYExporter.prototype = {
 							output.setUint8( fOffset, 3 );
 							fOffset += 1;
 
-							output[ faceIndexFunc ]( fOffset, writtenVertices + i );
+							output.setUint32( fOffset, writtenVertices + i );
 							fOffset += indexByteCount;
 
-							output[ faceIndexFunc ]( fOffset, writtenVertices + i + 1 );
+							output.setUint32( fOffset, writtenVertices + i + 1 );
 							fOffset += indexByteCount;
 
-							output[ faceIndexFunc ]( fOffset, writtenVertices + i + 2 );
+							output.setUint32( fOffset, writtenVertices + i + 2 );
 							fOffset += indexByteCount;
 
 						}
@@ -543,7 +528,7 @@ PLYExporter.prototype = {
 
 			} );
 
-			result = `${ header }${vertexList}\n${ includeIndices ? `${faceList}\n` : '' }`;
+			result = `${ header }${vertexList}${ includeIndices ? `${faceList}\n` : '\n' }`;
 
 		}
 

+ 24 - 0
examples/jsm/libs/stats.module.d.ts

@@ -0,0 +1,24 @@
+declare interface Stats {
+  REVISION: number;
+  dom: HTMLDivElement;
+  addPanel(panel: Stats.Panel): Stats.Panel;
+  showPanel(id: number): void;
+  begin(): void;
+  end(): void;
+  update(): void;
+  domElement: HTMLDivElement;
+  setMode(id: number): void;
+}
+
+declare function Stats(): Stats;
+
+declare namespace Stats {
+  interface Panel {
+    dom: HTMLCanvasElement;
+    update(value: number, maxValue: number): void;
+  }
+
+  function Panel(): Panel;
+}
+
+export default Stats

+ 1 - 1
examples/jsm/loaders/EXRLoader.js

@@ -1136,7 +1136,7 @@ EXRLoader.prototype = Object.assign( Object.create( DataTextureLoader.prototype
 
 		function parseValue( dataView, buffer, offset, type, size ) {
 
-			if ( type === 'string' || type === 'iccProfile' ) {
+			if ( type === 'string' || type === 'stringvector' || type === 'iccProfile' ) {
 
 				return parseFixedLengthString( buffer, offset, size );
 

+ 19 - 1
examples/jsm/loaders/GLTFLoader.d.ts

@@ -14,7 +14,16 @@ export interface GLTF {
 	scene: Scene;
 	scenes: Scene[];
 	cameras: Camera[];
-	asset: object;
+	asset: {
+		copyright?: string;
+		generator?: string;
+		version?: string;
+		minVersion?: string;
+		extensions?: any;
+		extras?: any;
+	};
+	parser: GLTFParser;
+	userData: any;
 }
 
 export class GLTFLoader extends Loader {
@@ -29,3 +38,12 @@ export class GLTFLoader extends Loader {
 	parse( data: ArrayBuffer | string, path: string, onLoad: ( gltf: GLTF ) => void, onError?: ( event: ErrorEvent ) => void ) : void;
 
 }
+
+export class GLTFParser {
+
+	json: any;
+
+	getDependency: (type: string, index: number) => Promise<any>;
+	getDependencies: (type: string) => Promise<any[]>;
+
+}

+ 97 - 2
examples/jsm/loaders/GLTFLoader.js

@@ -557,6 +557,7 @@ var GLTFLoader = ( function () {
 		this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
 		this.json = json;
 		this.dracoLoader = dracoLoader;
+		this.dracoLoader.preload();
 
 	}
 
@@ -2461,6 +2462,100 @@ var GLTFLoader = ( function () {
 
 	}
 
+	/**
+	 * @param {BufferGeometry} geometry
+	 * @param {Number} drawMode
+	 * @return {BufferGeometry}
+	 */
+	function toTrianglesDrawMode( geometry, drawMode ) {
+
+		var index = geometry.getIndex();
+
+		// generate index if not present
+
+		if ( index === null ) {
+
+			var indices = [];
+
+			var position = geometry.getAttribute( 'position' );
+
+			if ( position !== undefined ) {
+
+				for ( var i = 0; i < position.count; i ++ ) {
+
+					indices.push( i );
+
+				}
+
+				geometry.setIndex( indices );
+				index = geometry.getIndex();
+
+			} else {
+
+				console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );
+				return geometry;
+
+			}
+
+		}
+
+		//
+
+		var numberOfTriangles = index.count - 2;
+		var newIndices = [];
+
+		if ( drawMode === TriangleFanDrawMode ) {
+
+			// gl.TRIANGLE_FAN
+
+			for ( var i = 1; i <= numberOfTriangles; i ++ ) {
+
+				newIndices.push( index.getX( 0 ) );
+				newIndices.push( index.getX( i ) );
+				newIndices.push( index.getX( i + 1 ) );
+
+			}
+
+		} else {
+
+			// gl.TRIANGLE_STRIP
+
+			for ( var i = 0; i < numberOfTriangles; i ++ ) {
+
+				if ( i % 2 === 0 ) {
+
+					newIndices.push( index.getX( i ) );
+					newIndices.push( index.getX( i + 1 ) );
+					newIndices.push( index.getX( i + 2 ) );
+
+
+				} else {
+
+					newIndices.push( index.getX( i + 2 ) );
+					newIndices.push( index.getX( i + 1 ) );
+					newIndices.push( index.getX( i ) );
+
+				}
+
+			}
+
+		}
+
+		if ( ( newIndices.length / 3 ) !== numberOfTriangles ) {
+
+			console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );
+
+		}
+
+		// build final geometry
+
+		var newGeometry = geometry.clone();
+		newGeometry.setIndex( newIndices );
+
+		return newGeometry;
+
+	}
+
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry
 	 *
@@ -2593,11 +2688,11 @@ var GLTFLoader = ( function () {
 
 						if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
 
-							mesh.drawMode = TriangleStripDrawMode;
+							mesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleStripDrawMode );
 
 						} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
 
-							mesh.drawMode = TriangleFanDrawMode;
+							mesh.geometry = toTrianglesDrawMode( mesh.geometry, TriangleFanDrawMode );
 
 						}
 

+ 187 - 0
examples/jsm/math/MeshSurfaceSampler.js

@@ -0,0 +1,187 @@
+/**
+ * @author donmccurdy / https://www.donmccurdy.com/
+ */
+
+import {
+	Triangle
+} from "../../../build/three.module.js";
+
+/**
+ * Utility class for sampling weighted random points on the surface of a mesh.
+ *
+ * Building the sampler is a one-time O(n) operation. Once built, any number of
+ * random samples may be selected in O(logn) time. Memory usage is O(n).
+ *
+ * References:
+ * - http://www.joesfer.com/?p=84
+ * - https://stackoverflow.com/a/4322940/1314762
+ */
+var MeshSurfaceSampler = ( function () {
+
+	var _face = new Triangle();
+
+	function MeshSurfaceSampler ( geometry ) {
+
+		if ( ! geometry.isBufferGeometry || geometry.attributes.position.itemSize !== 3 ) {
+
+			throw new Error( 'THREE.MeshSurfaceSampler: Requires BufferGeometry triangle mesh.' );
+
+		}
+
+		if ( geometry.index ) {
+
+			console.warn( 'THREE.MeshSurfaceSampler: Converting geometry to non-indexed BufferGeometry.' );
+
+			geometry = geometry.toNonIndexed();
+
+		}
+
+		this.geometry = geometry;
+
+		this.positionAttribute = this.geometry.getAttribute( 'position' );
+		this.weightAttribute = null;
+
+		this.distribution = null;
+
+	};
+
+	MeshSurfaceSampler.prototype = {
+
+		constructor: MeshSurfaceSampler,
+
+		setWeightAttribute: function ( name ) {
+
+			this.weightAttribute = name ? this.geometry.getAttribute( name ) : null;
+
+			return this;
+
+		},
+
+		build: function () {
+
+			var positionAttribute = this.positionAttribute;
+			var weightAttribute = this.weightAttribute;
+
+			var faceWeights = new Float32Array( positionAttribute.count / 3 );
+
+			// Accumulate weights for each mesh face.
+
+			for ( var i = 0; i < positionAttribute.count; i += 3 ) {
+
+				var faceWeight = 1;
+
+				if ( weightAttribute ) {
+
+					faceWeight = weightAttribute.getX( i )
+						+ weightAttribute.getX( i + 1 )
+						+ weightAttribute.getX( i + 2 );
+
+				}
+
+				_face.a.fromBufferAttribute( positionAttribute, i );
+				_face.b.fromBufferAttribute( positionAttribute, i + 1 );
+				_face.c.fromBufferAttribute( positionAttribute, i + 2 );
+				faceWeight *= _face.getArea();
+
+				faceWeights[ i / 3 ] = faceWeight;
+
+			}
+
+			// Store cumulative total face weights in an array, where weight index
+			// corresponds to face index.
+
+			this.distribution = new Float32Array( positionAttribute.count / 3 );
+
+			var cumulativeTotal = 0;
+
+			for ( var i = 0; i < faceWeights.length; i ++ ) {
+
+				cumulativeTotal += faceWeights[ i ];
+
+				this.distribution[ i ] = cumulativeTotal;
+
+			}
+
+			return this;
+
+		},
+
+		sample: function ( targetPosition, targetNormal ) {
+
+			var cumulativeTotal = this.distribution[ this.distribution.length - 1 ];
+
+			var faceIndex = this.binarySearch( Math.random() * cumulativeTotal );
+
+			return this.sampleFace( faceIndex, targetPosition, targetNormal );
+
+		},
+
+		binarySearch: function ( x ) {
+
+			var dist = this.distribution;
+			var start = 0;
+			var end = dist.length - 1;
+
+			var index = -1;
+
+			while ( start <= end ) {
+
+				var mid = Math.floor( ( start + end ) / 2 );
+
+				if ( dist[ mid - 1 ] <= x && dist[ mid ] > x ) {
+
+					index = mid;
+
+					break;
+
+				} else if ( x < dist[ mid ] ) {
+
+					end = mid - 1;
+
+				} else {
+
+					start = mid + 1;
+
+				}
+
+			}
+
+			return index;
+
+		},
+
+		sampleFace: function ( faceIndex, targetPosition, targetNormal ) {
+
+			var u = Math.random();
+			var v = Math.random();
+
+			if ( u + v > 1 ) {
+
+				u = 1 - u;
+				v = 1 - v;
+
+			}
+
+			_face.a.fromBufferAttribute( this.positionAttribute, faceIndex * 3 );
+			_face.b.fromBufferAttribute( this.positionAttribute, faceIndex * 3 + 1 );
+			_face.c.fromBufferAttribute( this.positionAttribute, faceIndex * 3 + 2 );
+
+			targetPosition
+				.set( 0, 0, 0 )
+				.addScaledVector( _face.a, u )
+				.addScaledVector( _face.b, v )
+				.addScaledVector( _face.c, 1 - ( u + v ) );
+
+			_face.getNormal( targetNormal );
+
+			return this;
+
+		}
+
+	};
+
+	return MeshSurfaceSampler;
+
+} )();
+
+export { MeshSurfaceSampler };

+ 0 - 22
examples/jsm/misc/CarControls.d.ts

@@ -1,22 +0,0 @@
-import {
-	Object3D,
-} from '../../../src/Three';
-
-export class CarControls {
-
-	constructor( maxSpeed?: number, acceleration?: number, brakePower?: number, turningRadius?: number, keys?: object );
-
-	// API
-	enabled: boolean;
-	elemNames: object;
-	maxSpeed: number;
-	acceleration: number;
-	turningRadius: number;
-	brakePower: number;
-	speed: number;
-
-	dispose(): void;
-	update( delta: number ): void;
-	setModel ( model: Object3D, elemNames: object ): void;
-
-}

+ 0 - 314
examples/jsm/misc/CarControls.js

@@ -1,314 +0,0 @@
-/**
- * @author alteredq / http://alteredqualia.com/
- * @author Lewy Blue https://github.com/looeee
- *
- * The model is expected to follow real world car proportions. You can try unusual car types
- * but your results may be unexpected. Scaled models are also not supported.
- *
- * Defaults are rough estimates for a real world scale car model
- *
- */
-
-import {
-	Box3,
-	Group,
-	Math as _Math,
-	Vector3
-} from "../../../build/three.module.js";
-
-var CarControls = ( function ( ) {
-
-	// private variables
-	var steeringWheelSpeed = 1.5;
-	var maxSteeringRotation = 0.6;
-
-	var acceleration = 0;
-
-	var maxSpeedReverse, accelerationReverse, deceleration;
-
-	var controlKeys = { LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, BRAKE: 32 };
-
-	var wheelOrientation = 0;
-	var carOrientation = 0;
-
-	var root = null;
-
-	var frontLeftWheelRoot = null;
-	var frontRightWheelRoot = null;
-
-	var frontLeftWheel = new Group();
-	var frontRightWheel = new Group();
-	var backLeftWheel = null;
-	var backRightWheel = null;
-
-	var steeringWheel = null;
-
-	var wheelDiameter = 1;
-	var length = 1;
-
-	var loaded = false;
-
-	var controls = {
-
-		brake: false,
-		moveForward: false,
-		moveBackward: false,
-		moveLeft: false,
-		moveRight: false
-
-	};
-
-	function CarControls( maxSpeed, acceleration, brakePower, turningRadius, keys ) {
-
-		this.enabled = true;
-
-		this.elemNames = {
-			flWheel: 'wheel_fl',
-			frWheel: 'wheel_fr',
-			rlWheel: 'wheel_rl',
-			rrWheel: 'wheel_rr',
-			steeringWheel: 'steering_wheel', // set to null to disable
-		};
-
-		// km/hr
-		this.maxSpeed = maxSpeed || 180;
-		maxSpeedReverse = - this.maxSpeed * 0.25;
-
-		// m/s
-		this.acceleration = acceleration || 10;
-		accelerationReverse = this.acceleration * 0.5;
-
-		// metres
-		this.turningRadius = turningRadius || 6;
-
-		// m/s
-		deceleration = this.acceleration * 2;
-
-		// multiplied with deceleration, so breaking deceleration = ( acceleration * 2 * brakePower ) m/s
-		this.brakePower = brakePower || 10;
-
-		// exposed so that a user can use this for various effect, e.g blur
-		this.speed = 0;
-
-		// keys used to control car - by default the arrow keys and space to brake
-		controlKeys = keys || controlKeys;
-
-		// local axes of rotation - these are likely to vary between models
-		this.wheelRotationAxis = 'x';
-		this.wheelTurnAxis = 'z';
-		this.steeringWheelTurnAxis = 'y';
-
-		document.addEventListener( 'keydown', this.onKeyDown, false );
-		document.addEventListener( 'keyup', this.onKeyUp, false );
-
-	}
-
-	CarControls.prototype = {
-
-		constructor: CarControls,
-
-		onKeyDown: function ( event ) {
-
-			switch ( event.keyCode ) {
-
-				case controlKeys.BRAKE:
-					controls.brake = true;
-					controls.moveForward = false;
-					controls.moveBackward = false;
-					break;
-
-				case controlKeys.UP: controls.moveForward = true; break;
-
-				case controlKeys.DOWN: controls.moveBackward = true; break;
-
-				case controlKeys.LEFT: controls.moveLeft = true; break;
-
-				case controlKeys.RIGHT: controls.moveRight = true; break;
-
-			}
-
-		},
-
-		onKeyUp: function ( event ) {
-
-			switch ( event.keyCode ) {
-
-				case controlKeys.BRAKE: controls.brake = false; break;
-
-				case controlKeys.UP: controls.moveForward = false; break;
-
-				case controlKeys.DOWN: controls.moveBackward = false; break;
-
-				case controlKeys.LEFT: controls.moveLeft = false; break;
-
-				case controlKeys.RIGHT: controls.moveRight = false; break;
-
-			}
-
-		},
-
-		dispose: function () {
-
-			document.removeEventListener( 'keydown', this.onKeyDown, false );
-			document.removeEventListener( 'keyup', this.onKeyUp, false );
-
-		},
-
-		update: function ( delta ) {
-
-			if ( ! loaded || ! this.enabled ) return;
-
-			var brakingDeceleration = 1;
-
-			if ( controls.brake ) brakingDeceleration = this.brakePower;
-
-			if ( controls.moveForward ) {
-
-				this.speed = _Math.clamp( this.speed + delta * this.acceleration, maxSpeedReverse, this.maxSpeed );
-				acceleration = _Math.clamp( acceleration + delta, - 1, 1 );
-
-			}
-
-			if ( controls.moveBackward ) {
-
-				this.speed = _Math.clamp( this.speed - delta * accelerationReverse, maxSpeedReverse, this.maxSpeed );
-				acceleration = _Math.clamp( acceleration - delta, - 1, 1 );
-
-			}
-
-			if ( controls.moveLeft ) {
-
-				wheelOrientation = _Math.clamp( wheelOrientation + delta * steeringWheelSpeed, - maxSteeringRotation, maxSteeringRotation );
-
-			}
-
-			if ( controls.moveRight ) {
-
-				wheelOrientation = _Math.clamp( wheelOrientation - delta * steeringWheelSpeed, - maxSteeringRotation, maxSteeringRotation );
-
-			}
-
-			// this.speed decay
-			if ( ! ( controls.moveForward || controls.moveBackward ) ) {
-
-				if ( this.speed > 0 ) {
-
-					var k = exponentialEaseOut( this.speed / this.maxSpeed );
-
-					this.speed = _Math.clamp( this.speed - k * delta * deceleration * brakingDeceleration, 0, this.maxSpeed );
-					acceleration = _Math.clamp( acceleration - k * delta, 0, 1 );
-
-				} else {
-
-					var k = exponentialEaseOut( this.speed / maxSpeedReverse );
-
-					this.speed = _Math.clamp( this.speed + k * delta * accelerationReverse * brakingDeceleration, maxSpeedReverse, 0 );
-					acceleration = _Math.clamp( acceleration + k * delta, - 1, 0 );
-
-				}
-
-			}
-
-			// steering decay
-			if ( ! ( controls.moveLeft || controls.moveRight ) ) {
-
-				if ( wheelOrientation > 0 ) {
-
-					wheelOrientation = _Math.clamp( wheelOrientation - delta * steeringWheelSpeed, 0, maxSteeringRotation );
-
-				} else {
-
-					wheelOrientation = _Math.clamp( wheelOrientation + delta * steeringWheelSpeed, - maxSteeringRotation, 0 );
-
-				}
-
-			}
-
-			var forwardDelta = - this.speed * delta;
-
-			carOrientation -= ( forwardDelta * this.turningRadius * 0.02 ) * wheelOrientation;
-
-			// movement of car
-			root.position.x += Math.sin( carOrientation ) * forwardDelta * length;
-			root.position.z += Math.cos( carOrientation ) * forwardDelta * length;
-
-			// angle of car
-			root.rotation.y = carOrientation;
-
-			// wheels rolling
-			var angularSpeedRatio = - 2 / wheelDiameter;
-
-			var wheelDelta = forwardDelta * angularSpeedRatio * length;
-
-			frontLeftWheel.rotation[ this.wheelRotationAxis ] -= wheelDelta;
-			frontRightWheel.rotation[ this.wheelRotationAxis ] -= wheelDelta;
-			backLeftWheel.rotation[ this.wheelRotationAxis ] -= wheelDelta;
-			backRightWheel.rotation[ this.wheelRotationAxis ] -= wheelDelta;
-
-			// rotation while steering
-			frontLeftWheelRoot.rotation[ this.wheelTurnAxis ] = wheelOrientation;
-			frontRightWheelRoot.rotation[ this.wheelTurnAxis ] = wheelOrientation;
-
-			steeringWheel.rotation[ this.steeringWheelTurnAxis ] = - wheelOrientation * 6;
-
-		},
-
-		setModel: function ( model, elemNames ) {
-
-			if ( elemNames ) this.elemNames = elemNames;
-
-			root = model;
-
-			this.setupWheels();
-			this.computeDimensions();
-
-			loaded = true;
-
-		},
-
-		setupWheels: function () {
-
-			frontLeftWheelRoot = root.getObjectByName( this.elemNames.flWheel );
-			frontRightWheelRoot = root.getObjectByName( this.elemNames.frWheel );
-			backLeftWheel = root.getObjectByName( this.elemNames.rlWheel );
-			backRightWheel = root.getObjectByName( this.elemNames.rrWheel );
-
-			if ( this.elemNames.steeringWheel !== null ) steeringWheel = root.getObjectByName( this.elemNames.steeringWheel );
-
-			while ( frontLeftWheelRoot.children.length > 0 ) frontLeftWheel.add( frontLeftWheelRoot.children[ 0 ] );
-			while ( frontRightWheelRoot.children.length > 0 ) frontRightWheel.add( frontRightWheelRoot.children[ 0 ] );
-
-			frontLeftWheelRoot.add( frontLeftWheel );
-			frontRightWheelRoot.add( frontRightWheel );
-
-		},
-
-		computeDimensions: function () {
-
-			var bb = new Box3().setFromObject( frontLeftWheelRoot );
-
-			var size = new Vector3();
-			bb.getSize( size );
-
-			wheelDiameter = Math.max( size.x, size.y, size.z );
-
-			bb.setFromObject( root );
-
-			size = bb.getSize( size );
-			length = Math.max( size.x, size.y, size.z );
-
-		}
-
-	};
-
-	function exponentialEaseOut( k ) {
-
-		return k === 1 ? 1 : - Math.pow( 2, - 10 * k ) + 1;
-
-	}
-
-	return CarControls;
-
-} )();
-
-export { CarControls };

+ 16 - 0
examples/jsm/misc/TubePainter.d.ts

@@ -0,0 +1,16 @@
+import {
+	Matrix4,
+	Mesh,
+	Vector3
+} from '../../../src/Three';
+
+export class TubePainter {
+
+	constructor();
+
+	mesh: Mesh;
+
+	stroke( position1: Vector3, position2: Vector3, matrix1: Matrix4, matrix2: Matrix4 ): void;
+	updateGeometry( start: number, end: number ): void;
+
+}

+ 7 - 0
examples/jsm/misc/TubePainter.js

@@ -131,6 +131,12 @@ function TubePainter() {
 
 	}
 
+	function setSize( value ) {
+
+		size = value;
+
+	}
+
 	function updateGeometry( start, end ) {
 
 		if ( start === end ) return;
@@ -155,6 +161,7 @@ function TubePainter() {
 	return {
 		mesh: mesh,
 		stroke: stroke,
+		setSize: setSize,
 		updateGeometry: updateGeometry
 	};
 

+ 0 - 1
examples/jsm/nodes/accessors/CameraNode.d.ts

@@ -19,7 +19,6 @@ export class CameraNode extends TempNode {
 
 	setCamera( camera: Camera ): void;
 	setScope( scope: string ): void;
-	generate( builder: NodeBuilder, output: string ): string;
 	onUpdateFrame( frame: NodeFrame ): void;
 	copy( source: CameraNode ): this;
 

+ 0 - 1
examples/jsm/nodes/accessors/ColorsNode.d.ts

@@ -8,7 +8,6 @@ export class ColorsNode extends TempNode {
 	index: number;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: ColorsNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/accessors/LightNode.d.ts

@@ -8,7 +8,6 @@ export class LightNode extends TempNode {
 	scope: string;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: LightNode ): this;
 
 	static TOTAL: string;

+ 0 - 1
examples/jsm/nodes/accessors/NormalNode.d.ts

@@ -8,7 +8,6 @@ export class NormalNode extends TempNode {
 	scope: string;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: NormalNode ): this;
 
 	static LOCAL: string;

+ 0 - 1
examples/jsm/nodes/accessors/PositionNode.d.ts

@@ -8,7 +8,6 @@ export class PositionNode extends TempNode {
 	scope: string;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: PositionNode ): this;
 
 	static LOCAL: string;

+ 0 - 2
examples/jsm/nodes/accessors/ReflectNode.d.ts

@@ -10,8 +10,6 @@ export class ReflectNode extends TempNode {
 	scope: string;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
-
 	static CUBE: string;
 	static SPHERE: string;
 	static VECTOR: string;

+ 0 - 1
examples/jsm/nodes/accessors/ScreenUVNode.d.ts

@@ -9,7 +9,6 @@ export class ScreenUVNode extends TempNode {
 	resolution: ResolutionNode;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: ScreenUVNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/accessors/UVNode.d.ts

@@ -8,7 +8,6 @@ export class UVNode extends TempNode {
 	index: number;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: UVNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/core/AttributeNode.d.ts

@@ -10,7 +10,6 @@ export class AttributeNode extends TempNode {
 
 	getAttributeType( builder: NodeBuilder ): string;
 	getType( builder: NodeBuilder ): string;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: AttributeNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/core/ConstNode.d.ts

@@ -12,7 +12,6 @@ export class ConstNode extends TempNode {
 	getType( builder: NodeBuilder ): string;
 	parse( src: string, useDefine?: boolean ): void;
 	build( builder: NodeBuilder, output: string ): string;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: ConstNode ): this;
 
 	static PI: string;

+ 0 - 1
examples/jsm/nodes/core/FunctionCallNode.d.ts

@@ -15,7 +15,6 @@ export class FunctionCallNode extends TempNode {
 	setFunction( func: FunctionNode, inputs?: Node[] ): void;
 	getFunction(): FunctionNode;
 	getType(): string;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: FunctionCallNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/core/FunctionNode.d.ts

@@ -24,7 +24,6 @@ export class FunctionNode extends TempNode {
 	getType( builder: NodeBuilder ): string;
 	getInputByName( name: string ): FunctionNodeInput | undefined;
 	getIncludeByName( name: string ): object | undefined;
-	generate( builder: NodeBuilder, output: string ): string;
 	parse( src: string, includes?: object[], extensions?: object, keywords?: object ): void;
 	copy( source: FunctionNode ): this;
 

+ 0 - 1
examples/jsm/nodes/core/InputNode.d.ts

@@ -10,6 +10,5 @@ export class InputNode extends TempNode {
 	setReadonly( value: boolean ): this;
 	getReadonly( builder: NodeBuilder ): boolean;
 	copy( source: InputNode ): this;
-	generate( builder: NodeBuilder, output: string, uuid?: string, type?: string, ns?: string, needsUpdate?: boolean ): string;
 
 }

+ 1 - 0
examples/jsm/nodes/core/Node.d.ts

@@ -15,6 +15,7 @@ export class Node {
 	analyzeAndFlow( builder: NodeBuilder, output: string, settings?: object ): object;
 	flow( builder: NodeBuilder, output: string, settings?: object ): object;
 	build( builder: NodeBuilder, output: string, uuid?: string ): string;
+	generate( builder: NodeBuilder, output: string, uuid?: string, type?: string, ns?: string ): string;
 	appendDepsNode( builder: NodeBuilder, data: object, output: string ): void;
 	setName( name: string ): this;
 	getName( builder: NodeBuilder ): string;

+ 6 - 0
examples/jsm/nodes/core/Node.js

@@ -94,6 +94,12 @@ Node.prototype = {
 
 	},
 
+	generate: function ( /* builder, output, uuid, type, ns */ ) {
+
+		// This method needs to be implemented in subclasses
+
+	},
+
 	appendDepsNode: function ( builder, data, output ) {
 
 		data.deps = ( data.deps || 0 ) + 1;

+ 0 - 1
examples/jsm/nodes/core/StructNode.d.ts

@@ -16,7 +16,6 @@ export class StructNode extends TempNode {
 
 	getType( builder: NodeBuilder ): string;
 	getInputByName( name: string ): StructNodeInput;
-	generate( builder: NodeBuilder, output: string ): string;
 	parse( src: string ): void;
 
 }

+ 0 - 1
examples/jsm/nodes/core/TempNode.d.ts

@@ -21,6 +21,5 @@ export class TempNode extends Node {
 	getLabel( builder: NodeBuilder ): string;
 	getUuid( unique: boolean ): string;
 	getTemp( builder: NodeBuilder, uuid: string ): string | undefined;
-	generate( builder: NodeBuilder, output: string, uuid?: string, type?: string, ns?: string ): string;
 
 }

+ 0 - 1
examples/jsm/nodes/core/VarNode.d.ts

@@ -9,7 +9,6 @@ export class VarNode extends Node {
 	nodeType: string;
 
 	getType( builder: NodeBuilder ): string;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: VarNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/effects/BlurNode.d.ts

@@ -24,7 +24,6 @@ export class BlurNode extends TempNode {
 	nodeType: string;
 
 	updateFrame( frame: NodeFrame ): void;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: BlurNode ): this;
 
 	static Nodes: {

+ 0 - 1
examples/jsm/nodes/effects/ColorAdjustmentNode.d.ts

@@ -13,7 +13,6 @@ export class ColorAdjustmentNode extends TempNode {
 	method: string;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: ColorAdjustmentNode ): this;
 
 	static Nodes: {

+ 0 - 1
examples/jsm/nodes/effects/LuminanceNode.d.ts

@@ -11,7 +11,6 @@ export class LuminanceNode extends TempNode {
 	rgb: Node;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: LuminanceNode ): this;
 
 	static Nodes: {

+ 0 - 1
examples/jsm/nodes/inputs/CubeTextureNode.d.ts

@@ -14,7 +14,6 @@ export class CubeTextureNode extends InputNode {
 	nodeType: string;
 
 	getTexture( builder: NodeBuilder, output: string ): string;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: CubeTextureNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/inputs/ReflectorNode.d.ts

@@ -19,7 +19,6 @@ export class ReflectorNode extends TempNode {
 
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: ReflectorNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/inputs/TextureNode.d.ts

@@ -19,7 +19,6 @@ export class TextureNode extends InputNode {
 	nodeType: string;
 
 	getTexture( builder: NodeBuilder, output: string ): string;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: TextureNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/materials/nodes/RawNode.d.ts

@@ -8,7 +8,6 @@ export class RawNode extends Node {
 	value: Node;
 	nodeType: string;
 
-	generate( builder: NodeBuilder ): string;
 	copy( source: RawNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/math/CondNode.d.ts

@@ -14,7 +14,6 @@ export class CondNode extends TempNode {
 	nodeType: string;
 
 	getCondType( builder: NodeBuilder ): string;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: CondNode ): this;
 
 	static EQUAL: string;

+ 0 - 1
examples/jsm/nodes/math/MathNode.d.ts

@@ -14,7 +14,6 @@ export class MathNode extends TempNode {
 
 	getNumInputs( builder: NodeBuilder ): number;
 	getInputType( builder: NodeBuilder ): string;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: MathNode ): this;
 
 	static RAD: string;

+ 0 - 1
examples/jsm/nodes/math/OperatorNode.d.ts

@@ -10,7 +10,6 @@ export class OperatorNode extends TempNode {
 	b: Node;
 	op: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: OperatorNode ): this;
 
 	static ADD: string;

+ 0 - 1
examples/jsm/nodes/misc/BumpMapNode.d.ts

@@ -13,7 +13,6 @@ export class BumpMapNode extends TempNode {
 	toNormalMap: boolean;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: BumpMapNode ): this;
 
 	static Nodes: {

+ 0 - 1
examples/jsm/nodes/misc/NormalMapNode.d.ts

@@ -13,7 +13,6 @@ export class NormalMapNode extends TempNode {
 	toNormalMap: boolean;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: NormalMapNode ): this;
 
 	static Nodes: {

+ 0 - 1
examples/jsm/nodes/misc/TextureCubeNode.d.ts

@@ -19,6 +19,5 @@ export class TextureCubeNode extends TempNode {
 	nodeType: string;
 
 	generateTextureCubeUV( builder: NodeBuilder, output: string ): string;
-	generate( builder: NodeBuilder, output: string ): string;
 
 }

+ 0 - 2
examples/jsm/nodes/misc/TextureCubeUVNode.d.ts

@@ -13,8 +13,6 @@ export class TextureCubeUVNode extends TempNode {
 	textureSize: FloatNode;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
-
 	static Nodes: {
 		TextureCubeUVData: StructNode;
 		textureCubeUV: FunctionNode;

+ 0 - 1
examples/jsm/nodes/procedural/CheckerNode.d.ts

@@ -11,7 +11,6 @@ export class CheckerNode extends TempNode {
 	uv: UVNode | UVTransformNode;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: CheckerNode ): this;
 
 	static Nodes: {

+ 0 - 1
examples/jsm/nodes/procedural/NoiseNode.d.ts

@@ -11,7 +11,6 @@ export class NoiseNode extends TempNode {
 	uv: UVNode | UVTransformNode;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: NoiseNode ): this;
 
 	static Nodes: {

+ 0 - 1
examples/jsm/nodes/utils/BypassNode.d.ts

@@ -9,7 +9,6 @@ export class BypassNode extends Node {
 	value: Node | undefined;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: BypassNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/utils/ColorSpaceNode.d.ts

@@ -11,7 +11,6 @@ export class ColorSpaceNode extends TempNode {
 	method: string | undefined;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	fromEncoding( encoding: number );
 	fromDecoding( encoding: number );
 	copy( source: ColorSpaceNode ): this;

+ 0 - 1
examples/jsm/nodes/utils/JoinNode.d.ts

@@ -12,7 +12,6 @@ export class JoinNode extends TempNode {
 	nodeType: string;
 
 	getNumElements(): number;
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: JoinNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/utils/SpecularMIPLevelNode.d.ts

@@ -11,7 +11,6 @@ export class SpecularMIPLevelNode extends TempNode {
 	maxMIPLevel: MaxMIPLevelNode;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: SpecularMIPLevelNode ): this;
 
 	static Nodes: {

+ 0 - 1
examples/jsm/nodes/utils/SubSlot.d.ts

@@ -7,7 +7,6 @@ export class SubSlots extends TempNode {
 
 	slots: Node[];
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: SubSlots ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/utils/SwitchNode.d.ts

@@ -9,7 +9,6 @@ export class SwitchNode extends Node {
 	components: string;
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	copy( source: SwitchNode ): this;
 
 }

+ 0 - 1
examples/jsm/nodes/utils/UVTransformNode.d.ts

@@ -12,7 +12,6 @@ export class UVTransformNode extends ExpressionNode {
 
 	nodeType: string;
 
-	generate( builder: NodeBuilder, output: string ): string;
 	setUvTransform( tx: number, ty: number, sx: number, sy: number, rotation: number, cx?: number, cy?: number ): void;
 	copy( source: UVTransformNode ): this;
 

Daži faili netika attēloti, jo izmaiņu fails ir pārāk liels