Selaa lähdekoodia

Merge pull request #9 from mrdoob/dev

Merge upstream.
gogoend 6 vuotta sitten
vanhempi
commit
2910a6192e
100 muutettua tiedostoa jossa 3815 lisäystä ja 2701 poistoa
  1. 15 0
      .editorconfig
  2. 1 1
      .github/ISSUE_TEMPLATE.md
  3. 1 1
      README.md
  4. 321 620
      build/three.js
  5. 387 385
      build/three.min.js
  6. 321 620
      build/three.module.js
  7. 3 1
      docs/api/en/core/Object3D.html
  8. 4 5
      docs/api/en/loaders/AnimationLoader.html
  9. 10 0
      docs/api/en/loaders/ImageBitmapLoader.html
  10. 1 1
      docs/api/en/loaders/ImageLoader.html
  11. 24 0
      docs/api/en/loaders/Loader.html
  12. 1 1
      docs/api/en/materials/Material.html
  13. 131 0
      docs/api/en/materials/MeshDistanceMaterial.html
  14. 150 0
      docs/api/en/materials/MeshMatcapMaterial.html
  15. 61 1
      docs/api/en/materials/MeshNormalMaterial.html
  16. 1 1
      docs/api/en/math/Matrix3.html
  17. 1 1
      docs/api/en/math/Matrix4.html
  18. 7 0
      docs/api/en/math/Quaternion.html
  19. 1 1
      docs/api/en/objects/Mesh.html
  20. 3 30
      docs/api/en/renderers/WebGLRenderer.html
  21. 15 3
      docs/api/en/textures/Texture.html
  22. 1 1
      docs/api/zh/core/Object3D.html
  23. 4 7
      docs/api/zh/loaders/AnimationLoader.html
  24. 10 0
      docs/api/zh/loaders/ImageBitmapLoader.html
  25. 20 0
      docs/api/zh/loaders/Loader.html
  26. 1 1
      docs/api/zh/materials/Material.html
  27. 112 0
      docs/api/zh/materials/MeshDistanceMaterial.html
  28. 120 0
      docs/api/zh/materials/MeshMatcapMaterial.html
  29. 42 1
      docs/api/zh/materials/MeshNormalMaterial.html
  30. 3 3
      docs/api/zh/math/Matrix3.html
  31. 5 5
      docs/api/zh/math/Matrix4.html
  32. 8 1
      docs/api/zh/math/Quaternion.html
  33. 1 1
      docs/api/zh/objects/Mesh.html
  34. 0 23
      docs/api/zh/renderers/WebGLRenderer.html
  35. 12 0
      docs/api/zh/textures/Texture.html
  36. 1 0
      docs/examples/exporters/GLTFExporter.html
  37. 145 0
      docs/examples/loaders/DRACOLoader.html
  38. 3 0
      docs/examples/loaders/GLTFLoader.html
  39. 1 1
      docs/examples/loaders/OBJLoader2.html
  40. 2 1
      docs/examples/loaders/SVGLoader.html
  41. 2 3
      docs/examples/objects/Lensflare.html
  42. 60 0
      docs/examples/utils/SkeletonUtils.html
  43. 9 2
      docs/list.js
  44. 8 1
      docs/manual/en/introduction/How-to-dispose-of-objects.html
  45. 1 0
      docs/manual/en/introduction/Loading-3D-models.html
  46. 7 7
      docs/manual/en/introduction/Matrix-transformations.html
  47. 7 7
      docs/manual/zh/introduction/Matrix-transformations.html
  48. 97 47
      docs/scenes/js/material.js
  49. 48 0
      editor/css/dark.css
  50. 48 0
      editor/css/light.css
  51. 0 2
      editor/examples/arkanoid.app.json
  52. 0 2
      editor/examples/camera.app.json
  53. 0 2
      editor/examples/particles.app.json
  54. 0 2
      editor/examples/pong.app.json
  55. 0 2
      editor/examples/shaders.app.json
  56. BIN
      editor/images/icon.png
  57. BIN
      editor/images/icon.xcf
  58. 24 18
      editor/index.html
  59. 0 2
      editor/js/Config.js
  60. 65 16
      editor/js/Editor.js
  61. 4 2
      editor/js/Loader.js
  62. 1 1
      editor/js/Menubar.Add.js
  63. 1 1
      editor/js/Menubar.Edit.js
  64. 1 1
      editor/js/Sidebar.Geometry.BufferGeometry.js
  65. 1 1
      editor/js/Sidebar.Geometry.Geometry.js
  66. 1 1
      editor/js/Sidebar.Geometry.Modifiers.js
  67. 3 1
      editor/js/Sidebar.Geometry.js
  68. 139 6
      editor/js/Sidebar.Material.js
  69. 2 2
      editor/js/Sidebar.Object.js
  70. 5 28
      editor/js/Sidebar.Project.js
  71. 3 3
      editor/js/Sidebar.Scene.js
  72. 1 1
      editor/js/Sidebar.Settings.js
  73. 4 4
      editor/js/Strings.js
  74. 48 0
      editor/js/Viewport.Camera.js
  75. 3 3
      editor/js/Viewport.Info.js
  76. 33 12
      editor/js/Viewport.js
  77. 1 2
      editor/js/libs/app.js
  78. 1 1
      editor/js/libs/codemirror/mode/glsl.js
  79. 38 38
      editor/js/libs/three.html.js
  80. 51 58
      editor/js/libs/ui.js
  81. 0 55
      editor/main.js
  82. 13 0
      editor/manifest.json
  83. 197 0
      editor/sw.js
  84. 50 39
      examples/files.js
  85. 4 2
      examples/js/MD2Character.js
  86. 4 2
      examples/js/MD2CharacterComplex.js
  87. 273 64
      examples/js/MarchingCubes.js
  88. 25 22
      examples/js/animation/MMDPhysics.js
  89. 14 14
      examples/js/controls/EditorControls.js
  90. 20 7
      examples/js/controls/TransformControls.js
  91. 3 3
      examples/js/effects/OutlineEffect.js
  92. 206 0
      examples/js/exporters/DracoExporter.js
  93. 62 29
      examples/js/exporters/GLTFExporter.js
  94. 7 3
      examples/js/libs/ammo.js
  95. 3 0
      examples/js/libs/draco/draco_encoder.js
  96. 2 2
      examples/js/loaders/ColladaLoader.js
  97. 22 7
      examples/js/loaders/FBXLoader.js
  98. 2 2
      examples/js/loaders/GCodeLoader.js
  99. 236 451
      examples/js/loaders/GLTFLoader.js
  100. 5 3
      examples/js/loaders/KTXLoader.js

+ 15 - 0
.editorconfig

@@ -0,0 +1,15 @@
+# http://editorconfig.org
+
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+
+[*.{js,ts,html}]
+charset = utf-8
+indent_style = tab
+indent_size = 2
+
+[*.{js,ts}]
+trim_trailing_whitespace = true

+ 1 - 1
.github/ISSUE_TEMPLATE.md

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

+ 1 - 1
README.md

@@ -10,7 +10,7 @@ three.js
 
 #### JavaScript 3D library ####
 
-The aim of the project is to create an easy to use, lightweight, 3D library. The library provides Canvas 2D, SVG, CSS3D and WebGL renderers.
+The aim of the project is to create an easy to use, lightweight, 3D library with a default WebGL renderer. The library also provides Canvas 2D, SVG and CSS3D renderers in the examples.
 
 [Examples](http://threejs.org/examples/) —
 [Documentation](http://threejs.org/docs/) —

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 321 - 620
build/three.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 387 - 385
build/three.min.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 321 - 620
build/three.module.js


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

@@ -46,7 +46,7 @@
 
 		<h3>[property:Material customDistanceMaterial]</h3>
 		<p>
-		Same as customDepthMaterial, but used with [page:PointLight]. Default is *undefined*.
+		Same as [page:.customDepthMaterial customDepthMaterial], but used with [page:PointLight]. Default is *undefined*.
 		</p>
 
 		<h3>[property:Boolean frustumCulled]</h3>
@@ -229,6 +229,8 @@
 		recursive -- if true, descendants of the object are also copied. Default is true.<br /><br />
 
 		Copy the given object into this object.
+
+		Note: event listeners and user-defined callbacks ([page:.onAfterRender] and [page:.onBeforeRender]) are not copied.
 		</p>
 
 		<h3>[method:Object3D getObjectById]( [param:Integer id] )</h3>

+ 4 - 5
docs/api/en/loaders/AnimationLoader.html

@@ -65,19 +65,18 @@
 		<p>
 		[page:String url] — the path or URL to the file. This can also be a
 			[link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].<br />
-		[page:Function onLoad] — Will be called when load completes. The argument will be the loaded [page:Animation animation].<br />
+		[page:Function onLoad] — Will be called when load completes. The argument will be the loaded [page:AnimationClip animation clips].<br />
 		[page:Function onProgress] — Will be called while load progresses. The argument will be the XMLHttpRequest instance, which contains .[page:Integer total] and .[page:Integer loaded] bytes.<br />
 		[page:Function onError] — Will be called if load errors.<br /><br />
 
 		Begin loading from url and pass the loaded animation to onLoad.
 		</p>
 
-		<h3>[method:null parse]( [param:JSON json], [param:Function onLoad] )</h3>
+		<h3>[method:Array parse]( [param:JSON json] )</h3>
 		<p>
-		[page:JSON json] — required<br />
-		[page:Function onLoad] — Will be called when parsing completes. <br /><br />
+		[page:JSON json] — required<br /><br />
 
-		Parse the JSON object and pass the result to onLoad. Individual clips in the object will
+		Parse the JSON object and return an array of animation clips. Individual clips in the object will
 		be parsed with [page:AnimationClip.parse].
 		</p>
 

+ 10 - 0
docs/api/en/loaders/ImageBitmapLoader.html

@@ -16,6 +16,13 @@
 			Unlike [page:FileLoader], [name] does not avoid multiple concurrent requests to the same URL.
 		</p>
 
+		<p>
+			Note that [page:Texture.flipY] and [page:Texture.premultiplyAlpha] with [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap] are ignored.
+			[link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap] needs these configuration on bitmap creation
+			unlike regular images need them on uploading to GPU. You need to set the equivalent options via [page:ImageBitmapLoader.setOptions]
+			instead. Refer to [link:https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.10 WebGL specification] for the detail.
+		</p>
+
 		<h2>Example</h2>
 
 		<p>
@@ -26,6 +33,9 @@
 		// instantiate a loader
 		var loader = new THREE.ImageBitmapLoader();
 
+		// set options if needed
+		loader.setOptions( { imageOrientation: 'flipY' } );
+
 		// load a image resource
 		loader.load(
 			// resource URL

+ 1 - 1
docs/api/en/loaders/ImageLoader.html

@@ -12,7 +12,7 @@
 
 		<p class="desc">
 			A loader for loading an [page:Image].
-			This uses the [page:FileLoader] internally for loading files, and is used internally by the
+			This is used internally by the
 			[page:CubeTextureLoader], [page:ObjectLoader] and [page:TextureLoader].
 		</p>
 

+ 24 - 0
docs/api/en/loaders/Loader.html

@@ -62,6 +62,30 @@
 		Creates an array of [page:Material] based on the array of parameters m. The index of the parameters decide the correct index of the materials.
 		</p>
 
+		<h2>Handlers</h2>
+
+		<p>
+		*[name].Handlers* is a special object normally used by other loaders like [page:GLTFLoader] or [page:MTLLoader]. It provides an
+		API that allows the definition of special mappings: What loaders should be used in order to load specific files. A typical use case
+		is to overwrite the default loader for textures.<br /><br />
+
+		Note: It's only possible to use *[name].Handlers* if the respective loader support the usage.
+		</p>
+
+		<h3>[method:null add]( [param:Object regex], [param:Loader loader] )</h3>
+		<p>
+		[page:Object regex] — A regular expression.<br />
+		[page:Loader loader] — The loader.
+		<p>
+		Registers a loader with the given regular expression.
+		</p>
+
+		<h3>[method:null get]( [param:String file] )</h3>
+		<p>
+		[page:String file] — The file path.
+		<p>
+		Can be used to retrieve the registered loader for the given file path.
+		</p>
 
 		<h2>Source</h2>
 

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

@@ -295,7 +295,7 @@
 		These needs to be disposed by [page:Texture Texture].
 		</p>
 
-		<h3>[method:null onBeforeCompile]( [param:Object shader], [param:WebGLRenderer renderer] )</h3>
+		<h3>[method:null onBeforeCompile]( [param:Shader shader], [param:WebGLRenderer renderer] )</h3>
 		<p>
 		An optional callback that is executed immediately before the shader program is compiled.
 		This function is called with the shader source code as a parameter. Useful for the modification of built-in materials.

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

@@ -0,0 +1,131 @@
+<!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:Material] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			[name] is internally used for implementing shadow mapping with [page:PointLight]s.<br/><br/>
+
+			Can also be used to customize the shadow casting of an object by assigning an instance of [name] to [page:Object3D.customDistanceMaterial].
+			The following examples demonstrates this approach in order to ensure transparent parts of objects do no cast shadows.
+		</p>
+
+		<h2>Example</h2>
+
+		[example:webgl_shadowmap_pointlight WebGL / shadowmap / pointlight]
+
+		<script>
+
+		// iOS iframe auto-resize workaround
+
+		if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {
+
+			var scene = document.getElementById( 'scene' );
+
+			scene.style.width = getComputedStyle( scene ).width;
+			scene.style.height = getComputedStyle( scene ).height;
+			scene.setAttribute( 'scrolling', 'no' );
+
+		}
+
+		</script>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Object parameters] )</h3>
+		<p>
+			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
+			Any property of the material (including any property inherited from [page:Material]) can be passed in here.
+		</p>
+
+		<h2>Properties</h2>
+		<p>See the base [page:Material] class for common properties.</p>
+
+		<h3>[property:Texture alphaMap]</h3>
+		<p>The alpha map is a grayscale texture that controls the opacity across the surface
+			(black: fully transparent; white: fully opaque). Default is null.<br /><br />
+
+			Only the color of the texture is used, ignoring the alpha channel if one exists.
+			For RGB and RGBA textures, the [page:WebGLRenderer WebGL] renderer will use the
+			green channel when sampling this texture due to the extra bit of precision provided
+			for green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
+			luminance/alpha textures will also still work as expected.
+		</p>
+
+		<h3>[property:Texture displacementMap]</h3>
+		<p>
+			The displacement map affects the position of the mesh's vertices. Unlike other maps
+			which only affect the light and shade of the material the displaced vertices can cast shadows,
+			block other objects, and otherwise act as real geometry. The displacement texture is
+			an image where the value of each pixel (white being the highest) is mapped against,
+			and repositions, the vertices of the mesh.
+		</p>
+
+		<h3>[property:Float displacementScale]</h3>
+		<p>
+			How much the displacement map affects the mesh (where black is no displacement,
+			and white is maximum displacement). Without a displacement map set, this value is not applied.
+			 Default is 1.
+		</p>
+
+		<h3>[property:Float displacementBias]</h3>
+		<p>
+			The offset of the displacement map's values on the mesh's vertices.
+			Without a displacement map set, this value is not applied. Default is 0.
+		</p>
+
+		<h3>[property:Float farDistance]</h3>
+		<p>
+			The far value of the point light's internal shadow camera.
+		</p>
+
+		<h3>[property:Boolean fog]</h3>
+		<p>Whether the material is affected by fog. Default is *false*.</p>
+
+		<h3>[property:Boolean isMeshDistanceMaterial]</h3>
+		<p>
+			Used to check whether this or derived classes are mesh depth materials. Default is *true*.<br /><br />
+
+			You should not change this, as it used internally for optimisation.
+		</p>
+
+		<h3>[property:Boolean lights]</h3>
+		<p>Whether the material is affected by lights. Default is *false*.</p>
+
+		<h3>[property:Texture map]</h3>
+		<p>The color map. Default is  null.</p>
+
+		<h3>[property:boolean morphTargets]</h3>
+		<p>Define whether the material uses morphTargets. Default is false.</p>
+
+		<h3>[property:Float nearDistance]</h3>
+		<p>
+			The near value of the point light's internal shadow camera.
+		</p>
+
+		<h3>[property:Vector3 referencePosition]</h3>
+		<p>
+			The position of the point light in world space.
+		</p>
+
+		<h3>[property:Boolean skinning]</h3>
+		<p>Define whether the material uses skinning. Default is false.</p>
+
+		<h2>Methods</h2>
+		<p>See the base [page:Material] class for common methods.</p>
+
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

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

@@ -0,0 +1,150 @@
+<!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:Material] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			[name] is defined by a MatCap (or Lit Sphere) texture, which encodes the material color and shading.<br/><br/>
+			[name] does not respond to lights since the matcap image file encodes baked lighting.
+			It will cast a shadow onto an object that receives shadows (and shadow clipping works), but it will not self-shadow or receive shadows.
+		</p>
+
+		<iframe id="scene" src="scenes/material-browser.html#MeshMatcapMaterial"></iframe>
+
+		<script>
+
+		// iOS iframe auto-resize workaround
+
+		if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {
+
+			var scene = document.getElementById( 'scene' );
+
+			scene.style.width = getComputedStyle( scene ).width;
+			scene.style.height = getComputedStyle( scene ).height;
+			scene.setAttribute( 'scrolling', 'no' );
+
+		}
+
+		</script>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:Object parameters] )</h3>
+		<p>
+			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
+			Any property of the material (including any property inherited from [page:Material]) can be passed in here.<br /><br />
+
+			The exception is the property [page:Hexadecimal color], which can be passed in as a hexadecimal
+			string and is *0xffffff* (white) by default. [page:Color.set]( color ) is called internally.
+		</p>
+
+		<h2>Properties</h2>
+		<p>See the base [page:Material] class for common properties.</p>
+
+		<h3>[property:Texture alphaMap]</h3>
+		<p>The alpha map is a grayscale texture that controls the opacity across the surface
+			(black: fully transparent; white: fully opaque). Default is null.<br /><br />
+
+			Only the color of the texture is used, ignoring the alpha channel if one exists.
+			For RGB and RGBA textures, the [page:WebGLRenderer WebGL] renderer will use the
+			green channel when sampling this texture due to the extra bit of precision provided
+			for green in DXT-compressed and uncompressed RGB 565 formats. Luminance-only and
+			luminance/alpha textures will also still work as expected.
+		</p>
+
+		<h3>[property:Texture bumpMap]</h3>
+		<p>
+			The texture to create a bump map. The black and white values map to the perceived depth in relation to the lights.
+			Bump doesn't actually affect the geometry of the object, only the lighting. If a normal map is defined this will
+			be ignored.
+		</p>
+
+		<h3>[property:Float bumpScale]</h3>
+		<p>How much the bump map affects the material. Typical ranges are 0-1. Default is 1.</p>
+
+		<h3>[property:Color color]</h3>
+		<p>[page:Color] of the material, by default set to white (0xffffff).</p>
+
+		<h3>[property:Texture displacementMap]</h3>
+		<p>
+			The displacement map affects the position of the mesh's vertices. Unlike other maps
+			which only affect the light and shade of the material the displaced vertices can cast shadows,
+			block other objects, and otherwise act as real geometry. The displacement texture is
+			an image where the value of each pixel (white being the highest) is mapped against,
+			and repositions, the vertices of the mesh.
+		</p>
+
+		<h3>[property:Float displacementScale]</h3>
+		<p>
+			How much the displacement map affects the mesh (where black is no displacement,
+			and white is maximum displacement). Without a displacement map set, this value is not applied.
+			 Default is 1.
+		</p>
+
+		<h3>[property:Float displacementBias]</h3>
+		<p>
+			The offset of the displacement map's values on the mesh's vertices.
+			Without a displacement map set, this value is not applied. Default is 0.
+		</p>
+
+		<h3>[property:Boolean isMeshMatcapMaterial]</h3>
+		<p>
+			Used to check whether this or derived classes are mesh Matcap materials. Default is *true*.<br /><br />
+
+			You should not change this, as it used internally for optimisation.
+		</p>
+
+		<h3>[property:Texture map]</h3>
+		<p>The color map. Default is null. The texture map color is modulated by the diffuse [page:.color].</p>
+
+		<h3>[property:Texture matcap]</h3>
+		<p>The matcap map. Default is null.</p>
+
+		<h3>[property:boolean morphNormals]</h3>
+		<p>
+			Defines whether the material uses morphNormals. Set as true to pass morphNormal
+			attributes from the [page:Geometry]	to the shader. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean morphTargets]</h3>
+		<p>Define whether the material uses morphTargets. Default is false.</p>
+
+		<h3>[property:Texture normalMap]</h3>
+		<p>
+			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
+			the way the color is lit. Normal maps do not change the actual shape of the surface, only the lighting.
+		</p>
+
+		<h3>[property:Integer normalMapType]</h3>
+		<p>
+			The type of normal map.<br /><br />
+
+			Options are [page:constant THREE.TangentSpaceNormalMap] (default), and [page:constant THREE.ObjectSpaceNormalMap].
+		</p>
+
+		<h3>[property:Vector2 normalScale]</h3>
+		<p>
+			How much the normal map affects the material. Typical ranges are 0-1.
+			Default is a [page:Vector2] set to (1,1).
+		</p>
+
+		<h3>[property:Boolean skinning]</h3>
+		<p>Define whether the material uses skinning. Default is false.</p>
+
+		<h2>Methods</h2>
+		<p>See the base [page:Material] class for common methods.</p>
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 61 - 1
docs/api/en/materials/MeshNormalMaterial.html

@@ -44,6 +44,38 @@
 		<h2>Properties</h2>
 		<p>See the base [page:Material] class for common properties.</p>
 
+		<h3>[property:Texture bumpMap]</h3>
+		<p>
+			The texture to create a bump map. The black and white values map to the perceived depth in relation to the lights.
+			Bump doesn't actually affect the geometry of the object, only the lighting. If a normal map is defined this will
+			be ignored.
+		</p>
+
+		<h3>[property:Float bumpScale]</h3>
+		<p>How much the bump map affects the material. Typical ranges are 0-1. Default is 1.</p>
+
+		<h3>[property:Texture displacementMap]</h3>
+		<p>
+			The displacement map affects the position of the mesh's vertices. Unlike other maps
+			which only affect the light and shade of the material the displaced vertices can cast shadows,
+			block other objects, and otherwise act as real geometry. The displacement texture is
+			an image where the value of each pixel (white being the highest) is mapped against,
+			and repositions, the vertices of the mesh.
+		</p>
+
+		<h3>[property:Float displacementScale]</h3>
+		<p>
+			How much the displacement map affects the mesh (where black is no displacement,
+			and white is maximum displacement). Without a displacement map set, this value is not applied.
+			 Default is 1.
+		</p>
+
+		<h3>[property:Float displacementBias]</h3>
+		<p>
+			The offset of the displacement map's values on the mesh's vertices.
+			Without a displacement map set, this value is not applied. Default is 0.
+		</p>
+
 		<h3>[property:Boolean fog]</h3>
 		<p>Whether the material is affected by fog. Default is *false*.</p>
 
@@ -57,9 +89,37 @@
 		<h3>[property:Boolean lights]</h3>
 		<p>Whether the material is affected by lights. Default is *false*.</p>
 
-		<h3>[property:boolean morphTargets]</h3>
+		<h3>[property:boolean morphNormals]</h3>
+		<p>
+			Defines whether the material uses morphNormals. Set as true to pass morphNormal
+			attributes from the [page:Geometry]	to the shader. Default is *false*.
+		</p>
+
+		<h3>[property:Boolean morphTargets]</h3>
 		<p>Define whether the material uses morphTargets. Default is false.</p>
 
+		<h3>[property:Texture normalMap]</h3>
+		<p>
+			The texture to create a normal map. The RGB values affect the surface normal for each pixel fragment and change
+			the way the color is lit. Normal maps do not change the actual shape of the surface, only the lighting.
+		</p>
+
+		<h3>[property:Integer normalMapType]</h3>
+		<p>
+			The type of normal map.<br /><br />
+
+			Options are [page:constant THREE.TangentSpaceNormalMap] (default), and [page:constant THREE.ObjectSpaceNormalMap].
+		</p>
+
+		<h3>[property:Vector2 normalScale]</h3>
+		<p>
+			How much the normal map affects the material. Typical ranges are 0-1.
+			Default is a [page:Vector2] set to (1,1).
+		</p>
+
+		<h3>[property:Boolean skinning]</h3>
+		<p>Define whether the material uses skinning. Default is false.</p>
+
 		<h3>[property:boolean wireframe]</h3>
 		<p>
 			Render geometry as wireframe. Default is false (i.e. render as smooth shaded).

+ 1 - 1
docs/api/en/math/Matrix3.html

@@ -55,7 +55,7 @@ m.elements = [ 11, 21, 31,
 
 		<h2>Properties</h2>
 
-		<h3>[property:Float32Array elements]</h3>
+		<h3>[property:Array elements]</h3>
 		<p>
 		A [link:https://en.wikipedia.org/wiki/Row-_and_column-major_order column-major]
 		 list of matrix values.

+ 1 - 1
docs/api/en/math/Matrix4.html

@@ -90,7 +90,7 @@ m.elements = [ 11, 21, 31, 41,
 
 		<h2>Properties</h2>
 
-		<h3>[property:Float32Array elements]</h3>
+		<h3>[property:Array elements]</h3>
 		<p>
 		A [link:https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order column-major]
 		 list of matrix values.

+ 7 - 0
docs/api/en/math/Quaternion.html

@@ -44,6 +44,13 @@
 
 		<h2>Properties</h2>
 
+		<h3>[property:Boolean isQuaternion]</h3>
+		<p>
+			Used to check whether this or derived classes are Quaternions. Default is *true*.<br /><br />
+
+			You should not change this, as it is used internally for optimisation.
+		</p>
+
 		<h3>[property:Float x]</h3>
 		<p>Changing this property will result in [page:.onChangeCallback onChangeCallback] being called.</p>
 

+ 1 - 1
docs/api/en/objects/Mesh.html

@@ -95,7 +95,7 @@
 		<h3>[method:null raycast]( [param:Raycaster raycaster], [param:Array intersects] )</h3>
 		<p>
 		Get intersections between a casted ray and this mesh.
-		[page:Raycaster.intersectObject] will call this method.
+		[page:Raycaster.intersectObject] will call this method, but the results are not ordered.
 		</p>
 
 		<h3>[method:null updateMorphTargets]()</h3>

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

@@ -279,13 +279,6 @@
 
 		<h2>Methods</h2>
 
-		<h3>[method:Integer allocTextureUnit]</h3>
-		<p>
-		Attempt to allocate a texture unit for use by a shader. Will warn if trying to allocate
-		more texture units than the GPU supports. This is mainly used internally.
-		See [page:WebGLRenderer.capabilities capabilities.maxTextures].
-		</p>
-
 		<h3>[method:null clear]( [param:Boolean color], [param:Boolean depth], [param:Boolean stencil] )</h3>
 		<p>
 		Tells the renderer to clear its color, depth or stencil drawing buffer(s).
@@ -346,7 +339,7 @@
 		<p>Returns an object that describes the attributes set on the WebGL context when it was created.</p>
 
 		<h3>[method:RenderTarget getRenderTarget]()</h3>
-		<p>Returns the current RenderTarget, if any.</p>
+		<p>Returns the current [page:RenderTarget RenderTarget] if there are; returns *null* otherwise.</p>
 
 		<h3>[method:Vector4 getCurrentViewport]( [param:Vector4 target] )</h3>
 		<p>
@@ -436,10 +429,10 @@
 
 		<h3>[method:null setRenderTarget]( [param:WebGLRenderTarget renderTarget], [param:Integer activeCubeFace], [param:Integer activeMipMapLevel] )</h3>
 		<p>
-		renderTarget -- The [page:WebGLRenderTarget renderTarget] that needs to be activated (optional).<br />
+		renderTarget -- The [page:WebGLRenderTarget renderTarget] that needs to be activated. When *null* is given, the canvas is set as the active render target instead.<br />
 		activeCubeFace -- Specifies the active cube side (PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5) of [page:WebGLRenderTargetCube] (optional).<br />
 		activeMipMapLevel -- Specifies the active mipmap level (optional).<br /><br />
-		This method sets the active rendertarget. If the parameter is omitted the canvas is set as the active rendertarget.
+		This method sets the active rendertarget.
 		</p>
 
 		<h3>[method:null setScissor]( [param:Integer x], [param:Integer y], [param:Integer width], [param:Integer height] )<br />
@@ -466,26 +459,6 @@
 			Setting [page:Boolean updateStyle] to false prevents any style changes to the output canvas.
 		</p>
 
-		<h3>[method:null setTexture2D]( [param:Texture texture], [param:number slot] )</h3>
-		<p>
-		texture -- The [page:Texture texture] that needs to be set.<br />
-		slot -- The number indicating which slot should be used by the texture.<br /><br />
-
-		This method sets the correct texture to the correct slot for the WebGL shader.
-		The slot number can be found as a value of the uniform of the sampler.<br /><br />
-
-		Note: This method replaces the older [method:null setTexture] method.
-		</p>
-
-		<h3>[method:null setTextureCube]( [param:CubeTexture cubeTexture], [param:Number slot] )</h3>
-		<p>
-		texture -- The [page:CubeTexture cubeTexture] that needs to be set.<br />
-		slot -- The number indicating which slot should be used by the texture.<br /><br />
-
-		This method sets the correct texture to the correct slot for the WebGL shader.
-		The slot number can be found as a value of the uniform of the sampler.
-		</p>
-
 		<h3>[method:null setViewport]( [param:Integer x], [param:Integer y], [param:Integer width], [param:Integer height] )<br />
 		[method:null setViewport]( [param:Vector4 vector] )</h3>
 

+ 15 - 3
docs/api/en/textures/Texture.html

@@ -55,6 +55,13 @@
 		as long as video is playing - the [page:VideoTexture VideoTexture] class handles this automatically.
 		</p>
 
+		<h3>[property:Boolean isTexture]</h3>
+		<p>
+			Used to check whether this or derived classes are Textures. Default is *true*.<br /><br />
+
+			You should not change this, as it is used internally for optimisation.
+		</p>
+
 		<h3>[property:array mipmaps]</h3>
 		<p>
 		Array of user-specified mipmaps (optional).
@@ -180,13 +187,18 @@
 
 		<h3>[property:boolean premultiplyAlpha]</h3>
 		<p>
-		False by default, which is the norm for PNG images. Set to true if the RGB values have
-		been stored premultiplied by alpha.
+		If set to *true*, the alpha channel, if present, is multiplied into the color channels when the texture is uploaded to the GPU. Defaut is *false*.<br /><br />
+
+		Note that this property has no effect for [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap].
+		You need to configure on bitmap creation instead. See [page:ImageBitmapLoader].
 		</p>
 
 		<h3>[property:boolean flipY]</h3>
 		<p>
-		True by default. Flips the image's Y axis to match the WebGL texture coordinate space.
+		If set to *true*, the texture is flipped along the vertical axis when uploaded to the GPU. Default is *true*.<br /><br />
+
+		Note that this property has no effect for [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap].
+		You need to configure on bitmap creation instead. See [page:ImageBitmapLoader].
 		</p>
 
 		<h3>[property:number unpackAlignment]</h3>

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

@@ -44,7 +44,7 @@
 	</p>
 
 	<h3>[property:Material customDistanceMaterial]</h3>
-	<p>与customDepthMaterial相同,但与[page:PointLight]一起使用。默认值为*undefined*。
+	<p>与[page:.customDepthMaterial customDepthMaterial]相同,但与[page:PointLight]一起使用。默认值为*undefined*。
 	</p>
 
 	<h3>[property:Boolean frustumCulled]</h3>

+ 4 - 7
docs/api/zh/loaders/AnimationLoader.html

@@ -65,20 +65,17 @@
 		<p>
 		[page:String url] — 文件的URL或者路径,也可以为
 			[link:https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs Data URI].<br />
-		[page:Function onLoad] — 加载完成时将调用。回调参数为将要加载的[page:Animation animation].<br />
+		[page:Function onLoad] — 加载完成时将调用。回调参数为将要加载的[page:AnimationClip animation clips].<br />
 		[page:Function onProgress] —  将在加载过程中进行调用。参数为XMLHttpRequest实例,实例包含[page:Integer total]和[page:Integer loaded]字节。<br />
 		[page:Function onError] — 在加载错误时被调用。<br /><br />
 
             从URL中进行加载并将动画传递给onLoad。
 		</p>
 
-		<h3>[method:null parse]( [param:JSON json], [param:Function onLoad] )</h3>
+		<h3>[method:Array parse]( [param:JSON json] )</h3>
 		<p>
-		[page:JSON json] — 请求<br />
-		[page:Function onLoad] — 当解析完成时,将被调用 <br /><br />
-
-            解析JSON对象并将结果传递给onLoad。对象中的单个片段将
-            用[page [page:AnimationClip.parse]进行解析。
+		[page:JSON json] — 请求 <br /><br />
+			TODO
 		</p>
 
 		<h2>源</h2>

+ 10 - 0
docs/api/zh/loaders/ImageBitmapLoader.html

@@ -16,6 +16,13 @@
 			不像[page:FileLoader], [name]无需避免对同一的URL进行多次请求。
 		</p>
 
+		<p>
+			Note that [page:Texture.flipY] and [page:Texture.premultiplyAlpha] with [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap] are ignored.
+			[link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap] needs these configuration on bitmap creation
+			unlike regular images need them on uploading to GPU. You need to set the equivalent options via [page:ImageBitmapLoader.setOptions]
+			instead. Refer to [link:https://www.khronos.org/registry/webgl/specs/latest/1.0/#6.10 WebGL specification] for the detail.
+		</p>
+
 		<h2>例子</h2>
 
 		<p>
@@ -26,6 +33,9 @@
 		// 初始化一个加载器
 		var loader = new THREE.ImageBitmapLoader();
 
+		// set options if needed
+		loader.setOptions( { imageOrientation: 'flipY' } );
+
 		// 加载一个图片资源
 		loader.load(
 			// 资源的URL

+ 20 - 0
docs/api/zh/loaders/Loader.html

@@ -61,6 +61,26 @@
 		基于参数数组m,来创建 [page:Material] 数组. 参数索引与材质的索引一致。
 		</p>
 
+		<h2>Handlers</h2>
+
+		<p>
+		TODO
+		</p>
+
+		<h3>[method:null add]( [param:Object regex], [param:Loader loader] )</h3>
+		<p>
+		[page:Object regex] — TODO<br />
+		[page:Loader loader] — TODO
+		<p>
+		TODO
+		</p>
+
+		<h3>[method:null get]( [param:String file] )</h3>
+		<p>
+		[page:String file] — TODO
+		<p>
+		TODO
+		</p>
 
 		<h2>Source</h2>
 

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

@@ -243,7 +243,7 @@
 <p> 处理材质。材质的纹理不会被处理。需要通过[page:Texture Texture]处理。
 </p>
 
-<h3>[method:null onBeforeCompile]( [param:Object shader], [param:WebGLRenderer renderer] )</h3>
+<h3>[method:null onBeforeCompile]( [param:Shader shader], [param:WebGLRenderer renderer] )</h3>
 <p> 在编译shader程序之前立即执行的可选回调。此函数使用shader源码作为参数。用于修改内置材质。
 </p>
 

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

@@ -0,0 +1,112 @@
+<!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:Material] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			TODO
+		</p>
+
+		<h2>Example</h2>
+
+		[example:webgl_shadowmap_pointlight WebGL / shadowmap / pointlight]
+
+		<script>
+
+		// iOS iframe auto-resize workaround
+
+		if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {
+
+			var scene = document.getElementById( 'scene' );
+
+			scene.style.width = getComputedStyle( scene ).width;
+			scene.style.height = getComputedStyle( scene ).height;
+			scene.setAttribute( 'scrolling', 'no' );
+
+		}
+
+		</script>
+
+		<h2>构造函数(Constructor)</h2>
+
+		<h3>[name]( [param:Object parameters] )</h3>
+		<p>[page:Object parameters] - (可选)用于定义材质外观的对象,具有一个或多个属性。
+			材质的任何属性都可以从此处传入(包括从[page:Material]继承的任何属性)。
+		</p>
+
+		<h2>属性(Properties)</h2>
+		<p>常用属性请参见基类[page:Material]。</p>
+
+		<h3>[property:Texture alphaMap]</h3>
+		<p>alpha贴图是一种灰度纹理,用于控制整个表面的不透明度(黑色:完全透明;白色:完全不透明)。默认值为null。<br /><br />
+			仅使用纹理的颜色,忽略alpha通道(如果存在)。对于RGB和RGBA纹理,[page:WebGLRenderer WebGL]渲染器在采样此纹理时将使用绿色通道,
+			因为在DXT压缩和未压缩RGB 565格式中为绿色提供了额外的精度。Luminance-only以及luminance/alpha纹理也仍然有效。
+		</p>
+
+		<h3>[property:Texture displacementMap]</h3>
+		<p> 位移贴图会影响网格顶点的位置,与仅影响材质的光照和阴影的其他贴图不同,移位的顶点可以投射阴影,阻挡其他对象,以及充当真实的几何体。
+			位移纹理是指:网格的所有顶点被映射为图像中每个像素的值(白色是最高的),并且被重定位。
+		</p>
+
+		<h3>[property:Float displacementScale]</h3>
+		<p>位移贴图对网格的影响程度(黑色是无位移,白色是最大位移)。如果没有设置位移贴图,则不会应用此值。默认值为1。
+		</p>
+
+		<h3>[property:Float displacementBias]</h3>
+		<p> 位移贴图在网格顶点上的偏移量。如果没有设置位移贴图,则不会应用此值。默认值为0。
+		</p>
+
+		<h3>[property:Float farDistance]</h3>
+		<p>
+			TODO
+		</p>
+
+		<h3>[property:Boolean fog]</h3>
+		<p> 材质是否受雾影响。默认值为*false*。</p>
+
+		<h3>[property:Boolean isMeshDistanceMaterial]</h3>
+		<p> 用于检查此类或派生类是否为深度网格材质。默认值为 *true*。<br /><br />
+
+			因为其通常用在内部优化,所以不应该更改该属性值。
+		</p>
+
+		<h3>[property:Boolean lights]</h3>
+		<p>材质是否受到光照的影响。默认值为 *false*。</p>
+
+		<h3>[property:Texture map]</h3>
+		<p>颜色贴图。默认为null。</p>
+
+		<h3>[property:boolean morphTargets]</h3>
+		<p>材质是否使用morphTargets。默认值为false。</p>
+
+		<h3>[property:Float nearDistance]</h3>
+		<p>
+			TODO
+		</p>
+
+		<h3>[property:Vector3 referencePosition]</h3>
+		<p>
+			TODO
+		</p>
+
+		<h3>[property:Boolean skinning]</h3>
+		<p>材质是否使用蒙皮。默认值为false。</p>
+
+		<h2>方法(Methods)</h2>
+		<p>常用方法请参见基类[page:Material]。</p>
+
+
+		<h2>源码(Source)</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

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

@@ -0,0 +1,120 @@
+<!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:Material] &rarr;
+
+		<h1>[name]</h1>
+
+		<p class="desc">
+			TODO
+		</p>
+
+		<iframe id="scene" src="scenes/material-browser.html#MeshMatcapMaterial"></iframe>
+
+		<script>
+
+		// iOS iframe auto-resize workaround
+
+		if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {
+
+			var scene = document.getElementById( 'scene' );
+
+			scene.style.width = getComputedStyle( scene ).width;
+			scene.style.height = getComputedStyle( scene ).height;
+			scene.setAttribute( 'scrolling', 'no' );
+
+		}
+
+		</script>
+
+		<h2>构造函数(Constructor)</h2>
+
+		<h3>[name]( [param:Object parameters] )</h3>
+		<p>[page:Object parameters] - (可选)用于定义材质外观的对象,具有一个或多个属性。
+			材质的任何属性都可以从此处传入(包括从[page:Material]继承的任何属性)。<br /><br />
+			属性[page:Hexadecimal color]例外,其可以作为十六进制字符串传递,默认情况下为 *0xffffff*(白色),内部调用[page:Color.set](color)。
+		</p>
+
+		<h2>属性(Properties)</h2>
+		<p>常用属性请参见基类[page:Material]。</p>
+
+		<h3>[property:Texture alphaMap]</h3>
+		<p>Talpha贴图是一种灰度纹理,用于控制整个表面的不透明度(黑色:完全透明;白色:完全不透明)。默认值为null。<br /><br />
+			仅使用纹理的颜色,忽略alpha通道(如果存在)。对于RGB和RGBA纹理,[page:WebGLRenderer WebGL]渲染器在采样此纹理时将使用绿色通道,
+			因为在DXT压缩和未压缩RGB 565格式中为绿色提供了额外的精度。Luminance-only以及luminance/alpha纹理也仍然有效。
+		</p>
+
+		<h3>[property:Texture bumpMap]</h3>
+		<p> 用于创建凹凸贴图的纹理。黑色和白色值映射到与光照相关的感知深度。凹凸实际上不会影响对象的几何形状,只影响光照。如果定义了法线贴图,则将忽略该贴图。
+		</p>
+
+		<h3>[property:Float bumpScale]</h3>
+		<p> 凹凸贴图会对材质产生多大影响。典型范围是0-1。默认值为1。</p>
+
+		<h3>[property:Color color]</h3>
+		<p>材质的颜色([page:Color]),默认值为白色 (0xffffff)。</p>
+
+		<h3>[property:Texture displacementMap]</h3>
+		<p> 位移贴图会影响网格顶点的位置,与仅影响材质的光照和阴影的其他贴图不同,移位的顶点可以投射阴影,阻挡其他对象,
+			以及充当真实的几何体。位移纹理是指:网格的所有顶点被映射为图像中每个像素的值(白色是最高的),并且被重定位。
+		</p>
+
+		<h3>[property:Float displacementScale]</h3>
+		<p> 位移贴图对网格的影响程度(黑色是无位移,白色是最大位移)。如果没有设置位移贴图,则不会应用此值。默认值为1。
+		</p>
+
+		<h3>[property:Float displacementBias]</h3>
+		<p>
+			位移贴图在网格顶点上的偏移量。如果没有设置位移贴图,则不会应用此值。默认值为0。
+		</p>
+
+		<h3>[property:Boolean isMeshMatcapMaterial]</h3>
+		<p>TODO<br /><br />
+
+			因为其通常用在内部优化,所以不应该更改该属性值。
+		</p>
+
+		<h3>[property:Texture map]</h3>
+		<p>颜色贴图。默认为null。纹理贴图颜色由漫反射颜色[page:.color]调节。</p>
+
+		<h3>[property:Texture matcap]</h3>
+		<p>TODO</p>
+
+		<h3>[property:boolean morphNormals]</h3>
+		<p> 定义是否使用morphNormals。设置为true可将morphNormal属性从[page:Geometry]传递到shader。默认值为*false*。
+		</p>
+
+		<h3>[property:Boolean morphTargets]</h3>
+		<p>定义材质是否使用morphTargets。默认值为false。</p>
+
+		<h3>[property:Texture normalMap]</h3>
+		<p> 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
+		</p>
+
+		<h3>[property:Integer normalMapType]</h3>
+		<p> 法线贴图的类型。<br /><br />
+			选项为[page:constant THREE.TangentSpaceNormalMap](默认)和[page:constant THREE.ObjectSpaceNormalMap]。
+		</p>
+
+		<h3>[property:Vector2 normalScale]</h3>
+		<p> 法线贴图对材质的影响程度。典型范围是0-1。默认值是[page:Vector2]设置为(1,1)。
+		</p>
+
+		<h3>[property:Boolean skinning]</h3>
+		<p>材质是否使用蒙皮。默认值为false。</p>
+
+		<h2>方法(Methods)</h2>
+		<p>常用方法请参见基类[page:Material]。</p>
+
+		<h2>源码(Source)</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 42 - 1
docs/api/zh/materials/MeshNormalMaterial.html

@@ -42,6 +42,27 @@
 		<h2>属性(Properties)</h2>
 		<p>常用属性请参见基类[page:Material]。</p>
 
+		<h3>[property:Texture bumpMap]</h3>
+		<p> 用于创建凹凸贴图的纹理。黑色和白色值映射到与光照相关的感知深度。凹凸实际上不会影响对象的几何形状,只影响光照。如果定义了法线贴图,则将忽略该贴图。
+		</p>
+
+		<h3>[property:Float bumpScale]</h3>
+		<p> 凹凸贴图会对材质产生多大影响。典型范围是0-1。默认值为1。</p>
+
+		<h3>[property:Texture displacementMap]</h3>
+		<p> 位移贴图会影响网格顶点的位置,与仅影响材质的光照和阴影的其他贴图不同,移位的顶点可以投射阴影,阻挡其他对象,
+			以及充当真实的几何体。位移纹理是指:网格的所有顶点被映射为图像中每个像素的值(白色是最高的),并且被重定位。
+		</p>
+
+		<h3>[property:Float displacementScale]</h3>
+		<p> 位移贴图对网格的影响程度(黑色是无位移,白色是最大位移)。如果没有设置位移贴图,则不会应用此值。默认值为1。
+		</p>
+
+		<h3>[property:Float displacementBias]</h3>
+		<p>
+			位移贴图在网格顶点上的偏移量。如果没有设置位移贴图,则不会应用此值。默认值为0。
+		</p>
+
 		<h3>[property:Boolean fog]</h3>
 		<p>材质是否受雾影响。默认值为*false*。</p>
 
@@ -54,9 +75,29 @@
 		<h3>[property:Boolean lights]</h3>
 		<p>材质是否受到光照的影响。默认值为 *false*。</p>
 
-		<h3>[property:boolean morphTargets]</h3>
+		<h3>[property:boolean morphNormals]</h3>
+		<p> 定义是否使用morphNormals。设置为true可将morphNormal属性从[page:Geometry]传递到shader。默认值为*false*。
+		</p>
+
+		<h3>[property:Boolean morphTargets]</h3>
 		<p>定义材质是否使用morphTargets。默认值为false。</p>
 
+		<h3>[property:Texture normalMap]</h3>
+		<p> 用于创建法线贴图的纹理。RGB值会影响每个像素片段的曲面法线,并更改颜色照亮的方式。法线贴图不会改变曲面的实际形状,只会改变光照。
+		</p>
+
+		<h3>[property:Integer normalMapType]</h3>
+		<p> 法线贴图的类型。<br /><br />
+			选项为[page:constant THREE.TangentSpaceNormalMap](默认)和[page:constant THREE.ObjectSpaceNormalMap]。
+		</p>
+
+		<h3>[property:Vector2 normalScale]</h3>
+		<p> 法线贴图对材质的影响程度。典型范围是0-1。默认值是[page:Vector2]设置为(1,1)。
+		</p>
+
+		<h3>[property:Boolean skinning]</h3>
+		<p>材质是否使用蒙皮。默认值为false。</p>
+
 		<h3>[property:boolean wireframe]</h3>
 		<p>
 			将几何体渲染为线框。默认值为*false*(即渲染为平滑着色)。

+ 3 - 3
docs/api/zh/math/Matrix3.html

@@ -53,7 +53,7 @@ m.elements = [ 11, 21, 31,
 
 		<h2>属性(Properties)</h2>
 
-		<h3>[property:Float32Array elements]</h3>
+		<h3>[property:Array elements]</h3>
 		<p>
 			矩阵列优先[link:https://en.wikipedia.org/wiki/Row-_and_column-major_order column-major]列表。
 		</p>
@@ -61,7 +61,7 @@ m.elements = [ 11, 21, 31,
 		<h3>[property:Boolean isMatrix3]</h3>
 		<p>
 				用于判定此对象或者此类的派生对象是否是三维矩阵。默认值为 *true*。<br /><br />
-			
+
 				不应该改变该值,因为它在内部用于优化。
 		</p>
 
@@ -103,7 +103,7 @@ m.elements = [ 11, 21, 31,
 		<p>
 		[page:Matrix3 m] - 取逆的矩阵。<br />
 		[page:Boolean throwOnDegenerate] - (optional) 如果设置为true,如果矩阵是退化的(如果不可逆的话),则会抛出一个错误。<br /><br />
-		
+
 		使用逆矩阵计算方法[link:https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution analytic method],
 		将当前矩阵设置为给定矩阵的逆矩阵[link:https://en.wikipedia.org/wiki/Invertible_matrix inverse],如果[page:Boolean throwOnDegenerate]
 		参数没有设置且给定矩阵不可逆,那么将当前矩阵设置为3X3单位矩阵。

+ 5 - 5
docs/api/zh/math/Matrix4.html

@@ -83,7 +83,7 @@ m.elements = [ 11, 21, 31, 41,
 
 		<h2>属性(Properties)</h2>
 
-		<h3>[property:Float32Array elements]</h3>
+		<h3>[property:Array elements]</h3>
 		<p>
 		矩阵列优先[link:https://en.wikipedia.org/wiki/Row-_and_column-major_order column-major]列表。
 		</p>
@@ -91,7 +91,7 @@ m.elements = [ 11, 21, 31, 41,
 		<h3>[property:Boolean isMatrix4]</h3>
 		<p>
 			用于判定此对象或者此类的派生对象是否是三维矩阵。默认值为 *true*。<br /><br />
-		
+
 			不应该改变该值,因为它在内部用于优化。
 		</p>
 
@@ -168,7 +168,7 @@ zAxis = (c, g, k)
 		<p>
 			[page:Array array] - 用来存储设置元素数据的数组<br />
 			[page:Integer offset] - (可选参数) 数组的偏移量,默认值为 0。<br /><br />
-	
+
 			使用基于列优先格式[link:https://en.wikipedia.org/wiki/Row-_and_column-major_order#Column-major_order column-major]的数组来设置该矩阵。
 			</p>
 
@@ -176,7 +176,7 @@ zAxis = (c, g, k)
 		<p>
 			[page:Matrix3 m] - 取逆的矩阵。<br />
 			[page:Boolean throwOnDegenerate] - (optional) 如果设置为true,如果矩阵是退化的(如果不可逆的话),则会抛出一个错误。<br /><br />
-			
+
 			使用逆矩阵计算方法[link:https://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution analytic method],
 			将当前矩阵设置为给定矩阵的逆矩阵[link:https://en.wikipedia.org/wiki/Invertible_matrix inverse],如果[page:Boolean throwOnDegenerate]
 			参数没有设置且给定矩阵不可逆,那么将当前矩阵设置为3X3单位矩阵。
@@ -251,7 +251,7 @@ xAxis.z, yAxis.z, zAxis.z, 0,
 		<h3>[method:this makeRotationX]( [param:Float theta] )</h3>
 		<p>
 		[page:Float theta] — Rotation angle in radians.<br /><br />
-		
+
 		把该矩阵设置为绕x轴旋转弧度[page:Float theta] (&theta;)大小的矩阵。
 		结果如下:
 		<code>

+ 8 - 1
docs/api/zh/math/Quaternion.html

@@ -44,6 +44,13 @@
 
 		<h2>Properties</h2>
 
+		<h3>[property:Boolean isQuaternion]</h3>
+		<p>
+			Used to check whether this or derived classes are Quaternions. Default is *true*.<br /><br />
+
+			You should not change this, as it is used internally for optimisation.
+		</p>
+
 		<h3>[property:Float x]</h3>
 		<p>Changing this property will result in [page:.onChangeCallback onChangeCallback] being called.</p>
 
@@ -290,4 +297,4 @@ q.slerp( qb, t )
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
 	</body>
-</html>
+</html>

+ 1 - 1
docs/api/zh/objects/Mesh.html

@@ -91,7 +91,7 @@
 		<h3>[method:null raycast]( [param:Raycaster raycaster], [param:Array intersects] )</h3>
 		<p>
 			在一条投射出去的[page:Ray](射线)和这个网格之间产生交互。
-			[page:Raycaster.intersectObject]将会调用这个方法
+			[page:Raycaster.intersectObject]将会调用这个方法但是这个结果是未排序的
 		</p>
 
 		<h3>[method:null updateMorphTargets]()</h3>

+ 0 - 23
docs/api/zh/renderers/WebGLRenderer.html

@@ -254,12 +254,6 @@
 
 		<h2>方法</h2>
 
-		<h3>[method:Integer allocTextureUnit]</h3>
-		<p>
-		尝试分配纹理单元以供着色器使用。如果尝试分配超过GPU支持量的纹理单元,则会报警告。主要供内部使用。
-		请参阅[page:WebGLRenderer.capabilities capabilities.maxTextures]。
-		</p>
-
 		<h3>[method:null clear]( [param:Boolean color], [param:Boolean depth], [param:Boolean stencil] )</h3>
 		<p>
 		告诉渲染器清除颜色、深度或模板缓存.
@@ -412,23 +406,6 @@
 		将[page:Boolean updateStyle]设置为false以阻止对canvas的样式做任何改变。
 		</p>
 
-		<h3>[method:null setTexture2D]( [param:Texture texture], [param:number slot] )</h3>
-		<p>
-		texture -- 需被设置的[page:Texture texture]<br />
-		slot -- 纹理应该使用的插槽号<br /><br />
-        该方法为WebGL着色器将正确的纹理设置到正确的插槽中。插槽号可作为取样器的全局变量(uniform)<br /><br />
-
-		说明: 该方法取代了旧的[method:null setTexture]方法
-		</p>
-
-		<h3>[method:null setTextureCube]( [param:CubeTexture cubeTexture], [param:Number slot] )</h3>
-		<p>
-		texture -- 需要被设置的[page:CubeTexture cubeTexture]<br />
-		slot -- 纹理应该使用的插槽号<br /><br />
-
-        该方法为WebGL着色器将正确的纹理设置到正确的插槽中。插槽号可作为取样器的全局变量(uniform)
-		</p>
-
 		<h3>[method:null setViewport]( [param:Integer x], [param:Integer y], [param:Integer width], [param:Integer height] )</h3>
 		<p>将视口大小设置为(x, y)到 (x + width, y + height).</p>
 

+ 12 - 0
docs/api/zh/textures/Texture.html

@@ -54,6 +54,14 @@
 		并在视频播放时不断地更新这个纹理贴图。——[page:VideoTexture VideoTexture] 类会对此自动进行处理。
 		</p>
 
+		<h3>[property:Boolean isTexture]</h3>
+		<p>
+			用于测试这个类或者派生类是否为Texture,默认为*true*。<br /><br />
+
+			你不应当对这个属性进行改变,因为它在内部使用,以用于优化。
+		</p>
+
+
 		<h3>[property:array mipmaps]</h3>
 		<p>
 		用户所给定的mipmap数组(可选)。
@@ -180,11 +188,15 @@
 		<p>
 			默认为false,这是PNG图像的规范。
 			如果RGB值已被Alpha预乘,请将其设为true。
+			Note that this property has no effect for [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap].
+			You need to configure on bitmap creation instead. See [page:ImageBitmapLoader].
 		</p>
 
 		<h3>[property:boolean flipY]</h3>
 		<p>
 		默认为true。翻转图像的Y轴以匹配WebGL纹理坐标空间。
+		Note that this property has no effect for [link:https://developer.mozilla.org/de/docs/Web/API/ImageBitmap ImageBitmap].
+		You need to configure on bitmap creation instead. See [page:ImageBitmapLoader].
 		</p>
 
 		<h3>[property:number unpackAlignment]</h3>

+ 1 - 0
docs/examples/exporters/GLTFExporter.html

@@ -97,6 +97,7 @@
 			<li>animations - Array<[page:AnimationClip AnimationClip]>. List of animations to be included in the export.</li>
 			<li>forceIndices - bool. Generate indices for non-index geometry and export with them. Default is false.</li>
 			<li>forcePowerOfTwoTextures - bool. Export with images resized to POT size. This option works only if embedImages is true. Default is false.</li>
+			<li>includeCustomExtensions - bool. Export custom glTF extensions defined on an object's <em>userData.gltfExtensions</em> property. Default is false.</li>
 		</ul>
 		</p>
 		<p>

+ 145 - 0
docs/examples/loaders/DRACOLoader.html

@@ -0,0 +1,145 @@
+<!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:Loader] &rarr;
+		<h1>[name]</h1>
+
+		<p class="desc">
+			A loader for geometry compressed with the Draco library. <br /><br />
+			[link:https://google.github.io/draco/ Draco] is an open source library for compressing and
+			decompressing 3D meshes and point clouds. Compressed geometry can be significantly smaller,
+			at the cost of additional decoding time on the client device.
+		</p>
+
+		<p>
+			Standalone Draco files have a <em>.drc</em> extension, and contain vertex positions,
+			normals, colors, and other attributes. Draco files <em>do not</em> contain materials,
+			textures, animation, or node hierarchies – to use these features, embed Draco geometry
+			inside of a glTF file. A normal glTF file can be converted to a Draco-compressed glTF file
+			using [link:https://github.com/AnalyticalGraphicsInc/gltf-pipeline glTF-Pipeline]. When
+			using Draco with glTF, an instance of DRACOLoader will be used internally by [page:GLTFLoader].
+		</p>
+
+		<h2>Example</h2>
+
+		<code>
+		// Instantiate a loader
+		var loader = new THREE.DRACOLoader();
+
+		// Specify path to a folder containing WASM/JS decoding libraries.
+		THREE.DRACOLoader.setDecoderPath( '/examples/js/libs/draco' );
+
+		// Optional: Pre-fetch Draco WASM/JS module.
+		THREE.DRACOLoader.getDecoderModule();
+
+		// Load a Draco geometry
+		loader.load(
+			// resource URL
+			'model.drc',
+			// called when the resource is loaded
+			function ( geometry ) {
+
+				var material = new THREE.MeshStandardMaterial( { color: 0x606060 } );
+				var mesh = new THREE.Mesh( geometry, material );
+				scene.add( mesh );
+
+			},
+			// called as loading progresses
+			function ( xhr ) {
+
+				console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
+
+			},
+			// called when loading has errors
+			function ( error ) {
+
+				console.log( 'An error happened' );
+
+			}
+		);
+		</code>
+
+		[example:webgl_loader_draco]
+
+		<h2>Browser compatibility</h2>
+
+		<p>DRACOLoader relies on ES6 [link:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise Promises],
+		which are not supported in IE11. To use the loader in IE11, you must
+		[link:https://github.com/stefanpenner/es6-promise include a polyfill]
+		providing a Promise replacement. DRACOLoader will automatically use
+		either the JS or the WASM decoding library, based on browser
+		capabilities.</p>
+
+		<br>
+		<hr>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [param:LoadingManager manager] )</h3>
+		<p>
+		[page:LoadingManager manager] — The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].
+		</p>
+		<p>
+		Creates a new [name].
+		</p>
+
+		<h2>Static Methods</h2>
+
+		<h3>[method:null setDecoderPath]( [param:String value] )</h3>
+		<p>
+		[page:String value] — Path to folder containing the JS and WASM decoder libraries.
+		</p>
+
+		<h3>[method:null setDecoderConfig]( [param:Object config] )</h3>
+		<p>
+			[page:String config.type] - (Optional) <em>"js"</em> or <em>"wasm"</em>.<br />
+		</p>
+		<p>
+		Provides configuration for the decoder libraries. Configuration cannot be changed
+		after loading the decoders.
+		</p>
+
+		<h3>[method:Promise getDecoderModule]()</h3>
+		<p>
+		Requests the decoder libraries, if not already loaded.
+		</p>
+
+		<h3>[method:null releaseDecoderModule]()</h3>
+		<p>
+		Disposes of the decoder library and deallocates memory. The decoder
+		[link:https://github.com/google/draco/issues/349 cannot be reloaded afterward].
+		</p>
+
+		<h2>Methods</h2>
+
+		<h3>[method:null load]( [param:String url], [param:Function onLoad], [param:Function onProgress], [param:Function onError] )</h3>
+		<p>
+		[page:String url] — A string containing the path/URL of the <em>.drc</em> file.<br />
+		[page:Function onLoad] — A function to be called after the loading is successfully completed.<br />
+		[page:Function onProgress] — (optional) A function to be called while the loading is in progress. The argument will be the XMLHttpRequest instance, that contains .[page:Integer total] and .[page:Integer loaded] bytes.<br />
+		[page:Function onError] — (optional) A function to be called if an error occurs during loading. The function receives error as an argument.<br />
+		</p>
+		<p>
+		Begin loading from url and call the <em>onLoad</em> function with the decompressed geometry.
+		</p>
+
+		<h3>[method:DRACOLoader setPath]( [param:String path] )</h3>
+		<p>
+		[page:String path] — Base path.
+		</p>
+		<p>
+		Set the base path for the <em>.drc</em> file.
+		</p>
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/DRACOLoader.js examples/js/loaders/DRACOLoader.js]
+	</body>
+</html>

+ 3 - 0
docs/examples/loaders/GLTFLoader.html

@@ -58,6 +58,9 @@
 		// Optional: Provide a DRACOLoader instance to decode compressed mesh data
 		THREE.DRACOLoader.setDecoderPath( '/examples/js/libs/draco' );
 		loader.setDRACOLoader( new THREE.DRACOLoader() );
+			
+		// Optional: Pre-fetch Draco WASM/JS module, to save time while parsing.
+		THREE.DRACOLoader.getDecoderModule();
 
 		// Load a glTF resource
 		loader.load(

+ 1 - 1
docs/examples/loaders/OBJLoader2.html

@@ -52,7 +52,7 @@
 
 		<h2>Methods</h2>
 
-		<h3>[method:Object3D parse]( {[param:arraybuffer content]|[param:String content]] )</h3>
+		<h3>[method:Object3D parse]( [param:arraybuffer content]|[param:String content] )</h3>
 		<p>
 			[[page:arraybuffer content]|[page:String content]] OBJ data as Uint8Array or String
 		</p>

+ 2 - 1
docs/examples/loaders/SVGLoader.html

@@ -26,8 +26,9 @@
 			// resource URL
 			'data/svgSample.svg',
 			// called when the resource is loaded
-			function ( paths ) {
+			function ( data ) {
 
+				var paths = data.paths;
 				var group = new THREE.Group();
 
 				for ( var i = 0; i < paths.length; i ++ ) {

+ 2 - 3
docs/examples/objects/Lensflare.html

@@ -44,13 +44,12 @@ light.add( lensflare );
 		<h2>Constructor</h2>
 
 
-		<h3>LensflareElement( [param:Texture texture], [param:Float size], [param:Float distance], [param:Color color], [param:Materials blending] )</h3>
+		<h3>LensflareElement( [param:Texture texture], [param:Float size], [param:Float distance], [param:Color color] )</h3>
 		<p>
 		[page:Texture texture] - THREE.Texture to use for the flare. <br />
 		[page:Float size] - (optional) size in pixels <br />
 		[page:Float distance] - (optional) (0-1) from light source (0 = at light source) <br />
-		[page:Color color] - (optional) the [page:Color] of the lens flare<br />
-		[page:Materials blending] - (optional) [page:Materials Blending Mode] - Defaults to THREE.NormalBlending
+		[page:Color color] - (optional) the [page:Color] of the lens flare
 		</p>
 
 		<h2>Properties</h2>

+ 60 - 0
docs/examples/utils/SkeletonUtils.html

@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		<h1>[name]</h1>
+
+		<p class="desc">Utility functions for [page:Skeleton], [page:SkinnedMesh], and [page:Bone] manipulation.</p>
+
+
+		<h2>Methods</h2>
+
+		<h3>[method:Object3D clone]( [param:Object3D object] )</h3>
+		<p>
+			Clones the given object and its descendants, ensuring that any [page:SkinnedMesh] instances
+			are correctly associated with their bones. Bones are also cloned, and must be descendants of
+			the object passed to this method. Other data, like geometries and materials, are reused by
+			reference.
+		</p>
+
+		<h3>[method:Object findBoneTrackData]( [param:String name], [param:Array tracks] )</h3>
+		<p></p>
+
+		<h3>[method:Bone getBoneByName]( [param:String name], [param:Skeleton skeleton] )</h3>
+		<p></p>
+
+		<h3>[method:Array getBones]( [param:Skeleton skeleton] )</h3>
+		<p></p>
+
+		<h3>[method:Array getEqualsBonesNames]( [param:Skeleton skeleton], [param:Skeleton targetSkeleton] )</h3>
+		<p></p>
+
+		<h3>[method:SkeletonHelper getHelperFromSkeleton]( [param:Skeleton skeleton] )</h3>
+		<p></p>
+
+		<h3>[method:Bone getNearestBone]( [param:Bone bone], [param:Array names] )</h3>
+		<p></p>
+
+		<h3>[method:Object getSkeletonOffsets]( [param:SkeletonHelper target], [param:SkeletonHelper source], [param:Object options] )</h3>
+		<p></p>
+
+		<h3>[method:this renameBones]( [param:Skeleton skeleton], [param:Array names] )</h3>
+		<p></p>
+
+		<h3>[method:null retarget]( [param:SkeletonHelper target], [param:SkeletonHelper source], [param:Object options] )</h3>
+		<p></p>
+
+		<h3>[method:AnimationClip retargetClip]( [param:SkeletonHelper target], [param:SkeletonHelper source], [param:AnimationClip clip], [param:Object options] )</h3>
+		<p></p>
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/utils/SkeletonUtils.js examples/js/utils/SkeletonUtils.js]
+	</body>
+</html>

+ 9 - 2
docs/list.js

@@ -253,7 +253,9 @@ var list = {
 				"Material": "api/en/materials/Material",
 				"MeshBasicMaterial": "api/en/materials/MeshBasicMaterial",
 				"MeshDepthMaterial": "api/en/materials/MeshDepthMaterial",
+				"MeshDistanceMaterial": "api/en/materials/MeshDistanceMaterial",
 				"MeshLambertMaterial": "api/en/materials/MeshLambertMaterial",
+				"MeshMatcapMaterial": "api/en/materials/MeshMatcapMaterial",
 				"MeshNormalMaterial": "api/en/materials/MeshNormalMaterial",
 				"MeshPhongMaterial": "api/en/materials/MeshPhongMaterial",
 				"MeshPhysicalMaterial": "api/en/materials/MeshPhysicalMaterial",
@@ -363,6 +365,7 @@ var list = {
 
 			"Loaders": {
 				"BabylonLoader": "examples/loaders/BabylonLoader",
+				"DRACOLoader": "examples/loaders/DRACOLoader",
 				"GLTFLoader": "examples/loaders/GLTFLoader",
 				"MMDLoader": "examples/loaders/MMDLoader",
 				"MTLLoader": "examples/loaders/MTLLoader",
@@ -382,7 +385,8 @@ var list = {
 
 			"Exporters": {
 				"GLTFExporter": "examples/exporters/GLTFExporter",
-				"PLYExporter": "examples/exporters/PLYExporter"
+				"PLYExporter": "examples/exporters/PLYExporter",
+				"ColladaExporter": "examples/exporters/ColladaExporter"
 			},
 
 			"Plugins": {
@@ -406,7 +410,8 @@ var list = {
 
 			"Utils": {
 				"BufferGeometryUtils": "examples/utils/BufferGeometryUtils",
-				"SceneUtils": "examples/utils/SceneUtils"
+				"SceneUtils": "examples/utils/SceneUtils",
+				"SkeletonUtils": "examples/utils/SkeletonUtils"
 			}
 
 		},
@@ -680,7 +685,9 @@ var list = {
 				"Material": "api/zh/materials/Material",
 				"MeshBasicMaterial": "api/zh/materials/MeshBasicMaterial",
 				"MeshDepthMaterial": "api/zh/materials/MeshDepthMaterial",
+				"MeshDistanceMaterial": "api/zh/materials/MeshDistanceMaterial",
 				"MeshLambertMaterial": "api/zh/materials/MeshLambertMaterial",
+				"MeshMatcapMaterial": "api/zh/materials/MeshMatcapMaterial",
 				"MeshNormalMaterial": "api/zh/materials/MeshNormalMaterial",
 				"MeshPhongMaterial": "api/zh/materials/MeshPhongMaterial",
 				"MeshPhysicalMaterial": "api/zh/materials/MeshPhysicalMaterial",

+ 8 - 1
docs/manual/en/introduction/How-to-dispose-of-objects.html

@@ -54,6 +54,13 @@
 		for realizing custom rendering destinations. These objects are only deallocated by executing [page:WebGLRenderTarget.dispose]().
 	</p>
 
+	<h2>Scenes</h2>
+
+	<p>
+		The renderer maintains for scenes special data structures for sorting and rendering. If for some reasons a scene object becomes obsolete in an application,
+		call [page:Scene.dispose]() in order to free these resources.
+	</p>
+
 	<h2>Miscellaneous</h2>
 
 	<p>
@@ -91,7 +98,7 @@
 		nothing happens. No resources were allocated so there is also no need for clean up.
 	</p>
 
-	<h3>Why happens when you call *dispose()* on a texture but the image is not loaded yet?</h3>
+	<h3>What happens when you call *dispose()* on a texture but the image is not loaded yet?</h3>
 
 	<p>
 		Internal resources for a texture are only allocated if the image has fully loaded. If you dispose a texture before the image was loaded,

+ 1 - 0
docs/manual/en/introduction/Loading-3D-models.html

@@ -63,6 +63,7 @@
 		<li><a href="https://www.foundry.com/products/modo" target="_blank" rel="noopener">Modo</a> by Foundry</li>
 		<li><a href="https://www.marmoset.co/toolbag/" target="_blank" rel="noopener">Toolbag</a> by Marmoset</li>
 		<li><a href="https://www.sidefx.com/products/houdini/" target="_blank" rel="noopener">Houdini</a> by SideFX</li>
+		<li><a href="https://labs.maxon.net/?p=3360" target="_blank" rel="noopener">Cinema 4D</a> by MAXON</li>
 		<li>&hellip;and <a href="https://github.com/khronosgroup/gltf#gltf-tools" target="_blank" rel="noopener">many more</a></li>
 	</ul>
 

+ 7 - 7
docs/manual/en/introduction/Matrix-transformations.html

@@ -22,25 +22,25 @@
 				Modify the object's *position*, *quaternion*, and *scale* properties, and let three.js recompute
 				the object's matrix from these properties:
 				<code>
-				object.position.copy(start_position);
-				object.quaternion.copy(quaternion);
+object.position.copy( start_position );
+object.quaternion.copy( quaternion );
 				</code>
 				By default, the *matrixAutoUpdate* property is set true, and the matrix will be automatically recalculated.
 				If the object is static, or you wish to manually control when recalculation occurs, better performance can be obtained by setting the property false:
 				<code>
-				object.matrixAutoUpdate = false;
+object.matrixAutoUpdate = false;
 				</code>
 				And after changing any properties, manually update the matrix:
 				<code>
-				object.updateMatrix();
+object.updateMatrix();
 				</code>
 			</li>
 			<li>
 				Modify the object's matrix directly. The [page:Matrix4] class has various methods for modifying the matrix:
 				<code>
-				object.matrix.setRotationFromQuaternion(quaternion);
-				object.matrix.setPosition(start_position);
-				object.matrixAutoUpdate = false;
+object.matrix.setRotationFromQuaternion( quaternion );
+object.matrix.setPosition( start_position );
+object.matrixAutoUpdate = false;
 				</code>
 				Note that *matrixAutoUpdate* <em>must</em> be set to *false* in this case, and you should make sure <em>not</em> to call *updateMatrix*. Calling *updateMatrix* will clobber the manual changes made to the matrix, recalculating the matrix from *position*, *scale*, and so on.
 			</li>

+ 7 - 7
docs/manual/zh/introduction/Matrix-transformations.html

@@ -22,25 +22,25 @@
 			<li>
 				修改对象的*position*,*quaternion*和*scale*属性,让three.js重新计算来自这些属性的对象矩阵:
 				<code>
-				object.position.copy(start_position);
-				object.quaternion.copy(quaternion);
+object.position.copy( start_position );
+object.quaternion.copy( quaternion );
 				</code>
 				默认情况下,*matrixAutoUpdate*属性设置为true,并且将自动重新计算矩阵。
 如果对象是静态的,或者您希望在重新计算时手动控制,则可以通过将属性设置为false来获得更好的性能:
 				<code>
-				object.matrixAutoUpdate = false;
+object.matrixAutoUpdate = false;
 				</code>
 				更改任何属性后,手动更新矩阵:
 				<code>
-				object.updateMatrix();
+object.updateMatrix();
 				</code>
 			</li>
 			<li>
 				直接修改对象的矩阵。 [page:Matrix4]类有各种修改矩阵的方法:
 				<code>
-				object.matrix.setRotationFromQuaternion(quaternion);
-				object.matrix.setPosition(start_position);
-				object.matrixAutoUpdate = false;
+object.matrix.setRotationFromQuaternion( quaternion );
+object.matrix.setPosition( start_position );
+object.matrixAutoUpdate = false;
 				</code>
 				请注意,在这种情况下,*matrixAutoUpdate* <em> 必须 </em>设置为*false*,并且您应该确保<em> 不 </em>调用*updateMatrix*。
 				调用*updateMatrix*将破坏对矩阵所做的手动更改,从*position*,*scale*重新计算矩阵,依此类推。

+ 97 - 47
docs/scenes/js/material.js

@@ -87,6 +87,9 @@ function getObjectsKeys( obj ) {
 
 }
 
+var textureLoader = new THREE.TextureLoader();
+var cubeTextureLoader = new THREE.CubeTextureLoader();
+
 var envMaps = ( function () {
 
 	var path = '../../examples/textures/cube/SwedishRoyalCastle/';
@@ -97,10 +100,10 @@ var envMaps = ( function () {
 		path + 'pz' + format, path + 'nz' + format
 	];
 
-	var reflectionCube = new THREE.CubeTextureLoader().load( urls );
+	var reflectionCube = cubeTextureLoader.load( urls );
 	reflectionCube.format = THREE.RGBFormat;
 
-	var refractionCube = new THREE.CubeTextureLoader().load( urls );
+	var refractionCube = cubeTextureLoader.load( urls );
 	refractionCube.mapping = THREE.CubeRefractionMapping;
 	refractionCube.format = THREE.RGBFormat;
 
@@ -112,18 +115,47 @@ var envMaps = ( function () {
 
 } )();
 
-var envMapKeys = getObjectsKeys( envMaps );
+var diffuseMaps = ( function () {
+
+	var bricks = textureLoader.load( '../../examples/textures/brick_diffuse.jpg' );
+	bricks.wrapS = THREE.RepeatWrapping;
+	bricks.wrapT = THREE.RepeatWrapping;
+	bricks.repeat.set( 9, 1 );
+
+	return {
+		none: null,
+		bricks: bricks
+	};
+
+} )();
+
+var matcaps = ( function () {
 
-var textureMaps = ( function () {
+	return {
+		none: null,
+		porcelainWhite: textureLoader.load( '../../examples/textures/matcaps/matcap-porcelain-white.jpg' )
+	};
+
+} )();
+
+var alphaMaps = ( function () {
+
+	var fibers = textureLoader.load( '../../examples/textures/alphaMap.jpg' );
+	fibers.wrapT = THREE.RepeatWrapping;
+	fibers.wrapS = THREE.RepeatWrapping;
+	fibers.repeat.set( 9, 1 );
 
 	return {
 		none: null,
-		grass: new THREE.TextureLoader().load( '../../examples/textures/terrain/grasslight-thin.jpg' )
+		fibers: fibers
 	};
 
 } )();
 
-var textureMapKeys = getObjectsKeys( textureMaps );
+var envMapKeys = getObjectsKeys( envMaps );
+var diffuseMapKeys = getObjectsKeys( diffuseMaps );
+var matcapKeys = getObjectsKeys( matcaps );
+var alphaMapKeys = getObjectsKeys( alphaMaps );
 
 function generateVertexColors( geometry ) {
 
@@ -247,7 +279,7 @@ function guiMaterial( gui, mesh, material, geometry ) {
 	var folder = gui.addFolder( 'THREE.Material' );
 
 	folder.add( material, 'transparent' );
-	folder.add( material, 'opacity', 0, 1 );
+	folder.add( material, 'opacity', 0, 1 ).step( 0.01 );
 	// folder.add( material, 'blending', constants.blendingMode );
 	// folder.add( material, 'blendSrc', constants.destinationFactors );
 	// folder.add( material, 'blendDst', constants.destinationFactors );
@@ -257,7 +289,7 @@ function guiMaterial( gui, mesh, material, geometry ) {
 	// folder.add( material, 'polygonOffset' );
 	// folder.add( material, 'polygonOffsetFactor' );
 	// folder.add( material, 'polygonOffsetUnits' );
-	folder.add( material, 'alphaTest', 0, 1 );
+	folder.add( material, 'alphaTest', 0, 1 ).step( 0.01 ).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'visible' );
 	folder.add( material, 'side', constants.side ).onChange( needsUpdate( material, geometry ) );
 
@@ -267,10 +299,9 @@ function guiMeshBasicMaterial( gui, mesh, material, geometry ) {
 
 	var data = {
 		color: material.color.getHex(),
-		envMaps: envMapKeys,
-		map: textureMapKeys,
-		specularMap: textureMapKeys,
-		alphaMap: textureMapKeys
+		envMaps: envMapKeys[ 0 ],
+		map: diffuseMapKeys[ 0 ],
+		alphaMap: alphaMapKeys[ 0 ]
 	};
 
 	var folder = gui.addFolder( 'THREE.MeshBasicMaterial' );
@@ -282,9 +313,8 @@ function guiMeshBasicMaterial( gui, mesh, material, geometry ) {
 	folder.add( material, 'fog' );
 
 	folder.add( data, 'envMaps', envMapKeys ).onChange( updateTexture( material, 'envMap', envMaps ) );
-	folder.add( data, 'map', textureMapKeys ).onChange( updateTexture( material, 'map', textureMaps ) );
-	folder.add( data, 'specularMap', textureMapKeys ).onChange( updateTexture( material, 'specularMap', textureMaps ) );
-	folder.add( data, 'alphaMap', textureMapKeys ).onChange( updateTexture( material, 'alphaMap', textureMaps ) );
+	folder.add( data, 'map', diffuseMapKeys ).onChange( updateTexture( material, 'map', diffuseMaps ) );
+	folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
 	folder.add( material, 'combine', constants.combine );
 	folder.add( material, 'reflectivity', 0, 1 );
 	folder.add( material, 'refractionRatio', 0, 1 );
@@ -293,11 +323,17 @@ function guiMeshBasicMaterial( gui, mesh, material, geometry ) {
 
 function guiMeshDepthMaterial( gui, mesh, material, geometry ) {
 
+	var data = {
+		alphaMap: alphaMapKeys[ 0 ]
+	};
+
 	var folder = gui.addFolder( 'THREE.MeshDepthMaterial' );
 
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 
+	folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
+
 }
 
 function guiMeshNormalMaterial( gui, mesh, material, geometry ) {
@@ -332,10 +368,9 @@ function guiMeshLambertMaterial( gui, mesh, material, geometry ) {
 	var data = {
 		color: material.color.getHex(),
 		emissive: material.emissive.getHex(),
-		envMaps: envMapKeys,
-		map: textureMapKeys,
-		specularMap: textureMapKeys,
-		alphaMap: textureMapKeys
+		envMaps: envMapKeys[ 0 ],
+		map: diffuseMapKeys[ 0 ],
+		alphaMap: alphaMapKeys[ 0 ]
 	};
 
 	var folder = gui.addFolder( 'THREE.MeshLambertMaterial' );
@@ -349,26 +384,39 @@ function guiMeshLambertMaterial( gui, mesh, material, geometry ) {
 	folder.add( material, 'fog' );
 
 	folder.add( data, 'envMaps', envMapKeys ).onChange( updateTexture( material, 'envMap', envMaps ) );
-	folder.add( data, 'map', textureMapKeys ).onChange( updateTexture( material, 'map', textureMaps ) );
-	folder.add( data, 'specularMap', textureMapKeys ).onChange( updateTexture( material, 'specularMap', textureMaps ) );
-	folder.add( data, 'alphaMap', textureMapKeys ).onChange( updateTexture( material, 'alphaMap', textureMaps ) );
+	folder.add( data, 'map', diffuseMapKeys ).onChange( updateTexture( material, 'map', diffuseMaps ) );
+	folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
 	folder.add( material, 'combine', constants.combine );
 	folder.add( material, 'reflectivity', 0, 1 );
 	folder.add( material, 'refractionRatio', 0, 1 );
 
 }
 
+function guiMeshMatcapMaterial( gui, mesh, material ) {
+
+	var data = {
+		color: material.color.getHex(),
+		matcap: matcapKeys[ 1 ],
+		alphaMap: alphaMapKeys[ 0 ]
+	};
+
+	var folder = gui.addFolder( 'THREE.MeshMatcapMaterial' );
+
+	folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
+	folder.add( data, 'matcap', matcapKeys ).onChange( updateTexture( material, 'matcap', matcaps ) );
+	folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
+
+}
+
 function guiMeshPhongMaterial( gui, mesh, material, geometry ) {
 
 	var data = {
 		color: material.color.getHex(),
 		emissive: material.emissive.getHex(),
 		specular: material.specular.getHex(),
-		envMaps: envMapKeys,
-		map: textureMapKeys,
-		lightMap: textureMapKeys,
-		specularMap: textureMapKeys,
-		alphaMap: textureMapKeys
+		envMaps: envMapKeys[ 0 ],
+		map: diffuseMapKeys[ 0 ],
+		alphaMap: alphaMapKeys[ 0 ]
 	};
 
 	var folder = gui.addFolder( 'THREE.MeshPhongMaterial' );
@@ -384,10 +432,8 @@ function guiMeshPhongMaterial( gui, mesh, material, geometry ) {
 	folder.add( material, 'vertexColors', constants.colors ).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'fog' );
 	folder.add( data, 'envMaps', envMapKeys ).onChange( updateTexture( material, 'envMap', envMaps ) );
-	folder.add( data, 'map', textureMapKeys ).onChange( updateTexture( material, 'map', textureMaps ) );
-	folder.add( data, 'lightMap', textureMapKeys ).onChange( updateTexture( material, 'lightMap', textureMaps ) );
-	folder.add( data, 'specularMap', textureMapKeys ).onChange( updateTexture( material, 'specularMap', textureMaps ) );
-	folder.add( data, 'alphaMap', textureMapKeys ).onChange( updateTexture( material, 'alphaMap', textureMaps ) );
+	folder.add( data, 'map', diffuseMapKeys ).onChange( updateTexture( material, 'map', diffuseMaps ) );
+	folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
 
 }
 
@@ -396,11 +442,9 @@ function guiMeshStandardMaterial( gui, mesh, material, geometry ) {
 	var data = {
 		color: material.color.getHex(),
 		emissive: material.emissive.getHex(),
-		envMaps: envMapKeys,
-		map: textureMapKeys,
-		lightMap: textureMapKeys,
-		specularMap: textureMapKeys,
-		alphaMap: textureMapKeys
+		envMaps: envMapKeys[ 0 ],
+		map: diffuseMapKeys[ 0 ],
+		alphaMap: alphaMapKeys[ 0 ]
 	};
 
 	var folder = gui.addFolder( 'THREE.MeshStandardMaterial' );
@@ -416,9 +460,8 @@ function guiMeshStandardMaterial( gui, mesh, material, geometry ) {
 	folder.add( material, 'vertexColors', constants.colors ).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'fog' );
 	folder.add( data, 'envMaps', envMapKeys ).onChange( updateTexture( material, 'envMap', envMaps ) );
-	folder.add( data, 'map', textureMapKeys ).onChange( updateTexture( material, 'map', textureMaps ) );
-	folder.add( data, 'lightMap', textureMapKeys ).onChange( updateTexture( material, 'lightMap', textureMaps ) );
-	folder.add( data, 'alphaMap', textureMapKeys ).onChange( updateTexture( material, 'alphaMap', textureMaps ) );
+	folder.add( data, 'map', diffuseMapKeys ).onChange( updateTexture( material, 'map', diffuseMaps ) );
+	folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
 
 	// TODO roughnessMap and metalnessMap
 
@@ -429,11 +472,9 @@ function guiMeshPhysicalMaterial( gui, mesh, material, geometry ) {
 	var data = {
 		color: material.color.getHex(),
 		emissive: material.emissive.getHex(),
-		envMaps: envMapKeys,
-		map: textureMapKeys,
-		lightMap: textureMapKeys,
-		specularMap: textureMapKeys,
-		alphaMap: textureMapKeys
+		envMaps: envMapKeys[ 0 ],
+		map: diffuseMapKeys[ 0 ],
+		alphaMap: alphaMapKeys[ 0 ]
 	};
 
 	var folder = gui.addFolder( 'THREE.MeshPhysicalMaterial' );
@@ -452,9 +493,8 @@ function guiMeshPhysicalMaterial( gui, mesh, material, geometry ) {
 	folder.add( material, 'vertexColors', constants.colors ).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'fog' );
 	folder.add( data, 'envMaps', envMapKeys ).onChange( updateTexture( material, 'envMap', envMaps ) );
-	folder.add( data, 'map', textureMapKeys ).onChange( updateTexture( material, 'map', textureMaps ) );
-	folder.add( data, 'lightMap', textureMapKeys ).onChange( updateTexture( material, 'lightMap', textureMaps ) );
-	folder.add( data, 'alphaMap', textureMapKeys ).onChange( updateTexture( material, 'alphaMap', textureMaps ) );
+	folder.add( data, 'map', diffuseMapKeys ).onChange( updateTexture( material, 'map', diffuseMaps ) );
+	folder.add( data, 'alphaMap', alphaMapKeys ).onChange( updateTexture( material, 'alphaMap', alphaMaps ) );
 
 	// TODO roughnessMap and metalnessMap
 
@@ -487,6 +527,16 @@ function chooseFromHash( gui, mesh, geometry ) {
 
 			break;
 
+		case 'MeshMatcapMaterial' :
+
+			material = new THREE.MeshMatcapMaterial( { matcap: matcaps.porcelainWhite } );
+			guiMaterial( gui, mesh, material, geometry );
+			guiMeshMatcapMaterial( gui, mesh, material, geometry );
+
+			return material;
+
+			break;
+
 		case 'MeshPhongMaterial' :
 
 			material = new THREE.MeshPhongMaterial( { color: 0x2194CE } );

+ 48 - 0
editor/css/dark.css

@@ -250,3 +250,51 @@ select {
 	.Outliner .option.active {
 		background-color: rgba(21,60,94,1);
 	}
+
+/* */
+
+@media all and ( max-width: 600px ) {
+
+	#menubar .menu .options {
+		max-height: calc(100% - 372px);
+	}
+
+	#menubar .menu.right {
+		display: none;
+	}
+
+	#viewport {
+		left: 0;
+		right: 0;
+		top: 32px;
+		height: calc(100% - 352px);
+	}
+
+	#script {
+		left: 0;
+		right: 0;
+		top: 32px;
+		height: calc(100% - 352px);
+	}
+
+	#player {
+		left: 0;
+		right: 0;
+		top: 32px;
+		height: calc(100% - 352px);
+	}
+
+	#sidebar {
+		left: 0;
+		width: 100%;
+		top: calc(100% - 320px);
+		bottom: 0;
+	}
+
+	#toolbar {
+		left: calc(50% - 140px);
+		width: 280px;
+		top: 68px;
+	}
+
+}

+ 48 - 0
editor/css/light.css

@@ -243,3 +243,51 @@ select {
 	.Outliner .option.active {
 		background-color: rgba(0,0,0,0.04);
 	}
+
+/* */
+
+@media all and ( max-width: 600px ) {
+
+	#menubar .menu .options {
+		max-height: calc(100% - 372px);
+	}
+
+	#menubar .menu.right {
+		display: none;
+	}
+
+	#viewport {
+		left: 0;
+		right: 0;
+		top: 32px;
+		height: calc(100% - 352px);
+	}
+
+	#script {
+		left: 0;
+		right: 0;
+		top: 32px;
+		height: calc(100% - 352px);
+	}
+
+	#player {
+		left: 0;
+		right: 0;
+		top: 32px;
+		height: calc(100% - 352px);
+	}
+
+	#sidebar {
+		left: 0;
+		width: 100%;
+		top: calc(100% - 320px);
+		bottom: 0;
+	}
+
+	#toolbar {
+		left: calc(50% - 140px);
+		width: 280px;
+		top: 68px;
+	}
+
+}

+ 0 - 2
editor/examples/arkanoid.app.json

@@ -3,8 +3,6 @@
 		"type": "App"
 	},
 	"project": {
-		"gammaInput": true,
-		"gammaOutput": true,
 		"shadows": true,
 		"vr": false
 	},

+ 0 - 2
editor/examples/camera.app.json

@@ -3,8 +3,6 @@
 		"type": "App"
 	},
 	"project": {
-		"gammaInput": true,
-		"gammaOutput": true,
 		"shadows": true,
 		"vr": false
 	},

+ 0 - 2
editor/examples/particles.app.json

@@ -3,8 +3,6 @@
 		"type": "App"
 	},
 	"project": {
-		"gammaInput": true,
-		"gammaOutput": true,
 		"shadows": true,
 		"vr": false
 	},

+ 0 - 2
editor/examples/pong.app.json

@@ -3,8 +3,6 @@
 		"type": "App"
 	},
 	"project": {
-		"gammaInput": true,
-		"gammaOutput": true,
 		"shadows": true,
 		"vr": false
 	},

+ 0 - 2
editor/examples/shaders.app.json

@@ -3,8 +3,6 @@
 		"type": "App"
 	},
 	"project": {
-		"gammaInput": true,
-		"gammaOutput": true,
 		"shadows": true,
 		"vr": false
 	},

BIN
editor/images/icon.png


BIN
editor/images/icon.xcf


+ 24 - 18
editor/index.html

@@ -4,12 +4,12 @@
 		<title>three.js / editor</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<!-- Origin Trial Token, feature = WebXR Device API (For Chrome M69+), origin = https://threejs.org, expires = 2019-03-06 -->
-		<meta http-equiv="origin-trial" data-feature="WebXR Device API (For Chrome M69+)" data-expires="2019-03-06" content="AvDjbxYpoTgOL1PS0JEra7KFCehfTlKnXpU/ORSwNdCQ35cX70cTUkXOnQ26A5XJi3eXHSKpBPchdt5lbcxDuAIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU02OSIsImV4cGlyeSI6MTU1MTgzMDM5OX0=">
+		<link rel="apple-touch-icon" href="images/icon.png">
+		<link rel="manifest" href="manifest.json">
 	</head>
 	<body ontouchstart="">
-		<link href="css/main.css" rel="stylesheet" />
-		<link id="theme" href="css/light.css" rel="stylesheet" />
+		<link rel="stylesheet" href="css/main.css">
+		<link rel="stylesheet" id="theme" href="css/light.css">
 
 		<script src="../build/three.js"></script>
 		<script src="../examples/js/libs/system.min.js"></script>
@@ -86,6 +86,9 @@
 		<script src="js/libs/ui.js"></script>
 		<script src="js/libs/ui.three.js"></script>
 
+		<script src="js/libs/html2canvas.js"></script>
+		<script src="js/libs/three.html.js"></script>
+
 		<script src="js/libs/app.js"></script>
 		<script src="js/Player.js"></script>
 		<script src="js/Script.js"></script>
@@ -138,6 +141,7 @@
 		<script src="js/Strings.js"></script>
 		<script src="js/Toolbar.js"></script>
 		<script src="js/Viewport.js"></script>
+		<script src="js/Viewport.Camera.js"></script>
 		<script src="js/Viewport.Info.js"></script>
 
 		<script src="js/Command.js"></script>
@@ -162,9 +166,6 @@
 		<script src="js/commands/SetMaterialMapCommand.js"></script>
 		<script src="js/commands/SetSceneCommand.js"></script>
 
-		<script src="js/libs/html2canvas.js"></script>
-		<script src="js/libs/three.html.js"></script>
-
 		<script>
 
 			window.URL = window.URL || window.webkitURL;
@@ -190,14 +191,11 @@
 			var player = new Player( editor );
 			document.body.appendChild( player.dom );
 
-			var menubar = new Menubar( editor );
-			document.body.appendChild( menubar.dom );
-
 			var sidebar = new Sidebar( editor );
 			document.body.appendChild( sidebar.dom );
 
-			var modal = new UI.Modal();
-			document.body.appendChild( modal.dom );
+			var menubar = new Menubar( editor );
+			document.body.appendChild( menubar.dom );
 
 			//
 
@@ -268,12 +266,6 @@
 				signals.scriptChanged.add( saveState );
 				signals.historyChanged.add( saveState );
 
-				signals.showModal.add( function ( content ) {
-
-					modal.show( content );
-
-				} );
-
 			} );
 
 			//
@@ -329,6 +321,20 @@
 
 			}
 
+			// ServiceWorker
+
+			if ( 'serviceWorker' in navigator ) {
+
+				try {
+
+					navigator.serviceWorker.register( 'sw.js' );
+
+				} catch ( error ) {
+
+				}
+
+			}
+
 			/*
 			window.addEventListener( 'message', function ( event ) {
 

+ 0 - 2
editor/js/Config.js

@@ -17,8 +17,6 @@ var Config = function () {
 
 		'project/renderer': 'WebGLRenderer',
 		'project/renderer/antialias': true,
-		'project/renderer/gammaInput': false,
-		'project/renderer/gammaOutput': false,
 		'project/renderer/shadows': true,
 
 		'project/vr': false,

+ 65 - 16
editor/js/Editor.js

@@ -22,10 +22,6 @@ var Editor = function () {
 		startPlayer: new Signal(),
 		stopPlayer: new Signal(),
 
-		// actions
-
-		showModal: new Signal(),
-
 		// notifications
 
 		editorCleared: new Signal(),
@@ -55,6 +51,9 @@ var Editor = function () {
 		objectChanged: new Signal(),
 		objectRemoved: new Signal(),
 
+		cameraAdded: new Signal(),
+		cameraRemoved: new Signal(),
+
 		helperAdded: new Signal(),
 		helperRemoved: new Signal(),
 
@@ -68,7 +67,9 @@ var Editor = function () {
 
 		showGridChanged: new Signal(),
 		refreshSidebarObject3D: new Signal(),
-		historyChanged: new Signal()
+		historyChanged: new Signal(),
+
+		viewportCameraChanged: new Signal()
 
 	};
 
@@ -99,6 +100,11 @@ var Editor = function () {
 	this.selected = null;
 	this.helpers = {};
 
+	this.cameras = {};
+	this.viewportCamera = this.camera;
+
+	this.addCamera( this.camera );
+
 };
 
 Editor.prototype = {
@@ -149,6 +155,7 @@ Editor.prototype = {
 			if ( child.geometry !== undefined ) scope.addGeometry( child.geometry );
 			if ( child.material !== undefined ) scope.addMaterial( child.material );
 
+			scope.addCamera( child );
 			scope.addHelper( child );
 
 		} );
@@ -199,6 +206,7 @@ Editor.prototype = {
 
 		object.traverse( function ( child ) {
 
+			scope.removeCamera( child );
 			scope.removeHelper( child );
 
 		} );
@@ -244,7 +252,37 @@ Editor.prototype = {
 
 	addAnimation: function ( object, animations ) {
 
-		this.animations[ object.uuid ] = animations;
+		if ( animations.length > 0 ) {
+
+			this.animations[ object.uuid ] = animations;
+
+		}
+
+	},
+
+	//
+
+	addCamera: function ( camera ) {
+
+		if ( camera.isCamera ) {
+
+			this.cameras[ camera.uuid ] = camera;
+
+			this.signals.cameraAdded.dispatch( camera );
+
+		}
+
+	},
+
+	removeCamera: function ( camera ) {
+
+		if ( this.cameras[ camera.uuid ] !== undefined ) {
+
+			delete this.cameras[ camera.uuid ];
+
+			this.signals.cameraRemoved.dispatch( camera );
+
+		}
 
 	},
 
@@ -259,29 +297,29 @@ Editor.prototype = {
 
 			var helper;
 
-			if ( object instanceof THREE.Camera ) {
+			if ( object.isCamera ) {
 
 				helper = new THREE.CameraHelper( object, 1 );
 
-			} else if ( object instanceof THREE.PointLight ) {
+			} else if ( object.isPointLight ) {
 
 				helper = new THREE.PointLightHelper( object, 1 );
 
-			} else if ( object instanceof THREE.DirectionalLight ) {
+			} else if ( object.isDirectionalLight ) {
 
 				helper = new THREE.DirectionalLightHelper( object, 1 );
 
-			} else if ( object instanceof THREE.SpotLight ) {
+			} else if ( object.isSpotLight ) {
 
 				helper = new THREE.SpotLightHelper( object, 1 );
 
-			} else if ( object instanceof THREE.HemisphereLight ) {
+			} else if ( object.isHemisphereLight ) {
 
 				helper = new THREE.HemisphereLightHelper( object, 1 );
 
-			} else if ( object instanceof THREE.SkinnedMesh ) {
+			} else if ( object.isSkinnedMesh ) {
 
-				helper = new THREE.SkeletonHelper( object );
+				helper = new THREE.SkeletonHelper( object.skeleton.bones[ 0 ] );
 
 			} else {
 
@@ -379,6 +417,13 @@ Editor.prototype = {
 
 	},
 
+	setViewportCamera: function ( uuid ) {
+
+		this.viewportCamera = this.cameras[ uuid ];
+		this.signals.viewportCameraChanged.dispatch( this.viewportCamera );
+
+	},
+
 	//
 
 	select: function ( object ) {
@@ -437,7 +482,11 @@ Editor.prototype = {
 
 	focus: function ( object ) {
 
-		this.signals.objectFocused.dispatch( object );
+		if ( object !== undefined ) {
+
+			this.signals.objectFocused.dispatch( object );
+
+		}
 
 	},
 
@@ -453,6 +502,8 @@ Editor.prototype = {
 		this.storage.clear();
 
 		this.camera.copy( this.DEFAULT_CAMERA );
+		this.scene.name = "Scene";
+		this.scene.userData = {};
 		this.scene.background.setHex( 0xaaaaaa );
 		this.scene.fog = null;
 
@@ -531,8 +582,6 @@ Editor.prototype = {
 
 			metadata: {},
 			project: {
-				gammaInput: this.config.getKey( 'project/renderer/gammaInput' ),
-				gammaOutput: this.config.getKey( 'project/renderer/gammaOutput' ),
 				shadows: this.config.getKey( 'project/renderer/shadows' ),
 				vr: this.config.getKey( 'project/vr' )
 			},

+ 4 - 2
editor/js/Loader.js

@@ -180,6 +180,7 @@ var Loader = function ( editor ) {
 
 					collada.scene.name = filename;
 
+					editor.addAnimation( collada.scene, collada.animations );
 					editor.execute( new AddObjectCommand( collada.scene ) );
 
 				}, false );
@@ -196,6 +197,7 @@ var Loader = function ( editor ) {
 					var loader = new THREE.FBXLoader( manager );
 					var object = loader.parse( contents );
 
+					editor.addAnimation( object, object.animations );
 					editor.execute( new AddObjectCommand( object ) );
 
 				}, false );
@@ -451,7 +453,7 @@ var Loader = function ( editor ) {
 					var contents = event.target.result;
 
 					var loader = new THREE.SVGLoader();
-					var paths = loader.parse( contents );
+					var paths = loader.parse( contents ).paths;
 
 					//
 
@@ -594,7 +596,7 @@ var Loader = function ( editor ) {
 
 				var result = loader.parse( data );
 
-				if ( result instanceof THREE.Scene ) {
+				if ( result.isScene ) {
 
 					editor.execute( new SetSceneCommand( result ) );
 

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

@@ -380,7 +380,7 @@ Menubar.Add = function ( editor ) {
 	option.setTextContent( strings.getKey( 'menubar/add/perspectivecamera' ) );
 	option.onClick( function () {
 
-		var camera = new THREE.PerspectiveCamera( 50, 1, 1, 10000 );
+		var camera = new THREE.PerspectiveCamera();
 		camera.name = 'PerspectiveCamera';
 
 		editor.execute( new AddObjectCommand( camera ) );

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

@@ -151,7 +151,7 @@ Menubar.Edit = function ( editor ) {
 
 			var material = object.material;
 
-			if ( material instanceof THREE.ShaderMaterial ) {
+			if ( material.isShaderMaterial ) {
 
 				try {
 

+ 1 - 1
editor/js/Sidebar.Geometry.BufferGeometry.js

@@ -17,7 +17,7 @@ Sidebar.Geometry.BufferGeometry = function ( editor ) {
 
 		var geometry = object.geometry;
 
-		if ( geometry instanceof THREE.BufferGeometry ) {
+		if ( geometry && geometry.isBufferGeometry ) {
 
 			container.clear();
 			container.setDisplay( 'block' );

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

@@ -39,7 +39,7 @@ Sidebar.Geometry.Geometry = function ( editor ) {
 
 		var geometry = object.geometry;
 
-		if ( geometry instanceof THREE.Geometry ) {
+		if ( geometry && geometry.isGeometry ) {
 
 			container.setDisplay( 'block' );
 

+ 1 - 1
editor/js/Sidebar.Geometry.Modifiers.js

@@ -17,7 +17,7 @@ Sidebar.Geometry.Modifiers = function ( editor, object ) {
 
 		geometry.computeVertexNormals();
 
-		if ( geometry instanceof THREE.BufferGeometry ) {
+		if ( geometry.isBufferGeometry ) {
 
 			geometry.attributes.normal.needsUpdate = true;
 

+ 3 - 1
editor/js/Sidebar.Geometry.js

@@ -55,7 +55,7 @@ Sidebar.Geometry = function ( editor ) {
 
 			case 'Convert':
 
-				if ( geometry instanceof THREE.Geometry ) {
+				if ( geometry && geometry.isGeometry ) {
 
 					editor.execute( new SetGeometryCommand( object, new THREE.BufferGeometry().fromGeometry( geometry ) ) );
 
@@ -179,6 +179,8 @@ Sidebar.Geometry = function ( editor ) {
 
 			}
 
+			if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere();
+
 			geometryBoundingSphere.setValue( Math.floor( geometry.boundingSphere.radius * 1000 ) / 1000 );
 
 		} else {

+ 139 - 6
editor/js/Sidebar.Material.js

@@ -83,10 +83,14 @@ Sidebar.Material = function ( editor ) {
 		'MeshDepthMaterial': 'MeshDepthMaterial',
 		'MeshNormalMaterial': 'MeshNormalMaterial',
 		'MeshLambertMaterial': 'MeshLambertMaterial',
+		'MeshMatcapMaterial': 'MeshMatcapMaterial',
 		'MeshPhongMaterial': 'MeshPhongMaterial',
+		'MeshToonMaterial': 'MeshToonMaterial',
 		'MeshStandardMaterial': 'MeshStandardMaterial',
 		'MeshPhysicalMaterial': 'MeshPhysicalMaterial',
+		'RawShaderMaterial': 'RawShaderMaterial',
 		'ShaderMaterial': 'ShaderMaterial',
+		'ShadowMaterial': 'ShadowMaterial',
 		'SpriteMaterial': 'SpriteMaterial'
 
 	} ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
@@ -257,6 +261,20 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialVertexColorsRow );
 
+	// depth packing
+
+	var materialDepthPackingRow = new UI.Row();
+	var materialDepthPacking = new UI.Select().setOptions( {
+		[ THREE.BasicDepthPacking ]: 'BasicDepthPacking',
+		[ THREE.RGBADepthPacking ]: 'RGBADepthPacking'
+	} );
+	materialDepthPacking.onChange( update );
+
+	materialDepthPackingRow.add( new UI.Text( strings.getKey( 'sidebar/material/depthPacking' ) ).setWidth( '90px' ) );
+	materialDepthPackingRow.add( materialDepthPacking );
+
+	container.add( materialDepthPackingRow );
+
 	// skinning
 
 	var materialSkinningRow = new UI.Row();
@@ -279,6 +297,18 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialMapRow );
 
+	// matcap map
+
+	var materialMatcapMapRow = new UI.Row();
+	var materialMatcapMapEnabled = new UI.Checkbox( false ).onChange( update );
+	var materialMatcapMap = new UI.Texture().onChange( update );
+
+	materialMatcapMapRow.add( new UI.Text( strings.getKey( 'sidebar/material/matcap' ) ).setWidth( '90px' ) );
+	materialMatcapMapRow.add( materialMatcapMapEnabled );
+	materialMatcapMapRow.add( materialMatcapMap );
+
+	container.add( materialMatcapMapRow );
+
 	// alpha map
 
 	var materialAlphaMapRow = new UI.Row();
@@ -419,6 +449,18 @@ Sidebar.Material = function ( editor ) {
 
 	container.add( materialEmissiveMapRow );
 
+	// gradient map
+
+	var materialGradientMapRow = new UI.Row();
+	var materialGradientMapEnabled = new UI.Checkbox( false ).onChange( update );
+	var materialGradientMap = new UI.Texture().onChange( update );
+
+	materialGradientMapRow.add( new UI.Text( strings.getKey( 'sidebar/material/gradientmap' ) ).setWidth( '90px' ) );
+	materialGradientMapRow.add( materialGradientMapEnabled );
+	materialGradientMapRow.add( materialGradientMap );
+
+	container.add( materialGradientMapRow );
+
 	// side
 
 	var materialSideRow = new UI.Row();
@@ -438,7 +480,7 @@ Sidebar.Material = function ( editor ) {
 	// shading
 
 	var materialShadingRow = new UI.Row();
-	var materialShading = new UI.Checkbox(false).setLeft( '100px' ).onChange( update );
+	var materialShading = new UI.Checkbox( false ).setLeft( '100px' ).onChange( update );
 
 	materialShadingRow.add( new UI.Text( strings.getKey( 'sidebar/material/flatshaded' ) ).setWidth( '90px' ) );
 	materialShadingRow.add( materialShading );
@@ -525,9 +567,9 @@ Sidebar.Material = function ( editor ) {
 		var textureWarning = false;
 		var objectHasUvs = false;
 
-		if ( object instanceof THREE.Sprite ) objectHasUvs = true;
-		if ( geometry instanceof THREE.Geometry && geometry.faceVertexUvs[ 0 ].length > 0 ) objectHasUvs = true;
-		if ( geometry instanceof THREE.BufferGeometry && geometry.attributes.uv !== undefined ) objectHasUvs = true;
+		if ( object.isSprite ) objectHasUvs = true;
+		if ( geometry.isGeometry && geometry.faceVertexUvs[ 0 ].length > 0 ) objectHasUvs = true;
+		if ( geometry.isBufferGeometry && geometry.attributes.uv !== undefined ) objectHasUvs = true;
 
 		if ( material ) {
 
@@ -537,10 +579,16 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
-			if ( material instanceof THREE[ materialClass.getValue() ] === false ) {
+			if ( material.type !== materialClass.getValue() ) {
 
 				material = new THREE[ materialClass.getValue() ]();
 
+				if ( material.type == "RawShaderMaterial" ) {
+
+					material.vertexShader = vertexShaderVariables + material.vertexShader;
+
+				}
+
 				editor.execute( new SetMaterialCommand( currentObject, material, currentMaterialSlot ), 'New Material: ' + materialClass.getValue() );
 				// TODO Copy other references in the scene graph
 				// keeping name and UUID then.
@@ -610,6 +658,17 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
+			if ( material.depthPacking !== undefined ) {
+
+				var depthPacking = parseInt( materialDepthPacking.getValue() );
+				if ( material.depthPacking !== depthPacking ) {
+
+					editor.execute( new SetMaterialValueCommand( currentObject, 'depthPacking', depthPacking, currentMaterialSlot ) );
+
+				}
+
+			}
+
 			if ( material.skinning !== undefined && material.skinning !== materialSkinning.getValue() ) {
 
 				editor.execute( new SetMaterialValueCommand( currentObject, 'skinning', materialSkinning.getValue(), currentMaterialSlot ) );
@@ -637,6 +696,27 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
+			if ( material.matcap !== undefined ) {
+
+				var mapEnabled = materialMatcapMapEnabled.getValue() === true;
+
+				if ( objectHasUvs ) {
+
+					var matcap = mapEnabled ? materialMatcapMap.getValue() : null;
+					if ( material.matcap !== matcap ) {
+
+						editor.execute( new SetMaterialMapCommand( currentObject, 'matcap', matcap, currentMaterialSlot ) );
+
+					}
+
+				} else {
+
+					if ( mapEnabled ) textureWarning = true;
+
+				}
+
+			}
+
 			if ( material.alphaMap !== undefined ) {
 
 				var mapEnabled = materialAlphaMapEnabled.getValue() === true;
@@ -891,6 +971,20 @@ Sidebar.Material = function ( editor ) {
 
 			}
 
+			if ( material.gradientMap !== undefined ) {
+
+				var gradientMapEnabled = materialGradientMapEnabled.getValue() === true;
+
+				var gradientMap = gradientMapEnabled ? materialGradientMap.getValue() : null;
+
+				if ( material.gradientMap !== gradientMap ) {
+
+					editor.execute( new SetMaterialMapCommand( currentObject, 'gradientMap', gradientMap, currentMaterialSlot ) );
+
+				}
+
+			}
+
 			if ( material.side !== undefined ) {
 
 				var side = parseInt( materialSide.getValue() );
@@ -945,7 +1039,7 @@ Sidebar.Material = function ( editor ) {
 
 			if ( material.wireframe !== undefined && material.wireframe !== materialWireframe.getValue() ) {
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'wireframe', materialWireframe.getValue(), currentMaterialSlot) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'wireframe', materialWireframe.getValue(), currentMaterialSlot ) );
 
 			}
 
@@ -983,8 +1077,10 @@ Sidebar.Material = function ( editor ) {
 			'clearCoatRoughness': materialClearCoatRoughnessRow,
 			'vertexShader': materialProgramRow,
 			'vertexColors': materialVertexColorsRow,
+			'depthPacking': materialDepthPackingRow,
 			'skinning': materialSkinningRow,
 			'map': materialMapRow,
+			'matcap': materialMatcapMapRow,
 			'alphaMap': materialAlphaMapRow,
 			'bumpMap': materialBumpMapRow,
 			'normalMap': materialNormalMapRow,
@@ -996,6 +1092,7 @@ Sidebar.Material = function ( editor ) {
 			'lightMap': materialLightMapRow,
 			'aoMap': materialAOMapRow,
 			'emissiveMap': materialEmissiveMapRow,
+			'gradientMap': materialGradientMapRow,
 			'side': materialSideRow,
 			'flatShading': materialShadingRow,
 			'blending': materialBlendingRow,
@@ -1122,6 +1219,12 @@ Sidebar.Material = function ( editor ) {
 
 		}
 
+		if ( material.depthPacking !== undefined ) {
+
+			materialDepthPacking.setValue( material.depthPacking );
+
+		}
+
 		if ( material.skinning !== undefined ) {
 
 			materialSkinning.setValue( material.skinning );
@@ -1140,6 +1243,18 @@ Sidebar.Material = function ( editor ) {
 
 		}
 
+		if ( material.matcap !== undefined ) {
+
+			materialMatcapMapEnabled.setValue( material.matcap !== null );
+
+			if ( material.matcap !== null || resetTextureSelectors ) {
+
+				materialMatcapMap.setValue( material.matcap );
+
+			}
+
+		}
+
 		if ( material.alphaMap !== undefined ) {
 
 			materialAlphaMapEnabled.setValue( material.alphaMap !== null );
@@ -1240,6 +1355,18 @@ Sidebar.Material = function ( editor ) {
 
 		}
 
+		if ( material.gradientMap !== undefined ) {
+
+			materialGradientMapEnabled.setValue( material.gradientMap !== null );
+
+			if ( material.gradientMap !== null || resetTextureSelectors ) {
+
+				materialGradientMap.setValue( material.gradientMap );
+
+			}
+
+		}
+
 		if ( material.reflectivity !== undefined ) {
 
 			materialReflectivity.setValue( material.reflectivity );
@@ -1377,6 +1504,12 @@ Sidebar.Material = function ( editor ) {
 
 	} );
 
+	var vertexShaderVariables = [
+		'uniform mat4 projectionMatrix;',
+		'uniform mat4 modelViewMatrix;\n',
+		'attribute vec3 position;\n\n',
+	].join( '\n' );
+
 	return container;
 
 };

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

@@ -542,8 +542,8 @@ Sidebar.Object = function ( editor ) {
 
 	function updateTransformRows( object ) {
 
-		if ( object instanceof THREE.Light ||
-		   ( object instanceof THREE.Object3D && object.userData.targetInverse ) ) {
+		if ( object.isLight ||
+		   ( object.isObject3D && object.userData.targetInverse ) ) {
 
 			objectRotationRow.setDisplay( 'none' );
 			objectScaleRow.setDisplay( 'none' );

+ 5 - 28
editor/js/Sidebar.Project.js

@@ -119,45 +119,22 @@ Sidebar.Project = function ( editor ) {
 	} );
 	rendererPropertiesRow.add( rendererShadows );
 
-	rendererPropertiesRow.add( new UI.Break() );
-
-	// Renderer / Gamma input
-
-	var rendererGammaInput = new UI.THREE.Boolean( config.getKey( 'project/renderer/gammaInput' ), strings.getKey( 'sidebar/project/gammainput' ) ).onChange( function () {
-
-		config.setKey( 'project/renderer/gammaInput', this.getValue() );
-		updateRenderer();
-
-	} );
-	rendererPropertiesRow.add( rendererGammaInput );
-
-	// Renderer / Gamma output
-
-	var rendererGammaOutput = new UI.THREE.Boolean( config.getKey( 'project/renderer/gammaOutput' ), strings.getKey( 'sidebar/project/gammaoutput' ) ).onChange( function () {
-
-		config.setKey( 'project/renderer/gammaOutput', this.getValue() );
-		updateRenderer();
-
-	} );
-	rendererPropertiesRow.add( rendererGammaOutput );
-
 	container.add( rendererPropertiesRow );
 
 	//
 
 	function updateRenderer() {
 
-		createRenderer( rendererType.getValue(), rendererAntialias.getValue(), rendererShadows.getValue(), rendererGammaInput.getValue(), rendererGammaOutput.getValue() );
+		createRenderer( rendererType.getValue(), rendererAntialias.getValue() );
 
 	}
 
-	function createRenderer( type, antialias, shadows, gammaIn, gammaOut ) {
+	function createRenderer( type, antialias, shadows ) {
 
 		rendererPropertiesRow.setDisplay( type === 'WebGLRenderer' ? '' : 'none' );
 
-		var renderer = new rendererTypes[ type ]( { antialias: antialias} );
-		renderer.gammaInput = gammaIn;
-		renderer.gammaOutput = gammaOut;
+		var renderer = new rendererTypes[ type ]( { antialias: antialias } );
+
 		if ( shadows && renderer.shadowMap ) {
 
 			renderer.shadowMap.enabled = true;
@@ -169,7 +146,7 @@ Sidebar.Project = function ( editor ) {
 
 	}
 
-	createRenderer( config.getKey( 'project/renderer' ), config.getKey( 'project/renderer/antialias' ), config.getKey( 'project/renderer/shadows' ), config.getKey( 'project/renderer/gammaInput' ), config.getKey( 'project/renderer/gammaOutput' ) );
+	createRenderer( config.getKey( 'project/renderer' ), config.getKey( 'project/renderer/antialias' ), config.getKey( 'project/renderer/shadows' ) );
 
 	return container;
 

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

@@ -59,7 +59,7 @@ Sidebar.Scene = function ( editor ) {
 
 		var html = '<span class="type ' + object.type + '"></span> ' + escapeHTML( object.name );
 
-		if ( object instanceof THREE.Mesh ) {
+		if ( object.isMesh ) {
 
 			var geometry = object.geometry;
 			var material = object.material;
@@ -231,13 +231,13 @@ Sidebar.Scene = function ( editor ) {
 
 			fogColor.setHexValue( scene.fog.color.getHex() );
 
-			if ( scene.fog instanceof THREE.Fog ) {
+			if ( scene.fog.isFog ) {
 
 				fogType.setValue( "Fog" );
 				fogNear.setValue( scene.fog.near );
 				fogFar.setValue( scene.fog.far );
 
-			} else if ( scene.fog instanceof THREE.FogExp2 ) {
+			} else if ( scene.fog.isFogExp2 ) {
 
 				fogType.setValue( "FogExp2" );
 				fogDensity.setValue( scene.fog.density );

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

@@ -72,7 +72,7 @@ Sidebar.Settings = function ( editor ) {
 	themeRow.add( new UI.Text( strings.getKey( 'sidebar/settings/theme' ) ).setWidth( '90px' ) );
 	themeRow.add( theme );
 
-	container.add( themeRow );
+	container.add( themeRow );	
 
 	container.add( new Sidebar.Settings.Shortcuts( editor ) );
 	container.add( new Sidebar.Settings.Viewport( editor ) );

+ 4 - 4
editor/js/Strings.js

@@ -183,6 +183,7 @@ var Strings = function ( config ) {
 			'sidebar/material/vertex': 'Vertex',
 			'sidebar/material/fragment': 'fragment',
 			'sidebar/material/color': 'Color',
+			'sidebar/material/depthPacking': 'Depth Packing',
 			'sidebar/material/roughness': 'Roughness',
 			'sidebar/material/metalness': 'Metalness',
 			'sidebar/material/emissive': 'Emissive',
@@ -195,6 +196,7 @@ var Strings = function ( config ) {
 			'sidebar/material/vertexcolors/face': 'Face',
 			'sidebar/material/vertexcolors/vertex': 'Vertex',
 			'sidebar/material/skinning': 'Skinning',
+			'sidebar/material/matcap': 'Matcap',
 			'sidebar/material/map': 'Map',
 			'sidebar/material/alphamap': 'Alpha Map',
 			'sidebar/material/bumpmap': 'Bump Map',
@@ -207,6 +209,7 @@ var Strings = function ( config ) {
 			'sidebar/material/lightmap': 'Light Map',
 			'sidebar/material/aomap': 'AO Map',
 			'sidebar/material/emissivemap': 'Emissive Map',
+			'sidebar/material/gradientmap': 'Gradient Map',
 			'sidebar/material/side': 'Side',
 			'sidebar/material/side/front': 'Front',
 			'sidebar/material/side/back': 'Back',
@@ -236,8 +239,6 @@ var Strings = function ( config ) {
 			'sidebar/project/renderer': 'Renderer',
 			'sidebar/project/antialias': 'antialias',
 			'sidebar/project/shadows': 'shadows',
-			'sidebar/project/gammainput': 'γ input',
-			'sidebar/project/gammaoutput': 'γ output',
 
 			'sidebar/settings': 'Settings',
 			'sidebar/settings/language': 'Language',
@@ -301,6 +302,7 @@ var Strings = function ( config ) {
 			'menubar/add/icosahedron': '二十面体',
 			'menubar/add/torus': '圆环体',
 			'menubar/add/torusknot': '环面纽结体',
+			'menubar/add/tube': '管',
 			'menubar/add/lathe': '酒杯',
 			'menubar/add/sprite': '精灵',
 			'menubar/add/pointlight': '点光源',
@@ -485,8 +487,6 @@ var Strings = function ( config ) {
 			'sidebar/project/renderer': '渲染器',
 			'sidebar/project/antialias': '抗锯齿',
 			'sidebar/project/shadows': '阴影',
-			'sidebar/project/gammainput': 'γ输入',
-			'sidebar/project/gammaoutput': 'γ输出',
 
 			'sidebar/settings': '设置',
 			'sidebar/settings/language': '语言',

+ 48 - 0
editor/js/Viewport.Camera.js

@@ -0,0 +1,48 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+Viewport.Camera = function ( editor ) {
+
+	var signals = editor.signals;
+
+	//
+
+	var cameraSelect = new UI.Select();
+	cameraSelect.setPosition( 'absolute' );
+	cameraSelect.setRight( '10px' );
+	cameraSelect.setTop( '10px' );
+	cameraSelect.onChange( function () {
+
+		editor.setViewportCamera( this.getValue() );
+
+	} );
+
+	signals.cameraAdded.add( update );
+	signals.cameraRemoved.add( update );
+
+	update();
+
+	//
+
+	function update() {
+
+		var options = {};
+
+		var cameras = editor.cameras;
+
+		for ( var key in cameras ) {
+
+			var camera = cameras[ key ];
+			options[ camera.uuid ] = camera.name;
+
+		}
+
+		cameraSelect.setOptions( options );
+		cameraSelect.setValue( editor.viewportCamera.uuid );
+
+	}
+
+	return cameraSelect;
+
+};

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

@@ -46,16 +46,16 @@ Viewport.Info = function ( editor ) {
 
 				objects ++;
 
-				if ( object instanceof THREE.Mesh ) {
+				if ( object.isMesh ) {
 
 					var geometry = object.geometry;
 
-					if ( geometry instanceof THREE.Geometry ) {
+					if ( geometry.isGeometry ) {
 
 						vertices += geometry.vertices.length;
 						triangles += geometry.faces.length;
 
-					} else if ( geometry instanceof THREE.BufferGeometry ) {
+					} else if ( geometry.isBufferGeometry ) {
 
 						vertices += geometry.attributes.position.count;
 

+ 33 - 12
editor/js/Viewport.js

@@ -10,6 +10,7 @@ var Viewport = function ( editor ) {
 	container.setId( 'viewport' );
 	container.setPosition( 'absolute' );
 
+	container.add( new Viewport.Camera( editor ) );
 	container.add( new Viewport.Info( editor ) );
 
 	//
@@ -198,7 +199,7 @@ var Viewport = function ( editor ) {
 
 	function onMouseDown( event ) {
 
-		event.preventDefault();
+		// event.preventDefault();
 
 		var array = getMousePosition( container.dom, event.clientX, event.clientY );
 		onDownPosition.fromArray( array );
@@ -312,6 +313,7 @@ var Viewport = function ( editor ) {
 
 		renderer.autoClear = false;
 		renderer.autoUpdateScene = false;
+		renderer.gammaOutput = true;
 		renderer.setPixelRatio( window.devicePixelRatio );
 		renderer.setSize( container.dom.offsetWidth, container.dom.offsetHeight );
 
@@ -393,7 +395,7 @@ var Viewport = function ( editor ) {
 
 		}
 
-		if ( object instanceof THREE.PerspectiveCamera ) {
+		if ( object.isPerspectiveCamera ) {
 
 			object.updateProjectionMatrix();
 
@@ -411,6 +413,7 @@ var Viewport = function ( editor ) {
 
 	signals.objectRemoved.add( function ( object ) {
 
+		controls.enabled = true; // see #14180
 		if ( object === transformControls.object ) {
 
 			transformControls.detach();
@@ -477,16 +480,20 @@ var Viewport = function ( editor ) {
 
 		}
 
-		if ( scene.fog instanceof THREE.Fog ) {
+		if ( scene.fog ) {
 
-			scene.fog.color.setHex( fogColor );
-			scene.fog.near = fogNear;
-			scene.fog.far = fogFar;
+			if ( scene.fog.isFog ) {
 
-		} else if ( scene.fog instanceof THREE.FogExp2 ) {
+				scene.fog.color.setHex( fogColor );
+				scene.fog.near = fogNear;
+				scene.fog.far = fogFar;
 
-			scene.fog.color.setHex( fogColor );
-			scene.fog.density = fogDensity;
+			} else if ( scene.fog.isFogExp2 ) {
+
+				scene.fog.color.setHex( fogColor );
+				scene.fog.density = fogDensity;
+
+			}
 
 		}
 
@@ -494,6 +501,17 @@ var Viewport = function ( editor ) {
 
 	} );
 
+	signals.viewportCameraChanged.add( function ( viewportCamera ) {
+
+		camera = viewportCamera;
+
+		camera.aspect = editor.camera.aspect;
+		camera.projectionMatrix.copy( editor.camera.projectionMatrix );
+
+		render();
+
+	} );
+
 	//
 
 	signals.windowResize.add( function () {
@@ -546,14 +564,17 @@ var Viewport = function ( editor ) {
 
 	function render() {
 
-		sceneHelpers.updateMatrixWorld();
 		scene.updateMatrixWorld();
-
 		renderer.render( scene, camera );
 
 		if ( renderer instanceof THREE.RaytracingRenderer === false ) {
 
-			renderer.render( sceneHelpers, camera );
+			if ( camera === editor.camera ) {
+
+				sceneHelpers.updateMatrixWorld();
+				renderer.render( sceneHelpers, camera );
+
+			}
 
 		}
 

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

@@ -21,13 +21,12 @@ var APP = {
 		this.load = function ( json ) {
 
 			renderer = new THREE.WebGLRenderer( { antialias: true } );
+			renderer.gammaOutput = true;
 			renderer.setClearColor( 0x000000 );
 			renderer.setPixelRatio( window.devicePixelRatio );
 
 			var project = json.project;
 
-			if ( project.gammaInput ) renderer.gammaInput = true;
-			if ( project.gammaOutput ) renderer.gammaOutput = true;
 			if ( project.shadows ) renderer.shadowMap.enabled = true;
 			if ( project.vr ) renderer.vr.enabled = true;
 

+ 1 - 1
editor/js/libs/codemirror/mode/glsl.js

@@ -205,7 +205,7 @@
     "do for while if else in out inout float int void bool true false " +
     "lowp mediump highp precision invariant discard return mat2 mat3 " +
     "mat4 vec2 vec3 vec4 ivec2 ivec3 ivec4 bvec2 bvec3 bvec4 sampler2D " +
-    "samplerCube struct gl_FragCoord gl_FragColor";
+    "samplerCube struct gl_FragCoord gl_FragColor gl_Position";
   var glslBuiltins = "radians degrees sin cos tan asin acos atan pow " +
     "exp log exp2 log2 sqrt inversesqrt abs sign floor ceil fract mod " +
     "min max clamp mix step smoothstep length distance dot cross " +

+ 38 - 38
editor/js/libs/three.html.js

@@ -2,74 +2,74 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
- THREE.HTMLGroup = function ( dom ) {
+THREE.HTMLGroup = function ( dom ) {
 
- 	THREE.Group.call( this );
+	THREE.Group.call( this );
 
- 	this.type = 'HTMLGroup';
+	this.type = 'HTMLGroup';
 
- 	/*
- 	dom.addEventListener( 'mousemove', function ( event ) {
+	/*
+	dom.addEventListener( 'mousemove', function ( event ) {
 
- 		console.log( 'mousemove' );
+		console.log( 'mousemove' );
 
- 	} );
+	} );
 
- 	dom.addEventListener( 'click', function ( event ) {
+	dom.addEventListener( 'click', function ( event ) {
 
- 		console.log( 'click' );
+		console.log( 'click' );
 
- 	} );
- 	*/
+	} );
+	*/
 
- };
+};
 
- THREE.HTMLGroup.prototype = Object.assign( Object.create( THREE.Group.prototype ), {
+THREE.HTMLGroup.prototype = Object.assign( Object.create( THREE.Group.prototype ), {
 
- 	constructor: THREE.HTMLGroup
+	constructor: THREE.HTMLGroup
 
- } );
+} );
 
- THREE.HTMLMesh = function ( dom ) {
+THREE.HTMLMesh = function ( dom ) {
 
- 	var texture = new THREE.HTMLTexture( dom );
+	var texture = new THREE.HTMLTexture( dom );
 
- 	var geometry = new THREE.PlaneBufferGeometry( texture.image.width * 0.05, texture.image.height * 0.05 );
- 	var material = new THREE.MeshBasicMaterial( { map: texture } );
+	var geometry = new THREE.PlaneBufferGeometry( texture.image.width * 0.05, texture.image.height * 0.05 );
+	var material = new THREE.MeshBasicMaterial( { map: texture } );
 
- 	THREE.Mesh.call( this, geometry, material );
+	THREE.Mesh.call( this, geometry, material );
 
- 	this.type = 'HTMLMesh';
+	this.type = 'HTMLMesh';
 
- };
+};
 
- THREE.HTMLMesh.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), {
+THREE.HTMLMesh.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), {
 
- 	constructor: THREE.HTMLMesh
+	constructor: THREE.HTMLMesh
 
- } );
+} );
 
- THREE.HTMLTexture = function ( dom ) {
+THREE.HTMLTexture = function ( dom ) {
 
- 	THREE.CanvasTexture.call( this, html2canvas( dom ) );
+	THREE.CanvasTexture.call( this, html2canvas( dom ) );
 
- 	this.dom = dom;
+	this.dom = dom;
 
- 	this.anisotropy = 16;
+	this.anisotropy = 16;
 
- };
+};
 
- THREE.HTMLTexture.prototype = Object.assign( Object.create( THREE.CanvasTexture.prototype ), {
+THREE.HTMLTexture.prototype = Object.assign( Object.create( THREE.CanvasTexture.prototype ), {
 
- 	constructor: THREE.HTMLTexture,
+	constructor: THREE.HTMLTexture,
 
- 	update: function () {
+	update: function () {
 
- 		console.log( 'yo!', this, this.dom );
+		console.log( 'yo!', this, this.dom );
 
- 		this.image = html2canvas( this.dom );
- 		this.needsUpdate = true;
+		this.image = html2canvas( this.dom );
+		this.needsUpdate = true;
 
- 	}
+	}
 
- } );
+} );

+ 51 - 58
editor/js/libs/ui.js

@@ -625,6 +625,56 @@ UI.Number = function ( number ) {
 
 	}
 
+	function onTouchStart( event ) {
+
+		if ( event.touches.length === 1 ) {
+
+			distance = 0;
+
+			onMouseDownValue = scope.value;
+
+			prevPointer = [ event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ];
+
+			document.addEventListener( 'touchmove', onTouchMove, false );
+			document.addEventListener( 'touchend', onTouchEnd, false );
+
+		}
+
+	}
+
+	function onTouchMove( event ) {
+
+		var currentValue = scope.value;
+
+		pointer = [ event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ];
+
+		distance += ( pointer[ 0 ] - prevPointer[ 0 ] ) - ( pointer[ 1 ] - prevPointer[ 1 ] );
+
+		var value = onMouseDownValue + ( distance / ( event.shiftKey ? 5 : 50 ) ) * scope.step;
+		value = Math.min( scope.max, Math.max( scope.min, value ) );
+
+		if ( currentValue !== value ) {
+
+			scope.setValue( value );
+			dom.dispatchEvent( changeEvent );
+
+		}
+
+		prevPointer = [ event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ];
+
+	}
+
+	function onTouchEnd( event ) {
+
+		if ( event.touches.length === 0 ) {
+
+			document.removeEventListener( 'touchmove', onTouchMove, false );
+			document.removeEventListener( 'touchend', onTouchEnd, false );
+
+		}
+
+	}
+
 	function onChange( event ) {
 
 		scope.setValue( dom.value );
@@ -648,6 +698,7 @@ UI.Number = function ( number ) {
 	onBlur();
 
 	dom.addEventListener( 'mousedown', onMouseDown, false );
+	dom.addEventListener( 'touchstart', onTouchStart, false );
 	dom.addEventListener( 'change', onChange, false );
 	dom.addEventListener( 'focus', onFocus, false );
 	dom.addEventListener( 'blur', onBlur, false );
@@ -944,61 +995,3 @@ UI.Button.prototype.setLabel = function ( value ) {
 	return this;
 
 };
-
-
-// Modal
-
-UI.Modal = function ( value ) {
-
-	var scope = this;
-
-	var dom = document.createElement( 'div' );
-
-	dom.style.position = 'absolute';
-	dom.style.width = '100%';
-	dom.style.height = '100%';
-	dom.style.backgroundColor = 'rgba(0,0,0,0.5)';
-	dom.style.display = 'none';
-	dom.style.alignItems = 'center';
-	dom.style.justifyContent = 'center';
-	dom.addEventListener( 'click', function ( event ) {
-
-		scope.hide();
-
-	} );
-
-	this.dom = dom;
-
-	this.container = new UI.Panel();
-	this.container.dom.style.width = '200px';
-	this.container.dom.style.padding = '20px';
-	this.container.dom.style.backgroundColor = '#ffffff';
-	this.container.dom.style.boxShadow = '0px 5px 10px rgba(0,0,0,0.5)';
-
-	this.add( this.container );
-
-	return this;
-
-};
-
-UI.Modal.prototype = Object.create( UI.Element.prototype );
-UI.Modal.prototype.constructor = UI.Modal;
-
-UI.Modal.prototype.show = function ( content ) {
-
-	this.container.clear();
-	this.container.add( content );
-
-	this.dom.style.display = 'flex';
-
-	return this;
-
-};
-
-UI.Modal.prototype.hide = function () {
-
-	this.dom.style.display = 'none';
-
-	return this;
-
-};

+ 0 - 55
editor/main.js

@@ -1,55 +0,0 @@
-const electron = require( 'electron' );
-const app = electron.app;
-const BrowserWindow = electron.BrowserWindow;
-
-const path = require( 'path' );
-const url = require( 'url' );
-
-// Keep a global reference of the window object, if you don't, the window will
-// be closed automatically when the JavaScript object is garbage collected.
-let mainWindow;
-
-function createWindow() {
-
-	mainWindow = new BrowserWindow( { webPreferences: {
-		nodeIntegration: false
-	} } );
-
-	mainWindow.maximize();
-	mainWindow.setMenu( null );
-
-	mainWindow.loadURL( url.format( {
-		pathname: path.join( __dirname, 'index.html' ),
-		protocol: 'file:',
-		slashes: true
-	} ) );
-
-	mainWindow.on( 'closed', function () {
-
-		mainWindow = null;
-
-	} );
-
-}
-
-app.on( 'ready', createWindow );
-
-app.on( 'window-all-closed', function () {
-
-	if ( process.platform !== 'darwin' ) {
-
-		app.quit();
-
-	}
-
-} );
-
-app.on( 'activate', function () {
-
-	if ( mainWindow === null ) {
-
-		createWindow();
-
-	}
-
-} );

+ 13 - 0
editor/manifest.json

@@ -0,0 +1,13 @@
+{
+  "short_name": "Editor",
+  "name": "Three.js Editor",
+  "icons": [
+    {
+      "src": "./images/icon.png",
+      "type": "image/png",
+      "sizes": "144x144"
+    }
+  ],
+  "start_url": ".",
+  "display": "standalone"
+}

+ 197 - 0
editor/sw.js

@@ -0,0 +1,197 @@
+// r103
+
+const staticAssets = [
+	'./',
+
+	'../build/three.js',
+	'../examples/js/libs/system.min.js',
+
+	'../examples/js/controls/EditorControls.js',
+	'../examples/js/controls/TransformControls.js',
+
+	'../examples/js/libs/jszip.min.js',
+	'../examples/js/libs/inflate.min.js',
+
+	'../examples/js/loaders/AMFLoader.js',
+	'../examples/js/loaders/AWDLoader.js',
+	'../examples/js/loaders/BabylonLoader.js',
+	'../examples/js/loaders/ColladaLoader.js',
+	'../examples/js/loaders/DRACOLoader.js',
+	'../examples/js/loaders/FBXLoader.js',
+	'../examples/js/loaders/GLTFLoader.js',
+	'../examples/js/loaders/deprecated/LegacyGLTFLoader.js',
+	'../examples/js/loaders/KMZLoader.js',
+	'../examples/js/loaders/MD2Loader.js',
+	'../examples/js/loaders/OBJLoader.js',
+	'../examples/js/loaders/MTLLoader.js',
+	'../examples/js/loaders/PlayCanvasLoader.js',
+	'../examples/js/loaders/PLYLoader.js',
+	'../examples/js/loaders/STLLoader.js',
+	'../examples/js/loaders/SVGLoader.js',
+	'../examples/js/loaders/TGALoader.js',
+	'../examples/js/loaders/TDSLoader.js',
+	'../examples/js/loaders/VRMLLoader.js',
+	'../examples/js/loaders/VTKLoader.js',
+	'../examples/js/loaders/ctm/lzma.js',
+	'../examples/js/loaders/ctm/ctm.js',
+	'../examples/js/loaders/ctm/CTMLoader.js',
+
+	'../examples/js/exporters/ColladaExporter.js',
+	'../examples/js/exporters/GLTFExporter.js',
+	'../examples/js/exporters/OBJExporter.js',
+	'../examples/js/exporters/STLExporter.js',
+
+	'../examples/js/renderers/Projector.js',
+	'../examples/js/renderers/RaytracingRenderer.js',
+	'../examples/js/renderers/SoftwareRenderer.js',
+	'../examples/js/renderers/SVGRenderer.js',
+
+	'./js/libs/codemirror/codemirror.css',
+	'./js/libs/codemirror/theme/monokai.css',
+
+	'./js/libs/codemirror/codemirror.js',
+	'./js/libs/codemirror/mode/javascript.js',
+	'./js/libs/codemirror/mode/glsl.js',
+
+	'./js/libs/esprima.js',
+	'./js/libs/jsonlint.js',
+	'./js/libs/glslprep.min.js',
+
+	'./js/libs/codemirror/addon/dialog.css',
+	'./js/libs/codemirror/addon/show-hint.css',
+	'./js/libs/codemirror/addon/tern.css',
+
+	'./js/libs/codemirror/addon/dialog.js',
+	'./js/libs/codemirror/addon/show-hint.js',
+	'./js/libs/codemirror/addon/tern.js',
+	'./js/libs/acorn/acorn.js',
+	'./js/libs/acorn/acorn_loose.js',
+	'./js/libs/acorn/walk.js',
+	'./js/libs/ternjs/polyfill.js',
+	'./js/libs/ternjs/signal.js',
+	'./js/libs/ternjs/tern.js',
+	'./js/libs/ternjs/def.js',
+	'./js/libs/ternjs/comment.js',
+	'./js/libs/ternjs/infer.js',
+	'./js/libs/ternjs/doc_comment.js',
+	'./js/libs/tern-threejs/threejs.js',
+
+	'./js/libs/signals.min.js',
+	'./js/libs/ui.js',
+	'./js/libs/ui.three.js',
+
+	'./js/libs/html2canvas.js',
+	'./js/libs/three.html.js',
+
+	'./js/libs/app.js',
+	'./js/Player.js',
+	'./js/Script.js',
+
+	'../examples/js/vr/WebVR.js',
+
+	//
+
+	'./css/main.css',
+	'./css/dark.css',
+	'./css/light.css',
+
+	'./js/Storage.js',
+
+	'./js/Editor.js',
+	'./js/Config.js',
+	'./js/History.js',
+	'./js/Loader.js',
+	'./js/Menubar.js',
+	'./js/Menubar.File.js',
+	'./js/Menubar.Edit.js',
+	'./js/Menubar.Add.js',
+	'./js/Menubar.Play.js',
+	// './js/Menubar.View.js',
+	'./js/Menubar.Examples.js',
+	'./js/Menubar.Help.js',
+	'./js/Menubar.Status.js',
+	'./js/Sidebar.js',
+	'./js/Sidebar.Scene.js',
+	'./js/Sidebar.Project.js',
+	'./js/Sidebar.Settings.js',
+	'./js/Sidebar.Settings.Shortcuts.js',
+	'./js/Sidebar.Settings.Viewport.js',
+	'./js/Sidebar.Properties.js',
+	'./js/Sidebar.Object.js',
+	'./js/Sidebar.Geometry.js',
+	'./js/Sidebar.Geometry.Geometry.js',
+	'./js/Sidebar.Geometry.BufferGeometry.js',
+	'./js/Sidebar.Geometry.Modifiers.js',
+	'./js/Sidebar.Geometry.BoxGeometry.js',
+	'./js/Sidebar.Geometry.CircleGeometry.js',
+	'./js/Sidebar.Geometry.CylinderGeometry.js',
+	'./js/Sidebar.Geometry.IcosahedronGeometry.js',
+	'./js/Sidebar.Geometry.PlaneGeometry.js',
+	'./js/Sidebar.Geometry.SphereGeometry.js',
+	'./js/Sidebar.Geometry.TorusGeometry.js',
+	'./js/Sidebar.Geometry.TorusKnotGeometry.js',
+	'./js/Sidebar.Geometry.TubeGeometry.js',
+	'../examples/js/geometries/TeapotBufferGeometry.js',
+	'./js/Sidebar.Geometry.TeapotBufferGeometry.js',
+	'./js/Sidebar.Geometry.LatheGeometry.js',
+	'./js/Sidebar.Material.js',
+	'./js/Sidebar.Animation.js',
+	'./js/Sidebar.Script.js',
+	'./js/Sidebar.History.js',
+	'./js/Strings.js',
+	'./js/Toolbar.js',
+	'./js/Viewport.js',
+	'./js/Viewport.Info.js',
+
+	'./js/Command.js',
+	'./js/commands/AddObjectCommand.js',
+	'./js/commands/RemoveObjectCommand.js',
+	'./js/commands/MoveObjectCommand.js',
+	'./js/commands/SetPositionCommand.js',
+	'./js/commands/SetRotationCommand.js',
+	'./js/commands/SetScaleCommand.js',
+	'./js/commands/SetValueCommand.js',
+	'./js/commands/SetUuidCommand.js',
+	'./js/commands/SetColorCommand.js',
+	'./js/commands/SetGeometryCommand.js',
+	'./js/commands/SetGeometryValueCommand.js',
+	'./js/commands/MultiCmdsCommand.js',
+	'./js/commands/AddScriptCommand.js',
+	'./js/commands/RemoveScriptCommand.js',
+	'./js/commands/SetScriptValueCommand.js',
+	'./js/commands/SetMaterialCommand.js',
+	'./js/commands/SetMaterialValueCommand.js',
+	'./js/commands/SetMaterialColorCommand.js',
+	'./js/commands/SetMaterialMapCommand.js',
+	'./js/commands/SetSceneCommand.js',
+
+	//
+
+	'./examples/arkanoid.app.json',
+	'./examples/camera.app.json',
+	'./examples/particles.app.json',
+	'./examples/pong.app.json',
+	'./examples/shaders.app.json'
+
+];
+
+self.addEventListener( 'install', async function ( event ) {
+
+	const cache = await caches.open( 'threejs-editor' );
+	cache.addAll( staticAssets );
+
+} );
+
+self.addEventListener( 'fetch', async function ( event ) {
+
+	const request = event.request;
+	event.respondWith( cacheFirst( request ) );
+
+} );
+
+async function cacheFirst( request ) {
+
+	const cachedResponse = await caches.match( request );
+	return cachedResponse || fetch( request );
+
+}

+ 50 - 39
examples/files.js

@@ -4,6 +4,7 @@ var files = {
 		"webgl_animation_keyframes",
 		"webgl_animation_skinning_blending",
 		"webgl_animation_skinning_morph",
+		"webgl_animation_multiple",
 		"webgl_camera",
 		"webgl_camera_array",
 		"webgl_camera_cinematic",
@@ -19,7 +20,6 @@ var files = {
 		"webgl_effects_peppersghost",
 		"webgl_effects_stereo",
 		"webgl_framebuffer_texture",
-		"webgl_furnace_test",
 		"webgl_geometries",
 		"webgl_geometries_parametric",
 		"webgl_geometry_colors",
@@ -44,6 +44,7 @@ var files = {
 		"webgl_geometry_terrain_raycast",
 		"webgl_geometry_text",
 		"webgl_geometry_text_shapes",
+		"webgl_geometry_text_stroke",
 		"webgl_hdr",
 		"webgl_helpers",
 		"webgl_interactive_buffergeometry",
@@ -67,6 +68,7 @@ var files = {
 		"webgl_lights_spotlight",
 		"webgl_lights_spotlights",
 		"webgl_lights_rectarealight",
+		"webgl_lightshafts",
 		"webgl_lines_colors",
 		"webgl_lines_dashed",
 		"webgl_lines_fat",
@@ -95,6 +97,7 @@ var files = {
 		"webgl_loader_json_claraio",
 		"webgl_loader_kmz",
 		"webgl_loader_ldraw",
+		"webgl_loader_lwo",
 		"webgl_loader_md2",
 		"webgl_loader_md2_control",
 		"webgl_loader_mmd",
@@ -155,6 +158,7 @@ var files = {
 		"webgl_materials_envmaps",
 		"webgl_materials_envmaps_exr",
 		"webgl_materials_envmaps_hdr",
+		"webgl_materials_envmaps_parallax",
 		"webgl_materials_grass",
 		"webgl_materials_lightmap",
 		"webgl_materials_matcap",
@@ -208,40 +212,10 @@ var files = {
 		"webgl_performance_doublesided",
 		"webgl_performance_nodes",
 		"webgl_performance_static",
-		"webgl_physics_cloth",
-		"webgl_physics_convex_break",
-		"webgl_physics_rope",
-		"webgl_physics_terrain",
-		"webgl_physics_volume",
 		"webgl_points_billboards",
 		"webgl_points_dynamic",
 		"webgl_points_sprites",
 		"webgl_points_waves",
-		"webgl_postprocessing",
-		"webgl_postprocessing_advanced",
-		"webgl_postprocessing_afterimage",
-		"webgl_postprocessing_backgrounds",
-		"webgl_postprocessing_crossfade",
-		"webgl_postprocessing_dof",
-		"webgl_postprocessing_dof2",
-		"webgl_postprocessing_fxaa",
-		"webgl_postprocessing_glitch",
-		"webgl_postprocessing_godrays",
-		"webgl_postprocessing_rgb_halftone",
-		"webgl_postprocessing_masking",
-		"webgl_postprocessing_ssaa",
-		"webgl_postprocessing_ssaa_unbiased",
-		"webgl_postprocessing_nodes",
-		"webgl_postprocessing_nodes_pass",
-		"webgl_postprocessing_outline",
-		"webgl_postprocessing_pixel",
-		"webgl_postprocessing_procedural",
-		"webgl_postprocessing_sao",
-		"webgl_postprocessing_smaa",
-		"webgl_postprocessing_sobel",
-		"webgl_postprocessing_ssao",
-		"webgl_postprocessing_taa",
-		"webgl_postprocessing_unreal_bloom",
 		"webgl_raycast_sprite",
 		"webgl_raycast_texture",
 		"webgl_read_float_buffer",
@@ -274,6 +248,33 @@ var files = {
 		"webgl_water",
 		"webgl_water_flowmap"
 	],
+	"webgl / postprocessing": [
+		"webgl_postprocessing",
+		"webgl_postprocessing_advanced",
+		"webgl_postprocessing_afterimage",
+		"webgl_postprocessing_backgrounds",
+		"webgl_postprocessing_crossfade",
+		"webgl_postprocessing_dof",
+		"webgl_postprocessing_dof2",
+		"webgl_postprocessing_fxaa",
+		"webgl_postprocessing_glitch",
+		"webgl_postprocessing_godrays",
+		"webgl_postprocessing_rgb_halftone",
+		"webgl_postprocessing_masking",
+		"webgl_postprocessing_ssaa",
+		"webgl_postprocessing_ssaa_unbiased",
+		"webgl_postprocessing_nodes",
+		"webgl_postprocessing_nodes_pass",
+		"webgl_postprocessing_outline",
+		"webgl_postprocessing_pixel",
+		"webgl_postprocessing_procedural",
+		"webgl_postprocessing_sao",
+		"webgl_postprocessing_smaa",
+		"webgl_postprocessing_sobel",
+		"webgl_postprocessing_ssao",
+		"webgl_postprocessing_taa",
+		"webgl_postprocessing_unreal_bloom"
+	],
 	"webgl / advanced": [
 		"webgl_buffergeometry",
 		"webgl_buffergeometry_constructed_from_geometry",
@@ -309,14 +310,13 @@ var files = {
 		"webgl_shadowmap_pcss",
 		"webgl_simple_gi",
 		"webgl_tiled_forward",
-		"webgl_worker_offscreencanvas"
-	],
-	"webgl deferred": [
+		"webgl_worker_offscreencanvas",
 		"webgldeferred_animation"
 	],
 	"webgl2": [
+		"webgl2_loader_gltf",
+		"webgl2_materials_texture2darray",
 		"webgl2_materials_texture3d",
-		"webgl2_materials_texture3d_volume",
 		"webgl2_multisampled_renderbuffers",
 		"webgl2_sandbox"
 	],
@@ -340,6 +340,13 @@ var files = {
 		"webvr_vive_paint",
 		"webvr_vive_sculpt"
 	],
+	"physics": [
+		"webgl_physics_cloth",
+		"webgl_physics_convex_break",
+		"webgl_physics_rope",
+		"webgl_physics_terrain",
+		"webgl_physics_volume"
+	],
 	"misc": [
 		"misc_animation_authoring",
 		"misc_animation_groups",
@@ -353,12 +360,15 @@ var files = {
 		"misc_controls_trackball",
 		"misc_controls_transform",
 		"misc_exporter_collada",
+		"misc_exporter_draco",
 		"misc_exporter_gltf",
 		"misc_exporter_obj",
 		"misc_exporter_stl",
 		"misc_fps",
 		"misc_lookat",
-		"misc_uv_tests"
+	],
+	"css2d": [
+		"css2d_label"
 	],
 	"css3d": [
 		"css3d_molecules",
@@ -370,9 +380,6 @@ var files = {
 		"css3d_sprites",
 		"css3d_youtube"
 	],
-	"css2d": [
-		"css2d_label"
-	],
 	"raytracing": [
 		"raytracing_sandbox"
 	],
@@ -384,5 +391,9 @@ var files = {
 	"svg": [
 		"svg_lines",
 		"svg_sandbox"
+	],
+	"tests": [
+		"webgl_furnace_test",
+		"misc_uv_tests"
 	]
 };

+ 4 - 2
examples/js/MD2Character.js

@@ -44,8 +44,10 @@ THREE.MD2Character = function () {
 
 		loader.load( config.baseUrl + config.body, function ( geo ) {
 
-			geo.computeBoundingBox();
-			scope.root.position.y = - scope.scale * geo.boundingBox.min.y;
+			var boundingBox = new THREE.Box3();
+			boundingBox.setFromBufferAttribute( geo.attributes.position );
+			
+			scope.root.position.y = - scope.scale * boundingBox.min.y;
 
 			var mesh = createPart( geo, scope.skinsBody[ 0 ] );
 			mesh.scale.set( scope.scale, scope.scale, scope.scale );

+ 4 - 2
examples/js/MD2CharacterComplex.js

@@ -156,8 +156,10 @@ THREE.MD2CharacterComplex = function () {
 
 		loader.load( config.baseUrl + config.body, function( geo ) {
 
-			geo.computeBoundingBox();
-			scope.root.position.y = - scope.scale * geo.boundingBox.min.y;
+			var boundingBox = new THREE.Box3();
+			boundingBox.setFromBufferAttribute( geo.attributes.position );
+
+			scope.root.position.y = - scope.scale * boundingBox.min.y;
 
 			var mesh = createPart( geo, scope.skinsBody[ 0 ] );
 			mesh.scale.set( scope.scale, scope.scale, scope.scale );

+ 273 - 64
examples/js/MarchingCubes.js

@@ -1,6 +1,7 @@
 /**
  * @author alteredq / http://alteredqualia.com/
  * @author mrdoob / http://mrdoob.com
+ * @author chaht01 / http://hyuntak.com
  * Port of http://webglsamples.org/blob/blob.html
  */
 
@@ -14,6 +15,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 	var vlist = new Float32Array( 12 * 3 );
 	var nlist = new Float32Array( 12 * 3 );
+	var clist = new Float32Array( 12 * 3 );
 
 	this.enableUvs = enableUvs !== undefined ? enableUvs : false;
 	this.enableColors = enableColors !== undefined ? enableColors : false;
@@ -45,6 +47,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 		this.field = new Float32Array( this.size3 );
 		this.normal_cache = new Float32Array( this.size3 * 3 );
+		this.palette = new Float32Array( this.size3 * 3 );
 
 		// immediate render mode simulator
 
@@ -83,7 +86,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 	}
 
-	function VIntX( q, offset, isol, x, y, z, valp1, valp2 ) {
+	function VIntX( q, offset, isol, x, y, z, valp1, valp2, c_offset1, c_offset2 ) {
 
 		var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
 			nc = scope.normal_cache;
@@ -96,9 +99,13 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 		nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q + 4 ], mu );
 		nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q + 5 ], mu );
 
+		clist[ offset + 0 ] = lerp( scope.palette[ c_offset1 * 3 + 0 ], scope.palette[ c_offset2 * 3 + 0 ], mu );
+		clist[ offset + 1 ] = lerp( scope.palette[ c_offset1 * 3 + 1 ], scope.palette[ c_offset2 * 3 + 1 ], mu );
+		clist[ offset + 2 ] = lerp( scope.palette[ c_offset1 * 3 + 2 ], scope.palette[ c_offset2 * 3 + 2 ], mu );
+
 	}
 
-	function VIntY( q, offset, isol, x, y, z, valp1, valp2 ) {
+	function VIntY( q, offset, isol, x, y, z, valp1, valp2, c_offset1, c_offset2 ) {
 
 		var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
 			nc = scope.normal_cache;
@@ -113,9 +120,13 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 		nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu );
 		nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu );
 
+		clist[ offset + 0 ] = lerp( scope.palette[ c_offset1 * 3 + 0 ], scope.palette[ c_offset2 * 3 + 0 ], mu );
+		clist[ offset + 1 ] = lerp( scope.palette[ c_offset1 * 3 + 1 ], scope.palette[ c_offset2 * 3 + 1 ], mu );
+		clist[ offset + 2 ] = lerp( scope.palette[ c_offset1 * 3 + 2 ], scope.palette[ c_offset2 * 3 + 2 ], mu );
+
 	}
 
-	function VIntZ( q, offset, isol, x, y, z, valp1, valp2 ) {
+	function VIntZ( q, offset, isol, x, y, z, valp1, valp2, c_offset1, c_offset2 ) {
 
 		var mu = ( isol - valp1 ) / ( valp2 - valp1 ),
 			nc = scope.normal_cache;
@@ -130,6 +141,10 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 		nlist[ offset + 1 ] = lerp( nc[ q + 1 ], nc[ q2 + 1 ], mu );
 		nlist[ offset + 2 ] = lerp( nc[ q + 2 ], nc[ q2 + 2 ], mu );
 
+		clist[ offset + 0 ] = lerp( scope.palette[ c_offset1 * 3 + 0 ], scope.palette[ c_offset2 * 3 + 0 ], mu );
+		clist[ offset + 1 ] = lerp( scope.palette[ c_offset1 * 3 + 1 ], scope.palette[ c_offset2 * 3 + 1 ], mu );
+		clist[ offset + 2 ] = lerp( scope.palette[ c_offset1 * 3 + 2 ], scope.palette[ c_offset2 * 3 + 2 ], mu );
+
 	}
 
 	function compNorm( q ) {
@@ -139,8 +154,10 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 		if ( scope.normal_cache[ q3 ] === 0.0 ) {
 
 			scope.normal_cache[ q3 + 0 ] = scope.field[ q - 1 ] - scope.field[ q + 1 ];
-			scope.normal_cache[ q3 + 1 ] = scope.field[ q - scope.yd ] - scope.field[ q + scope.yd ];
-			scope.normal_cache[ q3 + 2 ] = scope.field[ q - scope.zd ] - scope.field[ q + scope.zd ];
+			scope.normal_cache[ q3 + 1 ] =
+				scope.field[ q - scope.yd ] - scope.field[ q + scope.yd ];
+			scope.normal_cache[ q3 + 2 ] =
+				scope.field[ q - scope.zd ] - scope.field[ q + scope.zd ];
 
 		}
 
@@ -195,7 +212,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( q );
 			compNorm( q1 );
-			VIntX( q * 3, 0, isol, fx, fy, fz, field0, field1 );
+			VIntX( q * 3, 0, isol, fx, fy, fz, field0, field1, q, q1 );
 
 		}
 
@@ -203,7 +220,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( q1 );
 			compNorm( q1y );
-			VIntY( q1 * 3, 3, isol, fx2, fy, fz, field1, field3 );
+			VIntY( q1 * 3, 3, isol, fx2, fy, fz, field1, field3, q1, q1y );
 
 		}
 
@@ -211,7 +228,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( qy );
 			compNorm( q1y );
-			VIntX( qy * 3, 6, isol, fx, fy2, fz, field2, field3 );
+			VIntX( qy * 3, 6, isol, fx, fy2, fz, field2, field3, qy, q1y );
 
 		}
 
@@ -219,7 +236,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( q );
 			compNorm( qy );
-			VIntY( q * 3, 9, isol, fx, fy, fz, field0, field2 );
+			VIntY( q * 3, 9, isol, fx, fy, fz, field0, field2, q, qy );
 
 		}
 
@@ -229,7 +246,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( qz );
 			compNorm( q1z );
-			VIntX( qz * 3, 12, isol, fx, fy, fz2, field4, field5 );
+			VIntX( qz * 3, 12, isol, fx, fy, fz2, field4, field5, qz, q1z );
 
 		}
 
@@ -237,7 +254,18 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( q1z );
 			compNorm( q1yz );
-			VIntY( q1z * 3, 15, isol, fx2, fy, fz2, field5, field7 );
+			VIntY(
+				q1z * 3,
+				15,
+				isol,
+				fx2,
+				fy,
+				fz2,
+				field5,
+				field7,
+				q1z,
+				q1yz
+			);
 
 		}
 
@@ -245,7 +273,18 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( qyz );
 			compNorm( q1yz );
-			VIntX( qyz * 3, 18, isol, fx, fy2, fz2, field6, field7 );
+			VIntX(
+				qyz * 3,
+				18,
+				isol,
+				fx,
+				fy2,
+				fz2,
+				field6,
+				field7,
+				qyz,
+				q1yz
+			);
 
 		}
 
@@ -253,17 +292,16 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( qz );
 			compNorm( qyz );
-			VIntY( qz * 3, 21, isol, fx, fy, fz2, field4, field6 );
+			VIntY( qz * 3, 21, isol, fx, fy, fz2, field4, field6, qz, qyz );
 
 		}
 
 		// vertical lines of the cube
-
 		if ( bits & 256 ) {
 
 			compNorm( q );
 			compNorm( qz );
-			VIntZ( q * 3, 24, isol, fx, fy, fz, field0, field4 );
+			VIntZ( q * 3, 24, isol, fx, fy, fz, field0, field4, q, qz );
 
 		}
 
@@ -271,7 +309,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( q1 );
 			compNorm( q1z );
-			VIntZ( q1 * 3, 27, isol, fx2, fy, fz, field1, field5 );
+			VIntZ( q1 * 3, 27, isol, fx2, fy, fz, field1, field5, q1, q1z );
 
 		}
 
@@ -279,7 +317,18 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( q1y );
 			compNorm( q1yz );
-			VIntZ( q1y * 3, 30, isol, fx2, fy2, fz, field3, field7 );
+			VIntZ(
+				q1y * 3,
+				30,
+				isol,
+				fx2,
+				fy2,
+				fz,
+				field3,
+				field7,
+				q1y,
+				q1yz
+			);
 
 		}
 
@@ -287,13 +336,17 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			compNorm( qy );
 			compNorm( qyz );
-			VIntZ( qy * 3, 33, isol, fx, fy2, fz, field2, field6 );
+			VIntZ( qy * 3, 33, isol, fx, fy2, fz, field2, field6, qy, qyz );
 
 		}
 
 		cubeindex <<= 4; // re-purpose cubeindex into an offset into triTable
 
-		var o1, o2, o3, numtris = 0, i = 0;
+		var o1,
+			o2,
+			o3,
+			numtris = 0,
+			i = 0;
 
 		// here is where triangles are created
 
@@ -303,11 +356,15 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 			o2 = o1 + 1;
 			o3 = o1 + 2;
 
-			posnormtriv( vlist, nlist,
+			posnormtriv(
+				vlist,
+				nlist,
+				clist,
 				3 * THREE.triTable[ o1 ],
 				3 * THREE.triTable[ o2 ],
 				3 * THREE.triTable[ o3 ],
-				renderCallback );
+				renderCallback
+			);
 
 			i += 3;
 			numtris ++;
@@ -322,7 +379,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 	// Immediate render mode simulator
 	/////////////////////////////////////
 
-	function posnormtriv( pos, norm, o1, o2, o3, renderCallback ) {
+	function posnormtriv( pos, norm, colors, o1, o2, o3, renderCallback ) {
 
 		var c = scope.count * 3;
 
@@ -360,7 +417,6 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 			scope.normalArray[ c + 7 ] = ny;
 			scope.normalArray[ c + 8 ] = nz;
 
-
 		} else {
 
 			scope.normalArray[ c + 0 ] = norm[ o1 + 0 ];
@@ -398,17 +454,17 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 		if ( scope.enableColors ) {
 
-			scope.colorArray[ c + 0 ] = pos[ o1 + 0 ];
-			scope.colorArray[ c + 1 ] = pos[ o1 + 1 ];
-			scope.colorArray[ c + 2 ] = pos[ o1 + 2 ];
+			scope.colorArray[ c + 0 ] = colors[ o1 + 0 ];
+			scope.colorArray[ c + 1 ] = colors[ o1 + 1 ];
+			scope.colorArray[ c + 2 ] = colors[ o1 + 2 ];
 
-			scope.colorArray[ c + 3 ] = pos[ o2 + 0 ];
-			scope.colorArray[ c + 4 ] = pos[ o2 + 1 ];
-			scope.colorArray[ c + 5 ] = pos[ o2 + 2 ];
+			scope.colorArray[ c + 3 ] = colors[ o2 + 0 ];
+			scope.colorArray[ c + 4 ] = colors[ o2 + 1 ];
+			scope.colorArray[ c + 5 ] = colors[ o2 + 2 ];
 
-			scope.colorArray[ c + 6 ] = pos[ o3 + 0 ];
-			scope.colorArray[ c + 7 ] = pos[ o3 + 1 ];
-			scope.colorArray[ c + 8 ] = pos[ o3 + 2 ];
+			scope.colorArray[ c + 6 ] = colors[ o3 + 0 ];
+			scope.colorArray[ c + 7 ] = colors[ o3 + 1 ];
+			scope.colorArray[ c + 8 ] = colors[ o3 + 2 ];
 
 		}
 
@@ -484,10 +540,35 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 	// Adds a reciprocal ball (nice and blobby) that, to be fast, fades to zero after
 	// a fixed distance, determined by strength and subtract.
 
-	this.addBall = function ( ballx, bally, ballz, strength, subtract ) {
+	this.addBall = function ( ballx, bally, ballz, strength, subtract, colors ) {
 
 		var sign = Math.sign( strength );
 		strength = Math.abs( strength );
+		var userDefineColor = ! ( colors === undefined || colors === null );
+		var ballColor = new THREE.Color( ballx, bally, ballz );
+		if ( userDefineColor ) {
+
+			try {
+
+				ballColor =
+					colors instanceof THREE.Color
+						? colors
+						: Array.isArray( colors )
+							? new THREE.Color(
+								Math.min( Math.abs( colors[ 0 ] ), 1 ),
+								Math.min( Math.abs( colors[ 1 ] ), 1 ),
+								Math.min( Math.abs( colors[ 2 ] ), 1 )
+						  )
+							: new THREE.Color( colors );
+
+			} catch ( err ) {
+
+				userDefineColor = false;
+				ballColor = new THREE.Color( ballx, bally, ballz );
+
+			}
+
+		}
 
 		// Let's solve the equation to find the radius:
 		// 1.0 / (0.000001 + radius^2) * strength - subtract = 0
@@ -501,19 +582,23 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 			ys = bally * this.size,
 			xs = ballx * this.size;
 
-		var min_z = Math.floor( zs - radius ); if ( min_z < 1 ) min_z = 1;
-		var max_z = Math.floor( zs + radius ); if ( max_z > this.size - 1 ) max_z = this.size - 1;
-		var min_y = Math.floor( ys - radius ); if ( min_y < 1 ) min_y = 1;
-		var max_y = Math.floor( ys + radius ); if ( max_y > this.size - 1 ) max_y = this.size - 1;
-		var min_x = Math.floor( xs - radius ); if ( min_x < 1 ) min_x = 1;
-		var max_x = Math.floor( xs + radius ); if ( max_x > this.size - 1 ) max_x = this.size - 1;
-
+		var min_z = Math.floor( zs - radius );
+		if ( min_z < 1 ) min_z = 1;
+		var max_z = Math.floor( zs + radius );
+		if ( max_z > this.size - 1 ) max_z = this.size - 1;
+		var min_y = Math.floor( ys - radius );
+		if ( min_y < 1 ) min_y = 1;
+		var max_y = Math.floor( ys + radius );
+		if ( max_y > this.size - 1 ) max_y = this.size - 1;
+		var min_x = Math.floor( xs - radius );
+		if ( min_x < 1 ) min_x = 1;
+		var max_x = Math.floor( xs + radius );
+		if ( max_x > this.size - 1 ) max_x = this.size - 1;
 
 		// Don't polygonize in the outer layer because normals aren't
 		// well-defined there.
 
 		var x, y, z, y_offset, z_offset, fx, fy, fz, fz2, fy2, val;
-
 		for ( z = min_z; z < max_z; z ++ ) {
 
 			z_offset = this.size2 * z;
@@ -530,7 +615,21 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 					fx = x / this.size - ballx;
 					val = strength / ( 0.000001 + fx * fx + fy2 + fz2 ) - subtract;
-					if ( val > 0.0 ) this.field[ y_offset + x ] += val * sign;
+					if ( val > 0.0 ) {
+
+						this.field[ y_offset + x ] += val * sign;
+
+						// optimization
+						// http://www.geisswerks.com/ryan/BLOBS/blobs.html
+						const ratio =
+							Math.sqrt( ( x - xs ) * ( x - xs ) + ( y - ys ) * ( y - ys ) + ( z - zs ) * ( z - zs ) ) / radius;
+						const contrib =
+							1 - ratio * ratio * ratio * ( ratio * ( ratio * 6 - 15 ) + 10 );
+						this.palette[ ( y_offset + x ) * 3 + 0 ] += ballColor.r * contrib;
+						this.palette[ ( y_offset + x ) * 3 + 1 ] += ballColor.g * contrib;
+						this.palette[ ( y_offset + x ) * 3 + 2 ] += ballColor.b * contrib;
+
+					}
 
 				}
 
@@ -542,14 +641,18 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 	this.addPlaneX = function ( strength, subtract ) {
 
-		var x, y, z, xx, val, xdiv, cxy,
-
+		var x,
+			y,
+			z,
+			xx,
+			val,
+			xdiv,
+			cxy,
 			// cache attribute lookups
 			size = this.size,
 			yd = this.yd,
 			zd = this.zd,
 			field = this.field,
-
 			dist = size * Math.sqrt( strength / subtract );
 
 		if ( dist > size ) dist = size;
@@ -582,14 +685,19 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 	this.addPlaneY = function ( strength, subtract ) {
 
-		var x, y, z, yy, val, ydiv, cy, cxy,
-
+		var x,
+			y,
+			z,
+			yy,
+			val,
+			ydiv,
+			cy,
+			cxy,
 			// cache attribute lookups
 			size = this.size,
 			yd = this.yd,
 			zd = this.zd,
 			field = this.field,
-
 			dist = size * Math.sqrt( strength / subtract );
 
 		if ( dist > size ) dist = size;
@@ -608,8 +716,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 					cxy = cy + x;
 
-					for ( z = 0; z < size; z ++ )
-						field[ zd * z + cxy ] += val;
+					for ( z = 0; z < size; z ++ ) field[ zd * z + cxy ] += val;
 
 				}
 
@@ -621,14 +728,19 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 	this.addPlaneZ = function ( strength, subtract ) {
 
-		var x, y, z, zz, val, zdiv, cz, cyz,
-
+		var x,
+			y,
+			z,
+			zz,
+			val,
+			zdiv,
+			cz,
+			cyz,
 			// cache attribute lookups
 			size = this.size,
 			yd = this.yd,
 			zd = this.zd,
 			field = this.field,
-
 			dist = size * Math.sqrt( strength / subtract );
 
 		if ( dist > size ) dist = size;
@@ -646,8 +758,7 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 					cyz = cz + y * yd;
 
-					for ( x = 0; x < size; x ++ )
-						field[ cyz + x ] += val;
+					for ( x = 0; x < size; x ++ ) field[ cyz + x ] += val;
 
 				}
 
@@ -661,6 +772,79 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 	// Updates
 	/////////////////////////////////////
 
+	this.setCell = function ( x, y, z, value ) {
+
+		var index = this.size2 * z + this.size * y + x;
+		this.field[ index ] = value;
+
+	};
+
+	this.getCell = function ( x, y, z ) {
+
+		var index = this.size2 * z + this.size * y + x;
+		return this.field[ index ];
+
+	};
+
+	this.blur = function ( intensity ) {
+
+		if ( intensity === undefined ) {
+
+			intensity = 1;
+
+		}
+
+		var field = this.field;
+		var fieldCopy = field.slice();
+		var size = this.size;
+		var size2 = this.size2;
+		for ( var x = 0; x < size; x ++ ) {
+
+			for ( var y = 0; y < size; y ++ ) {
+
+				for ( var z = 0; z < size; z ++ ) {
+
+					var index = size2 * z + size * y + x;
+					var val = fieldCopy[ index ];
+					var count = 1;
+
+					for ( var x2 = - 1; x2 <= 1; x2 += 2 ) {
+
+						var x3 = x2 + x;
+						if ( x3 < 0 || x3 >= size ) continue;
+
+						for ( var y2 = - 1; y2 <= 1; y2 += 2 ) {
+
+							var y3 = y2 + y;
+							if ( y3 < 0 || y3 >= size ) continue;
+
+							for ( var z2 = - 1; z2 <= 1; z2 += 2 ) {
+
+								var z3 = z2 + z;
+								if ( z3 < 0 || z3 >= size ) continue;
+
+								var index2 = size2 * z3 + size * y3 + x3;
+								var val2 = fieldCopy[ index2 ];
+
+								count ++;
+								val += intensity * ( val2 - val ) / count;
+
+							}
+
+						}
+
+					}
+
+					field[ index ] = val;
+
+				}
+
+			}
+
+		}
+
+	};
+
 	this.reset = function () {
 
 		var i;
@@ -671,6 +855,9 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 			this.normal_cache[ i * 3 ] = 0.0;
 			this.field[ i ] = 0.0;
+			this.palette[ i * 3 ] = this.palette[ i * 3 + 1 ] = this.palette[
+				i * 3 + 2
+			] = 0.0;
 
 		}
 
@@ -713,7 +900,9 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 	this.generateGeometry = function () {
 
-		console.warn( 'THREE.MarchingCubes: generateGeometry() now returns THREE.BufferGeometry' );
+		console.warn(
+			"THREE.MarchingCubes: generateGeometry() now returns THREE.BufferGeometry"
+		);
 		return this.generateBufferGeometry();
 
 	};
@@ -738,10 +927,26 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 		var geo_callback = function ( object ) {
 
-			if ( scope.hasPositions ) posArray = concatenate( posArray, object.positionArray, object.count * 3 );
-			if ( scope.hasNormals ) normArray = concatenate( normArray, object.normalArray, object.count * 3 );
-			if ( scope.hasColors ) colorArray = concatenate( colorArray, object.colorArray, object.count * 3 );
-			if ( scope.hasUvs ) uvArray = concatenate( uvArray, object.uvArray, object.count * 2 );
+			if ( scope.hasPositions )
+				posArray = concatenate(
+					posArray,
+					object.positionArray,
+					object.count * 3
+				);
+			if ( scope.hasNormals )
+				normArray = concatenate(
+					normArray,
+					object.normalArray,
+					object.count * 3
+				);
+			if ( scope.hasColors )
+				colorArray = concatenate(
+					colorArray,
+					object.colorArray,
+					object.count * 3
+				);
+			if ( scope.hasUvs )
+				uvArray = concatenate( uvArray, object.uvArray, object.count * 2 );
 
 			object.count = 0;
 
@@ -749,10 +954,14 @@ THREE.MarchingCubes = function ( resolution, material, enableUvs, enableColors )
 
 		this.render( geo_callback );
 
-		if ( this.hasPositions ) geo.addAttribute( 'position', new THREE.BufferAttribute( posArray, 3 ) );
-		if ( this.hasNormals ) geo.addAttribute( 'normal', new THREE.BufferAttribute( normArray, 3 ) );
-		if ( this.hasColors ) geo.addAttribute( 'color', new THREE.BufferAttribute( colorArray, 3 ) );
-		if ( this.hasUvs ) geo.addAttribute( 'uv', new THREE.BufferAttribute( uvArray, 2 ) );
+		if ( this.hasPositions )
+			geo.addAttribute( "position", new THREE.BufferAttribute( posArray, 3 ) );
+		if ( this.hasNormals )
+			geo.addAttribute( "normal", new THREE.BufferAttribute( normArray, 3 ) );
+		if ( this.hasColors )
+			geo.addAttribute( "color", new THREE.BufferAttribute( colorArray, 3 ) );
+		if ( this.hasUvs )
+			geo.addAttribute( "uv", new THREE.BufferAttribute( uvArray, 2 ) );
 
 		return geo;
 

+ 25 - 22
examples/js/animation/MMDPhysics.js

@@ -994,14 +994,8 @@ THREE.MMDPhysics = ( function () {
 		_getWorldTransformForBone: function () {
 
 			var manager = this.manager;
-
-			var tr = manager.allocTransform();
-			this.body.getMotionState().getWorldTransform( tr );
-			var tr2 = manager.multiplyTransforms( tr, this.boneOffsetFormInverse );
-
-			manager.freeTransform( tr );
-
-			return tr2;
+			var tr = this.body.getCenterOfMassTransform();
+			return manager.multiplyTransforms( tr, this.boneOffsetFormInverse );
 
 		},
 
@@ -1057,7 +1051,11 @@ THREE.MMDPhysics = ( function () {
 			//this.bone.quaternion.multiply( thQ2 );
 
 			thQ3.setFromRotationMatrix( this.bone.matrix );
-			this.bone.quaternion.copy( thQ2.multiply( thQ3 ) );
+
+			// Renormalizing quaternion here because repeatedly transforming
+			// quaternion continuously accumulates floating point error and
+			// can end up being overflow. See #15335
+			this.bone.quaternion.copy( thQ2.multiply( thQ3 ).normalize() );
 
 			manager.freeThreeQuaternion( thQ );
 			manager.freeThreeQuaternion( thQ2 );
@@ -1072,19 +1070,24 @@ THREE.MMDPhysics = ( function () {
 
 			var manager = this.manager;
 
-			var tr = this.body.getCenterOfMassTransform();
-			var origin = tr.getOrigin();
-			
-			var matrixInv = manager.allocThreeMatrix4();
-			matrixInv.copy( this.bone.parent.matrixWorld ).getInverse( matrixInv );
-			
-			var pos = manager.allocThreeVector3();
-			pos.set( origin.x(), origin.y(), origin.z() ).applyMatrix4( matrixInv );
-
-			this.bone.position.copy( pos );
-
-			manager.freeThreeVector3( pos );
-			manager.freeThreeMatrix4( matrixInv );
+			var tr = this._getWorldTransformForBone();
+
+			var thV = manager.allocThreeVector3();
+
+			var o = manager.getOrigin( tr );
+			thV.set( o.x(), o.y(), o.z() );
+
+			if ( this.bone.parent ) {
+
+				this.bone.parent.worldToLocal( thV );
+
+			}
+
+			this.bone.position.copy( thV );
+
+			manager.freeThreeVector3( thV );
+
+			manager.freeTransform( tr );
 
 		}
 

+ 14 - 14
examples/js/controls/EditorControls.js

@@ -13,7 +13,7 @@ THREE.EditorControls = function ( object, domElement ) {
 
 	this.enabled = true;
 	this.center = new THREE.Vector3();
-	this.panSpeed = 0.001;
+	this.panSpeed = 0.002;
 	this.zoomSpeed = 0.1;
 	this.rotationSpeed = 0.005;
 
@@ -104,8 +104,8 @@ THREE.EditorControls = function ( object, domElement ) {
 
 		spherical.setFromVector3( vector );
 
-		spherical.theta += delta.x;
-		spherical.phi += delta.y;
+		spherical.theta += delta.x * scope.rotationSpeed;
+		spherical.phi += delta.y * scope.rotationSpeed;
 
 		spherical.makeSafe();
 
@@ -159,7 +159,7 @@ THREE.EditorControls = function ( object, domElement ) {
 
 		if ( state === STATE.ROTATE ) {
 
-			scope.rotate( delta.set( - movementX * scope.rotationSpeed, - movementY * scope.rotationSpeed, 0 ) );
+			scope.rotate( delta.set( - movementX, - movementY, 0 ) );
 
 		} else if ( state === STATE.ZOOM ) {
 
@@ -235,13 +235,13 @@ THREE.EditorControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 
 			case 1:
-				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
-				touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+				touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
 				break;
 
 			case 2:
-				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
-				touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 );
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+				touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
 				prevDistance = touches[ 0 ].distanceTo( touches[ 1 ] );
 				break;
 
@@ -277,14 +277,14 @@ THREE.EditorControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 
 			case 1:
-				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
-				touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
-				scope.rotate( touches[ 0 ].sub( getClosest( touches[ 0 ], prevTouches ) ).multiplyScalar( - scope.rotationSpeed ) );
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+				touches[ 1 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+				scope.rotate( touches[ 0 ].sub( getClosest( touches[ 0 ], prevTouches ) ).multiplyScalar( - 1 ) );
 				break;
 
 			case 2:
-				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 );
-				touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 );
+				touches[ 0 ].set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
+				touches[ 1 ].set( event.touches[ 1 ].pageX, event.touches[ 1 ].pageY, 0 ).divideScalar( window.devicePixelRatio );
 				var distance = touches[ 0 ].distanceTo( touches[ 1 ] );
 				scope.zoom( delta.set( 0, 0, prevDistance - distance ) );
 				prevDistance = distance;
@@ -295,7 +295,7 @@ THREE.EditorControls = function ( object, domElement ) {
 				offset0.x = - offset0.x;
 				offset1.x = - offset1.x;
 
-				scope.pan( offset0.add( offset1 ).multiplyScalar( 0.5 ) );
+				scope.pan( offset0.add( offset1 ) );
 
 				break;
 

+ 20 - 7
examples/js/controls/TransformControls.js

@@ -128,6 +128,13 @@ THREE.TransformControls = function ( camera, domElement ) {
 		domElement.removeEventListener( "touchcancel", onPointerUp );
 		domElement.removeEventListener( "touchleave", onPointerUp );
 
+		this.traverse( function ( child ) {
+
+			if ( child.geometry ) child.geometry.dispose();
+			if ( child.material ) child.material.dispose();
+
+		} );
+
 	};
 
 	// Set current object
@@ -396,27 +403,33 @@ THREE.TransformControls = function ( camera, domElement ) {
 
 				if ( pointEnd.dot( pointStart ) < 0 ) d *= -1;
 
-				_tempVector.set( d, d, d );
+				_tempVector2.set( d, d, d );
 
 			} else {
 
-				_tempVector.copy( pointEnd ).divide( pointStart );
+				_tempVector.copy(pointStart);
+				_tempVector2.copy(pointEnd);
+
+				_tempVector.applyQuaternion( worldQuaternionInv );
+				_tempVector2.applyQuaternion( worldQuaternionInv );
+
+				_tempVector2.divide( _tempVector );
 
 				if ( axis.search( 'X' ) === -1 ) {
-					_tempVector.x = 1;
+					_tempVector2.x = 1;
 				}
 				if ( axis.search( 'Y' ) === -1 ) {
-					_tempVector.y = 1;
+					_tempVector2.y = 1;
 				}
 				if ( axis.search( 'Z' ) === -1 ) {
-					_tempVector.z = 1;
+					_tempVector2.z = 1;
 				}
 
 			}
 
 			// Apply scale
 
-			object.scale.copy( scaleStart ).multiply( _tempVector );
+			object.scale.copy( scaleStart ).multiply( _tempVector2 );
 
 		} else if ( mode === 'rotate' ) {
 
@@ -1183,7 +1196,7 @@ THREE.TransformControlsGizmo = function () {
 
 				var AXIS_HIDE_TRESHOLD = 0.99;
 				var PLANE_HIDE_TRESHOLD = 0.2;
-				var AXIS_FLIP_TRESHOLD = -0.4;
+				var AXIS_FLIP_TRESHOLD = 0.0;
 
 
 				if ( handle.name === 'X' || handle.name === 'XYZX' ) {

+ 3 - 3
examples/js/effects/OutlineEffect.js

@@ -66,9 +66,9 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 	};
 
 	var uniformsChunk = {
-		outlineThickness: { type: "f", value: defaultThickness },
-		outlineColor: { type: "c", value: defaultColor },
-		outlineAlpha: { type: "f", value: defaultAlpha }
+		outlineThickness: { value: defaultThickness },
+		outlineColor: { value: defaultColor },
+		outlineAlpha: { value: defaultAlpha }
 	};
 
 	var vertexShaderChunk = [

+ 206 - 0
examples/js/exporters/DracoExporter.js

@@ -0,0 +1,206 @@
+'use strict';
+
+/**
+ * Export draco compressed files from threejs geometry objects.
+ *
+ * Draco files are compressed and usually are smaller than conventional 3D file formats.
+ *
+ * The exporter receives a options object containing
+ *  - decodeSpeed, indicates how to tune the encoder regarding decode speed (0 gives better speed but worst quality)
+ *  - encodeSpeed, indicates how to tune the encoder parameters (0 gives better speed but worst quality)
+ *  - encoderMethod
+ *  - quantization, indicates the presision of each type of data stored in the draco file in the order (POSITION, NORMAL, COLOR, TEX_COORD, GENERIC)
+ *  - exportUvs
+ *  - exportNormals
+ *
+ * @class DRACOExporter
+ * @author tentone
+ */
+
+THREE.DRACOExporter = function () {};
+
+THREE.DRACOExporter.prototype = {
+
+	constructor: THREE.DRACOExporter,
+
+	parse: function ( geometry, options ) {
+
+
+		if ( DracoEncoderModule === undefined ) {
+
+			throw new Error( 'THREE.DRACOExporter: required the draco_decoder to work.' );
+
+		}
+
+		if ( options === undefined ) {
+
+			options = {
+
+				decodeSpeed: 5,
+				encodeSpeed: 5,
+				encoderMethod: THREE.DRACOExporter.MESH_EDGEBREAKER_ENCODING,
+				quantization: [ 16, 8, 8, 8, 8 ],
+				exportUvs: true,
+				exportNormals: true,
+				exportColor: false,
+
+			};
+
+		}
+
+		var dracoEncoder = DracoEncoderModule();
+		var encoder = new dracoEncoder.Encoder();
+		var builder = new dracoEncoder.MeshBuilder();
+		var mesh = new dracoEncoder.Mesh();
+
+		if ( geometry.isGeometry === true ) {
+
+			var bufferGeometry = new THREE.BufferGeometry();
+			bufferGeometry.fromGeometry( geometry );
+			geometry = bufferGeometry;
+
+		}
+
+		if ( geometry.isBufferGeometry !== true ) {
+
+			throw new Error( 'THREE.DRACOExporter.parse(geometry, options): geometry is not a THREE.Geometry or THREE.BufferGeometry instance.' );
+
+		}
+
+		var vertices = geometry.getAttribute( 'position' );
+		builder.AddFloatAttributeToMesh( mesh, dracoEncoder.POSITION, vertices.count, vertices.itemSize, vertices.array );
+
+		var faces = geometry.getIndex();
+
+		if ( faces !== null ) {
+
+			builder.AddFacesToMesh( mesh, faces.count, faces.array );
+
+		} else {
+
+			var faces = new ( vertices.count > 65535 ? Uint32Array : Uint16Array ) ( vertices.count );
+
+			for ( var i = 0; i < faces.length; i ++ ) {
+
+				faces[ i ] = i;
+
+			}
+
+			builder.AddFacesToMesh( mesh, vertices.count, faces );
+
+		}
+
+		if ( options.exportNormals === true ) {
+
+			var normals = geometry.getAttribute( 'normal' );
+
+			if ( normals !== undefined ) {
+
+				builder.AddFloatAttributeToMesh( mesh, dracoEncoder.NORMAL, normals.count, normals.itemSize, normals.array );
+
+			}
+
+		}
+
+		if ( options.exportUvs === true ) {
+
+			var uvs = geometry.getAttribute( 'uv' );
+
+			if ( uvs !== undefined ) {
+
+				builder.AddFloatAttributeToMesh( mesh, dracoEncoder.TEX_COORD, uvs.count, uvs.itemSize, uvs.array );
+
+			}
+
+		}
+
+		if ( options.exportColor === true ) {
+
+			var colors = geometry.getAttribute( 'color' );
+
+			if ( colors !== undefined ) {
+
+				builder.AddFloatAttributeToMesh( mesh, dracoEncoder.COLOR, colors.count, colors.itemSize, colors.array );
+
+			}
+
+		}
+
+		//Compress using draco encoder
+
+		var encodedData = new dracoEncoder.DracoInt8Array();
+
+		//Sets the desired encoding and decoding speed for the given options from 0 (slowest speed, but the best compression) to 10 (fastest, but the worst compression).
+
+		encoder.SetSpeedOptions( options.encodeSpeed || 5, options.decodeSpeed || 5 );
+
+		// Sets the desired encoding method for a given geometry.
+
+		if ( options.encoderMethod !== undefined ) {
+
+			encoder.SetEncodingMethod( options.encoderMethod );
+
+		}
+
+		// Sets the quantization (number of bits used to represent) compression options for a named attribute.
+		// The attribute values will be quantized in a box defined by the maximum extent of the attribute values.
+		if ( options.quantization !== undefined ) {
+
+			for ( var i = 0; i < 5; i ++ ) {
+
+				if ( options.quantization[ i ] !== undefined ) {
+
+					encoder.SetAttributeQuantization( i, options.quantization[ i ] );
+
+				}
+
+			}
+
+		}
+
+		var length = encoder.EncodeMeshToDracoBuffer( mesh, encodedData );
+		dracoEncoder.destroy( mesh );
+
+		if ( length === 0 ) {
+
+			throw new Error( 'THREE.DRACOExporter: Draco encoding failed.' );
+
+		}
+
+		//Copy encoded data to buffer.
+		var outputData = new Int8Array( new ArrayBuffer( length ) );
+
+		for ( var i = 0; i < length; i ++ ) {
+
+			outputData[ i ] = encodedData.GetValue( i );
+
+		}
+
+		dracoEncoder.destroy( encodedData );
+		dracoEncoder.destroy( encoder );
+		dracoEncoder.destroy( builder );
+
+		return outputData;
+
+	}
+
+};
+
+// Encoder methods
+
+THREE.DRACOExporter.MESH_EDGEBREAKER_ENCODING = 1;
+THREE.DRACOExporter.MESH_SEQUENTIAL_ENCODING = 0;
+
+// Geometry type
+
+THREE.DRACOExporter.POINT_CLOUD = 0;
+THREE.DRACOExporter.TRIANGULAR_MESH = 1;
+
+// Attribute type
+
+THREE.DRACOExporter.INVALID = - 1;
+THREE.DRACOExporter.POSITION = 0;
+THREE.DRACOExporter.NORMAL = 1;
+THREE.DRACOExporter.COLOR = 2;
+THREE.DRACOExporter.TEX_COORD = 3;
+THREE.DRACOExporter.GENERIC = 4;

+ 62 - 29
examples/js/exporters/GLTFExporter.js

@@ -80,7 +80,8 @@ THREE.GLTFExporter.prototype = {
 			embedImages: true,
 			animations: [],
 			forceIndices: false,
-			forcePowerOfTwoTextures: false
+			forcePowerOfTwoTextures: false,
+			includeCustomExtensions: false
 		};
 
 		options = Object.assign( {}, DEFAULT_OPTIONS, options );
@@ -340,21 +341,50 @@ THREE.GLTFExporter.prototype = {
 		 * Serializes a userData.
 		 *
 		 * @param {THREE.Object3D|THREE.Material} object
-		 * @returns {Object}
+		 * @param {Object} gltfProperty
 		 */
-		function serializeUserData( object ) {
+		function serializeUserData( object, gltfProperty ) {
+
+			if ( Object.keys( object.userData ).length === 0 ) {
+
+				return;
+
+			}
 
 			try {
 
-				return JSON.parse( JSON.stringify( object.userData ) );
+				var json = JSON.parse( JSON.stringify( object.userData ) );
+
+				if ( options.includeCustomExtensions && json.gltfExtensions ) {
+
+					if ( gltfProperty.extensions === undefined ) {
+
+						gltfProperty.extensions = {};
+
+					}
+
+					for ( var extensionName in json.gltfExtensions ) {
+
+						gltfProperty.extensions[ extensionName ] = json.gltfExtensions[ extensionName ];
+						extensionsUsed[ extensionName ] = true;
+
+					}
+
+					delete json.gltfExtensions;
+
+				}
+
+				if ( Object.keys( json ).length > 0 ) {
+
+					gltfProperty.extras = json;
+
+				}
 
 			} catch ( error ) {
 
 				console.warn( 'THREE.GLTFExporter: userData of \'' + object.name + '\' ' +
 					'won\'t be serialized because of JSON.stringify error - ' + error.message );
 
-				return {};
-
 			}
 
 		}
@@ -1025,11 +1055,7 @@ THREE.GLTFExporter.prototype = {
 
 			}
 
-			if ( Object.keys( material.userData ).length > 0 ) {
-
-				gltfMaterial.extras = serializeUserData( material );
-
-			}
+			serializeUserData( material, gltfMaterial );
 
 			outputJSON.materials.push( gltfMaterial );
 
@@ -1136,9 +1162,22 @@ THREE.GLTFExporter.prototype = {
 			var modifiedAttribute = null;
 			for ( var attributeName in geometry.attributes ) {
 
+				// Ignore morph target attributes, which are exported later.
+				if ( attributeName.substr( 0, 5 ) === 'morph' ) continue;
+
 				var attribute = geometry.attributes[ attributeName ];
 				attributeName = nameConversion[ attributeName ] || attributeName.toUpperCase();
 
+				// Prefix all geometry attributes except the ones specifically
+				// listed in the spec; non-spec attributes are considered custom.
+				var validVertexAttributes =
+						/^(POSITION|NORMAL|TANGENT|TEXCOORD_\d+|COLOR_\d+|JOINTS_\d+|WEIGHTS_\d+)$/;
+				if ( ! validVertexAttributes.test( attributeName ) ) {
+
+					attributeName = '_' + attributeName;
+
+				}
+
 				if ( cachedData.attributes.has( attribute ) ) {
 
 					attributes[ attributeName ] = cachedData.attributes.get( attribute );
@@ -1158,15 +1197,11 @@ THREE.GLTFExporter.prototype = {
 
 				}
 
-				if ( attributeName.substr( 0, 5 ) !== 'MORPH' ) {
+				var accessor = processAccessor( modifiedAttribute || attribute, geometry );
+				if ( accessor !== null ) {
 
-					var accessor = processAccessor( modifiedAttribute || attribute, geometry );
-					if ( accessor !== null ) {
-
-						attributes[ attributeName ] = accessor;
-						cachedData.attributes.set( attribute, accessor );
-
-					}
+					attributes[ attributeName ] = accessor;
+					cachedData.attributes.set( attribute, accessor );
 
 				}
 
@@ -1276,8 +1311,6 @@ THREE.GLTFExporter.prototype = {
 
 			}
 
-			var extras = ( Object.keys( geometry.userData ).length > 0 ) ? serializeUserData( geometry ) : undefined;
-
 			var forceIndices = options.forceIndices;
 			var isMultiMaterial = Array.isArray( mesh.material );
 
@@ -1319,7 +1352,7 @@ THREE.GLTFExporter.prototype = {
 					attributes: attributes,
 				};
 
-				if ( extras ) primitive.extras = extras;
+				serializeUserData( geometry, primitive );
 
 				if ( targets.length > 0 ) primitive.targets = targets;
 
@@ -1336,6 +1369,8 @@ THREE.GLTFExporter.prototype = {
 
 					}
 
+					if ( primitive.indices === null ) delete primitive.indices;
+
 				}
 
 				var material = processMaterial( materials[ groups[ i ].materialIndex ] );
@@ -1699,11 +1734,7 @@ THREE.GLTFExporter.prototype = {
 
 			}
 
-			if ( object.userData && Object.keys( object.userData ).length > 0 ) {
-
-				gltfNode.extras = serializeUserData( object );
-
-			}
+			serializeUserData( object, gltfNode );
 
 			if ( object.isMesh || object.isLine || object.isPoints ) {
 
@@ -1734,7 +1765,7 @@ THREE.GLTFExporter.prototype = {
 
 			} else if ( object.isLight ) {
 
-				console.warn( 'THREE.GLTFExporter: Only directional, point, and spot lights are supported.' );
+				console.warn( 'THREE.GLTFExporter: Only directional, point, and spot lights are supported.', object );
 				return null;
 
 			}
@@ -1844,6 +1875,8 @@ THREE.GLTFExporter.prototype = {
 
 			}
 
+			serializeUserData( scene, gltfScene );
+
 		}
 
 		/**
@@ -2125,7 +2158,7 @@ THREE.GLTFExporter.Utils = {
 				console.warn( 'THREE.GLTFExporter: Morph target interpolation mode not yet supported. Using LINEAR instead.' );
 
 				sourceTrack = sourceTrack.clone();
-				sourceTrack.setInterpolation( InterpolateLinear );
+				sourceTrack.setInterpolation( THREE.InterpolateLinear );
 
 			}
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 7 - 3
examples/js/libs/ammo.js


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 3 - 0
examples/js/libs/draco/draco_encoder.js


+ 2 - 2
examples/js/loaders/ColladaLoader.js

@@ -1506,7 +1506,7 @@ THREE.ColladaLoader.prototype = {
 
 			}
 
-			material.name = data.name;
+			material.name = data.name || '';
 
 			function getTexture( textureObject ) {
 
@@ -1834,7 +1834,7 @@ THREE.ColladaLoader.prototype = {
 
 			}
 
-			camera.name = data.name;
+			camera.name = data.name || '';
 
 			return camera;
 

+ 22 - 7
examples/js/loaders/FBXLoader.js

@@ -499,7 +499,7 @@ THREE.FBXLoader = ( function () {
 					break;
 				default:
 					console.warn( 'THREE.FBXLoader: unknown material type "%s". Defaulting to MeshPhongMaterial.', type );
-					material = new THREE.MeshPhongMaterial( { color: 0x3300ff } );
+					material = new THREE.MeshPhongMaterial();
 					break;
 
 			}
@@ -532,11 +532,13 @@ THREE.FBXLoader = ( function () {
 				parameters.color = new THREE.Color().fromArray( materialNode.DiffuseColor.value );
 
 			}
+
 			if ( materialNode.DisplacementFactor ) {
 
 				parameters.displacementScale = materialNode.DisplacementFactor.value;
 
 			}
+
 			if ( materialNode.Emissive ) {
 
 				parameters.emissive = new THREE.Color().fromArray( materialNode.Emissive.value );
@@ -547,31 +549,37 @@ THREE.FBXLoader = ( function () {
 				parameters.emissive = new THREE.Color().fromArray( materialNode.EmissiveColor.value );
 
 			}
+
 			if ( materialNode.EmissiveFactor ) {
 
 				parameters.emissiveIntensity = parseFloat( materialNode.EmissiveFactor.value );
 
 			}
+
 			if ( materialNode.Opacity ) {
 
 				parameters.opacity = parseFloat( materialNode.Opacity.value );
 
 			}
+
 			if ( parameters.opacity < 1.0 ) {
 
 				parameters.transparent = true;
 
 			}
+
 			if ( materialNode.ReflectionFactor ) {
 
 				parameters.reflectivity = materialNode.ReflectionFactor.value;
 
 			}
+
 			if ( materialNode.Shininess ) {
 
 				parameters.shininess = materialNode.Shininess.value;
 
 			}
+
 			if ( materialNode.Specular ) {
 
 				parameters.specular = new THREE.Color().fromArray( materialNode.Specular.value );
@@ -594,7 +602,12 @@ THREE.FBXLoader = ( function () {
 						parameters.bumpMap = self.getTexture( textureMap, child.ID );
 						break;
 
+					case 'Maya|TEX_ao_map':
+						parameters.aoMap = self.getTexture( textureMap, child.ID );
+						break;
+
 					case 'DiffuseColor':
+					case 'Maya|TEX_color_map':
 						parameters.map = self.getTexture( textureMap, child.ID );
 						break;
 
@@ -602,12 +615,12 @@ THREE.FBXLoader = ( function () {
 						parameters.displacementMap = self.getTexture( textureMap, child.ID );
 						break;
 
-
 					case 'EmissiveColor':
 						parameters.emissiveMap = self.getTexture( textureMap, child.ID );
 						break;
 
 					case 'NormalMap':
+					case 'Maya|TEX_normal_map':
 						parameters.normalMap = self.getTexture( textureMap, child.ID );
 						break;
 
@@ -2336,15 +2349,17 @@ THREE.FBXLoader = ( function () {
 
 			var rawClips = this.parseClips();
 
-			if ( rawClips === undefined ) return;
+			if ( rawClips !== undefined ) {
+
+				for ( var key in rawClips ) {
 
-			for ( var key in rawClips ) {
+					var rawClip = rawClips[ key ];
 
-				var rawClip = rawClips[ key ];
+					var clip = this.addClip( rawClip );
 
-				var clip = this.addClip( rawClip );
+					animationClips.push( clip );
 
-				animationClips.push( clip );
+				}
 
 			}
 

+ 2 - 2
examples/js/loaders/GCodeLoader.js

@@ -146,7 +146,7 @@ THREE.GCodeLoader.prototype.parse = function ( data ) {
 		} else if ( cmd === 'G2' || cmd === 'G3' ) {
 
 			//G2/G3 - Arc Movement ( G2 clock wise and G3 counter clock wise )
-			console.warn( 'THREE.GCodeLoader: Arc command not supported' );
+			//console.warn( 'THREE.GCodeLoader: Arc command not supported' );
 
 		} else if ( cmd === 'G90' ) {
 
@@ -170,7 +170,7 @@ THREE.GCodeLoader.prototype.parse = function ( data ) {
 
 		} else {
 
-			console.warn( 'THREE.GCodeLoader: Command not supported:' + cmd );
+			//console.warn( 'THREE.GCodeLoader: Command not supported:' + cmd );
 
 		}
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 236 - 451
examples/js/loaders/GLTFLoader.js


+ 5 - 3
examples/js/loaders/KTXLoader.js

@@ -137,13 +137,15 @@ var KhronosTextureContainer = ( function () {
 		for ( var level = 0; level < mipmapCount; level ++ ) {
 
 			var imageSize = new Int32Array( this.arrayBuffer, dataOffset, 1 )[ 0 ]; // size per face, since not supporting array cubemaps
+			dataOffset += 4; // size of the image + 4 for the imageSize field
+			
 			for ( var face = 0; face < this.numberOfFaces; face ++ ) {
 
-				var byteArray = new Uint8Array( this.arrayBuffer, dataOffset + 4, imageSize );
+				var byteArray = new Uint8Array( this.arrayBuffer, dataOffset, imageSize );
 
 				mipmaps.push( { "data": byteArray, "width": width, "height": height } );
-
-				dataOffset += imageSize + 4; // size of the image + 4 for the imageSize field
+				
+				dataOffset += imageSize;
 				dataOffset += 3 - ( ( imageSize + 3 ) % 4 ); // add padding for odd sized image
 
 			}

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä