Mr.doob 4 years ago
parent
commit
2dc8f8cd9b
100 changed files with 2703 additions and 1593 deletions
  1. 779 429
      build/three.js
  2. 0 0
      build/three.min.js
  3. 793 313
      build/three.module.js
  4. 0 100
      docs/api/en/core/Face3.html
  5. 1 2
      docs/api/en/core/Object3D.html
  6. 1 1
      docs/api/en/core/Raycaster.html
  7. 1 2
      docs/api/en/extras/core/Font.html
  8. 1 2
      docs/api/en/lights/DirectionalLight.html
  9. 0 1
      docs/api/en/lights/PointLight.html
  10. 0 2
      docs/api/en/loaders/CubeTextureLoader.html
  11. 3 3
      docs/api/en/loaders/ImageBitmapLoader.html
  12. 1 1
      docs/api/en/materials/LineBasicMaterial.html
  13. 0 5
      docs/api/en/materials/Material.html
  14. 5 0
      docs/api/en/materials/MeshMatcapMaterial.html
  15. 5 0
      docs/api/en/materials/MeshNormalMaterial.html
  16. 5 0
      docs/api/en/materials/MeshPhongMaterial.html
  17. 4 0
      docs/api/en/materials/MeshStandardMaterial.html
  18. 1 1
      docs/api/en/materials/PointsMaterial.html
  19. 4 4
      docs/api/en/materials/RawShaderMaterial.html
  20. 1 4
      docs/api/en/materials/ShaderMaterial.html
  21. 3 4
      docs/api/en/materials/SpriteMaterial.html
  22. 3 2
      docs/api/en/renderers/WebGLCubeRenderTarget.html
  23. 3 2
      docs/api/en/renderers/WebGLRenderTarget.html
  24. 3 0
      docs/api/en/renderers/WebGLRenderer.html
  25. 2 2
      docs/api/en/textures/Texture.html
  26. 0 96
      docs/api/zh/core/Face3.html
  27. 1 2
      docs/api/zh/core/Object3D.html
  28. 1 1
      docs/api/zh/core/Raycaster.html
  29. 1 2
      docs/api/zh/extras/core/Font.html
  30. 1 2
      docs/api/zh/lights/DirectionalLight.html
  31. 0 1
      docs/api/zh/lights/PointLight.html
  32. 0 2
      docs/api/zh/loaders/CubeTextureLoader.html
  33. 3 3
      docs/api/zh/loaders/ImageBitmapLoader.html
  34. 1 1
      docs/api/zh/materials/LineBasicMaterial.html
  35. 0 4
      docs/api/zh/materials/Material.html
  36. 4 0
      docs/api/zh/materials/MeshMatcapMaterial.html
  37. 4 0
      docs/api/zh/materials/MeshNormalMaterial.html
  38. 3 0
      docs/api/zh/materials/MeshPhongMaterial.html
  39. 4 4
      docs/api/zh/materials/MeshPhysicalMaterial.html
  40. 3 0
      docs/api/zh/materials/MeshStandardMaterial.html
  41. 1 1
      docs/api/zh/materials/PointsMaterial.html
  42. 4 4
      docs/api/zh/materials/RawShaderMaterial.html
  43. 1 5
      docs/api/zh/materials/ShaderMaterial.html
  44. 2 3
      docs/api/zh/materials/SpriteMaterial.html
  45. 1 1
      docs/api/zh/math/MathUtils.html
  46. 3 2
      docs/api/zh/renderers/WebGLCubeRenderTarget.html
  47. 3 2
      docs/api/zh/renderers/WebGLRenderTarget.html
  48. 3 3
      docs/api/zh/renderers/WebGLRenderer.html
  49. 2 2
      docs/api/zh/textures/Texture.html
  50. 8 0
      docs/examples/en/exporters/GLTFExporter.html
  51. 74 13
      docs/examples/en/loaders/3DMLoader.html
  52. 15 4
      docs/examples/en/loaders/GLTFLoader.html
  53. 133 0
      docs/examples/en/loaders/KTX2Loader.html
  54. 0 1
      docs/examples/en/renderers/CSS3DRenderer.html
  55. 8 0
      docs/examples/zh/exporters/GLTFExporter.html
  56. 13 6
      docs/examples/zh/loaders/GLTFLoader.html
  57. 0 1
      docs/examples/zh/renderers/CSS3DRenderer.html
  58. 1 1
      docs/index.html
  59. 1 6
      docs/list.json
  60. 6 6
      docs/manual/ar/introduction/Installation.html
  61. 0 42
      docs/manual/ar/introduction/Typescript-setup.html
  62. 1 1
      docs/manual/ar/introduction/Useful-links.html
  63. 1 1
      docs/manual/en/introduction/Creating-a-scene.html
  64. 6 6
      docs/manual/en/introduction/Installation.html
  65. 0 45
      docs/manual/en/introduction/Typescript-setup.html
  66. 1 1
      docs/manual/en/introduction/Useful-links.html
  67. 15 15
      docs/manual/ko/introduction/Installation.html
  68. 0 41
      docs/manual/ko/introduction/Typescript-setup.html
  69. 2 2
      docs/manual/ko/introduction/Useful-links.html
  70. 4 4
      docs/manual/zh/introduction/Installation.html
  71. 0 40
      docs/manual/zh/introduction/Typescript-setup.html
  72. 1 1
      docs/manual/zh/introduction/Useful-links.html
  73. 2 1
      docs/scenes/material-browser.html
  74. 1 2
      editor/css/main.css
  75. 1 1
      editor/examples/shaders.app.json
  76. 3 1
      editor/index.html
  77. 25 22
      editor/js/Command.js
  78. 5 0
      editor/js/Editor.js
  79. 7 7
      editor/js/History.js
  80. 28 1
      editor/js/Menubar.Edit.js
  81. 8 4
      editor/js/Menubar.File.js
  82. 3 1
      editor/js/Menubar.Help.js
  83. 48 3
      editor/js/Menubar.View.js
  84. 2 0
      editor/js/Menubar.js
  85. 3 2
      editor/js/Script.js
  86. 2 2
      editor/js/Sidebar.Material.js
  87. 1 1
      editor/js/Sidebar.Object.js
  88. 82 0
      editor/js/Sidebar.Project.Materials.js
  89. 164 0
      editor/js/Sidebar.Project.Renderer.js
  90. 145 0
      editor/js/Sidebar.Project.Video.js
  91. 14 253
      editor/js/Sidebar.Project.js
  92. 10 10
      editor/js/Sidebar.Scene.js
  93. 2 2
      editor/js/Sidebar.Settings.History.js
  94. 8 4
      editor/js/Sidebar.Settings.Shortcuts.js
  95. 6 2
      editor/js/Sidebar.Settings.Viewport.js
  96. 12 8
      editor/js/Sidebar.Settings.js
  97. 1 7
      editor/js/Sidebar.js
  98. 9 0
      editor/js/Strings.js
  99. 1 1
      editor/js/Viewport.Info.js
  100. 155 0
      editor/js/Viewport.VR.js

File diff suppressed because it is too large
+ 779 - 429
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
+ 793 - 313
build/three.module.js


+ 0 - 100
docs/api/en/core/Face3.html

@@ -1,100 +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>
-
-		<p class="desc">
-		Triangular face used in deprecated geometry. These are created automatically for all
-		standard geometry types, however if you are building a custom geometry you will have to
-		create them manually.
-		</p>
-
-		<h2>Constructor</h2>
-
-		<h3>[name]( [param:Integer a], [param:Integer b], [param:Integer c], [param:Vector3 normal], [param:Color color], [param:Integer materialIndex] )</h3>
-		<p>
-		a — Vertex A index.<br />
-		b — Vertex B index.<br />
-		c — Vertex C index.<br /><br />
-
-		normal — (optional) Face normal ([page:Vector3 Vector3]) or array of vertex normals.
-		If a single vector is passed in, this sets [page:.normal], otherwise if an array of three
-		vectors is passed in this sets [page:.vertexNormals]<br /><br />
-
-		color — (optional) Face [page:Color color] or array of vertex [page:Color colors].
-		If a single vector is passed in, this sets [page:.color], otherwise if an array of three
-		vectors is passed in this sets [page:.vertexColors]<br /><br />
-
-		materialIndex — (optional) which index of an array of materials to associate
-		with the face.
-		</p>
-
-		<h2>Properties</h2>
-
-		<h3>[property:Integer a]</h3>
-		<p>
-		Vertex A index.
-		</p>
-
-		<h3>[property:Integer b]</h3>
-		<p>
-		Vertex B index.
-		</p>
-
-		<h3>[property:Integer c]</h3>
-		<p>
-		Vertex C index.
-		</p>
-
-		<h3>[property:Vector3 normal]</h3>
-		<p>
-		Face normal - vector showing the direction of the Face3. If calculated automatically,
-		this is the normalized cross product of two edges of the
-		triangle. Default is *(0, 0, 0)*.
-		</p>
-
-		<h3>[property:Color color]</h3>
-		<p>
-		Face color - for this to be used a material's [page:Material.vertexColors vertexColors] property
-		must be set to *true*.
-		</p>
-
-		<h3>[property:Array vertexNormals]</h3>
-		<p>
-		Array of 3 [page:Vector3 vertex normals].
-		</p>
-
-		<h3>[property:Array vertexColors]</h3>
-		<p>
-		Array of 3 vertex colors - for these to be used a material's [page:Material.vertexColors vertexColors] property
-		must be set to *true*.
-		</p>
-
-
-		<h3>[property:Integer materialIndex]</h3>
-		<p>
-		Material index (points to an index in the associated array of materials). Default is *0*.
-		</p>
-
-		<h2>Methods</h2>
-
-		<h3>[method:Face3 clone]()</h3>
-		<p>Creates a new clone of the Face3 object.</p>
-
-		<h3>[method:Face3 copy]( [param:Face3 face3] )</h3>
-		<p>Copy the parameters of another Face3 into this.</p>
-
-
-		<h2>Source</h2>
-
-		<p>
-			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-		</p>
-	</body>
-</html>

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

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

+ 1 - 1
docs/api/en/core/Raycaster.html

@@ -172,7 +172,7 @@
 		<p>
 			[page:Float distance] – distance between the origin of the ray and the intersection<br />
 			[page:Vector3 point] – point of intersection, in world coordinates<br />
-			[page:Face3 face] – intersected face<br />
+			[page:Object face] – intersected face<br />
 			[page:Integer faceIndex] – index of the intersected face<br />
 			[page:Object3D object] – the intersected object<br />
 			[page:Vector2 uv] - U,V coordinates at point of intersection<br />

+ 1 - 2
docs/api/en/extras/core/Font.html

@@ -18,8 +18,7 @@
 		<h2>Examples</h2>
 
 		<p>
-		[example:webgl_geometry_text_shapes geometry / text / shapes ]<br/>
-		[example:webgl_shaders_vector vector / text ]<br/>
+		[example:webgl_geometry_text_shapes geometry / text / shapes ]
 		</p>
 
 		<h2>Constructor</h2>

+ 1 - 2
docs/api/en/lights/DirectionalLight.html

@@ -50,8 +50,7 @@
 			[example:webgl_effects_parallaxbarrier effects / parallaxbarrier ]<br />
 			[example:webgl_effects_stereo effects / stereo ]<br />
 			[example:webgl_geometry_extrude_splines geometry / extrude / splines ]<br />
-			[example:webgl_materials_bumpmap materials / bumpmap ]<br />
-			[example:webgl_materials_cubemap_balls_reflection materials / cubemap / balls / reflection ]
+			[example:webgl_materials_bumpmap materials / bumpmap ]
 		</p>
 
 		<h2>Constructor</h2>

+ 0 - 1
docs/api/en/lights/PointLight.html

@@ -30,7 +30,6 @@ scene.add( light );
 
 		<p>
 			[example:webgl_lights_pointlights lights / pointlights ]<br />
-			[example:webgl_lights_pointlights2 lights / pointlights2 ]<br />
 			[example:webgl_effects_anaglyph effects / anaglyph ]<br />
 			[example:webgl_geometry_text geometry / text ]<br />
 			[example:webgl_lensflares lensflares ]

+ 0 - 2
docs/api/en/loaders/CubeTextureLoader.html

@@ -36,8 +36,6 @@ scene.background = new THREE.CubeTextureLoader()
 
 		<p>
 			[example:webgl_materials_cubemap materials / cubemap]<br />
-			[example:webgl_materials_cubemap_balls_reflection materials / cubemap / balls / reflection]<br />
-			[example:webgl_materials_cubemap_balls_refraction materials / cubemap / balls / refraction]<br />
 			[example:webgl_materials_cubemap_dynamic materials / cubemap / dynamic]<br />
 			[example:webgl_materials_cubemap_refraction materials / cubemap / refraction]
 		</p>

+ 3 - 3
docs/api/en/loaders/ImageBitmapLoader.html

@@ -12,14 +12,14 @@
 		<h1>[name]</h1>
 
 		<p class="desc">
-			A loader for loading an [page:Image] as an [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap].
+			A loader for loading an [page:Image] as an [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap].
 			An ImageBitmap provides an asynchronous and resource efficient pathway to prepare textures for rendering in WebGL.<br/>
 			Unlike [page:FileLoader], [name] does not avoid multiple concurrent requests to the same URL.
 		</p>
 
 		<p>
-			Note that [page:Texture.flipY] and [page:Texture.premultiplyAlpha] with [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap] are ignored.
-			[link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap] needs these configuration on bitmap creation
+			Note that [page:Texture.flipY] and [page:Texture.premultiplyAlpha] with [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap] are ignored.
+			[link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap] needs these configuration on bitmap creation
 			unlike regular images need them on uploading to GPU. You need to set the equivalent options via [page:ImageBitmapLoader.setOptions]
 			instead. Refer to [link:https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.10 WebGL specification] for the detail.
 		</p>

+ 1 - 1
docs/api/en/materials/LineBasicMaterial.html

@@ -27,7 +27,7 @@
 		<h2>Examples</h2>
 
 		<p>
-			[example:webgl_buffergeometry_drawcalls WebGL / buffergeometry / drawcalls]<br />
+			[example:webgl_buffergeometry_drawrange WebGL / buffergeometry / drawrange]<br />
 			[example:webgl_buffergeometry_lines WebGL / buffergeometry / lines]<br />
 			[example:webgl_buffergeometry_lines_indexed WebGL / buffergeometry / lines / indexed]<br />
 			[example:webgl_decals WebGL / decals]<br />

+ 0 - 5
docs/api/en/materials/Material.html

@@ -162,11 +162,6 @@
 		Which stencil operation to perform when the comparison function returns true and the depth test passes. Default is [page:Materials KeepStencilOp]. See the stencil operations [page:Materials constants] for all possible values.
 		</p>
 
-		<h3>[property:Boolean flatShading]</h3>
-		<p>
-		Define whether the material is rendered with flat shading. Default is false.
-		</p>
-
 		<h3>[property:Boolean fog]</h3>
 		<p>Whether the material is affected by fog. Default is *true*.</p>
 

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

@@ -95,6 +95,11 @@
 			Without a displacement map set, this value is not applied. Default is 0.
 		</p>
 
+		<h3>[property:Boolean flatShading]</h3>
+		<p>
+		Define whether the material is rendered with flat shading. Default is false.
+		</p>
+
 		<h3>[property:Texture map]</h3>
 		<p>The color map. Default is null. The texture map color is modulated by the diffuse [page:.color].</p>
 

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

@@ -75,6 +75,11 @@
 			Without a displacement map set, this value is not applied. Default is 0.
 		</p>
 
+		<h3>[property:Boolean flatShading]</h3>
+		<p>
+		Define whether the material is rendered with flat shading. Default is false.
+		</p>
+
 		<h3>[property:Boolean fog]</h3>
 		<p>Whether the material is affected by fog. Default is *false*.</p>
 

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

@@ -142,6 +142,11 @@
 		<h3>[property:Texture envMap]</h3>
 		<p>The environment map. Default is null.</p>
 
+		<h3>[property:Boolean flatShading]</h3>
+		<p>
+		Define whether the material is rendered with flat shading. Default is false.
+		</p>
+
 		<h3>[property:Texture lightMap]</h3>
 		<p>The light map. Default is null. The lightMap requires a second set of UVs.</p>
 

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

@@ -172,6 +172,10 @@
 		<h3>[property:Float envMapIntensity]</h3>
 		<p>Scales the effect of the environment map by multiplying its color.</p>
 
+		<h3>[property:Boolean flatShading]</h3>
+		<p>
+		Define whether the material is rendered with flat shading. Default is false.
+		</p>
 
 		<h3>[property:Texture lightMap]</h3>
 		<p>The light map. Default is null. The lightMap requires a second set of UVs.</p>

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

@@ -40,7 +40,7 @@
 		<h2>Examples</h2>
 		<p>
 			[example:misc_controls_fly misc / controls / fly]<br />
-			[example:webgl_buffergeometry_drawcalls WebGL / BufferGeometry / drawcalls]<br />
+			[example:webgl_buffergeometry_drawrange WebGL / BufferGeometry / drawrange]<br />
 			[example:webgl_buffergeometry_points WebGL / BufferGeometry / points]<br />
 			[example:webgl_buffergeometry_points_interleaved WebGL / BufferGeometry / points / interleaved]<br />
 			[example:webgl_camera WebGL / camera ]<br />

+ 4 - 4
docs/api/en/materials/RawShaderMaterial.html

@@ -33,11 +33,11 @@
 		<p>
 			[example:webgl_buffergeometry_rawshader WebGL / buffergeometry / rawshader]<br />
 			[example:webgl_buffergeometry_instancing_billboards WebGL / buffergeometry / instancing / billboards]<br />
-			[example:webgl_buffergeometry_instancing_dynamic WebGL / buffergeometry / instancing / dynamic]<br />
-			[example:webgl_buffergeometry_instancing_interleaved_dynamic WebGL / buffergeometry / instancing / interleaved / dynamic]<br />
 			[example:webgl_buffergeometry_instancing WebGL / buffergeometry / instancing]<br />
-			[example:webgl_interactive_instances_gpu WebGL / interactive / instances /gpu]<br />
-			[example:webgl_raymarching_reflect WebGL / raymarching / reflect]
+			[example:webgl_raymarching_reflect WebGL / raymarching / reflect]<br />
+			[example:webgl2_volume_cloud WebGL 2 / volume / cloud]<br />
+			[example:webgl2_volume_instancing WebGL 2 / volume / instancing]<br />
+			[example:webgl2_volume_perlin WebGL 2 / volume / perlin]
 		</p>
 
 		<h2>Constructor</h2>

+ 1 - 4
docs/api/en/materials/ShaderMaterial.html

@@ -103,17 +103,14 @@
 			[example:webgl_gpgpu_birds webgl / gpgpu / birds]<br />
 			[example:webgl_gpgpu_protoplanet webgl / gpgpu / protoplanet]<br />
 			[example:webgl_gpgpu_water webgl / gpgpu / water]<br />
-			[example:webgl_hdr webgl / hdr]<br />
 			[example:webgl_interactive_points webgl / interactive / points]<br />
-			[example:webgl_kinect webgl / kinect]<br />
+			[example:webgl_video_kinect webgl / video / kinect]<br />
 			[example:webgl_lights_hemisphere webgl / lights / hemisphere]<br />
 			[example:webgl_marchingcubes webgl / marchingcubes]<br />
-			[example:webgl_materials_bumpmap_skin webgl / materials / bumpmap / skin]<br />
 			[example:webgl_materials_envmaps webgl / materials / envmaps]<br />
 			[example:webgl_materials_lightmap webgl / materials / lightmap]<br />
 			[example:webgl_materials_parallaxmap webgl / materials / parallaxmap]<br />
 			[example:webgl_materials_shaders_fresnel webgl / materials / shaders / fresnel]<br />
-			[example:webgl_materials_skin webgl / materials / skin]<br />
 			[example:webgl_materials_wireframe webgl / materials / wireframe]<br />
 			[example:webgl_modifier_tessellation webgl / modifier / tessellation]<br />
 			[example:webgl_postprocessing_dof2 webgl / postprocessing / dof2]<br />

+ 3 - 4
docs/api/en/materials/SpriteMaterial.html

@@ -26,10 +26,9 @@
 
 		<h2>Examples</h2>
 		<p>
-			[example:webgl_sprites webGL / sprites]<br />
-			[example:software_sandbox software / sandbox]<br />
-			[example:svg_sandbox svg / sandbox]<br />
-			[example:webgl_materials_cubemap_dynamic webgl / materials / cubemap / dynamic]
+			[example:webgl_raycast_sprite WebGL / raycast / sprite]<br />
+			[example:webgl_sprites WebGL / sprites]<br />
+			[example:svg_sandbox SVG / sandbox]
 		</p>
 
 		<h2>Constructor</h2>

+ 3 - 2
docs/api/en/renderers/WebGLCubeRenderTarget.html

@@ -36,12 +36,13 @@
 		[page:Constant wrapT] - default is [page:Textures ClampToEdgeWrapping]. <br />
 		[page:Constant magFilter] - default is [page:Textures .LinearFilter]. <br />
 		[page:Constant minFilter] - default is [page:Textures LinearFilter]. <br />
+		[page:Boolean generateMipmaps] - default is *false*.<br />
 		[page:Constant format] - default is [page:Textures RGBAFormat]. <br />
 		[page:Constant type] - default is [page:Textures UnsignedByteType]. <br />
 		[page:Number anisotropy] - default is *1*. See [page:Texture.anistropy]<br />
 		[page:Constant encoding] - default is [page:Textures LinearEncoding]. <br />
-		[page:Boolean depthBuffer] - default is *true*. Set this to false if you don't need it. <br />
-		[page:Boolean stencilBuffer] - default is *false*. Set this to true if you need it.<br /><br />
+		[page:Boolean depthBuffer] - default is *true*.<br />
+		[page:Boolean stencilBuffer] - default is *false*.<br /><br />
 
 		Creates a new [name]
 		</p>

+ 3 - 2
docs/api/en/renderers/WebGLRenderTarget.html

@@ -35,12 +35,13 @@
 		[page:Constant wrapT] - default is [page:Textures ClampToEdgeWrapping]. <br />
 		[page:Constant magFilter] - default is [page:Textures LinearFilter]. <br />
 		[page:Constant minFilter] - default is [page:Textures LinearFilter]. <br />
+		[page:Boolean generateMipmaps] - default is *false*.<br />
 		[page:Constant format] - default is [page:Textures RGBAFormat]. <br />
 		[page:Constant type] - default is [page:Textures UnsignedByteType]. <br />
 		[page:Number anisotropy] - default is *1*. See [page:Texture.anisotropy]<br />
 		[page:Constant encoding] - default is [page:Textures LinearEncoding]. <br />
-		[page:Boolean depthBuffer] - default is *true*. Set this to false if you don't need it. <br />
-		[page:Boolean stencilBuffer] - default is *false*. Set this to true if you need it.<br /><br />
+		[page:Boolean depthBuffer] - default is *true*. <br />
+		[page:Boolean stencilBuffer] - default is *false*.<br /><br />
 
 		Creates a new [name]
 		</p>

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

@@ -310,6 +310,9 @@
 		<h3>[method:null copyTextureToTexture]( [param:Vector2 position], [param:Texture srcTexture], [param:Texture dstTexture], [param:Number level] )</h3>
 		<p>Copies all pixels of a texture to an existing texture starting from the given position. Enables access to [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGLRenderingContext/texSubImage2D WebGLRenderingContext.texSubImage2D].</p>
 
+		<h3>[method:null copyTextureToTexture3D]( [param:Box3 sourceBox], [param:Vector2 position], [param:Texture srcTexture], [param:Texture dstTexture], [param:Number level] )</h3>
+		<p>Copies the pixels of a texture in the bounds '[page:Box3 sourceBox]' in the desination texture starting from the given position. Enables access to [link:https://developer.mozilla.org/en-US/docs/Web/API/WebGL2RenderingContext/texSubImage3D WebGL2RenderingContext.texSubImage3D].</p>
+
 		<h3>[method:null dispose]( )</h3>
 		<p>Dispose of the current rendering context.</p>
 

+ 2 - 2
docs/api/en/textures/Texture.html

@@ -191,7 +191,7 @@
 		<p>
 		If set to *true*, the alpha channel, if present, is multiplied into the color channels when the texture is uploaded to the GPU. Default is *false*.<br /><br />
 
-		Note that this property has no effect for [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap].
+		Note that this property has no effect for [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap].
 		You need to configure on bitmap creation instead. See [page:ImageBitmapLoader].
 		</p>
 
@@ -199,7 +199,7 @@
 		<p>
 		If set to *true*, the texture is flipped along the vertical axis when uploaded to the GPU. Default is *true*.<br /><br />
 
-		Note that this property has no effect for [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap].
+		Note that this property has no effect for [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap].
 		You need to configure on bitmap creation instead. See [page:ImageBitmapLoader].
 		</p>
 

+ 0 - 96
docs/api/zh/core/Face3.html

@@ -1,96 +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>
-
-		<p class="desc">
-			在 deprecated geometry 中被使用到的三角形面。这些三角形面会为所有标准几何体自动创建。
-			然而,如果你正在构建一个自定义几何体,你需要手动创建这些三角形面。
-		</p>
-
-		<h2>构造函数</h2>
-
-		<h3>[name]( [param:Integer a], [param:Integer b], [param:Integer c], [param:Vector3 normal], [param:Color color], [param:Integer materialIndex] )</h3>
-		<p>
-			a — 顶点 A 的索引。<br />
-			b — 顶点 B 的索引。<br />
-			c — 顶点 C 的索引。<br /><br />
-
-			normal — (可选) 面的法向量 ([page:Vector3 Vector3]) 或顶点法向量队列。
-			如果参数传入单一矢量,则用该量设置面的法向量 [page:.normal],如果传入的是包含三个矢量的队列,
-			则用该量设置 [page:.vertexNormals]<br /><br />
-
-			color — (可选) 面的颜色值 [page:Color color] 或顶点颜色值的队列。
-			如果参数传入单一矢量,则用该量设置 [page:.color],如果传入的是包含三个矢量的队列,
-			则用该量设置 [page:.vertexColors]<br /><br />
-
-			materialIndex — (可选) 材质队列中与该面对应的材质的索引。
-		</p>
-
-		<h2>属性</h2>
-
-		<h3>[property:Integer a]</h3>
-		<p>
-			顶点 A 的索引。
-		</p>
-
-		<h3>[property:Integer b]</h3>
-		<p>
-			顶点 B 的索引。
-		</p>
-
-		<h3>[property:Integer c]</h3>
-		<p>
-			顶点 C 的索引。
-		</p>
-
-		<h3>[property:Vector3 normal]</h3>
-		<p>
-			面的法向量 - 矢量展示 Face3 的方向。如果该量是通过调用自动计算的,
-			该值等于归一化的两条边的差积。默认值是 *(0, 0, 0)*。
-		</p>
-
-		<h3>[property:Color color]</h3>
-		<p>
-			面的颜色值 - 在被用于指定材质的 [page:Material.vertexColors vertexColors] 属性时,该值必须被设置为
-			*true*。
-		</p>
-
-		<h3>[property:Array vertexNormals]</h3>
-		<p>
-			包含三个 [page:Vector3 vertex normals] 的队列。
-		</p>
-
-		<h3>[property:Array vertexColors]</h3>
-		<p>
-			包含 3 个顶点颜色值的队列 - 在被用于指定材质的 [page:Material.vertexColors vertexColors] 属性时,该值必须被设置为
-			*true*。
-		</p>
-
-		<h3>[property:Integer materialIndex]</h3>
-		<p>
-			材质队列中与该面相关的材质的索引。默认值为 *0*。
-		</p>
-
-		<h2>方法</h2>
-
-		<h3>[method:Face3 clone]()</h3>
-		<p>克隆该 Face3 对象。</p>
-
-		<h3>[method:Face3 copy]( [param:Face3 face3] )</h3>
-		<p>将参数指定的 Face3 对象的数据拷贝到当前对象。</p>
-
-
-		<h2>源代码</h2>
-
-		<p>
-			[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-		</p>
-	</body>
-</html>

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

@@ -51,8 +51,7 @@
 
 	<h3>[property:Boolean frustumCulled]</h3>
 	<p>
-		当这个属性被设置的时候,它将在渲染物体之前,检查每一帧的物体是否在摄像机的视锥体中。
-		否则,即使该物体不可见,它也将在每一帧中被渲染,默认值为*true*。
+		When this is set, it checks every frame if the object is in the frustum of the camera before rendering the object. If set to `false` the object gets rendered every frame even if it is not in the frustum of the camera. Default is `true`.
 	</p>
 
 	<h3>[property:Integer id]</h3>

+ 1 - 1
docs/api/zh/core/Raycaster.html

@@ -175,7 +175,7 @@
 		<p>
 			[page:Float distance] —— 射线投射原点和相交部分之间的距离。<br />
 			[page:Vector3 point] —— 相交部分的点(世界坐标)<br />
-			[page:Face3 face] —— 相交的面<br />
+			[page:Object face] —— 相交的面<br />
 			[page:Integer faceIndex] —— 相交的面的索引<br />
 			[page:Object3D object] —— 相交的物体<br />
 			[page:Vector2 uv] —— 相交部分的点的UV坐标。<br />

+ 1 - 2
docs/api/zh/extras/core/Font.html

@@ -19,8 +19,7 @@
 		<h2>例子</h2>
 
 		<p>
-		[example:webgl_geometry_text_shapes geometry / text / shapes ]<br/>
-		[example:webgl_shaders_vector vector / text ]<br/>
+		[example:webgl_geometry_text_shapes geometry / text / shapes ]
 		</p>
 
 		<h2>构造函数</h2>

+ 1 - 2
docs/api/zh/lights/DirectionalLight.html

@@ -46,8 +46,7 @@
 			[example:webgl_effects_parallaxbarrier effects / parallaxbarrier ]<br />
 			[example:webgl_effects_stereo effects / stereo ]<br />
 			[example:webgl_geometry_extrude_splines geometry / extrude / splines ]<br />
-			[example:webgl_materials_bumpmap materials / bumpmap ]<br />
-			[example:webgl_materials_cubemap_balls_reflection materials / cubemap / balls / reflection ]
+			[example:webgl_materials_bumpmap materials / bumpmap ]
 		</p>
 
 		<h2>构造器</h2>

+ 0 - 1
docs/api/zh/lights/PointLight.html

@@ -29,7 +29,6 @@
 
 		<p>
 			[example:webgl_lights_pointlights lights / pointlights ]<br />
-			[example:webgl_lights_pointlights2 lights / pointlights2 ]<br />
 			[example:webgl_effects_anaglyph effects / anaglyph ]<br />
 			[example:webgl_geometry_text geometry / text ]<br />
 			[example:webgl_lensflares lensflares ]

+ 0 - 2
docs/api/zh/loaders/CubeTextureLoader.html

@@ -36,8 +36,6 @@ scene.background = new THREE.CubeTextureLoader()
 
 		<p>
 			[example:webgl_materials_cubemap materials / cubemap]<br />
-			[example:webgl_materials_cubemap_balls_reflection materials / cubemap / balls / reflection]<br />
-			[example:webgl_materials_cubemap_balls_refraction materials / cubemap / balls / refraction]<br />
 			[example:webgl_materials_cubemap_dynamic materials / cubemap / dynamic]<br />
 			[example:webgl_materials_cubemap_refraction materials / cubemap / refraction]
 		</p>

+ 3 - 3
docs/api/zh/loaders/ImageBitmapLoader.html

@@ -12,14 +12,14 @@
 		<h1>[name]</h1>
 
 		<p class="desc">
-			一个把[page:Image]加载为[link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap]的加载器。
+			一个把[page:Image]加载为[link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap]的加载器。
 			ImageBitmap提供了一种异步且有效的资源的途径,用于在WebGL中渲染的纹理。<br/>
 			不像[page:FileLoader], [name]无需避免对同一的URL进行多次请求。
 		</p>
 
 		<p>
-			Note that [page:Texture.flipY] and [page:Texture.premultiplyAlpha] with [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap] are ignored.
-			[link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap] needs these configuration on bitmap creation
+			Note that [page:Texture.flipY] and [page:Texture.premultiplyAlpha] with [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap] are ignored.
+			[link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap] needs these configuration on bitmap creation
 			unlike regular images need them on uploading to GPU. You need to set the equivalent options via [page:ImageBitmapLoader.setOptions]
 			instead. Refer to [link:https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.10 WebGL specification] for the detail.
 		</p>

+ 1 - 1
docs/api/zh/materials/LineBasicMaterial.html

@@ -27,7 +27,7 @@
 		<h2>例子</h2>
 
 		<p>
-			[example:webgl_buffergeometry_drawcalls WebGL / buffergeometry / drawcalls]<br />
+			[example:webgl_buffergeometry_drawrange WebGL / buffergeometry / drawrange]<br />
 			[example:webgl_buffergeometry_lines WebGL / buffergeometry / lines]<br />
 			[example:webgl_buffergeometry_lines_indexed WebGL / buffergeometry / lines / indexed]<br />
 			[example:webgl_decals WebGL / decals]<br />

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

@@ -142,10 +142,6 @@ Which stencil operation to perform when the comparison function returns true but
 Which stencil operation to perform when the comparison function returns true and the depth test passes. Default is [page:Materials KeepStencilOp]. See the stencil operations [page:Materials constants] for all possible values.
 </p>
 
-<h3>[property:Boolean flatShading]</h3>
-<p> 定义材质是否使用平面着色进行渲染。默认值为false。
-</p>
-
 <h3>[property:Boolean fog]</h3>
 <p>材质是否受雾影响。默认为*true*。</p>
 

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

@@ -80,6 +80,10 @@
 			位移贴图在网格顶点上的偏移量。如果没有设置位移贴图,则不会应用此值。默认值为0。
 		</p>
 
+		<h3>[property:Boolean flatShading]</h3>
+		<p> 定义材质是否使用平面着色进行渲染。默认值为false。
+		</p>
+
 		<h3>[property:Texture map]</h3>
 		<p>颜色贴图。默认为null。纹理贴图颜色由漫反射颜色[page:.color]调节。</p>
 

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

@@ -62,6 +62,10 @@
 			位移贴图在网格顶点上的偏移量。如果没有设置位移贴图,则不会应用此值。默认值为0。
 		</p>
 
+		<h3>[property:Boolean flatShading]</h3>
+		<p> 定义材质是否使用平面着色进行渲染。默认值为false。
+		</p>
+
 		<h3>[property:Boolean fog]</h3>
 		<p>材质是否受雾影响。默认值为*false*。</p>
 

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

@@ -112,6 +112,9 @@
 		<h3>[property:Texture envMap]</h3>
 		<p>环境贴图。默认值为null。</p>
 
+		<h3>[property:Boolean flatShading]</h3>
+		<p> 定义材质是否使用平面着色进行渲染。默认值为false。
+		</p>
 
 		<h3>[property:Texture lightMap]</h3>
 		<p>光照贴图。默认值为null。lightMap需要第二组UV。</p>

+ 4 - 4
docs/api/zh/materials/MeshPhysicalMaterial.html

@@ -11,8 +11,8 @@
 
 		<h1>物理网格材质([name])</h1>
 
-		<p class="desc"> [page:MeshStandardMaterial]的扩展,能够更好地控制反射率。<br /><br />
-			请注意,为了获得最佳效果,您在使用此材质时应始终指定环境贴图。
+		<p class="desc">
+			[page:MeshStandardMaterial]的扩展,提供了更高级的基于物理的渲染属性:
 		</p>
 
 		<ul>
@@ -70,13 +70,13 @@
 
 		<h3>[name]( [param:Object parameters] )</h3>
 		<p> [page:Object parameters] - (可选)用于定义材质外观的对象,具有一个或多个属性。
-			材质的任何属性都可以从此处传入(包括从[page:Material]继承的任何属性)<br /><br />
+			材质的任何属性都可以从此处传入(包括从[page:Material]和[page:MeshStandardMaterial]继承的任何属性)<br /><br />
 			属性[page:Hexadecimal color]例外,其可以作为十六进制字符串传递,默认情况下为 *0xffffff*(白色),内部调用[page:Color.set](color)。
 		</p>
 
 
 		<h2>属性(Properties)</h2>
-		<p>共有属性请参见其基类[page:Material]。</p>
+		<p>共有属性请参见其基类[page:Material]和[page:MeshStandardMaterial]。</p>
 
 		<h3>[property:Float clearcoat]</h3>
 		<p>

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

@@ -140,6 +140,9 @@
 		<h3>[property:Float envMapIntensity]</h3>
 		<p> 通过乘以环境贴图的颜色来缩放环境贴图的效果。</p>
 
+		<h3>[property:Boolean flatShading]</h3>
+		<p> 定义材质是否使用平面着色进行渲染。默认值为false。
+		</p>
 
 		<h3>[property:Texture lightMap]</h3>
 		<p>光照贴图。默认值为null。lightMap需要第二组UV。</p>

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

@@ -41,7 +41,7 @@
 		<h2>例子</h2>
 		<p>
 			[example:misc_controls_fly misc / controls / fly]<br />
-			[example:webgl_buffergeometry_drawcalls WebGL / BufferGeometry / drawcalls]<br />
+			[example:webgl_buffergeometry_drawrange WebGL / BufferGeometry / drawrange]<br />
 			[example:webgl_buffergeometry_points WebGL / BufferGeometry / points]<br />
 			[example:webgl_buffergeometry_points_interleaved WebGL / BufferGeometry / points / interleaved]<br />
 			[example:webgl_camera WebGL / camera ]<br />

+ 4 - 4
docs/api/zh/materials/RawShaderMaterial.html

@@ -32,11 +32,11 @@
 		<p>
 			[example:webgl_buffergeometry_rawshader WebGL / buffergeometry / rawshader]<br />
 			[example:webgl_buffergeometry_instancing_billboards WebGL / buffergeometry / instancing / billboards]<br />
-			[example:webgl_buffergeometry_instancing_dynamic WebGL / buffergeometry / instancing / dynamic]<br />
-			[example:webgl_buffergeometry_instancing_interleaved_dynamic WebGL / buffergeometry / instancing / interleaved / dynamic]<br />
 			[example:webgl_buffergeometry_instancing WebGL / buffergeometry / instancing]<br />
-			[example:webgl_interactive_instances_gpu WebGL / interactive / instances /gpu]<br />
-			[example:webgl_raymarching_reflect WebGL / raymarching / reflect]
+			[example:webgl_raymarching_reflect WebGL / raymarching / reflect]<br />
+			[example:webgl2_volume_cloud WebGL 2 / volume / cloud]<br />
+			[example:webgl2_volume_instancing WebGL 2 / volume / instancing]<br />
+			[example:webgl2_volume_perlin WebGL 2 / volume / perlin]
 		</p>
 
 		<h2>构造函数(Constructor)</h2>

+ 1 - 5
docs/api/zh/materials/ShaderMaterial.html

@@ -93,18 +93,14 @@
 			[example:webgl_gpgpu_birds webgl / gpgpu / birds]<br />
 			[example:webgl_gpgpu_protoplanet webgl / gpgpu / protoplanet]<br />
 			[example:webgl_gpgpu_water webgl / gpgpu / water]<br />
-			[example:webgl_hdr webgl / hdr]<br />
 			[example:webgl_interactive_points webgl / interactive / points]<br />
-			[example:webgl_kinect webgl / kinect]<br />
+			[example:webgl_video_kinect webgl / video / kinect]<br />
 			[example:webgl_lights_hemisphere webgl / lights / hemisphere]<br />
 			[example:webgl_marchingcubes webgl / marchingcubes]<br />
-			[example:webgl_materials_bumpmap_skin webgl / materials / bumpmap / skin]<br />
 			[example:webgl_materials_envmaps webgl / materials / envmaps]<br />
 			[example:webgl_materials_lightmap webgl / materials / lightmap]<br />
 			[example:webgl_materials_parallaxmap webgl / materials / parallaxmap]<br />
 			[example:webgl_materials_shaders_fresnel webgl / materials / shaders / fresnel]<br />
-			[example:webgl_materials_skin webgl / materials / skin]<br />
-			[example:webgl_materials_texture_hdr webgl / materials / texture / hdr]<br />
 			[example:webgl_materials_wireframe webgl / materials / wireframe]<br />
 			[example:webgl_modifier_tessellation webgl / modifier / tessellation]<br />
 			[example:webgl_postprocessing_dof2 webgl / postprocessing / dof2]<br />

+ 2 - 3
docs/api/zh/materials/SpriteMaterial.html

@@ -26,10 +26,9 @@
 
 		<h2>例子</h2>
 		<p>
+			[example:webgl_raycast_sprite WebGL / raycast / sprite]<br />
 			[example:webgl_sprites WebGL / sprites]<br />
-			[example:software_sandbox software / sandbox]<br />
-			[example:svg_sandbox svg / sandbox]<br />
-			[example:webgl_materials_cubemap_dynamic webgl / materials / cubemap / dynamic]
+			[example:svg_sandbox SVG / sandbox]
 		</p>
 
 		<h2>构造函数(Constructor)</h2>

+ 1 - 1
docs/api/zh/math/MathUtils.html

@@ -104,7 +104,7 @@
 		<p>
 		[page:Float x] - 根据其在最小值和最大值之间的位置来计算的值。 <br />
 		[page:Float min] - 任何x比最小值还小会返回0.<br />
-		[page:Float max] - 任何x比最大值还大会返回0.<br /><br />
+		[page:Float max] - 任何x比最大值还大会返回1.<br /><br />
 
 		返回0-1之间的值,该值表示x在最小值和最大值之间移动的百分比,但是当x接近最小值和最大值时,变化程度会平滑或减慢。<br/><br/>
 

+ 3 - 2
docs/api/zh/renderers/WebGLCubeRenderTarget.html

@@ -33,12 +33,13 @@
 		[page:Constant wrapT] - 默认是[page:Textures ClampToEdgeWrapping]. <br />
 		[page:Constant magFilter] - 默认是[page:Textures .LinearFilter]. <br />
 		[page:Constant minFilter] - 默认是[page:Textures LinearFilter]. <br />
+		[page:Boolean generateMipmaps] - 默认是*false*.<br />
 		[page:Constant format] - 默认是[page:Textures RGBAFormat]. <br />
 		[page:Constant type] - 默认是[page:Textures UnsignedByteType]. <br />
 		[page:Number anisotropy] - 默认是 *1*. 参见[page:Texture.anistropy]<br />
 		[page:Constant encoding] - 默认是[page:Textures LinearEncoding]. <br />
-		[page:Boolean depthBuffer] - 默认是*true*.如果不需要就设为false <br />
-		[page:Boolean stencilBuffer] - default is *false*. Set this to true if you need it.<br /><br />
+		[page:Boolean depthBuffer] - 默认是*true*.<br />
+		[page:Boolean stencilBuffer] - default is *false*.<br /><br />
 
 		创建一个新[name]
 		</p>

+ 3 - 2
docs/api/zh/renderers/WebGLRenderTarget.html

@@ -31,12 +31,13 @@
 		[page:Constant wrapT] - 默认是[page:Textures ClampToEdgeWrapping]. <br />
 		[page:Constant magFilter] - 默认是[page:Textures LinearFilter]. <br />
 		[page:Constant minFilter] - 默认是[page:Textures LinearFilter]. <br />
+		[page:Boolean generateMipmaps] - 默认是*false*.<br />
 		[page:Constant format] - 默认是[page:Textures RGBAFormat]. <br />
 		[page:Constant type] - 默认是[page:Textures UnsignedByteType]. <br />
 		[page:Number anisotropy] - 默认是*1*. 参见[page:Texture.anisotropy]<br />
 		[page:Constant encoding] - 默认是[page:Textures LinearEncoding]. <br />
-		[page:Boolean depthBuffer] - 默认是*true*. 如果不需要就设为false <br />
-		[page:Boolean stencilBuffer] - default is *false*. Set this to true if you need it.<br /><br />
+		[page:Boolean depthBuffer] - 默认是*true*.<br />
+		[page:Boolean stencilBuffer] - 默认是*false*.<br /><br />
 
 		创建一个新[name]
 		</p>

+ 3 - 3
docs/api/zh/renderers/WebGLRenderer.html

@@ -143,9 +143,9 @@
 		<p>默认是 *2*. </p>
 
 		<h3>[property:number outputEncoding]</h3>
-		<p>Defines the output encoding of the renderer. Default is [page:Textures THREE.LinearEncoding].</p>
-		<p>If a render target has been set using [page:WebGLRenderer.setRenderTarget .setRenderTarget] then renderTarget.texture.encoding will be used instead.</p>
-		<p>See the [page:Textures texture constants] page for details of other formats.</p>
+		<p>定义渲染器的输出编码。默认为[page:Textures THREE.LinearEncoding]</p>
+		<p>如果渲染目标已经使用 [page:WebGLRenderer.setRenderTarget .setRenderTarget]、之后将直接使用renderTarget.texture.encoding</p>
+		<p>查看[page:Textures texture constants]页面以获取其他格式细节</p>
 
 		<h3>[property:Object info]</h3>
 		<p>一个对象,包含有关图形板内存和渲染过程的一系列统计信息。这些信息可用于调试或仅仅满足下好奇心。改对象包含以下字段:</p>

+ 2 - 2
docs/api/zh/textures/Texture.html

@@ -190,7 +190,7 @@
 		<p>
 		If set to *true*, the alpha channel, if present, is multiplied into the color channels when the texture is uploaded to the GPU. Default is *false*.<br /><br />
 
-		Note that this property has no effect for [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap].
+		Note that this property has no effect for [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap].
 		You need to configure on bitmap creation instead. See [page:ImageBitmapLoader].
 		</p>
 
@@ -198,7 +198,7 @@
 		<p>
 		If set to *true*, the texture is flipped along the vertical axis when uploaded to the GPU. Default is *true*.<br /><br />
 
-		Note that this property has no effect for [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap].
+		Note that this property has no effect for [link:https://developer.mozilla.org/en-US/docs/Web/API/ImageBitmap ImageBitmap].
 		You need to configure on bitmap creation instead. See [page:ImageBitmapLoader].
 		</p>
 

+ 8 - 0
docs/examples/en/exporters/GLTFExporter.html

@@ -33,6 +33,14 @@
 			<li>KHR_texture_transform</li>
 		</ul>
 
+		<p>
+			The following glTF 2.0 extension is supported by an external user plugin
+		</p>
+
+		<ul>
+			<li>[link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]</li>
+		</ul>
+
 		<h2>Code Example</h2>
 
 		<code>

+ 74 - 13
docs/examples/en/loaders/3DMLoader.html

@@ -12,15 +12,15 @@
 
 		<p class="desc">
 			A loader for Rhinoceros 3d files and objects. <br /><br />
-			Rhinoceros is a 3D modeler used to create, edit, analyze, document, render, animate, and translate NURBS curves, surfaces, solids, point clouds, as well as polygon meshes and SubD objects.
+			Rhinoceros is a 3D modeler used to create, edit, analyze, document, render, animate, and translate NURBS curves, surfaces, breps, extrusions, point clouds, as well as polygon meshes and SubD objects.
 			[link:https://github.com/mcneel/rhino3dm rhino3dm.js] is compiled to WebAssembly from the open source geometry library [link:https://github.com/mcneel/opennurbs openNURBS].
-			Currently uses rhino3dm.js 0.13.0
+			The loader currently uses <a href="https://www.npmjs.com/package/rhino3dm/v/0.15.0-beta">rhino3dm.js 0.15.0-beta.</a>
 		</p>
 
 		<h2>Supported Conversions</h2>
 
 		<p>
-			[name] loads the following objects to a respective three.js type:
+			The [name] converts Rhino objects to the following three.js types:
 		</p>
 
 		<table>
@@ -42,7 +42,7 @@
 			</tr>
 			<tr>
 				<td>Curve</td>
-				<td>[page:Line Line] <sup>1</sup></td>
+				<td>[page:Line Line] <sup> 1</sup></td>
 			</tr>
 			<tr>
 				<td>Mesh</td>
@@ -50,15 +50,15 @@
 			</tr>
 			<tr>
 				<td>Extrusion</td>
-				<td>[page:Mesh Mesh] <sup> 2</sup></td>
+				<td>[page:Mesh Mesh]<sup> 2</sup></td>
 			</tr>
 			<tr>
 				<td>BREP</td>
-				<td>[page:Object3D Object3D] <sup>2, 3</sup></td>
+				<td>[page:Mesh Mesh]<sup> 2</sup></td>
 			</tr>
 			<tr>
 				<td>SubD</td>
-				<td>[page:Mesh Mesh] <sup>4</sup></td>
+				<td>[page:Mesh Mesh]<sup> 3</sup></td>
 			</tr>
 			<tr>
 				<td>InstanceReferences</td>
@@ -80,19 +80,26 @@
 				<td>SpotLight</td>
 				<td>[page:SpotLight SpotLight]</td>
 			</tr>
+			<tr>
+				<td>File3dm</td>
+				<td>[page:Object3D Object3D]<sup> 4</sup></td>
+			</tr>
 		</table>
 
 		<p><i>
 			<sup>1</sup> NURBS curves are discretized to a hardcoded resolution.
 		</i></p>
 		<p><i>
-			<sup>2</sup> Types which are based on BREPs and NURBS surfaces are represented with their "Render Mesh".
+			<sup>2</sup> Types which are based on BREPs and NURBS surfaces are represented with their "Render Mesh". Render meshes might not be associated with these objects if they have not been displayed in an appropriate display mode in Rhino (i.e. "Shaded", "Rendered", etc), or are created programmatically, for example, via Grasshopper or directly with the rhino3dm library.
+		</i></p>
+		<p><i>
+			<sup>3</sup> SubD objects are represented by subdividing their control net.
 		</i></p>
 		<p><i>
-			<sup>3</sup> BREPS are converted to an Object3D with it's children array populated with BREP Faces
+			<sup>4</sup> Whether a Rhino Document (File3dm) is loaded or parsed, the returned object is an [page:Object3D Object3D] with all Rhino objects (File3dmObject) as children.
 		</i></p>
 		<p><i>
-			<sup>4</sup> SubD objects are represented by subdividing their control net.
+			<sup>5</sup> All resulting three.js objects have useful properties from the Rhino object (i.e. layer index, name, etc.) populated in their userData object.
 		</i></p>
 
 		<h2>Code Example</h2>
@@ -101,8 +108,9 @@
 		// Instantiate a loader
 		const loader = new Rhino3dmLoader();
 
-		// Specify path to a folder containing WASM/JS libraries.
-		loader.setLibraryPath( '/examples/jsm/libs/rhino3dm/' );
+		// Specify path to a folder containing WASM/JS libraries or a CDN.
+		//loader.setLibraryPath( '/path_to_library/rhino3dm/' );
+		loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/[email protected]/' );
 
 		// Load a 3DM file
 		loader.load(
@@ -161,13 +169,66 @@
 		[page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives error as an argument.<br />
 		</p>
 		<p>
-		Begin loading from url and call the <em>onLoad</em> function with the geometry.
+		Begin loading from url and call the <em>onLoad</em> function with the resulting Object3d.
+		</p>
+
+		<h3>[method:null parse]( [param:ArrayBuffer buffer], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )</h3>
+		<p>
+		[page:ArrayBuffer buffer] — An ArrayBuffer representing the Rhino <em>File3dm</em> document.<br />
+		[page:Function onLoad] — A function to be called after the loading is successfully completed.<br />
+		[page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives error as an argument.<br />
+		</p>
+		<p>
+		Parse a File3dm ArrayBuffer and call the <em>onLoad</em> function with the resulting Object3d.
+		See <a href="https://github.com/mcneel/rhino-developer-samples/tree/7/rhino3dm/js/SampleParse3dmObjects">this example</a> for further reference.
 		</p>
 
+		<code>
+		import rhino3dm from 'https://cdn.jsdelivr.net/npm/[email protected]/rhino3dm.module.js'
+
+		// Instantiate a loader
+		const loader = new Rhino3dmLoader();
+
+		// Specify path to a folder containing WASM/JS libraries or a CDN.
+		loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/[email protected]/' );
+
+		rhino3dm().then(async m => {
+
+			console.log('Loaded rhino3dm.');
+			const rhino = m; // global
+			
+			// create Rhino Document and add a point to it
+			const doc = new rhino.File3dm();
+			const ptA = [0, 0, 0];
+			const point = new rhino.Point( ptA );
+			doc.objects().add( point, null );
+
+			// create a copy of the doc.toByteArray data to get an ArrayBuffer
+			const buffer = new Uint8Array( doc.toByteArray() ).buffer;
+
+			loader.parse( buffer, function ( object ) {
+
+				scene.add( object );
+			
+			} );
+
+		})
+
+		</code>
+
 		<h3>[method:this setLibraryPath]( [param:String value] )</h3>
 		<p>
 		[page:String value] — Path to folder containing the JS and WASM libraries.
 		</p>
+		<code>
+		// Instantiate a loader
+		const loader = new Rhino3dmLoader();
+
+		// Specify path to a folder containing the WASM/JS library:
+		loader.setLibraryPath( '/path_to_library/rhino3dm/' );
+		// or from a CDN:
+		loader.setLibraryPath( 'https://cdn.jsdelivr.net/npm/[email protected]/' );
+		</code>
 
 		<h3>[method:this setWorkerLimit]( [param:Number workerLimit] )</h3>
 		<p>

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

@@ -38,7 +38,15 @@
 			<li>KHR_texture_transform<sup>2</sup></li>
 			<li>EXT_texture_webp</li>
 			<li>EXT_meshopt_compression</li>
-			<li>MSFT_texture_dds</li>
+		</ul>
+
+		<p>
+			The following glTF 2.0 extension is supported by an external user plugin
+		</p>
+
+		<ul>
+			<li>[link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]<sup>3</sup></li>
+			<li>[link:https://github.com/takahirox/three-gltf-extensions MSFT_texture_dds]</li>
 		</ul>
 
 		<p><i>
@@ -54,6 +62,10 @@
 			#[link:https://github.com/mrdoob/three.js/issues/12788 12788].
 		</i></p>
 
+		<p><i>
+			<sup>3</sup>You can also manually process the extension after loading in your application. See [link:https://threejs.org/examples/#webgl_loader_gltf_variants Three.js glTF materials variants example].
+		</i></p>
+
 		<h2>Code Example</h2>
 
 		<code>
@@ -193,10 +205,9 @@
 		Refer to this [link:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/draco#readme readme] for the details of Draco and its decoder.
 		</p>
 
-
-		<h3>[method:null setDDSLoader]( [param:DDSLoader ddsLoader] )</h3>
+		<h3>[method:null setKTX2Loader]( [param:KTX2Loader ktx2Loader] )</h3>
 		<p>
-		[page:DDSLoader ddsLoader] — Instance of THREE.DDSLoader, to be used for loading compressed textures with the MSFT_TEXTURE_DDS extension.
+		[page:KTX2Loader ktx2Loader] — Instance of THREE.KTX2Loader, to be used for loading KTX2 compressed textures.
 		</p>
 
 		<h3>[method:null parse]( [param:ArrayBuffer data], [param:String path], [param:Function onLoad], [param:Function onError] )</h3>

+ 133 - 0
docs/examples/en/loaders/KTX2Loader.html

@@ -0,0 +1,133 @@
+<!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>
+		[page:Loader] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			Loader for KTX 2.0 GPU Texture containers.<br><br>
+
+			[link:http://github.khronos.org/KTX-Specification/ KTX 2.0] is a container format for various GPU texture formats. The loader
+ 			supports Basis Universal GPU textures, which can be quickly transcoded to
+ 			a wide variety of GPU texture compression formats. While KTX 2.0 also allows
+ 			other hardware-specific formats, this loader does not yet parse them.
+		</p>
+
+		<p>
+			This loader parses the KTX 2.0 container and then relies on
+			[page:BasisTextureLoader] to complete the transcoding process. 
+			The required WASM transcoder and JS wrapper are available from the 
+			[link:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/basis examples/js/libs/basis]
+			directory.
+		</p>
+
+		<h2>Code Example</h2>
+
+		<code>
+		var ktx2Loader = new THREE.KTX2Loader();
+		ktx2Loader.setTranscoderPath( 'examples/js/libs/basis/' );
+		ktx2Loader.detectSupport( renderer );
+		ktx2Loader.load( 'diffuse.ktx2', function ( texture ) {
+		
+			var material = new THREE.MeshStandardMaterial( { map: texture } );
+		
+		}, function () {
+		
+			console.log( 'onProgress' );
+		
+		}, function ( e ) {
+		
+			console.error( e );
+		
+		} );
+		</code>
+
+		<h2>Examples</h2>
+
+		<p>
+			[example:webgl_loader_texture_ktx2]
+		</p>
+
+		<h2>Browser compatibility</h2>
+
+		<p>
+			See notes for [page:BasisTextureLoader]. This loader relies on ES6 Promises and Web Assembly, which are not
+			supported in IE11.
+		</p>
+
+		<br>
+		<hr>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:LoadingManager manager] )</h3>
+		<p>
+		[page:LoadingManager manager] — The [page:LoadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].
+		</p>
+		<p>
+		Creates a new [name].
+		</p>
+
+		<h2>Properties</h2>
+		<p>See the base [page:Loader] class for common properties.</p>
+
+		<h2>Methods</h2>
+		<p>See the base [page:Loader] class for common methods.</p>
+
+		<h3>[method:null load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )</h3>
+		<p>
+		[page:String url] — A string containing the path/URL of the <em>.basis</em> file.<br />
+		[page:Function onLoad] — A function to be called after the loading is successfully completed.<br />
+		[page:Function onProgress] — (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, that contains .[page:Integer total] and .[page:Integer loaded] bytes.<br />
+		[page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives error as an argument.<br />
+		</p>
+		<p>
+		Load from url and call the <em>onLoad</em> function with the transcoded [page:CompressedTexture].
+		</p>
+
+		<h3>[method:this detectSupport]( [param:WebGLRenderer renderer] )</h3>
+		<p>
+		[page:WebGLRenderer renderer] — A renderer instance.
+		</p>
+		<p>
+		Detects hardware support for available compressed texture formats, to determine
+		the output format for the transcoder. Must be called before loading a texture.
+		</p>
+
+		<h3>[method:this setTranscoderPath]( [param:String path] )</h3>
+		<p>
+		[page:String path] — Path to folder containing the WASM transcoder and JS wrapper.
+		</p>
+		<p>
+		The WASM transcoder and JS wrapper are available from the
+		[link:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/basis examples/js/libs/basis]
+		directory.
+		</p>
+
+		<h3>[method:this setWorkerLimit]( [param:Number limit] )</h3>
+		<p>
+		[page:Number limit] — Maximum number of workers. Default is '4'.
+		</p>
+		<p>
+		Sets the maximum number of web workers to be allocated by this instance.
+		</p>
+
+		<h3>[method:this dispose]()</h3>
+		<p>
+		Disposes the loader object, de-allocating any Web Workers created.
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/loaders/KTX2Loader.js examples/jsm/loaders/KTX2Loader.js]
+		</p>
+	</body>
+</html>

+ 0 - 1
docs/examples/en/renderers/CSS3DRenderer.html

@@ -27,7 +27,6 @@
 		<p>
 			[example:css3d_molecules molecules]<br />
 			[example:css3d_orthographic orthographic camera]<br />
-			[example:css3d_panorama panorama]<br />
 			[example:css3d_periodictable periodictable]<br />
 			[example:css3d_sprites sprites]<br />
 		</p>

+ 8 - 0
docs/examples/zh/exporters/GLTFExporter.html

@@ -33,6 +33,14 @@
 			<li>KHR_texture_transform</li>
 		</ul>
 
+		<p>
+			The following glTF 2.0 extension is supported by an external user plugin
+		</p>
+
+		<ul>
+			<li>[link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]</li>
+		</ul>
+
 		<h2>代码示例</h2>
 
 		<code>

+ 13 - 6
docs/examples/zh/loaders/GLTFLoader.html

@@ -36,7 +36,15 @@
 			<li>KHR_texture_transform<sup>2</sup></li>
 			<li>EXT_texture_webp</li>
 			<li>EXT_meshopt_compression</li>
-			<li>MSFT_texture_dds</li>
+		</ul>
+
+		<p>
+			The following glTF 2.0 extension is supported by an external user plugin
+		</p>
+
+		<ul>
+			<li>[link:https://github.com/takahirox/three-gltf-extensions KHR_materials_variants]<sup>3</sup></li>
+			<li>[link:https://github.com/takahirox/three-gltf-extensions MSFT_texture_dds]</li>
 		</ul>
 
 		<p><i>
@@ -53,6 +61,10 @@
 			#[link:https://github.com/mrdoob/three.js/issues/12788 12788]。
 		</i></p>
 
+		<p><i>
+			<sup>3</sup>You can also manually process the extension after loading in your application. See [link:https://threejs.org/examples/#webgl_loader_gltf_variants Three.js glTF materials variants example].
+		</i></p>
+
 		<h2>代码示例</h2>
 
 		<code>
@@ -188,11 +200,6 @@
 		请参阅[link:https://github.com/mrdoob/three.js/tree/dev/examples/js/libs/draco#readme readme]来了解Draco及其解码器的详细信息。
 		</p>
 
-		<h3>[method:null setDDSLoader]( [param:DDSLoader ddsLoader] )</h3>
-		<p>
-		[page:DDSLoader ddsLoader] — THREE.DDSLoader的实例,用于加载使用MSFT_TEXTURE_DDS扩展压缩过的纹理。
-		</p>
-
 		<h3>[method:null parse]( [param:ArrayBuffer data], [param:String path], [param:Function onLoad], [param:Function onError] )</h3>
 		<p>
 		[page:ArrayBuffer data] — 需要解析的glTF文件,值为一个ArrayBuffer或<em>JSON</em>字符串。<br />

+ 0 - 1
docs/examples/zh/renderers/CSS3DRenderer.html

@@ -28,7 +28,6 @@
 		<p>
 			[example:css3d_molecules molecules]<br />
 			[example:css3d_orthographic orthographic camera]<br />
-			[example:css3d_panorama panorama]<br />
 			[example:css3d_periodictable periodictable]<br />
 			[example:css3d_sprites sprites]<br />
 		</p>

+ 1 - 1
docs/index.html

@@ -27,7 +27,7 @@
 		<div id="panel">
 
 			<div id="header">
-				<h1><a href="http://threejs.org">three.js</a></h1>
+				<h1><a href="https://threejs.org">three.js</a></h1>
 
 				<div id="sections">
 					<span class="selected">docs</span>

+ 1 - 6
docs/list.json

@@ -10,7 +10,6 @@
 				"Browser support": "manual/en/introduction/Browser-support",
 				"WebGL compatibility check": "manual/en/introduction/WebGL-compatibility-check",
 				"How to run things locally": "manual/en/introduction/How-to-run-things-locally",
-				"Typescript setup": "manual/en/introduction/Typescript-setup",
 				"Drawing lines": "manual/en/introduction/Drawing-lines",
 				"Creating text": "manual/en/introduction/Creating-text",
 				"Loading 3D models": "manual/en/introduction/Loading-3D-models",
@@ -87,7 +86,6 @@
 				"BufferGeometry": "api/en/core/BufferGeometry",
 				"Clock": "api/en/core/Clock",
 				"EventDispatcher": "api/en/core/EventDispatcher",
-				"Face3": "api/en/core/Face3",
 				"GLBufferAttribute": "api/en/core/GLBufferAttribute",
 				"InstancedBufferAttribute": "api/en/core/InstancedBufferAttribute",
 				"InstancedBufferGeometry": "api/en/core/InstancedBufferGeometry",
@@ -371,6 +369,7 @@
 				"BasisTextureLoader": "examples/en/loaders/BasisTextureLoader",
 				"DRACOLoader": "examples/en/loaders/DRACOLoader",
 				"GLTFLoader": "examples/en/loaders/GLTFLoader",
+				"KTX2Loader": "examples/en/loaders/KTX2Loader",
 				"MMDLoader": "examples/en/loaders/MMDLoader",
 				"MTLLoader": "examples/en/loaders/MTLLoader",
 				"OBJLoader": "examples/en/loaders/OBJLoader",
@@ -450,7 +449,6 @@
 				"دعم المتصفح": "manual/ar/introduction/Browser-support",
 				"فحص توافق WebGL": "manual/ar/introduction/WebGL-compatibility-check",
 				"كيف تدير الأشياء محليًا": "manual/ar/introduction/How-to-run-things-locally",
-				"إعدادات Typescript": "manual/ar/introduction/Typescript-setup",
 				"رسم خطوط": "manual/ar/introduction/Drawing-lines",
 				"إنشاء نص": "manual/ar/introduction/Creating-text",
 				"تحميل نماذج ثلاثية الأبعاد": "manual/ar/introduction/Loading-3D-models",
@@ -523,7 +521,6 @@
 				"浏览器支持": "manual/zh/introduction/Browser-support",
 				"WebGL兼容性检查": "manual/zh/introduction/WebGL-compatibility-check",
 				"如何在本地运行Three.js": "manual/zh/introduction/How-to-run-things-locally",
-				"Typescript设置": "manual/zh/introduction/Typescript-setup",
 				"画线": "manual/zh/introduction/Drawing-lines",
 				"创建文字": "manual/zh/introduction/Creating-text",
 				"载入3D模型": "manual/zh/introduction/Loading-3D-models",
@@ -599,7 +596,6 @@
 				"BufferGeometry": "api/zh/core/BufferGeometry",
 				"Clock": "api/zh/core/Clock",
 				"EventDispatcher": "api/zh/core/EventDispatcher",
-				"Face3": "api/zh/core/Face3",
 				"GLBufferAttribute": "api/zh/core/GLBufferAttribute",
 				"InstancedBufferAttribute": "api/zh/core/InstancedBufferAttribute",
 				"InstancedBufferGeometry": "api/zh/core/InstancedBufferGeometry",
@@ -959,7 +955,6 @@
 				"브라우저 지원": "manual/ko/introduction/Browser-support",
 				"WebGL 호환성 검사": "manual/ko/introduction/WebGL-compatibility-check",
 				"로컬 환경에서 구동 방법": "manual/ko/introduction/How-to-run-things-locally",
-				"Typescript 설정": "manual/ko/introduction/Typescript-setup",
 				"선 그리기": "manual/ko/introduction/Drawing-lines",
 				"텍스트 만들기": "manual/ko/introduction/Creating-text",
 				"3D 모델 불러오기": "manual/ko/introduction/Loading-3D-models",

+ 6 - 6
docs/manual/ar/introduction/Installation.html

@@ -87,9 +87,9 @@
 		<code>
 		&lt;script type="module">
 
-		  // Find the latest version by visiting https://unpkg.com/three. The URL will
-		  // redirect to the newest stable release.
-		  import * as THREE from 'https://unpkg.com/three/build/three.module.js';
+		  // Find the latest version by visiting https://unpkg.com/three.
+
+		  import * as THREE from 'https://unpkg.com/three@&lt;version&gt;/build/three.module.js';
 
 		  const scene = new THREE.Scene();
 
@@ -125,9 +125,9 @@
 		<code>
 		&lt;script type="module">
 
-		  // Find the latest version by visiting https://unpkg.com/three. The URL will
-		  // redirect to the newest stable release.
-		  import { OrbitControls } from 'https://unpkg.com/three/examples/jsm/controls/OrbitControls.js';
+		  // Find the latest version by visiting https://unpkg.com/three.
+
+		  import { OrbitControls } from 'https://unpkg.com/three@&lt;version&gt;/examples/jsm/controls/OrbitControls.js';
 
 		  const controls = new OrbitControls();
 

+ 0 - 42
docs/manual/ar/introduction/Typescript-setup.html

@@ -1,42 +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>Typescript إعدادات</h1>
-
-		<p>
-			three.js هي مكتبة قائمة على JavaScript. ومع ذلك ، من الممكن استخدامه في مشروع TypeScript ، حيث تعرض المكتبة [link:https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html Declaration Files] ملفات التصريح (ملفات * d.ts *).
-		</p>
-
-		<p>
-			الحد الأدنى من التكوين المطلوب لكي يتمكن برنامج التحويل البرمجي TypeScript من
-			اكتشف أنواع three.js.
-			<br>
-			ستحتاج إلى ضبط الخيار [link:https://www.typescriptlang.org/docs/handbook/module-resolution.html moduleResolution] على *node* ، وخيار [link:https://www.typescriptlang.org/docs/handbook/compiler-options.html target] على *es6* أو  ما هو أحدث.
-		</p>
-
-		<code>
-		// Example of minimal `tsconfig.json` file
-		{
-			"compilerOptions": {
-				"target": "es6",
-				"moduleResolution": "node",
-			},
-			"include": [ "./src/**/*.ts" ],
-		}
-		</code>
-
-		<p>
-			ملاحظة: اعتبارًا من اليوم ، ليس من الممكن استخدام كتابة three.js بدون استخدام هذين الخيارين.
-		</p>
-
-		<p>
-			ملاحظة: يحدث أن بعض التصريحات غير صحيحة و / أو مفقودة. تُعد المساهمة في ملفات التصريح مفيدة حقًا للمجتمع ، مما يجعل كتابات three.js أفضل وأكثر دقة.
-		</p>
-	</body>
-</html>

+ 1 - 1
docs/manual/ar/introduction/Useful-links.html

@@ -103,7 +103,7 @@
 			[link:http://www.physgl.org/ physgl.org] - واجهة JavaScript الأمامية مع أغلفة لـ three.js ، لجلب رسومات WebGL للطلاب الذين يتعلمون الفيزياء والرياضيات.
 		 </li>
 		 <li>
-			 [link:https://whs.io/ Whitestorm.js] – إطار عمل modular three.js مع البرنامج المساعد AmmoNext للفيزياء.
+			 [link:https://whsjs.readme.io/ Whitestorm.js] – إطار عمل modular three.js مع البرنامج المساعد AmmoNext للفيزياء.
 		 </li>
 
 		<li>

+ 1 - 1
docs/manual/en/introduction/Creating-a-scene.html

@@ -114,7 +114,7 @@
 		<p>This will be run every frame (normally 60 times per second), and give the cube a nice rotation animation. Basically, anything you want to move or change while the app is running has to go through the animate loop. You can of course call other functions from there, so that you don't end up with a <strong>animate</strong> function that's hundreds of lines.</p>
 
 		<h2>The result</h2>
-		<p>Congratulations! You have now completed your first three.js application. It's simple, you have to start somewhere.</p>
+		<p>Congratulations! You have now completed your first three.js application. It's simple, but you have to start somewhere.</p>
 
 		<p>The full code is available below and as an editable [link:https://jsfiddle.net/fxurzeb4/ live example]. Play around with it to get a better understanding of how it works.</p>
 

+ 6 - 6
docs/manual/en/introduction/Installation.html

@@ -69,9 +69,9 @@
 		<code>
 		&lt;script type="module">
 
-		  // Find the latest version by visiting https://unpkg.com/three. The URL will
-		  // redirect to the newest stable release.
-		  import * as THREE from 'https://unpkg.com/three/build/three.module.js';
+		  // Find the latest version by visiting https://unpkg.com/three.
+
+		  import * as THREE from 'https://unpkg.com/three@&lt;version&gt;/build/three.module.js';
 
 		  const scene = new THREE.Scene();
 
@@ -107,9 +107,9 @@
 		<code>
 		&lt;script type="module">
 
-		  // Find the latest version by visiting https://unpkg.com/three. The URL will
-		  // redirect to the newest stable release.
-		  import { OrbitControls } from 'https://unpkg.com/three/examples/jsm/controls/OrbitControls.js';
+		  // Find the latest version by visiting https://unpkg.com/three.
+
+		  import { OrbitControls } from 'https://unpkg.com/three@&lt;version&gt;/examples/jsm/controls/OrbitControls.js';
 
 		  const controls = new OrbitControls();
 

+ 0 - 45
docs/manual/en/introduction/Typescript-setup.html

@@ -1,45 +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>
-
-		<p>
-			three.js is a JavaScript-based library. However, it's possible to use it in a TypeScript project, as the library
-			exposes [link:https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html Declaration Files] (*d.ts* files).
-		</p>
-
-		<p>
-			A minimal configuration is required for the TypeScript compiler to
-			discover three.js types.<br>
-			You will need to set the [link:https://www.typescriptlang.org/docs/handbook/module-resolution.html moduleResolution]
-			option to *node*, and the [link:https://www.typescriptlang.org/docs/handbook/compiler-options.html target] option to *es6* or newer.
-		</p>
-
-		<code>
-		// Example of minimal `tsconfig.json` file
-		{
-			"compilerOptions": {
-				"target": "es6",
-				"moduleResolution": "node",
-			},
-			"include": [ "./src/**/*.ts" ],
-		}
-		</code>
-
-		<p>
-			Note: As of today, it's not yet possible to use three.js typings without using those two options.
-		</p>
-
-		<p>
-			Note: It happens that some declarations are incorrect and/or missing.
-			Contributing to Declaration Files is really helpful for the community, making three.js
-			typings better and more accurate.
-		</p>
-	</body>
-</html>

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

@@ -113,7 +113,7 @@
  			graphics to students learning physics and math.
 		 </li>
 		 <li>
-			 [link:https://whs.io/ Whitestorm.js] – Modular three.js framework with AmmoNext physics plugin.
+			 [link:https://whsjs.readme.io/ Whitestorm.js] – Modular three.js framework with AmmoNext physics plugin.
 		 </li>
 
 		<li>

+ 15 - 15
docs/manual/ko/introduction/Installation.html

@@ -79,9 +79,9 @@
     <code>
 		&lt;script type="module">
 
-		  // Find the latest version by visiting https://unpkg.com/three. The URL will
-		  // redirect to the newest stable release.
-		  import * as THREE from 'https://unpkg.com/three@&lt;VERSION>/build/three.module.js';
+		  // Find the latest version by visiting https://unpkg.com/three.
+
+		  import * as THREE from 'https://unpkg.com/three@&lt;version&gt;/build/three.module.js';
 
 		  const scene = new THREE.Scene();
 
@@ -99,12 +99,12 @@
     <p>
         three.js는 3D 엔진의 주요 컴포넌트들에 초점을 두고 있습니다. 다른 여러 유용한 컴포넌트들 —
         controls, loaders, post-processing effects — 은
-        [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm examples/jsm] 폴더에 있습니다. 이들은 "예제"로 불리는데, 그대로 사용할 수도 있고, 
+        [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm examples/jsm] 폴더에 있습니다. 이들은 "예제"로 불리는데, 그대로 사용할 수도 있고,
         재조합 및 커스터마이징이 가능하기 때문입니다. 이 컴포넌트들은 언제나 코어 라이브러리와 상응하게 이루어져있으며, 이는 다른 비슷한 서드파티 패키지들이 다양한 사람들에 의해 유지보수되고, 최신버전 반영이 안되는 점과는 대비되는 점입니다.
     </p>
 
     <p>
-        예제들은 각각 따로 <em>설치할</em> 필요는 없지만, 각각 <em>import</em>를 해 주어야 합니다. 
+        예제들은 각각 따로 <em>설치할</em> 필요는 없지만, 각각 <em>import</em>를 해 주어야 합니다.
         three.js가 npm을 통해 설치되었다면, [page:OrbitControls] 컴포넌트를 다음과 같이 불러올 수 있습니다.
     </p>
 
@@ -122,9 +122,9 @@
     <code>
 		&lt;script type="module">
 
-		  // Find the latest version by visiting https://unpkg.com/three. The URL will
-		  // redirect to the newest stable release.
-		  import { OrbitControls } from 'https://unpkg.com/three@&lt;VERSION>/examples/jsm/controls/OrbitControls.js';
+		  // Find the latest version by visiting https://unpkg.com/three.
+
+		  import { OrbitControls } from 'https://unpkg.com/three@&lt;version&gt;/examples/jsm/controls/OrbitControls.js';
 
 		  const controls = new OrbitControls();
 
@@ -140,7 +140,7 @@
     <h3>CommonJS 불러오기</h3>
 
     <p>
-        대부분의 자바스크립트 번들러는 이제 ES 모듈을 기본적으로 지원하지만, 오래된 빌드 도구들은 그렇지 않을 수 있습니다. 
+        대부분의 자바스크립트 번들러는 이제 ES 모듈을 기본적으로 지원하지만, 오래된 빌드 도구들은 그렇지 않을 수 있습니다.
         이 경우에, 번들러에 ES 모듈을 인식할 수 있도록 설정해줄 수 있습니다. 예를들어 [link:http://browserify.org/
         Browserify] 는 [link:https://github.com/babel/babelify babelify] 플러그인을 불러오기만 하면 됩니다.
     </p>
@@ -150,16 +150,16 @@
     <p>
         npm을 통해 설치하는 경우, 호스팅 및 CDN으로 설치했을 때와 import 경로가 다릅니다. 이 점은 양쪽의 사용자 모두에게 불편한 문제가 될 것이라는 점을 알고 있습니다.
         빌드 도구나 번들러를 사용하는 개발자들은 상대경로보다 단순한 패키지 구분자(ex: 'three')로 사용하기를 선호하지만 <em>examples/</em> 폴더의 파일들은
-        <em>three.module.js</em>에 상대 경로를 사용하기 때문에 예상을 빗나가게 됩니다. 빌드 도구를 사용하지 않는 사람들 — 빠른 프로토타입 제작, 학습용도, 개인적 취향 — 도 마찬가지로 이러한 상대 경로를 싫어할 텐데, 
+        <em>three.module.js</em>에 상대 경로를 사용하기 때문에 예상을 빗나가게 됩니다. 빌드 도구를 사용하지 않는 사람들 — 빠른 프로토타입 제작, 학습용도, 개인적 취향 — 도 마찬가지로 이러한 상대 경로를 싫어할 텐데,
         특정 폴더 구조가 필요하고, 전역 <em>THREE.*</em>를 사용하는 것보다 엄격하기 때문입니다.
     </p>
 
     <p>
-        [link:https://github.com/WICG/import-maps import maps] 이 후에 활발하게 지원된다면 이러한 상대 경로들을 npm 패키지 이름, 'three'처럼 단순한 패키지 식별자로 변경할 예정입니다. 
-        이는 npm 패키지에서 주로 쓰이는 경로 작성법과 일치하고, 두 사용자군 모두에게 파일을 불러오는 데에 동일한 코드를 사용할 수 있게 해 줄 것입니다. 
-        빌드 도구를 사용하지 않는 것을 선호하는 사용자들에게도, 간단한 JSON 맵핑을 통해 CDN이나 직접 파일 폴더에서 불러오는 것을 가능하게 해 줄 것입니다. 
+        [link:https://github.com/WICG/import-maps import maps] 이 후에 활발하게 지원된다면 이러한 상대 경로들을 npm 패키지 이름, 'three'처럼 단순한 패키지 식별자로 변경할 예정입니다.
+        이는 npm 패키지에서 주로 쓰이는 경로 작성법과 일치하고, 두 사용자군 모두에게 파일을 불러오는 데에 동일한 코드를 사용할 수 있게 해 줄 것입니다.
+        빌드 도구를 사용하지 않는 것을 선호하는 사용자들에게도, 간단한 JSON 맵핑을 통해 CDN이나 직접 파일 폴더에서 불러오는 것을 가능하게 해 줄 것입니다.
         실험적 방법으로, [link:https://glitch.com/edit/#!/three-import-map?path=index.html import map
-        예제]처럼 map polyfill과 함께 import 해서 더 간단하게 사용해볼 수도 있습니다. 
+        예제]처럼 map polyfill과 함께 import 해서 더 간단하게 사용해볼 수도 있습니다.
     </p>
 
     <h3>Node.js</h3>
@@ -183,4 +183,4 @@
 
 </body>
 
-</html>
+</html>

+ 0 - 41
docs/manual/ko/introduction/Typescript-setup.html

@@ -1,41 +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>
-
-		<p>
-			three.js는 자바스크립트 기반 라이브러리입니다. 하지만 TypeScript 프로젝트에도 사용이 가능한데, [link:https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html Declaration Files] (*d.ts* 파일)의 라이브러리 노출 설정을 통해 가능합니다.
-		</p>
-
-		<p>
-			컴파일러가 three.js의 타입을 확인하기 위해 약간의 설정이 필요합니다.<br>
-			[link:https://www.typescriptlang.org/docs/handbook/module-resolution.html moduleResolution]옵션을 *노드*에 설정하고
-			[link:https://www.typescriptlang.org/docs/handbook/compiler-options.html target] 옵션을 *es6* 혹은 최신 버전으로 설정합니다.
-		</p>
-
-		<code>
-		// Example of minimal `tsconfig.json` file
-		{
-			"compilerOptions": {
-				"target": "es6",
-				"moduleResolution": "node",
-			},
-			"include": [ "./src/**/*.ts" ],
-		}
-		</code>
-
-		<p>
-			주의: 현 시점에서 three.js는 위 두 설정을 하지 않고서는 사용할 수 없습니다.
-		</p>
-
-		<p>
-			주의: 몇몇 선언들은 틀리거나 찾을 수 없음으로 나올 것입니다. 선언문 파일들에 대한 교정 작업 지원은 커뮤니티와 three.js를 보다 정확하고 좋게 만드는 데에 도움이 될 것입니다.
-		</p>
-	</body>
-</html>

+ 2 - 2
docs/manual/ko/introduction/Useful-links.html

@@ -112,7 +112,7 @@
  			graphics to students learning physics and math.
 		 </li>
 		 <li>
-			 [link:https://whs.io/ Whitestorm.js] – Modular three.js framework with AmmoNext physics plugin.
+			 [link:https://whsjs.readme.io/ Whitestorm.js] – Modular three.js framework with AmmoNext physics plugin.
 		 </li>
 
 		<li>
@@ -180,4 +180,4 @@
 	 </ul>
 
 	</body>
-</html>
+</html>

+ 4 - 4
docs/manual/zh/introduction/Installation.html

@@ -70,8 +70,8 @@
 		&lt;script type="module">
 
 		  // 通过访问 https://unpkg.com/three 来查找最新版本。
-		  // 该URL将会重定向到最新的稳定版本。
-		  import * as THREE from 'https://unpkg.com/three/build/three.module.js';
+
+		  import * as THREE from 'https://unpkg.com/three@&lt;version&gt;/build/three.module.js';
 
 		  const scene = new THREE.Scene();
 
@@ -108,8 +108,8 @@
 		&lt;script type="module">
 
 		  // 通过访问 https://unpkg.com/three 来查找最新版本。
-		  // 该URL将会重定向到最新的稳定版本。
-		  import { OrbitControls } from 'https://unpkg.com/three/examples/jsm/controls/OrbitControls.js';
+
+		  import { OrbitControls } from 'https://unpkg.com/three@&lt;version&gt;/examples/jsm/controls/OrbitControls.js';
 
 		  const controls = new OrbitControls();
 

+ 0 - 40
docs/manual/zh/introduction/Typescript-setup.html

@@ -1,40 +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>TypeScript设置([name])</h1>
-
-		<p>
-			three.js是一个基于JavaScript的库。但是,可以在TypeScript项目中使用它,因为该库公开了声明文件 [link:https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html Declaration Files](*d.ts* 文件)。
-		</p>
-
-		<p>
-			TypeScript编译器需要最少的配置即可发现three.js类型。<br>
-			你将需要设置 [link:https://www.typescriptlang.org/docs/handbook/module-resolution.html moduleResolution] (模块解析)为 *node* 和 [link:https://www.typescriptlang.org/docs/handbook/compiler-options.html target] (目标) 为 *es6* 或更高版本。
-		</p>
-
-		<code>
-		// tsconfig.json文件最少配置例子
-		{
-			"compilerOptions": {
-				"target": "es6",
-				"moduleResolution": "node",
-			},
-			"include": [ "./src/**/*.ts" ],
-		}
-		</code>
-
-		<p>
-			注意:到目前为止,如果不使用这两个选项,则无法使用three.js类型。
-		</p>
-
-		<p>
-			注意:某些声明可能不正确或缺失。为声明文件做贡献对社区真的很有帮助,使Three.js开发会更好更准确。
-		</p>
-	</body>
-</html>

+ 1 - 1
docs/manual/zh/introduction/Useful-links.html

@@ -114,7 +114,7 @@
  			graphics to students learning physics and math.
 		 </li>
 		 <li>
-			 [link:https://whs.io/ Whitestorm.js] – Modular three.js framework with AmmoNext physics plugin.
+			 [link:https://whsjs.readme.io/ Whitestorm.js] – Modular three.js framework with AmmoNext physics plugin.
 		 </li>
 
 		<li>

+ 2 - 1
docs/scenes/material-browser.html

@@ -490,6 +490,8 @@
 				const folder = gui.addFolder( 'THREE.MeshMatcapMaterial' );
 
 				folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
+
+				folder.add( material, 'flatShading' ).onChange( needsUpdate( material, geometry ) );
 				folder.add( data, 'matcap', matcapKeys ).onChange( updateTexture( material, 'matcap', matcaps ) );
 				folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
 
@@ -539,7 +541,6 @@
 				const folder = gui.addFolder( 'THREE.MeshToonMaterial' );
 
 				folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
-
 				folder.add( data, 'map', diffuseMapKeys ).onChange( updateTexture( material, 'map', diffuseMaps ) );
 				folder.add( data, 'gradientMap', gradientMapKeys ).onChange( updateTexture( material, 'gradientMap', gradientMaps ) );
 				folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );

+ 1 - 2
editor/css/main.css

@@ -78,7 +78,6 @@ textarea, input { outline: none; } /* osx */
 
 .TabbedPanel .Tabs .Tab {
 	padding: 10px;
-	vertical-align: middle;
 	text-transform: uppercase;
 }
 
@@ -240,7 +239,7 @@ textarea, input { outline: none; } /* osx */
 /* */
 
 #outliner .Script:after {
-	content: '{...}' /* ❮/❯ */
+	content: '◎'
 }
 
 /*  */

+ 1 - 1
editor/examples/shaders.app.json

@@ -39,7 +39,7 @@
 				"uuid": "EA781333-F3AE-470D-9110-A9724FCB42AA",
 				"type": "IcosahedronGeometry",
 				"radius": 1,
-				"detail": 4
+				"detail": 24
 			}],
 		"materials": [
 			{

+ 3 - 1
editor/index.html

@@ -25,6 +25,8 @@
 
 		<link rel="stylesheet" href="css/main.css">
 
+		<script src="https://unpkg.com/@ffmpeg/[email protected]/dist/ffmpeg.min.js" defer></script>
+
 		<script src="../examples/js/libs/draco/draco_encoder.js"></script>
 
 		<link rel="stylesheet" href="js/libs/codemirror/codemirror.css">
@@ -75,7 +77,7 @@
 
 			Number.prototype.format = function () {
 
-				return this.toString().replace( /(\d)(?=(\d{3})+(?!\d))/g, "$1," );
+				return this.toString().replace( /(\d)(?=(\d{3})+(?!\d))/g, '$1,' );
 
 			};
 

+ 25 - 22
editor/js/Command.js

@@ -1,38 +1,41 @@
-
 /**
  * @param editor pointer to main editor object used to initialize
  *        each command object with a reference to the editor
  * @constructor
  */
 
-function Command( editor ) {
+class Command {
 
-	this.id = - 1;
-	this.inMemory = false;
-	this.updatable = false;
-	this.type = '';
-	this.name = '';
-	this.editor = editor;
+	constructor( editor ) {
 
-}
+		this.id = - 1;
+		this.inMemory = false;
+		this.updatable = false;
+		this.type = '';
+		this.name = '';
+		this.editor = editor;
+
+	}
 
-Command.prototype.toJSON = function () {
+	toJSON() {
 
-	var output = {};
-	output.type = this.type;
-	output.id = this.id;
-	output.name = this.name;
-	return output;
+		const output = {};
+		output.type = this.type;
+		output.id = this.id;
+		output.name = this.name;
+		return output;
 
-};
+	}
 
-Command.prototype.fromJSON = function ( json ) {
+	fromJSON( json ) {
 
-	this.inMemory = true;
-	this.type = json.type;
-	this.id = json.id;
-	this.name = json.name;
+		this.inMemory = true;
+		this.type = json.type;
+		this.id = json.id;
+		this.name = json.name;
 
-};
+	}
+
+}
 
 export { Command };

+ 5 - 0
editor/js/Editor.js

@@ -26,6 +26,11 @@ function Editor() {
 		startPlayer: new Signal(),
 		stopPlayer: new Signal(),
 
+		// vr
+
+		toggleVR: new Signal(),
+		exitedVR: new Signal(),
+
 		// notifications
 
 		editorCleared: new Signal(),

+ 7 - 7
editor/js/History.js

@@ -45,7 +45,7 @@ History.prototype = {
 			lastCmd.script === cmd.script &&
 			lastCmd.attributeName === cmd.attributeName;
 
-		if ( isUpdatableCmd && cmd.type === "SetScriptValueCommand" ) {
+		if ( isUpdatableCmd && cmd.type === 'SetScriptValueCommand' ) {
 
 			// When the cmd.type is "SetScriptValueCommand" the timeDifference is ignored
 
@@ -89,7 +89,7 @@ History.prototype = {
 
 		if ( this.historyDisabled ) {
 
-			alert( "Undo/Redo disabled while scene is playing." );
+			alert( 'Undo/Redo disabled while scene is playing.' );
 			return;
 
 		}
@@ -124,7 +124,7 @@ History.prototype = {
 
 		if ( this.historyDisabled ) {
 
-			alert( "Undo/Redo disabled while scene is playing." );
+			alert( 'Undo/Redo disabled while scene is playing.' );
 			return;
 
 		}
@@ -171,7 +171,7 @@ History.prototype = {
 
 		for ( var i = 0; i < this.undos.length; i ++ ) {
 
-			if ( this.undos[ i ].hasOwnProperty( "json" ) ) {
+			if ( this.undos[ i ].hasOwnProperty( 'json' ) ) {
 
 				history.undos.push( this.undos[ i ].json );
 
@@ -183,7 +183,7 @@ History.prototype = {
 
 		for ( var i = 0; i < this.redos.length; i ++ ) {
 
-			if ( this.redos[ i ].hasOwnProperty( "json" ) ) {
+			if ( this.redos[ i ].hasOwnProperty( 'json' ) ) {
 
 				history.redos.push( this.redos[ i ].json );
 
@@ -242,7 +242,7 @@ History.prototype = {
 
 		if ( this.historyDisabled ) {
 
-			alert( "Undo/Redo disabled while scene is playing." );
+			alert( 'Undo/Redo disabled while scene is playing.' );
 			return;
 
 		}
@@ -300,7 +300,7 @@ History.prototype = {
 		var cmd = this.redo();
 		while ( cmd !== undefined ) {
 
-			if ( ! cmd.hasOwnProperty( "json" ) ) {
+			if ( ! cmd.hasOwnProperty( 'json' ) ) {
 
 				cmd.json = cmd.toJSON();
 

+ 28 - 1
editor/js/Menubar.Edit.js

@@ -1,7 +1,10 @@
+import { Box3, Vector3 } from '../../build/three.module.js';
+
 import { UIPanel, UIRow, UIHorizontalRule } from './libs/ui.js';
 
 import { AddObjectCommand } from './commands/AddObjectCommand.js';
 import { RemoveObjectCommand } from './commands/RemoveObjectCommand.js';
+import { SetPositionCommand } from './commands/SetPositionCommand.js';
 
 function MenubarEdit( editor ) {
 
@@ -85,6 +88,30 @@ function MenubarEdit( editor ) {
 
 	options.add( new UIHorizontalRule() );
 
+	// Center
+
+	var option = new UIRow();
+	option.setClass( 'option' );
+	option.setTextContent( strings.getKey( 'menubar/edit/center' ) );
+	option.onClick( function () {
+
+		var object = editor.selected;
+
+		if ( object === null || object.parent === null ) return; // avoid centering the camera or scene
+
+		const aabb = new Box3().setFromObject( object );
+		const center = aabb.getCenter( new Vector3() );
+		const newPosition = new Vector3();
+
+		newPosition.x = object.position.x + ( object.position.x - center.x );
+		newPosition.y = object.position.y + ( object.position.y - center.y );
+		newPosition.z = object.position.z + ( object.position.z - center.z );
+
+		editor.execute( new SetPositionCommand( editor, object, newPosition ) );
+
+	} );
+	options.add( option );
+
 	// Clone
 
 	var option = new UIRow();
@@ -94,7 +121,7 @@ function MenubarEdit( editor ) {
 
 		var object = editor.selected;
 
-		if ( object.parent === null ) return; // avoid cloning the camera or scene
+		if ( object === null || object.parent === null ) return; // avoid cloning the camera or scene
 
 		object = object.clone();
 

+ 8 - 4
editor/js/Menubar.File.js

@@ -1,6 +1,6 @@
 import * as THREE from '../../build/three.module.js';
 
-import { zipSync, strToU8 } from './libs/fflate-deflate.min.module.js';
+import { zipSync, strToU8 } from '../../examples/jsm/libs/fflate.module.min.js';
 
 import { UIPanel, UIRow, UIHorizontalRule } from './libs/ui.js';
 
@@ -390,7 +390,7 @@ function MenubarFile( editor ) {
 
 		var exporter = new USDZExporter();
 
-		saveArrayBuffer( exporter.parse( editor.scene, { binary: true } ), 'model.usdz' );
+		saveArrayBuffer( await exporter.parse( editor.scene, { binary: true } ), 'model.usdz' );
 
 	} );
 	options.add( option );
@@ -488,12 +488,16 @@ function MenubarFile( editor ) {
 	var link = document.createElement( 'a' );
 	function save( blob, filename ) {
 
+		if ( link.href ) {
+
+			URL.revokeObjectURL( link.href );
+
+		}
+
 		link.href = URL.createObjectURL( blob );
 		link.download = filename || 'data.json';
 		link.dispatchEvent( new MouseEvent( 'click' ) );
 
-		// URL.revokeObjectURL( url ); breaks Firefox...
-
 	}
 
 	function saveArrayBuffer( buffer, filename ) {

+ 3 - 1
editor/js/Menubar.Help.js

@@ -28,6 +28,7 @@ function MenubarHelp( editor ) {
 	} );
 	options.add( option );
 
+	/*
 	// Icon
 
 	var option = new UIRow();
@@ -39,6 +40,7 @@ function MenubarHelp( editor ) {
 
 	} );
 	options.add( option );
+	*/
 
 	// About
 
@@ -47,7 +49,7 @@ function MenubarHelp( editor ) {
 	option.setTextContent( strings.getKey( 'menubar/help/about' ) );
 	option.onClick( function () {
 
-		window.open( 'http://threejs.org', '_blank' );
+		window.open( 'https://threejs.org', '_blank' );
 
 	} );
 	options.add( option );

+ 48 - 3
editor/js/Menubar.View.js

@@ -14,18 +14,63 @@ function MenubarView( editor ) {
 	options.setClass( 'options' );
 	container.add( options );
 
-	// VR mode
+	// Fullscreen
 
 	var option = new UIRow();
 	option.setClass( 'option' );
-	option.setTextContent( 'VR mode' );
+	option.setTextContent( 'Fullscreen' );
 	option.onClick( function () {
 
-		editor.signals.enterVR.dispatch();
+		if ( document.fullscreenElement === null ) {
+
+			document.documentElement.requestFullscreen();
+
+		} else if ( document.exitFullscreen ) {
+
+			document.exitFullscreen();
+
+		}
+
+		// Safari
+
+		if ( document.webkitFullscreenElement === null ) {
+
+			document.documentElement.webkitRequestFullscreen();
+
+		} else if ( document.webkitExitFullscreen ) {
+
+			document.webkitExitFullscreen();
+
+		}
 
 	} );
 	options.add( option );
 
+	// VR (Work in progress)
+
+	if ( 'xr' in navigator ) {
+
+		navigator.xr.isSessionSupported( 'immersive-vr' )
+			.then( function ( supported ) {
+
+				if ( supported ) {
+
+					var option = new UIRow();
+					option.setClass( 'option' );
+					option.setTextContent( 'VR' );
+					option.onClick( function () {
+
+						editor.signals.toggleVR.dispatch();
+
+					} );
+					options.add( option );
+
+				}
+
+			} );
+
+	}
+
 	return container;
 
 }

+ 2 - 0
editor/js/Menubar.js

@@ -4,6 +4,7 @@ import { MenubarAdd } from './Menubar.Add.js';
 import { MenubarEdit } from './Menubar.Edit.js';
 import { MenubarFile } from './Menubar.File.js';
 import { MenubarExamples } from './Menubar.Examples.js';
+import { MenubarView } from './Menubar.View.js';
 import { MenubarHelp } from './Menubar.Help.js';
 import { MenubarPlay } from './Menubar.Play.js';
 import { MenubarStatus } from './Menubar.Status.js';
@@ -18,6 +19,7 @@ function Menubar( editor ) {
 	container.add( new MenubarAdd( editor ) );
 	container.add( new MenubarPlay( editor ) );
 	container.add( new MenubarExamples( editor ) );
+	container.add( new MenubarView( editor ) );
 	container.add( new MenubarHelp( editor ) );
 
 	container.add( new MenubarStatus( editor ) );

+ 3 - 2
editor/js/Script.js

@@ -379,7 +379,7 @@ function Script( editor ) {
 
 					mode = 'glsl';
 					name = 'Vertex Shader';
-					source = object.material.vertexShader || "";
+					source = object.material.vertexShader || '';
 
 					break;
 
@@ -387,7 +387,7 @@ function Script( editor ) {
 
 					mode = 'glsl';
 					name = 'Fragment Shader';
-					source = object.material.fragmentShader || "";
+					source = object.material.fragmentShader || '';
 
 					break;
 
@@ -403,6 +403,7 @@ function Script( editor ) {
 					source = JSON.stringify( json, null, '\t' );
 
 			}
+
 			title.setValue( object.material.name + ' / ' + name );
 
 		}

+ 2 - 2
editor/js/Sidebar.Material.js

@@ -628,7 +628,7 @@ function SidebarMaterial( editor ) {
 
 				material = new materialClasses[ materialClass.getValue() ]();
 
-				if ( material.type === "RawShaderMaterial" ) {
+				if ( material.type === 'RawShaderMaterial' ) {
 
 					material.vertexShader = vertexShaderVariables + material.vertexShader;
 
@@ -1209,7 +1209,7 @@ function SidebarMaterial( editor ) {
 
 		if ( textureWarning ) {
 
-			console.warn( "Can't set texture, model doesn't have texture coordinates" );
+			console.warn( 'Can\'t set texture, model doesn\'t have texture coordinates' );
 
 		}
 

+ 1 - 1
editor/js/Sidebar.Object.js

@@ -215,7 +215,7 @@ function SidebarObject( editor ) {
 	// intensity
 
 	var objectIntensityRow = new UIRow();
-	var objectIntensity = new UINumber().setRange( 0, Infinity ).onChange( update );
+	var objectIntensity = new UINumber().onChange( update );
 
 	objectIntensityRow.add( new UIText( strings.getKey( 'sidebar/object/intensity' ) ).setWidth( '90px' ) );
 	objectIntensityRow.add( objectIntensity );

+ 82 - 0
editor/js/Sidebar.Project.Materials.js

@@ -0,0 +1,82 @@
+import { UIBreak, UIPanel, UIRow, UIText, UIListbox, UIButton } from './libs/ui.js';
+
+import { SetMaterialCommand } from './commands/SetMaterialCommand.js';
+
+function SidebarProjectMaterials( editor ) {
+
+	var signals = editor.signals;
+	var strings = editor.strings;
+
+	var container = new UIPanel();
+
+	var headerRow = new UIRow();
+	headerRow.add( new UIText( strings.getKey( 'sidebar/project/materials' ).toUpperCase() ) );
+
+	container.add( headerRow );
+
+	var listbox = new UIListbox();
+	container.add( listbox );
+
+	container.add( new UIBreak() );
+
+	var buttonsRow = new UIRow();
+	container.add( buttonsRow );
+
+	var assignMaterial = new UIButton( strings.getKey( 'sidebar/project/Assign' ) );
+	assignMaterial.onClick( function () {
+
+		var selectedObject = editor.selected;
+
+		if ( selectedObject !== null ) {
+
+			var oldMaterial = selectedObject.material;
+
+			// only assing materials to objects with a material property (e.g. avoid assigning material to THREE.Group)
+
+			if ( oldMaterial !== undefined ) {
+
+				var material = editor.getMaterialById( parseInt( listbox.getValue() ) );
+
+				if ( material !== undefined ) {
+
+					editor.removeMaterial( oldMaterial );
+					editor.execute( new SetMaterialCommand( editor, selectedObject, material ) );
+					editor.addMaterial( material );
+
+				}
+
+			}
+
+		}
+
+	} );
+	buttonsRow.add( assignMaterial );
+
+	// Signals
+
+	function refreshMaterialBrowserUI() {
+
+		listbox.setItems( Object.values( editor.materials ) );
+
+	}
+
+	signals.objectSelected.add( function ( object ) {
+
+		if ( object !== null ) {
+
+			var index = Object.values( editor.materials ).indexOf( object.material );
+			listbox.selectIndex( index );
+
+		}
+
+	} );
+
+	signals.materialAdded.add( refreshMaterialBrowserUI );
+	signals.materialChanged.add( refreshMaterialBrowserUI );
+	signals.materialRemoved.add( refreshMaterialBrowserUI );
+
+	return container;
+
+}
+
+export { SidebarProjectMaterials };

+ 164 - 0
editor/js/Sidebar.Project.Renderer.js

@@ -0,0 +1,164 @@
+import * as THREE from '../../build/three.module.js';
+
+import { UINumber, UIPanel, UIRow, UISelect, UIText } from './libs/ui.js';
+import { UIBoolean } from './libs/ui.three.js';
+
+function SidebarProjectRenderer( editor ) {
+
+	var config = editor.config;
+	var signals = editor.signals;
+	var strings = editor.strings;
+
+	var currentRenderer = null;
+
+	var container = new UIPanel();
+
+	var headerRow = new UIRow();
+	headerRow.add( new UIText( strings.getKey( 'sidebar/project/renderer' ).toUpperCase() ) );
+	container.add( headerRow );
+
+	// Antialias
+
+	var antialiasRow = new UIRow();
+	container.add( antialiasRow );
+
+	antialiasRow.add( new UIText( strings.getKey( 'sidebar/project/antialias' ) ).setWidth( '90px' ) );
+
+	var antialiasBoolean = new UIBoolean( config.getKey( 'project/renderer/antialias' ) ).onChange( createRenderer );
+	antialiasRow.add( antialiasBoolean );
+
+	// Physically Correct lights
+
+	var physicallyCorrectLightsRow = new UIRow();
+	container.add( physicallyCorrectLightsRow );
+
+	physicallyCorrectLightsRow.add( new UIText( strings.getKey( 'sidebar/project/physicallyCorrectLights' ) ).setWidth( '90px' ) );
+
+	var physicallyCorrectLightsBoolean = new UIBoolean( config.getKey( 'project/renderer/physicallyCorrectLights' ) ).onChange( function () {
+
+		currentRenderer.physicallyCorrectLights = this.getValue();
+		signals.rendererUpdated.dispatch();
+
+	} );
+	physicallyCorrectLightsRow.add( physicallyCorrectLightsBoolean );
+
+	// Shadows
+
+	var shadowsRow = new UIRow();
+	container.add( shadowsRow );
+
+	shadowsRow.add( new UIText( strings.getKey( 'sidebar/project/shadows' ) ).setWidth( '90px' ) );
+
+	var shadowsBoolean = new UIBoolean( config.getKey( 'project/renderer/shadows' ) ).onChange( updateShadows );
+	shadowsRow.add( shadowsBoolean );
+
+	var shadowTypeSelect = new UISelect().setOptions( {
+		0: 'Basic',
+		1: 'PCF',
+		2: 'PCF Soft',
+		//	3: 'VSM'
+	} ).setWidth( '125px' ).onChange( updateShadows );
+	shadowTypeSelect.setValue( config.getKey( 'project/renderer/shadowType' ) );
+	shadowsRow.add( shadowTypeSelect );
+
+	function updateShadows() {
+
+		currentRenderer.shadowMap.enabled = shadowsBoolean.getValue();
+		currentRenderer.shadowMap.type = parseFloat( shadowTypeSelect.getValue() );
+
+		signals.rendererUpdated.dispatch();
+
+	}
+
+	// Tonemapping
+
+	var toneMappingRow = new UIRow();
+	container.add( toneMappingRow );
+
+	toneMappingRow.add( new UIText( strings.getKey( 'sidebar/project/toneMapping' ) ).setWidth( '90px' ) );
+
+	var toneMappingSelect = new UISelect().setOptions( {
+		0: 'No',
+		1: 'Linear',
+		2: 'Reinhard',
+		3: 'Cineon',
+		4: 'ACESFilmic'
+	} ).setWidth( '120px' ).onChange( updateToneMapping );
+	toneMappingSelect.setValue( config.getKey( 'project/renderer/toneMapping' ) );
+	toneMappingRow.add( toneMappingSelect );
+
+	var toneMappingExposure = new UINumber( config.getKey( 'project/renderer/toneMappingExposure' ) );
+	toneMappingExposure.setDisplay( toneMappingSelect.getValue() === '0' ? 'none' : '' );
+	toneMappingExposure.setWidth( '30px' ).setMarginLeft( '10px' );
+	toneMappingExposure.setRange( 0, 10 );
+	toneMappingExposure.onChange( updateToneMapping );
+	toneMappingRow.add( toneMappingExposure );
+
+	function updateToneMapping() {
+
+		toneMappingExposure.setDisplay( toneMappingSelect.getValue() === '0' ? 'none' : '' );
+
+		currentRenderer.toneMapping = parseFloat( toneMappingSelect.getValue() );
+		currentRenderer.toneMappingExposure = toneMappingExposure.getValue();
+		signals.rendererUpdated.dispatch();
+
+	}
+
+	//
+
+	function createRenderer() {
+
+		currentRenderer = new THREE.WebGLRenderer( { antialias: antialiasBoolean.getValue() } );
+		currentRenderer.outputEncoding = THREE.sRGBEncoding;
+		currentRenderer.physicallyCorrectLights = physicallyCorrectLightsBoolean.getValue();
+		currentRenderer.shadowMap.enabled = shadowsBoolean.getValue();
+		currentRenderer.shadowMap.type = parseFloat( shadowTypeSelect.getValue() );
+		currentRenderer.toneMapping = parseFloat( toneMappingSelect.getValue() );
+		currentRenderer.toneMappingExposure = toneMappingExposure.getValue();
+
+		signals.rendererChanged.dispatch( currentRenderer );
+
+	}
+
+	createRenderer();
+
+
+	// Signals
+
+	signals.editorCleared.add( function () {
+
+		currentRenderer.physicallyCorrectLights = false;
+		currentRenderer.shadowMap.enabled = true;
+		currentRenderer.shadowMap.type = THREE.PCFShadowMap;
+		currentRenderer.toneMapping = THREE.NoToneMapping;
+		currentRenderer.toneMappingExposure = 1;
+
+		physicallyCorrectLightsBoolean.setValue( currentRenderer.physicallyCorrectLights );
+		shadowsBoolean.setValue( currentRenderer.shadowMap.enabled );
+		shadowTypeSelect.setValue( currentRenderer.shadowMap.type );
+		toneMappingSelect.setValue( currentRenderer.toneMapping );
+		toneMappingExposure.setValue( currentRenderer.toneMappingExposure );
+		toneMappingExposure.setDisplay( currentRenderer.toneMapping === 0 ? 'none' : '' );
+
+		signals.rendererUpdated.dispatch();
+
+	} );
+
+	signals.rendererUpdated.add( function () {
+
+		config.setKey(
+			'project/renderer/antialias', antialiasBoolean.getValue(),
+			'project/renderer/physicallyCorrectLights', physicallyCorrectLightsBoolean.getValue(),
+			'project/renderer/shadows', shadowsBoolean.getValue(),
+			'project/renderer/shadowType', parseFloat( shadowTypeSelect.getValue() ),
+			'project/renderer/toneMapping', parseFloat( toneMappingSelect.getValue() ),
+			'project/renderer/toneMappingExposure', toneMappingExposure.getValue()
+		);
+
+	} );
+
+	return container;
+
+}
+
+export { SidebarProjectRenderer };

+ 145 - 0
editor/js/Sidebar.Project.Video.js

@@ -0,0 +1,145 @@
+import { UIBreak, UIButton, UIInteger, UIPanel, UIProgress, UIRow, UIText } from './libs/ui.js';
+
+import { APP } from './libs/app.js';
+
+function SidebarProjectVideo( editor ) {
+
+	var container = new UIPanel();
+	container.setId( 'render' );
+
+	// Video
+
+	container.add( new UIText( 'Video' ).setTextTransform( 'uppercase' ) );
+	container.add( new UIBreak(), new UIBreak() );
+
+	// Resolution
+
+	var resolutionRow = new UIRow();
+	container.add( resolutionRow );
+
+	resolutionRow.add( new UIText( 'Resolution' ).setWidth( '90px' ) );
+
+	var videoWidth = new UIInteger( 1024 ).setTextAlign( 'center' ).setWidth( '28px' );
+	resolutionRow.add( videoWidth );
+
+	resolutionRow.add( new UIText( '×' ).setTextAlign( 'center' ).setFontSize( '12px' ).setWidth( '12px' ) );
+
+	var videoHeight = new UIInteger( 1024 ).setTextAlign( 'center' ).setWidth( '28px' );
+	resolutionRow.add( videoHeight );
+
+	var videoFPS = new UIInteger( 30 ).setTextAlign( 'center' ).setWidth( '20px' );
+	resolutionRow.add( videoFPS );
+
+	resolutionRow.add( new UIText( 'fps' ).setFontSize( '12px' ) );
+
+	// Duration
+
+	var videoDurationRow = new UIRow();
+	videoDurationRow.add( new UIText( 'Duration' ).setWidth( '90px' ) );
+
+	var videoDuration = new UIInteger( 10 );
+	videoDurationRow.add( videoDuration );
+
+	container.add( videoDurationRow );
+
+	// Render
+
+	container.add( new UIText( '' ).setWidth( '90px' ) );
+
+	const progress = new UIProgress( 0 );
+	progress.setDisplay( 'none' );
+	progress.setWidth( '170px' );
+	container.add( progress );
+
+	const renderButton = new UIButton( 'RENDER' );
+	renderButton.setWidth( '170px' );
+	renderButton.onClick( async () => {
+
+		renderButton.setDisplay( 'none' );
+		progress.setDisplay( '' );
+		progress.setValue( 0 );
+
+		const player = new APP.Player();
+		player.load( editor.toJSON() );
+		player.setPixelRatio( 1 );
+		player.setSize( videoWidth.getValue(), videoHeight.getValue() );
+
+		const canvas = player.dom.firstElementChild;
+
+		//
+
+		const { createFFmpeg, fetchFile } = FFmpeg; // eslint-disable-line no-undef
+		const ffmpeg = createFFmpeg( { log: true } );
+
+		await ffmpeg.load();
+
+		ffmpeg.setProgress( ( { ratio } ) => {
+
+			progress.setValue( ratio );
+
+		} );
+
+		const fps = videoFPS.getValue();
+		const duration = videoDuration.getValue();
+		const frames = duration * fps;
+
+		let currentTime = 0;
+
+		for ( let i = 0; i < frames; i ++ ) {
+
+			player.render( currentTime );
+
+			const num = i.toString().padStart( 5, '0' );
+			ffmpeg.FS( 'writeFile', `tmp.${num}.png`, await fetchFile( canvas.toDataURL() ) );
+			currentTime += 1 / fps;
+
+			progress.setValue( i / frames );
+
+		}
+
+		await ffmpeg.run( '-framerate', String( fps ), '-pattern_type', 'glob', '-i', '*.png', '-c:v', 'libx264', '-pix_fmt', 'yuv420p', '-preset', 'slow', '-crf', String( 6 ), 'out.mp4' );
+
+		const data = ffmpeg.FS( 'readFile', 'out.mp4' );
+
+		for ( let i = 0; i < frames; i ++ ) {
+
+			const num = i.toString().padStart( 5, '0' );
+			ffmpeg.FS( 'unlink', `tmp.${num}.png` );
+
+		}
+
+		save( new Blob( [ data.buffer ], { type: 'video/mp4' } ), 'out.mp4' );
+
+		player.dispose();
+
+		renderButton.setDisplay( '' );
+		progress.setDisplay( 'none' );
+
+	} );
+	container.add( renderButton );
+
+	// SAVE
+
+	const link = document.createElement( 'a' );
+
+	function save( blob, filename ) {
+
+		if ( link.href ) {
+
+			URL.revokeObjectURL( link.href );
+
+		}
+
+		link.href = URL.createObjectURL( blob );
+		link.download = filename;
+		link.dispatchEvent( new MouseEvent( 'click' ) );
+
+	}
+
+	//
+
+	return container;
+
+}
+
+export { SidebarProjectVideo };

+ 14 - 253
editor/js/Sidebar.Project.js

@@ -1,25 +1,20 @@
-import * as THREE from '../../build/three.module.js';
+import { UIPanel, UIRow, UIInput, UICheckbox, UIText, UISpan } from './libs/ui.js';
 
-import { UIPanel, UIRow, UIInput, UICheckbox, UIText, UIListbox, UISpan, UIButton, UISelect, UINumber } from './libs/ui.js';
-import { UIBoolean } from './libs/ui.three.js';
-
-import { SetMaterialCommand } from './commands/SetMaterialCommand.js';
+/* import { SidebarProjectMaterials } from './Sidebar.Project.Materials.js'; */
+import { SidebarProjectRenderer } from './Sidebar.Project.Renderer.js';
+import { SidebarProjectVideo } from './Sidebar.Project.Video.js';
 
 function SidebarProject( editor ) {
 
 	var config = editor.config;
-	var signals = editor.signals;
 	var strings = editor.strings;
 
-	var currentRenderer = null;
-
 	var container = new UISpan();
 
-	var projectsettings = new UIPanel();
-	projectsettings.setBorderTop( '0' );
-	projectsettings.setPaddingTop( '20px' );
-
-	container.add( projectsettings );
+	var settings = new UIPanel();
+	settings.setBorderTop( '0' );
+	settings.setPaddingTop( '20px' );
+	container.add( settings );
 
 	// Title
 
@@ -33,7 +28,7 @@ function SidebarProject( editor ) {
 	titleRow.add( new UIText( strings.getKey( 'sidebar/project/title' ) ).setWidth( '90px' ) );
 	titleRow.add( title );
 
-	projectsettings.add( titleRow );
+	settings.add( titleRow );
 
 	// Editable
 
@@ -47,7 +42,7 @@ function SidebarProject( editor ) {
 	editableRow.add( new UIText( strings.getKey( 'sidebar/project/editable' ) ).setWidth( '90px' ) );
 	editableRow.add( editable );
 
-	projectsettings.add( editableRow );
+	settings.add( editableRow );
 
 	// WebVR
 
@@ -61,247 +56,13 @@ function SidebarProject( editor ) {
 	vrRow.add( new UIText( strings.getKey( 'sidebar/project/vr' ) ).setWidth( '90px' ) );
 	vrRow.add( vr );
 
-	projectsettings.add( vrRow );
-
-	// Renderer
-
-	var rendererPanel = new UIPanel();
-	container.add( rendererPanel );
-
-	var headerRow = new UIRow();
-	headerRow.add( new UIText( strings.getKey( 'sidebar/project/renderer' ).toUpperCase() ) );
-	rendererPanel.add( headerRow );
-
-	// Renderer / Antialias
-
-	var antialiasRow = new UIRow();
-	var antialiasBoolean = new UIBoolean( config.getKey( 'project/renderer/antialias' ) ).onChange( function () {
-
-		createRenderer();
-
-	} );
-
-	antialiasRow.add( new UIText( strings.getKey( 'sidebar/project/antialias' ) ).setWidth( '90px' ) );
-	antialiasRow.add( antialiasBoolean );
-
-	rendererPanel.add( antialiasRow );
-
-	// Renderer / Shadows
-
-	var shadowsRow = new UIRow();
-	var shadowsBoolean = new UIBoolean( config.getKey( 'project/renderer/shadows' ) ).onChange( function () {
-
-		currentRenderer.shadowMap.enabled = this.getValue();
-		signals.rendererUpdated.dispatch();
-
-	} );
-
-	shadowsRow.add( new UIText( strings.getKey( 'sidebar/project/shadows' ) ).setWidth( '90px' ) );
-	shadowsRow.add( shadowsBoolean );
-
-	var shadowTypeSelect = new UISelect().setOptions( {
-		0: 'Basic',
-		1: 'PCF',
-		2: 'PCF (Soft)',
-		//	3: 'VSM'
-	} ).setWidth( '125px' ).onChange( function () {
-
-		currentRenderer.shadowMap.type = parseFloat( this.getValue() );
-		signals.rendererUpdated.dispatch();
-
-	} );
-	shadowTypeSelect.setValue( config.getKey( 'project/renderer/shadowType' ) );
-
-	shadowsRow.add( shadowTypeSelect );
-
-	rendererPanel.add( shadowsRow );
-
-	// Renderer / Physically Correct lights
-
-	var physicallyCorrectLightsRow = new UIRow();
-	var physicallyCorrectLightsBoolean = new UIBoolean( config.getKey( 'project/renderer/physicallyCorrectLights' ) ).onChange( function () {
-
-		currentRenderer.physicallyCorrectLights = this.getValue();
-		signals.rendererUpdated.dispatch();
-
-	} );
-
-	physicallyCorrectLightsRow.add( new UIText( strings.getKey( 'sidebar/project/physicallyCorrectLights' ) ).setWidth( '90px' ) );
-	physicallyCorrectLightsRow.add( physicallyCorrectLightsBoolean );
-
-	rendererPanel.add( physicallyCorrectLightsRow );
-
-	// Renderer / Tonemapping
-
-	var toneMappingRow = new UIRow();
-	var toneMappingSelect = new UISelect().setOptions( {
-		0: 'None',
-		1: 'Linear',
-		2: 'Reinhard',
-		3: 'Cineon',
-		4: 'ACESFilmic'
-	} ).setWidth( '120px' ).onChange( function () {
-
-		currentRenderer.toneMapping = parseFloat( this.getValue() );
-		toneMappingExposure.setDisplay( currentRenderer.toneMapping === 0 ? 'none' : '' );
-		signals.rendererUpdated.dispatch();
-
-	} );
-	toneMappingSelect.setValue( config.getKey( 'project/renderer/toneMapping' ) );
-
-	toneMappingRow.add( new UIText( strings.getKey( 'sidebar/project/toneMapping' ) ).setWidth( '90px' ) );
-	toneMappingRow.add( toneMappingSelect );
-
-	var toneMappingExposure = new UINumber( config.getKey( 'project/renderer/toneMappingExposure' ) );
-	toneMappingExposure.setDisplay( toneMappingSelect.getValue() === '0' ? 'none' : '' );
-	toneMappingExposure.setWidth( '30px' ).setMarginLeft( '10px' );
-	toneMappingExposure.setRange( 0, 10 );
-	toneMappingExposure.onChange( function () {
-
-		currentRenderer.toneMappingExposure = this.getValue();
-		signals.rendererUpdated.dispatch();
-
-	} );
-	toneMappingRow.add( toneMappingExposure );
-
-	rendererPanel.add( toneMappingRow );
+	settings.add( vrRow );
 
 	//
 
-	function createRenderer() {
-
-		currentRenderer = new THREE.WebGLRenderer( { antialias: antialiasBoolean.getValue() } );
-		currentRenderer.outputEncoding = THREE.sRGBEncoding;
-		currentRenderer.physicallyCorrectLights = physicallyCorrectLightsBoolean.getValue();
-		currentRenderer.shadowMap.enabled = shadowsBoolean.getValue();
-		currentRenderer.shadowMap.type = parseFloat( shadowTypeSelect.getValue() );
-		currentRenderer.toneMapping = parseFloat( toneMappingSelect.getValue() );
-		currentRenderer.toneMappingExposure = toneMappingExposure.getValue();
-
-		signals.rendererChanged.dispatch( currentRenderer );
-
-	}
-
-	createRenderer();
-
-	// Materials
-
-	var materials = new UIPanel();
-
-	var headerRow = new UIRow();
-	headerRow.add( new UIText( strings.getKey( 'sidebar/project/materials' ).toUpperCase() ) );
-
-	materials.add( headerRow );
-
-	var listbox = new UIListbox();
-	materials.add( listbox );
-
-	var buttonsRow = new UIRow();
-	buttonsRow.setPadding( '10px 0px' );
-	materials.add( buttonsRow );
-
-	/*
-	var addButton = new UI.Button().setLabel( 'Add' ).setMarginRight( '5px' );
-	addButton.onClick( function () {
-
-		editor.addMaterial( new THREE.MeshStandardMaterial() );
-
-	} );
-	buttonsRow.add( addButton );
-	*/
-
-	var assignMaterial = new UIButton().setLabel( strings.getKey( 'sidebar/project/Assign' ) ).setMargin( '0px 5px' );
-	assignMaterial.onClick( function () {
-
-		var selectedObject = editor.selected;
-
-		if ( selectedObject !== null ) {
-
-			var oldMaterial = selectedObject.material;
-
-			// only assing materials to objects with a material property (e.g. avoid assigning material to THREE.Group)
-
-			if ( oldMaterial !== undefined ) {
-
-				var material = editor.getMaterialById( parseInt( listbox.getValue() ) );
-
-				if ( material !== undefined ) {
-
-					editor.removeMaterial( oldMaterial );
-					editor.execute( new SetMaterialCommand( editor, selectedObject, material ) );
-					editor.addMaterial( material );
-
-				}
-
-			}
-
-		}
-
-	} );
-	buttonsRow.add( assignMaterial );
-
-	container.add( materials );
-
-	// signals
-
-	signals.editorCleared.add( function () {
-
-		currentRenderer.physicallyCorrectLights = false;
-		currentRenderer.shadowMap.enabled = true;
-		currentRenderer.shadowMap.type = 1;
-		currentRenderer.toneMapping = 0;
-		currentRenderer.toneMappingExposure = 1;
-
-		refreshRendererUI();
-
-		signals.rendererUpdated.dispatch();
-
-	} );
-
-	function refreshRendererUI() {
-
-		physicallyCorrectLightsBoolean.setValue( currentRenderer.physicallyCorrectLights );
-		shadowsBoolean.setValue( currentRenderer.shadowMap.enabled );
-		shadowTypeSelect.setValue( currentRenderer.shadowMap.type );
-		toneMappingSelect.setValue( currentRenderer.toneMapping );
-		toneMappingExposure.setValue( currentRenderer.toneMappingExposure );
-		toneMappingExposure.setDisplay( currentRenderer.toneMapping === 0 ? 'none' : '' );
-
-	}
-
-	signals.rendererUpdated.add( function () {
-
-		config.setKey(
-			'project/renderer/antialias', antialiasBoolean.getValue(),
-			'project/renderer/physicallyCorrectLights', physicallyCorrectLightsBoolean.getValue(),
-			'project/renderer/shadows', shadowsBoolean.getValue(),
-			'project/renderer/shadowType', parseFloat( shadowTypeSelect.getValue() ),
-			'project/renderer/toneMapping', parseFloat( toneMappingSelect.getValue() ),
-			'project/renderer/toneMappingExposure', toneMappingExposure.getValue()
-		);
-
-	} );
-
-	signals.objectSelected.add( function ( object ) {
-
-		if ( object !== null ) {
-
-			var index = Object.values( editor.materials ).indexOf( object.material );
-			listbox.selectIndex( index );
-
-		}
-
-	} );
-
-	signals.materialAdded.add( refreshMaterialBrowserUI );
-	signals.materialChanged.add( refreshMaterialBrowserUI );
-	signals.materialRemoved.add( refreshMaterialBrowserUI );
-
-	function refreshMaterialBrowserUI() {
-
-		listbox.setItems( Object.values( editor.materials ) );
-
-	}
+	/* container.add( new SidebarProjectMaterials( editor ) ); */
+	container.add( new SidebarProjectRenderer( editor ) );
+	container.add( new SidebarProjectVideo( editor ) );
 
 	return container;
 

+ 10 - 10
editor/js/Sidebar.Scene.js

@@ -166,7 +166,7 @@ function SidebarScene( editor ) {
 
 	var backgroundType = new UISelect().setOptions( {
 
-		'None': 'None',
+		'None': '',
 		'Color': 'Color',
 		'Texture': 'Texture',
 		'Equirectangular': 'Equirect'
@@ -215,7 +215,7 @@ function SidebarScene( editor ) {
 
 	var environmentType = new UISelect().setOptions( {
 
-		'None': 'None',
+		'None': '',
 		'Background': 'Background'
 
 	} ).setWidth( '150px' );
@@ -260,7 +260,7 @@ function SidebarScene( editor ) {
 	var fogTypeRow = new UIRow();
 	var fogType = new UISelect().setOptions( {
 
-		'None': 'None',
+		'None': '',
 		'Fog': 'Linear',
 		'FogExp2': 'Exponential'
 
@@ -353,7 +353,7 @@ function SidebarScene( editor ) {
 
 			if ( scene.background.isColor ) {
 
-				backgroundType.setValue( "Color" );
+				backgroundType.setValue( 'Color' );
 				backgroundColor.setHexValue( scene.background.getHex() );
 				backgroundTexture.setValue( null );
 				backgroundEquirectangularTexture.setValue( null );
@@ -364,7 +364,7 @@ function SidebarScene( editor ) {
 
 		} else {
 
-			backgroundType.setValue( "None" );
+			backgroundType.setValue( 'None' );
 			backgroundTexture.setValue( null );
 			backgroundEquirectangularTexture.setValue( null );
 
@@ -376,7 +376,7 @@ function SidebarScene( editor ) {
 
 		} else {
 
-			environmentType.setValue( "None" );
+			environmentType.setValue( 'None' );
 
 		}
 
@@ -386,20 +386,20 @@ function SidebarScene( editor ) {
 
 			if ( scene.fog.isFog ) {
 
-				fogType.setValue( "Fog" );
+				fogType.setValue( 'Fog' );
 				fogNear.setValue( scene.fog.near );
 				fogFar.setValue( scene.fog.far );
 
 			} else if ( scene.fog.isFogExp2 ) {
 
-				fogType.setValue( "FogExp2" );
+				fogType.setValue( 'FogExp2' );
 				fogDensity.setValue( scene.fog.density );
 
 			}
 
 		} else {
 
-			fogType.setValue( "None" );
+			fogType.setValue( 'None' );
 
 		}
 
@@ -452,7 +452,7 @@ function SidebarScene( editor ) {
 
 		if ( ignoreObjectSelectedSignal === true ) return;
 
-		if ( object !== null ) {
+		if ( object !== null && object.parent !== null ) {
 
 			let needsRefresh = false;
 			let parent = object.parent;

+ 2 - 2
editor/js/Sidebar.History.js → editor/js/Sidebar.Settings.History.js

@@ -2,7 +2,7 @@
 import { UIPanel, UIBreak, UIText } from './libs/ui.js';
 import { UIBoolean, UIOutliner } from './libs/ui.three.js';
 
-function SidebarHistory( editor ) {
+function SidebarSettingsHistory( editor ) {
 
 	var strings = editor.strings;
 
@@ -130,4 +130,4 @@ function SidebarHistory( editor ) {
 
 }
 
-export { SidebarHistory };
+export { SidebarSettingsHistory };

+ 8 - 4
editor/js/Sidebar.Settings.Shortcuts.js

@@ -1,4 +1,4 @@
-import { UIDiv, UIBreak, UIText, UIRow, UIInput } from './libs/ui.js';
+import { UIPanel, UIText, UIRow, UIInput } from './libs/ui.js';
 
 import { RemoveObjectCommand } from './commands/RemoveObjectCommand.js';
 
@@ -17,8 +17,11 @@ function SidebarSettingsShortcuts( editor ) {
 	var config = editor.config;
 	var signals = editor.signals;
 
-	var container = new UIDiv();
-	container.add( new UIBreak() );
+	var container = new UIPanel();
+
+	var headerRow = new UIRow();
+	headerRow.add( new UIText( strings.getKey( 'sidebar/settings/shortcuts' ).toUpperCase() ) );
+	container.add( headerRow );
 
 	var shortcuts = [ 'translate', 'rotate', 'scale', 'undo', 'focus' ];
 
@@ -27,7 +30,8 @@ function SidebarSettingsShortcuts( editor ) {
 		var configName = 'settings/shortcuts/' + name;
 		var shortcutRow = new UIRow();
 
-		var shortcutInput = new UIInput().setWidth( '150px' ).setFontSize( '12px' );
+		var shortcutInput = new UIInput().setWidth( '15px' ).setFontSize( '12px' );
+		shortcutInput.setTextAlign( 'center' );
 		shortcutInput.setTextTransform( 'lowercase' );
 		shortcutInput.onChange( function () {
 

+ 6 - 2
editor/js/Sidebar.Settings.Viewport.js

@@ -1,4 +1,4 @@
-import { UIDiv, UIText, UIRow } from './libs/ui.js';
+import { UIPanel, UIText, UIRow } from './libs/ui.js';
 import { UIBoolean } from './libs/ui.three.js';
 
 
@@ -7,7 +7,11 @@ function SidebarSettingsViewport( editor ) {
 	var signals = editor.signals;
 	var strings = editor.strings;
 
-	var container = new UIDiv();
+	var container = new UIPanel();
+
+	var headerRow = new UIRow();
+	headerRow.add( new UIText( strings.getKey( 'sidebar/settings/viewport' ).toUpperCase() ) );
+	container.add( headerRow );
 
 	// grid
 

+ 12 - 8
editor/js/Sidebar.Settings.js

@@ -1,17 +1,20 @@
-import { UIPanel, UIRow, UISelect, UIText, UIInteger } from './libs/ui.js';
+import { UIPanel, UIRow, UISelect, UISpan, UIText, UIInteger } from './libs/ui.js';
 
 import { SidebarSettingsViewport } from './Sidebar.Settings.Viewport.js';
 import { SidebarSettingsShortcuts } from './Sidebar.Settings.Shortcuts.js';
+import { SidebarSettingsHistory } from './Sidebar.Settings.History.js';
 
 function SidebarSettings( editor ) {
 
 	var config = editor.config;
 	var strings = editor.strings;
 
-	var container = new UIPanel();
-	container.setBorderTop( '0' );
-	container.setPaddingTop( '20px' );
-	container.setPaddingBottom( '20px' );
+	var container = new UISpan();
+
+	var settings = new UIPanel();
+	settings.setBorderTop( '0' );
+	settings.setPaddingTop( '20px' );
+	container.add( settings );
 
 	// language
 
@@ -42,7 +45,7 @@ function SidebarSettings( editor ) {
 	languageRow.add( new UIText( strings.getKey( 'sidebar/settings/language' ) ).setWidth( '90px' ) );
 	languageRow.add( language );
 
-	container.add( languageRow );
+	settings.add( languageRow );
 
 	// export precision
 
@@ -60,12 +63,13 @@ function SidebarSettings( editor ) {
 	exportPrecisionRow.add( new UIText( strings.getKey( 'sidebar/settings/exportPrecision' ) ).setWidth( '90px' ) );
 	exportPrecisionRow.add( exportPrecision );
 
-	container.add( exportPrecisionRow );
+	settings.add( exportPrecisionRow );
 
 	//
 
-	container.add( new SidebarSettingsShortcuts( editor ) );
 	container.add( new SidebarSettingsViewport( editor ) );
+	container.add( new SidebarSettingsShortcuts( editor ) );
+	container.add( new SidebarSettingsHistory( editor ) );
 
 	return container;
 

+ 1 - 7
editor/js/Sidebar.js

@@ -5,7 +5,6 @@ import { SidebarProperties } from './Sidebar.Properties.js';
 import { SidebarScript } from './Sidebar.Script.js';
 import { SidebarAnimation } from './Sidebar.Animation.js';
 import { SidebarProject } from './Sidebar.Project.js';
-import { SidebarHistory } from './Sidebar.History.js';
 import { SidebarSettings } from './Sidebar.Settings.js';
 
 function Sidebar( editor ) {
@@ -21,13 +20,8 @@ function Sidebar( editor ) {
 		new SidebarAnimation( editor ),
 		new SidebarScript( editor )
 	);
-
 	var project = new SidebarProject( editor );
-
-	var settings = new UISpan().add(
-		new SidebarSettings( editor ),
-		new SidebarHistory( editor )
-	);
+	var settings = new SidebarSettings( editor );
 
 	container.addTab( 'scene', strings.getKey( 'sidebar/scene' ), scene );
 	container.addTab( 'project', strings.getKey( 'sidebar/project' ), project );

+ 9 - 0
editor/js/Strings.js

@@ -28,6 +28,7 @@ function Strings( config ) {
 			'menubar/edit/undo': 'Undo (Ctrl+Z)',
 			'menubar/edit/redo': 'Redo (Ctrl+Shift+Z)',
 			'menubar/edit/clear_history': 'Clear History',
+			'menubar/edit/center': 'Center',
 			'menubar/edit/clone': 'Clone',
 			'menubar/edit/delete': 'Delete (Del)',
 			'menubar/edit/fixcolormaps': 'Fix Color Maps',
@@ -304,12 +305,14 @@ function Strings( config ) {
 			'sidebar/settings/language': 'Language',
 			'sidebar/settings/exportPrecision': 'Export Precision',
 
+			'sidebar/settings/shortcuts': 'Shortcuts',
 			'sidebar/settings/shortcuts/translate': 'Translate',
 			'sidebar/settings/shortcuts/rotate': 'Rotate',
 			'sidebar/settings/shortcuts/scale': 'Scale',
 			'sidebar/settings/shortcuts/undo': 'Undo',
 			'sidebar/settings/shortcuts/focus': 'Focus',
 
+			'sidebar/settings/viewport': 'Viewport',
 			'sidebar/settings/viewport/grid': 'Grid',
 			'sidebar/settings/viewport/helpers': 'Helpers',
 
@@ -352,6 +355,7 @@ function Strings( config ) {
 			'menubar/edit/undo': 'Annuler (Ctrl+Z)',
 			'menubar/edit/redo': 'Refaire (Ctrl+Shift+Z)',
 			'menubar/edit/clear_history': 'Supprimer Historique',
+			'menubar/edit/center': 'Center',
 			'menubar/edit/clone': 'Cloner',
 			'menubar/edit/delete': 'Supprimer (Supp)',
 			'menubar/edit/fixcolormaps': 'Correction des couleurs',
@@ -628,12 +632,14 @@ function Strings( config ) {
 			'sidebar/settings/language': 'Langue',
 			'sidebar/settings/exportPrecision': 'Précision à l\'exportation',
 
+			'sidebar/settings/shortcuts': 'Shortcuts',
 			'sidebar/settings/shortcuts/translate': 'Position',
 			'sidebar/settings/shortcuts/rotate': 'Rotation',
 			'sidebar/settings/shortcuts/scale': 'Échelle',
 			'sidebar/settings/shortcuts/undo': 'Annuler',
 			'sidebar/settings/shortcuts/focus': 'Focus',
 
+			'sidebar/settings/viewport': 'Viewport',
 			'sidebar/settings/viewport/grid': 'Grille',
 			'sidebar/settings/viewport/helpers': 'Helpers',
 
@@ -676,6 +682,7 @@ function Strings( config ) {
 			'menubar/edit/undo': '撤销 (Ctrl+Z)',
 			'menubar/edit/redo': '重做 (Ctrl+Shift+Z)',
 			'menubar/edit/clear_history': '清空历史记录',
+			'menubar/edit/center': 'Center',
 			'menubar/edit/clone': '拷贝',
 			'menubar/edit/delete': '删除 (Del)',
 			'menubar/edit/fixcolormaps': '修复颜色贴图',
@@ -936,12 +943,14 @@ function Strings( config ) {
 			'sidebar/settings/language': '语言',
 			'sidebar/settings/exportPrecision': '输出精度',
 
+			'sidebar/settings/shortcuts': 'Shortcuts',
 			'sidebar/settings/shortcuts/translate': '移动',
 			'sidebar/settings/shortcuts/rotate': '旋转',
 			'sidebar/settings/shortcuts/scale': '缩放',
 			'sidebar/settings/shortcuts/undo': '撤销',
 			'sidebar/settings/shortcuts/focus': '聚焦',
 
+			'sidebar/settings/viewport': 'Viewport',
 			'sidebar/settings/viewport/grid': '网格',
 			'sidebar/settings/viewport/helpers': '辅助',
 

+ 1 - 1
editor/js/Viewport.Info.js

@@ -88,7 +88,7 @@ function ViewportInfo( editor ) {
 
 	function updateFrametime( frametime ) {
 
-		frametimeText.setValue( Number( frametime ).toFixed( 2 ) + " ms" );
+		frametimeText.setValue( Number( frametime ).toFixed( 2 ) + ' ms' );
 
 	}
 

+ 155 - 0
editor/js/Viewport.VR.js

@@ -0,0 +1,155 @@
+import * as THREE from '../../build/three.module.js';
+
+import { HTMLMesh } from './libs/three.html.js';
+
+import { XRControllerModelFactory } from '../../examples/jsm/webxr/XRControllerModelFactory.js';
+
+class VR {
+
+	constructor( editor ) {
+
+		const signals = editor.signals;
+
+		let group = null;
+
+		let camera = null;
+		let renderer = null;
+
+		const intersectables = [];
+
+		this.currentSession = null;
+
+		const onSessionStarted = async ( session ) => {
+
+			if ( group === null ) {
+
+				group = new THREE.Group();
+				editor.sceneHelpers.add( group );
+
+				const mesh = new HTMLMesh( document.getElementById( 'sidebar' ), 300, 700 );
+				mesh.position.set( 1, 1.5, - 0.5 );
+				mesh.rotation.y = - 0.5;
+				group.add( mesh );
+
+				intersectables.push( mesh );
+
+				// controllers
+
+				const controller1 = renderer.xr.getController( 0 );
+				controller1.addEventListener( 'select', onSelect );
+				group.add( controller1 );
+
+				const controller2 = renderer.xr.getController( 1 );
+				controller2.addEventListener( 'selectstart', onSelect );
+				group.add( controller2 );
+
+				const geometry = new THREE.BufferGeometry();
+				geometry.setFromPoints( [ new THREE.Vector3( 0, 0, 0 ), new THREE.Vector3( 0, 0, - 5 ) ] );
+
+				controller1.add( new THREE.Line( geometry ) );
+				controller2.add( new THREE.Line( geometry ) );
+
+				//
+
+				const controllerModelFactory = new XRControllerModelFactory();
+
+				const controllerGrip1 = renderer.xr.getControllerGrip( 0 );
+				controllerGrip1.add( controllerModelFactory.createControllerModel( controllerGrip1 ) );
+				group.add( controllerGrip1 );
+
+				const controllerGrip2 = renderer.xr.getControllerGrip( 1 );
+				controllerGrip2.add( controllerModelFactory.createControllerModel( controllerGrip2 ) );
+				group.add( controllerGrip2 );
+
+			}
+
+			camera = editor.camera.clone();
+
+			group.visible = true;
+
+			this.currentSession = session;
+			this.currentSession.addEventListener( 'end', onSessionEnded );
+
+			await renderer.xr.setSession( this.currentSession );
+
+		};
+
+		const onSessionEnded = async () => {
+
+			editor.camera.copy( camera );
+
+			group.visible = false;
+
+			this.currentSession.removeEventListener( 'end', onSessionEnded );
+			this.currentSession = null;
+
+			await renderer.xr.setSession( null );
+
+			signals.exitedVR.dispatch();
+
+		};
+
+		//
+
+		function onSelect( event ) {
+
+			const controller = event.target;
+
+			const intersections = getIntersections( controller );
+
+			if ( intersections.length > 0 ) {
+
+				const intersection = intersections[ 0 ];
+
+				const object = intersection.object;
+				const uv = intersection.uv;
+
+				object.material.map.click( uv.x, 1 - uv.y );
+
+			}
+
+		}
+
+		const raycaster = new THREE.Raycaster();
+		const tempMatrix = new THREE.Matrix4();
+
+		function getIntersections( controller ) {
+
+			tempMatrix.identity().extractRotation( controller.matrixWorld );
+
+			raycaster.ray.origin.setFromMatrixPosition( controller.matrixWorld );
+			raycaster.ray.direction.set( 0, 0, - 1 ).applyMatrix4( tempMatrix );
+
+			return raycaster.intersectObjects( intersectables );
+
+		}
+
+		// signals
+
+		signals.toggleVR.add( () => {
+
+			if ( this.currentSession === null ) {
+
+				const sessionInit = { optionalFeatures: [ 'local-floor', 'bounded-floor' ] };
+				navigator.xr.requestSession( 'immersive-vr', sessionInit ).then( onSessionStarted );
+
+			} else {
+
+				this.currentSession.end();
+
+			}
+
+		} );
+
+		signals.rendererChanged.add( ( value ) => {
+
+			renderer = value;
+			renderer.xr.enabled = true;
+
+		} );
+
+	}
+
+}
+
+export { VR };

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