浏览代码

Merge branch 'dev' of https://github.com/mrdoob/three.js into dev

Dinesh Salunke 5 年之前
父节点
当前提交
f1ac751d89
共有 93 个文件被更改,包括 5038 次插入900 次删除
  1. 610 143
      build/three.js
  2. 442 435
      build/three.min.js
  3. 612 143
      build/three.module.js
  4. 7 2
      docs/api/en/materials/Material.html
  5. 7 2
      docs/api/zh/materials/Material.html
  6. 89 0
      docs/examples/en/controls/DeviceOrientationControls.html
  7. 119 0
      docs/examples/en/controls/DragControls.html
  8. 166 0
      docs/examples/en/controls/FirstPersonControls.html
  9. 95 0
      docs/examples/en/controls/FlyControls.html
  10. 187 0
      docs/examples/en/controls/OrthographicTrackballControls.html
  11. 149 0
      docs/examples/en/controls/PointerLockControls.html
  12. 211 0
      docs/examples/en/controls/TrackballControls.html
  13. 225 0
      docs/examples/en/controls/TransformControls.html
  14. 89 0
      docs/examples/zh/controls/DeviceOrientationControls.html
  15. 119 0
      docs/examples/zh/controls/DragControls.html
  16. 166 0
      docs/examples/zh/controls/FirstPersonControls.html
  17. 95 0
      docs/examples/zh/controls/FlyControls.html
  18. 187 0
      docs/examples/zh/controls/OrthographicTrackballControls.html
  19. 149 0
      docs/examples/zh/controls/PointerLockControls.html
  20. 211 0
      docs/examples/zh/controls/TrackballControls.html
  21. 225 0
      docs/examples/zh/controls/TransformControls.html
  22. 18 2
      docs/list.js
  23. 3 2
      editor/index.html
  24. 17 1
      editor/js/Menubar.Add.js
  25. 0 2
      editor/js/Sidebar.Geometry.BoxGeometry.js
  26. 0 2
      editor/js/Sidebar.Geometry.CircleGeometry.js
  27. 0 2
      editor/js/Sidebar.Geometry.CylinderGeometry.js
  28. 49 0
      editor/js/Sidebar.Geometry.DodecahedronGeometry.js
  29. 0 2
      editor/js/Sidebar.Geometry.ExtrudeGeometry.js
  30. 0 5
      editor/js/Sidebar.Geometry.IcosahedronGeometry.js
  31. 0 2
      editor/js/Sidebar.Geometry.LatheGeometry.js
  32. 0 4
      editor/js/Sidebar.Geometry.OctahedronGeometry.js
  33. 0 2
      editor/js/Sidebar.Geometry.PlaneGeometry.js
  34. 0 2
      editor/js/Sidebar.Geometry.RingGeometry.js
  35. 0 2
      editor/js/Sidebar.Geometry.ShapeGeometry.js
  36. 0 2
      editor/js/Sidebar.Geometry.SphereGeometry.js
  37. 0 4
      editor/js/Sidebar.Geometry.TetrahedronGeometry.js
  38. 0 2
      editor/js/Sidebar.Geometry.TorusGeometry.js
  39. 0 2
      editor/js/Sidebar.Geometry.TorusKnotGeometry.js
  40. 0 2
      editor/js/Sidebar.Geometry.TubeGeometry.js
  41. 3 3
      editor/js/Sidebar.Properties.js
  42. 3 3
      editor/js/Sidebar.js
  43. 8 0
      editor/js/Strings.js
  44. 1 1
      editor/js/libs/ui.js
  45. 2 1
      examples/files.js
  46. 6 2
      examples/js/controls/FirstPersonControls.js
  47. 2 2
      examples/js/controls/OrthographicTrackballControls.js
  48. 1 1
      examples/js/controls/PointerLockControls.js
  49. 4 4
      examples/js/postprocessing/OutlinePass.js
  50. 1 3
      examples/jsm/controls/DeviceOrientationControls.d.ts
  51. 1 1
      examples/jsm/controls/FirstPersonControls.d.ts
  52. 9 5
      examples/jsm/controls/FirstPersonControls.js
  53. 0 1
      examples/jsm/controls/OrthographicTrackballControls.d.ts
  54. 2 2
      examples/jsm/controls/OrthographicTrackballControls.js
  55. 2 1
      examples/jsm/controls/PointerLockControls.d.ts
  56. 0 2
      examples/jsm/controls/TrackballControls.d.ts
  57. 5 11
      examples/jsm/controls/TransformControls.d.ts
  58. 2 2
      examples/jsm/loaders/MMDLoader.d.ts
  59. 1 1
      examples/jsm/loaders/VTKLoader.d.ts
  60. 7 7
      examples/jsm/loaders/obj2/utils/CodeSerializer.js
  61. 4 4
      examples/jsm/postprocessing/OutlinePass.js
  62. 2 2
      examples/jsm/renderers/WebGLDeferredRenderer.d.ts
  63. 9 19
      examples/misc_controls_drag.html
  64. 2 2
      examples/webvr_ballshooter.html
  65. 2 2
      examples/webvr_cubes.html
  66. 2 2
      examples/webvr_dragging.html
  67. 2 2
      examples/webvr_lorenzattractor.html
  68. 195 0
      examples/webvr_multiview.html
  69. 2 2
      examples/webvr_paint.html
  70. 2 2
      examples/webvr_panorama.html
  71. 2 2
      examples/webvr_rollercoaster.html
  72. 2 2
      examples/webvr_sandbox.html
  73. 2 2
      examples/webvr_sculpt.html
  74. 2 2
      examples/webvr_video.html
  75. 2 2
      examples/webvr_vive_paint.html
  76. 2 2
      examples/webvr_vive_sculpt.html
  77. 5 5
      package.json
  78. 15 0
      src/Three.Legacy.js
  79. 11 0
      src/Three.js
  80. 2 2
      src/animation/KeyframeTrack.d.ts
  81. 1 1
      src/helpers/ArrowHelper.js
  82. 10 0
      src/loaders/MaterialLoader.js
  83. 6 3
      src/materials/Material.js
  84. 50 0
      src/renderers/WebGLMultiviewRenderTarget.js
  85. 61 11
      src/renderers/WebGLRenderer.js
  86. 8 1
      src/renderers/webgl/WebGLCapabilities.js
  87. 211 0
      src/renderers/webgl/WebGLMultiview.js
  88. 46 6
      src/renderers/webgl/WebGLProgram.js
  89. 2 1
      src/renderers/webgl/WebGLState.js
  90. 67 1
      src/renderers/webgl/WebGLTextures.js
  91. 2 0
      src/utils.d.ts
  92. 0 0
      utils/build/rollup-examples.config.js
  93. 0 0
      utils/build/rollup.config.js

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


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


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


+ 7 - 2
docs/api/en/materials/Material.html

@@ -128,6 +128,11 @@
 		Whether rendering this material has any effect on the stencil buffer. Default is *false*.
 		</p>
 
+		<h3>[property:Boolean stencilWriteMask]</h3>
+		<p>
+		The bit mask to use when writing to the stencil buffer. Default is *0xFF*.
+		</p>
+
 		<h3>[property:Boolean stencilFunc]</h3>
 		<p>
 		The stencil comparison function to use. Default is [page:Materials AlwaysStencilFunc]. See stencil function [page:Materials constants] for all possible values.
@@ -138,9 +143,9 @@
 		The value to use when performing stencil comparisons or stencil operations. Default is *0*.
 		</p>
 
-		<h3>[property:Boolean stencilMask]</h3>
+		<h3>[property:Boolean stencilFuncMask]</h3>
 		<p>
-		The bit mask to use when comparing against or writing to the stencil buffer. Default is *0xFF*.
+		The bit mask to use when comparing against the stencil buffer. Default is *0xFF*.
 		</p>
 
 		<h3>[property:Integer stencilFail]</h3>

+ 7 - 2
docs/api/zh/materials/Material.html

@@ -108,6 +108,11 @@
 Whether rendering this material has any effect on the stencil buffer. Default is *false*.
 </p>
 
+<h3>[property:Boolean stencilWriteMask]</h3>
+<p>
+The bit mask to use when writing to the stencil buffer. Default is *0xFF*.
+</p>
+
 <h3>[property:Boolean stencilFunc]</h3>
 <p>
 The stencil comparison function to use. Default is [page:Materials AlwaysStencilFunc]. See stencil function [page:Materials constants] for all possible values.
@@ -118,9 +123,9 @@ The stencil comparison function to use. Default is [page:Materials AlwaysStencil
 The value to use when performing stencil comparisons or stencil operations. Default is *0*.
 </p>
 
-<h3>[property:Boolean stencilMask]</h3>
+<h3>[property:Boolean stencilFuncMask]</h3>
 <p>
-The bit mask to use when comparing against or writing to the stencil buffer. Default is *0xFF*.
+The bit mask to use when comparing against the stencil buffer. Default is *0xFF*.
 </p>
 
 <h3>[property:Integer stencilFail]</h3>

+ 89 - 0
docs/examples/en/controls/DeviceOrientationControls.html

@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			Can be used to orient the camera based on the mobile device's orientation.
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_deviceorientation misc / controls / deviceorientation ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera object] )</h3>
+		<p>
+			<p>
+				[page:Camera object]: The camera to be controlled.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:Number alphaOffset]</h3>
+		<p>
+			The alpha offset in radians. Default is *0*.
+		</p>
+
+		<h3>[property:Object deviceOrientation]</h3>
+		<p>
+			The current *deviceorientation* event object.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h3>[property:Camera object]</h3>
+		<p>
+			The camera to be controlled.
+		</p>
+
+		<h3>[property:Number screenOrientation]</h3>
+		<p>
+			The orientation in degrees (in 90-degree increments) of the viewport relative to the device's natural orientation. Default is *0*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null connect] ()</h3>
+		<p>
+			Adds the event listeners of the controls and enables it.
+		</p>
+
+		<h3>[method:null disconnect] ()</h3>
+		<p>
+			Removes the event listeners of the controls and disables it.
+		</p>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null update] ()</h3>
+		<p>
+			Updates the controls. Usually called in the animation loop.
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/DeviceOrientationControls.js examples/js/controls/DeviceOrientationControls.js]
+		</p>
+	</body>
+</html>

+ 119 - 0
docs/examples/en/controls/DragControls.html

@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:EventDispatcher] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+		This class can be used to provide a drag'n'drop interaction.
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_drag misc / controls / drag ]</p>
+
+		<code>
+var controls = new THREE.DragControls( objects, camera, renderer.domElement );
+
+// add event listener to highlight dragged objects
+
+controls.addEventListener( 'dragstart', function ( event ) {
+
+	event.object.material.emissive.set( 0xaaaaaa );
+
+} );
+
+controls.addEventListener( 'dragend', function ( event ) {
+
+	event.object.material.emissive.set( 0x000000 );
+
+} );
+
+		</code>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Array objects], [param:Camera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:Array objects]: An array of draggable 3D objects.
+			</p>
+			<p>
+			[page:Camera camera]: The camera of the rendered scene.
+			</p>
+			<p>
+			[page:HTMLDOMElement domElement]: The HTML element used for event listeners.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>dragstart</h3>
+		<p>
+			Fires when the user starts to drag a 3D object.
+		</p>
+
+		<h3>drag</h3>
+		<p>
+			Fires when the user drags a 3D object.
+		</p>
+
+		<h3>dragend</h3>
+		<p>
+			Fires when the user has finished dragging a 3D object.
+		</p>
+
+		<h3>hoveron</h3>
+		<p>
+			Fires when the pointer is moved onto a 3D object, or onto one of its children.
+		</p>
+
+		<h3>hoveroff</h3>
+		<p>
+			Fires when the pointer is moved out of a 3D object.
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h2>Methods</h2>
+
+		<p>See the base [page:EventDispatcher] class for common methods.</p>
+
+		<h3>[method:null activate] ()</h3>
+		<p>
+			Adds the event listeners of the controls.
+		</p>
+
+		<h3>[method:null deactivate] ()</h3>
+		<p>
+			Removes the event listeners of the controls.
+		</p>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/DragControls.js examples/js/controls/DragControls.js]
+		</p>
+	</body>
+</html>

+ 166 - 0
docs/examples/en/controls/FirstPersonControls.html

@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			This class is an alternative implementation of [page:FlyControls].
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:webgl_geometry_terrain webgl / geometry / terrain ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera object], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:Camera object]: The camera to be controlled.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:Boolean activeLook]</h3>
+		<p>
+			Whether or not it's possible to look around. Default is *true*.
+		</p>
+
+		<h3>[property:Boolean autoForward]</h3>
+		<p>
+			Whether or not the camera is automatically moved forward. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean constrainVertical]</h3>
+		<p>
+			Whether or not looking around is vertically constrained by [[page:.verticalMin], [page:.verticalMax]]. Default is *false*.
+		</p>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled. Default is *true*.
+		</p>
+
+		<h3>[property:Number heightCoef]</h3>
+		<p>
+			Determines how much faster the camera moves when it's y-component is near [page:.heightMax]. Default is *1*.
+		</p>
+
+		<h3>[property:Number heightMax]</h3>
+		<p>
+			Upper camera height limit used for movement speed adjusment. Default is *1*.
+		</p>
+
+		<h3>[property:Number heightMin]</h3>
+		<p>
+			Lower camera height limit used for movement speed adjusment. Default is *0*.
+		</p>
+
+		<h3>[property:Boolean heightSpeed]</h3>
+		<p>
+			Whether or not the camera's height influences the forward movement speed. Default is *false*.
+			Use the properties [page:.heightCoef], [page:.heightMin] and [page:.heightMax] for configuration.
+		</p>
+
+		<h3>[property:Boolean lookVertical]</h3>
+		<p>
+			Whether or not it's possible to vertically look around. Default is *true*.
+		</p>
+
+		<h3>[property:Number lookSpeed]</h3>
+		<p>
+			The look around speed. Default is *0.005*.
+		</p>
+
+		<h3>[property:Boolean mouseDragOn]</h3>
+		<p>
+			Whether or not the mouse is pressed down. Read-only property.
+		</p>
+
+		<h3>[property:Number movementSpeed]</h3>
+		<p>
+			The movement speed. Default is *1*.
+		</p>
+
+		<h3>[property:Camera object]</h3>
+		<p>
+			The camera to be controlled.
+		</p>
+
+		<h3>[property:Number verticalMax]</h3>
+		<p>
+			How far you can vertically look around, upper limit. Range is 0 to Math.PI radians. Default is *Math.PI*.
+		</p>
+
+		<h3>[property:Number verticalMin]</h3>
+		<p>
+			How far you can vertically look around, lower limit. Range is 0 to Math.PI radians. Default is *0*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null handleResize] ()</h3>
+		<p>
+			Should be called if the application window is resized.
+		</p>
+
+		<h3>[method:FirstPersonControls lookAt]( [param:Vector3 vector] )<br />
+		[method:FirstPersonControls lookAt]( [param:Float x], [param:Float y], [param:Float z] )</h3>
+		<p>
+			<p>
+				<p>
+					vector - A vector representing the target position.
+				</p>
+				<p>
+					Optionally, the x, y, z components of the world space position.
+				</p>
+			</p>
+			<p>
+				Ensures the controls orient the camera towards the defined target position.
+			</p>
+		</p>
+
+		<h3>[method:null update] ( [param:Number delta] )</h3>
+		<p>
+			<p>
+				[page:Number delta]: Time delta value.
+			</p>
+			<p>
+				Updates the controls. Usually called in the animation loop.
+			</p>
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/FirstPersonControls.js examples/js/controls/FirstPersonControls.js]
+		</p>
+	</body>
+</html>

+ 95 - 0
docs/examples/en/controls/FlyControls.html

@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			[name] enables a navigation similar to fly modes in DCC tools like Blender. You can arbitrarily transform the camera in
+			3D space without any limitations (e.g. focus on a specific target).
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_fly misc / controls / fly ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera object], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:Camera object]: The camera to be controlled.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:Boolean autoForward]</h3>
+		<p>
+			If set to *true*, the camera automatically moves forward (and does not stop) when initially translated. Default is *false*.
+		</p>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Boolean dragToLook]</h3>
+		<p>
+			If set to *true*, you can only look around by performing a drag interaction. Default is *false*.
+		</p>
+
+		<h3>[property:Number movementSpeed]</h3>
+		<p>
+			The movement speed. Default is *1*.
+		</p>
+
+		<h3>[property:Camera object]</h3>
+		<p>
+			The camera to be controlled.
+		</p>
+
+		<h3>[property:Number rollSpeed]</h3>
+		<p>
+			The rotation speed. Default is *0.005*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null update] ( [param:Number delta] )</h3>
+		<p>
+			<p>
+				[page:Number delta]: Time delta value.
+			</p>
+			<p>
+				Updates the controls. Usually called in the animation loop.
+			</p>
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/FlyControls.js examples/js/controls/FlyControls.js]
+		</p>
+	</body>
+</html>

+ 187 - 0
docs/examples/en/controls/OrthographicTrackballControls.html

@@ -0,0 +1,187 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:EventDispatcher] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			<p>
+				This class is a special version of [page:TrackballControls] which supports orthographic cameras.
+			</p>
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_trackball_orthographic misc / controls / trackball / orthographic ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:OrthographicCamera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:OrthographicCamera camera]: The orthographic camera of the rendered scene.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>change</h3>
+		<p>
+			Fires when the camera has been transformed by the controls.
+		</p>
+
+		<h3>start</h3>
+		<p>
+			Fires when an interaction (e.g. touch) was initiated.
+		</p>
+
+		<h3>end</h3>
+		<p>
+			Fires when an interaction has finished.
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Number dynamicDampingFactor]</h3>
+		<p>
+			Defines the intensity of damping. Only considered if [page:.staticMoving staticMoving] is set to *false*. Default is *0.2*.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h3>[property:Array keys]</h3>
+		<p>
+			This array holds keycodes for controlling interactions.
+			<ul>
+				<li>When the first defined key is pressed, all mouse interactions (left, middle, right) performs orbiting.</li>
+				<li>When the second defined key is pressed, all mouse interactions (left, middle, right) performs zooming.</li>
+				<li>When the third defined key is pressed, all mouse interactions (left, middle, right) performs panning.</li>
+			</ul>
+			Default is *65, 83, 68* which represents A, S, D.
+		</p>
+
+		<h3>[property:Boolean noPan]</h3>
+		<p>
+			Whether or not panning is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noRoll]</h3>
+		<p>
+			Whether or not rolling is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noRotate]</h3>
+		<p>
+			Whether or not rotation is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noZoom]</h3>
+		<p>
+			Whether or not zooming is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:OrthographicCamera object]</h3>
+		<p>
+			The camera being controlled.
+		</p>
+
+		<h3>[property:Number panSpeed]</h3>
+		<p>
+			The zoom speed. Default is *0.3*.
+		</p>
+
+		<h3>[property:Number rotateSpeed]</h3>
+		<p>
+			The rotation speed. Default is *1.0*.
+		</p>
+
+		<h3>[property:Object screen]</h3>
+		<p>
+			Represents the properties of the screen. Automatically set when [page:.handleResize handleResize]() is called.
+			<ul>
+				<li>left: Represents the offset in pixels to the screen's left boundary.</li>
+				<li>top: Represents the offset in pixels to the screen's top boundary.</li>
+				<li>width: Represents the screen width in pixels.</li>
+				<li>height: Represents the screen height in pixels.</li>
+			</ul>
+		</p>
+
+		<h3>[property:Boolean staticMoving]</h3>
+		<p>
+			Whether or not damping is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Number zoomSpeed]</h3>
+		<p>
+			The zoom speed. Default is *1.2*.
+		</p>
+
+		<h2>Methods</h2>
+
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null handleResize] ()</h3>
+		<p>
+			Should be called if the application window is resized.
+		</p>
+
+		<h3>[method:null panCamera] ()</h3>
+		<p>
+			Performs panning if necessary. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null reset] ()</h3>
+		<p>
+			Resets the controls to its initial state.
+		</p>
+
+		<h3>[method:null rotateCamera] ()</h3>
+		<p>
+			Rotates the camera if necessary. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null update] ()</h3>
+		<p>
+			Updates the controls. Usually called in the animation loop.
+		</p>
+
+		<h3>[method:null zoomCamera] ()</h3>
+		<p>
+			Performs zooming if necessary. Called by [page:.update update]().
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/TrackballControls.js examples/js/controls/TrackballControls.js]
+		</p>
+	</body>
+</html>

+ 149 - 0
docs/examples/en/controls/PointerLockControls.html

@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:EventDispatcher] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+		The implementation of this class is based on the [link:https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API Pointer Lock API].
+		[name] is a perfect choice for first person 3D games.
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_pointerlock misc / controls / pointerlock ]</p>
+
+		<code>
+var controls = new PointerLockControls( camera );
+
+// add event listener to show/hide a UI (e.g. the game's menu)
+
+controls.addEventListener( 'lock', function () {
+
+	menu.style.display = 'none';
+
+} );
+
+controls.addEventListener( 'unlock', function () {
+
+	menu.style.display = 'block';
+
+} );
+
+		</code>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+			[page:Camera camera]: The camera of the rendered scene.
+			</p>
+			<p>
+			[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the document's body.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>change</h3>
+		<p>
+			Fires when the user moves the mouse.
+		</p>
+
+		<h3>lock</h3>
+		<p>
+			Fires when the pointer lock status is "locked" (in other words: the mouse is captured).
+		</p>
+
+		<h3>unlock</h3>
+		<p>
+			Fires when the pointer lock status is "unlocked" (in other words: the mouse is not captured anymore).
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the document's body.
+		</p>
+
+
+		<h3>[property:Boolean isLocked]</h3>
+		<p>
+			Whether or not the controls are locked.
+		</p>
+
+		<h2>Methods</h2>
+
+		<p>See the base [page:EventDispatcher] class for common methods.</p>
+
+		<h3>[method:null connect] ()</h3>
+		<p>
+			Adds the event listeners of the controls.
+		</p>
+
+		<h3>[method:null disconnect] ()</h3>
+		<p>
+			Removes the event listeners of the controls.
+		</p>
+
+		<h3>[method:Vector3 getDirection] ( [param:Vector3 target] )</h3>
+		<p>
+			<p>
+				[page:Vector3 target]: The target vector.
+			</p>
+			<p>
+				Returns the look direction of the camera.
+			</p>
+		</p>
+
+		<h3>[method:null lock] ()</h3>
+		<p>
+			Activates the pointer lock.
+		</p>
+
+		<h3>[method:null moveForward] ( [param:Number distance] )</h3>
+		<p>
+			<p>
+				[page:Number distance]: The signed distance.
+			</p>
+			<p>
+				Moves the camera forward parallel to the xz-plane. Assumes camera.up is y-up.
+			</p>
+		</p>
+
+		<h3>[method:null moveRight] ( [param:Number distance] )</h3>
+		<p>
+			<p>
+				[page:Number distance]: The signed distance.
+			</p>
+			<p>
+				Moves the camera sidewards parallel to the xz-plane.
+			</p>
+		</p>
+
+		<h3>[method:null unlock] ()</h3>
+		<p>
+			Exits the pointer lock.
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/PointerLockControls.js examples/js/controls/PointerLockControls.js]
+		</p>
+	</body>
+</html>

+ 211 - 0
docs/examples/en/controls/TrackballControls.html

@@ -0,0 +1,211 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:EventDispatcher] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			<p>
+				[name] is similar to [page:OrbitControls]. However, it does not maintain a constant camera [page:Object3D.up up] vector.
+				That means if the camera orbits over the “north” and “south” poles, it does not flip to stay "right side up".
+			</p>
+			<p>
+				Notice that [name] can only be used with a perspective camera. Use [page:OrthographicTrackballControls] when working with an orthographic camera.
+			</p>
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_trackball misc / controls / trackball ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:PerspectiveCamera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:PerspectiveCamera camera]: The perspective camera of the rendered scene.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>change</h3>
+		<p>
+			Fires when the camera has been transformed by the controls.
+		</p>
+
+		<h3>start</h3>
+		<p>
+			Fires when an interaction (e.g. touch) was initiated.
+		</p>
+
+		<h3>end</h3>
+		<p>
+			Fires when an interaction has finished.
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Number dynamicDampingFactor]</h3>
+		<p>
+			Defines the intensity of damping. Only considered if [page:.staticMoving staticMoving] is set to *false*. Default is *0.2*.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h3>[property:Array keys]</h3>
+		<p>
+			This array holds keycodes for controlling interactions.
+			<ul>
+				<li>When the first defined key is pressed, all mouse interactions (left, middle, right) performs orbiting.</li>
+				<li>When the second defined key is pressed, all mouse interactions (left, middle, right) performs zooming.</li>
+				<li>When the third defined key is pressed, all mouse interactions (left, middle, right) performs panning.</li>
+			</ul>
+			Default is *65, 83, 68* which represents A, S, D.
+		</p>
+
+		<h3>[property:Number maxDistance]</h3>
+		<p>
+			 How far you can zoom in. Default is *Infinity*.
+		</p>
+
+		<h3>[property:Number minDistance]</h3>
+		<p>
+			 How far you can zoom in. Default is *0*.
+		</p>
+
+		<h3>
+			[property:Object mouseButtons]</h3>
+		<p>
+			This object contains references to the mouse actions used by the controls.
+			<ul>
+				<li>.LEFT is assinged with *THREE.MOUSE.ROTATE*</li>
+				<li>.MIDDLE is assinged with *THREE.MOUSE.ZOOM*</li>
+				<li>.RIGHT is assinged with *THREE.MOUSE.PAN*</li>
+			</ul>
+		</p>
+
+		<h3>[property:Boolean noPan]</h3>
+		<p>
+			Whether or not panning is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noRotate]</h3>
+		<p>
+			Whether or not rotation is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noZoom]</h3>
+		<p>
+			Whether or not zooming is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:PerspectiveCamera object]</h3>
+		<p>
+			The camera being controlled.
+		</p>
+
+		<h3>[property:Number panSpeed]</h3>
+		<p>
+			The zoom speed. Default is *0.3*.
+		</p>
+
+		<h3>[property:Number rotateSpeed]</h3>
+		<p>
+			The rotation speed. Default is *1.0*.
+		</p>
+
+		<h3>[property:Object screen]</h3>
+		<p>
+			Represents the properties of the screen. Automatically set when [page:.handleResize handleResize]() is called.
+			<ul>
+				<li>left: Represents the offset in pixels to the screen's left boundary.</li>
+				<li>top: Represents the offset in pixels to the screen's top boundary.</li>
+				<li>width: Represents the screen width in pixels.</li>
+				<li>height: Represents the screen height in pixels.</li>
+			</ul>
+		</p>
+
+		<h3>[property:Boolean staticMoving]</h3>
+		<p>
+			Whether or not damping is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Number zoomSpeed]</h3>
+		<p>
+			The zoom speed. Default is *1.2*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null checkDistances] ()</h3>
+		<p>
+			Ensures the controls stay in the range [minDistance, maxDistance]. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null handleResize] ()</h3>
+		<p>
+			Should be called if the application window is resized.
+		</p>
+
+		<h3>[method:null panCamera] ()</h3>
+		<p>
+			Performs panning if necessary. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null reset] ()</h3>
+		<p>
+			Resets the controls to its initial state.
+		</p>
+
+		<h3>[method:null rotateCamera] ()</h3>
+		<p>
+			Rotates the camera if necessary. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null update] ()</h3>
+		<p>
+			Updates the controls. Usually called in the animation loop.
+		</p>
+
+		<h3>[method:null zoomCamera] ()</h3>
+		<p>
+			Performs zooming if necessary. Called by [page:.update update]().
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/TrackballControls.js examples/js/controls/TrackballControls.js]
+		</p>
+	</body>
+</html>

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

@@ -0,0 +1,225 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:Object3D] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			This class can be used to transform objects in 3D space by adapting a similar interaction model of DCC tools like Blender.
+			Unlike other controls, it is not intended to transform the scene's camera.
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_transform misc / controls / transform ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:Camera camera]: The camera of the rendered scene.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>change</h3>
+		<p>
+			Fires if any type of change (object or property change) is performed. Property changes
+			are separate events you can add event listeners to. The event type is "propertyname-changed".
+		</p>
+
+		<h3>mouseDown</h3>
+		<p>
+			Fires if a pointer (mouse/touch) becomes active.
+		</p>
+
+		<h3>mouseUp</h3>
+		<p>
+			Fires if a pointer (mouse/touch) is no longer active.
+		</p>
+
+		<h3>objectChange</h3>
+		<p>
+			Fires if the controlled 3D object is changed.
+		</p>
+
+		<h2>Properties</h2>
+
+		<p>See the base [page:Object3D] class for common properties.</p>
+
+		<h3>[property:String axis]</h3>
+		<p>
+			The current transformation axis.
+		</p>
+
+		<h3>[property:Camera camera]</h3>
+		<p>
+			The camera of the rendered scene.
+		</p>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Boolean dragging]</h3>
+		<p>
+			Whether or not dragging is currently performed. Read-only property.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h3>[property:String mode]</h3>
+		<p>
+			The current transformation mode. Possible values are "translate", "rotate" and "scale". Default is *translate*.
+		</p>
+
+		<h3>[property:Object3D object]</h3>
+		<p>
+			The 3D object being controlled.
+		</p>
+
+		<h3>[property:Number rotationSnap]</h3>
+		<p>
+			By default, 3D objects are continously rotated. If you set this property to a numeric value (radians), you can define in which
+			steps the 3D object should be rotated. Deault is *null*.
+		</p>
+
+		<h3>[property:Boolean showX]</h3>
+		<p>
+			Whether or not the x-axis helper should be visible. Default is *true*.
+		</p>
+
+		<h3>[property:Boolean showY]</h3>
+		<p>
+			Whether or not the y-axis helper should be visible. Default is *true*.
+		</p>
+
+		<h3>[property:Boolean showZ]</h3>
+		<p>
+			Whether or not the z-axis helper should be visible. Default is *true*.
+		</p>
+
+		<h3>[property:Number size]</h3>
+		<p>
+			The size of the helper UI (axes/planes). Default is *1*.
+		</p>
+
+		<h3>[property:String space]</h3>
+		<p>
+			Defines in which coordinate space transformations should be performed. Possible values are "world" and "local". Default is *world*.
+		</p>
+
+		<h3>[property:Number translationSnap]</h3>
+		<p>
+			By default, 3D objects are continously translated. If you set this property to a numeric value (world units), you can define in which
+			steps the 3D object should be translated. Deault is *null*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<p>See the base [page:Object3D] class for common methods.</p>
+
+		<h3>[method:TransformControls attach] ( [param:Object3D object] )</h3>
+		<p>
+			<p>
+				[page:Object3D object]: The 3D object that should be transformed.
+			</p>
+			<p>
+				Sets the 3D object that should be transformed and ensures the controls UI is visible.
+			</p>
+		</p>
+
+		<h3>[method:TransformControls detach] ()</h3>
+		<p>
+			Removes the current 3D object from the controls and makes the helper UI is invisible.
+		</p>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:String getMode] ()</h3>
+		<p>
+			Returns the transformation mode.
+		</p>
+
+		<h3>[method:null setMode] ( [param:String mode] )</h3>
+		<p>
+			<p>
+				[page:String mode]: The transformation mode.
+			</p>
+			<p>
+				Sets the transformation mode.
+			</p>
+		</p>
+
+		<h3>[method:null setRotationSnap] ( [param:Number rotationSnap] )</h3>
+		<p>
+			<p>
+				[page:Number rotationSnap]: The rotation snap.
+			</p>
+			<p>
+				Sets the rotation snap.
+			</p>
+		</p>
+
+		<h3>[method:null setSize] ( [param:Number size] )</h3>
+		<p>
+			<p>
+				[page:Number size]: The size of the helper UI.
+			</p>
+			<p>
+				Sets the size of the helper UI.
+			</p>
+		</p>
+
+		<h3>[method:null setSpace] ( [param:String space] )</h3>
+		<p>
+			<p>
+				[page:String space]: The coordinate space in which transformations are applied.
+			</p>
+			<p>
+				Sets the coordinate space in which transformations are applied.
+			</p>
+		</p>
+
+		<h3>[method:null setTranslationSnap] ( [param:Number translationSnap] )</h3>
+		<p>
+			<p>
+				[page:Number translationSnap]: The translation snap.
+			</p>
+			<p>
+				Sets the translation snap.
+			</p>
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/TransformControls.js examples/js/controls/TransformControls.js]
+		</p>
+	</body>
+</html>

+ 89 - 0
docs/examples/zh/controls/DeviceOrientationControls.html

@@ -0,0 +1,89 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			Can be used to orient the camera based on the mobile device's orientation.
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_deviceorientation misc / controls / deviceorientation ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera object] )</h3>
+		<p>
+			<p>
+				[page:Camera object]: The camera to be controlled.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:Number alphaOffset]</h3>
+		<p>
+			The alpha offset in radians. Default is *0*.
+		</p>
+
+		<h3>[property:Object deviceOrientation]</h3>
+		<p>
+			The current *deviceorientation* event object.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h3>[property:Camera object]</h3>
+		<p>
+			The camera to be controlled.
+		</p>
+
+		<h3>[property:Number screenOrientation]</h3>
+		<p>
+			The orientation in degrees (in 90-degree increments) of the viewport relative to the device's natural orientation. Default is *0*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null connect] ()</h3>
+		<p>
+			Adds the event listeners of the controls and enables it.
+		</p>
+
+		<h3>[method:null disconnect] ()</h3>
+		<p>
+			Removes the event listeners of the controls and disables it.
+		</p>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null update] ()</h3>
+		<p>
+			Updates the controls. Usually called in the animation loop.
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/DeviceOrientationControls.js examples/js/controls/DeviceOrientationControls.js]
+		</p>
+	</body>
+</html>

+ 119 - 0
docs/examples/zh/controls/DragControls.html

@@ -0,0 +1,119 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:EventDispatcher] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+		This class can be used to provide a drag'n'drop interaction.
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_drag misc / controls / drag ]</p>
+
+		<code>
+var controls = new THREE.DragControls( objects, camera, renderer.domElement );
+
+// add event listener to highlight dragged objects
+
+controls.addEventListener( 'dragstart', function ( event ) {
+
+	event.object.material.emissive.set( 0xaaaaaa );
+
+} );
+
+controls.addEventListener( 'dragend', function ( event ) {
+
+	event.object.material.emissive.set( 0x000000 );
+
+} );
+
+		</code>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Array objects], [param:Camera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:Array objects]: An array of draggable 3D objects.
+			</p>
+			<p>
+			[page:Camera camera]: The camera of the rendered scene.
+			</p>
+			<p>
+			[page:HTMLDOMElement domElement]: The HTML element used for event listeners.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>dragstart</h3>
+		<p>
+			Fires when the user starts to drag a 3D object.
+		</p>
+
+		<h3>drag</h3>
+		<p>
+			Fires when the user drags a 3D object.
+		</p>
+
+		<h3>dragend</h3>
+		<p>
+			Fires when the user has finished dragging a 3D object.
+		</p>
+
+		<h3>hoveron</h3>
+		<p>
+			Fires when the pointer is moved onto a 3D object, or onto one of its children.
+		</p>
+
+		<h3>hoveroff</h3>
+		<p>
+			Fires when the pointer is moved out of a 3D object.
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h2>Methods</h2>
+
+		<p>See the base [page:EventDispatcher] class for common methods.</p>
+
+		<h3>[method:null activate] ()</h3>
+		<p>
+			Adds the event listeners of the controls.
+		</p>
+
+		<h3>[method:null deactivate] ()</h3>
+		<p>
+			Removes the event listeners of the controls.
+		</p>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/DragControls.js examples/js/controls/DragControls.js]
+		</p>
+	</body>
+</html>

+ 166 - 0
docs/examples/zh/controls/FirstPersonControls.html

@@ -0,0 +1,166 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			This class is an alternative implementation of [page:FlyControls].
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:webgl_geometry_terrain webgl / geometry / terrain ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera object], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:Camera object]: The camera to be controlled.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:Boolean activeLook]</h3>
+		<p>
+			Whether or not it's possible to look around. Default is *true*.
+		</p>
+
+		<h3>[property:Boolean autoForward]</h3>
+		<p>
+			Whether or not the camera is automatically moved forward. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean constrainVertical]</h3>
+		<p>
+			Whether or not looking around is vertically constrained by [[page:.verticalMin], [page:.verticalMax]]. Default is *false*.
+		</p>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled. Default is *true*.
+		</p>
+
+		<h3>[property:Number heightCoef]</h3>
+		<p>
+			Determines how much faster the camera moves when it's y-component is near [page:.heightMax]. Default is *1*.
+		</p>
+
+		<h3>[property:Number heightMax]</h3>
+		<p>
+			Upper camera height limit used for movement speed adjusment. Default is *1*.
+		</p>
+
+		<h3>[property:Number heightMin]</h3>
+		<p>
+			Lower camera height limit used for movement speed adjusment. Default is *0*.
+		</p>
+
+		<h3>[property:Boolean heightSpeed]</h3>
+		<p>
+			Whether or not the camera's height influences the forward movement speed. Default is *false*.
+			Use the properties [page:.heightCoef], [page:.heightMin] and [page:.heightMax] for configuration.
+		</p>
+
+		<h3>[property:Boolean lookVertical]</h3>
+		<p>
+			Whether or not it's possible to vertically look around. Default is *true*.
+		</p>
+
+		<h3>[property:Number lookSpeed]</h3>
+		<p>
+			The look around speed. Default is *0.005*.
+		</p>
+
+		<h3>[property:Boolean mouseDragOn]</h3>
+		<p>
+			Whether or not the mouse is pressed down. Read-only property.
+		</p>
+
+		<h3>[property:Number movementSpeed]</h3>
+		<p>
+			The movement speed. Default is *1*.
+		</p>
+
+		<h3>[property:Camera object]</h3>
+		<p>
+			The camera to be controlled.
+		</p>
+
+		<h3>[property:Number verticalMax]</h3>
+		<p>
+			How far you can vertically look around, upper limit. Range is 0 to Math.PI radians. Default is *Math.PI*.
+		</p>
+
+		<h3>[property:Number verticalMin]</h3>
+		<p>
+			How far you can vertically look around, lower limit. Range is 0 to Math.PI radians. Default is *0*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null handleResize] ()</h3>
+		<p>
+			Should be called if the application window is resized.
+		</p>
+
+		<h3>[method:FirstPersonControls lookAt]( [param:Vector3 vector] )<br />
+		[method:FirstPersonControls lookAt]( [param:Float x], [param:Float y], [param:Float z] )</h3>
+		<p>
+			<p>
+				<p>
+					vector - A vector representing the target position.
+				</p>
+				<p>
+					Optionally, the x, y, z components of the world space position.
+				</p>
+			</p>
+			<p>
+				Ensures the controls orient the camera towards the defined target position.
+			</p>
+		</p>
+
+		<h3>[method:null update] ( [param:Number delta] )</h3>
+		<p>
+			<p>
+				[page:Number delta]: Time delta value.
+			</p>
+			<p>
+				Updates the controls. Usually called in the animation loop.
+			</p>
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/FirstPersonControls.js examples/js/controls/FirstPersonControls.js]
+		</p>
+	</body>
+</html>

+ 95 - 0
docs/examples/zh/controls/FlyControls.html

@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			[name] enables a navigation similar to fly modes in DCC tools like Blender. You can arbitrarily transform the camera in
+			3D space without any limitations (e.g. focus on a specific target).
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_fly misc / controls / fly ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera object], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:Camera object]: The camera to be controlled.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:Boolean autoForward]</h3>
+		<p>
+			If set to *true*, the camera automatically moves forward (and does not stop) when initially translated. Default is *false*.
+		</p>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Boolean dragToLook]</h3>
+		<p>
+			If set to *true*, you can only look around by performing a drag interaction. Default is *false*.
+		</p>
+
+		<h3>[property:Number movementSpeed]</h3>
+		<p>
+			The movement speed. Default is *1*.
+		</p>
+
+		<h3>[property:Camera object]</h3>
+		<p>
+			The camera to be controlled.
+		</p>
+
+		<h3>[property:Number rollSpeed]</h3>
+		<p>
+			The rotation speed. Default is *0.005*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null update] ( [param:Number delta] )</h3>
+		<p>
+			<p>
+				[page:Number delta]: Time delta value.
+			</p>
+			<p>
+				Updates the controls. Usually called in the animation loop.
+			</p>
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/FlyControls.js examples/js/controls/FlyControls.js]
+		</p>
+	</body>
+</html>

+ 187 - 0
docs/examples/zh/controls/OrthographicTrackballControls.html

@@ -0,0 +1,187 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:EventDispatcher] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			<p>
+				This class is a special version of [page:TrackballControls] which supports orthographic cameras.
+			</p>
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_trackball_orthographic misc / controls / trackball / orthographic ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:OrthographicCamera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:OrthographicCamera camera]: The orthographic camera of the rendered scene.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>change</h3>
+		<p>
+			Fires when the camera has been transformed by the controls.
+		</p>
+
+		<h3>start</h3>
+		<p>
+			Fires when an interaction (e.g. touch) was initiated.
+		</p>
+
+		<h3>end</h3>
+		<p>
+			Fires when an interaction has finished.
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Number dynamicDampingFactor]</h3>
+		<p>
+			Defines the intensity of damping. Only considered if [page:.staticMoving staticMoving] is set to *false*. Default is *0.2*.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h3>[property:Array keys]</h3>
+		<p>
+			This array holds keycodes for controlling interactions.
+			<ul>
+				<li>When the first defined key is pressed, all mouse interactions (left, middle, right) performs orbiting.</li>
+				<li>When the second defined key is pressed, all mouse interactions (left, middle, right) performs zooming.</li>
+				<li>When the third defined key is pressed, all mouse interactions (left, middle, right) performs panning.</li>
+			</ul>
+			Default is *65, 83, 68* which represents A, S, D.
+		</p>
+
+		<h3>[property:Boolean noPan]</h3>
+		<p>
+			Whether or not panning is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noRoll]</h3>
+		<p>
+			Whether or not rolling is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noRotate]</h3>
+		<p>
+			Whether or not rotation is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noZoom]</h3>
+		<p>
+			Whether or not zooming is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:OrthographicCamera object]</h3>
+		<p>
+			The camera being controlled.
+		</p>
+
+		<h3>[property:Number panSpeed]</h3>
+		<p>
+			The zoom speed. Default is *0.3*.
+		</p>
+
+		<h3>[property:Number rotateSpeed]</h3>
+		<p>
+			The rotation speed. Default is *1.0*.
+		</p>
+
+		<h3>[property:Object screen]</h3>
+		<p>
+			Represents the properties of the screen. Automatically set when [page:.handleResize handleResize]() is called.
+			<ul>
+				<li>left: Represents the offset in pixels to the screen's left boundary.</li>
+				<li>top: Represents the offset in pixels to the screen's top boundary.</li>
+				<li>width: Represents the screen width in pixels.</li>
+				<li>height: Represents the screen height in pixels.</li>
+			</ul>
+		</p>
+
+		<h3>[property:Boolean staticMoving]</h3>
+		<p>
+			Whether or not damping is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Number zoomSpeed]</h3>
+		<p>
+			The zoom speed. Default is *1.2*.
+		</p>
+
+		<h2>Methods</h2>
+
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null handleResize] ()</h3>
+		<p>
+			Should be called if the application window is resized.
+		</p>
+
+		<h3>[method:null panCamera] ()</h3>
+		<p>
+			Performs panning if necessary. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null reset] ()</h3>
+		<p>
+			Resets the controls to its initial state.
+		</p>
+
+		<h3>[method:null rotateCamera] ()</h3>
+		<p>
+			Rotates the camera if necessary. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null update] ()</h3>
+		<p>
+			Updates the controls. Usually called in the animation loop.
+		</p>
+
+		<h3>[method:null zoomCamera] ()</h3>
+		<p>
+			Performs zooming if necessary. Called by [page:.update update]().
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/TrackballControls.js examples/js/controls/TrackballControls.js]
+		</p>
+	</body>
+</html>

+ 149 - 0
docs/examples/zh/controls/PointerLockControls.html

@@ -0,0 +1,149 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:EventDispatcher] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+		The implementation of this class is based on the [link:https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API Pointer Lock API].
+		[name] is a perfect choice for first person 3D games.
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_pointerlock misc / controls / pointerlock ]</p>
+
+		<code>
+var controls = new PointerLockControls( camera );
+
+// add event listener to show/hide a UI (e.g. the game's menu)
+
+controls.addEventListener( 'lock', function () {
+
+	menu.style.display = 'none';
+
+} );
+
+controls.addEventListener( 'unlock', function () {
+
+	menu.style.display = 'block';
+
+} );
+
+		</code>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+			[page:Camera camera]: The camera of the rendered scene.
+			</p>
+			<p>
+			[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the document's body.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>change</h3>
+		<p>
+			Fires when the user moves the mouse.
+		</p>
+
+		<h3>lock</h3>
+		<p>
+			Fires when the pointer lock status is "locked" (in other words: the mouse is captured).
+		</p>
+
+		<h3>unlock</h3>
+		<p>
+			Fires when the pointer lock status is "unlocked" (in other words: the mouse is not captured anymore).
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the document's body.
+		</p>
+
+
+		<h3>[property:Boolean isLocked]</h3>
+		<p>
+			Whether or not the controls are locked.
+		</p>
+
+		<h2>Methods</h2>
+
+		<p>See the base [page:EventDispatcher] class for common methods.</p>
+
+		<h3>[method:null connect] ()</h3>
+		<p>
+			Adds the event listeners of the controls.
+		</p>
+
+		<h3>[method:null disconnect] ()</h3>
+		<p>
+			Removes the event listeners of the controls.
+		</p>
+
+		<h3>[method:Vector3 getDirection] ( [param:Vector3 target] )</h3>
+		<p>
+			<p>
+				[page:Vector3 target]: The target vector.
+			</p>
+			<p>
+				Returns the look direction of the camera.
+			</p>
+		</p>
+
+		<h3>[method:null lock] ()</h3>
+		<p>
+			Activates the pointer lock.
+		</p>
+
+		<h3>[method:null moveForward] ( [param:Number distance] )</h3>
+		<p>
+			<p>
+				[page:Number distance]: The signed distance.
+			</p>
+			<p>
+				Moves the camera forward parallel to the xz-plane. Assumes camera.up is y-up.
+			</p>
+		</p>
+
+		<h3>[method:null moveRight] ( [param:Number distance] )</h3>
+		<p>
+			<p>
+				[page:Number distance]: The signed distance.
+			</p>
+			<p>
+				Moves the camera sidewards parallel to the xz-plane.
+			</p>
+		</p>
+
+		<h3>[method:null unlock] ()</h3>
+		<p>
+			Exits the pointer lock.
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/PointerLockControls.js examples/js/controls/PointerLockControls.js]
+		</p>
+	</body>
+</html>

+ 211 - 0
docs/examples/zh/controls/TrackballControls.html

@@ -0,0 +1,211 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:EventDispatcher] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			<p>
+				[name] is similar to [page:OrbitControls]. However, it does not maintain a constant camera [page:Object3D.up up] vector.
+				That means if the camera orbits over the “north” and “south” poles, it does not flip to stay "right side up".
+			</p>
+			<p>
+				Notice that [name] can only be used with a perspective camera. Use [page:OrthographicTrackballControls] when working with an orthographic camera.
+			</p>
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_trackball misc / controls / trackball ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:PerspectiveCamera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:PerspectiveCamera camera]: The perspective camera of the rendered scene.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>change</h3>
+		<p>
+			Fires when the camera has been transformed by the controls.
+		</p>
+
+		<h3>start</h3>
+		<p>
+			Fires when an interaction (e.g. touch) was initiated.
+		</p>
+
+		<h3>end</h3>
+		<p>
+			Fires when an interaction has finished.
+		</p>
+
+		<h2>Properties</h2>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Number dynamicDampingFactor]</h3>
+		<p>
+			Defines the intensity of damping. Only considered if [page:.staticMoving staticMoving] is set to *false*. Default is *0.2*.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h3>[property:Array keys]</h3>
+		<p>
+			This array holds keycodes for controlling interactions.
+			<ul>
+				<li>When the first defined key is pressed, all mouse interactions (left, middle, right) performs orbiting.</li>
+				<li>When the second defined key is pressed, all mouse interactions (left, middle, right) performs zooming.</li>
+				<li>When the third defined key is pressed, all mouse interactions (left, middle, right) performs panning.</li>
+			</ul>
+			Default is *65, 83, 68* which represents A, S, D.
+		</p>
+
+		<h3>[property:Number maxDistance]</h3>
+		<p>
+			 How far you can zoom in. Default is *Infinity*.
+		</p>
+
+		<h3>[property:Number minDistance]</h3>
+		<p>
+			 How far you can zoom in. Default is *0*.
+		</p>
+
+		<h3>
+			[property:Object mouseButtons]</h3>
+		<p>
+			This object contains references to the mouse actions used by the controls.
+			<ul>
+				<li>.LEFT is assinged with *THREE.MOUSE.ROTATE*</li>
+				<li>.MIDDLE is assinged with *THREE.MOUSE.ZOOM*</li>
+				<li>.RIGHT is assinged with *THREE.MOUSE.PAN*</li>
+			</ul>
+		</p>
+
+		<h3>[property:Boolean noPan]</h3>
+		<p>
+			Whether or not panning is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noRotate]</h3>
+		<p>
+			Whether or not rotation is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean noZoom]</h3>
+		<p>
+			Whether or not zooming is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:PerspectiveCamera object]</h3>
+		<p>
+			The camera being controlled.
+		</p>
+
+		<h3>[property:Number panSpeed]</h3>
+		<p>
+			The zoom speed. Default is *0.3*.
+		</p>
+
+		<h3>[property:Number rotateSpeed]</h3>
+		<p>
+			The rotation speed. Default is *1.0*.
+		</p>
+
+		<h3>[property:Object screen]</h3>
+		<p>
+			Represents the properties of the screen. Automatically set when [page:.handleResize handleResize]() is called.
+			<ul>
+				<li>left: Represents the offset in pixels to the screen's left boundary.</li>
+				<li>top: Represents the offset in pixels to the screen's top boundary.</li>
+				<li>width: Represents the screen width in pixels.</li>
+				<li>height: Represents the screen height in pixels.</li>
+			</ul>
+		</p>
+
+		<h3>[property:Boolean staticMoving]</h3>
+		<p>
+			Whether or not damping is disabled. Default is *false*.
+		</p>
+
+		<h3>[property:Number zoomSpeed]</h3>
+		<p>
+			The zoom speed. Default is *1.2*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null checkDistances] ()</h3>
+		<p>
+			Ensures the controls stay in the range [minDistance, maxDistance]. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:null handleResize] ()</h3>
+		<p>
+			Should be called if the application window is resized.
+		</p>
+
+		<h3>[method:null panCamera] ()</h3>
+		<p>
+			Performs panning if necessary. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null reset] ()</h3>
+		<p>
+			Resets the controls to its initial state.
+		</p>
+
+		<h3>[method:null rotateCamera] ()</h3>
+		<p>
+			Rotates the camera if necessary. Called by [page:.update update]().
+		</p>
+
+		<h3>[method:null update] ()</h3>
+		<p>
+			Updates the controls. Usually called in the animation loop.
+		</p>
+
+		<h3>[method:null zoomCamera] ()</h3>
+		<p>
+			Performs zooming if necessary. Called by [page:.update update]().
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/TrackballControls.js examples/js/controls/TrackballControls.js]
+		</p>
+	</body>
+</html>

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

@@ -0,0 +1,225 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:Object3D] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			This class can be used to transform objects in 3D space by adapting a similar interaction model of DCC tools like Blender.
+			Unlike other controls, it is not intended to transform the scene's camera.
+		</p>
+
+		<h2>Example</h2>
+
+		<p>[example:misc_controls_transform misc / controls / transform ]</p>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )</h3>
+		<p>
+			<p>
+				[page:Camera camera]: The camera of the rendered scene.
+			</p>
+			<p>
+				[page:HTMLDOMElement domElement]: (optional) The HTML element used for event listeners. By default this is the whole document,
+				however if you only want the controls to work over a specific element (e.g. the canvas) you can specify that here.
+			</p>
+			<p>
+				Creates a new instance of [name].
+			</p>
+		</p>
+
+		<h2>Events</h2>
+
+		<h3>change</h3>
+		<p>
+			Fires if any type of change (object or property change) is performed. Property changes
+			are separate events you can add event listeners to. The event type is "propertyname-changed".
+		</p>
+
+		<h3>mouseDown</h3>
+		<p>
+			Fires if a pointer (mouse/touch) becomes active.
+		</p>
+
+		<h3>mouseUp</h3>
+		<p>
+			Fires if a pointer (mouse/touch) is no longer active.
+		</p>
+
+		<h3>objectChange</h3>
+		<p>
+			Fires if the controlled 3D object is changed.
+		</p>
+
+		<h2>Properties</h2>
+
+		<p>See the base [page:Object3D] class for common properties.</p>
+
+		<h3>[property:String axis]</h3>
+		<p>
+			The current transformation axis.
+		</p>
+
+		<h3>[property:Camera camera]</h3>
+		<p>
+			The camera of the rendered scene.
+		</p>
+
+		<h3>[property:HTMLDOMElement domElement]</h3>
+		<p>
+			The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will
+			not set up new event listeners. Default is the whole document.
+		</p>
+
+		<h3>[property:Boolean dragging]</h3>
+		<p>
+			Whether or not dragging is currently performed. Read-only property.
+		</p>
+
+		<h3>[property:Boolean enabled]</h3>
+		<p>
+			Whether or not the controls are enabled.
+		</p>
+
+		<h3>[property:String mode]</h3>
+		<p>
+			The current transformation mode. Possible values are "translate", "rotate" and "scale". Default is *translate*.
+		</p>
+
+		<h3>[property:Object3D object]</h3>
+		<p>
+			The 3D object being controlled.
+		</p>
+
+		<h3>[property:Number rotationSnap]</h3>
+		<p>
+			By default, 3D objects are continously rotated. If you set this property to a numeric value (radians), you can define in which
+			steps the 3D object should be rotated. Deault is *null*.
+		</p>
+
+		<h3>[property:Boolean showX]</h3>
+		<p>
+			Whether or not the x-axis helper should be visible. Default is *true*.
+		</p>
+
+		<h3>[property:Boolean showY]</h3>
+		<p>
+			Whether or not the y-axis helper should be visible. Default is *true*.
+		</p>
+
+		<h3>[property:Boolean showZ]</h3>
+		<p>
+			Whether or not the z-axis helper should be visible. Default is *true*.
+		</p>
+
+		<h3>[property:Number size]</h3>
+		<p>
+			The size of the helper UI (axes/planes). Default is *1*.
+		</p>
+
+		<h3>[property:String space]</h3>
+		<p>
+			Defines in which coordinate space transformations should be performed. Possible values are "world" and "local". Default is *world*.
+		</p>
+
+		<h3>[property:Number translationSnap]</h3>
+		<p>
+			By default, 3D objects are continously translated. If you set this property to a numeric value (world units), you can define in which
+			steps the 3D object should be translated. Deault is *null*.
+		</p>
+
+		<h2>Methods</h2>
+
+		<p>See the base [page:Object3D] class for common methods.</p>
+
+		<h3>[method:TransformControls attach] ( [param:Object3D object] )</h3>
+		<p>
+			<p>
+				[page:Object3D object]: The 3D object that should be transformed.
+			</p>
+			<p>
+				Sets the 3D object that should be transformed and ensures the controls UI is visible.
+			</p>
+		</p>
+
+		<h3>[method:TransformControls detach] ()</h3>
+		<p>
+			Removes the current 3D object from the controls and makes the helper UI is invisible.
+		</p>
+
+		<h3>[method:null dispose] ()</h3>
+		<p>
+			Should be called if the controls is no longer required.
+		</p>
+
+		<h3>[method:String getMode] ()</h3>
+		<p>
+			Returns the transformation mode.
+		</p>
+
+		<h3>[method:null setMode] ( [param:String mode] )</h3>
+		<p>
+			<p>
+				[page:String mode]: The transformation mode.
+			</p>
+			<p>
+				Sets the transformation mode.
+			</p>
+		</p>
+
+		<h3>[method:null setRotationSnap] ( [param:Number rotationSnap] )</h3>
+		<p>
+			<p>
+				[page:Number rotationSnap]: The rotation snap.
+			</p>
+			<p>
+				Sets the rotation snap.
+			</p>
+		</p>
+
+		<h3>[method:null setSize] ( [param:Number size] )</h3>
+		<p>
+			<p>
+				[page:Number size]: The size of the helper UI.
+			</p>
+			<p>
+				Sets the size of the helper UI.
+			</p>
+		</p>
+
+		<h3>[method:null setSpace] ( [param:String space] )</h3>
+		<p>
+			<p>
+				[page:String space]: The coordinate space in which transformations are applied.
+			</p>
+			<p>
+				Sets the coordinate space in which transformations are applied.
+			</p>
+		</p>
+
+		<h3>[method:null setTranslationSnap] ( [param:Number translationSnap] )</h3>
+		<p>
+			<p>
+				[page:Number translationSnap]: The translation snap.
+			</p>
+			<p>
+				Sets the translation snap.
+			</p>
+		</p>
+
+		<h2>Source</h2>
+
+		<p>
+			[link:https://github.com/mrdoob/three.js/blob/master/examples/js/controls/TransformControls.js examples/js/controls/TransformControls.js]
+		</p>
+	</body>
+</html>

+ 18 - 2
docs/list.js

@@ -354,7 +354,15 @@ var list = {
 			},
 
 			"Controls": {
-				"OrbitControls": "examples/en/controls/OrbitControls"
+				"DeviceOrientationControls": "examples/en/controls/DeviceOrientationControls",
+				"DragControls": "examples/en/controls/DragControls",
+				"FirstPersonControls": "examples/en/controls/FirstPersonControls",
+				"FlyControls": "examples/en/controls/FlyControls",
+				"OrbitControls": "examples/en/controls/OrbitControls",
+				"OrthographicTrackballControls": "examples/en/controls/OrthographicTrackballControls",
+				"PointerLockControls": "examples/en/controls/PointerLockControls",
+				"TrackballControls": "examples/en/controls/TrackballControls",
+				"TransformControls": "examples/en/controls/TransformControls"
 			},
 
 			"Geometries": {
@@ -790,7 +798,15 @@ var list = {
 			},
 
 			"控制": {
-				"OrbitControls": "examples/zh/controls/OrbitControls"
+				"DeviceOrientationControls": "examples/zh/controls/DeviceOrientationControls",
+				"DragControls": "examples/zh/controls/DragControls",
+				"FirstPersonControls": "examples/zh/controls/FirstPersonControls",
+				"FlyControls": "examples/zh/controls/FlyControls",
+				"OrbitControls": "examples/zh/controls/OrbitControls",
+				"OrthographicTrackballControls": "examples/zh/controls/OrthographicTrackballControls",
+				"PointerLockControls": "examples/zh/controls/PointerLockControls",
+				"TrackballControls": "examples/zh/controls/TrackballControls",
+				"TransformControls": "examples/zh/controls/TransformControls"
 			},
 
 			"几何体": {

+ 3 - 2
editor/index.html

@@ -7,8 +7,8 @@
 		<link rel="apple-touch-icon" href="images/icon.png">
 		<link rel="manifest" href="manifest.json">
 		<link rel="shortcut icon" href="../files/favicon.ico" />
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body ontouchstart="">
 		<link rel="stylesheet" href="css/main.css">
@@ -126,6 +126,7 @@
 		<script src="js/Sidebar.Geometry.BoxGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.CircleGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.CylinderGeometry.js"></script>
+		<script src="js/Sidebar.Geometry.DodecahedronGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.ExtrudeGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.IcosahedronGeometry.js"></script>
 		<script src="js/Sidebar.Geometry.OctahedronGeometry.js"></script>

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

@@ -85,6 +85,22 @@ Menubar.Add = function ( editor ) {
 	} );
 	options.add( option );
 
+	// Dodecahedron
+
+	var option = new UI.Row();
+	option.setClass( 'option' );
+	option.setTextContent( strings.getKey( 'menubar/add/dodecahedron' ) );
+	option.onClick( function () {
+
+		var geometry = new THREE.DodecahedronBufferGeometry( 1, 0 );
+		var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
+		mesh.name = 'Dodecahedron';
+
+		editor.execute( new AddObjectCommand( editor, mesh ) );
+
+	} );
+	options.add( option );
+
 	// Icosahedron
 
 	var option = new UI.Row();
@@ -162,7 +178,7 @@ Menubar.Add = function ( editor ) {
 		editor.execute( new AddObjectCommand( editor, mesh ) );
 
 	} );
-	options.add( option )
+	options.add( option );
 
 	// Ring
 

+ 0 - 2
editor/js/Sidebar.Geometry.BoxGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.BoxGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 2
editor/js/Sidebar.Geometry.CircleGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.CircleGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 2
editor/js/Sidebar.Geometry.CylinderGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.CylinderGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 49 - 0
editor/js/Sidebar.Geometry.DodecahedronGeometry.js

@@ -0,0 +1,49 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+Sidebar.Geometry.DodecahedronGeometry = function ( editor, object ) {
+
+	var strings = editor.strings;
+
+	var container = new UI.Row();
+
+	var geometry = object.geometry;
+	var parameters = geometry.parameters;
+
+	// radius
+
+	var radiusRow = new UI.Row();
+	var radius = new UI.Number( parameters.radius ).onChange( update );
+
+	radiusRow.add( new UI.Text( strings.getKey( 'sidebar/geometry/dodecahedron_geometry/radius' ) ).setWidth( '90px' ) );
+	radiusRow.add( radius );
+
+	container.add( radiusRow );
+
+	// detail
+
+	var detailRow = new UI.Row();
+	var detail = new UI.Integer( parameters.detail ).setRange( 0, Infinity ).onChange( update );
+
+	detailRow.add( new UI.Text( strings.getKey( 'sidebar/geometry/dodecahedron_geometry/detail' ) ).setWidth( '90px' ) );
+	detailRow.add( detail );
+
+	container.add( detailRow );
+
+	//
+
+	function update() {
+
+		editor.execute( new SetGeometryCommand( editor, object, new THREE[ geometry.type ](
+			radius.getValue(),
+			detail.getValue()
+		) ) );
+
+	}
+
+	return container;
+
+};
+
+Sidebar.Geometry.DodecahedronBufferGeometry = Sidebar.Geometry.DodecahedronGeometry;

+ 0 - 2
editor/js/Sidebar.Geometry.ExtrudeGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.ExtrudeGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 5
editor/js/Sidebar.Geometry.IcosahedronGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.IcosahedronGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;
@@ -33,7 +31,6 @@ Sidebar.Geometry.IcosahedronGeometry = function ( editor, object ) {
 
 	container.add( detailRow );
 
-
 	//
 
 	function update() {
@@ -43,8 +40,6 @@ Sidebar.Geometry.IcosahedronGeometry = function ( editor, object ) {
 			detail.getValue()
 		) ) );
 
-		signals.objectChanged.dispatch( object );
-
 	}
 
 	return container;

+ 0 - 2
editor/js/Sidebar.Geometry.LatheGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.LatheGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 4
editor/js/Sidebar.Geometry.OctahedronGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.OctahedronGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;
@@ -43,8 +41,6 @@ Sidebar.Geometry.OctahedronGeometry = function ( editor, object ) {
 			detail.getValue()
 		) ) );
 
-		signals.objectChanged.dispatch( object );
-
 	}
 
 	return container;

+ 0 - 2
editor/js/Sidebar.Geometry.PlaneGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.PlaneGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 2
editor/js/Sidebar.Geometry.RingGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.RingGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 2
editor/js/Sidebar.Geometry.ShapeGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.ShapeGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 2
editor/js/Sidebar.Geometry.SphereGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.SphereGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 4
editor/js/Sidebar.Geometry.TetrahedronGeometry.js

@@ -7,8 +7,6 @@ Sidebar.Geometry.TetrahedronGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;
@@ -44,8 +42,6 @@ Sidebar.Geometry.TetrahedronGeometry = function ( editor, object ) {
 			detail.getValue()
 		) ) );
 
-		signals.objectChanged.dispatch( object );
-
 	}
 
 	return container;

+ 0 - 2
editor/js/Sidebar.Geometry.TorusGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.TorusGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 2
editor/js/Sidebar.Geometry.TorusKnotGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.TorusKnotGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 0 - 2
editor/js/Sidebar.Geometry.TubeGeometry.js

@@ -6,8 +6,6 @@ Sidebar.Geometry.TubeGeometry = function ( editor, object ) {
 
 	var strings = editor.strings;
 
-	var signals = editor.signals;
-
 	var container = new UI.Row();
 
 	var geometry = object.geometry;

+ 3 - 3
editor/js/Sidebar.Properties.js

@@ -9,9 +9,9 @@ Sidebar.Properties = function ( editor ) {
 	var container = new UI.TabbedPanel();
 	container.setId( 'properties' );
 
-	container.addPanel( 'object', strings.getKey( 'sidebar/properties/object' ), new Sidebar.Object( editor ) );
-	container.addPanel( 'geometry', strings.getKey( 'sidebar/properties/geometry' ), new Sidebar.Geometry( editor ) );
-	container.addPanel( 'material', strings.getKey( 'sidebar/properties/material' ), new Sidebar.Material( editor ) );
+	container.addTab( 'object', strings.getKey( 'sidebar/properties/object' ), new Sidebar.Object( editor ) );
+	container.addTab( 'geometry', strings.getKey( 'sidebar/properties/geometry' ), new Sidebar.Geometry( editor ) );
+	container.addTab( 'material', strings.getKey( 'sidebar/properties/material' ), new Sidebar.Material( editor ) );
 
 	return container;
 

+ 3 - 3
editor/js/Sidebar.js

@@ -21,9 +21,9 @@ var Sidebar = function ( editor ) {
 		new Sidebar.History( editor )
 	);
 
-	container.addPanel( 'scene', strings.getKey( 'sidebar/scene' ), scene );
-	container.addPanel( 'project', strings.getKey( 'sidebar/project' ), new Sidebar.Project( editor ) );
-	container.addPanel( 'settings', strings.getKey( 'sidebar/settings' ), settings );
+	container.addTab( 'scene', strings.getKey( 'sidebar/scene' ), scene );
+	container.addTab( 'project', strings.getKey( 'sidebar/project' ), new Sidebar.Project( editor ) );
+	container.addTab( 'settings', strings.getKey( 'sidebar/settings' ), settings );
 
 	return container;
 

+ 8 - 0
editor/js/Strings.js

@@ -41,6 +41,7 @@ var Strings = function ( config ) {
 			'menubar/add/cylinder': 'Cylinder',
 			'menubar/add/ring': 'Ring',
 			'menubar/add/sphere': 'Sphere',
+			'menubar/add/dodecahedron': 'Dodecahedron',
 			'menubar/add/icosahedron': 'Icosahedron',
 			'menubar/add/octahedron': 'Octahedron',
 			'menubar/add/tetrahedron': 'Tetrahedron',
@@ -148,6 +149,9 @@ var Strings = function ( config ) {
 			'sidebar/geometry/geometry/vertices': 'Vertices',
 			'sidebar/geometry/geometry/faces': 'Faces',
 
+			'sidebar/geometry/dodecahedron_geometry/radius': 'Radius',
+			'sidebar/geometry/dodecahedron_geometry/detail': 'Detail',
+
 			'sidebar/geometry/icosahedron_geometry/radius': 'Radius',
 			'sidebar/geometry/icosahedron_geometry/detail': 'Detail',
 
@@ -338,6 +342,7 @@ var Strings = function ( config ) {
 			'menubar/add/cylinder': '圆柱体',
 			'menubar/add/ring': '环',
 			'menubar/add/sphere': '球体',
+			'menubar/add/dodecahedron': 'Dodecahedron',
 			'menubar/add/icosahedron': '二十面体',
 			'menubar/add/octahedron': '八面体',
 			'menubar/add/tetrahedron': '四面体',
@@ -435,6 +440,9 @@ var Strings = function ( config ) {
 			'sidebar/geometry/geometry/vertices': '顶点',
 			'sidebar/geometry/geometry/faces': '面',
 
+			'sidebar/geometry/dodecahedron_geometry/radius': '半径',
+			'sidebar/geometry/dodecahedron_geometry/detail': '面片分段',
+
 			'sidebar/geometry/icosahedron_geometry/radius': '半径',
 			'sidebar/geometry/icosahedron_geometry/detail': '面片分段',
 

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

@@ -1098,7 +1098,7 @@ UI.TabbedPanel.prototype.select = function ( id ) {
 
 }
 
-UI.TabbedPanel.prototype.addPanel = function ( id, label, items ) {
+UI.TabbedPanel.prototype.addTab = function ( id, label, items ) {
 
 	var tab = new UI.TabbedPanel.Tab( label, this );
 	tab.setId( id );

+ 2 - 1
examples/files.js

@@ -52,7 +52,6 @@ var files = {
 		"webgl_interactive_cubes_gpu",
 		"webgl_interactive_instances_gpu",
 		"webgl_interactive_cubes_ortho",
-		"webgl_interactive_draggablecubes",
 		"webgl_interactive_lines",
 		"webgl_interactive_points",
 		"webgl_interactive_raycasting_points",
@@ -338,6 +337,7 @@ var files = {
 		"webvr_cubes",
 		"webvr_dragging",
 		"webvr_lorenzattractor",
+		"webvr_multiview",
 		"webvr_panorama",
 		"webvr_paint",
 		"webvr_rollercoaster",
@@ -360,6 +360,7 @@ var files = {
 		"misc_animation_keys",
 		"misc_boxselection",
 		"misc_controls_deviceorientation",
+		"misc_controls_drag",
 		"misc_controls_fly",
 		"misc_controls_map",
 		"misc_controls_orbit",

+ 6 - 2
examples/js/controls/FirstPersonControls.js

@@ -10,6 +10,8 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 
 	this.domElement = ( domElement !== undefined ) ? domElement : document;
 
+	// API
+
 	this.enabled = true;
 
 	this.movementSpeed = 1.0;
@@ -29,6 +31,10 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 	this.verticalMin = 0;
 	this.verticalMax = Math.PI;
 
+	this.mouseDragOn = false;
+
+	// internals
+
 	this.autoSpeedFactor = 0.0;
 
 	this.mouseX = 0;
@@ -39,8 +45,6 @@ THREE.FirstPersonControls = function ( object, domElement ) {
 	this.moveLeft = false;
 	this.moveRight = false;
 
-	this.mouseDragOn = false;
-
 	this.viewHalfX = 0;
 	this.viewHalfY = 0;
 

+ 2 - 2
examples/js/controls/OrthographicTrackballControls.js

@@ -19,8 +19,6 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	this.screen = { left: 0, top: 0, width: 0, height: 0 };
 
-	this.radius = 0;
-
 	this.rotateSpeed = 1.0;
 	this.zoomSpeed = 1.2;
 
@@ -36,6 +34,8 @@ THREE.OrthographicTrackballControls = function ( object, domElement ) {
 
 	// internals
 
+	this.radius = 0;
+
 	this.target = new THREE.Vector3();
 
 	var EPS = 0.000001;

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

@@ -22,7 +22,7 @@ THREE.PointerLockControls = function ( camera, domElement ) {
 
 	var PI_2 = Math.PI / 2;
 
-	var vec = new Vector3();
+	var vec = new THREE.Vector3();
 
 	function onMouseMove( event ) {
 

+ 4 - 4
examples/js/postprocessing/OutlinePass.js

@@ -510,18 +510,18 @@ THREE.OutlinePass.prototype = Object.assign( Object.create( THREE.Pass.prototype
 				void main() {\
 					vec2 invSize = 1.0 / texSize;\
 					float weightSum = gaussianPdf(0.0, kernelRadius);\
-					vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\
+					vec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;\
 					vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\
 					vec2 uvOffset = delta;\
 					for( int i = 1; i <= MAX_RADIUS; i ++ ) {\
 						float w = gaussianPdf(uvOffset.x, kernelRadius);\
-						vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb;\
-						vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb;\
+						vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);\
+						vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);\
 						diffuseSum += ((sample1 + sample2) * w);\
 						weightSum += (2.0 * w);\
 						uvOffset += delta;\
 					}\
-					gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\
+					gl_FragColor = diffuseSum/weightSum;\
 				}"
 		} );
 

+ 1 - 3
examples/jsm/controls/DeviceOrientationControls.d.ts

@@ -1,6 +1,5 @@
 import {
-  Camera,
-  Vector3
+  Camera
 } from '../../../src/Three';
 
 export class DeviceOrientationControls {
@@ -14,7 +13,6 @@ export class DeviceOrientationControls {
   deviceOrientation: any;
   enabled: boolean;
   screenOrientation: number;
-  target: Vector3;
 
   connect(): void;
   disconnect(): void;

+ 1 - 1
examples/jsm/controls/FirstPersonControls.d.ts

@@ -22,7 +22,7 @@ export class FirstPersonControls {
   constrainVertical: boolean;
   verticalMin: number;
   verticalMax: number;
-  autoSpeedFactor: number;
+	mouseDragOn: boolean;
 
   handleResize(): void;
   lookAt(x: number | Vector3, y: number, z: number): this;

+ 9 - 5
examples/jsm/controls/FirstPersonControls.js

@@ -16,6 +16,8 @@ var FirstPersonControls = function ( object, domElement ) {
 
 	this.domElement = ( domElement !== undefined ) ? domElement : document;
 
+	// API
+
 	this.enabled = true;
 
 	this.movementSpeed = 1.0;
@@ -35,11 +37,6 @@ var FirstPersonControls = function ( object, domElement ) {
 	this.verticalMin = 0;
 	this.verticalMax = Math.PI;
 
-	this.autoSpeedFactor = 0.0;
-
-	this.mouseX = 0;
-	this.mouseY = 0;
-
 	this.moveForward = false;
 	this.moveBackward = false;
 	this.moveLeft = false;
@@ -47,6 +44,13 @@ var FirstPersonControls = function ( object, domElement ) {
 
 	this.mouseDragOn = false;
 
+	// internals
+
+	this.autoSpeedFactor = 0.0;
+
+	this.mouseX = 0;
+	this.mouseY = 0;
+
 	this.viewHalfX = 0;
 	this.viewHalfY = 0;
 

+ 0 - 1
examples/jsm/controls/OrthographicTrackballControls.d.ts

@@ -8,7 +8,6 @@ export class OrthographicTrackballControls extends EventDispatcher {
 
   enabled: boolean;
   screen: {left: number; top: number; width: number; height: number};
-  radius: number;
   rotateSpeed: number;
   zoomSpeed: number;
   noRotate: boolean;

+ 2 - 2
examples/jsm/controls/OrthographicTrackballControls.js

@@ -26,8 +26,6 @@ var OrthographicTrackballControls = function ( object, domElement ) {
 
 	this.screen = { left: 0, top: 0, width: 0, height: 0 };
 
-	this.radius = 0;
-
 	this.rotateSpeed = 1.0;
 	this.zoomSpeed = 1.2;
 
@@ -43,6 +41,8 @@ var OrthographicTrackballControls = function ( object, domElement ) {
 
 	// internals
 
+	this.radius = 0;
+
 	this.target = new Vector3();
 
 	var EPS = 0.000001;

+ 2 - 1
examples/jsm/controls/PointerLockControls.d.ts

@@ -8,7 +8,6 @@ export class PointerLockControls extends EventDispatcher {
   constructor(camera: Camera, domElement?: HTMLElement);
 
   domElement: HTMLElement;
-  object: Camera;
 
   // API
 
@@ -19,6 +18,8 @@ export class PointerLockControls extends EventDispatcher {
   dispose(): void;
   getObject(): Camera;
   getDirection(v: Vector3): Vector3;
+  moveForward(distance: number): void;
+  moveRight(distance: number): void;
   lock(): void;
   unlock(): void;
 

+ 0 - 2
examples/jsm/controls/TrackballControls.d.ts

@@ -42,6 +42,4 @@ export class TrackballControls extends EventDispatcher {
   rotateCamera(): void;
 
   handleResize(): void;
-
-  handleEvent(event: any): void;
 }

+ 5 - 11
examples/jsm/controls/TransformControls.d.ts

@@ -14,12 +14,12 @@ export class TransformControls extends Object3D {
   // API
 
   camera: Camera;
-  object: Object3D;
+  object: Object3D | undefined;
   enabled: boolean;
-  axis: string;
+  axis: string | null;
   mode: string;
-  translationSnap: Vector3;
-  rotationSnap: Vector3;
+  translationSnap: number | null;
+  rotationSnap: number | null;
   space: string;
   size: number;
   dragging: boolean;
@@ -27,19 +27,14 @@ export class TransformControls extends Object3D {
   showY: boolean;
   showZ: boolean;
   isTransformControls: boolean;
-  visible: boolean;
   mouseButtons: {
-    LEFT: MOUSE; 
+    LEFT: MOUSE;
     MIDDLE: MOUSE;
     RIGHT: MOUSE;
   };
 
   attach(object: Object3D): this;
   detach(): this;
-  pointerHover(pointer: Object): void;
-  pointerDown(pointer: Object): void;
-  pointerMove(pointer: Object): void;
-  pointerUp(pointer: Object): void;
   getMode(): string;
   setMode(mode: string): void;
   setTranslationSnap(translationSnap: Number | null): void;
@@ -47,6 +42,5 @@ export class TransformControls extends Object3D {
   setSize(size: number): void;
   setSpace(space: string): void;
   dispose(): void;
-  update(): void;
 
 }

+ 2 - 2
examples/jsm/loaders/MMDLoader.d.ts

@@ -20,11 +20,11 @@ export class MMDLoader extends Loader {
   parser: object | null;
 
   load(url: string, onLoad: (mesh: SkinnedMesh) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
-  loadAnimation(url: string, onLoad: (object: SkinnedMesh | AnimationClip) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
+  loadAnimation(url: string, object: SkinnedMesh | THREE.Camera, onLoad: (object: SkinnedMesh | AnimationClip) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
   loadPMD(url: string, onLoad: (object: object) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
   loadPMX(url: string, onLoad: (object: object) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
   loadVMD(url: string, onLoad: (object: object) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
-  loadVPD(url: string, onLoad: (object: object) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
+  loadVPD(url: string, isUnicode: boolean, onLoad: (object: object) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
   loadWithAnimation(url: string, vmdUrl: string | string[], onLoad: (object: MMDLoaderAnimationObject) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;
   setAnimationPath(animationPath: string): this;
 }

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

@@ -4,7 +4,7 @@ import {
   LoadingManager
 } from '../../../src/Three';
 
-export class VRMLLoader extends Loader {
+export class VTKLoader extends Loader {
   constructor(manager?: LoadingManager);
 
   load(url: string, onLoad: (geometry: BufferGeometry) => void, onProgress?: (event: ProgressEvent) => void, onError?: (event: ErrorEvent) => void): void;

+ 7 - 7
examples/jsm/loaders/obj2/utils/CodeSerializer.js

@@ -21,8 +21,8 @@ const CodeSerializer = {
 			part = serializationTarget[ name ];
 			if ( typeof ( part ) === 'string' || part instanceof String ) {
 
-				part = part.replace( '\n', '\\n' );
-				part = part.replace( '\r', '\\r' );
+				part = part.replace( /\n/g, '\\n' );
+				part = part.replace( /\r/g, '\\r' );
 				objectString += '\t' + name + ': "' + part + '",\n';
 
 			} else if ( part instanceof Array ) {
@@ -31,7 +31,7 @@ const CodeSerializer = {
 
 			} else if ( typeof part === 'object' ) {
 
-				console.log( 'Omitting object "' + name + '" and replace it with empty object.');
+				console.log( 'Omitting object "' + name + '" and replace it with empty object.' );
 				objectString += '\t' + name + ': {},\n';
 
 			} else {
@@ -75,7 +75,7 @@ const CodeSerializer = {
 
 			if ( name === 'constructor' ) {
 
-				if ( !funcInstructions.isRemoveCode() ) {
+				if ( ! funcInstructions.isRemoveCode() ) {
 
 					constructorString = fullObjectName + ' = ' + funcInstructions.getCode() + ';\n\n';
 
@@ -89,7 +89,7 @@ const CodeSerializer = {
 					funcInstructions = funcTemp;
 
 				}
-				if ( !funcInstructions.isRemoveCode() ) {
+				if ( ! funcInstructions.isRemoveCode() ) {
 
 					if ( isExtended ) {
 
@@ -136,7 +136,7 @@ const CodeSerializer = {
 
 				} else if ( typeof objectPart === 'object' ) {
 
-					console.log( 'Omitting object "' + funcInstructions.getName() + '" and replace it with empty object.');
+					console.log( 'Omitting object "' + funcInstructions.getName() + '" and replace it with empty object.' );
 					funcInstructions.setCode( "{}" );
 
 				} else {
@@ -257,7 +257,7 @@ CodeSerializationInstruction.prototype = {
 	 * Returns the serialized function code
 	 * @return {String}
 	 */
-	getCode: function() {
+	getCode: function () {
 
 		return this.code;
 

+ 4 - 4
examples/jsm/postprocessing/OutlinePass.js

@@ -530,18 +530,18 @@ OutlinePass.prototype = Object.assign( Object.create( Pass.prototype ), {
 				void main() {\
 					vec2 invSize = 1.0 / texSize;\
 					float weightSum = gaussianPdf(0.0, kernelRadius);\
-					vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\
+					vec4 diffuseSum = texture2D( colorTexture, vUv) * weightSum;\
 					vec2 delta = direction * invSize * kernelRadius/float(MAX_RADIUS);\
 					vec2 uvOffset = delta;\
 					for( int i = 1; i <= MAX_RADIUS; i ++ ) {\
 						float w = gaussianPdf(uvOffset.x, kernelRadius);\
-						vec3 sample1 = texture2D( colorTexture, vUv + uvOffset).rgb;\
-						vec3 sample2 = texture2D( colorTexture, vUv - uvOffset).rgb;\
+						vec4 sample1 = texture2D( colorTexture, vUv + uvOffset);\
+						vec4 sample2 = texture2D( colorTexture, vUv - uvOffset);\
 						diffuseSum += ((sample1 + sample2) * w);\
 						weightSum += (2.0 * w);\
 						uvOffset += delta;\
 					}\
-					gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\
+					gl_FragColor = diffuseSum/weightSum;\
 				}"
 		} );
 

+ 2 - 2
examples/jsm/renderers/WebGLDeferredRenderer.d.ts

@@ -8,9 +8,9 @@ import {
 export interface WebGLDeferredRendererParameters {
   antialias?: boolean;
   cacheKeepAlive?: boolean;
-  height?: Vector2;
+  height?: number;
   renderer?: WebGLRenderer;
-  width?: Vector2;
+  width?: number;
 }
 
 export class WebGLDeferredRenderer {

+ 9 - 19
examples/webgl_interactive_draggablecubes.html → examples/misc_controls_drag.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgl - draggable cubes</title>
+		<title>three.js webgl - drag controls</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<link type="text/css" rel="stylesheet" href="main.css">
@@ -18,7 +18,7 @@
 	<body>
 
 		<div id="info">
-			<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - draggable cubes
+			<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webgl - drag controls
 		</div>
 
 		<script type="module">
@@ -27,11 +27,10 @@
 
 			import Stats from './jsm/libs/stats.module.js';
 
-			import { TrackballControls } from './jsm/controls/TrackballControls.js';
 			import { DragControls } from './jsm/controls/DragControls.js';
 
 			var container, stats;
-			var camera, controls, scene, renderer;
+			var camera, scene, renderer;
 			var objects = [];
 
 			init();
@@ -98,24 +97,17 @@
 
 				container.appendChild( renderer.domElement );
 
-				controls = new TrackballControls( camera, renderer.domElement );
-				controls.rotateSpeed = 1.0;
-				controls.zoomSpeed = 1.2;
-				controls.panSpeed = 0.8;
-				controls.noZoom = false;
-				controls.noPan = false;
-				controls.staticMoving = true;
-				controls.dynamicDampingFactor = 0.3;
+				var controls = new DragControls( objects, camera, renderer.domElement );
 
-				var dragControls = new DragControls( objects, camera, renderer.domElement );
-				dragControls.addEventListener( 'dragstart', function () {
+				controls.addEventListener( 'dragstart', function ( event ) {
 
-					controls.enabled = false;
+					event.object.material.emissive.set( 0xaaaaaa );
 
 				} );
-				dragControls.addEventListener( 'dragend', function () {
 
-					controls.enabled = true;
+				controls.addEventListener( 'dragend', function ( event ) {
+
+					event.object.material.emissive.set( 0x000000 );
 
 				} );
 
@@ -150,8 +142,6 @@
 
 			function render() {
 
-				controls.update();
-
 				renderer.render( scene, camera );
 
 			}

+ 2 - 2
examples/webvr_ballshooter.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 2 - 2
examples/webvr_cubes.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 2 - 2
examples/webvr_dragging.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 2 - 2
examples/webvr_lorenzattractor.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 195 - 0
examples/webvr_multiview.html

@@ -0,0 +1,195 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webvr - multiview</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #101010;
+				color: #fff;
+				margin: 0px;
+				overflow: hidden;
+			}
+			a {
+				color: #48f;
+			}
+		</style>
+	</head>
+	<body>
+		<script type="module">
+
+			import * as THREE from '../build/three.module.js';
+			import { BoxLineGeometry } from './jsm/geometries/BoxLineGeometry.js';
+			import { WEBVR } from './jsm/vr/WebVR.js';
+			import Stats from './jsm/libs/stats.module.js';
+
+			var container;
+			var camera, scene, renderer;
+
+			var room;
+			var stats;
+
+			var count = 0;
+			var radius = 0.02;
+			var normal = new THREE.Vector3();
+			var relativeVelocity = new THREE.Vector3();
+
+			var clock = new THREE.Clock();
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				//
+
+				var canvas = document.createElement( 'canvas' );
+
+
+				// Currently OVR_multiview2 is supported just on WebGL2 non-multisampled contexts
+				// so we must create the context manually ensuring `antialias` is set to false
+				//
+				// There is an ongoing discussion on how to add multisampled multiview support
+				// on the Khronos Group's WebGL repo: https://github.com/KhronosGroup/WebGL/issues/2912
+				// as soon as that will get solved we will update the code so it will be
+				// transparent for the user and you could use this extension with or without multisampled
+				// contexts
+				var context = canvas.getContext( 'webgl2', { antialias: false } );
+
+				renderer = new THREE.WebGLRenderer( { canvas: canvas, context: context } );
+
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.vr.enabled = true;
+				container.appendChild( renderer.domElement );
+
+				var info = document.createElement( 'div' );
+				info.style.position = 'absolute';
+				info.style.top = '10px';
+				info.style.width = '100%';
+				info.style.textAlign = 'center';
+				info.innerHTML = '<a href="https://threejs.org" target="_blank" rel="noopener">three.js</a> webvr - multiview<br/>';
+				info.innerHTML += renderer.capabilities.multiview ? `<span style="color: #33ff33"><b>OVR_multiview2</b> is supported in your browser</span>` :
+					`<span style="color: #ff3333"><b>OVR_multiview2</b> is not supported or enabled in your browser</span>`;
+
+				container.appendChild( info );
+
+				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0x505050 );
+
+				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 10 );
+
+				room = new THREE.LineSegments(
+					new BoxLineGeometry( 6, 6, 6, 10, 10, 10 ),
+					new THREE.LineBasicMaterial( { color: renderer.capabilities.multiview ? 0x99ff99 : 0xff3333 } )
+				);
+				room.geometry.translate( 0, 3, 0 );
+				scene.add( room );
+
+				var light = new THREE.HemisphereLight( 0xffffff, 0x444444 );
+				light.position.set( 1, 1, 1 );
+				scene.add( light );
+
+				var geometry = new THREE.IcosahedronBufferGeometry( radius );
+
+				for ( var i = 0; i < 2000; i ++ ) {
+
+					var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
+
+					object.position.x = Math.random() * 4 - 2;
+					object.position.y = Math.random() * 4;
+					object.position.z = Math.random() * 4 - 2;
+
+					object.userData.velocity = new THREE.Vector3();
+					object.userData.velocity.x = 2 * Math.random() - 1;
+					object.userData.velocity.y = 2 * Math.random() - 1;
+					object.userData.velocity.z = 2 * Math.random() - 1;
+
+					room.add( object );
+
+				}
+
+				//
+
+				document.body.appendChild( WEBVR.createButton( renderer ) );
+
+				//
+
+				stats = new Stats();
+				container.appendChild( stats.dom );
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function animate() {
+
+				renderer.setAnimationLoop( render );
+
+			}
+
+			function render() {
+
+				//
+				stats.update();
+
+				var delta = clock.getDelta();
+
+				var range = 3 - radius;
+
+				for ( var i = 0; i < room.children.length; i ++ ) {
+
+					var object = room.children[ i ];
+
+					object.position.x += object.userData.velocity.x * delta;
+					object.position.y += object.userData.velocity.y * delta;
+					object.position.z += object.userData.velocity.z * delta;
+
+					// keep objects inside room
+
+					if ( object.position.x < - range || object.position.x > range ) {
+
+						object.position.x = THREE.Math.clamp( object.position.x, - range, range );
+						object.userData.velocity.x = - object.userData.velocity.x;
+
+					}
+
+					if ( object.position.y < radius || object.position.y > 6 ) {
+
+						object.position.y = Math.max( object.position.y, radius );
+						object.userData.velocity.y = - object.userData.velocity.y;
+
+					}
+
+					if ( object.position.z < - range || object.position.z > range ) {
+
+						object.position.z = THREE.Math.clamp( object.position.z, - range, range );
+						object.userData.velocity.z = - object.userData.velocity.z;
+
+					}
+
+				}
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 2 - 2
examples/webvr_paint.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 2 - 2
examples/webvr_panorama.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 		<script src="js/vr/HelioWebXRPolyfill.js"></script>

+ 2 - 2
examples/webvr_rollercoaster.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 2 - 2
examples/webvr_sandbox.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 2 - 2
examples/webvr_sculpt.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 2 - 2
examples/webvr_video.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 		<div id="container"></div>

+ 2 - 2
examples/webvr_vive_paint.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 2 - 2
examples/webvr_vive_sculpt.html

@@ -5,8 +5,8 @@
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
 		<link type="text/css" rel="stylesheet" href="main.css">
-		<!-- WebXR Device API (For Chrome M76+), expires 09/09/2019 -->
-		<meta http-equiv="origin-trial" content="Ai1/G787sugfmWtk1xQExa8N6OqwDsJyNn+OwpA1J4PozR1lixRYIQ4Tmp00vrGWS8FQQ2iDyqjwaewrOfYvPAUAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU2ODAyMzQ3OH0=">
+		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
+		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body>
 

+ 5 - 5
package.json

@@ -45,12 +45,12 @@
     }
   },
   "scripts": {
-    "build": "rollup -c",
+    "build": "rollup -c utils/build/rollup.config.js",
     "build-test": "rollup -c test/rollup.unit.config.js",
-    "build-closure": "rollup -c && google-closure-compiler --warning_level=VERBOSE --jscomp_off=globalThis --jscomp_off=checkTypes --externs utils/build/externs.js --language_in=ECMASCRIPT5_STRICT --js build/three.js --js_output_file build/three.min.js",
-    "build-examples": "rollup -c rollup-examples.config.js",
-    "dev": "concurrently --names \"ROLLUP,HTTP\" -c \"bgBlue.bold,bgGreen.bold\" \"rollup -c -w -m inline\" \"http-server -c-1 -p 8080\"",
-    "dev-test": "concurrently --names \"ROLLUP,ROLLUPTEST,HTTP\" -c \"bgBlue.bold,bgRed.bold,bgGreen.bold\" \"rollup -c -w -m inline\" \"rollup -c test/rollup.unit.config.js -w -m inline\" \"http-server -p 8080\"",
+    "build-closure": "rollup -c utils/build/rollup.config.js && google-closure-compiler --warning_level=VERBOSE --jscomp_off=globalThis --jscomp_off=checkTypes --externs utils/build/externs.js --language_in=ECMASCRIPT5_STRICT --js build/three.js --js_output_file build/three.min.js",
+    "build-examples": "rollup -c utils/build/rollup-examples.config.js",
+    "dev": "concurrently --names \"ROLLUP,HTTP\" -c \"bgBlue.bold,bgGreen.bold\" \"rollup -c utils/build/rollup.config.js -w -m inline\" \"http-server -c-1 -p 8080\"",
+    "dev-test": "concurrently --names \"ROLLUP,ROLLUPTEST,HTTP\" -c \"bgBlue.bold,bgRed.bold,bgGreen.bold\" \"rollup -c utils/build/rollup.config.js -w -m inline\" \"rollup -c test/rollup.unit.config.js -w -m inline\" \"http-server -p 8080\"",
     "start": "npm run dev",
     "lint": "eslint src --ext js --ext ts && tsc src/Three.d.ts --noEmit",
     "test": "npm run build-test && qunit -r failonlyreporter test/unit/three.source.unit.js",

+ 15 - 0
src/Three.Legacy.js

@@ -1327,6 +1327,21 @@ Object.defineProperties( Material.prototype, {
 			console.warn( 'THREE.' + this.type + ': .shading has been removed. Use the boolean .flatShading instead.' );
 			this.flatShading = ( value === FlatShading );
 
+		}
+	},
+
+	stencilMask: {
+		get: function () {
+
+			console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
+			return this.stencilFuncMask;
+
+		},
+		set: function ( value ) {
+
+			console.warn( 'THREE.' + this.type + ': .stencilMask has been removed. Use .stencilFuncMask instead.' );
+			this.stencilFuncMask = value;
+
 		}
 	}
 

+ 11 - 0
src/Three.js

@@ -1,4 +1,5 @@
 import './polyfills.js';
+import { REVISION } from './constants.js';
 
 export { WebGLMultisampleRenderTarget } from './renderers/WebGLMultisampleRenderTarget.js';
 export { WebGLRenderTargetCube } from './renderers/WebGLRenderTargetCube.js';
@@ -158,3 +159,13 @@ export { ShapeUtils } from './extras/ShapeUtils.js';
 export { WebGLUtils } from './renderers/webgl/WebGLUtils.js';
 export * from './constants.js';
 export * from './Three.Legacy.js';
+
+if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) {
+
+	/* eslint-disable no-undef */
+	__THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: {
+		revision: REVISION,
+	} } ) );
+	/* eslint-enable no-undef */
+
+}

+ 2 - 2
src/animation/KeyframeTrack.d.ts

@@ -13,8 +13,8 @@ export class KeyframeTrack {
 	);
 
 	name: string;
-	times: any[];
-	values: any[];
+	times: Float32Array;
+	values: Float32Array;
 
 	ValueTypeName: string;
 	TimeBufferType: Float32Array;

+ 1 - 1
src/helpers/ArrowHelper.js

@@ -97,7 +97,7 @@ ArrowHelper.prototype.setLength = function ( length, headLength, headWidth ) {
 	if ( headLength === undefined ) headLength = 0.2 * length;
 	if ( headWidth === undefined ) headWidth = 0.2 * headLength;
 
-	this.line.scale.set( 1, Math.max( 0, length - headLength ), 1 );
+	this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458
 	this.line.updateMatrix();
 
 	this.cone.scale.set( headWidth, headLength, headWidth );

+ 10 - 0
src/loaders/MaterialLoader.js

@@ -79,6 +79,16 @@ MaterialLoader.prototype = Object.assign( Object.create( Loader.prototype ), {
 		if ( json.depthTest !== undefined ) material.depthTest = json.depthTest;
 		if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite;
 		if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite;
+
+		if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite;
+		if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask;
+		if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc;
+		if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef;
+		if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask;
+		if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail;
+		if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail;
+		if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass;
+
 		if ( json.wireframe !== undefined ) material.wireframe = json.wireframe;
 		if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth;
 		if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap;

+ 6 - 3
src/materials/Material.js

@@ -41,9 +41,10 @@ function Material() {
 	this.depthTest = true;
 	this.depthWrite = true;
 
+	this.stencilWriteMask = 0xff;
 	this.stencilFunc = AlwaysStencilFunc;
 	this.stencilRef = 0;
-	this.stencilMask = 0xff;
+	this.stencilFuncMask = 0xff;
 	this.stencilFail = KeepStencilOp;
 	this.stencilZFail = KeepStencilOp;
 	this.stencilZPass = KeepStencilOp;
@@ -259,9 +260,10 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 		data.depthWrite = this.depthWrite;
 
 		data.stencilWrite = this.stencilWrite;
+		data.stencilWriteMask = this.stencilWriteMask;
 		data.stencilFunc = this.stencilFunc;
 		data.stencilRef = this.stencilRef;
-		data.stencilMask = this.stencilMask;
+		data.stencilFuncMask = this.stencilFuncMask;
 		data.stencilFail = this.stencilFail;
 		data.stencilZFail = this.stencilZFail;
 		data.stencilZPass = this.stencilZPass;
@@ -363,9 +365,10 @@ Material.prototype = Object.assign( Object.create( EventDispatcher.prototype ),
 		this.depthWrite = source.depthWrite;
 
 		this.stencilWrite = source.stencilWrite;
+		this.stencilWriteMask = source.stencilWriteMask;
 		this.stencilFunc = source.stencilFunc;
 		this.stencilRef = source.stencilRef;
-		this.stencilMask = source.stencilMask;
+		this.stencilFuncMask = source.stencilFuncMask;
 		this.stencilFail = source.stencilFail;
 		this.stencilZFail = source.stencilZFail;
 		this.stencilZPass = source.stencilZPass;

+ 50 - 0
src/renderers/WebGLMultiviewRenderTarget.js

@@ -0,0 +1,50 @@
+/**
+ * @author fernandojsg / http://fernandojsg.com
+ * @author Takahiro https://github.com/takahirox
+ */
+
+import { WebGLRenderTarget } from './WebGLRenderTarget.js';
+
+function WebGLMultiviewRenderTarget( width, height, numViews, options ) {
+
+	WebGLRenderTarget.call( this, width, height, options );
+
+	this.depthBuffer = false;
+	this.stencilBuffer = false;
+
+	this.numViews = numViews;
+
+}
+
+WebGLMultiviewRenderTarget.prototype = Object.assign( Object.create( WebGLRenderTarget.prototype ), {
+
+	constructor: WebGLMultiviewRenderTarget,
+
+	isWebGLMultiviewRenderTarget: true,
+
+	copy: function ( source ) {
+
+		WebGLRenderTarget.prototype.copy.call( this, source );
+
+		this.numViews = source.numViews;
+
+		return this;
+
+	},
+
+	setNumViews: function ( numViews ) {
+
+		if ( this.numViews !== numViews ) {
+
+			this.numViews = numViews;
+			this.dispose();
+
+		}
+
+		return this;
+
+	}
+
+} );
+
+export { WebGLMultiviewRenderTarget };

+ 61 - 11
src/renderers/WebGLRenderer.js

@@ -40,6 +40,7 @@ import { WebGLState } from './webgl/WebGLState.js';
 import { WebGLTextures } from './webgl/WebGLTextures.js';
 import { WebGLUniforms } from './webgl/WebGLUniforms.js';
 import { WebGLUtils } from './webgl/WebGLUtils.js';
+import { WebGLMultiview } from './webgl/WebGLMultiview.js';
 import { WebVRManager } from './webvr/WebVRManager.js';
 import { WebXRManager } from './webvr/WebXRManager.js';
 
@@ -312,6 +313,10 @@ function WebGLRenderer( parameters ) {
 
 	this.vr = vr;
 
+	// Multiview
+
+	var multiview = new WebGLMultiview( _this, _gl );
+
 	// shadow map
 
 	var shadowMap = new WebGLShadowMap( _this, objects, capabilities.maxTextureSize );
@@ -1175,6 +1180,12 @@ function WebGLRenderer( parameters ) {
 
 		}
 
+		if ( capabilities.multiview ) {
+
+			multiview.attachCamera( camera );
+
+		}
+
 		//
 
 		background.render( currentRenderList, scene, camera, forceClear );
@@ -1229,6 +1240,12 @@ function WebGLRenderer( parameters ) {
 
 		state.setPolygonOffset( false );
 
+		if ( capabilities.multiview ) {
+
+			multiview.detachCamera( camera );
+
+		}
+
 		if ( vr.enabled ) {
 
 			vr.submitFrame();
@@ -1375,19 +1392,27 @@ function WebGLRenderer( parameters ) {
 
 				_currentArrayCamera = camera;
 
-				var cameras = camera.cameras;
+				if ( capabilities.multiview ) {
+
+					renderObject(	object, scene, camera, geometry, material, group );
+
+				} else {
+
+					var cameras = camera.cameras;
 
-				for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
+					for ( var j = 0, jl = cameras.length; j < jl; j ++ ) {
 
-					var camera2 = cameras[ j ];
+						var camera2 = cameras[ j ];
 
-					if ( object.layers.test( camera2.layers ) ) {
+						if ( object.layers.test( camera2.layers ) ) {
 
-						state.viewport( _currentViewport.copy( camera2.viewport ) );
+							state.viewport( _currentViewport.copy( camera2.viewport ) );
 
-						currentRenderState.setupLights( camera2 );
+							currentRenderState.setupLights( camera2 );
 
-						renderObject( object, scene, camera2, geometry, material, group );
+							renderObject( object, scene, camera2, geometry, material, group );
+
+						}
 
 					}
 
@@ -1682,7 +1707,15 @@ function WebGLRenderer( parameters ) {
 
 		if ( refreshProgram || _currentCamera !== camera ) {
 
-			p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
+			if ( program.numMultiviewViews > 0 ) {
+
+				multiview.updateCameraProjectionMatricesUniform( camera, p_uniforms );
+
+			} else {
+
+				p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
+
+			}
 
 			if ( capabilities.logarithmicDepthBuffer ) {
 
@@ -1730,7 +1763,15 @@ function WebGLRenderer( parameters ) {
 				material.isShaderMaterial ||
 				material.skinning ) {
 
-				p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
+				if ( program.numMultiviewViews > 0 ) {
+
+					multiview.updateCameraViewMatricesUniform( camera, p_uniforms );
+
+				} else {
+
+					p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );
+
+				}
 
 			}
 
@@ -1935,8 +1976,17 @@ function WebGLRenderer( parameters ) {
 
 		// common matrices
 
-		p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
-		p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
+		if ( program.numMultiviewViews > 0 ) {
+
+			multiview.updateObjectMatricesUniforms( object, camera, p_uniforms );
+
+		} else {
+
+			p_uniforms.setValue( _gl, 'modelViewMatrix', object.modelViewMatrix );
+			p_uniforms.setValue( _gl, 'normalMatrix', object.normalMatrix );
+
+		}
+
 		p_uniforms.setValue( _gl, 'modelMatrix', object.matrixWorld );
 
 		return program;

+ 8 - 1
src/renderers/webgl/WebGLCapabilities.js

@@ -86,6 +86,10 @@ function WebGLCapabilities( gl, extensions, parameters ) {
 
 	var maxSamples = isWebGL2 ? gl.getParameter( gl.MAX_SAMPLES ) : 0;
 
+	var multiviewExt = extensions.get( 'OVR_multiview2' );
+	var multiview = isWebGL2 && !! multiviewExt && ! gl.getContextAttributes().antialias;
+	var maxMultiviewViews = multiview ? gl.getParameter( multiviewExt.MAX_VIEWS_OVR ) : 0;
+
 	return {
 
 		isWebGL2: isWebGL2,
@@ -110,7 +114,10 @@ function WebGLCapabilities( gl, extensions, parameters ) {
 		floatFragmentTextures: floatFragmentTextures,
 		floatVertexTextures: floatVertexTextures,
 
-		maxSamples: maxSamples
+		maxSamples: maxSamples,
+
+		multiview: multiview,
+		maxMultiviewViews: maxMultiviewViews
 
 	};
 

+ 211 - 0
src/renderers/webgl/WebGLMultiview.js

@@ -0,0 +1,211 @@
+/**
+ * @author fernandojsg / http://fernandojsg.com
+ * @author Takahiro https://github.com/takahirox
+ */
+
+import { WebGLMultiviewRenderTarget } from '../WebGLMultiviewRenderTarget.js';
+import { Matrix3 } from '../../math/Matrix3.js';
+import { Matrix4 } from '../../math/Matrix4.js';
+import { Vector2 } from '../../math/Vector2.js';
+
+function WebGLMultiview( renderer, gl ) {
+
+	var DEFAULT_NUMVIEWS = 2;
+
+	var capabilities = renderer.capabilities;
+	var properties = renderer.properties;
+
+	var maxNumViews = capabilities.maxMultiviewViews;
+
+	var renderTarget, currentRenderTarget;
+	var mat3, mat4, cameraArray, renderSize;
+
+	function getCameraArray( camera ) {
+
+		if ( camera.isArrayCamera ) return camera.cameras;
+
+		cameraArray[ 0 ] = camera;
+
+		return cameraArray;
+
+	}
+
+	//
+
+	function updateCameraProjectionMatricesUniform( camera, uniforms ) {
+
+		var cameras = getCameraArray( camera );
+
+		for ( var i = 0; i < cameras.length; i ++ ) {
+
+			mat4[ i ].copy( cameras[ i ].projectionMatrix );
+
+		}
+
+		uniforms.setValue( gl, 'projectionMatrices', mat4 );
+
+	}
+
+	function updateCameraViewMatricesUniform( camera, uniforms ) {
+
+		var cameras = getCameraArray( camera );
+
+		for ( var i = 0; i < cameras.length; i ++ ) {
+
+			mat4[ i ].copy( cameras[ i ].matrixWorldInverse );
+
+		}
+
+		uniforms.setValue( gl, 'viewMatrices', mat4 );
+
+	}
+
+	function updateObjectMatricesUniforms( object, camera, uniforms ) {
+
+		var cameras = getCameraArray( camera );
+
+		for ( var i = 0; i < cameras.length; i ++ ) {
+
+			mat4[ i ].multiplyMatrices( cameras[ i ].matrixWorldInverse, object.matrixWorld );
+			mat3[ i ].getNormalMatrix( mat4[ i ] );
+
+		}
+
+		uniforms.setValue( gl, 'modelViewMatrices', mat4 );
+		uniforms.setValue( gl, 'normalMatrices', mat3 );
+
+	}
+
+	function isMultiviewCompatible( camera ) {
+
+		if ( ! camera.isArrayCamera ) return true;
+
+		var cameras = camera.cameras;
+
+		if ( cameras.length > maxNumViews ) return false;
+
+		for ( var i = 1, il = cameras.length; i < il; i ++ ) {
+
+			if ( cameras[ 0 ].viewport.z !== cameras[ i ].viewport.z ||
+				cameras[ 0 ].viewport.w !== cameras[ i ].viewport.w ) return false;
+
+		}
+
+		return true;
+
+	}
+
+	function resizeRenderTarget( camera ) {
+
+		if ( currentRenderTarget ) {
+
+			renderSize.set( currentRenderTarget.width, currentRenderTarget.height );
+
+		} else {
+
+			renderer.getDrawingBufferSize( renderSize );
+
+		}
+
+		if ( camera.isArrayCamera ) {
+
+			var viewport = camera.cameras[ 0 ].viewport;
+
+			renderTarget.setSize( viewport.z, viewport.w );
+
+			renderTarget.setNumViews( camera.cameras.length );
+
+		} else {
+
+			renderTarget.setSize( renderSize.x, renderSize.y );
+			renderTarget.setNumViews( DEFAULT_NUMVIEWS );
+
+		}
+
+	}
+
+	function attachCamera( camera ) {
+
+		if ( ! isMultiviewCompatible( camera ) ) return;
+
+		currentRenderTarget = renderer.getRenderTarget();
+		resizeRenderTarget( camera );
+		renderer.setRenderTarget( renderTarget );
+
+	}
+
+	function detachCamera( camera ) {
+
+		if ( renderTarget !== renderer.getRenderTarget() ) return;
+
+		renderer.setRenderTarget( currentRenderTarget );
+		flush( camera );
+
+	}
+
+	function flush( camera ) {
+
+		var srcRenderTarget = renderTarget;
+		var numViews = srcRenderTarget.numViews;
+
+		var srcFramebuffers = properties.get( srcRenderTarget ).__webglViewFramebuffers;
+
+		var viewWidth = srcRenderTarget.width;
+		var viewHeight = srcRenderTarget.height;
+
+		if ( camera.isArrayCamera ) {
+
+			for ( var i = 0; i < numViews; i ++ ) {
+
+				var viewport = camera.cameras[ i ].viewport;
+
+				var x1 = viewport.x;
+				var y1 = viewport.y;
+				var x2 = x1 + viewport.z;
+				var y2 = y1 + viewport.w;
+
+				gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ i ] );
+				gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, x1, y1, x2, y2, gl.COLOR_BUFFER_BIT, gl.NEAREST );
+
+			}
+
+		} else {
+
+			gl.bindFramebuffer( gl.READ_FRAMEBUFFER, srcFramebuffers[ 0 ] );
+			gl.blitFramebuffer( 0, 0, viewWidth, viewHeight, 0, 0, renderSize.x, renderSize.y, gl.COLOR_BUFFER_BIT, gl.NEAREST );
+
+		}
+
+	}
+
+
+	if ( renderer.capabilities.multiview ) {
+
+		renderTarget = new WebGLMultiviewRenderTarget( 0, 0, DEFAULT_NUMVIEWS );
+
+		renderSize = new Vector2();
+		mat4 = [];
+		mat3 = [];
+		cameraArray = [];
+
+		var maxViews = capabilities.maxMultiviewViews;
+
+		for ( var i = 0; i < maxViews; i ++ ) {
+
+			mat4[ i ] = new Matrix4();
+			mat3[ i ] = new Matrix3();
+
+		}
+
+	}
+
+
+	this.attachCamera = attachCamera;
+	this.detachCamera = detachCamera;
+	this.updateCameraProjectionMatricesUniform = updateCameraProjectionMatricesUniform;
+	this.updateCameraViewMatricesUniform = updateCameraViewMatricesUniform;
+	this.updateObjectMatricesUniforms = updateObjectMatricesUniforms;
+
+}
+
+export { WebGLMultiview };

+ 46 - 6
src/renderers/webgl/WebGLProgram.js

@@ -340,6 +340,9 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 
 	var prefixVertex, prefixFragment;
 
+	var renderTarget = renderer.getRenderTarget();
+	var numMultiviewViews = renderTarget && renderTarget.isWebGLMultiviewRenderTarget ? renderTarget.numViews : 0;
+
 	if ( material.isRawShaderMaterial ) {
 
 		prefixVertex = [
@@ -427,14 +430,29 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 
 			parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '',
 			parameters.logarithmicDepthBuffer && ( capabilities.isWebGL2 || extensions.get( 'EXT_frag_depth' ) ) ? '#define USE_LOGDEPTHBUF_EXT' : '',
-
 			'uniform mat4 modelMatrix;',
-			'uniform mat4 modelViewMatrix;',
-			'uniform mat4 projectionMatrix;',
-			'uniform mat4 viewMatrix;',
-			'uniform mat3 normalMatrix;',
 			'uniform vec3 cameraPosition;',
 
+			numMultiviewViews > 0 ? [
+				'uniform mat4 modelViewMatrices[' + numMultiviewViews + '];',
+				'uniform mat3 normalMatrices[' + numMultiviewViews + '];',
+				'uniform mat4 viewMatrices[' + numMultiviewViews + '];',
+				'uniform mat4 projectionMatrices[' + numMultiviewViews + '];',
+
+				'#define modelViewMatrix modelViewMatrices[VIEW_ID]',
+				'#define normalMatrix normalMatrices[VIEW_ID]',
+				'#define viewMatrix viewMatrices[VIEW_ID]',
+				'#define projectionMatrix projectionMatrices[VIEW_ID]'
+
+			].join( '\n' ) : [
+
+				'uniform mat4 modelViewMatrix;',
+				'uniform mat4 projectionMatrix;',
+				'uniform mat4 viewMatrix;',
+				'uniform mat3 normalMatrix;',
+
+			].join( '\n' ),
+
 			'attribute vec3 position;',
 			'attribute vec3 normal;',
 			'attribute vec2 uv;',
@@ -551,9 +569,15 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 
 			( ( material.extensions ? material.extensions.shaderTextureLOD : false ) || parameters.envMap ) && ( capabilities.isWebGL2 || extensions.get( 'EXT_shader_texture_lod' ) ) ? '#define TEXTURE_LOD_EXT' : '',
 
-			'uniform mat4 viewMatrix;',
 			'uniform vec3 cameraPosition;',
 
+			numMultiviewViews > 0 ? [
+
+				'uniform mat4 viewMatrices[' + numMultiviewViews + '];',
+				'#define viewMatrix viewMatrices[VIEW_ID]'
+
+			].join( '\n' ) : 'uniform mat4 viewMatrix;',
+
 			( parameters.toneMapping !== NoToneMapping ) ? '#define TONE_MAPPING' : '',
 			( parameters.toneMapping !== NoToneMapping ) ? ShaderChunk[ 'tonemapping_pars_fragment' ] : '', // this code is required here because it is used by the toneMapping() function defined below
 			( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( 'toneMapping', parameters.toneMapping ) : '',
@@ -607,6 +631,15 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 		// GLSL 3.0 conversion
 		prefixVertex = [
 			'#version 300 es\n',
+
+			numMultiviewViews > 0 ? [
+
+				'#extension GL_OVR_multiview2 : require',
+				'layout(num_views = ' + numMultiviewViews + ') in;',
+				'#define VIEW_ID gl_ViewID_OVR'
+
+			].join( '\n' ) : '',
+
 			'#define attribute in',
 			'#define varying out',
 			'#define texture2D texture'
@@ -614,6 +647,12 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 
 		prefixFragment = [
 			'#version 300 es\n',
+			numMultiviewViews > 0 ? [
+
+				'#extension GL_OVR_multiview2 : require',
+				'#define VIEW_ID gl_ViewID_OVR'
+
+			].join( '\n' ) : '',
 			'#define varying in',
 			isGLSL3ShaderMaterial ? '' : 'out highp vec4 pc_fragColor;',
 			isGLSL3ShaderMaterial ? '' : '#define gl_FragColor pc_fragColor',
@@ -771,6 +810,7 @@ function WebGLProgram( renderer, extensions, code, material, shader, parameters,
 	this.program = program;
 	this.vertexShader = glVertexShader;
 	this.fragmentShader = glFragmentShader;
+	this.numMultiviewViews = numMultiviewViews;
 
 	return this;
 

+ 2 - 1
src/renderers/webgl/WebGLState.js

@@ -685,7 +685,8 @@ function WebGLState( gl, extensions, utils, capabilities ) {
 		stencilBuffer.setTest( stencilWrite );
 		if ( stencilWrite ) {
 
-			stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilMask );
+			stencilBuffer.setMask( material.stencilWriteMask );
+			stencilBuffer.setFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask );
 			stencilBuffer.setOp( material.stencilFail, material.stencilZFail, material.stencilZPass );
 
 		}

+ 67 - 1
src/renderers/webgl/WebGLTextures.js

@@ -260,6 +260,21 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 		}
 
+		if ( renderTarget.isWebGLMultiviewRenderTarget ) {
+
+			_gl.deleteTexture( renderTargetProperties.__webglColorTexture );
+			_gl.deleteTexture( renderTargetProperties.__webglDepthStencilTexture );
+
+			info.memory.textures -= 2;
+
+			for ( var i = 0, il = renderTargetProperties.__webglViewFramebuffers.length; i < il; i ++ ) {
+
+				_gl.deleteFramebuffer( renderTargetProperties.__webglViewFramebuffers[ i ] );
+
+			}
+
+		}
+
 		properties.remove( renderTarget.texture );
 		properties.remove( renderTarget );
 
@@ -946,6 +961,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 		var isCube = ( renderTarget.isWebGLRenderTargetCube === true );
 		var isMultisample = ( renderTarget.isWebGLMultisampleRenderTarget === true );
+		var isMultiview = ( renderTarget.isWebGLMultiviewRenderTarget === true );
 		var supportsMips = isPowerOfTwo( renderTarget ) || capabilities.isWebGL2;
 
 		// Setup framebuffer
@@ -998,6 +1014,56 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 				}
 
+			} else if ( isMultiview ) {
+
+				if ( capabilities.multiview ) {
+
+					var width = renderTarget.width;
+					var height = renderTarget.height;
+					var numViews = renderTarget.numViews;
+
+					_gl.bindFramebuffer( _gl.FRAMEBUFFER, renderTargetProperties.__webglFramebuffer );
+
+					var ext = extensions.get( 'OVR_multiview2' );
+
+					info.memory.textures += 2;
+
+					var colorTexture = _gl.createTexture();
+					_gl.bindTexture( _gl.TEXTURE_2D_ARRAY, colorTexture );
+					_gl.texParameteri( _gl.TEXTURE_2D_ARRAY, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
+					_gl.texParameteri( _gl.TEXTURE_2D_ARRAY, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
+					_gl.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, _gl.RGBA8, width, height, numViews, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, null );
+					ext.framebufferTextureMultiviewOVR( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, colorTexture, 0, 0, numViews );
+
+					var depthStencilTexture = _gl.createTexture();
+					_gl.bindTexture( _gl.TEXTURE_2D_ARRAY, depthStencilTexture );
+					_gl.texParameteri( _gl.TEXTURE_2D_ARRAY, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
+					_gl.texParameteri( _gl.TEXTURE_2D_ARRAY, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
+					_gl.texImage3D( _gl.TEXTURE_2D_ARRAY, 0, _gl.DEPTH24_STENCIL8, width, height, numViews, 0, _gl.DEPTH_STENCIL, _gl.UNSIGNED_INT_24_8, null );
+					ext.framebufferTextureMultiviewOVR( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, depthStencilTexture, 0, 0, numViews );
+
+					var viewFramebuffers = new Array( numViews );
+					for ( var i = 0; i < numViews; ++ i ) {
+
+						viewFramebuffers[ i ] = _gl.createFramebuffer();
+						_gl.bindFramebuffer( _gl.FRAMEBUFFER, viewFramebuffers[ i ] );
+						_gl.framebufferTextureLayer( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, colorTexture, 0, i );
+
+					}
+
+					renderTargetProperties.__webglColorTexture = colorTexture;
+					renderTargetProperties.__webglDepthStencilTexture = depthStencilTexture;
+					renderTargetProperties.__webglViewFramebuffers = viewFramebuffers;
+
+					_gl.bindFramebuffer( _gl.FRAMEBUFFER, null );
+					_gl.bindTexture( _gl.TEXTURE_2D_ARRAY, null );
+
+				} else {
+
+					console.warn( 'THREE.WebGLRenderer: WebGLMultiviewRenderTarget can only be used with WebGL2 and Multiview extension support.' );
+
+				}
+
 			}
 
 		}
@@ -1023,7 +1089,7 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils,
 
 			state.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
 
-		} else {
+		} else if ( ! isMultiview ) {
 
 			state.bindTexture( _gl.TEXTURE_2D, textureProperties.__webglTexture );
 			setTextureParameters( _gl.TEXTURE_2D, renderTarget.texture, supportsMips );

+ 2 - 0
src/utils.d.ts

@@ -0,0 +1,2 @@
+export function arrayMin( array: number[] ): number;
+export function arrayMax( array: number[] ): number;

+ 0 - 0
rollup-examples.config.js → utils/build/rollup-examples.config.js


+ 0 - 0
rollup.config.js → utils/build/rollup.config.js


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