Mr.doob 4 years ago
parent
commit
636376a48b
100 changed files with 1885 additions and 2907 deletions
  1. 19 30
      build/three.js
  2. 0 0
      build/three.min.js
  3. 20 34
      build/three.module.js
  4. 5 0
      docs/api/ar/animation/AnimationUtils.html
  5. 5 0
      docs/api/en/animation/AnimationUtils.html
  6. 51 0
      docs/api/en/constants/BufferAttributeUsage.html
  7. 2 0
      docs/api/en/constants/Materials.html
  8. 2 2
      docs/api/en/core/BufferAttribute.html
  9. 3 0
      docs/api/en/core/InstancedBufferGeometry.html
  10. 4 4
      docs/api/en/geometries/SphereGeometry.html
  11. 0 3
      docs/api/en/materials/LineBasicMaterial.html
  12. 0 4
      docs/api/en/materials/MeshBasicMaterial.html
  13. 0 3
      docs/api/en/materials/MeshDepthMaterial.html
  14. 0 3
      docs/api/en/materials/MeshDistanceMaterial.html
  15. 0 9
      docs/api/en/materials/MeshLambertMaterial.html
  16. 0 9
      docs/api/en/materials/MeshMatcapMaterial.html
  17. 0 9
      docs/api/en/materials/MeshNormalMaterial.html
  18. 0 9
      docs/api/en/materials/MeshPhongMaterial.html
  19. 0 16
      docs/api/en/materials/MeshStandardMaterial.html
  20. 0 9
      docs/api/en/materials/MeshToonMaterial.html
  21. 0 4
      docs/api/en/materials/PointsMaterial.html
  22. 0 11
      docs/api/en/materials/ShaderMaterial.html
  23. 5 0
      docs/api/ko/animation/AnimationUtils.html
  24. 4 5
      docs/api/zh/animation/AnimationUtils.html
  25. 51 0
      docs/api/zh/constants/BufferAttributeUsage.html
  26. 1 1
      docs/api/zh/constants/Renderer.html
  27. 2 2
      docs/api/zh/core/BufferAttribute.html
  28. 3 0
      docs/api/zh/core/InstancedBufferGeometry.html
  29. 4 4
      docs/api/zh/geometries/SphereGeometry.html
  30. 0 3
      docs/api/zh/materials/LineBasicMaterial.html
  31. 0 4
      docs/api/zh/materials/MeshBasicMaterial.html
  32. 0 3
      docs/api/zh/materials/MeshDepthMaterial.html
  33. 0 3
      docs/api/zh/materials/MeshDistanceMaterial.html
  34. 0 7
      docs/api/zh/materials/MeshLambertMaterial.html
  35. 0 7
      docs/api/zh/materials/MeshMatcapMaterial.html
  36. 0 7
      docs/api/zh/materials/MeshNormalMaterial.html
  37. 0 7
      docs/api/zh/materials/MeshPhongMaterial.html
  38. 0 15
      docs/api/zh/materials/MeshStandardMaterial.html
  39. 0 9
      docs/api/zh/materials/MeshToonMaterial.html
  40. 0 3
      docs/api/zh/materials/PointsMaterial.html
  41. 0 8
      docs/api/zh/materials/ShaderMaterial.html
  42. 2 4
      docs/api/zh/math/Matrix3.html
  43. 2 4
      docs/api/zh/math/Matrix4.html
  44. 8 3
      docs/examples/en/controls/OrbitControls.html
  45. 8 0
      docs/examples/en/controls/TransformControls.html
  46. 3 0
      docs/examples/en/exporters/ColladaExporter.html
  47. 4 0
      docs/examples/en/loaders/GLTFLoader.html
  48. 40 57
      docs/examples/en/math/Lut.html
  49. 9 4
      docs/examples/ko/controls/OrbitControls.html
  50. 7 0
      docs/examples/ko/controls/TransformControls.html
  51. 8 3
      docs/examples/zh/controls/OrbitControls.html
  52. 7 0
      docs/examples/zh/controls/TransformControls.html
  53. 4 0
      docs/examples/zh/loaders/GLTFLoader.html
  54. 40 57
      docs/examples/zh/math/Lut.html
  55. 1 5
      docs/list.json
  56. 0 123
      docs/manual/ar/introduction/Browser-support.html
  57. 0 122
      docs/manual/en/introduction/Browser-support.html
  58. 8 3
      docs/manual/en/introduction/Libraries-and-Plugins.html
  59. 2 2
      docs/manual/ja/introduction/Animation-system.html
  60. 0 125
      docs/manual/ja/introduction/Browser-support.html
  61. 0 27
      docs/manual/ja/introduction/How-to-update-things.html
  62. 9 4
      docs/manual/ja/introduction/Libraries-and-Plugins.html
  63. 0 130
      docs/manual/ko/introduction/Browser-support.html
  64. 0 124
      docs/manual/zh/introduction/Browser-support.html
  65. 3 3
      docs/scenes/geometry-browser.html
  66. 1 0
      editor/index.html
  67. 1 0
      editor/js/Editor.js
  68. 49 15
      editor/js/Loader.js
  69. 1 1
      editor/js/Menubar.Add.js
  70. 12 0
      editor/js/Menubar.Help.js
  71. 63 0
      editor/js/Sidebar.Material.BooleanProperty.js
  72. 90 0
      editor/js/Sidebar.Material.ColorProperty.js
  73. 65 0
      editor/js/Sidebar.Material.ConstantProperty.js
  74. 193 0
      editor/js/Sidebar.Material.MapProperty.js
  75. 63 0
      editor/js/Sidebar.Material.NumberProperty.js
  76. 76 0
      editor/js/Sidebar.Material.Program.js
  77. 257 1506
      editor/js/Sidebar.Material.js
  78. 7 1
      editor/js/Sidebar.Scene.js
  79. 30 48
      editor/js/Strings.js
  80. 4 2
      editor/js/Viewport.js
  81. 1 1
      editor/js/libs/ui.three.js
  82. 7 1
      editor/sw.js
  83. 14 6
      examples/js/controls/OrbitControls.js
  84. 17 8
      examples/js/controls/TrackballControls.js
  85. 13 5
      examples/js/controls/TransformControls.js
  86. 0 2
      examples/js/effects/OutlineEffect.js
  87. 26 2
      examples/js/exporters/ColladaExporter.js
  88. 97 7
      examples/js/exporters/GLTFExporter.js
  89. 2 2
      examples/js/exporters/USDZExporter.js
  90. 19 6
      examples/js/interactive/HTMLMesh.js
  91. 3 3
      examples/js/lines/LineMaterial.js
  92. 42 82
      examples/js/loaders/FBXLoader.js
  93. 183 10
      examples/js/loaders/GLTFLoader.js
  94. 1 1
      examples/js/loaders/HDRCubeTextureLoader.js
  95. 154 122
      examples/js/loaders/LDrawLoader.js
  96. 0 1
      examples/js/loaders/LWOLoader.js
  97. 0 1
      examples/js/loaders/MMDLoader.js
  98. 1 1
      examples/js/loaders/RGBELoader.js
  99. 34 14
      examples/js/loaders/SVGLoader.js
  100. 13 12
      examples/js/math/Lut.js

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


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


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


+ 5 - 0
docs/api/ar/animation/AnimationUtils.html

@@ -42,6 +42,11 @@
 		ترجاع *true* إذا كان الكائن مصفوفة مكتوبة (typed array.).
 		ترجاع *true* إذا كان الكائن مصفوفة مكتوبة (typed array.).
 		</p>
 		</p>
 
 
+		<h3>[method:AnimationClip makeClipAdditive]( [param:AnimationClip targetClip], [param:Number referenceFrame], [param:AnimationClip referenceClip], [param:Number fps] )</h3>
+		<p>
+		Converts the keyframes of the given animation clip to an additive format.
+		</p>
+
 		<h3>[method:Array sortedArray]( values, stride, order )</h3>
 		<h3>[method:Array sortedArray]( values, stride, order )</h3>
 		<p>
 		<p>
 		يفرز المصفوفة التي تم إرجاعها مسبقًا بناءا [page:AnimationUtils.getKeyframeOrder getKeyframeOrder].
 		يفرز المصفوفة التي تم إرجاعها مسبقًا بناءا [page:AnimationUtils.getKeyframeOrder getKeyframeOrder].

+ 5 - 0
docs/api/en/animation/AnimationUtils.html

@@ -42,6 +42,11 @@
 		Returns *true* if the object is a typed array.
 		Returns *true* if the object is a typed array.
 		</p>
 		</p>
 
 
+		<h3>[method:AnimationClip makeClipAdditive]( [param:AnimationClip targetClip], [param:Number referenceFrame], [param:AnimationClip referenceClip], [param:Number fps] )</h3>
+		<p>
+		Converts the keyframes of the given animation clip to an additive format.
+		</p>
+
 		<h3>[method:Array sortedArray]( values, stride, order )</h3>
 		<h3>[method:Array sortedArray]( values, stride, order )</h3>
 		<p>
 		<p>
 		Sorts the array previously returned by [page:AnimationUtils.getKeyframeOrder getKeyframeOrder].
 		Sorts the array previously returned by [page:AnimationUtils.getKeyframeOrder getKeyframeOrder].

+ 51 - 0
docs/api/en/constants/BufferAttributeUsage.html

@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		<h1>Buffer Attribute Usage Constants</h1>
+
+		<p>
+			The usage constants can be used to provide a hint to the API regarding how the geometry buffer attribute will be used in order to optimize performance.
+		</p>
+
+		<h2>Code Example</h2>
+
+		<code>
+		const geometry = new THREE.BufferGeometry();
+		const positionAttribute = new THREE.BufferAttribute( array, 3 , false );
+		positionAttribute.setUsage( THREE.DynamicDrawUsage );
+		geometry.setAttribute( 'position', positionAttribute );
+		</code>
+
+		<h2>Examples</h2>
+		<p>[example:webgl_buffergeometry_drawrange materials / buffergeometry / drawrange ]</p>
+
+		<h2>Geometry Usage</h2>
+		<code>
+		THREE.StaticDrawUsage
+		THREE.DynamicDrawUsage
+		THREE.StreamDrawUsage
+
+		THREE.StaticReadUsage
+		THREE.DynamicReadUsage
+		THREE.StreamReadUsage
+
+		THREE.StaticCopyUsage
+		THREE.DynamicCopyUsage
+		THREE.StreamCopyUsage
+		</code>
+
+		For more detailed information on each of these constants see [link:https://www.khronos.org/opengl/wiki/Buffer_Object#Buffer_Object_Usage this OpenGL documentation].
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js]
+		</p>
+	</body>
+</html>

+ 2 - 0
docs/api/en/constants/Materials.html

@@ -48,6 +48,7 @@
 		<code>
 		<code>
 		THREE.NeverDepth
 		THREE.NeverDepth
 		THREE.AlwaysDepth
 		THREE.AlwaysDepth
+		THREE.EqualDepth
 		THREE.LessDepth
 		THREE.LessDepth
 		THREE.LessEqualDepth
 		THREE.LessEqualDepth
 		THREE.GreaterEqualDepth
 		THREE.GreaterEqualDepth
@@ -58,6 +59,7 @@
 		Which depth function the material uses to compare incoming pixels Z-depth against the current Z-depth buffer value. If the result of the comparison is true, the pixel will be drawn.<br />
 		Which depth function the material uses to compare incoming pixels Z-depth against the current Z-depth buffer value. If the result of the comparison is true, the pixel will be drawn.<br />
 		[page:Materials NeverDepth] will never return true.<br />
 		[page:Materials NeverDepth] will never return true.<br />
 		[page:Materials AlwaysDepth] will always return true.<br />
 		[page:Materials AlwaysDepth] will always return true.<br />
+		[page:Materials EqualDepth] will return true if the incoming pixel Z-depth is equal to the current buffer Z-depth.<br />
 		[page:Materials LessDepth] will return true if the incoming pixel Z-depth is less than the current buffer Z-depth.<br />
 		[page:Materials LessDepth] will return true if the incoming pixel Z-depth is less than the current buffer Z-depth.<br />
 		[page:Materials LessEqualDepth] is the default and will return true if the incoming pixel Z-depth is less than or equal to the current buffer Z-depth.<br />
 		[page:Materials LessEqualDepth] is the default and will return true if the incoming pixel Z-depth is less than or equal to the current buffer Z-depth.<br />
 		[page:Materials GreaterEqualDepth] will return true if the incoming pixel Z-depth is greater than or equal to the current buffer Z-depth.<br />
 		[page:Materials GreaterEqualDepth] will return true if the incoming pixel Z-depth is greater than or equal to the current buffer Z-depth.<br />

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

@@ -97,7 +97,7 @@
 		<p>
 		<p>
 			Defines the intended usage pattern of the data store for optimization purposes. Corresponds to the *usage* parameter of
 			Defines the intended usage pattern of the data store for optimization purposes. Corresponds to the *usage* parameter of
 			[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData]().
 			[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData]().
-			Default is *THREE.StaticDrawUsage*.
+			Default is [page:BufferAttributeUsage StaticDrawUsage]. See usage [page:BufferAttributeUsage constants] for all possible values.
 		</p>
 		</p>
 
 
 		<h3>[property:Integer version]</h3>
 		<h3>[property:Integer version]</h3>
@@ -179,7 +179,7 @@
 		</p>
 		</p>
 
 
 		<h3>[method:BufferAttribute setUsage] ( [param:Usage value] ) </h3>
 		<h3>[method:BufferAttribute setUsage] ( [param:Usage value] ) </h3>
-		<p>Set [page:BufferAttribute.usage usage] to value.</p>
+		<p>Set [page:BufferAttribute.usage usage] to value. See usage [page:BufferAttributeUsage constants] for all possible input values.</p>
 
 
 		<h3>[method:BufferAttribute setX]( [param:Integer index], [param:Float x] ) </h3>
 		<h3>[method:BufferAttribute setX]( [param:Integer index], [param:Float x] ) </h3>
 		<p>Sets the x component of the vector at the given index.</p>
 		<p>Sets the x component of the vector at the given index.</p>

+ 3 - 0
docs/api/en/core/InstancedBufferGeometry.html

@@ -31,6 +31,9 @@
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 		<p>See [page:BufferGeometry] for inherited methods.</p>
 		<p>See [page:BufferGeometry] for inherited methods.</p>
 
 
+		<h3>[method:InstancedBufferGeometry copy]( [param:InstancedBufferGeometry source] )</h3>
+		<p>Copies the given [name] to this instance.</p>
+
 		<h2>Source</h2>
 		<h2>Source</h2>
 
 
 		<p>
 		<p>

+ 4 - 4
docs/api/en/geometries/SphereGeometry.html

@@ -33,8 +33,8 @@
 
 
 		<h2>Code Example</h2>
 		<h2>Code Example</h2>
 
 
-		<code>const geometry = new THREE.SphereGeometry( 5, 32, 32 );
-		const material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
+		<code>const geometry = new THREE.SphereGeometry( 15, 32, 16 );
+		const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
 		const sphere = new THREE.Mesh( geometry, material );
 		const sphere = new THREE.Mesh( geometry, material );
 		scene.add( sphere );
 		scene.add( sphere );
 		</code>
 		</code>
@@ -45,8 +45,8 @@
 
 
 		<p>
 		<p>
 		radius — sphere radius. Default is 1.<br />
 		radius — sphere radius. Default is 1.<br />
-		widthSegments — number of horizontal segments. Minimum value is 3, and the default is 8.<br />
-		heightSegments — number of vertical segments. Minimum value is 2, and the default is 6.<br />
+		widthSegments — number of horizontal segments. Minimum value is 3, and the default is 32.<br />
+		heightSegments — number of vertical segments. Minimum value is 2, and the default is 16.<br />
 		phiStart — specify horizontal starting angle. Default is 0.<br />
 		phiStart — specify horizontal starting angle. Default is 0.<br />
 		phiLength — specify horizontal sweep angle size. Default is Math.PI * 2.<br />
 		phiLength — specify horizontal sweep angle size. Default is Math.PI * 2.<br />
 		thetaStart — specify vertical starting angle. Default is 0.<br />
 		thetaStart — specify vertical starting angle. Default is 0.<br />

+ 0 - 3
docs/api/en/materials/LineBasicMaterial.html

@@ -87,9 +87,6 @@
 			property and it is ignored by the [page:WebGLRenderer WebGL] renderer.
 			property and it is ignored by the [page:WebGLRenderer WebGL] renderer.
 		</p>
 		</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>Define whether the material uses morphTargets. Default is false.</p>
-
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 		<p>See the base [page:Material] class for common methods.</p>
 		<p>See the base [page:Material] class for common methods.</p>
 
 

+ 0 - 4
docs/api/en/materials/MeshBasicMaterial.html

@@ -92,10 +92,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>The color map. Default is  null.</p>
 		<p>The color map. Default is  null.</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>Define whether the material uses morphTargets. Default is false.</p>
-
-
 		<h3>[property:Float reflectivity]</h3>
 		<h3>[property:Float reflectivity]</h3>
 		<p>
 		<p>
 			How much the environment map affects the surface; also see [page:.combine].
 			How much the environment map affects the surface; also see [page:.combine].

+ 0 - 3
docs/api/en/materials/MeshDepthMaterial.html

@@ -84,9 +84,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>The color map. Default is  null.</p>
 		<p>The color map. Default is  null.</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>Define whether the material uses morphTargets. Default is false.</p>
-
 		<h3>[property:Boolean wireframe]</h3>
 		<h3>[property:Boolean wireframe]</h3>
 		<p>Render geometry as wireframe. Default is false (i.e. render as smooth shaded).</p>
 		<p>Render geometry as wireframe. Default is false (i.e. render as smooth shaded).</p>
 
 

+ 0 - 3
docs/api/en/materials/MeshDistanceMaterial.html

@@ -95,9 +95,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>The color map. Default is  null.</p>
 		<p>The color map. Default is  null.</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>Define whether the material uses morphTargets. Default is false.</p>
-
 		<h3>[property:Float nearDistance]</h3>
 		<h3>[property:Float nearDistance]</h3>
 		<p>
 		<p>
 			The near value of the point light's internal shadow camera.
 			The near value of the point light's internal shadow camera.

+ 0 - 9
docs/api/en/materials/MeshLambertMaterial.html

@@ -119,15 +119,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>The color map. Default is  null.</p>
 		<p>The color map. Default is  null.</p>
 
 
-		<h3>[property:Boolean morphNormals]</h3>
-		<p>
-			Defines whether the material uses morphNormals. Set as true to pass morphNormal
-			attributes from the 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:Float reflectivity]</h3>
 		<h3>[property:Float reflectivity]</h3>
 		<p>How much the environment map affects the surface; also see [page:.combine].</p>
 		<p>How much the environment map affects the surface; also see [page:.combine].</p>
 
 

+ 0 - 9
docs/api/en/materials/MeshMatcapMaterial.html

@@ -106,15 +106,6 @@
 		<h3>[property:Texture matcap]</h3>
 		<h3>[property:Texture matcap]</h3>
 		<p>The matcap map. Default is null.</p>
 		<p>The matcap map. Default is null.</p>
 
 
-		<h3>[property:Boolean morphNormals]</h3>
-		<p>
-			Defines whether the material uses morphNormals. Set as true to pass morphNormal
-			attributes from the 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>
 		<h3>[property:Texture normalMap]</h3>
 		<p>
 		<p>
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change

+ 0 - 9
docs/api/en/materials/MeshNormalMaterial.html

@@ -83,15 +83,6 @@
 		<h3>[property:Boolean fog]</h3>
 		<h3>[property:Boolean fog]</h3>
 		<p>Whether the material is affected by fog. Default is *false*.</p>
 		<p>Whether the material is affected by fog. Default is *false*.</p>
 
 
-		<h3>[property:Boolean morphNormals]</h3>
-		<p>
-			Defines whether the material uses morphNormals. Set as true to pass morphNormal
-			attributes from the 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>
 		<h3>[property:Texture normalMap]</h3>
 		<p>
 		<p>
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change

+ 0 - 9
docs/api/en/materials/MeshPhongMaterial.html

@@ -156,15 +156,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>The color map. Default is null. The texture map color is modulated by the diffuse [page:.color].</p>
 		<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 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>
 		<h3>[property:Texture normalMap]</h3>
 		<p>
 		<p>
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change

+ 0 - 16
docs/api/en/materials/MeshStandardMaterial.html

@@ -196,15 +196,6 @@
 		<h3>[property:Texture metalnessMap]</h3>
 		<h3>[property:Texture metalnessMap]</h3>
 		<p>The blue channel of this texture is used to alter the metalness of the material.</p>
 		<p>The blue channel of this texture is used to alter the metalness of the material.</p>
 
 
-		<h3>[property:Boolean morphNormals]</h3>
-		<p>
-			Defines whether the material uses morphNormals. Set as true to pass morphNormal
-			attributes from the 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>
 		<h3>[property:Texture normalMap]</h3>
 		<p>
 		<p>
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
@@ -242,13 +233,6 @@
 		<h3>[property:Texture roughnessMap]</h3>
 		<h3>[property:Texture roughnessMap]</h3>
 		<p>The green channel of this texture is used to alter the roughness of the material.</p>
 		<p>The green channel of this texture is used to alter the roughness of the material.</p>
 
 
-		<h3>[property:Boolean vertexTangents]</h3>
-		<p>
-		Defines whether precomputed vertex tangents, which must be provided in a vec4 "tangent" attribute,
-		are used. When disabled, tangents are derived automatically. Using precomputed tangents will give
-		more accurate normal map details in some cases, such as with mirrored UVs. Default is false.
-		</p>
-
 		<h3>[property:Boolean wireframe]</h3>
 		<h3>[property:Boolean wireframe]</h3>
 		<p>Render geometry as wireframe. Default is *false* (i.e. render as flat polygons).</p>
 		<p>Render geometry as wireframe. Default is *false* (i.e. render as flat polygons).</p>
 
 

+ 0 - 9
docs/api/en/materials/MeshToonMaterial.html

@@ -133,15 +133,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>The color map. Default is null. The texture map color is modulated by the diffuse [page:.color].</p>
 		<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 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>
 		<h3>[property:Texture normalMap]</h3>
 		<p>
 		<p>
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change

+ 0 - 4
docs/api/en/materials/PointsMaterial.html

@@ -82,12 +82,8 @@
 		<p>[page:Color] of the material, by default set to white (0xffffff).</p>
 		<p>[page:Color] of the material, by default set to white (0xffffff).</p>
 
 
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
-
 		<p>Sets the color of the points using data from a [page:Texture].</p>
 		<p>Sets the color of the points using data from a [page:Texture].</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>Define whether the material uses morphTargets. Default is false.</p>
-
 		<h3>[property:Number size]</h3>
 		<h3>[property:Number size]</h3>
 		<p>Sets the size of the points. Default is 1.0.<br/>
 		<p>Sets the size of the points. Default is 1.0.<br/>
 			Will be capped if it exceeds the hardware dependent parameter [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParameter gl.ALIASED_POINT_SIZE_RANGE].</p>
 			Will be capped if it exceeds the hardware dependent parameter [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParameter gl.ALIASED_POINT_SIZE_RANGE].</p>

+ 0 - 11
docs/api/en/materials/ShaderMaterial.html

@@ -367,17 +367,6 @@ this.extensions = {
 		always be 1 regardless of the set value.
 		always be 1 regardless of the set value.
 		</p>
 		</p>
 
 
-
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>
-		When set to true, morph target attributes are available in the vertex shader. Default is *false*.
-		</p>
-
-		<h3>[property:Boolean morphNormals]</h3>
-		<p>
-		When set to true, morph normal attributes are available in the vertex shader. Default is *false*.
-		</p>
-
 		<h3>[property:Boolean flatShading]</h3>
 		<h3>[property:Boolean flatShading]</h3>
 		<p>
 		<p>
 		Define whether the material is rendered with flat shading. Default is false.
 		Define whether the material is rendered with flat shading. Default is false.

+ 5 - 0
docs/api/ko/animation/AnimationUtils.html

@@ -42,6 +42,11 @@
 		타입 배열이면 *true*를 리턴합니다.
 		타입 배열이면 *true*를 리턴합니다.
 		</p>
 		</p>
 
 
+		<h3>[method:AnimationClip makeClipAdditive]( [param:AnimationClip targetClip], [param:Number referenceFrame], [param:AnimationClip referenceClip], [param:Number fps] )</h3>
+		<p>
+		Converts the keyframes of the given animation clip to an additive format.
+		</p>
+
 		<h3>[method:Array sortedArray]( values, stride, order )</h3>
 		<h3>[method:Array sortedArray]( values, stride, order )</h3>
 		<p>
 		<p>
 		이전에 [page:AnimationUtils.getKeyframeOrder getKeyframeOrder]를 통해 리턴된 배열을 정렬합니다.
 		이전에 [page:AnimationUtils.getKeyframeOrder getKeyframeOrder]를 통해 리턴된 배열을 정렬합니다.

+ 4 - 5
docs/api/zh/animation/AnimationUtils.html

@@ -37,17 +37,16 @@
 		返回一个数组,时间和值可以根据此数组排序。
 		返回一个数组,时间和值可以根据此数组排序。
 		</p>
 		</p>
 
 
-		<h3>[method:Number insertKeyframe]( [param:KeyframeTrack track], [param:Number time] )</h3>
-		<p></p>
-
 		<h3>[method:Boolean isTypedArray]( object )</h3>
 		<h3>[method:Boolean isTypedArray]( object )</h3>
 		<p>
 		<p>
 		如果该对象是类型化数组,返回*true*
 		如果该对象是类型化数组,返回*true*
 
 
 		</p>
 		</p>
 
 
-		<h3>[method:AnimationClip mergeMorphTargetTracks]( [param:AnimationClip clip], [param:Object3D root] )</h3>
-		<p></p>
+		<h3>[method:AnimationClip makeClipAdditive]( [param:AnimationClip targetClip], [param:Number referenceFrame], [param:AnimationClip referenceClip], [param:Number fps] )</h3>
+		<p>
+		Converts the keyframes of the given animation clip to an additive format.
+		</p>
 
 
 		<h3>[method:Array sortedArray]( values, stride, order )</h3>
 		<h3>[method:Array sortedArray]( values, stride, order )</h3>
 		<p>
 		<p>

+ 51 - 0
docs/api/zh/constants/BufferAttributeUsage.html

@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html lang="zh">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		<h1>Buffer Attribute Usage Constants</h1>
+
+		<p>
+			The usage constants can be used to provide a hint to the API regarding how the geometry buffer attribute will be used in order to optimize performance.
+		</p>
+
+		<h2>Code Example</h2>
+
+		<code>
+		const geometry = new THREE.BufferGeometry();
+		const positionAttribute = new THREE.BufferAttribute( array, 3 , false );
+		positionAttribute.setUsage( THREE.DynamicDrawUsage );
+		geometry.setAttribute( 'position', positionAttribute );
+		</code>
+
+		<h2>Examples</h2>
+		<p>[example:webgl_buffergeometry_drawrange materials / buffergeometry / drawrange ]</p>
+
+		<h2>Geometry Usage</h2>
+		<code>
+		THREE.StaticDrawUsage
+		THREE.DynamicDrawUsage
+		THREE.StreamDrawUsage
+
+		THREE.StaticReadUsage
+		THREE.DynamicReadUsage
+		THREE.StreamReadUsage
+
+		THREE.StaticCopyUsage
+		THREE.DynamicCopyUsage
+		THREE.StreamCopyUsage
+		</code>
+
+		For more detailed information on each of these constants see [link:https://www.khronos.org/opengl/wiki/Buffer_Object#Buffer_Object_Usage this OpenGL documentation].
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/src/constants.js src/constants.js]
+		</p>
+	</body>
+</html>

+ 1 - 1
docs/api/zh/constants/Renderer.html

@@ -35,7 +35,7 @@
 
 
 		[page:constant BasicShadowMap] 能够给出没有经过过滤的阴影映射 —— 速度最快,但质量最差。<br />
 		[page:constant BasicShadowMap] 能够给出没有经过过滤的阴影映射 —— 速度最快,但质量最差。<br />
 		[page:constant PCFShadowMap] 为默认值,使用Percentage-Closer Filtering (PCF)算法来过滤阴影映射。<br />
 		[page:constant PCFShadowMap] 为默认值,使用Percentage-Closer Filtering (PCF)算法来过滤阴影映射。<br />
-		[page:constant PCFSoftShadowMap] filters shadow maps using the Percentage-Closer Filtering (PCF) algorithm with better soft shadows especially when using low-resolution shadow maps.<br />
+		[page:constant PCFSoftShadowMap] 和PCFShadowMap一样使用 Percentage-Closer Filtering (PCF) 算法过滤阴影映射,但在使用低分辨率阴影图时具有更好的软阴影。<br />
 		[page:constant VSMShadowMap] 使用Variance Shadow Map (VSM)算法来过滤阴影映射。当使用VSMShadowMap时,所有阴影接收者也将会投射阴影。
 		[page:constant VSMShadowMap] 使用Variance Shadow Map (VSM)算法来过滤阴影映射。当使用VSMShadowMap时,所有阴影接收者也将会投射阴影。
 		</p>
 		</p>
 
 

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

@@ -87,7 +87,7 @@
 		<p>
 		<p>
 			Defines the intended usage pattern of the data store for optimization purposes. Corresponds to the *usage* parameter of
 			Defines the intended usage pattern of the data store for optimization purposes. Corresponds to the *usage* parameter of
 			[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData]().
 			[link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/bufferData WebGLRenderingContext.bufferData]().
-			Default is *THREE.StaticDrawUsage*.
+			Default is [page:BufferAttributeUsage StaticDrawUsage]. See usage [page:BufferAttributeUsage constants] for all possible values.
 		</p>
 		</p>
 
 
 		<h3>[property:Integer version]</h3>
 		<h3>[property:Integer version]</h3>
@@ -160,7 +160,7 @@
 		</p>
 		</p>
 
 
 		<h3>[method:BufferAttribute setUsage] ( [param:Usage value] ) </h3>
 		<h3>[method:BufferAttribute setUsage] ( [param:Usage value] ) </h3>
-		<p>Set [page:BufferAttribute.usage usage] to value.</p>
+		<p>Set [page:BufferAttribute.usage usage] to value. See usage [page:BufferAttributeUsage constants] for all possible input values.</p>
 
 
 		<h3>[method:BufferAttribute setX]( [param:Integer index], [param:Float x] ) </h3>
 		<h3>[method:BufferAttribute setX]( [param:Integer index], [param:Float x] ) </h3>
 		<p>设置给定索引的矢量的第一维数据(设置 X 值)。</p>
 		<p>设置给定索引的矢量的第一维数据(设置 X 值)。</p>

+ 3 - 0
docs/api/zh/core/InstancedBufferGeometry.html

@@ -31,6 +31,9 @@
 		<h2>方法</h2>
 		<h2>方法</h2>
 		<p>继承方法详见 [page:BufferGeometry]。</p>
 		<p>继承方法详见 [page:BufferGeometry]。</p>
 
 
+		<h3>[method:InstancedBufferGeometry copy]( [param:InstancedBufferGeometry source] )</h3>
+		<p>Copies the given [name] to this instance.</p>
+
 		<h2>源代码</h2>
 		<h2>源代码</h2>
 
 
 		<p>
 		<p>

+ 4 - 4
docs/api/zh/geometries/SphereGeometry.html

@@ -33,8 +33,8 @@
 
 
 		<h2>代码示例</h2>
 		<h2>代码示例</h2>
 
 
-		<code>const geometry = new THREE.SphereGeometry( 5, 32, 32 );
-		const material = new THREE.MeshBasicMaterial( {color: 0xffff00} );
+		<code>const geometry = new THREE.SphereGeometry( 15, 32, 16 );
+		const material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
 		const sphere = new THREE.Mesh( geometry, material );
 		const sphere = new THREE.Mesh( geometry, material );
 		scene.add( sphere );
 		scene.add( sphere );
 		</code>
 		</code>
@@ -45,8 +45,8 @@
 
 
 		<p>
 		<p>
 			radius — 球体半径,默认为1。<br />
 			radius — 球体半径,默认为1。<br />
-			widthSegments — 水平分段数(沿着经线分段),最小值为3,默认值为8。<br />
-			heightSegments — 垂直分段数(沿着纬线分段),最小值为2,默认值为6。<br />
+			widthSegments — 水平分段数(沿着经线分段),最小值为3,默认值为32。<br />
+			heightSegments — 垂直分段数(沿着纬线分段),最小值为2,默认值为16。<br />
 			phiStart — 指定水平(经线)起始角度,默认值为0。。<br />
 			phiStart — 指定水平(经线)起始角度,默认值为0。。<br />
 			phiLength — 指定水平(经线)扫描角度的大小,默认值为 Math.PI * 2。<br />
 			phiLength — 指定水平(经线)扫描角度的大小,默认值为 Math.PI * 2。<br />
 			thetaStart — 指定垂直(纬线)起始角度,默认值为0。<br />
 			thetaStart — 指定垂直(纬线)起始角度,默认值为0。<br />

+ 0 - 3
docs/api/zh/materials/LineBasicMaterial.html

@@ -76,9 +76,6 @@
 			并且会被[page:WebGLRenderer WebGL]渲染器忽略。
 			并且会被[page:WebGLRenderer WebGL]渲染器忽略。
 		</p>
 		</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>Define whether the material uses morphTargets. Default is false.</p>
-
 		<h2>方法(Methods)</h2>
 		<h2>方法(Methods)</h2>
 		<p>共有方法请参见其基类[page:Material]。</p>
 		<p>共有方法请参见其基类[page:Material]。</p>
 
 

+ 0 - 4
docs/api/zh/materials/MeshBasicMaterial.html

@@ -82,10 +82,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p> 颜色贴图。默认为null。</p>
 		<p> 颜色贴图。默认为null。</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>材质是否使用morphTargets。默认值为false。</p>
-
-
 		<h3>[property:Float reflectivity]</h3>
 		<h3>[property:Float reflectivity]</h3>
 		<p> 环境贴图对表面的影响程度; 见[page:.combine]。默认值为1,有效范围介于0(无反射)和1(完全反射)之间。
 		<p> 环境贴图对表面的影响程度; 见[page:.combine]。默认值为1,有效范围介于0(无反射)和1(完全反射)之间。
 		</p>
 		</p>

+ 0 - 3
docs/api/zh/materials/MeshDepthMaterial.html

@@ -73,9 +73,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>颜色贴图。默认为null。</p>
 		<p>颜色贴图。默认为null。</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>材质是否使用morphTargets。默认值为false。</p>
-
 		<h3>[property:Boolean wireframe]</h3>
 		<h3>[property:Boolean wireframe]</h3>
 		<p> 将几何体渲染为线框。默认值为*false*(即渲染为平滑着色)。</p>
 		<p> 将几何体渲染为线框。默认值为*false*(即渲染为平滑着色)。</p>
 
 

+ 0 - 3
docs/api/zh/materials/MeshDistanceMaterial.html

@@ -84,9 +84,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>颜色贴图。默认为null。</p>
 		<p>颜色贴图。默认为null。</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>材质是否使用morphTargets。默认值为false。</p>
-
 		<h3>[property:Float nearDistance]</h3>
 		<h3>[property:Float nearDistance]</h3>
 		<p>
 		<p>
 			The near value of the point light's internal shadow camera.
 			The near value of the point light's internal shadow camera.

+ 0 - 7
docs/api/zh/materials/MeshLambertMaterial.html

@@ -101,13 +101,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>颜色贴图。默认为null。</p>
 		<p>颜色贴图。默认为null。</p>
 
 
-		<h3>[property:Boolean morphNormals]</h3>
-		<p> 定义是否使用morphNormals。设置为true可将morphNormal属性从geometry传递到shader。默认值为*false*。
-		</p>
-
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>定义材质是否使用morphTargets。默认值为false。</p>
-
 		<h3>[property:Float reflectivity]</h3>
 		<h3>[property:Float reflectivity]</h3>
 		<p> 环境贴图对表面的影响程度; 见[page:.combine]。默认值为1,有效范围介于0(无反射)和1(完全反射)之间。</p>
 		<p> 环境贴图对表面的影响程度; 见[page:.combine]。默认值为1,有效范围介于0(无反射)和1(完全反射)之间。</p>
 
 

+ 0 - 7
docs/api/zh/materials/MeshMatcapMaterial.html

@@ -90,13 +90,6 @@
 		<h3>[property:Texture matcap]</h3>
 		<h3>[property:Texture matcap]</h3>
 		<p>matcap贴图,默认为null。</p>
 		<p>matcap贴图,默认为null。</p>
 
 
-		<h3>[property:Boolean morphNormals]</h3>
-		<p> 定义是否使用morphNormals。设置为true可将morphNormal属性从geometry传递到shader。默认值为*false*。
-		</p>
-
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>定义材质是否使用morphTargets。默认值为false。</p>
-
 		<h3>[property:Texture normalMap]</h3>
 		<h3>[property:Texture normalMap]</h3>
 		<p> 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
 		<p> 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
 			In case the material has a normal map authored using the left handed convention, the y component of normalScale
 			In case the material has a normal map authored using the left handed convention, the y component of normalScale

+ 0 - 7
docs/api/zh/materials/MeshNormalMaterial.html

@@ -69,13 +69,6 @@
 		<h3>[property:Boolean fog]</h3>
 		<h3>[property:Boolean fog]</h3>
 		<p>材质是否受雾影响。默认值为*false*。</p>
 		<p>材质是否受雾影响。默认值为*false*。</p>
 
 
-		<h3>[property:Boolean morphNormals]</h3>
-		<p> 定义是否使用morphNormals。设置为true可将morphNormal属性从geometry传递到shader。默认值为*false*。
-		</p>
-
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>定义材质是否使用morphTargets。默认值为false。</p>
-
 		<h3>[property:Texture normalMap]</h3>
 		<h3>[property:Texture normalMap]</h3>
 		<p> 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
 		<p> 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
 			In case the material has a normal map authored using the left handed convention, the y component of normalScale
 			In case the material has a normal map authored using the left handed convention, the y component of normalScale

+ 0 - 7
docs/api/zh/materials/MeshPhongMaterial.html

@@ -125,13 +125,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>颜色贴图。默认为null。纹理贴图颜色由漫反射颜色[page:.color]调节。</p>
 		<p>颜色贴图。默认为null。纹理贴图颜色由漫反射颜色[page:.color]调节。</p>
 
 
-		<h3>[property:Boolean morphNormals]</h3>
-		<p> 定义是否使用morphNormals。设置为true可将morphNormal属性从geometry传递到shader。默认值为*false*。
-		</p>
-
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>定义材质是否使用morphTargets。默认值为false。</p>
-
 		<h3>[property:Texture normalMap]</h3>
 		<h3>[property:Texture normalMap]</h3>
 		<p> 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
 		<p> 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
 			In case the material has a normal map authored using the left handed convention, the y component of normalScale
 			In case the material has a normal map authored using the left handed convention, the y component of normalScale

+ 0 - 15
docs/api/zh/materials/MeshStandardMaterial.html

@@ -161,13 +161,6 @@
 		<h3>[property:Texture metalnessMap]</h3>
 		<h3>[property:Texture metalnessMap]</h3>
 		<p> 该纹理的蓝色通道用于改变材质的金属度。</p>
 		<p> 该纹理的蓝色通道用于改变材质的金属度。</p>
 
 
-		<h3>[property:Boolean morphNormals]</h3>
-		<p> 定义是否使用morphNormals。设置为true可将morphNormal属性从geometry传递到shader。默认值为*false*。
-		</p>
-
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>定义材质是否使用morphTargets。默认值为false。</p>
-
 		<h3>[property:Texture normalMap]</h3>
 		<h3>[property:Texture normalMap]</h3>
 		<p>用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
 		<p>用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
 			In case the material has a normal map authored using the left handed convention, the y component of normalScale
 			In case the material has a normal map authored using the left handed convention, the y component of normalScale
@@ -198,14 +191,6 @@
 		<h3>[property:Texture roughnessMap]</h3>
 		<h3>[property:Texture roughnessMap]</h3>
 		<p>该纹理的绿色通道用于改变材质的粗糙度。</p>
 		<p>该纹理的绿色通道用于改变材质的粗糙度。</p>
 
 
-		<h3>[property:Boolean vertexTangents]</h3>
-		<p>
-		Defines whether precomputed vertex tangents, which must be provided in a vec4 "tangent" attribute,
-		are used. When disabled, tangents are derived automatically. Using precomputed tangents will give
-		more accurate normal map details in some cases, such as with mirrored UVs. Default is false.
-		</p>
-
-
 		<h3>[property:Boolean wireframe]</h3>
 		<h3>[property:Boolean wireframe]</h3>
 		<p>将几何体渲染为线框。默认值为*false*(即渲染为平面多边形)。</p>
 		<p>将几何体渲染为线框。默认值为*false*(即渲染为平面多边形)。</p>
 
 

+ 0 - 9
docs/api/zh/materials/MeshToonMaterial.html

@@ -133,15 +133,6 @@
 		<h3>[property:Texture map]</h3>
 		<h3>[property:Texture map]</h3>
 		<p>The color map. Default is null. The texture map color is modulated by the diffuse [page:.color].</p>
 		<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 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>
 		<h3>[property:Texture normalMap]</h3>
 		<p>
 		<p>
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
 			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change

+ 0 - 3
docs/api/zh/materials/PointsMaterial.html

@@ -82,9 +82,6 @@
 
 
 		<p>使用[page:Texture]中的数据设置点的颜色。</p>
 		<p>使用[page:Texture]中的数据设置点的颜色。</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p>材质是否使用morphTargets。默认值为false。</p>
-
 		<h3>[property:Number size]</h3>
 		<h3>[property:Number size]</h3>
 		<p>设置点的大小。默认值为1.0。<br/>
 		<p>设置点的大小。默认值为1.0。<br/>
 			Will be capped if it exceeds the hardware dependent parameter [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParameter gl.ALIASED_POINT_SIZE_RANGE].</p>
 			Will be capped if it exceeds the hardware dependent parameter [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/getParameter gl.ALIASED_POINT_SIZE_RANGE].</p>

+ 0 - 8
docs/api/zh/materials/ShaderMaterial.html

@@ -325,14 +325,6 @@ this.extensions = {
 			由于[link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]与大多数平台上[page:WebGLRenderer WebGL]渲染器的限制,无论如何设置该值,线宽始终为1。
 			由于[link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile]与大多数平台上[page:WebGLRenderer WebGL]渲染器的限制,无论如何设置该值,线宽始终为1。
 		</p>
 		</p>
 
 
-		<h3>[property:Boolean morphTargets]</h3>
-		<p> When set to true, morph target attributes are available in the vertex shader. Default is *false*.
-		</p>
-
-		<h3>[property:Boolean morphNormals]</h3>
-		<p> When set to true, morph normal attributes are available in the vertex shader. Default is *false*.
-		</p>
-
 		<h3>[property:Boolean flatShading]</h3>
 		<h3>[property:Boolean flatShading]</h3>
 		<p> 定义材质是否使用平面着色进行渲染。默认值为false。
 		<p> 定义材质是否使用平面着色进行渲染。默认值为false。
 		</p>
 		</p>

+ 2 - 4
docs/api/zh/math/Matrix3.html

@@ -102,9 +102,7 @@ zAxis = (c, f, i)
 
 
 		<h3>[method:this invert]()</h3>
 		<h3>[method:this invert]()</h3>
 		<p>
 		<p>
-		Inverts this matrix, using the [link:https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution analytic method].
-
-		You can not invert with a determinant of zero. If you attempt this, the method produces a zero matrix instead.
+		将当前矩阵翻转为它的逆矩阵,使用 [link:https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution analytic method] 解析方式。你不能对行或列为 0 的矩阵进行翻转,如果你尝试这样做,该方法将生成一个零矩阵。
 		</p>
 		</p>
 
 
 		<h3>[method:this getNormalMatrix]( [param:Matrix4 m] )</h3>
 		<h3>[method:this getNormalMatrix]( [param:Matrix4 m] )</h3>
@@ -153,7 +151,7 @@ zAxis = (c, f, i)
 		<p>将矩阵[page:Matrix3 m]乘以当前矩阵。</p>
 		<p>将矩阵[page:Matrix3 m]乘以当前矩阵。</p>
 
 
 		<h3>[method:this setFromMatrix4]( [param:Matrix4 m] )</h3>
 		<h3>[method:this setFromMatrix4]( [param:Matrix4 m] )</h3>
-		<p>将当前矩阵设置为4X4矩阵[page:Matrix4 m]左上3X3</p>
+		<p>根据参数 [page:Matrix4 m] 左上 3x3 的矩阵值,设置当前矩阵的值。</p>
 
 
 		<h3>[method:this setUvTransform]( [param:Float tx], [param:Float ty], [param:Float sx], [param:Float sy], [param:Float rotation], [param:Float cx], [param:Float cy] )</h3>
 		<h3>[method:this setUvTransform]( [param:Float tx], [param:Float ty], [param:Float sx], [param:Float sy], [param:Float rotation], [param:Float cx], [param:Float cy] )</h3>
 		<p>
 		<p>

+ 2 - 4
docs/api/zh/math/Matrix4.html

@@ -175,9 +175,7 @@ zAxis = (c, g, k)
 
 
 		<h3>[method:this invert]()</h3>
 		<h3>[method:this invert]()</h3>
 		<p>
 		<p>
-		Inverts this matrix, using the [link:https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution analytic method].
-
-		You can not invert with a determinant of zero. If you attempt this, the method produces a zero matrix instead.
+		将当前矩阵翻转为它的逆矩阵,使用 [link:https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution analytic method] 解析方式。你不能对行或列为 0 的矩阵进行翻转,如果你尝试这样做,该方法将生成一个零矩阵。
 		</p>
 		</p>
 
 
 		<h3>[method:Float getMaxScaleOnAxis]()</h3>
 		<h3>[method:Float getMaxScaleOnAxis]()</h3>
@@ -353,7 +351,7 @@ x, y, 1, 0,
 		</p>
 		</p>
 
 
 		<h3>[method:this setFromMatrix3]( [param:Matrix3 m] )</h3>
 		<h3>[method:this setFromMatrix3]( [param:Matrix3 m] )</h3>
-		<p>Set the upper 3x3 elements of this matrix to the values of the Matrix3 [page:Matrix3 m].</p>
+		<p>根据参数 [page:Matrix3 m] 的值,设置当前矩阵左上 3x3 的矩阵值。</p>
 
 
 		<h3>[method:this setPosition]( [param:Vector3 v] )</h3>
 		<h3>[method:this setPosition]( [param:Vector3 v] )</h3>
 		<h3>[method:this setPosition]( [param:Float x], [param:Float y], [param:Float z] ) // optional API</h3>
 		<h3>[method:this setPosition]( [param:Float x], [param:Float y], [param:Float z] ) // optional API</h3>

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

@@ -216,7 +216,7 @@ controls.mouseButtons = {
 
 
 		<h3>[property:Vector3 position0]</h3>
 		<h3>[property:Vector3 position0]</h3>
 		<p>
 		<p>
-			Used internally by the [method:saveState] and [method:reset] methods.
+			Used internally by the [page:.saveState] and [page:.reset] methods.
 		</p>
 		</p>
 
 
 		<h3>[property:Float rotateSpeed]</h3>
 		<h3>[property:Float rotateSpeed]</h3>
@@ -233,7 +233,7 @@ controls.mouseButtons = {
 
 
 		<h3>[property:Vector3 target0]</h3>
 		<h3>[property:Vector3 target0]</h3>
 		<p>
 		<p>
-			Used internally by the [method:saveState] and [method:reset] methods.
+			Used internally by the [page:.saveState] and [page:.reset] methods.
 		</p>
 		</p>
 
 
 		<h3>[property:Vector3 target]</h3>
 		<h3>[property:Vector3 target]</h3>
@@ -255,7 +255,7 @@ controls.touches = {
 
 
 		<h3>[property:Float zoom0]</h3>
 		<h3>[property:Float zoom0]</h3>
 		<p>
 		<p>
-			Used internally by the [method:saveState] and [method:reset] methods.
+			Used internally by the [page:.saveState] and [page:.reset] methods.
 		</p>
 		</p>
 
 
 		<h3>[property:Float zoomSpeed]</h3>
 		<h3>[property:Float zoomSpeed]</h3>
@@ -282,6 +282,11 @@ controls.touches = {
 			Get the current vertical rotation, in radians.
 			Get the current vertical rotation, in radians.
 		</p>
 		</p>
 
 
+		<h3>[method:Float getDistance] ()</h3>
+		<p>
+			Returns the distance from the camera to the target.
+		</p>
+
 		<h3>[method:void listenToKeyEvents] ( [param:HTMLDOMElement domElement] )</h3>
 		<h3>[method:void listenToKeyEvents] ( [param:HTMLDOMElement domElement] )</h3>
 		<p>
 		<p>
 			Adds key event listeners to the given DOM element. *window* is a recommended argument for using this method.
 			Adds key event listeners to the given DOM element. *window* is a recommended argument for using this method.

+ 8 - 0
docs/examples/en/controls/TransformControls.html

@@ -161,6 +161,14 @@
 			Should be called if the controls is no longer required.
 			Should be called if the controls is no longer required.
 		</p>
 		</p>
 
 
+		<h3>[method:Raycaster getRaycaster] ()</h3>
+		<p>
+			Returns the [page:Raycaster] object that is used for user interaction. This object is shared between all instances of
+			TransformControls. If you set the [page:Object3D.layers .layers] property of the [name], you will also want to
+			set the [page:Raycaster.layers .layers] property on the [page:Raycaster] with a matching value, or else the [name]
+			won't work as expected.
+		</p>
+
 		<h3>[method:String getMode] ()</h3>
 		<h3>[method:String getMode] ()</h3>
 		<p>
 		<p>
 			Returns the transformation mode.
 			Returns the transformation mode.

+ 3 - 0
docs/examples/en/exporters/ColladaExporter.html

@@ -48,6 +48,9 @@
 			<li>version - string. Which version of Collada to export. The options are "1.4.1" or "1.5.0". Defaults to "1.4.1".</li>
 			<li>version - string. Which version of Collada to export. The options are "1.4.1" or "1.5.0". Defaults to "1.4.1".</li>
 			<li>author - string. The name to include in the author field. Author field is excluded by default.</li>
 			<li>author - string. The name to include in the author field. Author field is excluded by default.</li>
 			<li>textureDirectory - string. The directory relative to the Collada file to save the textures to.</li>
 			<li>textureDirectory - string. The directory relative to the Collada file to save the textures to.</li>
+			<li>upAxis - string. Either Y_UP (default), Z_UP or X_UP.</li>
+			<li>unitName - string. Name of the unit. Can be any string, but could be for example "meter", "inch", or "parsec".</li>
+			<li>unitMeter - number. Length of the unit in meters.</li>
 		</ul>
 		</ul>
 		</p>
 		</p>
 		<p>
 		<p>

+ 4 - 0
docs/examples/en/loaders/GLTFLoader.html

@@ -30,8 +30,12 @@
 		<ul>
 		<ul>
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_materials_clearcoat</li>
 			<li>KHR_materials_clearcoat</li>
+			<li>KHR_materials_ior</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
+			<li>KHR_materials_specular</li>
+			<li>KHR_materials_transmission</li>
 			<li>KHR_materials_unlit</li>
 			<li>KHR_materials_unlit</li>
+			<li>KHR_materials_volume</li>
 			<li>KHR_mesh_quantization</li>
 			<li>KHR_mesh_quantization</li>
 			<li>KHR_lights_punctual<sup>1</sup></li>
 			<li>KHR_lights_punctual<sup>1</sup></li>
 			<li>KHR_texture_basisu</li>
 			<li>KHR_texture_basisu</li>

+ 40 - 57
docs/examples/en/math/Lut.html

@@ -23,116 +23,99 @@
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]( colormap, numberOfColors )</h3>
+		<h3>[name]( [param:String colormap], [param:Number count] )</h3>
 		<p>
 		<p>
-		colormap - optional argument that sets a colormap from predefined colormaps. Available colormaps are : "rainbow", "cooltowarm", "blackbody".
-		numberOfColors - optional argument that sets the number of colors used to represent the data array.
+		colormap - Sets a colormap from predefined colormaps. Available colormaps are : *rainbow*, *cooltowarm*, *blackbody*, *grayscale*. Default is *rainbow*.<br />
+		count - Sets the number of colors used to represent the data array. Default is *32*.
 		</p>
 		</p>
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
 
 
-		<h3>[property:Float minV]</h3>
+		<h3>[property:Array lut]</h3>
 		<p>
 		<p>
-		The minimum value to be represented with the lookup table. Default is 0.
+		The lookup table for the selected color map represented as an array of [page:Color]s.
 		</p>
 		</p>
 
 
-		<h3>[property:Float maxV]</h3>
+		<h3>[property:Array map]</h3>
 		<p>
 		<p>
-		The maximum value to be represented with the lookup table. Default is 1.
+		The currently selected color map. Default is the *rainbow* color map.
 		</p>
 		</p>
 
 
-		<h3>.[legend]</h3>
+		<h3>[property:Number minV]</h3>
 		<p>
 		<p>
-		The legend of the lookup table.
+		The minimum value to be represented with the lookup table. Default is *0*.
 		</p>
 		</p>
 
 
-		<h2>Methods</h2>
-
-		<h3>[method:null copy]( [param:Lut lut] ) [param:Lut this]</h3>
-		<p>
-		color — Lut to copy.
-		</p>
+		<h3>[property:Number maxV]</h3>
 		<p>
 		<p>
-		Copies given lut.
+		The maximum value to be represented with the lookup table. Default is *1*.
 		</p>
 		</p>
 
 
-		<h3>.setLegendOn [parameters]</h3>
+		<h3>[property:Number n]</h3>
 		<p>
 		<p>
-		parameters - { layout: value, position: { x: value, y: value, z: value }, dimensions: { width: value, height: value } }
-		layout — Horizontal or vertical layout. Default is vertical.<br />
-		position — The position x,y,z of the legend.<br />
-		dimensions — The dimensions (width and height) of the legend.<br />
-		</p>
-		<p>
-		Sets this Lut with the legend on.
+		The number of colors of the current selected color map. Default is *32*.
 		</p>
 		</p>
 
 
-		<h3>.setLegendOff</h3>
+		<h2>Methods</h2>
+
+		<h3>[method:null copy]( [param:Lut lut] ) [param:Lut this]</h3>
 		<p>
 		<p>
+		color — Lut to copy.
 		</p>
 		</p>
 		<p>
 		<p>
-		Sets this Lut with the legend off.
+		Copies the given lut.
 		</p>
 		</p>
 
 
-    <h3>.setLegendLabels [parameters, callback]</h3>
+		<h3>[method:Lut addColorMap]( [param:String name], [param:Array arrayOfColors] )</h3>
 		<p>
 		<p>
-		parameters - { fontsize: value, fontface: value, title: value, um: value, ticks: value, decimal: value, notation: value }
-		fontsize — Font size to be used for labels.<br />
-		fontface — Font type to be used for labels.<br />
-		title — The title of the legend.<br />
-		um — The unit of measurements of the legend.<br />
-		ticks — The number of ticks to be displayed.<br />
-		decimal — The number of decimals to be used for legend values.<br />
-		notation — Legend notation: standard (default) or scientific.<br />
-		callback — An optional callback to be used to format the legend labels.<br />
+		name — The name of the color map.<br />
+		arrayOfColors — An array of color values. Each value is an array holding a threshold and the actual color value as a hexadecimal number.
 		</p>
 		</p>
 		<p>
 		<p>
-		Sets the labels of the legend of this Lut.
+		Adds a color map to this [name] instance.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut setMin]( [param:Float minV] )</h3>
-		<p>
-		minV — The minimum value to be represented with the lookup table.<br />
-		</p>
+		<h3>[method:HTMLCanvasElement createCanvas]()</h3>
 		<p>
 		<p>
-		Sets this Lut with the minimum value to be represented.
+		Creates a canvas in order to visualize the lookup table as a texture.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut setMax]( [param:Float maxV] )</h3>
+		<h3>[method:Color getColor]( [param:Number alpha] )</h3>
 		<p>
 		<p>
-		maxV — The maximum value to be represented with the lookup table.<br />
+		value -- the data value to be displayed as a color.
 		</p>
 		</p>
 		<p>
 		<p>
-		Sets this Lut with the maximum value to be represented.
+		Returns an instance of [page:Color] for the given data value.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut changeNumberOfColors]( [param:Float numberOfColors] )</h3>
+		<h3>[method:Lut setColorMap]( [param:String colormap], [param:Number count] )</h3>
 		<p>
 		<p>
-		numberOfColors — The number of colors to be used to represent the data array.<br />
+		colormap — The name of the color map.<br />
+		count — The number of colors. Default is *32*.
 		</p>
 		</p>
 		<p>
 		<p>
-		Sets this Lut with the number of colors to be used.
+		Configure the lookup table for the given color map and number of colors.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut changeColorMap]( [param:Float colorMap] )</h3>
+		<h3>[method:Lut setMin]( [param:Number minV] )</h3>
 		<p>
 		<p>
-		colorMap — The name of the color map to be used to represent the data array.<br />
+		minV — The minimum value to be represented with the lookup table
 		</p>
 		</p>
 		<p>
 		<p>
-		Sets this Lut with the colormap to be used.
+		Sets this Lut with the minimum value to be represented.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut addColorMap]( colorMapName, arrayOfColors )</h3>
+		<h3>[method:Lut setMax]( [param:Number maxV] )</h3>
 		<p>
 		<p>
-		Insert a new color map into the set of available color maps.
+		maxV — The maximum value to be represented with the lookup table.
 		</p>
 		</p>
-
-		<h3>[method:Lut getColor]( value ) [param:Lut this]</h3>
 		<p>
 		<p>
-		value -- the data value to be displayed as a color.
+		Sets this Lut with the maximum value to be represented.
 		</p>
 		</p>
+
+		<h3>[method:HTMLCanvasElement updateCanvas]( [param:HTMLCanvasElement canvas] )</h3>
 		<p>
 		<p>
-		Returns a [page:Color].
+		Updates the canvas with the [name]'s data.
 		</p>
 		</p>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

+ 9 - 4
docs/examples/ko/controls/OrbitControls.html

@@ -212,7 +212,7 @@ controls.mouseButtons = {
 
 
 		<h3>[property:Vector3 position0]</h3>
 		<h3>[property:Vector3 position0]</h3>
 		<p>
 		<p>
-			해당 프로퍼티는 [method:saveState] 및 [method:reset] 메서드에서 내부적으로 사용합니다.
+			해당 프로퍼티는 [page:.saveState] 및 [page:.reset] 메서드에서 내부적으로 사용합니다.
 		</p>
 		</p>
 
 
 		<h3>[property:Float rotateSpeed]</h3>
 		<h3>[property:Float rotateSpeed]</h3>
@@ -229,7 +229,7 @@ controls.mouseButtons = {
 
 
 		<h3>[property:Vector3 target0]</h3>
 		<h3>[property:Vector3 target0]</h3>
 		<p>
 		<p>
-			[method:saveState] 및 [method:rest] 메서드에서 내부적으로 사용합니다.
+			[page:.saveState] 및 [method:rest] 메서드에서 내부적으로 사용합니다.
 		</p>
 		</p>
 
 
 		<h3>[property:Vector3 target]</h3>
 		<h3>[property:Vector3 target]</h3>
@@ -250,7 +250,7 @@ controls.touches = {
 
 
 		<h3>[property:Float zoom0]</h3>
 		<h3>[property:Float zoom0]</h3>
 		<p>
 		<p>
-			[method:saveState] 및 [method:reset] 메서드에서 내부적으로 사용합니다.
+			[page:.saveState] 및 [page:.reset] 메서드에서 내부적으로 사용합니다.
 		</p>
 		</p>
 
 
 		<h3>[property:Float zoomSpeed]</h3>
 		<h3>[property:Float zoomSpeed]</h3>
@@ -278,6 +278,11 @@ controls.touches = {
 			라디안 단위로 현재 수직 회전값을 가져옵니다.
 			라디안 단위로 현재 수직 회전값을 가져옵니다.
 		</p>
 		</p>
 
 
+		<h3>[method:Float getDistance] ()</h3>
+		<p>
+			Returns the distance from the camera to the target.
+		</p>
+
 		<h3>[method:void listenToKeyEvents] ( [param:HTMLDOMElement domElement] )</h3>
 		<h3>[method:void listenToKeyEvents] ( [param:HTMLDOMElement domElement] )</h3>
 		<p>
 		<p>
 			Adds key event listeners to the given DOM element. *window* is a recommended argument for using this method.
 			Adds key event listeners to the given DOM element. *window* is a recommended argument for using this method.
@@ -290,7 +295,7 @@ controls.touches = {
 
 
 		<h3>[method:null saveState] ()</h3>
 		<h3>[method:null saveState] ()</h3>
 		<p>
 		<p>
-			컨트롤의 현재 상태를 저장합니다. 나중에 [page:.rest]을 이용하여 현재 상태로 복구할 수 있습니다.
+			컨트롤의 현재 상태를 저장합니다. 나중에 [page:.reset]을 이용하여 현재 상태로 복구할 수 있습니다.
 		</p>
 		</p>
 
 
 		<h3>[method:Boolean update] ()</h3>
 		<h3>[method:Boolean update] ()</h3>

+ 7 - 0
docs/examples/ko/controls/TransformControls.html

@@ -159,6 +159,13 @@
 			컨트롤을 더이상 필요하지 않을 경우 호출해야 합니다.
 			컨트롤을 더이상 필요하지 않을 경우 호출해야 합니다.
 		</p>
 		</p>
 
 
+		<h3>[method:Raycaster getRaycaster] ()</h3>
+		<p>
+			사용자 상호 작용에 사용되는 [page:Raycaster] 객체를 반환합니다. 이 개체는의 모든 인스턴스간에 공유됩니다. TransformControls. [name] 의
+			[page:Object3D.layers .layers] 속성을 설정하면 [page:Raycaster] 의 [page:Raycaster.layers .layers] 속성을 일치하는
+			값으로 설정하거나 그렇지 않으면 [name] 예상대로 작동하지 않습니다.
+		</p>
+
 		<h3>[method:String getMode] ()</h3>
 		<h3>[method:String getMode] ()</h3>
 		<p>
 		<p>
 			변환 모드를 반환합니다.
 			변환 모드를 반환합니다.

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

@@ -214,7 +214,7 @@ controls.mouseButtons = {
 
 
 		<h3>[property:Vector3 position0]</h3>
 		<h3>[property:Vector3 position0]</h3>
 		<p>
 		<p>
-			由[method:saveState]和[method:reset]方法在内部使用。
+			由[page:.saveState]和[page:.reset]方法在内部使用。
 		</p>
 		</p>
 
 
 		<h3>[property:Float rotateSpeed]</h3>
 		<h3>[property:Float rotateSpeed]</h3>
@@ -231,7 +231,7 @@ controls.mouseButtons = {
 
 
 		<h3>[property:Vector3 target0]</h3>
 		<h3>[property:Vector3 target0]</h3>
 		<p>
 		<p>
-			由[method:saveState]和[method:reset]方法在内部使用。
+			由[page:.saveState]和[page:.reset]方法在内部使用。
 		</p>
 		</p>
 
 
 		<h3>[property:Vector3 target]</h3>
 		<h3>[property:Vector3 target]</h3>
@@ -253,7 +253,7 @@ controls.touches = {
 
 
 		<h3>[property:Float zoom0]</h3>
 		<h3>[property:Float zoom0]</h3>
 		<p>
 		<p>
-			由[method:saveState]和[method:reset]方法在内部使用。
+			由[page:.saveState]和[page:.reset]方法在内部使用。
 		</p>
 		</p>
 
 
 		<h3>[property:Float zoomSpeed]</h3>
 		<h3>[property:Float zoomSpeed]</h3>
@@ -280,6 +280,11 @@ controls.touches = {
 			获得当前的垂直旋转,单位为弧度。
 			获得当前的垂直旋转,单位为弧度。
 		</p>
 		</p>
 
 
+		<h3>[method:Float getDistance] ()</h3>
+		<p>
+			Returns the distance from the camera to the target.
+		</p>
+
 		<h3>[method:void listenToKeyEvents] ( [param:HTMLDOMElement domElement] )</h3>
 		<h3>[method:void listenToKeyEvents] ( [param:HTMLDOMElement domElement] )</h3>
 		<p>
 		<p>
 			为指定的DOM元素添加按键监听。推荐将window作为指定的DOM元素。
 			为指定的DOM元素添加按键监听。推荐将window作为指定的DOM元素。

+ 7 - 0
docs/examples/zh/controls/TransformControls.html

@@ -160,6 +160,13 @@
 			若不再需要该控制器,则应当调用此函数。
 			若不再需要该控制器,则应当调用此函数。
 		</p>
 		</p>
 
 
+		<h3>[method:Raycaster getRaycaster] ()</h3>
+		<p>
+			返回用于用户交互的 [page:Raycaster] 对象。 此对象在所有实例之间共享 变换控件。 如果您设置 [name] 的
+			[page:Object3D.layers .layers] 属性,您还需要 使用匹配值设置 [page:Raycaster] 上的
+			[page:Raycaster.layers .layers] 属性,否则设置 [name] 不会按预期工作。
+		</p>
+
 		<h3>[method:String getMode] ()</h3>
 		<h3>[method:String getMode] ()</h3>
 		<p>
 		<p>
 			返回变换模式。
 			返回变换模式。

+ 4 - 0
docs/examples/zh/loaders/GLTFLoader.html

@@ -28,8 +28,12 @@
 		<ul>
 		<ul>
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_materials_clearcoat</li>
 			<li>KHR_materials_clearcoat</li>
+			<li>KHR_materials_ior</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
+			<li>KHR_materials_specular</li>
+			<li>KHR_materials_transmission</li>
 			<li>KHR_materials_unlit</li>
 			<li>KHR_materials_unlit</li>
+			<li>KHR_materials_volume</li>
 			<li>KHR_mesh_quantization</li>
 			<li>KHR_mesh_quantization</li>
 			<li>KHR_lights_punctual<sup>1</sup></li>
 			<li>KHR_lights_punctual<sup>1</sup></li>
 			<li>KHR_texture_basisu</li>
 			<li>KHR_texture_basisu</li>

+ 40 - 57
docs/examples/zh/math/Lut.html

@@ -23,116 +23,99 @@
 		<h2>构造函数</h2>
 		<h2>构造函数</h2>
 
 
 
 
-		<h3>[name]( colormap, numberOfColors )</h3>
+		<h3>[name]( [param:String colormap], [param:Number count] )</h3>
 		<p>
 		<p>
-		colormap - (可选)从预定义的颜色表中设置一个颜色表。可选值有:"rainbow"、 "cooltowarm"、 "blackbody"。
-		numberOfColors - (可选)设置用于表示数据数组的颜色数量。
+		colormap - Sets a colormap from predefined colormaps. Available colormaps are : *rainbow*, *cooltowarm*, *blackbody*, *grayscale*. Default is *rainbow*.<br />
+		count - Sets the number of colors used to represent the data array. Default is *32*.
 		</p>
 		</p>
 
 
 		<h2>属性</h2>
 		<h2>属性</h2>
 
 
-		<h3>[property:Float minV]</h3>
+		<h3>[property:Array lut]</h3>
 		<p>
 		<p>
-		查找表所表示的最小值,默认为0。
+		The lookup table for the selected color map represented as an array of [page:Color]s.
 		</p>
 		</p>
 
 
-		<h3>[property:Float maxV]</h3>
+		<h3>[property:Array map]</h3>
 		<p>
 		<p>
-		查找表所表示的最小值,默认为1。
+		The currently selected color map. Default is the *rainbow* color map.
 		</p>
 		</p>
 
 
-		<h3>.[legend]</h3>
+		<h3>[property:Number minV]</h3>
 		<p>
 		<p>
-		查找表的图例。
+		The minimum value to be represented with the lookup table. Default is *0*.
 		</p>
 		</p>
 
 
-		<h2>方法</h2>
-
-		<h3>[method:null copy]( [param:Lut lut] ) [param:Lut this]</h3>
+		<h3>[property:Number maxV]</h3>
 		<p>
 		<p>
-		color — 要拷贝的 Lut。
-		</p>
-		<p>
-		拷贝给定的 Lut。
+		The maximum value to be represented with the lookup table. Default is *1*.
 		</p>
 		</p>
 
 
-		<h3>.setLegendOn [parameters]</h3>
-		<p>
-		parameters - { layout: value, position: { x: value, y: value, z: value }, dimensions: { width: value, height: value } }
-		layout — Horizontal or vertical layout. Default is vertical.<br />
-		position — The position x,y,z of the legend.<br />
-		dimensions — The dimensions (width and height) of the legend.<br />
-		</p>
+		<h3>[property:Number n]</h3>
 		<p>
 		<p>
-		Sets this Lut with the legend on.
+		The number of colors of the current selected color map. Default is *32*.
 		</p>
 		</p>
 
 
-		<h3>.setLegendOff</h3>
+		<h2>方法</h2>
+
+		<h3>[method:null copy]( [param:Lut lut] ) [param:Lut this]</h3>
 		<p>
 		<p>
+		color — Lut to copy.
 		</p>
 		</p>
 		<p>
 		<p>
-		Sets this Lut with the legend off.
+		Copies the given lut.
 		</p>
 		</p>
 
 
-    <h3>.setLegendLabels [parameters, callback]</h3>
+		<h3>[method:Lut addColorMap]( [param:String name], [param:Array arrayOfColors] )</h3>
 		<p>
 		<p>
-		parameters - { fontsize: value, fontface: value, title: value, um: value, ticks: value, decimal: value, notation: value }
-		fontsize — Font size to be used for labels.<br />
-		fontface — Font type to be used for labels.<br />
-		title — The title of the legend.<br />
-		um — The unit of measurements of the legend.<br />
-		ticks — The number of ticks to be displayed.<br />
-		decimal — The number of decimals to be used for legend values.<br />
-		notation — Legend notation: standard (default) or scientific.<br />
-		callback — An optional callback to be used to format the legend labels.<br />
+		name — The name of the color map.<br />
+		arrayOfColors — An array of color values. Each value is an array holding a threshold and the actual color value as a hexadecimal number.
 		</p>
 		</p>
 		<p>
 		<p>
-		Sets the labels of the legend of this Lut.
+		Adds a color map to this [name] instance.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut setMin]( [param:Float minV] )</h3>
+		<h3>[method:HTMLCanvasElement createCanvas]()</h3>
 		<p>
 		<p>
-		minV — 查找表所表示的最小值。<br />
-		</p>
-		<p>
-		将查找表要表示的最小值设为该值。
+		Creates a canvas in order to visualize the lookup table as a texture.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut setMax]( [param:Float maxV] )</h3>
+		<h3>[method:Color getColor]( [param:Number alpha] )</h3>
 		<p>
 		<p>
-		maxV — 查找表所表示的最小值。<br />
+		value -- the data value to be displayed as a color.
 		</p>
 		</p>
 		<p>
 		<p>
-		将查找表要表示的最大值设为该值。
+		Returns an instance of [page:Color] for the given data value.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut changeNumberOfColors]( [param:Float numberOfColors] )</h3>
+		<h3>[method:Lut setColorMap]( [param:String colormap], [param:Number count] )</h3>
 		<p>
 		<p>
-		numberOfColors — 用于表示数据数组的颜色数量。<br />
+		colormap — The name of the color map.<br />
+		count — The number of colors. Default is *32*.
 		</p>
 		</p>
 		<p>
 		<p>
-		设置查找表中要使用的颜色的数量。
+		Configure the lookup table for the given color map and number of colors.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut changeColorMap]( [param:Float colorMap] )</h3>
+		<h3>[method:Lut setMin]( [param:Number minV] )</h3>
 		<p>
 		<p>
-		colorMap — 用于表示数据数组的颜色表名称。<br />
+		minV — The minimum value to be represented with the lookup table
 		</p>
 		</p>
 		<p>
 		<p>
-		设置查找表的颜色表为传入的颜色表。
+		Sets this Lut with the minimum value to be represented.
 		</p>
 		</p>
 
 
-		<h3>[method:Lut addColorMap]( colorMapName, arrayOfColors )</h3>
+		<h3>[method:Lut setMax]( [param:Number maxV] )</h3>
 		<p>
 		<p>
-		插入一个新的颜色表到可用颜色表中。
+		maxV — The maximum value to be represented with the lookup table.
 		</p>
 		</p>
-
-		<h3>[method:Lut getColor]( value ) [param:Lut this]</h3>
 		<p>
 		<p>
-		value -- 作为颜色展示的数据值。
+		Sets this Lut with the maximum value to be represented.
 		</p>
 		</p>
+
+		<h3>[method:HTMLCanvasElement updateCanvas]( [param:HTMLCanvasElement canvas] )</h3>
 		<p>
 		<p>
-		返回一个[page:Color]。
+		Updates the canvas with the [name]'s data.
 		</p>
 		</p>
 
 
 		<h2>源码</h2>
 		<h2>源码</h2>

+ 1 - 5
docs/list.json

@@ -7,7 +7,6 @@
 			"Getting Started": {
 			"Getting Started": {
 				"Creating a scene": "manual/en/introduction/Creating-a-scene",
 				"Creating a scene": "manual/en/introduction/Creating-a-scene",
 				"Installation": "manual/en/introduction/Installation",
 				"Installation": "manual/en/introduction/Installation",
-				"Browser support": "manual/en/introduction/Browser-support",
 				"WebGL compatibility check": "manual/en/introduction/WebGL-compatibility-check",
 				"WebGL compatibility check": "manual/en/introduction/WebGL-compatibility-check",
 				"How to run things locally": "manual/en/introduction/How-to-run-things-locally",
 				"How to run things locally": "manual/en/introduction/How-to-run-things-locally",
 				"Drawing lines": "manual/en/introduction/Drawing-lines",
 				"Drawing lines": "manual/en/introduction/Drawing-lines",
@@ -76,6 +75,7 @@
 				"Animation": "api/en/constants/Animation",
 				"Animation": "api/en/constants/Animation",
 				"Core": "api/en/constants/Core",
 				"Core": "api/en/constants/Core",
 				"CustomBlendingEquation": "api/en/constants/CustomBlendingEquations",
 				"CustomBlendingEquation": "api/en/constants/CustomBlendingEquations",
+				"BufferAttributeUsage": "api/en/constants/BufferAttributeUsage",
 				"Materials": "api/en/constants/Materials",
 				"Materials": "api/en/constants/Materials",
 				"Renderer": "api/en/constants/Renderer",
 				"Renderer": "api/en/constants/Renderer",
 				"Textures": "api/en/constants/Textures"
 				"Textures": "api/en/constants/Textures"
@@ -448,7 +448,6 @@
 			"البدء": {
 			"البدء": {
 				"إنشاء مشهد": "manual/ar/introduction/Creating-a-scene",
 				"إنشاء مشهد": "manual/ar/introduction/Creating-a-scene",
 				"التثبيت": "manual/ar/introduction/Installation",
 				"التثبيت": "manual/ar/introduction/Installation",
-				"دعم المتصفح": "manual/ar/introduction/Browser-support",
 				"فحص توافق WebGL": "manual/ar/introduction/WebGL-compatibility-check",
 				"فحص توافق WebGL": "manual/ar/introduction/WebGL-compatibility-check",
 				"كيف تدير الأشياء محليًا": "manual/ar/introduction/How-to-run-things-locally",
 				"كيف تدير الأشياء محليًا": "manual/ar/introduction/How-to-run-things-locally",
 				"رسم خطوط": "manual/ar/introduction/Drawing-lines",
 				"رسم خطوط": "manual/ar/introduction/Drawing-lines",
@@ -520,7 +519,6 @@
 			"起步": {
 			"起步": {
 				"创建一个场景": "manual/zh/introduction/Creating-a-scene",
 				"创建一个场景": "manual/zh/introduction/Creating-a-scene",
 				"安装": "manual/zh/introduction/Installation",
 				"安装": "manual/zh/introduction/Installation",
-				"浏览器支持": "manual/zh/introduction/Browser-support",
 				"WebGL兼容性检查": "manual/zh/introduction/WebGL-compatibility-check",
 				"WebGL兼容性检查": "manual/zh/introduction/WebGL-compatibility-check",
 				"如何在本地运行Three.js": "manual/zh/introduction/How-to-run-things-locally",
 				"如何在本地运行Three.js": "manual/zh/introduction/How-to-run-things-locally",
 				"画线": "manual/zh/introduction/Drawing-lines",
 				"画线": "manual/zh/introduction/Drawing-lines",
@@ -955,7 +953,6 @@
 			"시작하기": {
 			"시작하기": {
 				"장면 만들기": "manual/ko/introduction/Creating-a-scene",
 				"장면 만들기": "manual/ko/introduction/Creating-a-scene",
 				"설치": "manual/ko/introduction/Installation",
 				"설치": "manual/ko/introduction/Installation",
-				"브라우저 지원": "manual/ko/introduction/Browser-support",
 				"WebGL 호환성 검사": "manual/ko/introduction/WebGL-compatibility-check",
 				"WebGL 호환성 검사": "manual/ko/introduction/WebGL-compatibility-check",
 				"로컬 환경에서 구동 방법": "manual/ko/introduction/How-to-run-things-locally",
 				"로컬 환경에서 구동 방법": "manual/ko/introduction/How-to-run-things-locally",
 				"선 그리기": "manual/ko/introduction/Drawing-lines",
 				"선 그리기": "manual/ko/introduction/Drawing-lines",
@@ -1053,7 +1050,6 @@
             "はじめてみましょう": {
             "はじめてみましょう": {
                 "シーンの作成": "manual/ja/introduction/Creating-a-scene",
                 "シーンの作成": "manual/ja/introduction/Creating-a-scene",
                 "インストールの方法": "manual/ja/introduction/Installation",
                 "インストールの方法": "manual/ja/introduction/Installation",
-                "サポートしているブラウザ": "manual/ja/introduction/Browser-support",
                 "WebGLの互換性の確認": "manual/ja/introduction/WebGL-compatibility-check",
                 "WebGLの互換性の確認": "manual/ja/introduction/WebGL-compatibility-check",
                 "localで実行する方法": "manual/ja/introduction/How-to-run-things-locally",
                 "localで実行する方法": "manual/ja/introduction/How-to-run-things-locally",
                 "線を引く": "manual/ja/introduction/Drawing-lines",
                 "線を引く": "manual/ja/introduction/Drawing-lines",

+ 0 - 123
docs/manual/ar/introduction/Browser-support.html

@@ -1,123 +0,0 @@
-<!DOCTYPE html>
-<html lang="ar">
-	<head>
-		<meta charset="utf-8">
-		<base href="../../../" />
-		<script src="page.js"></script>
-		<link type="text/css" rel="stylesheet" href="page.css" />
-	</head>
-	<body class="rtl">
-		<h1>([name]) دعم المتصفح</h1>
-
-		<h2>نظرة عامة</h2>
-		<div>
-			<p>
-				يمكن لـ Three.js استخدام WebGL لعرض المشاهد الخاصة بك على جميع المتصفحات الحديثة. بالنسبة إلى المتصفحات الأقدم ، وخاصة Internet Explorer 10 والإصدارات الأقدم ، قد تضطر إلى الرجوع إلى أحد المستعرضات الأخرى [link:https://github.com/mrdoob/three.js/tree/master/examples/jsm/renderers renderers] (CSS2DRenderer و CSS3DRenderer و SVGRenderer). بالإضافة إلى ذلك ، قد تضطر إلى تضمين بعض polyfills ، بالأخص إذا كنت تستخدم ملفات من المجلد [link:https://github.com/mrdoob/three.js/tree/master/examples /examples].
-			</p>
-			<p>
-				ملاحظة: إذا لم تكن بحاجة إلى دعم هذه المتصفحات القديمة ، فلا يوصى باستخدام برامج العارض الأخرى لأنها أبطأ وتدعم ميزات أقل من WebGLRenderer.
-			</p>
-		</div>
-
-		<h2>المتصفحات التي تدعم WebGL</h2>
-		<div>
-			<p>
-				Google Chrome 9+, Firefox 4+, Opera 15+, Safari 5.1+, Internet Explorer 11 و Microsoft Edge.<br/>
-				يمكنك العثور على المتصفحات التي تدعم WebGL في [link:https://caniuse.com/#feat=webgl Can I use WebGL].
-			</p>
-		</div>
-
-		<h2>ميزات لغة JavaScript أو واجهات الويب البرمجية المستخدمة في three.js</h2>
-		<div>
-			<p>
-				فيما يلي بعض الميزات المستخدمة في three.js. قد يتطلب بعض منهم polyfills إضافية.
-			</p>
-			<table>
-				<thead>
-					<tr>
-						<th>الخاصية</th>
-						<th>نطاق الاستخدم</th>
-						<th>الوحدات</th>
-					</tr>
-				</thead>
-				<tbody>
-					<tr>
-						<td>Typed Arrays</td>
-						<td>Source</td>
-						<td>BufferAttribute, BufferGeometry, etc.</td>
-					</tr>
-					<tr>
-						<td>Web Audio API</td>
-						<td>Source</td>
-						<td>Audio, AudioContext, AudioListener, etc.</td>
-					</tr>
-					<tr>
-						<td>WebXR Device API</td>
-						<td>Source</td>
-						<td>WebXRManager</td>
-					</tr>
-					<tr>
-						<td>Blob</td>
-						<td>Source</td>
-						<td>FileLoader, etc.</td>
-					</tr>
-					<tr>
-						<td>Promise</td>
-						<td>Examples</td>
-						<td>GLTFLoader, DRACOLoader, BasisTextureLoader, GLTFExporter, VRButton, ARButton, etc.</td>
-					</tr>
-					<tr>
-						<td>Fetch</td>
-						<td>Examples</td>
-						<td>ImageBitmapLoader, etc.</td>
-					</tr>
-					<tr>
-						<td>File API</td>
-						<td>Examples</td>
-						<td>GLTFExporter, etc.</td>
-					</tr>
-					<tr>
-						<td>URL API</td>
-						<td>Examples</td>
-						<td>GLTFLoader, etc.</td>
-					</tr>
-					<tr>
-						<td>Pointer Lock API</td>
-						<td>Examples</td>
-						<td>PointerLockControls</td>
-					</tr>
-				</tbody>
-			</table>
-		</div>
-
-		<h2>Polyfills</h2>
-		<div>
-			<p>فقط قم باستيراد polyfills بناءً على متطلباتك. إذا أخذنا IE9 كمثال ، فأنت بحاجة إلى ملء هذه الميزات على الأقل:</p>
-			<ul>
-				<li>Typed Arrays</li>
-				<li>Blob</li>
-			</ul>
-		</div>
-
-		<h3>مقترح polyfills</h3>
-		<div>
-			<ul>
-				<li>
-					[link:https://github.com/zloirock/core-js core-js]
-				</li>
-				<li>
-					[link:https://github.com/inexorabletash/polyfill/blob/master/typedarray.js typedarray.js]
-				</li>
-				<li>
-					[link:https://github.com/stefanpenner/es6-promise/ ES6-Promise]
-				</li>
-				<li>
-					[link:https://github.com/eligrey/Blob.js Blob.js]
-				</li>
-				<li>
-					[link:https://github.com/github/fetch fetch]
-				</li>
-			</ul>
-		</div>
-	</body>
-</html>

+ 0 - 122
docs/manual/en/introduction/Browser-support.html

@@ -1,122 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-	<meta charset="utf-8">
-	<base href="../../../" />
-	<script src="page.js"></script>
-	<link type="text/css" rel="stylesheet" href="page.css" />
-</head>
-<body>
-	<h1>[name]</h1>
-
-	<h2>Overview</h2>
-	<div>
-		<p>
-			Three.js can use WebGL to render your scenes on all modern browsers. For older browsers, especially Internet Explorer 10 and below, you may have to fallback to one of the other [link:https://github.com/mrdoob/three.js/tree/master/examples/jsm/renderers renderers] (CSS2DRenderer, CSS3DRenderer, SVGRenderer). Additionally, you may have to include some polyfills, especially if you are using files from the [link:https://github.com/mrdoob/three.js/tree/master/examples /examples] folder.
-		</p>
-		<p>
-			Note: if you don't need to support these old browsers, then it is not recommended to use the other renderers as they are slower and support less features than the WebGLRenderer.
-		</p>
-	</div>
-
-	<h2>Browsers that support WebGL</h2>
-	<div>
-		<p>
-			Google Chrome 9+, Firefox 4+, Opera 15+, Safari 5.1+, Internet Explorer 11 and Microsoft Edge. You can find which browsers support WebGL at [link:https://caniuse.com/#feat=webgl Can I use WebGL].
-		</p>
-	</div>
-
-	<h2>JavaScript Language Features or Web APIs Used in three.js</h2>
-	<div>
-		<p>
-			Here are some features used in three.js. Some of them may require additional polyfills.
-		</p>
-		<table>
-			<thead>
-				<tr>
-					<th>Feature</th>
-					<th>Use Scope</th>
-					<th>Modules</th>
-				</tr>
-			</thead>
-			<tbody>
-				<tr>
-					<td>Typed Arrays</td>
-					<td>Source</td>
-					<td>BufferAttribute, BufferGeometry, etc.</td>
-				</tr>
-				<tr>
-					<td>Web Audio API</td>
-					<td>Source</td>
-					<td>Audio, AudioContext, AudioListener, etc.</td>
-				</tr>
-				<tr>
-					<td>WebXR Device API</td>
-					<td>Source</td>
-					<td>WebXRManager</td>
-				</tr>
-				<tr>
-					<td>Blob</td>
-					<td>Source</td>
-					<td>FileLoader, etc.</td>
-				</tr>
-				<tr>
-					<td>Promise</td>
-					<td>Examples</td>
-					<td>GLTFLoader, DRACOLoader, BasisTextureLoader, GLTFExporter, VRButton, ARButton, etc.</td>
-				</tr>
-				<tr>
-					<td>Fetch</td>
-					<td>Examples</td>
-					<td>ImageBitmapLoader, etc.</td>
-				</tr>
-				<tr>
-					<td>File API</td>
-					<td>Examples</td>
-					<td>GLTFExporter, etc.</td>
-				</tr>
-				<tr>
-					<td>URL API</td>
-					<td>Examples</td>
-					<td>GLTFLoader, etc.</td>
-				</tr>
-				<tr>
-					<td>Pointer Lock API</td>
-					<td>Examples</td>
-					<td>PointerLockControls</td>
-				</tr>
-			</tbody>
-		</table>
-	</div>
-
-	<h2>Polyfills</h2>
-	<div>
-		<p>Just import polyfills based on your requirements. Taking IE9 as an example, you need to polyfill at least these features:</p>
-		<ul>
-			<li>Typed Arrays</li>
-			<li>Blob</li>
-		</ul>
-	</div>
-
-	<h3>Suggested polyfills</h3>
-	<div>
-		<ul>
-			<li>
-				[link:https://github.com/zloirock/core-js core-js]
-			</li>
-			<li>
-				[link:https://github.com/inexorabletash/polyfill/blob/master/typedarray.js typedarray.js]
-			</li>
-			<li>
-				[link:https://github.com/stefanpenner/es6-promise/ ES6-Promise]
-			</li>
-			<li>
-				[link:https://github.com/eligrey/Blob.js Blob.js]
-			</li>
-			<li>
-				[link:https://github.com/github/fetch fetch]
-			</li>
-		</ul>
-	</div>
-</body>
-</html>

+ 8 - 3
docs/manual/en/introduction/Libraries-and-Plugins.html

@@ -35,7 +35,7 @@
 			<li>[link:https://github.com/vanruesc/postprocessing postprocessing]</li>
 			<li>[link:https://github.com/vanruesc/postprocessing postprocessing]</li>
 		</ul>
 		</ul>
 
 
-		<h3>Intersection and Raycasting Performance</h3>
+		<h3>Intersection and Raycast Performance</h3>
 		
 		
 		<ul>
 		<ul>
 			<li>[link:https://github.com/gkjohnson/three-mesh-bvh three-mesh-bvh]</li>
 			<li>[link:https://github.com/gkjohnson/three-mesh-bvh three-mesh-bvh]</li>
@@ -52,7 +52,13 @@
 			<li>[link:https://github.com/gkjohnson/urdf-loaders/tree/master/javascript urdf-loader]</li>
 			<li>[link:https://github.com/gkjohnson/urdf-loaders/tree/master/javascript urdf-loader]</li>
 			<li>[link:https://github.com/NASA-AMMOS/3DTilesRendererJS 3d-tiles-renderer-js]</li>
 			<li>[link:https://github.com/NASA-AMMOS/3DTilesRendererJS 3d-tiles-renderer-js]</li>
 			<li>[link:https://github.com/kaisalmen/WWOBJLoader WebWorker OBJLoader]</li>
 			<li>[link:https://github.com/kaisalmen/WWOBJLoader WebWorker OBJLoader]</li>
-			<li>[link:https://github.com/agviegas/IFC.js IFC.js]</li>
+			<li>[link:https://github.com/IFCjs/web-ifc-three IFC.js]</li>
+		</ul>
+
+		<h3>Geometry</h3>
+
+		<ul>
+			<li>[link:https://github.com/spite/THREE.MeshLine THREE.MeshLine]</li>
 		</ul>
 		</ul>
 
 
 		<h3>3D Text and Layout</h3>
 		<h3>3D Text and Layout</h3>
@@ -68,7 +74,6 @@
 			<li>[link:https://github.com/creativelifeform/three-nebula three-nebula]</li>
 			<li>[link:https://github.com/creativelifeform/three-nebula three-nebula]</li>
 		</ul>
 		</ul>
 		
 		
-		
 		<h3>Inverse Kinematics</h3>
 		<h3>Inverse Kinematics</h3>
 
 
 		<ul>
 		<ul>

+ 2 - 2
docs/manual/ja/introduction/Animation-system.html

@@ -13,7 +13,7 @@
 
 
 		<p class="desc">
 		<p class="desc">
 			three.jsのアニメーションシステムの中では、モデルの様々なプロパティをアニメーション化できます。
 			three.jsのアニメーションシステムの中では、モデルの様々なプロパティをアニメーション化できます。
-			例えば、装飾を行なったモデル([page:SkinnedMesh skinned and rigged model])の骨格や、[page:Geometry.morphTargets morphTargets]、異なるマテリアルの要素(色、不透明度、有無)、可視性、変形などを操作できます。
+			例えば、装飾を行なったモデル([page:SkinnedMesh skinned and rigged model])の骨格や、morphTargets、異なるマテリアルの要素(色、不透明度、有無)、可視性、変形などを操作できます。
 			アニメーションの要素は、フェードインやフェードアウト、クロスフェード、重ね合わせが可能です。
 			アニメーションの要素は、フェードインやフェードアウト、クロスフェード、重ね合わせが可能です。
 			同一のオブジェクトであっても異なるものであっても、異なるアニメーションの比重やタイムスケールは独立して変更出来ます。また、同じオブジェクトでも、異なるオブジェクトでもアニメーションは同期出来ます。<br /><br />
 			同一のオブジェクトであっても異なるものであっても、異なるアニメーションの比重やタイムスケールは独立して変更出来ます。また、同じオブジェクトでも、異なるオブジェクトでもアニメーションは同期出来ます。<br /><br />
 
 
@@ -39,7 +39,7 @@
 
 
 			こういった*AnimationClip*の中では、アニメーションの要素のデータは別の[page:KeyframeTrack]に保存されています。キャラクターオブジェクトが骨格を持っていると仮定すると、あるキートラックフレームは腕の下の方の骨の、位置の時間変化のデータを保存し、別のキートラックは同じ骨の回転成分の動きのデータを保存し、また別のキートラックは他の骨の位置や回転、スケールの変化といったデータを保存します。AnimationClipは、このようなたくさんのトラックで構成できることがわかります。
 			こういった*AnimationClip*の中では、アニメーションの要素のデータは別の[page:KeyframeTrack]に保存されています。キャラクターオブジェクトが骨格を持っていると仮定すると、あるキートラックフレームは腕の下の方の骨の、位置の時間変化のデータを保存し、別のキートラックは同じ骨の回転成分の動きのデータを保存し、また別のキートラックは他の骨の位置や回転、スケールの変化といったデータを保存します。AnimationClipは、このようなたくさんのトラックで構成できることがわかります。
 
 
-			モデルが[page:Geometry.morphTargets morph targets]を持っていると仮定すると(例えば、友好的な顔から怒った顔にモーフィングするような場合)、それぞれのトラックは特定のモーフィングターゲットの[page:Mesh.morphTargetInfluences influence]がclipのパフォーマンス中にどうやって変化するかについての情報を持っています。
+			モデルがmorph targetsを持っていると仮定すると(例えば、友好的な顔から怒った顔にモーフィングするような場合)、それぞれのトラックは特定のモーフィングターゲットの[page:Mesh.morphTargetInfluences influence]がclipのパフォーマンス中にどうやって変化するかについての情報を持っています。
 
 
 		</p>
 		</p>
 
 

+ 0 - 125
docs/manual/ja/introduction/Browser-support.html

@@ -1,125 +0,0 @@
-<!DOCTYPE html>
-<html lang="ja">
-<head>
-	<meta charset="utf-8">
-	<base href="../../../" />
-	<script src="page.js"></script>
-	<link type="text/css" rel="stylesheet" href="page.css" />
-</head>
-<body>
-	<h1>[name]</h1>
-
-	<h2>概要</h2>
-	<div>
-		<p>
-			モダンなブラウザ上であれば、Three.jsはWebGLを使ってsceneを描画出来ます。古いブラウザ(特にInternet Explore 10以下)では、他の[link:https://github.com/mrdoob/three.js/tree/master/examples/jsm/renderers renderers] (CSS2DRenderer, CSS3DRenderer, SVGRenderer)に後方互換する必要があるでしょう。さらに、特に [link:https://github.com/mrdoob/three.js/tree/master/examples /examples] フォルダのファイルを使用している場合は、いくつかのpolyfillを含める必要がある可能性があります。
-		</p>
-		<p>
-			注意事項: もし古いブラウザをサポートする必要がないなら、WebGLRenderer以外を使うことはおすすめしません。というのも、他のrendererは遅い上に、サポートしている機能が少ないからです。
-		</p>
-	</div>
-
-	<h2>WebGLをサポートしているブラウザ</h2>
-	<div>
-		<p>
-			Google Chrome 9以上、Firefox 4以上、Opera 15以上、Safari 5.1以上、Internet Explore 11以上、もしくはMicrosoft Edge。
-			どのブラウザがWebGLをサポートしているのかは[link:https://caniuse.com/#feat=webgl Can I use WebGL]を確認してください。
-		</p>
-	</div>
-
-	<h2>three.jsで使用されるJavaScriptの機能とWeb APIs</h2>
-	<div>
-		<p>
-			three.jsで使われる機能の中には追加のpolyfillsが必要になるものがあります。
-		</p>
-		<table>
-			<thead>
-				<tr>
-					<th>機能</th>
-					<th>スコープ</th>
-					<th>モジュール</th>
-				</tr>
-			</thead>
-			<tbody>
-				<tr>
-					<td>Typed Arrays</td>
-					<td>Source</td>
-					<td>BufferAttribute, BufferGeometry, etc.</td>
-				</tr>
-				<tr>
-					<td>Web Audio API</td>
-					<td>Source</td>
-					<td>Audio, AudioContext, AudioListener, etc.</td>
-				</tr>
-				<tr>
-					<td>WebXR Device API</td>
-					<td>Source</td>
-					<td>WebXRManager</td>
-				</tr>
-				<tr>
-					<td>Blob</td>
-					<td>Source</td>
-					<td>FileLoader, etc.</td>
-				</tr>
-				<tr>
-					<td>Promise</td>
-					<td>Examples</td>
-					<td>GLTFLoader, DRACOLoader, BasisTextureLoader, GLTFExporter, VRButton, ARButton, etc.</td>
-				</tr>
-				<tr>
-					<td>Fetch</td>
-					<td>Examples</td>
-					<td>ImageBitmapLoader, etc.</td>
-				</tr>
-				<tr>
-					<td>File API</td>
-					<td>Examples</td>
-					<td>GLTFExporter, etc.</td>
-				</tr>
-				<tr>
-					<td>URL API</td>
-					<td>Examples</td>
-					<td>GLTFLoader, etc.</td>
-				</tr>
-				<tr>
-					<td>Pointer Lock API</td>
-					<td>Examples</td>
-					<td>PointerLockControls</td>
-				</tr>
-			</tbody>
-		</table>
-	</div>
-
-	<h2>Polyfills</h2>
-	<div>
-		<p>
-			要件に応じてポリフィルをインポートするだけです。例えば、IE9の場合は少なくとも以下の機能を追加する必要があります。
-		</p>
-		<ul>
-			<li>Typed Arrays</li>
-			<li>Blob</li>
-		</ul>
-	</div>
-
-	<h3>おすすめのpolyfills</h3>
-	<div>
-		<ul>
-			<li>
-				[link:https://github.com/zloirock/core-js core-js]
-			</li>
-			<li>
-				[link:https://github.com/inexorabletash/polyfill/blob/master/typedarray.js typedarray.js]
-			</li>
-			<li>
-				[link:https://github.com/stefanpenner/es6-promise/ ES6-Promise]
-			</li>
-			<li>
-				[link:https://github.com/eligrey/Blob.js Blob.js]
-			</li>
-			<li>
-				[link:https://github.com/github/fetch fetch]
-			</li>
-		</ul>
-	</div>
-</body>
-</html>

+ 0 - 27
docs/manual/ja/introduction/How-to-update-things.html

@@ -126,33 +126,6 @@ line.geometry.computeBoundingSphere();
 
 
     </div>
     </div>
 
 
-    <h2>Geometry</h2>
-    <div>
-        <p>
-            下記に示してあるフラグはさまざまなジオメトリの要素の更新をコントロールします。 更新にはコストがかかるので、更新が必要な要素のみを、更新するように設定してください。 バッファが変化すると、自動的にこれらのフラグはflaseにリセットされます。 バッファを更新し続けたいのであれば、このフラグをtrueに設定し続ける必要があります。 これは[page:Geometry]にのみ適用されて、[page:BufferGeometry]には適用されないことに注意してください。
-        </p>
-        <code>
-const geometry = new THREE.Geometry();
-geometry.verticesNeedUpdate = true;
-geometry.elementsNeedUpdate = true;
-geometry.morphTargetsNeedUpdate = true;
-geometry.uvsNeedUpdate = true;
-geometry.normalsNeedUpdate = true;
-geometry.colorsNeedUpdate = true;
-geometry.tangentsNeedUpdate = true;
-			</code>
-
-        <p>
-            [link:https://github.com/mrdoob/three.js/releases/tag/r66 r66]以前のバージョンでは、メッシュは<em>dynamic</em>フラグを有効にする必要があります。これは内部で型付き配列を保持するために必要になります。
-        </p>
-
-        <code>
-// removed after r66
-geometry.dynamic = true;
-			</code>
-
-    </div>
-
     <h2>Materials</h2>
     <h2>Materials</h2>
     <div>
     <div>
         <p>
         <p>

+ 9 - 4
docs/manual/ja/introduction/Libraries-and-Plugins.html

@@ -36,7 +36,7 @@
         <li>[link:https://github.com/vanruesc/postprocessing postprocessing]</li>
         <li>[link:https://github.com/vanruesc/postprocessing postprocessing]</li>
     </ul>
     </ul>
 
 
-    <h3>Intersection and Raycasting Performance</h3>
+    <h3>Intersection and Raycast Performance</h3>
 
 
     <ul>
     <ul>
         <li>[link:https://github.com/gkjohnson/three-mesh-bvh three-mesh-bvh]</li>
         <li>[link:https://github.com/gkjohnson/three-mesh-bvh three-mesh-bvh]</li>
@@ -52,7 +52,13 @@
         <li>[link:https://github.com/gkjohnson/urdf-loaders/tree/master/javascript urdf-loader]</li>
         <li>[link:https://github.com/gkjohnson/urdf-loaders/tree/master/javascript urdf-loader]</li>
         <li>[link:https://github.com/NASA-AMMOS/3DTilesRendererJS 3d-tiles-renderer-js]</li>
         <li>[link:https://github.com/NASA-AMMOS/3DTilesRendererJS 3d-tiles-renderer-js]</li>
         <li>[link:https://github.com/kaisalmen/WWOBJLoader WebWorker OBJLoader]</li>
         <li>[link:https://github.com/kaisalmen/WWOBJLoader WebWorker OBJLoader]</li>
-        <li>[link:https://github.com/agviegas/IFC.js IFC.js]</li>
+        <li>[link:https://github.com/IFCjs/web-ifc-three IFC.js]</li>
+    </ul>
+
+    <h3>Geometry</h3>
+
+    <ul>
+        <li>[link:https://github.com/spite/THREE.MeshLine THREE.MeshLine]</li>
     </ul>
     </ul>
 
 
     <h3>3D Text and Layout</h3>
     <h3>3D Text and Layout</h3>
@@ -68,7 +74,6 @@
         <li>[link:https://github.com/creativelifeform/three-nebula three-nebula]</li>
         <li>[link:https://github.com/creativelifeform/three-nebula three-nebula]</li>
     </ul>
     </ul>
 
 
-
     <h3>Inverse Kinematics</h3>
     <h3>Inverse Kinematics</h3>
 
 
     <ul>
     <ul>
@@ -93,4 +98,4 @@
 
 
 </body>
 </body>
 
 
-</html>
+</html>

+ 0 - 130
docs/manual/ko/introduction/Browser-support.html

@@ -1,130 +0,0 @@
-<!DOCTYPE html>
-<html lang="ko">
-
-<head>
-    <meta charset="utf-8">
-    <base href="../../../" />
-    <script src="page.js"></script>
-    <link type="text/css" rel="stylesheet" href="page.css" />
-</head>
-
-<body>
-    <h1>브라우저 지원([name])</h1>
-
-    <h2>개요</h2>
-    <div>
-        <p>
-            Three.js 는 WebGL을 통해 대부분의 현대 브라우저에서 scene을 렌더링할 수 있습니다. 오래된 브라우저, 특히 Internet Explorer 10 이하 버전에서는 다른
-            [link:https://github.com/mrdoob/three.js/tree/master/examples/jsm/renderers 렌더러] (CSS2DRenderer,
-            CSS3DRenderer, SVGRenderer)를 사용해야 합니다. 또한,
-            polyfills를 몇가지 포함해야 할 수도 있는데 [link:https://github.com/mrdoob/three.js/tree/master/examples /examples] 폴더의
-            파일을 불러올때에는 필수입니다.
-        </p>
-        <p>
-            오래된 브라우저를 지원할 필요가 없다면, 다른 렌더러를 사용하는 것은 추천하지 않습니다. WebGLRenderer보다 느릴뿐더러 더 적은 기능을 지원하기 때문입니다.
-        </p>
-    </div>
-
-    <h2>WebGL지원 웹 브라우저</h2>
-    <div>
-        <p>
-            Google Chrome 9+, Firefox 4+, Opera 15+, Safari 5.1+, Internet Explorer 11 및 Microsoft Edge. [link:https://caniuse.com/#feat=webgl Can I use WebGL]에서 어떤 브라우저들이 지원하는지 확인해볼 수 있습니다.
-        </p>
-    </div>
-
-    <h2>JavaScript 언어 특성 및 three.js에서 사용된 Web API</h2>
-    <div>
-        <p>
-            three.js에서 사용된 특성들은 다음과 같습니다. 이 중 몇개는 추가로 polyfills가 필요합니다.
-        </p>
-        <table>
-            <thead>
-                <tr>
-                    <th>특성</th>
-                    <th>사용 범위</th>
-                    <th>모듈</th>
-                </tr>
-            </thead>
-            <tbody>
-                <tr>
-                    <td>Typed Arrays</td>
-                    <td>Source</td>
-                    <td>BufferAttribute, BufferGeometry, etc.</td>
-                </tr>
-                <tr>
-                    <td>Web Audio API</td>
-                    <td>Source</td>
-                    <td>Audio, AudioContext, AudioListener, etc.</td>
-                </tr>
-                <tr>
-                    <td>WebXR Device API</td>
-                    <td>Source</td>
-                    <td>WebXRManager</td>
-                </tr>
-                <tr>
-                    <td>Blob</td>
-                    <td>Source</td>
-                    <td>FileLoader, etc.</td>
-                </tr>
-                <tr>
-                    <td>Promise</td>
-                    <td>Examples</td>
-                    <td>GLTFLoader, DRACOLoader, BasisTextureLoader, GLTFExporter, VRButton, ARButton, etc.</td>
-                </tr>
-                <tr>
-                    <td>Fetch</td>
-                    <td>Examples</td>
-                    <td>ImageBitmapLoader, etc.</td>
-                </tr>
-                <tr>
-                    <td>File API</td>
-                    <td>Examples</td>
-                    <td>GLTFExporter, etc.</td>
-                </tr>
-                <tr>
-                    <td>URL API</td>
-                    <td>Examples</td>
-                    <td>GLTFLoader, etc.</td>
-                </tr>
-                <tr>
-                    <td>Pointer Lock API</td>
-                    <td>Examples</td>
-                    <td>PointerLockControls</td>
-                </tr>
-            </tbody>
-        </table>
-    </div>
-
-    <h2>Polyfills</h2>
-    <div>
-        <p>필요에 따라 polyfills을 import 하세요. IE9를 예로들면 적어도 다음과 같은 polyfills가 필요할 것입니다.
-            these features:</p>
-        <ul>
-            <li>Typed Arrays</li>
-            <li>Blob</li>
-        </ul>
-    </div>
-
-    <h3>추천 polyfills</h3>
-    <div>
-        <ul>
-            <li>
-                [link:https://github.com/zloirock/core-js core-js]
-            </li>
-            <li>
-                [link:https://github.com/inexorabletash/polyfill/blob/master/typedarray.js typedarray.js]
-            </li>
-            <li>
-                [link:https://github.com/stefanpenner/es6-promise/ ES6-Promise]
-            </li>
-            <li>
-                [link:https://github.com/eligrey/Blob.js Blob.js]
-            </li>
-            <li>
-                [link:https://github.com/github/fetch fetch]
-            </li>
-        </ul>
-    </div>
-</body>
-
-</html>

+ 0 - 124
docs/manual/zh/introduction/Browser-support.html

@@ -1,124 +0,0 @@
-<!DOCTYPE html>
-<html lang="zh">
-<head>
-	<meta charset="utf-8">
-	<base href="../../../" />
-	<script src="page.js"></script>
-	<link type="text/css" rel="stylesheet" href="page.css" />
-</head>
-<body>
-	<h1>浏览器支持([name])</h1>
-
-	<h2>总览</h2>
-	<div>
-		<p>
-            在所有现代浏览器中,Three.js可以使用WebGL来渲染场景。对于较旧的浏览器,特别是Internet Explorer 10或者更低版本浏览器,你将需要回落到其它[link:https://github.com/mrdoob/three.js/tree/master/examples/jsm/renderers renderers](CSS2DRenderer、CSS3DRenderer、SVGRenderer)。此外,你或许不得不包含一些额外的“填充物”来解决兼容性问题,特别是当你使用[link:https://github.com/mrdoob/three.js/tree/master/examples /examples]目录中的文件时。
-		</p>
-		<p>
-            注意:如果你并不需要支持较旧的浏览器,那就不推荐使用其他渲染器来进行渲染,因为与WebGLRenderer相比,其它渲染器渲染较慢,并且不支持WebGL的诸多特性。
-		</p>
-	</div>
-
-	<h2>支持WebGL的浏览器</h2>
-	<div>
-		<p>
-			Google Chrome 9+、Firefox 4+、Opera 15+、Safari 5.1+、Internet Explorer 11 和 Microsoft Edge。你可以点击[link:https://caniuse.com/#feat=webgl Can I use WebGL]来查阅各个浏览器对WebGL的支持性。
-		</p>
-	</div>
-
-	<h2>
-        在Three.js中所使用到的JavaScript语言特性或者Web API
-        </h2>
-	<div>
-		<p>
-            这里是一些在Three.js中使用到的特性,其中的一部分需要额外的“填充物”(Polyfills)来解决兼容性问题。
-		</p>
-		<table>
-			<thead>
-				<tr>
-					<th>特性</th>
-					<th>适用范围</th>
-					<th>模块</th>
-				</tr>
-			</thead>
-			<tbody>
-				<tr>
-					<td>Typed Arrays</td>
-					<td>Source</td>
-					<td>BufferAttribute, BufferGeometry, etc.</td>
-				</tr>
-				<tr>
-					<td>Web Audio API</td>
-					<td>Source</td>
-					<td>Audio, AudioContext, AudioListener, etc.</td>
-				</tr>
-				<tr>
-					<td>WebXR Device API</td>
-					<td>Source</td>
-					<td>WebXRManager</td>
-				</tr>
-				<tr>
-					<td>Blob</td>
-					<td>Source</td>
-					<td>FileLoader, etc.</td>
-				</tr>
-				<tr>
-					<td>Promise</td>
-					<td>Examples</td>
-					<td>GLTFLoader, DRACOLoader, BasisTextureLoader, GLTFExporter, VRButton, ARButton, etc.</td>
-				</tr>
-				<tr>
-					<td>Fetch</td>
-					<td>Examples</td>
-					<td>ImageBitmapLoader, etc.</td>
-				</tr>
-				<tr>
-					<td>File API</td>
-					<td>Examples</td>
-					<td>GLTFExporter, etc.</td>
-				</tr>
-				<tr>
-					<td>URL API</td>
-					<td>Examples</td>
-					<td>GLTFLoader, etc.</td>
-				</tr>
-				<tr>
-					<td>Pointer Lock API</td>
-					<td>Examples</td>
-					<td>PointerLockControls</td>
-				</tr>
-			</tbody>
-		</table>
-	</div>
-
-	<h2>关于用于解决兼容性问题的“填充物”</h2>
-	<div>
-		<p>根据你的需求,引入相关的“填充物”即可。以IE9为例,你至少需要来使用“填充物”完成以下的功能。</p>
-		<ul>
-			<li>Typed Arrays</li>
-			<li>Blob</li>
-		</ul>
-	</div>
-
-	<h3>建议的“填充物”</h3>
-	<div>
-		<ul>
-			<li>
-				[link:https://github.com/zloirock/core-js core-js]
-			</li>
-			<li>
-				[link:https://github.com/inexorabletash/polyfill/blob/master/typedarray.js typedarray.js]
-			</li>
-			<li>
-				[link:https://github.com/stefanpenner/es6-promise/ ES6-Promise]
-			</li>
-			<li>
-				[link:https://github.com/eligrey/Blob.js Blob.js]
-			</li>
-			<li>
-				[link:https://github.com/github/fetch fetch]
-			</li>
-		</ul>
-	</div>
-</body>
-</html>

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

@@ -458,8 +458,8 @@
 
 
 					const data = {
 					const data = {
 						radius: 15,
 						radius: 15,
-						widthSegments: 8,
-						heightSegments: 6,
+						widthSegments: 32,
+						heightSegments: 16,
 						phiStart: 0,
 						phiStart: 0,
 						phiLength: twoPi,
 						phiLength: twoPi,
 						thetaStart: 0,
 						thetaStart: 0,
@@ -479,7 +479,7 @@
 					const folder = gui.addFolder( 'THREE.SphereGeometry' );
 					const folder = gui.addFolder( 'THREE.SphereGeometry' );
 
 
 					folder.add( data, 'radius', 1, 30 ).onChange( generateGeometry );
 					folder.add( data, 'radius', 1, 30 ).onChange( generateGeometry );
-					folder.add( data, 'widthSegments', 3, 32 ).step( 1 ).onChange( generateGeometry );
+					folder.add( data, 'widthSegments', 3, 64 ).step( 1 ).onChange( generateGeometry );
 					folder.add( data, 'heightSegments', 2, 32 ).step( 1 ).onChange( generateGeometry );
 					folder.add( data, 'heightSegments', 2, 32 ).step( 1 ).onChange( generateGeometry );
 					folder.add( data, 'phiStart', 0, twoPi ).onChange( generateGeometry );
 					folder.add( data, 'phiStart', 0, twoPi ).onChange( generateGeometry );
 					folder.add( data, 'phiLength', 0, twoPi ).onChange( generateGeometry );
 					folder.add( data, 'phiLength', 0, twoPi ).onChange( generateGeometry );

+ 1 - 0
editor/index.html

@@ -172,6 +172,7 @@
 				signals.objectRemoved.add( saveState );
 				signals.objectRemoved.add( saveState );
 				signals.materialChanged.add( saveState );
 				signals.materialChanged.add( saveState );
 				signals.sceneBackgroundChanged.add( saveState );
 				signals.sceneBackgroundChanged.add( saveState );
+				signals.sceneEnvironmentChanged.add( saveState );
 				signals.sceneFogChanged.add( saveState );
 				signals.sceneFogChanged.add( saveState );
 				signals.sceneGraphChanged.add( saveState );
 				signals.sceneGraphChanged.add( saveState );
 				signals.scriptChanged.add( saveState );
 				signals.scriptChanged.add( saveState );

+ 1 - 0
editor/js/Editor.js

@@ -132,6 +132,7 @@ Editor.prototype = {
 		this.scene.name = scene.name;
 		this.scene.name = scene.name;
 
 
 		this.scene.background = scene.background;
 		this.scene.background = scene.background;
+		this.scene.environment = scene.environment;
 		this.scene.fog = scene.fog;
 		this.scene.fog = scene.fog;
 
 
 		this.scene.userData = JSON.parse( JSON.stringify( scene.userData ) );
 		this.scene.userData = JSON.parse( JSON.stringify( scene.userData ) );

+ 49 - 15
editor/js/Loader.js

@@ -192,8 +192,7 @@ function Loader( editor ) {
 						} else {
 						} else {
 
 
 							var material = new THREE.PointsMaterial( { size: 0.01 } );
 							var material = new THREE.PointsMaterial( { size: 0.01 } );
-
-							if ( geometry.hasAttribute( 'color' ) === true ) material.vertexColors = true;
+							material.vertexColors = geometry.hasAttribute( 'color' );
 
 
 							object = new THREE.Points( geometry, material );
 							object = new THREE.Points( geometry, material );
 							object.name = filename;
 							object.name = filename;
@@ -354,13 +353,12 @@ function Loader( editor ) {
 					var { IFCLoader } = await import( '../../examples/jsm/loaders/IFCLoader.js' );
 					var { IFCLoader } = await import( '../../examples/jsm/loaders/IFCLoader.js' );
 
 
 					var loader = new IFCLoader();
 					var loader = new IFCLoader();
-					loader.setWasmPath( '../../examples/jsm/loaders/ifc/' );
-
-					var scene = await loader.parse( event.target.result );
+					loader.ifcManager.setWasmPath( '../../examples/jsm/loaders/ifc/' );
 
 
-					scene.name = filename;
+					var model = await loader.parse( event.target.result );
+					model.mesh.name = filename;
 
 
-					editor.execute( new AddObjectCommand( editor, scene ) );
+					editor.execute( new AddObjectCommand( editor, model.mesh ) );
 
 
 				}, false );
 				}, false );
 				reader.readAsArrayBuffer( file );
 				reader.readAsArrayBuffer( file );
@@ -385,6 +383,31 @@ function Loader( editor ) {
 
 
 				break;
 				break;
 
 
+			case 'ldr':
+			case 'mpd':
+
+				reader.addEventListener( 'load', async function ( event ) {
+
+					var { LDrawLoader } = await import( '../../examples/jsm/loaders/LDrawLoader.js' );
+
+					var loader = new LDrawLoader();
+					loader.fileMap = {}; // TODO Uh...
+					loader.setPath( '../../examples/models/ldraw/officialLibrary/' );
+					loader.parse( event.target.result, undefined, function ( group ) {
+
+						group.name = filename;
+						// Convert from LDraw coordinates: rotate 180 degrees around OX
+						group.rotation.x = Math.PI;
+
+						editor.execute( new AddObjectCommand( editor, group ) );
+
+					} );
+
+				}, false );
+				reader.readAsText( file );
+
+				break;
+
 			case 'md2':
 			case 'md2':
 
 
 				reader.addEventListener( 'load', async function ( event ) {
 				reader.addEventListener( 'load', async function ( event ) {
@@ -394,10 +417,7 @@ function Loader( editor ) {
 					var { MD2Loader } = await import( '../../examples/jsm/loaders/MD2Loader.js' );
 					var { MD2Loader } = await import( '../../examples/jsm/loaders/MD2Loader.js' );
 
 
 					var geometry = new MD2Loader().parse( contents );
 					var geometry = new MD2Loader().parse( contents );
-					var material = new THREE.MeshStandardMaterial( {
-						morphTargets: true,
-						morphNormals: true
-					} );
+					var material = new THREE.MeshStandardMaterial();
 
 
 					var mesh = new THREE.Mesh( geometry, material );
 					var mesh = new THREE.Mesh( geometry, material );
 					mesh.mixer = new THREE.AnimationMixer( mesh );
 					mesh.mixer = new THREE.AnimationMixer( mesh );
@@ -438,12 +458,26 @@ function Loader( editor ) {
 					var { PLYLoader } = await import( '../../examples/jsm/loaders/PLYLoader.js' );
 					var { PLYLoader } = await import( '../../examples/jsm/loaders/PLYLoader.js' );
 
 
 					var geometry = new PLYLoader().parse( contents );
 					var geometry = new PLYLoader().parse( contents );
-					var material = new THREE.MeshStandardMaterial();
+					var object;
 
 
-					var mesh = new THREE.Mesh( geometry, material );
-					mesh.name = filename;
+					if ( geometry.index !== null ) {
 
 
-					editor.execute( new AddObjectCommand( editor, mesh ) );
+						var material = new THREE.MeshStandardMaterial();
+
+						object = new THREE.Mesh( geometry, material );
+						object.name = filename;
+
+					} else {
+
+						var material = new THREE.PointsMaterial( { size: 0.01 } );
+						material.vertexColors = geometry.hasAttribute( 'color' );
+
+						object = new THREE.Points( geometry, material );
+						object.name = filename;
+
+					}
+
+					editor.execute( new AddObjectCommand( editor, object ) );
 
 
 				}, false );
 				}, false );
 				reader.readAsArrayBuffer( file );
 				reader.readAsArrayBuffer( file );

+ 1 - 1
editor/js/Menubar.Add.js

@@ -205,7 +205,7 @@ function MenubarAdd( editor ) {
 	option.setTextContent( strings.getKey( 'menubar/add/sphere' ) );
 	option.setTextContent( strings.getKey( 'menubar/add/sphere' ) );
 	option.onClick( function () {
 	option.onClick( function () {
 
 
-		var geometry = new THREE.SphereGeometry( 1, 8, 6, 0, Math.PI * 2, 0, Math.PI );
+		var geometry = new THREE.SphereGeometry( 1, 32, 16, 0, Math.PI * 2, 0, Math.PI );
 		var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
 		var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
 		mesh.name = 'Sphere';
 		mesh.name = 'Sphere';
 
 

+ 12 - 0
editor/js/Menubar.Help.js

@@ -54,6 +54,18 @@ function MenubarHelp( editor ) {
 	} );
 	} );
 	options.add( option );
 	options.add( option );
 
 
+	// Manual
+
+	var option = new UIRow();
+	option.setClass( 'option' );
+	option.setTextContent( strings.getKey( 'menubar/help/manual' ) );
+	option.onClick( function () {
+
+		window.open( 'https://github.com/mrdoob/three.js/wiki/Editor-Manual', '_blank' );
+
+	} );
+	options.add( option );
+
 	return container;
 	return container;
 
 
 }
 }

+ 63 - 0
editor/js/Sidebar.Material.BooleanProperty.js

@@ -0,0 +1,63 @@
+import { UICheckbox, UIRow, UIText } from './libs/ui.js';
+import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
+
+function SidebarMaterialBooleanProperty( editor, property, name ) {
+
+	const signals = editor.signals;
+
+	const container = new UIRow();
+	container.add( new UIText( name ).setWidth( '90px' ) );
+
+	const boolean = new UICheckbox().setLeft( '100px' ).onChange( onChange );
+	container.add( boolean );
+
+	let object = null;
+	let material = null;
+
+	function onChange() {
+
+		if ( material[ property ] !== boolean.getValue() ) {
+
+			editor.execute( new SetMaterialValueCommand( editor, object, property, boolean.getValue(), 0 /* TODO: currentMaterialSlot */ ) );
+
+		}
+
+	}
+
+	function update() {
+
+		if ( object === null ) return;
+		if ( object.material === undefined ) return;
+
+		material = object.material;
+
+		if ( property in material ) {
+
+			boolean.setValue( material[ property ] );
+			container.setDisplay( '' );
+
+		} else {
+
+			container.setDisplay( 'none' );
+
+		}
+
+	}
+
+	//
+
+	signals.objectSelected.add( function ( selected ) {
+
+		object = selected;
+
+		update();
+
+	} );
+
+	signals.materialChanged.add( update );
+
+	return container;
+
+}
+
+export { SidebarMaterialBooleanProperty };

+ 90 - 0
editor/js/Sidebar.Material.ColorProperty.js

@@ -0,0 +1,90 @@
+import { UIColor, UINumber, UIRow, UIText } from './libs/ui.js';
+import { SetMaterialColorCommand } from './commands/SetMaterialColorCommand.js';
+import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
+
+function SidebarMaterialColorProperty( editor, property, name ) {
+
+	const signals = editor.signals;
+
+	const container = new UIRow();
+	container.add( new UIText( name ).setWidth( '90px' ) );
+
+	const color = new UIColor().onInput( onChange );
+	container.add( color );
+
+	let intensity;
+
+	if ( property === 'emissive' ) {
+
+		intensity = new UINumber().setWidth( '30px' ).onChange( onChange );
+		container.add( intensity );
+
+	}
+
+	let object = null;
+	let material = null;
+
+	function onChange() {
+
+		if ( material[ property ].getHex() !== color.getHexValue() ) {
+
+			editor.execute( new SetMaterialColorCommand( editor, object, property, color.getHexValue(), 0 /* TODO: currentMaterialSlot */ ) );
+
+		}
+
+		if ( intensity !== undefined ) {
+
+			if ( material[ `${ property }Intensity` ] !== intensity.getValue() ) {
+
+				editor.execute( new SetMaterialValueCommand( editor, object, `${ property }Intensity`, intensity.getValue(), /* TODO: currentMaterialSlot*/ 0 ) );
+
+			}
+
+		}
+
+	}
+
+	function update() {
+
+		if ( object === null ) return;
+		if ( object.material === undefined ) return;
+
+		material = object.material;
+
+		if ( property in material ) {
+
+			color.setHexValue( material[ property ].getHexString() );
+
+			if ( intensity !== undefined ) {
+
+				intensity.setValue( material[ `${ property }Intensity` ] );
+
+			}
+
+			container.setDisplay( '' );
+
+		} else {
+
+			container.setDisplay( 'none' );
+
+		}
+
+	}
+
+	//
+
+	signals.objectSelected.add( function ( selected ) {
+
+		object = selected;
+
+		update();
+
+	} );
+
+	signals.materialChanged.add( update );
+
+	return container;
+
+}
+
+export { SidebarMaterialColorProperty };

+ 65 - 0
editor/js/Sidebar.Material.ConstantProperty.js

@@ -0,0 +1,65 @@
+import { UIRow, UISelect, UIText } from './libs/ui.js';
+import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
+
+function SidebarMaterialConstantProperty( editor, property, name, options ) {
+
+	const signals = editor.signals;
+
+	const container = new UIRow();
+	container.add( new UIText( name ).setWidth( '90px' ) );
+
+	const constant = new UISelect().setOptions( options ).onChange( onChange );
+	container.add( constant );
+
+	let object = null;
+	let material = null;
+
+	function onChange() {
+
+		const value = parseInt( constant.getValue() );
+
+		if ( material[ property ] !== value ) {
+
+			editor.execute( new SetMaterialValueCommand( editor, object, property, value, 0 /* TODO: currentMaterialSlot */ ) );
+
+		}
+
+	}
+
+	function update() {
+
+		if ( object === null ) return;
+		if ( object.material === undefined ) return;
+
+		material = object.material;
+
+		if ( property in material ) {
+
+			constant.setValue( material[ property ] );
+			container.setDisplay( '' );
+
+		} else {
+
+			container.setDisplay( 'none' );
+
+		}
+
+	}
+
+	//
+
+	signals.objectSelected.add( function ( selected ) {
+
+		object = selected;
+
+		update();
+
+	} );
+
+	signals.materialChanged.add( update );
+
+	return container;
+
+}
+
+export { SidebarMaterialConstantProperty };

+ 193 - 0
editor/js/Sidebar.Material.MapProperty.js

@@ -0,0 +1,193 @@
+import * as THREE from '../../build/three.module.js';
+
+import { UICheckbox, UINumber, UIRow, UIText } from './libs/ui.js';
+import { UITexture } from './libs/ui.three.js';
+import { SetMaterialMapCommand } from './commands/SetMaterialMapCommand.js';
+import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
+import { SetMaterialVectorCommand } from './commands/SetMaterialVectorCommand.js';
+
+function SidebarMaterialMapProperty( editor, property, name ) {
+
+	const signals = editor.signals;
+
+	const container = new UIRow();
+	container.add( new UIText( name ).setWidth( '90px' ) );
+
+	const enabled = new UICheckbox( false ).setMarginRight( '8px' ).onChange( onChange );
+	container.add( enabled );
+
+	const map = new UITexture().onChange( onMapChange );
+	container.add( map );
+
+	const mapType = property.replace( 'Map', '' );
+
+	let intensity;
+
+	if ( property === 'aoMap' ) {
+
+		intensity = new UINumber().setWidth( '30px' ).onChange( onIntensityChange );
+		container.add( intensity );
+
+	}
+
+	let scale;
+
+	if ( property === 'bumpMap' || property === 'displacementMap' ) {
+
+		scale = new UINumber().setWidth( '30px' ).onChange( onScaleChange );
+		container.add( scale );
+
+	}
+
+	let scaleX, scaleY;
+
+	if ( property === 'normalMap' || property === 'clearcoatNormalMap' ) {
+
+		scaleX = new UINumber().setWidth( '30px' ).onChange( onScaleXYChange );
+		container.add( scaleX );
+
+		scaleY = new UINumber().setWidth( '30px' ).onChange( onScaleXYChange );
+		container.add( scaleY );
+
+	}
+
+	let object = null;
+	let material = null;
+
+	function onChange() {
+
+		const newMap = enabled.getValue() ? map.getValue() : null;
+
+		if ( material[ 'property' ] !== newMap ) {
+
+			const geometry = object.geometry;
+
+			if ( newMap !== null && geometry.isBufferGeometry && geometry.attributes.uv === undefined ) {
+
+				console.warn( 'Geometry doesn\'t have uvs:', geometry );
+
+			}
+
+			editor.execute( new SetMaterialMapCommand( editor, object, property, newMap, 0 /* TODO: currentMaterialSlot */ ) );
+
+		}
+
+	}
+
+	function onMapChange( texture ) {
+
+		if ( texture !== null ) {
+
+			if ( texture.isDataTexture !== true && texture.encoding !== THREE.sRGBEncoding ) {
+
+				texture.encoding = THREE.sRGBEncoding;
+				material.needsUpdate = true;
+
+			}
+
+		}
+
+		enabled.setDisabled( false );
+
+		onChange();
+
+	}
+
+	function onIntensityChange() {
+
+		if ( material[ `${ property }Intensity` ] !== intensity.getValue() ) {
+
+			editor.execute( new SetMaterialValueCommand( editor, object, `${ property }Intensity`, intensity.getValue(), 0 /* TODO: currentMaterialSlot */ ) );
+
+		}
+
+	}
+
+	function onScaleChange() {
+
+		if ( material[ `${ mapType }Scale` ] !== scale.getValue() ) {
+
+			editor.execute( new SetMaterialValueCommand( editor, object, `${ mapType }Scale`, scale.getValue(), 0 /* TODO: currentMaterialSlot */ ) );
+
+		}
+
+	}
+
+	function onScaleXYChange() {
+
+		const value = [ scaleX.getValue(), scaleY.getValue() ];
+
+		if ( material[ `${ mapType }Scale` ].x !== value[ 0 ] || material[ `${ mapType }Scale` ].y !== value[ 1 ] ) {
+
+			editor.execute( new SetMaterialVectorCommand( editor, object, `${ mapType }Scale`, value, 0 /* TODOL currentMaterialSlot */ ) );
+
+		}
+
+	}
+
+	function update() {
+
+		if ( object === null ) return;
+		if ( object.material === undefined ) return;
+
+		material = object.material;
+
+		if ( property in material ) {
+
+			if ( material[ property ] !== null ) {
+
+				map.setValue( material[ property ] );
+
+			}
+
+			enabled.setValue( material[ property ] !== null );
+			enabled.setDisabled( map.getValue() === null );
+
+			if ( intensity !== undefined ) {
+
+				intensity.setValue( material[ `${ property }Intensity` ] );
+
+			}
+
+			if ( scale !== undefined ) {
+
+				scale.setValue( material[ `${ mapType }Scale` ] );
+
+			}
+
+			if ( scaleX !== undefined ) {
+
+				scaleX.setValue( material[ `${ mapType }Scale` ].x );
+				scaleY.setValue( material[ `${ mapType }Scale` ].y );
+
+			}
+
+			container.setDisplay( '' );
+
+		} else {
+
+			container.setDisplay( 'none' );
+
+		}
+
+	}
+
+	//
+
+	signals.objectSelected.add( function ( selected ) {
+
+		object = selected;
+
+		map.setValue( null );
+
+		update();
+
+	} );
+
+	signals.materialChanged.add( update );
+
+	return container;
+
+}
+
+export { SidebarMaterialMapProperty };

+ 63 - 0
editor/js/Sidebar.Material.NumberProperty.js

@@ -0,0 +1,63 @@
+import { UINumber, UIRow, UIText } from './libs/ui.js';
+import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
+
+function SidebarMaterialNumberProperty( editor, property, name, range = [ - Infinity, Infinity ] ) {
+
+	const signals = editor.signals;
+
+	const container = new UIRow();
+	container.add( new UIText( name ).setWidth( '90px' ) );
+
+	const number = new UINumber().setWidth( '60px' ).setRange( range[ 0 ], range[ 1 ] ).onChange( onChange );
+	container.add( number );
+
+	let object = null;
+	let material = null;
+
+	function onChange() {
+
+		if ( material[ property ] !== number.getValue() ) {
+
+			editor.execute( new SetMaterialValueCommand( editor, object, property, number.getValue(), 0 /* TODO: currentMaterialSlot */ ) );
+
+		}
+
+	}
+
+	function update() {
+
+		if ( object === null ) return;
+		if ( object.material === undefined ) return;
+
+		material = object.material;
+
+		if ( property in material ) {
+
+			number.setValue( material[ property ] );
+			container.setDisplay( '' );
+
+		} else {
+
+			container.setDisplay( 'none' );
+
+		}
+
+	}
+
+	//
+
+	signals.objectSelected.add( function ( selected ) {
+
+		object = selected;
+
+		update();
+
+	} );
+
+	signals.materialChanged.add( update );
+
+	return container;
+
+}
+
+export { SidebarMaterialNumberProperty };

+ 76 - 0
editor/js/Sidebar.Material.Program.js

@@ -0,0 +1,76 @@
+import { UIButton, UIRow, UIText } from './libs/ui.js';
+
+function SidebarMaterialProgram( editor, property ) {
+
+	const signals = editor.signals;
+	const strings = editor.strings;
+
+	let object = null;
+	let material = null;
+
+	const container = new UIRow();
+	container.add( new UIText( strings.getKey( 'sidebar/material/program' ) ).setWidth( '90px' ) );
+
+	const programInfo = new UIButton( strings.getKey( 'sidebar/material/info' ) );
+	programInfo.setMarginRight( '4px' );
+	programInfo.onClick( function () {
+
+		signals.editScript.dispatch( object, 'programInfo' );
+
+	} );
+	container.add( programInfo );
+
+	const programVertex = new UIButton( strings.getKey( 'sidebar/material/vertex' ) );
+	programVertex.setMarginRight( '4px' );
+	programVertex.onClick( function () {
+
+		signals.editScript.dispatch( object, 'vertexShader' );
+
+	} );
+	container.add( programVertex );
+
+	const programFragment = new UIButton( strings.getKey( 'sidebar/material/fragment' ) );
+	programFragment.setMarginRight( '4px' );
+	programFragment.onClick( function () {
+
+		signals.editScript.dispatch( object, 'fragmentShader' );
+
+	} );
+	container.add( programFragment );
+
+	function update() {
+
+		if ( object === null ) return;
+		if ( object.material === undefined ) return;
+
+		material = object.material;
+
+		if ( property in material ) {
+
+			container.setDisplay( '' );
+
+		} else {
+
+			container.setDisplay( 'none' );
+
+		}
+
+	}
+
+	//
+
+	signals.objectSelected.add( function ( selected ) {
+
+		object = selected;
+
+		update();
+
+	} );
+
+	signals.materialChanged.add( update );
+
+	return container;
+
+}
+
+export { SidebarMaterialProgram };

+ 257 - 1506
editor/js/Sidebar.Material.js

@@ -1,57 +1,38 @@
 import * as THREE from '../../build/three.module.js';
 import * as THREE from '../../build/three.module.js';
 
 
-import { UIButton, UICheckbox, UIColor, UIInput, UINumber, UIPanel, UIRow, UISelect, UIText } from './libs/ui.js';
-import { UITexture } from './libs/ui.three.js';
+import { UIButton, UIInput, UIPanel, UIRow, UISelect, UIText } from './libs/ui.js';
 
 
 import { SetMaterialCommand } from './commands/SetMaterialCommand.js';
 import { SetMaterialCommand } from './commands/SetMaterialCommand.js';
-import { SetMaterialColorCommand } from './commands/SetMaterialColorCommand.js';
-import { SetMaterialMapCommand } from './commands/SetMaterialMapCommand.js';
 import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
 import { SetMaterialValueCommand } from './commands/SetMaterialValueCommand.js';
-import { SetMaterialVectorCommand } from './commands/SetMaterialVectorCommand.js';
 
 
-var materialClasses = {
-	'LineBasicMaterial': THREE.LineBasicMaterial,
-	'LineDashedMaterial': THREE.LineDashedMaterial,
-	'MeshBasicMaterial': THREE.MeshBasicMaterial,
-	'MeshDepthMaterial': THREE.MeshDepthMaterial,
-	'MeshNormalMaterial': THREE.MeshNormalMaterial,
-	'MeshLambertMaterial': THREE.MeshLambertMaterial,
-	'MeshMatcapMaterial': THREE.MeshMatcapMaterial,
-	'MeshPhongMaterial': THREE.MeshPhongMaterial,
-	'MeshToonMaterial': THREE.MeshToonMaterial,
-	'MeshStandardMaterial': THREE.MeshStandardMaterial,
-	'MeshPhysicalMaterial': THREE.MeshPhysicalMaterial,
-	'RawShaderMaterial': THREE.RawShaderMaterial,
-	'ShaderMaterial': THREE.ShaderMaterial,
-	'ShadowMaterial': THREE.ShadowMaterial,
-	'SpriteMaterial': THREE.SpriteMaterial,
-	'PointsMaterial': THREE.PointsMaterial
-};
+import { SidebarMaterialBooleanProperty } from './Sidebar.Material.BooleanProperty.js';
+import { SidebarMaterialColorProperty } from './Sidebar.Material.ColorProperty.js';
+import { SidebarMaterialConstantProperty } from './Sidebar.Material.ConstantProperty.js';
+import { SidebarMaterialMapProperty } from './Sidebar.Material.MapProperty.js';
+import { SidebarMaterialNumberProperty } from './Sidebar.Material.NumberProperty.js';
+import { SidebarMaterialProgram } from './Sidebar.Material.Program.js';
 
 
 function SidebarMaterial( editor ) {
 function SidebarMaterial( editor ) {
 
 
-	var strings = editor.strings;
-
-	var signals = editor.signals;
+	const signals = editor.signals;
+	const strings = editor.strings;
 
 
-	var currentObject;
+	let currentObject;
 
 
-	var currentMaterialSlot = 0;
+	let currentMaterialSlot = 0;
 
 
-	var epsilon = 0.01 - Number.EPSILON;
-
-	var container = new UIPanel();
+	const container = new UIPanel();
 	container.setBorderTop( '0' );
 	container.setBorderTop( '0' );
 	container.setDisplay( 'none' );
 	container.setDisplay( 'none' );
 	container.setPaddingTop( '20px' );
 	container.setPaddingTop( '20px' );
 
 
 	// Current material slot
 	// Current material slot
 
 
-	var materialSlotRow = new UIRow();
+	const materialSlotRow = new UIRow();
 
 
 	materialSlotRow.add( new UIText( strings.getKey( 'sidebar/material/slot' ) ).setWidth( '90px' ) );
 	materialSlotRow.add( new UIText( strings.getKey( 'sidebar/material/slot' ) ).setWidth( '90px' ) );
 
 
-	var materialSlotSelect = new UISelect().setWidth( '170px' ).setFontSize( '12px' ).onChange( update );
+	const materialSlotSelect = new UISelect().setWidth( '170px' ).setFontSize( '12px' ).onChange( update );
 	materialSlotSelect.setOptions( { 0: '' } ).setValue( 0 );
 	materialSlotSelect.setOptions( { 0: '' } ).setValue( 0 );
 	materialSlotRow.add( materialSlotSelect );
 	materialSlotRow.add( materialSlotSelect );
 
 
@@ -59,8 +40,8 @@ function SidebarMaterial( editor ) {
 
 
 	// type
 	// type
 
 
-	var materialClassRow = new UIRow();
-	var materialClass = new UISelect().setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
+	const materialClassRow = new UIRow();
+	const materialClass = new UISelect().setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
 
 
 	materialClassRow.add( new UIText( strings.getKey( 'sidebar/material/type' ) ).setWidth( '90px' ) );
 	materialClassRow.add( new UIText( strings.getKey( 'sidebar/material/type' ) ).setWidth( '90px' ) );
 	materialClassRow.add( materialClass );
 	materialClassRow.add( materialClass );
@@ -69,9 +50,10 @@ function SidebarMaterial( editor ) {
 
 
 	// uuid
 	// uuid
 
 
-	var materialUUIDRow = new UIRow();
-	var materialUUID = new UIInput().setWidth( '102px' ).setFontSize( '12px' ).setDisabled( true );
-	var materialUUIDRenew = new UIButton( strings.getKey( 'sidebar/material/new' ) ).setMarginLeft( '7px' ).onClick( function () {
+	const materialUUIDRow = new UIRow();
+	const materialUUID = new UIInput().setWidth( '102px' ).setFontSize( '12px' ).setDisabled( true );
+	const materialUUIDRenew = new UIButton( strings.getKey( 'sidebar/material/new' ) ).setMarginLeft( '7px' );
+	materialUUIDRenew.onClick( function () {
 
 
 		materialUUID.setValue( THREE.MathUtils.generateUUID() );
 		materialUUID.setValue( THREE.MathUtils.generateUUID() );
 		update();
 		update();
@@ -86,8 +68,8 @@ function SidebarMaterial( editor ) {
 
 
 	// name
 	// name
 
 
-	var materialNameRow = new UIRow();
-	var materialName = new UIInput().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () {
+	const materialNameRow = new UIRow();
+	const materialName = new UIInput().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () {
 
 
 		editor.execute( new SetMaterialValueCommand( editor, editor.selected, 'name', materialName.getValue(), currentMaterialSlot ) );
 		editor.execute( new SetMaterialValueCommand( editor, editor.selected, 'name', materialName.getValue(), currentMaterialSlot ) );
 
 
@@ -100,521 +82,245 @@ function SidebarMaterial( editor ) {
 
 
 	// program
 	// program
 
 
-	var materialProgramRow = new UIRow();
-	materialProgramRow.add( new UIText( strings.getKey( 'sidebar/material/program' ) ).setWidth( '90px' ) );
-
-	var materialProgramInfo = new UIButton( strings.getKey( 'sidebar/material/info' ) );
-	materialProgramInfo.setMarginRight( '4px' );
-	materialProgramInfo.onClick( function () {
-
-		signals.editScript.dispatch( currentObject, 'programInfo' );
-
-	} );
-	materialProgramRow.add( materialProgramInfo );
-
-	var materialProgramVertex = new UIButton( strings.getKey( 'sidebar/material/vertex' ) );
-	materialProgramVertex.setMarginRight( '4px' );
-	materialProgramVertex.onClick( function () {
-
-		signals.editScript.dispatch( currentObject, 'vertexShader' );
-
-	} );
-	materialProgramRow.add( materialProgramVertex );
-
-	var materialProgramFragment = new UIButton( strings.getKey( 'sidebar/material/fragment' ) );
-	materialProgramFragment.setMarginRight( '4px' );
-	materialProgramFragment.onClick( function () {
-
-		signals.editScript.dispatch( currentObject, 'fragmentShader' );
-
-	} );
-	materialProgramRow.add( materialProgramFragment );
-
-	container.add( materialProgramRow );
+	const materialProgram = new SidebarMaterialProgram( editor, 'vertexShader' );
+	container.add( materialProgram );
 
 
 	// color
 	// color
 
 
-	var materialColorRow = new UIRow();
-	var materialColor = new UIColor().onInput( update );
+	const materialColor = new SidebarMaterialColorProperty( editor, 'color', strings.getKey( 'sidebar/material/color' ) );
+	container.add( materialColor );
 
 
-	materialColorRow.add( new UIText( strings.getKey( 'sidebar/material/color' ) ).setWidth( '90px' ) );
-	materialColorRow.add( materialColor );
-
-	container.add( materialColorRow );
-
-	// roughness
-
-	var materialRoughnessRow = new UIRow();
-	var materialRoughness = new UINumber( 0.5 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update );
-
-	materialRoughnessRow.add( new UIText( strings.getKey( 'sidebar/material/roughness' ) ).setWidth( '90px' ) );
-	materialRoughnessRow.add( materialRoughness );
-
-	container.add( materialRoughnessRow );
-
-	// metalness
-
-	var materialMetalnessRow = new UIRow();
-	var materialMetalness = new UINumber( 0.5 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update );
-
-	materialMetalnessRow.add( new UIText( strings.getKey( 'sidebar/material/metalness' ) ).setWidth( '90px' ) );
-	materialMetalnessRow.add( materialMetalness );
-
-	container.add( materialMetalnessRow );
-
-	/*
-	// sheen
-
-	var materialSheenRow = new UIRow();
-	var materialSheenEnabled = new UICheckbox( false ).onChange( update );
-	var materialSheen = new UIColor().setHexValue( 0x000000 ).onInput( update );
-
-	materialSheenRow.add( new UIText( strings.getKey( 'sidebar/material/sheen' ) ).setWidth( '90px' ) )
-	materialSheenRow.add( materialSheenEnabled );
-	materialSheenRow.add( materialSheen );
-
-	container.add( materialSheenRow );
-	*/
-
-	// transmission
+	// specular
 
 
-	var materialTransmissionRow = new UIRow();
-	var materialTransmission = new UINumber( 1 ).setWidth( '30px' ).setRange( 0, 1 ).onChange( update );
+	const materialSpecular = new SidebarMaterialColorProperty( editor, 'specular', strings.getKey( 'sidebar/material/specular' ) );
+	container.add( materialSpecular );
 
 
-	materialTransmissionRow.add( new UIText( strings.getKey( 'sidebar/material/transmission' ) ).setWidth( '90px' ) );
-	materialTransmissionRow.add( materialTransmission );
+	// shininess
 
 
-	container.add( materialTransmissionRow );
+	const materialShininess = new SidebarMaterialNumberProperty( editor, 'shininess', strings.getKey( 'sidebar/material/shininess' ) );
+	container.add( materialShininess );
 
 
 	// emissive
 	// emissive
 
 
-	var materialEmissiveRow = new UIRow();
-	var materialEmissive = new UIColor().setHexValue( 0x000000 ).onInput( update );
-	var materialEmissiveIntensity = new UINumber( 1 ).setWidth( '30px' ).onChange( update );
-
-	materialEmissiveRow.add( new UIText( strings.getKey( 'sidebar/material/emissive' ) ).setWidth( '90px' ) );
-	materialEmissiveRow.add( materialEmissive );
-	materialEmissiveRow.add( materialEmissiveIntensity );
-
-	container.add( materialEmissiveRow );
-
-	// specular
-
-	var materialSpecularRow = new UIRow();
-	var materialSpecular = new UIColor().setHexValue( 0x111111 ).onInput( update );
+	const materialEmissive = new SidebarMaterialColorProperty( editor, 'emissive', strings.getKey( 'sidebar/material/emissive' ) );
+	container.add( materialEmissive );
 
 
-	materialSpecularRow.add( new UIText( strings.getKey( 'sidebar/material/specular' ) ).setWidth( '90px' ) );
-	materialSpecularRow.add( materialSpecular );
+	// reflectivity
 
 
-	container.add( materialSpecularRow );
+	const materialReflectivity = new SidebarMaterialNumberProperty( editor, 'reflectivity', strings.getKey( 'sidebar/material/reflectivity' ) );
+	container.add( materialReflectivity );
 
 
-	// shininess
+	// roughness
 
 
-	var materialShininessRow = new UIRow();
-	var materialShininess = new UINumber( 30 ).onChange( update );
+	const materialRoughness = new SidebarMaterialNumberProperty( editor, 'roughness', strings.getKey( 'sidebar/material/roughness' ), [ 0, 1 ] );
+	container.add( materialRoughness );
 
 
-	materialShininessRow.add( new UIText( strings.getKey( 'sidebar/material/shininess' ) ).setWidth( '90px' ) );
-	materialShininessRow.add( materialShininess );
+	// metalness
 
 
-	container.add( materialShininessRow );
+	const materialMetalness = new SidebarMaterialNumberProperty( editor, 'metalness', strings.getKey( 'sidebar/material/metalness' ), [ 0, 1 ] );
+	container.add( materialMetalness );
 
 
 	// clearcoat
 	// clearcoat
 
 
-	var materialClearcoatRow = new UIRow();
-	var materialClearcoat = new UINumber( 1 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update );
-
-	materialClearcoatRow.add( new UIText( strings.getKey( 'sidebar/material/clearcoat' ) ).setWidth( '90px' ) );
-	materialClearcoatRow.add( materialClearcoat );
-
-	container.add( materialClearcoatRow );
+	const materialClearcoat = new SidebarMaterialNumberProperty( editor, 'clearcoat', strings.getKey( 'sidebar/material/clearcoat' ), [ 0, 1 ] );
+	container.add( materialClearcoat );
 
 
 	// clearcoatRoughness
 	// clearcoatRoughness
 
 
-	var materialClearcoatRoughnessRow = new UIRow();
-	var materialClearcoatRoughness = new UINumber( 1 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update );
+	const materialClearcoatRoughness = new SidebarMaterialNumberProperty( editor, 'clearcoatRoughness', strings.getKey( 'sidebar/material/clearcoatroughness' ), [ 0, 1 ] );
+	container.add( materialClearcoatRoughness );
 
 
-	materialClearcoatRoughnessRow.add( new UIText( strings.getKey( 'sidebar/material/clearcoatroughness' ) ).setWidth( '90px' ) );
-	materialClearcoatRoughnessRow.add( materialClearcoatRoughness );
+	// transmission
 
 
-	container.add( materialClearcoatRoughnessRow );
+	const materialTransmission = new SidebarMaterialNumberProperty( editor, 'transmission', strings.getKey( 'sidebar/material/transmission' ), [ 0, 1 ] );
+	container.add( materialTransmission );
 
 
-	// vertex colors
+	// attenuation distance
 
 
-	var materialVertexColorsRow = new UIRow();
-	var materialVertexColors = new UICheckbox( false ).onChange( update );
+	const materialAttenuationDistance = new SidebarMaterialNumberProperty( editor, 'attenuationDistance', strings.getKey( 'sidebar/material/attenuationDistance' ) );
+	container.add( materialAttenuationDistance );
 
 
-	materialVertexColorsRow.add( new UIText( strings.getKey( 'sidebar/material/vertexcolors' ) ).setWidth( '90px' ) );
-	materialVertexColorsRow.add( materialVertexColors );
+	// attenuation tint
 
 
-	container.add( materialVertexColorsRow );
+	const materialAttenuationTint = new SidebarMaterialColorProperty( editor, 'attenuationTint', strings.getKey( 'sidebar/material/attenuationTint' ) );
+	container.add( materialAttenuationTint );
 
 
-	// vertex tangents
+	// thickness
 
 
-	var materialVertexTangentsRow = new UIRow();
-	var materialVertexTangents = new UICheckbox( false ).onChange( update );
+	const materialThickness = new SidebarMaterialNumberProperty( editor, 'thickness', strings.getKey( 'sidebar/material/thickness' ) );
+	container.add( materialThickness );
 
 
-	materialVertexTangentsRow.add( new UIText( strings.getKey( 'sidebar/material/vertextangents' ) ).setWidth( '90px' ) );
-	materialVertexTangentsRow.add( materialVertexTangents );
+	// vertex colors
 
 
-	container.add( materialVertexTangentsRow );
+	const materialVertexColors = new SidebarMaterialBooleanProperty( editor, 'vertexColors', strings.getKey( 'sidebar/material/vertexcolors' ) );
+	container.add( materialVertexColors );
 
 
 	// depth packing
 	// depth packing
 
 
-	var materialDepthPackingRow = new UIRow();
-	var materialDepthPacking = new UISelect().setOptions( {
-		[ THREE.BasicDepthPacking ]: 'BasicDepthPacking',
-		[ THREE.RGBADepthPacking ]: 'RGBADepthPacking'
-	} );
-	materialDepthPacking.onChange( update );
-
-	materialDepthPackingRow.add( new UIText( strings.getKey( 'sidebar/material/depthPacking' ) ).setWidth( '90px' ) );
-	materialDepthPackingRow.add( materialDepthPacking );
+	const materialDepthPackingOptions = {
+		[ THREE.BasicDepthPacking ]: 'Basic',
+		[ THREE.RGBADepthPacking ]: 'RGBA'
+	};
 
 
-	container.add( materialDepthPackingRow );
+	const materialDepthPacking = new SidebarMaterialConstantProperty( editor, 'depthPacking', strings.getKey( 'sidebar/material/depthPacking' ), materialDepthPackingOptions );
+	container.add( materialDepthPacking );
 
 
 	// map
 	// map
 
 
-	var materialMapRow = new UIRow();
-	var materialMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialMap = new UITexture().onChange( updateMaterial );
+	const materialMap = new SidebarMaterialMapProperty( editor, 'map', strings.getKey( 'sidebar/material/map' ) );
+	container.add( materialMap );
 
 
-	materialMapRow.add( new UIText( strings.getKey( 'sidebar/material/map' ) ).setWidth( '90px' ) );
-	materialMapRow.add( materialMapEnabled );
-	materialMapRow.add( materialMap );
+	// specular map
 
 
-	container.add( materialMapRow );
+	const materialSpecularMap = new SidebarMaterialMapProperty( editor, 'specularMap', strings.getKey( 'sidebar/material/specularmap' ) );
+	container.add( materialSpecularMap );
 
 
-	// matcap map
+	// emissive map
 
 
-	var materialMatcapMapRow = new UIRow();
-	var materialMatcapMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialMatcapMap = new UITexture().onChange( update );
+	const materialEmissiveMap = new SidebarMaterialMapProperty( editor, 'emissiveMap', strings.getKey( 'sidebar/material/emissivemap' ) );
+	container.add( materialEmissiveMap );
 
 
-	materialMatcapMapRow.add( new UIText( strings.getKey( 'sidebar/material/matcap' ) ).setWidth( '90px' ) );
-	materialMatcapMapRow.add( materialMatcapMapEnabled );
-	materialMatcapMapRow.add( materialMatcapMap );
+	// matcap map
 
 
-	container.add( materialMatcapMapRow );
+	const materialMatcapMap = new SidebarMaterialMapProperty( editor, 'matcap', strings.getKey( 'sidebar/material/matcap' ) );
+	container.add( materialMatcapMap );
 
 
 	// alpha map
 	// alpha map
 
 
-	var materialAlphaMapRow = new UIRow();
-	var materialAlphaMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialAlphaMap = new UITexture().onChange( update );
-
-	materialAlphaMapRow.add( new UIText( strings.getKey( 'sidebar/material/alphamap' ) ).setWidth( '90px' ) );
-	materialAlphaMapRow.add( materialAlphaMapEnabled );
-	materialAlphaMapRow.add( materialAlphaMap );
-
-	container.add( materialAlphaMapRow );
+	const materialAlphaMap = new SidebarMaterialMapProperty( editor, 'alphaMap', strings.getKey( 'sidebar/material/alphamap' ) );
+	container.add( materialAlphaMap );
 
 
 	// bump map
 	// bump map
 
 
-	var materialBumpMapRow = new UIRow();
-	var materialBumpMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialBumpMap = new UITexture().onChange( update );
-	var materialBumpScale = new UINumber( 1 ).setWidth( '30px' ).onChange( update );
-
-	materialBumpMapRow.add( new UIText( strings.getKey( 'sidebar/material/bumpmap' ) ).setWidth( '90px' ) );
-	materialBumpMapRow.add( materialBumpMapEnabled );
-	materialBumpMapRow.add( materialBumpMap );
-	materialBumpMapRow.add( materialBumpScale );
-
-	container.add( materialBumpMapRow );
+	const materialBumpMap = new SidebarMaterialMapProperty( editor, 'bumpMap', strings.getKey( 'sidebar/material/bumpmap' ) );
+	container.add( materialBumpMap );
 
 
 	// normal map
 	// normal map
 
 
-	var materialNormalMapRow = new UIRow();
-	var materialNormalMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialNormalMap = new UITexture().onChange( update );
-	var materialNormalScaleX = new UINumber( 1 ).setWidth( '30px' ).onChange( update );
-	var materialNormalScaleY = new UINumber( 1 ).setWidth( '30px' ).onChange( update );
-
-	materialNormalMapRow.add( new UIText( strings.getKey( 'sidebar/material/normalmap' ) ).setWidth( '90px' ) );
-	materialNormalMapRow.add( materialNormalMapEnabled );
-	materialNormalMapRow.add( materialNormalMap );
-	materialNormalMapRow.add( materialNormalScaleX );
-	materialNormalMapRow.add( materialNormalScaleY );
-
-	container.add( materialNormalMapRow );
+	const materialNormalMap = new SidebarMaterialMapProperty( editor, 'normalMap', strings.getKey( 'sidebar/material/normalmap' ) );
+	container.add( materialNormalMap );
 
 
 	// clearcoat normal map
 	// clearcoat normal map
 
 
-	var materialClearcoatNormalMapRow = new UIRow();
-	var materialClearcoatNormalMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialClearcoatNormalMap = new UITexture().onChange( update );
-	var materialClearcoatNormalScaleX = new UINumber( 1 ).setWidth( '30px' ).onChange( update );
-	var materialClearcoatNormalScaleY = new UINumber( 1 ).setWidth( '30px' ).onChange( update );
-
-	materialClearcoatNormalMapRow.add( new UIText( strings.getKey( 'sidebar/material/clearcoatnormalmap' ) ).setWidth( '90px' ) );
-	materialClearcoatNormalMapRow.add( materialClearcoatNormalMapEnabled );
-	materialClearcoatNormalMapRow.add( materialClearcoatNormalMap );
-	materialClearcoatNormalMapRow.add( materialClearcoatNormalScaleX );
-	materialClearcoatNormalMapRow.add( materialClearcoatNormalScaleY );
-
-	container.add( materialClearcoatNormalMapRow );
+	const materialClearcoatNormalMap = new SidebarMaterialMapProperty( editor, 'clearcoatNormalMap', strings.getKey( 'sidebar/material/clearcoatnormalmap' ) );
+	container.add( materialClearcoatNormalMap );
 
 
 	// displacement map
 	// displacement map
 
 
-	var materialDisplacementMapRow = new UIRow();
-	var materialDisplacementMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialDisplacementMap = new UITexture().onChange( update );
-	var materialDisplacementScale = new UINumber( 1 ).setWidth( '30px' ).onChange( update );
-
-	materialDisplacementMapRow.add( new UIText( strings.getKey( 'sidebar/material/displacemap' ) ).setWidth( '90px' ) );
-	materialDisplacementMapRow.add( materialDisplacementMapEnabled );
-	materialDisplacementMapRow.add( materialDisplacementMap );
-	materialDisplacementMapRow.add( materialDisplacementScale );
-
-	container.add( materialDisplacementMapRow );
+	const materialDisplacementMap = new SidebarMaterialMapProperty( editor, 'displacementMap', strings.getKey( 'sidebar/material/displacementmap' ) );
+	container.add( materialDisplacementMap );
 
 
 	// roughness map
 	// roughness map
 
 
-	var materialRoughnessMapRow = new UIRow();
-	var materialRoughnessMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialRoughnessMap = new UITexture().onChange( update );
-
-	materialRoughnessMapRow.add( new UIText( strings.getKey( 'sidebar/material/roughmap' ) ).setWidth( '90px' ) );
-	materialRoughnessMapRow.add( materialRoughnessMapEnabled );
-	materialRoughnessMapRow.add( materialRoughnessMap );
-
-	container.add( materialRoughnessMapRow );
+	const materialRoughnessMap = new SidebarMaterialMapProperty( editor, 'roughnessMap', strings.getKey( 'sidebar/material/roughnessmap' ) );
+	container.add( materialRoughnessMap );
 
 
 	// metalness map
 	// metalness map
 
 
-	var materialMetalnessMapRow = new UIRow();
-	var materialMetalnessMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialMetalnessMap = new UITexture().onChange( update );
-
-	materialMetalnessMapRow.add( new UIText( strings.getKey( 'sidebar/material/metalmap' ) ).setWidth( '90px' ) );
-	materialMetalnessMapRow.add( materialMetalnessMapEnabled );
-	materialMetalnessMapRow.add( materialMetalnessMap );
-
-	container.add( materialMetalnessMapRow );
-
-	// specular map
-
-	var materialSpecularMapRow = new UIRow();
-	var materialSpecularMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialSpecularMap = new UITexture().onChange( update );
-
-	materialSpecularMapRow.add( new UIText( strings.getKey( 'sidebar/material/specularmap' ) ).setWidth( '90px' ) );
-	materialSpecularMapRow.add( materialSpecularMapEnabled );
-	materialSpecularMapRow.add( materialSpecularMap );
-
-	container.add( materialSpecularMapRow );
+	const materialMetalnessMap = new SidebarMaterialMapProperty( editor, 'metalnessMap', strings.getKey( 'sidebar/material/metalnessmap' ) );
+	container.add( materialMetalnessMap );
 
 
 	// env map
 	// env map
 
 
-	var materialEnvMapRow = new UIRow();
-	var materialEnvMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialEnvMap = new UITexture( THREE.EquirectangularReflectionMapping ).onChange( updateMaterial );
-	var materialReflectivity = new UINumber( 1 ).setWidth( '30px' ).onChange( update );
-
-	materialEnvMapRow.add( new UIText( strings.getKey( 'sidebar/material/envmap' ) ).setWidth( '90px' ) );
-	materialEnvMapRow.add( materialEnvMapEnabled );
-	materialEnvMapRow.add( materialEnvMap );
-	materialEnvMapRow.add( materialReflectivity );
-
-	container.add( materialEnvMapRow );
+	const materialEnvMap = new SidebarMaterialMapProperty( editor, 'envMap', strings.getKey( 'sidebar/material/envmap' ) );
+	container.add( materialEnvMap );
 
 
 	// light map
 	// light map
 
 
-	var materialLightMapRow = new UIRow();
-	var materialLightMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialLightMap = new UITexture().onChange( update );
-
-	materialLightMapRow.add( new UIText( strings.getKey( 'sidebar/material/lightmap' ) ).setWidth( '90px' ) );
-	materialLightMapRow.add( materialLightMapEnabled );
-	materialLightMapRow.add( materialLightMap );
-
-	container.add( materialLightMapRow );
+	const materialLightMap = new SidebarMaterialMapProperty( editor, 'lightMap', strings.getKey( 'sidebar/material/lightmap' ) );
+	container.add( materialLightMap );
 
 
 	// ambient occlusion map
 	// ambient occlusion map
 
 
-	var materialAOMapRow = new UIRow();
-	var materialAOMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialAOMap = new UITexture().onChange( update );
-	var materialAOScale = new UINumber( 1 ).setRange( 0, 1 ).setWidth( '30px' ).onChange( update );
-
-	materialAOMapRow.add( new UIText( strings.getKey( 'sidebar/material/aomap' ) ).setWidth( '90px' ) );
-	materialAOMapRow.add( materialAOMapEnabled );
-	materialAOMapRow.add( materialAOMap );
-	materialAOMapRow.add( materialAOScale );
-
-	container.add( materialAOMapRow );
-
-	// emissive map
-
-	var materialEmissiveMapRow = new UIRow();
-	var materialEmissiveMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialEmissiveMap = new UITexture().onChange( updateMaterial );
-
-	materialEmissiveMapRow.add( new UIText( strings.getKey( 'sidebar/material/emissivemap' ) ).setWidth( '90px' ) );
-	materialEmissiveMapRow.add( materialEmissiveMapEnabled );
-	materialEmissiveMapRow.add( materialEmissiveMap );
-
-	container.add( materialEmissiveMapRow );
+	const materialAOMap = new SidebarMaterialMapProperty( editor, 'aoMap', strings.getKey( 'sidebar/material/aomap' ) );
+	container.add( materialAOMap );
 
 
 	// gradient map
 	// gradient map
 
 
-	var materialGradientMapRow = new UIRow();
-	var materialGradientMapEnabled = new UICheckbox( false ).onChange( update );
-	var materialGradientMap = new UITexture().onChange( update );
-
-	materialGradientMapRow.add( new UIText( strings.getKey( 'sidebar/material/gradientmap' ) ).setWidth( '90px' ) );
-	materialGradientMapRow.add( materialGradientMapEnabled );
-	materialGradientMapRow.add( materialGradientMap );
-
-	container.add( materialGradientMapRow );
+	const materialGradientMap = new SidebarMaterialMapProperty( editor, 'gradientMap', strings.getKey( 'sidebar/material/gradientmap' ) );
+	container.add( materialGradientMap );
 
 
 	// side
 	// side
 
 
-	var materialSideRow = new UIRow();
-	var materialSide = new UISelect().setOptions( {
-
-		0: strings.getKey( 'sidebar/material/side/front' ),
-		1: strings.getKey( 'sidebar/material/side/back' ),
-		2: strings.getKey( 'sidebar/material/side/double' )
-
-	} ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
-
-	materialSideRow.add( new UIText( strings.getKey( 'sidebar/material/side' ) ).setWidth( '90px' ) );
-	materialSideRow.add( materialSide );
+	const materialSideOptions = {
+		0: 'Front',
+		1: 'Back',
+		2: 'Double'
+	};
 
 
-	container.add( materialSideRow );
+	const materialSide = new SidebarMaterialConstantProperty( editor, 'side', strings.getKey( 'sidebar/material/side' ), materialSideOptions );
+	container.add( materialSide );
 
 
 	// size
 	// size
 
 
-	var materialSizeRow = new UIRow();
-	var materialSize = new UINumber( 1 ).setWidth( '60px' ).setRange( 0, Infinity ).onChange( update );
-
-	materialSizeRow.add( new UIText( strings.getKey( 'sidebar/material/size' ) ).setWidth( '90px' ) );
-	materialSizeRow.add( materialSize );
-
-	container.add( materialSizeRow );
+	const materialSize = new SidebarMaterialNumberProperty( editor, 'size', strings.getKey( 'sidebar/material/size' ), [ 0, Infinity ] );
+	container.add( materialSize );
 
 
 	// sizeAttenuation
 	// sizeAttenuation
 
 
-	var materialSizeAttenuationRow = new UIRow();
-	var materialSizeAttenuation = new UICheckbox( true ).onChange( update );
-
-	materialSizeAttenuationRow.add( new UIText( strings.getKey( 'sidebar/material/sizeAttenuation' ) ).setWidth( '90px' ) );
-	materialSizeAttenuationRow.add( materialSizeAttenuation );
-
-	container.add( materialSizeAttenuationRow );
-
-	// shading
+	const materialSizeAttenuation = new SidebarMaterialBooleanProperty( editor, 'sizeAttenuation', strings.getKey( 'sidebar/material/sizeAttenuation' ) );
+	container.add( materialSizeAttenuation );
 
 
-	var materialShadingRow = new UIRow();
-	var materialShading = new UICheckbox( false ).setLeft( '100px' ).onChange( update );
+	// flatShading
 
 
-	materialShadingRow.add( new UIText( strings.getKey( 'sidebar/material/flatshaded' ) ).setWidth( '90px' ) );
-	materialShadingRow.add( materialShading );
-
-	container.add( materialShadingRow );
+	const materialFlatShading = new SidebarMaterialBooleanProperty( editor, 'flatShading', strings.getKey( 'sidebar/material/flatShading' ) );
+	container.add( materialFlatShading );
 
 
 	// blending
 	// blending
 
 
-	var materialBlendingRow = new UIRow();
-	var materialBlending = new UISelect().setOptions( {
-
-		0: strings.getKey( 'sidebar/material/blending/no' ),
-		1: strings.getKey( 'sidebar/material/blending/normal' ),
-		2: strings.getKey( 'sidebar/material/blending/additive' ),
-		3: strings.getKey( 'sidebar/material/blending/subtractive' ),
-		4: strings.getKey( 'sidebar/material/blending/multiply' ),
-		5: strings.getKey( 'sidebar/material/blending/custom' )
-
-	} ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
-
-	materialBlendingRow.add( new UIText( strings.getKey( 'sidebar/material/blending' ) ).setWidth( '90px' ) );
-	materialBlendingRow.add( materialBlending );
+	const materialBlendingOptions = {
+		0: 'No',
+		1: 'Normal',
+		2: 'Additive',
+		3: 'Subtractive',
+		4: 'Multiply',
+		5: 'Custom'
+	};
 
 
-	container.add( materialBlendingRow );
+	const materialBlending = new SidebarMaterialConstantProperty( editor, 'blending', strings.getKey( 'sidebar/material/blending' ), materialBlendingOptions );
+	container.add( materialBlending );
 
 
 	// opacity
 	// opacity
 
 
-	var materialOpacityRow = new UIRow();
-	var materialOpacity = new UINumber( 1 ).setWidth( '60px' ).setRange( 0, 1 ).onChange( update );
-
-	materialOpacityRow.add( new UIText( strings.getKey( 'sidebar/material/opacity' ) ).setWidth( '90px' ) );
-	materialOpacityRow.add( materialOpacity );
-
-	container.add( materialOpacityRow );
+	const materialOpacity = new SidebarMaterialNumberProperty( editor, 'opacity', strings.getKey( 'sidebar/material/opacity' ), [ 0, 1 ] );
+	container.add( materialOpacity );
 
 
 	// transparent
 	// transparent
 
 
-	var materialTransparentRow = new UIRow();
-	var materialTransparent = new UICheckbox().setLeft( '100px' ).onChange( update );
-
-	materialTransparentRow.add( new UIText( strings.getKey( 'sidebar/material/transparent' ) ).setWidth( '90px' ) );
-	materialTransparentRow.add( materialTransparent );
-
-	container.add( materialTransparentRow );
+	const materialTransparent = new SidebarMaterialBooleanProperty( editor, 'transparent', strings.getKey( 'sidebar/material/transparent' ) );
+	container.add( materialTransparent );
 
 
 	// alpha test
 	// alpha test
 
 
-	var materialAlphaTestRow = new UIRow();
-	var materialAlphaTest = new UINumber().setWidth( '60px' ).setRange( 0, 1 ).onChange( update );
-
-	materialAlphaTestRow.add( new UIText( strings.getKey( 'sidebar/material/alphatest' ) ).setWidth( '90px' ) );
-	materialAlphaTestRow.add( materialAlphaTest );
-
-	container.add( materialAlphaTestRow );
+	const materialAlphaTest = new SidebarMaterialNumberProperty( editor, 'alphaTest', strings.getKey( 'sidebar/material/alphatest' ), [ 0, 1 ] );
+	container.add( materialAlphaTest );
 
 
 	// depth test
 	// depth test
 
 
-	var materialDepthTestRow = new UIRow();
-	var materialDepthTest = new UICheckbox().onChange( update );
-
-	materialDepthTestRow.add( new UIText( strings.getKey( 'sidebar/material/depthtest' ) ).setWidth( '90px' ) );
-	materialDepthTestRow.add( materialDepthTest );
-
-	container.add( materialDepthTestRow );
+	const materialDepthTest = new SidebarMaterialBooleanProperty( editor, 'depthTest', strings.getKey( 'sidebar/material/depthtest' ) );
+	container.add( materialDepthTest );
 
 
 	// depth write
 	// depth write
 
 
-	var materialDepthWriteRow = new UIRow();
-	var materialDepthWrite = new UICheckbox().onChange( update );
-
-	materialDepthWriteRow.add( new UIText( strings.getKey( 'sidebar/material/depthwrite' ) ).setWidth( '90px' ) );
-	materialDepthWriteRow.add( materialDepthWrite );
-
-	container.add( materialDepthWriteRow );
+	const materialDepthWrite = new SidebarMaterialBooleanProperty( editor, 'depthWrite', strings.getKey( 'sidebar/material/depthwrite' ) );
+	container.add( materialDepthWrite );
 
 
 	// wireframe
 	// wireframe
 
 
-	var materialWireframeRow = new UIRow();
-	var materialWireframe = new UICheckbox( false ).onChange( update );
-
-	materialWireframeRow.add( new UIText( strings.getKey( 'sidebar/material/wireframe' ) ).setWidth( '90px' ) );
-	materialWireframeRow.add( materialWireframe );
-
-	container.add( materialWireframeRow );
+	const materialWireframe = new SidebarMaterialBooleanProperty( editor, 'wireframe', strings.getKey( 'sidebar/material/wireframe' ) );
+	container.add( materialWireframe );
 
 
 	//
 	//
 
 
 	function update() {
 	function update() {
 
 
-		var object = currentObject;
-
-		var geometry = object.geometry;
-
-		var previousSelectedSlot = currentMaterialSlot;
+		const previousSelectedSlot = currentMaterialSlot;
 
 
 		currentMaterialSlot = parseInt( materialSlotSelect.getValue() );
 		currentMaterialSlot = parseInt( materialSlotSelect.getValue() );
 
 
-		if ( currentMaterialSlot !== previousSelectedSlot ) refreshUI( true );
-
-		var material = editor.getObjectMaterial( currentObject, currentMaterialSlot );
+		if ( currentMaterialSlot !== previousSelectedSlot ) refreshUI();
 
 
-		var textureWarning = false;
-		var objectHasUvs = false;
-
-		if ( object.isSprite ) objectHasUvs = true;
-		if ( geometry.isGeometry && geometry.faceVertexUvs[ 0 ].length > 0 ) objectHasUvs = true;
-		if ( geometry.isBufferGeometry && geometry.attributes.uv !== undefined ) objectHasUvs = true;
+		let material = editor.getObjectMaterial( currentObject, currentMaterialSlot );
 
 
 		if ( material ) {
 		if ( material ) {
 
 
@@ -656,1145 +362,190 @@ function SidebarMaterial( editor ) {
 
 
 			}
 			}
 
 
-			if ( material.color !== undefined && material.color.getHex() !== materialColor.getHexValue() ) {
-
-				editor.execute( new SetMaterialColorCommand( editor, currentObject, 'color', materialColor.getHexValue(), currentMaterialSlot ) );
-
-			}
-
-			if ( material.roughness !== undefined && Math.abs( material.roughness - materialRoughness.getValue() ) >= epsilon ) {
-
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'roughness', materialRoughness.getValue(), currentMaterialSlot ) );
-
-			}
-
-			if ( material.metalness !== undefined && Math.abs( material.metalness - materialMetalness.getValue() ) >= epsilon ) {
-
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'metalness', materialMetalness.getValue(), currentMaterialSlot ) );
-
-			}
-
-			/*
-			if ( material.sheen !== undefined ) {
-
-				var sheenEnabled = materialSheenEnabled.getValue() === true;
-
-				var sheen = sheenEnabled ? new Color(materialSheen.getHexValue()) : null;
-
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'sheen', sheen, currentMaterialSlot ) );
-
-			}
-
-			if ( material.sheen !== undefined && material.sheen !== null && material.sheen.getHex() !== materialSheen.getHexValue() ) {
-
-				editor.execute( new SetMaterialColorCommand( editor, currentObject, 'sheen', materialSheen.getHexValue(), currentMaterialSlot ) );
+			refreshUI();
 
 
-			}
-			*/
+		}
 
 
-			if ( material.transmission !== undefined && Math.abs( material.transmission - materialTransmission.getValue() ) >= epsilon ) {
+	}
 
 
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'transmission', materialTransmission.getValue(), currentMaterialSlot ) );
+	//
 
 
-			}
+	function setRowVisibility() {
 
 
-			if ( material.emissive !== undefined && material.emissive.getHex() !== materialEmissive.getHexValue() ) {
+		const material = currentObject.material;
 
 
-				editor.execute( new SetMaterialColorCommand( editor, currentObject, 'emissive', materialEmissive.getHexValue(), currentMaterialSlot ) );
+		if ( Array.isArray( material ) ) {
 
 
-			}
+			materialSlotRow.setDisplay( '' );
 
 
-			if ( material.emissiveIntensity !== undefined && material.emissiveIntensity !== materialEmissiveIntensity.getValue() ) {
+			if ( material.length === 0 ) return;
 
 
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'emissiveIntensity', materialEmissiveIntensity.getValue(), currentMaterialSlot ) );
+			material = material[ currentMaterialSlot ];
 
 
-			}
+		} else {
 
 
-			if ( material.specular !== undefined && material.specular.getHex() !== materialSpecular.getHexValue() ) {
+			materialSlotRow.setDisplay( 'none' );
 
 
-				editor.execute( new SetMaterialColorCommand( editor, currentObject, 'specular', materialSpecular.getHexValue(), currentMaterialSlot ) );
+		}
 
 
-			}
+	}
 
 
-			if ( material.shininess !== undefined && Math.abs( material.shininess - materialShininess.getValue() ) >= epsilon ) {
+	function refreshUI() {
 
 
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'shininess', materialShininess.getValue(), currentMaterialSlot ) );
+		if ( ! currentObject ) return;
 
 
-			}
+		let material = currentObject.material;
 
 
-			if ( material.clearcoat !== undefined && Math.abs( material.clearcoat - materialClearcoat.getValue() ) >= epsilon ) {
+		if ( Array.isArray( material ) ) {
 
 
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'clearcoat', materialClearcoat.getValue(), currentMaterialSlot ) );
+			const slotOptions = {};
 
 
-			}
+			currentMaterialSlot = Math.max( 0, Math.min( material.length, currentMaterialSlot ) );
 
 
-			if ( material.clearcoatRoughness !== undefined && Math.abs( material.clearcoatRoughness - materialClearcoatRoughness.getValue() ) >= epsilon ) {
+			for ( let i = 0; i < material.length; i ++ ) {
 
 
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'clearcoatRoughness', materialClearcoatRoughness.getValue(), currentMaterialSlot ) );
+				slotOptions[ i ] = String( i + 1 ) + ': ' + material[ i ].name;
 
 
 			}
 			}
 
 
-			if ( material.vertexColors !== undefined ) {
-
-				var vertexColors = materialVertexColors.getValue();
-
-				if ( material.vertexColors !== vertexColors ) {
+			materialSlotSelect.setOptions( slotOptions ).setValue( currentMaterialSlot );
 
 
-					editor.execute( new SetMaterialValueCommand( editor, currentObject, 'vertexColors', vertexColors, currentMaterialSlot ) );
+		}
 
 
-				}
+		material = editor.getObjectMaterial( currentObject, currentMaterialSlot );
 
 
-			}
+		if ( material.uuid !== undefined ) {
 
 
-			if ( material.depthPacking !== undefined ) {
+			materialUUID.setValue( material.uuid );
 
 
-				var depthPacking = parseInt( materialDepthPacking.getValue() );
-				if ( material.depthPacking !== depthPacking ) {
+		}
 
 
-					editor.execute( new SetMaterialValueCommand( editor, currentObject, 'depthPacking', depthPacking, currentMaterialSlot ) );
+		if ( material.name !== undefined ) {
 
 
-				}
+			materialName.setValue( material.name );
 
 
-			}
+		}
 
 
-			if ( material.map !== undefined ) {
+		if ( currentObject.isMesh ) {
 
 
-				var mapEnabled = materialMapEnabled.getValue() === true;
+			materialClass.setOptions( meshMaterialOptions );
 
 
-				if ( objectHasUvs ) {
+		} else if ( currentObject.isSprite ) {
 
 
-					var map = mapEnabled ? materialMap.getValue() : null;
-					if ( material.map !== map ) {
+			materialClass.setOptions( spriteMaterialOptions );
 
 
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'map', map, currentMaterialSlot ) );
+		} else if ( currentObject.isPoints ) {
 
 
-					}
+			materialClass.setOptions( pointsMaterialOptions );
 
 
-				} else {
+		} else if ( currentObject.isLine ) {
 
 
-					if ( mapEnabled ) textureWarning = true;
+			materialClass.setOptions( lineMaterialOptions );
 
 
-				}
+		}
 
 
-			}
+		materialClass.setValue( material.type );
 
 
-			if ( material.matcap !== undefined ) {
+		setRowVisibility();
 
 
-				var mapEnabled = materialMatcapMapEnabled.getValue() === true;
+	}
 
 
-				if ( objectHasUvs ) {
+	// events
 
 
-					var matcap = mapEnabled ? materialMatcapMap.getValue() : null;
-					if ( material.matcap !== matcap ) {
+	signals.objectSelected.add( function ( object ) {
 
 
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'matcap', matcap, currentMaterialSlot ) );
+		let hasMaterial = false;
 
 
-					}
+		if ( object && object.material ) {
 
 
-				} else {
+			hasMaterial = true;
 
 
-					if ( mapEnabled ) textureWarning = true;
+			if ( Array.isArray( object.material ) && object.material.length === 0 ) {
 
 
-				}
+				hasMaterial = false;
 
 
 			}
 			}
 
 
-			if ( material.alphaMap !== undefined ) {
-
-				var mapEnabled = materialAlphaMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var alphaMap = mapEnabled ? materialAlphaMap.getValue() : null;
-					if ( material.alphaMap !== alphaMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'alphaMap', alphaMap, currentMaterialSlot ) );
-
-					}
-
-				} else {
+		}
 
 
-					if ( mapEnabled ) textureWarning = true;
+		if ( hasMaterial ) {
 
 
-				}
+			currentObject = object;
+			refreshUI();
+			container.setDisplay( '' );
 
 
-			}
+		} else {
 
 
-			if ( material.bumpMap !== undefined ) {
+			currentObject = null;
+			container.setDisplay( 'none' );
 
 
-				var bumpMapEnabled = materialBumpMapEnabled.getValue() === true;
+		}
 
 
-				if ( objectHasUvs ) {
+	} );
 
 
-					var bumpMap = bumpMapEnabled ? materialBumpMap.getValue() : null;
-					if ( material.bumpMap !== bumpMap ) {
+	signals.materialChanged.add( refreshUI );
 
 
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'bumpMap', bumpMap, currentMaterialSlot ) );
+	return container;
 
 
-					}
+}
 
 
-					if ( material.bumpScale !== materialBumpScale.getValue() ) {
+const materialClasses = {
+	'LineBasicMaterial': THREE.LineBasicMaterial,
+	'LineDashedMaterial': THREE.LineDashedMaterial,
+	'MeshBasicMaterial': THREE.MeshBasicMaterial,
+	'MeshDepthMaterial': THREE.MeshDepthMaterial,
+	'MeshNormalMaterial': THREE.MeshNormalMaterial,
+	'MeshLambertMaterial': THREE.MeshLambertMaterial,
+	'MeshMatcapMaterial': THREE.MeshMatcapMaterial,
+	'MeshPhongMaterial': THREE.MeshPhongMaterial,
+	'MeshToonMaterial': THREE.MeshToonMaterial,
+	'MeshStandardMaterial': THREE.MeshStandardMaterial,
+	'MeshPhysicalMaterial': THREE.MeshPhysicalMaterial,
+	'RawShaderMaterial': THREE.RawShaderMaterial,
+	'ShaderMaterial': THREE.ShaderMaterial,
+	'ShadowMaterial': THREE.ShadowMaterial,
+	'SpriteMaterial': THREE.SpriteMaterial,
+	'PointsMaterial': THREE.PointsMaterial
+};
 
 
-						editor.execute( new SetMaterialValueCommand( editor, currentObject, 'bumpScale', materialBumpScale.getValue(), currentMaterialSlot ) );
+const vertexShaderVariables = [
+	'uniform mat4 projectionMatrix;',
+	'uniform mat4 modelViewMatrix;\n',
+	'attribute vec3 position;\n\n',
+].join( '\n' );
+
+const meshMaterialOptions = {
+	'MeshBasicMaterial': 'MeshBasicMaterial',
+	'MeshDepthMaterial': 'MeshDepthMaterial',
+	'MeshNormalMaterial': 'MeshNormalMaterial',
+	'MeshLambertMaterial': 'MeshLambertMaterial',
+	'MeshMatcapMaterial': 'MeshMatcapMaterial',
+	'MeshPhongMaterial': 'MeshPhongMaterial',
+	'MeshToonMaterial': 'MeshToonMaterial',
+	'MeshStandardMaterial': 'MeshStandardMaterial',
+	'MeshPhysicalMaterial': 'MeshPhysicalMaterial',
+	'RawShaderMaterial': 'RawShaderMaterial',
+	'ShaderMaterial': 'ShaderMaterial',
+	'ShadowMaterial': 'ShadowMaterial'
+};
 
 
-					}
+const lineMaterialOptions = {
+	'LineBasicMaterial': 'LineBasicMaterial',
+	'LineDashedMaterial': 'LineDashedMaterial',
+	'RawShaderMaterial': 'RawShaderMaterial',
+	'ShaderMaterial': 'ShaderMaterial'
+};
 
 
-				} else {
+const spriteMaterialOptions = {
+	'SpriteMaterial': 'SpriteMaterial',
+	'RawShaderMaterial': 'RawShaderMaterial',
+	'ShaderMaterial': 'ShaderMaterial'
+};
 
 
-					if ( bumpMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.normalMap !== undefined ) {
-
-				var normalMapEnabled = materialNormalMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var normalMap = normalMapEnabled ? materialNormalMap.getValue() : null;
-					if ( material.normalMap !== normalMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'normalMap', normalMap, currentMaterialSlot ) );
-
-					}
-
-					if ( material.normalScale.x !== materialNormalScaleX.getValue() ||
-						material.normalScale.y !== materialNormalScaleY.getValue() ) {
-
-						var value = [
-							materialNormalScaleX.getValue(),
-							materialNormalScaleY.getValue()
-						];
-						editor.execute( new SetMaterialVectorCommand( editor, currentObject, 'normalScale', value, currentMaterialSlot ) );
-
-					}
-
-				} else {
-
-					if ( normalMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.clearcoatNormalMap !== undefined ) {
-
-				var clearcoatNormalMapEnabled = materialClearcoatNormalMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var clearcoatNormalMap = clearcoatNormalMapEnabled ? materialClearcoatNormalMap.getValue() : null;
-
-					if ( material.clearcoatNormalMap !== clearcoatNormalMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'clearcoatNormalMap', clearcoatNormalMap, currentMaterialSlot ) );
-
-					}
-
-					if ( material.clearcoatNormalScale.x !== materialClearcoatNormalScaleX.getValue() ||
-						material.clearcoatNormalScale.y !== materialClearcoatNormalScaleY.getValue() ) {
-
-						var value = [
-							materialClearcoatNormalScaleX.getValue(),
-							materialClearcoatNormalScaleY.getValue()
-						];
-						editor.execute( new SetMaterialVectorCommand( editor, currentObject, 'clearcoatNormalScale', value, currentMaterialSlot ) );
-
-					}
-
-				} else {
-
-					if ( clearcoatNormalMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.displacementMap !== undefined ) {
-
-				var displacementMapEnabled = materialDisplacementMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var displacementMap = displacementMapEnabled ? materialDisplacementMap.getValue() : null;
-					if ( material.displacementMap !== displacementMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'displacementMap', displacementMap, currentMaterialSlot ) );
-
-					}
-
-					if ( material.displacementScale !== materialDisplacementScale.getValue() ) {
-
-						editor.execute( new SetMaterialValueCommand( editor, currentObject, 'displacementScale', materialDisplacementScale.getValue(), currentMaterialSlot ) );
-
-					}
-
-				} else {
-
-					if ( displacementMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.roughnessMap !== undefined ) {
-
-				var roughnessMapEnabled = materialRoughnessMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var roughnessMap = roughnessMapEnabled ? materialRoughnessMap.getValue() : null;
-					if ( material.roughnessMap !== roughnessMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'roughnessMap', roughnessMap, currentMaterialSlot ) );
-
-					}
-
-				} else {
-
-					if ( roughnessMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.metalnessMap !== undefined ) {
-
-				var metalnessMapEnabled = materialMetalnessMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var metalnessMap = metalnessMapEnabled ? materialMetalnessMap.getValue() : null;
-					if ( material.metalnessMap !== metalnessMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'metalnessMap', metalnessMap, currentMaterialSlot ) );
-
-					}
-
-				} else {
-
-					if ( metalnessMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.specularMap !== undefined ) {
-
-				var specularMapEnabled = materialSpecularMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var specularMap = specularMapEnabled ? materialSpecularMap.getValue() : null;
-					if ( material.specularMap !== specularMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'specularMap', specularMap, currentMaterialSlot ) );
-
-					}
-
-				} else {
-
-					if ( specularMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.envMap !== undefined ) {
-
-				var envMapEnabled = materialEnvMapEnabled.getValue() === true;
-
-				var envMap = envMapEnabled ? materialEnvMap.getValue() : null;
-
-				if ( material.envMap !== envMap ) {
-
-					editor.execute( new SetMaterialMapCommand( editor, currentObject, 'envMap', envMap, currentMaterialSlot ) );
-
-				}
-
-			}
-
-			if ( material.reflectivity !== undefined ) {
-
-				var reflectivity = materialReflectivity.getValue();
-
-				if ( material.reflectivity !== reflectivity ) {
-
-					editor.execute( new SetMaterialValueCommand( editor, currentObject, 'reflectivity', reflectivity, currentMaterialSlot ) );
-
-				}
-
-			}
-
-			if ( material.lightMap !== undefined ) {
-
-				var lightMapEnabled = materialLightMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var lightMap = lightMapEnabled ? materialLightMap.getValue() : null;
-					if ( material.lightMap !== lightMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'lightMap', lightMap, currentMaterialSlot ) );
-
-					}
-
-				} else {
-
-					if ( lightMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.aoMap !== undefined ) {
-
-				var aoMapEnabled = materialAOMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var aoMap = aoMapEnabled ? materialAOMap.getValue() : null;
-					if ( material.aoMap !== aoMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'aoMap', aoMap, currentMaterialSlot ) );
-
-					}
-
-					if ( material.aoMapIntensity !== materialAOScale.getValue() ) {
-
-						editor.execute( new SetMaterialValueCommand( editor, currentObject, 'aoMapIntensity', materialAOScale.getValue(), currentMaterialSlot ) );
-
-					}
-
-				} else {
-
-					if ( aoMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.emissiveMap !== undefined ) {
-
-				var emissiveMapEnabled = materialEmissiveMapEnabled.getValue() === true;
-
-				if ( objectHasUvs ) {
-
-					var emissiveMap = emissiveMapEnabled ? materialEmissiveMap.getValue() : null;
-					if ( material.emissiveMap !== emissiveMap ) {
-
-						editor.execute( new SetMaterialMapCommand( editor, currentObject, 'emissiveMap', emissiveMap, currentMaterialSlot ) );
-
-					}
-
-				} else {
-
-					if ( emissiveMapEnabled ) textureWarning = true;
-
-				}
-
-			}
-
-			if ( material.gradientMap !== undefined ) {
-
-				var gradientMapEnabled = materialGradientMapEnabled.getValue() === true;
-
-				var gradientMap = gradientMapEnabled ? materialGradientMap.getValue() : null;
-
-				if ( material.gradientMap !== gradientMap ) {
-
-					editor.execute( new SetMaterialMapCommand( editor, currentObject, 'gradientMap', gradientMap, currentMaterialSlot ) );
-
-				}
-
-			}
-
-			if ( material.side !== undefined ) {
-
-				var side = parseInt( materialSide.getValue() );
-				if ( material.side !== side ) {
-
-					editor.execute( new SetMaterialValueCommand( editor, currentObject, 'side', side, currentMaterialSlot ) );
-
-				}
-
-
-			}
-
-			if ( material.size !== undefined ) {
-
-				var size = materialSize.getValue();
-				if ( material.size !== size ) {
-
-					editor.execute( new SetMaterialValueCommand( editor, currentObject, 'size', size, currentMaterialSlot ) );
-
-				}
-
-			}
-
-			if ( material.sizeAttenuation !== undefined ) {
-
-				var sizeAttenuation = materialSizeAttenuation.getValue();
-				if ( material.sizeAttenuation !== sizeAttenuation ) {
-
-					editor.execute( new SetMaterialValueCommand( editor, currentObject, 'sizeAttenuation', sizeAttenuation, currentMaterialSlot ) );
-
-				}
-
-			}
-
-			if ( material.flatShading !== undefined ) {
-
-				var flatShading = materialShading.getValue();
-				if ( material.flatShading != flatShading ) {
-
-					editor.execute( new SetMaterialValueCommand( editor, currentObject, 'flatShading', flatShading, currentMaterialSlot ) );
-
-				}
-
-			}
-
-			if ( material.blending !== undefined ) {
-
-				var blending = parseInt( materialBlending.getValue() );
-				if ( material.blending !== blending ) {
-
-					editor.execute( new SetMaterialValueCommand( editor, currentObject, 'blending', blending, currentMaterialSlot ) );
-
-				}
-
-			}
-
-			if ( material.opacity !== undefined && Math.abs( material.opacity - materialOpacity.getValue() ) >= epsilon ) {
-
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'opacity', materialOpacity.getValue(), currentMaterialSlot ) );
-
-			}
-
-			if ( material.transparent !== undefined && material.transparent !== materialTransparent.getValue() ) {
-
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'transparent', materialTransparent.getValue(), currentMaterialSlot ) );
-
-			}
-
-			if ( material.alphaTest !== undefined && Math.abs( material.alphaTest - materialAlphaTest.getValue() ) >= epsilon ) {
-
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'alphaTest', materialAlphaTest.getValue(), currentMaterialSlot ) );
-
-			}
-
-			if ( material.depthTest !== undefined && material.depthTest !== materialDepthTest.getValue() ) {
-
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'depthTest', materialDepthTest.getValue(), currentMaterialSlot ) );
-
-			}
-
-			if ( material.depthWrite !== undefined && material.depthWrite !== materialDepthWrite.getValue() ) {
-
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'depthWrite', materialDepthWrite.getValue(), currentMaterialSlot ) );
-
-			}
-
-			if ( material.wireframe !== undefined && material.wireframe !== materialWireframe.getValue() ) {
-
-				editor.execute( new SetMaterialValueCommand( editor, currentObject, 'wireframe', materialWireframe.getValue(), currentMaterialSlot ) );
-
-			}
-
-			refreshUI();
-
-		}
-
-		if ( textureWarning ) {
-
-			console.warn( 'Can\'t set texture, model doesn\'t have texture coordinates' );
-
-		}
-
-	}
-
-	function updateMaterial( texture ) {
-
-		if ( texture !== null ) {
-
-			if ( texture.isDataTexture !== true && texture.encoding !== THREE.sRGBEncoding ) {
-
-				texture.encoding = THREE.sRGBEncoding;
-				var object = currentObject;
-				if ( object !== null ) {
-
-					object.material.needsUpdate = true;
-
-				}
-
-			}
-
-		}
-
-		update();
-
-	}
-
-	//
-
-	function setRowVisibility() {
-
-		var properties = {
-			'name': materialNameRow,
-			'color': materialColorRow,
-			'roughness': materialRoughnessRow,
-			'metalness': materialMetalnessRow,
-			'emissive': materialEmissiveRow,
-			// 'sheen': materialSheenRow,
-			'transmission': materialTransmissionRow,
-			'specular': materialSpecularRow,
-			'shininess': materialShininessRow,
-			'clearcoat': materialClearcoatRow,
-			'clearcoatRoughness': materialClearcoatRoughnessRow,
-			'vertexShader': materialProgramRow,
-			'vertexColors': materialVertexColorsRow,
-			'vertexTangents': materialVertexTangentsRow,
-			'depthPacking': materialDepthPackingRow,
-			'map': materialMapRow,
-			'matcap': materialMatcapMapRow,
-			'alphaMap': materialAlphaMapRow,
-			'bumpMap': materialBumpMapRow,
-			'normalMap': materialNormalMapRow,
-			'clearcoatNormalMap': materialClearcoatNormalMapRow,
-			'displacementMap': materialDisplacementMapRow,
-			'roughnessMap': materialRoughnessMapRow,
-			'metalnessMap': materialMetalnessMapRow,
-			'specularMap': materialSpecularMapRow,
-			'envMap': materialEnvMapRow,
-			'lightMap': materialLightMapRow,
-			'aoMap': materialAOMapRow,
-			'emissiveMap': materialEmissiveMapRow,
-			'gradientMap': materialGradientMapRow,
-			'side': materialSideRow,
-			'size': materialSizeRow,
-			'sizeAttenuation': materialSizeAttenuationRow,
-			'flatShading': materialShadingRow,
-			'blending': materialBlendingRow,
-			'opacity': materialOpacityRow,
-			'transparent': materialTransparentRow,
-			'alphaTest': materialAlphaTestRow,
-			'depthTest': materialDepthTestRow,
-			'depthWrite': materialDepthWriteRow,
-			'wireframe': materialWireframeRow
-		};
-
-		var material = currentObject.material;
-
-		if ( Array.isArray( material ) ) {
-
-			materialSlotRow.setDisplay( '' );
-
-			if ( material.length === 0 ) return;
-
-			material = material[ currentMaterialSlot ];
-
-		} else {
-
-			materialSlotRow.setDisplay( 'none' );
-
-		}
-
-		for ( var property in properties ) {
-
-			properties[ property ].setDisplay( material[ property ] !== undefined ? '' : 'none' );
-
-		}
-
-	}
-
-
-	function refreshUI( resetTextureSelectors ) {
-
-		if ( ! currentObject ) return;
-
-		var material = currentObject.material;
-
-		if ( Array.isArray( material ) ) {
-
-			var slotOptions = {};
-
-			currentMaterialSlot = Math.max( 0, Math.min( material.length, currentMaterialSlot ) );
-
-			for ( var i = 0; i < material.length; i ++ ) {
-
-				slotOptions[ i ] = String( i + 1 ) + ': ' + material[ i ].name;
-
-			}
-
-			materialSlotSelect.setOptions( slotOptions ).setValue( currentMaterialSlot );
-
-		}
-
-		material = editor.getObjectMaterial( currentObject, currentMaterialSlot );
-
-		if ( material.uuid !== undefined ) {
-
-			materialUUID.setValue( material.uuid );
-
-		}
-
-		if ( material.name !== undefined ) {
-
-			materialName.setValue( material.name );
-
-		}
-
-		if ( currentObject.isMesh ) {
-
-			materialClass.setOptions( meshMaterialOptions );
-
-		} else if ( currentObject.isSprite ) {
-
-			materialClass.setOptions( spriteMaterialOptions );
-
-		} else if ( currentObject.isPoints ) {
-
-			materialClass.setOptions( pointsMaterialOptions );
-
-		} else if ( currentObject.isLine ) {
-
-			materialClass.setOptions( lineMaterialOptions );
-
-		}
-
-		materialClass.setValue( material.type );
-
-
-		if ( material.color !== undefined ) {
-
-			materialColor.setHexValue( material.color.getHexString() );
-
-		}
-
-		if ( material.roughness !== undefined ) {
-
-			materialRoughness.setValue( material.roughness );
-
-		}
-
-		if ( material.metalness !== undefined ) {
-
-			materialMetalness.setValue( material.metalness );
-
-		}
-
-		/*
-		if ( material.sheen !== undefined && material.sheen !== null ) {
-
-			materialSheenEnabled.setValue( true );
-			materialSheen.setHexValue( material.sheen.getHexString() );
-
-		}
-		*/
-
-		if ( material.transmission !== undefined ) {
-
-			materialTransmission.setValue( material.transmission );
-
-		}
-
-		if ( material.emissive !== undefined ) {
-
-			materialEmissive.setHexValue( material.emissive.getHexString() );
-
-			materialEmissiveIntensity.setValue( material.emissiveIntensity );
-
-		}
-
-		if ( material.specular !== undefined ) {
-
-			materialSpecular.setHexValue( material.specular.getHexString() );
-
-		}
-
-		if ( material.shininess !== undefined ) {
-
-			materialShininess.setValue( material.shininess );
-
-		}
-
-		if ( material.clearcoat !== undefined ) {
-
-			materialClearcoat.setValue( material.clearcoat );
-
-		}
-
-		if ( material.clearcoatRoughness !== undefined ) {
-
-			materialClearcoatRoughness.setValue( material.clearcoatRoughness );
-
-		}
-
-		if ( material.vertexColors !== undefined ) {
-
-			materialVertexColors.setValue( material.vertexColors );
-
-		}
-
-		if ( material.depthPacking !== undefined ) {
-
-			materialDepthPacking.setValue( material.depthPacking );
-
-		}
-
-		if ( material.map !== undefined ) {
-
-			materialMapEnabled.setValue( material.map !== null );
-
-			if ( material.map !== null || resetTextureSelectors ) {
-
-				materialMap.setValue( material.map );
-
-			}
-
-		}
-
-		if ( material.matcap !== undefined ) {
-
-			materialMatcapMapEnabled.setValue( material.matcap !== null );
-
-			if ( material.matcap !== null || resetTextureSelectors ) {
-
-				materialMatcapMap.setValue( material.matcap );
-
-			}
-
-		}
-
-		if ( material.alphaMap !== undefined ) {
-
-			materialAlphaMapEnabled.setValue( material.alphaMap !== null );
-
-			if ( material.alphaMap !== null || resetTextureSelectors ) {
-
-				materialAlphaMap.setValue( material.alphaMap );
-
-			}
-
-		}
-
-		if ( material.bumpMap !== undefined ) {
-
-			materialBumpMapEnabled.setValue( material.bumpMap !== null );
-
-			if ( material.bumpMap !== null || resetTextureSelectors ) {
-
-				materialBumpMap.setValue( material.bumpMap );
-
-			}
-
-			materialBumpScale.setValue( material.bumpScale );
-
-		}
-
-		if ( material.normalMap !== undefined ) {
-
-			materialNormalMapEnabled.setValue( material.normalMap !== null );
-
-			if ( material.normalMap !== null || resetTextureSelectors ) {
-
-				materialNormalMap.setValue( material.normalMap );
-
-			}
-
-			materialNormalScaleX.setValue( material.normalScale.x );
-			materialNormalScaleY.setValue( material.normalScale.y );
-
-		}
-
-		if ( material.clearcoatNormalMap !== undefined ) {
-
-			materialClearcoatNormalMapEnabled.setValue( material.clearcoatNormalMap !== null );
-
-			if ( material.clearcoatNormalMap !== null || resetTextureSelectors ) {
-
-				materialClearcoatNormalMap.setValue( material.clearcoatNormalMap );
-
-			}
-
-			materialClearcoatNormalScaleX.setValue( material.clearcoatNormalScale.x );
-			materialClearcoatNormalScaleY.setValue( material.clearcoatNormalScale.y );
-
-		}
-
-		if ( material.displacementMap !== undefined ) {
-
-			materialDisplacementMapEnabled.setValue( material.displacementMap !== null );
-
-			if ( material.displacementMap !== null || resetTextureSelectors ) {
-
-				materialDisplacementMap.setValue( material.displacementMap );
-
-			}
-
-			materialDisplacementScale.setValue( material.displacementScale );
-
-		}
-
-		if ( material.roughnessMap !== undefined ) {
-
-			materialRoughnessMapEnabled.setValue( material.roughnessMap !== null );
-
-			if ( material.roughnessMap !== null || resetTextureSelectors ) {
-
-				materialRoughnessMap.setValue( material.roughnessMap );
-
-			}
-
-		}
-
-		if ( material.metalnessMap !== undefined ) {
-
-			materialMetalnessMapEnabled.setValue( material.metalnessMap !== null );
-
-			if ( material.metalnessMap !== null || resetTextureSelectors ) {
-
-				materialMetalnessMap.setValue( material.metalnessMap );
-
-			}
-
-		}
-
-		if ( material.specularMap !== undefined ) {
-
-			materialSpecularMapEnabled.setValue( material.specularMap !== null );
-
-			if ( material.specularMap !== null || resetTextureSelectors ) {
-
-				materialSpecularMap.setValue( material.specularMap );
-
-			}
-
-		}
-
-		if ( material.envMap !== undefined ) {
-
-			materialEnvMapEnabled.setValue( material.envMap !== null );
-
-			if ( material.envMap !== null || resetTextureSelectors ) {
-
-				materialEnvMap.setValue( material.envMap );
-
-			}
-
-		}
-
-		if ( material.gradientMap !== undefined ) {
-
-			materialGradientMapEnabled.setValue( material.gradientMap !== null );
-
-			if ( material.gradientMap !== null || resetTextureSelectors ) {
-
-				materialGradientMap.setValue( material.gradientMap );
-
-			}
-
-		}
-
-		if ( material.reflectivity !== undefined ) {
-
-			materialReflectivity.setValue( material.reflectivity );
-
-		}
-
-		if ( material.lightMap !== undefined ) {
-
-			materialLightMapEnabled.setValue( material.lightMap !== null );
-
-			if ( material.lightMap !== null || resetTextureSelectors ) {
-
-				materialLightMap.setValue( material.lightMap );
-
-			}
-
-		}
-
-		if ( material.aoMap !== undefined ) {
-
-			materialAOMapEnabled.setValue( material.aoMap !== null );
-
-			if ( material.aoMap !== null || resetTextureSelectors ) {
-
-				materialAOMap.setValue( material.aoMap );
-
-			}
-
-			materialAOScale.setValue( material.aoMapIntensity );
-
-		}
-
-		if ( material.emissiveMap !== undefined ) {
-
-			materialEmissiveMapEnabled.setValue( material.emissiveMap !== null );
-
-			if ( material.emissiveMap !== null || resetTextureSelectors ) {
-
-				materialEmissiveMap.setValue( material.emissiveMap );
-
-			}
-
-		}
-
-		if ( material.side !== undefined ) {
-
-			materialSide.setValue( material.side );
-
-		}
-
-		if ( material.size !== undefined ) {
-
-			materialSize.setValue( material.size );
-
-		}
-
-		if ( material.sizeAttenuation !== undefined ) {
-
-			materialSizeAttenuation.setValue( material.sizeAttenuation );
-
-		}
-
-		if ( material.flatShading !== undefined ) {
-
-			materialShading.setValue( material.flatShading );
-
-		}
-
-		if ( material.blending !== undefined ) {
-
-			materialBlending.setValue( material.blending );
-
-		}
-
-		if ( material.opacity !== undefined ) {
-
-			materialOpacity.setValue( material.opacity );
-
-		}
-
-		if ( material.transparent !== undefined ) {
-
-			materialTransparent.setValue( material.transparent );
-
-		}
-
-		if ( material.alphaTest !== undefined ) {
-
-			materialAlphaTest.setValue( material.alphaTest );
-
-		}
-
-		if ( material.depthTest !== undefined ) {
-
-			materialDepthTest.setValue( material.depthTest );
-
-		}
-
-		if ( material.depthWrite !== undefined ) {
-
-			materialDepthWrite.setValue( material.depthWrite );
-
-		}
-
-		if ( material.wireframe !== undefined ) {
-
-			materialWireframe.setValue( material.wireframe );
-
-		}
-
-		setRowVisibility();
-
-	}
-
-	// events
-
-	signals.objectSelected.add( function ( object ) {
-
-		var hasMaterial = false;
-
-		if ( object && object.material ) {
-
-			hasMaterial = true;
-
-			if ( Array.isArray( object.material ) && object.material.length === 0 ) {
-
-				hasMaterial = false;
-
-			}
-
-		}
-
-		if ( hasMaterial ) {
-
-			var objectChanged = object !== currentObject;
-
-			currentObject = object;
-			refreshUI( objectChanged );
-			container.setDisplay( '' );
-
-		} else {
-
-			currentObject = null;
-			container.setDisplay( 'none' );
-
-		}
-
-	} );
-
-	signals.materialChanged.add( function () {
-
-		refreshUI();
-
-	} );
-
-	var vertexShaderVariables = [
-		'uniform mat4 projectionMatrix;',
-		'uniform mat4 modelViewMatrix;\n',
-		'attribute vec3 position;\n\n',
-	].join( '\n' );
-
-	var meshMaterialOptions = {
-		'MeshBasicMaterial': 'MeshBasicMaterial',
-		'MeshDepthMaterial': 'MeshDepthMaterial',
-		'MeshNormalMaterial': 'MeshNormalMaterial',
-		'MeshLambertMaterial': 'MeshLambertMaterial',
-		'MeshMatcapMaterial': 'MeshMatcapMaterial',
-		'MeshPhongMaterial': 'MeshPhongMaterial',
-		'MeshToonMaterial': 'MeshToonMaterial',
-		'MeshStandardMaterial': 'MeshStandardMaterial',
-		'MeshPhysicalMaterial': 'MeshPhysicalMaterial',
-		'RawShaderMaterial': 'RawShaderMaterial',
-		'ShaderMaterial': 'ShaderMaterial',
-		'ShadowMaterial': 'ShadowMaterial'
-	};
-
-	var lineMaterialOptions = {
-		'LineBasicMaterial': 'LineBasicMaterial',
-		'LineDashedMaterial': 'LineDashedMaterial',
-		'RawShaderMaterial': 'RawShaderMaterial',
-		'ShaderMaterial': 'ShaderMaterial'
-	};
-
-	var spriteMaterialOptions = {
-		'SpriteMaterial': 'SpriteMaterial',
-		'RawShaderMaterial': 'RawShaderMaterial',
-		'ShaderMaterial': 'ShaderMaterial'
-	};
-
-	var pointsMaterialOptions = {
-		'PointsMaterial': 'PointsMaterial',
-		'RawShaderMaterial': 'RawShaderMaterial',
-		'ShaderMaterial': 'ShaderMaterial'
-	};
-
-	return container;
-
-}
+const pointsMaterialOptions = {
+	'PointsMaterial': 'PointsMaterial',
+	'RawShaderMaterial': 'RawShaderMaterial',
+	'ShaderMaterial': 'ShaderMaterial'
+};
 
 
 export { SidebarMaterial };
 export { SidebarMaterial };

+ 7 - 1
editor/js/Sidebar.Scene.js

@@ -402,7 +402,12 @@ function SidebarScene( editor ) {
 
 
 		if ( scene.environment ) {
 		if ( scene.environment ) {
 
 
-			// TODO
+			if ( scene.environment.mapping === THREE.EquirectangularReflectionMapping ) {
+
+				environmentType.setValue( 'Equirectangular' );
+				environmentEquirectangularTexture.setValue( scene.environment );
+
+			}
 
 
 		} else {
 		} else {
 
 
@@ -434,6 +439,7 @@ function SidebarScene( editor ) {
 		}
 		}
 
 
 		refreshBackgroundUI();
 		refreshBackgroundUI();
+		refreshEnvironmentUI();
 		refreshFogUI();
 		refreshFogUI();
 
 
 	}
 	}

+ 30 - 48
editor/js/Strings.js

@@ -78,6 +78,7 @@ function Strings( config ) {
 			'menubar/help/source_code': 'Source Code',
 			'menubar/help/source_code': 'Source Code',
 			'menubar/help/icons': 'Icon Pack',
 			'menubar/help/icons': 'Icon Pack',
 			'menubar/help/about': 'About',
 			'menubar/help/about': 'About',
+			'menubar/help/manual': 'Manual',
 
 
 			'sidebar/animations': 'Animations',
 			'sidebar/animations': 'Animations',
 			'sidebar/animations/play': 'Play',
 			'sidebar/animations/play': 'Play',
@@ -242,24 +243,26 @@ function Strings( config ) {
 			'sidebar/material/depthPacking': 'Depth Packing',
 			'sidebar/material/depthPacking': 'Depth Packing',
 			'sidebar/material/roughness': 'Roughness',
 			'sidebar/material/roughness': 'Roughness',
 			'sidebar/material/metalness': 'Metalness',
 			'sidebar/material/metalness': 'Metalness',
-			'sidebar/material/sheen': 'Sheen',
-			'sidebar/material/transmission': 'Transmission',
+			'sidebar/material/reflectivity': 'Reflectivity',
 			'sidebar/material/emissive': 'Emissive',
 			'sidebar/material/emissive': 'Emissive',
 			'sidebar/material/specular': 'Specular',
 			'sidebar/material/specular': 'Specular',
 			'sidebar/material/shininess': 'Shininess',
 			'sidebar/material/shininess': 'Shininess',
 			'sidebar/material/clearcoat': 'Clearcoat',
 			'sidebar/material/clearcoat': 'Clearcoat',
 			'sidebar/material/clearcoatroughness': 'Clearcoat Roughness',
 			'sidebar/material/clearcoatroughness': 'Clearcoat Roughness',
+			'sidebar/material/transmission': 'Transmission',
+			'sidebar/material/attenuationDistance': 'Attenuation Distance',
+			'sidebar/material/attenuationTint': 'Attenuation Tint',
+			'sidebar/material/thickness': 'Thickness',
 			'sidebar/material/vertexcolors': 'Vertex Colors',
 			'sidebar/material/vertexcolors': 'Vertex Colors',
-			'sidebar/material/vertextangents': 'Vertex Tangents',
 			'sidebar/material/matcap': 'Matcap',
 			'sidebar/material/matcap': 'Matcap',
 			'sidebar/material/map': 'Map',
 			'sidebar/material/map': 'Map',
 			'sidebar/material/alphamap': 'Alpha Map',
 			'sidebar/material/alphamap': 'Alpha Map',
 			'sidebar/material/bumpmap': 'Bump Map',
 			'sidebar/material/bumpmap': 'Bump Map',
 			'sidebar/material/normalmap': 'Normal Map',
 			'sidebar/material/normalmap': 'Normal Map',
 			'sidebar/material/clearcoatnormalmap': 'Clearcoat Normal Map',
 			'sidebar/material/clearcoatnormalmap': 'Clearcoat Normal Map',
-			'sidebar/material/displacemap': 'Displace Map',
-			'sidebar/material/roughmap': 'Rough. Map',
-			'sidebar/material/metalmap': 'Metal. Map',
+			'sidebar/material/displacementmap': 'Displace Map',
+			'sidebar/material/roughnessmap': 'Rough. Map',
+			'sidebar/material/metalnessmap': 'Metal. Map',
 			'sidebar/material/specularmap': 'Specular Map',
 			'sidebar/material/specularmap': 'Specular Map',
 			'sidebar/material/envmap': 'Env Map',
 			'sidebar/material/envmap': 'Env Map',
 			'sidebar/material/lightmap': 'Light Map',
 			'sidebar/material/lightmap': 'Light Map',
@@ -267,19 +270,10 @@ function Strings( config ) {
 			'sidebar/material/emissivemap': 'Emissive Map',
 			'sidebar/material/emissivemap': 'Emissive Map',
 			'sidebar/material/gradientmap': 'Gradient Map',
 			'sidebar/material/gradientmap': 'Gradient Map',
 			'sidebar/material/side': 'Side',
 			'sidebar/material/side': 'Side',
-			'sidebar/material/side/front': 'Front',
-			'sidebar/material/side/back': 'Back',
-			'sidebar/material/side/double': 'Double',
 			'sidebar/material/size': 'Size',
 			'sidebar/material/size': 'Size',
 			'sidebar/material/sizeAttenuation': 'Size Attenuation',
 			'sidebar/material/sizeAttenuation': 'Size Attenuation',
-			'sidebar/material/flatshaded': 'Flat Shaded',
+			'sidebar/material/flatShading': 'Flat Shading',
 			'sidebar/material/blending': 'Blending',
 			'sidebar/material/blending': 'Blending',
-			'sidebar/material/blending/no': 'No',
-			'sidebar/material/blending/normal': 'Normal',
-			'sidebar/material/blending/additive': 'Additive',
-			'sidebar/material/blending/subtractive': 'Subtractive',
-			'sidebar/material/blending/multiply': 'Multiply',
-			'sidebar/material/blending/custom': 'Custom',
 			'sidebar/material/opacity': 'Opacity',
 			'sidebar/material/opacity': 'Opacity',
 			'sidebar/material/transparent': 'Transparent',
 			'sidebar/material/transparent': 'Transparent',
 			'sidebar/material/alphatest': 'Alpha Test',
 			'sidebar/material/alphatest': 'Alpha Test',
@@ -412,6 +406,7 @@ function Strings( config ) {
 			'menubar/help/source_code': 'Code Source',
 			'menubar/help/source_code': 'Code Source',
 			'menubar/help/icons': 'Icon Pack',
 			'menubar/help/icons': 'Icon Pack',
 			'menubar/help/about': 'A propos',
 			'menubar/help/about': 'A propos',
+			'menubar/help/manual': 'Manual',
 
 
 			'sidebar/animations': 'Animations',
 			'sidebar/animations': 'Animations',
 			'sidebar/animations/play': 'Play',
 			'sidebar/animations/play': 'Play',
@@ -576,24 +571,26 @@ function Strings( config ) {
 			'sidebar/material/depthPacking': 'Encodage profondeur de couleur',
 			'sidebar/material/depthPacking': 'Encodage profondeur de couleur',
 			'sidebar/material/roughness': 'Rugosité',
 			'sidebar/material/roughness': 'Rugosité',
 			'sidebar/material/metalness': 'Métal',
 			'sidebar/material/metalness': 'Métal',
-			'sidebar/material/sheen': 'Éclat',
-			'sidebar/material/transmission': 'Transmission',
+			'sidebar/material/reflectivity': 'Reflectivity',
 			'sidebar/material/emissive': 'Émissif',
 			'sidebar/material/emissive': 'Émissif',
 			'sidebar/material/specular': 'Spéculaire',
 			'sidebar/material/specular': 'Spéculaire',
 			'sidebar/material/shininess': 'Brillance',
 			'sidebar/material/shininess': 'Brillance',
 			'sidebar/material/clearcoat': 'Vernis',
 			'sidebar/material/clearcoat': 'Vernis',
 			'sidebar/material/clearcoatroughness': 'Rugosité du vernis',
 			'sidebar/material/clearcoatroughness': 'Rugosité du vernis',
+			'sidebar/material/transmission': 'Transmission',
+			'sidebar/material/attenuationDistance': 'Attenuation Distance',
+			'sidebar/material/attenuationTint': 'Attenuation Tint',
+			'sidebar/material/thickness': 'Thickness',
 			'sidebar/material/vertexcolors': 'Couleurs aux Sommets',
 			'sidebar/material/vertexcolors': 'Couleurs aux Sommets',
-			'sidebar/material/vertextangents': 'Tangentes aux sommets',
 			'sidebar/material/matcap': 'Matcap',
 			'sidebar/material/matcap': 'Matcap',
 			'sidebar/material/map': 'Texture',
 			'sidebar/material/map': 'Texture',
 			'sidebar/material/alphamap': 'Texture de transparence',
 			'sidebar/material/alphamap': 'Texture de transparence',
 			'sidebar/material/bumpmap': 'Texture de relief',
 			'sidebar/material/bumpmap': 'Texture de relief',
 			'sidebar/material/normalmap': 'Texture de normales',
 			'sidebar/material/normalmap': 'Texture de normales',
 			'sidebar/material/clearcoatnormalmap': 'Texture des normales du vernis',
 			'sidebar/material/clearcoatnormalmap': 'Texture des normales du vernis',
-			'sidebar/material/displacemap': 'Texture de déplacement',
-			'sidebar/material/roughmap': 'Texture de rugosité',
-			'sidebar/material/metalmap': 'Texture métallique',
+			'sidebar/material/displacementmap': 'Texture de déplacement',
+			'sidebar/material/roughnessmap': 'Texture de rugosité',
+			'sidebar/material/metalnessmap': 'Texture métallique',
 			'sidebar/material/specularmap': 'Texture spéculaire',
 			'sidebar/material/specularmap': 'Texture spéculaire',
 			'sidebar/material/envmap': 'Texture d\'environnement',
 			'sidebar/material/envmap': 'Texture d\'environnement',
 			'sidebar/material/lightmap': 'Texture d\'éclairage',
 			'sidebar/material/lightmap': 'Texture d\'éclairage',
@@ -601,19 +598,10 @@ function Strings( config ) {
 			'sidebar/material/emissivemap': 'Texture d\'émission',
 			'sidebar/material/emissivemap': 'Texture d\'émission',
 			'sidebar/material/gradientmap': 'Texture de gradient',
 			'sidebar/material/gradientmap': 'Texture de gradient',
 			'sidebar/material/side': 'Côté',
 			'sidebar/material/side': 'Côté',
-			'sidebar/material/side/front': 'Face avant',
-			'sidebar/material/side/back': 'Face Arrière',
-			'sidebar/material/side/double': 'Double face',
 			'sidebar/material/size': 'Size',
 			'sidebar/material/size': 'Size',
 			'sidebar/material/sizeAttenuation': 'Size Attenuation',
 			'sidebar/material/sizeAttenuation': 'Size Attenuation',
-			'sidebar/material/flatshaded': 'Rendu plat',
+			'sidebar/material/flatShading': 'Flat Shading',
 			'sidebar/material/blending': 'Mélange',
 			'sidebar/material/blending': 'Mélange',
-			'sidebar/material/blending/no': 'Non',
-			'sidebar/material/blending/normal': 'Normal',
-			'sidebar/material/blending/additive': 'Ajouter',
-			'sidebar/material/blending/subtractive': 'Soustraire',
-			'sidebar/material/blending/multiply': 'Multiplier',
-			'sidebar/material/blending/custom': 'Personnaliser',
 			'sidebar/material/opacity': 'Opacité',
 			'sidebar/material/opacity': 'Opacité',
 			'sidebar/material/transparent': 'Transparence',
 			'sidebar/material/transparent': 'Transparence',
 			'sidebar/material/alphatest': 'Test de transparence',
 			'sidebar/material/alphatest': 'Test de transparence',
@@ -746,6 +734,7 @@ function Strings( config ) {
 			'menubar/help/source_code': '源码',
 			'menubar/help/source_code': '源码',
 			'menubar/help/icons': '图标组件包',
 			'menubar/help/icons': '图标组件包',
 			'menubar/help/about': '关于',
 			'menubar/help/about': '关于',
+			'menubar/help/manual': 'Manual',
 
 
 			'sidebar/animations': '动画',
 			'sidebar/animations': '动画',
 			'sidebar/animations/play': '播放',
 			'sidebar/animations/play': '播放',
@@ -910,24 +899,26 @@ function Strings( config ) {
 			'sidebar/material/depthPacking': '深度包装',
 			'sidebar/material/depthPacking': '深度包装',
 			'sidebar/material/roughness': '粗糙度',
 			'sidebar/material/roughness': '粗糙度',
 			'sidebar/material/metalness': '金属度',
 			'sidebar/material/metalness': '金属度',
-			'sidebar/material/sheen': '光泽',
-			'sidebar/material/transmission': '透射',
+			'sidebar/material/reflectivity': 'Reflectivity',
 			'sidebar/material/emissive': '自发光',
 			'sidebar/material/emissive': '自发光',
 			'sidebar/material/specular': '高光',
 			'sidebar/material/specular': '高光',
 			'sidebar/material/shininess': '高光大小',
 			'sidebar/material/shininess': '高光大小',
 			'sidebar/material/clearcoat': '清漆',
 			'sidebar/material/clearcoat': '清漆',
 			'sidebar/material/clearcoatroughness': '清漆粗糙度',
 			'sidebar/material/clearcoatroughness': '清漆粗糙度',
+			'sidebar/material/transmission': 'Transmission',
+			'sidebar/material/attenuationDistance': 'Attenuation Distance',
+			'sidebar/material/attenuationTint': 'Attenuation Tint',
+			'sidebar/material/thickness': 'Thickness',
 			'sidebar/material/vertexcolors': '顶点颜色',
 			'sidebar/material/vertexcolors': '顶点颜色',
-			'sidebar/material/vertextangents': '顶点切线',
 			'sidebar/material/matcap': '材质捕获',
 			'sidebar/material/matcap': '材质捕获',
 			'sidebar/material/map': '贴图',
 			'sidebar/material/map': '贴图',
 			'sidebar/material/alphamap': '透明贴图',
 			'sidebar/material/alphamap': '透明贴图',
 			'sidebar/material/bumpmap': '凹凸贴图',
 			'sidebar/material/bumpmap': '凹凸贴图',
 			'sidebar/material/normalmap': '法线贴图',
 			'sidebar/material/normalmap': '法线贴图',
 			'sidebar/material/clearcoatnormalmap': '清漆法线贴图',
 			'sidebar/material/clearcoatnormalmap': '清漆法线贴图',
-			'sidebar/material/displacemap': '置换贴图',
-			'sidebar/material/roughmap': '粗糙贴图',
-			'sidebar/material/metalmap': '金属贴图',
+			'sidebar/material/displacementmap': '置换贴图',
+			'sidebar/material/roughnessmap': '粗糙贴图',
+			'sidebar/material/metalnessmap': '金属贴图',
 			'sidebar/material/specularmap': '高光贴图',
 			'sidebar/material/specularmap': '高光贴图',
 			'sidebar/material/envmap': '环境贴图',
 			'sidebar/material/envmap': '环境贴图',
 			'sidebar/material/lightmap': '光照贴图',
 			'sidebar/material/lightmap': '光照贴图',
@@ -935,19 +926,10 @@ function Strings( config ) {
 			'sidebar/material/emissivemap': '自发光贴图',
 			'sidebar/material/emissivemap': '自发光贴图',
 			'sidebar/material/gradientmap': '渐变贴图',
 			'sidebar/material/gradientmap': '渐变贴图',
 			'sidebar/material/side': '面',
 			'sidebar/material/side': '面',
-			'sidebar/material/side/front': '正面',
-			'sidebar/material/side/back': '背面',
-			'sidebar/material/side/double': '双面',
 			'sidebar/material/size': '大小',
 			'sidebar/material/size': '大小',
 			'sidebar/material/sizeAttenuation': '大小衰减',
 			'sidebar/material/sizeAttenuation': '大小衰减',
-			'sidebar/material/flatshaded': '平面着色',
+			'sidebar/material/flatShading': 'Flat Shading',
 			'sidebar/material/blending': '混合',
 			'sidebar/material/blending': '混合',
-			'sidebar/material/blending/no': '无',
-			'sidebar/material/blending/normal': '正常混合',
-			'sidebar/material/blending/additive': '和混合',
-			'sidebar/material/blending/subtractive': '差混合',
-			'sidebar/material/blending/multiply': '积混合',
-			'sidebar/material/blending/custom': '自定义混合',
 			'sidebar/material/opacity': '透明度',
 			'sidebar/material/opacity': '透明度',
 			'sidebar/material/transparent': '透明性',
 			'sidebar/material/transparent': '透明性',
 			'sidebar/material/alphatest': 'α测试',
 			'sidebar/material/alphatest': 'α测试',

+ 4 - 2
editor/js/Viewport.js

@@ -175,7 +175,8 @@ function Viewport( editor ) {
 
 
 		raycaster.setFromCamera( mouse, camera );
 		raycaster.setFromCamera( mouse, camera );
 
 
-		return raycaster.intersectObjects( objects );
+		return raycaster.intersectObjects( objects )
+			.filter( intersect => intersect.object.visible === true );
 
 
 	}
 	}
 
 
@@ -596,7 +597,8 @@ function Viewport( editor ) {
 
 
 				if ( environmentEquirectangularTexture ) {
 				if ( environmentEquirectangularTexture ) {
 
 
-					scene.environment = pmremGenerator.fromEquirectangular( environmentEquirectangularTexture ).texture;
+					environmentEquirectangularTexture.mapping = THREE.EquirectangularReflectionMapping;
+					scene.environment = environmentEquirectangularTexture;
 
 
 				}
 				}
 
 

+ 1 - 1
editor/js/libs/ui.three.js

@@ -56,7 +56,7 @@ class UITexture extends UISpan {
 
 
 					// assuming RGBE/Radiance HDR iamge format
 					// assuming RGBE/Radiance HDR iamge format
 
 
-					const loader = new RGBELoader().setDataType( THREE.UnsignedByteType );
+					const loader = new RGBELoader().setDataType( THREE.FloatType );
 					loader.load( event.target.result, function ( hdrTexture ) {
 					loader.load( event.target.result, function ( hdrTexture ) {
 
 
 						hdrTexture.sourceFile = file.name;
 						hdrTexture.sourceFile = file.name;

+ 7 - 1
editor/sw.js

@@ -1,4 +1,4 @@
-// r130.1
+// r131
 
 
 const cacheName = 'threejs-editor';
 const cacheName = 'threejs-editor';
 
 
@@ -175,6 +175,12 @@ const assets = [
 	'./js/Sidebar.Geometry.TubeGeometry.js',
 	'./js/Sidebar.Geometry.TubeGeometry.js',
 	'./js/Sidebar.Geometry.TeapotGeometry.js',
 	'./js/Sidebar.Geometry.TeapotGeometry.js',
 	'./js/Sidebar.Material.js',
 	'./js/Sidebar.Material.js',
+	'./js/Sidebar.Material.BooleanProperty.js',
+	'./js/Sidebar.Material.ColorProperty.js',
+	'./js/Sidebar.Material.ConstantProperty.js',
+	'./js/Sidebar.Material.MapProperty.js',
+	'./js/Sidebar.Material.NumberProperty.js',
+	'./js/Sidebar.Material.Program.js',
 	'./js/Sidebar.Animation.js',
 	'./js/Sidebar.Animation.js',
 	'./js/Sidebar.Script.js',
 	'./js/Sidebar.Script.js',
 	'./js/Strings.js',
 	'./js/Strings.js',

+ 14 - 6
examples/js/controls/OrbitControls.js

@@ -111,6 +111,12 @@
 
 
 			};
 			};
 
 
+			this.getDistance = function () {
+
+				return this.object.position.distanceTo( this.target );
+
+			};
+
 			this.listenToKeyEvents = function ( domElement ) {
 			this.listenToKeyEvents = function ( domElement ) {
 
 
 				domElement.addEventListener( 'keydown', onKeyDown );
 				domElement.addEventListener( 'keydown', onKeyDown );
@@ -258,8 +264,8 @@
 				scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
 				scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
 				scope.domElement.removeEventListener( 'pointercancel', onPointerCancel );
 				scope.domElement.removeEventListener( 'pointercancel', onPointerCancel );
 				scope.domElement.removeEventListener( 'wheel', onMouseWheel );
 				scope.domElement.removeEventListener( 'wheel', onMouseWheel );
-				scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
-				scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
+				scope.domElement.removeEventListener( 'pointermove', onPointerMove );
+				scope.domElement.removeEventListener( 'pointerup', onPointerUp );
 
 
 				if ( scope._domElementKeyEvents !== null ) {
 				if ( scope._domElementKeyEvents !== null ) {
 
 
@@ -704,8 +710,9 @@
 
 
 				if ( pointers.length === 0 ) {
 				if ( pointers.length === 0 ) {
 
 
-					scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
-					scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
+					scope.domElement.setPointerCapture( event.pointerId );
+					scope.domElement.addEventListener( 'pointermove', onPointerMove );
+					scope.domElement.addEventListener( 'pointerup', onPointerUp );
 
 
 				} //
 				} //
 
 
@@ -758,8 +765,9 @@
 
 
 				if ( pointers.length === 0 ) {
 				if ( pointers.length === 0 ) {
 
 
-					scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
-					scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
+					scope.domElement.releasePointerCapture( event.pointerId );
+					scope.domElement.removeEventListener( 'pointermove', onPointerMove );
+					scope.domElement.removeEventListener( 'pointerup', onPointerUp );
 
 
 				}
 				}
 
 

+ 17 - 8
examples/js/controls/TrackballControls.js

@@ -389,8 +389,9 @@
 
 
 				if ( _pointers.length === 0 ) {
 				if ( _pointers.length === 0 ) {
 
 
-					scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
-					scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
+					scope.domElement.setPointerCapture( event.pointerId );
+					scope.domElement.addEventListener( 'pointermove', onPointerMove );
+					scope.domElement.addEventListener( 'pointerup', onPointerUp );
 
 
 				} //
 				} //
 
 
@@ -444,8 +445,9 @@
 
 
 				if ( _pointers.length === 0 ) {
 				if ( _pointers.length === 0 ) {
 
 
-					scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
-					scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
+					scope.domElement.releasePointerCapture( event.pointerId );
+					scope.domElement.removeEventListener( 'pointermove', onPointerMove );
+					scope.domElement.removeEventListener( 'pointerup', onPointerUp );
 
 
 				}
 				}
 
 
@@ -537,8 +539,6 @@
 
 
 				}
 				}
 
 
-				scope.domElement.ownerDocument.addEventListener( 'pointermove', onPointerMove );
-				scope.domElement.ownerDocument.addEventListener( 'pointerup', onPointerUp );
 				scope.dispatchEvent( _startEvent );
 				scope.dispatchEvent( _startEvent );
 
 
 			}
 			}
@@ -568,8 +568,6 @@
 			function onMouseUp() {
 			function onMouseUp() {
 
 
 				_state = STATE.NONE;
 				_state = STATE.NONE;
-				scope.domElement.ownerDocument.removeEventListener( 'pointermove', onPointerMove );
-				scope.domElement.ownerDocument.removeEventListener( 'pointerup', onPointerUp );
 				scope.dispatchEvent( _endEvent );
 				scope.dispatchEvent( _endEvent );
 
 
 			}
 			}
@@ -687,6 +685,15 @@
 
 
 						break;
 						break;
 
 
+					case 2:
+						_state = STATE.TOUCH_ZOOM_PAN;
+
+						_moveCurr.copy( getMouseOnCircle( event.pageX - _movePrev.pageX, event.pageY - _movePrev.pageY ) );
+
+						_movePrev.copy( _moveCurr );
+
+						break;
+
 				}
 				}
 
 
 				scope.dispatchEvent( _endEvent );
 				scope.dispatchEvent( _endEvent );
@@ -752,6 +759,8 @@
 				scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
 				scope.domElement.removeEventListener( 'pointerdown', onPointerDown );
 				scope.domElement.removeEventListener( 'pointercancel', onPointerCancel );
 				scope.domElement.removeEventListener( 'pointercancel', onPointerCancel );
 				scope.domElement.removeEventListener( 'wheel', onMouseWheel );
 				scope.domElement.removeEventListener( 'wheel', onMouseWheel );
+				scope.domElement.removeEventListener( 'pointermove', onPointerMove );
+				scope.domElement.removeEventListener( 'pointerup', onPointerUp );
 				window.removeEventListener( 'keydown', keydown );
 				window.removeEventListener( 'keydown', keydown );
 				window.removeEventListener( 'keyup', keyup );
 				window.removeEventListener( 'keyup', keyup );
 
 

+ 13 - 5
examples/js/controls/TransformControls.js

@@ -149,7 +149,7 @@
 			this._onPointerUp = onPointerUp.bind( this );
 			this._onPointerUp = onPointerUp.bind( this );
 			this.domElement.addEventListener( 'pointerdown', this._onPointerDown );
 			this.domElement.addEventListener( 'pointerdown', this._onPointerDown );
 			this.domElement.addEventListener( 'pointermove', this._onPointerHover );
 			this.domElement.addEventListener( 'pointermove', this._onPointerHover );
-			this.domElement.ownerDocument.addEventListener( 'pointerup', this._onPointerUp );
+			this.domElement.addEventListener( 'pointerup', this._onPointerUp );
 
 
 		} // updateMatrixWorld  updates key transformation variables
 		} // updateMatrixWorld  updates key transformation variables
 
 
@@ -523,8 +523,8 @@
 
 
 			this.domElement.removeEventListener( 'pointerdown', this._onPointerDown );
 			this.domElement.removeEventListener( 'pointerdown', this._onPointerDown );
 			this.domElement.removeEventListener( 'pointermove', this._onPointerHover );
 			this.domElement.removeEventListener( 'pointermove', this._onPointerHover );
-			this.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove );
-			this.domElement.ownerDocument.removeEventListener( 'pointerup', this._onPointerUp );
+			this.domElement.removeEventListener( 'pointermove', this._onPointerMove );
+			this.domElement.removeEventListener( 'pointerup', this._onPointerUp );
 			this.traverse( function ( child ) {
 			this.traverse( function ( child ) {
 
 
 				if ( child.geometry ) child.geometry.dispose();
 				if ( child.geometry ) child.geometry.dispose();
@@ -551,6 +551,12 @@
 			this.axis = null;
 			this.axis = null;
 			return this;
 			return this;
 
 
+		}
+
+		getRaycaster() {
+
+			return _raycaster;
+
 		} // TODO: deprecate
 		} // TODO: deprecate
 
 
 
 
@@ -647,7 +653,8 @@
 	function onPointerDown( event ) {
 	function onPointerDown( event ) {
 
 
 		if ( ! this.enabled ) return;
 		if ( ! this.enabled ) return;
-		this.domElement.ownerDocument.addEventListener( 'pointermove', this._onPointerMove );
+		this.domElement.setPointerCapture( event.pointerId );
+		this.domElement.addEventListener( 'pointermove', this._onPointerMove );
 		this.pointerHover( this._getPointer( event ) );
 		this.pointerHover( this._getPointer( event ) );
 		this.pointerDown( this._getPointer( event ) );
 		this.pointerDown( this._getPointer( event ) );
 
 
@@ -663,7 +670,8 @@
 	function onPointerUp( event ) {
 	function onPointerUp( event ) {
 
 
 		if ( ! this.enabled ) return;
 		if ( ! this.enabled ) return;
-		this.domElement.ownerDocument.removeEventListener( 'pointermove', this._onPointerMove );
+		this.domElement.releasePointerCapture( event.pointerId );
+		this.domElement.removeEventListener( 'pointermove', this._onPointerMove );
 		this.pointerUp( this._getPointer( event ) );
 		this.pointerUp( this._getPointer( event ) );
 
 
 	}
 	}

+ 0 - 2
examples/js/effects/OutlineEffect.js

@@ -243,8 +243,6 @@
 
 
 				if ( material.name === 'invisible' ) return;
 				if ( material.name === 'invisible' ) return;
 				const outlineParameters = originalMaterial.userData.outlineParameters;
 				const outlineParameters = originalMaterial.userData.outlineParameters;
-				material.morphTargets = originalMaterial.morphTargets;
-				material.morphNormals = originalMaterial.morphNormals;
 				material.fog = originalMaterial.fog;
 				material.fog = originalMaterial.fog;
 				material.toneMapped = originalMaterial.toneMapped;
 				material.toneMapped = originalMaterial.toneMapped;
 				material.premultipliedAlpha = originalMaterial.premultipliedAlpha;
 				material.premultipliedAlpha = originalMaterial.premultipliedAlpha;

+ 26 - 2
examples/js/exporters/ColladaExporter.js

@@ -19,9 +19,33 @@
 			options = Object.assign( {
 			options = Object.assign( {
 				version: '1.4.1',
 				version: '1.4.1',
 				author: null,
 				author: null,
-				textureDirectory: ''
+				textureDirectory: '',
+				upAxis: 'Y_UP',
+				unitName: null,
+				unitMeter: null
 			}, options );
 			}, options );
 
 
+			if ( options.upAxis.match( /^[XYZ]_UP$/ ) === null ) {
+
+				console.error( 'ColladaExporter: Invalid upAxis: valid values are X_UP, Y_UP or Z_UP.' );
+				return null;
+
+			}
+
+			if ( options.unitName !== null && options.unitMeter === null ) {
+
+				console.error( 'ColladaExporter: unitMeter needs to be specified if unitName is specified.' );
+				return null;
+
+			}
+
+			if ( options.unitMeter !== null && options.unitName === null ) {
+
+				console.error( 'ColladaExporter: unitName needs to be specified if unitMeter is specified.' );
+				return null;
+
+			}
+
 			if ( options.textureDirectory !== '' ) {
 			if ( options.textureDirectory !== '' ) {
 
 
 				options.textureDirectory = `${options.textureDirectory}/`.replace( /\\/g, '/' ).replace( /\/+/g, '/' );
 				options.textureDirectory = `${options.textureDirectory}/`.replace( /\\/g, '/' ).replace( /\/+/g, '/' );
@@ -437,7 +461,7 @@
 			const libraryMaterials = [];
 			const libraryMaterials = [];
 			const libraryVisualScenes = processObject( object );
 			const libraryVisualScenes = processObject( object );
 			const specLink = version === '1.4.1' ? 'http://www.collada.org/2005/11/COLLADASchema' : 'https://www.khronos.org/collada/';
 			const specLink = version === '1.4.1' ? 'http://www.collada.org/2005/11/COLLADASchema' : 'https://www.khronos.org/collada/';
-			let dae = '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>' + `<COLLADA xmlns="${specLink}" version="${version}">` + '<asset>' + ( '<contributor>' + '<authoring_tool>three.js Collada Exporter</authoring_tool>' + ( options.author !== null ? `<author>${options.author}</author>` : '' ) + '</contributor>' + `<created>${new Date().toISOString()}</created>` + `<modified>${new Date().toISOString()}</modified>` + '<up_axis>Y_UP</up_axis>' ) + '</asset>';
+			let dae = '<?xml version="1.0" encoding="UTF-8" standalone="no" ?>' + `<COLLADA xmlns="${specLink}" version="${version}">` + '<asset>' + ( '<contributor>' + '<authoring_tool>three.js Collada Exporter</authoring_tool>' + ( options.author !== null ? `<author>${options.author}</author>` : '' ) + '</contributor>' + `<created>${new Date().toISOString()}</created>` + `<modified>${new Date().toISOString()}</modified>` + ( options.unitName !== null ? `<unit name="${options.unitName}" meter="${options.unitMeter}" />` : '' ) + `<up_axis>${options.upAxis}</up_axis>` ) + '</asset>';
 			dae += `<library_images>${libraryImages.join( '' )}</library_images>`;
 			dae += `<library_images>${libraryImages.join( '' )}</library_images>`;
 			dae += `<library_effects>${libraryEffects.join( '' )}</library_effects>`;
 			dae += `<library_effects>${libraryEffects.join( '' )}</library_effects>`;
 			dae += `<library_materials>${libraryMaterials.join( '' )}</library_materials>`;
 			dae += `<library_materials>${libraryMaterials.join( '' )}</library_materials>`;

+ 97 - 7
examples/js/exporters/GLTFExporter.js

@@ -20,6 +20,16 @@
 				return new GLTFMaterialsPBRSpecularGlossiness( writer );
 				return new GLTFMaterialsPBRSpecularGlossiness( writer );
 
 
 			} );
 			} );
+			this.register( function ( writer ) {
+
+				return new GLTFMaterialsTransmissionExtension( writer );
+
+			} );
+			this.register( function ( writer ) {
+
+				return new GLTFMaterialsVolumeExtension( writer );
+
+			} );
 
 
 		}
 		}
 
 
@@ -1126,14 +1136,10 @@
 					index: this.processTexture( material.normalMap )
 					index: this.processTexture( material.normalMap )
 				};
 				};
 
 
-				if ( material.normalScale && material.normalScale.x !== - 1 ) {
-
-					if ( material.normalScale.x !== material.normalScale.y ) {
-
-						console.warn( 'THREE.GLTFExporter: Normal scale components are different, ignoring Y and exporting X.' );
-
-					}
+				if ( material.normalScale && material.normalScale.x !== 1 ) {
 
 
+					// glTF normal scale is univariate. Ignore `y`, which may be flipped.
+					// Context: https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995
 					normalMapDef.scale = material.normalScale.x;
 					normalMapDef.scale = material.normalScale.x;
 
 
 				}
 				}
@@ -2060,6 +2066,90 @@
 
 
 		}
 		}
 
 
+	}
+	/**
+ * Transmission Materials Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_transmission
+ */
+
+
+	class GLTFMaterialsTransmissionExtension {
+
+		constructor( writer ) {
+
+			this.writer = writer;
+			this.name = 'KHR_materials_transmission';
+
+		}
+
+		writeMaterial( material, materialDef ) {
+
+			if ( ! material.isMeshPhysicalMaterial || material.transmission === 0 ) return;
+			const writer = this.writer;
+			const extensionsUsed = writer.extensionsUsed;
+			const extensionDef = {};
+			extensionDef.transmissionFactor = material.transmission;
+
+			if ( material.transmissionMap ) {
+
+				const transmissionMapDef = {
+					index: writer.processTexture( material.transmissionMap )
+				};
+				writer.applyTextureTransform( transmissionMapDef, material.transmissionMap );
+				extensionDef.transmissionTexture = transmissionMapDef;
+
+			}
+
+			materialDef.extensions = materialDef.extensions || {};
+			materialDef.extensions[ this.name ] = extensionDef;
+			extensionsUsed[ this.name ] = true;
+
+		}
+
+	}
+	/**
+ * Materials Volume Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_volume
+ */
+
+
+	class GLTFMaterialsVolumeExtension {
+
+		constructor( writer ) {
+
+			this.writer = writer;
+			this.name = 'KHR_materials_volume';
+
+		}
+
+		writeMaterial( material, materialDef ) {
+
+			if ( ! material.isMeshPhysicalMaterial || material.thickness === 0 ) return;
+			const writer = this.writer;
+			const extensionsUsed = writer.extensionsUsed;
+			const extensionDef = {};
+			extensionDef.thicknessFactor = material.thickness;
+
+			if ( material.thicknessMap ) {
+
+				const thicknessMapDef = {
+					index: writer.processTexture( material.thicknessMap )
+				};
+				writer.applyTextureTransform( thicknessMapDef, material.thicknessMap );
+				extensionDef.thicknessTexture = thicknessMapDef;
+
+			}
+
+			extensionDef.attenuationDistance = material.attenuationDistance;
+			extensionDef.attenuationColor = material.attenuationTint.toArray();
+			materialDef.extensions = materialDef.extensions || {};
+			materialDef.extensions[ this.name ] = extensionDef;
+			extensionsUsed[ this.name ] = true;
+
+		}
+
 	}
 	}
 	/**
 	/**
  * Static utility functions
  * Static utility functions

+ 2 - 2
examples/js/exporters/USDZExporter.js

@@ -396,7 +396,7 @@ ${array.join( '' )}
 
 
 		}
 		}
 
 
-		if ( material.roughnessMap !== null ) {
+		if ( material.roughnessMap !== null && material.roughness === 1 ) {
 
 
 			inputs.push( `${pad}float inputs:roughness.connect = </Materials/Material_${material.id}/Texture_${material.roughnessMap.id}_roughness.outputs:g>` );
 			inputs.push( `${pad}float inputs:roughness.connect = </Materials/Material_${material.id}/Texture_${material.roughnessMap.id}_roughness.outputs:g>` );
 			samplers.push( buildTexture( material.roughnessMap, 'roughness' ) );
 			samplers.push( buildTexture( material.roughnessMap, 'roughness' ) );
@@ -407,7 +407,7 @@ ${array.join( '' )}
 
 
 		}
 		}
 
 
-		if ( material.metalnessMap !== null ) {
+		if ( material.metalnessMap !== null && material.metalness === 1 ) {
 
 
 			inputs.push( `${pad}float inputs:metallic.connect = </Materials/Material_${material.id}/Texture_${material.metalnessMap.id}_metallic.outputs:b>` );
 			inputs.push( `${pad}float inputs:metallic.connect = </Materials/Material_${material.id}/Texture_${material.metalnessMap.id}_metallic.outputs:b>` );
 			samplers.push( buildTexture( material.metalnessMap, 'metallic' ) );
 			samplers.push( buildTexture( material.metalnessMap, 'metallic' ) );

+ 19 - 6
examples/js/interactive/HTMLMesh.js

@@ -57,6 +57,8 @@
 	} //
 	} //
 
 
 
 
+	const canvases = new WeakMap();
+
 	function html2canvas( element ) {
 	function html2canvas( element ) {
 
 
 		var range = document.createRange();
 		var range = document.createRange();
@@ -233,14 +235,25 @@
 
 
 		}
 		}
 
 
-		var offset = element.getBoundingClientRect();
-		var canvas = document.createElement( 'canvas' );
-		canvas.width = offset.width;
-		canvas.height = offset.height;
-		var context = canvas.getContext( '2d'
+		const offset = element.getBoundingClientRect();
+		let canvas;
+
+		if ( canvases.has( element ) ) {
+
+			canvas = canvases.get( element );
+
+		} else {
+
+			canvas = document.createElement( 'canvas' );
+			canvas.width = offset.width;
+			canvas.height = offset.height;
+
+		}
+
+		const context = canvas.getContext( '2d'
 			/*, { alpha: false }*/
 			/*, { alpha: false }*/
 		);
 		);
-		var clipper = new Clipper( context ); // console.time( 'drawElement' );
+		const clipper = new Clipper( context ); // console.time( 'drawElement' );
 
 
 		drawElement( element ); // console.timeEnd( 'drawElement' );
 		drawElement( element ); // console.timeEnd( 'drawElement' );
 
 

+ 3 - 3
examples/js/lines/LineMaterial.js

@@ -221,7 +221,7 @@
 
 
 			#endif
 			#endif
 
 
-			float alpha = opacity;
+			float alpha = 1.0;
 
 
 			#ifdef ALPHA_TO_COVERAGE
 			#ifdef ALPHA_TO_COVERAGE
 
 
@@ -251,12 +251,12 @@
 
 
 			#endif
 			#endif
 
 
-			vec4 diffuseColor = vec4( diffuse, alpha );
+			vec4 diffuseColor = vec4( diffuse, opacity * alpha );
 
 
 			#include <logdepthbuf_fragment>
 			#include <logdepthbuf_fragment>
 			#include <color_fragment>
 			#include <color_fragment>
 
 
-			gl_FragColor = vec4( diffuseColor.rgb, alpha );
+			gl_FragColor = diffuseColor;
 
 
 			#include <tonemapping_fragment>
 			#include <tonemapping_fragment>
 			#include <encodings_fragment>
 			#include <encodings_fragment>

+ 42 - 82
examples/js/loaders/FBXLoader.js

@@ -549,7 +549,13 @@
 					case 'DiffuseColor':
 					case 'DiffuseColor':
 					case 'Maya|TEX_color_map':
 					case 'Maya|TEX_color_map':
 						parameters.map = scope.getTexture( textureMap, child.ID );
 						parameters.map = scope.getTexture( textureMap, child.ID );
-						parameters.map.encoding = THREE.sRGBEncoding;
+
+						if ( parameters.map !== undefined ) {
+
+							parameters.map.encoding = THREE.sRGBEncoding;
+
+						}
+
 						break;
 						break;
 
 
 					case 'DisplacementColor':
 					case 'DisplacementColor':
@@ -558,7 +564,13 @@
 
 
 					case 'EmissiveColor':
 					case 'EmissiveColor':
 						parameters.emissiveMap = scope.getTexture( textureMap, child.ID );
 						parameters.emissiveMap = scope.getTexture( textureMap, child.ID );
-						parameters.emissiveMap.encoding = THREE.sRGBEncoding;
+
+						if ( parameters.emissiveMap !== undefined ) {
+
+							parameters.emissiveMap.encoding = THREE.sRGBEncoding;
+
+						}
+
 						break;
 						break;
 
 
 					case 'NormalMap':
 					case 'NormalMap':
@@ -568,13 +580,25 @@
 
 
 					case 'ReflectionColor':
 					case 'ReflectionColor':
 						parameters.envMap = scope.getTexture( textureMap, child.ID );
 						parameters.envMap = scope.getTexture( textureMap, child.ID );
-						parameters.envMap.mapping = THREE.EquirectangularReflectionMapping;
-						parameters.envMap.encoding = THREE.sRGBEncoding;
+
+						if ( parameters.envMap !== undefined ) {
+
+							parameters.envMap.mapping = THREE.EquirectangularReflectionMapping;
+							parameters.envMap.encoding = THREE.sRGBEncoding;
+
+						}
+
 						break;
 						break;
 
 
 					case 'SpecularColor':
 					case 'SpecularColor':
 						parameters.specularMap = scope.getTexture( textureMap, child.ID );
 						parameters.specularMap = scope.getTexture( textureMap, child.ID );
-						parameters.specularMap.encoding = THREE.sRGBEncoding;
+
+						if ( parameters.specularMap !== undefined ) {
+
+							parameters.specularMap.encoding = THREE.sRGBEncoding;
+
+						}
+
 						break;
 						break;
 
 
 					case 'TransparentColor':
 					case 'TransparentColor':
@@ -612,7 +636,17 @@
 
 
 			}
 			}
 
 
-			return textureMap.get( id );
+			const texture = textureMap.get( id );
+
+			if ( texture.image !== undefined ) {
+
+				return texture;
+
+			} else {
+
+				return undefined;
+
+			}
 
 
 		} // Parse nodes in FBXTree.Objects.Deformer
 		} // Parse nodes in FBXTree.Objects.Deformer
 		// Deformer node can contain skinning or Vertex Cache animation data, however only skinning is supported here
 		// Deformer node can contain skinning or Vertex Cache animation data, however only skinning is supported here
@@ -757,7 +791,6 @@
 			} );
 			} );
 			this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
 			this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
 			this.createAmbientLight();
 			this.createAmbientLight();
-			this.setupMorphMaterials();
 			sceneGraph.traverse( function ( node ) {
 			sceneGraph.traverse( function ( node ) {
 
 
 				if ( node.userData.transformData ) {
 				if ( node.userData.transformData ) {
@@ -1336,71 +1369,6 @@
 
 
 		}
 		}
 
 
-		setupMorphMaterials() {
-
-			const scope = this;
-			sceneGraph.traverse( function ( child ) {
-
-				if ( child.isMesh ) {
-
-					if ( child.geometry.morphAttributes.position && child.geometry.morphAttributes.position.length ) {
-
-						if ( Array.isArray( child.material ) ) {
-
-							child.material.forEach( function ( material, i ) {
-
-								scope.setupMorphMaterial( child, material, i );
-
-							} );
-
-						} else {
-
-							scope.setupMorphMaterial( child, child.material );
-
-						}
-
-					}
-
-				}
-
-			} );
-
-		}
-
-		setupMorphMaterial( child, material, index ) {
-
-			const uuid = child.uuid;
-			const matUuid = material.uuid; // if a geometry has morph targets, it cannot share the material with other geometries
-
-			let sharedMat = false;
-			sceneGraph.traverse( function ( node ) {
-
-				if ( node.isMesh ) {
-
-					if ( Array.isArray( node.material ) ) {
-
-						node.material.forEach( function ( mat ) {
-
-							if ( mat.uuid === matUuid && node.uuid !== uuid ) sharedMat = true;
-
-						} );
-
-					} else if ( node.material.uuid === matUuid && node.uuid !== uuid ) sharedMat = true;
-
-				}
-
-			} );
-
-			if ( sharedMat === true ) {
-
-				const clonedMat = material.clone();
-				clonedMat.morphTargets = true;
-				if ( index === undefined ) child.material = clonedMat; else child.material[ index ] = clonedMat;
-
-			} else material.morphTargets = true;
-
-		}
-
 	} // parse Geometry data from FBXTree and return map of BufferGeometries
 	} // parse Geometry data from FBXTree and return map of BufferGeometries
 
 
 
 
@@ -2151,16 +2119,8 @@
 			}
 			}
 
 
 			const curve = new THREE.NURBSCurve( degree, knots, controlPoints, startKnot, endKnot );
 			const curve = new THREE.NURBSCurve( degree, knots, controlPoints, startKnot, endKnot );
-			const vertices = curve.getPoints( controlPoints.length * 7 );
-			const positions = new Float32Array( vertices.length * 3 );
-			vertices.forEach( function ( vertex, i ) {
-
-				vertex.toArray( positions, i * 3 );
-
-			} );
-			const geometry = new THREE.BufferGeometry();
-			geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
-			return geometry;
+			const points = curve.getPoints( controlPoints.length * 12 );
+			return new THREE.BufferGeometry().setFromPoints( points );
 
 
 		}
 		}
 
 

+ 183 - 10
examples/js/loaders/GLTFLoader.js

@@ -28,6 +28,21 @@
 
 
 				return new GLTFMaterialsTransmissionExtension( parser );
 				return new GLTFMaterialsTransmissionExtension( parser );
 
 
+			} );
+			this.register( function ( parser ) {
+
+				return new GLTFMaterialsVolumeExtension( parser );
+
+			} );
+			this.register( function ( parser ) {
+
+				return new GLTFMaterialsIorExtension( parser );
+
+			} );
+			this.register( function ( parser ) {
+
+				return new GLTFMaterialsSpecularExtension( parser );
+
 			} );
 			} );
 			this.register( function ( parser ) {
 			this.register( function ( parser ) {
 
 
@@ -319,9 +334,12 @@
 		KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
 		KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
 		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_LIGHTS_PUNCTUAL: 'KHR_lights_punctual',
 		KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
 		KHR_MATERIALS_CLEARCOAT: 'KHR_materials_clearcoat',
+		KHR_MATERIALS_IOR: 'KHR_materials_ior',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
+		KHR_MATERIALS_SPECULAR: 'KHR_materials_specular',
 		KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
 		KHR_MATERIALS_TRANSMISSION: 'KHR_materials_transmission',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
+		KHR_MATERIALS_VOLUME: 'KHR_materials_volume',
 		KHR_TEXTURE_BASISU: 'KHR_texture_basisu',
 		KHR_TEXTURE_BASISU: 'KHR_texture_basisu',
 		KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
 		KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
 		KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
 		KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
@@ -632,6 +650,167 @@
 
 
 		}
 		}
 
 
+	}
+	/**
+ * Materials Volume Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_volume
+ */
+
+
+	class GLTFMaterialsVolumeExtension {
+
+		constructor( parser ) {
+
+			this.parser = parser;
+			this.name = EXTENSIONS.KHR_MATERIALS_VOLUME;
+
+		}
+
+		getMaterialType( materialIndex ) {
+
+			const parser = this.parser;
+			const materialDef = parser.json.materials[ materialIndex ];
+			if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
+			return THREE.MeshPhysicalMaterial;
+
+		}
+
+		extendMaterialParams( materialIndex, materialParams ) {
+
+			const parser = this.parser;
+			const materialDef = parser.json.materials[ materialIndex ];
+
+			if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
+
+				return Promise.resolve();
+
+			}
+
+			const pending = [];
+			const extension = materialDef.extensions[ this.name ];
+			materialParams.thickness = extension.thicknessFactor !== undefined ? extension.thicknessFactor : 0;
+
+			if ( extension.thicknessTexture !== undefined ) {
+
+				pending.push( parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) );
+
+			}
+
+			materialParams.attenuationDistance = extension.attenuationDistance || 0;
+			const colorArray = extension.attenuationColor || [ 1, 1, 1 ];
+			materialParams.attenuationTint = new THREE.Color( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ] );
+			return Promise.all( pending );
+
+		}
+
+	}
+	/**
+ * Materials ior Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_ior
+ */
+
+
+	class GLTFMaterialsIorExtension {
+
+		constructor( parser ) {
+
+			this.parser = parser;
+			this.name = EXTENSIONS.KHR_MATERIALS_IOR;
+
+		}
+
+		getMaterialType( materialIndex ) {
+
+			const parser = this.parser;
+			const materialDef = parser.json.materials[ materialIndex ];
+			if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
+			return THREE.MeshPhysicalMaterial;
+
+		}
+
+		extendMaterialParams( materialIndex, materialParams ) {
+
+			const parser = this.parser;
+			const materialDef = parser.json.materials[ materialIndex ];
+
+			if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
+
+				return Promise.resolve();
+
+			}
+
+			const extension = materialDef.extensions[ this.name ];
+			materialParams.ior = extension.ior !== undefined ? extension.ior : 1.5;
+			return Promise.resolve();
+
+		}
+
+	}
+	/**
+ * Materials specular Extension
+ *
+ * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_materials_specular
+ */
+
+
+	class GLTFMaterialsSpecularExtension {
+
+		constructor( parser ) {
+
+			this.parser = parser;
+			this.name = EXTENSIONS.KHR_MATERIALS_SPECULAR;
+
+		}
+
+		getMaterialType( materialIndex ) {
+
+			const parser = this.parser;
+			const materialDef = parser.json.materials[ materialIndex ];
+			if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
+			return THREE.MeshPhysicalMaterial;
+
+		}
+
+		extendMaterialParams( materialIndex, materialParams ) {
+
+			const parser = this.parser;
+			const materialDef = parser.json.materials[ materialIndex ];
+
+			if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
+
+				return Promise.resolve();
+
+			}
+
+			const pending = [];
+			const extension = materialDef.extensions[ this.name ];
+			materialParams.specularIntensity = extension.specularFactor !== undefined ? extension.specularFactor : 1.0;
+
+			if ( extension.specularTexture !== undefined ) {
+
+				pending.push( parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) );
+
+			}
+
+			const colorArray = extension.specularColorFactor || [ 1, 1, 1 ];
+			materialParams.specularTint = new THREE.Color( colorArray[ 0 ], colorArray[ 1 ], colorArray[ 2 ] );
+
+			if ( extension.specularColorTexture !== undefined ) {
+
+				pending.push( parser.assignTexture( materialParams, 'specularTintMap', extension.specularColorTexture ).then( function ( texture ) {
+
+					texture.encoding = THREE.sRGBEncoding;
+
+				} ) );
+
+			}
+
+			return Promise.all( pending );
+
+		}
+
 	}
 	}
 	/**
 	/**
  * BasisU THREE.Texture Extension
  * BasisU THREE.Texture Extension
@@ -2392,7 +2571,7 @@
    * @param {Object} materialParams
    * @param {Object} materialParams
    * @param {string} mapName
    * @param {string} mapName
    * @param {Object} mapDef
    * @param {Object} mapDef
-   * @return {Promise}
+   * @return {Promise<Texture>}
    */
    */
 
 
 
 
@@ -2424,6 +2603,7 @@
 				}
 				}
 
 
 				materialParams[ mapName ] = texture;
 				materialParams[ mapName ] = texture;
+				return texture;
 
 
 			} );
 			} );
 
 
@@ -2445,8 +2625,6 @@
 			const useVertexTangents = geometry.attributes.tangent !== undefined;
 			const useVertexTangents = geometry.attributes.tangent !== undefined;
 			const useVertexColors = geometry.attributes.color !== undefined;
 			const useVertexColors = geometry.attributes.color !== undefined;
 			const useFlatShading = geometry.attributes.normal === undefined;
 			const useFlatShading = geometry.attributes.normal === undefined;
-			const useMorphTargets = Object.keys( geometry.morphAttributes ).length > 0;
-			const useMorphNormals = useMorphTargets && geometry.morphAttributes.normal !== undefined;
 
 
 			if ( mesh.isPoints ) {
 			if ( mesh.isPoints ) {
 
 
@@ -2486,15 +2664,13 @@
 			} // Clone the material if it will be modified
 			} // Clone the material if it will be modified
 
 
 
 
-			if ( useVertexTangents || useVertexColors || useFlatShading || useMorphTargets ) {
+			if ( useVertexTangents || useVertexColors || useFlatShading ) {
 
 
 				let cacheKey = 'ClonedMaterial:' + material.uuid + ':';
 				let cacheKey = 'ClonedMaterial:' + material.uuid + ':';
 				if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
 				if ( material.isGLTFSpecularGlossinessMaterial ) cacheKey += 'specular-glossiness:';
 				if ( useVertexTangents ) cacheKey += 'vertex-tangents:';
 				if ( useVertexTangents ) cacheKey += 'vertex-tangents:';
 				if ( useVertexColors ) cacheKey += 'vertex-colors:';
 				if ( useVertexColors ) cacheKey += 'vertex-colors:';
 				if ( useFlatShading ) cacheKey += 'flat-shading:';
 				if ( useFlatShading ) cacheKey += 'flat-shading:';
-				if ( useMorphTargets ) cacheKey += 'morph-targets:';
-				if ( useMorphNormals ) cacheKey += 'morph-normals:';
 				let cachedMaterial = this.cache.get( cacheKey );
 				let cachedMaterial = this.cache.get( cacheKey );
 
 
 				if ( ! cachedMaterial ) {
 				if ( ! cachedMaterial ) {
@@ -2502,13 +2678,10 @@
 					cachedMaterial = material.clone();
 					cachedMaterial = material.clone();
 					if ( useVertexColors ) cachedMaterial.vertexColors = true;
 					if ( useVertexColors ) cachedMaterial.vertexColors = true;
 					if ( useFlatShading ) cachedMaterial.flatShading = true;
 					if ( useFlatShading ) cachedMaterial.flatShading = true;
-					if ( useMorphTargets ) cachedMaterial.morphTargets = true;
-					if ( useMorphNormals ) cachedMaterial.morphNormals = true;
 
 
 					if ( useVertexTangents ) {
 					if ( useVertexTangents ) {
 
 
-						cachedMaterial.vertexTangents = true; // https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995
-
+						// https://github.com/mrdoob/three.js/issues/11438#issuecomment-507003995
 						if ( cachedMaterial.normalScale ) cachedMaterial.normalScale.y *= - 1;
 						if ( cachedMaterial.normalScale ) cachedMaterial.normalScale.y *= - 1;
 						if ( cachedMaterial.clearcoatNormalScale ) cachedMaterial.clearcoatNormalScale.y *= - 1;
 						if ( cachedMaterial.clearcoatNormalScale ) cachedMaterial.clearcoatNormalScale.y *= - 1;
 
 

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

@@ -6,7 +6,7 @@
 
 
 			super( manager );
 			super( manager );
 			this.hdrLoader = new THREE.RGBELoader();
 			this.hdrLoader = new THREE.RGBELoader();
-			this.type = THREE.UnsignedByteType;
+			this.type = THREE.FloatType;
 
 
 		}
 		}
 
 

+ 154 - 122
examples/js/loaders/LDrawLoader.js

@@ -17,89 +17,131 @@
 	const FILE_LOCATION_TRY_RELATIVE = 4;
 	const FILE_LOCATION_TRY_RELATIVE = 4;
 	const FILE_LOCATION_TRY_ABSOLUTE = 5;
 	const FILE_LOCATION_TRY_ABSOLUTE = 5;
 	const FILE_LOCATION_NOT_FOUND = 6;
 	const FILE_LOCATION_NOT_FOUND = 6;
-	const conditionalLineVertShader =
-/* glsl */
-`
-	attribute vec3 control0;
-	attribute vec3 control1;
-	attribute vec3 direction;
-	varying float discardFlag;
-
-	#include <common>
-	#include <color_pars_vertex>
-	#include <fog_pars_vertex>
-	#include <logdepthbuf_pars_vertex>
-	#include <clipping_planes_pars_vertex>
-	void main() {
-		#include <color_vertex>
-
-		vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
-		gl_Position = projectionMatrix * mvPosition;
-
-		// Transform the line segment ends and control points into camera clip space
-		vec4 c0 = projectionMatrix * modelViewMatrix * vec4( control0, 1.0 );
-		vec4 c1 = projectionMatrix * modelViewMatrix * vec4( control1, 1.0 );
-		vec4 p0 = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
-		vec4 p1 = projectionMatrix * modelViewMatrix * vec4( position + direction, 1.0 );
-
-		c0.xy /= c0.w;
-		c1.xy /= c1.w;
-		p0.xy /= p0.w;
-		p1.xy /= p1.w;
-
-		// Get the direction of the segment and an orthogonal vector
-		vec2 dir = p1.xy - p0.xy;
-		vec2 norm = vec2( -dir.y, dir.x );
-
-		// Get control point directions from the line
-		vec2 c0dir = c0.xy - p1.xy;
-		vec2 c1dir = c1.xy - p1.xy;
-
-		// If the vectors to the controls points are pointed in different directions away
-		// from the line segment then the line should not be drawn.
-		float d0 = dot( normalize( norm ), normalize( c0dir ) );
-		float d1 = dot( normalize( norm ), normalize( c1dir ) );
-		discardFlag = float( sign( d0 ) != sign( d1 ) );
-
-		#include <logdepthbuf_vertex>
-		#include <clipping_planes_vertex>
-		#include <fog_vertex>
-	}
-	`;
-	const conditionalLineFragShader =
-/* glsl */
-`
-	uniform vec3 diffuse;
-	uniform float opacity;
-	varying float discardFlag;
-
-	#include <common>
-	#include <color_pars_fragment>
-	#include <fog_pars_fragment>
-	#include <logdepthbuf_pars_fragment>
-	#include <clipping_planes_pars_fragment>
-	void main() {
-
-		if ( discardFlag > 0.5 ) discard;
-
-		#include <clipping_planes_fragment>
-		vec3 outgoingLight = vec3( 0.0 );
-		vec4 diffuseColor = vec4( diffuse, opacity );
-		#include <logdepthbuf_fragment>
-		#include <color_fragment>
-		outgoingLight = diffuseColor.rgb; // simple shader
-		gl_FragColor = vec4( outgoingLight, diffuseColor.a );
-		#include <tonemapping_fragment>
-		#include <encodings_fragment>
-		#include <fog_fragment>
-		#include <premultiplied_alpha_fragment>
-	}
-	`;
 
 
 	const _tempVec0 = new THREE.Vector3();
 	const _tempVec0 = new THREE.Vector3();
 
 
 	const _tempVec1 = new THREE.Vector3();
 	const _tempVec1 = new THREE.Vector3();
 
 
+	class LDrawConditionalLineMaterial extends THREE.ShaderMaterial {
+
+		constructor( parameters ) {
+
+			super( {
+				uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib.fog, {
+					diffuse: {
+						value: new THREE.Color()
+					},
+					opacity: {
+						value: 1.0
+					}
+				} ] ),
+				vertexShader:
+      /* glsl */
+      `
+				attribute vec3 control0;
+				attribute vec3 control1;
+				attribute vec3 direction;
+				varying float discardFlag;
+
+				#include <common>
+				#include <color_pars_vertex>
+				#include <fog_pars_vertex>
+				#include <logdepthbuf_pars_vertex>
+				#include <clipping_planes_pars_vertex>
+				void main() {
+					#include <color_vertex>
+
+					vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
+					gl_Position = projectionMatrix * mvPosition;
+
+					// Transform the line segment ends and control points into camera clip space
+					vec4 c0 = projectionMatrix * modelViewMatrix * vec4( control0, 1.0 );
+					vec4 c1 = projectionMatrix * modelViewMatrix * vec4( control1, 1.0 );
+					vec4 p0 = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
+					vec4 p1 = projectionMatrix * modelViewMatrix * vec4( position + direction, 1.0 );
+
+					c0.xy /= c0.w;
+					c1.xy /= c1.w;
+					p0.xy /= p0.w;
+					p1.xy /= p1.w;
+
+					// Get the direction of the segment and an orthogonal vector
+					vec2 dir = p1.xy - p0.xy;
+					vec2 norm = vec2( -dir.y, dir.x );
+
+					// Get control point directions from the line
+					vec2 c0dir = c0.xy - p1.xy;
+					vec2 c1dir = c1.xy - p1.xy;
+
+					// If the vectors to the controls points are pointed in different directions away
+					// from the line segment then the line should not be drawn.
+					float d0 = dot( normalize( norm ), normalize( c0dir ) );
+					float d1 = dot( normalize( norm ), normalize( c1dir ) );
+					discardFlag = float( sign( d0 ) != sign( d1 ) );
+
+					#include <logdepthbuf_vertex>
+					#include <clipping_planes_vertex>
+					#include <fog_vertex>
+				}
+			`,
+				fragmentShader:
+      /* glsl */
+      `
+			uniform vec3 diffuse;
+			uniform float opacity;
+			varying float discardFlag;
+
+			#include <common>
+			#include <color_pars_fragment>
+			#include <fog_pars_fragment>
+			#include <logdepthbuf_pars_fragment>
+			#include <clipping_planes_pars_fragment>
+			void main() {
+
+				if ( discardFlag > 0.5 ) discard;
+
+				#include <clipping_planes_fragment>
+				vec3 outgoingLight = vec3( 0.0 );
+				vec4 diffuseColor = vec4( diffuse, opacity );
+				#include <logdepthbuf_fragment>
+				#include <color_fragment>
+				outgoingLight = diffuseColor.rgb; // simple shader
+				gl_FragColor = vec4( outgoingLight, diffuseColor.a );
+				#include <tonemapping_fragment>
+				#include <encodings_fragment>
+				#include <fog_fragment>
+				#include <premultiplied_alpha_fragment>
+			}
+			`
+			} );
+			Object.defineProperties( this, {
+				opacity: {
+					get: function () {
+
+						return this.uniforms.opacity.value;
+
+					},
+					set: function ( value ) {
+
+						this.uniforms.opacity.value = value;
+
+					}
+				},
+				color: {
+					get: function () {
+
+						return this.uniforms.diffuse.value;
+
+					}
+				}
+			} );
+			this.setValues( parameters );
+			this.isLDrawConditionalLineMaterial = true;
+
+		}
+
+	}
+
 	function smoothNormals( triangles, lineSegments ) {
 	function smoothNormals( triangles, lineSegments ) {
 
 
 		function hashVertex( v ) {
 		function hashVertex( v ) {
@@ -154,13 +196,7 @@
 
 
 			}
 			}
 
 
-		} // NOTE: Some of the normals wind up being skewed in an unexpected way because
-		// quads provide more "influence" to some vertex normals than a triangle due to
-		// the fact that a quad is made up of two triangles and all triangles are weighted
-		// equally. To fix this quads could be tracked separately so their vertex normals
-		// are weighted appropriately or we could try only adding a normal direction
-		// once per normal.
-		// Iterate until we've tried to connect all triangles to share normals
+		} // Iterate until we've tried to connect all triangles to share normals
 
 
 
 
 		while ( true ) {
 		while ( true ) {
@@ -181,14 +217,14 @@
 
 
 				if ( tri.n0 === null ) {
 				if ( tri.n0 === null ) {
 
 
-					tri.n0 = faceNormal.clone();
+					tri.n0 = faceNormal.clone().multiplyScalar( tri.fromQuad ? 0.5 : 1.0 );
 					normals.push( tri.n0 );
 					normals.push( tri.n0 );
 
 
 				}
 				}
 
 
 				if ( tri.n1 === null ) {
 				if ( tri.n1 === null ) {
 
 
-					tri.n1 = faceNormal.clone();
+					tri.n1 = faceNormal.clone().multiplyScalar( tri.fromQuad ? 0.5 : 1.0 );
 					normals.push( tri.n1 );
 					normals.push( tri.n1 );
 
 
 				}
 				}
@@ -249,7 +285,8 @@
 
 
 									const norm = tri[ `n${next}` ];
 									const norm = tri[ `n${next}` ];
 									otherTri[ `n${otherIndex}` ] = norm;
 									otherTri[ `n${otherIndex}` ] = norm;
-									norm.add( otherTri.faceNormal );
+									const isDoubledVert = otherTri.fromQuad && otherIndex !== 2;
+									norm.addScaledVector( otherTri.faceNormal, isDoubledVert ? 0.5 : 1.0 );
 
 
 								}
 								}
 
 
@@ -257,7 +294,8 @@
 
 
 									const norm = tri[ `n${index}` ];
 									const norm = tri[ `n${index}` ];
 									otherTri[ `n${otherNext}` ] = norm;
 									otherTri[ `n${otherNext}` ] = norm;
-									norm.add( otherTri.faceNormal );
+									const isDoubledVert = otherTri.fromQuad && otherNext !== 2;
+									norm.addScaledVector( otherTri.faceNormal, isDoubledVert ? 0.5 : 1.0 );
 
 
 								}
 								}
 
 
@@ -723,7 +761,6 @@
 
 
 			let luminance = 0;
 			let luminance = 0;
 			let finishType = FINISH_TYPE_DEFAULT;
 			let finishType = FINISH_TYPE_DEFAULT;
-			let canHaveEnvMap = true;
 			let edgeMaterial = null;
 			let edgeMaterial = null;
 			const name = lineParser.getToken();
 			const name = lineParser.getToken();
 
 
@@ -864,7 +901,6 @@
 					material = new THREE.MeshStandardMaterial( {
 					material = new THREE.MeshStandardMaterial( {
 						color: colour,
 						color: colour,
 						roughness: 0.3,
 						roughness: 0.3,
-						envMapIntensity: 0.3,
 						metalness: 0
 						metalness: 0
 					} );
 					} );
 					break;
 					break;
@@ -904,7 +940,6 @@
 						roughness: 0.9,
 						roughness: 0.9,
 						metalness: 0
 						metalness: 0
 					} );
 					} );
-					canHaveEnvMap = false;
 					break;
 					break;
 
 
 				case FINISH_TYPE_MATTE_METALLIC:
 				case FINISH_TYPE_MATTE_METALLIC:
@@ -937,7 +972,6 @@
 			material.depthWrite = ! isTransparent;
 			material.depthWrite = ! isTransparent;
 			material.polygonOffset = true;
 			material.polygonOffset = true;
 			material.polygonOffsetFactor = 1;
 			material.polygonOffsetFactor = 1;
-			material.userData.canHaveEnvMap = canHaveEnvMap;
 
 
 			if ( luminance !== 0 ) {
 			if ( luminance !== 0 ) {
 
 
@@ -955,25 +989,15 @@
 					depthWrite: ! isTransparent
 					depthWrite: ! isTransparent
 				} );
 				} );
 				edgeMaterial.userData.code = code;
 				edgeMaterial.userData.code = code;
-				edgeMaterial.name = name + ' - Edge';
-				edgeMaterial.userData.canHaveEnvMap = false; // This is the material used for conditional edges
-
-				edgeMaterial.userData.conditionalEdgeMaterial = new THREE.ShaderMaterial( {
-					vertexShader: conditionalLineVertShader,
-					fragmentShader: conditionalLineFragShader,
-					uniforms: THREE.UniformsUtils.merge( [ THREE.UniformsLib.fog, {
-						diffuse: {
-							value: new THREE.Color( edgeColour )
-						},
-						opacity: {
-							value: alpha
-						}
-					} ] ),
+				edgeMaterial.name = name + ' - Edge'; // This is the material used for conditional edges
+
+				edgeMaterial.userData.conditionalEdgeMaterial = new LDrawConditionalLineMaterial( {
 					fog: true,
 					fog: true,
 					transparent: isTransparent,
 					transparent: isTransparent,
-					depthWrite: ! isTransparent
+					depthWrite: ! isTransparent,
+					color: edgeColour,
+					opacity: alpha
 				} );
 				} );
-				edgeMaterial.userData.conditionalEdgeMaterial.userData.canHaveEnvMap = false;
 
 
 			}
 			}
 
 
@@ -1367,7 +1391,8 @@
 							faceNormal: faceNormal,
 							faceNormal: faceNormal,
 							n0: null,
 							n0: null,
 							n1: null,
 							n1: null,
-							n2: null
+							n2: null,
+							fromQuad: false
 						} );
 						} );
 
 
 						if ( doubleSided === true ) {
 						if ( doubleSided === true ) {
@@ -1381,7 +1406,8 @@
 								faceNormal: faceNormal,
 								faceNormal: faceNormal,
 								n0: null,
 								n0: null,
 								n1: null,
 								n1: null,
-								n2: null
+								n2: null,
+								fromQuad: false
 							} );
 							} );
 
 
 						}
 						}
@@ -1415,17 +1441,20 @@
 
 
 						_tempVec1.subVectors( v2, v1 );
 						_tempVec1.subVectors( v2, v1 );
 
 
-						faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize();
+						faceNormal = new THREE.Vector3().crossVectors( _tempVec0, _tempVec1 ).normalize(); // specifically place the triangle diagonal in the v0 and v1 slots so we can
+						// account for the doubling of vertices later when smoothing normals.
+
 						triangles.push( {
 						triangles.push( {
 							material: material,
 							material: material,
 							colourCode: material.userData.code,
 							colourCode: material.userData.code,
-							v0: v0,
-							v1: v1,
-							v2: v2,
+							v0: v2,
+							v1: v0,
+							v2: v1,
 							faceNormal: faceNormal,
 							faceNormal: faceNormal,
 							n0: null,
 							n0: null,
 							n1: null,
 							n1: null,
-							n2: null
+							n2: null,
+							fromQuad: true
 						} );
 						} );
 						triangles.push( {
 						triangles.push( {
 							material: material,
 							material: material,
@@ -1436,7 +1465,8 @@
 							faceNormal: faceNormal,
 							faceNormal: faceNormal,
 							n0: null,
 							n0: null,
 							n1: null,
 							n1: null,
-							n2: null
+							n2: null,
+							fromQuad: true
 						} );
 						} );
 
 
 						if ( doubleSided === true ) {
 						if ( doubleSided === true ) {
@@ -1450,18 +1480,20 @@
 								faceNormal: faceNormal,
 								faceNormal: faceNormal,
 								n0: null,
 								n0: null,
 								n1: null,
 								n1: null,
-								n2: null
+								n2: null,
+								fromQuad: true
 							} );
 							} );
 							triangles.push( {
 							triangles.push( {
 								material: material,
 								material: material,
 								colourCode: material.userData.code,
 								colourCode: material.userData.code,
-								v0: v0,
-								v1: v3,
-								v2: v2,
+								v0: v2,
+								v1: v0,
+								v2: v3,
 								faceNormal: faceNormal,
 								faceNormal: faceNormal,
 								n0: null,
 								n0: null,
 								n1: null,
 								n1: null,
-								n2: null
+								n2: null,
+								fromQuad: true
 							} );
 							} );
 
 
 						}
 						}

+ 0 - 1
examples/js/loaders/LWOLoader.js

@@ -176,7 +176,6 @@
 
 
 						spec.size = 0.1;
 						spec.size = 0.1;
 						spec.map = mat.map;
 						spec.map = mat.map;
-						spec.morphTargets = mat.morphTargets;
 						materials[ i ] = new THREE.PointsMaterial( spec );
 						materials[ i ] = new THREE.PointsMaterial( spec );
 
 
 					} else if ( type === 'lines' ) {
 					} else if ( type === 'lines' ) {

+ 0 - 1
examples/js/loaders/MMDLoader.js

@@ -960,7 +960,6 @@
 				params.emissive = new THREE.Color().fromArray( material.ambient );
 				params.emissive = new THREE.Color().fromArray( material.ambient );
 				params.transparent = params.opacity !== 1.0; //
 				params.transparent = params.opacity !== 1.0; //
 
 
-				params.morphTargets = geometry.morphTargets.length > 0 ? true : false;
 				params.fog = true; // blend
 				params.fog = true; // blend
 
 
 				params.blending = THREE.CustomBlending;
 				params.blending = THREE.CustomBlending;

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

@@ -7,7 +7,7 @@
 		constructor( manager ) {
 		constructor( manager ) {
 
 
 			super( manager );
 			super( manager );
-			this.type = THREE.UnsignedByteType;
+			this.type = THREE.FloatType;
 
 
 		} // adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html
 		} // adapted from http://www.graphics.cornell.edu/~bjw/rgbe.html
 
 

+ 34 - 14
examples/js/loaders/SVGLoader.js

@@ -651,29 +651,49 @@
 
 
 				const x = parseFloatWithUnits( node.getAttribute( 'x' ) || 0 );
 				const x = parseFloatWithUnits( node.getAttribute( 'x' ) || 0 );
 				const y = parseFloatWithUnits( node.getAttribute( 'y' ) || 0 );
 				const y = parseFloatWithUnits( node.getAttribute( 'y' ) || 0 );
-				const rx = parseFloatWithUnits( node.getAttribute( 'rx' ) || 0 );
-				const ry = parseFloatWithUnits( node.getAttribute( 'ry' ) || 0 );
+				const rx = parseFloatWithUnits( node.getAttribute( 'rx' ) || node.getAttribute( 'ry' ) || 0 );
+				const ry = parseFloatWithUnits( node.getAttribute( 'ry' ) || node.getAttribute( 'rx' ) || 0 );
 				const w = parseFloatWithUnits( node.getAttribute( 'width' ) );
 				const w = parseFloatWithUnits( node.getAttribute( 'width' ) );
-				const h = parseFloatWithUnits( node.getAttribute( 'height' ) );
-				const path = new THREE.ShapePath();
-				path.moveTo( x + 2 * rx, y );
-				path.lineTo( x + w - 2 * rx, y );
-				if ( rx !== 0 || ry !== 0 ) path.bezierCurveTo( x + w, y, x + w, y, x + w, y + 2 * ry );
-				path.lineTo( x + w, y + h - 2 * ry );
-				if ( rx !== 0 || ry !== 0 ) path.bezierCurveTo( x + w, y + h, x + w, y + h, x + w - 2 * rx, y + h );
-				path.lineTo( x + 2 * rx, y + h );
+				const h = parseFloatWithUnits( node.getAttribute( 'height' ) ); // Ellipse arc to Bezier approximation Coefficient (Inversed). See:
+				// https://spencermortensen.com/articles/bezier-circle/
+
+				const bci = 1 - 0.551915024494;
+				const path = new THREE.ShapePath(); // top left
+
+				path.moveTo( x + rx, y ); // top right
+
+				path.lineTo( x + w - rx, y );
 
 
 				if ( rx !== 0 || ry !== 0 ) {
 				if ( rx !== 0 || ry !== 0 ) {
 
 
-					path.bezierCurveTo( x, y + h, x, y + h, x, y + h - 2 * ry );
+					path.bezierCurveTo( x + w - rx * bci, y, x + w, y + ry * bci, x + w, y + ry );
+
+				} // bottom right
+
+
+				path.lineTo( x + w, y + h - ry );
+
+				if ( rx !== 0 || ry !== 0 ) {
+
+					path.bezierCurveTo( x + w, y + h - ry * bci, x + w - rx * bci, y + h, x + w - rx, y + h );
+
+				} // bottom left
+
+
+				path.lineTo( x + rx, y + h );
+
+				if ( rx !== 0 || ry !== 0 ) {
+
+					path.bezierCurveTo( x + rx * bci, y + h, x, y + h - ry * bci, x, y + h - ry );
+
+				} // back to top left
 
 
-				}
 
 
-				path.lineTo( x, y + 2 * ry );
+				path.lineTo( x, y + ry );
 
 
 				if ( rx !== 0 || ry !== 0 ) {
 				if ( rx !== 0 || ry !== 0 ) {
 
 
-					path.bezierCurveTo( x, y, x, y, x + 2 * rx, y );
+					path.bezierCurveTo( x, y + ry * bci, x + rx * bci, y, x + rx, y );
 
 
 				}
 				}
 
 

+ 13 - 12
examples/js/math/Lut.js

@@ -2,16 +2,20 @@
 
 
 	class Lut {
 	class Lut {
 
 
-		constructor( colormap, numberofcolors ) {
+		constructor( colormap, count = 32 ) {
 
 
 			this.lut = [];
 			this.lut = [];
-			this.setColorMap( colormap, numberofcolors );
+			this.map = [];
+			this.n = 0;
+			this.minV = 0;
+			this.maxV = 1;
+			this.setColorMap( colormap, count );
 
 
 		}
 		}
 
 
 		set( value ) {
 		set( value ) {
 
 
-			if ( value instanceof Lut ) {
+			if ( value.isLut === true ) {
 
 
 				this.copy( value );
 				this.copy( value );
 
 
@@ -35,10 +39,10 @@
 
 
 		}
 		}
 
 
-		setColorMap( colormap, numberofcolors = 32 ) {
+		setColorMap( colormap, count = 32 ) {
 
 
 			this.map = ColorMapKeywords[ colormap ] || ColorMapKeywords.rainbow;
 			this.map = ColorMapKeywords[ colormap ] || ColorMapKeywords.rainbow;
-			this.n = numberofcolors;
+			this.n = count;
 			const step = 1.0 / this.n;
 			const step = 1.0 / this.n;
 			this.lut.length = 0;
 			this.lut.length = 0;
 
 
@@ -95,9 +99,10 @@
 
 
 		}
 		}
 
 
-		addColorMap( colormapName, arrayOfColors ) {
+		addColorMap( name, arrayOfColors ) {
 
 
-			ColorMapKeywords[ colormapName ] = arrayOfColors;
+			ColorMapKeywords[ name ] = arrayOfColors;
+			return this;
 
 
 		}
 		}
 
 
@@ -151,11 +156,7 @@
 
 
 	}
 	}
 
 
-	Lut.prototype.lut = [];
-	Lut.prototype.map = [];
-	Lut.prototype.n = 256;
-	Lut.prototype.minV = 0;
-	Lut.prototype.maxV = 1;
+	Lut.prototype.isLut = true;
 	const ColorMapKeywords = {
 	const ColorMapKeywords = {
 		'rainbow': [[ 0.0, 0x0000FF ], [ 0.2, 0x00FFFF ], [ 0.5, 0x00FF00 ], [ 0.8, 0xFFFF00 ], [ 1.0, 0xFF0000 ]],
 		'rainbow': [[ 0.0, 0x0000FF ], [ 0.2, 0x00FFFF ], [ 0.5, 0x00FF00 ], [ 0.8, 0xFFFF00 ], [ 1.0, 0xFF0000 ]],
 		'cooltowarm': [[ 0.0, 0x3C4EC2 ], [ 0.2, 0x9BBCFF ], [ 0.5, 0xDCDCDC ], [ 0.8, 0xF6A385 ], [ 1.0, 0xB40426 ]],
 		'cooltowarm': [[ 0.0, 0x3C4EC2 ], [ 0.2, 0x9BBCFF ], [ 0.5, 0xDCDCDC ], [ 0.8, 0xF6A385 ], [ 1.0, 0xB40426 ]],

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