Browse Source

Merge remote-tracking branch 'upstream/dev' into normal-packed-material

LeonYuanYao 5 years ago
parent
commit
f35f2fd258
100 changed files with 3248 additions and 5180 deletions
  1. 1 1
      .github/ISSUE_TEMPLATE.md
  2. 196 85
      build/three.js
  3. 542 535
      build/three.min.js
  4. 195 84
      build/three.module.js
  5. 0 1
      docs/api/en/cameras/OrthographicCamera.html
  6. 0 79
      docs/api/en/constants/DrawModes.html
  7. 12 0
      docs/api/en/core/BufferAttribute.html
  8. 7 0
      docs/api/en/core/BufferGeometry.html
  9. 3 3
      docs/api/en/core/Object3D.html
  10. 3 1
      docs/api/en/core/Raycaster.html
  11. 4 4
      docs/api/en/extras/core/Path.html
  12. 7 8
      docs/api/en/helpers/SkeletonHelper.html
  13. 1 2
      docs/api/en/loaders/managers/LoadingManager.html
  14. 6 2
      docs/api/en/materials/Material.html
  15. 2 5
      docs/api/en/materials/MeshBasicMaterial.html
  16. 2 5
      docs/api/en/materials/MeshLambertMaterial.html
  17. 2 5
      docs/api/en/materials/MeshPhongMaterial.html
  18. 2 5
      docs/api/en/materials/MeshStandardMaterial.html
  19. 165 20
      docs/api/en/materials/MeshToonMaterial.html
  20. 2 1
      docs/api/en/math/Box2.html
  21. 4 1
      docs/api/en/math/Box3.html
  22. 2 1
      docs/api/en/math/Frustum.html
  23. 1 1
      docs/api/en/math/Plane.html
  24. 3 4
      docs/api/en/math/Ray.html
  25. 2 1
      docs/api/en/math/Sphere.html
  26. 2 2
      docs/api/en/math/Spherical.html
  27. 2 1
      docs/api/en/math/Triangle.html
  28. 3 0
      docs/api/en/math/Vector3.html
  29. 11 0
      docs/api/en/objects/InstancedMesh.html
  30. 0 15
      docs/api/en/objects/Mesh.html
  31. 11 1
      docs/api/en/renderers/WebGLRenderer.html
  32. 0 79
      docs/api/zh/constants/DrawModes.html
  33. 1 1
      docs/api/zh/core/Geometry.html
  34. 3 1
      docs/api/zh/core/Raycaster.html
  35. 4 4
      docs/api/zh/extras/core/Path.html
  36. 7 6
      docs/api/zh/helpers/SkeletonHelper.html
  37. 6 2
      docs/api/zh/materials/Material.html
  38. 176 24
      docs/api/zh/materials/MeshToonMaterial.html
  39. 3 3
      docs/api/zh/math/Ray.html
  40. 11 0
      docs/api/zh/objects/InstancedMesh.html
  41. 0 14
      docs/api/zh/objects/Mesh.html
  42. 11 1
      docs/api/zh/renderers/WebGLRenderer.html
  43. 9 1
      docs/examples/en/loaders/DRACOLoader.html
  44. 2 1
      docs/examples/en/loaders/GLTFLoader.html
  45. 1 1
      docs/examples/en/loaders/MTLLoader.html
  46. 1 1
      docs/examples/en/loaders/PCDLoader.html
  47. 0 0
      docs/examples/en/math/Lut.html
  48. 86 0
      docs/examples/en/math/MeshSurfaceSampler.html
  49. 10 0
      docs/examples/en/utils/BufferGeometryUtils.html
  50. 9 1
      docs/examples/zh/loaders/DRACOLoader.html
  51. 3 2
      docs/examples/zh/loaders/GLTFLoader.html
  52. 1 1
      docs/examples/zh/loaders/PCDLoader.html
  53. 0 0
      docs/examples/zh/math/Lut.html
  54. 86 0
      docs/examples/zh/math/MeshSurfaceSampler.html
  55. 10 0
      docs/examples/zh/utils/BufferGeometryUtils.html
  56. 6 6
      docs/list.js
  57. 18 17
      docs/manual/en/introduction/How-to-create-VR-content.html
  58. 18 17
      docs/manual/zh/introduction/How-to-create-VR-content.html
  59. 13 0
      docs/prettify/threejs.css
  60. 1 3
      editor/index.html
  61. 25 1
      editor/js/Loader.js
  62. 6 6
      editor/js/Menubar.Examples.js
  63. 36 0
      editor/js/Menubar.File.js
  64. 1 0
      editor/js/Sidebar.Material.js
  65. 1 1
      editor/js/Sidebar.Project.js
  66. 17 1
      editor/js/Strings.js
  67. 2 2
      editor/js/libs/app.js
  68. 5 2
      editor/sw.js
  69. 0 5
      examples/css3d_molecules.html
  70. 16 2
      examples/css3d_panorama_deviceorientation.html
  71. 22 21
      examples/files.js
  72. 25 2
      examples/js/controls/DeviceOrientationControls.js
  73. 10 2
      examples/js/controls/OrbitControls.js
  74. 95 105
      examples/js/effects/OutlineEffect.js
  75. 12 21
      examples/js/exporters/GLTFExporter.js
  76. 1 1
      examples/js/exporters/OBJExporter.js
  77. 12 27
      examples/js/exporters/PLYExporter.js
  78. 123 1
      examples/js/lights/LightProbeGenerator.js
  79. 3 1
      examples/js/lines/LineMaterial.js
  80. 192 8
      examples/js/loaders/3MFLoader.js
  81. 8 0
      examples/js/loaders/DRACOLoader.js
  82. 293 93
      examples/js/loaders/EXRLoader.js
  83. 15 17
      examples/js/loaders/FBXLoader.js
  84. 210 132
      examples/js/loaders/GLTFLoader.js
  85. 2 0
      examples/js/loaders/LWOLoader.js
  86. 1 0
      examples/js/loaders/MD2Loader.js
  87. 1 0
      examples/js/loaders/MMDLoader.js
  88. 1 1
      examples/js/loaders/MTLLoader.js
  89. 9 0
      examples/js/loaders/OBJLoader.js
  90. 97 7
      examples/js/loaders/PCDLoader.js
  91. 279 59
      examples/js/loaders/VRMLLoader.js
  92. 0 2219
      examples/js/loaders/deprecated/LegacyGLTFLoader.js
  93. 0 821
      examples/js/loaders/deprecated/LegacyJSONLoader.js
  94. 0 305
      examples/js/misc/CarControls.js
  95. 27 13
      examples/js/modifiers/SubdivisionModifier.js
  96. 3 3
      examples/js/objects/Fire.js
  97. 3 3
      examples/js/objects/Reflector.js
  98. 3 3
      examples/js/objects/Refractor.js
  99. 3 3
      examples/js/objects/Water.js
  100. 0 233
      examples/js/pmrem/PMREMCubeUVPacker.js

+ 1 - 1
.github/ISSUE_TEMPLATE.md

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

File diff suppressed because it is too large
+ 196 - 85
build/three.js


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


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


+ 0 - 1
docs/api/en/cameras/OrthographicCamera.html

@@ -33,7 +33,6 @@
 		<p>[example:webgl_rtt rtt ]</p>
 		<p>[example:webgl_shaders_tonemapping shaders / tonemapping ]</p>
 		<p>[example:webgl_shadowmap shadowmap ]</p>
-		<p>[example:webgl_terrain_dynamic terrain / dynamic ]</p>
 
 		<code>var camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
 scene.add( camera );</code>

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

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

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

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

+ 7 - 0
docs/api/en/core/BufferGeometry.html

@@ -144,6 +144,13 @@
 			Hashmap of [page:BufferAttribute]s holding details of the geometry's [page:Geometry.morphTargets morphTargets].
 		</p>
 
+		<h3>[property:Boolean morphTargetsRelative]</h3>
+		<p>
+			Used to control the morph target behavior; when set to true, the morph target data is treated as relative offsets, rather than as absolute positions/normals.
+
+			Default is *false*.
+		</p>
+
 		<h3>[property:String name]</h3>
 		<p>
 		Optional name for this bufferGeometry instance. Default is an empty string.

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

@@ -240,7 +240,7 @@
 		<p>
 		id -- Unique number of the object instance<br /><br />
 
-		Searches through the object's children and returns the first with a matching id.<br />
+		Searches through an object and its children, starting with the object itself, and returns the first with a matching id.<br />
 		Note that ids are assigned in chronological order: 1, 2, 3, ..., incrementing by one for each new object.
 		</p>
 
@@ -248,7 +248,7 @@
 		<p>
 		name -- String to match to the children's Object3D.name property. <br /><br />
 
-		Searches through the object's children and returns the first with a matching name.<br />
+		Searches through an object and its children, starting with the object itself, and returns the first with a matching name.<br />
 		Note that for most objects the name is an empty string by default. You will
 		have to set it manually to make use of this method.
 		</p>
@@ -258,7 +258,7 @@
 		name -- the property name to search for. <br />
 		value -- value of the given property. <br /><br />
 
-		Searches through the object's children and returns the first with a property that matches the value given.
+		Searches through an object and its children, starting with the object itself, and returns the first with a property that matches the value given.
 		</p>
 
 		<h3>[method:Vector3 getWorldPosition]( [param:Vector3 target] )</h3>

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

@@ -58,6 +58,7 @@
 			Examples: [example:webgl_interactive_cubes Raycasting to a Mesh]<br />
 			[example:webgl_interactive_cubes_ortho Raycasting to a Mesh in using an OrthographicCamera]<br />
 			[example:webgl_interactive_buffergeometry Raycasting to a Mesh with BufferGeometry]<br />
+			[example:webgl_instancing_raycast Raycasting to a InstancedMesh]<br />
 			[example:webgl_interactive_lines Raycasting to a Line]<br />
 			[example:webgl_interactive_raycasting_points Raycasting to Points]<br />
 			[example:webgl_geometry_terrain_raycast Terrain raycasting]<br />
@@ -170,7 +171,8 @@
 			[page:Integer faceIndex] – index of the intersected face<br />
 			[page:Object3D object] – the intersected object<br />
 			[page:Vector2 uv] - U,V coordinates at point of intersection<br />
-			[page:Vector2 uv2] - Second set of U,V coordinates at point of intersection
+			[page:Vector2 uv2] - Second set of U,V coordinates at point of intersection<br />
+			[page:Integer instanceId] – The index number of the instance where the ray intersects the InstancedMesh
 		</p>
 		<p>
 		*Raycaster* delegates to the [page:Object3D.raycast raycast] method of the passed object, when evaluating whether the ray intersects the object or not. This allows [page:Mesh meshes] to respond differently to ray casting than [page:Line lines] and [page:Points pointclouds].

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

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

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

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

+ 1 - 2
docs/api/en/loaders/managers/LoadingManager.html

@@ -26,8 +26,7 @@
 			[example:webgl_loader_fbx WebGL / loader / fbx]<br />
 			[example:webgl_loader_obj WebGL / loader / obj]<br />
 			[example:webgl_materials_reflectivity WebGL / materials / reflectivity]<br />
-			[example:webgl_postprocessing_outline WebGL / postprocesing / outline]<br />
-			[example:webgl_terrain_dynamic WebGL / terrain / dynamic]
+			[example:webgl_postprocessing_outline WebGL / postprocesing / outline]
 		</p>
 
 		<p>

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

@@ -186,8 +186,7 @@
 
 		<h3>[property:Boolean needsUpdate]</h3>
 		<p>
-		Specifies that the material needs to be recompiled.<br />
-		This property is automatically set to *true* when instancing a new material.
+		Specifies that the material needs to be recompiled.
 		</p>
 
 		<h3>[property:Float opacity]</h3>
@@ -296,6 +295,11 @@
 		This gets automatically assigned, so this shouldn't be edited.
 		</p>
 
+		<h3>[property:Integer version]</h3>
+		<p>
+		This starts at *0* and counts how many times [property:Boolean needsUpdate] is set to *true*.
+		</p>
+
 		<h3>[property:Integer vertexColors]</h3>
 		<p>
 		Defines whether vertex coloring is used.

+ 2 - 5
docs/api/en/materials/MeshBasicMaterial.html

@@ -64,8 +64,7 @@
 
 		<h3>[property:Texture aoMap]</h3>
 		<p>The red channel of this texture is used as the ambient occlusion map. Default is null.
-		The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat]
-		and [page:Texture offset] Texture properties.</p>
+		The aoMap requires a second set of UVs.</p>
 
 		<h3>[property:Float aoMapIntensity]</h3>
 		<p>Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.</p>
@@ -93,9 +92,7 @@
 		<p>The environment map. Default is null.</p>
 
 		<h3>[property:Texture lightMap]</h3>
-		<p>The light map. Default is null. The lightMap requires a second set of UVs,
-		and consequently will ignore the [page:Texture repeat] and [page:Texture offset]
-		Texture properties.</p>
+		<p>The light map. Default is null. The lightMap requires a second set of UVs.</p>
 
 		<h3>[property:Float lightMapIntensity]</h3>
 		<p>Intensity of the baked light. Default is 1.</p>

+ 2 - 5
docs/api/en/materials/MeshLambertMaterial.html

@@ -75,8 +75,7 @@
 
 		<h3>[property:Texture aoMap]</h3>
 		<p>The red channel of this texture is used as the ambient occlusion map. Default is null.
-		The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat]
-		and [page:Texture offset] Texture properties.</p>
+		The aoMap requires a second set of UVs.</p>
 
 		<h3>[property:Float aoMapIntensity]</h3>
 		<p>Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.</p>
@@ -120,9 +119,7 @@
 		</p>
 
 		<h3>[property:Texture lightMap]</h3>
-		<p>The light map. Default is null. The lightMap requires a second set of UVs,
-		and consequently will ignore the [page:Texture repeat] and [page:Texture offset]
-		Texture properties.</p>
+		<p>The light map. Default is null. The lightMap requires a second set of UVs.</p>
 
 		<h3>[property:Float lightMapIntensity]</h3>
 		<p>Intensity of the baked light. Default is 1.</p>

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

@@ -74,8 +74,7 @@
 
 		<h3>[property:Texture aoMap]</h3>
 		<p>The red channel of this texture is used as the ambient occlusion map. Default is null.
-		The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat]
-		and [page:Texture offset] Texture properties.</p>
+		The aoMap requires a second set of UVs.</p>
 
 		<h3>[property:Float aoMapIntensity]</h3>
 		<p>Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.</p>
@@ -153,9 +152,7 @@
 
 
 		<h3>[property:Texture lightMap]</h3>
-		<p>The light map. Default is null. The lightMap requires a second set of UVs,
-		and consequently will ignore the [page:Texture repeat] and [page:Texture offset]
-		Texture properties.</p>
+		<p>The light map. Default is null. The lightMap requires a second set of UVs.</p>
 
 		<h3>[property:Float lightMapIntensity]</h3>
 		<p>Intensity of the baked light. Default is 1.</p>

+ 2 - 5
docs/api/en/materials/MeshStandardMaterial.html

@@ -99,8 +99,7 @@
 
 		<h3>[property:Texture aoMap]</h3>
 		<p>The red channel of this texture is used as the ambient occlusion map. Default is null.
-		The aoMap requires a second set of UVs, and consequently will ignore the [page:Texture repeat]
-		and [page:Texture offset] Texture properties.</p>
+		The aoMap requires a second set of UVs.</p>
 
 		<h3>[property:Float aoMapIntensity]</h3>
 		<p>Intensity of the ambient occlusion effect. Default is 1. Zero is no occlusion effect.</p>
@@ -191,9 +190,7 @@
 
 
 		<h3>[property:Texture lightMap]</h3>
-		<p>The light map. Default is null. The lightMap requires a second set of UVs,
-		and consequently will ignore the [page:Texture repeat] and [page:Texture offset]
-		Texture properties.</p>
+		<p>The light map. Default is null. The lightMap requires a second set of UVs.</p>
 
 		<h3>[property:Float lightMapIntensity]</h3>
 		<p>Intensity of the baked light. Default is 1.</p>

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

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

+ 2 - 1
docs/api/en/math/Box2.html

@@ -174,7 +174,8 @@
 			[page:Vector2 min] - (required ) [page:Vector2] representing the lower (x, y) boundary of the box. <br>
 			[page:Vector2 max]  - (required) [page:Vector2] representing the upper (x, y) boundary of the box. <br /><br />
 
-			Sets the lower and upper (x, y) boundaries of this box.
+			Sets the lower and upper (x, y) boundaries of this box.<br>
+			Please note that this method only copies the values from the given objects.
 		</p>
 
 		<h3>[method:Box2 setFromCenterAndSize]( [param:Vector2 center], [param:Vector2 size] )</h3>

+ 4 - 1
docs/api/en/math/Box3.html

@@ -138,6 +138,7 @@
 
 		Expands the boundaries of this box to include [page:Object3D object] and its children,
 		accounting for the object's, and children's, world transforms.
+		The function may result in a larger box than strictly necessary.
 
 		</p>
 
@@ -247,7 +248,8 @@
 		[page:Vector3 min] - [page:Vector3] representing the lower (x, y, z) boundary of the box.<br />
 		[page:Vector3 max] - [page:Vector3] representing the lower upper (x, y, z) boundary of the box.<br /><br />
 
-		Sets the lower and upper (x, y, z) boundaries of this box.
+		Sets the lower and upper (x, y, z) boundaries of this box.<br>
+		Please note that this method only copies the values from the given objects.
 		</p>
 
 		<h3>[method:Box3 setFromArray]( [param:Array array] ) [param:Box3 this]</h3>
@@ -279,6 +281,7 @@
 
 		Computes the world-axis-aligned bounding box of an [page:Object3D] (including its children),
 		accounting for the object's, and children's, world transforms.
+		The function may result in a larger box than strictly necessary.
 
 		</p>
 

+ 2 - 1
docs/api/en/math/Frustum.html

@@ -91,7 +91,8 @@
 
 		<h3>[method:Frustum set]( [param:Plane p0], [param:Plane p1], [param:Plane p2], [param:Plane p3], [param:Plane p4], [param:Plane p5] )</h3>
 		<p>
-		Sets the current frustum from the passed planes. No plane order is implicitely implied.
+		Sets the current frustum from the passed planes. No plane order is implicitely implied.<br>
+		Please note that this method only copies the values from the given objects.
 		</p>
 
 		<h3>[method:Frustum setFromMatrix]( [param:Matrix4 matrix] )</h3>

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

@@ -130,7 +130,7 @@
 			[page:Vector3 normal] - a unit length [page:Vector3] defining the normal of the plane.<br />
 			[page:Float constant] - the signed distance from the origin to the plane. Default is *0*.<br /><br />
 
-			 Sets the plane's [page:.normal normal] and [page:.constant constant] properties.
+			Sets this plane's [page:.normal normal] and [page:.constant constant] properties by copying the values from the given normal.
 		</p>
 
 		<h3>[method:Plane setComponents]( [param:Float x], [param:Float y], [param:Float z], [param:Float w] )</h3>

+ 3 - 4
docs/api/en/math/Ray.html

@@ -25,7 +25,7 @@
 		<p>
 		[page:Vector3 origin] - (optional) the origin of the [page:Ray]. Default is a [page:Vector3] at (0, 0, 0).<br />
 		[page:Vector3 direction] - [page:Vector3] The direction of the [page:Ray]. This must be normalized
-		 (with [page:Vector3.normalize]) for the methods to operate properly.  Default is a [page:Vector3] at (0, 0, 0).<br /><br />
+		 (with [page:Vector3.normalize]) for the methods to operate properly.  Default is a [page:Vector3] at (0, 0, -1).<br /><br />
 
 		Creates a new [name].
 		</p>
@@ -38,7 +38,7 @@
 		<h3>[property:Vector3 direction]</h3>
 		<p>
 		The direction of the [page:Ray]. This must be normalized (with [page:Vector3.normalize])
-		for the methods to operate properly. Default is a [page:Vector3] at (0, 0, 0).
+		for the methods to operate properly. Default is a [page:Vector3] at (0, 0, -1).
 		</p>
 
 
@@ -201,8 +201,7 @@
 		This must be normalized (with [page:Vector3.normalize]) for the methods to operate
 		properly.<br /><br />
 
-		Copy the parameters to the [page:.origin origin] and [page:.direction direction] properties
-		of this ray.
+		Sets this ray's [page:.origin origin] and [page:.direction direction] properties by copying the values from the given objects.
 		</p>
 
 

+ 2 - 1
docs/api/en/math/Sphere.html

@@ -114,7 +114,8 @@
 			[page:Vector3 center] - center of the sphere.<br />
 			[page:Float radius] - radius of the sphere.<br /><br />
 
-		Sets the [page:.center center] and [page:.radius radius] properties of this sphere.
+		Sets the [page:.center center] and [page:.radius radius] properties of this sphere.<br>
+		Please note that this method only copies the values from the given center.
 		</p>
 
 		<h3>[method:Sphere setFromPoints]( [param:Array points], [param:Vector3 optionalCenter] )</h3>

+ 2 - 2
docs/api/en/math/Spherical.html

@@ -20,8 +20,8 @@
 		<p>
 		[page:Float radius] - the radius, or the [link:https://en.wikipedia.org/wiki/Euclidean_distance Euclidean distance]
 		(straight-line distance) from the point to the origin. Default is *1.0*.<br />
-		[page:Float phi] - polar angle from the y (up) axis. Default is *0*.<br />
-		[page:Float theta] - equator angle around the y (up) axis. Default is *0*.<br /><br />
+		[page:Float phi] - polar angle in radians from the y (up) axis. Default is *0*.<br />
+		[page:Float theta] - equator angle in radians around the y (up) axis. Default is *0*.<br /><br />
 
 		The poles (phi) are at the positive and negative y axis. The equator (theta) starts at positive z.
 		</p>

+ 2 - 1
docs/api/en/math/Triangle.html

@@ -123,7 +123,8 @@
 
 		<h3>[method:Triangle set]( [param:Vector3 a], [param:Vector3 b], [param:Vector3 c] ) [param:Triangle this]</h3>
 		<p>
-		Sets the triangle's [page:.a a], [page:.b b] and [page:.c c] properties to the passed [page:vector3 vector3s].
+		Sets the triangle's [page:.a a], [page:.b b] and [page:.c c] properties to the passed [page:vector3 vector3s].<br>
+		Please note that this method only copies the values from the given objects.
 		</p>
 
 		<h3>[method:Triangle setFromPointsAndIndices]( [param:Array points], [param:Integer i0], [param:Integer i1], [param:Integer i2] ) [param:Triangle this]</h3>

+ 3 - 0
docs/api/en/math/Vector3.html

@@ -113,6 +113,9 @@ var d = a.distanceTo( b );
 		Multiplies this vector (with an implicit 1 in the 4th dimension) and m, and divides by perspective.
 		</p>
 
+		<h3>[method:this applyNormalMatrix]( [param:Matrix3 m] )</h3>
+		<p>Multiplies this vector by normal matrix [page:Matrix3 m] and normalizes the result.</p>
+
 		<h3>[method:this applyQuaternion]( [param:Quaternion quaternion] )</h3>
 		<p>
 		Applies a [page:Quaternion] transform to this vector.

+ 11 - 0
docs/api/en/objects/InstancedMesh.html

@@ -53,6 +53,17 @@
 		<h2>Methods</h2>
 		<p>See the base [page:Mesh] class for common methods.</p>
 
+		<h3>[method:null getMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )</h3>
+		<p>
+			[page:Integer index]: The index of an instance. Values have to be in the range [0, count].
+		</p>
+		<p>
+			[page:Matrix4 matrix]: This 4x4 matrix will be set to the local transformation matrix of the defined instance.
+		</p>
+		<p>
+			Get the local transformation matrix of the defined instance.
+		</p>
+
 		<h3>[method:null setMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )</h3>
 		<p>
 			[page:Integer index]: The index of an instance. Values have to be in the range [0, count].

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

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

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

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

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

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

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

@@ -12,7 +12,7 @@
 
 		<div class="desc">
 		<p>
-			Geometry 是对 [page:BufferGeometry] 的用户有好替代。Geometry 利用 [page:Vector3]
+			Geometry 是一个便于用户使用的 [page:BufferGeometry] 的替代品。Geometry 利用 [page:Vector3]
 			或 [page:Color] 存储了几何体的相关 attributes(如顶点位置,面信息,颜色等)比起 BufferGeometry
 			更容易读写,但是运行效率不如有类型的队列。
 		</p>

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

@@ -56,6 +56,7 @@
 			其它示例:<br>[example:webgl_interactive_cubes Raycasting to a Mesh]<br />
 			[example:webgl_interactive_cubes_ortho Raycasting to a Mesh in using an OrthographicCamera]<br />
 			[example:webgl_interactive_buffergeometry Raycasting to a Mesh with BufferGeometry]<br />
+			[example:webgl_instancing_raycast Raycasting to a InstancedMesh]<br />
 			[example:webgl_interactive_lines Raycasting to a Line]<br />
 			[example:webgl_interactive_raycasting_points Raycasting to Points]<br />
 			[example:webgl_geometry_terrain_raycast Terrain raycasting]<br />
@@ -170,7 +171,8 @@
 			[page:Integer faceIndex] —— 相交的面的索引<br />
 			[page:Object3D object] —— 相交的物体<br />
 			[page:Vector2 uv] —— 相交部分的点的UV坐标。<br />
-			[page:Vector2 uv2] —— Second set of U,V coordinates at point of intersection
+			[page:Vector2 uv2] —— Second set of U,V coordinates at point of intersection<br />
+			[page:Integer instanceId] – The index number of the instance where the ray intersects the InstancedMesh
 		</p>
 		<p>
 			当计算这条射线是否和物体相交的时候,*Raycaster*将传入的对象委托给[page:Object3D.raycast raycast]方法。

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

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

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

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

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

@@ -163,8 +163,7 @@ Which stencil operation to perform when the comparison function returns true and
 <p>对象的可选名称(不必是唯一的)。默认值为空字符串。</p>
 
 <h3>[property:Boolean needsUpdate]</h3>
-<p>指定需要重新编译材质。<br/>
-	实例化新材质时,此属性自动设置为true。
+<p>指定需要重新编译材质。
 </p>
 
 <h3>[property:Float opacity]</h3>
@@ -255,6 +254,11 @@ Defines whether this material is tone mapped according to the renderer's [page:W
 <p> 此材质实例的[link:http://en.wikipedia.org/wiki/Universally_unique_identifier UUID],会自动分配,不应该被更改。
 </p>
 
+<h3>[property:Integer version]</h3>
+<p>
+This starts at *0* and counts how many times [property:Boolean needsUpdate] is set to *true*.
+</p>
+
 <h3>[property:Integer vertexColors]</h3>
 <p> 是否使用顶点着色。默认值为[page:Materials THREE.NoColors]。
 	其他选项有[page:Materials THREE.VertexColors] 和 [page:Materials THREE.FaceColors]。

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

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

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

@@ -24,7 +24,7 @@
 		<p>
 		[page:Vector3 origin] - (可选)[page:Ray](射线)的原点,默认值是一个位于(0, 0, 0)的[page:Vector3]。<br />
 		[page:Vector3 direction] - [page:Vector3] [page:Ray](射线)的方向。该向量必须经过标准化(使用[page:Vector3.normalize]),这样才能使方法正常运行。
-		默认值是一个位于(0, 0, 0)的[page:Vector3]。<br /><br />
+		默认值是一个位于(0, 0, -1)的[page:Vector3]。<br /><br />
 
 		创建一个新的[name]。
 		</p>
@@ -37,7 +37,7 @@
 		<h3>[property:Vector3 direction]</h3>
 		<p>
 		[page:Ray](射线)的方向。该向量必须经过标准化(使用[page:Vector3.normalize]),这样才能使方法正常运行。
-		默认值是一个位于(0, 0, 0)的[page:Vector3]。
+		默认值是一个位于(0, 0, -1)的[page:Vector3]。
 		</p>
 
 
@@ -190,7 +190,7 @@
 		<p>
 		[page:Vector3 origin] - [page:Ray](射线)的[page:.origin origin](原点)。<br />
 		[page:Vector3 origin] - [page:Ray](射线)的[page:.direction direction](方向)。
-		
+
 		该向量必须经过标准化(使用[page:Vector3.normalize]),这样才能使方法正常运行。
 		<br /><br />
 

+ 11 - 0
docs/api/zh/objects/InstancedMesh.html

@@ -53,6 +53,17 @@
 		<h2>Methods</h2>
 		<p>See the base [page:Mesh] class for common methods.</p>
 
+		<h3>[method:null getMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )</h3>
+		<p>
+			[page:Integer index]: The index of an instance. Values have to be in the range [0, count].
+		</p>
+		<p>
+			[page:Matrix4 matrix]: This 4x4 matrix will be set to the local transformation matrix of the defined instance.
+		</p>
+		<p>
+			Get the local transformation matrix of the defined instance.
+		</p>
+
 		<h3>[method:null setMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )</h3>
 		<p>
 			[page:Integer index]: The index of an instance. Values have to be in the range [0, count].

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

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

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

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

+ 9 - 1
docs/examples/en/loaders/DRACOLoader.html

@@ -34,7 +34,10 @@
 		var loader = new THREE.DRACOLoader();
 
 		// Specify path to a folder containing WASM/JS decoding libraries.
-		loader.setDecoderPath( '/examples/js/libs/draco' );
+		loader.setDecoderPath( '/examples/js/libs/draco/' );
+
+		// Optional: Pre-fetch Draco WASM/JS module.
+		loader.preload();
 
 		// Load a Draco geometry
 		loader.load(
@@ -128,6 +131,11 @@
 		in the application.
 		</p>
 
+		<h3>[method:this preload]()</h3>
+		<p>
+		Requests the decoder libraries, if not already loaded.
+		</p>
+
 		<h3>[method:this dispose]()</h3>
 		<p>
 		Disposes of the decoder resources and deallocates memory. The decoder

+ 2 - 1
docs/examples/en/loaders/GLTFLoader.html

@@ -32,6 +32,7 @@
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_unlit</li>
+			<li>KHR_mesh_quantization</li>
 			<li>KHR_lights_punctual<sup>1</sup></li>
 			<li>KHR_texture_transform<sup>2</sup></li>
 			<li>MSFT_texture_dds</li>
@@ -58,7 +59,7 @@
 
 		// Optional: Provide a DRACOLoader instance to decode compressed mesh data
 		var dracoLoader = new THREE.DRACOLoader();
-		dracoLoader.setDecoderPath( '/examples/js/libs/draco' );
+		dracoLoader.setDecoderPath( '/examples/js/libs/draco/' );
 		loader.setDRACOLoader( dracoLoader );
 
 		// Load a glTF resource

+ 1 - 1
docs/examples/en/loaders/MTLLoader.html

@@ -12,7 +12,7 @@
 
 		<h1>[name]</h1>
 
-		<p class="desc">A loader for loading an <em>.mtl</em> resource, used internaly by [page:OBJLoader].<br />
+		<p class="desc">A loader for loading an <em>.mtl</em> resource, used internally by [page:OBJLoader].<br />
 		The Material Template Library format (MTL) or .MTL File Format is a companion file format to .OBJ that describes surface shading
 		(material) properties of objects within one or more .OBJ files.
 		</p>

+ 1 - 1
docs/examples/en/loaders/PCDLoader.html

@@ -14,7 +14,7 @@
 
 		<p class="desc">A loader for loading a <em>.pcd</em> resource. <br />
 		Point Cloud Data is a file format for <a href="https://en.wikipedia.org/wiki/Point_Cloud_Library">Point Cloud Library</a>. <br />
-		Loader support ascii and binary. Compressed binary files are not supported.
+		Loader support ascii and (compressed) binary.
 		</p>
 
 		<h2>Example</h2>

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


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

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

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

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

+ 9 - 1
docs/examples/zh/loaders/DRACOLoader.html

@@ -34,7 +34,10 @@
 		var loader = new THREE.DRACOLoader();
 
 		// Specify path to a folder containing WASM/JS decoding libraries.
-		loader.setDecoderPath( '/examples/js/libs/draco' );
+		loader.setDecoderPath( '/examples/js/libs/draco/' );
+
+		// Optional: Pre-fetch Draco WASM/JS module.
+		loader.preload();
 
 		// Load a Draco geometry
 		loader.load(
@@ -128,6 +131,11 @@
 		in the application.
 		</p>
 
+		<h3>[method:this preload]()</h3>
+		<p>
+		Requests the decoder libraries, if not already loaded.
+		</p>
+
 		<h3>[method:this dispose]()</h3>
 		<p>
 		Disposes of the decoder resources and deallocates memory. The decoder

+ 3 - 2
docs/examples/zh/loaders/GLTFLoader.html

@@ -30,6 +30,7 @@
 			<li>KHR_draco_mesh_compression</li>
 			<li>KHR_materials_pbrSpecularGlossiness</li>
 			<li>KHR_materials_unlit</li>
+			<li>KHR_mesh_quantization</li>
 			<li>KHR_lights_punctual<sup>1</sup></li>
 			<li>KHR_texture_transform<sup>2</sup></li>
 			<li>MSFT_texture_dds</li>
@@ -42,7 +43,7 @@
 			<sup>2</sup>支持UV变换,但存在一些重要的限制。
 			Transforms applied to
 			a texture using the first UV slot (all textures except aoMap and lightMap) must share the same
-			transform, or no transfor at all. 
+			transform, or no transfor at all.
 			aoMap 和 lightMap 纹理不能被变换。每个材质最多只能使用一次变换。
 			每次对使用具有唯一变换的纹理都会导致一次额外的GPU纹理上传。
 			请参阅#[link:https://github.com/mrdoob/three.js/pull/13831 13831] 和
@@ -57,7 +58,7 @@
 
 		// Optional: Provide a DRACOLoader instance to decode compressed mesh data
 		var dracoLoader = new THREE.DRACOLoader();
-		dracoLoader.setDecoderPath( '/examples/js/libs/draco' );
+		dracoLoader.setDecoderPath( '/examples/js/libs/draco/' );
 		loader.setDRACOLoader( dracoLoader );
 
 		// Load a glTF resource

+ 1 - 1
docs/examples/zh/loaders/PCDLoader.html

@@ -14,7 +14,7 @@
 
 		<p class="desc">A loader for loading a <em>.pcd</em> resource. <br />
 		Point Cloud Data is a file format for <a href="https://en.wikipedia.org/wiki/Point_Cloud_Library">Point Cloud Library</a>. <br />
-		Loader support ascii and binary. Compressed binary files are not supported.
+		Loader support ascii and (compressed) binary.
 		</p>
 
 		<h2>Example</h2>

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


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

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

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

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

+ 6 - 6
docs/list.js

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

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

@@ -20,30 +20,30 @@
 	<h2>Workflow</h2>
 
 	<p>
-		First, you have to include [link:https://github.com/mrdoob/three.js/blob/master/examples/js/vr/WebVR.js WebVR.js]
+		First, you have to include [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/webxr/VRButton.js VRButton.js]
 		into your project.
 	</p>
 
 	<code>
-import { WEBVR } from 'three/examples/jsm/vr/WebVR.js';
+import { VRButton } from 'three/examples/jsm/webxr/VRButton.js';
 	</code>
 
 	<p>
-		*WEBVR.createButton()* does two important things: It creates a button which indicates
+		*VRButton.createButton()* does two important things: It creates a button which indicates
 		VR compatibility. Besides, it initiates a VR session if the user activates the button. The only thing you have
 		to do is to add the following line of code to your app.
 	</p>
 
 	<code>
-document.body.appendChild( WEBVR.createButton( renderer ) );
+document.body.appendChild( VRButton.createButton( renderer ) );
 	</code>
 
 	<p>
-		Next, you have to tell your instance of *WebGLRenderer* to enable VR rendering.
+		Next, you have to tell your instance of *WebGLRenderer* to enable XR rendering.
 	</p>
 
 	<code>
-renderer.vr.enabled = true;
+renderer.xr.enabled = true;
 	</code>
 
 	<p>
@@ -65,17 +65,18 @@ renderer.setAnimationLoop( function () {
 	<p>
 		Have a look at one of the official WebVR examples to see this workflow in action.<br /><br />
 
-		[example:webvr_ballshooter WebVR / ballshoter]<br />
-		[example:webvr_cubes WebVR / cubes]<br />
-		[example:webvr_dragging WebVR / dragging]<br />
-		[example:webvr_lorenzattractor WebVR / lorenzattractor]<br />
-		[example:webvr_panorama WebVR / panorama]<br />
-		[example:webvr_paint WebVR / paint]<br />
-		[example:webvr_rollercoaster WebVR / rollercoaster]<br />
-		[example:webvr_sandbox WebVR / sandbox]<br />
-		[example:webvr_sculpt WebVR / sculpt]<br />
-		[example:webvr_vive_paint WebVR / vive / paint]<br />
-		[example:webvr_vive_sculpt WebVR / vive / sculpt]<br />
+		[example:webxr_vr_ballshooter WebXR / VR / ballshooter]<br />
+		[example:webxr_vr_cubes WebXR / VR / cubes]<br />
+		[example:webxr_vr_dragging WebXR / VR / dragging]<br />
+		[example:webxr_vr_lorenzattractor WebXR / VR / lorenzattractor]<br />
+		[example:webxr_vr_multiview WebXR / VR / multiview]<br />
+		[example:webxr_vr_paint WebXR / VR / paint]<br />
+		[example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]<br />
+		[example:webxr_vr_panorama WebXR / VR / panorama]<br />
+		[example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]<br />
+		[example:webxr_vr_sandbox WebXR / VR / sandbox]<br />
+		[example:webxr_vr_sculpt WebXR / VR / sculpt]<br />
+		[example:webxr_vr_video WebXR / VR / video]
 	</p>
 
 </body>

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

@@ -19,29 +19,29 @@
 	<h2>工作流程</h2>
 
 	<p>
-		首先,你需要将[link:https://github.com/mrdoob/three.js/blob/master/examples/js/vr/WebVR.js WebVR.js]
+		首先,你需要将[link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/webxr/VRButton.js VRButton.js]
 		包含到你的项目中。
 	</p>
 
 	<code>
-import { WEBVR } from 'three/examples/jsm/vr/WebVR.js';
+import { VRButton } from 'three/examples/jsm/webxr/VRButton.js';
 	</code>
 
-	<p>*WEBVR.createButton()*做了两件重要的事情:首先,它创建了一个按钮,指示了VR的兼容性;
+	<p>*VRButton.createButton()*做了两件重要的事情:首先,它创建了一个按钮,指示了VR的兼容性;
 		此外,若用户激活了这个按钮,则它将开启一个VR会话。
 		你所要做的唯一一件事情,便是把下面的这一行代码加入到你的应用程序里。
 	</p>
 
 	<code>
-document.body.appendChild( WEBVR.createButton( renderer ) );
+document.body.appendChild( VRButton.createButton( renderer ) );
 	</code>
 
 	<p>
-		接下来,你需要告诉你的*WebGLRenderer*实例来启用VR渲染。
+		接下来,你需要告诉你的*WebGLRenderer*实例来启用XR渲染。
 	</p>
 
 	<code>
-renderer.vr.enabled = true;
+renderer.xr.enabled = true;
 	</code>
 
 	<p>
@@ -65,17 +65,18 @@ renderer.setAnimationLoop( function () {
 		请查看官方示例中与WebVR相关的示例,了解这一工作流程的实际使用、运行情况。
 		<br /><br />
 
-		[example:webvr_ballshooter WebVR / ballshoter]<br />
-		[example:webvr_cubes WebVR / cubes]<br />
-		[example:webvr_dragging WebVR / dragging]<br />
-		[example:webvr_lorenzattractor WebVR / lorenzattractor]<br />
-		[example:webvr_panorama WebVR / panorama]<br />
-		[example:webvr_paint WebVR / paint]<br />
-		[example:webvr_rollercoaster WebVR / rollercoaster]<br />
-		[example:webvr_sandbox WebVR / sandbox]<br />
-		[example:webvr_sculpt WebVR / sculpt]<br />
-		[example:webvr_vive_paint WebVR / vive / paint]<br />
-		[example:webvr_vive_sculpt WebVR / vive / sculpt]<br />
+		[example:webxr_vr_ballshooter WebXR / VR / ballshooter]<br />
+		[example:webxr_vr_cubes WebXR / VR / cubes]<br />
+		[example:webxr_vr_dragging WebXR / VR / dragging]<br />
+		[example:webxr_vr_lorenzattractor WebXR / VR / lorenzattractor]<br />
+		[example:webxr_vr_multiview WebXR / VR / multiview]<br />
+		[example:webxr_vr_paint WebXR / VR / paint]<br />
+		[example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]<br />
+		[example:webxr_vr_panorama WebXR / VR / panorama]<br />
+		[example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]<br />
+		[example:webxr_vr_sandbox WebXR / VR / sandbox]<br />
+		[example:webxr_vr_sculpt WebXR / VR / sculpt]<br />
+		[example:webxr_vr_video WebXR / VR / video]
 	</p>
 
 </body>

+ 13 - 0
docs/prettify/threejs.css

@@ -13,3 +13,16 @@ pre.prettyprint, code.prettyprint {
 	background-color: #F5F5F5;
 	font-family: 'Roboto Mono', monospace;
 }
+
+@media (prefers-color-scheme: dark) {
+
+	pre .str, code .str { color: #BB55FF; } /* string */
+	pre .com, code .com { color: #666666; } /* comment */
+	pre .lit, code .lit { color: #ff3399; } /* literal */
+	pre .pln, code .pln { color: #aaaaaa; } /* plaintext */
+
+	pre.prettyprint, code.prettyprint {
+		background-color: #333333;
+	}
+
+}

+ 1 - 3
editor/index.html

@@ -7,8 +7,6 @@
 		<link rel="apple-touch-icon" href="images/icon.png">
 		<link rel="manifest" href="manifest.json">
 		<link rel="shortcut icon" href="../files/favicon.ico" />
-		<!-- WebXR Device API (For Chrome M76+), expires 10/16/2019 -->
-		<meta http-equiv="origin-trial" content="AtWCPo0cZgy0zJDSYftemy7eZvmcwR5qy/4osFkMkLZ0ar6OYyKfbu93pjpxiOVzcWNIVxgoWoK8YtxCXeFSqgIAAABTeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJYUkRldmljZU03NiIsImV4cGlyeSI6MTU3MTE4Mzk5OX0=">
 	</head>
 	<body ontouchstart="">
 		<link rel="stylesheet" href="css/main.css">
@@ -26,7 +24,6 @@
 		<script src="../examples/js/loaders/DRACOLoader.js"></script>
 		<script src="../examples/js/loaders/FBXLoader.js"></script>
 		<script src="../examples/js/loaders/GLTFLoader.js"></script>
-		<script src="../examples/js/loaders/deprecated/LegacyGLTFLoader.js"></script>
 		<script src="../examples/js/loaders/KMZLoader.js"></script>
 		<script src="../examples/js/loaders/MD2Loader.js"></script>
 		<script src="../examples/js/loaders/OBJLoader.js"></script>
@@ -42,6 +39,7 @@
 		<script src="../examples/js/exporters/ColladaExporter.js"></script>
 		<script src="../examples/js/exporters/GLTFExporter.js"></script>
 		<script src="../examples/js/exporters/OBJExporter.js"></script>
+		<script src="../examples/js/exporters/PLYExporter.js"></script>
 		<script src="../examples/js/exporters/STLExporter.js"></script>
 
 		<script src="../examples/js/renderers/Projector.js"></script>

+ 25 - 1
editor/js/Loader.js

@@ -105,6 +105,30 @@ var Loader = function ( editor ) {
 
 				break;
 
+			case 'drc':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var loader = new THREE.DRACOLoader();
+					loader.setDecoderPath( '../examples/js/libs/draco/' );
+					loader.decodeDracoFile( contents, function ( geometry ) {
+
+						var material = new THREE.MeshStandardMaterial();
+
+						var mesh = new THREE.Mesh( geometry, material );
+						mesh.name = filename;
+
+						editor.execute( new AddObjectCommand( editor, mesh ) );
+
+					} );
+
+				}, false );
+				reader.readAsArrayBuffer( file );
+
+				break;
+
 			case 'fbx':
 
 				reader.addEventListener( 'load', function ( event ) {
@@ -158,7 +182,7 @@ var Loader = function ( editor ) {
 
 					if ( isGLTF1( contents ) ) {
 
-						loader = new THREE.LegacyGLTFLoader( manager );
+						alert( 'Import of glTF asset not possible. Only versions >= 2.0 are supported. Please try to upgrade the file to glTF 2.0 using glTF-Pipeline.' );
 
 					} else {
 

+ 6 - 6
editor/js/Menubar.Examples.js

@@ -21,11 +21,11 @@ Menubar.Examples = function ( editor ) {
 	// Examples
 
 	var items = [
-		{ title: 'Arkanoid', file: 'arkanoid.app.json' },
-		{ title: 'Camera', file: 'camera.app.json' },
-		{ title: 'Particles', file: 'particles.app.json' },
-		{ title: 'Pong', file: 'pong.app.json' },
-		{ title: 'Shaders', file: 'shaders.app.json' }
+		{ title: 'menubar/examples/Arkanoid', file: 'arkanoid.app.json' },
+		{ title: 'menubar/examples/Camera', file: 'camera.app.json' },
+		{ title: 'menubar/examples/Particles', file: 'particles.app.json' },
+		{ title: 'menubar/examples/Pong', file: 'pong.app.json' },
+		{ title: 'menubar/examples/Shaders', file: 'shaders.app.json' }
 	];
 
 	var loader = new THREE.FileLoader();
@@ -38,7 +38,7 @@ Menubar.Examples = function ( editor ) {
 
 			var option = new UI.Row();
 			option.setClass( 'option' );
-			option.setTextContent( item.title );
+			option.setTextContent( strings.getKey( item.title ) );
 			option.onClick( function () {
 
 				if ( confirm( 'Any unsaved data will be lost. Are you sure?' ) ) {

+ 36 - 0
editor/js/Menubar.File.js

@@ -266,6 +266,42 @@ Menubar.File = function ( editor ) {
 	} );
 	options.add( option );
 
+	// Export PLY (ASCII)
+
+	var option = new UI.Row();
+	option.setClass( 'option' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/ply' ) );
+	option.onClick( function () {
+
+		var exporter = new THREE.PLYExporter();
+
+		exporter.parse( editor.scene, function ( result ) {
+
+			saveArrayBuffer( result, 'model.ply' );
+
+		} );
+
+	} );
+	options.add( option );
+
+	// Export PLY (Binary)
+
+	var option = new UI.Row();
+	option.setClass( 'option' );
+	option.setTextContent( strings.getKey( 'menubar/file/export/ply_binary' ) );
+	option.onClick( function () {
+
+		var exporter = new THREE.PLYExporter();
+
+		exporter.parse( editor.scene, function ( result ) {
+
+			saveArrayBuffer( result, 'model-binary.ply' );
+
+		}, { binary: true } );
+
+	} );
+	options.add( option );
+
 	// Export STL (ASCII)
 
 	var option = new UI.Row();

+ 1 - 0
editor/js/Sidebar.Material.js

@@ -1160,6 +1160,7 @@ Sidebar.Material = function ( editor ) {
 			'alphaMap': materialAlphaMapRow,
 			'bumpMap': materialBumpMapRow,
 			'normalMap': materialNormalMapRow,
+			'clearcoatNormalMap': materialClearcoatNormalMapRow,
 			'displacementMap': materialDisplacementMapRow,
 			'roughnessMap': materialRoughnessMapRow,
 			'metalnessMap': materialMetalnessMapRow,

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

@@ -199,7 +199,7 @@ Sidebar.Project = function ( editor ) {
 	buttonsRow.add( addButton );
 	*/
 
-	var assignMaterial = new UI.Button().setLabel( 'Assign' ).setMargin( '0px 5px' );
+	var assignMaterial = new UI.Button().setLabel( strings.getKey( 'sidebar/project/Assign' ) ).setMargin( '0px 5px' );
 	assignMaterial.onClick( function () {
 
 		if ( editor.selected !== null ) {

+ 17 - 1
editor/js/Strings.js

@@ -20,6 +20,8 @@ var Strings = function ( config ) {
 			'menubar/file/export/glb': 'Export GLB',
 			'menubar/file/export/gltf': 'Export GLTF',
 			'menubar/file/export/obj': 'Export OBJ',
+			'menubar/file/export/ply': 'Export PLY',
+			'menubar/file/export/ply_binary': 'Export PLY (Binary)',
 			'menubar/file/export/stl': 'Export STL',
 			'menubar/file/export/stl_binary': 'Export STL (Binary)',
 			'menubar/file/publish': 'Publish',
@@ -65,6 +67,11 @@ var Strings = function ( config ) {
 			'menubar/play/play': 'Play',
 
 			'menubar/examples': 'Examples',
+			'menubar/examples/Arkanoid': 'Arkanoid',
+			'menubar/examples/Camera': 'Camera',
+			'menubar/examples/Particles': 'Particles',
+			'menubar/examples/Pong': 'Pong',
+			'menubar/examples/Shaders': 'Shaders',
 
 			'menubar/help': 'Help',
 			'menubar/help/source_code': 'Source Code',
@@ -281,6 +288,7 @@ var Strings = function ( config ) {
 			'sidebar/project/antialias': 'antialias',
 			'sidebar/project/shadows': 'shadows',
 			'sidebar/project/materials': 'Materials',
+			'sidebar/project/Assign': 'Assign',
 
 			'sidebar/settings': 'Settings',
 			'sidebar/settings/language': 'Language',
@@ -319,6 +327,8 @@ var Strings = function ( config ) {
 			'menubar/file/export/glb': '导出GLB',
 			'menubar/file/export/gltf': '导出GLTF',
 			'menubar/file/export/obj': '导出OBJ',
+			'menubar/file/export/ply': '导出PLY',
+			'menubar/file/export/ply_binary': '导出PLY(二进制)',
 			'menubar/file/export/stl': '导出STL',
 			'menubar/file/export/stl_binary': '导出STL(二进制)',
 			'menubar/file/publish': '发布',
@@ -364,6 +374,11 @@ var Strings = function ( config ) {
 			'menubar/play/play': '启动',
 
 			'menubar/examples': '示例',
+			'menubar/examples/Arkanoid': '打砖块',
+			'menubar/examples/Camera': ' 摄像机',
+			'menubar/examples/Particles': '粒子',
+			'menubar/examples/Pong': '乒乓球',
+			'menubar/examples/Shaders': '着色器',
 
 			'menubar/help': '帮助',
 			'menubar/help/source_code': '源码',
@@ -553,7 +568,8 @@ var Strings = function ( config ) {
 			'sidebar/project/renderer': '渲染器',
 			'sidebar/project/antialias': '抗锯齿',
 			'sidebar/project/shadows': '阴影',
-			'sidebar/project/materials': 'Materials',
+			'sidebar/project/materials': '材质',
+			'sidebar/project/Assign': '应用',
 
 			'sidebar/settings': '设置',
 			'sidebar/settings/language': '语言',

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

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

+ 5 - 2
editor/sw.js

@@ -1,4 +1,4 @@
-// r109
+// r111
 
 const assets = [
 	'./',
@@ -12,13 +12,15 @@ const assets = [
 	'../examples/js/libs/chevrotain.min.js',
 	'../examples/js/libs/jszip.min.js',
 	'../examples/js/libs/inflate.min.js',
+	'../examples/js/libs/draco/draco_decoder.js',
+	'../examples/js/libs/draco/draco_decoder.wasm',
+	'../examples/js/libs/draco/draco_wasm_wrapper.js',
 
 	'../examples/js/loaders/AMFLoader.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',
@@ -34,6 +36,7 @@ const assets = [
 	'../examples/js/exporters/ColladaExporter.js',
 	'../examples/js/exporters/GLTFExporter.js',
 	'../examples/js/exporters/OBJExporter.js',
+	'../examples/js/exporters/PLYExporter.js',
 	'../examples/js/exporters/STLExporter.js',
 
 	'../examples/js/renderers/Projector.js',

+ 0 - 5
examples/css3d_molecules.html

@@ -135,7 +135,6 @@
 
 				controls = new TrackballControls( camera, renderer.domElement );
 				controls.rotateSpeed = 0.5;
-				controls.addEventListener( 'change', render );
 
 				//
 
@@ -484,8 +483,6 @@
 
 					}
 
-					render();
-
 				} );
 
 
@@ -500,8 +497,6 @@
 
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
-				render();
-
 			}
 
 			function animate() {

+ 16 - 2
examples/css3d_panorama_deviceorientation.html

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

+ 22 - 21
examples/files.js

@@ -47,11 +47,13 @@ var files = {
 		"webgl_geometry_text_shapes",
 		"webgl_geometry_text_stroke",
 		"webgl_helpers",
-		"webgl_instancing_suzanne",
+		"webgl_instancing_dynamic",
+		"webgl_instancing_interactive",
+		"webgl_instancing_raycast",
+		"webgl_instancing_scatter",
 		"webgl_interactive_buffergeometry",
 		"webgl_interactive_cubes",
 		"webgl_interactive_cubes_gpu",
-		"webgl_interactive_instances_gpu",
 		"webgl_interactive_cubes_ortho",
 		"webgl_interactive_lines",
 		"webgl_interactive_points",
@@ -61,6 +63,7 @@ var files = {
 		"webgl_layers",
 		"webgl_lensflares",
 		"webgl_lightprobe",
+		"webgl_lightprobe_cubecamera",
 		"webgl_lights_hemisphere",
 		"webgl_lights_physical",
 		"webgl_lights_pointlights",
@@ -129,7 +132,7 @@ var files = {
 		"webgl_materials_blending_custom",
 		"webgl_materials_bumpmap",
 		"webgl_materials_bumpmap_skin",
-		"webgl_materials_cars",
+		"webgl_materials_car",
 		"webgl_materials_channels",
 		"webgl_materials_cubemap",
 		"webgl_materials_cubemap_balls_reflection",
@@ -222,7 +225,6 @@ var files = {
 		"webgl_shadowmesh",
 		"webgl_skinning_simple",
 		"webgl_sprites",
-		"webgl_terrain_dynamic",
 		"webgl_test_memory",
 		"webgl_test_memory2",
 		"webgl_tonemapping",
@@ -276,10 +278,8 @@ var files = {
 		"webgl_buffergeometry_drawrange",
 		"webgl_buffergeometry_indexed",
 		"webgl_buffergeometry_instancing",
-		"webgl_buffergeometry_instancing2",
 		"webgl_buffergeometry_instancing_billboards",
-		"webgl_buffergeometry_instancing_dynamic",
-		"webgl_buffergeometry_instancing_interleaved_dynamic",
+		"webgl_buffergeometry_instancing_interleaved",
 		"webgl_buffergeometry_instancing_lambert",
 		"webgl_buffergeometry_lines",
 		"webgl_buffergeometry_lines_indexed",
@@ -320,20 +320,20 @@ var files = {
 		"webaudio_timing",
 		"webaudio_visualizer"
 	],
-	"webvr": [
-		"webvr_ballshooter",
-		"webvr_cubes",
-		"webvr_dragging",
-		"webvr_lorenzattractor",
-		"webvr_multiview",
-		"webvr_panorama",
-		"webvr_paint",
-		"webvr_rollercoaster",
-		"webvr_sandbox",
-		"webvr_sculpt",
-		"webvr_video",
-		"webvr_vive_paint",
-		"webvr_vive_sculpt"
+	"webxr": [
+		"webxr_ar_paint",
+		"webxr_vr_ballshooter",
+		"webxr_vr_cubes",
+		"webxr_vr_dragging",
+		"webxr_vr_lorenzattractor",
+		"webxr_vr_multiview",
+		"webxr_vr_panorama",
+		"webxr_vr_panorama_depth",
+		"webxr_vr_paint",
+		"webxr_vr_rollercoaster",
+		"webxr_vr_sandbox",
+		"webxr_vr_sculpt",
+		"webxr_vr_video"
 	],
 	"physics": [
 		"webgl_physics_cloth",
@@ -359,6 +359,7 @@ var files = {
 		"misc_exporter_draco",
 		"misc_exporter_gltf",
 		"misc_exporter_obj",
+		"misc_exporter_ply",
 		"misc_exporter_stl",
 		"misc_lookat",
 	],

+ 25 - 2
examples/js/controls/DeviceOrientationControls.js

@@ -61,8 +61,31 @@ THREE.DeviceOrientationControls = function ( object ) {
 
 		onScreenOrientationChangeEvent(); // run once on load
 
-		window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
-		window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
+		// iOS 13+
+
+		if ( window.DeviceOrientationEvent !== undefined && typeof window.DeviceOrientationEvent.requestPermission === 'function' ) {
+
+			window.DeviceOrientationEvent.requestPermission().then( function ( response ) {
+
+				if ( response == 'granted' ) {
+
+					window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
+					window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
+
+				}
+
+			} ).catch( function ( error ) {
+
+				console.error( 'THREE.DeviceOrientationControls: Unable to use DeviceOrientation API:', error );
+
+			} );
+
+		} else {
+
+			window.addEventListener( 'orientationchange', onScreenOrientationChangeEvent, false );
+			window.addEventListener( 'deviceorientation', onDeviceOrientationChangeEvent, false );
+
+		}
 
 		scope.enabled = true;
 

+ 10 - 2
examples/js/controls/OrbitControls.js

@@ -258,7 +258,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 		document.removeEventListener( 'mousemove', onMouseMove, false );
 		document.removeEventListener( 'mouseup', onMouseUp, false );
 
-		window.removeEventListener( 'keydown', onKeyDown, false );
+		scope.domElement.removeEventListener( 'keydown', onKeyDown, false );
 
 		//scope.dispatchEvent( { type: 'dispose' } ); // should this be added here?
 
@@ -1136,7 +1136,15 @@ THREE.OrbitControls = function ( object, domElement ) {
 	scope.domElement.addEventListener( 'touchend', onTouchEnd, false );
 	scope.domElement.addEventListener( 'touchmove', onTouchMove, false );
 
-	window.addEventListener( 'keydown', onKeyDown, false );
+	scope.domElement.addEventListener( 'keydown', onKeyDown, false );
+
+	// make sure element can receive keys.
+
+	if ( scope.domElement.tabIndex === - 1 ) {
+
+		scope.domElement.tabIndex = 0;
+
+	}
 
 	// force an update at start
 

+ 95 - 105
examples/js/effects/OutlineEffect.js

@@ -54,9 +54,6 @@
  * 	visible: true,
  * 	keepAlive: true
  * };
- *
- * TODO
- *  - support shader material without objectNormal in its vertexShader
  */
 
 THREE.OutlineEffect = function ( renderer, parameters ) {
@@ -90,58 +87,57 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 	//this.cache = cache;  // for debug
 
-	// copied from WebGLPrograms and removed some materials
-	var shaderIDs = {
-		MeshBasicMaterial: 'basic',
-		MeshLambertMaterial: 'lambert',
-		MeshPhongMaterial: 'phong',
-		MeshToonMaterial: 'phong',
-		MeshStandardMaterial: 'physical',
-		MeshPhysicalMaterial: 'physical'
-	};
-
-	var uniformsChunk = {
+	var uniformsOutline = {
 		outlineThickness: { value: defaultThickness },
 		outlineColor: { value: defaultColor },
 		outlineAlpha: { value: defaultAlpha }
 	};
 
-	var vertexShaderChunk = [
+	var vertexShader = [
+		"#include <common>",
+		"#include <uv_pars_vertex>",
+		"#include <displacementmap_pars_vertex>",
+		"#include <fog_pars_vertex>",
+		"#include <morphtarget_pars_vertex>",
+		"#include <skinning_pars_vertex>",
+		"#include <logdepthbuf_pars_vertex>",
+		"#include <clipping_planes_pars_vertex>",
 
 		"uniform float outlineThickness;",
 
-		"vec4 calculateOutline( vec4 pos, vec3 objectNormal, vec4 skinned ) {",
-
+		"vec4 calculateOutline( vec4 pos, vec3 normal, vec4 skinned ) {",
 		"	float thickness = outlineThickness;",
 		"	const float ratio = 1.0;", // TODO: support outline thickness ratio for each vertex
-		"	vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + objectNormal, 1.0 );",
+		"	vec4 pos2 = projectionMatrix * modelViewMatrix * vec4( skinned.xyz + normal, 1.0 );",
 		// NOTE: subtract pos2 from pos because BackSide objectNormal is negative
 		"	vec4 norm = normalize( pos - pos2 );",
 		"	return pos + norm * thickness * pos.w * ratio;",
+		"}",
 
-		"}"
+		"void main() {",
 
-	].join( "\n" );
+		"	#include <uv_vertex>",
 
-	var vertexShaderChunk2 = [
+		"	#include <beginnormal_vertex>",
+		"	#include <morphnormal_vertex>",
+		"	#include <skinbase_vertex>",
+		"	#include <skinnormal_vertex>",
 
-		"#if ! defined( LAMBERT ) && ! defined( PHONG ) && ! defined( TOON ) && ! defined( STANDARD )",
-		"	#ifndef USE_ENVMAP",
-		"		vec3 objectNormal = normalize( normal );",
-		"	#endif",
-		"#endif",
+		"	#include <begin_vertex>",
+		"	#include <morphtarget_vertex>",
+		"	#include <skinning_vertex>",
+		"	#include <displacementmap_vertex>",
+		"	#include <project_vertex>",
 
-		"#ifdef FLIP_SIDED",
-		"	objectNormal = -objectNormal;",
-		"#endif",
+		"	vec3 outlineNormal = - objectNormal;", // the outline material is always rendered with THREE.BackSide
 
-		"#ifdef DECLARE_TRANSFORMED",
-		"	vec3 transformed = vec3( position );",
-		"#endif",
+		"	gl_Position = calculateOutline( gl_Position, outlineNormal, vec4( transformed, 1.0 ) );",
 
-		"gl_Position = calculateOutline( gl_Position, objectNormal, vec4( transformed, 1.0 ) );",
+		"	#include <logdepthbuf_vertex>",
+		"	#include <clipping_planes_vertex>",
+		"	#include <fog_vertex>",
 
-		"#include <fog_vertex>"
+		"}",
 
 	].join( "\n" );
 
@@ -149,92 +145,40 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 		"#include <common>",
 		"#include <fog_pars_fragment>",
+		"#include <logdepthbuf_pars_fragment>",
+		"#include <clipping_planes_pars_fragment>",
 
 		"uniform vec3 outlineColor;",
 		"uniform float outlineAlpha;",
 
 		"void main() {",
 
+		"	#include <clipping_planes_fragment>",
+		"	#include <logdepthbuf_fragment>",
+
 		"	gl_FragColor = vec4( outlineColor, outlineAlpha );",
 
+		"	#include <premultiplied_alpha_fragment>",
+		"	#include <tonemapping_fragment>",
+		"	#include <encodings_fragment>",
 		"	#include <fog_fragment>",
 
 		"}"
 
 	].join( "\n" );
 
-	function createInvisibleMaterial() {
-
-		return new THREE.ShaderMaterial( { name: 'invisible', visible: false } );
-
-	}
-
-	function createMaterial( originalMaterial ) {
-
-		var shaderID = shaderIDs[ originalMaterial.type ];
-		var originalUniforms, originalVertexShader;
-
-		if ( shaderID !== undefined ) {
-
-			var shader = THREE.ShaderLib[ shaderID ];
-			originalUniforms = shader.uniforms;
-			originalVertexShader = shader.vertexShader;
-
-		} else if ( originalMaterial.isRawShaderMaterial === true ) {
-
-			originalUniforms = originalMaterial.uniforms;
-			originalVertexShader = originalMaterial.vertexShader;
-
-			if ( ! /attribute\s+vec3\s+position\s*;/.test( originalVertexShader ) ||
-			     ! /attribute\s+vec3\s+normal\s*;/.test( originalVertexShader ) ) {
-
-				console.warn( 'THREE.OutlineEffect requires both vec3 position and normal attributes in vertex shader, ' +
-				              'does not draw outline for ' + originalMaterial.name + '(uuid:' + originalMaterial.uuid + ') material.' );
-
-				return createInvisibleMaterial();
-
-			}
-
-		} else if ( originalMaterial.isShaderMaterial === true ) {
-
-			originalUniforms = originalMaterial.uniforms;
-			originalVertexShader = originalMaterial.vertexShader;
-
-		} else {
-
-			return createInvisibleMaterial();
-
-		}
-
-		var uniforms = Object.assign( {}, originalUniforms, uniformsChunk );
-
-		var vertexShader = originalVertexShader
-			// put vertexShaderChunk right before "void main() {...}"
-			.replace( /void\s+main\s*\(\s*\)/, vertexShaderChunk + '\nvoid main()' )
-			// put vertexShaderChunk2 the end of "void main() {...}"
-			// Note: here assums originalVertexShader ends with "}" of "void main() {...}"
-			.replace( /\}\s*$/, vertexShaderChunk2 + '\n}' )
-			// remove any light related lines
-			// Note: here is very sensitive to originalVertexShader
-			// TODO: consider safer way
-			.replace( /#include\s+<[\w_]*light[\w_]*>/g, '' );
-
-		var defines = {};
-
-		if ( ! /vec3\s+transformed\s*=/.test( originalVertexShader ) &&
-		     ! /#include\s+<begin_vertex>/.test( originalVertexShader ) ) defines.DECLARE_TRANSFORMED = true;
+	function createMaterial() {
 
 		return new THREE.ShaderMaterial( {
-			defines: defines,
-			uniforms: uniforms,
+			type: 'OutlineEffect',
+			uniforms: THREE.UniformsUtils.merge( [
+				THREE.UniformsLib[ 'fog' ],
+				THREE.UniformsLib[ 'displacementmap' ],
+				uniformsOutline
+			] ),
 			vertexShader: vertexShader,
 			fragmentShader: fragmentShader,
-			side: THREE.BackSide,
-			//wireframe: true,
-			skinning: false,
-			morphTargets: false,
-			morphNormals: false,
-			fog: false
+			side: THREE.BackSide
 		} );
 
 	}
@@ -246,7 +190,7 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 		if ( data === undefined ) {
 
 			data = {
-				material: createMaterial( originalMaterial ),
+				material: createMaterial(),
 				used: true,
 				keepAlive: defaultKeepAlive,
 				count: 0
@@ -274,9 +218,32 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 	}
 
+	function isCompatible( object ) {
+
+		var geometry = object.geometry;
+		var hasNormals = false;
+
+		if ( object.geometry !== undefined ) {
+
+			if ( geometry.isBufferGeometry ) {
+
+				hasNormals = geometry.attributes.normal !== undefined;
+
+			} else {
+
+				hasNormals = true; // the renderer always produces a normal attribute for Geometry
+
+			}
+
+		}
+
+		return ( object.isMesh === true && object.material !== undefined && hasNormals === true );
+
+	}
+
 	function setOutlineMaterial( object ) {
 
-		if ( object.material === undefined ) return;
+		if ( isCompatible( object ) === false ) return;
 
 		if ( Array.isArray( object.material ) ) {
 
@@ -299,7 +266,7 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 	function restoreOriginalMaterial( object ) {
 
-		if ( object.material === undefined ) return;
+		if ( isCompatible( object ) === false ) return;
 
 		if ( Array.isArray( object.material ) ) {
 
@@ -344,6 +311,14 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 		}
 
+		if ( originalMaterial.displacementMap ) {
+
+			material.uniforms.displacementMap.value = originalMaterial.displacementMap;
+			material.uniforms.displacementScale.value = originalMaterial.displacementScale;
+			material.uniforms.displacementBias.value = originalMaterial.displacementBias;
+
+		}
+
 	}
 
 	function updateOutlineMaterial( material, originalMaterial ) {
@@ -356,6 +331,9 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 		material.morphTargets = originalMaterial.morphTargets;
 		material.morphNormals = originalMaterial.morphNormals;
 		material.fog = originalMaterial.fog;
+		material.toneMapped = originalMaterial.toneMapped;
+		material.premultipliedAlpha = originalMaterial.premultipliedAlpha;
+		material.displacementMap = originalMaterial.displacementMap;
 
 		if ( outlineParameters !== undefined ) {
 
@@ -382,6 +360,18 @@ THREE.OutlineEffect = function ( renderer, parameters ) {
 
 		if ( originalMaterial.wireframe === true || originalMaterial.depthTest === false ) material.visible = false;
 
+		if ( originalMaterial.clippingPlanes ) {
+
+			material.clipping = true;
+
+			material.clippingPlanes = originalMaterial.clippingPlanes;
+			material.clipIntersection = originalMaterial.clipIntersection;
+			material.clipShadows = originalMaterial.clipShadows;
+
+		}
+
+		material.version = originalMaterial.version; // update outline material if necessary
+
 	}
 
 	function cleanupCache() {

+ 12 - 21
examples/js/exporters/GLTFExporter.js

@@ -1175,20 +1175,7 @@ THREE.GLTFExporter.prototype = {
 
 				}
 
-				if ( mesh.drawMode === THREE.TriangleFanDrawMode ) {
-
-					console.warn( 'GLTFExporter: TriangleFanDrawMode and wireframe incompatible.' );
-					mode = WEBGL_CONSTANTS.TRIANGLE_FAN;
-
-				} else if ( mesh.drawMode === THREE.TriangleStripDrawMode ) {
-
-					mode = mesh.material.wireframe ? WEBGL_CONSTANTS.LINE_STRIP : WEBGL_CONSTANTS.TRIANGLE_STRIP;
-
-				} else {
-
-					mode = mesh.material.wireframe ? WEBGL_CONSTANTS.LINES : WEBGL_CONSTANTS.TRIANGLES;
-
-				}
+				mode = mesh.material.wireframe ? WEBGL_CONSTANTS.LINES : WEBGL_CONSTANTS.TRIANGLES;
 
 			}
 
@@ -1339,14 +1326,18 @@ THREE.GLTFExporter.prototype = {
 						// Clones attribute not to override
 						var relativeAttribute = attribute.clone();
 
-						for ( var j = 0, jl = attribute.count; j < jl; j ++ ) {
+						if ( ! geometry.morphTargetsRelative ) {
+
+							for ( var j = 0, jl = attribute.count; j < jl; j ++ ) {
 
-							relativeAttribute.setXYZ(
-								j,
-								attribute.getX( j ) - baseAttribute.getX( j ),
-								attribute.getY( j ) - baseAttribute.getY( j ),
-								attribute.getZ( j ) - baseAttribute.getZ( j )
-							);
+								relativeAttribute.setXYZ(
+									j,
+									attribute.getX( j ) - baseAttribute.getX( j ),
+									attribute.getY( j ) - baseAttribute.getY( j ),
+									attribute.getZ( j ) - baseAttribute.getZ( j )
+									);
+
+							}
 
 						}
 

+ 1 - 1
examples/js/exporters/OBJExporter.js

@@ -105,7 +105,7 @@ THREE.OBJExporter.prototype = {
 						normal.z = normals.getZ( i );
 
 						// transfrom the normal to world space
-						normal.applyMatrix3( normalMatrixWorld );
+						normal.applyMatrix3( normalMatrixWorld ).normalize();
 
 						// transform the normal to export format
 						output += 'vn ' + normal.x + ' ' + normal.y + ' ' + normal.z + '\n';

+ 12 - 27
examples/js/exporters/PLYExporter.js

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

+ 123 - 1
examples/js/lights/LightProbeGenerator.js

@@ -50,7 +50,7 @@ THREE.LightProbeGenerator = {
 				color.setRGB( data[ i ] / 255, data[ i + 1 ] / 255, data[ i + 2 ] / 255 );
 
 				// convert to linear color space
-				color.copySRGBToLinear( color );
+				convertColorToLinear( color, cubeTexture.encoding );
 
 				// pixel coordinate on unit cube
 
@@ -116,6 +116,128 @@ THREE.LightProbeGenerator = {
 
 		return new THREE.LightProbe( sh );
 
+	},
+
+	fromRenderTargetCube: function ( renderer, renderTargetCube ) {
+
+		// The renderTarget must be set to RGBA in order to make readRenderTargetPixels works
+		var norm, lengthSq, weight, totalWeight = 0;
+
+		var coord = new THREE.Vector3();
+
+		var dir = new THREE.Vector3();
+
+		var color = new THREE.Color();
+
+		var shBasis = [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
+
+		var sh = new THREE.SphericalHarmonics3();
+		var shCoefficients = sh.coefficients;
+
+		for ( var faceIndex = 0; faceIndex < 6; faceIndex ++ ) {
+
+			var imageWidth = renderTargetCube.width; // assumed to be square
+			var data = new Uint8Array( imageWidth * imageWidth * 4 );
+			renderer.readRenderTargetPixels( renderTargetCube, 0, 0, imageWidth, imageWidth, data, faceIndex );
+
+			var pixelSize = 2 / imageWidth;
+
+			for ( var i = 0, il = data.length; i < il; i += 4 ) { // RGBA assumed
+
+				// pixel color
+				color.setRGB( data[ i ] / 255, data[ i + 1 ] / 255, data[ i + 2 ] / 255 );
+
+				// convert to linear color space
+				convertColorToLinear( color, renderTargetCube.texture.encoding );
+
+				// pixel coordinate on unit cube
+
+				var pixelIndex = i / 4;
+
+				var col = - 1 + ( pixelIndex % imageWidth + 0.5 ) * pixelSize;
+
+				var row = 1 - ( Math.floor( pixelIndex / imageWidth ) + 0.5 ) * pixelSize;
+
+				switch ( faceIndex ) {
+
+					case 0: coord.set( 1, row, - col ); break;
+
+					case 1: coord.set( - 1, row, col ); break;
+
+					case 2: coord.set( col, 1, - row ); break;
+
+					case 3: coord.set( col, - 1, row ); break;
+
+					case 4: coord.set( col, row, 1 ); break;
+
+					case 5: coord.set( - col, row, - 1 ); break;
+
+				}
+
+				// weight assigned to this pixel
+
+				lengthSq = coord.lengthSq();
+
+				weight = 4 / ( Math.sqrt( lengthSq ) * lengthSq );
+
+				totalWeight += weight;
+
+				// direction vector to this pixel
+				dir.copy( coord ).normalize();
+
+				// evaluate SH basis functions in direction dir
+				THREE.SphericalHarmonics3.getBasisAt( dir, shBasis );
+
+				// accummuulate
+				for ( var j = 0; j < 9; j ++ ) {
+
+					shCoefficients[ j ].x += shBasis[ j ] * color.r * weight;
+					shCoefficients[ j ].y += shBasis[ j ] * color.g * weight;
+					shCoefficients[ j ].z += shBasis[ j ] * color.b * weight;
+
+				}
+
+			}
+
+		}
+
+		// normalize
+		norm = ( 4 * Math.PI ) / totalWeight;
+
+		for ( var j = 0; j < 9; j ++ ) {
+
+			shCoefficients[ j ].x *= norm;
+			shCoefficients[ j ].y *= norm;
+			shCoefficients[ j ].z *= norm;
+
+		}
+
+		return new THREE.LightProbe( sh );
+
+	}
+
+};
+
+var convertColorToLinear = function ( color, encoding ) {
+
+	switch ( encoding ) {
+
+		case THREE.sRGBEncoding:
+
+			color.convertSRGBToLinear();
+			break;
+
+		case THREE.LinearEncoding:
+
+			break;
+
+		default:
+
+			console.warn( 'WARNING: LightProbeGenerator convertColorToLinear() encountered an unsupported encoding.' );
+			break;
+
 	}
 
+	return color;
+
 };

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

@@ -246,7 +246,9 @@ THREE.LineMaterial = function ( parameters ) {
 		uniforms: THREE.UniformsUtils.clone( THREE.ShaderLib[ 'line' ].uniforms ),
 
 		vertexShader: THREE.ShaderLib[ 'line' ].vertexShader,
-		fragmentShader: THREE.ShaderLib[ 'line' ].fragmentShader
+		fragmentShader: THREE.ShaderLib[ 'line' ].fragmentShader,
+
+		clipping: true // required for clipping support
 
 	} );
 

+ 192 - 8
examples/js/loaders/3MFLoader.js

@@ -14,6 +14,8 @@
  *
  * - Texture 2D
  * - Texture 2D Groups
+ * - Color Groups (Vertex Colors)
+ * - Metallic Display Properties (PBR)
  */
 
 THREE.ThreeMFLoader = function ( manager ) {
@@ -260,6 +262,7 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
 
 				var basematerialNode = basematerialNodes[ i ];
 				var basematerialData = parseBasematerialNode( basematerialNode );
+				basematerialData.index = i; // the order and count of the material nodes form an implicit 0-based index
 				basematerialsData.basematerials.push( basematerialData );
 
 			}
@@ -283,7 +286,7 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
 
 		}
 
-		function parseTextures2DGroupNodes( texture2DGroupNode ) {
+		function parseTextures2DGroupNode( texture2DGroupNode ) {
 
 			var texture2DGroupData = {
 				id: texture2DGroupNode.getAttribute( 'id' ), // required
@@ -311,12 +314,71 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
 
 		}
 
+		function parseColorGroupNode( colorGroupNode ) {
+
+			var colorGroupData = {
+				id: colorGroupNode.getAttribute( 'id' ), // required
+				displaypropertiesid: colorGroupNode.getAttribute( 'displaypropertiesid' )
+			};
+
+			var colorNodes = colorGroupNode.querySelectorAll( 'color' );
+
+			var colors = [];
+			var colorObject = new THREE.Color();
+
+			for ( var i = 0; i < colorNodes.length; i ++ ) {
+
+				var colorNode = colorNodes[ i ];
+				var color = colorNode.getAttribute( 'color' );
+
+				colorObject.setStyle( color.substring( 0, 7 ) );
+				colorObject.convertSRGBToLinear(); // color is in sRGB
+
+				colors.push( colorObject.r, colorObject.g, colorObject.b );
+
+			}
+
+			colorGroupData[ 'colors' ] = new Float32Array( colors );
+
+			return colorGroupData;
+
+		}
+
+		function parseMetallicDisplaypropertiesNode( metallicDisplaypropetiesNode ) {
+
+			var metallicDisplaypropertiesData = {
+				id: metallicDisplaypropetiesNode.getAttribute( 'id' ) // required
+			};
+
+			var metallicNodes = metallicDisplaypropetiesNode.querySelectorAll( 'pbmetallic' );
+
+			var metallicData = [];
+
+			for ( var i = 0; i < metallicNodes.length; i ++ ) {
+
+				var metallicNode = metallicNodes[ i ];
+
+				metallicData.push( {
+					name: metallicNode.getAttribute( 'name' ), // required
+					metallicness: parseFloat( metallicNode.getAttribute( 'metallicness' ) ), // required
+					roughness: parseFloat( metallicNode.getAttribute( 'roughness' ) ) // required
+				} );
+
+			}
+
+			metallicDisplaypropertiesData.data = metallicData;
+
+			return metallicDisplaypropertiesData;
+
+		}
+
 		function parseBasematerialNode( basematerialNode ) {
 
 			var basematerialData = {};
 
 			basematerialData[ 'name' ] = basematerialNode.getAttribute( 'name' ); // required
 			basematerialData[ 'displaycolor' ] = basematerialNode.getAttribute( 'displaycolor' ); // required
+			basematerialData[ 'displaypropertiesid' ] = basematerialNode.getAttribute( 'displaypropertiesid' );
 
 			return basematerialData;
 
@@ -567,13 +629,39 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
 
 			//
 
+			resourcesData[ 'colorgroup' ] = {};
+			var colorGroupNodes = resourcesNode.querySelectorAll( 'colorgroup' );
+
+			for ( var i = 0; i < colorGroupNodes.length; i ++ ) {
+
+				var colorGroupNode = colorGroupNodes[ i ];
+				var colorGroupData = parseColorGroupNode( colorGroupNode );
+				resourcesData[ 'colorgroup' ][ colorGroupData[ 'id' ] ] = colorGroupData;
+
+			}
+
+			//
+
+			resourcesData[ 'pbmetallicdisplayproperties' ] = {};
+			var pbmetallicdisplaypropertiesNodes = resourcesNode.querySelectorAll( 'pbmetallicdisplayproperties' );
+
+			for ( var i = 0; i < pbmetallicdisplaypropertiesNodes.length; i ++ ) {
+
+				var pbmetallicdisplaypropertiesNode = pbmetallicdisplaypropertiesNodes[ i ];
+				var pbmetallicdisplaypropertiesData = parseMetallicDisplaypropertiesNode( pbmetallicdisplaypropertiesNode );
+				resourcesData[ 'pbmetallicdisplayproperties' ][ pbmetallicdisplaypropertiesData[ 'id' ] ] = pbmetallicdisplaypropertiesData;
+
+			}
+
+			//
+
 			resourcesData[ 'texture2dgroup' ] = {};
 			var textures2DGroupNodes = resourcesNode.querySelectorAll( 'texture2dgroup' );
 
 			for ( var i = 0; i < textures2DGroupNodes.length; i ++ ) {
 
 				var textures2DGroupNode = textures2DGroupNodes[ i ];
-				var textures2DGroupData = parseTextures2DGroupNodes( textures2DGroupNode );
+				var textures2DGroupData = parseTextures2DGroupNode( textures2DGroupNode );
 				resourcesData[ 'texture2dgroup' ][ textures2DGroupData[ 'id' ] ] = textures2DGroupData;
 
 			}
@@ -877,6 +965,73 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
 
 		}
 
+		function buildVertexColorMesh( colorgroup, triangleProperties, modelData, meshData ) {
+
+			// geometry
+
+			var geometry = new THREE.BufferGeometry();
+
+			var positionData = [];
+			var colorData = [];
+
+			var vertices = meshData.vertices;
+			var colors = colorgroup.colors;
+
+			for ( var i = 0, l = triangleProperties.length; i < l; i ++ ) {
+
+				var triangleProperty = triangleProperties[ i ];
+
+				var v1 = triangleProperty.v1;
+				var v2 = triangleProperty.v2;
+				var v3 = triangleProperty.v3;
+
+				positionData.push( vertices[ ( v1 * 3 ) + 0 ] );
+				positionData.push( vertices[ ( v1 * 3 ) + 1 ] );
+				positionData.push( vertices[ ( v1 * 3 ) + 2 ] );
+
+				positionData.push( vertices[ ( v2 * 3 ) + 0 ] );
+				positionData.push( vertices[ ( v2 * 3 ) + 1 ] );
+				positionData.push( vertices[ ( v2 * 3 ) + 2 ] );
+
+				positionData.push( vertices[ ( v3 * 3 ) + 0 ] );
+				positionData.push( vertices[ ( v3 * 3 ) + 1 ] );
+				positionData.push( vertices[ ( v3 * 3 ) + 2 ] );
+
+				//
+
+				var p1 = triangleProperty.p1;
+				var p2 = triangleProperty.p2;
+				var p3 = triangleProperty.p3;
+
+				colorData.push( colors[ ( p1 * 3 ) + 0 ] );
+				colorData.push( colors[ ( p1 * 3 ) + 1 ] );
+				colorData.push( colors[ ( p1 * 3 ) + 2 ] );
+
+				colorData.push( colors[ ( ( p2 || p1 ) * 3 ) + 0 ] );
+				colorData.push( colors[ ( ( p2 || p1 ) * 3 ) + 1 ] );
+				colorData.push( colors[ ( ( p2 || p1 ) * 3 ) + 2 ] );
+
+				colorData.push( colors[ ( ( p3 || p1 ) * 3 ) + 0 ] );
+				colorData.push( colors[ ( ( p3 || p1 ) * 3 ) + 1 ] );
+				colorData.push( colors[ ( ( p3 || p1 ) * 3 ) + 2 ] );
+
+			}
+
+			geometry.setAttribute( 'position', new THREE.Float32BufferAttribute( positionData, 3 ) );
+			geometry.setAttribute( 'color', new THREE.Float32BufferAttribute( colorData, 3 ) );
+
+			// material
+
+			var material = new THREE.MeshPhongMaterial( { vertexColors: THREE.VertexColors, flatShading: true } );
+
+			// mesh
+
+			var mesh = new THREE.Mesh( geometry, material );
+
+			return mesh;
+
+		}
+
 		function buildDefaultMesh( meshData ) {
 
 			var geometry = new THREE.BufferGeometry();
@@ -896,7 +1051,7 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
 			var keys = Object.keys( resourceMap );
 			var meshes = [];
 
-			for ( var i = 0; i < keys.length; i ++ ) {
+			for ( var i = 0, il = keys.length; i < il; i ++ ) {
 
 				var resourceId = keys[ i ];
 				var triangleProperties = resourceMap[ resourceId ];
@@ -908,16 +1063,21 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
 						var basematerials = modelData.resources.basematerials[ resourceId ];
 						var newMeshes = buildBasematerialsMeshes( basematerials, triangleProperties, modelData, meshData, textureData, objectData );
 
-						for ( var i = 0, l = newMeshes.length; i < l; i ++ ) {
+						for ( var j = 0, jl = newMeshes.length; j < jl; j ++ ) {
 
-							meshes.push( newMeshes[ i ] );
+							meshes.push( newMeshes[ j ] );
 
 						}
 						break;
 
 					case 'texture':
 						var texture2dgroup = modelData.resources.texture2dgroup[ resourceId ];
-						meshes.push( buildTexturedMesh( texture2dgroup, triangleProperties, modelData, meshData, textureData ) );
+						meshes.push( buildTexturedMesh( texture2dgroup, triangleProperties, modelData, meshData, textureData, objectData ) );
+						break;
+
+					case 'vertexColors':
+						var colorgroup = modelData.resources.colorgroup[ resourceId ];
+						meshes.push( buildVertexColorMesh( colorgroup, triangleProperties, modelData, meshData ) );
 						break;
 
 					case 'default':
@@ -945,6 +1105,10 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
 
 				return 'material';
 
+			} else if ( modelData.resources.colorgroup[ pid ] !== undefined ) {
+
+				return 'vertexColors';
+
 			} else if ( pid === 'default' ) {
 
 				return 'default';
@@ -1047,9 +1211,29 @@ THREE.ThreeMFLoader.prototype = Object.assign( Object.create( THREE.Loader.proto
 
 		}
 
-		function buildBasematerial( materialData ) {
+		function buildBasematerial( materialData, objects, modelData ) {
+
+			var material;
+
+			var displaypropertiesid = materialData.displaypropertiesid;
+			var pbmetallicdisplayproperties = modelData.resources.pbmetallicdisplayproperties;
+
+			if ( displaypropertiesid !== null && pbmetallicdisplayproperties[ displaypropertiesid ] !== undefined ) {
+
+				// metallic display property, use StandardMaterial
+
+				var pbmetallicdisplayproperty = pbmetallicdisplayproperties[ displaypropertiesid ];
+				var metallicData = pbmetallicdisplayproperty.data[ materialData.index ];
 
-			var material = new THREE.MeshPhongMaterial( { flatShading: true } );
+				material = new THREE.MeshStandardMaterial( { flatShading: true, roughness: metallicData.roughness, metalness: metallicData.metallicness } );
+
+			} else {
+
+				// otherwise use PhongMaterial
+
+				material = new THREE.MeshPhongMaterial( { flatShading: true } );
+
+			}
 
 			material.name = materialData.name;
 

+ 8 - 0
examples/js/loaders/DRACOLoader.js

@@ -220,6 +220,14 @@ THREE.DRACOLoader.prototype = Object.assign( Object.create( THREE.Loader.prototy
 
 	},
 
+	preload: function () {
+
+		this._initDecoder();
+
+		return this;
+
+	},
+
 	_initDecoder: function () {
 
 		if ( this.decoderPending ) return this.decoderPending;

+ 293 - 93
examples/js/loaders/EXRLoader.js

@@ -1,8 +1,9 @@
 /**
  * @author Richard M. / https://github.com/richardmonette
+ * @author ScieCode / http://github.com/sciecode
  *
- * OpenEXR loader which, currently, supports reading 16 bit half data, in either
- * uncompressed or PIZ wavelet compressed form.
+ * OpenEXR loader which, currently, supports uncompressed, ZIP(S), RLE and PIZ wavelet compression.
+ * Supports reading 16 and 32 bit data format, except for PIZ compression which only reads 16-bit data.
  *
  * Referred to the original Industrial Light & Magic OpenEXR implementation and the TinyEXR / Syoyo Fujita
  * implementation, so I have preserved their copyright notices.
@@ -690,7 +691,134 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 		}
 
-		function decompressPIZ( outBuffer, outOffset, uInt8Array, inDataView, inOffset, tmpBufSize, num_channels, exrChannelInfos, dataWidth, num_lines ) {
+		function predictor( source ) {
+
+			for ( var t = 1; t < source.length; t ++ ) {
+
+				var d = source[ t - 1 ] + source[ t ] - 128;
+				source[ t ] = d;
+
+			}
+
+		}
+
+		function interleaveScalar( source, out ) {
+
+			var t1 = 0;
+			var t2 = Math.floor( ( source.length + 1 ) / 2 );
+			var s = 0;
+			var stop = source.length - 1;
+
+			while ( true ) {
+
+				if ( s > stop ) break;
+				out[ s ++ ] = source[ t1 ++ ];
+
+				if ( s > stop ) break;
+				out[ s ++ ] = source[ t2 ++ ];
+
+			}
+
+		}
+
+		function decodeRunLength( source ) {
+
+			var size = source.byteLength;
+			var out = new Array();
+			var p = 0;
+
+			var reader = new DataView( source );
+
+			while ( size > 0 ) {
+
+				var l = reader.getInt8( p ++ );
+
+				if ( l < 0 ) {
+
+					var count = - l;
+					size -= count + 1;
+
+					for ( var i = 0; i < count; i ++ ) {
+
+						out.push( reader.getUint8( p ++ ) );
+
+					}
+
+
+				} else {
+
+					var count = l;
+					size -= 2;
+
+					var value = reader.getUint8( p ++ );
+
+					for ( var i = 0; i < count + 1; i ++ ) {
+
+						out.push( value );
+
+					}
+
+
+				}
+
+			}
+
+			return out;
+
+		}
+
+		function uncompressRaw( info ) {
+
+			return new DataView( info.array.buffer, info.offset.value, info.size );
+
+		}
+
+		function uncompressRLE( info ) {
+
+			var compressed = info.viewer.buffer.slice( info.offset.value, info.offset.value + info.size );
+
+			var rawBuffer = new Uint8Array( decodeRunLength( compressed ) );
+			var tmpBuffer = new Uint8Array( rawBuffer.length );
+
+			predictor( rawBuffer ); // revert predictor
+
+			interleaveScalar( rawBuffer, tmpBuffer ); // interleave pixels
+
+			return new DataView( tmpBuffer.buffer );
+
+		}
+
+		function uncompressZIP( info ) {
+
+			var compressed = info.array.slice( info.offset.value, info.offset.value + info.size );
+
+			if ( typeof Zlib === 'undefined' ) {
+
+				console.error( 'THREE.EXRLoader: External library Inflate.min.js required, obtain or import from https://github.com/imaya/zlib.js' );
+
+			}
+
+			var inflate = new Zlib.Inflate( compressed, { resize: true, verify: true } ); // eslint-disable-line no-undef
+
+			var rawBuffer = new Uint8Array( inflate.decompress().buffer );
+			var tmpBuffer = new Uint8Array( rawBuffer.length );
+
+			predictor( rawBuffer ); // revert predictor
+
+			interleaveScalar( rawBuffer, tmpBuffer ); // interleave pixels
+
+			return new DataView( tmpBuffer.buffer );
+
+		}
+
+		function uncompressPIZ( info ) {
+
+			var inDataView = info.viewer;
+			var inOffset = { value: info.offset.value };
+
+			var tmpBufSize = info.width * scanlineBlockSize * ( EXRHeader.channels.length * BYTES_PER_HALF );
+			var outBuffer = new Uint16Array( tmpBufSize );
+			var outOffset = { value: 0 };
 
 			var bitmap = new Uint8Array( BITMAP_SIZE );
 
@@ -718,19 +846,19 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 			var length = parseUint32( inDataView, inOffset );
 
-			hufUncompress( uInt8Array, inDataView, inOffset, length, outBuffer, outOffset, tmpBufSize );
+			hufUncompress( info.array, inDataView, inOffset, length, outBuffer, outOffset, tmpBufSize );
 
-			var pizChannelData = new Array( num_channels );
+			var pizChannelData = new Array( info.channels );
 
 			var outBufferEnd = 0;
 
-			for ( var i = 0; i < num_channels; i ++ ) {
+			for ( var i = 0; i < info.channels; i ++ ) {
 
 				pizChannelData[ i ] = {};
 				pizChannelData[ i ][ 'start' ] = outBufferEnd;
 				pizChannelData[ i ][ 'end' ] = pizChannelData[ i ][ 'start' ];
-				pizChannelData[ i ][ 'nx' ] = dataWidth;
-				pizChannelData[ i ][ 'ny' ] = num_lines;
+				pizChannelData[ i ][ 'nx' ] = info.width;
+				pizChannelData[ i ][ 'ny' ] = info.lines;
 				pizChannelData[ i ][ 'size' ] = 1;
 
 				outBufferEnd += pizChannelData[ i ].nx * pizChannelData[ i ].ny * pizChannelData[ i ].size;
@@ -739,7 +867,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 			var fooOffset = 0;
 
-			for ( var i = 0; i < num_channels; i ++ ) {
+			for ( var i = 0; i < info.channels; i ++ ) {
 
 				for ( var j = 0; j < pizChannelData[ i ].size; ++ j ) {
 
@@ -758,7 +886,25 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 			applyLut( lut, outBuffer, outBufferEnd );
 
-			return true;
+			var tmpBuffer = new Uint8Array( outBuffer.buffer.byteLength );
+			var tmpOffset = 0;
+			var n = info.width * 2;
+
+			for ( var y = 0; y < info.lines; y ++ ) {
+
+				for ( var c = 0; c < info.channels; c ++ ) {
+
+					var cd = pizChannelData[ c ];
+					var cp = new Uint8Array( outBuffer.buffer, cd.end * 2 + y * n, n );
+
+					tmpBuffer.set( cp, tmpOffset );
+					tmpOffset += n;
+
+				}
+
+			}
+
+			return new DataView( tmpBuffer.buffer );
 
 		}
 
@@ -979,7 +1125,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 		function parseValue( dataView, buffer, offset, type, size ) {
 
-			if ( type === 'string' || type === 'iccProfile' ) {
+			if ( type === 'string' || type === 'stringvector' || type === 'iccProfile' ) {
 
 				return parseFixedLengthString( buffer, offset, size );
 
@@ -1059,147 +1205,205 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 		}
 
 		// offsets
-
 		var dataWindowHeight = EXRHeader.dataWindow.yMax + 1;
-		var scanlineBlockSize = 1; // 1 for NO_COMPRESSION
-
-		if ( EXRHeader.compression === 'PIZ_COMPRESSION' ) {
-
-			scanlineBlockSize = 32;
 
-		}
+		var uncompress;
+		var scanlineBlockSize;
 
-		var numBlocks = dataWindowHeight / scanlineBlockSize;
+		switch ( EXRHeader.compression ) {
 
-		for ( var i = 0; i < numBlocks; i ++ ) {
+			case 'NO_COMPRESSION':
 
-			parseUlong( bufferDataView, offset ); // scanlineOffset
+				scanlineBlockSize = 1;
+				uncompress = uncompressRaw;
+				break;
 
-		}
+			case 'RLE_COMPRESSION':
 
-		// we should be passed the scanline offset table, start reading pixel data
+				scanlineBlockSize = 1;
+				uncompress = uncompressRLE;
+				break;
 
-		var width = EXRHeader.dataWindow.xMax - EXRHeader.dataWindow.xMin + 1;
-		var height = EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1;
-		var numChannels = EXRHeader.channels.length;
+			case 'ZIPS_COMPRESSION':
 
-		switch ( this.type ) {
+				scanlineBlockSize = 1;
+				uncompress = uncompressZIP;
+				break;
 
-			case THREE.FloatType:
+			case 'ZIP_COMPRESSION':
 
-				var byteArray = new Float32Array( width * height * numChannels );
+				scanlineBlockSize = 16;
+				uncompress = uncompressZIP;
 				break;
 
-			case THREE.HalfFloatType:
+			case 'PIZ_COMPRESSION':
 
-				var byteArray = new Uint16Array( width * height * numChannels );
+				scanlineBlockSize = 32;
+				uncompress = uncompressPIZ;
 				break;
 
 			default:
 
-				console.error( 'THREE.EXRLoader: unsupported type: ', this.type );
-				break;
+				throw 'EXRLoader.parse: ' + EXRHeader.compression + ' is unsupported';
 
 		}
 
-		var channelOffsets = {
-			R: 0,
-			G: 1,
-			B: 2,
-			A: 3
-		};
+		var size_t;
+		var getValue;
 
-		if ( EXRHeader.compression === 'NO_COMPRESSION' ) {
+		// mixed pixelType not supported
+		var pixelType = EXRHeader.channels[ 0 ].pixelType;
 
-			for ( var y = 0; y < height; y ++ ) {
+		if ( pixelType === 1 ) { // half
 
-				var y_scanline = parseUint32( bufferDataView, offset );
-				parseUint32( bufferDataView, offset ); // dataSize
+			switch ( this.type ) {
 
-				for ( var channelID = 0; channelID < EXRHeader.channels.length; channelID ++ ) {
+				case THREE.FloatType:
 
-					var cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ];
+					getValue = parseFloat16;
+					size_t = INT16_SIZE;
+					break;
 
-					if ( EXRHeader.channels[ channelID ].pixelType === 1 ) { // half
+				case THREE.HalfFloatType:
 
-						for ( var x = 0; x < width; x ++ ) {
+					getValue = parseUint16;
+					size_t = INT16_SIZE;
+					break;
 
-							switch ( this.type ) {
+			}
 
-								case THREE.FloatType:
+		} else if ( pixelType === 2 ) { // float
 
-									var val = parseFloat16( bufferDataView, offset );
-									break;
+			switch ( this.type ) {
 
-								case THREE.HalfFloatType:
+				case THREE.FloatType:
 
-									var val = parseUint16( bufferDataView, offset );
-									break;
+					getValue = parseFloat32;
+					size_t = FLOAT32_SIZE;
+					break;
 
-							}
+				case THREE.HalfFloatType:
 
-							byteArray[ ( ( ( height - y_scanline ) * ( width * numChannels ) ) + ( x * numChannels ) ) + cOff ] = val;
+					throw 'EXRLoader.parse: unsupported HalfFloatType texture for FloatType image file.';
 
-						}
+			}
 
-					} else {
+		} else {
 
-						throw 'EXRLoader._parser: unsupported pixelType ' + EXRHeader.channels[ channelID ].pixelType + '. Only pixelType is 1 (HALF) is supported.';
+			throw 'EXRLoader.parse: unsupported pixelType ' + pixelType + ' for ' + EXRHeader.compression + '.';
 
-					}
+		}
+
+		var numBlocks = dataWindowHeight / scanlineBlockSize;
+
+		for ( var i = 0; i < numBlocks; i ++ ) {
+
+			parseUlong( bufferDataView, offset ); // scanlineOffset
+
+		}
+
+		// we should be passed the scanline offset table, start reading pixel data
+
+		var width = EXRHeader.dataWindow.xMax - EXRHeader.dataWindow.xMin + 1;
+		var height = EXRHeader.dataWindow.yMax - EXRHeader.dataWindow.yMin + 1;
+		// Firefox only supports RGBA (half) float textures
+		// var numChannels = EXRHeader.channels.length;
+		var numChannels = 4;
+		var size = width * height * numChannels;
+
+		// Fill initially with 1s for the alpha value if the texture is not RGBA, RGB values will be overwritten
+		switch ( this.type ) {
+
+			case THREE.FloatType:
+
+				var byteArray = new Float32Array( size );
+
+				if ( EXRHeader.channels.length < numChannels ) {
+
+					byteArray.fill( 1, 0, size );
 
 				}
 
-			}
+				break;
 
-		} else if ( EXRHeader.compression === 'PIZ_COMPRESSION' ) {
+			case THREE.HalfFloatType:
 
-			for ( var scanlineBlockIdx = 0; scanlineBlockIdx < height / scanlineBlockSize; scanlineBlockIdx ++ ) {
+				var byteArray = new Uint16Array( size );
 
-				parseUint32( bufferDataView, offset ); // line_no
-				parseUint32( bufferDataView, offset ); // data_len
+				if ( EXRHeader.channels.length < numChannels ) {
 
-				var tmpBufferSize = width * scanlineBlockSize * ( EXRHeader.channels.length * BYTES_PER_HALF );
-				var tmpBuffer = new Uint16Array( tmpBufferSize );
-				var tmpOffset = { value: 0 };
+					byteArray.fill( 0x3C00, 0, size ); // Uint16Array holds half float data, 0x3C00 is 1
 
-				decompressPIZ( tmpBuffer, tmpOffset, uInt8Array, bufferDataView, offset, tmpBufferSize, numChannels, EXRHeader.channels, width, scanlineBlockSize );
+				}
 
-				for ( var line_y = 0; line_y < scanlineBlockSize; line_y ++ ) {
+				break;
 
-					for ( var channelID = 0; channelID < EXRHeader.channels.length; channelID ++ ) {
+			default:
 
-						var cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ];
+				console.error( 'THREE.EXRLoader: unsupported type: ', this.type );
+				break;
+
+		}
+
+		var channelOffsets = {
+			R: 0,
+			G: 1,
+			B: 2,
+			A: 3
+		};
 
-						if ( EXRHeader.channels[ channelID ].pixelType === 1 ) { // half
+		var compressionInfo = {
 
-							for ( var x = 0; x < width; x ++ ) {
+			array: uInt8Array,
+			viewer: bufferDataView,
+			offset: offset,
+			channels: EXRHeader.channels.length,
+			width: width,
+			lines: scanlineBlockSize,
+			size: 0
 
-								var idx = ( channelID * ( scanlineBlockSize * width ) ) + ( line_y * width ) + x;
+		};
 
-								switch ( this.type ) {
+		if ( EXRHeader.compression === 'NO_COMPRESSION' ||
+			EXRHeader.compression === 'ZIP_COMPRESSION' ||
+			EXRHeader.compression === 'ZIPS_COMPRESSION' ||
+			EXRHeader.compression === 'RLE_COMPRESSION' ||
+			EXRHeader.compression === 'PIZ_COMPRESSION' ) {
 
-									case THREE.FloatType:
+			var size;
+			var viewer;
+			var tmpOffset = { value: 0 };
 
-										var val = decodeFloat16( tmpBuffer[ idx ] );
-										break;
+			for ( var scanlineBlockIdx = 0; scanlineBlockIdx < height / scanlineBlockSize; scanlineBlockIdx ++ ) {
 
-									case THREE.HalfFloatType:
+				parseUint32( bufferDataView, offset ); // line_no
+				size = parseUint32( bufferDataView, offset ); // data_len
 
-										var val = tmpBuffer[ idx ];
-										break;
+				compressionInfo.offset = offset;
+				compressionInfo.size = size;
 
-								}
+				viewer = uncompress( compressionInfo );
 
-								var true_y = line_y + ( scanlineBlockIdx * scanlineBlockSize );
+				offset.value += size;
 
-								byteArray[ ( ( ( height - true_y ) * ( width * numChannels ) ) + ( x * numChannels ) ) + cOff ] = val;
+				for ( var line_y = 0; line_y < scanlineBlockSize; line_y ++ ) {
 
-							}
+					var true_y = line_y + ( scanlineBlockIdx * scanlineBlockSize );
 
-						} else {
+					if ( true_y >= height ) break;
 
-							throw 'EXRLoader._parser: unsupported pixelType ' + EXRHeader.channels[ channelID ].pixelType + '. Only pixelType is 1 (HALF) is supported.';
+					for ( var channelID = 0; channelID < EXRHeader.channels.length; channelID ++ ) {
+
+						var cOff = channelOffsets[ EXRHeader.channels[ channelID ].name ];
+
+						for ( var x = 0; x < width; x ++ ) {
+
+							var idx = ( line_y * ( EXRHeader.channels.length * width ) ) + ( channelID * width ) + x;
+							tmpOffset.value = idx * size_t;
+
+							var val = getValue( viewer, tmpOffset );
+
+							byteArray[ ( ( ( height - 1 - true_y ) * ( width * numChannels ) ) + ( x * numChannels ) ) + cOff ] = val;
 
 						}
 
@@ -1209,10 +1413,6 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 
 			}
 
-		} else {
-
-			throw 'EXRLoader._parser: ' + EXRHeader.compression + ' is unsupported';
-
 		}
 
 		return {
@@ -1220,7 +1420,7 @@ THREE.EXRLoader.prototype = Object.assign( Object.create( THREE.DataTextureLoade
 			width: width,
 			height: height,
 			data: byteArray,
-			format: EXRHeader.channels.length == 4 ? THREE.RGBAFormat : THREE.RGBFormat,
+			format: numChannels === 4 ? THREE.RGBAFormat : THREE.RGBFormat,
 			type: this.type
 		};
 

+ 15 - 17
examples/js/loaders/FBXLoader.js

@@ -1613,10 +1613,10 @@ THREE.FBXLoader = ( function () {
 
 			if ( buffers.normal.length > 0 ) {
 
-				var normalAttribute = new THREE.Float32BufferAttribute( buffers.normal, 3 );
-
 				var normalMatrix = new THREE.Matrix3().getNormalMatrix( preTransform );
-				normalMatrix.applyToBufferAttribute( normalAttribute );
+
+				var normalAttribute = new THREE.Float32BufferAttribute( buffers.normal, 3 );
+				normalAttribute.applyNormalMatrix( normalMatrix );
 
 				geo.setAttribute( 'normal', normalAttribute );
 
@@ -2058,10 +2058,12 @@ THREE.FBXLoader = ( function () {
 
 			if ( morphTargets.length === 0 ) return;
 
+			parentGeo.morphTargetsRelative = true;
+
 			parentGeo.morphAttributes.position = [];
 			// parentGeo.morphAttributes.normal = []; // not implemented
 
-			 var self = this;
+			var self = this;
 			morphTargets.forEach( function ( morphTarget ) {
 
 				morphTarget.rawTargets.forEach( function ( rawTarget ) {
@@ -2086,33 +2088,29 @@ THREE.FBXLoader = ( function () {
 		// Normal and position attributes only have data for the vertices that are affected by the morph
 		genMorphGeometry: function ( parentGeo, parentGeoNode, morphGeoNode, preTransform, name ) {
 
-			var morphGeo = new THREE.BufferGeometry();
-			if ( morphGeoNode.attrName ) morphGeo.name = morphGeoNode.attrName;
-
 			var vertexIndices = ( parentGeoNode.PolygonVertexIndex !== undefined ) ? parentGeoNode.PolygonVertexIndex.a : [];
 
-			// make a copy of the parent's vertex positions
-			var vertexPositions = ( parentGeoNode.Vertices !== undefined ) ? parentGeoNode.Vertices.a.slice() : [];
-
-			var morphPositions = ( morphGeoNode.Vertices !== undefined ) ? morphGeoNode.Vertices.a : [];
+			var morphPositionsSparse = ( morphGeoNode.Vertices !== undefined ) ? morphGeoNode.Vertices.a : [];
 			var indices = ( morphGeoNode.Indexes !== undefined ) ? morphGeoNode.Indexes.a : [];
 
+			var length = parentGeo.attributes.position.count * 3;
+			var morphPositions = new Float32Array( length );
+
 			for ( var i = 0; i < indices.length; i ++ ) {
 
 				var morphIndex = indices[ i ] * 3;
 
-				// FBX format uses blend shapes rather than morph targets. This can be converted
-				// by additively combining the blend shape positions with the original geometry's positions
-				vertexPositions[ morphIndex ] += morphPositions[ i * 3 ];
-				vertexPositions[ morphIndex + 1 ] += morphPositions[ i * 3 + 1 ];
-				vertexPositions[ morphIndex + 2 ] += morphPositions[ i * 3 + 2 ];
+				morphPositions[ morphIndex ] = morphPositionsSparse[ i * 3 ];
+				morphPositions[ morphIndex + 1 ] = morphPositionsSparse[ i * 3 + 1 ];
+				morphPositions[ morphIndex + 2 ] = morphPositionsSparse[ i * 3 + 2 ];
 
 			}
 
 			// TODO: add morph normal support
 			var morphGeoInfo = {
 				vertexIndices: vertexIndices,
-				vertexPositions: vertexPositions,
+				vertexPositions: morphPositions,
+
 			};
 
 			var morphBuffers = this.genBuffers( morphGeoInfo );

+ 210 - 132
examples/js/loaders/GLTFLoader.js

@@ -150,7 +150,7 @@ THREE.GLTFLoader = ( function () {
 
 			if ( json.asset === undefined || json.asset.version[ 0 ] < 2 ) {
 
-				if ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported. Use LegacyGLTFLoader instead.' ) );
+				if ( onError ) onError( new Error( 'THREE.GLTFLoader: Unsupported asset. glTF versions >=2.0 are supported.' ) );
 				return;
 
 			}
@@ -188,6 +188,10 @@ THREE.GLTFLoader = ( function () {
 							extensions[ extensionName ] = new GLTFTextureTransformExtension();
 							break;
 
+						case EXTENSIONS.KHR_MESH_QUANTIZATION:
+							extensions[ extensionName ] = new GLTFMeshQuantizationExtension();
+							break;
+
 						default:
 
 							if ( extensionsRequired.indexOf( extensionName ) >= 0 ) {
@@ -263,6 +267,7 @@ THREE.GLTFLoader = ( function () {
 		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
 		KHR_MATERIALS_UNLIT: 'KHR_materials_unlit',
 		KHR_TEXTURE_TRANSFORM: 'KHR_texture_transform',
+		KHR_MESH_QUANTIZATION: 'KHR_mesh_quantization',
 		MSFT_TEXTURE_DDS: 'MSFT_texture_dds'
 	};
 
@@ -428,7 +433,7 @@ THREE.GLTFLoader = ( function () {
 
 		} else if ( this.header.version < 2.0 ) {
 
-			throw new Error( 'THREE.GLTFLoader: Legacy binary file detected. Use LegacyGLTFLoader instead.' );
+			throw new Error( 'THREE.GLTFLoader: Legacy binary file detected.' );
 
 		}
 
@@ -485,6 +490,7 @@ THREE.GLTFLoader = ( function () {
 		this.name = EXTENSIONS.KHR_DRACO_MESH_COMPRESSION;
 		this.json = json;
 		this.dracoLoader = dracoLoader;
+		this.dracoLoader.preload();
 
 	}
 
@@ -981,6 +987,17 @@ THREE.GLTFLoader = ( function () {
 
 	}
 
+	/**
+	 * Mesh Quantization Extension
+	 *
+	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/2.0/Khronos/KHR_mesh_quantization
+	 */
+	function GLTFMeshQuantizationExtension() {
+
+		this.name = EXTENSIONS.KHR_MESH_QUANTIZATION;
+
+	}
+
 	/*********************************/
 	/********** INTERPOLATION ********/
 	/*********************************/
@@ -1186,24 +1203,26 @@ THREE.GLTFLoader = ( function () {
 
 	}
 
-	var defaultMaterial;
-
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#default-material
 	 */
-	function createDefaultMaterial() {
-
-		defaultMaterial = defaultMaterial || new THREE.MeshStandardMaterial( {
-			color: 0xFFFFFF,
-			emissive: 0x000000,
-			metalness: 1,
-			roughness: 1,
-			transparent: false,
-			depthTest: true,
-			side: THREE.FrontSide
-		} );
+	function createDefaultMaterial( cache ) {
+
+		if ( cache[ 'DefaultMaterial' ] === undefined ) {
+
+			cache[ 'DefaultMaterial' ] = new THREE.MeshStandardMaterial( {
+				color: 0xFFFFFF,
+				emissive: 0x000000,
+				metalness: 1,
+				roughness: 1,
+				transparent: false,
+				depthTest: true,
+				side: THREE.FrontSide
+			} );
+
+		}
 
-		return defaultMaterial;
+		return cache[ 'DefaultMaterial' ];
 
 	}
 
@@ -1309,95 +1328,9 @@ THREE.GLTFLoader = ( function () {
 			var morphPositions = accessors[ 0 ];
 			var morphNormals = accessors[ 1 ];
 
-			// Clone morph target accessors before modifying them.
-
-			for ( var i = 0, il = morphPositions.length; i < il; i ++ ) {
-
-				if ( geometry.attributes.position === morphPositions[ i ] ) continue;
-
-				morphPositions[ i ] = cloneBufferAttribute( morphPositions[ i ] );
-
-			}
-
-			for ( var i = 0, il = morphNormals.length; i < il; i ++ ) {
-
-				if ( geometry.attributes.normal === morphNormals[ i ] ) continue;
-
-				morphNormals[ i ] = cloneBufferAttribute( morphNormals[ i ] );
-
-			}
-
-			for ( var i = 0, il = targets.length; i < il; i ++ ) {
-
-				var target = targets[ i ];
-				var attributeName = 'morphTarget' + i;
-
-				if ( hasMorphPosition ) {
-
-					// Three.js morph position is absolute value. The formula is
-					//   basePosition
-					//     + weight0 * ( morphPosition0 - basePosition )
-					//     + weight1 * ( morphPosition1 - basePosition )
-					//     ...
-					// while the glTF one is relative
-					//   basePosition
-					//     + weight0 * glTFmorphPosition0
-					//     + weight1 * glTFmorphPosition1
-					//     ...
-					// then we need to convert from relative to absolute here.
-
-					if ( target.POSITION !== undefined ) {
-
-						var positionAttribute = morphPositions[ i ];
-						positionAttribute.name = attributeName;
-
-						var position = geometry.attributes.position;
-
-						for ( var j = 0, jl = positionAttribute.count; j < jl; j ++ ) {
-
-							positionAttribute.setXYZ(
-								j,
-								positionAttribute.getX( j ) + position.getX( j ),
-								positionAttribute.getY( j ) + position.getY( j ),
-								positionAttribute.getZ( j ) + position.getZ( j )
-							);
-
-						}
-
-					}
-
-				}
-
-				if ( hasMorphNormal ) {
-
-					// see target.POSITION's comment
-
-					if ( target.NORMAL !== undefined ) {
-
-						var normalAttribute = morphNormals[ i ];
-						normalAttribute.name = attributeName;
-
-						var normal = geometry.attributes.normal;
-
-						for ( var j = 0, jl = normalAttribute.count; j < jl; j ++ ) {
-
-							normalAttribute.setXYZ(
-								j,
-								normalAttribute.getX( j ) + normal.getX( j ),
-								normalAttribute.getY( j ) + normal.getY( j ),
-								normalAttribute.getZ( j ) + normal.getZ( j )
-							);
-
-						}
-
-					}
-
-				}
-
-			}
-
 			if ( hasMorphPosition ) geometry.morphAttributes.position = morphPositions;
 			if ( hasMorphNormal ) geometry.morphAttributes.normal = morphNormals;
+			geometry.morphTargetsRelative = true;
 
 			return geometry;
 
@@ -1485,31 +1418,6 @@ THREE.GLTFLoader = ( function () {
 
 	}
 
-	function cloneBufferAttribute( attribute ) {
-
-		if ( attribute.isInterleavedBufferAttribute ) {
-
-			var count = attribute.count;
-			var itemSize = attribute.itemSize;
-			var array = attribute.array.slice( 0, count * itemSize );
-
-			for ( var i = 0, j = 0; i < count; ++ i ) {
-
-				array[ j ++ ] = attribute.getX( i );
-				if ( itemSize >= 2 ) array[ j ++ ] = attribute.getY( i );
-				if ( itemSize >= 3 ) array[ j ++ ] = attribute.getZ( i );
-				if ( itemSize >= 4 ) array[ j ++ ] = attribute.getW( i );
-
-			}
-
-			return new THREE.BufferAttribute( array, itemSize, attribute.normalized );
-
-		}
-
-		return attribute.clone();
-
-	}
-
 	/* GLTF PARSER */
 
 	function GLTFParser( json, extensions, options ) {
@@ -2065,6 +1973,14 @@ THREE.GLTFLoader = ( function () {
 
 			}
 
+			// Materials sample aoMap from UV set 1 and other maps from UV set 0 - this can't be configured
+			// However, we will copy UV set 0 to UV set 1 on demand for aoMap
+			if ( mapDef.texCoord !== undefined && mapDef.texCoord != 0 && ! ( mapName === 'aoMap' && mapDef.texCoord == 1 ) ) {
+
+				console.warn( 'THREE.GLTFLoader: Custom UV set ' + mapDef.texCoord + ' for texture ' + mapName + ' not yet supported.' );
+
+			}
+
 			if ( parser.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] ) {
 
 				var transform = mapDef.extensions !== undefined ? mapDef.extensions[ EXTENSIONS.KHR_TEXTURE_TRANSFORM ] : undefined;
@@ -2184,7 +2100,6 @@ THREE.GLTFLoader = ( function () {
 
 		if ( material.aoMap && geometry.attributes.uv2 === undefined && geometry.attributes.uv !== undefined ) {
 
-			console.log( 'THREE.GLTFLoader: Duplicating UVs to support aoMap.' );
 			geometry.setAttribute( 'uv2', new THREE.BufferAttribute( geometry.attributes.uv.array, 2 ) );
 
 		}
@@ -2362,6 +2277,73 @@ THREE.GLTFLoader = ( function () {
 
 	};
 
+	/**
+	 * @param {THREE.BufferGeometry} geometry
+	 * @param {GLTF.Primitive} primitiveDef
+	 * @param {GLTFParser} parser
+	 */
+	function computeBounds( geometry, primitiveDef, parser ) {
+
+		var attributes = primitiveDef.attributes;
+
+		var box = new THREE.Box3();
+
+		if ( attributes.POSITION !== undefined ) {
+
+			var accessor = parser.json.accessors[ attributes.POSITION ];
+			var min = accessor.min;
+			var max = accessor.max;
+
+			box.set(
+				new THREE.Vector3( min[ 0 ], min[ 1 ], min[ 2 ] ),
+				new THREE.Vector3( max[ 0 ], max[ 1 ], max[ 2 ] ) );
+
+		} else {
+
+			return;
+
+		}
+
+		var targets = primitiveDef.targets;
+
+		if ( targets !== undefined ) {
+
+			var vector = new THREE.Vector3();
+
+			for ( var i = 0, il = targets.length; i < il; i ++ ) {
+
+				var target = targets[ i ];
+
+				if ( target.POSITION !== undefined ) {
+
+					var accessor = parser.json.accessors[ target.POSITION ];
+					var min = accessor.min;
+					var max = accessor.max;
+
+					// we need to get max of absolute components because target weight is [-1,1]
+					vector.setX( Math.max( Math.abs( min[ 0 ] ), Math.abs( max[ 0 ] ) ) );
+					vector.setY( Math.max( Math.abs( min[ 1 ] ), Math.abs( max[ 1 ] ) ) );
+					vector.setZ( Math.max( Math.abs( min[ 2 ] ), Math.abs( max[ 2 ] ) ) );
+
+					box.expandByVector( vector );
+
+				}
+
+			}
+
+		}
+
+		geometry.boundingBox = box;
+
+		var sphere = new THREE.Sphere();
+
+		box.getCenter( sphere.center );
+		sphere.radius = box.min.distanceTo( box.max ) / 2;
+
+		geometry.boundingSphere = sphere;
+
+	}
+
 	/**
 	 * @param {THREE.BufferGeometry} geometry
 	 * @param {GLTF.Primitive} primitiveDef
@@ -2410,6 +2392,8 @@ THREE.GLTFLoader = ( function () {
 
 		assignExtrasToUserData( geometry, primitiveDef );
 
+		computeBounds( geometry, primitiveDef, parser );
+
 		return Promise.all( pending ).then( function () {
 
 			return primitiveDef.targets !== undefined
@@ -2420,6 +2404,100 @@ THREE.GLTFLoader = ( function () {
 
 	}
 
+	/**
+	 * @param {THREE.BufferGeometry} geometry
+	 * @param {Number} drawMode
+	 * @return {THREE.BufferGeometry}
+	 */
+	function toTrianglesDrawMode( geometry, drawMode ) {
+
+		var index = geometry.getIndex();
+
+		// generate index if not present
+
+		if ( index === null ) {
+
+			var indices = [];
+
+			var position = geometry.getAttribute( 'position' );
+
+			if ( position !== undefined ) {
+
+				for ( var i = 0; i < position.count; i ++ ) {
+
+					indices.push( i );
+
+				}
+
+				geometry.setIndex( indices );
+				index = geometry.getIndex();
+
+			} else {
+
+				console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Undefined position attribute. Processing not possible.' );
+				return geometry;
+
+			}
+
+		}
+
+		//
+
+		var numberOfTriangles = index.count - 2;
+		var newIndices = [];
+
+		if ( drawMode === THREE.TriangleFanDrawMode ) {
+
+			// gl.TRIANGLE_FAN
+
+			for ( var i = 1; i <= numberOfTriangles; i ++ ) {
+
+				newIndices.push( index.getX( 0 ) );
+				newIndices.push( index.getX( i ) );
+				newIndices.push( index.getX( i + 1 ) );
+
+			}
+
+		} else {
+
+			// gl.TRIANGLE_STRIP
+
+			for ( var i = 0; i < numberOfTriangles; i ++ ) {
+
+				if ( i % 2 === 0 ) {
+
+					newIndices.push( index.getX( i ) );
+					newIndices.push( index.getX( i + 1 ) );
+					newIndices.push( index.getX( i + 2 ) );
+
+
+				} else {
+
+					newIndices.push( index.getX( i + 2 ) );
+					newIndices.push( index.getX( i + 1 ) );
+					newIndices.push( index.getX( i ) );
+
+				}
+
+			}
+
+		}
+
+		if ( ( newIndices.length / 3 ) !== numberOfTriangles ) {
+
+			console.error( 'THREE.GLTFLoader.toTrianglesDrawMode(): Unable to generate correct amount of triangles.' );
+
+		}
+
+		// build final geometry
+
+		var newGeometry = geometry.clone();
+		newGeometry.setIndex( newIndices );
+
+		return newGeometry;
+
+	}
+
 	/**
 	 * Specification: https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#geometry
 	 *
@@ -2508,7 +2586,7 @@ THREE.GLTFLoader = ( function () {
 		for ( var i = 0, il = primitives.length; i < il; i ++ ) {
 
 			var material = primitives[ i ].material === undefined
-				? createDefaultMaterial()
+				? createDefaultMaterial( this.cache )
 				: this.getDependency( 'material', primitives[ i ].material );
 
 			pending.push( material );
@@ -2552,11 +2630,11 @@ THREE.GLTFLoader = ( function () {
 
 						if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_STRIP ) {
 
-							mesh.drawMode = THREE.TriangleStripDrawMode;
+							mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleStripDrawMode );
 
 						} else if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLE_FAN ) {
 
-							mesh.drawMode = THREE.TriangleFanDrawMode;
+							mesh.geometry = toTrianglesDrawMode( mesh.geometry, THREE.TriangleFanDrawMode );
 
 						}
 

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

@@ -3013,6 +3013,8 @@ GeometryParser.prototype = {
 
 		}
 
+		geometry.morphTargetsRelative = false;
+
 	},
 
 };

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

@@ -366,6 +366,7 @@ THREE.MD2Loader.prototype = Object.assign( Object.create( THREE.Loader.prototype
 
 			geometry.morphAttributes.position = morphPositions;
 			geometry.morphAttributes.normal = morphNormals;
+			geometry.morphTargetsRelative = false;
 
 			geometry.animations = THREE.AnimationClip.CreateClipsFromMorphTargetSequences( frames, 10 );
 

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

@@ -922,6 +922,7 @@ THREE.MMDLoader = ( function () {
 
 			geometry.morphTargets = morphTargets;
 			geometry.morphAttributes.position = morphPositions;
+			geometry.morphTargetsRelative = false;
 
 			geometry.userData.MMD = {
 				bones: bones,

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

@@ -123,7 +123,7 @@ THREE.MTLLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype
 } );
 
 /**
- * Create a new THREE-MTLLoader.MaterialCreator
+ * Create a new THREE.MTLLoader.MaterialCreator
  * @param baseUrl - Url relative to which textures are loaded
  * @param options - Set of options on how to construct the materials
  *                  side: Which side to apply the material

+ 9 - 0
examples/js/loaders/OBJLoader.js

@@ -10,6 +10,8 @@ THREE.OBJLoader = ( function () {
 	var material_library_pattern = /^mtllib /;
 	// usemtl material_name
 	var material_use_pattern = /^usemtl /;
+	// usemap map_name
+	var map_use_pattern = /^usemap /;
 
 	function ParserState() {
 
@@ -570,6 +572,13 @@ THREE.OBJLoader = ( function () {
 
 					state.materialLibraries.push( line.substring( 7 ).trim() );
 
+				} else if ( map_use_pattern.test( line ) ) {
+
+					// the line is parsed but ignored since the loader assumes textures are defined MTL files
+					// (according to https://www.okino.com/conv/imp_wave.htm, 'usemap' is the old-style Wavefront texture reference method)
+
+					console.warn( 'THREE.OBJLoader: Rendering identifier "usemap" not supported. Textures must be defined in MTL files.' );
+
 				} else if ( lineFirstChar === 's' ) {
 
 					result = line.split( ' ' );

+ 97 - 7
examples/js/loaders/PCDLoader.js

@@ -3,9 +3,6 @@
  * @author Mugen87 / https://github.com/Mugen87
  *
  * Description: A THREE loader for PCD ascii and binary files.
- *
- * Limitations: Compressed binary files are not supported.
- *
  */
 
 THREE.PCDLoader = function ( manager ) {
@@ -54,6 +51,60 @@ THREE.PCDLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype
 
 	parse: function ( data, url ) {
 
+		// from https://gitlab.com/taketwo/three-pcd-loader/blob/master/decompress-lzf.js
+
+		function decompressLZF( inData, outLength ) {
+
+			var inLength = inData.length;
+			var outData = new Uint8Array( outLength );
+			var inPtr = 0;
+			var outPtr = 0;
+			var ctrl;
+			var len;
+			var ref;
+			do {
+
+				ctrl = inData[ inPtr ++ ];
+				if ( ctrl < ( 1 << 5 ) ) {
+
+					ctrl ++;
+					if ( outPtr + ctrl > outLength ) throw new Error( 'Output buffer is not large enough' );
+					if ( inPtr + ctrl > inLength ) throw new Error( 'Invalid compressed data' );
+					do {
+
+						outData[ outPtr ++ ] = inData[ inPtr ++ ];
+
+					} while ( -- ctrl );
+
+				} else {
+
+					len = ctrl >> 5;
+					ref = outPtr - ( ( ctrl & 0x1f ) << 8 ) - 1;
+					if ( inPtr >= inLength ) throw new Error( 'Invalid compressed data' );
+					if ( len === 7 ) {
+
+						len += inData[ inPtr ++ ];
+						if ( inPtr >= inLength ) throw new Error( 'Invalid compressed data' );
+
+					}
+					ref -= inData[ inPtr ++ ];
+					if ( outPtr + len + 2 > outLength ) throw new Error( 'Output buffer is not large enough' );
+					if ( ref < 0 ) throw new Error( 'Invalid compressed data' );
+					if ( ref >= outPtr ) throw new Error( 'Invalid compressed data' );
+					do {
+
+						outData[ outPtr ++ ] = outData[ ref ++ ];
+
+					} while ( -- len + 2 );
+
+				}
+
+			} while ( inPtr < inLength );
+
+			return outData;
+
+		}
+
 		function parseHeader( data ) {
 
 			var PCDheader = {};
@@ -219,15 +270,54 @@ THREE.PCDLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype
 
 		}
 
-		// binary
+		// binary-compressed
+
+		// normally data in PCD files are organized as array of structures: XYZRGBXYZRGB
+		// binary compressed PCD files organize their data as structure of arrays: XXYYZZRGBRGB
+		// that requires a totally different parsing approach compared to non-compressed data
 
 		if ( PCDheader.data === 'binary_compressed' ) {
 
-			console.error( 'THREE.PCDLoader: binary_compressed files are not supported' );
-			return;
+			var sizes = new Uint32Array( data.slice( PCDheader.headerLen, PCDheader.headerLen + 8 ) );
+			var compressedSize = sizes[ 0 ];
+			var decompressedSize = sizes[ 1 ];
+			var decompressed = decompressLZF( new Uint8Array( data, PCDheader.headerLen + 8, compressedSize ), decompressedSize );
+			var dataview = new DataView( decompressed.buffer );
+
+			var offset = PCDheader.offset;
+
+			for ( var i = 0; i < PCDheader.points; i ++ ) {
+
+				if ( offset.x !== undefined ) {
+
+					position.push( dataview.getFloat32( ( PCDheader.points * offset.x ) + PCDheader.size[ 0 ] * i, this.littleEndian ) );
+					position.push( dataview.getFloat32( ( PCDheader.points * offset.y ) + PCDheader.size[ 1 ] * i, this.littleEndian ) );
+					position.push( dataview.getFloat32( ( PCDheader.points * offset.z ) + PCDheader.size[ 2 ] * i, this.littleEndian ) );
+
+				}
+
+				if ( offset.rgb !== undefined ) {
+
+					color.push( dataview.getUint8( ( PCDheader.points * ( offset.rgb + 2 ) + PCDheader.size[ 3 ] * i ) / 255.0 ) );
+					color.push( dataview.getUint8( ( PCDheader.points * ( offset.rgb + 1 ) + PCDheader.size[ 3 ] * i ) / 255.0 ) );
+					color.push( dataview.getUint8( ( PCDheader.points * ( offset.rgb + 0 ) + PCDheader.size[ 3 ] * i ) / 255.0 ) );
+
+				}
+
+				if ( offset.normal_x !== undefined ) {
+
+					normal.push( dataview.getFloat32( ( PCDheader.points * offset.normal_x ) + PCDheader.size[ 4 ] * i, this.littleEndian ) );
+					normal.push( dataview.getFloat32( ( PCDheader.points * offset.normal_y ) + PCDheader.size[ 5 ] * i, this.littleEndian ) );
+					normal.push( dataview.getFloat32( ( PCDheader.points * offset.normal_z ) + PCDheader.size[ 6 ] * i, this.littleEndian ) );
+
+				}
+
+			}
 
 		}
 
+		// binary
+
 		if ( PCDheader.data === 'binary' ) {
 
 			var dataview = new DataView( data, PCDheader.headerLen );
@@ -287,7 +377,7 @@ THREE.PCDLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype
 
 		}
 
-		// build mesh
+		// build point cloud
 
 		var mesh = new THREE.Points( geometry, material );
 		var name = url.split( '' ).reverse().join( '' );

+ 279 - 59
examples/js/loaders/VRMLLoader.js

@@ -146,6 +146,7 @@ THREE.VRMLLoader = ( function () {
 				//
 
 				var StringLiteral = createToken( { name: "StringLiteral", pattern: /"(:?[^\\"\n\r]+|\\(:?[bfnrtv"\\/]|u[0-9a-fA-F]{4}))*"/ } );
+				var HexLiteral = createToken( { name: 'HexLiteral', pattern: /0[xX][0-9a-fA-F]+/ } );
 				var NumberLiteral = createToken( { name: 'NumberLiteral', pattern: /[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?/ } );
 				var TrueLiteral = createToken( { name: 'TrueLiteral', pattern: /TRUE/ } );
 				var FalseLiteral = createToken( { name: 'FalseLiteral', pattern: /FALSE/ } );
@@ -184,6 +185,7 @@ THREE.VRMLLoader = ( function () {
 					Identifier,
 					RouteIdentifier,
 					StringLiteral,
+					HexLiteral,
 					NumberLiteral,
 					LSquare,
 					RSquare,
@@ -425,6 +427,20 @@ THREE.VRMLLoader = ( function () {
 
 					}
 
+					if ( ctx.HexLiteral ) {
+
+						field.type = 'hex';
+
+						for ( var i = 0, l = ctx.HexLiteral.length; i < l; i ++ ) {
+
+							var hexLiteral = ctx.HexLiteral[ i ];
+
+							field.values.push( hexLiteral.image );
+
+						}
+
+					}
+
 					if ( ctx.TrueLiteral ) {
 
 						field.type = 'boolean';
@@ -578,7 +594,7 @@ THREE.VRMLLoader = ( function () {
 						break;
 
 					case 'Appearance':
-						build = buildApperanceNode( node );
+						build = buildAppearanceNode( node );
 						break;
 
 					case 'Material':
@@ -589,6 +605,10 @@ THREE.VRMLLoader = ( function () {
 						build = buildImageTextureNode( node );
 						break;
 
+					case 'PixelTexture':
+						build = buildPixelTextureNode( node );
+						break;
+
 					case 'TextureTransform':
 						build = buildTextureTransformNode( node );
 						break;
@@ -658,7 +678,6 @@ THREE.VRMLLoader = ( function () {
 
 					case 'FontStyle':
 					case 'MovieTexture':
-					case 'PixelTexture':
 
 					case 'ColorInterpolator':
 					case 'CoordinateInterpolator':
@@ -810,12 +829,12 @@ THREE.VRMLLoader = ( function () {
 
 				}
 
+				var radius = 10000;
+
 				// sky
 
 				if ( skyColor ) {
 
-					var radius = 10000;
-
 					var skyGeometry = new THREE.SphereBufferGeometry( radius, 32, 16 );
 					var skyMaterial = new THREE.MeshBasicMaterial( { fog: false, side: THREE.BackSide, depthWrite: false, depthTest: false } );
 
@@ -990,7 +1009,7 @@ THREE.VRMLLoader = ( function () {
 
 			}
 
-			function buildApperanceNode( node ) {
+			function buildAppearanceNode( node ) {
 
 				var material = new THREE.MeshPhongMaterial();
 				var transformData;
@@ -1030,13 +1049,13 @@ THREE.VRMLLoader = ( function () {
 							var textureNode = fieldValues[ 0 ];
 							if ( textureNode !== null ) {
 
-								if ( textureNode.name === 'ImageTexture' ) {
+								if ( textureNode.name === 'ImageTexture' || textureNode.name === 'PixelTexture' ) {
 
 									material.map = getNode( textureNode );
 
 								} else {
 
-									// MovieTexture and PixelTexture not supported yet
+									// MovieTexture not supported yet
 
 								}
 
@@ -1061,12 +1080,45 @@ THREE.VRMLLoader = ( function () {
 
 				// only apply texture transform data if a texture was defined
 
-				if ( material.map && transformData ) {
+				if ( material.map ) {
+
+					// respect VRML lighting model
+
+					if ( material.map.__type ) {
+
+						switch ( material.map.__type ) {
+
+							case TEXTURE_TYPE.INTENSITY_ALPHA:
+								material.opacity = 1; // ignore transparency
+								break;
+
+							case TEXTURE_TYPE.RGB:
+								material.color.set( 0xffffff ); // ignore material color
+								break;
 
-					material.map.center.copy( transformData.center );
-					material.map.rotation = transformData.rotation;
-					material.map.repeat.copy( transformData.scale );
-					material.map.offset.copy( transformData.translation );
+							case TEXTURE_TYPE.RGBA:
+								material.color.set( 0xffffff ); // ignore material color
+								material.opacity = 1; // ignore transparency
+								break;
+
+							default:
+
+						}
+
+						delete material.map.__type;
+
+					}
+
+					// apply texture transform
+
+					if ( transformData ) {
+
+						material.map.center.copy( transformData.center );
+						material.map.rotation = transformData.rotation;
+						material.map.repeat.copy( transformData.scale );
+						material.map.offset.copy( transformData.translation );
+
+					}
 
 				}
 
@@ -1124,6 +1176,163 @@ THREE.VRMLLoader = ( function () {
 
 			}
 
+			function parseHexColor( hex, textureType, color ) {
+
+				switch ( textureType ) {
+
+					case TEXTURE_TYPE.INTENSITY:
+						// Intensity texture: A one-component image specifies one-byte hexadecimal or integer values representing the intensity of the image
+						var value = parseInt( hex );
+						color.r = value;
+						color.g = value;
+						color.b = value;
+						break;
+
+					case TEXTURE_TYPE.INTENSITY_ALPHA:
+						// Intensity+Alpha texture: A two-component image specifies the intensity in the first (high) byte and the alpha opacity in the second (low) byte.
+						var value = parseInt( "0x" + hex.substring( 2, 4 ) );
+						color.r = value;
+						color.g = value;
+						color.b = value;
+						color.a = parseInt( "0x" + hex.substring( 4, 6 ) );
+						break;
+
+					case TEXTURE_TYPE.RGB:
+						// RGB texture: Pixels in a three-component image specify the red component in the first (high) byte, followed by the green and blue components
+						color.r = parseInt( "0x" + hex.substring( 2, 4 ) );
+						color.g = parseInt( "0x" + hex.substring( 4, 6 ) );
+						color.b = parseInt( "0x" + hex.substring( 6, 8 ) );
+						break;
+
+					case TEXTURE_TYPE.RGBA:
+						// RGBA texture: Four-component images specify the alpha opacity byte after red/green/blue
+						color.r = parseInt( "0x" + hex.substring( 2, 4 ) );
+						color.g = parseInt( "0x" + hex.substring( 4, 6 ) );
+						color.b = parseInt( "0x" + hex.substring( 6, 8 ) );
+						color.a = parseInt( "0x" + hex.substring( 8, 10 ) );
+						break;
+
+					default:
+
+				}
+
+			}
+
+			function getTextureType( num_components ) {
+
+				var type;
+
+				switch ( num_components ) {
+
+					case 1:
+						type = TEXTURE_TYPE.INTENSITY;
+						break;
+
+					case 2:
+						type = TEXTURE_TYPE.INTENSITY_ALPHA;
+						break;
+
+					case 3:
+						type = TEXTURE_TYPE.RGB;
+						break;
+
+					case 4:
+						type = TEXTURE_TYPE.RGBA;
+						break;
+
+					default:
+
+				}
+
+				return type;
+
+			}
+
+			function buildPixelTextureNode( node ) {
+
+				var texture;
+				var wrapS = THREE.RepeatWrapping;
+				var wrapT = THREE.RepeatWrapping;
+
+				var fields = node.fields;
+
+				for ( var i = 0, l = fields.length; i < l; i ++ ) {
+
+					var field = fields[ i ];
+					var fieldName = field.name;
+					var fieldValues = field.values;
+
+					switch ( fieldName ) {
+
+						case 'image':
+							var width = fieldValues[ 0 ];
+							var height = fieldValues[ 1 ];
+							var num_components = fieldValues[ 2 ];
+
+							var useAlpha = ( num_components === 2 || num_components === 4 );
+							var textureType = getTextureType( num_components );
+
+							var size = ( ( useAlpha === true ) ? 4 : 3 ) * ( width * height );
+							var data = new Uint8Array( size );
+
+							var color = { r: 0, g: 0, b: 0, a: 0 };
+
+							for ( var j = 3, k = 0, jl = fieldValues.length; j < jl; j ++, k ++ ) {
+
+								parseHexColor( fieldValues[ j ], textureType, color );
+
+								if ( useAlpha === true ) {
+
+									var stride = k * 4;
+
+									data[ stride + 0 ] = color.r;
+									data[ stride + 1 ] = color.g;
+									data[ stride + 2 ] = color.b;
+									data[ stride + 3 ] = color.a;
+
+								} else {
+
+									var stride = k * 3;
+
+									data[ stride + 0 ] = color.r;
+									data[ stride + 1 ] = color.g;
+									data[ stride + 2 ] = color.b;
+
+								}
+
+							}
+
+							texture = new THREE.DataTexture( data, width, height, ( useAlpha === true ) ? THREE.RGBAFormat : THREE.RGBFormat );
+							texture.__type = textureType; // needed for material modifications
+							break;
+
+						case 'repeatS':
+							if ( fieldValues[ 0 ] === false ) wrapS = THREE.ClampToEdgeWrapping;
+							break;
+
+						case 'repeatT':
+							if ( fieldValues[ 0 ] === false ) wrapT = THREE.ClampToEdgeWrapping;
+							break;
+
+						default:
+							console.warn( 'THREE.VRMLLoader: Unknown field:', fieldName );
+							break;
+
+					}
+
+				}
+
+				if ( texture ) {
+
+					texture.wrapS = wrapS;
+					texture.wrapT = wrapT;
+
+				}
+
+				return texture;
+
+			}
+
 			function buildImageTextureNode( node ) {
 
 				var texture;
@@ -2223,83 +2432,69 @@ THREE.VRMLLoader = ( function () {
 			 */
 			function paintFaces( geometry, radius, angles, colors, topDown ) {
 
-				var direction = ( topDown === true ) ? 1 : - 1;
+				// compute threshold values
 
-				var coord = [], A = {}, B = {}, applyColor = false;
+				var thresholds = [];
+				var startAngle = ( topDown === true ) ? 0 : Math.PI;
 
-				for ( var k = 0; k < angles.length; k ++ ) {
+				for ( var i = 0, l = colors.length; i < l; i ++ ) {
 
-					// push the vector at which the color changes
+					var angle = ( i === 0 ) ? 0 : angles[ i - 1 ];
+					angle = ( topDown === true ) ? angle : ( startAngle - angle );
 
-					var vec = {
-						x: direction * ( Math.cos( angles[ k ] ) * radius ),
-						y: direction * ( Math.sin( angles[ k ] ) * radius )
-					};
+					var point = new THREE.Vector3();
+					point.setFromSphericalCoords( radius, angle, 0 );
 
-					coord.push( vec );
+					thresholds.push( point );
 
 				}
 
-				var index = geometry.index;
+				// generate vertex colors
+
+				var indices = geometry.index;
 				var positionAttribute = geometry.attributes.position;
 				var colorAttribute = new THREE.BufferAttribute( new Float32Array( geometry.attributes.position.count * 3 ), 3 );
 
 				var position = new THREE.Vector3();
 				var color = new THREE.Color();
 
-				for ( var i = 0; i < index.count; i ++ ) {
-
-					var vertexIndex = index.getX( i );
-
-					position.fromBufferAttribute( positionAttribute, vertexIndex );
-
-					for ( var j = 0; j < colors.length; j ++ ) {
-
-						// linear interpolation between aColor and bColor, calculate proportion
-						// A is previous point (angle)
-
-						if ( j === 0 ) {
-
-							A.x = 0;
-							A.y = ( topDown === true ) ? radius : - 1 * radius;
+				for ( var i = 0; i < indices.count; i ++ ) {
 
-						} else {
-
-							A.x = coord[ j - 1 ].x;
-							A.y = coord[ j - 1 ].y;
+					var index = indices.getX( i );
+					position.fromBufferAttribute( positionAttribute, index );
 
-						}
+					var thresholdIndexA, thresholdIndexB;
+					var t = 1;
 
-						// B is current point (angle)
+					for ( var j = 1; j < thresholds.length; j ++ ) {
 
-						B = coord[ j ];
+						thresholdIndexA = j - 1;
+						thresholdIndexB = j;
 
-						if ( B !== undefined ) {
+						var thresholdA = thresholds[ thresholdIndexA ];
+						var thresholdB = thresholds[ thresholdIndexB ];
 
-							// p has to be between the points A and B which we interpolate
+						if ( topDown === true ) {
 
-							applyColor = ( topDown === true ) ? ( position.y <= A.y && position.y > B.y ) : ( position.y >= A.y && position.y < B.y );
+							// interpolation for sky color
 
-							if ( applyColor === true ) {
+							if ( position.y <= thresholdA.y && position.y > thresholdB.y ) {
 
-								var aColor = colors[ j ];
-								var bColor = colors[ j + 1 ];
+								t = Math.abs( thresholdA.y - position.y ) / Math.abs( thresholdA.y - thresholdB.y );
 
-								// below is simple linear interpolation
+								break;
 
-								var t = Math.abs( position.y - A.y ) / ( A.y - B.y );
+							}
 
-								// to make it faster, you can only calculate this if the y coord changes, the color is the same for points with the same y
+						} else {
 
-								color.copy( aColor ).lerp( bColor, t );
+							// interpolation for ground color
 
-								colorAttribute.setXYZ( vertexIndex, color.r, color.g, color.b );
+							if ( position.y >= thresholdA.y && position.y < thresholdB.y ) {
 
-							} else {
+								t = Math.abs( thresholdA.y - position.y ) / Math.abs( thresholdA.y - thresholdB.y );
 
-								var colorIndex = ( topDown === true ) ? colors.length - 1 : 0;
-								var c = colors[ colorIndex ];
-								colorAttribute.setXYZ( vertexIndex, c.r, c.g, c.b );
+								break;
 
 							}
 
@@ -2307,6 +2502,13 @@ THREE.VRMLLoader = ( function () {
 
 					}
 
+					var colorA = colors[ thresholdIndexA ];
+					var colorB = colors[ thresholdIndexB ];
+
+					color.copy( colorA ).lerp( colorB, t );
+
+					colorAttribute.setXYZ( index, color.r, color.g, color.b );
+
 				}
 
 				geometry.setAttribute( 'color', colorAttribute );
@@ -2382,6 +2584,7 @@ THREE.VRMLLoader = ( function () {
 		var Identifier = tokenVocabulary[ 'Identifier' ];
 		var RouteIdentifier = tokenVocabulary[ 'RouteIdentifier' ];
 		var StringLiteral = tokenVocabulary[ 'StringLiteral' ];
+		var HexLiteral = tokenVocabulary[ 'HexLiteral' ];
 		var NumberLiteral = tokenVocabulary[ 'NumberLiteral' ];
 		var TrueLiteral = tokenVocabulary[ 'TrueLiteral' ];
 		var FalseLiteral = tokenVocabulary[ 'FalseLiteral' ];
@@ -2485,6 +2688,11 @@ THREE.VRMLLoader = ( function () {
 
 						$.CONSUME( StringLiteral );
 
+					} },
+					{ ALT: function () {
+
+						$.CONSUME( HexLiteral );
+
 					} },
 					{ ALT: function () {
 
@@ -2533,6 +2741,11 @@ THREE.VRMLLoader = ( function () {
 
 						$.CONSUME( StringLiteral );
 
+					} },
+					{ ALT: function () {
+
+						$.CONSUME( HexLiteral );
+
 					} },
 					{ ALT: function () {
 
@@ -2576,6 +2789,13 @@ THREE.VRMLLoader = ( function () {
 
 	}
 
+	var TEXTURE_TYPE = {
+		INTENSITY: 1,
+		INTENSITY_ALPHA: 2,
+		RGB: 3,
+		RGBA: 4
+	};
+
 	return VRMLLoader;
 
 } )();

+ 0 - 2219
examples/js/loaders/deprecated/LegacyGLTFLoader.js

@@ -1,2219 +0,0 @@
-/**
- * @author Rich Tibbett / https://github.com/richtr
- * @author mrdoob / http://mrdoob.com/
- * @author Tony Parisi / http://www.tonyparisi.com/
- * @author Takahiro / https://github.com/takahirox
- */
-
-THREE.LegacyGLTFLoader = ( function () {
-
-	function LegacyGLTFLoader( manager ) {
-
-		THREE.Loader.call( this, manager );
-
-	}
-
-	LegacyGLTFLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
-
-		constructor: LegacyGLTFLoader,
-
-		load: function ( url, onLoad, onProgress, onError ) {
-
-			var scope = this;
-
-			var resourcePath;
-
-			if ( this.resourcePath !== '' ) {
-
-				resourcePath = this.resourcePath;
-
-			} else if ( this.path !== '' ) {
-
-				resourcePath = this.path;
-
-			} else {
-
-				resourcePath = THREE.LoaderUtils.extractUrlBase( url );
-
-			}
-
-			var loader = new THREE.FileLoader( scope.manager );
-
-			loader.setPath( this.path );
-			loader.setResponseType( 'arraybuffer' );
-
-			loader.load( url, function ( data ) {
-
-				scope.parse( data, resourcePath, onLoad );
-
-			}, onProgress, onError );
-
-		},
-
-		parse: function ( data, path, callback ) {
-
-			var content;
-			var extensions = {};
-
-			var magic = THREE.LoaderUtils.decodeText( new Uint8Array( data, 0, 4 ) );
-
-			if ( magic === BINARY_EXTENSION_HEADER_DEFAULTS.magic ) {
-
-				extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );
-				content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;
-
-			} else {
-
-				content = THREE.LoaderUtils.decodeText( new Uint8Array( data ) );
-
-			}
-
-			var json = JSON.parse( content );
-
-			if ( json.extensionsUsed && json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_COMMON ) >= 0 ) {
-
-				extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] = new GLTFMaterialsCommonExtension( json );
-
-			}
-
-			var parser = new GLTFParser( json, extensions, {
-
-				crossOrigin: this.crossOrigin,
-				manager: this.manager,
-				path: path || this.resourcePath || ''
-
-			} );
-
-			parser.parse( function ( scene, scenes, cameras, animations ) {
-
-				var glTF = {
-					"scene": scene,
-					"scenes": scenes,
-					"cameras": cameras,
-					"animations": animations
-				};
-
-				callback( glTF );
-
-			} );
-
-		}
-
-	} );
-
-	/* GLTFREGISTRY */
-
-	function GLTFRegistry() {
-
-		var objects = {};
-
-		return	{
-
-			get: function ( key ) {
-
-				return objects[ key ];
-
-			},
-
-			add: function ( key, object ) {
-
-				objects[ key ] = object;
-
-			},
-
-			remove: function ( key ) {
-
-				delete objects[ key ];
-
-			},
-
-			removeAll: function () {
-
-				objects = {};
-
-			},
-
-			update: function ( scene, camera ) {
-
-				for ( var name in objects ) {
-
-					var object = objects[ name ];
-
-					if ( object.update ) {
-
-						object.update( scene, camera );
-
-					}
-
-				}
-
-			}
-
-		};
-
-	}
-
-	/* GLTFSHADERS */
-
-	LegacyGLTFLoader.Shaders = {
-
-		update: function () {
-
-			console.warn( 'THREE.LegacyGLTFLoader.Shaders has been deprecated, and now updates automatically.' );
-
-		}
-
-	};
-
-	/* GLTFSHADER */
-
-	function GLTFShader( targetNode, allNodes ) {
-
-		var boundUniforms = {};
-
-		// bind each uniform to its source node
-
-		var uniforms = targetNode.material.uniforms;
-
-		for ( var uniformId in uniforms ) {
-
-			var uniform = uniforms[ uniformId ];
-
-			if ( uniform.semantic ) {
-
-				var sourceNodeRef = uniform.node;
-
-				var sourceNode = targetNode;
-
-				if ( sourceNodeRef ) {
-
-					sourceNode = allNodes[ sourceNodeRef ];
-
-				}
-
-				boundUniforms[ uniformId ] = {
-					semantic: uniform.semantic,
-					sourceNode: sourceNode,
-					targetNode: targetNode,
-					uniform: uniform
-				};
-
-			}
-
-		}
-
-		this.boundUniforms = boundUniforms;
-		this._m4 = new THREE.Matrix4();
-
-	}
-
-	// Update - update all the uniform values
-	GLTFShader.prototype.update = function ( scene, camera ) {
-
-		var boundUniforms = this.boundUniforms;
-
-		for ( var name in boundUniforms ) {
-
-			var boundUniform = boundUniforms[ name ];
-
-			switch ( boundUniform.semantic ) {
-
-				case "MODELVIEW":
-
-					var m4 = boundUniform.uniform.value;
-					m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld );
-					break;
-
-				case "MODELVIEWINVERSETRANSPOSE":
-
-					var m3 = boundUniform.uniform.value;
-					this._m4.multiplyMatrices( camera.matrixWorldInverse, boundUniform.sourceNode.matrixWorld );
-					m3.getNormalMatrix( this._m4 );
-					break;
-
-				case "PROJECTION":
-
-					var m4 = boundUniform.uniform.value;
-					m4.copy( camera.projectionMatrix );
-					break;
-
-				case "JOINTMATRIX":
-
-					var m4v = boundUniform.uniform.value;
-
-					for ( var mi = 0; mi < m4v.length; mi ++ ) {
-
-						// So it goes like this:
-						// SkinnedMesh world matrix is already baked into MODELVIEW;
-						// transform joints to local space,
-						// then transform using joint's inverse
-						m4v[ mi ]
-							.getInverse( boundUniform.sourceNode.matrixWorld )
-							.multiply( boundUniform.targetNode.skeleton.bones[ mi ].matrixWorld )
-							.multiply( boundUniform.targetNode.skeleton.boneInverses[ mi ] )
-							.multiply( boundUniform.targetNode.bindMatrix );
-
-					}
-
-					break;
-
-				default :
-
-					console.warn( "Unhandled shader semantic: " + boundUniform.semantic );
-					break;
-
-			}
-
-		}
-
-	};
-
-
-	/* ANIMATION */
-
-	LegacyGLTFLoader.Animations = {
-
-		update: function () {
-
-			console.warn( 'THREE.LegacyGLTFLoader.Animation has been deprecated. Use THREE.AnimationMixer instead.' );
-
-		}
-
-	};
-
-	/*********************************/
-	/********** EXTENSIONS ***********/
-	/*********************************/
-
-	var EXTENSIONS = {
-		KHR_BINARY_GLTF: 'KHR_binary_glTF',
-		KHR_MATERIALS_COMMON: 'KHR_materials_common'
-	};
-
-	/* MATERIALS COMMON EXTENSION */
-
-	function GLTFMaterialsCommonExtension( json ) {
-
-		this.name = EXTENSIONS.KHR_MATERIALS_COMMON;
-
-		this.lights = {};
-
-		var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) || {};
-		var lights = extension.lights || {};
-
-		for ( var lightId in lights ) {
-
-			var light = lights[ lightId ];
-			var lightNode;
-
-			var lightParams = light[ light.type ];
-			var color = new THREE.Color().fromArray( lightParams.color );
-
-			switch ( light.type ) {
-
-				case "directional":
-					lightNode = new THREE.DirectionalLight( color );
-					lightNode.position.set( 0, 0, 1 );
-					break;
-
-				case "point":
-					lightNode = new THREE.PointLight( color );
-					break;
-
-				case "spot":
-					lightNode = new THREE.SpotLight( color );
-					lightNode.position.set( 0, 0, 1 );
-					break;
-
-				case "ambient":
-					lightNode = new THREE.AmbientLight( color );
-					break;
-
-			}
-
-			if ( lightNode ) {
-
-				this.lights[ lightId ] = lightNode;
-
-			}
-
-		}
-
-	}
-
-	/* BINARY EXTENSION */
-
-	var BINARY_EXTENSION_BUFFER_NAME = 'binary_glTF';
-
-	var BINARY_EXTENSION_HEADER_DEFAULTS = { magic: 'glTF', version: 1, contentFormat: 0 };
-
-	var BINARY_EXTENSION_HEADER_LENGTH = 20;
-
-	function GLTFBinaryExtension( data ) {
-
-		this.name = EXTENSIONS.KHR_BINARY_GLTF;
-
-		var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );
-
-		var header = {
-			magic: THREE.LoaderUtils.decodeText( new Uint8Array( data.slice( 0, 4 ) ) ),
-			version: headerView.getUint32( 4, true ),
-			length: headerView.getUint32( 8, true ),
-			contentLength: headerView.getUint32( 12, true ),
-			contentFormat: headerView.getUint32( 16, true )
-		};
-
-		for ( var key in BINARY_EXTENSION_HEADER_DEFAULTS ) {
-
-			var value = BINARY_EXTENSION_HEADER_DEFAULTS[ key ];
-
-			if ( header[ key ] !== value ) {
-
-				throw new Error( 'Unsupported glTF-Binary header: Expected "%s" to be "%s".', key, value );
-
-			}
-
-		}
-
-		var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH, header.contentLength );
-
-		this.header = header;
-		this.content = THREE.LoaderUtils.decodeText( contentArray );
-		this.body = data.slice( BINARY_EXTENSION_HEADER_LENGTH + header.contentLength, header.length );
-
-	}
-
-	GLTFBinaryExtension.prototype.loadShader = function ( shader, bufferViews ) {
-
-		var bufferView = bufferViews[ shader.extensions[ EXTENSIONS.KHR_BINARY_GLTF ].bufferView ];
-		var array = new Uint8Array( bufferView );
-
-		return THREE.LoaderUtils.decodeText( array );
-
-	};
-
-	/*********************************/
-	/********** INTERNALS ************/
-	/*********************************/
-
-	/* CONSTANTS */
-
-	var WEBGL_CONSTANTS = {
-		FLOAT: 5126,
-		//FLOAT_MAT2: 35674,
-		FLOAT_MAT3: 35675,
-		FLOAT_MAT4: 35676,
-		FLOAT_VEC2: 35664,
-		FLOAT_VEC3: 35665,
-		FLOAT_VEC4: 35666,
-		LINEAR: 9729,
-		REPEAT: 10497,
-		SAMPLER_2D: 35678,
-		TRIANGLES: 4,
-		LINES: 1,
-		UNSIGNED_BYTE: 5121,
-		UNSIGNED_SHORT: 5123,
-
-		VERTEX_SHADER: 35633,
-		FRAGMENT_SHADER: 35632
-	};
-
-	var WEBGL_TYPE = {
-		5126: Number,
-		//35674: THREE.Matrix2,
-		35675: THREE.Matrix3,
-		35676: THREE.Matrix4,
-		35664: THREE.Vector2,
-		35665: THREE.Vector3,
-		35666: THREE.Vector4,
-		35678: THREE.Texture
-	};
-
-	var WEBGL_COMPONENT_TYPES = {
-		5120: Int8Array,
-		5121: Uint8Array,
-		5122: Int16Array,
-		5123: Uint16Array,
-		5125: Uint32Array,
-		5126: Float32Array
-	};
-
-	var WEBGL_FILTERS = {
-		9728: THREE.NearestFilter,
-		9729: THREE.LinearFilter,
-		9984: THREE.NearestMipmapNearestFilter,
-		9985: THREE.LinearMipmapNearestFilter,
-		9986: THREE.NearestMipmapLinearFilter,
-		9987: THREE.LinearMipmapLinearFilter
-	};
-
-	var WEBGL_WRAPPINGS = {
-		33071: THREE.ClampToEdgeWrapping,
-		33648: THREE.MirroredRepeatWrapping,
-		10497: THREE.RepeatWrapping
-	};
-
-	var WEBGL_TEXTURE_FORMATS = {
-		6406: THREE.AlphaFormat,
-		6407: THREE.RGBFormat,
-		6408: THREE.RGBAFormat,
-		6409: THREE.LuminanceFormat,
-		6410: THREE.LuminanceAlphaFormat
-	};
-
-	var WEBGL_TEXTURE_DATATYPES = {
-		5121: THREE.UnsignedByteType,
-		32819: THREE.UnsignedShort4444Type,
-		32820: THREE.UnsignedShort5551Type,
-		33635: THREE.UnsignedShort565Type
-	};
-
-	var WEBGL_SIDES = {
-		1028: THREE.BackSide, // Culling front
-		1029: THREE.FrontSide // Culling back
-		//1032: THREE.NoSide   // Culling front and back, what to do?
-	};
-
-	var WEBGL_DEPTH_FUNCS = {
-		512: THREE.NeverDepth,
-		513: THREE.LessDepth,
-		514: THREE.EqualDepth,
-		515: THREE.LessEqualDepth,
-		516: THREE.GreaterEqualDepth,
-		517: THREE.NotEqualDepth,
-		518: THREE.GreaterEqualDepth,
-		519: THREE.AlwaysDepth
-	};
-
-	var WEBGL_BLEND_EQUATIONS = {
-		32774: THREE.AddEquation,
-		32778: THREE.SubtractEquation,
-		32779: THREE.ReverseSubtractEquation
-	};
-
-	var WEBGL_BLEND_FUNCS = {
-		0: THREE.ZeroFactor,
-		1: THREE.OneFactor,
-		768: THREE.SrcColorFactor,
-		769: THREE.OneMinusSrcColorFactor,
-		770: THREE.SrcAlphaFactor,
-		771: THREE.OneMinusSrcAlphaFactor,
-		772: THREE.DstAlphaFactor,
-		773: THREE.OneMinusDstAlphaFactor,
-		774: THREE.DstColorFactor,
-		775: THREE.OneMinusDstColorFactor,
-		776: THREE.SrcAlphaSaturateFactor
-		// The followings are not supported by Three.js yet
-		//32769: CONSTANT_COLOR,
-		//32770: ONE_MINUS_CONSTANT_COLOR,
-		//32771: CONSTANT_ALPHA,
-		//32772: ONE_MINUS_CONSTANT_COLOR
-	};
-
-	var WEBGL_TYPE_SIZES = {
-		'SCALAR': 1,
-		'VEC2': 2,
-		'VEC3': 3,
-		'VEC4': 4,
-		'MAT2': 4,
-		'MAT3': 9,
-		'MAT4': 16
-	};
-
-	var PATH_PROPERTIES = {
-		scale: 'scale',
-		translation: 'position',
-		rotation: 'quaternion'
-	};
-
-	var INTERPOLATION = {
-		LINEAR: THREE.InterpolateLinear,
-		STEP: THREE.InterpolateDiscrete
-	};
-
-	var STATES_ENABLES = {
-		2884: 'CULL_FACE',
-		2929: 'DEPTH_TEST',
-		3042: 'BLEND',
-		3089: 'SCISSOR_TEST',
-		32823: 'POLYGON_OFFSET_FILL',
-		32926: 'SAMPLE_ALPHA_TO_COVERAGE'
-	};
-
-	/* UTILITY FUNCTIONS */
-
-	function _each( object, callback, thisObj ) {
-
-		if ( ! object ) {
-
-			return Promise.resolve();
-
-		}
-
-		var results;
-		var fns = [];
-
-		if ( Object.prototype.toString.call( object ) === '[object Array]' ) {
-
-			results = [];
-
-			var length = object.length;
-
-			for ( var idx = 0; idx < length; idx ++ ) {
-
-				var value = callback.call( thisObj || this, object[ idx ], idx );
-
-				if ( value ) {
-
-					fns.push( value );
-
-					if ( value instanceof Promise ) {
-
-						value.then( function ( key, value ) {
-
-							results[ key ] = value;
-
-						}.bind( this, idx ) );
-
-					} else {
-
-						results[ idx ] = value;
-
-					}
-
-				}
-
-			}
-
-		} else {
-
-			results = {};
-
-			for ( var key in object ) {
-
-				if ( object.hasOwnProperty( key ) ) {
-
-					var value = callback.call( thisObj || this, object[ key ], key );
-
-					if ( value ) {
-
-						fns.push( value );
-
-						if ( value instanceof Promise ) {
-
-							value.then( function ( key, value ) {
-
-								results[ key ] = value;
-
-							}.bind( this, key ) );
-
-						} else {
-
-							results[ key ] = value;
-
-						}
-
-					}
-
-				}
-
-			}
-
-		}
-
-		return Promise.all( fns ).then( function () {
-
-			return results;
-
-		} );
-
-	}
-
-	function resolveURL( url, path ) {
-
-		// Invalid URL
-		if ( typeof url !== 'string' || url === '' )
-			return '';
-
-		// Absolute URL http://,https://,//
-		if ( /^(https?:)?\/\//i.test( url ) ) {
-
-			return url;
-
-		}
-
-		// Data URI
-		if ( /^data:.*,.*$/i.test( url ) ) {
-
-			return url;
-
-		}
-
-		// Blob URL
-		if ( /^blob:.*$/i.test( url ) ) {
-
-			return url;
-
-		}
-
-		// Relative URL
-		return ( path || '' ) + url;
-
-	}
-
-	// Three.js seems too dependent on attribute names so globally
-	// replace those in the shader code
-	function replaceTHREEShaderAttributes( shaderText, technique ) {
-
-		// Expected technique attributes
-		var attributes = {};
-
-		for ( var attributeId in technique.attributes ) {
-
-			var pname = technique.attributes[ attributeId ];
-
-			var param = technique.parameters[ pname ];
-			var atype = param.type;
-			var semantic = param.semantic;
-
-			attributes[ attributeId ] = {
-				type: atype,
-				semantic: semantic
-			};
-
-		}
-
-		// Figure out which attributes to change in technique
-
-		var shaderParams = technique.parameters;
-		var shaderAttributes = technique.attributes;
-		var params = {};
-
-		for ( var attributeId in attributes ) {
-
-			var pname = shaderAttributes[ attributeId ];
-			var shaderParam = shaderParams[ pname ];
-			var semantic = shaderParam.semantic;
-			if ( semantic ) {
-
-				params[ attributeId ] = shaderParam;
-
-			}
-
-		}
-
-		for ( var pname in params ) {
-
-			var param = params[ pname ];
-			var semantic = param.semantic;
-
-			var regEx = new RegExp( "\\b" + pname + "\\b", "g" );
-
-			switch ( semantic ) {
-
-				case "POSITION":
-
-					shaderText = shaderText.replace( regEx, 'position' );
-					break;
-
-				case "NORMAL":
-
-					shaderText = shaderText.replace( regEx, 'normal' );
-					break;
-
-				case 'TEXCOORD_0':
-				case 'TEXCOORD0':
-				case 'TEXCOORD':
-
-					shaderText = shaderText.replace( regEx, 'uv' );
-					break;
-
-				case 'TEXCOORD_1':
-
-					shaderText = shaderText.replace( regEx, 'uv2' );
-					break;
-
-				case 'COLOR_0':
-				case 'COLOR0':
-				case 'COLOR':
-
-					shaderText = shaderText.replace( regEx, 'color' );
-					break;
-
-				case "WEIGHT":
-
-					shaderText = shaderText.replace( regEx, 'skinWeight' );
-					break;
-
-				case "JOINT":
-
-					shaderText = shaderText.replace( regEx, 'skinIndex' );
-					break;
-
-			}
-
-		}
-
-		return shaderText;
-
-	}
-
-	function createDefaultMaterial() {
-
-		return new THREE.MeshPhongMaterial( {
-			color: 0x00000,
-			emissive: 0x888888,
-			specular: 0x000000,
-			shininess: 0,
-			transparent: false,
-			depthTest: true,
-			side: THREE.FrontSide
-		} );
-
-	}
-
-	// Deferred constructor for RawShaderMaterial types
-	function DeferredShaderMaterial( params ) {
-
-		this.isDeferredShaderMaterial = true;
-
-		this.params = params;
-
-	}
-
-	DeferredShaderMaterial.prototype.create = function () {
-
-		var uniforms = THREE.UniformsUtils.clone( this.params.uniforms );
-
-		for ( var uniformId in this.params.uniforms ) {
-
-			var originalUniform = this.params.uniforms[ uniformId ];
-
-			if ( originalUniform.value instanceof THREE.Texture ) {
-
-				uniforms[ uniformId ].value = originalUniform.value;
-				uniforms[ uniformId ].value.needsUpdate = true;
-
-			}
-
-			uniforms[ uniformId ].semantic = originalUniform.semantic;
-			uniforms[ uniformId ].node = originalUniform.node;
-
-		}
-
-		this.params.uniforms = uniforms;
-
-		return new THREE.RawShaderMaterial( this.params );
-
-	};
-
-	/* GLTF PARSER */
-
-	function GLTFParser( json, extensions, options ) {
-
-		this.json = json || {};
-		this.extensions = extensions || {};
-		this.options = options || {};
-
-		// loader object cache
-		this.cache = new GLTFRegistry();
-
-	}
-
-	GLTFParser.prototype._withDependencies = function ( dependencies ) {
-
-		var _dependencies = {};
-
-		for ( var i = 0; i < dependencies.length; i ++ ) {
-
-			var dependency = dependencies[ i ];
-			var fnName = "load" + dependency.charAt( 0 ).toUpperCase() + dependency.slice( 1 );
-
-			var cached = this.cache.get( dependency );
-
-			if ( cached !== undefined ) {
-
-				_dependencies[ dependency ] = cached;
-
-			} else if ( this[ fnName ] ) {
-
-				var fn = this[ fnName ]();
-				this.cache.add( dependency, fn );
-
-				_dependencies[ dependency ] = fn;
-
-			}
-
-		}
-
-		return _each( _dependencies, function ( dependency ) {
-
-			return dependency;
-
-		} );
-
-	};
-
-	GLTFParser.prototype.parse = function ( callback ) {
-
-		var json = this.json;
-
-		// Clear the loader cache
-		this.cache.removeAll();
-
-		// Fire the callback on complete
-		this._withDependencies( [
-
-			"scenes",
-			"cameras",
-			"animations"
-
-		] ).then( function ( dependencies ) {
-
-			var scenes = [];
-
-			for ( var name in dependencies.scenes ) {
-
-				scenes.push( dependencies.scenes[ name ] );
-
-			}
-
-			var scene = json.scene !== undefined ? dependencies.scenes[ json.scene ] : scenes[ 0 ];
-
-			var cameras = [];
-
-			for ( var name in dependencies.cameras ) {
-
-				var camera = dependencies.cameras[ name ];
-				cameras.push( camera );
-
-			}
-
-			var animations = [];
-
-			for ( var name in dependencies.animations ) {
-
-				animations.push( dependencies.animations[ name ] );
-
-			}
-
-			callback( scene, scenes, cameras, animations );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadShaders = function () {
-
-		var json = this.json;
-		var extensions = this.extensions;
-		var options = this.options;
-
-		return this._withDependencies( [
-
-			"bufferViews"
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.shaders, function ( shader ) {
-
-				if ( shader.extensions && shader.extensions[ EXTENSIONS.KHR_BINARY_GLTF ] ) {
-
-					return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].loadShader( shader, dependencies.bufferViews );
-
-				}
-
-				return new Promise( function ( resolve ) {
-
-					var loader = new THREE.FileLoader( options.manager );
-					loader.setResponseType( 'text' );
-					loader.load( resolveURL( shader.uri, options.path ), function ( shaderText ) {
-
-						resolve( shaderText );
-
-					} );
-
-				} );
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadBuffers = function () {
-
-		var json = this.json;
-		var extensions = this.extensions;
-		var options = this.options;
-
-		return _each( json.buffers, function ( buffer, name ) {
-
-			if ( name === BINARY_EXTENSION_BUFFER_NAME ) {
-
-				return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body;
-
-			}
-
-			if ( buffer.type === 'arraybuffer' || buffer.type === undefined ) {
-
-				return new Promise( function ( resolve ) {
-
-					var loader = new THREE.FileLoader( options.manager );
-					loader.setResponseType( 'arraybuffer' );
-					loader.load( resolveURL( buffer.uri, options.path ), function ( buffer ) {
-
-						resolve( buffer );
-
-					} );
-
-				} );
-
-			} else {
-
-				console.warn( 'THREE.LegacyGLTFLoader: ' + buffer.type + ' buffer type is not supported' );
-
-			}
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadBufferViews = function () {
-
-		var json = this.json;
-
-		return this._withDependencies( [
-
-			"buffers"
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.bufferViews, function ( bufferView ) {
-
-				var arraybuffer = dependencies.buffers[ bufferView.buffer ];
-
-				var byteLength = bufferView.byteLength !== undefined ? bufferView.byteLength : 0;
-
-				return arraybuffer.slice( bufferView.byteOffset, bufferView.byteOffset + byteLength );
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadAccessors = function () {
-
-		var json = this.json;
-
-		return this._withDependencies( [
-
-			"bufferViews"
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.accessors, function ( accessor ) {
-
-				var arraybuffer = dependencies.bufferViews[ accessor.bufferView ];
-				var itemSize = WEBGL_TYPE_SIZES[ accessor.type ];
-				var TypedArray = WEBGL_COMPONENT_TYPES[ accessor.componentType ];
-
-				// For VEC3: itemSize is 3, elementBytes is 4, itemBytes is 12.
-				var elementBytes = TypedArray.BYTES_PER_ELEMENT;
-				var itemBytes = elementBytes * itemSize;
-
-				// The buffer is not interleaved if the stride is the item size in bytes.
-				if ( accessor.byteStride && accessor.byteStride !== itemBytes ) {
-
-					// Use the full buffer if it's interleaved.
-					var array = new TypedArray( arraybuffer );
-
-					// Integer parameters to IB/IBA are in array elements, not bytes.
-					var ib = new THREE.InterleavedBuffer( array, accessor.byteStride / elementBytes );
-
-					return new THREE.InterleavedBufferAttribute( ib, itemSize, accessor.byteOffset / elementBytes );
-
-				} else {
-
-					array = new TypedArray( arraybuffer, accessor.byteOffset, accessor.count * itemSize );
-
-					return new THREE.BufferAttribute( array, itemSize );
-
-				}
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadTextures = function () {
-
-		var json = this.json;
-		var options = this.options;
-
-		return this._withDependencies( [
-
-			"bufferViews"
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.textures, function ( texture ) {
-
-				if ( texture.source ) {
-
-					return new Promise( function ( resolve ) {
-
-						var source = json.images[ texture.source ];
-						var sourceUri = source.uri;
-						var isObjectURL = false;
-
-						if ( source.extensions && source.extensions[ EXTENSIONS.KHR_BINARY_GLTF ] ) {
-
-							var metadata = source.extensions[ EXTENSIONS.KHR_BINARY_GLTF ];
-							var bufferView = dependencies.bufferViews[ metadata.bufferView ];
-							var blob = new Blob( [ bufferView ], { type: metadata.mimeType } );
-							sourceUri = URL.createObjectURL( blob );
-							isObjectURL = true;
-
-						}
-
-						var textureLoader = options.manager.getHandler( sourceUri );
-
-						if ( textureLoader === null ) {
-
-							textureLoader = new THREE.TextureLoader( options.manager );
-
-						}
-
-						textureLoader.setCrossOrigin( options.crossOrigin );
-
-						textureLoader.load( resolveURL( sourceUri, options.path ), function ( _texture ) {
-
-							if ( isObjectURL ) URL.revokeObjectURL( sourceUri );
-
-							_texture.flipY = false;
-
-							if ( texture.name !== undefined ) _texture.name = texture.name;
-
-							_texture.format = texture.format !== undefined ? WEBGL_TEXTURE_FORMATS[ texture.format ] : THREE.RGBAFormat;
-
-							if ( texture.internalFormat !== undefined && _texture.format !== WEBGL_TEXTURE_FORMATS[ texture.internalFormat ] ) {
-
-								console.warn( 'THREE.LegacyGLTFLoader: Three.js doesn\'t support texture internalFormat which is different from texture format. ' +
-															'internalFormat will be forced to be the same value as format.' );
-
-							}
-
-							_texture.type = texture.type !== undefined ? WEBGL_TEXTURE_DATATYPES[ texture.type ] : THREE.UnsignedByteType;
-
-							if ( texture.sampler ) {
-
-								var sampler = json.samplers[ texture.sampler ];
-
-								_texture.magFilter = WEBGL_FILTERS[ sampler.magFilter ] || THREE.LinearFilter;
-								_texture.minFilter = WEBGL_FILTERS[ sampler.minFilter ] || THREE.NearestMipmapLinearFilter;
-								_texture.wrapS = WEBGL_WRAPPINGS[ sampler.wrapS ] || THREE.RepeatWrapping;
-								_texture.wrapT = WEBGL_WRAPPINGS[ sampler.wrapT ] || THREE.RepeatWrapping;
-
-							}
-
-							resolve( _texture );
-
-						}, undefined, function () {
-
-							if ( isObjectURL ) URL.revokeObjectURL( sourceUri );
-
-							resolve();
-
-						} );
-
-					} );
-
-				}
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadMaterials = function () {
-
-		var json = this.json;
-
-		return this._withDependencies( [
-
-			"shaders",
-			"textures"
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.materials, function ( material ) {
-
-				var materialType;
-				var materialValues = {};
-				var materialParams = {};
-
-				var khr_material;
-
-				if ( material.extensions && material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) {
-
-					khr_material = material.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ];
-
-				}
-
-				if ( khr_material ) {
-
-					// don't copy over unused values to avoid material warning spam
-					var keys = [ 'ambient', 'emission', 'transparent', 'transparency', 'doubleSided' ];
-
-					switch ( khr_material.technique ) {
-
-						case 'BLINN' :
-						case 'PHONG' :
-							materialType = THREE.MeshPhongMaterial;
-							keys.push( 'diffuse', 'specular', 'shininess' );
-							break;
-
-						case 'LAMBERT' :
-							materialType = THREE.MeshLambertMaterial;
-							keys.push( 'diffuse' );
-							break;
-
-						case 'CONSTANT' :
-						default :
-							materialType = THREE.MeshBasicMaterial;
-							break;
-
-					}
-
-					keys.forEach( function ( v ) {
-
-						if ( khr_material.values[ v ] !== undefined ) materialValues[ v ] = khr_material.values[ v ];
-
-					} );
-
-					if ( khr_material.doubleSided || materialValues.doubleSided ) {
-
-						materialParams.side = THREE.DoubleSide;
-
-					}
-
-					if ( khr_material.transparent || materialValues.transparent ) {
-
-						materialParams.transparent = true;
-						materialParams.opacity = ( materialValues.transparency !== undefined ) ? materialValues.transparency : 1;
-
-					}
-
-				} else if ( material.technique === undefined ) {
-
-					materialType = THREE.MeshPhongMaterial;
-
-					Object.assign( materialValues, material.values );
-
-				} else {
-
-					materialType = DeferredShaderMaterial;
-
-					var technique = json.techniques[ material.technique ];
-
-					materialParams.uniforms = {};
-
-					var program = json.programs[ technique.program ];
-
-					if ( program ) {
-
-						materialParams.fragmentShader = dependencies.shaders[ program.fragmentShader ];
-
-						if ( ! materialParams.fragmentShader ) {
-
-							console.warn( "ERROR: Missing fragment shader definition:", program.fragmentShader );
-							materialType = THREE.MeshPhongMaterial;
-
-						}
-
-						var vertexShader = dependencies.shaders[ program.vertexShader ];
-
-						if ( ! vertexShader ) {
-
-							console.warn( "ERROR: Missing vertex shader definition:", program.vertexShader );
-							materialType = THREE.MeshPhongMaterial;
-
-						}
-
-						// IMPORTANT: FIX VERTEX SHADER ATTRIBUTE DEFINITIONS
-						materialParams.vertexShader = replaceTHREEShaderAttributes( vertexShader, technique );
-
-						var uniforms = technique.uniforms;
-
-						for ( var uniformId in uniforms ) {
-
-							var pname = uniforms[ uniformId ];
-							var shaderParam = technique.parameters[ pname ];
-
-							var ptype = shaderParam.type;
-
-							if ( WEBGL_TYPE[ ptype ] ) {
-
-								var pcount = shaderParam.count;
-								var value;
-
-								if ( material.values !== undefined ) value = material.values[ pname ];
-
-								var uvalue = new WEBGL_TYPE[ ptype ]();
-								var usemantic = shaderParam.semantic;
-								var unode = shaderParam.node;
-
-								switch ( ptype ) {
-
-									case WEBGL_CONSTANTS.FLOAT:
-
-										uvalue = shaderParam.value;
-
-										if ( pname == "transparency" ) {
-
-											materialParams.transparent = true;
-
-										}
-
-										if ( value !== undefined ) {
-
-											uvalue = value;
-
-										}
-
-										break;
-
-									case WEBGL_CONSTANTS.FLOAT_VEC2:
-									case WEBGL_CONSTANTS.FLOAT_VEC3:
-									case WEBGL_CONSTANTS.FLOAT_VEC4:
-									case WEBGL_CONSTANTS.FLOAT_MAT3:
-
-										if ( shaderParam && shaderParam.value ) {
-
-											uvalue.fromArray( shaderParam.value );
-
-										}
-
-										if ( value ) {
-
-											uvalue.fromArray( value );
-
-										}
-
-										break;
-
-									case WEBGL_CONSTANTS.FLOAT_MAT2:
-
-										// what to do?
-										console.warn( "FLOAT_MAT2 is not a supported uniform type" );
-										break;
-
-									case WEBGL_CONSTANTS.FLOAT_MAT4:
-
-										if ( pcount ) {
-
-											uvalue = new Array( pcount );
-
-											for ( var mi = 0; mi < pcount; mi ++ ) {
-
-												uvalue[ mi ] = new WEBGL_TYPE[ ptype ]();
-
-											}
-
-											if ( shaderParam && shaderParam.value ) {
-
-												var m4v = shaderParam.value;
-												uvalue.fromArray( m4v );
-
-											}
-
-											if ( value ) {
-
-												uvalue.fromArray( value );
-
-											}
-
-										} else {
-
-											if ( shaderParam && shaderParam.value ) {
-
-												var m4 = shaderParam.value;
-												uvalue.fromArray( m4 );
-
-											}
-
-											if ( value ) {
-
-												uvalue.fromArray( value );
-
-											}
-
-										}
-
-										break;
-
-									case WEBGL_CONSTANTS.SAMPLER_2D:
-
-										if ( value !== undefined ) {
-
-											uvalue = dependencies.textures[ value ];
-
-										} else if ( shaderParam.value !== undefined ) {
-
-											uvalue = dependencies.textures[ shaderParam.value ];
-
-										} else {
-
-											uvalue = null;
-
-										}
-
-										break;
-
-								}
-
-								materialParams.uniforms[ uniformId ] = {
-									value: uvalue,
-									semantic: usemantic,
-									node: unode
-								};
-
-							} else {
-
-								throw new Error( "Unknown shader uniform param type: " + ptype );
-
-							}
-
-						}
-
-						var states = technique.states || {};
-						var enables = states.enable || [];
-						var functions = states.functions || {};
-
-						var enableCullFace = false;
-						var enableDepthTest = false;
-						var enableBlend = false;
-
-						for ( var i = 0, il = enables.length; i < il; i ++ ) {
-
-							var enable = enables[ i ];
-
-							switch ( STATES_ENABLES[ enable ] ) {
-
-								case 'CULL_FACE':
-
-									enableCullFace = true;
-
-									break;
-
-								case 'DEPTH_TEST':
-
-									enableDepthTest = true;
-
-									break;
-
-								case 'BLEND':
-
-									enableBlend = true;
-
-									break;
-
-								// TODO: implement
-								case 'SCISSOR_TEST':
-								case 'POLYGON_OFFSET_FILL':
-								case 'SAMPLE_ALPHA_TO_COVERAGE':
-
-									break;
-
-								default:
-
-									throw new Error( "Unknown technique.states.enable: " + enable );
-
-							}
-
-						}
-
-						if ( enableCullFace ) {
-
-							materialParams.side = functions.cullFace !== undefined ? WEBGL_SIDES[ functions.cullFace ] : THREE.FrontSide;
-
-						} else {
-
-							materialParams.side = THREE.DoubleSide;
-
-						}
-
-						materialParams.depthTest = enableDepthTest;
-						materialParams.depthFunc = functions.depthFunc !== undefined ? WEBGL_DEPTH_FUNCS[ functions.depthFunc ] : THREE.LessDepth;
-						materialParams.depthWrite = functions.depthMask !== undefined ? functions.depthMask[ 0 ] : true;
-
-						materialParams.blending = enableBlend ? THREE.CustomBlending : THREE.NoBlending;
-						materialParams.transparent = enableBlend;
-
-						var blendEquationSeparate = functions.blendEquationSeparate;
-
-						if ( blendEquationSeparate !== undefined ) {
-
-							materialParams.blendEquation = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 0 ] ];
-							materialParams.blendEquationAlpha = WEBGL_BLEND_EQUATIONS[ blendEquationSeparate[ 1 ] ];
-
-						} else {
-
-							materialParams.blendEquation = THREE.AddEquation;
-							materialParams.blendEquationAlpha = THREE.AddEquation;
-
-						}
-
-						var blendFuncSeparate = functions.blendFuncSeparate;
-
-						if ( blendFuncSeparate !== undefined ) {
-
-							materialParams.blendSrc = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 0 ] ];
-							materialParams.blendDst = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 1 ] ];
-							materialParams.blendSrcAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 2 ] ];
-							materialParams.blendDstAlpha = WEBGL_BLEND_FUNCS[ blendFuncSeparate[ 3 ] ];
-
-						} else {
-
-							materialParams.blendSrc = THREE.OneFactor;
-							materialParams.blendDst = THREE.ZeroFactor;
-							materialParams.blendSrcAlpha = THREE.OneFactor;
-							materialParams.blendDstAlpha = THREE.ZeroFactor;
-
-						}
-
-					}
-
-				}
-
-				if ( Array.isArray( materialValues.diffuse ) ) {
-
-					materialParams.color = new THREE.Color().fromArray( materialValues.diffuse );
-
-				} else if ( typeof ( materialValues.diffuse ) === 'string' ) {
-
-					materialParams.map = dependencies.textures[ materialValues.diffuse ];
-
-				}
-
-				delete materialParams.diffuse;
-
-				if ( typeof ( materialValues.reflective ) === 'string' ) {
-
-					materialParams.envMap = dependencies.textures[ materialValues.reflective ];
-
-				}
-
-				if ( typeof ( materialValues.bump ) === 'string' ) {
-
-					materialParams.bumpMap = dependencies.textures[ materialValues.bump ];
-
-				}
-
-				if ( Array.isArray( materialValues.emission ) ) {
-
-					if ( materialType === THREE.MeshBasicMaterial ) {
-
-						materialParams.color = new THREE.Color().fromArray( materialValues.emission );
-
-					} else {
-
-						materialParams.emissive = new THREE.Color().fromArray( materialValues.emission );
-
-					}
-
-				} else if ( typeof ( materialValues.emission ) === 'string' ) {
-
-					if ( materialType === THREE.MeshBasicMaterial ) {
-
-						materialParams.map = dependencies.textures[ materialValues.emission ];
-
-					} else {
-
-						materialParams.emissiveMap = dependencies.textures[ materialValues.emission ];
-
-					}
-
-				}
-
-				if ( Array.isArray( materialValues.specular ) ) {
-
-					materialParams.specular = new THREE.Color().fromArray( materialValues.specular );
-
-				} else if ( typeof ( materialValues.specular ) === 'string' ) {
-
-					materialParams.specularMap = dependencies.textures[ materialValues.specular ];
-
-				}
-
-				if ( materialValues.shininess !== undefined ) {
-
-					materialParams.shininess = materialValues.shininess;
-
-				}
-
-				var _material = new materialType( materialParams );
-				if ( material.name !== undefined ) _material.name = material.name;
-
-				return _material;
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadMeshes = function () {
-
-		var json = this.json;
-
-		return this._withDependencies( [
-
-			"accessors",
-			"materials"
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.meshes, function ( mesh ) {
-
-				var group = new THREE.Group();
-				if ( mesh.name !== undefined ) group.name = mesh.name;
-
-				if ( mesh.extras ) group.userData = mesh.extras;
-
-				var primitives = mesh.primitives || [];
-
-				for ( var name in primitives ) {
-
-					var primitive = primitives[ name ];
-
-					if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === undefined ) {
-
-						var geometry = new THREE.BufferGeometry();
-
-						var attributes = primitive.attributes;
-
-						for ( var attributeId in attributes ) {
-
-							var attributeEntry = attributes[ attributeId ];
-
-							if ( ! attributeEntry ) return;
-
-							var bufferAttribute = dependencies.accessors[ attributeEntry ];
-
-							switch ( attributeId ) {
-
-								case 'POSITION':
-									geometry.setAttribute( 'position', bufferAttribute );
-									break;
-
-								case 'NORMAL':
-									geometry.setAttribute( 'normal', bufferAttribute );
-									break;
-
-								case 'TEXCOORD_0':
-								case 'TEXCOORD0':
-								case 'TEXCOORD':
-									geometry.setAttribute( 'uv', bufferAttribute );
-									break;
-
-								case 'TEXCOORD_1':
-									geometry.setAttribute( 'uv2', bufferAttribute );
-									break;
-
-								case 'COLOR_0':
-								case 'COLOR0':
-								case 'COLOR':
-									geometry.setAttribute( 'color', bufferAttribute );
-									break;
-
-								case 'WEIGHT':
-									geometry.setAttribute( 'skinWeight', bufferAttribute );
-									break;
-
-								case 'JOINT':
-									geometry.setAttribute( 'skinIndex', bufferAttribute );
-									break;
-
-								default:
-
-									if ( ! primitive.material ) break;
-
-									var material = json.materials[ primitive.material ];
-
-									if ( ! material.technique ) break;
-
-									var parameters = json.techniques[ material.technique ].parameters || {};
-
-									for ( var attributeName in parameters ) {
-
-										if ( parameters[ attributeName ][ 'semantic' ] === attributeId ) {
-
-											geometry.setAttribute( attributeName, bufferAttribute );
-
-										}
-
-									}
-
-							}
-
-						}
-
-						if ( primitive.indices ) {
-
-							geometry.setIndex( dependencies.accessors[ primitive.indices ] );
-
-						}
-
-						var material = dependencies.materials !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial();
-
-						var meshNode = new THREE.Mesh( geometry, material );
-						meshNode.castShadow = true;
-						meshNode.name = ( name === "0" ? group.name : group.name + name );
-
-						if ( primitive.extras ) meshNode.userData = primitive.extras;
-
-						group.add( meshNode );
-
-					} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
-
-						var geometry = new THREE.BufferGeometry();
-
-						var attributes = primitive.attributes;
-
-						for ( var attributeId in attributes ) {
-
-							var attributeEntry = attributes[ attributeId ];
-
-							if ( ! attributeEntry ) return;
-
-							var bufferAttribute = dependencies.accessors[ attributeEntry ];
-
-							switch ( attributeId ) {
-
-								case 'POSITION':
-									geometry.setAttribute( 'position', bufferAttribute );
-									break;
-
-								case 'COLOR_0':
-								case 'COLOR0':
-								case 'COLOR':
-									geometry.setAttribute( 'color', bufferAttribute );
-									break;
-
-							}
-
-						}
-
-						var material = dependencies.materials[ primitive.material ];
-
-						var meshNode;
-
-						if ( primitive.indices ) {
-
-							geometry.setIndex( dependencies.accessors[ primitive.indices ] );
-
-							meshNode = new THREE.LineSegments( geometry, material );
-
-						} else {
-
-							meshNode = new THREE.Line( geometry, material );
-
-						}
-
-						meshNode.name = ( name === "0" ? group.name : group.name + name );
-
-						if ( primitive.extras ) meshNode.userData = primitive.extras;
-
-						group.add( meshNode );
-
-					} else {
-
-						console.warn( "Only triangular and line primitives are supported" );
-
-					}
-
-				}
-
-				return group;
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadCameras = function () {
-
-		var json = this.json;
-
-		return _each( json.cameras, function ( camera ) {
-
-			if ( camera.type == "perspective" && camera.perspective ) {
-
-				var yfov = camera.perspective.yfov;
-				var aspectRatio = camera.perspective.aspectRatio !== undefined ? camera.perspective.aspectRatio : 1;
-
-				// According to COLLADA spec...
-				// aspectRatio = xfov / yfov
-				var xfov = yfov * aspectRatio;
-
-				var _camera = new THREE.PerspectiveCamera( THREE.Math.radToDeg( xfov ), aspectRatio, camera.perspective.znear || 1, camera.perspective.zfar || 2e6 );
-				if ( camera.name !== undefined ) _camera.name = camera.name;
-
-				if ( camera.extras ) _camera.userData = camera.extras;
-
-				return _camera;
-
-			} else if ( camera.type == "orthographic" && camera.orthographic ) {
-
-				var _camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, camera.orthographic.znear, camera.orthographic.zfar );
-				if ( camera.name !== undefined ) _camera.name = camera.name;
-
-				if ( camera.extras ) _camera.userData = camera.extras;
-
-				return _camera;
-
-			}
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadSkins = function () {
-
-		var json = this.json;
-
-		return this._withDependencies( [
-
-			"accessors"
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.skins, function ( skin ) {
-
-				var bindShapeMatrix = new THREE.Matrix4();
-
-				if ( skin.bindShapeMatrix !== undefined ) bindShapeMatrix.fromArray( skin.bindShapeMatrix );
-
-				var _skin = {
-					bindShapeMatrix: bindShapeMatrix,
-					jointNames: skin.jointNames,
-					inverseBindMatrices: dependencies.accessors[ skin.inverseBindMatrices ]
-				};
-
-				return _skin;
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadAnimations = function () {
-
-		var json = this.json;
-
-		return this._withDependencies( [
-
-			"accessors",
-			"nodes"
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.animations, function ( animation, animationId ) {
-
-				var tracks = [];
-
-				for ( var channelId in animation.channels ) {
-
-					var channel = animation.channels[ channelId ];
-					var sampler = animation.samplers[ channel.sampler ];
-
-					if ( sampler ) {
-
-						var target = channel.target;
-						var name = target.id;
-						var input = animation.parameters !== undefined ? animation.parameters[ sampler.input ] : sampler.input;
-						var output = animation.parameters !== undefined ? animation.parameters[ sampler.output ] : sampler.output;
-
-						var inputAccessor = dependencies.accessors[ input ];
-						var outputAccessor = dependencies.accessors[ output ];
-
-						var node = dependencies.nodes[ name ];
-
-						if ( node ) {
-
-							node.updateMatrix();
-							node.matrixAutoUpdate = true;
-
-							var TypedKeyframeTrack = PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.rotation
-								? THREE.QuaternionKeyframeTrack
-								: THREE.VectorKeyframeTrack;
-
-							var targetName = node.name ? node.name : node.uuid;
-							var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear;
-
-							// KeyframeTrack.optimize() will modify given 'times' and 'values'
-							// buffers before creating a truncated copy to keep. Because buffers may
-							// be reused by other tracks, make copies here.
-							tracks.push( new TypedKeyframeTrack(
-								targetName + '.' + PATH_PROPERTIES[ target.path ],
-								THREE.AnimationUtils.arraySlice( inputAccessor.array, 0 ),
-								THREE.AnimationUtils.arraySlice( outputAccessor.array, 0 ),
-								interpolation
-							) );
-
-						}
-
-					}
-
-				}
-
-				var name = animation.name !== undefined ? animation.name : "animation_" + animationId;
-
-				return new THREE.AnimationClip( name, undefined, tracks );
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadNodes = function () {
-
-		var json = this.json;
-		var extensions = this.extensions;
-		var scope = this;
-
-		return _each( json.nodes, function ( node ) {
-
-			var matrix = new THREE.Matrix4();
-
-			var _node;
-
-			if ( node.jointName ) {
-
-				_node = new THREE.Bone();
-				_node.name = node.name !== undefined ? node.name : node.jointName;
-				_node.jointName = node.jointName;
-
-			} else {
-
-				_node = new THREE.Object3D();
-				if ( node.name !== undefined ) _node.name = node.name;
-
-			}
-
-			if ( node.extras ) _node.userData = node.extras;
-
-			if ( node.matrix !== undefined ) {
-
-				matrix.fromArray( node.matrix );
-				_node.applyMatrix( matrix );
-
-			} else {
-
-				if ( node.translation !== undefined ) {
-
-					_node.position.fromArray( node.translation );
-
-				}
-
-				if ( node.rotation !== undefined ) {
-
-					_node.quaternion.fromArray( node.rotation );
-
-				}
-
-				if ( node.scale !== undefined ) {
-
-					_node.scale.fromArray( node.scale );
-
-				}
-
-			}
-
-			return _node;
-
-		} ).then( function ( __nodes ) {
-
-			return scope._withDependencies( [
-
-				"meshes",
-				"skins",
-				"cameras"
-
-			] ).then( function ( dependencies ) {
-
-				return _each( __nodes, function ( _node, nodeId ) {
-
-					var node = json.nodes[ nodeId ];
-
-					if ( node.meshes !== undefined ) {
-
-						for ( var meshId in node.meshes ) {
-
-							var mesh = node.meshes[ meshId ];
-							var group = dependencies.meshes[ mesh ];
-
-							if ( group === undefined ) {
-
-								console.warn( 'LegacyGLTFLoader: Couldn\'t find node "' + mesh + '".' );
-								continue;
-
-							}
-
-							for ( var childrenId in group.children ) {
-
-								var child = group.children[ childrenId ];
-
-								// clone Mesh to add to _node
-
-								var originalMaterial = child.material;
-								var originalGeometry = child.geometry;
-								var originalUserData = child.userData;
-								var originalName = child.name;
-
-								var material;
-
-								if ( originalMaterial.isDeferredShaderMaterial ) {
-
-									originalMaterial = material = originalMaterial.create();
-
-								} else {
-
-									material = originalMaterial;
-
-								}
-
-								switch ( child.type ) {
-
-									case 'LineSegments':
-										child = new THREE.LineSegments( originalGeometry, material );
-										break;
-
-									case 'LineLoop':
-										child = new THREE.LineLoop( originalGeometry, material );
-										break;
-
-									case 'Line':
-										child = new THREE.Line( originalGeometry, material );
-										break;
-
-									default:
-										child = new THREE.Mesh( originalGeometry, material );
-
-								}
-
-								child.castShadow = true;
-								child.userData = originalUserData;
-								child.name = originalName;
-
-								var skinEntry;
-
-								if ( node.skin ) {
-
-									skinEntry = dependencies.skins[ node.skin ];
-
-								}
-
-								// Replace Mesh with SkinnedMesh in library
-								if ( skinEntry ) {
-
-									var getJointNode = function ( jointId ) {
-
-										var keys = Object.keys( __nodes );
-
-										for ( var i = 0, il = keys.length; i < il; i ++ ) {
-
-											var n = __nodes[ keys[ i ] ];
-
-											if ( n.jointName === jointId ) return n;
-
-										}
-
-										return null;
-
-									};
-
-									var geometry = originalGeometry;
-									var material = originalMaterial;
-									material.skinning = true;
-
-									child = new THREE.SkinnedMesh( geometry, material );
-									child.castShadow = true;
-									child.userData = originalUserData;
-									child.name = originalName;
-
-									var bones = [];
-									var boneInverses = [];
-
-									for ( var i = 0, l = skinEntry.jointNames.length; i < l; i ++ ) {
-
-										var jointId = skinEntry.jointNames[ i ];
-										var jointNode = getJointNode( jointId );
-
-										if ( jointNode ) {
-
-											bones.push( jointNode );
-
-											var m = skinEntry.inverseBindMatrices.array;
-											var mat = new THREE.Matrix4().fromArray( m, i * 16 );
-											boneInverses.push( mat );
-
-										} else {
-
-											console.warn( "WARNING: joint: '" + jointId + "' could not be found" );
-
-										}
-
-									}
-
-									child.bind( new THREE.Skeleton( bones, boneInverses ), skinEntry.bindShapeMatrix );
-
-									var buildBoneGraph = function ( parentJson, parentObject, property ) {
-
-										var children = parentJson[ property ];
-
-										if ( children === undefined ) return;
-
-										for ( var i = 0, il = children.length; i < il; i ++ ) {
-
-											var nodeId = children[ i ];
-											var bone = __nodes[ nodeId ];
-											var boneJson = json.nodes[ nodeId ];
-
-											if ( bone !== undefined && bone.isBone === true && boneJson !== undefined ) {
-
-												parentObject.add( bone );
-												buildBoneGraph( boneJson, bone, 'children' );
-
-											}
-
-										}
-
-									};
-
-									buildBoneGraph( node, child, 'skeletons' );
-
-								}
-
-								_node.add( child );
-
-							}
-
-						}
-
-					}
-
-					if ( node.camera !== undefined ) {
-
-						var camera = dependencies.cameras[ node.camera ];
-
-						_node.add( camera );
-
-					}
-
-					if ( node.extensions
-							 && node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ]
-							 && node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ) {
-
-						var extensionLights = extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].lights;
-						var light = extensionLights[ node.extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].light ];
-
-						_node.add( light );
-
-					}
-
-					return _node;
-
-				} );
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadScenes = function () {
-
-		var json = this.json;
-
-		// scene node hierachy builder
-
-		function buildNodeHierachy( nodeId, parentObject, allNodes ) {
-
-			var _node = allNodes[ nodeId ];
-			parentObject.add( _node );
-
-			var node = json.nodes[ nodeId ];
-
-			if ( node.children ) {
-
-				var children = node.children;
-
-				for ( var i = 0, l = children.length; i < l; i ++ ) {
-
-					var child = children[ i ];
-					buildNodeHierachy( child, _node, allNodes );
-
-				}
-
-			}
-
-		}
-
-		return this._withDependencies( [
-
-			"nodes"
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.scenes, function ( scene ) {
-
-				var _scene = new THREE.Scene();
-				if ( scene.name !== undefined ) _scene.name = scene.name;
-
-				if ( scene.extras ) _scene.userData = scene.extras;
-
-				var nodes = scene.nodes || [];
-
-				for ( var i = 0, l = nodes.length; i < l; i ++ ) {
-
-					var nodeId = nodes[ i ];
-					buildNodeHierachy( nodeId, _scene, dependencies.nodes );
-
-				}
-
-				_scene.traverse( function ( child ) {
-
-					// Register raw material meshes with LegacyGLTFLoader.Shaders
-					if ( child.material && child.material.isRawShaderMaterial ) {
-
-						child.gltfShader = new GLTFShader( child, dependencies.nodes );
-						child.onBeforeRender = function ( renderer, scene, camera ) {
-
-							this.gltfShader.update( scene, camera );
-
-						};
-
-					}
-
-				} );
-
-				return _scene;
-
-			} );
-
-		} );
-
-	};
-
-	return LegacyGLTFLoader;
-
-} )();

+ 0 - 821
examples/js/loaders/deprecated/LegacyJSONLoader.js

@@ -1,821 +0,0 @@
-/**
- * @author mrdoob / http://mrdoob.com/
- * @author alteredq / http://alteredqualia.com/
- */
-
-THREE.LegacyJSONLoader = ( function () {
-
-	function LegacyJSONLoader( manager ) {
-
-		if ( typeof manager === 'boolean' ) {
-
-			console.warn( 'THREE.JSONLoader: showStatus parameter has been removed from constructor.' );
-			manager = undefined;
-
-		}
-
-		THREE.Loader.call( this, manager );
-
-		this.withCredentials = false;
-
-	}
-
-	LegacyJSONLoader.prototype = Object.assign( Object.create( THREE.Loader.prototype ), {
-
-		constructor: LegacyJSONLoader,
-
-		load: function ( url, onLoad, onProgress, onError ) {
-
-			var scope = this;
-
-			var path = ( this.path === '' ) ? THREE.LoaderUtils.extractUrlBase( url ) : this.path;
-
-			var loader = new THREE.FileLoader( this.manager );
-			loader.setPath( this.path );
-			loader.setWithCredentials( this.withCredentials );
-			loader.load( url, function ( text ) {
-
-				var json = JSON.parse( text );
-				var metadata = json.metadata;
-
-				if ( metadata !== undefined ) {
-
-					var type = metadata.type;
-
-					if ( type !== undefined ) {
-
-						if ( type.toLowerCase() === 'object' ) {
-
-							console.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
-							return;
-
-						}
-
-					}
-
-				}
-
-				var object = scope.parse( json, path );
-				onLoad( object.geometry, object.materials );
-
-			}, onProgress, onError );
-
-		},
-
-		parse: ( function () {
-
-			var _BlendingMode = {
-				NoBlending: THREE.NoBlending,
-				NormalBlending: THREE.NormalBlending,
-				AdditiveBlending: THREE.AdditiveBlending,
-				SubtractiveBlending: THREE.SubtractiveBlending,
-				MultiplyBlending: THREE.MultiplyBlending,
-				CustomBlending: THREE.CustomBlending
-			};
-
-			var _color = new THREE.Color();
-			var _textureLoader = new THREE.TextureLoader();
-			var _materialLoader = new THREE.MaterialLoader();
-
-			function initMaterials( materials, texturePath, crossOrigin, manager ) {
-
-				var array = [];
-
-				for ( var i = 0; i < materials.length; ++ i ) {
-
-					array[ i ] = createMaterial( materials[ i ], texturePath, crossOrigin, manager );
-
-				}
-
-				return array;
-
-			}
-
-			function createMaterial( m, texturePath, crossOrigin, manager ) {
-
-				// convert from old material format
-
-				var textures = {};
-
-				//
-
-				var json = {
-					uuid: THREE.Math.generateUUID(),
-					type: 'MeshLambertMaterial'
-				};
-
-				for ( var name in m ) {
-
-					var value = m[ name ];
-
-					switch ( name ) {
-
-						case 'DbgColor':
-						case 'DbgIndex':
-						case 'opticalDensity':
-						case 'illumination':
-							break;
-						case 'DbgName':
-							json.name = value;
-							break;
-						case 'blending':
-							json.blending = _BlendingMode[ value ];
-							break;
-						case 'colorAmbient':
-						case 'mapAmbient':
-							console.warn( 'THREE.LegacyJSONLoader.createMaterial:', name, 'is no longer supported.' );
-							break;
-						case 'colorDiffuse':
-							json.color = _color.fromArray( value ).getHex();
-							break;
-						case 'colorSpecular':
-							json.specular = _color.fromArray( value ).getHex();
-							break;
-						case 'colorEmissive':
-							json.emissive = _color.fromArray( value ).getHex();
-							break;
-						case 'specularCoef':
-							json.shininess = value;
-							break;
-						case 'shading':
-							if ( value.toLowerCase() === 'basic' ) json.type = 'MeshBasicMaterial';
-							if ( value.toLowerCase() === 'phong' ) json.type = 'MeshPhongMaterial';
-							if ( value.toLowerCase() === 'standard' ) json.type = 'MeshStandardMaterial';
-							break;
-						case 'mapDiffuse':
-							json.map = loadTexture( value, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapDiffuseRepeat':
-						case 'mapDiffuseOffset':
-						case 'mapDiffuseWrap':
-						case 'mapDiffuseAnisotropy':
-							break;
-						case 'mapEmissive':
-							json.emissiveMap = loadTexture( value, m.mapEmissiveRepeat, m.mapEmissiveOffset, m.mapEmissiveWrap, m.mapEmissiveAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapEmissiveRepeat':
-						case 'mapEmissiveOffset':
-						case 'mapEmissiveWrap':
-						case 'mapEmissiveAnisotropy':
-							break;
-						case 'mapLight':
-							json.lightMap = loadTexture( value, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapLightRepeat':
-						case 'mapLightOffset':
-						case 'mapLightWrap':
-						case 'mapLightAnisotropy':
-							break;
-						case 'mapAO':
-							json.aoMap = loadTexture( value, m.mapAORepeat, m.mapAOOffset, m.mapAOWrap, m.mapAOAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapAORepeat':
-						case 'mapAOOffset':
-						case 'mapAOWrap':
-						case 'mapAOAnisotropy':
-							break;
-						case 'mapBump':
-							json.bumpMap = loadTexture( value, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapBumpScale':
-							json.bumpScale = value;
-							break;
-						case 'mapBumpRepeat':
-						case 'mapBumpOffset':
-						case 'mapBumpWrap':
-						case 'mapBumpAnisotropy':
-							break;
-						case 'mapNormal':
-							json.normalMap = loadTexture( value, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapNormalFactor':
-							json.normalScale = value;
-							break;
-						case 'mapNormalRepeat':
-						case 'mapNormalOffset':
-						case 'mapNormalWrap':
-						case 'mapNormalAnisotropy':
-							break;
-						case 'mapSpecular':
-							json.specularMap = loadTexture( value, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapSpecularRepeat':
-						case 'mapSpecularOffset':
-						case 'mapSpecularWrap':
-						case 'mapSpecularAnisotropy':
-							break;
-						case 'mapMetalness':
-							json.metalnessMap = loadTexture( value, m.mapMetalnessRepeat, m.mapMetalnessOffset, m.mapMetalnessWrap, m.mapMetalnessAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapMetalnessRepeat':
-						case 'mapMetalnessOffset':
-						case 'mapMetalnessWrap':
-						case 'mapMetalnessAnisotropy':
-							break;
-						case 'mapRoughness':
-							json.roughnessMap = loadTexture( value, m.mapRoughnessRepeat, m.mapRoughnessOffset, m.mapRoughnessWrap, m.mapRoughnessAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapRoughnessRepeat':
-						case 'mapRoughnessOffset':
-						case 'mapRoughnessWrap':
-						case 'mapRoughnessAnisotropy':
-							break;
-						case 'mapAlpha':
-							json.alphaMap = loadTexture( value, m.mapAlphaRepeat, m.mapAlphaOffset, m.mapAlphaWrap, m.mapAlphaAnisotropy, textures, texturePath, crossOrigin, manager );
-							break;
-						case 'mapAlphaRepeat':
-						case 'mapAlphaOffset':
-						case 'mapAlphaWrap':
-						case 'mapAlphaAnisotropy':
-							break;
-						case 'flipSided':
-							json.side = THREE.BackSide;
-							break;
-						case 'doubleSided':
-							json.side = THREE.DoubleSide;
-							break;
-						case 'transparency':
-							console.warn( 'THREE.LegacyJSONLoader.createMaterial: transparency has been renamed to opacity' );
-							json.opacity = value;
-							break;
-						case 'depthTest':
-						case 'depthWrite':
-						case 'colorWrite':
-						case 'opacity':
-						case 'reflectivity':
-						case 'transparent':
-						case 'visible':
-						case 'wireframe':
-							json[ name ] = value;
-							break;
-						case 'vertexColors':
-							if ( value === true ) json.vertexColors = THREE.VertexColors;
-							if ( value === 'face' ) json.vertexColors = THREE.FaceColors;
-							break;
-						default:
-							console.error( 'THREE.LegacyJSONLoader.createMaterial: Unsupported', name, value );
-							break;
-
-					}
-
-				}
-
-				if ( json.type === 'MeshBasicMaterial' ) delete json.emissive;
-				if ( json.type !== 'MeshPhongMaterial' ) delete json.specular;
-
-				if ( json.opacity < 1 ) json.transparent = true;
-
-				_materialLoader.setTextures( textures );
-
-				return _materialLoader.parse( json );
-
-			}
-
-			function loadTexture( path, repeat, offset, wrap, anisotropy, textures, texturePath, crossOrigin, manager ) {
-
-				var fullPath = texturePath + path;
-				var loader = manager.getHandler( fullPath );
-
-				var texture;
-
-				if ( loader !== null ) {
-
-					texture = loader.load( fullPath );
-
-				} else {
-
-					_textureLoader.setCrossOrigin( crossOrigin );
-					texture = _textureLoader.load( fullPath );
-
-				}
-
-				if ( repeat !== undefined ) {
-
-					texture.repeat.fromArray( repeat );
-
-					if ( repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
-					if ( repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
-
-				}
-
-				if ( offset !== undefined ) {
-
-					texture.offset.fromArray( offset );
-
-				}
-
-				if ( wrap !== undefined ) {
-
-					if ( wrap[ 0 ] === 'repeat' ) texture.wrapS = THREE.RepeatWrapping;
-					if ( wrap[ 0 ] === 'mirror' ) texture.wrapS = THREE.MirroredRepeatWrapping;
-
-					if ( wrap[ 1 ] === 'repeat' ) texture.wrapT = THREE.RepeatWrapping;
-					if ( wrap[ 1 ] === 'mirror' ) texture.wrapT = THREE.MirroredRepeatWrapping;
-
-				}
-
-				if ( anisotropy !== undefined ) {
-
-					texture.anisotropy = anisotropy;
-
-				}
-
-				var uuid = THREE.Math.generateUUID();
-
-				textures[ uuid ] = texture;
-
-				return uuid;
-
-			}
-
-			function parseModel( json, geometry ) {
-
-				function isBitSet( value, position ) {
-
-					return value & ( 1 << position );
-
-				}
-
-				var i, j, fi,
-
-					offset, zLength,
-
-					colorIndex, normalIndex, uvIndex, materialIndex,
-
-					type,
-					isQuad,
-					hasMaterial,
-					hasFaceVertexUv,
-					hasFaceNormal, hasFaceVertexNormal,
-					hasFaceColor, hasFaceVertexColor,
-
-					vertex, face, faceA, faceB, hex, normal,
-
-					uvLayer, uv, u, v,
-
-					faces = json.faces,
-					vertices = json.vertices,
-					normals = json.normals,
-					colors = json.colors,
-
-					scale = json.scale,
-
-					nUvLayers = 0;
-
-
-				if ( json.uvs !== undefined ) {
-
-					// disregard empty arrays
-
-					for ( i = 0; i < json.uvs.length; i ++ ) {
-
-						if ( json.uvs[ i ].length ) nUvLayers ++;
-
-					}
-
-					for ( i = 0; i < nUvLayers; i ++ ) {
-
-						geometry.faceVertexUvs[ i ] = [];
-
-					}
-
-				}
-
-				offset = 0;
-				zLength = vertices.length;
-
-				while ( offset < zLength ) {
-
-					vertex = new THREE.Vector3();
-
-					vertex.x = vertices[ offset ++ ] * scale;
-					vertex.y = vertices[ offset ++ ] * scale;
-					vertex.z = vertices[ offset ++ ] * scale;
-
-					geometry.vertices.push( vertex );
-
-				}
-
-				offset = 0;
-				zLength = faces.length;
-
-				while ( offset < zLength ) {
-
-					type = faces[ offset ++ ];
-
-					isQuad = isBitSet( type, 0 );
-					hasMaterial = isBitSet( type, 1 );
-					hasFaceVertexUv = isBitSet( type, 3 );
-					hasFaceNormal = isBitSet( type, 4 );
-					hasFaceVertexNormal = isBitSet( type, 5 );
-					hasFaceColor = isBitSet( type, 6 );
-					hasFaceVertexColor = isBitSet( type, 7 );
-
-					// console.log("type", type, "bits", isQuad, hasMaterial, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
-
-					if ( isQuad ) {
-
-						faceA = new THREE.Face3();
-						faceA.a = faces[ offset ];
-						faceA.b = faces[ offset + 1 ];
-						faceA.c = faces[ offset + 3 ];
-
-						faceB = new THREE.Face3();
-						faceB.a = faces[ offset + 1 ];
-						faceB.b = faces[ offset + 2 ];
-						faceB.c = faces[ offset + 3 ];
-
-						offset += 4;
-
-						if ( hasMaterial ) {
-
-							materialIndex = faces[ offset ++ ];
-							faceA.materialIndex = materialIndex;
-							faceB.materialIndex = materialIndex;
-
-						}
-
-						// to get face <=> uv index correspondence
-
-						fi = geometry.faces.length;
-
-						if ( hasFaceVertexUv ) {
-
-							for ( i = 0; i < nUvLayers; i ++ ) {
-
-								uvLayer = json.uvs[ i ];
-
-								geometry.faceVertexUvs[ i ][ fi ] = [];
-								geometry.faceVertexUvs[ i ][ fi + 1 ] = [];
-
-								for ( j = 0; j < 4; j ++ ) {
-
-									uvIndex = faces[ offset ++ ];
-
-									u = uvLayer[ uvIndex * 2 ];
-									v = uvLayer[ uvIndex * 2 + 1 ];
-
-									uv = new THREE.Vector2( u, v );
-
-									if ( j !== 2 ) geometry.faceVertexUvs[ i ][ fi ].push( uv );
-									if ( j !== 0 ) geometry.faceVertexUvs[ i ][ fi + 1 ].push( uv );
-
-								}
-
-							}
-
-						}
-
-						if ( hasFaceNormal ) {
-
-							normalIndex = faces[ offset ++ ] * 3;
-
-							faceA.normal.set(
-								normals[ normalIndex ++ ],
-								normals[ normalIndex ++ ],
-								normals[ normalIndex ]
-							);
-
-							faceB.normal.copy( faceA.normal );
-
-						}
-
-						if ( hasFaceVertexNormal ) {
-
-							for ( i = 0; i < 4; i ++ ) {
-
-								normalIndex = faces[ offset ++ ] * 3;
-
-								normal = new THREE.Vector3(
-									normals[ normalIndex ++ ],
-									normals[ normalIndex ++ ],
-									normals[ normalIndex ]
-								);
-
-
-								if ( i !== 2 ) faceA.vertexNormals.push( normal );
-								if ( i !== 0 ) faceB.vertexNormals.push( normal );
-
-							}
-
-						}
-
-
-						if ( hasFaceColor ) {
-
-							colorIndex = faces[ offset ++ ];
-							hex = colors[ colorIndex ];
-
-							faceA.color.setHex( hex );
-							faceB.color.setHex( hex );
-
-						}
-
-
-						if ( hasFaceVertexColor ) {
-
-							for ( i = 0; i < 4; i ++ ) {
-
-								colorIndex = faces[ offset ++ ];
-								hex = colors[ colorIndex ];
-
-								if ( i !== 2 ) faceA.vertexColors.push( new THREE.Color( hex ) );
-								if ( i !== 0 ) faceB.vertexColors.push( new THREE.Color( hex ) );
-
-							}
-
-						}
-
-						geometry.faces.push( faceA );
-						geometry.faces.push( faceB );
-
-					} else {
-
-						face = new THREE.Face3();
-						face.a = faces[ offset ++ ];
-						face.b = faces[ offset ++ ];
-						face.c = faces[ offset ++ ];
-
-						if ( hasMaterial ) {
-
-							materialIndex = faces[ offset ++ ];
-							face.materialIndex = materialIndex;
-
-						}
-
-						// to get face <=> uv index correspondence
-
-						fi = geometry.faces.length;
-
-						if ( hasFaceVertexUv ) {
-
-							for ( i = 0; i < nUvLayers; i ++ ) {
-
-								uvLayer = json.uvs[ i ];
-
-								geometry.faceVertexUvs[ i ][ fi ] = [];
-
-								for ( j = 0; j < 3; j ++ ) {
-
-									uvIndex = faces[ offset ++ ];
-
-									u = uvLayer[ uvIndex * 2 ];
-									v = uvLayer[ uvIndex * 2 + 1 ];
-
-									uv = new THREE.Vector2( u, v );
-
-									geometry.faceVertexUvs[ i ][ fi ].push( uv );
-
-								}
-
-							}
-
-						}
-
-						if ( hasFaceNormal ) {
-
-							normalIndex = faces[ offset ++ ] * 3;
-
-							face.normal.set(
-								normals[ normalIndex ++ ],
-								normals[ normalIndex ++ ],
-								normals[ normalIndex ]
-							);
-
-						}
-
-						if ( hasFaceVertexNormal ) {
-
-							for ( i = 0; i < 3; i ++ ) {
-
-								normalIndex = faces[ offset ++ ] * 3;
-
-								normal = new THREE.Vector3(
-									normals[ normalIndex ++ ],
-									normals[ normalIndex ++ ],
-									normals[ normalIndex ]
-								);
-
-								face.vertexNormals.push( normal );
-
-							}
-
-						}
-
-
-						if ( hasFaceColor ) {
-
-							colorIndex = faces[ offset ++ ];
-							face.color.setHex( colors[ colorIndex ] );
-
-						}
-
-
-						if ( hasFaceVertexColor ) {
-
-							for ( i = 0; i < 3; i ++ ) {
-
-								colorIndex = faces[ offset ++ ];
-								face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
-
-							}
-
-						}
-
-						geometry.faces.push( face );
-
-					}
-
-				}
-
-			}
-
-			function parseSkin( json, geometry ) {
-
-				var influencesPerVertex = ( json.influencesPerVertex !== undefined ) ? json.influencesPerVertex : 2;
-
-				if ( json.skinWeights ) {
-
-					for ( var i = 0, l = json.skinWeights.length; i < l; i += influencesPerVertex ) {
-
-						var x = json.skinWeights[ i ];
-						var y = ( influencesPerVertex > 1 ) ? json.skinWeights[ i + 1 ] : 0;
-						var z = ( influencesPerVertex > 2 ) ? json.skinWeights[ i + 2 ] : 0;
-						var w = ( influencesPerVertex > 3 ) ? json.skinWeights[ i + 3 ] : 0;
-
-						geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
-
-					}
-
-				}
-
-				if ( json.skinIndices ) {
-
-					for ( var i = 0, l = json.skinIndices.length; i < l; i += influencesPerVertex ) {
-
-						var a = json.skinIndices[ i ];
-						var b = ( influencesPerVertex > 1 ) ? json.skinIndices[ i + 1 ] : 0;
-						var c = ( influencesPerVertex > 2 ) ? json.skinIndices[ i + 2 ] : 0;
-						var d = ( influencesPerVertex > 3 ) ? json.skinIndices[ i + 3 ] : 0;
-
-						geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
-
-					}
-
-				}
-
-				geometry.bones = json.bones;
-
-				if ( geometry.bones && geometry.bones.length > 0 && ( geometry.skinWeights.length !== geometry.skinIndices.length || geometry.skinIndices.length !== geometry.vertices.length ) ) {
-
-					console.warn( 'When skinning, number of vertices (' + geometry.vertices.length + '), skinIndices (' +
-						geometry.skinIndices.length + '), and skinWeights (' + geometry.skinWeights.length + ') should match.' );
-
-				}
-
-			}
-
-			function parseMorphing( json, geometry ) {
-
-				var scale = json.scale;
-
-				if ( json.morphTargets !== undefined ) {
-
-					for ( var i = 0, l = json.morphTargets.length; i < l; i ++ ) {
-
-						geometry.morphTargets[ i ] = {};
-						geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
-						geometry.morphTargets[ i ].vertices = [];
-
-						var dstVertices = geometry.morphTargets[ i ].vertices;
-						var srcVertices = json.morphTargets[ i ].vertices;
-
-						for ( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
-
-							var vertex = new THREE.Vector3();
-							vertex.x = srcVertices[ v ] * scale;
-							vertex.y = srcVertices[ v + 1 ] * scale;
-							vertex.z = srcVertices[ v + 2 ] * scale;
-
-							dstVertices.push( vertex );
-
-						}
-
-					}
-
-				}
-
-				if ( json.morphColors !== undefined && json.morphColors.length > 0 ) {
-
-					console.warn( 'THREE.JSONLoader: "morphColors" no longer supported. Using them as face colors.' );
-
-					var faces = geometry.faces;
-					var morphColors = json.morphColors[ 0 ].colors;
-
-					for ( var i = 0, l = faces.length; i < l; i ++ ) {
-
-						faces[ i ].color.fromArray( morphColors, i * 3 );
-
-					}
-
-				}
-
-			}
-
-			function parseAnimations( json, geometry ) {
-
-				var outputAnimations = [];
-
-				// parse old style Bone/Hierarchy animations
-				var animations = [];
-
-				if ( json.animation !== undefined ) {
-
-					animations.push( json.animation );
-
-				}
-
-				if ( json.animations !== undefined ) {
-
-					if ( json.animations.length ) {
-
-						animations = animations.concat( json.animations );
-
-					} else {
-
-						animations.push( json.animations );
-
-					}
-
-				}
-
-				for ( var i = 0; i < animations.length; i ++ ) {
-
-					var clip = THREE.AnimationClip.parseAnimation( animations[ i ], geometry.bones );
-					if ( clip ) outputAnimations.push( clip );
-
-				}
-
-				// parse implicit morph animations
-				if ( geometry.morphTargets ) {
-
-					// TODO: Figure out what an appropraite FPS is for morph target animations -- defaulting to 10, but really it is completely arbitrary.
-					var morphAnimationClips = THREE.AnimationClip.CreateClipsFromMorphTargetSequences( geometry.morphTargets, 10 );
-					outputAnimations = outputAnimations.concat( morphAnimationClips );
-
-				}
-
-				if ( outputAnimations.length > 0 ) geometry.animations = outputAnimations;
-
-			}
-
-			return function parse( json, path ) {
-
-				if ( json.data !== undefined ) {
-
-					// Geometry 4.0 spec
-					json = json.data;
-
-				}
-
-				if ( json.scale !== undefined ) {
-
-					json.scale = 1.0 / json.scale;
-
-				} else {
-
-					json.scale = 1.0;
-
-				}
-
-				var geometry = new THREE.Geometry();
-
-				parseModel( json, geometry );
-				parseSkin( json, geometry );
-				parseMorphing( json, geometry );
-				parseAnimations( json, geometry );
-
-				geometry.computeFaceNormals();
-				geometry.computeBoundingSphere();
-
-				if ( json.materials === undefined || json.materials.length === 0 ) {
-
-					return { geometry: geometry };
-
-				} else {
-
-					var materials = initMaterials( json.materials, this.resourcePath || path, this.crossOrigin, this.manager );
-
-					return { geometry: geometry, materials: materials };
-
-				}
-
-			};
-
-		} )()
-
-	} );
-
-	return LegacyJSONLoader;
-
-} )();

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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