Mr.doob 8 years ago
parent
commit
6c63d5694c
100 changed files with 5126 additions and 5890 deletions
  1. 29 8
      build/three.js
  2. 366 362
      build/three.min.js
  3. 29 8
      build/three.module.js
  4. 12 6
      docs/api/cameras/CubeCamera.html
  5. 0 10
      docs/api/constants/Materials.html
  6. 13 10
      docs/api/core/InterleavedBufferAttribute.html
  7. 18 19
      docs/api/core/Layers.html
  8. 1 1
      docs/api/extras/core/Font.html
  9. 0 179
      docs/api/extras/objects/MorphBlendMesh.html
  10. 1 1
      docs/api/geometries/RingBufferGeometry.html
  11. 1 1
      docs/api/geometries/RingGeometry.html
  12. 161 0
      docs/api/geometries/TextBufferGeometry.html
  13. 12 4
      docs/api/helpers/DirectionalLightHelper.html
  14. 13 4
      docs/api/helpers/HemisphereLightHelper.html
  15. 13 6
      docs/api/helpers/PointLightHelper.html
  16. 12 2
      docs/api/helpers/RectAreaLightHelper.html
  17. 11 3
      docs/api/helpers/SpotLightHelper.html
  18. 14 7
      docs/api/materials/Material.html
  19. 5 1
      docs/api/materials/MeshBasicMaterial.html
  20. 7 3
      docs/api/materials/MeshLambertMaterial.html
  21. 7 3
      docs/api/materials/MeshPhongMaterial.html
  22. 5 1
      docs/api/materials/MeshStandardMaterial.html
  23. 2 2
      docs/api/materials/PointsMaterial.html
  24. 5 6
      docs/api/materials/ShaderMaterial.html
  25. 1 1
      docs/api/math/Matrix4.html
  26. 19 37
      docs/api/math/Plane.html
  27. 2 2
      docs/api/objects/Group.html
  28. 1 1
      docs/api/objects/Mesh.html
  29. 133 133
      docs/api/renderers/WebGLRenderTarget.html
  30. 1 1
      docs/api/renderers/WebGLRenderer.html
  31. 0 9
      docs/examples/loaders/ColladaLoader.html
  32. 12 11
      docs/examples/loaders/GLTFLoader.html
  33. 43 118
      docs/index.html
  34. 3 2
      docs/list.js
  35. 1 1
      docs/manual/introduction/Animation-system.html
  36. 71 71
      docs/manual/introduction/How-to-run-thing-locally.html
  37. 2 2
      docs/manual/introduction/How-to-update-things.html
  38. 72 0
      docs/manual/introduction/Import-via-modules.html
  39. 3 3
      docs/manual/introduction/Useful-links.html
  40. 1 1
      docs/scenes/bones-browser.html
  41. 1 1
      docs/scenes/geometry-browser.html
  42. 70 8
      docs/scenes/js/geometry.js
  43. 4 12
      docs/scenes/js/material.js
  44. 1 1
      docs/scenes/material-browser.html
  45. 2 47
      editor/index.html
  46. 28 7
      editor/js/Editor.js
  47. 24 1
      editor/js/Loader.js
  48. 24 15
      editor/js/Menubar.File.js
  49. 127 55
      editor/js/Sidebar.Material.js
  50. 3 62
      editor/js/Viewport.js
  51. 13 8
      editor/js/commands/SetMaterialColorCommand.js
  52. 14 5
      editor/js/commands/SetMaterialCommand.js
  53. 14 9
      editor/js/commands/SetMaterialValueCommand.js
  54. 26 40
      editor/js/libs/app.js
  55. 0 68
      editor/js/libs/tern-threejs/threejs.js
  56. 1 1
      examples/canvas_ascii_effect.html
  57. 13 11
      examples/canvas_camera_orthographic.html
  58. 1 1
      examples/canvas_camera_orthographic2.html
  59. 1 1
      examples/canvas_geometry_birds.html
  60. 2 1
      examples/canvas_geometry_cube.html
  61. 1 1
      examples/canvas_geometry_earth.html
  62. 1 1
      examples/canvas_geometry_hierarchy.html
  63. 1 1
      examples/canvas_geometry_nurbs.html
  64. 1 1
      examples/canvas_geometry_shapes.html
  65. 1 1
      examples/canvas_geometry_terrain.html
  66. 1 1
      examples/canvas_geometry_text.html
  67. 1 1
      examples/canvas_interactive_cubes.html
  68. 1 1
      examples/canvas_interactive_cubes_tween.html
  69. 1 1
      examples/canvas_interactive_particles.html
  70. 1 1
      examples/canvas_interactive_voxelpainter.html
  71. 2 4
      examples/canvas_lines_dashed.html
  72. 1 1
      examples/canvas_materials_video.html
  73. 1 1
      examples/canvas_morphtargets_horse.html
  74. 1 1
      examples/canvas_particles_sprites.html
  75. 1 1
      examples/canvas_performance.html
  76. 1 1
      examples/canvas_sandbox.html
  77. 18 29
      examples/css3d_molecules.html
  78. 2 1
      examples/css3d_sandbox.html
  79. 10 4
      examples/files.js
  80. 25 21
      examples/index.html
  81. 1 1
      examples/js/GPUParticleSystem.js
  82. 23 2
      examples/js/Mirror.js
  83. 318 0
      examples/js/MorphBlendMesh.js
  84. 40 23
      examples/js/animation/MMDPhysics.js
  85. 92 5
      examples/js/controls/DragControls.js
  86. 0 2
      examples/js/controls/EditorControls.js
  87. 0 10
      examples/js/controls/TransformControls.js
  88. 1 1
      examples/js/crossfade/scenes.js
  89. 922 0
      examples/js/exporters/GLTFExporter.js
  90. 17 11
      examples/js/loaders/3MFLoader.js
  91. 71 76
      examples/js/loaders/AMFLoader.js
  92. 126 180
      examples/js/loaders/AssimpJSONLoader.js
  93. 836 789
      examples/js/loaders/AssimpLoader.js
  94. 76 64
      examples/js/loaders/BVHLoader.js
  95. 118 120
      examples/js/loaders/BabylonLoader.js
  96. 2 0
      examples/js/loaders/BinaryLoader.js
  97. 0 9
      examples/js/loaders/ColladaLoader.js
  98. 785 179
      examples/js/loaders/ColladaLoader2.js
  99. 155 78
      examples/js/loaders/FBXLoader.js
  100. 0 2872
      examples/js/loaders/GLTF2Loader.js

File diff suppressed because it is too large
+ 29 - 8
build/three.js


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


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


+ 12 - 6
docs/api/cameras/CubeCamera.html

@@ -20,21 +20,21 @@
 		<div>[example:webgl_materials_cubemap_dynamic2 materials / cubemap / dynamic2 ]</div>
 		<div>[example:webgl_materials_cubemap_dynamic2 materials / cubemap / dynamic2 ]</div>
 		<div>[example:webgl_shading_physical shading / physical ]</div>
 		<div>[example:webgl_shading_physical shading / physical ]</div>
 
 
-		<code>//Create cube camera
+		<code>// Create cube camera
 		var cubeCamera = new THREE.CubeCamera( 1, 100000, 128 );
 		var cubeCamera = new THREE.CubeCamera( 1, 100000, 128 );
 		scene.add( cubeCamera );
 		scene.add( cubeCamera );
 
 
-		//Create car
+		// Create car
 		var chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeCamera.renderTarget } );
 		var chromeMaterial = new THREE.MeshLambertMaterial( { color: 0xffffff, envMap: cubeCamera.renderTarget } );
 		var car = new Mesh( carGeometry, chromeMaterial );
 		var car = new Mesh( carGeometry, chromeMaterial );
 		scene.add( car );
 		scene.add( car );
 
 
-		//Update the render target cube
+		// Update the render target cube
 		car.setVisible( false );
 		car.setVisible( false );
 		cubeCamera.position.copy( car.position );
 		cubeCamera.position.copy( car.position );
-		cubeCamera.updateCubeMap( renderer, scene );
+		cubeCamera.update( renderer, scene );
 
 
-		//Render the scene
+		// Render the scene
 		car.setVisible( true );
 		car.setVisible( true );
 		renderer.render( scene, camera );
 		renderer.render( scene, camera );
 		</code>
 		</code>
@@ -67,7 +67,7 @@
 		<div>See the base [page:Object3D] class for common methods.</div>
 		<div>See the base [page:Object3D] class for common methods.</div>
 
 
 
 
-		<h3>[method:null updateCubeMap]( [page:WebGLRenderer renderer], [page:Scene scene] )</h3>
+		<h3>[method:null update]( [page:WebGLRenderer renderer], [page:Scene scene] )</h3>
 		<div>
 		<div>
 		renderer -- The current WebGL renderer <br />
 		renderer -- The current WebGL renderer <br />
 		scene -- The current scene
 		scene -- The current scene
@@ -76,6 +76,12 @@
 		Call this to update the [page:CubeCamera.renderTarget renderTarget].
 		Call this to update the [page:CubeCamera.renderTarget renderTarget].
 		</div>
 		</div>
 
 
+		<h3>[method:null clear]( [page:WebGLRenderer renderer], [page:Boolean color], [page:Boolean depth], [page:Boolean stencil] )</h3>
+		<div>
+		Call this to clear the [page:CubeCamera.renderTarget renderTarget] color, depth, and/or stencil buffers.
+		The color buffer is set to the renderer's current clear color. Arguments default to *true*.
+		</div>
+
 		<h2>Source</h2>
 		<h2>Source</h2>
 
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 0 - 10
docs/api/constants/Materials.html

@@ -28,16 +28,6 @@
 		</div>
 		</div>
 
 
 
 
-		<h2>Shading</h2>
-		<code>
-	  THREE.SmoothShading
-		THREE.FlatShading
-		</code>
-		<div>
-		[page:Constant SmoothShading] is the default and linearly interpolates color between vertices.<br />
-		[page:Constant FlatShading] uses the color of the first vertex for every pixel in a face.
-		</div>
-
 		<h2>Colors</h2>
 		<h2>Colors</h2>
 		<code>
 		<code>
 		THREE.NoColors
 		THREE.NoColors

+ 13 - 10
docs/api/core/InterleavedBufferAttribute.html

@@ -27,6 +27,19 @@
 			The [page:InterleavedBuffer InterleavedBuffer] instance passed in the constructor.
 			The [page:InterleavedBuffer InterleavedBuffer] instance passed in the constructor.
 		</div>
 		</div>
 
 
+		<h3>[property:TypedArray array]</h3>
+		<div>
+			The value of [page:InterleavedBufferAttribute.data data].array.
+		</div>
+
+		<h3>[property:Integer count]</h3>
+		<div>
+			The value of [page:InterleavedBufferAttribute.data data].count.
+
+			If the buffer is storing a 3-component vector (such as a position, normal, or color),
+			then this will count the number of such vectors stored.
+		</div>
+
 		<h3>[property:Integer itemSize]</h3>
 		<h3>[property:Integer itemSize]</h3>
 		<div>
 		<div>
 		</div>
 		</div>
@@ -47,16 +60,6 @@
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
-		<h3>[method:Integer count]()</h3>
-		<div>
-			The value of [page:InterleavedBufferAttribute.data data].count.
-		</div>
-
-		<h3>[method:Array array]()</h3>
-		<div>
-			The value of [page:InterleavedBufferAttribute.data data].array.
-		</div>
-
 		<h3>[method:null getX]( index ) </h3>
 		<h3>[method:null getX]( index ) </h3>
 		<div>
 		<div>
 
 

+ 18 - 19
docs/api/core/Layers.html

@@ -11,15 +11,14 @@
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
 		<div class="desc">
 		<div class="desc">
-		An object providing a [link:https://en.wikipedia.org/wiki/Mask_(computing) bit mask] and accessor methods
-		used to control an [page:Object3D]'s visibility.
-		A [page:Layers] object assigns an [page:Object3D] to 0 or more of 32 layers numbered 0 to 31.<br /><br />
+      			A [page:Layers] object assigns an [page:Object3D] to 1 or more of 32 layers numbered 0 to 31
+      			- internally the layers are stored as a [link:https://en.wikipedia.org/wiki/Mask_(computing) bit mask], and by default all
+      			Object3Ds are a member of layer 0.<br /><br />
 
 
-		This is used to control visibility - an object must share a layer with a [page:Camera camera]
-		to be visible when that camera's view is renderered.<br /><br />
+      			This can be used to control visibility - an object must share a layer with a [page:Camera camera] to be visible when that camera's
+      			view is renderered.<br /><br />
 
 
-		All classes that inherit from [page:Object3D] have a [property:layers] property which is an instance
-		of this class.
+      			All classes that inherit from [page:Object3D] have an [page:Object3D.layers] property which is an instance of this class.
 		</div>
 		</div>
 
 
 
 
@@ -28,14 +27,14 @@
 
 
 		<h3>[name]()</h3>
 		<h3>[name]()</h3>
 		<div>
 		<div>
-		Create a new Layers object, with an initial mask set to layer 1.
+			Create a new Layers object, with membership initially set to layer 0.
 		</div>
 		</div>
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
 
 
 		<h3>[property:Integer mask]</h3>
 		<h3>[property:Integer mask]</h3>
 		<div>
 		<div>
-		Internal layer mask.
+		 	A bit mask storing which of the 32 layers this layers object is currently a member of.
 		</div>
 		</div>
 
 
 
 
@@ -43,37 +42,37 @@
 
 
 		<h3>[method:null disable]( [page:Integer layer] )</h3>
 		<h3>[method:null disable]( [page:Integer layer] )</h3>
 		<div>
 		<div>
-		layer - an integer from 0 to 31.<br /><br />
+			layer - an integer from 0 to 31.<br /><br />
 
 
-		Remove *layer* from the mask.
+			Remove membership of this *layer*.
 		</div>
 		</div>
 
 
 		<h3>[method:null enable]( [page:Integer layer] )</h3>
 		<h3>[method:null enable]( [page:Integer layer] )</h3>
 		<div>
 		<div>
-		layer - an integer from 0 to 31.<br /><br />
+			layer - an integer from 0 to 31.<br /><br />
 
 
-		Add *layer* to the mask.
+			Add membership of this *layer*.
 		</div>
 		</div>
 
 
 		<h3>[method:null set]( [page:Integer layer] )</h3>
 		<h3>[method:null set]( [page:Integer layer] )</h3>
 		<div>
 		<div>
-		layer - an integer from 0 to 31.<br /><br />
+			layer - an integer from 0 to 31.<br /><br />
 
 
-		Set the layer mask to the value *layer*.
+			Set membership to *layer*, and remove membership all other layers.
 		</div>
 		</div>
 
 
 		<h3>[method:Boolean test]( [page:Integer layers] )</h3>
 		<h3>[method:Boolean test]( [page:Integer layers] )</h3>
 		<div>
 		<div>
-		layers - a 32bit bit mask of layer numbers.<br /><br />
+			layers - a Layers object<br /><br />
 
 
-		Returns true if *layers* and [page:.mask] have any bits set in common.
+			Returns true if this and the passed *layers* object are members of the same set of layers.
 		</div>
 		</div>
 
 
 		<h3>[method:null toggle]( [page:Integer layer] )</h3>
 		<h3>[method:null toggle]( [page:Integer layer] )</h3>
 		<div>
 		<div>
-		layer - an integer from 0 to 31.<br /><br />
+			layer - an integer from 0 to 31.<br /><br />
 
 
-		Toggle the *layer* value in the mask.
+			Toggle membership of *layer*.
 		</div>
 		</div>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

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

@@ -50,7 +50,7 @@
 		<div>
 		<div>
 			[page:String text] -- string of text.<br />
 			[page:String text] -- string of text.<br />
 			[page:Float size] -- (optional) scale for the [page:Shape Shapes]. Default is *100*.<br />
 			[page:Float size] -- (optional) scale for the [page:Shape Shapes]. Default is *100*.<br />
-			[page:Integer divisions] -- (optional) fineness of the [page:Shape Shapes]. Default is *5*.<br />
+			[page:Integer divisions] -- (optional) fineness of the [page:Shape Shapes]. Default is *4*.<br />
 
 
 			Creates an array of [page:Shape Shapes] representing the text in the font.
 			Creates an array of [page:Shape Shapes] representing the text in the font.
 		</div>
 		</div>

+ 0 - 179
docs/api/extras/objects/MorphBlendMesh.html

@@ -1,179 +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>
-		[page:Mesh] &rarr;
-
-		<h1>[name]</h1>
-
-		<div class="desc">A mesh that can blend together multiple animated morph targets.</div>
-
-		<h2>Example</h2>
-		[example:webgl_morphtargets_md2_control morphtargets / md2 / controll]
-
-
-		<h2>Constructor</h2>
-
-
-		<h3>[name]([page:Geometry geometry], [page:Material material])</h3>
-		<div>
-		geometry — An instance of [page:Geometry].<br />
-		material — An instance of [page:Material] (optional).
-		</div>
-
-		<h2>Properties</h2>
-
-
-		<h3>[property:object animationsMap]</h3>
-		<div>
-		An object of named animations as added by [page:MorphBlendMesh.createAnimation].
-		</div>
-
-		<h3>[property:array animationsList]</h3>
-		<div>
-		The list of animations as added by [page:MorphBlendMesh.createAnimation].
-		</div>
-
-		<h2>Methods</h2>
-
-
-
-		<h3>[method:null setAnimationWeight]([page:String name], [page:Float weight])</h3>
-		<div>
-		name -- The name of the animation<br />
-		weight -- Weight of the animation, typically 0-1
-		</div>
-		<div>
-		Set the weight of how much this animation will apply to the overall morph. 0 is off, 1 is full weight.
-		</div>
-
-		<h3>[method:null setAnimationFPS]([page:String name], [page:Float fps])</h3>
-		<div>
-		name -- The name of the animation <br />
-		fps -- The number of frames (morphTargets) per second
-		</div>
-		<div>
-		A frame is typically 1 morph target.
-		</div>
-
-		<h3>[method:null createAnimation]([page:String name], [page:Integer start], [page:Integer end], [page:Float fps])</h3>
-		<div>
-		name -- The name of the animation <br />
-		start -- The starting frame (morph)<br />
-		end -- The ending frame (morph)<br />
-		fps -- How many frames (morphs) to play per second
-		</div>
-		<div>
-		Creates an animation object that gets added to both the [page:MorphBlendMesh.animationsMap animationsMap] and
-		[page:MorphBlendMesh.animationsList animationsList].<br/><br/>
-
-		Animation object:<br/><br/>
-		startFrame -- Starting frame<br/>
-		endFrame -- Ending frame<br/>
-		length -- The number of frames<br/>
-		fps -- The frames per second<br/>
-		duration -- The length of the animation in seconds<br/>
-		lastFrame -- The previous frame that was played<br/>
-		currentFrame -- The current frame<br/>
-		active -- Whether or not the animation is being played<br/>
-		time -- The time in seconds of the animation<br/>
-		direction -- Which way to play the animation<br/>
-		weight -- The weight of the animation<br/>
-		directionBackwards -- Is playing backwards<br/>
-		mirroredLoop -- Loop back and forth
-		</div>
-
-		<h3>[method:null playAnimation]([page:String name])</h3>
-		<div>
-		name -- The name of the animation
-		</div>
-		<div>
-		Sets the animation to active and animation time to 0
-		</div>
-
-		<h3>[method:null update]([page:Float delta])</h3>
-		<div>
-		delta -- Time in seconds
-		</div>
-		<div>
-		Updates and plays the animation
-		</div>
-
-		<h3>[method:null autoCreateAnimations]([page:Float fps])</h3>
-		<div>
-		fps -- Frames per second
-		</div>
-		<div>
-		Goes through the geometry's morphTargets and generates animations based on the morphTargets' names. Names
-		are of the form "walk_01", "walk_02", "walk_03", etc or "run001", "run002", "run003".
-		</div>
-
-		<h3>[method:null setAnimationDuration]([page:String name], [page:Float duration])</h3>
-		<div>
-		name -- The name of the animation <br />
-		duration -- How long in seconds to play the animation
-		</div>
-		<div>
-		Updates the animation object with proper values to update the duration.
-		</div>
-
-		<h3>[method:null setAnimationDirectionForward]([page:String name])</h3>
-		<div>
-		name -- The name of the animation
-		</div>
-		<div>
-		Sets the animation to play forwards
-		</div>
-
-		<h3>[method:null setAnimationDirectionBackward]([page:String name])</h3>
-		<div>
-		name -- The name of the animation
-		</div>
-		<div>
-		Sets the animation to play backwards
-		</div>
-
-		<h3>[method:Float getAnimationDuration]([page:String name])</h3>
-		<div>
-		name -- The name of the animation
-		</div>
-		<div>
-		Returns the duration in seconds of the animation. Returns -1 if it can't be found.
-		</div>
-
-		<h3>[method:Float getAnimationTime]([page:String name])</h3>
-		<div>
-		name -- The name of the animation
-		</div>
-		<div>
-		Returns the current time position of the animation.
-		</div>
-
-		<h3>[method:null setAnimationTime]([page:String name], [page:Float time])</h3>
-		<div>
-		name -- The name of the animation <br />
-		time -- The time in seconds
-		</div>
-		<div>
-		Sets the current time position of the animation
-		</div>
-
-		<h3>[method:null stopAnimation]([page:String name])</h3>
-		<div>
-		name -- The name of the animation
-		</div>
-		<div>
-		Stops the playback of the animation
-		</div>
-
-		<h2>Source</h2>
-
-		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-	</body>
-</html>

+ 1 - 1
docs/api/geometries/RingBufferGeometry.html

@@ -44,7 +44,7 @@
 
 
 		<h3>[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])</h3>
 		<h3>[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])</h3>
 		<div>
 		<div>
-		innerRadius — Default is 0, but it doesn't work right when innerRadius is set to 0.<br />
+		innerRadius — Default is 20. <br />
 		outerRadius — Default is 50. <br />
 		outerRadius — Default is 50. <br />
 		thetaSegments — Number of segments.  A higher number means the ring will be more round.  Minimum is 3.  Default is 8. <br />
 		thetaSegments — Number of segments.  A higher number means the ring will be more round.  Minimum is 3.  Default is 8. <br />
 		phiSegments — Minimum is 1.  Default is 8.<br />
 		phiSegments — Minimum is 1.  Default is 8.<br />

+ 1 - 1
docs/api/geometries/RingGeometry.html

@@ -44,7 +44,7 @@
 
 
 		<h3>[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])</h3>
 		<h3>[name]([page:Float innerRadius], [page:Float outerRadius], [page:Integer thetaSegments], [page:Integer phiSegments], [page:Float thetaStart], [page:Float thetaLength])</h3>
 		<div>
 		<div>
-		innerRadius — Default is 0, but it doesn't work right when innerRadius is set to 0.<br />
+		innerRadius — Default is 20. <br />
 		outerRadius — Default is 50. <br />
 		outerRadius — Default is 50. <br />
 		thetaSegments — Number of segments.  A higher number means the ring will be more round.  Minimum is 3.  Default is 8. <br />
 		thetaSegments — Number of segments.  A higher number means the ring will be more round.  Minimum is 3.  Default is 8. <br />
 		phiSegments — Minimum is 1.  Default is 8.<br />
 		phiSegments — Minimum is 1.  Default is 8.<br />

+ 161 - 0
docs/api/geometries/TextBufferGeometry.html

@@ -0,0 +1,161 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:ExtrudeBufferGeometry] &rarr;
+
+		<h1>[name]</h1>
+
+		<div class="desc">
+			A class for generating text as a single geometry. It is constructed by providing a string of text, and a hash of
+			parameters consisting of a loaded [page:Font] and settings for the geometry's parent [page:ExtrudeBufferGeometry].
+			See the [page:Font], [page:FontLoader] and [page:Creating_Text] pages for additional details.
+		</div>
+
+		<iframe id="scene" src="scenes/geometry-browser.html#TextBufferGeometry"></iframe>
+
+		<script>
+
+		// iOS iframe auto-resize workaround
+
+		if ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) {
+
+			var scene = document.getElementById( 'scene' );
+
+			scene.style.width = getComputedStyle( scene ).width;
+			scene.style.height = getComputedStyle( scene ).height;
+			scene.setAttribute( 'scrolling', 'no' );
+
+		}
+
+		</script>
+
+		<h2>Examples</h2>
+
+		<div>
+		[example:webgl_geometry_text geometry / text ]<br/>
+		[example:webgl_geometry_text2 geometry / text2 ]
+		</div>
+
+		<code>
+		var loader = new THREE.FontLoader();
+
+		loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) {
+
+			var geometry = new THREE.TextBufferGeometry( 'Hello three.js!', {
+				font: font,
+				size: 80,
+				height: 5,
+				curveSegments: 12,
+				bevelEnabled: true,
+				bevelThickness: 10,
+				bevelSize: 8,
+				bevelSegments: 5
+			} );
+		} );
+		</code>
+
+		<h2>Constructor</h2>
+
+		<h3>[name]([page:String text], [page:Object parameters])</h3>
+		<div>
+		text — The text that needs to be shown. <br />
+		parameters — Object that can contains the following parameters.
+		<ul>
+			<li>font — an instance of THREE.Font.</li>
+			<li>size — Float. Size of the text. Default is 100.</li>
+			<li>height — Float. Thickness to extrude text.  Default is 50.</li>
+			<li>curveSegments — Integer. Number of points on the curves. Default is 12.</li>
+			<li>bevelEnabled — Boolean. Turn on bevel. Default is False.</li>
+			<li>bevelThickness — Float. How deep into text bevel goes. Default is 10.</li>
+			<li>bevelSize — Float. How far from text outline is bevel. Default is 8.</li>
+			<li>bevelSegments — Integer. Number of bevel segments. Default is 3.</li>
+		</ul>
+		</div>
+
+		<h2>Available Fonts</h2>
+
+		<div>
+		TextGeometry uses <a href='http://gero3.github.io/facetype.js/' target="_top">typeface.json</a> generated fonts.
+		Some existing fonts can be found located in <b>/examples/fonts</b> and must be included in the page.
+		</div>
+		<table>
+			<tr>
+				<th>Font</th>
+				<th>Weight</th>
+				<th>Style</th>
+				<th>File Path</th>
+			</tr>
+			<tr>
+				<td>helvetiker</td>
+				<td>normal</td>
+				<td>normal</td>
+				<td>/examples/fonts/helvetiker_regular.typeface.json</td>
+			</tr>
+			<tr>
+				<td>helvetiker</td>
+				<td>bold</td>
+				<td>normal</td>
+				<td>/examples/fonts/helvetiker_bold.typeface.json</td>
+			</tr>
+			<tr>
+				<td>optimer</td>
+				<td>normal</td>
+				<td>normal</td>
+				<td>/examples/fonts/optimer_regular.typeface.json</td>
+			</tr>
+			<tr>
+				<td>optimer</td>
+				<td>bold</td>
+				<td>normal</td>
+				<td>/examples/fonts/optimer_bold.typeface.json</td>
+			</tr>
+			<tr>
+				<td>gentilis</td>
+				<td>normal</td>
+				<td>normal</td>
+				<td>/examples/fonts/gentilis_regular.typeface.json</td>
+			</tr>
+			<tr>
+				<td>gentilis</td>
+				<td>bold</td>
+				<td>normal</td>
+				<td>/examples/fonts/gentilis_bold.typeface.json</td>
+			</tr>
+			<tr>
+				<td>droid sans</td>
+				<td>normal</td>
+				<td>normal</td>
+				<td>/examples/fonts/droid/droid_sans_regular.typeface.json</td>
+			</tr>
+			<tr>
+				<td>droid sans</td>
+				<td>bold</td>
+				<td>normal</td>
+				<td>/examples/fonts/droid/droid_sans_bold.typeface.json</td>
+			</tr>
+			<tr>
+				<td>droid serif</td>
+				<td>normal</td>
+				<td>normal</td>
+				<td>/examples/fonts/droid/droid_serif_regular.typeface.json</td>
+			</tr>
+			<tr>
+				<td>droid serif</td>
+				<td>bold</td>
+				<td>normal</td>
+				<td>/examples/fonts/droid/droid_serif_bold.typeface.json</td>
+			</tr>
+		</table>
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 12 - 4
docs/api/helpers/DirectionalLightHelper.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html lang="en">
 <html lang="en">
 	<head>
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="list.js"></script>
 		<script src="page.js"></script>
 		<script src="page.js"></script>
@@ -32,10 +32,13 @@
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]( [page:DirectionalLight light], [page:Number size] )</h3>
+		<h3>[name]( [page:DirectionalLight light], [page:Number size], [page:Hex color] )</h3>
 		<div>
 		<div>
-		[page:DirectionalLight light]-- The light to be visualized. <br />
-		[page:Number size] -- (optional) dimensions of the plane. Default is *1*.<br /><br />
+			[page:DirectionalLight light]-- The light to be visualized. <br /><br />
+
+			[page:Number size] -- (optional) dimensions of the plane. Default is *1*.<br /><br />
+			
+			[page:Hex color] -- (optional) if this is not the set the helper will take the color of the light.
 		</div>
 		</div>
 
 
 
 
@@ -58,6 +61,11 @@
 			light's [page:Object3D.matrixWorld matrixWorld].
 			light's [page:Object3D.matrixWorld matrixWorld].
 		</div>
 		</div>
 
 
+		<h3>[property:hex color]</h3>
+		<div>
+			The color parameter passed in the constructor. Default is *undefined*. If this is changed, 
+			the helper's color will update the next time [page:.update update] is called.
+		</div>
 
 
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>

+ 13 - 4
docs/api/helpers/HemisphereLightHelper.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html lang="en">
 <html lang="en">
 	<head>
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="list.js"></script>
 		<script src="page.js"></script>
 		<script src="page.js"></script>
@@ -29,10 +29,13 @@ scene.add( helper );
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
-		<h3>[name]([page:HemisphereLight light], [page:Number sphereSize])</h3>
+		<h3>[name]( [page:HemisphereLight light], [page:Number sphereSize], [page:Hex color] )</h3>
 		<div>
 		<div>
-		[page:HemisphereLight light] -- The light being visualized. <br />
-		[page:Number size] -- The size of the mesh used to visualize the light.
+			[page:HemisphereLight light] -- The light being visualized. <br /><br />
+
+			[page:Number size] -- The size of the mesh used to visualize the light.<br /><br />
+			
+			[page:Hex color] -- (optional) if this is not the set the helper will take the color of the light.
 		</div>
 		</div>
 
 
 
 
@@ -51,6 +54,12 @@ scene.add( helper );
 			hemisphereLight's [page:Object3D.matrixWorld matrixWorld].
 			hemisphereLight's [page:Object3D.matrixWorld matrixWorld].
 		</div>
 		</div>
 
 
+		<h3>[property:hex color]</h3>
+		<div>
+			 The color parameter passed in the constructor. Default is *undefined*. If this is changed, the helper's color will update
+			the next time [page:.update update] is called.
+		</div>
+
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 		<div>See the base [page:Object3D] class for common methods.</div>
 		<div>See the base [page:Object3D] class for common methods.</div>

+ 13 - 6
docs/api/helpers/PointLightHelper.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html lang="en">
 <html lang="en">
 	<head>
 	<head>
-		<meta charset="utf-8" />
+		<meta charset="utf-8" />
 		<base href="../../" />
 		<base href="../../" />
 		<script src="list.js"></script>
 		<script src="list.js"></script>
 		<script src="page.js"></script>
 		<script src="page.js"></script>
@@ -37,12 +37,14 @@
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
-		<h3>[name]( [page:PointLight light], [page:Float sphereSize] )</h3>
+		<h3>[name]( [page:PointLight light], [page:Float sphereSize], [page:Hex color] )</h3>
 		<div>
 		<div>
-		[page:PointLight light] -- The light to be visualized. <br />
-		 [page:Float sphereSize] -- (optional) The size of the sphere helper. Default is *1*.
-		</div>
+		[page:PointLight light] -- The light to be visualized. <br /><br />
+
+		[page:Float sphereSize] -- (optional) The size of the sphere helper. Default is *1*.<br /><br />
 
 
+		[page:Hex color] -- (optional) if this is not the set the helper will take the color of the light.
+		</div>
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
 		<div>See the base [page:Mesh] class for common properties.</div>
 		<div>See the base [page:Mesh] class for common properties.</div>
@@ -59,7 +61,12 @@
 			pointLight's [page:Object3D.matrixWorld matrixWorld].
 			pointLight's [page:Object3D.matrixWorld matrixWorld].
 		</div>
 		</div>
 
 
-
+		<h3>[property:hex color]</h3>
+		<div>
+			 The color parameter passed in the constructor. Default is *undefined*. If this is changed, the helper's color will update
+			the next time [page:.update update] is called.
+		</div>
+		
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 		<div>See the base [page:Mesh] class for common methods.</div>
 		<div>See the base [page:Mesh] class for common methods.</div>
 
 

+ 12 - 2
docs/api/helpers/RectAreaLightHelper.html

@@ -29,8 +29,12 @@ scene.add( helper );
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
-		<h3>[name]( [page:RectAreaLight light] )</h3>
-		<div>[page:RectAreaLight light] -- The light being visualized.</div>
+		<h3>[name]( [page:RectAreaLight light], [page:Hex color] )</h3>
+		<div>
+			[page:RectAreaLight light] -- The light being visualized.<br /><br />
+
+			[page:Hex color] -- (optional) if this is not the set the helper will take the color of the light.
+		</div>
 
 
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
@@ -39,6 +43,12 @@ scene.add( helper );
 		<h3>[property:RectAreaLight light]</h3>
 		<h3>[property:RectAreaLight light]</h3>
 		<div>Reference to the RectAreaLight being visualized.</div>
 		<div>Reference to the RectAreaLight being visualized.</div>
 
 
+		<h3>[property:hex color]</h3>
+		<div>
+						 The color parameter passed in the constructor. Default is *undefined*. If this is changed, the helper's color will update
+						the next time [page:.update update] is called.
+		</div>
+
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 		<div>See the base [page:Object3D] class for common methods.</div>
 		<div>See the base [page:Object3D] class for common methods.</div>

+ 11 - 3
docs/api/helpers/SpotLightHelper.html

@@ -35,8 +35,12 @@
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:SpotLight light])</h3>
-		<div>light -- The [page:SpotLight] to be visualized.</div>
+		<h3>[name]( [page:SpotLight light], [page:Hex color] )</h3>
+		<div>
+			[page:SpotLight light] -- The [page:SpotLight] to be visualized. <br /><br/>
+			
+			[page:Hex color] -- (optional) if this is not the set the helper will take the color of the light. 
+		</div>
 
 
 
 
 		<h2>Properties</h2>
 		<h2>Properties</h2>
@@ -45,7 +49,6 @@
 		<h3>[property:LineSegments cone]</h3>
 		<h3>[property:LineSegments cone]</h3>
 		<div>[page:LineSegments] used to visualize the light.</div>
 		<div>[page:LineSegments] used to visualize the light.</div>
 
 
-
 		<h3>[property:SpotLight light]</h3>
 		<h3>[property:SpotLight light]</h3>
 		<div>Reference to the [page:SpotLight] being visualized.</div>
 		<div>Reference to the [page:SpotLight] being visualized.</div>
 
 
@@ -58,6 +61,11 @@
 			spotLight's [page:Object3D.matrixWorld matrixWorld].
 			spotLight's [page:Object3D.matrixWorld matrixWorld].
 		</div>
 		</div>
 
 
+		<h3>[property:hex color]</h3>
+		<div>
+					 The color parameter passed in the constructor. Default is *undefined*. If this is changed, the helper's color will update
+					the next time [page:.update update] is called.
+		</div>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 		<div>See the base [page:Object3D] class for common methods.</div>
 		<div>See the base [page:Object3D] class for common methods.</div>

+ 14 - 7
docs/api/materials/Material.html

@@ -84,7 +84,7 @@
 		<div>
 		<div>
 		User-defined clipping planes specified as THREE.Plane objects in world space.
 		User-defined clipping planes specified as THREE.Plane objects in world space.
 		These planes apply to the objects this material is attached to.
 		These planes apply to the objects this material is attached to.
-		Points in space whose dot product with the plane is negative are cut away.
+		Points in space whose signed distance to the plane is negative are clipped (not rendered).
 		See the [example:webgl_clipping_intersection WebGL / clipping /intersection] example.
 		See the [example:webgl_clipping_intersection WebGL / clipping /intersection] example.
 		Default is *null*.
 		Default is *null*.
 		</div>
 		</div>
@@ -102,12 +102,15 @@
 
 
 		<h3>[property:Material customDepthMaterial]</h3>
 		<h3>[property:Material customDepthMaterial]</h3>
 		<div>
 		<div>
-		Custom depth material to be used by this material in depth based computation. If a material uses any custom logic to position the vertices (animation, displacement other than the default texture based, instancing...) the depth material should also include that logic in order to make effects like shadows and SSAO work. Defining this property allows the WebGLRenderer to use this instance of the material instead of the internal cache. Default is *undefined*.
+		Custom depth material to be used by this material when rendering to the depth map.
+		When shadow-casting with a [page:DirectionalLight] or [page:SpotLight], if you are (a) modifying vertex positions in the vertex shader,
+		(b) using a displacement map, (c) using an alpha map with alphaTest, or (d) using a transparent texture with alphaTest,
+		you must specify a customDepthMaterial for proper shadows. Default is *undefined*.
 		</div>
 		</div>
 		
 		
 		<h3>[property:Material customDistanceMaterial]</h3>
 		<h3>[property:Material customDistanceMaterial]</h3>
 		<div>
 		<div>
-		Same as customDepthMaterial but used for specific computation (point lights for example). Default is *undefined*
+		Same as customDepthMaterial, but used with [page:PointLight]. Default is *undefined*.
 		</div>
 		</div>
 		
 		
 		<h3>[property:Object defines]</h3>
 		<h3>[property:Object defines]</h3>
@@ -204,10 +207,9 @@
 		Default is *false*.
 		Default is *false*.
 		</div>
 		</div>
 
 
-		<h3>[property:Integer shading]</h3>
+		<h3>[property:Boolean flatShading]</h3>
 		<div>
 		<div>
-		Defines how the material is shaded.
-		This can be either [page:Materials THREE.SmoothShading] (default)	or [page:Materials THREE.FlatShading].
+		Define whether the material is rendered with flat shading. Default is false.
 		</div>
 		</div>
 
 
 		<h3>[property:Integer side]</h3>
 		<h3>[property:Integer side]</h3>
@@ -250,7 +252,12 @@
 		<div>
 		<div>
 		Defines whether this material is visible. Default is *true*.
 		Defines whether this material is visible. Default is *true*.
 		</div>
 		</div>
-
+		
+		<h3>[property:object userData]</h3>
+		<div>
+		An object that can be used to store custom data about the Material. It should not hold
+		references to functions as these will not be cloned.
+		</div>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 

+ 5 - 1
docs/api/materials/MeshBasicMaterial.html

@@ -117,7 +117,11 @@
 		</div>
 		</div>
 
 
 		<h3>[property:Float refractionRatio]</h3>
 		<h3>[property:Float refractionRatio]</h3>
-		<div>The index of refraction for an environment map using [page:Textures THREE.CubeRefractionMapping]. Default is *0.98*.</div>
+		<div>
+			The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material.
+			It is used with environment mapping modes [page:Textures THREE.CubeRefractionMapping] and [page:Textures THREE.EquirectangularRefractionMapping].
+			The refraction ratio should not exceed 1. Default is *0.98*.
+		</div>
 
 
 		<h3>[property:Boolean skinning]</h3>
 		<h3>[property:Boolean skinning]</h3>
 		<div>Define whether the material uses skinning. Default is false.</div>
 		<div>Define whether the material uses skinning. Default is false.</div>

+ 7 - 3
docs/api/materials/MeshLambertMaterial.html

@@ -15,8 +15,8 @@
 		<div class="desc">
 		<div class="desc">
 			A material for non-shiny surfaces, without specular highlights.<br /><br />
 			A material for non-shiny surfaces, without specular highlights.<br /><br />
 
 
-			The uses a non-physically based [link:https://en.wikipedia.org/wiki/Lambertian_reflectance Lambertian]
-			model	for calculating reflectance. This can simulate some surfaces (such as untreated wood or stone) well,
+			The material uses a non-physically based [link:https://en.wikipedia.org/wiki/Lambertian_reflectance Lambertian]
+			model for calculating reflectance. This can simulate some surfaces (such as untreated wood or stone) well,
 			but cannot simulate shiny surfaces with specular highlights (such as varnished wood).<br /><br />
 			but cannot simulate shiny surfaces with specular highlights (such as varnished wood).<br /><br />
 
 
 
 
@@ -143,7 +143,11 @@
 		<div>How much the environment map affects the surface; also see [page:.combine].</div>
 		<div>How much the environment map affects the surface; also see [page:.combine].</div>
 
 
 		<h3>[property:Float refractionRatio]</h3>
 		<h3>[property:Float refractionRatio]</h3>
-		<div>The index of refraction for an environment map using [page:Textures THREE.CubeRefractionMapping]. Default is *0.98*.</div>
+		<div>
+			The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material.
+			It is used with environment mapping modes [page:Textures THREE.CubeRefractionMapping] and [page:Textures THREE.EquirectangularRefractionMapping].
+			The refraction ratio should not exceed 1. Default is *0.98*.
+		</div>
 
 
 		<h3>[property:Boolean skinning]</h3>
 		<h3>[property:Boolean skinning]</h3>
 		<div>Define whether the material uses skinning. Default is false.</div>
 		<div>Define whether the material uses skinning. Default is false.</div>

+ 7 - 3
docs/api/materials/MeshPhongMaterial.html

@@ -15,8 +15,8 @@
 		<div class="desc">
 		<div class="desc">
 			A material for shiny surfaces with specular highlights.<br /><br />
 			A material for shiny surfaces with specular highlights.<br /><br />
 
 
-			The uses a non-physically based [link:https://en.wikipedia.org/wiki/Blinn-Phong_shading_model Blinn-Phong]
-			model	for calculating reflectance. Unlike the Lambertian model used in the [page:MeshLambertMaterial]
+			The material uses a non-physically based [link:https://en.wikipedia.org/wiki/Blinn-Phong_shading_model Blinn-Phong]
+			model for calculating reflectance. Unlike the Lambertian model used in the [page:MeshLambertMaterial]
 			this can simulate shiny surfaces with specular highlights (such as varnished wood).<br /><br />
 			this can simulate shiny surfaces with specular highlights (such as varnished wood).<br /><br />
 
 
 			Shading is calculated using a [link:https://en.wikipedia.org/wiki/Phong_shading Phong] shading model.
 			Shading is calculated using a [link:https://en.wikipedia.org/wiki/Phong_shading Phong] shading model.
@@ -192,7 +192,11 @@
 		</div>
 		</div>
 
 
 		<h3>[property:Float refractionRatio]</h3>
 		<h3>[property:Float refractionRatio]</h3>
-		<div>The index of refraction for an environment map using [page:Textures THREE.CubeRefractionMapping]. Default is *0.98*.</div>
+		<div>
+			The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material.
+			It is used with environment mapping modes [page:Textures THREE.CubeRefractionMapping] and [page:Textures THREE.EquirectangularRefractionMapping].
+			The refraction ratio should not exceed 1. Default is *0.98*.
+		</div>
 
 
 		<h3>[property:Float shininess]</h3>
 		<h3>[property:Float shininess]</h3>
 		<div>How shiny the [page:.specular] highlight is; a higher value gives a sharper highlight. Default is *30*.</div>
 		<div>How shiny the [page:.specular] highlight is; a higher value gives a sharper highlight. Default is *30*.</div>

+ 5 - 1
docs/api/materials/MeshStandardMaterial.html

@@ -226,7 +226,11 @@
 		</div>
 		</div>
 
 
 		<h3>[property:Float refractionRatio]</h3>
 		<h3>[property:Float refractionRatio]</h3>
-		<div>The index of refraction for an environment map using [page:Textures THREE.CubeRefractionMapping]. Default is *0.98*.</div>
+		<div>
+			The index of refraction (IOR) of air (approximately 1) divided by the index of refraction of the material.
+			It is used with environment mapping modes [page:Textures THREE.CubeRefractionMapping] and [page:Textures THREE.EquirectangularRefractionMapping].
+			The refraction ratio should not exceed 1. Default is *0.98*.
+		</div>
 
 
 		<h3>[property:Float roughness]</h3>
 		<h3>[property:Float roughness]</h3>
 		<div>
 		<div>

+ 2 - 2
docs/api/materials/PointsMaterial.html

@@ -44,11 +44,11 @@ for ( var i = 0; i < 10000; i ++ ) {
 	star.y = THREE.Math.randFloatSpread( 2000 );
 	star.y = THREE.Math.randFloatSpread( 2000 );
 	star.z = THREE.Math.randFloatSpread( 2000 );
 	star.z = THREE.Math.randFloatSpread( 2000 );
 
 
-	starsGeometry.vertices.push( star )
+	starsGeometry.vertices.push( star );
 
 
 }
 }
 
 
-var starsMaterial = new THREE.PointsMaterial( { color: 0x888888 } )
+var starsMaterial = new THREE.PointsMaterial( { color: 0x888888 } );
 
 
 var starField = new THREE.Points( starsGeometry, starsMaterial );
 var starField = new THREE.Points( starsGeometry, starsMaterial );
 
 

+ 5 - 6
docs/api/materials/ShaderMaterial.html

@@ -14,7 +14,7 @@
 
 
 		<div class="desc">
 		<div class="desc">
 			A material rendered with custom shaders. A shader is a small program written in
 			A material rendered with custom shaders. A shader is a small program written in
-			[link:https://www.khronos.org/files/opengles_shading_language.pdf_ES GLSL] that runs on the GPU.
+			[link:https://www.khronos.org/files/opengles_shading_language.pdf GLSL] that runs on the GPU.
 			You may want to use a custom shader if you need to:
 			You may want to use a custom shader if you need to:
 		<ul>
 		<ul>
 			<li>implement an effect not included with any of the built-in [page:Material materials]</li>
 			<li>implement an effect not included with any of the built-in [page:Material materials]</li>
@@ -40,7 +40,7 @@
 				must be used instead.
 				must be used instead.
 			</li>
 			</li>
 			<li>
 			<li>
-				Built in attributes an uniforms are passed to the shaders along with your code.
+				Built in attributes and uniforms are passed to the shaders along with your code.
 				If you don't want the [page:WebGLProgram] to add anything to your shader code, you can use
 				If you don't want the [page:WebGLProgram] to add anything to your shader code, you can use
 				[page:RawShaderMaterial] instead of this class.
 				[page:RawShaderMaterial] instead of this class.
 			</li>
 			</li>
@@ -296,7 +296,7 @@ this.defaultAttributeValues = {
 
 
 		<h3>[property:Object extensions]</h3>
 		<h3>[property:Object extensions]</h3>
 		<div>
 		<div>
-		An object with the folowing properties:
+		An object with the following properties:
 		<code>
 		<code>
 this.extensions = {
 this.extensions = {
 	derivatives: false, // set to use derivatives
 	derivatives: false, // set to use derivatives
@@ -371,10 +371,9 @@ this.extensions = {
 		You should not need to access this property.
 		You should not need to access this property.
 		</div>
 		</div>
 
 
-		<h3>[property:Number shading]</h3>
+		<h3>[property:Boolean flatShading]</h3>
 		<div>
 		<div>
-		Define shading type, which determines whether normals are smoothed between vertices;
-		possible values are [page:Materials THREE.SmoothShading] or [page:Materials THREE.FlatShading]. Default is THREE.SmoothShading.
+		Define whether the material is rendered with flat shading. Default is false.
 		</div>
 		</div>
 
 
 
 

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

@@ -260,7 +260,7 @@ xAxis.z, yAxis.z, zAxis.z, 0,
 		[link:https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion here].
 		[link:https://en.wikipedia.org/wiki/Rotation_matrix#Quaternion here].
 		The rest of the matrix is set to the identity. So, given [page:Quaternion q] = w + xi + yj + zk, the resulting matrix will be:
 		The rest of the matrix is set to the identity. So, given [page:Quaternion q] = w + xi + yj + zk, the resulting matrix will be:
 		<code>
 		<code>
-1-2y²-2z²    2xy-2zw    2xz-2yw    0
+1-2y²-2z²    2xy-2zw    2xz+2yw    0
 2xy+2zw      1-2x²-2z²  2yz-2xw    0
 2xy+2zw      1-2x²-2z²  2yz-2xw    0
 2xz-2yw      2yz+2xw    1-2x²-2y²  0
 2xz-2yw      2yz+2xw    1-2x²-2y²  0
 0            0          0          1
 0            0          0          1

+ 19 - 37
docs/api/math/Plane.html

@@ -11,9 +11,8 @@
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
 		<div class="desc">
 		<div class="desc">
-			A two dimensional surface that extends infinitely in 3d space, defined by
-			a [link:https://en.wikipedia.org/wiki/Normal_(geometry) normal vector], and a
-			distance from the origin along the normal.
+			A two dimensional surface that extends infinitely in 3d space, represented in [link:http://mathworld.wolfram.com/HessianNormalForm.html Hessian normal form]
+			by a unit length normal vector and a constant.
 		</div>
 		</div>
 
 
 
 
@@ -22,10 +21,8 @@
 
 
 		<h3>[name]( [page:Vector3 normal], [page:Float constant] )</h3>
 		<h3>[name]( [page:Vector3 normal], [page:Float constant] )</h3>
 		<div>
 		<div>
-		[page:Vector3 normal] - (optional) a [page:Vector3] defining the direction of the
-		plane. Default is *(1, 0, 0)*.<br />
-		[page:Float constant] - (optional) the negative distance from the origin to the plane along
-		 the [page:Vector3 normal] vector. Default is *0*.
+		[page:Vector3 normal] - (optional) a unit length [page:Vector3] defining the normal of the plane. Default is *(1, 0, 0)*.<br />
+		[page:Float constant] - (optional) the signed distance from the origin to the plane. Default is *0*.
 		</div>
 		</div>
 
 
 
 
@@ -68,10 +65,10 @@
 		</div>
 		</div>
 
 
 		<h3>[method:Float distanceToPoint]( [page:Vector3 point] )</h3>
 		<h3>[method:Float distanceToPoint]( [page:Vector3 point] )</h3>
-		<div>Returns the smallest distance from the [page:Vector3 point] to the plane.</div>
+		<div>Returns the signed distance from the [page:Vector3 point] to the plane.</div>
 
 
 		<h3>[method:Float distanceToSphere]( [page:Sphere sphere] )</h3>
 		<h3>[method:Float distanceToSphere]( [page:Sphere sphere] )</h3>
-		<div>Returns the smallest distance from the [page:Sphere sphere] to the plane.</div>
+		<div>Returns the signed distance from the [page:Sphere sphere] to the plane.</div>
 
 
 		<h3>[method:Boolean equals]( [page:Plane plane] )</h3>
 		<h3>[method:Boolean equals]( [page:Plane plane] )</h3>
 		<div>
 		<div>
@@ -113,8 +110,7 @@
 
 
 		<h3>[method:Plane negate]()</h3>
 		<h3>[method:Plane negate]()</h3>
 		<div>
 		<div>
-		Negates both the normal vector and constant, effectively mirroring the plane across
-		the origin.
+		Negates both the normal vector and the constant.
 		</div>
 		</div>
 
 
 		<h3>[method:Plane normalize]()</h3>
 		<h3>[method:Plane normalize]()</h3>
@@ -123,44 +119,31 @@
 			value accordingly.
 			value accordingly.
 		</div>
 		</div>
 
 
-		<h3>[method:Vector3 orthoPoint]( [page:Vector3 point], [page:Vector3 optionalTarget] )</h3>
-		<div>
-		[page:Vector3 point] - [page:Vector3] <br />
-		[page:Vector3 optionalTarget] - (optional) if specified, the result will be copied
-		into this [page:Vector3], otherwise a new [page:Vector3] will be created.<br /><br />
-
-		Returns a vector in the same direction as the Plane's normal, but with magnitude
-		equal to the passed point's original distance to the plane.
-		</div>
-
 		<h3>[method:Vector3 projectPoint]( [page:Vector3 point], [page:Vector3 optionalTarget] )</h3>
 		<h3>[method:Vector3 projectPoint]( [page:Vector3 point], [page:Vector3 optionalTarget] )</h3>
 		<div>
 		<div>
 		[page:Vector3 point] - the [page:Vector3] to project onto the plane.<br />
 		[page:Vector3 point] - the [page:Vector3] to project onto the plane.<br />
 		[page:Vector3 optionalTarget] - (optional) if specified, the result will be copied into this [page:Vector3],
 		[page:Vector3 optionalTarget] - (optional) if specified, the result will be copied into this [page:Vector3],
 		otherwise a new [page:Vector3] will be created.<br /><br />
 		otherwise a new [page:Vector3] will be created.<br /><br />
 
 
-		Projects a [page:Vector3 point] onto the plane. The projected point is the closest
-		 point on the plane to the passed point, so a line drawn from the projected point
-		 and the passed point would be orthogonal to the plane.
+		Projects a [page:Vector3 point] onto the plane.
 		</div>
 		</div>
 
 
 		<h3>[method:Plane set]( [page:Vector3 normal], [page:Float constant] )</h3>
 		<h3>[method:Plane set]( [page:Vector3 normal], [page:Float constant] )</h3>
 		<div>
 		<div>
-			[page:Vector3 normal] -  a [page:Vector3] defining the direction of the	plane.<br />
-			[page:Float constant] - (optional) the negative distance from the origin to the plane along
-			 the [page:Vector3 normal] vector. Default is *0*.<br /><br />
+			[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 the plane's [page:.normal normal] and [page:.constant constant] properties.
 		</div>
 		</div>
 
 
 		<h3>[method:Plane setComponents]( [page:Float x], [page:Float y], [page:Float z], [page:Float w] )</h3>
 		<h3>[method:Plane setComponents]( [page:Float x], [page:Float y], [page:Float z], [page:Float w] )</h3>
 		<div>
 		<div>
-		[page:Float x] - x value of the normal vector.<br />
-		[page:Float y] - y value of the normal vector.<br />
-		[page:Float z] - z value of the normal vector.<br />
+		[page:Float x] - x value of the unit length normal vector.<br />
+		[page:Float y] - y value of the unit length normal vector.<br />
+		[page:Float z] - z value of the unit length normal vector.<br />
 		[page:Float w] - the value of the plane's [page:.constant constant] property.<br /><br />
 		[page:Float w] - the value of the plane's [page:.constant constant] property.<br /><br />
 
 
-		Set the individual components that make up the plane.
+		Set the individual components that define the plane.
 		</div>
 		</div>
 
 
 		<h3>[method:Plane setFromCoplanarPoints]( [page:Vector3 a], [page:Vector3 b], [page:Vector3 c] )</h3>
 		<h3>[method:Plane setFromCoplanarPoints]( [page:Vector3 a], [page:Vector3 b], [page:Vector3 c] )</h3>
@@ -169,13 +152,13 @@
 		 [page:Vector3 a] - second point on the plane.<br />
 		 [page:Vector3 a] - second point on the plane.<br />
 		 [page:Vector3 a] - third point on the plane.<br /><br />
 		 [page:Vector3 a] - third point on the plane.<br /><br />
 
 
-		Defines the plane based on the 3 provided points. The winding order is counter
-		clockwise, and determines which direction the [page:.normal normal] will point.
+		Defines the plane based on the 3 provided points. The winding order is assumed to be counter-clockwise,
+		and determines the direction of the [page:.normal normal].
 		</div>
 		</div>
 
 
 		<h3>[method:Plane setFromNormalAndCoplanarPoint]( [page:Vector3 normal], [page:Vector3 point] ) [page:Vector3 this]</h3>
 		<h3>[method:Plane setFromNormalAndCoplanarPoint]( [page:Vector3 normal], [page:Vector3 point] ) [page:Vector3 this]</h3>
 		<div>
 		<div>
-		[page:Vector3 normal] - a [page:Vector3] defining the direction of the plane.<br />
+		[page:Vector3 normal] - a unit length [page:Vector3] defining the normal of the plane.<br />
 		[page:Vector3 point] - [page:Vector3]<br /><br />
 		[page:Vector3 point] - [page:Vector3]<br /><br />
 
 
 		Sets the plane's properties as defined by a [page:Vector3 normal] and an arbitrary coplanar [page:Vector3 point].
 		Sets the plane's properties as defined by a [page:Vector3 normal] and an arbitrary coplanar [page:Vector3 point].
@@ -185,9 +168,8 @@
 		<div>
 		<div>
 		[page:Vector3 offset] - the amount to move the plane by.<br /><br />
 		[page:Vector3 offset] - the amount to move the plane by.<br /><br />
 
 
-		Translates the plane the distance defined by the [page:Vector3 offset] vector.
-		Note that this only affects	the constant (distance from origin) and will not affect
-		the normal vector.
+		Translates the plane by the distance defined by the [page:Vector3 offset] vector.
+		Note that this only affects the plane constant and will not affect the normal vector.
 		</div>
 		</div>
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>

+ 2 - 2
docs/api/objects/Group.html

@@ -13,7 +13,7 @@
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
 		<div class="desc">
 		<div class="desc">
-			This is almost identical to an [page:Object3D Object3D]. It's purpose is to make working
+			This is almost identical to an [page:Object3D Object3D]. Its purpose is to make working
 			with groups of objects syntactically clearer.
 			with groups of objects syntactically clearer.
 		</div>
 		</div>
 
 
@@ -28,7 +28,7 @@
 		cubeA.position.set( 100, 100, 0 );
 		cubeA.position.set( 100, 100, 0 );
 
 
 		var cubeB = new THREE.Mesh( geometry, material );
 		var cubeB = new THREE.Mesh( geometry, material );
-		cubeA.position.set( -100, -100, 0 );
+		cubeB.position.set( -100, -100, 0 );
 
 
 		//create a group and add the two cubes
 		//create a group and add the two cubes
 		//These cubes can now be rotated / scaled etc as a group
 		//These cubes can now be rotated / scaled etc as a group

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

@@ -14,7 +14,7 @@
 
 
 		<div class="desc">
 		<div class="desc">
 			Class representing triangular [link:https://en.wikipedia.org/wiki/Polygon_mesh polygon mesh] based objects.
 			Class representing triangular [link:https://en.wikipedia.org/wiki/Polygon_mesh polygon mesh] based objects.
-		  Also serves as a base for other classes such as [page:MorphBlendMesh] and [page:SkinnedMesh].
+		  Also serves as a base for other classes such as [page:SkinnedMesh].
 		</div>
 		</div>
 
 
 
 

+ 133 - 133
docs/api/renderers/WebGLRenderTarget.html

@@ -1,134 +1,134 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
+<!DOCTYPE html>
+<html lang="en">
+	<head>
 		<meta charset="utf-8" />
 		<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>
-
-		<div class="desc">
-			A [link:https://msdn.microsoft.com/en-us/library/bb976073.aspx render target] is a buffer
-			where the video card draws pixels for a scene that	is being rendered in the background.
-			It is used in different effects, such as applying postprocessing to a rendered image
-			before displaying it on the screen.
-		</div>
-
-
-		<h2>Constructor</h2>
-
-
-		<h3>[name]([page:Number width], [page:Number height], [page:Object options])</h3>
-
-		<div>
-		[page:Float width] - The width of the renderTarget. <br />
-		[page:Float height] - The height of the renderTarget.<br />
-		options - (optional0 object that holds texture parameters for an auto-generated target
-		texture and depthBuffer/stencilBuffer booleans.
-
-		For an explanation of the texture parameters see [page:Texture Texture]. The following are
-		valid options:<br /><br />
-
-		[page:Constant wrapS] - default is [page:Textures ClampToEdgeWrapping]. <br />
-		[page:Constant wrapT] - default is [page:Textures ClampToEdgeWrapping]. <br />
-		[page:Constant magFilter] - default is [page:Textures .LinearFilter]. <br />
-		[page:Constant minFilter] - default is [page:Textures LinearFilter]. <br />
-		[page:Constant format] - default is [page:Textures RGBAFormat]. <br />
-		[page:Constant type] - default is [page:Textures UnsignedByteType]. <br />
-		[page:Number anisotropy] - default is *1*. See [page:Texture.anistropy]<br />
-		[page:Constant encoding] - default is [page:Textures LinearEncoding]. <br />
-		[page:Boolean depthBuffer] - default is *true*. Set this to false if you don't need it. <br />
-		[page:Boolean stencilBuffer] - default is *true*. Set this to false if you don't need it.<br /><br />
-
-		Creates a new [name]]
-		</div>
-
-		<h2>Properties</h2>
-
-		<h3>[property:number uuid]</h3>
-		<div>
-		A unique number for this render target instance.
-		</div>
-
-		<h3>[property:number width]</h3>
-		<div>
-		The width of the render target.
-		</div>
-
-		<h3>[property:number height]</h3>
-		<div>
-		The height of the render target.
-		</div>
-
-		<h3>[property:Vector4 scissor]</h3>
-		<div>
-		A rectangular area inside the render target's viewport. Fragments that are outside the area will be discarded.
-		</div>
-
-		<h3>[property:boolean scissorTest]</h3>
-		<div>
-		Indicates whether the scissor test is active or not.
-		</div>
-
-		<h3>[property:Vector4 viewport]</h3>
-		<div>
-		The viewport of this render target.
-		</div>
-
-		<h3>[property:Texture texture]</h3>
-		<div>
-		This texture instance holds the rendered pixels. Use it as input for further processing.
-		</div>
-
-		<h3>[property:boolean depthBuffer]</h3>
-		<div>
-		Renders to the depth buffer. Default is true.
-		</div>
-
-		<h3>[property:boolean stencilBuffer]</h3>
-		<div>
-		Renders to the stencil buffer. Default is true.
-		</div>
-
-		<h3>[property:DepthTexture depthTexture]</h3>
-		<div>
-		If set, the scene depth will be rendered to this texture. Default is null.
-		</div>
-
-
-		<h2>Methods</h2>
-
-		<h3>[method:null setSize]( [page:Number width], [page:Number height] )</h3>
-		<div>
-		Sets the size of the render target.
-		</div>
-
-		<h3>[method:WebGLRenderTarget clone]()</h3>
-		<div>
-		Creates a copy of this render target.
-		</div>
-
-		<h3>[method:WebGLRenderTarget copy]( [page:WebGLRenderTarget source] )</h3>
-		<div>
-		Adopts the settings of the given render target.
-		</div>
-
-		<h3>[method:null dispose]()</h3>
-		<div>
-		Dispatches a dispose event.
-		</div>
-
-
-
-
-
-		<h3>[page:EventDispatcher EventDispatcher] methods are available on this class.</h3>
-
-		<h2>Source</h2>
-
-		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-	</body>
-</html>
+		<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>
+
+		<div class="desc">
+			A [link:https://msdn.microsoft.com/en-us/library/bb976073.aspx render target] is a buffer
+			where the video card draws pixels for a scene that	is being rendered in the background.
+			It is used in different effects, such as applying postprocessing to a rendered image
+			before displaying it on the screen.
+		</div>
+
+
+		<h2>Constructor</h2>
+
+
+		<h3>[name]([page:Number width], [page:Number height], [page:Object options])</h3>
+
+		<div>
+		[page:Float width] - The width of the renderTarget. <br />
+		[page:Float height] - The height of the renderTarget.<br />
+		options - (optional object that holds texture parameters for an auto-generated target
+		texture and depthBuffer/stencilBuffer booleans.
+
+		For an explanation of the texture parameters see [page:Texture Texture]. The following are
+		valid options:<br /><br />
+
+		[page:Constant wrapS] - default is [page:Textures ClampToEdgeWrapping]. <br />
+		[page:Constant wrapT] - default is [page:Textures ClampToEdgeWrapping]. <br />
+		[page:Constant magFilter] - default is [page:Textures .LinearFilter]. <br />
+		[page:Constant minFilter] - default is [page:Textures LinearFilter]. <br />
+		[page:Constant format] - default is [page:Textures RGBAFormat]. <br />
+		[page:Constant type] - default is [page:Textures UnsignedByteType]. <br />
+		[page:Number anisotropy] - default is *1*. See [page:Texture.anistropy]<br />
+		[page:Constant encoding] - default is [page:Textures LinearEncoding]. <br />
+		[page:Boolean depthBuffer] - default is *true*. Set this to false if you don't need it. <br />
+		[page:Boolean stencilBuffer] - default is *true*. Set this to false if you don't need it.<br /><br />
+
+		Creates a new [name]
+		</div>
+
+		<h2>Properties</h2>
+
+		<h3>[property:number uuid]</h3>
+		<div>
+		A unique number for this render target instance.
+		</div>
+
+		<h3>[property:number width]</h3>
+		<div>
+		The width of the render target.
+		</div>
+
+		<h3>[property:number height]</h3>
+		<div>
+		The height of the render target.
+		</div>
+
+		<h3>[property:Vector4 scissor]</h3>
+		<div>
+		A rectangular area inside the render target's viewport. Fragments that are outside the area will be discarded.
+		</div>
+
+		<h3>[property:boolean scissorTest]</h3>
+		<div>
+		Indicates whether the scissor test is active or not.
+		</div>
+
+		<h3>[property:Vector4 viewport]</h3>
+		<div>
+		The viewport of this render target.
+		</div>
+
+		<h3>[property:Texture texture]</h3>
+		<div>
+		This texture instance holds the rendered pixels. Use it as input for further processing.
+		</div>
+
+		<h3>[property:boolean depthBuffer]</h3>
+		<div>
+		Renders to the depth buffer. Default is true.
+		</div>
+
+		<h3>[property:boolean stencilBuffer]</h3>
+		<div>
+		Renders to the stencil buffer. Default is true.
+		</div>
+
+		<h3>[property:DepthTexture depthTexture]</h3>
+		<div>
+		If set, the scene depth will be rendered to this texture. Default is null.
+		</div>
+
+
+		<h2>Methods</h2>
+
+		<h3>[method:null setSize]( [page:Number width], [page:Number height] )</h3>
+		<div>
+		Sets the size of the render target.
+		</div>
+
+		<h3>[method:WebGLRenderTarget clone]()</h3>
+		<div>
+		Creates a copy of this render target.
+		</div>
+
+		<h3>[method:WebGLRenderTarget copy]( [page:WebGLRenderTarget source] )</h3>
+		<div>
+		Adopts the settings of the given render target.
+		</div>
+
+		<h3>[method:null dispose]()</h3>
+		<div>
+		Dispatches a dispose event.
+		</div>
+
+
+
+
+
+		<h3>[page:EventDispatcher EventDispatcher] methods are available on this class.</h3>
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

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

@@ -152,7 +152,7 @@
 		various WebGL extensions are supported.
 		various WebGL extensions are supported.
 		</div>
 		</div>
 
 
-		<h3>[property:Boolean gammaFactor]</h3>
+		<h3>[property:Float gammaFactor]</h3>
 		<div>Default is *2*. </div>
 		<div>Default is *2*. </div>
 
 
 
 

+ 0 - 9
docs/examples/loaders/ColladaLoader.html

@@ -86,15 +86,6 @@
 		Parse an <em>XML Document</em> and return an [page:Object object] that contain loaded parts: .[page:Scene scene], .[page:Array morphs], .[page:Array skins], .[page:Array animations], .[page:Object dae]
 		Parse an <em>XML Document</em> and return an [page:Object object] that contain loaded parts: .[page:Scene scene], .[page:Array morphs], .[page:Array skins], .[page:Array animations], .[page:Object dae]
 		</div>
 		</div>
 
 
-		<h3>[method:null setPreferredShading]( [page:Integer shading] )</h3>
-		<div>
-		[page:Integer shading] — required
-		</div>
-		<div>
-		Set the .[page:Integer shading] property on the resource's materials.<br />
-		Options are [page:Materials THREE.SmoothShading], [page:Materials THREE.FlatShading].
-		</div>
-
 		<h3>[method:null applySkin]( [page:Geometry geometry], [page:Object instanceCtrl], [page:Integer frame] )</h3>
 		<h3>[method:null applySkin]( [page:Geometry geometry], [page:Object instanceCtrl], [page:Integer frame] )</h3>
 		<div>
 		<div>
 		[page:Geometry geometry] — required<br />
 		[page:Geometry geometry] — required<br />

+ 12 - 11
docs/examples/loaders/GLTF2Loader.html → docs/examples/loaders/GLTFLoader.html

@@ -19,28 +19,29 @@
 		for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf)
 		for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf)
 		or binary (.glb) format. External files store textures (.jpg, .png, ...) and additional binary
 		or binary (.glb) format. External files store textures (.jpg, .png, ...) and additional binary
 		data (.bin). A glTF asset may deliver one or more scenes, including meshes, materials,
 		data (.bin). A glTF asset may deliver one or more scenes, including meshes, materials,
-		textures, shaders, skins, skeletons, morph targets, animations, lights, and/or cameras.
+		textures, skins, skeletons, morph targets, animations, lights, and/or cameras.
 		</div>
 		</div>
 
 
 		<h2>Extensions</h2>
 		<h2>Extensions</h2>
 
 
 		<div>
 		<div>
-		GLTF2Loader supports the following glTF extensions:
+		GLTFLoader supports the following glTF extensions:
 		</div>
 		</div>
 
 
 		<ul>
 		<ul>
 			<li>
 			<li>
-				KHR_lights
+				<a target="_blank" href="https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_pbrSpecularGlossiness">
+					KHR_materials_pbrSpecularGlossiness
+				</a>
 			</li>
 			</li>
 			<li>
 			<li>
 				<a target="_blank" href="https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_common">
 				<a target="_blank" href="https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_common">
 					KHR_materials_common
 					KHR_materials_common
 				</a>
 				</a>
+				(experimental)
 			</li>
 			</li>
 			<li>
 			<li>
-				<a target="_blank" href="https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_pbrSpecularGlossiness">
-					KHR_materials_pbrSpecularGlossiness
-				</a>
+				KHR_lights (experimental)
 			</li>
 			</li>
 		</ul>
 		</ul>
 
 
@@ -48,7 +49,7 @@
 
 
 		<code>
 		<code>
 		// Instantiate a loader
 		// Instantiate a loader
-		var loader = new THREE.GLTF2Loader();
+		var loader = new THREE.GLTFLoader();
 
 
 		// Load a glTF resource
 		// Load a glTF resource
 		loader.load( 'models/gltf/duck/duck.gltf', function ( gltf ) {
 		loader.load( 'models/gltf/duck/duck.gltf', function ( gltf ) {
@@ -61,7 +62,7 @@
 		} );
 		} );
 		</code>
 		</code>
 
 
-		[example:webgl_loader_gltf2]
+		[example:webgl_loader_gltf]
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
@@ -91,7 +92,7 @@
 
 
 		<h3>[method:null setPath]( [page:String path] )</h3>
 		<h3>[method:null setPath]( [page:String path] )</h3>
 		<div>
 		<div>
-		[page:String path] — Base path for loading additional resources e.g. textures, GLSL shaders, .bin data.
+		[page:String path] — Base path for loading additional resources e.g. textures and .bin data.
 		</div>
 		</div>
 		<div>
 		<div>
 		Set the base path for additional resources.
 		Set the base path for additional resources.
@@ -106,7 +107,7 @@
 		<div>
 		<div>
 		[page:Object json] — <em>JSON</em> object to parse.<br />
 		[page:Object json] — <em>JSON</em> object to parse.<br />
 		[page:Function callBack] — Will be called when parse completes.<br />
 		[page:Function callBack] — Will be called when parse completes.<br />
-		[page:String path] — The base path from which to find subsequent glTF resources such as textures, GLSL shaders and .bin data files.<br />
+		[page:String path] — The base path from which to find subsequent glTF resources such as textures and .bin data files.<br />
 		</div>
 		</div>
 		<div>
 		<div>
 		Parse a glTF-based <em>JSON</em> structure and fire [page:Function callback] when complete. The argument to [page:Function callback] will be an [page:object] that contains loaded parts: .[page:Scene scene], .[page:Array scenes], .[page:Array cameras], and .[page:Array animations].
 		Parse a glTF-based <em>JSON</em> structure and fire [page:Function callback] when complete. The argument to [page:Function callback] will be an [page:object] that contains loaded parts: .[page:Scene scene], .[page:Array scenes], .[page:Array cameras], and .[page:Array animations].
@@ -114,6 +115,6 @@
 
 
 		<h2>Source</h2>
 		<h2>Source</h2>
 
 
-		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/GLTF2Loader.js examples/js/loaders/GLTF2Loader.js]
+		[link:https://github.com/mrdoob/three.js/blob/master/examples/js/loaders/GLTFLoader.js examples/js/loaders/GLTFLoader.js]
 	</body>
 	</body>
 </html>
 </html>

+ 43 - 118
docs/index.html

@@ -39,7 +39,7 @@
 
 
 		</div>
 		</div>
 
 
-		<iframe></iframe>
+		<iframe name="viewer"></iframe>
 
 
 		<script src="list.js"></script>
 		<script src="list.js"></script>
 
 
@@ -57,11 +57,6 @@
 			var categoryElements = [];
 			var categoryElements = [];
 
 
 
 
-// ----------------------------------------------------------------------------
-// Initialization
-// ----------------------------------------------------------------------------
-
-
 			// Functionality for hamburger button (on small devices)
 			// Functionality for hamburger button (on small devices)
 
 
 			expandButton.onclick = function ( event ) {
 			expandButton.onclick = function ( event ) {
@@ -92,28 +87,40 @@
 
 
 			};
 			};
 
 
-
 			// Activate content and title change on browser navigation
 			// Activate content and title change on browser navigation
 
 
 			window.onpopstate = createNewIframe;
 			window.onpopstate = createNewIframe;
 
 
-
 			// Create the navigation panel and configure the iframe
 			// Create the navigation panel and configure the iframe
 
 
 			createNavigation();
 			createNavigation();
 			createNewIframe();
 			createNewIframe();
 
 
+			// Navigation Panel
+
+			function createLink( pageName, pageURL ) {
+
+				var link = document.createElement( 'a' );
+				link.href = pageURL + '.html';
+				link.textContent = pageName;
+				link.setAttribute( 'target', 'viewer' );
+				link.addEventListener( 'click', function ( event ) {
 
 
-// ----------------------------------------------------------------------------
-// Navigation Panel
-// ----------------------------------------------------------------------------
+					window.location.hash = pageURL;
+					panel.classList.add( 'collapsed' );
+
+				} );
+
+				return link;
 
 
+			}
 
 
-			function createNavigation () {
+			function createNavigation() {
 
 
 				// Create the navigation panel using data from list.js
 				// Create the navigation panel using data from list.js
 
 
-				var navigation = createAndAppendDOMElement( { type: 'div', parent: content } );
+				var navigation = document.createElement( 'div' );
+				content.appendChild( navigation );
 
 
 				for ( var section in list ) {
 				for ( var section in list ) {
 
 
@@ -121,7 +128,9 @@
 
 
 					var categories = list[ section ];
 					var categories = list[ section ];
 
 
-					var sectionHead = createAndAppendDOMElement( { type: 'h2', parent: navigation, content: section } )
+					var sectionHead = document.createElement( 'h2' );
+					sectionHead.textContent = section;
+					navigation.appendChild( sectionHead );
 
 
 					for ( var category in categories ) {
 					for ( var category in categories ) {
 
 
@@ -129,9 +138,15 @@
 
 
 						var pages = categories[ category ];
 						var pages = categories[ category ];
 
 
-						var categoryContainer = createAndAppendDOMElement( { type: 'div', parent: navigation } );
-						var categoryHead = createAndAppendDOMElement( { type: 'h3', parent: categoryContainer, content: category } );
-						var categoryContent = createAndAppendDOMElement( { type: 'ul', parent: categoryContainer } );
+						var categoryContainer = document.createElement( 'div' );
+						navigation.appendChild( categoryContainer );
+
+						var categoryHead = document.createElement( 'h3' );
+						categoryHead.textContent = category;
+						categoryContainer.appendChild( categoryHead );
+
+						var categoryContent = document.createElement( 'ul' );
+						categoryContainer.appendChild( categoryContent );
 
 
 						for ( var pageName in pages ) {
 						for ( var pageName in pages ) {
 
 
@@ -139,14 +154,11 @@
 
 
 							var pageURL = pages[ pageName ];
 							var pageURL = pages[ pageName ];
 
 
-							var listElement = createAndAppendDOMElement( { type: 'li', parent: categoryContent } );
-							var linkElement = createAndAppendDOMElement( { type: 'a', parent: listElement, content: pageName } );
-
-							// The href attribute is only used for the option to create a new tab by right click
+							var listElement = document.createElement( 'li' );
+							categoryContent.appendChild( listElement );
 
 
-							linkElement.setAttribute( 'href', '#' + pageURL );
-
-							addClickHandlers( linkElement, pageURL );
+							var linkElement = createLink( pageName, pageURL )
+							listElement.appendChild( linkElement );
 
 
 							// Gather the main properties for the current subpage
 							// Gather the main properties for the current subpage
 
 
@@ -171,92 +183,15 @@
 
 
 				}
 				}
 
 
-			};
-
-
-			function createAndAppendDOMElement( properties ) {
-
-				// Helper function for creating and appending new DOM elements
-
-				var newElement = document.createElement( properties.type );
-
-				properties.parent.appendChild( newElement );
-
-				if ( properties.content ) {
-
-					newElement.textContent = properties.content;
-
-				}
-
-				return newElement;
-
 			}
 			}
 
 
 
 
-			function addClickHandlers ( linkElement, pageURL ) {
-
-				// Helper function for adding ClickHandlers to the page links
-
-				linkElement.onclick = function ( event ) {
-
-					event.preventDefault();
-
-					window.location.hash = pageURL;
-					createNewIframe();
-
-					panel.classList.add( 'collapsed' );
-
-				};
-
-			};
-
-
-// ----------------------------------------------------------------------------
-// Query Strings (optional)
-// ----------------------------------------------------------------------------
-
-
-//			(uncomment the following lines and the first line in updateFilter(), if you want query strings):
-
-//			filterInput.value = extractFromQueryString();
-//			updateFilter();
-//
-//
-//			function extractFromQueryString() {
-//
-//				var queryString = window.location.search;
-//
-//				if ( queryString.indexOf( '?q=' ) === -1 ) return '';
-//
-//				return queryString.substr( 3 );
-//
-//			}
-//
-//			function updateQueryString() {
-//
-//				var searchString = filterInput.value;
-//				var query = '';
-//
-//				if (searchString !== '') {
-//
-//					query = '?q=' + searchString;
-//
-//				}
-//
-//				window.history.replaceState( {} , '', window.location.pathname + query + window.location.hash ); 
-//
-//			}
-
-
-// ----------------------------------------------------------------------------
-// Filtering
-// ----------------------------------------------------------------------------
-
+			// Filtering
 
 
 			function updateFilter() {
 			function updateFilter() {
 
 
-//			(uncomment the following line and the "Query strings" section, if you want query strings):
-//			updateQueryString();
+				// (uncomment the following line and the "Query strings" section, if you want query strings):
+				// updateQueryString();
 
 
 				var regExp = new RegExp( filterInput.value, 'gi' );
 				var regExp = new RegExp( filterInput.value, 'gi' );
 
 
@@ -297,7 +232,6 @@
 
 
 			}
 			}
 
 
-
 			function displayFilteredPanel() {
 			function displayFilteredPanel() {
 
 
 				// Show/hide categories depending on their content
 				// Show/hide categories depending on their content
@@ -340,10 +274,7 @@
 			}
 			}
 
 
 
 
-// ----------------------------------------------------------------------------
-// Routing
-// ----------------------------------------------------------------------------
-
+			// Routing
 
 
 			function setUrlFragment( pageName ) {
 			function setUrlFragment( pageName ) {
 
 
@@ -365,7 +296,6 @@
 
 
 			}
 			}
 
 
-
 			function createNewIframe() {
 			function createNewIframe() {
 
 
 				// Change the content displayed in the iframe
 				// Change the content displayed in the iframe
@@ -404,11 +334,10 @@
 
 
 			}
 			}
 
 
-
-			function decomposePageName ( pageName, oldDelimiter, newDelimiter ) {
+			function decomposePageName( pageName, oldDelimiter, newDelimiter ) {
 
 
 				// Helper function for separating the member (if existing) from the pageName
 				// Helper function for separating the member (if existing) from the pageName
-				// For example: 'Geometry.morphTarget' can be converted to 
+				// For example: 'Geometry.morphTarget' can be converted to
 				// ['Geometry', '.morphTarget'] or ['Geometry', '#morphTarget']
 				// ['Geometry', '.morphTarget'] or ['Geometry', '#morphTarget']
 				// Note: According RFC 3986 no '#' allowed inside of an URL fragment!
 				// Note: According RFC 3986 no '#' allowed inside of an URL fragment!
 
 
@@ -432,11 +361,7 @@
 
 
 			}
 			}
 
 
-
-// ----------------------------------------------------------------------------
-// ASCII Art ;-)
-// ----------------------------------------------------------------------------
-
+			//
 
 
 			console.log([
 			console.log([
 				'    __     __',
 				'    __     __',

+ 3 - 2
docs/list.js

@@ -4,6 +4,7 @@ var list = {
 
 
 		"Getting Started": {
 		"Getting Started": {
 			"Creating a scene": "manual/introduction/Creating-a-scene",
 			"Creating a scene": "manual/introduction/Creating-a-scene",
+			"Import via modules": "manual/introduction/Import-via-modules",
 			"WebGL compatibility check": "manual/introduction/WebGL-compatibility-check",
 			"WebGL compatibility check": "manual/introduction/WebGL-compatibility-check",
 			"How to run things locally": "manual/introduction/How-to-run-thing-locally",
 			"How to run things locally": "manual/introduction/How-to-run-thing-locally",
 			"Drawing Lines": "manual/introduction/Drawing-lines",
 			"Drawing Lines": "manual/introduction/Drawing-lines",
@@ -131,7 +132,6 @@ var list = {
 
 
 		"Extras / Objects": {
 		"Extras / Objects": {
 			"ImmediateRenderObject": "api/extras/objects/ImmediateRenderObject",
 			"ImmediateRenderObject": "api/extras/objects/ImmediateRenderObject",
-			"MorphBlendMesh": "api/extras/objects/MorphBlendMesh"
 		},
 		},
 
 
 		"Geometries": {
 		"Geometries": {
@@ -168,6 +168,7 @@ var list = {
 			"SphereGeometry": "api/geometries/SphereGeometry",
 			"SphereGeometry": "api/geometries/SphereGeometry",
 			"TetrahedronBufferGeometry": "api/geometries/TetrahedronBufferGeometry",
 			"TetrahedronBufferGeometry": "api/geometries/TetrahedronBufferGeometry",
 			"TetrahedronGeometry": "api/geometries/TetrahedronGeometry",
 			"TetrahedronGeometry": "api/geometries/TetrahedronGeometry",
+			"TextBufferGeometry": "api/geometries/TextBufferGeometry",
 			"TextGeometry": "api/geometries/TextGeometry",
 			"TextGeometry": "api/geometries/TextGeometry",
 			"TorusBufferGeometry": "api/geometries/TorusBufferGeometry",
 			"TorusBufferGeometry": "api/geometries/TorusBufferGeometry",
 			"TorusGeometry": "api/geometries/TorusGeometry",
 			"TorusGeometry": "api/geometries/TorusGeometry",
@@ -340,7 +341,7 @@ var list = {
 		"Loaders": {
 		"Loaders": {
 			"BabylonLoader": "examples/loaders/BabylonLoader",
 			"BabylonLoader": "examples/loaders/BabylonLoader",
 			"ColladaLoader": "examples/loaders/ColladaLoader",
 			"ColladaLoader": "examples/loaders/ColladaLoader",
-			"GLTF2Loader": "examples/loaders/GLTF2Loader",
+			"GLTFLoader": "examples/loaders/GLTFLoader",
 			"MTLLoader": "examples/loaders/MTLLoader",
 			"MTLLoader": "examples/loaders/MTLLoader",
 			"OBJLoader": "examples/loaders/OBJLoader",
 			"OBJLoader": "examples/loaders/OBJLoader",
 			"OBJLoader2": "examples/loaders/OBJLoader2",
 			"OBJLoader2": "examples/loaders/OBJLoader2",

+ 1 - 1
docs/manual/introduction/Animation-system.html

@@ -111,7 +111,7 @@
 				<li>[page:ObjectLoader THREE.ObjectLoader]</li>
 				<li>[page:ObjectLoader THREE.ObjectLoader]</li>
 				<li>THREE.BVHLoader</li>
 				<li>THREE.BVHLoader</li>
 				<li>THREE.FBXLoader</li>
 				<li>THREE.FBXLoader</li>
-				<li>[page:GLTF2Loader THREE.GLTF2Loader]</li>
+				<li>[page:GLTFLoader THREE.GLTFLoader]</li>
 				<li>THREE.MMDLoader</li>
 				<li>THREE.MMDLoader</li>
 				<li>THREE.SEA3DLoader</li>
 				<li>THREE.SEA3DLoader</li>
 			</ul>
 			</ul>

+ 71 - 71
docs/manual/introduction/How-to-run-thing-locally.html

@@ -40,64 +40,6 @@
 			</p>
 			</p>
 		</div>
 		</div>
 
 
-		<h2>Change local files security policy</h2>
-		<div>
-			<h4>Safari</h4>
-			<div>
-				<p>
-					Enable the develop menu using the preferences panel, under Advanced -&gt; "Show develop menu
-					in menu bar".
-				</p>
-
-				<p>
-					Then from the safari "Develop" menu, select "Disable local file restrictions", it is also
-					worth noting safari has some odd behaviour with caches, so it is advisable to use the
-					"Disable caches" option in the same menu; if you are editing &amp; debugging using safari.
-				</p>
-			</div>
-
-
-			<h4>Chrome</h4>
-			<div>
-				<p>Close all running Chrome instances first. The important word here is 'all'.</p>
-
-				<p>
-					On Windows, you may check for Chrome instances using the Windows Task Manager.
-					Alternatively, if you see a Chrome icon in the system tray, then you may open its context
-					menu and click 'Exit'. This should close all Chrome instances.
-				</p>
-
-				<p>Then start the Chrome executable with a command line flag:</p>
-
-				<code>chrome --allow-file-access-from-files</code>
-
-				<p>
-					On Windows, probably the easiest is probably to create a special shortcut icon which has
-					added the flag given above (right-click on shortcut -&gt; properties -&gt; target).
-				</p>
-
-				<p>On Mac OSX, you can do this with</p>
-
-				<code>open /Applications/Google\ Chrome.app --args --allow-file-access-from-files</code>
-			</div>
-
-			<h4>Firefox</h4>
-			<div>
-				<ol>
-				<li>
-					In the address bar, type <code>about:config</code>
-				</li>
-				<li>
-					Find the <code>security.fileuri.strict_origin_policy</code> parameter
-				</li>
-				<li>
-					Set it to <em>false</em>
-				</li>
-				</ol>
-			</div>
-
-		</div>
-
 
 
 		<h2>Run a local server</h2>
 		<h2>Run a local server</h2>
 		<div>
 		<div>
@@ -107,7 +49,16 @@
 				three.js application.
 				three.js application.
 			</p>
 			</p>
 
 
-			<h4>Running a Python server</h4>
+			<h3>Node.js server</h3>
+			<div>
+				<p>Node.js has a simple HTTP server package. To install:</p>
+				<code>npm install http-server -g</code>
+
+				<p>To run (from your local directory):</p>
+				<code>http-server . -p 8000</code>
+			</div>
+
+			<h3>Python server</h3>
 			<div>
 			<div>
 				<p>
 				<p>
 					If you have [link:http://python.org/ Python] installed, it should be enough to run this
 					If you have [link:http://python.org/ Python] installed, it should be enough to run this
@@ -126,7 +77,7 @@ python -m http.server
 				<code>http://localhost:8000/</code>
 				<code>http://localhost:8000/</code>
 			</div>
 			</div>
 
 
-			<h4>Running a Ruby server</h4>
+			<h3>Ruby server</h3>
 			<div>
 			<div>
 				<p>If you have Ruby installed, you can get the same result running this instead:</p>
 				<p>If you have Ruby installed, you can get the same result running this instead:</p>
 				<code>
 				<code>
@@ -134,22 +85,13 @@ ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot =>
 				</code>
 				</code>
 			</div>
 			</div>
 
 
-			<h4>Running a PHP server</h4>
+			<h3>PHP server</h3>
 			<div>
 			<div>
 				<p>PHP also has a built-in web server, starting with php 5.4.0:</p>
 				<p>PHP also has a built-in web server, starting with php 5.4.0:</p>
 				<code>php -S localhost:8000</code>
 				<code>php -S localhost:8000</code>
 			</div>
 			</div>
 
 
-			<h4>Running a Node.js server</h4>
-			<div>
-				<p>Node.js has a simple HTTP server package. To install:</p>
-				<code>npm install http-server -g</code>
-
-				<p>To run (from your local directory):</p>
-				<code>http-server . -p 8000</code>
-			</div>
-
-			<h4>Running lighttpd on Mac</h4>
+			<h3>Lighttpd</h3>
 			<div>
 			<div>
 				<p>
 				<p>
 					Lighttpd is a very lightweight general purpose webserver. We'll cover installing it on OSX with
 					Lighttpd is a very lightweight general purpose webserver. We'll cover installing it on OSX with
@@ -180,6 +122,64 @@ ruby -r webrick -e "s = WEBrick::HTTPServer.new(:Port => 8000, :DocumentRoot =>
 				</ol>
 				</ol>
 			</div>
 			</div>
 
 
+		<h2>Change local files security policy</h2>
+		<div>
+			<h3>Safari</h3>
+			<div>
+				<p>
+					Enable the develop menu using the preferences panel, under Advanced -&gt; "Show develop menu
+					in menu bar".
+				</p>
+
+				<p>
+					Then from the safari "Develop" menu, select "Disable local file restrictions", it is also
+					worth noting safari has some odd behaviour with caches, so it is advisable to use the
+					"Disable caches" option in the same menu; if you are editing &amp; debugging using safari.
+				</p>
+			</div>
+
+
+			<h3>Chrome</h3>
+			<div>
+				<p>Close all running Chrome instances first. The important word here is 'all'.</p>
+
+				<p>
+					On Windows, you may check for Chrome instances using the Windows Task Manager.
+					Alternatively, if you see a Chrome icon in the system tray, then you may open its context
+					menu and click 'Exit'. This should close all Chrome instances.
+				</p>
+
+				<p>Then start the Chrome executable with a command line flag:</p>
+
+				<code>chrome --allow-file-access-from-files</code>
+
+				<p>
+					On Windows, probably the easiest is probably to create a special shortcut icon which has
+					added the flag given above (right-click on shortcut -&gt; properties -&gt; target).
+				</p>
+
+				<p>On Mac OSX, you can do this with</p>
+
+				<code>open /Applications/Google\ Chrome.app --args --allow-file-access-from-files</code>
+			</div>
+
+			<h3>Firefox</h3>
+			<div>
+				<ol>
+				<li>
+					In the address bar, type <code>about:config</code>
+				</li>
+				<li>
+					Find the <code>security.fileuri.strict_origin_policy</code> parameter
+				</li>
+				<li>
+					Set it to <em>false</em>
+				</li>
+				</ol>
+			</div>
+
+		</div>
+
 			<p>
 			<p>
 				Other simple alternatives are [link:http://stackoverflow.com/q/12905426/24874 discussed here]
 				Other simple alternatives are [link:http://stackoverflow.com/q/12905426/24874 discussed here]
 				on Stack Overflow.
 				on Stack Overflow.

+ 2 - 2
docs/manual/introduction/How-to-update-things.html

@@ -118,7 +118,7 @@ line.geometry.attributes.position.needsUpdate = true; // required after the firs
 					[link:http://jsfiddle.net/w67tzfhx/ Here is a fiddle] showing an animated line which you can adapt to your use case.
 					[link:http://jsfiddle.net/w67tzfhx/ Here is a fiddle] showing an animated line which you can adapt to your use case.
 				</p>
 				</p>
 
 
-				<h4>Examples:</h4>
+				<h3>Examples:</h3>
 					[example:webgl_custom_attributes WebGL / custom / attributes]<br />
 					[example:webgl_custom_attributes WebGL / custom / attributes]<br />
 					[example:webgl_buffergeometry_custom_attributes_particles WebGL / buffergeometry / custom / attributes / particles]
 					[example:webgl_buffergeometry_custom_attributes_particles WebGL / buffergeometry / custom / attributes / particles]
 
 
@@ -155,7 +155,7 @@ geometry.tangentsNeedUpdate = true;
 		geometry.dynamic = true;
 		geometry.dynamic = true;
 				</code>
 				</code>
 
 
-				<h4>Example:</h4>
+				<h3>Examples:</h3>
 					[example:webgl_geometry_dynamic WebGL / geometry / dynamic]<br />
 					[example:webgl_geometry_dynamic WebGL / geometry / dynamic]<br />
 			</div>
 			</div>
 
 

+ 72 - 0
docs/manual/introduction/Import-via-modules.html

@@ -0,0 +1,72 @@
+<!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><br />
+
+		<div>
+			While importing three.js via script tags is a great way to get up and running fast, it has a few drawbacks for longer lived projects, for example:
+			<ul>
+				<li>You have to manually fetch and include a copy of the library as part of your project's source code</li>
+				<li>Updating the library's version is a manual process</li>
+				<li>When checking in a new version of the library your version control diffs are cluttered by the many lines of the build file</li>
+			</ul>
+		</div>
+
+		<div>Using a dependency manager like npm avoids these caveats by allowing you to simply download and import your desired version of the libarary onto your machine.</div>
+
+		<h2>Installation via npm</h2>
+
+		<div>Three.js is published as an npm module, see: <a href="https://www.npmjs.com/package/three" target="_blank">npm</a>. This means all you need to do to include three.js into your project is run "npm install three"</div>
+
+		<h2>Importing the module</h2>
+
+		<div>Assuming that you're bundling your files with a tool such as <a href="https://webpack.github.io/" target="_blank">Webpack</a> or <a href="https://github.com/substack/node-browserify" target="_blank">Browserify</a>, which allow you to "require('modules') in the browser by bundling up all of your dependencies."</div>
+
+		<div>
+			You should now be able to import the module into your source files and continue to use it as per normal.
+		</div>
+
+		<code>
+		var THREE = require('three');
+
+		var scene = new THREE.Scene();
+		...
+		</code>
+
+		<div>
+			You're also able to leverage <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import" target="_blank">ES6 import syntax</a>:
+		</div>
+
+		<code>
+		import * as THREE from 'three';
+
+		const scene = new THREE.Scene();
+		...
+		</code>
+
+		<div>
+			or if you wish to import only select parts of three.js library, for example Scene:
+		</div>
+
+		<code>
+		import { Scene } from 'three';
+
+		const scene = new Scene();
+		...
+		</code>
+
+		<h2>Caveats</h2>
+
+		<div>
+			Currenlty it's not possible to import the files within the "examples/js" directroy in this way.
+			This is due to some of the files relying on global namespace pollution of THREE. For more information see <a href="https://github.com/mrdoob/three.js/issues/9562" target="_blank">Transform `examples/js` to support modules #9562</a>.
+		</div>
+	</body>
+</html>

+ 3 - 3
docs/manual/introduction/Useful-links.html

@@ -31,7 +31,7 @@
 
 
 		<h2>Tutorials and courses</h2>
 		<h2>Tutorials and courses</h2>
 
 
-		<h4>Getting started with three.js</h4>
+		<h3>Getting started with three.js</h3>
 		<ul>
 		<ul>
 			<li>
 			<li>
 				[link:https://codepen.io/rachsmith/post/beginning-with-3d-webgl-pt-1-the-scene Beginning with 3D WebGL] by [link:https://codepen.io/rachsmith/ Rachel Smith].
 				[link:https://codepen.io/rachsmith/post/beginning-with-3d-webgl-pt-1-the-scene Beginning with 3D WebGL] by [link:https://codepen.io/rachsmith/ Rachel Smith].
@@ -41,7 +41,7 @@
 			</li>
 			</li>
 		</ul>
 		</ul>
 
 
-		<h4>More extensive / advanced articles and courses</h4>
+		<h3>More extensive / advanced articles and courses</h3>
 		<ul>
 		<ul>
 			<li>
 			<li>
 				[link:http://blog.cjgammon.com/ Collection of tutorials] by [link:http://www.cjgammon.com/ CJ Gammon].
 				[link:http://blog.cjgammon.com/ Collection of tutorials] by [link:http://www.cjgammon.com/ CJ Gammon].
@@ -65,7 +65,7 @@
 		 </li>
 		 </li>
 		</ul>
 		</ul>
 
 
-		<h4>Tutorials in other languages</h4>
+		<h3>Tutorials in other languages</h3>
 		<ul>
 		<ul>
 			<li>
 			<li>
 				[link:http://www.natural-science.or.jp/article/20120220155529.php Building A Physics Simulation Environment] - three.js tutorial in Japanese
 				[link:http://www.natural-science.or.jp/article/20120220155529.php Building A Physics Simulation Environment] - three.js tutorial in Japanese

+ 1 - 1
docs/scenes/bones-browser.html

@@ -149,7 +149,7 @@
 					color: 0x156289,
 					color: 0x156289,
 					emissive: 0x072534,
 					emissive: 0x072534,
 					side: THREE.DoubleSide,
 					side: THREE.DoubleSide,
-					shading: THREE.FlatShading
+					flatShading: true
 				} );
 				} );
 
 
 				var mesh = new THREE.SkinnedMesh( geometry,	material );
 				var mesh = new THREE.SkinnedMesh( geometry,	material );

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

@@ -94,7 +94,7 @@
 					color: 0x156289,
 					color: 0x156289,
 					emissive: 0x072534,
 					emissive: 0x072534,
 					side: THREE.DoubleSide,
 					side: THREE.DoubleSide,
-					shading: THREE.FlatShading
+					flatShading: true
 				} )
 				} )
 
 
 			) );
 			) );

+ 70 - 8
docs/scenes/js/geometry.js

@@ -22,13 +22,6 @@ var constants = {
 
 
 	},
 	},
 
 
-	shading : {
-
-		"THREE.FlatShading" : THREE.FlatShading,
-		"THREE.SmoothShading" : THREE.SmoothShading
-
-	},
-
 	colors : {
 	colors : {
 
 
 		"THREE.NoColors" : THREE.NoColors,
 		"THREE.NoColors" : THREE.NoColors,
@@ -984,6 +977,75 @@ var guis = {
 
 
 	},
 	},
 
 
+	TextBufferGeometry : function( mesh ) {
+
+		var data = {
+			text : "TextBufferGeometry",
+			size : 5,
+			height : 2,
+			curveSegments : 12,
+			font : "helvetiker",
+			weight : "regular",
+			bevelEnabled : false,
+			bevelThickness : 1,
+			bevelSize : 0.5,
+			bevelSegments : 3
+		};
+
+		var fonts = [
+			"helvetiker",
+			"optimer",
+			"gentilis",
+			"droid/droid_serif"
+		];
+
+		var weights = [
+			"regular", "bold"
+		];
+
+		function generateGeometry() {
+
+			var loader = new THREE.FontLoader();
+			loader.load( '../../examples/fonts/' + data.font + '_' + data.weight + '.typeface.json', function ( font ) {
+
+				var geometry = new THREE.TextBufferGeometry( data.text, {
+					font: font,
+					size: data.size,
+					height: data.height,
+					curveSegments: data.curveSegments,
+					bevelEnabled: data.bevelEnabled,
+					bevelThickness: data.bevelThickness,
+					bevelSize: data.bevelSize,
+					bevelSegments: data.bevelSegments
+				} );
+				geometry.center();
+
+				updateGroupGeometry( mesh, geometry );
+
+			} );
+
+		}
+
+		//Hide the wireframe
+		mesh.children[ 0 ].visible = false;
+
+		var folder = gui.addFolder( 'THREE.TextBufferGeometry' );
+
+		folder.add( data, 'text' ).onChange( generateGeometry );
+		folder.add( data, 'size', 1, 30 ).onChange( generateGeometry );
+		folder.add( data, 'height', 1, 20 ).onChange( generateGeometry );
+		folder.add( data, 'curveSegments', 1, 20 ).step( 1 ).onChange( generateGeometry );
+		folder.add( data, 'font', fonts ).onChange( generateGeometry );
+		folder.add( data, 'weight', weights ).onChange( generateGeometry );
+		folder.add( data, 'bevelEnabled' ).onChange( generateGeometry );
+		folder.add( data, 'bevelThickness', 0.1, 3 ).onChange( generateGeometry );
+		folder.add( data, 'bevelSize', 0.1, 3 ).onChange( generateGeometry );
+		folder.add( data, 'bevelSegments', 0, 8 ).step( 1 ).onChange( generateGeometry );
+
+		generateGeometry();
+
+	},
+
 	TorusBufferGeometry : function( mesh ) {
 	TorusBufferGeometry : function( mesh ) {
 
 
 		var data = {
 		var data = {
@@ -1356,7 +1418,7 @@ function chooseFromHash ( mesh ) {
 
 
 	}
 	}
 
 
-	if ( selectedGeometry === 'TextGeometry' ) {
+	if ( selectedGeometry === 'TextGeometry' || selectedGeometry === 'TextBufferGeometry' ) {
 
 
 		return { fixed : true };
 		return { fixed : true };
 
 

+ 4 - 12
docs/scenes/js/material.js

@@ -20,13 +20,6 @@ var constants = {
 
 
 	},
 	},
 
 
-	shading : {
-
-		"THREE.FlatShading" : THREE.FlatShading,
-		"THREE.SmoothShading" : THREE.SmoothShading
-
-	},
-
 	colors : {
 	colors : {
 
 
 		"THREE.NoColors" : THREE.NoColors,
 		"THREE.NoColors" : THREE.NoColors,
@@ -202,7 +195,6 @@ function needsUpdate ( material, geometry ) {
 
 
 	return function () {
 	return function () {
 
 
-		material.shading = +material.shading; //Ensure number
 		material.vertexColors = +material.vertexColors; //Ensure number
 		material.vertexColors = +material.vertexColors; //Ensure number
 		material.side = +material.side; //Ensure number
 		material.side = +material.side; //Ensure number
 		material.needsUpdate = true;
 		material.needsUpdate = true;
@@ -330,7 +322,6 @@ function guiMeshBasicMaterial ( gui, mesh, material, geometry ) {
 	folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
 	folder.addColor( data, 'color' ).onChange( handleColorChange( material.color ) );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
-	folder.add( material, 'shading', constants.shading);
 	folder.add( material, 'vertexColors', constants.colors).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'vertexColors', constants.colors).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'fog' );
 	folder.add( material, 'fog' );
 
 
@@ -360,6 +351,7 @@ function guiMeshNormalMaterial ( gui, mesh, material, geometry ) {
 
 
 	var folder = gui.addFolder('THREE.MeshNormalMaterial');
 	var folder = gui.addFolder('THREE.MeshNormalMaterial');
 
 
+	folder.add( material, 'flatShading' ).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'morphTargets' ).onChange( updateMorphs( mesh, material ) );
 	folder.add( material, 'morphTargets' ).onChange( updateMorphs( mesh, material ) );
@@ -438,7 +430,7 @@ function guiMeshPhongMaterial ( gui, mesh, material, geometry ) {
 	folder.addColor( data, 'specular' ).onChange( handleColorChange( material.specular ) );
 	folder.addColor( data, 'specular' ).onChange( handleColorChange( material.specular ) );
 
 
 	folder.add( material, 'shininess', 0, 100);
 	folder.add( material, 'shininess', 0, 100);
-	folder.add( material, 'shading', constants.shading).onChange( needsUpdate( material, geometry ) );
+	folder.add( material, 'flatShading' ).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'vertexColors', constants.colors);
 	folder.add( material, 'vertexColors', constants.colors);
@@ -470,7 +462,7 @@ function guiMeshStandardMaterial ( gui, mesh, material, geometry ) {
 
 
 	folder.add( material, 'roughness', 0, 1 );
 	folder.add( material, 'roughness', 0, 1 );
 	folder.add( material, 'metalness', 0, 1 );
 	folder.add( material, 'metalness', 0, 1 );
-	folder.add( material, 'shading', constants.shading).onChange( needsUpdate( material, geometry ) );
+	folder.add( material, 'flatShading' ).onChange( needsUpdate( material, geometry ) );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframe' );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'wireframeLinewidth', 0, 10 );
 	folder.add( material, 'vertexColors', constants.colors);
 	folder.add( material, 'vertexColors', constants.colors);
@@ -533,7 +525,7 @@ function chooseFromHash ( gui, mesh, geometry ) {
 
 
 	case "MeshDepthMaterial" :
 	case "MeshDepthMaterial" :
 
 
-		material = new THREE.MeshDepthMaterial({color: 0x2194CE});
+		material = new THREE.MeshDepthMaterial();
 		guiMaterial( gui, mesh, material, geometry );
 		guiMaterial( gui, mesh, material, geometry );
 		guiMeshDepthMaterial( gui, mesh, material, geometry );
 		guiMeshDepthMaterial( gui, mesh, material, geometry );
 
 

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

@@ -44,7 +44,7 @@
 
 
 			var gui = new dat.GUI();
 			var gui = new dat.GUI();
 			var scene = new THREE.Scene();
 			var scene = new THREE.Scene();
-			var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 50 );
+			var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 10, 50 );
 			camera.position.z = 30;
 			camera.position.z = 30;
 
 
 			var renderer = new THREE.WebGLRenderer( { antialias: true } );
 			var renderer = new THREE.WebGLRenderer( { antialias: true } );

+ 2 - 47
editor/index.html

@@ -41,6 +41,7 @@
 		<script src="../examples/js/loaders/KMZLoader.js"></script>
 		<script src="../examples/js/loaders/KMZLoader.js"></script>
 		<script src="../examples/js/loaders/MD2Loader.js"></script>
 		<script src="../examples/js/loaders/MD2Loader.js"></script>
 		<script src="../examples/js/loaders/OBJLoader.js"></script>
 		<script src="../examples/js/loaders/OBJLoader.js"></script>
+		<script src="../examples/js/loaders/MTLLoader.js"></script>
 		<script src="../examples/js/loaders/PlayCanvasLoader.js"></script>
 		<script src="../examples/js/loaders/PlayCanvasLoader.js"></script>
 		<script src="../examples/js/loaders/PLYLoader.js"></script>
 		<script src="../examples/js/loaders/PLYLoader.js"></script>
 		<script src="../examples/js/loaders/STLLoader.js"></script>
 		<script src="../examples/js/loaders/STLLoader.js"></script>
@@ -53,6 +54,7 @@
 		<script src="../examples/js/loaders/ctm/ctm.js"></script>
 		<script src="../examples/js/loaders/ctm/ctm.js"></script>
 		<script src="../examples/js/loaders/ctm/CTMLoader.js"></script>
 		<script src="../examples/js/loaders/ctm/CTMLoader.js"></script>
 		<script src="../examples/js/exporters/OBJExporter.js"></script>
 		<script src="../examples/js/exporters/OBJExporter.js"></script>
+		<script src="../examples/js/exporters/GLTFExporter.js"></script>
 		<script src="../examples/js/exporters/STLExporter.js"></script>
 		<script src="../examples/js/exporters/STLExporter.js"></script>
 
 
 		<script src="../examples/js/renderers/Projector.js"></script>
 		<script src="../examples/js/renderers/Projector.js"></script>
@@ -97,8 +99,6 @@
 		<script src="js/Player.js"></script>
 		<script src="js/Player.js"></script>
 		<script src="js/Script.js"></script>
 		<script src="js/Script.js"></script>
 
 
-		<script src="../examples/js/effects/VREffect.js"></script>
-		<script src="../examples/js/controls/VRControls.js"></script>
 		<script src="../examples/js/vr/WebVR.js"></script>
 		<script src="../examples/js/vr/WebVR.js"></script>
 
 
 		<script src="js/Storage.js"></script>
 		<script src="js/Storage.js"></script>
@@ -404,51 +404,6 @@
 			}, false );
 			}, false );
 			*/
 			*/
 
 
-			// VR
-
-			var groupVR;
-
-			// TODO: Use editor.signals.enteredVR (WebVR 1.0)
-
-			editor.signals.enterVR.add( function () {
-
-				if ( groupVR === undefined ) {
-
-					groupVR = new THREE.HTMLGroup( viewport.dom );
-					editor.sceneHelpers.add( groupVR );
-
-					var mesh = new THREE.HTMLMesh( sidebar.dom );
-					mesh.position.set( 15, 0, 15 );
-					mesh.rotation.y = - 0.5;
-					groupVR.add( mesh );
-
-					var signals = editor.signals;
-
-					function updateTexture() {
-
-						mesh.material.map.update();
-
-					}
-
-					signals.objectSelected.add( updateTexture );
-					signals.objectAdded.add( updateTexture );
-					signals.objectChanged.add( updateTexture );
-					signals.objectRemoved.add( updateTexture );
-					signals.sceneGraphChanged.add( updateTexture );
-					signals.historyChanged.add( updateTexture );
-
-				}
-
-				groupVR.visible = true;
-
-			} );
-
-			editor.signals.exitedVR.add( function () {
-
-				if ( groupVR !== undefined ) groupVR.visible = false;
-
-			} );
-
 		</script>
 		</script>
 	</body>
 	</body>
 </html>
 </html>

+ 28 - 7
editor/js/Editor.js

@@ -22,13 +22,6 @@ var Editor = function () {
 		startPlayer: new Signal(),
 		startPlayer: new Signal(),
 		stopPlayer: new Signal(),
 		stopPlayer: new Signal(),
 
 
-		// vr
-
-		enterVR: new Signal(),
-
-		enteredVR: new Signal(),
-		exitedVR: new Signal(),
-
 		// actions
 		// actions
 
 
 		showModal: new Signal(),
 		showModal: new Signal(),
@@ -347,6 +340,34 @@ Editor.prototype = {
 
 
 	},
 	},
 
 
+	getObjectMaterial: function ( object, slot ) {
+
+		var material = object.material;
+
+		if ( Array.isArray( material ) ) {
+
+			material = material[ slot ];
+
+		}
+
+		return material;
+
+	},
+
+	setObjectMaterial: function ( object, slot, newMaterial ) {
+
+		if ( Array.isArray( object.material ) ) {
+
+			object.material[ slot ] = newMaterial;
+
+		} else {
+
+			object.material = newMaterial;
+
+		}
+
+	},
+
 	//
 	//
 
 
 	select: function ( object ) {
 	select: function ( object ) {

+ 24 - 1
editor/js/Loader.js

@@ -177,7 +177,7 @@ var Loader = function ( editor ) {
 					var contents = event.target.result;
 					var contents = event.target.result;
 
 
 					var loader = new THREE.GLTFLoader();
 					var loader = new THREE.GLTFLoader();
-					loader.parse( contents, function ( result ) {
+					loader.parse( contents, '', function ( result ) {
 
 
 						result.scene.name = filename;
 						result.scene.name = filename;
 						editor.execute( new AddObjectCommand( result.scene ) );
 						editor.execute( new AddObjectCommand( result.scene ) );
@@ -428,6 +428,29 @@ var Loader = function ( editor ) {
 
 
 				break;
 				break;
 
 
+			case 'zip':
+
+				reader.addEventListener( 'load', function ( event ) {
+
+					var contents = event.target.result;
+
+					var zip = new JSZip( contents );
+
+					// BLOCKS
+
+					if ( zip.files[ 'model.obj' ] && zip.files[ 'materials.mtl' ] ) {
+
+						var materials = new THREE.MTLLoader().parse( zip.file( 'materials.mtl' ).asText() );
+						var object = new THREE.OBJLoader().setMaterials( materials ).parse( zip.file( 'model.obj' ).asText() );
+						editor.execute( new AddObjectCommand( object ) );
+
+					}
+
+				}, false );
+				reader.readAsBinaryString( file );
+
+				break;
+
 			default:
 			default:
 
 
 				alert( 'Unsupported file format (' + extension +  ').' );
 				alert( 'Unsupported file format (' + extension +  ').' );

+ 24 - 15
editor/js/Menubar.File.js

@@ -172,6 +172,29 @@ Menubar.File = function ( editor ) {
 	} );
 	} );
 	options.add( option );
 	options.add( option );
 
 
+	//
+
+	options.add( new UI.HorizontalRule() );
+
+	// Export GLTF
+
+	var option = new UI.Row();
+	option.setClass( 'option' );
+	option.setTextContent( 'Export GLTF' );
+	option.onClick( function () {
+
+		var exporter = new THREE.GLTFExporter();
+
+		exporter.parse( editor.scene, function ( result ) {
+
+			saveString( JSON.stringify( result, null, 2 ), 'scene.gltf' );
+
+		} );
+
+
+	} );
+	options.add( option );
+
 	// Export OBJ
 	// Export OBJ
 
 
 	var option = new UI.Row();
 	var option = new UI.Row();
@@ -250,8 +273,6 @@ Menubar.File = function ( editor ) {
 
 
 			if ( vr ) {
 			if ( vr ) {
 
 
-				includes.push( '<script src="js/VRControls.js"></script>' );
-				includes.push( '<script src="js/VREffect.js"></script>' );
 				includes.push( '<script src="js/WebVR.js"></script>' );
 				includes.push( '<script src="js/WebVR.js"></script>' );
 
 
 			}
 			}
@@ -274,19 +295,7 @@ Menubar.File = function ( editor ) {
 
 
 		if ( vr ) {
 		if ( vr ) {
 
 
-			loader.load( '../examples/js/controls/VRControls.js', function ( content ) {
-
-				zip.file( 'js/VRControls.js', content );
-
-			} );
-
-			loader.load( '../examples/js/effects/VREffect.js', function ( content ) {
-
-				zip.file( 'js/VREffect.js', content );
-
-			} );
-
-			loader.load( '../examples/js/WebVR.js', function ( content ) {
+			loader.load( '../examples/js/vr/WebVR.js', function ( content ) {
 
 
 				zip.file( 'js/WebVR.js', content );
 				zip.file( 'js/WebVR.js', content );
 
 

+ 127 - 55
editor/js/Sidebar.Material.js

@@ -5,8 +5,11 @@
 Sidebar.Material = function ( editor ) {
 Sidebar.Material = function ( editor ) {
 
 
 	var signals = editor.signals;
 	var signals = editor.signals;
+
 	var currentObject;
 	var currentObject;
 
 
+	var currentMaterialSlot = 0;
+
 	var container = new UI.Panel();
 	var container = new UI.Panel();
 	container.setBorderTop( '0' );
 	container.setBorderTop( '0' );
 	container.setPaddingTop( '20px' );
 	container.setPaddingTop( '20px' );
@@ -14,13 +17,27 @@ Sidebar.Material = function ( editor ) {
 	// New / Copy / Paste
 	// New / Copy / Paste
 
 
 	var copiedMaterial;
 	var copiedMaterial;
+
 	var managerRow = new UI.Row();
 	var managerRow = new UI.Row();
 
 
+	// Current material slot
+
+	var materialSlotRow = new UI.Row();
+
+	materialSlotRow.add( new UI.Text( 'Slot' ).setWidth( '90px' ) );
+
+	var materialSlotSelect =  new UI.Select().setWidth( '170px' ).setFontSize( '12px' ).onChange( update );
+
+	materialSlotRow.add( materialSlotSelect );
+
+	container.add( materialSlotRow );
+
 	managerRow.add( new UI.Text( '' ).setWidth( '90px' ) );
 	managerRow.add( new UI.Text( '' ).setWidth( '90px' ) );
+
 	managerRow.add( new UI.Button( 'New' ).onClick( function () {
 	managerRow.add( new UI.Button( 'New' ).onClick( function () {
 
 
 		var material = new THREE[ materialClass.getValue() ]();
 		var material = new THREE[ materialClass.getValue() ]();
-		editor.execute( new SetMaterialCommand( currentObject, material ), 'New Material: ' + materialClass.getValue() );
+		editor.execute( new SetMaterialCommand( currentObject, material, currentMaterialSlot ), 'New Material: ' + materialClass.getValue() );
 		update();
 		update();
 
 
 	} ) );
 	} ) );
@@ -29,13 +46,21 @@ Sidebar.Material = function ( editor ) {
 
 
 		copiedMaterial = currentObject.material;
 		copiedMaterial = currentObject.material;
 
 
+		if ( Array.isArray( copiedMaterial ) ) {
+
+			if ( copiedMaterial.length === 0 ) return;
+
+			copiedMaterial = copiedMaterial[ currentMaterialSlot ];
+
+		}
+
 	} ) );
 	} ) );
 
 
 	managerRow.add( new UI.Button( 'Paste' ).setMarginLeft( '4px' ).onClick( function () {
 	managerRow.add( new UI.Button( 'Paste' ).setMarginLeft( '4px' ).onClick( function () {
 
 
 		if ( copiedMaterial === undefined ) return;
 		if ( copiedMaterial === undefined ) return;
 
 
-		editor.execute( new SetMaterialCommand( currentObject, copiedMaterial ), 'Pasted Material: ' + materialClass.getValue() );
+		editor.execute( new SetMaterialCommand( currentObject, copiedMaterial, currentMaterialSlot ), 'Pasted Material: ' + materialClass.getValue() );
 		refreshUI();
 		refreshUI();
 		update();
 		update();
 
 
@@ -90,7 +115,7 @@ Sidebar.Material = function ( editor ) {
 	var materialNameRow = new UI.Row();
 	var materialNameRow = new UI.Row();
 	var materialName = new UI.Input().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () {
 	var materialName = new UI.Input().setWidth( '150px' ).setFontSize( '12px' ).onChange( function () {
 
 
-		editor.execute( new SetMaterialValueCommand( editor.selected, 'name', materialName.getValue() ) );
+		editor.execute( new SetMaterialValueCommand( editor.selected, 'name', materialName.getValue(), currentMaterialSlot ) );
 
 
 	} );
 	} );
 
 
@@ -410,15 +435,9 @@ Sidebar.Material = function ( editor ) {
 	// shading
 	// shading
 
 
 	var materialShadingRow = new UI.Row();
 	var materialShadingRow = new UI.Row();
-	var materialShading = new UI.Select().setOptions( {
-
-		0: 'No',
-		1: 'Flat',
-		2: 'Smooth'
+	var materialShading = new UI.Checkbox(false).setLeft( '100px' ).onChange( update );
 
 
-	} ).setWidth( '150px' ).setFontSize( '12px' ).onChange( update );
-
-	materialShadingRow.add( new UI.Text( 'Shading' ).setWidth( '90px' ) );
+	materialShadingRow.add( new UI.Text( 'Flat Shaded' ).setWidth( '90px' ) );
 	materialShadingRow.add( materialShading );
 	materialShadingRow.add( materialShading );
 
 
 	container.add( materialShadingRow );
 	container.add( materialShadingRow );
@@ -493,6 +512,14 @@ Sidebar.Material = function ( editor ) {
 		var geometry = object.geometry;
 		var geometry = object.geometry;
 		var material = object.material;
 		var material = object.material;
 
 
+		var previousSelectedSlot = currentMaterialSlot;
+
+		currentMaterialSlot = parseInt( materialSlotSelect.getValue() );
+
+		if ( currentMaterialSlot !== previousSelectedSlot ) refreshUI( true );
+
+		material  = editor.getObjectMaterial( currentObject, currentMaterialSlot )
+
 		var textureWarning = false;
 		var textureWarning = false;
 		var objectHasUvs = false;
 		var objectHasUvs = false;
 
 
@@ -504,7 +531,7 @@ Sidebar.Material = function ( editor ) {
 
 
 			if ( material.uuid !== undefined && material.uuid !== materialUUID.getValue() ) {
 			if ( material.uuid !== undefined && material.uuid !== materialUUID.getValue() ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'uuid', materialUUID.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'uuid', materialUUID.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
@@ -512,7 +539,7 @@ Sidebar.Material = function ( editor ) {
 
 
 				material = new THREE[ materialClass.getValue() ]();
 				material = new THREE[ materialClass.getValue() ]();
 
 
-				editor.execute( new SetMaterialCommand( currentObject, material ), 'New Material: ' + materialClass.getValue() );
+				editor.execute( new SetMaterialCommand( currentObject, material, currentMaterialSlot ), 'New Material: ' + materialClass.getValue() );
 				// TODO Copy other references in the scene graph
 				// TODO Copy other references in the scene graph
 				// keeping name and UUID then.
 				// keeping name and UUID then.
 				// Also there should be means to create a unique
 				// Also there should be means to create a unique
@@ -523,49 +550,49 @@ Sidebar.Material = function ( editor ) {
 
 
 			if ( material.color !== undefined && material.color.getHex() !== materialColor.getHexValue() ) {
 			if ( material.color !== undefined && material.color.getHex() !== materialColor.getHexValue() ) {
 
 
-				editor.execute( new SetMaterialColorCommand( currentObject, 'color', materialColor.getHexValue() ) );
+				editor.execute( new SetMaterialColorCommand( currentObject, 'color', materialColor.getHexValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.roughness !== undefined && Math.abs( material.roughness - materialRoughness.getValue() ) >= 0.01 ) {
 			if ( material.roughness !== undefined && Math.abs( material.roughness - materialRoughness.getValue() ) >= 0.01 ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'roughness', materialRoughness.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'roughness', materialRoughness.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.metalness !== undefined && Math.abs( material.metalness - materialMetalness.getValue() ) >= 0.01 ) {
 			if ( material.metalness !== undefined && Math.abs( material.metalness - materialMetalness.getValue() ) >= 0.01 ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'metalness', materialMetalness.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'metalness', materialMetalness.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.emissive !== undefined && material.emissive.getHex() !== materialEmissive.getHexValue() ) {
 			if ( material.emissive !== undefined && material.emissive.getHex() !== materialEmissive.getHexValue() ) {
 
 
-				editor.execute( new SetMaterialColorCommand( currentObject, 'emissive', materialEmissive.getHexValue() ) );
+				editor.execute( new SetMaterialColorCommand( currentObject, 'emissive', materialEmissive.getHexValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.specular !== undefined && material.specular.getHex() !== materialSpecular.getHexValue() ) {
 			if ( material.specular !== undefined && material.specular.getHex() !== materialSpecular.getHexValue() ) {
 
 
-				editor.execute( new SetMaterialColorCommand( currentObject, 'specular', materialSpecular.getHexValue() ) );
+				editor.execute( new SetMaterialColorCommand( currentObject, 'specular', materialSpecular.getHexValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.shininess !== undefined && Math.abs( material.shininess - materialShininess.getValue() ) >= 0.01 ) {
 			if ( material.shininess !== undefined && Math.abs( material.shininess - materialShininess.getValue() ) >= 0.01 ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'shininess', materialShininess.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'shininess', materialShininess.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.clearCoat !== undefined && Math.abs( material.clearCoat - materialClearCoat.getValue() ) >= 0.01 ) {
 			if ( material.clearCoat !== undefined && Math.abs( material.clearCoat - materialClearCoat.getValue() ) >= 0.01 ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoat', materialClearCoat.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoat', materialClearCoat.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.clearCoatRoughness !== undefined && Math.abs( material.clearCoatRoughness - materialClearCoatRoughness.getValue() ) >= 0.01 ) {
 			if ( material.clearCoatRoughness !== undefined && Math.abs( material.clearCoatRoughness - materialClearCoatRoughness.getValue() ) >= 0.01 ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoatRoughness', materialClearCoatRoughness.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'clearCoatRoughness', materialClearCoatRoughness.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
@@ -575,7 +602,7 @@ Sidebar.Material = function ( editor ) {
 
 
 				if ( material.vertexColors !== vertexColors ) {
 				if ( material.vertexColors !== vertexColors ) {
 
 
-					editor.execute( new SetMaterialValueCommand( currentObject, 'vertexColors', vertexColors ) );
+					editor.execute( new SetMaterialValueCommand( currentObject, 'vertexColors', vertexColors, currentMaterialSlot ) );
 
 
 				}
 				}
 
 
@@ -583,7 +610,7 @@ Sidebar.Material = function ( editor ) {
 
 
 			if ( material.skinning !== undefined && material.skinning !== materialSkinning.getValue() ) {
 			if ( material.skinning !== undefined && material.skinning !== materialSkinning.getValue() ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'skinning', materialSkinning.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'skinning', materialSkinning.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
@@ -596,7 +623,7 @@ Sidebar.Material = function ( editor ) {
 					var map = mapEnabled ? materialMap.getValue() : null;
 					var map = mapEnabled ? materialMap.getValue() : null;
 					if ( material.map !== map ) {
 					if ( material.map !== map ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'map', map ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'map', map, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -617,7 +644,7 @@ Sidebar.Material = function ( editor ) {
 					var alphaMap = mapEnabled ? materialAlphaMap.getValue() : null;
 					var alphaMap = mapEnabled ? materialAlphaMap.getValue() : null;
 					if ( material.alphaMap !== alphaMap ) {
 					if ( material.alphaMap !== alphaMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'alphaMap', alphaMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'alphaMap', alphaMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -638,13 +665,13 @@ Sidebar.Material = function ( editor ) {
 					var bumpMap = bumpMapEnabled ? materialBumpMap.getValue() : null;
 					var bumpMap = bumpMapEnabled ? materialBumpMap.getValue() : null;
 					if ( material.bumpMap !== bumpMap ) {
 					if ( material.bumpMap !== bumpMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'bumpMap', bumpMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'bumpMap', bumpMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
 					if ( material.bumpScale !== materialBumpScale.getValue() ) {
 					if ( material.bumpScale !== materialBumpScale.getValue() ) {
 
 
-						editor.execute( new SetMaterialValueCommand( currentObject, 'bumpScale', materialBumpScale.getValue() ) );
+						editor.execute( new SetMaterialValueCommand( currentObject, 'bumpScale', materialBumpScale.getValue(), currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -665,7 +692,7 @@ Sidebar.Material = function ( editor ) {
 					var normalMap = normalMapEnabled ? materialNormalMap.getValue() : null;
 					var normalMap = normalMapEnabled ? materialNormalMap.getValue() : null;
 					if ( material.normalMap !== normalMap ) {
 					if ( material.normalMap !== normalMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'normalMap', normalMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'normalMap', normalMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -686,13 +713,13 @@ Sidebar.Material = function ( editor ) {
 					var displacementMap = displacementMapEnabled ? materialDisplacementMap.getValue() : null;
 					var displacementMap = displacementMapEnabled ? materialDisplacementMap.getValue() : null;
 					if ( material.displacementMap !== displacementMap ) {
 					if ( material.displacementMap !== displacementMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'displacementMap', displacementMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'displacementMap', displacementMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
 					if ( material.displacementScale !== materialDisplacementScale.getValue() ) {
 					if ( material.displacementScale !== materialDisplacementScale.getValue() ) {
 
 
-						editor.execute( new SetMaterialValueCommand( currentObject, 'displacementScale', materialDisplacementScale.getValue() ) );
+						editor.execute( new SetMaterialValueCommand( currentObject, 'displacementScale', materialDisplacementScale.getValue(), currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -713,7 +740,7 @@ Sidebar.Material = function ( editor ) {
 					var roughnessMap = roughnessMapEnabled ? materialRoughnessMap.getValue() : null;
 					var roughnessMap = roughnessMapEnabled ? materialRoughnessMap.getValue() : null;
 					if ( material.roughnessMap !== roughnessMap ) {
 					if ( material.roughnessMap !== roughnessMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'roughnessMap', roughnessMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'roughnessMap', roughnessMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -734,7 +761,7 @@ Sidebar.Material = function ( editor ) {
 					var metalnessMap = metalnessMapEnabled ? materialMetalnessMap.getValue() : null;
 					var metalnessMap = metalnessMapEnabled ? materialMetalnessMap.getValue() : null;
 					if ( material.metalnessMap !== metalnessMap ) {
 					if ( material.metalnessMap !== metalnessMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'metalnessMap', metalnessMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'metalnessMap', metalnessMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -755,7 +782,7 @@ Sidebar.Material = function ( editor ) {
 					var specularMap = specularMapEnabled ? materialSpecularMap.getValue() : null;
 					var specularMap = specularMapEnabled ? materialSpecularMap.getValue() : null;
 					if ( material.specularMap !== specularMap ) {
 					if ( material.specularMap !== specularMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'specularMap', specularMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'specularMap', specularMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -775,7 +802,7 @@ Sidebar.Material = function ( editor ) {
 
 
 				if ( material.envMap !== envMap ) {
 				if ( material.envMap !== envMap ) {
 
 
-					editor.execute( new SetMaterialMapCommand( currentObject, 'envMap', envMap ) );
+					editor.execute( new SetMaterialMapCommand( currentObject, 'envMap', envMap, currentMaterialSlot ) );
 
 
 				}
 				}
 
 
@@ -787,7 +814,7 @@ Sidebar.Material = function ( editor ) {
 
 
 				if ( material.reflectivity !== reflectivity ) {
 				if ( material.reflectivity !== reflectivity ) {
 
 
-					editor.execute( new SetMaterialValueCommand( currentObject, 'reflectivity', reflectivity ) );
+					editor.execute( new SetMaterialValueCommand( currentObject, 'reflectivity', reflectivity, currentMaterialSlot ) );
 
 
 				}
 				}
 
 
@@ -802,7 +829,7 @@ Sidebar.Material = function ( editor ) {
 					var lightMap = lightMapEnabled ? materialLightMap.getValue() : null;
 					var lightMap = lightMapEnabled ? materialLightMap.getValue() : null;
 					if ( material.lightMap !== lightMap ) {
 					if ( material.lightMap !== lightMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'lightMap', lightMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'lightMap', lightMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -823,13 +850,13 @@ Sidebar.Material = function ( editor ) {
 					var aoMap = aoMapEnabled ? materialAOMap.getValue() : null;
 					var aoMap = aoMapEnabled ? materialAOMap.getValue() : null;
 					if ( material.aoMap !== aoMap ) {
 					if ( material.aoMap !== aoMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'aoMap', aoMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'aoMap', aoMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
 					if ( material.aoMapIntensity !== materialAOScale.getValue() ) {
 					if ( material.aoMapIntensity !== materialAOScale.getValue() ) {
 
 
-						editor.execute( new SetMaterialValueCommand( currentObject, 'aoMapIntensity', materialAOScale.getValue() ) );
+						editor.execute( new SetMaterialValueCommand( currentObject, 'aoMapIntensity', materialAOScale.getValue(), currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -850,7 +877,7 @@ Sidebar.Material = function ( editor ) {
 					var emissiveMap = emissiveMapEnabled ? materialEmissiveMap.getValue() : null;
 					var emissiveMap = emissiveMapEnabled ? materialEmissiveMap.getValue() : null;
 					if ( material.emissiveMap !== emissiveMap ) {
 					if ( material.emissiveMap !== emissiveMap ) {
 
 
-						editor.execute( new SetMaterialMapCommand( currentObject, 'emissiveMap', emissiveMap ) );
+						editor.execute( new SetMaterialMapCommand( currentObject, 'emissiveMap', emissiveMap, currentMaterialSlot ) );
 
 
 					}
 					}
 
 
@@ -867,19 +894,19 @@ Sidebar.Material = function ( editor ) {
 				var side = parseInt( materialSide.getValue() );
 				var side = parseInt( materialSide.getValue() );
 				if ( material.side !== side ) {
 				if ( material.side !== side ) {
 
 
-					editor.execute( new SetMaterialValueCommand( currentObject, 'side', side ) );
+					editor.execute( new SetMaterialValueCommand( currentObject, 'side', side, currentMaterialSlot ) );
 
 
 				}
 				}
 
 
 
 
 			}
 			}
 
 
-			if ( material.shading !== undefined ) {
+			if ( material.flatShading !== undefined ) {
 
 
-				var shading = parseInt( materialShading.getValue() );
-				if ( material.shading !== shading ) {
+				var flatShading = materialShading.getValue();
+				if ( material.flatShading != flatShading ) {
 
 
-					editor.execute( new SetMaterialValueCommand( currentObject, 'shading', shading ) );
+					editor.execute( new SetMaterialValueCommand( currentObject, 'flatShading', flatShading, currentMaterialSlot ) );
 
 
 				}
 				}
 
 
@@ -890,7 +917,7 @@ Sidebar.Material = function ( editor ) {
 				var blending = parseInt( materialBlending.getValue() );
 				var blending = parseInt( materialBlending.getValue() );
 				if ( material.blending !== blending ) {
 				if ( material.blending !== blending ) {
 
 
-					editor.execute( new SetMaterialValueCommand( currentObject, 'blending', blending ) );
+					editor.execute( new SetMaterialValueCommand( currentObject, 'blending', blending, currentMaterialSlot ) );
 
 
 				}
 				}
 
 
@@ -898,31 +925,31 @@ Sidebar.Material = function ( editor ) {
 
 
 			if ( material.opacity !== undefined && Math.abs( material.opacity - materialOpacity.getValue() ) >= 0.01 ) {
 			if ( material.opacity !== undefined && Math.abs( material.opacity - materialOpacity.getValue() ) >= 0.01 ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'opacity', materialOpacity.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'opacity', materialOpacity.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.transparent !== undefined && material.transparent !== materialTransparent.getValue() ) {
 			if ( material.transparent !== undefined && material.transparent !== materialTransparent.getValue() ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'transparent', materialTransparent.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'transparent', materialTransparent.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.alphaTest !== undefined && Math.abs( material.alphaTest - materialAlphaTest.getValue() ) >= 0.01 ) {
 			if ( material.alphaTest !== undefined && Math.abs( material.alphaTest - materialAlphaTest.getValue() ) >= 0.01 ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'alphaTest', materialAlphaTest.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'alphaTest', materialAlphaTest.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
 			if ( material.wireframe !== undefined && material.wireframe !== materialWireframe.getValue() ) {
 			if ( material.wireframe !== undefined && material.wireframe !== materialWireframe.getValue() ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'wireframe', materialWireframe.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'wireframe', materialWireframe.getValue(), currentMaterialSlot) );
 
 
 			}
 			}
 
 
 			if ( material.wireframeLinewidth !== undefined && Math.abs( material.wireframeLinewidth - materialWireframeLinewidth.getValue() ) >= 0.01 ) {
 			if ( material.wireframeLinewidth !== undefined && Math.abs( material.wireframeLinewidth - materialWireframeLinewidth.getValue() ) >= 0.01 ) {
 
 
-				editor.execute( new SetMaterialValueCommand( currentObject, 'wireframeLinewidth', materialWireframeLinewidth.getValue() ) );
+				editor.execute( new SetMaterialValueCommand( currentObject, 'wireframeLinewidth', materialWireframeLinewidth.getValue(), currentMaterialSlot ) );
 
 
 			}
 			}
 
 
@@ -968,7 +995,7 @@ Sidebar.Material = function ( editor ) {
 			'aoMap': materialAOMapRow,
 			'aoMap': materialAOMapRow,
 			'emissiveMap': materialEmissiveMapRow,
 			'emissiveMap': materialEmissiveMapRow,
 			'side': materialSideRow,
 			'side': materialSideRow,
-			'shading': materialShadingRow,
+			'flatShading': materialShadingRow,
 			'blending': materialBlendingRow,
 			'blending': materialBlendingRow,
 			'opacity': materialOpacityRow,
 			'opacity': materialOpacityRow,
 			'transparent': materialTransparentRow,
 			'transparent': materialTransparentRow,
@@ -978,6 +1005,20 @@ Sidebar.Material = function ( editor ) {
 
 
 		var material = currentObject.material;
 		var material = currentObject.material;
 
 
+		if ( Array.isArray( material ) ) {
+
+			materialSlotRow.setDisplay( '' );
+
+			if ( material.length === 0 ) return;
+
+			material = material[ currentMaterialSlot ];
+
+		} else {
+
+			materialSlotRow.setDisplay( 'none' );
+
+		}
+
 		for ( var property in properties ) {
 		for ( var property in properties ) {
 
 
 			properties[ property ].setDisplay( material[ property ] !== undefined ? '' : 'none' );
 			properties[ property ].setDisplay( material[ property ] !== undefined ? '' : 'none' );
@@ -993,6 +1034,24 @@ Sidebar.Material = function ( editor ) {
 
 
 		var material = currentObject.material;
 		var material = currentObject.material;
 
 
+		if ( Array.isArray( material ) ) {
+
+			var slotOptions = {};
+
+			currentMaterialSlot = Math.max( 0, Math.min( material.length, currentMaterialSlot ) );
+
+			for ( var i = 0; i < material.length; i ++ ) {
+
+				slotOptions[ i ] = String( i + 1 ) + ': ' + material[ i ].name;
+
+			}
+
+			materialSlotSelect.setOptions( slotOptions ).setValue( currentMaterialSlot );
+
+		}
+
+		material = editor.getObjectMaterial( currentObject, currentMaterialSlot );
+
 		if ( material.uuid !== undefined ) {
 		if ( material.uuid !== undefined ) {
 
 
 			materialUUID.setValue( material.uuid );
 			materialUUID.setValue( material.uuid );
@@ -1229,9 +1288,9 @@ Sidebar.Material = function ( editor ) {
 
 
 		}
 		}
 
 
-		if ( material.shading !== undefined ) {
+		if ( material.flatShading !== undefined ) {
 
 
-			materialShading.setValue( material.shading );
+			materialShading.setValue( material.flatShading );
 
 
 		}
 		}
 
 
@@ -1279,8 +1338,21 @@ Sidebar.Material = function ( editor ) {
 
 
 	signals.objectSelected.add( function ( object ) {
 	signals.objectSelected.add( function ( object ) {
 
 
-		if ( object && object.material &&
-			Array.isArray( object.material ) === false ) {
+		var hasMaterial = false;
+
+		if ( object && object.material ) {
+
+			hasMaterial = true;
+
+			if ( Array.isArray( object.material ) && object.material.length === 0 ) {
+
+				hasMaterial = false;
+
+			}
+
+		}
+
+		if ( hasMaterial ) {
 
 
 			var objectChanged = object !== currentObject;
 			var objectChanged = object !== currentObject;
 
 

+ 3 - 62
editor/js/Viewport.js

@@ -22,18 +22,6 @@ var Viewport = function ( editor ) {
 
 
 	var objects = [];
 	var objects = [];
 
 
-	//
-
-	var vrEffect, vrControls;
-
-	if ( WEBVR.isAvailable() === true ) {
-
-		var vrCamera = new THREE.PerspectiveCamera();
-		vrCamera.projectionMatrix = camera.projectionMatrix;
-		camera.add( vrCamera );
-
-	}
-
 	// helpers
 	// helpers
 
 
 	var grid = new THREE.GridHelper( 60, 60 );
 	var grid = new THREE.GridHelper( 60, 60 );
@@ -283,12 +271,6 @@ var Viewport = function ( editor ) {
 
 
 	} );
 	} );
 
 
-	signals.enterVR.add( function () {
-
-		vrEffect.isPresenting ? vrEffect.exitPresent() : vrEffect.requestPresent();
-
-	} );
-
 	signals.themeChanged.add( function ( value ) {
 	signals.themeChanged.add( function ( value ) {
 
 
 		switch ( value ) {
 		switch ( value ) {
@@ -345,19 +327,6 @@ var Viewport = function ( editor ) {
 
 
 		container.dom.appendChild( renderer.domElement );
 		container.dom.appendChild( renderer.domElement );
 
 
-		if ( WEBVR.isAvailable() === true ) {
-
-			vrControls = new THREE.VRControls( vrCamera );
-			vrEffect = new THREE.VREffect( renderer );
-
-			window.addEventListener( 'vrdisplaypresentchange', function ( event ) {
-
-				effect.isPresenting ? signals.enteredVR.dispatch() : signals.exitedVR.dispatch();
-
-			}, false );
-
-		}
-
 		render();
 		render();
 
 
 	} );
 	} );
@@ -557,49 +526,21 @@ var Viewport = function ( editor ) {
 
 
 	//
 	//
 
 
-	function animate() {
-
-		requestAnimationFrame( animate );
-
-		if ( vrEffect && vrEffect.isPresenting ) {
-
-			render();
-
-		}
-
-	}
-
 	function render() {
 	function render() {
 
 
 		sceneHelpers.updateMatrixWorld();
 		sceneHelpers.updateMatrixWorld();
 		scene.updateMatrixWorld();
 		scene.updateMatrixWorld();
 
 
-		if ( vrEffect && vrEffect.isPresenting ) {
+		renderer.render( scene, camera );
 
 
-			vrControls.update();
+		if ( renderer instanceof THREE.RaytracingRenderer === false ) {
 
 
-			camera.updateMatrixWorld();
-
-			vrEffect.render( scene, vrCamera );
-			vrEffect.render( sceneHelpers, vrCamera );
-
-		} else {
-
-			renderer.render( scene, camera );
-
-			if ( renderer instanceof THREE.RaytracingRenderer === false ) {
-
-				renderer.render( sceneHelpers, camera );
-
-			}
+			renderer.render( sceneHelpers, camera );
 
 
 		}
 		}
 
 
-
 	}
 	}
 
 
-	requestAnimationFrame( animate );
-
 	return container;
 	return container;
 
 
 };
 };

+ 13 - 8
editor/js/commands/SetMaterialColorCommand.js

@@ -10,7 +10,7 @@
  * @constructor
  * @constructor
  */
  */
 
 
-var SetMaterialColorCommand = function ( object, attributeName, newValue ) {
+var SetMaterialColorCommand = function ( object, attributeName, newValue, slot ) {
 
 
 	Command.call( this );
 	Command.call( this );
 
 
@@ -20,24 +20,29 @@ var SetMaterialColorCommand = function ( object, attributeName, newValue ) {
 
 
 	this.object = object;
 	this.object = object;
 	this.attributeName = attributeName;
 	this.attributeName = attributeName;
-	this.oldValue = ( object !== undefined ) ? this.object.material[ this.attributeName ].getHex() : undefined;
-	this.newValue = newValue;
+	this.slot = slot;
+
+	var material = this.editor.getObjectMaterial( this.object, this.slot );
 
 
+	this.oldValue = ( material !== undefined ) ? material[ this.attributeName ].getHex() : undefined;
+	this.newValue = newValue;
+	
 };
 };
 
 
 SetMaterialColorCommand.prototype = {
 SetMaterialColorCommand.prototype = {
 
 
 	execute: function () {
 	execute: function () {
-
-		this.object.material[ this.attributeName ].setHex( this.newValue );
-		this.editor.signals.materialChanged.dispatch( this.object.material );
+		var material = this.editor.getObjectMaterial( this.object, this.slot )
+		material[ this.attributeName ].setHex( this.newValue );
+		this.editor.signals.materialChanged.dispatch( material );
 
 
 	},
 	},
 
 
 	undo: function () {
 	undo: function () {
+		var material = this.editor.getObjectMaterial( this.object, this.slot )
 
 
-		this.object.material[ this.attributeName ].setHex( this.oldValue );
-		this.editor.signals.materialChanged.dispatch( this.object.material );
+		material[ this.attributeName ].setHex( this.oldValue );
+		this.editor.signals.materialChanged.dispatch( material );
 
 
 	},
 	},
 
 

+ 14 - 5
editor/js/commands/SetMaterialCommand.js

@@ -9,7 +9,8 @@
  * @constructor
  * @constructor
  */
  */
 
 
-var SetMaterialCommand = function ( object, newMaterial ) {
+
+var SetMaterialCommand = function ( object, newMaterial , slot) {
 
 
 	Command.call( this );
 	Command.call( this );
 
 
@@ -17,23 +18,31 @@ var SetMaterialCommand = function ( object, newMaterial ) {
 	this.name = 'New Material';
 	this.name = 'New Material';
 
 
 	this.object = object;
 	this.object = object;
-	this.oldMaterial = ( object !== undefined ) ? object.material : undefined;
-	this.newMaterial = newMaterial;
 
 
+	this.slot = slot;
+
+	var material = this.editor.getObjectMaterial( this.object, this.slot );
+
+	this.oldMaterial = material;
+
+	this.newMaterial = newMaterial;
+	
 };
 };
 
 
 SetMaterialCommand.prototype = {
 SetMaterialCommand.prototype = {
 
 
 	execute: function () {
 	execute: function () {
+		
+		this.editor.setObjectMaterial( this.object, this.slot, this.newMaterial );
 
 
-		this.object.material = this.newMaterial;
 		this.editor.signals.materialChanged.dispatch( this.newMaterial );
 		this.editor.signals.materialChanged.dispatch( this.newMaterial );
 
 
 	},
 	},
 
 
 	undo: function () {
 	undo: function () {
+		
+		this.editor.setObjectMaterial( this.object, this.slot, this.oldMaterial );
 
 
-		this.object.material = this.oldMaterial;
 		this.editor.signals.materialChanged.dispatch( this.oldMaterial );
 		this.editor.signals.materialChanged.dispatch( this.oldMaterial );
 
 
 	},
 	},

+ 14 - 9
editor/js/commands/SetMaterialValueCommand.js

@@ -10,16 +10,20 @@
  * @constructor
  * @constructor
  */
  */
 
 
-var SetMaterialValueCommand = function ( object, attributeName, newValue ) {
+var SetMaterialValueCommand = function ( object, attributeName, newValue, slot ) {
 
 
 	Command.call( this );
 	Command.call( this );
 
 
 	this.type = 'SetMaterialValueCommand';
 	this.type = 'SetMaterialValueCommand';
 	this.name = 'Set Material.' + attributeName;
 	this.name = 'Set Material.' + attributeName;
 	this.updatable = true;
 	this.updatable = true;
+	this.slot = slot;
 
 
 	this.object = object;
 	this.object = object;
-	this.oldValue = ( object !== undefined ) ? object.material[ attributeName ] : undefined;
+
+	var material = this.editor.getObjectMaterial( this.object, this.slot );
+	
+	this.oldValue = ( material !== undefined ) ? material[ attributeName ] : undefined;
 	this.newValue = newValue;
 	this.newValue = newValue;
 	this.attributeName = attributeName;
 	this.attributeName = attributeName;
 
 
@@ -28,20 +32,21 @@ var SetMaterialValueCommand = function ( object, attributeName, newValue ) {
 SetMaterialValueCommand.prototype = {
 SetMaterialValueCommand.prototype = {
 
 
 	execute: function () {
 	execute: function () {
-
-		this.object.material[ this.attributeName ] = this.newValue;
-		this.object.material.needsUpdate = true;
+		var material = this.editor.getObjectMaterial( this.object, this.slot );
+		material[ this.attributeName ] = this.newValue;
+		material.needsUpdate = true;
 		this.editor.signals.objectChanged.dispatch( this.object );
 		this.editor.signals.objectChanged.dispatch( this.object );
-		this.editor.signals.materialChanged.dispatch( this.object.material );
+		this.editor.signals.materialChanged.dispatch( material );
 
 
 	},
 	},
 
 
 	undo: function () {
 	undo: function () {
+		var material = this.editor.getObjectMaterial( this.object, this.slot );
 
 
-		this.object.material[ this.attributeName ] = this.oldValue;
-		this.object.material.needsUpdate = true;
+		material[ this.attributeName ] = this.oldValue;
+		material.needsUpdate = true;
 		this.editor.signals.objectChanged.dispatch( this.object );
 		this.editor.signals.objectChanged.dispatch( this.object );
-		this.editor.signals.materialChanged.dispatch( this.object.material );
+		this.editor.signals.materialChanged.dispatch( material );
 
 
 	},
 	},
 
 

+ 26 - 40
editor/js/libs/app.js

@@ -9,19 +9,17 @@ var APP = {
 		var loader = new THREE.ObjectLoader();
 		var loader = new THREE.ObjectLoader();
 		var camera, scene, renderer;
 		var camera, scene, renderer;
 
 
-		var controls, effect, cameraVR, isVR;
-
 		var events = {};
 		var events = {};
 
 
-		this.dom = document.createElement( 'div' );
+		var dom = document.createElement( 'div' );
+
+		this.dom = dom;
 
 
 		this.width = 500;
 		this.width = 500;
 		this.height = 500;
 		this.height = 500;
 
 
 		this.load = function ( json ) {
 		this.load = function ( json ) {
 
 
-			isVR = json.project.vr;
-
 			renderer = new THREE.WebGLRenderer( { antialias: true } );
 			renderer = new THREE.WebGLRenderer( { antialias: true } );
 			renderer.setClearColor( 0x000000 );
 			renderer.setClearColor( 0x000000 );
 			renderer.setPixelRatio( window.devicePixelRatio );
 			renderer.setPixelRatio( window.devicePixelRatio );
@@ -36,7 +34,13 @@ var APP = {
 
 
 			}
 			}
 
 
-			this.dom.appendChild( renderer.domElement );
+			if ( json.project.vr ) {
+
+				renderer.vr.enabled = true;
+
+			}
+
+			dom.appendChild( renderer.domElement );
 
 
 			this.setScene( loader.parse( json.scene ) );
 			this.setScene( loader.parse( json.scene ) );
 			this.setCamera( loader.parse( json.camera ) );
 			this.setCamera( loader.parse( json.camera ) );
@@ -116,26 +120,20 @@ var APP = {
 			camera.aspect = this.width / this.height;
 			camera.aspect = this.width / this.height;
 			camera.updateProjectionMatrix();
 			camera.updateProjectionMatrix();
 
 
-			if ( isVR === true ) {
-
-				cameraVR = new THREE.PerspectiveCamera();
-				cameraVR.projectionMatrix = camera.projectionMatrix;
-				camera.add( cameraVR );
+			if ( renderer.vr.enabled ) {
 
 
-				controls = new THREE.VRControls( cameraVR );
-				effect = new THREE.VREffect( renderer );
+				WEBVR.checkAvailability().catch( function( message ) {
 
 
-				if ( WEBVR.isAvailable() === true ) {
+					dom.appendChild( WEBVR.getMessageContainer( message ) );
 
 
-					this.dom.appendChild( WEBVR.getButton( effect ) );
+				} );
 
 
-				}
+				WEBVR.getVRDisplay( function ( device ) {
 
 
-				if ( WEBVR.isLatestAvailable() === false ) {
+					renderer.vr.setDevice( device );
+					dom.appendChild( WEBVR.getButton( device, renderer.domElement ) );
 
 
-					this.dom.appendChild( WEBVR.getMessage() );
-
-				}
+				} );
 
 
 			}
 			}
 
 
@@ -177,12 +175,10 @@ var APP = {
 
 
 		}
 		}
 
 
-		var prevTime, request;
+		var prevTime;
 
 
 		function animate( time ) {
 		function animate( time ) {
 
 
-			request = requestAnimationFrame( animate );
-
 			try {
 			try {
 
 
 				dispatch( events.update, { time: time, delta: time - prevTime } );
 				dispatch( events.update, { time: time, delta: time - prevTime } );
@@ -193,18 +189,7 @@ var APP = {
 
 
 			}
 			}
 
 
-			if ( isVR === true ) {
-
-				camera.updateMatrixWorld();
-
-				controls.update();
-				effect.render( scene, cameraVR );
-
-			} else {
-
-				renderer.render( scene, camera );
-
-			}
+			renderer.render( scene, camera );
 
 
 			prevTime = time;
 			prevTime = time;
 
 
@@ -212,6 +197,8 @@ var APP = {
 
 
 		this.play = function () {
 		this.play = function () {
 
 
+			prevTime = performance.now();
+
 			document.addEventListener( 'keydown', onDocumentKeyDown );
 			document.addEventListener( 'keydown', onDocumentKeyDown );
 			document.addEventListener( 'keyup', onDocumentKeyUp );
 			document.addEventListener( 'keyup', onDocumentKeyUp );
 			document.addEventListener( 'mousedown', onDocumentMouseDown );
 			document.addEventListener( 'mousedown', onDocumentMouseDown );
@@ -223,8 +210,7 @@ var APP = {
 
 
 			dispatch( events.start, arguments );
 			dispatch( events.start, arguments );
 
 
-			request = requestAnimationFrame( animate );
-			prevTime = performance.now();
+			renderer.animate( animate );
 
 
 		};
 		};
 
 
@@ -241,15 +227,15 @@ var APP = {
 
 
 			dispatch( events.stop, arguments );
 			dispatch( events.stop, arguments );
 
 
-			cancelAnimationFrame( request );
+			renderer.animate( null );
 
 
 		};
 		};
 
 
 		this.dispose = function () {
 		this.dispose = function () {
 
 
-			while ( this.dom.children.length ) {
+			while ( dom.children.length ) {
 
 
-				this.dom.removeChild( this.dom.firstChild );
+				dom.removeChild( dom.firstChild );
 
 
 			}
 			}
 
 

+ 0 - 68
editor/js/libs/tern-threejs/threejs.js

@@ -1731,74 +1731,6 @@
       "!doc": "base class for immediate rendering objects.",
       "!doc": "base class for immediate rendering objects.",
       "!type": "fn()"
       "!type": "fn()"
     },
     },
-    "MorphBlendMesh": {
-      "!url": "http://threejs.org/docs/#Reference/extras/objects/MorphBlendMesh",
-      "prototype": {
-        "!proto": "THREE.Mesh.prototype",
-        "animationsMap": {
-          "!type": "object",
-          "!doc": "todo"
-        },
-        "animationsList": {
-          "!type": "array",
-          "!doc": "todo"
-        },
-        "setAnimationWeight": {
-          "!type": "fn(name: todo, weight: todo) -> todo",
-          "!doc": "todo"
-        },
-        "setAnimationFPS": {
-          "!type": "fn(name: todo, fps: todo) -> todo",
-          "!doc": "todo"
-        },
-        "createAnimation": {
-          "!type": "fn(name: todo, start: todo, end: todo, fps: todo) -> todo",
-          "!doc": "todo"
-        },
-        "playAnimation": {
-          "!type": "fn(name: todo) -> todo",
-          "!doc": "todo"
-        },
-        "update": {
-          "!type": "fn(delta: todo) -> todo",
-          "!doc": "todo"
-        },
-        "autoCreateAnimations": {
-          "!type": "fn(fps: todo) -> todo",
-          "!doc": "todo"
-        },
-        "setAnimationDuration": {
-          "!type": "fn(name: todo, duration: todo) -> todo",
-          "!doc": "todo"
-        },
-        "setAnimationDirectionForward": {
-          "!type": "fn(name: todo) -> todo",
-          "!doc": "todo"
-        },
-        "getAnimationDuration": {
-          "!type": "fn(name: todo) -> todo",
-          "!doc": "todo"
-        },
-        "getAnimationTime": {
-          "!type": "fn(name: todo) -> todo",
-          "!doc": "todo"
-        },
-        "setAnimationDirectionBackward": {
-          "!type": "fn(name: todo) -> todo",
-          "!doc": "todo"
-        },
-        "setAnimationTime": {
-          "!type": "fn(name: todo, time: todo) -> todo",
-          "!doc": "todo"
-        },
-        "stopAnimation": {
-          "!type": "fn(name: todo) -> todo",
-          "!doc": "todo"
-        }
-      },
-      "!doc": "todo",
-      "!type": "fn(geometry: todo, material: todo)"
-    },
     "AmbientLight": {
     "AmbientLight": {
       "!url": "http://threejs.org/docs/#Reference/lights/AmbientLight",
       "!url": "http://threejs.org/docs/#Reference/lights/AmbientLight",
       "prototype": {
       "prototype": {

+ 1 - 1
examples/canvas_ascii_effect.html

@@ -62,6 +62,7 @@
 				controls = new THREE.TrackballControls( camera );
 				controls = new THREE.TrackballControls( camera );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				var light = new THREE.PointLight( 0xffffff );
 				var light = new THREE.PointLight( 0xffffff );
 				light.position.set( 500, 500, 500 );
 				light.position.set( 500, 500, 500 );
@@ -82,7 +83,6 @@
 				scene.add( plane );
 				scene.add( plane );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setSize( width, height );
 				renderer.setSize( width, height );
 				// container.appendChild( renderer.domElement );
 				// container.appendChild( renderer.domElement );
 
 

+ 13 - 11
examples/canvas_camera_orthographic.html

@@ -26,6 +26,7 @@
 
 
 			var container, stats;
 			var container, stats;
 			var camera, scene, renderer;
 			var camera, scene, renderer;
+			var frustumSize = 1000;
 
 
 			init();
 			init();
 			animate();
 			animate();
@@ -43,12 +44,12 @@
 				info.innerHTML = '<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - orthographic view';
 				info.innerHTML = '<a href="http://threejs.org" target="_blank" rel="noopener">three.js</a> - orthographic view';
 				container.appendChild( info );
 				container.appendChild( info );
 
 
-				camera = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, - 500, 1000 );
-				camera.position.x = 200;
-				camera.position.y = 100;
-				camera.position.z = 200;
+				var aspect = window.innerWidth / window.innerHeight;
+				camera = new THREE.OrthographicCamera( frustumSize * aspect / - 2, frustumSize * aspect / 2, frustumSize / 2, frustumSize / - 2, 1, 2000 );
+				camera.position.y = 400;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				// Grid
 				// Grid
 
 
@@ -94,7 +95,6 @@
 				scene.add( directionalLight );
 				scene.add( directionalLight );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );
@@ -110,10 +110,12 @@
 
 
 			function onWindowResize() {
 			function onWindowResize() {
 
 
-				camera.left = window.innerWidth / - 2;
-				camera.right = window.innerWidth / 2;
-				camera.top = window.innerHeight / 2;
-				camera.bottom = window.innerHeight / - 2;
+				var aspect = window.innerWidth / window.innerHeight;
+
+				camera.left   = - frustumSize * aspect / 2;
+				camera.right  =   frustumSize * aspect / 2;
+				camera.top    =   frustumSize / 2;
+				camera.bottom = - frustumSize / 2;
 
 
 				camera.updateProjectionMatrix();
 				camera.updateProjectionMatrix();
 
 
@@ -137,8 +139,8 @@
 
 
 				var timer = Date.now() * 0.0001;
 				var timer = Date.now() * 0.0001;
 
 
-				camera.position.x = Math.cos( timer ) * 200;
-				camera.position.z = Math.sin( timer ) * 200;
+				camera.position.x = Math.cos( timer ) * 800;
+				camera.position.z = Math.sin( timer ) * 800;
 				camera.lookAt( scene.position );
 				camera.lookAt( scene.position );
 
 
 				renderer.render( scene, camera );
 				renderer.render( scene, camera );

+ 1 - 1
examples/canvas_camera_orthographic2.html

@@ -118,6 +118,7 @@
 				camera.position.z = 200;
 				camera.position.z = 200;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				// Grid
 				// Grid
 
 
@@ -163,7 +164,6 @@
 				scene.add( directionalLight );
 				scene.add( directionalLight );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_geometry_birds.html

@@ -342,6 +342,7 @@
 				camera.position.z = 450;
 				camera.position.z = 450;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xffffff );
 
 
 				birds = [];
 				birds = [];
 				boids = [];
 				boids = [];
@@ -366,7 +367,6 @@
 				}
 				}
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xffffff );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
 

+ 2 - 1
examples/canvas_geometry_cube.html

@@ -60,6 +60,8 @@
 				camera.position.z = 500;
 				camera.position.z = 500;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
+
 
 
 				// Cube
 				// Cube
 
 
@@ -90,7 +92,6 @@
 				scene.add( plane );
 				scene.add( plane );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_geometry_earth.html

@@ -62,6 +62,7 @@
 				camera.position.z = 500;
 				camera.position.z = 500;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xffffff );
 
 
 				group = new THREE.Group();
 				group = new THREE.Group();
 				scene.add( group );
 				scene.add( group );
@@ -111,7 +112,6 @@
 				group.add( mesh );
 				group.add( mesh );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xffffff );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_geometry_hierarchy.html

@@ -50,6 +50,7 @@
 				camera.position.z = 500;
 				camera.position.z = 500;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xffffff );
 
 
 				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
 				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
 				var material = new THREE.MeshNormalMaterial( { overdraw: 0.5 } );
 				var material = new THREE.MeshNormalMaterial( { overdraw: 0.5 } );
@@ -73,7 +74,6 @@
 				scene.add( group );
 				scene.add( group );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xffffff );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_geometry_nurbs.html

@@ -71,6 +71,7 @@
 				camera.position.set( 0, 150, 500 );
 				camera.position.set( 0, 150, 500 );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				group = new THREE.Group();
 				group = new THREE.Group();
 				group.position.y = 50;
 				group.position.y = 50;
@@ -127,7 +128,6 @@
 				//
 				//
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_geometry_shapes.html

@@ -61,6 +61,7 @@
 				camera.position.set( 0, 150, 500 );
 				camera.position.set( 0, 150, 500 );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				group = new THREE.Group();
 				group = new THREE.Group();
 				group.position.y = 50;
 				group.position.y = 50;
@@ -293,7 +294,6 @@
 				//
 				//
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.sortElements = false;
 				renderer.sortElements = false;

+ 1 - 1
examples/canvas_geometry_terrain.html

@@ -67,6 +67,7 @@
 				camera.position.z = 500;
 				camera.position.z = 500;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xbfd1e5 );
 
 
 				var data = generateHeight( 1024, 1024 );
 				var data = generateHeight( 1024, 1024 );
 				var texture = new THREE.CanvasTexture( generateTexture( data, 1024, 1024 ) );
 				var texture = new THREE.CanvasTexture( generateTexture( data, 1024, 1024 ) );
@@ -88,7 +89,6 @@
 				scene.add( mesh );
 				scene.add( mesh );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xbfd1e5 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
 

+ 1 - 1
examples/canvas_geometry_text.html

@@ -66,6 +66,7 @@
 				camera.position.set( 0, 150, 500 );
 				camera.position.set( 0, 150, 500 );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				// Get text from hash
 				// Get text from hash
 
 
@@ -112,7 +113,6 @@
 				scene.add( group );
 				scene.add( group );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_interactive_cubes.html

@@ -53,6 +53,7 @@
 				camera.position.set( 0, 300, 500 );
 				camera.position.set( 0, 300, 500 );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
 				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
 
 
@@ -97,7 +98,6 @@
 				mouse = new THREE.Vector2();
 				mouse = new THREE.Vector2();
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_interactive_cubes_tween.html

@@ -52,6 +52,7 @@
 				camera.position.z = 500;
 				camera.position.z = 500;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
 				var geometry = new THREE.BoxGeometry( 100, 100, 100 );
 
 
@@ -77,7 +78,6 @@
 				mouse = new THREE.Vector2();
 				mouse = new THREE.Vector2();
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild(renderer.domElement);
 				container.appendChild(renderer.domElement);

+ 1 - 1
examples/canvas_interactive_particles.html

@@ -71,6 +71,7 @@
 				camera.position.set( 0, 300, 500 );
 				camera.position.set( 0, 300, 500 );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				for ( var i = 0; i < 100; i ++ ) {
 				for ( var i = 0; i < 100; i ++ ) {
 
 
@@ -89,7 +90,6 @@
 				mouse = new THREE.Vector2();
 				mouse = new THREE.Vector2();
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_interactive_voxelpainter.html

@@ -54,6 +54,7 @@
 				camera.lookAt( new THREE.Vector3() );
 				camera.lookAt( new THREE.Vector3() );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				// Grid
 				// Grid
 
 
@@ -95,7 +96,6 @@
 				scene.add( directionalLight );
 				scene.add( directionalLight );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild(renderer.domElement);
 				container.appendChild(renderer.domElement);

+ 2 - 4
examples/canvas_lines_dashed.html

@@ -61,8 +61,7 @@
 				camera.position.z = 150;
 				camera.position.z = 150;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
-
-				scene.fog = new THREE.Fog( 0x111111, 150, 200 );
+				scene.background = new THREE.Color( 0x111111 );
 
 
 				root = new THREE.Object3D();
 				root = new THREE.Object3D();
 
 
@@ -93,13 +92,12 @@
 				objects.push( object );
 				objects.push( object );
 				scene.add( object );
 				scene.add( object );
 
 
-				var object = new THREE.LineSegments( geometryCube, new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 3, gapSize: 1, linewidth: 2 } ) );
+				var object = new THREE.LineSegments( geometryCube, new THREE.LineDashedMaterial( { color: 0xffaa00, dashSize: 30, gapSize: 10, linewidth: 2 } ) );
 
 
 				objects.push( object );
 				objects.push( object );
 				scene.add( object );
 				scene.add( object );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0x111111 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( WIDTH, HEIGHT );
 				renderer.setSize( WIDTH, HEIGHT );
 
 

+ 1 - 1
examples/canvas_materials_video.html

@@ -67,6 +67,7 @@
 				camera.position.z = 1000;
 				camera.position.z = 1000;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				video = document.getElementById( 'video' );
 				video = document.getElementById( 'video' );
 
 
@@ -150,7 +151,6 @@
 				}
 				}
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_morphtargets_horse.html

@@ -51,6 +51,7 @@
 				camera.target = new THREE.Vector3( 0, 150, 0 );
 				camera.target = new THREE.Vector3( 0, 150, 0 );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				//
 				//
 
 
@@ -85,7 +86,6 @@
 				//
 				//
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild(renderer.domElement);
 				container.appendChild(renderer.domElement);

+ 1 - 1
examples/canvas_particles_sprites.html

@@ -47,6 +47,7 @@
 				camera.position.z = 1000;
 				camera.position.z = 1000;
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0x000040 );
 
 
 				var material = new THREE.SpriteMaterial( {
 				var material = new THREE.SpriteMaterial( {
 					map: new THREE.CanvasTexture( generateSprite() ),
 					map: new THREE.CanvasTexture( generateSprite() ),
@@ -63,7 +64,6 @@
 				}
 				}
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0x000040 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_performance.html

@@ -39,6 +39,7 @@
 				document.body.appendChild( container );
 				document.body.appendChild( container );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
 				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
 				camera.position.set( 0, 1000, 1000 );
 				camera.position.set( 0, 1000, 1000 );
@@ -79,7 +80,6 @@
 				scene.add( light );
 				scene.add( light );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 1 - 1
examples/canvas_sandbox.html

@@ -44,6 +44,7 @@
 				var controls = new THREE.OrbitControls( camera );
 				var controls = new THREE.OrbitControls( camera );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
 
 
 				// Grid
 				// Grid
 
 
@@ -81,7 +82,6 @@
 				}
 				}
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				container.appendChild( renderer.domElement );
 				container.appendChild( renderer.domElement );

+ 18 - 29
examples/css3d_molecules.html

@@ -11,14 +11,7 @@
 
 
 			body {
 			body {
 				background-color: #050505;
 				background-color: #050505;
-
-				background: rgb(43,45,48); /* Old browsers */
-				background: -moz-radial-gradient(center, ellipse cover,  rgba(43,45,48,1) 0%, rgba(0,0,0,1) 100%); /* FF3.6+ */
-				background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(43,45,48,1)), color-stop(100%,rgba(0,0,0,1))); /* Chrome,Safari4+ */
-				background: -webkit-radial-gradient(center, ellipse cover,  rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* Chrome10+,Safari5.1+ */
-				background: -o-radial-gradient(center, ellipse cover,  rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* Opera 12+ */
-				background: -ms-radial-gradient(center, ellipse cover,  rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* IE10+ */
-				background: radial-gradient(ellipse at center,  rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%); /* W3C */
+				background: radial-gradient(ellipse at center,  rgba(43,45,48,1) 0%,rgba(0,0,0,1) 100%);
 
 
 				margin: 0;
 				margin: 0;
 				font-family: Arial;
 				font-family: Arial;
@@ -286,27 +279,18 @@
 
 
 			//
 			//
 
 
-			function colorify( ctx, width, height, color, a ) {
+			function colorify( ctx, width, height, color ) {
 
 
-				var r = color.r;
-				var g = color.g;
-				var b = color.b;
+				var r = color.r, g = color.g, b = color.b;
 
 
 				var imageData = ctx.getImageData( 0, 0, width, height );
 				var imageData = ctx.getImageData( 0, 0, width, height );
 				var data = imageData.data;
 				var data = imageData.data;
 
 
-				for ( var y = 0; y < height; y ++ ) {
-
-					for ( var x = 0; x < width; x ++ ) {
-
-						var index = ( y * width + x ) * 4;
+				for ( var i = 0, l = data.length; i < l; i += 4 ) {
 
 
-						data[ index ]     *= r;
-						data[ index + 1 ] *= g;
-						data[ index + 2 ] *= b;
-						data[ index + 3 ] *= a;
-
-					}
+					data[ i + 0 ] *= r;
+					data[ i + 1 ] *= g;
+					data[ i + 2 ] *= b;
 
 
 				}
 				}
 
 
@@ -344,13 +328,17 @@
 
 
 				objects = [];
 				objects = [];
 
 
-				loader.load( url, function ( geometry, geometryBonds ) {
+				loader.load( url, function ( pdb ) {
+
+					var geometryAtoms = pdb.geometryAtoms;
+					var geometryBonds = pdb.geometryBonds;
+					var json = pdb.json;
 
 
-					var offset = geometry.center();
+					var offset = geometryAtoms.center();
 					geometryBonds.translate( offset.x, offset.y, offset.z );
 					geometryBonds.translate( offset.x, offset.y, offset.z );
 
 
-					var positions = geometry.getAttribute( 'position' );
-					var colors = geometry.getAttribute( 'color' );
+					var positions = geometryAtoms.getAttribute( 'position' );
+					var colors = geometryAtoms.getAttribute( 'color' );
 
 
 					var position = new THREE.Vector3();
 					var position = new THREE.Vector3();
 					var color = new THREE.Color();
 					var color = new THREE.Color();
@@ -365,14 +353,15 @@
 						color.g = colors.getY( i );
 						color.g = colors.getY( i );
 						color.b = colors.getZ( i );
 						color.b = colors.getZ( i );
 
 
-						var element = geometry.elements[ i ];
+						var atom = json.atoms[ i ];
+						var element = atom[ 4 ];
 
 
 						if ( ! colorSpriteMap[ element ] ) {
 						if ( ! colorSpriteMap[ element ] ) {
 
 
 							var canvas = imageToCanvas( baseSprite );
 							var canvas = imageToCanvas( baseSprite );
 							var context = canvas.getContext( '2d' );
 							var context = canvas.getContext( '2d' );
 
 
-							colorify( context, canvas.width, canvas.height, color, 1 );
+							colorify( context, canvas.width, canvas.height, color );
 
 
 							var dataUrl = canvas.toDataURL();
 							var dataUrl = canvas.toDataURL();
 
 

+ 2 - 1
examples/css3d_sandbox.html

@@ -55,6 +55,8 @@
 				controls = new THREE.TrackballControls( camera );
 				controls = new THREE.TrackballControls( camera );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
+				scene.background = new THREE.Color( 0xf0f0f0 );
+
 				scene2 = new THREE.Scene();
 				scene2 = new THREE.Scene();
 
 
 				var material = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframeLinewidth: 1, side: THREE.DoubleSide } );
 				var material = new THREE.MeshBasicMaterial( { color: 0x000000, wireframe: true, wireframeLinewidth: 1, side: THREE.DoubleSide } );
@@ -92,7 +94,6 @@
 				//
 				//
 
 
 				renderer = new THREE.WebGLRenderer();
 				renderer = new THREE.WebGLRenderer();
-				renderer.setClearColor( 0xf0f0f0 );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				document.body.appendChild( renderer.domElement );
 				document.body.appendChild( renderer.domElement );

+ 10 - 4
examples/files.js

@@ -18,7 +18,6 @@ var files = {
 		"webgl_effects_parallaxbarrier",
 		"webgl_effects_parallaxbarrier",
 		"webgl_effects_peppersghost",
 		"webgl_effects_peppersghost",
 		"webgl_effects_stereo",
 		"webgl_effects_stereo",
-		"webgl_exporter_obj",
 		"webgl_geometries",
 		"webgl_geometries",
 		"webgl_geometries2",
 		"webgl_geometries2",
 		"webgl_geometry_colors",
 		"webgl_geometry_colors",
@@ -91,7 +90,7 @@ var files = {
 		"webgl_loader_ctm_materials",
 		"webgl_loader_ctm_materials",
 		"webgl_loader_draco",
 		"webgl_loader_draco",
 		"webgl_loader_fbx",
 		"webgl_loader_fbx",
-		"webgl_loader_gltf2",
+		"webgl_loader_gltf",
 		"webgl_loader_imagebitmap",
 		"webgl_loader_imagebitmap",
 		"webgl_loader_json_blender",
 		"webgl_loader_json_blender",
 		"webgl_loader_json_claraio",
 		"webgl_loader_json_claraio",
@@ -110,6 +109,7 @@ var files = {
 		"webgl_loader_nrrd",
 		"webgl_loader_nrrd",
 		"webgl_loader_pcd",
 		"webgl_loader_pcd",
 		"webgl_loader_pdb",
 		"webgl_loader_pdb",
+		"webgl_loader_playcanvas",
 		"webgl_loader_ply",
 		"webgl_loader_ply",
 		"webgl_loader_prwm",
 		"webgl_loader_prwm",
 		"webgl_loader_ttf",
 		"webgl_loader_ttf",
@@ -146,7 +146,6 @@ var files = {
 		"webgl_materials_envmaps_hdr",
 		"webgl_materials_envmaps_hdr",
 		"webgl_materials_grass",
 		"webgl_materials_grass",
 		"webgl_materials_lightmap",
 		"webgl_materials_lightmap",
-		"webgl_materials_modified",
 		"webgl_materials_nodes",
 		"webgl_materials_nodes",
 		"webgl_materials_normalmap",
 		"webgl_materials_normalmap",
 		"webgl_materials_parallaxmap",
 		"webgl_materials_parallaxmap",
@@ -221,7 +220,9 @@ var files = {
 		"webgl_postprocessing_nodes",
 		"webgl_postprocessing_nodes",
 		"webgl_postprocessing_outline",
 		"webgl_postprocessing_outline",
 		"webgl_postprocessing_procedural",
 		"webgl_postprocessing_procedural",
+		"webgl_postprocessing_sao",
 		"webgl_postprocessing_smaa",
 		"webgl_postprocessing_smaa",
+		"webgl_postprocessing_sobel",
 		"webgl_postprocessing_ssao",
 		"webgl_postprocessing_ssao",
 		"webgl_postprocessing_taa",
 		"webgl_postprocessing_taa",
 		"webgl_postprocessing_unreal_bloom",
 		"webgl_postprocessing_unreal_bloom",
@@ -276,7 +277,9 @@ var files = {
 		"webgl_custom_attributes_points",
 		"webgl_custom_attributes_points",
 		"webgl_custom_attributes_points2",
 		"webgl_custom_attributes_points2",
 		"webgl_custom_attributes_points3",
 		"webgl_custom_attributes_points3",
-		"webgl_raymarching_reflect"
+		"webgl_materials_modified",
+		"webgl_raymarching_reflect",
+		"webgl_shadowmap_pcss"
 	],
 	],
 	"webgl deferred": [
 	"webgl deferred": [
 		"webgldeferred_animation"
 		"webgldeferred_animation"
@@ -317,10 +320,13 @@ var files = {
 		"misc_controls_pointerlock",
 		"misc_controls_pointerlock",
 		"misc_controls_trackball",
 		"misc_controls_trackball",
 		"misc_controls_transform",
 		"misc_controls_transform",
+		"misc_exporter_gltf",
+		"misc_exporter_obj",
 		"misc_fps",
 		"misc_fps",
 		"misc_lights_test",
 		"misc_lights_test",
 		"misc_lookat",
 		"misc_lookat",
 		"misc_sound",
 		"misc_sound",
+		"misc_sound_visualizer",
 		"misc_ubiquity_test",
 		"misc_ubiquity_test",
 		"misc_ubiquity_test2",
 		"misc_ubiquity_test2",
 		"misc_uv_tests"
 		"misc_uv_tests"

+ 25 - 21
examples/index.html

@@ -304,6 +304,27 @@
 		var links = {};
 		var links = {};
 		var selected = null;
 		var selected = null;
 
 
+		function createLink( file ) {
+
+			var link = document.createElement( 'a' );
+			link.className = 'link';
+			link.href = file + '.html';
+			link.textContent = getName( file );
+			link.setAttribute( 'target', 'viewer' );
+			link.addEventListener( 'click', function ( event ) {
+
+				if ( event.button === 0 ) {
+
+					selectFile( file );
+
+				}
+
+			} );
+
+			return link;
+
+		}
+
 		for ( var key in files ) {
 		for ( var key in files ) {
 
 
 			var section = files[ key ];
 			var section = files[ key ];
@@ -315,29 +336,12 @@
 
 
 			for ( var i = 0; i < section.length; i ++ ) {
 			for ( var i = 0; i < section.length; i ++ ) {
 
 
-				( function ( file ) {
-
-					var name = getName( file );
-
-					var link = document.createElement( 'a' );
-					link.className = 'link';
-					link.textContent = name;
-					link.href = file + '.html';
-					link.setAttribute( 'target', 'viewer' );
-					link.addEventListener( 'click', function ( event ) {
-
-						if ( event.button === 0 ) {
-
-							selectFile( file );
-
-						}
-
-					} );
-					container.appendChild( link );
+				var file = section[ i ];
 
 
-					links[ file ] = link;
+				var link = createLink( file );
+				container.appendChild( link );
 
 
-				} )( section[ i ] );
+				links[ file ] = link;
 
 
 			}
 			}
 
 

+ 1 - 1
examples/js/GPUParticleSystem.js

@@ -77,7 +77,7 @@ THREE.GPUParticleSystem = function( options ) {
 			'	v.y = ( velocity.y - 0.5 ) * 3.0;',
 			'	v.y = ( velocity.y - 0.5 ) * 3.0;',
 			'	v.z = ( velocity.z - 0.5 ) * 3.0;',
 			'	v.z = ( velocity.z - 0.5 ) * 3.0;',
 
 
-			'	newPosition = positionStart + ( v * 10.0 ) * ( uTime - startTime );',
+			'	newPosition = positionStart + ( v * 10.0 ) * timeElapsed;',
 
 
 			'	vec3 noise = texture2D( tNoise, vec2( newPosition.x * 0.015 + ( uTime * 0.05 ), newPosition.y * 0.02 + ( uTime * 0.015 ) ) ).rgb;',
 			'	vec3 noise = texture2D( tNoise, vec2( newPosition.x * 0.015 + ( uTime * 0.05 ), newPosition.y * 0.02 + ( uTime * 0.015 ) ) ).rgb;',
 			'	vec3 noiseVel = ( noise.rgb - 0.5 ) * 30.0;',
 			'	vec3 noiseVel = ( noise.rgb - 0.5 ) * 30.0;',

+ 23 - 2
examples/js/Mirror.js

@@ -13,6 +13,8 @@ THREE.Mirror = function ( width, height, options ) {
 
 
 	options = options || {};
 	options = options || {};
 
 
+	var viewport = new THREE.Vector4();
+
 	var textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512;
 	var textureWidth = options.textureWidth !== undefined ? options.textureWidth : 512;
 	var textureHeight = options.textureHeight !== undefined ? options.textureHeight : 512;
 	var textureHeight = options.textureHeight !== undefined ? options.textureHeight : 512;
 
 
@@ -134,11 +136,12 @@ THREE.Mirror = function ( width, height, options ) {
 		target.add( mirrorWorldPosition );
 		target.add( mirrorWorldPosition );
 
 
 		mirrorCamera.position.copy( view );
 		mirrorCamera.position.copy( view );
-		mirrorCamera.up.set( 0, - 1, 0 );
+		mirrorCamera.up.set( 0, 1, 0 );
 		mirrorCamera.up.applyMatrix4( rotationMatrix );
 		mirrorCamera.up.applyMatrix4( rotationMatrix );
-		mirrorCamera.up.reflect( normal ).negate();
+		mirrorCamera.up.reflect( normal );
 		mirrorCamera.lookAt( target );
 		mirrorCamera.lookAt( target );
 
 
+		mirrorCamera.aspect = camera.aspect;
 		mirrorCamera.near = camera.near;
 		mirrorCamera.near = camera.near;
 		mirrorCamera.far = camera.far;
 		mirrorCamera.far = camera.far;
 
 
@@ -201,6 +204,24 @@ THREE.Mirror = function ( width, height, options ) {
 
 
 		renderer.setRenderTarget( currentRenderTarget );
 		renderer.setRenderTarget( currentRenderTarget );
 
 
+		// Restore viewport
+
+		var bounds = camera.bounds;
+
+		if ( bounds !== undefined ) {
+
+			var size = renderer.getSize();
+			var pixelRatio = renderer.getPixelRatio();
+
+			viewport.x = bounds.x * size.width * pixelRatio;
+			viewport.y = bounds.y * size.height * pixelRatio;
+			viewport.z = bounds.z * size.width * pixelRatio;
+			viewport.w = bounds.w * size.height * pixelRatio;
+
+			renderer.state.viewport( viewport );
+
+		}
+
 		scope.visible = true;
 		scope.visible = true;
 
 
 	};
 	};

+ 318 - 0
examples/js/MorphBlendMesh.js

@@ -0,0 +1,318 @@
+/**
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.MorphBlendMesh = function ( geometry, material ) {
+
+	THREE.Mesh.call( this, geometry, material );
+
+	this.animationsMap = {};
+	this.animationsList = [];
+
+	// prepare default animation
+	// (all frames played together in 1 second)
+
+	var numFrames = this.geometry.morphTargets.length;
+
+	var name = "__default";
+
+	var startFrame = 0;
+	var endFrame = numFrames - 1;
+
+	var fps = numFrames / 1;
+
+	this.createAnimation( name, startFrame, endFrame, fps );
+	this.setAnimationWeight( name, 1 );
+
+}
+
+THREE.MorphBlendMesh.prototype = Object.assign( Object.create( THREE.Mesh.prototype ), {
+
+	constructor: THREE.MorphBlendMesh,
+
+	createAnimation: function ( name, start, end, fps ) {
+
+		var animation = {
+
+			start: start,
+			end: end,
+
+			length: end - start + 1,
+
+			fps: fps,
+			duration: ( end - start ) / fps,
+
+			lastFrame: 0,
+			currentFrame: 0,
+
+			active: false,
+
+			time: 0,
+			direction: 1,
+			weight: 1,
+
+			directionBackwards: false,
+			mirroredLoop: false
+
+		};
+
+		this.animationsMap[ name ] = animation;
+		this.animationsList.push( animation );
+
+	},
+
+		autoCreateAnimations: function ( fps ) {
+
+		var pattern = /([a-z]+)_?(\d+)/i;
+
+		var firstAnimation, frameRanges = {};
+
+		var geometry = this.geometry;
+
+		for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
+
+			var morph = geometry.morphTargets[ i ];
+			var chunks = morph.name.match( pattern );
+
+			if ( chunks && chunks.length > 1 ) {
+
+				var name = chunks[ 1 ];
+
+				if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity };
+
+				var range = frameRanges[ name ];
+
+				if ( i < range.start ) range.start = i;
+				if ( i > range.end ) range.end = i;
+
+				if ( ! firstAnimation ) firstAnimation = name;
+
+			}
+
+		}
+
+		for ( var name in frameRanges ) {
+
+			var range = frameRanges[ name ];
+			this.createAnimation( name, range.start, range.end, fps );
+
+		}
+
+		this.firstAnimation = firstAnimation;
+
+	},
+
+	setAnimationDirectionForward: function ( name ) {
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			animation.direction = 1;
+			animation.directionBackwards = false;
+
+		}
+
+	},
+
+	setAnimationDirectionBackward: function ( name ) {
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			animation.direction = - 1;
+			animation.directionBackwards = true;
+
+		}
+
+	},
+
+	setAnimationFPS: function ( name, fps ) {
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			animation.fps = fps;
+			animation.duration = ( animation.end - animation.start ) / animation.fps;
+
+		}
+
+	},
+
+	setAnimationDuration: function ( name, duration ) {
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			animation.duration = duration;
+			animation.fps = ( animation.end - animation.start ) / animation.duration;
+
+		}
+
+	},
+
+	setAnimationWeight: function ( name, weight ) {
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			animation.weight = weight;
+
+		}
+
+	},
+
+	setAnimationTime: function ( name, time ) {
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			animation.time = time;
+
+		}
+
+	},
+
+	getAnimationTime: function ( name ) {
+
+		var time = 0;
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			time = animation.time;
+
+		}
+
+		return time;
+
+	},
+
+	getAnimationDuration: function ( name ) {
+
+		var duration = - 1;
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			duration = animation.duration;
+
+		}
+
+		return duration;
+
+	},
+
+	playAnimation: function ( name ) {
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			animation.time = 0;
+			animation.active = true;
+
+		} else {
+
+			console.warn( "THREE.MorphBlendMesh: animation[" + name + "] undefined in .playAnimation()" );
+
+		}
+
+	},
+
+	stopAnimation: function ( name ) {
+
+		var animation = this.animationsMap[ name ];
+
+		if ( animation ) {
+
+			animation.active = false;
+
+		}
+
+	},
+
+	update: function ( delta ) {
+
+		for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) {
+
+			var animation = this.animationsList[ i ];
+
+			if ( ! animation.active ) continue;
+
+			var frameTime = animation.duration / animation.length;
+
+			animation.time += animation.direction * delta;
+
+			if ( animation.mirroredLoop ) {
+
+				if ( animation.time > animation.duration || animation.time < 0 ) {
+
+					animation.direction *= - 1;
+
+					if ( animation.time > animation.duration ) {
+
+						animation.time = animation.duration;
+						animation.directionBackwards = true;
+
+					}
+
+					if ( animation.time < 0 ) {
+
+						animation.time = 0;
+						animation.directionBackwards = false;
+
+					}
+
+				}
+
+			} else {
+
+				animation.time = animation.time % animation.duration;
+
+				if ( animation.time < 0 ) animation.time += animation.duration;
+
+			}
+
+			var keyframe = animation.start + THREE.Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 );
+			var weight = animation.weight;
+
+			if ( keyframe !== animation.currentFrame ) {
+
+				this.morphTargetInfluences[ animation.lastFrame ] = 0;
+				this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight;
+
+				this.morphTargetInfluences[ keyframe ] = 0;
+
+				animation.lastFrame = animation.currentFrame;
+				animation.currentFrame = keyframe;
+
+			}
+
+			var mix = ( animation.time % frameTime ) / frameTime;
+
+			if ( animation.directionBackwards ) mix = 1 - mix;
+
+			if ( animation.currentFrame !== animation.lastFrame ) {
+
+				this.morphTargetInfluences[ animation.currentFrame ] = mix * weight;
+				this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight;
+
+			} else {
+
+				this.morphTargetInfluences[ animation.currentFrame ] = weight;
+
+			}
+
+		}
+
+	}
+
+} );

+ 40 - 23
examples/js/animation/MMDPhysics.js

@@ -57,9 +57,14 @@ THREE.MMDPhysics.prototype = {
 
 
 		}
 		}
 
 
-		var currentPosition = mesh.position.clone();
-		var currentRotation = mesh.rotation.clone();
-		var currentScale = mesh.scale.clone();
+		var helper = this.helper;
+		var currentPosition = helper.allocThreeVector3();
+		var currentRotation = helper.allocThreeVector3();
+		var currentScale = helper.allocThreeVector3();
+
+		currentPosition.copy( mesh.position );
+		currentRotation.copy( mesh.rotation );
+		currentScale.copy( mesh.scale );
 
 
 		mesh.position.set( 0, 0, 0 );
 		mesh.position.set( 0, 0, 0 );
 		mesh.rotation.set( 0, 0, 0 );
 		mesh.rotation.set( 0, 0, 0 );
@@ -85,6 +90,10 @@ THREE.MMDPhysics.prototype = {
 
 
 		this.reset();
 		this.reset();
 
 
+		helper.freeThreeVector3( currentPosition );
+		helper.freeThreeVector3( currentRotation );
+		helper.freeThreeVector3( currentScale );
+
 	},
 	},
 
 
 	initWorld: function () {
 	initWorld: function () {
@@ -374,34 +383,35 @@ THREE.MMDPhysics.ResourceHelper.prototype = {
 
 
 	},
 	},
 
 
+	setOriginFromThreeVector3: function ( t, v ) {
+
+		t.getOrigin().setValue( v.x, v.y, v.z );
+
+	},
+
 	setBasisFromArray3: function ( t, a ) {
 	setBasisFromArray3: function ( t, a ) {
 
 
 		var thQ = this.allocThreeQuaternion();
 		var thQ = this.allocThreeQuaternion();
 		var thE = this.allocThreeEuler();
 		var thE = this.allocThreeEuler();
 		thE.set( a[ 0 ], a[ 1 ], a[ 2 ] );
 		thE.set( a[ 0 ], a[ 1 ], a[ 2 ] );
-		this.setBasisFromArray4( t, thQ.setFromEuler( thE ).toArray() );
+		this.setBasisFromThreeQuaternion( t, thQ.setFromEuler( thE ) );
 
 
 		this.freeThreeEuler( thE );
 		this.freeThreeEuler( thE );
 		this.freeThreeQuaternion( thQ );
 		this.freeThreeQuaternion( thQ );
 
 
 	},
 	},
 
 
-	setBasisFromArray4: function ( t, a ) {
+	setBasisFromThreeQuaternion: function ( t, a ) {
 
 
-		var q = this.array4ToQuaternion( a );
-		this.setBasis( t, q );
-		this.freeQuaternion( q );
-
-	},
+		var q = this.allocQuaternion();
 
 
-	array4ToQuaternion: function( a ) {
+		q.setX( a.x );
+		q.setY( a.y );
+		q.setZ( a.z );
+		q.setW( a.w );
+		this.setBasis( t, q );
 
 
-		var q = this.allocQuaternion();
-		q.setX( a[ 0 ] );
-		q.setY( a[ 1 ] );
-		q.setZ( a[ 2 ] );
-		q.setW( a[ 3 ] );
-		return q;
+		this.freeQuaternion( q );
 
 
 	},
 	},
 
 
@@ -707,9 +717,10 @@ THREE.MMDPhysics.RigidBody.prototype = {
 		helper.setOriginFromArray3( boneOffsetForm, params.position );
 		helper.setOriginFromArray3( boneOffsetForm, params.position );
 		helper.setBasisFromArray3( boneOffsetForm, params.rotation );
 		helper.setBasisFromArray3( boneOffsetForm, params.rotation );
 
 
+		var vector = helper.allocThreeVector3();
 		var boneForm = helper.allocTransform();
 		var boneForm = helper.allocTransform();
 		helper.setIdentity( boneForm );
 		helper.setIdentity( boneForm );
-		helper.setOriginFromArray3( boneForm, bone.getWorldPosition().toArray() );
+		helper.setOriginFromThreeVector3( boneForm, bone.getWorldPosition( vector ) );
 
 
 		var form = helper.multiplyTransforms( boneForm, boneOffsetForm );
 		var form = helper.multiplyTransforms( boneForm, boneOffsetForm );
 		var state = new Ammo.btDefaultMotionState( form );
 		var state = new Ammo.btDefaultMotionState( form );
@@ -746,6 +757,7 @@ THREE.MMDPhysics.RigidBody.prototype = {
 		helper.freeVector3( localInertia );
 		helper.freeVector3( localInertia );
 		helper.freeTransform( form );
 		helper.freeTransform( form );
 		helper.freeTransform( boneForm );
 		helper.freeTransform( boneForm );
+		helper.freeThreeVector3( vector );
 
 
 	},
 	},
 
 
@@ -800,16 +812,21 @@ THREE.MMDPhysics.RigidBody.prototype = {
 	getBoneTransform: function () {
 	getBoneTransform: function () {
 
 
 		var helper = this.helper;
 		var helper = this.helper;
-		var p = this.bone.getWorldPosition();
-		var q = this.bone.getWorldQuaternion();
+		var p = helper.allocThreeVector3();
+		var q = helper.allocThreeQuaternion();
+
+		this.bone.getWorldPosition( p );
+		this.bone.getWorldQuaternion( q );
 
 
 		var tr = helper.allocTransform();
 		var tr = helper.allocTransform();
-		helper.setOriginFromArray3( tr, p.toArray() );
-		helper.setBasisFromArray4( tr, q.toArray() );
+		helper.setOriginFromThreeVector3( tr, p );
+		helper.setBasisFromThreeQuaternion( tr, q );
 
 
 		var form = helper.multiplyTransforms( tr, this.boneOffsetForm );
 		var form = helper.multiplyTransforms( tr, this.boneOffsetForm );
 
 
 		helper.freeTransform( tr );
 		helper.freeTransform( tr );
+		helper.freeThreeQuaternion( q );
+		helper.freeThreeVector3( p );
 
 
 		return form;
 		return form;
 
 
@@ -1114,7 +1131,7 @@ THREE.MMDPhysicsHelper.prototype._init = function () {
 				return new THREE.SphereBufferGeometry( param.width, 16, 8 );
 				return new THREE.SphereBufferGeometry( param.width, 16, 8 );
 
 
 			case 1:
 			case 1:
-				return new THREE.BoxBufferGeometry( param.width * 2, param.height * 2, param.depth * 2, 8, 8, 8);
+				return new THREE.BoxBufferGeometry( param.width * 2, param.height * 2, param.depth * 2, 8, 8, 8 );
 
 
 			case 2:
 			case 2:
 				return new createCapsuleGeometry( param.width, param.height, 16, 8 );
 				return new createCapsuleGeometry( param.width, param.height, 16, 8 );

+ 92 - 5
examples/js/controls/DragControls.js

@@ -30,7 +30,11 @@ THREE.DragControls = function ( _objects, _camera, _domElement ) {
 
 
 		_domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
 		_domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
 		_domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
 		_domElement.addEventListener( 'mousedown', onDocumentMouseDown, false );
-		_domElement.addEventListener( 'mouseup', onDocumentMouseUp, false );
+		_domElement.addEventListener( 'mouseup', onDocumentMouseCancel, false );
+		_domElement.addEventListener( 'mouseleave', onDocumentMouseCancel, false );
+		_domElement.addEventListener( 'touchmove', onDocumentTouchMove, false );
+		_domElement.addEventListener( 'touchstart', onDocumentTouchStart, false );
+		_domElement.addEventListener( 'touchend', onDocumentTouchEnd, false );
 
 
 	}
 	}
 
 
@@ -38,7 +42,11 @@ THREE.DragControls = function ( _objects, _camera, _domElement ) {
 
 
 		_domElement.removeEventListener( 'mousemove', onDocumentMouseMove, false );
 		_domElement.removeEventListener( 'mousemove', onDocumentMouseMove, false );
 		_domElement.removeEventListener( 'mousedown', onDocumentMouseDown, false );
 		_domElement.removeEventListener( 'mousedown', onDocumentMouseDown, false );
-		_domElement.removeEventListener( 'mouseup', onDocumentMouseUp, false );
+		_domElement.removeEventListener( 'mouseup', onDocumentMouseCancel, false );
+		_domElement.removeEventListener( 'mouseleave', onDocumentMouseCancel, false );
+		_domElement.removeEventListener( 'touchmove', onDocumentTouchMove, false );
+		_domElement.removeEventListener( 'touchstart', onDocumentTouchStart, false );
+		_domElement.removeEventListener( 'touchend', onDocumentTouchEnd, false );
 
 
 	}
 	}
 
 
@@ -54,8 +62,8 @@ THREE.DragControls = function ( _objects, _camera, _domElement ) {
 
 
 		var rect = _domElement.getBoundingClientRect();
 		var rect = _domElement.getBoundingClientRect();
 
 
-		_mouse.x = ( (event.clientX - rect.left) / rect.width ) * 2 - 1;
-		_mouse.y = - ( (event.clientY - rect.top) / rect.height ) * 2 + 1;
+		_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
+		_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;
 
 
 		_raycaster.setFromCamera( _mouse, _camera );
 		_raycaster.setFromCamera( _mouse, _camera );
 
 
@@ -134,7 +142,86 @@ THREE.DragControls = function ( _objects, _camera, _domElement ) {
 
 
 	}
 	}
 
 
-	function onDocumentMouseUp( event ) {
+	function onDocumentMouseCancel( event ) {
+
+		event.preventDefault();
+
+		if ( _selected ) {
+
+			scope.dispatchEvent( { type: 'dragend', object: _selected } );
+
+			_selected = null;
+
+		}
+
+		_domElement.style.cursor = 'auto';
+
+	}
+
+	function onDocumentTouchMove( event ) {
+
+		event.preventDefault();
+		event = event.changedTouches[ 0 ];
+
+		var rect = _domElement.getBoundingClientRect();
+
+		_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
+		_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;
+
+		_raycaster.setFromCamera( _mouse, _camera );
+
+		if ( _selected && scope.enabled ) {
+
+			if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
+
+				_selected.position.copy( _intersection.sub( _offset ) );
+
+			}
+
+			scope.dispatchEvent( { type: 'drag', object: _selected } );
+
+			return;
+
+		}
+
+	}
+
+	function onDocumentTouchStart( event ) {
+
+		event.preventDefault();
+		event = event.changedTouches[ 0 ];
+
+		var rect = _domElement.getBoundingClientRect();
+
+		_mouse.x = ( ( event.clientX - rect.left ) / rect.width ) * 2 - 1;
+		_mouse.y = - ( ( event.clientY - rect.top ) / rect.height ) * 2 + 1;
+
+		_raycaster.setFromCamera( _mouse, _camera );
+
+		var intersects = _raycaster.intersectObjects( _objects );
+
+		if ( intersects.length > 0 ) {
+
+			_selected = intersects[ 0 ].object;
+
+			_plane.setFromNormalAndCoplanarPoint( _camera.getWorldDirection( _plane.normal ), _selected.position );
+
+			if ( _raycaster.ray.intersectPlane( _plane, _intersection ) ) {
+
+				_offset.copy( _intersection ).sub( _selected.position );
+
+			}
+
+			_domElement.style.cursor = 'move';
+
+			scope.dispatchEvent( { type: 'dragstart', object: _selected } );
+
+		}
+
+
+	}
+
+	function onDocumentTouchEnd( event ) {
 
 
 		event.preventDefault();
 		event.preventDefault();
 
 

+ 0 - 2
examples/js/controls/EditorControls.js

@@ -199,8 +199,6 @@ THREE.EditorControls = function ( object, domElement ) {
 
 
 	// touch
 	// touch
 
 
-	var touch = new THREE.Vector3();
-
 	var touches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 	var touches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 	var prevTouches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 	var prevTouches = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
 
 

+ 0 - 10
examples/js/controls/TransformControls.js

@@ -83,8 +83,6 @@
 
 
 	THREE.TransformGizmo = function () {
 	THREE.TransformGizmo = function () {
 
 
-		var scope = this;
-
 		this.init = function () {
 		this.init = function () {
 
 
 			THREE.Object3D.call( this );
 			THREE.Object3D.call( this );
@@ -441,13 +439,6 @@
 
 
 			THREE.TransformGizmo.prototype.update.apply( this, arguments );
 			THREE.TransformGizmo.prototype.update.apply( this, arguments );
 
 
-			var group = {
-
-				handles: this[ "handles" ],
-				pickers: this[ "pickers" ]
-
-			};
-
 			var tempMatrix = new THREE.Matrix4();
 			var tempMatrix = new THREE.Matrix4();
 			var worldRotation = new THREE.Euler( 0, 0, 1 );
 			var worldRotation = new THREE.Euler( 0, 0, 1 );
 			var tempQuaternion = new THREE.Quaternion();
 			var tempQuaternion = new THREE.Quaternion();
@@ -625,7 +616,6 @@
 
 
 		var _mode = "translate";
 		var _mode = "translate";
 		var _dragging = false;
 		var _dragging = false;
-		var _plane = "XY";
 		var _gizmo = {
 		var _gizmo = {
 
 
 			"translate": new THREE.TransformGizmoTranslate(),
 			"translate": new THREE.TransformGizmoTranslate(),

+ 1 - 1
examples/js/crossfade/scenes.js

@@ -87,7 +87,7 @@ function Scene ( type, numObjects, cameraZ, fov, rotationSpeed, clearColor ) {
 
 
 	this.rotationSpeed = rotationSpeed;
 	this.rotationSpeed = rotationSpeed;
 
 
-	var defaultMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, shading: THREE.FlatShading, vertexColors: THREE.VertexColors } );
+	var defaultMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, flatShading: true, vertexColors: THREE.VertexColors } );
 	this.mesh = new THREE.Mesh( generateGeometry( type, numObjects ), defaultMaterial );
 	this.mesh = new THREE.Mesh( generateGeometry( type, numObjects ), defaultMaterial );
 	this.scene.add( this.mesh );
 	this.scene.add( this.mesh );
 
 

+ 922 - 0
examples/js/exporters/GLTFExporter.js

@@ -0,0 +1,922 @@
+/**
+ * @author fernandojsg / http://fernandojsg.com
+ */
+
+ //------------------------------------------------------------------------------
+ // Constants
+ //------------------------------------------------------------------------------
+var WEBGL_CONSTANTS = {
+	POINTS: 0x0000,
+	LINES: 0x0001,
+	LINE_LOOP: 0x0002,
+	LINE_STRIP: 0x0003,
+	TRIANGLES: 0x0004,
+	TRIANGLE_STRIP: 0x0005,
+	TRIANGLE_FAN: 0x0006,
+
+	UNSIGNED_BYTE: 0x1401,
+	UNSIGNED_SHORT: 0x1403,
+	FLOAT: 0x1406,
+	UNSIGNED_INT: 0x1405,
+	ARRAY_BUFFER: 0x8892,
+	ELEMENT_ARRAY_BUFFER: 0x8893,
+
+	NEAREST: 0x2600,
+	LINEAR: 0x2601,
+	NEAREST_MIPMAP_NEAREST: 0x2700,
+	LINEAR_MIPMAP_NEAREST: 0x2701,
+	NEAREST_MIPMAP_LINEAR: 0x2702,
+	LINEAR_MIPMAP_LINEAR: 0x2703
+};
+
+var THREE_TO_WEBGL = {
+	// @TODO Replace with computed property name [THREE.*] when available on es6
+	1003: WEBGL_CONSTANTS.NEAREST,
+	1004: WEBGL_CONSTANTS.LINEAR,
+	1005: WEBGL_CONSTANTS.NEAREST_MIPMAP_NEAREST,
+	1006: WEBGL_CONSTANTS.LINEAR_MIPMAP_NEAREST,
+	1007: WEBGL_CONSTANTS.NEAREST_MIPMAP_LINEAR,
+	1008: WEBGL_CONSTANTS.LINEAR_MIPMAP_LINEAR
+ };
+
+//------------------------------------------------------------------------------
+// GLTF Exporter
+//------------------------------------------------------------------------------
+THREE.GLTFExporter = function () {};
+
+THREE.GLTFExporter.prototype = {
+
+	constructor: THREE.GLTFExporter,
+
+	/**
+	 * Parse scenes and generate GLTF output
+	 * @param  {THREE.Scene or [THREE.Scenes]} input   THREE.Scene or Array of THREE.Scenes
+	 * @param  {Function} onDone  Callback on completed
+	 * @param  {Object} options options
+	 *                          trs: Exports position, rotation and scale instead of matrix
+	 */
+	parse: function ( input, onDone, options ) {
+
+		options = options || {};
+
+		var outputJSON = {
+
+			asset: {
+
+				version: "2.0",
+				generator: "THREE.JS GLTFExporter" // @QUESTION Does it support spaces?
+
+		 	}
+
+    };
+
+		var byteOffset = 0;
+		var dataViews = [];
+
+		/**
+		 * Compare two arrays
+		 */
+		/**
+		 * Compare two arrays
+		 * @param  {Array} array1 Array 1 to compare
+		 * @param  {Array} array2 Array 2 to compare
+		 * @return {Boolean}        Returns true if both arrays are equal
+		 */
+		function equalArray ( array1, array2 ) {
+
+			return ( array1.length === array2.length ) && array1.every( function( element, index ) {
+
+    		return element === array2[ index ];
+
+			});
+
+		}
+
+		/**
+		 * Get the min and he max vectors from the given attribute
+		 * @param  {THREE.WebGLAttribute} attribute Attribute to find the min/max
+		 * @return {Object} Object containing the `min` and `max` values (As an array of attribute.itemSize components)
+		 */
+		function getMinMax ( attribute ) {
+
+			var output = {
+
+				min: new Array( attribute.itemSize ).fill( Number.POSITIVE_INFINITY ),
+				max: new Array( attribute.itemSize ).fill( Number.NEGATIVE_INFINITY )
+
+			};
+
+			for ( var i = 0; i < attribute.count; i++ ) {
+
+				for ( var a = 0; a < attribute.itemSize; a++ ) {
+
+					var value = attribute.array[ i * attribute.itemSize + a ];
+					output.min[ a ] = Math.min( output.min[ a ], value );
+					output.max[ a ] = Math.max( output.max[ a ], value );
+
+				}
+
+			}
+
+			return output;
+		}
+
+		/**
+		 * Process a buffer to append to the default one.
+		 * @param  {THREE.BufferAttribute} attribute     Attribute to store
+		 * @param  {Integer} componentType Component type (Unsigned short, unsigned int or float)
+		 * @return {Integer}               Index of the buffer created (Currently always 0)
+		 */
+		function processBuffer ( attribute, componentType ) {
+
+			if ( !outputJSON.buffers ) {
+
+				outputJSON.buffers = [
+
+					{
+
+						byteLength: 0,
+						uri: ''
+
+					}
+
+				];
+
+			}
+
+			// Create a new dataview and dump the attribute's array into it
+			var dataView = new DataView( new ArrayBuffer( attribute.array.byteLength ) );
+
+			var offset = 0;
+			var offsetInc = componentType === WEBGL_CONSTANTS.UNSIGNED_SHORT ? 2 : 4;
+
+			for ( var i = 0; i < attribute.count; i++ ) {
+
+				for (var a = 0; a < attribute.itemSize; a++ ) {
+
+					var value = attribute.array[ i * attribute.itemSize + a ];
+
+					if ( componentType === WEBGL_CONSTANTS.FLOAT ) {
+
+						dataView.setFloat32( offset, value, true );
+
+					} else if ( componentType === WEBGL_CONSTANTS.UNSIGNED_INT ) {
+
+						dataView.setUint8( offset, value, true );
+
+					} else if ( componentType === WEBGL_CONSTANTS.UNSIGNED_SHORT ) {
+
+						dataView.setUint16( offset, value, true );
+
+					}
+
+					offset += offsetInc;
+
+				}
+
+			}
+
+			// We just use one buffer
+			dataViews.push( dataView );
+
+			// Always using just one buffer
+			return 0;
+		}
+
+		/**
+		 * Process and generate a BufferView
+		 * @param  {[type]} data [description]
+		 * @return {[type]}      [description]
+		 */
+		function processBufferView ( data, componentType ) {
+
+			var isVertexAttributes = componentType === WEBGL_CONSTANTS.FLOAT;
+
+			if ( !outputJSON.bufferViews ) {
+
+				outputJSON.bufferViews = [];
+
+			}
+
+			var gltfBufferView = {
+
+				buffer: processBuffer( data, componentType ),
+				byteOffset: byteOffset,
+				byteLength: data.array.byteLength,
+				byteStride: data.itemSize * ( componentType === WEBGL_CONSTANTS.UNSIGNED_SHORT ? 2 : 4 ),
+				target: isVertexAttributes ? WEBGL_CONSTANTS.ARRAY_BUFFER : WEBGL_CONSTANTS.ELEMENT_ARRAY_BUFFER
+
+			};
+
+			byteOffset += data.array.byteLength;
+
+			outputJSON.bufferViews.push( gltfBufferView );
+
+			// @TODO Ideally we'll have just two bufferviews: 0 is for vertex attributes, 1 for indices
+			var output = {
+
+				id: outputJSON.bufferViews.length - 1,
+				byteLength: 0
+
+			};
+
+			return output;
+
+		}
+
+		/**
+		 * Process attribute to generate an accessor
+		 * @param  {THREE.WebGLAttribute} attribute Attribute to process
+		 * @return {Integer}           Index of the processed accessor on the "accessors" array
+		 */
+		function processAccessor ( attribute ) {
+
+			if ( !outputJSON.accessors ) {
+
+				outputJSON.accessors = [];
+
+			}
+
+			var types = [
+
+				'SCALAR',
+				'VEC2',
+				'VEC3',
+				'VEC4'
+
+			];
+
+			var componentType;
+
+			// Detect the component type of the attribute array (float, uint or ushort)
+			if ( attribute.array.constructor === Float32Array ) {
+
+				componentType = WEBGL_CONSTANTS.FLOAT;
+
+			} else if ( attribute.array.constructor === Uint32Array ) {
+
+				componentType = WEBGL_CONSTANTS.UNSIGNED_INT;
+
+			} else if ( attribute.array.constructor === Uint16Array ) {
+
+				componentType = WEBGL_CONSTANTS.UNSIGNED_SHORT;
+
+			} else {
+
+				throw new Error( 'THREE.GLTFExporter: Unsupported bufferAttribute component type.' );
+
+			}
+
+			var minMax = getMinMax( attribute );
+			var bufferView = processBufferView( attribute, componentType );
+
+			var gltfAccessor = {
+
+				bufferView: bufferView.id,
+				byteOffset: bufferView.byteOffset,
+				componentType: componentType,
+				count: attribute.count,
+				max: minMax.max,
+				min: minMax.min,
+				type: types[ attribute.itemSize - 1 ]
+
+			};
+
+			outputJSON.accessors.push( gltfAccessor );
+
+			return outputJSON.accessors.length - 1;
+
+		}
+
+		/**
+		 * Process image
+		 * @param  {Texture} map Texture to process
+		 * @return {Integer}     Index of the processed texture in the "images" array
+		 */
+		function processImage ( map ) {
+
+			if ( !outputJSON.images ) {
+
+				outputJSON.images = [];
+
+			}
+
+			var gltfImage = {};
+
+			if ( options.embedImages ) {
+
+				// @TODO { bufferView, mimeType }
+
+			} else {
+
+				// @TODO base64 based on options
+				gltfImage.uri = map.image.src;
+
+			}
+
+			outputJSON.images.push( gltfImage );
+
+			return outputJSON.images.length - 1;
+
+		}
+
+		/**
+		 * Process sampler
+		 * @param  {Texture} map Texture to process
+		 * @return {Integer}     Index of the processed texture in the "samplers" array
+		 */
+		function processSampler ( map ) {
+
+			if ( !outputJSON.samplers ) {
+
+				outputJSON.samplers = [];
+
+			}
+
+			var gltfSampler = {
+
+				magFilter: THREE_TO_WEBGL[ map.magFilter ],
+				minFilter: THREE_TO_WEBGL[ map.minFilter ],
+				wrapS: THREE_TO_WEBGL[ map.wrapS ],
+				wrapT: THREE_TO_WEBGL[ map.wrapT ]
+
+			};
+
+			outputJSON.samplers.push( gltfSampler );
+
+			return outputJSON.samplers.length - 1;
+
+		}
+
+		/**
+		 * Process texture
+		 * @param  {Texture} map Map to process
+		 * @return {Integer}     Index of the processed texture in the "textures" array
+		 */
+		function processTexture ( map ) {
+
+			if (!outputJSON.textures) {
+
+				outputJSON.textures = [];
+
+			}
+
+			var gltfTexture = {
+
+				sampler: processSampler( map ),
+				source: processImage( map )
+
+			};
+
+			outputJSON.textures.push( gltfTexture );
+
+			return outputJSON.textures.length - 1;
+
+		}
+
+		/**
+		 * Process material
+		 * @param  {THREE.Material} material Material to process
+		 * @return {Integer}      Index of the processed material in the "materials" array
+		 */
+		function processMaterial ( material ) {
+
+			if ( !outputJSON.materials ) {
+
+				outputJSON.materials = [];
+
+			}
+
+			if ( material instanceof THREE.ShaderMaterial ) {
+
+				console.warn( 'GLTFExporter: THREE.ShaderMaterial not supported.' );
+				return null;
+
+			}
+
+
+			if ( !( material instanceof THREE.MeshStandardMaterial ) ) {
+
+				console.warn( 'GLTFExporter: Currently just THREE.StandardMaterial is supported. Material conversion may lose information.' );
+
+			}
+
+			// @QUESTION Should we avoid including any attribute that has the default value?
+			var gltfMaterial = {
+
+				pbrMetallicRoughness: {}
+
+			};
+
+			// pbrMetallicRoughness.baseColorFactor
+			var color = material.color.toArray().concat( [ material.opacity ] );
+
+			if ( !equalArray( color, [ 1, 1, 1, 1 ] ) ) {
+
+				gltfMaterial.pbrMetallicRoughness.baseColorFactor = color;
+
+			}
+
+			if ( material instanceof THREE.MeshStandardMaterial ) {
+
+				gltfMaterial.pbrMetallicRoughness.metallicFactor = material.metalness;
+				gltfMaterial.pbrMetallicRoughness.roughnessFactor = material.roughness;
+
+ 			} else {
+
+					gltfMaterial.pbrMetallicRoughness.metallicFactor = 0.5;
+					gltfMaterial.pbrMetallicRoughness.roughnessFactor = 0.5;
+
+			}
+
+			// pbrMetallicRoughness.baseColorTexture
+			if ( material.map ) {
+
+				gltfMaterial.pbrMetallicRoughness.baseColorTexture = {
+
+					index: processTexture( material.map ),
+					texCoord: 0 // @FIXME
+
+				};
+
+			}
+
+			if ( material instanceof THREE.MeshBasicMaterial ||
+				material instanceof THREE.LineBasicMaterial ||
+				material instanceof THREE.PointsMaterial ) {
+
+			} else {
+
+				// emissiveFactor
+				var emissive = material.emissive.clone().multiplyScalar( material.emissiveIntensity ).toArray();
+
+				if ( !equalArray( emissive, [ 0, 0, 0 ] ) ) {
+
+					gltfMaterial.emissiveFactor = emissive;
+
+				}
+
+				// emissiveTexture
+				if ( material.emissiveMap ) {
+
+					gltfMaterial.emissiveTexture = {
+
+						index: processTexture( material.emissiveMap ),
+						texCoord: 0 // @FIXME
+
+					};
+
+				}
+
+			}
+
+			// normalTexture
+			if ( material.normalMap ) {
+
+				gltfMaterial.normalTexture = {
+
+					index: processTexture( material.normalMap ),
+					texCoord: 0 // @FIXME
+
+				};
+
+			}
+
+			// occlusionTexture
+			if ( material.aoMap ) {
+
+				gltfMaterial.occlusionTexture = {
+
+					index: processTexture( material.aoMap ),
+					texCoord: 0 // @FIXME
+
+				};
+
+			}
+
+			// alphaMode
+			if ( material.transparent ) {
+
+				gltfMaterial.alphaMode = 'BLEND'; // @FIXME We should detect MASK or BLEND
+
+			}
+
+			// doubleSided
+			if ( material.side === THREE.DoubleSide ) {
+
+				gltfMaterial.doubleSided = true;
+
+			}
+
+			if ( material.name ) {
+
+				gltfMaterial.name = material.name;
+
+			}
+
+			outputJSON.materials.push( gltfMaterial );
+
+			return outputJSON.materials.length - 1;
+
+		}
+
+		/**
+		 * Process mesh
+		 * @param  {THREE.Mesh} mesh Mesh to process
+		 * @return {Integer}      Index of the processed mesh in the "meshes" array
+		 */
+		function processMesh( mesh ) {
+
+			if ( !outputJSON.meshes ) {
+
+				outputJSON.meshes = [];
+
+			}
+
+			var geometry = mesh.geometry;
+
+			// Use the correct mode
+			if ( mesh instanceof THREE.LineSegments ) {
+
+				mode = WEBGL_CONSTANTS.LINES;
+
+			} else if ( mesh instanceof THREE.LineLoop ) {
+
+				mode = WEBGL_CONSTANTS.LINE_LOOP;
+
+			} else if ( mesh instanceof THREE.Line ) {
+
+				mode = WEBGL_CONSTANTS.LINE_STRIP;
+
+			} else if ( mesh instanceof THREE.Points ) {
+
+				mode = WEBGL_CONSTANTS.POINTS;
+
+			} else {
+
+				if ( !( geometry instanceof THREE.BufferGeometry) ) {
+
+					var geometryTemp = new THREE.BufferGeometry();
+					geometryTemp.fromGeometry( geometry );
+					geometry = geometryTemp;
+
+				}
+
+				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;
+
+				}
+
+			}
+
+			var gltfMesh = {
+				primitives: [
+					{
+						mode: mode,
+						attributes: {},
+					}
+				]
+			};
+
+			var material = processMaterial( mesh.material );
+			if ( material ) {
+
+				gltfMesh.primitives[ 0 ].material = material;
+
+			}
+
+
+			if ( geometry.index ) {
+
+				gltfMesh.primitives[ 0 ].indices = processAccessor( geometry.index );
+
+			}
+
+			// We've just one primitive per mesh
+			var gltfAttributes = gltfMesh.primitives[ 0 ].attributes;
+			var attributes = geometry.attributes;
+
+			// Conversion between attributes names in threejs and gltf spec
+			var nameConversion = {
+
+				uv: 'TEXCOORD_0',
+				uv2: 'TEXCOORD_1',
+				color: 'COLOR_0',
+				skinWeight: 'WEIGHTS_0',
+				skinIndex: 'JOINTS_0'
+
+			};
+
+			// @QUESTION Detect if .vertexColors = THREE.VertexColors?
+			// For every attribute create an accessor
+			for ( var attributeName in geometry.attributes ) {
+
+				var attribute = geometry.attributes[ attributeName ];
+				attributeName = nameConversion[ attributeName ] || attributeName.toUpperCase();
+				gltfAttributes[ attributeName ] = processAccessor( attribute );
+
+			}
+
+			outputJSON.meshes.push( gltfMesh );
+
+			return outputJSON.meshes.length - 1;
+		}
+
+		/**
+		 * Process camera
+		 * @param  {THREE.Camera} camera Camera to process
+		 * @return {Integer}      Index of the processed mesh in the "camera" array
+		 */
+		function processCamera( camera ) {
+
+			if ( !outputJSON.cameras ) {
+
+				outputJSON.cameras = [];
+
+			}
+
+			var isOrtho = camera instanceof THREE.OrthographicCamera;
+
+			var gltfCamera = {
+
+				type: isOrtho ? 'orthographic' : 'perspective'
+
+			};
+
+			if ( isOrtho ) {
+
+				gltfCamera.orthographic = {
+
+					xmag: camera.right * 2,
+					ymag: camera.top * 2,
+					zfar: camera.far,
+					znear: camera.near
+
+				};
+
+			} else {
+
+				gltfCamera.perspective = {
+
+					aspectRatio: camera.aspect,
+					yfov: THREE.Math.degToRad( camera.fov ) / camera.aspect,
+					zfar: camera.far,
+					znear: camera.near
+
+				};
+
+			}
+
+			if ( camera.name ) {
+
+				gltfCamera.name = camera.type;
+
+			}
+
+			outputJSON.cameras.push( gltfCamera );
+
+			return outputJSON.cameras.length - 1;
+		}
+
+		/**
+		 * Process Object3D node
+		 * @param  {THREE.Object3D} node Object3D to processNode
+		 * @return {Integer}      Index of the node in the nodes list
+		 */
+		function processNode ( object ) {
+
+			if ( !outputJSON.nodes ) {
+
+				outputJSON.nodes = [];
+
+			}
+
+			var gltfNode = {};
+
+			if ( options.trs ) {
+
+				var rotation = object.quaternion.toArray();
+				var position = object.position.toArray();
+				var scale = object.scale.toArray();
+
+				if ( !equalArray( rotation, [ 0, 0, 0, 1 ] ) ) {
+
+					gltfNode.rotation = rotation;
+
+				}
+
+				if ( !equalArray( position, [ 0, 0, 0 ] ) ) {
+
+					gltfNode.position = position;
+
+				}
+
+				if ( !equalArray( scale, [ 1, 1, 1 ] ) ) {
+
+					gltfNode.scale = scale;
+
+				}
+
+			} else {
+
+				object.updateMatrix();
+				if (! equalArray( object.matrix.elements, [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ] ) ) {
+
+					gltfNode.matrix = object.matrix.elements;
+
+				}
+
+			}
+
+			if ( object.name ) {
+
+				gltfNode.name = object.name;
+
+			}
+
+			if ( object.userData && Object.keys( object.userData ).length > 0 ) {
+
+				try {
+
+					gltfNode.extras = JSON.parse( JSON.stringify( object.userData ) );
+
+				} catch (e) {
+
+					throw new Error( 'GLTFExporter: userData can\'t be serialized' );
+
+				}
+
+			}
+
+			if ( object instanceof THREE.Mesh ||
+				object instanceof THREE.Line ||
+				object instanceof THREE.Points ) {
+
+				gltfNode.mesh = processMesh( object );
+
+			} else if ( object instanceof THREE.Camera ) {
+
+				gltfNode.camera = processCamera( object );
+
+			}
+
+			if ( object.children.length > 0 ) {
+
+				gltfNode.children = [];
+
+				for ( var i = 0, l = object.children.length; i < l; i ++ ) {
+
+					var child = object.children[ i ];
+					if ( child instanceof THREE.Mesh ||
+						child instanceof THREE.Camera ||
+						child instanceof THREE.Group ||
+						child instanceof THREE.Line ||
+						child instanceof THREE.Points) {
+
+						gltfNode.children.push( processNode( child ) );
+
+					}
+
+				}
+
+			}
+
+			outputJSON.nodes.push( gltfNode );
+
+			return outputJSON.nodes.length - 1;
+
+		}
+
+		/**
+		 * Process Scene
+		 * @param  {THREE.Scene} node Scene to process
+		 */
+		function processScene( scene ) {
+
+			if ( !outputJSON.scenes ) {
+
+				outputJSON.scenes = [];
+				outputJSON.scene = 0;
+
+			}
+
+			var gltfScene = {
+
+				nodes: []
+
+			};
+
+			if ( scene.name ) {
+
+				gltfScene.name = scene.name;
+
+			}
+
+			outputJSON.scenes.push( gltfScene );
+
+			for ( var i = 0, l = scene.children.length; i < l; i ++ ) {
+
+				var child = scene.children[ i ];
+
+				// @TODO We don't process lights yet
+				if ( child instanceof THREE.Mesh ||
+					child instanceof THREE.Camera ||
+					child instanceof THREE.Group ||
+					child instanceof THREE.Line ||
+					child instanceof THREE.Points) {
+
+					gltfScene.nodes.push( processNode( child ) );
+
+				}
+
+			}
+
+		}
+
+		/**
+		 * Creates a THREE.Scene to hold a list of objects and parse it
+		 * @param  {Array} objects List of objects to process
+		 */
+		function processObjects ( objects ) {
+
+			var scene = new THREE.Scene();
+			scene.name = 'AuxScene';
+
+			for ( var i = 0; i < objects.length; i++ ) {
+
+				// We push directly to children instead of calling `add` to prevent
+				// modify the .parent and break its original scene and hierarchy
+				scene.children.push( objects[ i ] );
+
+			}
+
+			processScene( scene );
+
+		}
+
+		function processInput( input ) {
+
+			input = input instanceof Array ? input : [ input ];
+
+			var objectsWithoutScene = [];
+			for ( i = 0; i < input.length; i++ ) {
+
+				if ( input[ i ] instanceof THREE.Scene ) {
+
+					processScene( input[ i ] );
+
+				} else {
+
+					objectsWithoutScene.push( input[ i ] );
+
+				}
+
+			}
+
+			if ( objectsWithoutScene.length > 0 ) {
+
+				processObjects( objectsWithoutScene );
+
+			}
+
+		}
+
+		processInput( input );
+
+		// Generate buffer
+		// Create a new blob with all the dataviews from the buffers
+		var blob = new Blob( dataViews, { type: 'application/octet-binary' } );
+
+		// Update the bytlength of the only main buffer and update the uri with the base64 representation of it
+		if ( outputJSON.buffers && outputJSON.buffers.length > 0 ) {
+
+			outputJSON.buffers[ 0 ].byteLength = blob.size;
+			objectURL = URL.createObjectURL( blob );
+
+			var reader = new window.FileReader();
+			 reader.readAsDataURL( blob );
+			 reader.onloadend = function() {
+
+				 base64data = reader.result;
+				 outputJSON.buffers[ 0 ].uri = base64data;
+				 onDone( outputJSON );
+
+			 };
+
+		} else {
+
+			onDone ( outputJSON );
+
+		}
+	}
+};

+ 17 - 11
examples/js/loaders/3MFLoader.js

@@ -1,3 +1,7 @@
+/**
+ * @author technohippy / https://github.com/technohippy
+ */
+
 THREE.ThreeMFLoader = function ( manager ) {
 THREE.ThreeMFLoader = function ( manager ) {
 
 
 	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
@@ -14,9 +18,9 @@ THREE.ThreeMFLoader.prototype = {
 		var scope = this;
 		var scope = this;
 		var loader = new THREE.FileLoader( scope.manager );
 		var loader = new THREE.FileLoader( scope.manager );
 		loader.setResponseType( 'arraybuffer' );
 		loader.setResponseType( 'arraybuffer' );
-		loader.load( url, function( text ) {
+		loader.load( url, function( buffer ) {
 
 
-			onLoad( scope.parse( text ) );
+			onLoad( scope.parse( buffer ) );
 
 
 		}, onProgress, onError );
 		}, onProgress, onError );
 
 
@@ -51,7 +55,7 @@ THREE.ThreeMFLoader.prototype = {
 
 
 				if ( e instanceof ReferenceError ) {
 				if ( e instanceof ReferenceError ) {
 
 
-					console.log( '	jszip missing and file is compressed.' );
+					console.error( 'THREE.ThreeMFLoader: jszip missing and file is compressed.' );
 					return null;
 					return null;
 
 
 				}
 				}
@@ -95,7 +99,7 @@ THREE.ThreeMFLoader.prototype = {
 
 
 				if ( TextDecoder === undefined ) {
 				if ( TextDecoder === undefined ) {
 
 
-					console.log( '	TextDecoder not present.	Please use TextDecoder polyfill.' );
+					console.error( 'THREE.ThreeMFLoader: TextDecoder not present. Please use a TextDecoder polyfill.' );
 					return null;
 					return null;
 
 
 				}
 				}
@@ -105,7 +109,7 @@ THREE.ThreeMFLoader.prototype = {
 
 
 				if ( xmlData.documentElement.nodeName.toLowerCase() !== 'model' ) {
 				if ( xmlData.documentElement.nodeName.toLowerCase() !== 'model' ) {
 
 
-					console.log( '	Error loading 3MF - no 3MF document found: ' + modelPart );
+					console.error( 'THREE.ThreeMFLoader: Error loading 3MF - no 3MF document found: ', modelPart );
 
 
 				}
 				}
 
 
@@ -372,7 +376,6 @@ THREE.ThreeMFLoader.prototype = {
 		function parseResourcesNode( resourcesNode ) {
 		function parseResourcesNode( resourcesNode ) {
 
 
 			var resourcesData = {};
 			var resourcesData = {};
-			var geometry, material;
 			var basematerialsNode = resourcesNode.querySelector( 'basematerials' );
 			var basematerialsNode = resourcesNode.querySelector( 'basematerials' );
 
 
 			if ( basematerialsNode ) {
 			if ( basematerialsNode ) {
@@ -479,7 +482,7 @@ THREE.ThreeMFLoader.prototype = {
 			geometry.computeBoundingSphere();
 			geometry.computeBoundingSphere();
 
 
 			var materialOpts = {
 			var materialOpts = {
-				shading: THREE.FlatShading
+				flatShading: true
 			};
 			};
 
 
 			if ( meshData[ 'colors' ] && 0 < meshData[ 'colors' ].length ) {
 			if ( meshData[ 'colors' ] && 0 < meshData[ 'colors' ].length ) {
@@ -499,8 +502,10 @@ THREE.ThreeMFLoader.prototype = {
 
 
 		function applyExtensions( extensions, meshData, modelXml, data3mf ) {
 		function applyExtensions( extensions, meshData, modelXml, data3mf ) {
 
 
-			if ( !extensions ) {
+			if ( ! extensions ) {
+
 				return;
 				return;
+
 			}
 			}
 
 
 			var availableExtensions = [];
 			var availableExtensions = [];
@@ -530,6 +535,7 @@ THREE.ThreeMFLoader.prototype = {
 				extension.apply( modelXml, extensions[ extension[ 'ns' ] ], meshData );
 				extension.apply( modelXml, extensions[ extension[ 'ns' ] ], meshData );
 
 
 			}
 			}
+
 		}
 		}
 
 
 		function buildMeshes( data3mf ) {
 		function buildMeshes( data3mf ) {
@@ -590,14 +596,14 @@ THREE.ThreeMFLoader.prototype = {
 		var data3mf = loadDocument( data );
 		var data3mf = loadDocument( data );
 		var meshes = buildMeshes( data3mf );
 		var meshes = buildMeshes( data3mf );
 
 
-		return build( meshes, data3mf[ 'rels' ], data3mf )
+		return build( meshes, data3mf[ 'rels' ], data3mf );
 
 
 	},
 	},
 
 
-    addExtension: function( extension ) {
+	addExtension: function( extension ) {
 
 
 		this.availableExtensions.push( extension );
 		this.availableExtensions.push( extension );
 
 
-    }
+	}
 
 
 };
 };

+ 71 - 76
examples/js/loaders/AMFLoader.js

@@ -50,12 +50,12 @@ THREE.AMFLoader.prototype = {
 			var view = new DataView( data );
 			var view = new DataView( data );
 			var magic = String.fromCharCode( view.getUint8( 0 ), view.getUint8( 1 ) );
 			var magic = String.fromCharCode( view.getUint8( 0 ), view.getUint8( 1 ) );
 
 
-			if ( magic === "PK" ) {
+			if ( magic === 'PK' ) {
 
 
 				var zip = null;
 				var zip = null;
 				var file = null;
 				var file = null;
 
 
-				console.log( "Loading Zip" );
+				console.log( 'THREE.AMFLoader: Loading Zip' );
 
 
 				try {
 				try {
 
 
@@ -65,7 +65,7 @@ THREE.AMFLoader.prototype = {
 
 
 					if ( e instanceof ReferenceError ) {
 					if ( e instanceof ReferenceError ) {
 
 
-						console.log( "	jszip missing and file is compressed." );
+						console.log( 'THREE.AMFLoader: jszip missing and file is compressed.' );
 						return null;
 						return null;
 
 
 					}
 					}
@@ -82,14 +82,14 @@ THREE.AMFLoader.prototype = {
 
 
 				}
 				}
 
 
-				console.log( "	Trying to load file asset: " + file );
+				console.log( 'THREE.AMFLoader: Trying to load file asset: ' + file );
 				view = new DataView( zip.file( file ).asArrayBuffer() );
 				view = new DataView( zip.file( file ).asArrayBuffer() );
 
 
 			}
 			}
 
 
-			if ( TextDecoder === undefined ) {
+			if ( window.TextDecoder === undefined ) {
 
 
-				console.log( "	TextDecoder not present.	Please use TextDecoder polyfill." );
+				console.log( 'THREE.AMFLoader: TextDecoder not present. Please use TextDecoder polyfill.' );
 				return null;
 				return null;
 
 
 			}
 			}
@@ -97,9 +97,9 @@ THREE.AMFLoader.prototype = {
 			var fileText = new TextDecoder( 'utf-8' ).decode( view );
 			var fileText = new TextDecoder( 'utf-8' ).decode( view );
 			var xmlData = new DOMParser().parseFromString( fileText, 'application/xml' );
 			var xmlData = new DOMParser().parseFromString( fileText, 'application/xml' );
 
 
-			if ( xmlData.documentElement.nodeName.toLowerCase() !== "amf" ) {
+			if ( xmlData.documentElement.nodeName.toLowerCase() !== 'amf' ) {
 
 
-				console.log( "	Error loading AMF - no AMF document found." );
+				console.log( 'THREE.AMFLoader: Error loading AMF - no AMF document found.' );
 				return null;
 				return null;
 
 
 			}
 			}
@@ -113,18 +113,18 @@ THREE.AMFLoader.prototype = {
 			var scale = 1.0;
 			var scale = 1.0;
 			var unit = 'millimeter';
 			var unit = 'millimeter';
 
 
-			if ( node.documentElement.attributes[ 'unit' ] !== undefined ) {
+			if ( node.documentElement.attributes.unit !== undefined ) {
 
 
-				unit = node.documentElement.attributes[ 'unit' ].value.toLowerCase();
+				unit = node.documentElement.attributes.unit.value.toLowerCase();
 
 
 			}
 			}
 
 
 			var scaleUnits = {
 			var scaleUnits = {
-				'millimeter': 1.0,
-				'inch': 25.4,
-				'feet': 304.8,
-				'meter': 1000.0,
-				'micron': 0.001
+				millimeter: 1.0,
+				inch: 25.4,
+				feet: 304.8,
+				meter: 1000.0,
+				micron: 0.001
 			};
 			};
 
 
 			if ( scaleUnits[ unit ] !== undefined ) {
 			if ( scaleUnits[ unit ] !== undefined ) {
@@ -133,15 +133,15 @@ THREE.AMFLoader.prototype = {
 
 
 			}
 			}
 
 
-			console.log( "	Unit scale: " + scale );
+			console.log( 'THREE.AMFLoader: Unit scale: ' + scale );
 			return scale;
 			return scale;
 
 
 		}
 		}
 
 
 		function loadMaterials( node ) {
 		function loadMaterials( node ) {
 
 
-			var matName = "AMF Material";
-			var matId = node.attributes[ 'id' ].textContent;
+			var matName = 'AMF Material';
+			var matId = node.attributes.id.textContent;
 			var color = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
 			var color = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
 
 
 			var loadedMaterial = null;
 			var loadedMaterial = null;
@@ -150,9 +150,9 @@ THREE.AMFLoader.prototype = {
 
 
 				var matChildEl = node.children[ i ];
 				var matChildEl = node.children[ i ];
 
 
-				if ( matChildEl.nodeName === "metadata" && matChildEl.attributes[ 'type' ] !== undefined ) {
+				if ( matChildEl.nodeName === 'metadata' && matChildEl.attributes.type !== undefined ) {
 
 
-					if ( matChildEl.attributes[ 'type' ].value === 'name' ) {
+					if ( matChildEl.attributes.type.value === 'name' ) {
 
 
 						matname = matChildEl.textContent;
 						matname = matChildEl.textContent;
 
 
@@ -167,7 +167,7 @@ THREE.AMFLoader.prototype = {
 			}
 			}
 
 
 			loadedMaterial = new THREE.MeshPhongMaterial( {
 			loadedMaterial = new THREE.MeshPhongMaterial( {
-				shading: THREE.FlatShading,
+				flatShading: true,
 				color: new THREE.Color( color.r, color.g, color.b ),
 				color: new THREE.Color( color.r, color.g, color.b ),
 				name: matName
 				name: matName
 			} );
 			} );
@@ -179,13 +179,13 @@ THREE.AMFLoader.prototype = {
 
 
 			}
 			}
 
 
-			return { 'id': matId, 'material': loadedMaterial };
+			return { id: matId, material: loadedMaterial };
 
 
 		}
 		}
 
 
 		function loadColor( node ) {
 		function loadColor( node ) {
 
 
-			var color = { 'r': 1.0, 'g': 1.0, 'b': 1.0, 'a': 1.0 };
+			var color = { r: 1.0, g: 1.0, b: 1.0, a: 1.0 };
 
 
 			for ( var i = 0; i < node.children.length; i ++ ) {
 			for ( var i = 0; i < node.children.length; i ++ ) {
 
 
@@ -217,23 +217,23 @@ THREE.AMFLoader.prototype = {
 
 
 		function loadMeshVolume( node ) {
 		function loadMeshVolume( node ) {
 
 
-			var volume = { "name": "", "triangles": [], "materialid": null };
+			var volume = { name: '', triangles: [], materialid: null };
 
 
 			var currVolumeNode = node.firstElementChild;
 			var currVolumeNode = node.firstElementChild;
 
 
-			if ( node.attributes[ 'materialid' ] !== undefined ) {
+			if ( node.attributes.materialid !== undefined ) {
 
 
-				volume.materialId = node.attributes[ 'materialid' ].nodeValue;
+				volume.materialId = node.attributes.materialid.nodeValue;
 
 
 			}
 			}
 
 
 			while ( currVolumeNode ) {
 			while ( currVolumeNode ) {
 
 
-				if ( currVolumeNode.nodeName === "metadata" ) {
+				if ( currVolumeNode.nodeName === 'metadata' ) {
 
 
-					if ( currVolumeNode.attributes[ 'type' ] !== undefined ) {
+					if ( currVolumeNode.attributes.type !== undefined ) {
 
 
-						if ( currVolumeNode.attributes[ 'type' ].value === 'name' ) {
+						if ( currVolumeNode.attributes.type.value === 'name' ) {
 
 
 							volume.name = currVolumeNode.textContent;
 							volume.name = currVolumeNode.textContent;
 
 
@@ -241,15 +241,13 @@ THREE.AMFLoader.prototype = {
 
 
 					}
 					}
 
 
-				} else if ( currVolumeNode.nodeName === "triangle" ) {
+				} else if ( currVolumeNode.nodeName === 'triangle' ) {
 
 
-					var v1 = currVolumeNode.getElementsByTagName("v1")[0].textContent;
-					var v2 = currVolumeNode.getElementsByTagName("v2")[0].textContent;
-					var v3 = currVolumeNode.getElementsByTagName("v3")[0].textContent;
+					var v1 = currVolumeNode.getElementsByTagName( 'v1' )[ 0 ].textContent;
+					var v2 = currVolumeNode.getElementsByTagName( 'v2' )[ 0 ].textContent;
+					var v3 = currVolumeNode.getElementsByTagName( 'v3' )[ 0 ].textContent;
 
 
-					volume.triangles.push( v1 );
-					volume.triangles.push( v2 );
-					volume.triangles.push( v3 );
+					volume.triangles.push( v1, v2, v3 );
 
 
 				}
 				}
 
 
@@ -269,31 +267,27 @@ THREE.AMFLoader.prototype = {
 
 
 			while ( currVerticesNode ) {
 			while ( currVerticesNode ) {
 
 
-				if ( currVerticesNode.nodeName === "vertex" ) {
+				if ( currVerticesNode.nodeName === 'vertex' ) {
 
 
 					var vNode = currVerticesNode.firstElementChild;
 					var vNode = currVerticesNode.firstElementChild;
 
 
 					while ( vNode ) {
 					while ( vNode ) {
 
 
-						if ( vNode.nodeName === "coordinates" ) {
+						if ( vNode.nodeName === 'coordinates' ) {
 
 
-							var x = vNode.getElementsByTagName("x")[0].textContent;
-							var y = vNode.getElementsByTagName("y")[0].textContent;
-							var z = vNode.getElementsByTagName("z")[0].textContent;
+							var x = vNode.getElementsByTagName( 'x' )[ 0 ].textContent;
+							var y = vNode.getElementsByTagName( 'y' )[ 0 ].textContent;
+							var z = vNode.getElementsByTagName( 'z' )[ 0 ].textContent;
 
 
-							vertArray.push(x);
-							vertArray.push(y);
-							vertArray.push(z);
+							vertArray.push( x, y, z );
 
 
-						} else if ( vNode.nodeName === "normal" ) {
+						} else if ( vNode.nodeName === 'normal' ) {
 
 
-							var nx = vNode.getElementsByTagName("nx")[0].textContent;
-							var ny = vNode.getElementsByTagName("ny")[0].textContent;
-							var nz = vNode.getElementsByTagName("nz")[0].textContent;
+							var nx = vNode.getElementsByTagName( 'nx' )[ 0 ].textContent;
+							var ny = vNode.getElementsByTagName( 'ny' )[ 0 ].textContent;
+							var nz = vNode.getElementsByTagName( 'nz' )[ 0 ].textContent;
 
 
-							normalArray.push(nx);
-							normalArray.push(ny);
-							normalArray.push(nz);
+							normalArray.push( nx, ny, nz );
 
 
 						}
 						}
 
 
@@ -306,24 +300,24 @@ THREE.AMFLoader.prototype = {
 
 
 			}
 			}
 
 
-			return { "vertices": vertArray, "normals": normalArray };
+			return { 'vertices': vertArray, 'normals': normalArray };
 
 
 		}
 		}
 
 
 		function loadObject( node ) {
 		function loadObject( node ) {
 
 
-			var objId = node.attributes[ 'id' ].textContent;
-			var loadedObject = { "name": "amfobject", "meshes": [] };
+			var objId = node.attributes.id.textContent;
+			var loadedObject = { name: 'amfobject', meshes: [] };
 			var currColor = null;
 			var currColor = null;
 			var currObjNode = node.firstElementChild;
 			var currObjNode = node.firstElementChild;
 
 
 			while ( currObjNode ) {
 			while ( currObjNode ) {
 
 
-				if ( currObjNode.nodeName === "metadata" ) {
+				if ( currObjNode.nodeName === 'metadata' ) {
 
 
-					if ( currObjNode.attributes[ 'type' ] !== undefined ) {
+					if ( currObjNode.attributes.type !== undefined ) {
 
 
-						if ( currObjNode.attributes[ 'type' ].value === 'name' ) {
+						if ( currObjNode.attributes.type.value === 'name' ) {
 
 
 							loadedObject.name = currObjNode.textContent;
 							loadedObject.name = currObjNode.textContent;
 
 
@@ -331,25 +325,25 @@ THREE.AMFLoader.prototype = {
 
 
 					}
 					}
 
 
-				} else if ( currObjNode.nodeName === "color" ) {
+				} else if ( currObjNode.nodeName === 'color' ) {
 
 
 					currColor = loadColor( currObjNode );
 					currColor = loadColor( currObjNode );
 
 
-				} else if ( currObjNode.nodeName === "mesh" ) {
+				} else if ( currObjNode.nodeName === 'mesh' ) {
 
 
 					var currMeshNode = currObjNode.firstElementChild;
 					var currMeshNode = currObjNode.firstElementChild;
-					var mesh = { "vertices": [], "normals": [], "volumes": [], "color": currColor };
+					var mesh = { vertices: [], normals: [], volumes: [], color: currColor };
 
 
 					while ( currMeshNode ) {
 					while ( currMeshNode ) {
 
 
-						if ( currMeshNode.nodeName === "vertices" ) {
+						if ( currMeshNode.nodeName === 'vertices' ) {
 
 
 							var loadedVertices = loadMeshVertices( currMeshNode );
 							var loadedVertices = loadMeshVertices( currMeshNode );
 
 
 							mesh.normals = mesh.normals.concat( loadedVertices.normals );
 							mesh.normals = mesh.normals.concat( loadedVertices.normals );
 							mesh.vertices = mesh.vertices.concat( loadedVertices.vertices );
 							mesh.vertices = mesh.vertices.concat( loadedVertices.vertices );
 
 
-						} else if ( currMeshNode.nodeName === "volume" ) {
+						} else if ( currMeshNode.nodeName === 'volume' ) {
 
 
 							mesh.volumes.push( loadMeshVolume( currMeshNode ) );
 							mesh.volumes.push( loadMeshVolume( currMeshNode ) );
 
 
@@ -372,26 +366,28 @@ THREE.AMFLoader.prototype = {
 		}
 		}
 
 
 		var xmlData = loadDocument( data );
 		var xmlData = loadDocument( data );
-		var amfName = "";
-		var amfAuthor = "";
+		var amfName = '';
+		var amfAuthor = '';
 		var amfScale = loadDocumentScale( xmlData );
 		var amfScale = loadDocumentScale( xmlData );
 		var amfMaterials = {};
 		var amfMaterials = {};
 		var amfObjects = {};
 		var amfObjects = {};
 		var children = xmlData.documentElement.children;
 		var children = xmlData.documentElement.children;
 
 
-		for ( var i = 0; i < children.length; i ++ ) {
+		var i, j;
+
+		for ( i = 0; i < children.length; i ++ ) {
 
 
 			var child = children[ i ];
 			var child = children[ i ];
 
 
 			if ( child.nodeName === 'metadata' ) {
 			if ( child.nodeName === 'metadata' ) {
 
 
-				if ( child.attributes[ 'type' ] !== undefined ) {
+				if ( child.attributes.type !== undefined ) {
 
 
-					if ( child.attributes[ 'type' ].value === 'name' ) {
+					if ( child.attributes.type.value === 'name' ) {
 
 
 						amfName = child.textContent;
 						amfName = child.textContent;
 
 
-					} else if ( child.attributes[ 'type' ].value === 'author' ) {
+					} else if ( child.attributes.type.value === 'author' ) {
 
 
 						amfAuthor = child.textContent;
 						amfAuthor = child.textContent;
 
 
@@ -416,11 +412,11 @@ THREE.AMFLoader.prototype = {
 		}
 		}
 
 
 		var sceneObject = new THREE.Group();
 		var sceneObject = new THREE.Group();
-		var defaultMaterial = new THREE.MeshPhongMaterial( { color: 0xaaaaff, shading: THREE.FlatShading } );
+		var defaultMaterial = new THREE.MeshPhongMaterial( { color: 0xaaaaff, flatShading: true } );
 
 
 		sceneObject.name = amfName;
 		sceneObject.name = amfName;
 		sceneObject.userData.author = amfAuthor;
 		sceneObject.userData.author = amfAuthor;
-		sceneObject.userData.loader = "AMF";
+		sceneObject.userData.loader = 'AMF';
 
 
 		for ( var id in amfObjects ) {
 		for ( var id in amfObjects ) {
 
 
@@ -429,16 +425,16 @@ THREE.AMFLoader.prototype = {
 			var newObject = new THREE.Group();
 			var newObject = new THREE.Group();
 			newObject.name = part.name || '';
 			newObject.name = part.name || '';
 
 
-			for ( var i = 0; i < meshes.length; i ++ ) {
+			for ( i = 0; i < meshes.length; i ++ ) {
 
 
 				var objDefaultMaterial = defaultMaterial;
 				var objDefaultMaterial = defaultMaterial;
 				var mesh = meshes[ i ];
 				var mesh = meshes[ i ];
-				var vertices = new THREE.BufferAttribute( new Float32Array( mesh.vertices ), 3 );
+				var vertices = new THREE.Float32BufferAttribute( mesh.vertices, 3 );
 				var normals = null;
 				var normals = null;
 
 
 				if ( mesh.normals.length ) {
 				if ( mesh.normals.length ) {
 
 
-					normals = new THREE.BufferAttribute( new Float32Array( mesh.normals ), 3 );
+					normals = new THREE.Float32BufferAttribute( mesh.normals, 3 );
 
 
 				}
 				}
 
 
@@ -460,14 +456,13 @@ THREE.AMFLoader.prototype = {
 
 
 				var volumes = mesh.volumes;
 				var volumes = mesh.volumes;
 
 
-				for ( var j = 0; j < volumes.length; j ++ ) {
+				for ( j = 0; j < volumes.length; j ++ ) {
 
 
 					var volume = volumes[ j ];
 					var volume = volumes[ j ];
 					var newGeometry = new THREE.BufferGeometry();
 					var newGeometry = new THREE.BufferGeometry();
-					var indexes = new  Uint32Array( volume.triangles );
 					var material = objDefaultMaterial;
 					var material = objDefaultMaterial;
 
 
-					newGeometry.setIndex( new THREE.BufferAttribute( indexes, 1 ) );
+					newGeometry.setIndex( volume.triangles );
 					newGeometry.addAttribute( 'position', vertices.clone() );
 					newGeometry.addAttribute( 'position', vertices.clone() );
 
 
 					if( normals ) {
 					if( normals ) {

+ 126 - 180
examples/js/loaders/AssimpJSONLoader.js

@@ -21,42 +21,44 @@ THREE.AssimpJSONLoader.prototype = {
 
 
 	constructor: THREE.AssimpJSONLoader,
 	constructor: THREE.AssimpJSONLoader,
 
 
+	crossOrigin: 'Anonymous',
+
 	load: function ( url, onLoad, onProgress, onError ) {
 	load: function ( url, onLoad, onProgress, onError ) {
 
 
 		var scope = this;
 		var scope = this;
 
 
-		this.texturePath = this.texturePath && ( typeof this.texturePath === "string" ) ? this.texturePath : this.extractUrlBase( url );
+		var path = THREE.Loader.prototype.extractUrlBase( url );
 
 
 		var loader = new THREE.FileLoader( this.manager );
 		var loader = new THREE.FileLoader( this.manager );
 		loader.load( url, function ( text ) {
 		loader.load( url, function ( text ) {
 
 
-			var json = JSON.parse( text ), scene, metadata;
+			var json = JSON.parse( text );
+			var metadata = json.__metadata__;
+
+			// check if __metadata__ meta header is present
+			// this header is used to disambiguate between different JSON-based file formats
 
 
-			// Check __metadata__ meta header if present
-			// This header is used to disambiguate between
-			// different JSON-based file formats.
-			metadata = json.__metadata__;
 			if ( typeof metadata !== 'undefined' ) {
 			if ( typeof metadata !== 'undefined' ) {
 
 
-				// Check if assimp2json at all
+				// check if assimp2json at all
+
 				if ( metadata.format !== 'assimp2json' ) {
 				if ( metadata.format !== 'assimp2json' ) {
 
 
-					onError( 'Not an assimp2json scene' );
+					onError( 'THREE.AssimpJSONLoader: Not an assimp2json scene.' );
 					return;
 					return;
 
 
-				}
-				// Check major format version
-				else if ( metadata.version < 100 && metadata.version >= 200 ) {
+				// check major format version
 
 
-					onError( 'Unsupported assimp2json file format version' );
+				} else if ( metadata.version < 100 && metadata.version >= 200 ) {
+
+					onError( 'THREE.AssimpJSONLoader: Unsupported assimp2json file format version.' );
 					return;
 					return;
 
 
 				}
 				}
 
 
 			}
 			}
 
 
-			scene = scope.parse( json );
-			onLoad( scene );
+			onLoad( scope.parse( json, path ) );
 
 
 		}, onProgress, onError );
 		}, onProgress, onError );
 
 
@@ -68,251 +70,195 @@ THREE.AssimpJSONLoader.prototype = {
 
 
 	},
 	},
 
 
-	setTexturePath: function ( value ) {
-
-		this.texturePath = value;
+	parse: function ( json, path ) {
 
 
-	},
+		function parseList( json, handler ) {
 
 
-	extractUrlBase: function ( url ) {
+			var meshes = new Array( json.length );
 
 
-		// from three/src/loaders/Loader.js
-		var parts = url.split( '/' );
-		parts.pop();
-		return ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/';
+			for ( var i = 0; i < json.length; ++ i ) {
 
 
-	},
+				meshes[ i ] = handler.call( this, json[ i ] );
 
 
-	parse: function ( json ) {
-
-		var meshes = this.parseList ( json.meshes, this.parseMesh );
-		var materials = this.parseList ( json.materials, this.parseMaterial );
-		return this.parseObject( json, json.rootnode, meshes, materials );
-
-	},
-
-	parseList : function( json, handler ) {
-
-		var meshes = new Array( json.length );
-		for ( var i = 0; i < json.length; ++ i ) {
+			}
 
 
-			meshes[ i ] = handler.call( this, json[ i ] );
+			return meshes;
 
 
 		}
 		}
-		return meshes;
-
-	},
-
-	parseMesh : function( json ) {
-
-		var geometry = new THREE.BufferGeometry();
-
-		var i, l, face;
 
 
-		var indices = [];
+		function parseMesh( json ) {
 
 
-		var vertices = json.vertices || [];
-		var normals = json.normals || [];
-		var uvs = json.texturecoords || [];
-		var colors = json.colors || [];
+			var geometry = new THREE.BufferGeometry();
 
 
-		uvs = uvs[ 0 ] || []; // only support for a single set of uvs
+			var i, l, face;
 
 
-		for ( i = 0, l = json.faces.length; i < l; i ++ ) {
+			var indices = [];
 
 
-			face = json.faces[ i ];
-			indices.push( face[ 0 ], face[ 1 ], face[ 2 ] );
+			var vertices = json.vertices || [];
+			var normals = json.normals || [];
+			var uvs = json.texturecoords || [];
+			var colors = json.colors || [];
 
 
-		}
-
-		geometry.setIndex( indices );
-		geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
+			uvs = uvs[ 0 ] || []; // only support for a single set of uvs
 
 
-		if ( normals.length > 0 ) {
+			for ( i = 0, l = json.faces.length; i < l; i ++ ) {
 
 
-			geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
-
-		}
+				face = json.faces[ i ];
+				indices.push( face[ 0 ], face[ 1 ], face[ 2 ] );
 
 
-		if ( uvs.length > 0 ) {
-
-			geometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
+			}
 
 
-		}
+			geometry.setIndex( indices );
+			geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( vertices, 3 ) );
 
 
-		if ( colors.length > 0 ) {
+			if ( normals.length > 0 ) {
 
 
-			geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
+				geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
 
 
-		}
+			}
 
 
-		geometry.computeBoundingSphere();
+			if ( uvs.length > 0 ) {
 
 
-		return geometry;
+				geometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
 
 
-	},
+			}
 
 
-	parseMaterial : function( json ) {
+			if ( colors.length > 0 ) {
 
 
-		var mat = null;
-		var scope = this;
-		var i, prop, has_textures = [],
+				geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
 
 
-		init_props = {
-			shading : THREE.SmoothShading
-		};
+			}
 
 
-		function toColor( value_arr ) {
+			geometry.computeBoundingSphere();
 
 
-			var col = new THREE.Color();
-			col.setRGB( value_arr[ 0 ], value_arr[ 1 ], value_arr[ 2 ] );
-			return col;
+			return geometry;
 
 
 		}
 		}
 
 
-		function defaultTexture() {
+		function parseMaterial( json ) {
 
 
-			var im = new Image();
-			im.width = 1;
-			im.height = 1;
-			return new THREE.Texture( im );
+			var material = new THREE.MeshPhongMaterial();
 
 
-		}
+			for ( var i in json.properties ) {
 
 
-		for ( i in json.properties ) {
+				var property = json.properties[ i ];
+				var key = property.key;
+				var value = property.value;
 
 
-			prop = json.properties[ i ];
+				switch ( key ) {
 
 
-			if ( prop.key === '$tex.file' ) {
+					case '$tex.file': {
 
 
-				// prop.semantic gives the type of the texture
-				// 1: diffuse
-				// 2: specular mao
-				// 5: height map (bumps)
-				// 6: normal map
-				// more values (i.e. emissive, environment) are known by assimp and may be relevant
-				if ( prop.semantic === 1 || prop.semantic === 5 || prop.semantic === 6 || prop.semantic === 2 ) {
+						var semantic =  property.semantic;
 
 
-					( function( semantic ) {
+						// prop.semantic gives the type of the texture
+						// 1: diffuse
+						// 2: specular mao
+						// 5: height map (bumps)
+						// 6: normal map
+						// more values (i.e. emissive, environment) are known by assimp and may be relevant
 
 
-						var loader = new THREE.TextureLoader( scope.manager ),
-						keyname;
+						if ( semantic === 1 || semantic === 2 || semantic === 5 || semantic === 6 ) {
 
 
-						if ( semantic === 1 ) {
+							var keyname;
 
 
-							keyname = 'map';
+							switch ( semantic ) {
 
 
-						} else if ( semantic === 5 ) {
+								case 1:
+									keyname = 'map';
+									break;
+								case 2:
+									keyname = 'specularMap';
+									break;
+								case 5:
+									keyname = 'bumpMap';
+									break;
+								case 6:
+									keyname = 'normalMap';
+									break;
 
 
-							keyname = 'bumpMap';
+							}
 
 
-						} else if ( semantic === 6 ) {
+							var texture = textureLoader.load( value );
 
 
-							keyname = 'normalMap';
+							// TODO: read texture settings from assimp.
+							// Wrapping is the default, though.
 
 
-						} else if ( semantic === 2 ) {
+							texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
 
 
-							keyname = 'specularMap';
+							material[ keyname ] = texture;
 
 
 						}
 						}
 
 
-						has_textures.push( keyname );
+						break;
 
 
-						loader.setCrossOrigin( this.crossOrigin );
-						var material_url = scope.texturePath + '/' + prop.value;
-						material_url = material_url.replace( /\\/g, '/' );
-						loader.load( material_url, function( tex ) {
+					}
 
 
-							if ( tex ) {
+					case '?mat.name':
+						material.name = value;
+						break;
 
 
-								// TODO: read texture settings from assimp.
-								// Wrapping is the default, though.
-								tex.wrapS = tex.wrapT = THREE.RepeatWrapping;
+					case '$clr.diffuse':
+						material.color.fromArray( value );
+						break;
 
 
-								mat[ keyname ] = tex;
-								mat.needsUpdate = true;
+					case '$clr.specular':
+						material.specular.fromArray( value );
+						break;
 
 
-							}
+					case '$clr.emissive':
+						material.emissive.fromArray( value );
+						break;
 
 
-						} );
+					case '$mat.shininess':
+						material.shininess = value;
+						break;
 
 
-					} )( prop.semantic );
+					case '$mat.shadingm':
+						// aiShadingMode_Flat
+						material.flatShading = ( value === 1 ) ? true : false;
+						break;
 
 
 				}
 				}
 
 
-			} else if ( prop.key === '?mat.name' ) {
-
-				init_props.name = prop.value;
-
-			} else if ( prop.key === '$clr.diffuse' ) {
-
-				init_props.color = toColor( prop.value );
-
-			} else if ( prop.key === '$clr.specular' ) {
-
-				init_props.specular = toColor( prop.value );
-
-			} else if ( prop.key === '$clr.emissive' ) {
+			}
 
 
-				init_props.emissive = toColor( prop.value );
+			return material;
 
 
-			} else if ( prop.key === '$mat.shadingm' ) {
+		}
 
 
-				// aiShadingMode_Flat
-				if ( prop.value === 1 ) {
+		function parseObject( json, node, meshes, materials ) {
 
 
-					init_props.shading = THREE.FlatShading;
+			var obj = new THREE.Object3D(),	i, idx;
 
 
-				}
+			obj.name = node.name || '';
+			obj.matrix = new THREE.Matrix4().fromArray( node.transformation ).transpose();
+			obj.matrix.decompose( obj.position, obj.quaternion, obj.scale );
 
 
-			} else if ( prop.key === '$mat.shininess' ) {
+			for ( i = 0; node.meshes && i < node.meshes.length; i ++ ) {
 
 
-				init_props.shininess = prop.value;
+				idx = node.meshes[ i ];
+				obj.add( new THREE.Mesh( meshes[ idx ], materials[ json.meshes[ idx ].materialindex ] ) );
 
 
 			}
 			}
 
 
-		}
-
-		// note: three.js does not like it when a texture is added after the geometry
-		// has been rendered once, see http://stackoverflow.com/questions/16531759/.
-		// for this reason we fill all slots upfront with default textures
-		if ( has_textures.length ) {
-
-			for ( i = has_textures.length - 1; i >= 0; -- i ) {
+			for ( i = 0; node.children && i < node.children.length; i ++ ) {
 
 
-				init_props[ has_textures[ i ]] = defaultTexture();
+				obj.add( parseObject( json, node.children[ i ], meshes, materials ) );
 
 
 			}
 			}
 
 
-		}
-
-		mat = new THREE.MeshPhongMaterial( init_props );
-		return mat;
-
-	},
-
-	parseObject : function( json, node, meshes, materials ) {
-
-		var obj = new THREE.Object3D(),	i, idx;
-
-		obj.name = node.name || "";
-		obj.matrix = new THREE.Matrix4().fromArray( node.transformation ).transpose();
-		obj.matrix.decompose( obj.position, obj.quaternion, obj.scale );
-
-		for ( i = 0; node.meshes && i < node.meshes.length; ++ i ) {
-
-			idx = node.meshes[ i ];
-			obj.add( new THREE.Mesh( meshes[ idx ], materials[ json.meshes[ idx ].materialindex ] ) );
+			return obj;
 
 
 		}
 		}
 
 
-		for ( i = 0; node.children && i < node.children.length; ++ i ) {
+		var textureLoader = new THREE.TextureLoader( this.manager );
+		textureLoader.setPath( path ).setCrossOrigin( this.crossOrigin );
 
 
-			obj.add( this.parseObject( json, node.children[ i ], meshes, materials ) );
-
-		}
-
-		return obj;
+		var meshes = parseList ( json.meshes, parseMesh );
+		var materials = parseList ( json.materials, parseMaterial );
+		return parseObject( json, json.rootnode, meshes, materials );
 
 
 	}
 	}
+
 };
 };

File diff suppressed because it is too large
+ 836 - 789
examples/js/loaders/AssimpLoader.js


+ 76 - 64
examples/js/loaders/BVHLoader.js

@@ -1,19 +1,20 @@
 /**
 /**
-* @author herzig / http://github.com/herzig
-*
-* Description: reads BVH files and outputs a single THREE.Skeleton and an THREE.AnimationClip
-*
-* Currently only supports bvh files containing a single root.
-*
-*/
+ * @author herzig / http://github.com/herzig
+ * @author Mugen87 / https://github.com/Mugen87
+ *
+ * Description: reads BVH files and outputs a single THREE.Skeleton and an THREE.AnimationClip
+ *
+ * Currently only supports bvh files containing a single root.
+ *
+ */
 
 
 THREE.BVHLoader = function( manager ) {
 THREE.BVHLoader = function( manager ) {
 
 
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+
 	this.animateBonePositions = true;
 	this.animateBonePositions = true;
 	this.animateBoneRotations = true;
 	this.animateBoneRotations = true;
 
 
-	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
-
 };
 };
 
 
 THREE.BVHLoader.prototype = {
 THREE.BVHLoader.prototype = {
@@ -40,14 +41,15 @@ THREE.BVHLoader.prototype = {
 			and outputs a skeleton structure including motion data
 			and outputs a skeleton structure including motion data
 
 
 			returns thee root node:
 			returns thee root node:
-			{ name: "", channels: [], children: [] }
+			{ name: '', channels: [], children: [] }
 		*/
 		*/
 		function readBvh( lines ) {
 		function readBvh( lines ) {
 
 
 			// read model structure
 			// read model structure
-			if ( nextLine( lines ) !== "HIERARCHY" ) {
 
 
-				throw "HIERARCHY expected";
+			if ( nextLine( lines ) !== 'HIERARCHY' ) {
+
+				console.error( 'THREE.BVHLoader: HIERARCHY expected.' );
 
 
 			}
 			}
 
 
@@ -55,35 +57,40 @@ THREE.BVHLoader.prototype = {
 			var root = readNode( lines, nextLine( lines ), list );
 			var root = readNode( lines, nextLine( lines ), list );
 
 
 			// read motion data
 			// read motion data
-			if ( nextLine( lines ) != "MOTION" ) {
 
 
-				throw "MOTION  expected";
+			if ( nextLine( lines ) !== 'MOTION' ) {
+
+				console.error( 'THREE.BVHLoader: MOTION expected.' );
 
 
 			}
 			}
 
 
 			// number of frames
 			// number of frames
+
 			var tokens = nextLine( lines ).split( /[\s]+/ );
 			var tokens = nextLine( lines ).split( /[\s]+/ );
 			var numFrames = parseInt( tokens[ 1 ] );
 			var numFrames = parseInt( tokens[ 1 ] );
+
 			if ( isNaN( numFrames ) ) {
 			if ( isNaN( numFrames ) ) {
 
 
-				throw "Failed to read number of frames.";
+				console.error( 'THREE.BVHLoader: Failed to read number of frames.' );
 
 
 			}
 			}
 
 
 			// frame time
 			// frame time
+
 			tokens = nextLine( lines ).split( /[\s]+/ );
 			tokens = nextLine( lines ).split( /[\s]+/ );
 			var frameTime = parseFloat( tokens[ 2 ] );
 			var frameTime = parseFloat( tokens[ 2 ] );
+
 			if ( isNaN( frameTime ) ) {
 			if ( isNaN( frameTime ) ) {
 
 
-				throw "Failed to read frame time.";
+				console.error( 'THREE.BVHLoader: Failed to read frame time.' );
 
 
 			}
 			}
 
 
 			// read frame data line by line
 			// read frame data line by line
-			for ( var i = 0; i < numFrames; ++ i ) {
 
 
-				tokens = nextLine( lines ).split( /[\s]+/ );
+			for ( var i = 0; i < numFrames; i ++ ) {
 
 
+				tokens = nextLine( lines ).split( /[\s]+/ );
 				readFrameData( tokens, i * frameTime, root );
 				readFrameData( tokens, i * frameTime, root );
 
 
 			}
 			}
@@ -105,16 +112,14 @@ THREE.BVHLoader.prototype = {
 		function readFrameData( data, frameTime, bone ) {
 		function readFrameData( data, frameTime, bone ) {
 
 
 			// end sites have no motion data
 			// end sites have no motion data
-			if ( bone.type === "ENDSITE" ) {
 
 
-				return;
-
-			}
+			if ( bone.type === 'ENDSITE' ) return;
 
 
 			// add keyframe
 			// add keyframe
+
 			var keyframe = {
 			var keyframe = {
 				time: frameTime,
 				time: frameTime,
-				position: { x: 0, y: 0, z: 0 },
+				position: new THREE.Vector3(),
 				rotation: new THREE.Quaternion()
 				rotation: new THREE.Quaternion()
 			};
 			};
 
 
@@ -127,40 +132,42 @@ THREE.BVHLoader.prototype = {
 			var vz = new THREE.Vector3( 0, 0, 1 );
 			var vz = new THREE.Vector3( 0, 0, 1 );
 
 
 			// parse values for each channel in node
 			// parse values for each channel in node
-			for ( var i = 0; i < bone.channels.length; ++ i ) {
+
+			for ( var i = 0; i < bone.channels.length; i ++ ) {
 
 
 				switch ( bone.channels[ i ] ) {
 				switch ( bone.channels[ i ] ) {
 
 
-				case "Xposition":
+				case 'Xposition':
 					keyframe.position.x = parseFloat( data.shift().trim() );
 					keyframe.position.x = parseFloat( data.shift().trim() );
 					break;
 					break;
-				case "Yposition":
+				case 'Yposition':
 					keyframe.position.y = parseFloat( data.shift().trim() );
 					keyframe.position.y = parseFloat( data.shift().trim() );
 					break;
 					break;
-				case "Zposition":
+				case 'Zposition':
 					keyframe.position.z = parseFloat( data.shift().trim() );
 					keyframe.position.z = parseFloat( data.shift().trim() );
 					break;
 					break;
-				case "Xrotation":
+				case 'Xrotation':
 					quat.setFromAxisAngle( vx, parseFloat( data.shift().trim() ) * Math.PI / 180 );
 					quat.setFromAxisAngle( vx, parseFloat( data.shift().trim() ) * Math.PI / 180 );
 					keyframe.rotation.multiply( quat );
 					keyframe.rotation.multiply( quat );
 					break;
 					break;
-				case "Yrotation":
+				case 'Yrotation':
 					quat.setFromAxisAngle( vy, parseFloat( data.shift().trim() ) * Math.PI / 180 );
 					quat.setFromAxisAngle( vy, parseFloat( data.shift().trim() ) * Math.PI / 180 );
 					keyframe.rotation.multiply( quat );
 					keyframe.rotation.multiply( quat );
 					break;
 					break;
-				case "Zrotation":
+				case 'Zrotation':
 					quat.setFromAxisAngle( vz, parseFloat( data.shift().trim() ) * Math.PI / 180 );
 					quat.setFromAxisAngle( vz, parseFloat( data.shift().trim() ) * Math.PI / 180 );
 					keyframe.rotation.multiply( quat );
 					keyframe.rotation.multiply( quat );
 					break;
 					break;
 				default:
 				default:
-					throw "invalid channel type";
+					console.warn( 'THREE.BVHLoader: Invalid channel type.' );
 
 
 				}
 				}
 
 
 			}
 			}
 
 
 			// parse child nodes
 			// parse child nodes
-			for ( var i = 0; i < bone.children.length; ++ i ) {
+
+			for ( var i = 0; i < bone.children.length; i ++ ) {
 
 
 				readFrameData( data, frameTime, bone.children[ i ] );
 				readFrameData( data, frameTime, bone.children[ i ] );
 
 
@@ -172,23 +179,24 @@ THREE.BVHLoader.prototype = {
 		 Recursively parses the HIERACHY section of the BVH file
 		 Recursively parses the HIERACHY section of the BVH file
 
 
 		 - lines: all lines of the file. lines are consumed as we go along.
 		 - lines: all lines of the file. lines are consumed as we go along.
-		 - firstline: line containing the node type and name e.g. "JOINT hip"
+		 - firstline: line containing the node type and name e.g. 'JOINT hip'
 		 - list: collects a flat list of nodes
 		 - list: collects a flat list of nodes
 
 
 		 returns: a BVH node including children
 		 returns: a BVH node including children
 		*/
 		*/
 		function readNode( lines, firstline, list ) {
 		function readNode( lines, firstline, list ) {
 
 
-			var node = { name: "", type: "", frames: [] };
+			var node = { name: '', type: '', frames: [] };
 			list.push( node );
 			list.push( node );
 
 
-			// parse node type and name.
+			// parse node type and name
+
 			var tokens = firstline.split( /[\s]+/ );
 			var tokens = firstline.split( /[\s]+/ );
 
 
-			if ( tokens[ 0 ].toUpperCase() === "END" && tokens[ 1 ].toUpperCase() === "SITE" ) {
+			if ( tokens[ 0 ].toUpperCase() === 'END' && tokens[ 1 ].toUpperCase() === 'SITE' ) {
 
 
-				node.type = "ENDSITE";
-				node.name = "ENDSITE"; // bvh end sites have no name
+				node.type = 'ENDSITE';
+				node.name = 'ENDSITE'; // bvh end sites have no name
 
 
 			} else {
 			} else {
 
 
@@ -197,49 +205,51 @@ THREE.BVHLoader.prototype = {
 
 
 			}
 			}
 
 
-			if ( nextLine( lines ) != "{" ) {
+			if ( nextLine( lines ) !== '{' ) {
 
 
-				throw "Expected opening { after type & name";
+				console.error( 'THREE.BVHLoader: Expected opening { after type & name' );
 
 
 			}
 			}
 
 
 			// parse OFFSET
 			// parse OFFSET
+
 			tokens = nextLine( lines ).split( /[\s]+/ );
 			tokens = nextLine( lines ).split( /[\s]+/ );
 
 
-			if ( tokens[ 0 ] !== "OFFSET" ) {
+			if ( tokens[ 0 ] !== 'OFFSET' ) {
 
 
-				throw "Expected OFFSET, but got: " + tokens[ 0 ];
+				console.error( 'THREE.BVHLoader: Expected OFFSET but got: ' + tokens[ 0 ] );
 
 
 			}
 			}
 
 
-			if ( tokens.length != 4 ) {
+			if ( tokens.length !== 4 ) {
 
 
-				throw "OFFSET: Invalid number of values";
+				console.error( 'THREE.BVHLoader: Invalid number of values for OFFSET.' );
 
 
 			}
 			}
 
 
-			var offset = {
-				x: parseFloat( tokens[ 1 ] ),
-				y: parseFloat( tokens[ 2 ] ),
-				z: parseFloat( tokens[ 3 ] )
-			};
+			var offset = new THREE.Vector3(
+				parseFloat( tokens[ 1 ] ),
+				parseFloat( tokens[ 2 ] ),
+				parseFloat( tokens[ 3 ] )
+			);
 
 
 			if ( isNaN( offset.x ) || isNaN( offset.y ) || isNaN( offset.z ) ) {
 			if ( isNaN( offset.x ) || isNaN( offset.y ) || isNaN( offset.z ) ) {
 
 
-				throw "OFFSET: Invalid values";
+				console.error( 'THREE.BVHLoader: Invalid values of OFFSET.' );
 
 
 			}
 			}
 
 
 			node.offset = offset;
 			node.offset = offset;
 
 
 			// parse CHANNELS definitions
 			// parse CHANNELS definitions
-			if ( node.type != "ENDSITE" ) {
+
+			if ( node.type !== 'ENDSITE' ) {
 
 
 				tokens = nextLine( lines ).split( /[\s]+/ );
 				tokens = nextLine( lines ).split( /[\s]+/ );
 
 
-				if ( tokens[ 0 ] != "CHANNELS" ) {
+				if ( tokens[ 0 ] !== 'CHANNELS' ) {
 
 
-					throw "Expected CHANNELS definition";
+					console.error( 'THREE.BVHLoader: Expected CHANNELS definition.' );
 
 
 				}
 				}
 
 
@@ -250,11 +260,12 @@ THREE.BVHLoader.prototype = {
 			}
 			}
 
 
 			// read children
 			// read children
+
 			while ( true ) {
 			while ( true ) {
 
 
 				var line = nextLine( lines );
 				var line = nextLine( lines );
 
 
-				if ( line === "}" ) {
+				if ( line === '}' ) {
 
 
 					return node;
 					return node;
 
 
@@ -284,9 +295,9 @@ THREE.BVHLoader.prototype = {
 			bone.position.add( source.offset );
 			bone.position.add( source.offset );
 			bone.name = source.name;
 			bone.name = source.name;
 
 
-			if ( source.type != "ENDSITE" ) {
+			if ( source.type !== 'ENDSITE' ) {
 
 
-				for ( var i = 0; i < source.children.length; ++ i ) {
+				for ( var i = 0; i < source.children.length; i ++ ) {
 
 
 					bone.add( toTHREEBone( source.children[ i ], list ) );
 					bone.add( toTHREEBone( source.children[ i ], list ) );
 
 
@@ -310,19 +321,21 @@ THREE.BVHLoader.prototype = {
 			var tracks = [];
 			var tracks = [];
 
 
 			// create a position and quaternion animation track for each node
 			// create a position and quaternion animation track for each node
-			for ( var i = 0; i < bones.length; ++ i ) {
+
+			for ( var i = 0; i < bones.length; i ++ ) {
 
 
 				var bone = bones[ i ];
 				var bone = bones[ i ];
 
 
-				if ( bone.type == "ENDSITE" )
+				if ( bone.type === 'ENDSITE' )
 					continue;
 					continue;
 
 
 				// track data
 				// track data
+
 				var times = [];
 				var times = [];
 				var positions = [];
 				var positions = [];
 				var rotations = [];
 				var rotations = [];
 
 
-				for ( var j = 0; j < bone.frames.length; ++ j ) {
+				for ( var j = 0; j < bone.frames.length; j ++ ) {
 
 
 					var frame = bone.frames[ j ];
 					var frame = bone.frames[ j ];
 
 
@@ -330,6 +343,7 @@ THREE.BVHLoader.prototype = {
 
 
 					// the animation system animates the position property,
 					// the animation system animates the position property,
 					// so we have to add the joint offset to all values
 					// so we have to add the joint offset to all values
+
 					positions.push( frame.position.x + bone.offset.x );
 					positions.push( frame.position.x + bone.offset.x );
 					positions.push( frame.position.y + bone.offset.y );
 					positions.push( frame.position.y + bone.offset.y );
 					positions.push( frame.position.z + bone.offset.z );
 					positions.push( frame.position.z + bone.offset.z );
@@ -343,21 +357,19 @@ THREE.BVHLoader.prototype = {
 
 
 				if ( scope.animateBonePositions ) {
 				if ( scope.animateBonePositions ) {
 
 
-					tracks.push( new THREE.VectorKeyframeTrack(
-						".bones[" + bone.name + "].position", times, positions ) );
+					tracks.push( new THREE.VectorKeyframeTrack( '.bones[' + bone.name + '].position', times, positions ) );
 
 
 				}
 				}
 
 
 				if ( scope.animateBoneRotations ) {
 				if ( scope.animateBoneRotations ) {
 
 
-					tracks.push( new THREE.QuaternionKeyframeTrack(
-						".bones[" + bone.name + "].quaternion", times, rotations ) );
+					tracks.push( new THREE.QuaternionKeyframeTrack( '.bones[' + bone.name + '].quaternion', times, rotations ) );
 
 
 				}
 				}
 
 
 			}
 			}
 
 
-			return new THREE.AnimationClip( "animation", - 1, tracks );
+			return new THREE.AnimationClip( 'animation', - 1, tracks );
 
 
 		}
 		}
 
 

+ 118 - 120
examples/js/loaders/BabylonLoader.js

@@ -1,5 +1,6 @@
 /**
 /**
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
+ * @author Mugen87 / https://github.com/Mugen87
  */
  */
 
 
 THREE.BabylonLoader = function ( manager ) {
 THREE.BabylonLoader = function ( manager ) {
@@ -27,220 +28,217 @@ THREE.BabylonLoader.prototype = {
 
 
 	parse: function ( json ) {
 	parse: function ( json ) {
 
 
-		var materials = this.parseMaterials( json );
-		var scene = this.parseObjects( json, materials );
+		function parseMaterials( json ) {
 
 
-		return scene;
-
-	},
-
-	parseMaterials: function ( json ) {
+			var materials = {};
 
 
-		var materials = {};
+			for ( var i = 0, l = json.materials.length; i < l; i ++ ) {
 
 
-		for ( var i = 0, l = json.materials.length; i < l; i ++ ) {
+				var data = json.materials[ i ];
 
 
-			var data = json.materials[ i ];
+				var material = new THREE.MeshPhongMaterial();
+				material.name = data.name;
+				material.color.fromArray( data.diffuse );
+				material.emissive.fromArray( data.emissive );
+				material.specular.fromArray( data.specular );
+				material.shininess = data.specularPower;
+				material.opacity = data.alpha;
 
 
-			var material = new THREE.MeshPhongMaterial();
-			material.name = data.name;
-			material.color.fromArray( data.diffuse );
-			material.emissive.fromArray( data.emissive );
-			material.specular.fromArray( data.specular );
-			material.shininess = data.specularPower;
-			material.opacity = data.alpha;
+				materials[ data.id ] = material;
 
 
-			materials[ data.id ] = material;
+			}
 
 
-		}
+			if ( json.multiMaterials ) {
 
 
-		if ( json.multiMaterials ) {
+				for ( var i = 0, l = json.multiMaterials.length; i < l; i ++ ) {
 
 
-			for ( var i = 0, l = json.multiMaterials.length; i < l; i ++ ) {
+					var data = json.multiMaterials[ i ];
 
 
-				var data = json.multiMaterials[ i ];
+					console.warn( 'THREE.BabylonLoader: Multi materials not yet supported.' );
 
 
-				console.warn( 'THREE.BabylonLoader: Multi materials not yet supported.' );
+					materials[ data.id ] = new THREE.MeshPhongMaterial();
 
 
-				materials[ data.id ] = new THREE.MeshPhongMaterial();
+				}
 
 
 			}
 			}
 
 
-		}
+			return materials;
 
 
-		return materials;
-
-	},
+		}
 
 
-	parseGeometry: function ( json ) {
+		function parseGeometry( json ) {
 
 
-		var geometry = new THREE.BufferGeometry();
+			var geometry = new THREE.BufferGeometry();
 
 
-		// indices
+			var indices = json.indices;
+			var positions = json.positions;
+			var normals = json.normals;
+			var uvs = json.uvs;
 
 
-		var indices = new Uint16Array( json.indices );
+			// indices
 
 
-		geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
+			geometry.setIndex( indices );
 
 
-		// positions
+			// positions
 
 
-		var positions = new Float32Array( json.positions );
+			for ( var j = 2, jl = positions.length; j < jl; j += 3 ) {
 
 
-		for ( var j = 2, jl = positions.length; j < jl; j += 3 ) {
+				positions[ j ] = - positions[ j ];
 
 
-			positions[ j ] = - positions[ j ];
+			}
 
 
-		}
+			geometry.addAttribute( 'position', new THREE.Float32BufferAttribute( positions, 3 ) );
 
 
-		geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+			// normals
 
 
-		// normals
+			if ( normals ) {
 
 
-		if ( json.normals ) {
+				for ( var j = 2, jl = normals.length; j < jl; j += 3 ) {
 
 
-			var normals = new Float32Array( json.normals );
+					normals[ j ] = - normals[ j ];
 
 
-			for ( var j = 2, jl = normals.length; j < jl; j += 3 ) {
+				}
 
 
-				normals[ j ] = - normals[ j ];
+				geometry.addAttribute( 'normal', new THREE.Float32BufferAttribute( normals, 3 ) );
 
 
 			}
 			}
 
 
-			geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
-
-		}
-
-		// uvs
+			// uvs
 
 
-		if ( json.uvs ) {
+			if ( uvs ) {
 
 
-			var uvs = new Float32Array( json.uvs );
+				geometry.addAttribute( 'uv', new THREE.Float32BufferAttribute( uvs, 2 ) );
 
 
-			geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
+			}
 
 
-		}
+			// offsets
 
 
-		// offsets
+			var subMeshes = json.subMeshes;
 
 
-		var subMeshes = json.subMeshes;
+			if ( subMeshes ) {
 
 
-		if ( subMeshes ) {
+				for ( var j = 0, jl = subMeshes.length; j < jl; j ++ ) {
 
 
-			for ( var j = 0, jl = subMeshes.length; j < jl; j ++ ) {
+					var subMesh = subMeshes[ j ];
 
 
-				var subMesh = subMeshes[ j ];
+					geometry.addGroup( subMesh.indexStart, subMesh.indexCount );
 
 
-				geometry.addGroup( subMesh.indexStart, subMesh.indexCount );
+				}
 
 
 			}
 			}
 
 
+			return geometry;
+
 		}
 		}
 
 
-		return geometry;
+		function parseObjects( json, materials ) {
 
 
-	},
+			var objects = {};
+			var scene = new THREE.Scene();
 
 
-	parseObjects: function ( json, materials ) {
+			var cameras = json.cameras;
 
 
-		var objects = {};
-		var scene = new THREE.Scene();
+			for ( var i = 0, l = cameras.length; i < l; i ++ ) {
 
 
-		var cameras = json.cameras;
+				var data = cameras[ i ];
 
 
-		for ( var i = 0, l = cameras.length; i < l; i ++ ) {
+				var camera = new THREE.PerspectiveCamera( ( data.fov / Math.PI ) * 180, 1.33, data.minZ, data.maxZ );
 
 
-			var data = cameras[ i ];
+				camera.name = data.name;
+				camera.position.fromArray( data.position );
+				if ( data.rotation ) camera.rotation.fromArray( data.rotation );
 
 
-			var camera = new THREE.PerspectiveCamera( ( data.fov / Math.PI ) * 180, 1.33, data.minZ, data.maxZ );
+				objects[ data.id ] = camera;
 
 
-			camera.name = data.name;
-			camera.position.fromArray( data.position );
-			if ( data.rotation ) camera.rotation.fromArray( data.rotation );
+			}
 
 
-			objects[ data.id ] = camera;
+			var lights = json.lights;
 
 
-		}
+			for ( var i = 0, l = lights.length; i < l; i ++ ) {
 
 
-		var lights = json.lights;
+				var data = lights[ i ];
 
 
-		for ( var i = 0, l = lights.length; i < l; i ++ ) {
+				var light;
 
 
-			var data = lights[ i ];
+				switch ( data.type ) {
 
 
-			var light;
+					case 0:
+						light = new THREE.PointLight();
+						break;
 
 
-			switch ( data.type ) {
+					case 1:
+						light = new THREE.DirectionalLight();
+						break;
 
 
-				case 0:
-					light = new THREE.PointLight();
-					break;
+					case 2:
+						light = new THREE.SpotLight();
+						break;
 
 
-				case 1:
-					light = new THREE.DirectionalLight();
-					break;
+					case 3:
+						light = new THREE.HemisphereLight();
+						break;
+				}
 
 
-				case 2:
-					light = new THREE.SpotLight();
-					break;
+				light.name = data.name;
+				if ( data.position ) light.position.set( data.position[ 0 ], data.position[ 1 ], - data.position[ 2 ] );
+				light.color.fromArray( data.diffuse );
+				if ( data.groundColor ) light.groundColor.fromArray( data.groundColor );
+				if ( data.intensity ) light.intensity = data.intensity;
 
 
-				case 3:
-					light = new THREE.HemisphereLight();
-					break;
-			}
+				objects[ data.id ] = light;
 
 
-			light.name = data.name;
-			if ( data.position ) light.position.set( data.position[ 0 ], data.position[ 1 ], - data.position[ 2 ] );
-			light.color.fromArray( data.diffuse );
-			if ( data.groundColor ) light.groundColor.fromArray( data.groundColor );
-			if ( data.intensity ) light.intensity = data.intensity;
+				scene.add( light );
 
 
-			objects[ data.id ] = light;
+			}
 
 
-			scene.add( light );
+			var meshes = json.meshes;
 
 
-		}
+			for ( var i = 0, l = meshes.length; i < l; i ++ ) {
 
 
-		var meshes = json.meshes;
+				var data = meshes[ i ];
 
 
-		for ( var i = 0, l = meshes.length; i < l; i ++ ) {
+				var object;
 
 
-			var data = meshes[ i ];
+				if ( data.indices ) {
 
 
-			var object;
+					var geometry = parseGeometry( data );
 
 
-			if ( data.indices ) {
+					object = new THREE.Mesh( geometry, materials[ data.materialId ] );
 
 
-				var geometry = this.parseGeometry( data );
+				} else {
 
 
-				object = new THREE.Mesh( geometry, materials[ data.materialId ] );
+					object = new THREE.Group();
 
 
-			} else {
+				}
 
 
-				object = new THREE.Group();
+				object.name = data.name;
+				object.position.set( data.position[ 0 ], data.position[ 1 ], - data.position[ 2 ] );
+				object.rotation.fromArray( data.rotation );
+				if ( data.rotationQuaternion ) object.quaternion.fromArray( data.rotationQuaternion );
+				object.scale.fromArray( data.scaling );
+				// object.visible = data.isVisible;
 
 
-			}
+				if ( data.parentId ) {
 
 
-			object.name = data.name;
-			object.position.set( data.position[ 0 ], data.position[ 1 ], - data.position[ 2 ] );
-			object.rotation.fromArray( data.rotation );
-			if ( data.rotationQuaternion ) object.quaternion.fromArray( data.rotationQuaternion );
-			object.scale.fromArray( data.scaling );
-			// object.visible = data.isVisible;
+					objects[ data.parentId ].add( object );
 
 
-			if ( data.parentId ) {
+				} else {
 
 
-				objects[ data.parentId ].add( object );
+					scene.add( object );
 
 
-			} else {
+				}
 
 
-				scene.add( object );
+				objects[ data.id ] = object;
 
 
 			}
 			}
 
 
-			objects[ data.id ] = object;
+			return scene;
 
 
 		}
 		}
 
 
+		var materials = parseMaterials( json );
+		var scene = parseObjects( json, materials );
+
 		return scene;
 		return scene;
 
 
 	}
 	}

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

@@ -19,6 +19,8 @@ THREE.BinaryLoader.prototype = {
 
 
 	constructor: THREE.BinaryLoader,
 	constructor: THREE.BinaryLoader,
 
 
+	crossOrigin: 'Anonymous',
+
 	// Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
 	// Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
 	//  - binary models consist of two files: JS and BIN
 	//  - binary models consist of two files: JS and BIN
 	//  - parameters
 	//  - parameters

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

@@ -31,7 +31,6 @@ THREE.ColladaLoader = function () {
 	var skins;
 	var skins;
 
 
 	var flip_uv = true;
 	var flip_uv = true;
-	var preferredShading = THREE.SmoothShading;
 
 
 	var options = {
 	var options = {
 		// Force Geometry to always be centered at the local origin of the
 		// Force Geometry to always be centered at the local origin of the
@@ -213,12 +212,6 @@ THREE.ColladaLoader = function () {
 
 
 	}
 	}
 
 
-	function setPreferredShading ( shading ) {
-
-		preferredShading = shading;
-
-	}
-
 	function parseAsset () {
 	function parseAsset () {
 
 
 		var elements = COLLADA.querySelectorAll('asset');
 		var elements = COLLADA.querySelectorAll('asset');
@@ -3817,7 +3810,6 @@ THREE.ColladaLoader = function () {
 
 
 		}
 		}
 
 
-		props[ 'shading' ] = preferredShading;
 		props[ 'side' ] = this.effect.doubleSided ? THREE.DoubleSide : THREE.FrontSide;
 		props[ 'side' ] = this.effect.doubleSided ? THREE.DoubleSide : THREE.FrontSide;
 
 
 		if ( props.diffuse !== undefined ) {
 		if ( props.diffuse !== undefined ) {
@@ -5536,7 +5528,6 @@ THREE.ColladaLoader = function () {
 
 
 		load: load,
 		load: load,
 		parse: parse,
 		parse: parse,
-		setPreferredShading: setPreferredShading,
 		applySkin: applySkin,
 		applySkin: applySkin,
 		geometries : geometries,
 		geometries : geometries,
 		options: options
 		options: options

File diff suppressed because it is too large
+ 785 - 179
examples/js/loaders/ColladaLoader2.js


+ 155 - 78
examples/js/loaders/FBXLoader.js

@@ -48,9 +48,7 @@
 
 
 			var self = this;
 			var self = this;
 
 
-			var resourceDirectory = url.split( /[\\\/]/ );
-			resourceDirectory.pop();
-			resourceDirectory = resourceDirectory.join( '/' ) + '/';
+			var resourceDirectory = THREE.Loader.prototype.extractUrlBase( url );
 
 
 			var loader = new THREE.FileLoader( this.manager );
 			var loader = new THREE.FileLoader( this.manager );
 			loader.setResponseType( 'arraybuffer' );
 			loader.setResponseType( 'arraybuffer' );
@@ -100,15 +98,13 @@
 
 
 				if ( ! isFbxFormatASCII( FBXText ) ) {
 				if ( ! isFbxFormatASCII( FBXText ) ) {
 
 
-					self.manager.itemError( url );
-					throw new Error( 'FBXLoader: Unknown format.' );
+					throw new Error( 'THREE.FBXLoader: Unknown format.' );
 
 
 				}
 				}
 
 
 				if ( getFbxVersion( FBXText ) < 7000 ) {
 				if ( getFbxVersion( FBXText ) < 7000 ) {
 
 
-					self.manager.itemError( url );
-					throw new Error( 'FBXLoader: FBX version not supported for file at ' + url + ', FileVersion: ' + getFbxVersion( FBXText ) );
+					throw new Error( 'THREE.FBXLoader: FBX version not supported, FileVersion: ' + getFbxVersion( FBXText ) );
 
 
 				}
 				}
 
 
@@ -189,12 +185,12 @@
 	/**
 	/**
 	 * Parses map of images referenced in FBXTree.
 	 * Parses map of images referenced in FBXTree.
 	 * @param {{Objects: {subNodes: {Texture: Object.<string, FBXTextureNode>}}}} FBXTree
 	 * @param {{Objects: {subNodes: {Texture: Object.<string, FBXTextureNode>}}}} FBXTree
-	 * @returns {Map<number, string(image blob URL)>}
+	 * @returns {Map<number, string(image blob/data URL)>}
 	 */
 	 */
 	function parseImages( FBXTree ) {
 	function parseImages( FBXTree ) {
 
 
 		/**
 		/**
-		 * @type {Map<number, string(image blob URL)>}
+		 * @type {Map<number, string(image blob/data URL)>}
 		 */
 		 */
 		var imageMap = new Map();
 		var imageMap = new Map();
 
 
@@ -224,12 +220,11 @@
 
 
 	/**
 	/**
 	 * @param {videoNode} videoNode - Node to get texture image information from.
 	 * @param {videoNode} videoNode - Node to get texture image information from.
-	 * @returns {string} - image blob URL
+	 * @returns {string} - image blob/data URL
 	 */
 	 */
 	function parseImage( videoNode ) {
 	function parseImage( videoNode ) {
 
 
-		var buffer = videoNode.properties.Content;
-		var array = new Uint8Array( buffer );
+		var content = videoNode.properties.Content;
 		var fileName = videoNode.properties.RelativeFilename || videoNode.properties.Filename;
 		var fileName = videoNode.properties.RelativeFilename || videoNode.properties.Filename;
 		var extension = fileName.slice( fileName.lastIndexOf( '.' ) + 1 ).toLowerCase();
 		var extension = fileName.slice( fileName.lastIndexOf( '.' ) + 1 ).toLowerCase();
 
 
@@ -264,7 +259,16 @@
 
 
 		}
 		}
 
 
-		return window.URL.createObjectURL( new Blob( [ array ], { type: type } ) );
+		if ( typeof content === 'string' ) {
+
+			return 'data:' + type + ';base64,' + content;
+
+		} else {
+
+			var array = new Uint8Array( content );
+			return window.URL.createObjectURL( new Blob( [ array ], { type: type } ) );
+
+		}
 
 
 	}
 	}
 
 
@@ -272,7 +276,7 @@
 	 * Parses map of textures referenced in FBXTree.
 	 * Parses map of textures referenced in FBXTree.
 	 * @param {{Objects: {subNodes: {Texture: Object.<string, FBXTextureNode>}}}} FBXTree
 	 * @param {{Objects: {subNodes: {Texture: Object.<string, FBXTextureNode>}}}} FBXTree
 	 * @param {THREE.TextureLoader} loader
 	 * @param {THREE.TextureLoader} loader
-	 * @param {Map<number, string(image blob URL)>} imageMap
+	 * @param {Map<number, string(image blob/data URL)>} imageMap
 	 * @param {Map<number, {parents: {ID: number, relationship: string}[], children: {ID: number, relationship: string}[]}>} connections
 	 * @param {Map<number, {parents: {ID: number, relationship: string}[], children: {ID: number, relationship: string}[]}>} connections
 	 * @returns {Map<number, THREE.Texture>}
 	 * @returns {Map<number, THREE.Texture>}
 	 */
 	 */
@@ -302,7 +306,7 @@
 	/**
 	/**
 	 * @param {textureNode} textureNode - Node to get texture information from.
 	 * @param {textureNode} textureNode - Node to get texture information from.
 	 * @param {THREE.TextureLoader} loader
 	 * @param {THREE.TextureLoader} loader
-	 * @param {Map<number, string(image blob URL)>} imageMap
+	 * @param {Map<number, string(image blob/data URL)>} imageMap
 	 * @param {Map<number, {parents: {ID: number, relationship: string}[], children: {ID: number, relationship: string}[]}>} connections
 	 * @param {Map<number, {parents: {ID: number, relationship: string}[], children: {ID: number, relationship: string}[]}>} connections
 	 * @returns {THREE.Texture}
 	 * @returns {THREE.Texture}
 	 */
 	 */
@@ -349,7 +353,7 @@
 
 
 		var currentPath = loader.path;
 		var currentPath = loader.path;
 
 
-		if ( fileName.indexOf( 'blob:' ) === 0 ) {
+		if ( fileName.indexOf( 'blob:' ) === 0 || fileName.indexOf( 'data:' ) === 0 ) {
 
 
 			loader.setPath( undefined );
 			loader.setPath( undefined );
 
 
@@ -442,7 +446,7 @@
 				material = new THREE.MeshLambertMaterial();
 				material = new THREE.MeshLambertMaterial();
 				break;
 				break;
 			default:
 			default:
-				console.warn( 'No implementation given for material type ' + type + ' in FBXLoader.js.  Defaulting to basic material' );
+				console.warn( 'THREE.FBXLoader: No implementation given for material type %s in FBXLoader.js. Defaulting to basic material.', type );
 				material = new THREE.MeshBasicMaterial( { color: 0x3300ff } );
 				material = new THREE.MeshBasicMaterial( { color: 0x3300ff } );
 				break;
 				break;
 
 
@@ -515,27 +519,27 @@
 
 
 			switch ( type ) {
 			switch ( type ) {
 
 
-				case "DiffuseColor":
-				case " \"DiffuseColor":
+				case 'DiffuseColor':
+				case ' "DiffuseColor':
 					parameters.map = textureMap.get( relationship.ID );
 					parameters.map = textureMap.get( relationship.ID );
 					break;
 					break;
 
 
-				case "Bump":
-				case " \"Bump":
+				case 'Bump':
+				case ' "Bump':
 					parameters.bumpMap = textureMap.get( relationship.ID );
 					parameters.bumpMap = textureMap.get( relationship.ID );
 					break;
 					break;
 
 
-				case "NormalMap":
-				case " \"NormalMap":
+				case 'NormalMap':
+				case ' "NormalMap':
 					parameters.normalMap = textureMap.get( relationship.ID );
 					parameters.normalMap = textureMap.get( relationship.ID );
 					break;
 					break;
 
 
-				case " \"AmbientColor":
-				case " \"EmissiveColor":
-				case "AmbientColor":
-				case "EmissiveColor":
+				case 'AmbientColor':
+				case 'EmissiveColor':
+				case ' "AmbientColor':
+				case ' "EmissiveColor':
 				default:
 				default:
-					console.warn( 'Unknown texture application of type ' + type + ', skipping texture' );
+					console.warn( 'THREE.FBXLoader: Unknown texture application of type %s, skipping texture.', type );
 					break;
 					break;
 
 
 			}
 			}
@@ -738,8 +742,38 @@
 
 
 		}
 		}
 
 
+		var weightTable = {};
+
+		if ( deformer ) {
+
+			var subDeformers = deformer.map;
+
+			for ( var key in subDeformers ) {
+
+				var subDeformer = subDeformers[ key ];
+				var indices = subDeformer.indices;
+
+				for ( var j = 0; j < indices.length; j ++ ) {
+
+					var index = indices[ j ];
+					var weight = subDeformer.weights[ j ];
+
+					if ( weightTable[ index ] === undefined ) weightTable[ index ] = [];
+
+					weightTable[ index ].push( {
+						id: subDeformer.index,
+						weight: weight
+					} );
+
+				}
+
+			}
+
+		}
+
 		var faceVertexBuffer = [];
 		var faceVertexBuffer = [];
 		var polygonIndex = 0;
 		var polygonIndex = 0;
+		var displayedWeightsWarning = false;
 
 
 		for ( var polygonVertexIndex = 0; polygonVertexIndex < indexBuffer.length; polygonVertexIndex ++ ) {
 		for ( var polygonVertexIndex = 0; polygonVertexIndex < indexBuffer.length; polygonVertexIndex ++ ) {
 
 
@@ -763,25 +797,14 @@
 
 
 			if ( deformer ) {
 			if ( deformer ) {
 
 
-				var subDeformers = deformer.map;
-
-				for ( var key in subDeformers ) {
-
-					var subDeformer = subDeformers[ key ];
-					var indices = subDeformer.indices;
+				if ( weightTable[ vertexIndex ] !== undefined ) {
 
 
-					for ( var j = 0; j < indices.length; j ++ ) {
+					var array = weightTable[ vertexIndex ];
 
 
-						var index = indices[ j ];
+					for ( var j = 0, jl = array.length; j < jl; j ++ ) {
 
 
-						if ( index === vertexIndex ) {
-
-							weights.push( subDeformer.weights[ j ] );
-							weightIndices.push( subDeformer.index );
-
-							break;
-
-						}
+						weights.push( array[ j ].weight );
+						weightIndices.push( array[ j ].id );
 
 
 					}
 					}
 
 
@@ -789,7 +812,12 @@
 
 
 				if ( weights.length > 4 ) {
 				if ( weights.length > 4 ) {
 
 
-					console.warn( 'FBXLoader: Vertex has more than 4 skinning weights assigned to vertex.  Deleting additional weights.' );
+					if ( ! displayedWeightsWarning ) {
+
+						console.warn( 'THREE.FBXLoader: Vertex has more than 4 skinning weights assigned to vertex. Deleting additional weights.' );
+						displayedWeightsWarning = true;
+
+					}
 
 
 					var WIndex = [ 0, 0, 0, 0 ];
 					var WIndex = [ 0, 0, 0, 0 ];
 					var Weight = [ 0, 0, 0, 0 ];
 					var Weight = [ 0, 0, 0, 0 ];
@@ -1222,7 +1250,7 @@
 
 
 		if ( THREE.NURBSCurve === undefined ) {
 		if ( THREE.NURBSCurve === undefined ) {
 
 
-			console.error( "THREE.FBXLoader relies on THREE.NURBSCurve for any nurbs present in the model.  Nurbs will show up as empty geometry." );
+			console.error( 'THREE.FBXLoader: The loader relies on THREE.NURBSCurve for any nurbs present in the model. Nurbs will show up as empty geometry.' );
 			return new THREE.BufferGeometry();
 			return new THREE.BufferGeometry();
 
 
 		}
 		}
@@ -1231,7 +1259,7 @@
 
 
 		if ( isNaN( order ) ) {
 		if ( isNaN( order ) ) {
 
 
-			console.error( "FBXLoader: Invalid Order " + geometryNode.properties.Order + " given for geometry ID: " + geometryNode.id );
+			console.error( 'THREE.FBXLoader: Invalid Order %s given for geometry ID: %s', geometryNode.properties.Order, geometryNode.id );
 			return new THREE.BufferGeometry();
 			return new THREE.BufferGeometry();
 
 
 		}
 		}
@@ -1345,7 +1373,7 @@
 
 
 				switch ( node.attrType ) {
 				switch ( node.attrType ) {
 
 
-					case "Mesh":
+					case 'Mesh':
 						/**
 						/**
 						 * @type {?THREE.BufferGeometry}
 						 * @type {?THREE.BufferGeometry}
 						 */
 						 */
@@ -1417,7 +1445,7 @@
 						}
 						}
 						break;
 						break;
 
 
-					case "NurbsCurve":
+					case 'NurbsCurve':
 						var geometry = null;
 						var geometry = null;
 
 
 						for ( var childrenIndex = 0, childrenLength = conns.children.length; childrenIndex < childrenLength; ++ childrenIndex ) {
 						for ( var childrenIndex = 0, childrenLength = conns.children.length; childrenIndex < childrenLength; ++ childrenIndex ) {
@@ -2154,6 +2182,41 @@
 			if ( curveNode.attr === 'R' ) {
 			if ( curveNode.attr === 'R' ) {
 
 
 				var curves = curveNode.curves;
 				var curves = curveNode.curves;
+
+				// Seems like some FBX files have AnimationCurveNode
+				// which doesn't have any connected AnimationCurve.
+				// Setting animation parameter for them here.
+
+				if ( curves.x === null ) {
+
+					curves.x = {
+						version: null,
+						times: [ 0.0 ],
+						values: [ 0.0 ]
+					};
+
+				}
+
+				if ( curves.y === null ) {
+
+					curves.y = {
+						version: null,
+						times: [ 0.0 ],
+						values: [ 0.0 ]
+					};
+
+				}
+
+				if ( curves.z === null ) {
+
+					curves.z = {
+						version: null,
+						times: [ 0.0 ],
+						values: [ 0.0 ]
+					};
+
+				}
+
 				curves.x.values = curves.x.values.map( degreeToRadian );
 				curves.x.values = curves.x.values.map( degreeToRadian );
 				curves.y.values = curves.y.values.map( degreeToRadian );
 				curves.y.values = curves.y.values.map( degreeToRadian );
 				curves.z.values = curves.z.values.map( degreeToRadian );
 				curves.z.values = curves.z.values.map( degreeToRadian );
@@ -3228,8 +3291,8 @@
 		} catch ( error ) {
 		} catch ( error ) {
 
 
 			// Curve is not fully plotted.
 			// Curve is not fully plotted.
-			console.log( bone );
-			console.log( error );
+			console.log( 'THREE.FBXLoader: ', bone );
+			console.log( 'THREE.FBXLoader: ', error );
 
 
 		}
 		}
 
 
@@ -3562,30 +3625,33 @@
 			this.currentProp = [];
 			this.currentProp = [];
 			this.currentPropName = '';
 			this.currentPropName = '';
 
 
-			var split = text.split( "\n" );
+			var split = text.split( '\n' );
 
 
-			for ( var line in split ) {
+			for ( var lineNum = 0, lineLength = split.length; lineNum < lineLength; lineNum ++ ) {
 
 
-				var l = split[ line ];
+				var l = split[ lineNum ];
 
 
-				// short cut
+				// skip comment line
 				if ( l.match( /^[\s\t]*;/ ) ) {
 				if ( l.match( /^[\s\t]*;/ ) ) {
 
 
 					continue;
 					continue;
 
 
-				} // skip comment line
+				}
+
+				// skip empty line
 				if ( l.match( /^[\s\t]*$/ ) ) {
 				if ( l.match( /^[\s\t]*$/ ) ) {
 
 
 					continue;
 					continue;
 
 
-				} // skip empty line
+				}
 
 
 				// beginning of node
 				// beginning of node
-				var beginningOfNodeExp = new RegExp( "^\\t{" + this.currentIndent + "}(\\w+):(.*){", '' );
+				var beginningOfNodeExp = new RegExp( '^\\t{' + this.currentIndent + '}(\\w+):(.*){', '' );
 				var match = l.match( beginningOfNodeExp );
 				var match = l.match( beginningOfNodeExp );
+
 				if ( match ) {
 				if ( match ) {
 
 
-					var nodeName = match[ 1 ].trim().replace( /^"/, '' ).replace( /"$/, "" );
+					var nodeName = match[ 1 ].trim().replace( /^"/, '' ).replace( /"$/, '' );
 					var nodeAttrs = match[ 2 ].split( ',' );
 					var nodeAttrs = match[ 2 ].split( ',' );
 
 
 					for ( var i = 0, l = nodeAttrs.length; i < l; i ++ ) {
 					for ( var i = 0, l = nodeAttrs.length; i < l; i ++ ) {
@@ -3598,12 +3664,22 @@
 				}
 				}
 
 
 				// node's property
 				// node's property
-				var propExp = new RegExp( "^\\t{" + ( this.currentIndent ) + "}(\\w+):[\\s\\t\\r\\n](.*)" );
+				var propExp = new RegExp( '^\\t{' + ( this.currentIndent ) + '}(\\w+):[\\s\\t\\r\\n](.*)' );
 				var match = l.match( propExp );
 				var match = l.match( propExp );
+
 				if ( match ) {
 				if ( match ) {
 
 
-					var propName = match[ 1 ].replace( /^"/, '' ).replace( /"$/, "" ).trim();
-					var propValue = match[ 2 ].replace( /^"/, '' ).replace( /"$/, "" ).trim();
+					var propName = match[ 1 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
+					var propValue = match[ 2 ].replace( /^"/, '' ).replace( /"$/, '' ).trim();
+
+					// for special case: base64 image data follows "Content: ," line
+					//	Content: ,
+					//	 "iVB..."
+					if ( propName === 'Content' && propValue === ',' ) {
+
+						propValue = split[ ++ lineNum ].replace( /"/g, '' ).trim();
+
+					}
 
 
 					this.parseNodeProperty( l, propName, propValue );
 					this.parseNodeProperty( l, propName, propValue );
 					continue;
 					continue;
@@ -3611,7 +3687,8 @@
 				}
 				}
 
 
 				// end of node
 				// end of node
-				var endOfNodeExp = new RegExp( "^\\t{" + ( this.currentIndent - 1 ) + "}}" );
+				var endOfNodeExp = new RegExp( '^\\t{' + ( this.currentIndent - 1 ) + '}}' );
+
 				if ( l.match( endOfNodeExp ) ) {
 				if ( l.match( endOfNodeExp ) ) {
 
 
 					this.nodeEnd();
 					this.nodeEnd();
@@ -3720,7 +3797,7 @@
 
 
 			var id = attrs[ 0 ];
 			var id = attrs[ 0 ];
 
 
-			if ( attrs[ 0 ] !== "" ) {
+			if ( attrs[ 0 ] !== '' ) {
 
 
 				id = parseInt( attrs[ 0 ] );
 				id = parseInt( attrs[ 0 ] );
 
 
@@ -3752,7 +3829,7 @@
 			var parentName = currentNode.name;
 			var parentName = currentNode.name;
 
 
 			// special case parent node's is like "Properties70"
 			// special case parent node's is like "Properties70"
-			// these chilren nodes must treat with careful
+			// these children nodes must treat with careful
 			if ( parentName !== undefined ) {
 			if ( parentName !== undefined ) {
 
 
 				var propMatch = parentName.match( /Properties(\d)+/ );
 				var propMatch = parentName.match( /Properties(\d)+/ );
@@ -3766,7 +3843,7 @@
 			}
 			}
 
 
 			// special case Connections
 			// special case Connections
-			if ( propName == 'C' ) {
+			if ( propName === 'C' ) {
 
 
 				var connProps = propValue.split( ',' ).slice( 1 );
 				var connProps = propValue.split( ',' ).slice( 1 );
 				var from = parseInt( connProps[ 0 ] );
 				var from = parseInt( connProps[ 0 ] );
@@ -3787,7 +3864,7 @@
 			}
 			}
 
 
 			// special case Connections
 			// special case Connections
-			if ( propName == 'Node' ) {
+			if ( propName === 'Node' ) {
 
 
 				var id = parseInt( propValue );
 				var id = parseInt( propValue );
 				currentNode.properties.id = id;
 				currentNode.properties.id = id;
@@ -3862,16 +3939,16 @@
 			// cast value in its type
 			// cast value in its type
 			switch ( innerPropType1 ) {
 			switch ( innerPropType1 ) {
 
 
-				case "int":
+				case 'int':
 					innerPropValue = parseInt( innerPropValue );
 					innerPropValue = parseInt( innerPropValue );
 					break;
 					break;
 
 
-				case "double":
+				case 'double':
 					innerPropValue = parseFloat( innerPropValue );
 					innerPropValue = parseFloat( innerPropValue );
 					break;
 					break;
 
 
-				case "ColorRGB":
-				case "Vector3D":
+				case 'ColorRGB':
+				case 'Vector3D':
 					innerPropValue = parseFloatArray( innerPropValue );
 					innerPropValue = parseFloatArray( innerPropValue );
 					break;
 					break;
 
 
@@ -3926,7 +4003,7 @@
 
 
 			var version = reader.getUint32();
 			var version = reader.getUint32();
 
 
-			console.log( 'FBX binary version: ' + version );
+			console.log( 'THREE.FBXLoader: FBX binary version: ' + version );
 
 
 			var allNodes = new FBXTree();
 			var allNodes = new FBXTree();
 
 
@@ -3951,7 +4028,7 @@
 			// footer size: 160bytes + 16-byte alignment padding
 			// footer size: 160bytes + 16-byte alignment padding
 			// - 16bytes: magic
 			// - 16bytes: magic
 			// - padding til 16-byte alignment (at least 1byte?)
 			// - padding til 16-byte alignment (at least 1byte?)
-			//   (seems like some exporters embed fixed 15bytes?)
+			//   (seems like some exporters embed fixed 15 or 16bytes?)
 			// - 4bytes: magic
 			// - 4bytes: magic
 			// - 4bytes: version
 			// - 4bytes: version
 			// - 120bytes: zero
 			// - 120bytes: zero
@@ -3962,7 +4039,7 @@
 
 
 			} else {
 			} else {
 
 
-				return reader.getOffset() + 160 + 15 >= reader.size();
+				return reader.getOffset() + 160 + 16 >= reader.size();
 
 
 			}
 			}
 
 
@@ -4270,7 +4347,7 @@
 
 
 					if ( window.Zlib === undefined ) {
 					if ( window.Zlib === undefined ) {
 
 
-						throw new Error( 'FBXLoader: Import inflate.min.js from https://github.com/imaya/zlib.js' );
+						throw new Error( 'THREE.FBXLoader: External library Inflate.min.js required, obtain or import from https://github.com/imaya/zlib.js' );
 
 
 					}
 					}
 
 
@@ -4305,7 +4382,7 @@
 					return reader.getArrayBuffer( length );
 					return reader.getArrayBuffer( length );
 
 
 				default:
 				default:
-					throw new Error( 'FBXLoader: Unknown property type ' + type );
+					throw new Error( 'THREE.FBXLoader: Unknown property type ' + type );
 
 
 			}
 			}
 
 
@@ -4845,7 +4922,7 @@
 		for ( var i = 0; i < CORRECT.length; ++ i ) {
 		for ( var i = 0; i < CORRECT.length; ++ i ) {
 
 
 			var num = read( 1 );
 			var num = read( 1 );
-			if ( num == CORRECT[ i ] ) {
+			if ( num === CORRECT[ i ] ) {
 
 
 				return false;
 				return false;
 
 
@@ -4870,7 +4947,7 @@
 			return version;
 			return version;
 
 
 		}
 		}
-		throw new Error( 'FBXLoader: Cannot find the version number for the file given.' );
+		throw new Error( 'THREE.FBXLoader: Cannot find the version number for the file given.' );
 
 
 	}
 	}
 
 

+ 0 - 2872
examples/js/loaders/GLTF2Loader.js

@@ -1,2872 +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
- * @author Don McCurdy / https://www.donmccurdy.com
- */
-
-THREE.GLTF2Loader = ( function () {
-
-	function GLTF2Loader( manager ) {
-
-		this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
-
-	}
-
-	GLTF2Loader.prototype = {
-
-		constructor: GLTF2Loader,
-
-		load: function ( url, onLoad, onProgress, onError ) {
-
-			var scope = this;
-
-			var path = this.path && ( typeof this.path === "string" ) ? this.path : THREE.Loader.prototype.extractUrlBase( url );
-
-			var loader = new THREE.FileLoader( scope.manager );
-
-			loader.setResponseType( 'arraybuffer' );
-
-			loader.load( url, function ( data ) {
-
-				scope.parse( data, onLoad, path );
-
-			}, onProgress, onError );
-
-		},
-
-		setCrossOrigin: function ( value ) {
-
-			this.crossOrigin = value;
-
-		},
-
-		setPath: function ( value ) {
-
-			this.path = value;
-
-		},
-
-		parse: function ( data, callback, path ) {
-
-			var content;
-			var extensions = {};
-
-			var magic = convertUint8ArrayToString( new Uint8Array( data, 0, 4 ) );
-
-			if ( magic === BINARY_EXTENSION_HEADER_MAGIC ) {
-
-				extensions[ EXTENSIONS.KHR_BINARY_GLTF ] = new GLTFBinaryExtension( data );
-				content = extensions[ EXTENSIONS.KHR_BINARY_GLTF ].content;
-
-			} else {
-
-				content = convertUint8ArrayToString( new Uint8Array( data ) );
-
-			}
-
-			var json = JSON.parse( content );
-
-			if ( json.extensionsUsed ) {
-
-				if( json.extensionsUsed.indexOf( EXTENSIONS.KHR_LIGHTS ) >= 0 ) {
-
-					extensions[ EXTENSIONS.KHR_LIGHTS ] = new GLTFLightsExtension( json );
-
-				}
-
-				if( json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_COMMON ) >= 0 ) {
-
-					extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] = new GLTFMaterialsCommonExtension( json );
-
-				}
-
-				if( json.extensionsUsed.indexOf( EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ) >= 0 ) {
-
-					extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] = new GLTFMaterialsPbrSpecularGlossinessExtension();
-
-				}
-
-				if ( json.extensionsUsed.indexOf( EXTENSIONS.KHR_TECHNIQUE_WEBGL ) >= 0 ) {
-
-					extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ] = new GLTFTechniqueWebglExtension( json );
-
-				}
-
-			}
-
-			console.time( 'GLTF2Loader' );
-
-			var parser = new GLTFParser( json, extensions, {
-
-				path: path || this.path,
-				crossOrigin: this.crossOrigin
-
-			} );
-
-			parser.parse( function ( scene, scenes, cameras, animations ) {
-
-				console.timeEnd( 'GLTF2Loader' );
-
-				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 );
-
-					}
-
-				}
-
-			}
-
-		};
-
-	}
-
-	/* 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;
-
-			}
-
-		}
-
-	};
-
-	/*********************************/
-	/********** EXTENSIONS ***********/
-	/*********************************/
-
-	var EXTENSIONS = {
-		KHR_BINARY_GLTF: 'KHR_binary_glTF',
-		KHR_LIGHTS: 'KHR_lights',
-		KHR_MATERIALS_COMMON: 'KHR_materials_common',
-		KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS: 'KHR_materials_pbrSpecularGlossiness',
-		KHR_TECHNIQUE_WEBGL: 'KHR_technique_webgl',
-	};
-
-	/**
-	 * Lights Extension
-	 *
-	 * Specification: PENDING
-	 */
-	function GLTFLightsExtension( json ) {
-
-		this.name = EXTENSIONS.KHR_LIGHTS;
-
-		this.lights = {};
-
-		var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_LIGHTS ] ) || {};
-		var lights = extension.lights || {};
-
-		for ( var lightId in lights ) {
-
-			var light = lights[ lightId ];
-			var lightNode;
-
-			var color = new THREE.Color().fromArray( light.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 ) {
-
-				lightNode.name = light.name || ( 'light_' + lightId );
-				this.lights[ lightId ] = lightNode;
-
-			}
-
-		}
-
-	}
-
-	/**
-	 * Common Materials Extension
-	 *
-	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_common
-	 */
-	function GLTFMaterialsCommonExtension( json ) {
-
-		this.name = EXTENSIONS.KHR_MATERIALS_COMMON;
-
-	}
-
-	GLTFMaterialsCommonExtension.prototype.getMaterialType = function ( material ) {
-
-		var khrMaterial = material.extensions[ this.name ];
-
-		switch ( khrMaterial.type ) {
-
-			case 'commonBlinn' :
-			case 'commonPhong' :
-				return THREE.MeshPhongMaterial;
-
-			case 'commonLambert' :
-				return THREE.MeshLambertMaterial;
-
-			case 'commonConstant' :
-			default :
-				return THREE.MeshBasicMaterial;
-
-		}
-
-	};
-
-	GLTFMaterialsCommonExtension.prototype.extendParams = function ( materialParams, material, dependencies ) {
-
-		var khrMaterial = material.extensions[ this.name ];
-
-		var keys = [];
-
-		// TODO: Currently ignored: 'ambientFactor', 'ambientTexture'
-		switch ( khrMaterial.type ) {
-
-			case 'commonBlinn' :
-			case 'commonPhong' :
-				keys.push( 'diffuseFactor', 'diffuseTexture', 'specularFactor', 'specularTexture', 'shininessFactor' );
-				break;
-
-			case 'commonLambert' :
-				keys.push( 'diffuseFactor', 'diffuseTexture' );
-				break;
-
-			case 'commonConstant' :
-			default :
-				break;
-
-		}
-
-		var materialValues = {};
-
-		keys.forEach( function( v ) {
-
-			if ( khrMaterial[ v ] !== undefined ) materialValues[ v ] = khrMaterial[ v ];
-
-		} );
-
-		if ( materialValues.diffuseFactor !== undefined ) {
-
-			materialParams.color = new THREE.Color().fromArray( materialValues.diffuseFactor );
-
-		}
-
-		if ( materialValues.diffuseTexture !== undefined ) {
-
-			materialParams.map = dependencies.textures[ materialValues.diffuseTexture.index ];
-
-		}
-
-		if ( materialValues.specularFactor !== undefined ) {
-
-			materialParams.specular = new THREE.Color().fromArray( materialValues.specularFactor );
-
-		}
-
-		if ( materialValues.specularTexture !== undefined ) {
-
-			materialParams.specularMap = dependencies.textures[ materialValues.specularTexture.index ];
-
-		}
-
-		if ( materialValues.shininessFactor !== undefined ) {
-
-			materialParams.shininess = materialValues.shininessFactor;
-
-		}
-
-	};
-
-	/* BINARY EXTENSION */
-
-	var BINARY_EXTENSION_BUFFER_NAME = 'binary_glTF';
-	var BINARY_EXTENSION_HEADER_MAGIC = 'glTF';
-	var BINARY_EXTENSION_HEADER_LENGTH = 12;
-	var BINARY_EXTENSION_CHUNK_TYPES = { JSON: 0x4E4F534A, BIN: 0x004E4942 };
-
-	function GLTFBinaryExtension( data ) {
-
-		this.name = EXTENSIONS.KHR_BINARY_GLTF;
-		this.content = null;
-		this.body = null;
-
-		var headerView = new DataView( data, 0, BINARY_EXTENSION_HEADER_LENGTH );
-
-		this.header = {
-			magic: convertUint8ArrayToString( new Uint8Array( data.slice( 0, 4 ) ) ),
-			version: headerView.getUint32( 4, true ),
-			length: headerView.getUint32( 8, true )
-		};
-
-		if ( this.header.magic !== BINARY_EXTENSION_HEADER_MAGIC ) {
-
-			throw new Error( 'GLTF2Loader: Unsupported glTF-Binary header.' );
-
-		} else if ( this.header.version < 2.0 ) {
-
-			throw new Error( 'GLTF2Loader: Legacy binary file detected. Use GLTFLoader instead.' );
-
-		}
-
-		var chunkView = new DataView( data, BINARY_EXTENSION_HEADER_LENGTH );
-		var chunkIndex = 0;
-
-		while ( chunkIndex < chunkView.byteLength ) {
-
-			var chunkLength = chunkView.getUint32( chunkIndex, true );
-			chunkIndex += 4;
-
-			var chunkType = chunkView.getUint32( chunkIndex, true );
-			chunkIndex += 4;
-
-			if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.JSON ) {
-
-				var contentArray = new Uint8Array( data, BINARY_EXTENSION_HEADER_LENGTH + chunkIndex, chunkLength );
-				this.content = convertUint8ArrayToString( contentArray );
-
-			} else if ( chunkType === BINARY_EXTENSION_CHUNK_TYPES.BIN ) {
-
-				var byteOffset = BINARY_EXTENSION_HEADER_LENGTH + chunkIndex;
-				this.body = data.slice( byteOffset, byteOffset + chunkLength );
-
-			}
-
-			// Clients must ignore chunks with unknown types.
-
-			chunkIndex += chunkLength;
-
-		}
-
-		if ( this.content === null ) {
-
-			throw new Error( 'GLTF2Loader: JSON content not found.' );
-
-		}
-
-	}
-
-	/**
-	 * WebGL Technique Extension
-	 *
-	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_technique_webgl
-	 */
-	function GLTFTechniqueWebglExtension( json ) {
-
-		this.name = EXTENSIONS.KHR_TECHNIQUE_WEBGL;
-
-		var extension = ( json.extensions && json.extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ] ) || {};
-
-		this.techniques = extension.techniques || {};
-		this.programs = extension.programs || {};
-		this.shaders = extension.shaders || {};
-
-	}
-
-	GLTFTechniqueWebglExtension.prototype.getMaterialType = function () {
-
-		return DeferredShaderMaterial;
-
-	};
-
-	GLTFTechniqueWebglExtension.prototype.extendParams = function ( materialParams, material, dependencies ) {
-
-		var extension = material[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ];
-		var technique = dependencies.techniques[ extension.technique ];
-
-		materialParams.uniforms = {};
-
-		var program = dependencies.programs[ technique.program ];
-
-		if ( program === undefined ) {
-
-			return;
-
-		}
-
-		materialParams.fragmentShader = dependencies.shaders[ program.fragmentShader ];
-
-		if ( ! materialParams.fragmentShader ) {
-
-			throw new Error( 'ERROR: Missing fragment shader definition:', program.fragmentShader );
-
-		}
-
-		var vertexShader = dependencies.shaders[ program.vertexShader ];
-
-		if ( ! vertexShader ) {
-
-			throw new Error( 'ERROR: Missing vertex shader definition:', program.vertexShader );
-
-		}
-
-		// 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;
-
-		}
-
-	};
-
-	/**
-	 * Specular-Glossiness Extension
-	 *
-	 * Specification: https://github.com/KhronosGroup/glTF/tree/master/extensions/Khronos/KHR_materials_pbrSpecularGlossiness
-	 */
-	function GLTFMaterialsPbrSpecularGlossinessExtension() {
-
-		return {
-
-			name: EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS,
-
-			getMaterialType: function () {
-
-				return THREE.ShaderMaterial;
-
-			},
-
-			extendParams: function ( params, material, dependencies ) {
-
-				// specification
-				// https://github.com/sbtron/glTF/tree/KHRpbrSpecGloss/extensions/Khronos/KHR_materials_pbrSpecularGlossiness
-
-				var pbrSpecularGlossiness = material.extensions[ this.name ];
-
-				var shader = THREE.ShaderLib[ 'standard' ];
-
-				var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
-
-				var specularMapParsFragmentChunk = [
-					'#ifdef USE_SPECULARMAP',
-					'	uniform sampler2D specularMap;',
-					'#endif'
-				].join( '\n' );
-
-				var glossinessMapParsFragmentChunk = [
-					'#ifdef USE_GLOSSINESSMAP',
-					'	uniform sampler2D glossinessMap;',
-					'#endif'
-				].join( '\n' );
-
-				var specularMapFragmentChunk = [
-					'vec3 specularFactor = specular;',
-					'#ifdef USE_SPECULARMAP',
-					'	vec4 texelSpecular = texture2D( specularMap, vUv );',
-					'	// reads channel RGB, compatible with a glTF Specular-Glossiness (RGBA) texture',
-					'	specularFactor *= texelSpecular.rgb;',
-					'#endif'
-				].join( '\n' );
-
-				var glossinessMapFragmentChunk = [
-					'float glossinessFactor = glossiness;',
-					'#ifdef USE_GLOSSINESSMAP',
-					'	vec4 texelGlossiness = texture2D( glossinessMap, vUv );',
-					'	// reads channel A, compatible with a glTF Specular-Glossiness (RGBA) texture',
-					'	glossinessFactor *= texelGlossiness.a;',
-					'#endif'
-				].join( '\n' );
-
-				var lightPhysicalFragmentChunk = [
-					'PhysicalMaterial material;',
-					'material.diffuseColor = diffuseColor.rgb;',
-					'material.specularRoughness = clamp( 1.0 - glossinessFactor, 0.04, 1.0 );',
-					'material.specularColor = specularFactor.rgb;',
-				].join( '\n' );
-
-				var fragmentShader = shader.fragmentShader
-							.replace( '#include <specularmap_fragment>', '' )
-							.replace( 'uniform float roughness;', 'uniform vec3 specular;' )
-							.replace( 'uniform float metalness;', 'uniform float glossiness;' )
-							.replace( '#include <roughnessmap_pars_fragment>', specularMapParsFragmentChunk )
-							.replace( '#include <metalnessmap_pars_fragment>', glossinessMapParsFragmentChunk )
-							.replace( '#include <roughnessmap_fragment>', specularMapFragmentChunk )
-							.replace( '#include <metalnessmap_fragment>', glossinessMapFragmentChunk )
-							.replace( '#include <lights_physical_fragment>', lightPhysicalFragmentChunk );
-
-				delete uniforms.roughness;
-				delete uniforms.metalness;
-				delete uniforms.roughnessMap;
-				delete uniforms.metalnessMap;
-
-				uniforms.specular = { value: new THREE.Color().setHex( 0x111111 ) };
-				uniforms.glossiness = { value: 0.5 };
-				uniforms.specularMap = { value: null };
-				uniforms.glossinessMap = { value: null };
-
-				params.vertexShader = shader.vertexShader;
-				params.fragmentShader = fragmentShader;
-				params.uniforms = uniforms;
-				params.defines = { 'STANDARD': '' };
-
-				params.color = new THREE.Color( 1.0, 1.0, 1.0 );
-				params.opacity = 1.0;
-
-				if ( Array.isArray( pbrSpecularGlossiness.diffuseFactor ) ) {
-
-					var array = pbrSpecularGlossiness.diffuseFactor;
-
-					params.color.fromArray( array );
-					params.opacity = array[ 3 ];
-
-				}
-
-				if ( pbrSpecularGlossiness.diffuseTexture !== undefined ) {
-
-					params.map = dependencies.textures[ pbrSpecularGlossiness.diffuseTexture.index ];
-
-				}
-
-				params.emissive = new THREE.Color( 0.0, 0.0, 0.0 );
-				params.glossiness = pbrSpecularGlossiness.glossinessFactor !== undefined ? pbrSpecularGlossiness.glossinessFactor : 1.0;
-				params.specular = new THREE.Color( 1.0, 1.0, 1.0 );
-
-				if ( Array.isArray( pbrSpecularGlossiness.specularFactor ) ) {
-
-					params.specular.fromArray( pbrSpecularGlossiness.specularFactor );
-
-				}
-
-				if ( pbrSpecularGlossiness.specularGlossinessTexture !== undefined ) {
-
-					params.glossinessMap = dependencies.textures[ pbrSpecularGlossiness.specularGlossinessTexture.index ];
-					params.specularMap = dependencies.textures[ pbrSpecularGlossiness.specularGlossinessTexture.index ];
-
-				}
-
-			},
-
-			createMaterial: function ( params ) {
-
-				// setup material properties based on MeshStandardMaterial for Specular-Glossiness
-
-				var material = new THREE.ShaderMaterial( {
-					defines: params.defines,
-					vertexShader: params.vertexShader,
-					fragmentShader: params.fragmentShader,
-					uniforms: params.uniforms,
-					fog: true,
-					lights: true,
-					opacity: params.opacity,
-					transparent: params.transparent
-				} );
-
-				material.color = params.color;
-
-				material.map = params.map === undefined ? null : params.map;
-
-				material.lightMap = null;
-				material.lightMapIntensity = 1.0;
-
-				material.aoMap = params.aoMap === undefined ? null : params.aoMap;
-				material.aoMapIntensity = 1.0;
-
-				material.emissive = params.emissive;
-				material.emissiveIntensity = 1.0;
-				material.emissiveMap = params.emissiveMap === undefined ? null : params.emissiveMap;
-
-				material.bumpMap = params.bumpMap === undefined ? null : params.bumpMap;
-				material.bumpScale = 1;
-
-				material.normalMap = params.normalMap === undefined ? null : params.normalMap;
-				material.normalScale = new THREE.Vector2( 1, 1 );
-
-				material.displacementMap = null;
-				material.displacementScale = 1;
-				material.displacementBias = 0;
-
-				material.specularMap = params.specularMap === undefined ? null : params.specularMap;
-				material.specular = params.specular;
-
-				material.glossinessMap = params.glossinessMap === undefined ? null : params.glossinessMap;
-				material.glossiness = params.glossiness;
-
-				material.alphaMap = null;
-
-				material.envMap = params.envMap === undefined ? null : params.envMap;
-				material.envMapIntensity = 1.0;
-
-				material.refractionRatio = 0.98;
-
-				material.extensions.derivatives = true;
-
-				return material;
-
-			},
-
-			// Here's based on refreshUniformsCommon() and refreshUniformsStandard() in WebGLRenderer.
-			refreshUniforms: function ( renderer, scene, camera, geometry, material, group ) {
-
-				var uniforms = material.uniforms;
-				var defines = material.defines;
-
-				uniforms.opacity.value = material.opacity;
-
-				uniforms.diffuse.value.copy( material.color );
-				uniforms.emissive.value.copy( material.emissive ).multiplyScalar( material.emissiveIntensity );
-
-				uniforms.map.value = material.map;
-				uniforms.specularMap.value = material.specularMap;
-				uniforms.alphaMap.value = material.alphaMap;
-
-				uniforms.lightMap.value = material.lightMap;
-				uniforms.lightMapIntensity.value = material.lightMapIntensity;
-
-				uniforms.aoMap.value = material.aoMap;
-				uniforms.aoMapIntensity.value = material.aoMapIntensity;
-
-				// uv repeat and offset setting priorities
-				// 1. color map
-				// 2. specular map
-				// 3. normal map
-				// 4. bump map
-				// 5. alpha map
-				// 6. emissive map
-
-				var uvScaleMap;
-
-				if ( material.map ) {
-
-					uvScaleMap = material.map;
-
-				} else if ( material.specularMap ) {
-
-					uvScaleMap = material.specularMap;
-
-				} else if ( material.displacementMap ) {
-
-					uvScaleMap = material.displacementMap;
-
-				} else if ( material.normalMap ) {
-
-					uvScaleMap = material.normalMap;
-
-				} else if ( material.bumpMap ) {
-
-					uvScaleMap = material.bumpMap;
-
-				} else if ( material.glossinessMap ) {
-
-					uvScaleMap = material.glossinessMap;
-
-				} else if ( material.alphaMap ) {
-
-					uvScaleMap = material.alphaMap;
-
-				} else if ( material.emissiveMap ) {
-
-					uvScaleMap = material.emissiveMap;
-
-				}
-
-				if ( uvScaleMap !== undefined ) {
-
-					// backwards compatibility
-					if ( uvScaleMap.isWebGLRenderTarget ) {
-
-						uvScaleMap = uvScaleMap.texture;
-
-					}
-
-					var offset = uvScaleMap.offset;
-					var repeat = uvScaleMap.repeat;
-
-					uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
-
-				}
-
-				uniforms.envMap.value = material.envMap;
-				uniforms.envMapIntensity.value = material.envMapIntensity;
-				uniforms.flipEnvMap.value = ( material.envMap && material.envMap.isCubeTexture ) ? -1 : 1;
-
-				uniforms.refractionRatio.value = material.refractionRatio;
-
-				uniforms.specular.value.copy( material.specular );
-				uniforms.glossiness.value = material.glossiness;
-
-				uniforms.glossinessMap.value = material.glossinessMap;
-
-				uniforms.emissiveMap.value = material.emissiveMap;
-				uniforms.bumpMap.value = material.bumpMap;
-				uniforms.normalMap.value = material.normalMap;
-
-				uniforms.displacementMap.value = material.displacementMap;
-				uniforms.displacementScale.value = material.displacementScale;
-				uniforms.displacementBias.value = material.displacementBias;
-
-				if ( uniforms.glossinessMap.value !== null && defines.USE_GLOSSINESSMAP === undefined ) {
-
-					defines.USE_GLOSSINESSMAP = '';
-					// set USE_ROUGHNESSMAP to enable vUv
-					defines.USE_ROUGHNESSMAP = ''
-
-				}
-
-				if ( uniforms.glossinessMap.value === null && defines.USE_GLOSSINESSMAP !== undefined ) {
-
-					delete defines.USE_GLOSSINESSMAP;
-					delete defines.USE_ROUGHNESSMAP;
-
-				}
-
-			}
-
-		};
-
-	}
-
-	/*********************************/
-	/********** 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',
-		weights: 'morphTargetInfluences'
-	};
-
-	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'
-	};
-
-	var ALPHA_MODES = {
-		OPAQUE: 'OPAQUE',
-		MASK: 'MASK',
-		BLEND: 'BLEND'
-	};
-
-	/* 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;
-
-	}
-
-	function convertUint8ArrayToString( array ) {
-
-		if ( window.TextDecoder !== undefined ) {
-
-			return new TextDecoder().decode( array );
-
-		}
-
-		// Avoid the String.fromCharCode.apply(null, array) shortcut, which
-		// throws a "maximum call stack size exceeded" error for large arrays.
-
-		var s = '';
-
-		for ( var i = 0, il = array.length; i < il; i ++ ) {
-
-			s += String.fromCharCode( array[ i ] );
-
-		}
-
-		return s;
-
-	}
-
-	// 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 'WEIGHTS_0':
-				case 'WEIGHT': // WEIGHT semantic deprecated.
-
-					shaderText = shaderText.replace( regEx, 'skinWeight' );
-					break;
-
-				case 'JOINTS_0':
-				case 'JOINT': // JOINT semantic deprecated.
-
-					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 options = this.options;
-		var extensions = this.extensions;
-
-		return this._withDependencies( [
-
-			"bufferViews"
-
-		] ).then( function ( dependencies ) {
-
-			var shaders = extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ] !== undefined ? extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ].shaders : json.shaders;
-
-			if ( shaders === undefined ) shaders = {};
-
-			return _each( shaders, function ( shader ) {
-
-				if ( shader.bufferView !== undefined ) {
-
-					var bufferView = dependencies.bufferViews[ shader.bufferView ];
-					var array = new Uint8Array( bufferView );
-					return convertUint8ArrayToString( array );
-
-				}
-
-				return new Promise( function ( resolve ) {
-
-					var loader = new THREE.FileLoader();
-					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 ( buffer.type === 'arraybuffer' || buffer.type === undefined ) {
-
-				// If present, GLB container is required to be the first buffer.
-				if ( buffer.uri === undefined && name === 0 ) {
-
-					return extensions[ EXTENSIONS.KHR_BINARY_GLTF ].body;
-
-				}
-
-				return new Promise( function ( resolve ) {
-
-					var loader = new THREE.FileLoader();
-					loader.setResponseType( 'arraybuffer' );
-					loader.load( resolveURL( buffer.uri, options.path ), function ( buffer ) {
-
-						resolve( buffer );
-
-					} );
-
-				} );
-
-			} else {
-
-				console.warn( 'THREE.GLTF2Loader: ' + 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 || 0;
-				var byteOffset = bufferView.byteOffset || 0;
-
-				return arraybuffer.slice( byteOffset, 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;
-
-				var array;
-
-				// 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.
-					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 !== undefined ) {
-
-					return new Promise( function ( resolve ) {
-
-						var source = json.images[ texture.source ];
-						var sourceUri = source.uri;
-
-						var urlCreator;
-
-						if ( source.bufferView !== undefined ) {
-
-							var bufferView = dependencies.bufferViews[ source.bufferView ];
-							var blob = new Blob( [ bufferView ], { type: source.mimeType } );
-							urlCreator = window.URL || window.webkitURL;
-							sourceUri = urlCreator.createObjectURL( blob );
-
-						}
-
-						var textureLoader = THREE.Loader.Handlers.get( sourceUri );
-
-						if ( textureLoader === null ) {
-
-							textureLoader = new THREE.TextureLoader();
-
-						}
-
-						textureLoader.setCrossOrigin( options.crossOrigin );
-
-						textureLoader.load( resolveURL( sourceUri, options.path ), function ( _texture ) {
-
-							if ( urlCreator !== undefined ) {
-
-								urlCreator.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.GLTF2Loader: 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;
-
-							var samplers = json.samplers || {};
-							var sampler = 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 () {
-
-							resolve();
-
-						} );
-
-					} );
-
-				}
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadMaterials = function () {
-
-		var json = this.json;
-		var extensions = this.extensions;
-
-		return this._withDependencies( [
-
-			'shaders',
-			'textures'
-
-		] ).then( function ( dependencies ) {
-
-			return _each( json.materials, function ( material ) {
-
-				var materialType;
-				var materialParams = {};
-				var materialExtensions = material.extensions || {};
-
-				if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_COMMON ] ) {
-
-					materialType = extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].getMaterialType( material );
-					extensions[ EXTENSIONS.KHR_MATERIALS_COMMON ].extendParams( materialParams, material, dependencies );
-
-				} else if ( materialExtensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ] ) {
-
-					materialType = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].getMaterialType( material );
-					extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].extendParams( materialParams, material, dependencies );
-
-				} else if ( materialExtensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ] ) {
-
-					materialType = extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ].getMaterialType( material );
-					extensions[ EXTENSIONS.KHR_TECHNIQUE_WEBGL ].extendParams( materialParams, material, dependencies );
-
-				} else if ( material.pbrMetallicRoughness !== undefined ) {
-
-					// Specification:
-					// https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#metallic-roughness-material
-
-					materialType = THREE.MeshStandardMaterial;
-
-					var metallicRoughness = material.pbrMetallicRoughness;
-
-					materialParams.color = new THREE.Color( 1.0, 1.0, 1.0 );
-					materialParams.opacity = 1.0;
-
-					if ( Array.isArray( metallicRoughness.baseColorFactor ) ) {
-
-						var array = metallicRoughness.baseColorFactor;
-
-						materialParams.color.fromArray( array );
-						materialParams.opacity = array[ 3 ];
-
-					}
-
-					if ( metallicRoughness.baseColorTexture !== undefined ) {
-
-						materialParams.map = dependencies.textures[ metallicRoughness.baseColorTexture.index ];
-
-						var alphaMode = metallicRoughness.baseColorTexture.alphaMode || ALPHA_MODES.OPAQUE;
-
-						if ( alphaMode !== ALPHA_MODES.OPAQUE ) {
-
-							materialParams.transparent = true;
-
-						}
-
-					}
-
-					materialParams.metalness = metallicRoughness.metallicFactor !== undefined ? metallicRoughness.metallicFactor : 1.0;
-					materialParams.roughness = metallicRoughness.roughnessFactor !== undefined ? metallicRoughness.roughnessFactor : 1.0;
-
-					if ( metallicRoughness.metallicRoughnessTexture !== undefined ) {
-
-						var textureIndex = metallicRoughness.metallicRoughnessTexture.index;
-						materialParams.metalnessMap = dependencies.textures[ textureIndex ];
-						materialParams.roughnessMap = dependencies.textures[ textureIndex ];
-
-					}
-
-				} else {
-
-					materialType = THREE.MeshPhongMaterial;
-
-				}
-
-				if ( material.doubleSided === true ) {
-
-					materialParams.side = THREE.DoubleSide;
-
-				}
-
-				if ( materialParams.opacity !== undefined && materialParams.opacity < 1.0 ) {
-
-					materialParams.transparent = true;
-
-				} else {
-
-					materialParams.transparent = false;
-
-				}
-
-				if ( material.normalTexture !== undefined ) {
-
-					materialParams.normalMap = dependencies.textures[ material.normalTexture.index ];
-
-				}
-
-				if ( material.occlusionTexture !== undefined ) {
-
-					materialParams.aoMap = dependencies.textures[ material.occlusionTexture.index ];
-
-				}
-
-				if ( material.emissiveFactor !== undefined ) {
-
-					if ( materialType === THREE.MeshBasicMaterial ) {
-
-						materialParams.color = new THREE.Color().fromArray( material.emissiveFactor );
-
-					} else {
-
-						materialParams.emissive = new THREE.Color().fromArray( material.emissiveFactor );
-
-					}
-
-				}
-
-				if ( material.emissiveTexture !== undefined ) {
-
-					if ( materialType === THREE.MeshBasicMaterial ) {
-
-						materialParams.map = dependencies.textures[ material.emissiveTexture.index ];
-
-					} else {
-
-						materialParams.emissiveMap = dependencies.textures[ material.emissiveTexture.index ];
-
-					}
-
-				}
-
-				var _material;
-
-				if ( materialType === THREE.ShaderMaterial ) {
-
-					_material = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].createMaterial( materialParams );
-
-				} else {
-
-					_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 ];
-
-					var material = primitive.material !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial();
-
-					var geometry;
-
-					var meshNode;
-
-					if ( primitive.mode === WEBGL_CONSTANTS.TRIANGLES || primitive.mode === undefined ) {
-
-						geometry = new THREE.BufferGeometry();
-
-						var attributes = primitive.attributes;
-
-						for ( var attributeId in attributes ) {
-
-							var attributeEntry = attributes[ attributeId ];
-
-							if ( attributeEntry === undefined ) return;
-
-							var bufferAttribute = dependencies.accessors[ attributeEntry ];
-
-							switch ( attributeId ) {
-
-								case 'POSITION':
-
-									geometry.addAttribute( 'position', bufferAttribute );
-									break;
-
-								case 'NORMAL':
-
-									geometry.addAttribute( 'normal', bufferAttribute );
-									break;
-
-								case 'TEXCOORD_0':
-								case 'TEXCOORD0':
-								case 'TEXCOORD':
-
-									geometry.addAttribute( 'uv', bufferAttribute );
-									break;
-
-								case 'TEXCOORD_1':
-
-									geometry.addAttribute( 'uv2', bufferAttribute );
-									break;
-
-								case 'COLOR_0':
-								case 'COLOR0':
-								case 'COLOR':
-
-									geometry.addAttribute( 'color', bufferAttribute );
-									break;
-
-								case 'WEIGHTS_0':
-								case 'WEIGHT': // WEIGHT semantic deprecated.
-
-									geometry.addAttribute( 'skinWeight', bufferAttribute );
-									break;
-
-								case 'JOINTS_0':
-								case 'JOINT': // JOINT semantic deprecated.
-
-									geometry.addAttribute( 'skinIndex', bufferAttribute );
-									break;
-
-							}
-
-						}
-
-						if ( primitive.indices !== undefined ) {
-
-							geometry.setIndex( dependencies.accessors[ primitive.indices ] );
-
-						}
-
-						if ( material.aoMap !== undefined
-								&& geometry.attributes.uv2 === undefined
-								&& geometry.attributes.uv !== undefined ) {
-
-							console.log( 'GLTF2Loader: Duplicating UVs to support aoMap.' );
-							geometry.addAttribute( 'uv2', new THREE.BufferAttribute( geometry.attributes.uv.array, 2 ) );
-
-						}
-
-						meshNode = new THREE.Mesh( geometry, material );
-						meshNode.castShadow = true;
-
-						if ( primitive.targets !== undefined ) {
-
-							var targets = primitive.targets;
-							var morphAttributes = geometry.morphAttributes;
-
-							morphAttributes.position = [];
-							morphAttributes.normal = [];
-
-							material.morphTargets = true;
-
-							for ( var i = 0, il = targets.length; i < il; i ++ ) {
-
-								var target = targets[ i ];
-								var attributeName = 'morphTarget' + i;
-
-								var positionAttribute, normalAttribute;
-
-								if ( target.POSITION !== undefined ) {
-
-									// Three.js morph formula is
-									//   position
-									//     + weight0 * ( morphTarget0 - position )
-									//     + weight1 * ( morphTarget1 - position )
-									//     ...
-									// while the glTF one is
-									//   position
-									//     + weight0 * morphTarget0
-									//     + weight1 * morphTarget1
-									//     ...
-									// then adding position to morphTarget.
-									// So morphTarget value will depend on mesh's position, then cloning attribute
-									// for the case if attribute is shared among two or more meshes.
-
-									positionAttribute = dependencies.accessors[ target.POSITION ].clone();
-									var position = geometry.attributes.position;
-
-									for ( var j = 0, jl = positionAttribute.array.length; j < jl; j ++ ) {
-
-										positionAttribute.array[ j ] += position.array[ j ];
-
-									}
-
-								} else {
-
-									// Copying the original position not to affect the final position.
-									// See the formula above.
-									positionAttribute = geometry.attributes.position.clone();
-
-								}
-
-								if ( target.NORMAL !== undefined ) {
-
-									material.morphNormals = true;
-
-									// see target.POSITION's comment
-
-									normalAttribute = dependencies.accessors[ target.NORMAL ].clone();
-									var normal = geometry.attributes.normal;
-
-									for ( var j = 0, jl = normalAttribute.array.length; j < jl; j ++ ) {
-
-										normalAttribute.array[ j ] += normal.array[ j ];
-
-									}
-
-								} else {
-
-									normalAttribute = geometry.attributes.normal.clone();
-
-								}
-
-								// TODO: implement
-								if ( target.TANGENT !== undefined ) {
-
-								}
-
-								positionAttribute.name = attributeName;
-								normalAttribute.name = attributeName;
-
-								morphAttributes.position.push( positionAttribute );
-								morphAttributes.normal.push( normalAttribute );
-
-							}
-
-							meshNode.updateMorphTargets();
-
-							if ( mesh.weights !== undefined ) {
-
-								for ( var i = 0, il = mesh.weights.length; i < il; i ++ ) {
-
-									meshNode.morphTargetInfluences[ i ] = mesh.weights[ i ];
-
-								}
-
-							}
-
-						}
-
-					} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
-
-						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.addAttribute( 'position', bufferAttribute );
-									break;
-
-								case 'COLOR_0':
-								case 'COLOR0':
-								case 'COLOR':
-									geometry.addAttribute( 'color', bufferAttribute );
-									break;
-
-							}
-
-						}
-
-						if ( primitive.indices !== undefined ) {
-
-							geometry.setIndex( dependencies.accessors[ primitive.indices ] );
-
-							meshNode = new THREE.LineSegments( geometry, material );
-
-						} else {
-
-							meshNode = new THREE.Line( geometry, material );
-
-						}
-
-					} else {
-
-						throw new Error( "Only triangular and line primitives are supported" );
-
-					}
-
-					if ( geometry.attributes.color !== undefined ) {
-
-						material.vertexColors = THREE.VertexColors;
-						material.needsUpdate = true;
-
-					}
-
-					meshNode.name = ( name === "0" ? group.name : group.name + name );
-
-					if ( primitive.extras ) meshNode.userData = primitive.extras;
-
-					group.add( meshNode );
-
-				}
-
-				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,
-					joints: skin.joints,
-					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.node !== undefined ? target.node : target.id; // NOTE: target.id is deprecated.
-						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;
-
-							switch ( PATH_PROPERTIES[ target.path ] ) {
-
-								case PATH_PROPERTIES.weights:
-
-									TypedKeyframeTrack = THREE.NumberKeyframeTrack;
-									break;
-
-								case PATH_PROPERTIES.rotation:
-
-									TypedKeyframeTrack = THREE.QuaternionKeyframeTrack;
-									break;
-
-								case PATH_PROPERTIES.position:
-								case PATH_PROPERTIES.scale:
-								default:
-
-									TypedKeyframeTrack = THREE.VectorKeyframeTrack;
-									break;
-
-							}
-
-							var targetName = node.name ? node.name : node.uuid;
-							var interpolation = sampler.interpolation !== undefined ? INTERPOLATION[ sampler.interpolation ] : THREE.InterpolateLinear;
-
-							var targetNames = [];
-
-							if ( PATH_PROPERTIES[ target.path ] === PATH_PROPERTIES.weights ) {
-
-								// node should be THREE.Group here but
-								// PATH_PROPERTIES.weights(morphTargetInfluences) should be
-								// the property of a mesh object under node.
-								// So finding targets here.
-
-								node.traverse( function ( object ) {
-
-									if ( object.isMesh === true && object.material.morphTargets === true ) {
-
-										targetNames.push( object.name ? object.name : object.uuid );
-
-									}
-
-								} );
-
-							} else {
-
-								targetNames.push( targetName );
-
-							}
-
-							// 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.
-							for ( var i = 0, il = targetNames.length; i < il; i ++ ) {
-
-								tracks.push( new TypedKeyframeTrack(
-									targetNames[ i ] + '.' + 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;
-
-		var nodes = json.nodes || [];
-		var skins = json.skins || [];
-
-		// Nothing in the node definition indicates whether it is a Bone or an
-		// Object3D. Use the skins' joint references to mark bones.
-		skins.forEach( function ( skin ) {
-
-			skin.joints.forEach( function ( id ) {
-
-				nodes[ id ].isBone = true;
-
-			} );
-
-		} );
-
-		return _each( json.nodes, function ( node ) {
-
-			var matrix = new THREE.Matrix4();
-
-			var _node = node.isBone === true ? new THREE.Bone() : new THREE.Object3D();
-
-			if ( node.name !== undefined ) {
-
-				_node.name = THREE.PropertyBinding.sanitizeNodeName( 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 ];
-
-					var meshes;
-
-					if ( node.mesh !== undefined) {
-
-						meshes = [ node.mesh ];
-
-					} else if ( node.meshes !== undefined ) {
-
-						console.warn( 'GLTF2Loader: Legacy glTF file detected. Nodes may have no more than 1 mesh.' );
-
-						meshes = node.meshes;
-
-					}
-
-					if ( meshes !== undefined ) {
-
-						for ( var meshId in meshes ) {
-
-							var mesh = meshes[ meshId ];
-							var group = dependencies.meshes[ mesh ];
-
-							if ( group === undefined ) {
-
-								console.warn( 'GLTF2Loader: 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 !== undefined ) {
-
-									skinEntry = dependencies.skins[ node.skin ];
-
-								}
-
-								// Replace Mesh with SkinnedMesh in library
-								if ( skinEntry ) {
-
-									var geometry = originalGeometry;
-									material = originalMaterial;
-									material.skinning = true;
-
-									child = new THREE.SkinnedMesh( geometry, material, false );
-									child.castShadow = true;
-									child.userData = originalUserData;
-									child.name = originalName;
-
-									var bones = [];
-									var boneInverses = [];
-
-									for ( var i = 0, l = skinEntry.joints.length; i < l; i ++ ) {
-
-										var jointId = skinEntry.joints[ i ];
-										var jointNode = __nodes[ 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, false ), 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_LIGHTS ].lights;
-						var light = extensionLights[ node.extensions[ EXTENSIONS.KHR_LIGHTS ].light ];
-
-						_node.add( light );
-
-					}
-
-					return _node;
-
-				} );
-
-			} );
-
-		} );
-
-	};
-
-	GLTFParser.prototype.loadScenes = function () {
-
-		var json = this.json;
-		var extensions = this.extensions;
-
-		// 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 GLTF2Loader.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);
-						};
-
-					}
-
-					// for Specular-Glossiness.
-					if ( child.material && child.material.type === 'ShaderMaterial' ) {
-
-						child.onBeforeRender = extensions[ EXTENSIONS.KHR_MATERIALS_PBR_SPECULAR_GLOSSINESS ].refreshUniforms;
-
-					}
-
-				} );
-
-				return _scene;
-
-			} );
-
-		} );
-
-	};
-
-	return GLTF2Loader;
-
-} )();

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