2
0
Эх сурвалжийг харах

Merge branch 'dev' into SpecularGlossiness

Takahiro 8 жил өмнө
parent
commit
6f3aa2792f
76 өөрчлөгдсөн 4044 нэмэгдсэн , 3209 устгасан
  1. 1 1
      build/three.js
  2. 305 307
      build/three.min.js
  3. 1 1
      build/three.module.js
  4. 5 5
      docs/api/animation/AnimationMixer.html
  5. 7 7
      docs/api/core/BufferGeometry.html
  6. 133 133
      docs/api/core/Face3.html
  7. 4 1
      docs/api/deprecated/DeprecatedList.html
  8. 1 1
      docs/api/extras/SceneUtils.html
  9. 10 3
      docs/api/helpers/BoxHelper.html
  10. 6 1
      docs/api/loaders/JSONLoader.html
  11. 2 2
      docs/api/materials/Material.html
  12. 4 3
      docs/api/materials/ShaderMaterial.html
  13. 7 3
      docs/api/materials/ShadowMaterial.html
  14. 1 1
      docs/api/math/Matrix4.html
  15. 3 0
      docs/api/renderers/WebGLRenderer.html
  16. 1 1
      docs/examples/loaders/OBJLoader.html
  17. 1 1
      docs/list.js
  18. 4 3
      docs/manual/introduction/How-to-update-things.html
  19. 0 0
      docs/manual/introduction/WebGL-compatibility-check.html
  20. 0 8
      editor/css/dark.css
  21. 0 26
      editor/css/main.css
  22. 0 2
      editor/index.html
  23. 0 13
      editor/js/Loader.js
  24. 4 4
      editor/js/Viewport.js
  25. 2 1
      examples/files.js
  26. 1 1
      examples/index.html
  27. 0 182
      examples/js/BlendCharacter.js
  28. 0 207
      examples/js/BlendCharacterGui.js
  29. 2 2
      examples/js/Cloth.js
  30. 313 321
      examples/js/GPUParticleSystem.js
  31. 37 21
      examples/js/controls/OrbitControls.js
  32. 38 25
      examples/js/loaders/GLTF2Loader.js
  33. 1 1
      examples/js/loaders/WWOBJLoader2.js
  34. 1580 1045
      examples/js/loaders/XLoader.js
  35. 26 4
      examples/js/postprocessing/AdaptiveToneMappingPass.js
  36. 4 2
      examples/js/shaders/ToneMapShader.js
  37. 16 12
      examples/models/json/scene-animation.json
  38. 53 85
      examples/webgl_animation_scene.html
  39. 397 116
      examples/webgl_animation_skinning_blending.html
  40. 340 0
      examples/webgl_buffergeometry_instancing2.html
  41. 1 4
      examples/webgl_geometry_spline_editor.html
  42. 7 0
      examples/webgl_gpu_particle_system.html
  43. 48 25
      examples/webgl_interactive_instances_gpu.html
  44. 0 383
      examples/webgl_lights_arealight.html
  45. 17 29
      examples/webgl_loader_collada_keyframe.html
  46. 17 29
      examples/webgl_loader_collada_kinematics.html
  47. 4 4
      examples/webgl_loader_x.html
  48. 308 0
      examples/webgl_materials_compile.html
  49. 48 46
      examples/webgl_physics_convex_break.html
  50. 2 4
      examples/webgl_postprocessing_outline.html
  51. 2 2
      examples/webvr_cubes.html
  52. 2 2
      examples/webvr_daydream.html
  53. 2 2
      examples/webvr_panorama.html
  54. 2 2
      examples/webvr_rollercoaster.html
  55. 2 2
      examples/webvr_sandbox.html
  56. 2 2
      examples/webvr_video.html
  57. 1 1
      package.json
  58. 1 1
      src/constants.js
  59. 20 8
      src/helpers/BoxHelper.js
  60. 0 2
      src/helpers/FaceNormalsHelper.js
  61. 0 2
      src/helpers/VertexNormalsHelper.js
  62. 3 3
      src/lights/SpotLightShadow.js
  63. 7 1
      src/materials/ShadowMaterial.js
  64. 86 53
      src/renderers/WebGLRenderer.js
  65. 82 2
      src/renderers/shaders/ShaderChunk/bsdfs.glsl
  66. 15 11
      src/renderers/shaders/ShaderChunk/dithering_pars_fragment.glsl
  67. 3 3
      src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl
  68. 1 0
      src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl
  69. 3 2
      src/renderers/shaders/ShaderLib/meshlambert_frag.glsl
  70. 3 2
      src/renderers/shaders/ShaderLib/meshphong_frag.glsl
  71. 3 2
      src/renderers/shaders/ShaderLib/meshphysical_frag.glsl
  72. 1 2
      src/renderers/webgl/WebGLProgram.js
  73. 1 1
      src/renderers/webgl/WebGLRenderLists.js
  74. 29 24
      src/renderers/webgl/WebGLShadowMap.js
  75. 10 1
      test/unit/src/math/Math.js
  76. 1 0
      utils/exporters/blender/addons/io_three/exporter/material.py

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 1 - 1
build/three.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 305 - 307
build/three.min.js


Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 1 - 1
build/three.module.js


+ 5 - 5
docs/api/animation/AnimationMixer.html

@@ -69,6 +69,11 @@
 			The first parameter can be either an [page:AnimationClip] object or the name of an AnimationClip.
 		</div>
 
+		<h3>[method:Object3D getRoot]()</h3>
+		<div>
+			Returns this mixer's root object.
+		</div>
+
 		<h3>[method:AnimationMixer stopAllAction]()</h3>
 		<div>
 			Deactivates all previously scheduled actions on this mixer.
@@ -81,11 +86,6 @@
 			This is usually done in the render loop, passing [page:Clock.getDelta clock.getDelta] scaled by the mixer's [page:.timeScale timeScale]).
 		</div>
 
-		<h3>[method:Object3D getRoot]()</h3>
-		<div>
-			Returns this mixer's root object.
-		</div>
-
 		<h3>[method:null uncacheClip]([page:AnimationClip clip])</h3>
 
 		<div>

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

@@ -138,12 +138,12 @@
 		<h3>[property:Array groups]</h3>
 		<div>
 			Split the geometry into groups, each of which will be rendered in a separate WebGL draw call.
-			This allows a [page:MultiMaterial] to be used with the bufferGeometry.<br /><br />
+			This allows an array of materials to be used with the bufferGeometry.<br /><br />
 
 			Each group is an object of the form:
 			<code>{ start: Integer, count: Integer, materialIndex: Integer }</code>
 			where start specifies the index of the first vertex in this draw call, count specifies
-			how many vertices are included, and materialIndex specifies the [page:MultiMaterial] index to use.<br /><br />
+			how many vertices are included, and materialIndex specifies the material array index to use.<br /><br />
 
 			Use [page:.addGroup] to add groups, rather than modifying this array directly.
 		</div>
@@ -329,11 +329,11 @@
 		<div>
 		Translate the geometry. This is typically done as a one time operation, and not during a loop.
     Use [page:Object3D.position] for typical real-time mesh translation.
-		</div>
-
-		<h3>[method:BufferGeometry updateFromObject] ( [page:Object3D object] )</h3>
-		<div>Updates the attributes for this BufferGeometry from an [page:Object3D].</div>
-
+		</div>
+
+		<h3>[method:BufferGeometry updateFromObject] ( [page:Object3D object] )</h3>
+		<div>Updates the attributes for this BufferGeometry from an [page:Object3D].</div>
+
 
 
 

+ 133 - 133
docs/api/core/Face3.html

@@ -1,134 +1,134 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
+<!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>
-
-		<div class="desc">
-		Triangular face used in [page:Geometry]. These are created automatically for all
-		standard geometry types, however if you are building a custom geometry you will have to
-		create them manually.
-		</div>
-
-
-		<h2>Examples</h2>
-
-		<div>[example:misc_ubiquity_test ubiquity / test ]</div>
-		<div>[example:svg_sandbox svg / sandbox ]</div>
-		<div>[example:webgl_exporter_obj WebGL / exporter / obj ]</div>
-		<div>[example:webgl_shaders_vector WebGL / shaders / vector ]</div>
-
-
-		<code>
-var material = new THREE.MeshStandardMaterial( { color : 0x00cc00 } );
-
-//create a triangular geometry
-var geometry = new THREE.Geometry();
-geometry.vertices.push( new THREE.Vector3( -50, -50, 0 ) );
-geometry.vertices.push( new THREE.Vector3(  50, -50, 0 ) );
-geometry.vertices.push( new THREE.Vector3(  50,  50, 0 ) );
-
-//create a new face using vertices 0, 1, 2
-var normal = new THREE.Vector3( 0, 1, 0 ); //optional
-var color = new THREE.Color( 0xffaa00 ); //optional
-var materialIndex = 0; //optional
-var face = new THREE.Face3( 0, 1, 2, normal, color, materialIndex );
-
-//add the face to the geometry's faces array
-geometry.faces.push( face );
-
-//the face normals and vertex normals can be calculated automatically if not supplied above
-geometry.computeFaceNormals();
-geometry.computeVertexNormals();
-
-scene.add( new THREE.Mesh( geometry, material ) );
-	</code>
-
-
-		<h2>Constructor</h2>
-
-		<h3>[name]( [page:Integer a], [page:Integer b], [page:Integer c], [page:Vector3 normal], [page:Color color], [page:Integer materialIndex] )</h3>
-		<div>
-		a — Vertex A index.<br />
-		b — Vertex B index.<br />
-		c — Vertex C index.<br /><br />
-
-		normal — (optional) Face normal ([page:Vector3 Vector3]) or array of vertex normals.
-		If a single vector is passed in, this sets [page:.normal], otherwise if an array of three
-		vectors is passed in this sets [page:.vertexNormals]<br /><br />
-
-		color — (optional) Face [page:Color color] or array of vertex [page:Color colors].
-		If a single vector is passed in, this sets [page:.color], otherwise if an array of three
-		vectors is passed in this sets [page:.vertexColors]<br /><br />
-
-		materialIndex — (optional) which index of a [page:MultiMaterial] to associate
-		with the face.
-		</div>
-
-		<h2>Properties</h2>
-
-		<h3>[property:Integer a]</h3>
-		<div>
-		Vertex A index.
-		</div>
-
-		<h3>[property:Integer b]</h3>
-		<div>
-		Vertex B index.
-		</div>
-
-		<h3>[property:Integer c]</h3>
-		<div>
-		Vertex C index.
-		</div>
-
-		<h3>[property:Vector3 normal]</h3>
-		<div>
-		Face normal - vector showing the direction of the Face3. If calculated automatically
-		(using [page:Geometry.computeFaceNormals]), this is the normalized cross product of two edges of the
-		triangle. Default is *(0, 0, 0)*.
-		</div>
-
-		<h3>[property:Color color]</h3>
-		<div>
-		Face color - for this to be used a material's [page:Material.vertexColors vertexColors] property
-		must be set to [page:Materials THREE.FaceColors].
-		</div>
-
-		<h3>[property:Array vertexNormals]</h3>
-		<div>
-		Array of 3 [page:Vector3 vertex normals].
-		</div>
-
-		<h3>[property:Array vertexColors]</h3>
-		<div>
-		Array of 3 vertex colors - for these to be used a material's [page:Material.vertexColors vertexColors] property
-		must be set to [page:Materials THREE.VertexColors].
-		</div>
-
-
-		<h3>[property:Integer materialIndex]</h3>
-		<div>
-		Material index (points to [page:MultiMaterial MultiMaterial.materials]). Default is *0*.
-		</div>
-
-		<h2>Methods</h2>
-
-		<h3>[method:Face3 clone]()</h3>
-		<div>Creates a new clone of the Face3 object.</div>
-
-		<h3>[method:Face3 copy]( [page:Face3 face3] )</h3>
-		<div>Copy the paramaters of another Face3 into this.</div>
-
-
-		<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">
+		Triangular face used in [page:Geometry]. These are created automatically for all
+		standard geometry types, however if you are building a custom geometry you will have to
+		create them manually.
+		</div>
+
+
+		<h2>Examples</h2>
+
+		<div>[example:misc_ubiquity_test ubiquity / test ]</div>
+		<div>[example:svg_sandbox svg / sandbox ]</div>
+		<div>[example:webgl_exporter_obj WebGL / exporter / obj ]</div>
+		<div>[example:webgl_shaders_vector WebGL / shaders / vector ]</div>
+
+
+		<code>
+var material = new THREE.MeshStandardMaterial( { color : 0x00cc00 } );
+
+//create a triangular geometry
+var geometry = new THREE.Geometry();
+geometry.vertices.push( new THREE.Vector3( -50, -50, 0 ) );
+geometry.vertices.push( new THREE.Vector3(  50, -50, 0 ) );
+geometry.vertices.push( new THREE.Vector3(  50,  50, 0 ) );
+
+//create a new face using vertices 0, 1, 2
+var normal = new THREE.Vector3( 0, 1, 0 ); //optional
+var color = new THREE.Color( 0xffaa00 ); //optional
+var materialIndex = 0; //optional
+var face = new THREE.Face3( 0, 1, 2, normal, color, materialIndex );
+
+//add the face to the geometry's faces array
+geometry.faces.push( face );
+
+//the face normals and vertex normals can be calculated automatically if not supplied above
+geometry.computeFaceNormals();
+geometry.computeVertexNormals();
+
+scene.add( new THREE.Mesh( geometry, material ) );
+	</code>
+
+
+		<h2>Constructor</h2>
+
+		<h3>[name]( [page:Integer a], [page:Integer b], [page:Integer c], [page:Vector3 normal], [page:Color color], [page:Integer materialIndex] )</h3>
+		<div>
+		a — Vertex A index.<br />
+		b — Vertex B index.<br />
+		c — Vertex C index.<br /><br />
+
+		normal — (optional) Face normal ([page:Vector3 Vector3]) or array of vertex normals.
+		If a single vector is passed in, this sets [page:.normal], otherwise if an array of three
+		vectors is passed in this sets [page:.vertexNormals]<br /><br />
+
+		color — (optional) Face [page:Color color] or array of vertex [page:Color colors].
+		If a single vector is passed in, this sets [page:.color], otherwise if an array of three
+		vectors is passed in this sets [page:.vertexColors]<br /><br />
+
+		materialIndex — (optional) which index of an array of materials to associate
+		with the face.
+		</div>
+
+		<h2>Properties</h2>
+
+		<h3>[property:Integer a]</h3>
+		<div>
+		Vertex A index.
+		</div>
+
+		<h3>[property:Integer b]</h3>
+		<div>
+		Vertex B index.
+		</div>
+
+		<h3>[property:Integer c]</h3>
+		<div>
+		Vertex C index.
+		</div>
+
+		<h3>[property:Vector3 normal]</h3>
+		<div>
+		Face normal - vector showing the direction of the Face3. If calculated automatically
+		(using [page:Geometry.computeFaceNormals]), this is the normalized cross product of two edges of the
+		triangle. Default is *(0, 0, 0)*.
+		</div>
+
+		<h3>[property:Color color]</h3>
+		<div>
+		Face color - for this to be used a material's [page:Material.vertexColors vertexColors] property
+		must be set to [page:Materials THREE.FaceColors].
+		</div>
+
+		<h3>[property:Array vertexNormals]</h3>
+		<div>
+		Array of 3 [page:Vector3 vertex normals].
+		</div>
+
+		<h3>[property:Array vertexColors]</h3>
+		<div>
+		Array of 3 vertex colors - for these to be used a material's [page:Material.vertexColors vertexColors] property
+		must be set to [page:Materials THREE.VertexColors].
+		</div>
+
+
+		<h3>[property:Integer materialIndex]</h3>
+		<div>
+		Material index (points to an index in the associated array of materials). Default is *0*.
+		</div>
+
+		<h2>Methods</h2>
+
+		<h3>[method:Face3 clone]()</h3>
+		<div>Creates a new clone of the Face3 object.</div>
+
+		<h3>[method:Face3 copy]( [page:Face3 face3] )</h3>
+		<div>Copy the paramaters of another Face3 into this.</div>
+
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 4 - 1
docs/api/deprecated/DeprecatedList.html

@@ -411,7 +411,10 @@
 		</div>
 
 		<h3>[page:MeshFaceMaterial]</h3>
-		<div>MeshFaceMaterial has been removed. Use [page:MultiMaterial] instead.</div>
+		<div>MeshFaceMaterial has been removed. Use an array of materials instead.</div>
+
+		<h3>[page:MultiMaterial]</h3>
+		<div>MultiMaterial has been removed. Use an array of materials instead.</div>
 
 		<h3>[page:MeshPhongMaterial]</h3>
 		<div>MeshPhongMaterial.metal has been removed. Use [page:MeshStandardMaterial] instead.</div>

+ 1 - 1
docs/api/extras/SceneUtils.html

@@ -22,7 +22,7 @@
 		materials -- The materials for the object.
 		</div>
 		<div>
-		Creates a new Group that contains a new mesh for each material defined in materials. Beware that this is not the same as MultiMaterial which defines multiple material for 1 mesh.<br />
+		Creates a new Group that contains a new mesh for each material defined in materials. Beware that this is not the same as an array of materials which defines multiple materials for 1 mesh.<br />
 		This is mostly useful for objects that need both a material and a wireframe implementation.
 		</div>
 

+ 10 - 3
docs/api/helpers/BoxHelper.html

@@ -54,10 +54,17 @@
 		<h2>Methods</h2>
 		<div>See the base [page:LineSegments] class for common methods.</div>
 
-		<h3>[method:null update]( [page:Object3D object] )</h3>
+		<h3>[method:null update]()</h3>
 		<div>
-			Updates the helper's geometry to match the dimensions of the
-		 	of the passed object, including any children. See [page:Box3.setFromObject].
+			Updates the helper's geometry to match the dimensions
+			of the object, including any children. See [page:Box3.setFromObject].
+		</div>
+
+		<h3>[method:BoxHelper setFromObject]( [page:Object3D object] )</h3>
+		<div>
+			[page:Object3D object] - [page:Object3D] to create the helper of.<br /><br />
+
+			Updates the wireframe box for the passed object.
 		</div>
 
 		<h2>Source</h2>

+ 6 - 1
docs/api/loaders/JSONLoader.html

@@ -28,13 +28,18 @@
 
 		// load a resource
 		loader.load(
+
 			// resource URL
 			'models/animated/monster/monster.js',
+
 			// Function when resource is loaded
 			function ( geometry, materials ) {
-				var material = new THREE.MultiMaterial( materials );
+
+				var material = materials[ 0 ];
 				var object = new THREE.Mesh( geometry, material );
+
 				scene.add( object );
+
 			}
 		);
 		</code>

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

@@ -17,8 +17,8 @@
 		They are defined in a (mostly) renderer-independent way, so you don't have to
 		rewrite materials if you decide to use a different renderer.<br /><br />
 
-		With the exception of [page:MultiMaterial MultiMaterial], the following properties
-		and methods are inherited by all other material types (although they may have different defaults).
+		The following properties and methods are inherited by all other material types
+		(although they may have different defaults).
 		</div>
 
 		<h2>Constructor</h2>

+ 4 - 3
docs/api/materials/ShaderMaterial.html

@@ -86,13 +86,14 @@
 		var material = new THREE.ShaderMaterial( {
 
 			uniforms: {
+
 				time: { value: 1.0 },
 				resolution: { value: new THREE.Vector2() }
+
 			},
-			attributes: {
-				vertexOpacity: { value: [] }
-			},
+
 			vertexShader: document.getElementById( 'vertexShader' ).textContent,
+
 			fragmentShader: document.getElementById( 'fragmentShader' ).textContent
 
 		} );

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

@@ -13,11 +13,11 @@
 		<h1>[name]</h1>
 
 		<div class="desc">
-		This material can recieve shadows, but otherwise is completely transparent.
+		This material can receive shadows, but otherwise is completely transparent.
 		</div>
 
 		<h3>Example</h3>
-		[example:webgl_geometry_spline_editor gemoetry / spline / editor]
+		[example:webgl_geometry_spline_editor geometry / spline / editor]
 
 		<code>
 var planeGeometry = new THREE.PlaneGeometry( 2000, 2000 );
@@ -34,7 +34,11 @@ scene.add( plane );
 
 		<h2>Constructor</h2>
 
-		<h3>[name]( )</h3>
+		<h3>[name]( [page:Object parameters] )</h3>
+		<div>
+			[page:Object parameters] - (optional) an object with one or more properties defining the material's appearance.
+			Any property of the material (including any property inherited from [page:Material] and [page:ShaderMaterial]) can be passed in here.<br /><br />
+		</div>
 
 
 		<h2>Properties</h2>

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

@@ -168,7 +168,7 @@ m, n, o, p
 		then the [page:Vector3 xAxis], [page:Vector3 yAxis], [page:Vector3 zAxis] will be set to:
 		<code>
 xAxis = (a, e, i)
-yAxis = (d, f, j)
+yAxis = (b, f, j)
 zAxis = (c, g, k)
 		</code>
 		</div>

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

@@ -305,6 +305,9 @@
 		This method clears a rendertarget. To do this, it activates the rendertarget.
 		</div>
 
+		<h3>[method:null compile]( [page:Scene scene], [page:Camera camera] )</h3>
+		<div>Compiles all materials in the scene with the camera. This is useful to precompile shaders before the first rendering.</div>
+		
 		<h3>[method:null dispose]( )</h3>
 		<div>Dispose of the current rendering context.</div>
 

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

@@ -67,7 +67,7 @@
 		<div>
 		Returns an [page:Object3D]. It contains the parsed meshes as [page:Mesh] and lines as [page:LineSegments].<br />
 		All geometry is created as [page:BufferGeometry]. Default materials are created as [page:MeshPhongMaterial].<br />
-		If an <em>obj</em> object or group uses multiple materials while declaring faces geometry groups and a [page:MultiMaterial] is used.
+		If an <em>obj</em> object or group uses multiple materials while declaring faces geometry groups and an array of materials are used.
 		</div>
 
 		<h2>Source</h2>

+ 1 - 1
docs/list.js

@@ -4,7 +4,7 @@ var list = {
 
 		"Getting Started": {
 			"Creating a scene": "manual/introduction/Creating-a-scene",
-			"Detecting WebGL and browser compatibility": "manual/introduction/Detecting-WebGL-and-browser-compatibility",
+			"WebGL compatibility check": "manual/introduction/WebGL-compatibility-check",
 			"How to run things locally": "manual/introduction/How-to-run-thing-locally",
 			"Drawing Lines": "manual/introduction/Drawing-lines",
 			"Creating Text": "manual/introduction/Creating-text",

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

@@ -69,14 +69,14 @@ var positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point
 geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
 
 // draw range
-drawCount = 2; // draw the first 2 points, only
+var drawCount = 2; // draw the first 2 points, only
 geometry.setDrawRange( 0, drawCount );
 
 // material
 var material = new THREE.LineBasicMaterial( { color: 0xff0000, linewidth: 2 } );
 
 // line
-line = new THREE.Line( geometry,  material );
+var line = new THREE.Line( geometry,  material );
 scene.add( line );
 				</code>
 			 	<p>
@@ -85,7 +85,8 @@ scene.add( line );
 				<code>
 var positions = line.geometry.attributes.position.array;
 
-var x = y = z = index = 0;
+var x, y, z, index;
+x = y = z = index = 0;
 
 for ( var i = 0, l = MAX_POINTS; i < l; i ++ ) {
 

+ 0 - 0
docs/manual/introduction/Detecting-WebGL-and-browser-compatibility.html → docs/manual/introduction/WebGL-compatibility-check.html


+ 0 - 8
editor/css/dark.css

@@ -245,11 +245,3 @@ select {
 	.Outliner .option.active {
 		background-color: rgba(21,60,94,1);
 	}
-
-.Panel.Collapsible.collapsed .Static .Button {
-	border-left-color: #444;
-}
-
-.Panel.Collapsible:not(.collapsed) .Static .Button {
-	border-top-color: #444;
-}

+ 0 - 26
editor/css/main.css

@@ -41,32 +41,6 @@ textarea, input { outline: none; } /* osx */
 	user-select: none;
 }
 
-	.Panel.Collapsible .Static {
-		margin: 0;
-	}
-
-	.Panel.Collapsible .Static .Button {
-		float: left;
-		margin-right: 6px;
-		width: 0;
-		height: 0;
-		border: 6px solid transparent;
-	}
-
-	.Panel.Collapsible.collapsed .Static .Button {
-		margin-top: 2px;
-		border-left-color: #bbb;
-	}
-
-	.Panel.Collapsible:not(.collapsed) .Static .Button {
-		margin-top: 6px;
-		border-top-color: #bbb;
-	}
-
-	.Panel.Collapsible.collapsed .Content {
-		display: none;
-	}
-
 /* CodeMirror */
 
 .CodeMirror {

+ 0 - 2
editor/index.html

@@ -38,8 +38,6 @@
 		<script src="../examples/js/exporters/OBJExporter.js"></script>
 		<script src="../examples/js/exporters/STLExporter.js"></script>
 
-		<script src="../examples/js/loaders/deprecated/SceneLoader.js"></script>
-
 		<script src="../examples/js/renderers/Projector.js"></script>
 		<script src="../examples/js/renderers/CanvasRenderer.js"></script>
 		<script src="../examples/js/renderers/RaytracingRenderer.js"></script>

+ 0 - 13
editor/js/Loader.js

@@ -525,19 +525,6 @@ var Loader = function ( editor ) {
 
 				break;
 
-			case 'scene':
-
-				// DEPRECATED
-
-				var loader = new THREE.SceneLoader();
-				loader.parse( data, function ( result ) {
-
-					editor.execute( new SetSceneCommand( result.scene ) );
-
-				}, '' );
-
-				break;
-
 			case 'app':
 
 				editor.fromJSON( data );

+ 4 - 4
editor/js/Viewport.js

@@ -60,7 +60,7 @@ var Viewport = function ( editor ) {
 
 		if ( object !== undefined ) {
 
-			selectionBox.update( object );
+			selectionBox.setFromObject( object );
 
 			if ( editor.helpers[ object.id ] !== undefined ) {
 
@@ -385,7 +385,7 @@ var Viewport = function ( editor ) {
 
 			if ( box.isEmpty() === false ) {
 
-				selectionBox.update( box );
+				selectionBox.setFromObject( object );
 				selectionBox.visible = true;
 
 			}
@@ -408,7 +408,7 @@ var Viewport = function ( editor ) {
 
 		if ( object !== undefined ) {
 
-			selectionBox.update( object );
+			selectionBox.setFromObject( object );
 
 		}
 
@@ -430,7 +430,7 @@ var Viewport = function ( editor ) {
 
 		if ( editor.selected === object ) {
 
-			selectionBox.update( object );
+			selectionBox.setFromObject( object );
 			transformControls.update();
 
 		}

+ 2 - 1
examples/files.js

@@ -67,7 +67,6 @@ var files = {
 		"webgl_lights_pointlights2",
 		"webgl_lights_spotlight",
 		"webgl_lights_spotlights",
-		"webgl_lights_arealight",
 		"webgl_lights_rectarealight",
 		"webgl_lines_colors",
 		"webgl_lines_cubes",
@@ -131,6 +130,7 @@ var files = {
 		"webgl_materials_bumpmap_skin",
 		"webgl_materials_cars",
 		"webgl_materials_channels",
+		"webgl_materials_compile",
 		"webgl_materials_cubemap",
 		"webgl_materials_cubemap_balls_reflection",
 		"webgl_materials_cubemap_balls_refraction",
@@ -254,6 +254,7 @@ var files = {
 		"webgl_buffergeometry_custom_attributes_particles",
 		"webgl_buffergeometry_drawcalls",
 		"webgl_buffergeometry_instancing",
+		"webgl_buffergeometry_instancing2",
 		"webgl_buffergeometry_instancing_billboards",
 		"webgl_buffergeometry_instancing_dynamic",
 		"webgl_buffergeometry_instancing_interleaved_dynamic",

+ 1 - 1
examples/index.html

@@ -473,7 +473,7 @@
 		}
 
 		filterInput.value = extractQuery();
-		updateFilter( )
+		updateFilter();
 
 		</script>
 

+ 0 - 182
examples/js/BlendCharacter.js

@@ -1,182 +0,0 @@
-/**
- * @author Michael Guerrero / http://realitymeltdown.com
- */
-
-THREE.BlendCharacter = function () {
-
-	this.weightSchedule = [];
-	this.warpSchedule = [];
-
-	this.load = function ( url, onLoad ) {
-
-		var scope = this;
-
-		var loader = new THREE.ObjectLoader();
-		loader.load( url, function( loadedObject ) {
-
-			// The exporter does not currently allow exporting a skinned mesh by itself
-			// so we must fish it out of the hierarchy it is embedded in (scene)
-			loadedObject.traverse( function( object ) {
-
-				if ( object instanceof THREE.SkinnedMesh ) {
-
-					scope.skinnedMesh = object;
-
-				}
-
-			} );
-
-			THREE.SkinnedMesh.call( scope, scope.skinnedMesh.geometry, scope.skinnedMesh.material );
-
-			// If we didn't successfully find the mesh, bail out
-			if ( scope.skinnedMesh == undefined ) {
-
-				console.log( 'unable to find skinned mesh in ' + url );
-				return;
-
-			}
-
-			scope.material.skinning = true;
-
-			scope.mixer = new THREE.AnimationMixer( scope );
-
-			// Create the animations
-			for ( var i = 0; i < scope.geometry.animations.length; ++ i ) {
-
-				scope.mixer.clipAction( scope.geometry.animations[ i ] );
-
-			}
-
-			// Loading is complete, fire the callback
-			if ( onLoad !== undefined ) onLoad();
-
-		} );
-
-	};
-
-	this.loadJSON = function ( url, onLoad ) {
-
-		var scope = this;
-
-		var loader = new THREE.JSONLoader();
-		loader.load( url, function( geometry, materials ) {
-
-			var originalMaterial = materials[ 0 ];
-			originalMaterial.skinning = true;
-
-			THREE.SkinnedMesh.call( scope, geometry, originalMaterial );
-
-			var mixer = new THREE.AnimationMixer( scope );
-			scope.mixer = mixer;
-
-			// Create the animations
-			for ( var i = 0; i < geometry.animations.length; ++ i ) {
-
-				mixer.clipAction( geometry.animations[ i ] );
-
-			}
-
-			// Loading is complete, fire the callback
-			if ( onLoad !== undefined ) onLoad();
-
-		} );
-
-	};
-	
-	this.update = function( dt ) {
-
-		this.mixer.update( dt );
-
-	};
-
-	this.play = function( animName, weight ) {
-
-		//console.log("play('%s', %f)", animName, weight);
-		return this.mixer.clipAction( animName ).
-				setEffectiveWeight( weight ).play();
-	};
-
-	this.crossfade = function( fromAnimName, toAnimName, duration ) {
-
-		this.mixer.stopAllAction();
-
-		var fromAction = this.play( fromAnimName, 1 );
-		var toAction = this.play( toAnimName, 1 );
-
-		fromAction.crossFadeTo( toAction, duration, false );
-
-	};
-
-	this.warp = function( fromAnimName, toAnimName, duration ) {
-
-		this.mixer.stopAllAction();
-
-		var fromAction = this.play( fromAnimName, 1 );
-		var toAction = this.play( toAnimName, 1 );
-
-		fromAction.crossFadeTo( toAction, duration, true );
-
-	};
-
-	this.applyWeight = function( animName, weight ) {
-
-		this.mixer.clipAction( animName ).setEffectiveWeight( weight );
-
-	};
-
-	this.getWeight = function( animName ) {
-
-		return this.mixer.clipAction( animName ).getEffectiveWeight();
-
-	};
-
-	this.pauseAll = function() {
-
-		this.mixer.timeScale = 0;
-
-	};
-
-	this.unPauseAll = function() {
-
-		this.mixer.timeScale = 1;
-
-	};
-
-
-	this.stopAll = function() {
-
-		this.mixer.stopAllAction();
-
-	};
-
-	this.showModel = function( boolean ) {
-
-		this.visible = boolean;
-
-	};
-
-};
-
-
-THREE.BlendCharacter.prototype = Object.create( THREE.SkinnedMesh.prototype );
-THREE.BlendCharacter.prototype.constructor = THREE.BlendCharacter;
-
-THREE.BlendCharacter.prototype.getForward = function() {
-
-	var forward = new THREE.Vector3();
-
-	return function() {
-
-		// pull the character's forward basis vector out of the matrix
-		forward.set(
-			- this.matrix.elements[ 8 ],
-			- this.matrix.elements[ 9 ],
-			- this.matrix.elements[ 10 ]
-		);
-
-		return forward;
-
-	}
-
-};
-

+ 0 - 207
examples/js/BlendCharacterGui.js

@@ -1,207 +0,0 @@
-/**
- * @author Michael Guerrero / http://realitymeltdown.com
- */
-
-function BlendCharacterGui( blendMesh ) {
-
-	var controls = {
-
-		gui: null,
-		"Show Model": true,
-		"Show Skeleton": false,
-		"Time Scale": 1.0,
-		"Step Size": 0.016,
-		"Crossfade Time": 3.5,
-		"idle": 0.33,
-		"walk": 0.33,
-		"run": 0.33
-
-	};
-
-	var blendMesh = blendMesh;
-
-	this.showModel = function() {
-
-		return controls[ 'Show Model' ];
-
-	};
-
-	this.showSkeleton = function() {
-
-		return controls[ 'Show Skeleton' ];
-
-	};
-
-	this.getTimeScale = function() {
-
-		return controls[ 'Time Scale' ];
-
-	};
-
-	this.update = function( time ) {
-
-		controls[ 'idle' ] = blendMesh.getWeight( 'idle' );
-		controls[ 'walk' ] = blendMesh.getWeight( 'walk' );
-		controls[ 'run' ] = blendMesh.getWeight( 'run' );
-
-	};
-
-	var init = function() {
-
-		controls.gui = new dat.GUI();
-
-		var settings = controls.gui.addFolder( 'Settings' );
-		var playback = controls.gui.addFolder( 'Playback' );
-		var blending = controls.gui.addFolder( 'Blend Tuning' );
-
-		settings.add( controls, "Show Model" ).onChange( controls.showModelChanged );
-		settings.add( controls, "Show Skeleton" ).onChange( controls.showSkeletonChanged );
-		settings.add( controls, "Time Scale", 0, 1, 0.01 );
-		settings.add( controls, "Step Size", 0.01, 0.1, 0.01 );
-		settings.add( controls, "Crossfade Time", 0.1, 6.0, 0.05 );
-
-		// These controls execute functions
-		playback.add( controls, "start" );
-		playback.add( controls, "pause" );
-		playback.add( controls, "step" );
-		playback.add( controls, "idle to walk" );
-		playback.add( controls, "walk to run" );
-		playback.add( controls, "warp walk to run" );
-
-		blending.add( controls, "idle", 0, 1, 0.01 ).listen().onChange( controls.weight );
-		blending.add( controls, "walk", 0, 1, 0.01 ).listen().onChange( controls.weight );
-		blending.add( controls, "run", 0, 1, 0.01 ).listen().onChange( controls.weight );
-
-		settings.open();
-		playback.open();
-		blending.open();
-
-	};
-
-	var getAnimationData = function() {
-
-		return {
-
-			detail: {
-
-				anims: [ "idle", "walk", "run" ],
-
-				weights: [ controls[ 'idle' ],
-						   controls[ 'walk' ],
-						   controls[ 'run' ] ]
-			}
-
-		};
-
-	};
-
-	controls.start = function() {
-
-		var startEvent = new CustomEvent( 'start-animation', getAnimationData() );
-		window.dispatchEvent( startEvent );
-
-	};
-
-	controls.stop = function() {
-
-		var stopEvent = new CustomEvent( 'stop-animation' );
-		window.dispatchEvent( stopEvent );
-
-	};
-
-	controls.pause = function() {
-
-		var pauseEvent = new CustomEvent( 'pause-animation' );
-		window.dispatchEvent( pauseEvent );
-
-	};
-
-	controls.step = function() {
-
-		var stepData = { detail: { stepSize: controls[ 'Step Size' ] } };
-		window.dispatchEvent( new CustomEvent( 'step-animation', stepData ) );
-
-	};
-
-	controls.weight = function() {
-
-		// renormalize
-		var sum = controls[ 'idle' ] + controls[ 'walk' ] + controls[ 'run' ];
-		controls[ 'idle' ] /= sum;
-		controls[ 'walk' ] /= sum;
-		controls[ 'run' ] /= sum;
-
-		var weightEvent = new CustomEvent( 'weight-animation', getAnimationData() );
-		window.dispatchEvent( weightEvent );
-
-	};
-
-	controls.crossfade = function( from, to ) {
-
-		var fadeData = getAnimationData();
-		fadeData.detail.from = from;
-		fadeData.detail.to = to;
-		fadeData.detail.time = controls[ "Crossfade Time" ];
-
-		window.dispatchEvent( new CustomEvent( 'crossfade', fadeData ) );
-
-	};
-
-	controls.warp = function( from, to ) {
-
-		var warpData = getAnimationData();
-		warpData.detail.from = 'walk';
-		warpData.detail.to = 'run';
-		warpData.detail.time = controls[ "Crossfade Time" ];
-
-		window.dispatchEvent( new CustomEvent( 'warp', warpData ) );
-
-	};
-
-	controls[ 'idle to walk' ] = function() {
-
-		controls.crossfade( 'idle', 'walk' );
-
-	};
-
-	controls[ 'walk to run' ] = function() {
-
-		controls.crossfade( 'walk', 'run' );
-
-	};
-
-	controls[ 'warp walk to run' ] = function() {
-
-		controls.warp( 'walk', 'run' );
-
-	};
-
-	controls.showSkeletonChanged = function() {
-
-		var data = {
-			detail: {
-				shouldShow: controls[ 'Show Skeleton' ]
-			}
-		};
-
-		window.dispatchEvent( new CustomEvent( 'toggle-show-skeleton', data ) );
-
-	};
-
-
-	controls.showModelChanged = function() {
-
-		var data = {
-			detail: {
-				shouldShow: controls[ 'Show Model' ]
-			}
-		};
-
-		window.dispatchEvent( new CustomEvent( 'toggle-show-model', data ) );
-
-	};
-
-
-	init.call( this );
-
-}

+ 2 - 2
examples/js/Cloth.js

@@ -101,7 +101,7 @@ Particle.prototype.integrate = function( timesq ) {
 
 var diff = new THREE.Vector3();
 
-function satisifyConstraints( p1, p2, distance ) {
+function satisfyConstraints( p1, p2, distance ) {
 
 	diff.subVectors( p2.position, p1.position );
 	var currentDist = diff.length();
@@ -272,7 +272,7 @@ function simulate( time ) {
 	for ( i = 0; i < il; i ++ ) {
 
 		constraint = constraints[ i ];
-		satisifyConstraints( constraint[ 0 ], constraint[ 1 ], constraint[ 2 ] );
+		satisfyConstraints( constraint[ 0 ], constraint[ 1 ], constraint[ 2 ] );
 
 	}
 

+ 313 - 321
examples/js/GPUParticleSystem.js

@@ -15,156 +15,115 @@
  *
  */
 
-THREE.GPUParticleSystem = function(options) {
+THREE.GPUParticleSystem = function( options ) {
 
-	var self = this;
-	var options = options || {};
+	THREE.Object3D.apply( this, arguments );
+
+	options = options || {};
 
 	// parse options and use defaults
-	self.PARTICLE_COUNT = options.maxParticles || 1000000;
-	self.PARTICLE_CONTAINERS = options.containerCount || 1;
-	
-	self.PARTICLE_NOISE_TEXTURE = options.particleNoiseTex || null;
-	self.PARTICLE_SPRITE_TEXTURE = options.particleSpriteTex || null;
-	
-	self.PARTICLES_PER_CONTAINER = Math.ceil(self.PARTICLE_COUNT / self.PARTICLE_CONTAINERS);
-	self.PARTICLE_CURSOR = 0;
-	self.time = 0;
-
-
-	// Custom vertex and fragement shader
-	var GPUParticleShader = {
 
-		vertexShader: [
+	this.PARTICLE_COUNT = options.maxParticles || 1000000;
+	this.PARTICLE_CONTAINERS = options.containerCount || 1;
 
-			'precision highp float;',
-			'const vec4 bitSh = vec4(256. * 256. * 256., 256. * 256., 256., 1.);',
-			'const vec4 bitMsk = vec4(0.,vec3(1./256.0));',
-			'const vec4 bitShifts = vec4(1.) / bitSh;',
+	this.PARTICLE_NOISE_TEXTURE = options.particleNoiseTex || null;
+	this.PARTICLE_SPRITE_TEXTURE = options.particleSpriteTex || null;
 
-			'#define FLOAT_MAX	1.70141184e38',
-			'#define FLOAT_MIN	1.17549435e-38',
+	this.PARTICLES_PER_CONTAINER = Math.ceil( this.PARTICLE_COUNT / this.PARTICLE_CONTAINERS );
+	this.PARTICLE_CURSOR = 0;
+	this.time = 0;
+	this.particleContainers = [];
+	this.rand = [];
 
-			'lowp vec4 encode_float(highp float v) {',
-			'highp float av = abs(v);',
+	// custom vertex and fragement shader
 
-			'//Handle special cases',
-			'if(av < FLOAT_MIN) {',
-			'return vec4(0.0, 0.0, 0.0, 0.0);',
-			'} else if(v > FLOAT_MAX) {',
-			'return vec4(127.0, 128.0, 0.0, 0.0) / 255.0;',
-			'} else if(v < -FLOAT_MAX) {',
-			'return vec4(255.0, 128.0, 0.0, 0.0) / 255.0;',
-			'}',
+	var GPUParticleShader = {
 
-			'highp vec4 c = vec4(0,0,0,0);',
+		vertexShader: [
 
-			'//Compute exponent and mantissa',
-			'highp float e = floor(log2(av));',
-			'highp float m = av * pow(2.0, -e) - 1.0;',
+			'uniform float uTime;',
+			'uniform float uScale;',
+			'uniform sampler2D tNoise;',
 
-			//Unpack mantissa
-			'c[1] = floor(128.0 * m);',
-			'm -= c[1] / 128.0;',
-			'c[2] = floor(32768.0 * m);',
-			'm -= c[2] / 32768.0;',
-			'c[3] = floor(8388608.0 * m);',
+			'attribute vec3 positionStart;',
+			'attribute float startTime;',
+			'attribute vec3 velocity;',
+			'attribute float turbulence;',
+			'attribute vec3 color;',
+			'attribute float size;',
+			'attribute float lifeTime;',
 
-			'//Unpack exponent',
-			'highp float ebias = e + 127.0;',
-			'c[0] = floor(ebias / 2.0);',
-			'ebias -= c[0] * 2.0;',
-			'c[1] += floor(ebias) * 128.0;',
+			'varying vec4 vColor;',
+			'varying float lifeLeft;',
 
-			'//Unpack sign bit',
-			'c[0] += 128.0 * step(0.0, -v);',
+			'void main() {',
 
-			'//Scale back to range',
-			'return c / 255.0;',
-			'}',
+			// unpack things from our attributes'
 
-			'vec4 pack(const in float depth)',
-			'{',
-			'const vec4 bit_shift = vec4(256.0*256.0*256.0, 256.0*256.0, 256.0, 1.0);',
-			'const vec4 bit_mask	= vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);',
-			'vec4 res = mod(depth*bit_shift*vec4(255), vec4(256))/vec4(255);',
-			'res -= res.xxyz * bit_mask;',
-			'return res;',
-			'}',
+			'	vColor = vec4( color, 1.0 );',
 
-			'float unpack(const in vec4 rgba_depth)',
-			'{',
-			'const vec4 bit_shift = vec4(1.0/(256.0*256.0*256.0), 1.0/(256.0*256.0), 1.0/256.0, 1.0);',
-			'float depth = dot(rgba_depth, bit_shift);',
-			'return depth;',
-			'}',
+			// convert our velocity back into a value we can use'
 
-			'uniform float uTime;',
-			'uniform float uScale;',
-			'uniform sampler2D tNoise;',
+			'	vec3 newPosition;',
+			'	vec3 v;',
 
-			'attribute vec4 particlePositionsStartTime;',
-			'attribute vec4 particleVelColSizeLife;',
+			'	float timeElapsed = uTime - startTime;',
 
-			'varying vec4 vColor;',
-			'varying float lifeLeft;',
+			'	lifeLeft = 1.0 - ( timeElapsed / lifeTime );',
 
-			'void main() {',
+			'	gl_PointSize = ( uScale * size ) * lifeLeft;',
 
-			'// unpack things from our attributes',
-			'vColor = encode_float( particleVelColSizeLife.y );',
+			'	v.x = ( velocity.x - 0.5 ) * 3.0;',
+			'	v.y = ( velocity.y - 0.5 ) * 3.0;',
+			'	v.z = ( velocity.z - 0.5 ) * 3.0;',
 
-			'// convert our velocity back into a value we can use',
-			'vec4 velTurb = encode_float( particleVelColSizeLife.x );',
-			'vec3 velocity = vec3( velTurb.xyz );',
-			'float turbulence = velTurb.w;',
+			'	newPosition = positionStart + ( v * 10.0 ) * ( uTime - startTime );',
 
-			'vec3 newPosition;',
+			'	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;',
 
-			'float timeElapsed = uTime - particlePositionsStartTime.a;',
+			'	newPosition = mix( newPosition, newPosition + vec3( noiseVel * ( turbulence * 5.0 ) ), ( timeElapsed / lifeTime ) );',
 
-			'lifeLeft = 1. - (timeElapsed / particleVelColSizeLife.w);',
+			'	if( v.y > 0. && v.y < .05 ) {',
 
-			'gl_PointSize = ( uScale * particleVelColSizeLife.z ) * lifeLeft;',
+			'		lifeLeft = 0.0;',
 
-			'velocity.x = ( velocity.x - .5 ) * 3.;',
-			'velocity.y = ( velocity.y - .5 ) * 3.;',
-			'velocity.z = ( velocity.z - .5 ) * 3.;',
+			'	}',
 
-			'newPosition = particlePositionsStartTime.xyz + ( velocity * 10. ) * ( uTime - particlePositionsStartTime.a );',
+			'	if( v.x < - 1.45 ) {',
 
-			'vec3 noise = texture2D( tNoise, vec2( newPosition.x * .015 + (uTime * .05), newPosition.y * .02 + (uTime * .015) )).rgb;',
-			'vec3 noiseVel = ( noise.rgb - .5 ) * 30.;',
+			'		lifeLeft = 0.0;',
 
-			'newPosition = mix(newPosition, newPosition + vec3(noiseVel * ( turbulence * 5. ) ), (timeElapsed / particleVelColSizeLife.a) );',
+			'	}',
 
-			'if( velocity.y > 0. && velocity.y < .05 ) {',
-			'lifeLeft = 0.;',
-			'}',
+			'	if( timeElapsed > 0.0 ) {',
 
-			'if( velocity.x < -1.45 ) {',
-			'lifeLeft = 0.;',
-			'}',
+			'		gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );',
+
+			'	} else {',
+
+			'		gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
+			'		lifeLeft = 0.0;',
+			'		gl_PointSize = 0.;',
+
+			'	}',
 
-			'if( timeElapsed > 0. ) {',
-			'gl_Position = projectionMatrix * modelViewMatrix * vec4( newPosition, 1.0 );',
-			'} else {',
-			'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
-			'lifeLeft = 0.;',
-			'gl_PointSize = 0.;',
-			'}',
 			'}'
 
-		].join("\n"),
+		].join( '\n' ),
 
 		fragmentShader: [
 
-			'float scaleLinear(float value, vec2 valueDomain) {',
-			'return (value - valueDomain.x) / (valueDomain.y - valueDomain.x);',
+			'float scaleLinear( float value, vec2 valueDomain ) {',
+
+			'	return ( value - valueDomain.x ) / ( valueDomain.y - valueDomain.x );',
+
 			'}',
 
-			'float scaleLinear(float value, vec2 valueDomain, vec2 valueRange) {',
-			'return mix(valueRange.x, valueRange.y, scaleLinear(value, valueDomain));',
+			'float scaleLinear( float value, vec2 valueDomain, vec2 valueRange ) {',
+
+			'	return mix( valueRange.x, valueRange.y, scaleLinear( value, valueDomain ) );',
+
 			'}',
 
 			'varying vec4 vColor;',
@@ -174,335 +133,368 @@ THREE.GPUParticleSystem = function(options) {
 
 			'void main() {',
 
-			'float alpha = 0.;',
+			'	float alpha = 0.;',
 
-			'if( lifeLeft > .995 ) {',
-			'alpha = scaleLinear( lifeLeft, vec2(1., .995), vec2(0., 1.));//mix( 0., 1., ( lifeLeft - .95 ) * 100. ) * .75;',
-			'} else {',
-			'alpha = lifeLeft * .75;',
-			'}',
+			'	if( lifeLeft > 0.995 ) {',
+
+			'		alpha = scaleLinear( lifeLeft, vec2( 1.0, 0.995 ), vec2( 0.0, 1.0 ) );',
 
-			'vec4 tex = texture2D( tSprite, gl_PointCoord );',
+			'	} else {',
+
+			'		alpha = lifeLeft * 0.75;',
+
+			'	}',
+
+			'	vec4 tex = texture2D( tSprite, gl_PointCoord );',
+			'	gl_FragColor = vec4( vColor.rgb * tex.a, alpha * tex.a );',
 
-			'gl_FragColor = vec4( vColor.rgb * tex.a, alpha * tex.a );',
 			'}'
 
-		].join("\n")
+		].join( '\n' )
 
 	};
 
 	// preload a million random numbers
-	self.rand = [];
 
-	for (var i = 1e5; i > 0; i--) {
-		self.rand.push(Math.random() - .5);
+	var i;
+
+	for ( i = 1e5; i > 0; i-- ) {
+
+		this.rand.push( Math.random() - 0.5 );
+
 	}
 
-	self.random = function() {
-		return ++i >= self.rand.length ? self.rand[i = 1] : self.rand[i];
+	this.random = function() {
+
+		return ++ i >= this.rand.length ? this.rand[ i = 1 ] : this.rand[ i ];
+
 	};
 
 	var textureLoader = new THREE.TextureLoader();
 
-	self.particleNoiseTex = self.PARTICLE_NOISE_TEXTURE || textureLoader.load("textures/perlin-512.png");
-	self.particleNoiseTex.wrapS = self.particleNoiseTex.wrapT = THREE.RepeatWrapping;
+	this.particleNoiseTex = this.PARTICLE_NOISE_TEXTURE || textureLoader.load( 'textures/perlin-512.png' );
+	this.particleNoiseTex.wrapS = this.particleNoiseTex.wrapT = THREE.RepeatWrapping;
 
-	self.particleSpriteTex = self.PARTICLE_SPRITE_TEXTURE || textureLoader.load("textures/particle2.png");
-	self.particleSpriteTex.wrapS = self.particleSpriteTex.wrapT = THREE.RepeatWrapping;
+	this.particleSpriteTex = this.PARTICLE_SPRITE_TEXTURE || textureLoader.load( 'textures/particle2.png' );
+	this.particleSpriteTex.wrapS = this.particleSpriteTex.wrapT = THREE.RepeatWrapping;
 
-	self.particleShaderMat = new THREE.ShaderMaterial({
+	this.particleShaderMat = new THREE.ShaderMaterial( {
 		transparent: true,
 		depthWrite: false,
 		uniforms: {
-			"uTime": {
+			'uTime': {
 				value: 0.0
 			},
-			"uScale": {
+			'uScale': {
 				value: 1.0
 			},
-			"tNoise": {
-				value: self.particleNoiseTex
+			'tNoise': {
+				value: this.particleNoiseTex
 			},
-			"tSprite": {
-				value: self.particleSpriteTex
+			'tSprite': {
+				value: this.particleSpriteTex
 			}
 		},
 		blending: THREE.AdditiveBlending,
 		vertexShader: GPUParticleShader.vertexShader,
 		fragmentShader: GPUParticleShader.fragmentShader
-	});
+	} );
 
 	// define defaults for all values
-	self.particleShaderMat.defaultAttributeValues.particlePositionsStartTime = [0, 0, 0, 0];
-	self.particleShaderMat.defaultAttributeValues.particleVelColSizeLife = [0, 0, 0, 0];
-
-	self.particleContainers = [];
 
-
-	// extend Object3D
-	THREE.Object3D.apply(this, arguments);
+	this.particleShaderMat.defaultAttributeValues.particlePositionsStartTime = [ 0, 0, 0, 0 ];
+	this.particleShaderMat.defaultAttributeValues.particleVelColSizeLife = [ 0, 0, 0, 0 ];
 
 	this.init = function() {
 
-		for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
+		for ( var i = 0; i < this.PARTICLE_CONTAINERS; i ++ ) {
 
-			var c = new THREE.GPUParticleContainer(self.PARTICLES_PER_CONTAINER, self);
-			self.particleContainers.push(c);
-			self.add(c);
+			var c = new THREE.GPUParticleContainer( this.PARTICLES_PER_CONTAINER, this );
+			this.particleContainers.push( c );
+			this.add( c );
 
 		}
 
 	};
 
-	this.spawnParticle = function(options) {
+	this.spawnParticle = function( options ) {
+
+		this.PARTICLE_CURSOR ++;
+
+		if ( this.PARTICLE_CURSOR >= this.PARTICLE_COUNT ) {
+
+			this.PARTICLE_CURSOR = 1;
 
-		self.PARTICLE_CURSOR++;
-		if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
-			self.PARTICLE_CURSOR = 1;
 		}
 
-		var currentContainer = self.particleContainers[Math.floor(self.PARTICLE_CURSOR / self.PARTICLES_PER_CONTAINER)];
+		var currentContainer = this.particleContainers[ Math.floor( this.PARTICLE_CURSOR / this.PARTICLES_PER_CONTAINER ) ];
 
-		currentContainer.spawnParticle(options);
+		currentContainer.spawnParticle( options );
 
 	};
 
-	this.update = function(time) {
-		for (var i = 0; i < self.PARTICLE_CONTAINERS; i++) {
+	this.update = function( time ) {
+
+		for ( var i = 0; i < this.PARTICLE_CONTAINERS; i ++ ) {
 
-			self.particleContainers[i].update(time);
+			this.particleContainers[ i ].update( time );
 
 		}
+
+	};
+
+	this.dispose = function() {
+
+		this.particleShaderMat.dispose();
+		this.particleNoiseTex.dispose();
+		this.particleSpriteTex.dispose();
+
+		for ( var i = 0; i < this.PARTICLE_CONTAINERS; i ++ ) {
+
+			this.particleContainers[ i ].dispose();
+
+		}
+
 	};
 
 	this.init();
 
 };
 
-THREE.GPUParticleSystem.prototype = Object.create(THREE.Object3D.prototype);
+THREE.GPUParticleSystem.prototype = Object.create( THREE.Object3D.prototype );
 THREE.GPUParticleSystem.prototype.constructor = THREE.GPUParticleSystem;
 
 
 // Subclass for particle containers, allows for very large arrays to be spread out
-THREE.GPUParticleContainer = function(maxParticles, particleSystem) {
-
-	var self = this;
-	self.PARTICLE_COUNT = maxParticles || 100000;
-	self.PARTICLE_CURSOR = 0;
-	self.time = 0;
-	self.DPR = window.devicePixelRatio;
-	self.GPUParticleSystem = particleSystem;
-
-	var particlesPerArray = Math.floor(self.PARTICLE_COUNT / self.MAX_ATTRIBUTES);
-
-	// extend Object3D
-	THREE.Object3D.apply(this, arguments);
-
-	// construct a couple small arrays used for packing variables into floats etc
-	var UINT8_VIEW = new Uint8Array(4);
-	var FLOAT_VIEW = new Float32Array(UINT8_VIEW.buffer);
-
-	function decodeFloat(x, y, z, w) {
-		UINT8_VIEW[0] = Math.floor(w);
-		UINT8_VIEW[1] = Math.floor(z);
-		UINT8_VIEW[2] = Math.floor(y);
-		UINT8_VIEW[3] = Math.floor(x);
-		return FLOAT_VIEW[0]
-	}
 
-	function componentToHex(c) {
-		var hex = c.toString(16);
-		return hex.length == 1 ? "0" + hex : hex;
-	}
+THREE.GPUParticleContainer = function( maxParticles, particleSystem ) {
 
-	function rgbToHex(r, g, b) {
-		return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
-	}
+	THREE.Object3D.apply( this, arguments );
 
-	function hexToRgb(hex) {
-		var r = hex >> 16;
-		var g = (hex & 0x00FF00) >> 8;
-		var b = hex & 0x0000FF;
+	this.PARTICLE_COUNT = maxParticles || 100000;
+	this.PARTICLE_CURSOR = 0;
+	this.time = 0;
+	this.offset = 0;
+	this.count = 0;
+	this.DPR = window.devicePixelRatio;
+	this.GPUParticleSystem = particleSystem;
+	this.particleUpdate = false;
 
-		if (r > 0) r--;
-		if (g > 0) g--;
-		if (b > 0) b--;
+	// geometry
 
-		return [r, g, b];
-	}
+	this.particleShaderGeo = new THREE.BufferGeometry();
 
-	self.particles = [];
-	self.deadParticles = [];
-	self.particlesAvailableSlot = [];
+	this.particleShaderGeo.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) );
+	this.particleShaderGeo.addAttribute( 'positionStart', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) );
+	this.particleShaderGeo.addAttribute( 'startTime', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) );
+	this.particleShaderGeo.addAttribute( 'velocity', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) );
+	this.particleShaderGeo.addAttribute( 'turbulence', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) );
+	this.particleShaderGeo.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT * 3 ), 3 ).setDynamic( true ) );
+	this.particleShaderGeo.addAttribute( 'size', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) );
+	this.particleShaderGeo.addAttribute( 'lifeTime', new THREE.BufferAttribute( new Float32Array( this.PARTICLE_COUNT ), 1 ).setDynamic( true ) );
 
-	// create a container for particles
-	self.particleUpdate = false;
+	// material
 
-	// Shader Based Particle System
-	self.particleShaderGeo = new THREE.BufferGeometry();
+	this.particleShaderMat = this.GPUParticleSystem.particleShaderMat;
 
-	// new hyper compressed attributes
-	self.particleVertices = new Float32Array(self.PARTICLE_COUNT * 3); // position
-	self.particlePositionsStartTime = new Float32Array(self.PARTICLE_COUNT * 4); // position
-	self.particleVelColSizeLife = new Float32Array(self.PARTICLE_COUNT * 4);
+	var position = new THREE.Vector3();
+	var velocity = new THREE.Vector3();
+	var color = new THREE.Color();
 
-	for (var i = 0; i < self.PARTICLE_COUNT; i++) {
-		self.particlePositionsStartTime[i * 4 + 0] = 100; //x
-		self.particlePositionsStartTime[i * 4 + 1] = 0; //y
-		self.particlePositionsStartTime[i * 4 + 2] = 0.0; //z
-		self.particlePositionsStartTime[i * 4 + 3] = 0.0; //startTime
+	this.spawnParticle = function( options ) {
 
-		self.particleVertices[i * 3 + 0] = 0; //x
-		self.particleVertices[i * 3 + 1] = 0; //y
-		self.particleVertices[i * 3 + 2] = 0.0; //z
+		var positionStartAttribute = this.particleShaderGeo.getAttribute( 'positionStart' );
+		var startTimeAttribute = this.particleShaderGeo.getAttribute( 'startTime' );
+		var velocityAttribute = this.particleShaderGeo.getAttribute( 'velocity' );
+		var turbulenceAttribute = this.particleShaderGeo.getAttribute( 'turbulence' );
+		var colorAttribute = this.particleShaderGeo.getAttribute( 'color' );
+		var sizeAttribute = this.particleShaderGeo.getAttribute( 'size' );
+		var lifeTimeAttribute = this.particleShaderGeo.getAttribute( 'lifeTime' );
 
-		self.particleVelColSizeLife[i * 4 + 0] = decodeFloat(128, 128, 0, 0); //vel
-		self.particleVelColSizeLife[i * 4 + 1] = decodeFloat(0, 254, 0, 254); //color
-		self.particleVelColSizeLife[i * 4 + 2] = 1.0; //size
-		self.particleVelColSizeLife[i * 4 + 3] = 0.0; //lifespan
-	}
+		options = options || {};
 
-	self.particleShaderGeo.addAttribute('position', new THREE.BufferAttribute(self.particleVertices, 3));
-	self.particleShaderGeo.addAttribute('particlePositionsStartTime', new THREE.BufferAttribute(self.particlePositionsStartTime, 4).setDynamic(true));
-	self.particleShaderGeo.addAttribute('particleVelColSizeLife', new THREE.BufferAttribute(self.particleVelColSizeLife, 4).setDynamic(true));
+		// setup reasonable default values for all arguments
 
-	self.posStart = self.particleShaderGeo.getAttribute('particlePositionsStartTime');
-	self.velCol = self.particleShaderGeo.getAttribute('particleVelColSizeLife');
+		position = options.position !== undefined ? position.copy( options.position ) : position.set( 0, 0, 0 );
+		velocity = options.velocity !== undefined ? velocity.copy( options.velocity ) : velocity.set( 0, 0, 0 );
+		color = options.color !== undefined ? color.set( options.color ) : color.set( 0xffffff );
 
-	self.particleShaderMat = self.GPUParticleSystem.particleShaderMat;
+		var positionRandomness = options.positionRandomness !== undefined ? options.positionRandomness : 0;
+		var velocityRandomness = options.velocityRandomness !== undefined ? options.velocityRandomness : 0;
+		var colorRandomness = options.colorRandomness !== undefined ? options.colorRandomness : 1;
+		var turbulence = options.turbulence !== undefined ? options.turbulence : 1;
+		var lifetime = options.lifetime !== undefined ? options.lifetime : 5;
+		var size = options.size !== undefined ? options.size : 10;
+		var sizeRandomness = options.sizeRandomness !== undefined ? options.sizeRandomness : 0;
+		var smoothPosition = options.smoothPosition !== undefined ? options.smoothPosition : false;
 
-	this.init = function() {
-		self.particleSystem = new THREE.Points(self.particleShaderGeo, self.particleShaderMat);
-		self.particleSystem.frustumCulled = false;
-		this.add(self.particleSystem);
-	};
+		if ( this.DPR !== undefined ) size *= this.DPR;
 
-	var options = {},
-		position = new THREE.Vector3(),
-		velocity = new THREE.Vector3(),
-		positionRandomness = 0.,
-		velocityRandomness = 0.,
-		color = 0xffffff,
-		colorRandomness = 0.,
-		turbulence = 0.,
-		lifetime = 0.,
-		size = 0.,
-		sizeRandomness = 0.,
-		smoothPosition = false,
-		i;
-
-	var maxVel = 2;
-	var maxSource = 250;
-	this.offset = 0;
-	this.count = 0;
+		i = this.PARTICLE_CURSOR;
 
-	this.spawnParticle = function(options) {
+		// position
 
-		options = options || {};
+		positionStartAttribute.array[ i * 3 + 0 ] = position.x + ( particleSystem.random() * positionRandomness );
+		positionStartAttribute.array[ i * 3 + 1 ] = position.y + ( particleSystem.random() * positionRandomness );
+		positionStartAttribute.array[ i * 3 + 2 ] = position.z + ( particleSystem.random() * positionRandomness );
+
+		if ( smoothPosition === true ) {
+
+			positionStartAttribute.array[ i * 3 + 0 ] += - ( velocity.x * particleSystem.random() );
+			positionStartAttribute.array[ i * 3 + 1 ] += - ( velocity.y * particleSystem.random() );
+			positionStartAttribute.array[ i * 3 + 2 ] += - ( velocity.z * particleSystem.random() );
 
-		// setup reasonable default values for all arguments
-		position = options.position !== undefined ? position.copy(options.position) : position.set(0., 0., 0.);
-		velocity = options.velocity !== undefined ? velocity.copy(options.velocity) : velocity.set(0., 0., 0.);
-		positionRandomness = options.positionRandomness !== undefined ? options.positionRandomness : 0.0;
-		velocityRandomness = options.velocityRandomness !== undefined ? options.velocityRandomness : 0.0;
-		color = options.color !== undefined ? options.color : 0xffffff;
-		colorRandomness = options.colorRandomness !== undefined ? options.colorRandomness : 1.0;
-		turbulence = options.turbulence !== undefined ? options.turbulence : 1.0;
-		lifetime = options.lifetime !== undefined ? options.lifetime : 5.0;
-		size = options.size !== undefined ? options.size : 10;
-		sizeRandomness = options.sizeRandomness !== undefined ? options.sizeRandomness : 0.0;
-		smoothPosition = options.smoothPosition !== undefined ? options.smoothPosition : false;
-
-		if (self.DPR !== undefined) size *= self.DPR;
-
-		i = self.PARTICLE_CURSOR;
-
-		self.posStart.array[i * 4 + 0] = position.x + ((particleSystem.random()) * positionRandomness); // - ( velocity.x * particleSystem.random() ); //x
-		self.posStart.array[i * 4 + 1] = position.y + ((particleSystem.random()) * positionRandomness); // - ( velocity.y * particleSystem.random() ); //y
-		self.posStart.array[i * 4 + 2] = position.z + ((particleSystem.random()) * positionRandomness); // - ( velocity.z * particleSystem.random() ); //z
-		self.posStart.array[i * 4 + 3] = self.time + (particleSystem.random() * 2e-2); //startTime
-
-		if (smoothPosition === true) {
-			self.posStart.array[i * 4 + 0] += -(velocity.x * particleSystem.random()); //x
-			self.posStart.array[i * 4 + 1] += -(velocity.y * particleSystem.random()); //y
-			self.posStart.array[i * 4 + 2] += -(velocity.z * particleSystem.random()); //z
 		}
 
-		var velX = velocity.x + (particleSystem.random()) * velocityRandomness;
-		var velY = velocity.y + (particleSystem.random()) * velocityRandomness;
-		var velZ = velocity.z + (particleSystem.random()) * velocityRandomness;
+		// velocity
 
-		// convert turbulence rating to something we can pack into a vec4
-		var turbulence = Math.floor(turbulence * 254);
+		var maxVel = 2;
 
-		// clamp our value to between 0. and 1.
-		velX = Math.floor(maxSource * ((velX - -maxVel) / (maxVel - -maxVel)));
-		velY = Math.floor(maxSource * ((velY - -maxVel) / (maxVel - -maxVel)));
-		velZ = Math.floor(maxSource * ((velZ - -maxVel) / (maxVel - -maxVel)));
+		var velX = velocity.x + particleSystem.random() * velocityRandomness;
+		var velY = velocity.y + particleSystem.random() * velocityRandomness;
+		var velZ = velocity.z + particleSystem.random() * velocityRandomness;
 
-		self.velCol.array[i * 4 + 0] = decodeFloat(velX, velY, velZ, turbulence); //vel
+		velX = THREE.Math.clamp( ( velX - ( - maxVel ) ) / ( maxVel - ( - maxVel ) ), 0, 1 );
+		velY = THREE.Math.clamp( ( velY - ( - maxVel ) ) / ( maxVel - ( - maxVel ) ), 0, 1 );
+		velZ = THREE.Math.clamp( ( velZ - ( - maxVel ) ) / ( maxVel - ( - maxVel ) ), 0, 1 );
 
-		var rgb = hexToRgb(color);
+		velocityAttribute.array[ i * 3 + 0 ] = velX;
+		velocityAttribute.array[ i * 3 + 1 ] = velY;
+		velocityAttribute.array[ i * 3 + 2 ] = velZ;
 
-		for (var c = 0; c < rgb.length; c++) {
-			rgb[c] = Math.floor(rgb[c] + ((particleSystem.random()) * colorRandomness) * 254);
-			if (rgb[c] > 254) rgb[c] = 254;
-			if (rgb[c] < 0) rgb[c] = 0;
-		}
+		// color
+
+		color.r = THREE.Math.clamp( color.r + particleSystem.random() * colorRandomness, 0, 1 );
+		color.g = THREE.Math.clamp( color.g + particleSystem.random() * colorRandomness, 0, 1 );
+		color.b = THREE.Math.clamp( color.b + particleSystem.random() * colorRandomness, 0, 1 );
+
+		colorAttribute.array[ i * 3 + 0 ] = color.r;
+		colorAttribute.array[ i * 3 + 1 ] = color.g;
+		colorAttribute.array[ i * 3 + 2 ] = color.b;
 
-		self.velCol.array[i * 4 + 1] = decodeFloat(rgb[0], rgb[1], rgb[2], 254); //color
-		self.velCol.array[i * 4 + 2] = size + (particleSystem.random()) * sizeRandomness; //size
-		self.velCol.array[i * 4 + 3] = lifetime; //lifespan
+		// turbulence, size, lifetime and starttime
+
+		turbulenceAttribute.array[ i ] = turbulence;
+		sizeAttribute.array[ i ] = size + particleSystem.random() * sizeRandomness;
+		lifeTimeAttribute.array[ i ] = lifetime;
+		startTimeAttribute.array[ i ] = this.time + particleSystem.random() * 2e-2;
+
+		// offset
+
+		if ( this.offset === 0 ) {
+
+			this.offset = this.PARTICLE_CURSOR;
 
-		if (this.offset == 0) {
-			this.offset = self.PARTICLE_CURSOR;
 		}
 
-		self.count++;
+		// counter and cursor
 
-		self.PARTICLE_CURSOR++;
+		this.count ++;
+		this.PARTICLE_CURSOR ++;
+
+		if ( this.PARTICLE_CURSOR >= this.PARTICLE_COUNT ) {
+
+			this.PARTICLE_CURSOR = 0;
 
-		if (self.PARTICLE_CURSOR >= self.PARTICLE_COUNT) {
-			self.PARTICLE_CURSOR = 0;
 		}
 
-		self.particleUpdate = true;
+		this.particleUpdate = true;
 
 	};
 
-	this.update = function(time) {
+	this.init = function() {
 
-		self.time = time;
-		self.particleShaderMat.uniforms['uTime'].value = time;
+		this.particleSystem = new THREE.Points( this.particleShaderGeo, this.particleShaderMat );
+		this.particleSystem.frustumCulled = false;
+		this.add( this.particleSystem );
+
+	};
+
+	this.update = function( time ) {
+
+		this.time = time;
+		this.particleShaderMat.uniforms.uTime.value = time;
 
 		this.geometryUpdate();
 
 	};
 
 	this.geometryUpdate = function() {
-		if (self.particleUpdate == true) {
-			self.particleUpdate = false;
 
-			// if we can get away with a partial buffer update, do so
-			if (self.offset + self.count < self.PARTICLE_COUNT) {
-				self.posStart.updateRange.offset = self.velCol.updateRange.offset = self.offset * 4;
-				self.posStart.updateRange.count = self.velCol.updateRange.count = self.count * 4;
+		if ( this.particleUpdate === true ) {
+
+			this.particleUpdate = false;
+
+			var positionStartAttribute = this.particleShaderGeo.getAttribute( 'positionStart' );
+			var startTimeAttribute = this.particleShaderGeo.getAttribute( 'startTime' );
+			var velocityAttribute = this.particleShaderGeo.getAttribute( 'velocity' );
+			var turbulenceAttribute = this.particleShaderGeo.getAttribute( 'turbulence' );
+			var colorAttribute = this.particleShaderGeo.getAttribute( 'color' );
+			var sizeAttribute = this.particleShaderGeo.getAttribute( 'size' );
+			var lifeTimeAttribute = this.particleShaderGeo.getAttribute( 'lifeTime' );
+
+			if ( this.offset + this.count < this.PARTICLE_COUNT ) {
+
+				positionStartAttribute.updateRange.offset = this.offset * positionStartAttribute.itemSize;
+				startTimeAttribute.updateRange.offset = this.offset * startTimeAttribute.itemSize;
+				velocityAttribute.updateRange.offset = this.offset * velocityAttribute.itemSize;
+				turbulenceAttribute.updateRange.offset = this.offset * turbulenceAttribute.itemSize;
+				colorAttribute.updateRange.offset = this.offset * colorAttribute.itemSize;
+				sizeAttribute.updateRange.offset = this.offset * sizeAttribute.itemSize;
+				lifeTimeAttribute.updateRange.offset = this.offset * lifeTimeAttribute.itemSize;
+
+				positionStartAttribute.updateRange.count = this.count * positionStartAttribute.itemSize;
+				startTimeAttribute.updateRange.count = this.count * startTimeAttribute.itemSize;
+				velocityAttribute.updateRange.count = this.count * velocityAttribute.itemSize;
+				turbulenceAttribute.updateRange.count = this.count * turbulenceAttribute.itemSize;
+				colorAttribute.updateRange.count = this.count * colorAttribute.itemSize;
+				sizeAttribute.updateRange.count = this.count * sizeAttribute.itemSize;
+				lifeTimeAttribute.updateRange.count = this.count * lifeTimeAttribute.itemSize;
+
 			} else {
-				self.posStart.updateRange.offset = 0;
-				self.posStart.updateRange.count = self.velCol.updateRange.count = (self.PARTICLE_COUNT * 4);
+
+				positionStartAttribute.updateRange.offset = 0;
+				startTimeAttribute.updateRange.offset = 0;
+				velocityAttribute.updateRange.offset = 0;
+				turbulenceAttribute.updateRange.offset = 0;
+				colorAttribute.updateRange.offset = 0;
+				sizeAttribute.updateRange.offset = 0;
+				lifeTimeAttribute.updateRange.offset = 0;
+
+				positionStartAttribute.updateRange.count = positionStartAttribute.count;
+				startTimeAttribute.updateRange.count = startTimeAttribute.count;
+				velocityAttribute.updateRange.count = velocityAttribute.count;
+				turbulenceAttribute.updateRange.count = turbulenceAttribute.count;
+				colorAttribute.updateRange.count = colorAttribute.count;
+				sizeAttribute.updateRange.count = sizeAttribute.count;
+				lifeTimeAttribute.updateRange.count = lifeTimeAttribute.count;
+
 			}
 
-			self.posStart.needsUpdate = true;
-			self.velCol.needsUpdate = true;
+			positionStartAttribute.needsUpdate = true;
+			startTimeAttribute.needsUpdate = true;
+			velocityAttribute.needsUpdate = true;
+			turbulenceAttribute.needsUpdate = true;
+			colorAttribute.needsUpdate = true;
+			sizeAttribute.needsUpdate = true;
+			lifeTimeAttribute.needsUpdate = true;
+
+			this.offset = 0;
+			this.count = 0;
 
-			self.offset = 0;
-			self.count = 0;
 		}
+
+	};
+
+	this.dispose = function() {
+
+		this.particleShaderGeo.dispose();
+
 	};
 
 	this.init();
 
 };
 
-THREE.GPUParticleContainer.prototype = Object.create(THREE.Object3D.prototype);
+THREE.GPUParticleContainer.prototype = Object.create( THREE.Object3D.prototype );
 THREE.GPUParticleContainer.prototype.constructor = THREE.GPUParticleContainer;

+ 37 - 21
examples/js/controls/OrbitControls.js

@@ -662,29 +662,37 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 		event.preventDefault();
 
-		if ( event.button === scope.mouseButtons.ORBIT ) {
+		switch ( event.button ) {
 
-			if ( scope.enableRotate === false ) return;
+			case scope.mouseButtons.ORBIT:
 
-			handleMouseDownRotate( event );
+				if ( scope.enableRotate === false ) return;
+
+				handleMouseDownRotate( event );
+
+				state = STATE.ROTATE;
+
+				break;
 
-			state = STATE.ROTATE;
+			case scope.mouseButtons.ZOOM:
 
-		} else if ( event.button === scope.mouseButtons.ZOOM ) {
+				if ( scope.enableZoom === false ) return;
 
-			if ( scope.enableZoom === false ) return;
+				handleMouseDownDolly( event );
 
-			handleMouseDownDolly( event );
+				state = STATE.DOLLY;
 
-			state = STATE.DOLLY;
+				break;
 
-		} else if ( event.button === scope.mouseButtons.PAN ) {
+			case scope.mouseButtons.PAN:
 
-			if ( scope.enablePan === false ) return;
+				if ( scope.enablePan === false ) return;
 
-			handleMouseDownPan( event );
+				handleMouseDownPan( event );
 
-			state = STATE.PAN;
+				state = STATE.PAN;
+
+				break;
 
 		}
 
@@ -705,23 +713,31 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 		event.preventDefault();
 
-		if ( state === STATE.ROTATE ) {
+		switch ( state ) {
 
-			if ( scope.enableRotate === false ) return;
+			case STATE.ROTATE:
 
-			handleMouseMoveRotate( event );
+				if ( scope.enableRotate === false ) return;
+
+				handleMouseMoveRotate( event );
+
+				break;
+
+			case STATE.DOLLY:
 
-		} else if ( state === STATE.DOLLY ) {
+				if ( scope.enableZoom === false ) return;
 
-			if ( scope.enableZoom === false ) return;
+				handleMouseMoveDolly( event );
 
-			handleMouseMoveDolly( event );
+				break;
 
-		} else if ( state === STATE.PAN ) {
+			case STATE.PAN:
 
-			if ( scope.enablePan === false ) return;
+				if ( scope.enablePan === false ) return;
 
-			handleMouseMovePan( event );
+				handleMouseMovePan( event );
+
+				break;
 
 		}
 

+ 38 - 25
examples/js/loaders/GLTF2Loader.js

@@ -718,12 +718,12 @@ THREE.GLTF2Loader = ( function () {
 
 			switch ( semantic ) {
 
-				case "POSITION":
+				case 'POSITION':
 
 					shaderText = shaderText.replace( regEx, 'position' );
 					break;
 
-				case "NORMAL":
+				case 'NORMAL':
 
 					shaderText = shaderText.replace( regEx, 'normal' );
 					break;
@@ -747,12 +747,14 @@ THREE.GLTF2Loader = ( function () {
 					shaderText = shaderText.replace( regEx, 'color' );
 					break;
 
-				case "WEIGHT":
+				case 'WEIGHTS_0':
+				case 'WEIGHT': // WEIGHT semantic deprecated.
 
 					shaderText = shaderText.replace( regEx, 'skinWeight' );
 					break;
 
-				case "JOINT":
+				case 'JOINTS_0':
+				case 'JOINT': // JOINT semantic deprecated.
 
 					shaderText = shaderText.replace( regEx, 'skinIndex' );
 					break;
@@ -1694,9 +1696,15 @@ THREE.GLTF2Loader = ( function () {
 
 					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 ) {
 
-						var geometry = new THREE.BufferGeometry();
+						geometry = new THREE.BufferGeometry();
 
 						var attributes = primitive.attributes;
 
@@ -1711,34 +1719,43 @@ THREE.GLTF2Loader = ( function () {
 							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 'WEIGHT':
+								case 'WEIGHTS_0':
+								case 'WEIGHT': // WEIGHT semantic deprecated.
+
 									geometry.addAttribute( 'skinWeight', bufferAttribute );
 									break;
 
-								case 'JOINT':
+								case 'JOINTS_0':
+								case 'JOINT': // JOINT semantic deprecated.
+
 									geometry.addAttribute( 'skinIndex', bufferAttribute );
 									break;
 
@@ -1752,19 +1769,12 @@ THREE.GLTF2Loader = ( function () {
 
 						}
 
-						var material = dependencies.materials !== undefined ? dependencies.materials[ primitive.material ] : createDefaultMaterial();
-
-						var meshNode = new THREE.Mesh( geometry, material );
+						meshNode = new THREE.Mesh( geometry, material );
 						meshNode.castShadow = true;
-						meshNode.name = ( name === "0" ? group.name : group.name + name );
-
-						if ( primitive.extras ) meshNode.userData = primitive.extras;
-
-						group.add( meshNode );
 
 					} else if ( primitive.mode === WEBGL_CONSTANTS.LINES ) {
 
-						var geometry = new THREE.BufferGeometry();
+						geometry = new THREE.BufferGeometry();
 
 						var attributes = primitive.attributes;
 
@@ -1792,10 +1802,6 @@ THREE.GLTF2Loader = ( function () {
 
 						}
 
-						var material = dependencies.materials[ primitive.material ];
-
-						var meshNode;
-
 						if ( primitive.indices !== undefined ) {
 
 							geometry.setIndex( dependencies.accessors[ primitive.indices ] );
@@ -1808,18 +1814,25 @@ THREE.GLTF2Loader = ( function () {
 
 						}
 
-						meshNode.name = ( name === "0" ? group.name : group.name + name );
+					} else {
 
-						if ( primitive.extras ) meshNode.userData = primitive.extras;
+						throw new Error( "Only triangular and line primitives are supported" );
 
-						group.add( meshNode );
+					}
 
-					} else {
+					if ( geometry.attributes.color !== undefined ) {
 
-						console.warn( "Only triangular and line primitives are supported" );
+						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;

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

@@ -208,7 +208,7 @@ THREE.OBJLoader2.WWOBJLoader2 = (function () {
 		if ( this.dataAvailable ) {
 
 			// fast-fail on bad type
-			if ( ! params.objAsArrayBuffer instanceof Uint8Array ) {
+			if ( ! ( params.objAsArrayBuffer instanceof Uint8Array ) ) {
 				throw 'Provided input is not of type arraybuffer! Aborting...';
 			}
 

+ 1580 - 1045
examples/js/loaders/XLoader.js

@@ -20,1080 +20,1615 @@
  *  - morph
  *  - scene
  */
-
 var XfileLoadMode$1 = XfileLoadMode = {
-    none: -1,
-    Element: 1,
-    FrameTransformMatrix_Read: 3,
-    Mesh: 5,
-    Vartex_init: 10,
-    Vartex_Read: 11,
-    Index_init: 20,
-    index_Read: 21,
-    Uv_init: 30,
-    Uv_Read: 31,
-    Normal_V_init: 40,
-    Normal_V_Read: 41,
-    Normal_I_init: 42,
-    Normal_I_Read: 43,
-    Mat_Face_init: 101,
-    Mat_Face_len_Read: 102,
-    Mat_Face_Set: 103,
-    Mat_Set: 111,
-    Mat_Set_Texture: 121,
-    Mat_Set_LightTex: 122,
-    Mat_Set_EmissiveTex: 123,
-    Mat_Set_BumpTex: 124,
-    Mat_Set_NormalTex: 125,
-    Mat_Set_EnvTex: 126,
-    Weit_init: 201,
-    Weit_IndexLength: 202,
-    Weit_Read_Index: 203,
-    Weit_Read_Value: 204,
-    Weit_Read_Matrx: 205,
-    Anim_init: 1001,
-    Anim_Reading: 1002,
-    Anim_KeyValueTypeRead: 1003,
-    Anim_KeyValueLength: 1004,
-    Anime_ReadKeyFrame: 1005
+	none: - 1,
+	Element: 1,
+	FrameTransformMatrix_Read: 3,
+	Mesh: 5,
+	Vartex_init: 10,
+	Vartex_Read: 11,
+	Index_init: 20,
+	index_Read: 21,
+	Uv_init: 30,
+	Uv_Read: 31,
+	Normal_V_init: 40,
+	Normal_V_Read: 41,
+	Normal_I_init: 42,
+	Normal_I_Read: 43,
+	Mat_Face_init: 101,
+	Mat_Face_len_Read: 102,
+	Mat_Face_Set: 103,
+	Mat_Set: 111,
+	Mat_detail: 121,
+	Mat_Set_Texture: 121,
+	Mat_Set_LightTex: 122,
+	Mat_Set_EmissiveTex: 123,
+	Mat_Set_BumpTex: 124,
+	Mat_Set_NormalTex: 125,
+	Mat_Set_EnvTex: 126,
+	Weit_init: 201,
+	Weit_IndexLength: 202,
+	Weit_Read_Index: 203,
+	Weit_Read_Value: 204,
+	Weit_Read_Matrx: 205,
+	Anim_init: 1001,
+	Anim_Reading: 1002,
+	Anim_KeyValueTypeRead: 1003,
+	Anim_KeyValueLength: 1004,
+	Anime_ReadKeyFrame: 1005
 };
 
-var classCallCheck = function (instance, Constructor) {
-  if (!(instance instanceof Constructor)) {
-    throw new TypeError("Cannot call a class as a function");
-  }
+var classCallCheck = function ( instance, Constructor ) {
+
+	if ( ! ( instance instanceof Constructor ) ) {
+
+		throw new TypeError( "Cannot call a class as a function" );
+
+	}
+
 };
 
 var createClass = function () {
-  function defineProperties(target, props) {
-    for (var i = 0; i < props.length; i++) {
-      var descriptor = props[i];
-      descriptor.enumerable = descriptor.enumerable || false;
-      descriptor.configurable = true;
-      if ("value" in descriptor) descriptor.writable = true;
-      Object.defineProperty(target, descriptor.key, descriptor);
-    }
-  }
-
-  return function (Constructor, protoProps, staticProps) {
-    if (protoProps) defineProperties(Constructor.prototype, protoProps);
-    if (staticProps) defineProperties(Constructor, staticProps);
-    return Constructor;
-  };
+
+	function defineProperties( target, props ) {
+
+		for ( var i = 0; i < props.length; i ++ ) {
+
+			var descriptor = props[ i ];
+			descriptor.enumerable = descriptor.enumerable || false;
+			descriptor.configurable = true;
+			if ( "value" in descriptor ) descriptor.writable = true;
+			Object.defineProperty( target, descriptor.key, descriptor );
+
+		}
+
+	}
+
+	return function ( Constructor, protoProps, staticProps ) {
+
+		if ( protoProps ) defineProperties( Constructor.prototype, protoProps );
+		if ( staticProps ) defineProperties( Constructor, staticProps );
+		return Constructor;
+
+	};
+
 }();
 
 var XAnimationObj = function () {
-    function XAnimationObj() {
-        classCallCheck(this, XAnimationObj);
-
-        this.fps = 30;
-        this.name = 'xanimation';
-        this.length = 0;
-        this.hierarchy = [];
-    }
-
-    createClass(XAnimationObj, [{
-        key: 'make',
-        value: function make(XAnimationInfoArray, mesh) {
-            var keys = Object.keys(XAnimationInfoArray);
-            var hierarchy_tmp = [];
-            for (var i = 0; i < keys.length; i++) {
-                var bone = null;
-                var parent = -1;
-                var baseIndex = -1;
-                for (var m = 0; m < mesh.skeleton.bones.length; m++) {
-                    if (mesh.skeleton.bones[m].name == XAnimationInfoArray[keys[i]].boneName) {
-                        bone = XAnimationInfoArray[keys[i]].boneName;
-                        parent = mesh.skeleton.bones[m].parent.name;
-                        baseIndex = m;
-                        break;
-                    }
-                }
-                hierarchy_tmp[baseIndex] = this.makeBonekeys(XAnimationInfoArray[keys[i]], bone, parent);
-            }
-            var keys2 = Object.keys(hierarchy_tmp);
-            for (var _i = 0; _i < keys2.length; _i++) {
-                this.hierarchy.push(hierarchy_tmp[_i]);
-                var parentId = -1;
-                for (var _m = 0; _m < this.hierarchy.length; _m++) {
-                    if (_i != _m && this.hierarchy[_i].parent === this.hierarchy[_m].name) {
-                        parentId = _m;
-                        break;
-                    }
-                }
-                this.hierarchy[_i].parent = parentId;
-            }
-        }
-    }, {
-        key: 'makeBonekeys',
-        value: function makeBonekeys(XAnimationInfo, bone, parent) {
-            var refObj = {};
-            refObj.name = bone;
-            refObj.parent = parent;
-            refObj.keys = [];
-            for (var i = 0; i < XAnimationInfo.keyFrames.length; i++) {
-                var keyframe = {};
-                keyframe.time = XAnimationInfo.keyFrames[i].time * this.fps;
-                keyframe.matrix = XAnimationInfo.keyFrames[i].matrix;
-                keyframe.pos = new THREE.Vector3().setFromMatrixPosition(keyframe.matrix);
-                keyframe.rot = new THREE.Quaternion().setFromRotationMatrix(keyframe.matrix);
-                keyframe.scl = new THREE.Vector3().setFromMatrixScale(keyframe.matrix);
-                refObj.keys.push(keyframe);
-            }
-            return refObj;
-        }
-    }]);
-    return XAnimationObj;
+
+	function XAnimationObj() {
+
+		classCallCheck( this, XAnimationObj );
+
+		this.fps = 30;
+		this.name = 'xanimation';
+		this.length = 0;
+		this.hierarchy = [];
+
+	}
+
+	createClass( XAnimationObj, [ {
+		key: 'make',
+		value: function make( XAnimationInfoArray, mesh ) {
+
+			var keys = Object.keys( XAnimationInfoArray );
+			var hierarchy_tmp = [];
+			for ( var i = 0; i < keys.length; i ++ ) {
+
+				var bone = null;
+				var parent = - 1;
+				var baseIndex = - 1;
+				for ( var m = 0; m < mesh.skeleton.bones.length; m ++ ) {
+
+					if ( mesh.skeleton.bones[ m ].name == XAnimationInfoArray[ keys[ i ] ].boneName ) {
+
+					bone = XAnimationInfoArray[ keys[ i ] ];
+					parent = mesh.skeleton.bones[ m ].parent.name;
+					baseIndex = m;
+					break;
+
+				}
+
+				}
+				hierarchy_tmp[ baseIndex ] = this.makeBonekeys( XAnimationInfoArray[ keys[ i ] ], bone, parent );
+
+			}
+			var keys2 = Object.keys( hierarchy_tmp );
+			for ( var _i = 0; _i < keys2.length; _i ++ ) {
+
+				this.hierarchy.push( hierarchy_tmp[ _i ] );
+				var parentId = - 1;
+				for ( var _m = 0; _m < this.hierarchy.length; _m ++ ) {
+
+					if ( _i != _m && this.hierarchy[ _i ].parent === this.hierarchy[ _m ].name ) {
+
+					parentId = _m;
+					break;
+
+				}
+
+				}
+				this.hierarchy[ _i ].parent = parentId;
+
+			}
+
+		}
+	}, {
+		key: 'makeBonekeys',
+		value: function makeBonekeys( XAnimationInfo, bone, parent ) {
+
+			var refObj = {};
+			refObj.name = bone.boneName;
+			refObj.parent = parent;
+			refObj.keys = [];
+			for ( var i = 0; i < XAnimationInfo.keyFrames.length; i ++ ) {
+
+				var keyframe = {};
+				keyframe.time = XAnimationInfo.keyFrames[ i ].time * this.fps;
+				keyframe.matrix = XAnimationInfo.keyFrames[ i ].matrix;
+				keyframe.pos = new THREE.Vector3().setFromMatrixPosition( keyframe.matrix );
+				keyframe.rot = new THREE.Quaternion().setFromRotationMatrix( keyframe.matrix );
+				keyframe.scl = new THREE.Vector3().setFromMatrixScale( keyframe.matrix );
+				refObj.keys.push( keyframe );
+
+			}
+			return refObj;
+
+		}
+	} ] );
+	return XAnimationObj;
+
 }();
 
 var Xdata = function Xdata() {
-    classCallCheck(this, Xdata);
 
-    this.FrameInfo = [];
-    this.FrameInfo_Raw = [];
-    this.AnimationSetInfo = [];
-    this.AnimTicksPerSecond = 60;
-    this.XAnimationObj = null;
+	classCallCheck( this, Xdata );
+
+	this.FrameInfo = [];
+	this.FrameInfo_Raw = [];
+	this.AnimationSetInfo = [];
+	this.AnimTicksPerSecond = 60;
+	this.XAnimationObj = null;
+
 };
 
 var XboneInf = function XboneInf() {
-    classCallCheck(this, XboneInf);
-
-    this.boneName = "";
-    this.BoneIndex = 0;
-    this.Indeces = [];
-    this.Weights = [];
-    this.initMatrix = null;
-    this.OffsetMatrix = null;
+
+	classCallCheck( this, XboneInf );
+
+	this.boneName = "";
+	this.BoneIndex = 0;
+	this.Indeces = [];
+	this.Weights = [];
+	this.initMatrix = null;
+	this.OffsetMatrix = null;
+
 };
 
 var XAnimationInfo$1 = XAnimationInfo = function XAnimationInfo() {
-    this.animeName = "";
-    this.boneName = "";
-    this.targetBone = null;
-    this.frameStartLv = 0;
-    this.keyFrames = [];
-    this.InverseMx = null;
+
+	this.animeName = "";
+	this.boneName = "";
+	this.targetBone = null;
+	this.frameStartLv = 0;
+	this.keyFrames = [];
+	this.InverseMx = null;
+
 };
 
 var XFrameInfo$1 = XFrameInfo = function XFrameInfo() {
-    this.Mesh = null;
-    this.Geometry = null;
-    this.FrameName = "";
-    this.ParentName = "";
-    this.frameStartLv = 0;
-    this.FrameTransformMatrix = null;
-    this.children = [];
-    this.BoneInfs = [];
-    this.VertexSetedBoneCount = [];
-    this.Materials = [];
+
+	this.Mesh = null;
+	this.Geometry = null;
+	this.FrameName = "";
+	this.ParentName = "";
+	this.frameStartLv = 0;
+	this.FrameTransformMatrix = null;
+	this.children = [];
+	this.BoneInfs = [];
+	this.VertexSetedBoneCount = [];
+	this.Materials = [];
+
 };
 
 var XKeyFrameInfo = function XKeyFrameInfo() {
-    classCallCheck(this, XKeyFrameInfo);
 
-    this.index = 0;
-    this.Frame = 0;
-    this.time = 0.0;
-    this.matrix = null;
+	classCallCheck( this, XKeyFrameInfo );
+
+	this.index = 0;
+	this.Frame = 0;
+	this.time = 0.0;
+	this.matrix = null;
+
 };
 
 THREE.XLoader = function () {
-    function XLoader(manager, Texloader, _zflg) {
-        classCallCheck(this, XLoader);
-
-        this.manager = manager !== undefined ? manager : new THREE.LoadingManager();
-        this.Texloader = Texloader !== undefined ? Texloader : new THREE.TextureLoader();
-        this.zflg = _zflg === undefined ? false : _zflg;
-        this.url = "";
-        this.baseDir = "";
-        this.nowReadMode = XfileLoadMode$1.none;
-        this.nowAnimationKeyType = 4;
-        this.tgtLength = 0;
-        this.nowReaded = 0;
-        this.elementLv = 0;
-        this.geoStartLv = Number.MAX_VALUE;
-        this.frameStartLv = Number.MAX_VALUE;
-        this.matReadLine = 0;
-        this.putMatLength = 0;
-        this.nowMat = null;
-        this.BoneInf = new XboneInf();
-        this.tmpUvArray = [];
-        this.normalVectors = [];
-        this.facesNormal = [];
-        this.nowFrameName = "";
-        this.nowAnimationSetName = "";
-        this.frameHierarchie = [];
-        this.endLineCount = 0;
-        this.geometry = null;
-        this.loadingXdata = null;
-        this.lines = null;
-        this.keyInfo = null;
-        this.animeKeyNames = null;
-        this.data = null;
-        this.onLoad = null;
-    }
-
-    createClass(XLoader, [{
-        key: 'load',
-        value: function load(_arg, onLoad, onProgress, onError) {
-            var _this = this;
-
-            var loader = new THREE.FileLoader(this.manager);
-            loader.setResponseType('arraybuffer');
-            for (var i = 0; i < _arg.length; i++) {
-                switch (i) {
-                    case 0:
-                        this.url = _arg[i];break;
-                    case 1:
-                        this.zflg = _arg[i];break;
-                }
-            }
-            loader.load(this.url, function (response) {
-                _this.parse(response, onLoad);
-            }, onProgress, onError);
-        }
-    }, {
-        key: 'isBinary',
-        value: function isBinary(binData) {
-            var reader = new DataView(binData);
-            var face_size = 32 / 8 * 3 + 32 / 8 * 3 * 3 + 16 / 8;
-            var n_faces = reader.getUint32(80, true);
-            var expect = 80 + 32 / 8 + n_faces * face_size;
-            if (expect === reader.byteLength) {
-                return true;
-            }
-            var fileLength = reader.byteLength;
-            for (var index = 0; index < fileLength; index++) {
-                if (reader.getUint8(index, false) > 127) {
-                    return true;
-                }
-            }
-            return false;
-        }
-    }, {
-        key: 'ensureBinary',
-        value: function ensureBinary(buf) {
-            if (typeof buf === "string") {
-                var array_buffer = new Uint8Array(buf.length);
-                for (var i = 0; i < buf.length; i++) {
-                    array_buffer[i] = buf.charCodeAt(i) & 0xff;
-                }
-                return array_buffer.buffer || array_buffer;
-            } else {
-                return buf;
-            }
-        }
-    }, {
-        key: 'ensureString',
-        value: function ensureString(buf) {
-            if (typeof buf !== "string") {
-                var array_buffer = new Uint8Array(buf);
-                var str = '';
-                for (var i = 0; i < buf.byteLength; i++) {
-                    str += String.fromCharCode(array_buffer[i]);
-                }
-                return str;
-            } else {
-                return buf;
-            }
-        }
-    }, {
-        key: 'parse',
-        value: function parse(data, onLoad) {
-            var binData = this.ensureBinary(data);
-            this.data = this.ensureString(data);
-            this.onLoad = onLoad;
-            return this.isBinary(binData) ? this.parseBinary(binData) : this.parseASCII();
-        }
-    }, {
-        key: 'parseBinary',
-        value: function parseBinary(data) {
-            return parseASCII(String.fromCharCode.apply(null, data));
-        }
-    }, {
-        key: 'parseASCII',
-        value: function parseASCII() {
-            var baseDir = "";
-            if (this.url.lastIndexOf("/") > 0) {
-                this.baseDir = this.url.substr(0, this.url.lastIndexOf("/") + 1);
-            }
-            this.loadingXdata = new Xdata();
-            this.lines = this.data.split("\n");
-            this.mainloop();
-        }
-    }, {
-        key: 'mainloop',
-        value: function mainloop() {
-            var _this2 = this;
-
-            var EndFlg = false;
-            for (var i = 0; i < 100; i++) {
-                this.lineRead(this.lines[this.endLineCount].trim());
-                this.endLineCount++;
-                if (this.endLineCount >= this.lines.length - 1) {
-                    EndFlg = true;
-                    this.readFinalize();
-                    setTimeout(function () {
-                        _this2.animationFinalize();
-                    }, 1);
-                    break;
-                }
-            }
-            if (!EndFlg) {
-                setTimeout(function () {
-                    _this2.mainloop();
-                }, 1);
-            }
-        }
-    }, {
-        key: 'lineRead',
-        value: function lineRead(line) {
-            if (line.indexOf("template ") > -1) {
-                return;
-            }
-            if (line.length === 0) {
-                return;
-            }
-            if (line.indexOf("{") > -1) {
-                this.elementLv++;
-            }
-            if (line.indexOf("AnimTicksPerSecond") > -1) {
-                var findA = line.indexOf("{");
-                this.loadingXdata.AnimTicksPerSecond = parseInt(line.substr(findA + 1, line.indexOf(";") - findA + 1), 10);
-            }
-            if (line.indexOf("}") > -1) {
-                if (this.elementLv < 1 || this.nowFrameName === "") {
-                    this.elementLv = 0;return;
-                }
-                this.endElement();
-                return;
-            }
-            if (line.indexOf("Frame ") > -1) {
-                this.beginFrame(line);
-                return;
-            }
-            if (line.indexOf("FrameTransformMatrix") > -1) {
-                this.nowReadMode = XfileLoadMode$1.FrameTransformMatrix_Read;
-                return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.FrameTransformMatrix_Read) {
-                var data = line.split(",");
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].FrameTransformMatrix = new THREE.Matrix4();
-                this.ParseMatrixData(this.loadingXdata.FrameInfo_Raw[this.nowFrameName].FrameTransformMatrix, data);
-                this.nowReadMode = XfileLoadMode$1.Element;
-                return;
-            }
-            if (line.indexOf("Mesh ") > -1) {
-                this.beginReadMesh(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Vartex_init) {
-                this.readVertexCount(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Vartex_Read) {
-                if (this.readVertex(line)) {
-                    return;
-                }
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Index_init) {
-                this.readIndexLength(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.index_Read) {
-                if (this.readVertexIndex(line)) {
-                    return;
-                }
-            }
-            if (line.indexOf("MeshNormals ") > -1) {
-                this.beginMeshNormal(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Normal_V_init) {
-                this.readMeshNormalCount(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Normal_V_Read) {
-                if (this.readMeshNormalVertex(line)) {
-                    return;
-                }
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Normal_I_init) {
-                this.readMeshNormalIndexCount(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Normal_I_Read) {
-                if (this.readMeshNormalIndex(line)) {
-                    return;
-                }
-            }
-            if (line.indexOf("MeshTextureCoords ") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Uv_init;return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Uv_init) {
-                this.readUvInit(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Uv_Read) {
-                if (this.readUv(line)) {
-                    return;
-                }
-            }
-            if (line.indexOf("MeshMaterialList ") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Mat_Face_init;
-                return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Mat_Face_init) {
-                this.nowReadMode = XfileLoadMode$1.Mat_Face_len_Read;
-                return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Mat_Face_len_Read) {
-                this.readMatrixSetLength(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Mat_Face_Set) {
-                if (this.readMaterialBind(line)) {
-                    return;
-                }
-            }
-            if (line.indexOf("Material ") > -1) {
-                this.readMaterialInit(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Mat_Set) {
-                this.readandSetMaterial(line);return;
-            }
-            if (this.nowReadMode >= XfileLoadMode$1.Mat_Set_Texture && this.nowReadMode < XfileLoadMode$1.Weit_init) {
-                this.readandSetMaterialTexture(line);return;
-            }
-            if (line.indexOf("SkinWeights ") > -1 && this.nowReadMode >= XfileLoadMode$1.Element) {
-                this.readBoneInit(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Weit_init) {
-                this.readBoneName(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Weit_IndexLength) {
-                this.readBoneVertexLength(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Weit_Read_Index) {
-                this.readandSetBoneVertex(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Weit_Read_Value) {
-                this.readandSetBoneWeightValue(line);return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Weit_Read_Matrx) {
-                this.readandSetBoneOffsetMatrixValue(line);return;
-            }
-            if (line.indexOf("AnimationSet ") > -1) {
-                this.readandCreateAnimationSet(line);return;
-            }
-            if (line.indexOf("Animation ") > -1 && this.nowReadMode === XfileLoadMode$1.Anim_init) {
-                this.readAndCreateAnimation(line);return;
-            }
-            if (line.indexOf("AnimationKey ") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Anim_KeyValueTypeRead;return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Anim_KeyValueTypeRead) {
-                this.nowAnimationKeyType = parseInt(line.substr(0, line.length - 1), 10);
-                this.nowReadMode = XfileLoadMode$1.Anim_KeyValueLength;
-                return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Anim_KeyValueLength) {
-                this.tgtLength = parseInt(line.substr(0, line.length - 1), 10);
-                this.nowReaded = 0;
-                this.nowReadMode = XfileLoadMode$1.Anime_ReadKeyFrame;
-                return;
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Anime_ReadKeyFrame) {
-                this.readAnimationKeyFrame(line);return;
-            }
-        }
-    }, {
-        key: 'endElement',
-        value: function endElement(line) {
-            if (this.nowReadMode < XfileLoadMode$1.Anim_init && this.loadingXdata.FrameInfo_Raw[this.nowFrameName].FrameStartLv === this.elementLv && this.nowReadMode > XfileLoadMode$1.none) {
-                if (this.frameHierarchie.length > 0) {
-                    this.loadingXdata.FrameInfo_Raw[this.nowFrameName].children = [];
-                    var keys = Object.keys(this.loadingXdata.FrameInfo_Raw);
-                    for (var m = 0; m < keys.length; m++) {
-                        if (this.loadingXdata.FrameInfo_Raw[keys[m]].ParentName === this.nowFrameName) {
-                            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].children.push(keys[m]);
-                        }
-                    }
-                    this.frameHierarchie.pop();
-                }
-                this.MakeOutputGeometry(this.nowFrameName, this.zflg);
-                this.frameStartLv = this.loadingXdata.FrameInfo_Raw[this.nowFrameName].FrameStartLv;
-                if (this.frameHierarchie.length > 0) {
-                    this.nowFrameName = this.frameHierarchie[this.frameHierarchie.length - 1];
-                    this.frameStartLv = this.loadingXdata.FrameInfo_Raw[this.nowFrameName].FrameStartLv;
-                } else {
-                    this.nowFrameName = "";
-                }
-            }
-            if (this.nowReadMode === XfileLoadMode$1.Mat_Set) {
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Materials.push(this.nowMat);
-                this.nowReadMode = XfileLoadMode$1.Element;
-            }
-            this.elementLv--;
-        }
-    }, {
-        key: 'beginFrame',
-        value: function beginFrame(line) {
-            this.frameStartLv = this.elementLv;
-            this.nowReadMode = XfileLoadMode$1.Element;
-            this.nowFrameName = line.substr(6, line.length - 8);
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName] = new XFrameInfo$1();
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].FrameName = this.nowFrameName;
-            if (this.frameHierarchie.length > 0) {
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].ParentName = this.frameHierarchie[this.frameHierarchie.length - 1];
-            }
-            this.frameHierarchie.push(this.nowFrameName);
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].FrameStartLv = this.frameStartLv;
-        }
-    }, {
-        key: 'beginReadMesh',
-        value: function beginReadMesh(line) {
-            if (this.nowFrameName === "") {
-                this.frameStartLv = this.elementLv;
-                this.nowFrameName = line.substr(5, line.length - 6);
-                if (this.nowFrameName === "") {
-                    this.nowFrameName = "mesh_" + this.loadingXdata.FrameInfo_Raw.length;
-                }
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName] = new XFrameInfo$1();
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].FrameName = this.nowFrameName;
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].FrameStartLv = this.frameStartLv;
-            }
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry = new THREE.Geometry();
-            this.geoStartLv = this.elementLv;
-            this.nowReadMode = XfileLoadMode$1.Vartex_init;
-            Bones = [];
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Materials = [];
-        }
-    }, {
-        key: 'readVertexCount',
-        value: function readVertexCount(line) {
-            this.nowReadMode = XfileLoadMode$1.Vartex_Read;
-            this.tgtLength = parseInt(line.substr(0, line.length - 1), 10);
-            this.nowReaded = 0;
-        }
-    }, {
-        key: 'readVertex',
-        value: function readVertex(line) {
-            var data = line.substr(0, line.length - 2).split(";");
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.vertices.push(new THREE.Vector3(parseFloat(data[0]), parseFloat(data[1]), parseFloat(data[2])));
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.skinIndices.push(new THREE.Vector4(0, 0, 0, 0));
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.skinWeights.push(new THREE.Vector4(1, 0, 0, 0));
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].VertexSetedBoneCount.push(0);
-            this.nowReaded++;
-            if (this.nowReaded >= this.tgtLength) {
-                this.nowReadMode = XfileLoadMode$1.Index_init;
-                return true;
-            }
-            return false;
-        }
-    }, {
-        key: 'readIndexLength',
-        value: function readIndexLength(line) {
-            this.nowReadMode = XfileLoadMode$1.index_Read;
-            this.tgtLength = parseInt(line.substr(0, line.length - 1), 10);
-            this.nowReaded = 0;
-        }
-    }, {
-        key: 'readVertexIndex',
-        value: function readVertexIndex(line) {
-            var data = line.substr(2, line.length - 4).split(",");
-            if (this.zflg) {
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faces.push(new THREE.Face3(parseInt(data[2], 10), parseInt(data[1], 10), parseInt(data[0], 10), new THREE.Vector3(1, 1, 1).normalize()));
-            } else {
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faces.push(new THREE.Face3(parseInt(data[0], 10), parseInt(data[1], 10), parseInt(data[2], 10), new THREE.Vector3(1, 1, 1).normalize()));
-            }
-            this.nowReaded++;
-            if (this.nowReaded >= this.tgtLength) {
-                this.nowReadMode = XfileLoadMode$1.Element;
-                return true;
-            }
-            return false;
-        }
-    }, {
-        key: 'beginMeshNormal',
-        value: function beginMeshNormal(line) {
-            this.nowReadMode = XfileLoadMode$1.Normal_V_init;
-            this.normalVectors = [];
-            this.facesNormal = [];
-        }
-    }, {
-        key: 'readMeshNormalCount',
-        value: function readMeshNormalCount(line) {
-            this.nowReadMode = XfileLoadMode$1.Normal_V_Read;
-            this.tgtLength = parseInt(line.substr(0, line.length - 1), 10);
-            this.nowReaded = 0;
-        }
-    }, {
-        key: 'readMeshNormalVertex',
-        value: function readMeshNormalVertex(line) {
-            var data = line.split(";");
-            this.normalVectors.push([parseFloat(data[0]), parseFloat(data[1]), parseFloat(data[2])]);
-            this.nowReaded++;
-            if (this.nowReaded >= this.tgtLength) {
-                this.nowReadMode = XfileLoadMode$1.Normal_I_init;
-                return true;
-            }
-            return false;
-        }
-    }, {
-        key: 'readMeshNormalIndexCount',
-        value: function readMeshNormalIndexCount(line) {
-            this.nowReadMode = XfileLoadMode$1.Normal_I_Read;
-            this.tgtLength = parseInt(line.substr(0, line.length - 1), 10);
-            this.nowReaded = 0;
-        }
-    }, {
-        key: 'readMeshNormalIndex',
-        value: function readMeshNormalIndex(line) {
-            var data = line.substr(2, line.length - 4).split(",");
-            var nowID = parseInt(data[0], 10);
-            var v1 = new THREE.Vector3(this.normalVectors[nowID][0], this.normalVectors[nowID][1], this.normalVectors[nowID][2]);
-            nowID = parseInt(data[1], 10);
-            var v2 = new THREE.Vector3(this.normalVectors[nowID][0], this.normalVectors[nowID][1], this.normalVectors[nowID][2]);
-            nowID = parseInt(data[2], 10);
-            var v3 = new THREE.Vector3(this.normalVectors[nowID][0], this.normalVectors[nowID][1], this.normalVectors[nowID][2]);
-            if (this.zflg) {
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faces[this.nowReaded].vertexNormals = [v3, v2, v1];
-            } else {
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faces[this.nowReaded].vertexNormals = [v1, v2, v3];
-            }
-            this.facesNormal.push(v1.normalize());
-            this.nowReaded++;
-            if (this.nowReaded >= this.tgtLength) {
-                this.nowReadMode = XfileLoadMode$1.Element;
-                return true;
-            }
-            return false;
-        }
-    }, {
-        key: 'readUvInit',
-        value: function readUvInit(line) {
-            this.nowReadMode = XfileLoadMode$1.Uv_Read;
-            this.tgtLength = parseInt(line.substr(0, line.length - 1), 10);
-            this.nowReaded = 0;
-            this.tmpUvArray = [];
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faceVertexUvs[0] = [];
-        }
-    }, {
-        key: 'readUv',
-        value: function readUv(line) {
-            var data = line.split(";");
-            if (THREE.XLoader.IsUvYReverse) {
-                this.tmpUvArray.push(new THREE.Vector2(parseFloat(data[0]), 1 - parseFloat(data[1])));
-            } else {
-                this.tmpUvArray.push(new THREE.Vector2(parseFloat(data[0]), parseFloat(data[1])));
-            }
-            this.nowReaded++;
-            if (this.nowReaded >= this.tgtLength) {
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faceVertexUvs[0] = [];
-                for (var m = 0; m < this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faces.length; m++) {
-                    this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faceVertexUvs[0][m] = [];
-                    this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faceVertexUvs[0][m].push(this.tmpUvArray[this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faces[m].a]);
-                    this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faceVertexUvs[0][m].push(this.tmpUvArray[this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faces[m].b]);
-                    this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faceVertexUvs[0][m].push(this.tmpUvArray[this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faces[m].c]);
-                }
-                this.nowReadMode = XfileLoadMode$1.Element;
-                this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.uvsNeedUpdate = true;
-                return true;
-            }
-            return false;
-        }
-    }, {
-        key: 'readMatrixSetLength',
-        value: function readMatrixSetLength(line) {
-            this.nowReadMode = XfileLoadMode$1.Mat_Face_Set;
-            this.tgtLength = parseInt(line.substr(0, line.length - 1), 10);
-            this.nowReaded = 0;
-        }
-    }, {
-        key: 'readMaterialBind',
-        value: function readMaterialBind(line) {
-            var data = line.split(",");
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].Geometry.faces[this.nowReaded].materialIndex = parseInt(data[0]);
-            this.nowReaded++;
-            if (this.nowReaded >= this.tgtLength) {
-                this.nowReadMode = XfileLoadMode$1.Element;
-                return true;
-            }
-            return false;
-        }
-    }, {
-        key: 'readMaterialInit',
-        value: function readMaterialInit(line) {
-            this.nowReadMode = XfileLoadMode$1.Mat_Set;
-            this.matReadLine = 0;
-            this.nowMat = new THREE.MeshPhongMaterial({ color: Math.random() * 0xffffff });
-            var matName = line.substr(9, line.length - 10);
-            if (matName !== "") {
-                this.nowMat.name = matName;
-            }
-            if (this.zflg) {
-                this.nowMat.side = THREE.BackSide;
-            } else {
-                this.nowMat.side = THREE.FrontSide;
-            }
-            this.nowMat.side = THREE.FrontSide;
-        }
-    }, {
-        key: 'readandSetMaterial',
-        value: function readandSetMaterial(line) {
-            var data = line.split(";");
-            this.matReadLine++;
-            switch (this.matReadLine) {
-                case 1:
-                    this.nowMat.color.r = data[0];
-                    this.nowMat.color.g = data[1];
-                    this.nowMat.color.b = data[2];
-                    break;
-                case 2:
-                    this.nowMat.shininess = data[0];
-                    break;
-                case 3:
-                    this.nowMat.specular.r = data[0];
-                    this.nowMat.specular.g = data[1];
-                    this.nowMat.specular.b = data[2];
-                    break;
-                case 4:
-                    this.nowMat.emissive.r = data[0];
-                    this.nowMat.emissive.g = data[1];
-                    this.nowMat.emissive.b = data[2];
-                    break;
-            }
-            if (line.indexOf("TextureFilename") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Mat_Set_Texture;
-            } else if (line.indexOf("BumpMapFilename") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Mat_Set_BumpTex;
-                this.nowMat.bumpScale = 0.05;
-            } else if (line.indexOf("NormalMapFilename") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Mat_Set_NormalTex;
-                this.nowMat.normalScale = new THREE.Vector2(2, 2);
-            } else if (line.indexOf("EmissiveMapFilename") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Mat_Set_EmissiveTex;
-            } else if (line.indexOf("LightMapFilename") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Mat_Set_LightTex;
-            }
-        }
-    }, {
-        key: 'readandSetMaterialTexture',
-        value: function readandSetMaterialTexture(line) {
-            var data = line.substr(1, line.length - 3);
-            if (data != undefined && data.length > 0) {
-                switch (this.nowReadMode) {
-                    case XfileLoadMode$1.Mat_Set_Texture:
-                        this.nowMat.map = this.Texloader.load(this.baseDir + data);
-                        break;
-                    case XfileLoadMode$1.Mat_Set_BumpTex:
-                        this.nowMat.bumpMap = this.Texloader.load(this.baseDir + data);
-                        break;
-                    case XfileLoadMode$1.Mat_Set_NormalTex:
-                        this.nowMat.normalMap = this.Texloader.load(this.baseDir + data);
-                        break;
-                    case XfileLoadMode$1.Mat_Set_EmissiveTex:
-                        this.nowMat.emissiveMap = this.Texloader.load(this.baseDir + data);
-                        break;
-                    case XfileLoadMode$1.Mat_Set_LightTex:
-                        this.nowMat.lightMap = this.Texloader.load(this.baseDir + data);
-                        break;
-                    case XfileLoadMode$1.Mat_Set_EnvTex:
-                        this.nowMat.envMap = this.Texloader.load(this.baseDir + data);
-                        break;
-                }
-            }
-            this.nowReadMode = XfileLoadMode$1.Mat_Set;
-            this.endLineCount++;
-            this.elementLv--;
-        }
-    }, {
-        key: 'readBoneInit',
-        value: function readBoneInit(line) {
-            this.nowReadMode = XfileLoadMode$1.Weit_init;
-            this.BoneInf = new XboneInf();
-        }
-    }, {
-        key: 'readBoneName',
-        value: function readBoneName(line) {
-            this.nowReadMode = XfileLoadMode$1.Weit_IndexLength;
-            this.BoneInf.boneName = line.substr(1, line.length - 3);
-            this.BoneInf.BoneIndex = this.loadingXdata.FrameInfo_Raw[this.nowFrameName].BoneInfs.length;
-            this.nowReaded = 0;
-        }
-    }, {
-        key: 'readBoneVertexLength',
-        value: function readBoneVertexLength(line) {
-            this.nowReadMode = XfileLoadMode$1.Weit_Read_Index;
-            this.tgtLength = parseInt(line.substr(0, line.length - 1), 10);
-            this.nowReaded = 0;
-        }
-    }, {
-        key: 'readandSetBoneVertex',
-        value: function readandSetBoneVertex(line) {
-            this.BoneInf.Indeces.push(parseInt(line.substr(0, line.length - 1), 10));
-            this.nowReaded++;
-            if (this.nowReaded >= this.tgtLength || line.indexOf(";") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Weit_Read_Value;
-                this.nowReaded = 0;
-            }
-        }
-    }, {
-        key: 'readandSetBoneWeightValue',
-        value: function readandSetBoneWeightValue(line) {
-            var nowVal = parseFloat(line.substr(0, line.length - 1));
-            this.BoneInf.Weights.push(nowVal);
-            this.nowReaded++;
-            if (this.nowReaded >= this.tgtLength || line.indexOf(";") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Weit_Read_Matrx;
-            }
-        }
-    }, {
-        key: 'readandSetBoneOffsetMatrixValue',
-        value: function readandSetBoneOffsetMatrixValue(line) {
-            var data = line.split(",");
-            this.BoneInf.initMatrix = new THREE.Matrix4();
-            this.ParseMatrixData(this.BoneInf.initMatrix, data);
-            this.BoneInf.OffsetMatrix = new THREE.Matrix4();
-            this.BoneInf.OffsetMatrix.getInverse(this.BoneInf.initMatrix);
-            this.loadingXdata.FrameInfo_Raw[this.nowFrameName].BoneInfs.push(this.BoneInf);
-            this.nowReadMode = XfileLoadMode$1.Element;
-        }
-    }, {
-        key: 'readandCreateAnimationSet',
-        value: function readandCreateAnimationSet(line) {
-            this.frameStartLv = this.elementLv;
-            this.nowReadMode = XfileLoadMode$1.Anim_init;
-            this.nowAnimationSetName = line.substr(13, line.length - 14).trim();
-            this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName] = [];
-        }
-    }, {
-        key: 'readAndCreateAnimation',
-        value: function readAndCreateAnimation(line) {
-            this.nowFrameName = line.substr(10, line.length - 11).trim();
-            this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName][this.nowFrameName] = new XAnimationInfo$1();
-            this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName][this.nowFrameName].animeName = this.nowFrameName;
-            this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName][this.nowFrameName].FrameStartLv = this.frameStartLv;
-            while (true) {
-                this.endLineCount++;
-                line = this.lines[this.endLineCount].trim();
-                if (line.indexOf("{") > -1 && line.indexOf("}") > -1) {
-                    this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName][this.nowFrameName].boneName = line.replace(/{/g, "").replace(/}/g, "").trim();
-                    break;
-                }
-            }
-        }
-    }, {
-        key: 'readAnimationKeyFrame',
-        value: function readAnimationKeyFrame(line) {
-            this.keyInfo = null;
-            var data = line.split(";");
-            var nowKeyframe = parseInt(data[0], 10);
-            var frameFound = false;
-            var tmpM = new THREE.Matrix4();
-            if (this.nowAnimationKeyType != 4) {
-                for (var mm = 0; mm < this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName][this.nowFrameName].keyFrames.length; mm++) {
-                    if (this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName][this.nowFrameName].keyFrames[mm].Frame === nowKeyframe) {
-                        this.keyInfo = this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName][this.nowFrameName].keyFrames[mm];
-                        frameFound = true;
-                        break;
-                    }
-                }
-            }
-            if (!frameFound) {
-                this.keyInfo = new XKeyFrameInfo();
-                this.keyInfo.matrix = new THREE.Matrix4();
-                this.keyInfo.Frame = nowKeyframe;
-            }
-            var data2 = data[2].split(",");
-            switch (this.nowAnimationKeyType) {
-                case 0:
-                    tmpM.makeRotationFromQuaternion(new THREE.Quaternion(parseFloat(data2[0]), parseFloat(data2[1]), parseFloat(data2[2])));
-                    this.keyInfo.matrix.multiply(tmpM);
-                    break;
-                case 1:
-                    tmpM.makeScale(parseFloat(data2[0]), parseFloat(data2[1]), parseFloat(data2[2]));
-                    this.keyInfo.matrix.multiply(tmpM);
-                    break;
-                case 2:
-                    tmpM.makeTranslation(parseFloat(data2[0]), parseFloat(data2[1]), parseFloat(data2[2]));
-                    this.keyInfo.matrix.multiply(tmpM);
-                    break;
-                case 4:
-                    this.ParseMatrixData(this.keyInfo.matrix, data2);
-                    break;
-            }
-            if (!frameFound) {
-                this.keyInfo.index = this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName][this.nowFrameName].keyFrames.length;
-                this.keyInfo.time = /*1.0 / this.loadingXdata.AnimTicksPerSecond * */this.keyInfo.Frame;
-                this.loadingXdata.AnimationSetInfo[this.nowAnimationSetName][this.nowFrameName].keyFrames.push(this.keyInfo);
-            }
-            this.nowReaded++;
-            if (this.nowReaded >= this.tgtLength || line.indexOf(";;;") > -1) {
-                this.nowReadMode = XfileLoadMode$1.Anim_init;
-            }
-        }
-    }, {
-        key: 'readFinalize',
-        value: function readFinalize() {
-            this.loadingXdata.FrameInfo = [];
-            var keys = Object.keys(this.loadingXdata.FrameInfo_Raw);
-            for (var i = 0; i < keys.length; i++) {
-                if (this.loadingXdata.FrameInfo_Raw[keys[i]].Mesh != null) {
-                    this.loadingXdata.FrameInfo.push(this.loadingXdata.FrameInfo_Raw[keys[i]].Mesh);
-                }
-            }
-            if (this.loadingXdata.FrameInfo != null & this.loadingXdata.FrameInfo.length > 0) {
-                for (var _i = 0; _i < this.loadingXdata.FrameInfo.length; _i++) {
-                    if (this.loadingXdata.FrameInfo[_i].parent == null) {
-                        this.loadingXdata.FrameInfo[_i].zflag = this.zflg;
-                        if (this.zflg) {
-                            this.loadingXdata.FrameInfo[_i].scale.set(-1, 1, 1);
-                        }
-                    }
-                }
-            }
-        }
-    }, {
-        key: 'ParseMatrixData',
-        value: function ParseMatrixData(targetMatrix, data) {
-            targetMatrix.set(parseFloat(data[0]), parseFloat(data[4]), parseFloat(data[8]), parseFloat(data[12]), parseFloat(data[1]), parseFloat(data[5]), parseFloat(data[9]), parseFloat(data[13]), parseFloat(data[2]), parseFloat(data[6]), parseFloat(data[10]), parseFloat(data[14]), parseFloat(data[3]), parseFloat(data[7]), parseFloat(data[11]), parseFloat(data[15]));
-        }
-    }, {
-        key: 'MakeOutputGeometry',
-        value: function MakeOutputGeometry(nowFrameName, _zflg) {
-            if (this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry != null) {
-                this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.computeBoundingBox();
-                this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.computeBoundingSphere();
-                this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.verticesNeedUpdate = true;
-                this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.normalsNeedUpdate = true;
-                this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.colorsNeedUpdate = true;
-                this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.uvsNeedUpdate = true;
-                this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.groupsNeedUpdate = true;
-                var putBones = [];
-                var BoneDics = [];
-                var rootBone = new THREE.Bone();
-                if (this.loadingXdata.FrameInfo_Raw[nowFrameName].BoneInfs != null && this.loadingXdata.FrameInfo_Raw[nowFrameName].BoneInfs.length) {
-                    var keys = Object.keys(this.loadingXdata.FrameInfo_Raw);
-                    var BoneDics_Name = [];
-                    for (var m = 0; m < keys.length; m++) {
-                        if (this.loadingXdata.FrameInfo_Raw[keys[m]].FrameStartLv <= this.loadingXdata.FrameInfo_Raw[nowFrameName].FrameStartLv && nowFrameName != keys[m]) {
-                            continue;
-                        }
-                        var b = new THREE.Bone();
-                        b.name = keys[m];
-                        b.applyMatrix(this.loadingXdata.FrameInfo_Raw[keys[m]].FrameTransformMatrix);
-                        b.matrixWorld = b.matrix;
-                        b.FrameTransformMatrix = this.loadingXdata.FrameInfo_Raw[keys[m]].FrameTransformMatrix;
-                        BoneDics_Name[b.name] = putBones.length;
-                        putBones.push(b);
-                    }
-                    for (var _m = 0; _m < putBones.length; _m++) {
-                        for (var dx = 0; dx < this.loadingXdata.FrameInfo_Raw[putBones[_m].name].children.length; dx++) {
-                            var nowBoneIndex = BoneDics_Name[this.loadingXdata.FrameInfo_Raw[putBones[_m].name].children[dx]];
-                            if (putBones[nowBoneIndex] != null) {
-                                putBones[_m].add(putBones[nowBoneIndex]);
-                            }
-                        }
-                    }
-                }
-                var mesh = null;
-                var bufferGeometry = new THREE.BufferGeometry();
-                if (putBones.length > 0) {
-                    if (this.loadingXdata.FrameInfo_Raw[putBones[0].name].children.length === 0 && nowFrameName != putBones[0].name) {
-                        putBones[0].add(putBones[1]);
-                        putBones[0].zflag = _zflg;
-                    }
-                    for (var _m2 = 0; _m2 < putBones.length; _m2++) {
-                        if (putBones[_m2].parent === null) {
-                            putBones[_m2].zflag = _zflg;
-                        }
-                        for (var bi = 0; bi < this.loadingXdata.FrameInfo_Raw[nowFrameName].BoneInfs.length; bi++) {
-                            if (putBones[_m2].name === this.loadingXdata.FrameInfo_Raw[nowFrameName].BoneInfs[bi].boneName) {
-                                for (var vi = 0; vi < this.loadingXdata.FrameInfo_Raw[nowFrameName].BoneInfs[bi].Indeces.length; vi++) {
-                                    var nowVertexID = this.loadingXdata.FrameInfo_Raw[nowFrameName].BoneInfs[bi].Indeces[vi];
-                                    var nowVal = this.loadingXdata.FrameInfo_Raw[nowFrameName].BoneInfs[bi].Weights[vi];
-                                    switch (this.loadingXdata.FrameInfo_Raw[nowFrameName].VertexSetedBoneCount[nowVertexID]) {
-                                        case 0:
-                                            this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.skinIndices[nowVertexID].x = _m2;
-                                            this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.skinWeights[nowVertexID].x = nowVal;
-                                            break;
-                                        case 1:
-                                            this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.skinIndices[nowVertexID].y = _m2;
-                                            this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.skinWeights[nowVertexID].y = nowVal;
-                                            break;
-                                        case 2:
-                                            this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.skinIndices[nowVertexID].z = _m2;
-                                            this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.skinWeights[nowVertexID].z = nowVal;
-                                            break;
-                                        case 3:
-                                            this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.skinIndices[nowVertexID].w = _m2;
-                                            this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry.skinWeights[nowVertexID].w = nowVal;
-                                            break;
-                                    }
-                                    this.loadingXdata.FrameInfo_Raw[nowFrameName].VertexSetedBoneCount[nowVertexID]++;
-                                }
-                            }
-                        }
-                    }
-                    for (var sk = 0; sk < this.loadingXdata.FrameInfo_Raw[nowFrameName].Materials.length; sk++) {
-                        this.loadingXdata.FrameInfo_Raw[nowFrameName].Materials[sk].skinning = true;
-                    }
-                    mesh = new THREE.SkinnedMesh(bufferGeometry.fromGeometry(this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry), new THREE.MultiMaterial(this.loadingXdata.FrameInfo_Raw[nowFrameName].Materials));
-                    var skeleton = new THREE.Skeleton(putBones);
-                    mesh.add(putBones[0]);
-                    mesh.bind(skeleton);
-                } else {
-                    mesh = new THREE.Mesh(bufferGeometry.fromGeometry(this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry), new THREE.MultiMaterial(this.loadingXdata.FrameInfo_Raw[nowFrameName].Materials));
-                }
-                mesh.name = nowFrameName;
-                this.loadingXdata.FrameInfo_Raw[nowFrameName].Mesh = mesh;
-                this.loadingXdata.FrameInfo_Raw[nowFrameName].Geometry = null;
-            }
-        }
-    }, {
-        key: 'animationFinalize',
-        value: function animationFinalize() {
-            this.animeKeyNames = Object.keys(this.loadingXdata.AnimationSetInfo);
-            if (this.animeKeyNames != null && this.animeKeyNames.length > 0) {
-                this.nowReaded = 0;
-                this.loadingXdata.XAnimationObj = [];
-                this.animationFinalize_step();
-            } else {
-                this.finalproc();
-            }
-        }
-    }, {
-        key: 'animationFinalize_step',
-        value: function animationFinalize_step() {
-            var i = this.nowReaded;
-            var keys = Object.keys(this.loadingXdata.FrameInfo_Raw);
-            var tgtModel = null;
-            for (var m = 0; m < this.loadingXdata.FrameInfo.length; m++) {
-                var keys2 = Object.keys(this.loadingXdata.AnimationSetInfo[this.animeKeyNames[i]]);
-                if (this.loadingXdata.AnimationSetInfo[this.animeKeyNames[i]][keys2[0]].boneName == this.loadingXdata.FrameInfo[m].name) {
-                    tgtModel = this.loadingXdata.FrameInfo[m];
-                }
-            }
-            if (tgtModel != null) {
-                this.loadingXdata.XAnimationObj[i] = new XAnimationObj();
-                this.loadingXdata.XAnimationObj[i].fps = this.loadingXdata.AnimTicksPerSecond;
-                this.loadingXdata.XAnimationObj[i].name = this.animeKeyNames[i];
-                this.loadingXdata.XAnimationObj[i].make(this.loadingXdata.AnimationSetInfo[this.animeKeyNames[i]], tgtModel);
-            }
-            this.nowReaded++;
-            if (this.nowReaded >= this.animeKeyNames.length) {
-                this.loadingXdata.AnimationSetInfo = null;
-                this.finalproc();
-            } else {
-                this.animationFinalize_step();
-            }
-        }
-    }, {
-        key: 'finalproc',
-        value: function finalproc() {
-            var _this3 = this;
-
-            setTimeout(function () {
-                _this3.onLoad(_this3.loadingXdata);
-            }, 1);
-        }
-    }]);
-    return XLoader;
+
+	function XLoader( manager, Texloader, _zflg ) {
+
+		classCallCheck( this, XLoader );
+
+		this.manager = manager !== undefined ? manager : new THREE.DefaultLoadingManager();
+		this.Texloader = Texloader !== undefined ? Texloader : new THREE.TextureLoader();
+		this.zflg = _zflg === undefined ? false : _zflg;
+		this.url = "";
+		this.baseDir = "";
+		this.nowReadMode = XfileLoadMode$1.none;
+		this.nowAnimationKeyType = 4;
+		this.tgtLength = 0;
+		this.nowReaded = 0;
+		this.elementLv = 0;
+		this.geoStartLv = Number.MAX_VALUE;
+		this.frameStartLv = Number.MAX_VALUE;
+		this.matReadLine = 0;
+		this.putMatLength = 0;
+		this.nowMat = null;
+		this.BoneInf = new XboneInf();
+		this.tmpUvArray = [];
+		this.normalVectors = [];
+		this.facesNormal = [];
+		this.nowFrameName = "";
+		this.nowAnimationSetName = "";
+		this.frameHierarchie = [];
+		this.endLineCount = 0;
+		this.geometry = null;
+		this.loadingXdata = null;
+		this.lines = null;
+		this.keyInfo = null;
+		this.animeKeyNames = null;
+		this.data = null;
+		this.onLoad = null;
+
+	}
+
+	createClass( XLoader, [ {
+		key: 'load',
+		value: function load( _arg, onLoad, onProgress, onError ) {
+
+			var _this = this;
+
+			var loader = new THREE.FileLoader( this.manager );
+			loader.setResponseType( 'arraybuffer' );
+			for ( var i = 0; i < _arg.length; i ++ ) {
+
+				switch ( i ) {
+
+					case 0:
+						this.url = _arg[ i ]; break;
+					case 1:
+						this.zflg = _arg[ i ]; break;
+
+				}
+
+			}
+			loader.load( this.url, function ( response ) {
+
+				_this.parse( response, onLoad );
+
+			}, onProgress, onError );
+
+		}
+	}, {
+		key: 'isBinary',
+		value: function isBinary( binData ) {
+
+			var reader = new DataView( binData );
+			var face_size = 32 / 8 * 3 + 32 / 8 * 3 * 3 + 16 / 8;
+			var n_faces = reader.getUint32( 80, true );
+			var expect = 80 + 32 / 8 + n_faces * face_size;
+			if ( expect === reader.byteLength ) {
+
+				return true;
+
+			}
+			var fileLength = reader.byteLength;
+			for ( var index = 0; index < fileLength; index ++ ) {
+
+				if ( reader.getUint8( index, false ) > 127 ) {
+
+				return true;
+
+			}
+
+			}
+			return false;
+
+		}
+	}, {
+		key: 'ensureBinary',
+		value: function ensureBinary( buf ) {
+
+			if ( typeof buf === "string" ) {
+
+			var array_buffer = new Uint8Array( buf.length );
+			for ( var i = 0; i < buf.length; i ++ ) {
+
+				array_buffer[ i ] = buf.charCodeAt( i ) & 0xff;
+
+			}
+			return array_buffer.buffer || array_buffer;
+
+		} else {
+
+			return buf;
+
+		}
+
+		}
+	}, {
+		key: 'ensureString',
+		value: function ensureString( buf ) {
+
+		if ( typeof buf !== "string" ) {
+
+			var array_buffer = new Uint8Array( buf );
+			var str = '';
+			for ( var i = 0; i < buf.byteLength; i ++ ) {
+
+				str += String.fromCharCode( array_buffer[ i ] );
+
+			}
+			return str;
+
+		} else {
+
+			return buf;
+
+		}
+
+	}
+	}, {
+	key: 'parse',
+	value: function parse( data, onLoad ) {
+
+		var binData = this.ensureBinary( data );
+		this.data = this.ensureString( data );
+		this.onLoad = onLoad;
+		return this.isBinary( binData ) ? this.parseBinary( binData ) : this.parseASCII();
+
+	}
+}, {
+	key: 'parseBinary',
+	value: function parseBinary( data ) {
+
+		return parseASCII( String.fromCharCode.apply( null, data ) );
+
+	}
+}, {
+	key: 'parseASCII',
+	value: function parseASCII() {
+
+		var baseDir = "";
+		if ( this.url.lastIndexOf( "/" ) > 0 ) {
+
+			this.baseDir = this.url.substr( 0, this.url.lastIndexOf( "/" ) + 1 );
+
+		}
+		this.loadingXdata = new Xdata();
+		this.loadingXdata.vertexNormalFromFile = false;
+		this.loadingXdata.faceNormalFromFile = false;
+		this.lines = this.data;
+		this.readedLength = 0;
+		this.mainloop();
+
+	}
+}, {
+	key: 'mainloop',
+	value: function mainloop() {
+
+		var _this2 = this;
+
+		var EndFlg = false;
+		for ( var i = 0; i < 10; i ++ ) {
+
+			var forceBreak = this.SectionRead();
+			this .endLineCount++;
+			if ( this.readedLength >= this.data.length ) {
+
+				EndFlg = true;
+				this.readFinalize();
+				setTimeout( function () {
+
+					_this2.animationFinalize();
+
+				}, 1 );
+				break;
+
+			}
+			if ( forceBreak ) {
+
+				break;
+
+			}
+
+		}
+		if ( ! EndFlg ) {
+
+			setTimeout( function () {
+
+				_this2.mainloop();
+
+			}, 1 );
+
+		}
+
+	}
+}, {
+	key: 'getNextSection',
+	value: function getNextSection( _offset, _start, _end ) {
+
+		var find = this.data.indexOf( "{", _offset );
+		return [ this.data.substr( _offset, _start - _offset ).trim(), this.data.substr( _start + 1, _end - _start - 1 ) ];
+
+	}
+}, {
+	key: 'getNextSection2',
+	value: function getNextSection2( _obj, _offset, _start, _end ) {
+
+		var find = _obj.indexOf( "{", _offset );
+		return [ _obj.substr( _offset, _start - _offset ).trim(), _obj.substr( _start + 1, _end - _start - 1 ) ];
+
+	}
+}, {
+	key: 'readMeshSection',
+	value: function readMeshSection( _baseOffset ) {
+
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry = new THREE.Geometry();
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Materials = [];
+		var find_2semi = this.data.indexOf( ";;", _baseOffset );
+		var offset = 0;
+		var v_data = this.getVertextDataSection( this.data.substr( _baseOffset, find_2semi - _baseOffset ), 0 );
+		for ( var i = 0; i < v_data[ 0 ].length; i ++ ) {
+
+			this.readVertex( v_data[ 0 ][ i ] );
+
+		}
+		offset = find_2semi + 2;
+		find_2semi = this.data.indexOf( ";;", offset );
+		var v_data2 = this.getVertextDataSection( this.data.substr( offset + 1, find_2semi - offset + 1 ), 0 );
+		for ( var _i = 0; _i < v_data2[ 0 ].length; _i ++ ) {
+
+			this.readVertexIndex( v_data2[ 0 ][ _i ] );
+
+		}
+		this.readedLength = offset + v_data2[ 1 ] + 1;
+
+	}
+}, {
+	key: 'getVertextDataSection',
+	value: function getVertextDataSection( _data, _offset ) {
+
+		var find = _data.indexOf( ";", _offset );
+		var find_2semi = _data.indexOf( ";;", _offset );
+		if ( find_2semi === - 1 ) {
+
+			find_2semi = _data.length - 1;
+
+		}
+		var v_data_base = _data.substr( find + 1, find_2semi - find + 2 );
+		return [ v_data_base.split( ";," ), find_2semi + 2 ];
+
+	}
+}, {
+	key: 'readVertexLines',
+	value: function readVertexLines( _data, find, find2, _readFunc ) {}
+}, {
+	key: 'readMeshMaterialSet',
+	value: function readMeshMaterialSet( _baseOffset ) {
+
+		var find = this.data.indexOf( ";", _baseOffset );
+		find = this.data.indexOf( ";", find + 2 );
+		find2 = this.data.indexOf( ";", find + 2 );
+		var _data = this.data.substr( find + 1, find2 - find + 1 );
+		var v_data = _data.split( "," );
+		for ( var i = 0; i < v_data.length; i ++ ) {
+
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces[ i ].materialIndex = parseInt( v_data[ i ], 10 );
+
+		}
+		this.readedLength = find2 + 1;
+
+	}
+}, {
+	key: 'readMaterial',
+	value: function readMaterial( _dataLine ) {
+
+		this.nowMat = new THREE.MeshPhongMaterial( { color: Math.random() * 0xffffff } );
+		if ( this.zflg ) {
+
+			this.nowMat.side = THREE.BackSide;
+
+		} else {
+
+			this.nowMat.side = THREE.FrontSide;
+
+		}
+		var find = _dataLine.indexOf( ";;" );
+		var _diff = _dataLine.substr( 0, find ).split( ";" );
+		this.nowMat.color.r = parseFloat( _diff[ 0 ] );
+		this.nowMat.color.g = parseFloat( _diff[ 1 ] );
+		this.nowMat.color.b = parseFloat( _diff[ 2 ] );
+		var find2 = _dataLine.indexOf( ";", find + 3 );
+		this.nowMat.shininess = parseFloat( _dataLine.substr( find + 2, find2 - find - 2 ) );
+		find = _dataLine.indexOf( ";;", find2 + 1 );
+		var _specular = _dataLine.substr( find2 + 1, find - find2 ).split( ";" );
+		this.nowMat.specular.r = parseFloat( _specular[ 0 ] );
+		this.nowMat.specular.g = parseFloat( _specular[ 1 ] );
+		this.nowMat.specular.b = parseFloat( _specular[ 2 ] );
+		find2 = _dataLine.indexOf( ";;", find + 2 );
+		var _emissive = _dataLine.substr( find + 2, find2 - find - 2 ).split( ";" );
+		this.nowMat.emissive.r = parseFloat( _emissive[ 0 ] );
+		this.nowMat.emissive.g = parseFloat( _emissive[ 1 ] );
+		this.nowMat.emissive.b = parseFloat( _emissive[ 2 ] );
+
+	}
+}, {
+	key: 'readSkinWeights',
+	value: function readSkinWeights( _data ) {
+
+		this.BoneInf = new XboneInf();
+		var find = _data.indexOf( ";" );
+		this.readBoneName( _data.substr( 0, find - 1 ).replace( '"', '' ) );
+		var find_1 = _data.indexOf( ";", find + 1 ) + 1;
+		var matrixStart = 0;
+		if ( parseInt( _data.substr( find, find_1 - find ), 10 ) === 0 ) {
+
+			matrixStart = find_1 + 1;
+
+		} else {
+
+			var _find = _data.indexOf( ";", find_1 + 1 );
+			var i_data = _data.substr( find_1, _find - find_1 ).split( "," );
+			for ( var i = 0; i < i_data.length; i ++ ) {
+
+				this.BoneInf.Indeces.push( parseInt( i_data[ i ], 10 ) );
+
+			}
+			var find3 = _data.indexOf( ";", _find + 1 );
+			var w_data = _data.substr( _find + 1, find3 - _find ).split( "," );
+			for ( var _i2 = 0; _i2 < w_data.length; _i2 ++ ) {
+
+				this.BoneInf.Weights.push( parseFloat( w_data[ _i2 ] ) );
+
+			}
+			matrixStart = find3 + 1;
+
+		}
+		var find4 = _data.indexOf( ";;", matrixStart + 1 );
+		var m_data = _data.substr( matrixStart, find4 - matrixStart ).split( "," );
+		this.BoneInf.initMatrix = new THREE.Matrix4();
+		this.ParseMatrixData( this.BoneInf.initMatrix, m_data );
+		this.BoneInf.OffsetMatrix = new THREE.Matrix4();
+		this.BoneInf.OffsetMatrix.getInverse( this.BoneInf.initMatrix );
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].BoneInfs.push( this.BoneInf );
+
+	}
+}, {
+	key: 'getPlaneStr',
+	value: function getPlaneStr( _str ) {
+
+		var firstDbl = _str.indexOf( '"' ) + 1;
+		var dbl2 = _str.indexOf( '"', firstDbl );
+		return _str.substr( firstDbl, dbl2 - firstDbl );
+
+	}
+}, {
+	key: 'readAnimationKeyFrame',
+	value: function readAnimationKeyFrame( _data ) {
+
+		var find1 = _data.indexOf( ';' );
+		this.nowAnimationKeyType = parseInt( _data.substr( 0, find1 ), 10 );
+		var find2 = _data.indexOf( ';', find1 + 1 );
+		var lines = _data.substr( find2 + 1 ).split( ';;,' );
+		for ( var i = 0; i < lines.length; i ++ ) {
+
+			this.readAnimationKeyFrameValue( lines[ i ] );
+
+		}
+
+	}
+}, {
+	key: 'SectionRead',
+	value: function SectionRead() {
+
+		var find = this.data.indexOf( "{", this.readedLength );
+		if ( find === - 1 ) {
+
+			this.readedLength = this.data.length; return;
+
+		}
+		var lines = this.data.substr( this.readedLength, find - this.readedLength ).split( /\r\n|\r|\n/ );
+		var line = lines[ 0 ];
+		for ( var i = lines.length - 1; i >= 0; i -- ) {
+
+			if ( lines[ i ].trim().length > 0 && lines[ i ].indexOf( '//' ) < 0 ) {
+
+				line = lines[ i ];
+				break;
+
+			}
+
+		}
+		var find2 = this.data.indexOf( "{", find + 1 );
+		var find3 = this.data.indexOf( "}", find + 1 );
+		var find4 = this.data.indexOf( "}", this.readedLength );
+		if ( find4 < find ) {
+
+			if ( this.elementLv < 1 || this.nowFrameName === "" ) {
+
+				this.elementLv = 0;
+
+			} else {
+
+				this.endElement();
+
+			}
+			this.readedLength = find4 + 1;
+			return false;
+
+		}
+		if ( find3 > find2 ) {
+
+			this .elementLv++;
+			if ( line.indexOf( "Frame " ) > - 1 ) {
+
+				this.beginFrame( line );
+
+			} else if ( line.indexOf( "Mesh " ) > - 1 ) {
+
+				this.readMeshSection( find + 1 );
+				this.nowReadMode = XfileLoadMode$1.Mesh;
+				return true;
+
+			} else if ( line.indexOf( "MeshMaterialList " ) > - 1 ) {
+
+			this.readMeshMaterialSet( find + 1 );
+			this.nowReadMode = XfileLoadMode$1.Mat_Set;
+			return true;
+
+		} else if ( line.indexOf( "Material " ) > - 1 ) {
+
+		var nextSemic = this.data.indexOf( ";;", find + 1 );
+		nextSemic = this.data.indexOf( ";;", nextSemic + 1 );
+		nextSemic = this.data.indexOf( ";;", nextSemic + 1 );
+		this.readMaterial( this.data.substr( find + 1, nextSemic - find + 1 ) );
+		this.readedLength = nextSemic + 2;
+		this.nowReadMode = XfileLoadMode$1.Mat_detail;
+		return true;
+
+	} else if ( line.indexOf( "AnimationSet " ) > - 1 ) {
+
+	this.readandCreateAnimationSet( line );
+	this.nowReadMode = XfileLoadMode$1.Anim_init;
+	this.readedLength = find + 1;
+	return false;
+
+} else if ( line.indexOf( "Animation " ) > - 1 ) {
+
+	this.readAndCreateAnimation( line );
+	this.nowReadMode = XfileLoadMode$1.Anim_Reading;
+	var tgtBoneName = this.data.substr( find2 + 1, find3 - find2 - 1 ).trim();
+	this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ][ this.nowFrameName ].boneName = tgtBoneName;
+	this.readedLength = find3 + 1;
+	return false;
+
+}
+			this.readedLength = find + 1;
+			return false;
+
+		} else {
+
+			var section = this.getNextSection( this.readedLength, find, find3 );
+			this.readedLength = find3 + 1;
+			if ( line.indexOf( "template " ) > - 1 ) {
+
+				this.elementLv = 0;
+				return false;
+
+			} else if ( line.indexOf( "AnimTicksPerSecond" ) > - 1 ) {
+
+				this.loadingXdata.AnimTicksPerSecond = parseInt( section[ 1 ].substr( 0, section[ 1 ].indexOf( ";" ) ), 10 );
+				this.elementLv = 0;
+				return false;
+
+			} else if ( line.indexOf( "FrameTransformMatrix" ) > - 1 ) {
+
+			var data = section[ 1 ].split( "," );
+			data[ 15 ] = data[ 15 ].substr( 0, data[ 15 ].indexOf( ';;' ) );
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].FrameTransformMatrix = new THREE.Matrix4();
+			this.ParseMatrixData( this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].FrameTransformMatrix, data );
+			this.nowReadMode = XfileLoadMode$1.Element;
+			return false;
+
+		} else if ( line.indexOf( "MeshTextureCoords" ) > - 1 ) {
+
+		var v_data = this.getVertextDataSection( section[ 1 ], 0 );
+		for ( var _i3 = 0; _i3 < v_data[ 0 ].length; _i3 ++ ) {
+
+		this.readUv( v_data[ 0 ][ _i3 ] );
+
+	}
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faceVertexUvs[ 0 ] = [];
+		for ( var m = 0; m < this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces.length; m ++ ) {
+
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faceVertexUvs[ 0 ][ m ] = [];
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faceVertexUvs[ 0 ][ m ].push( this.tmpUvArray[ this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces[ m ].a ] );
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faceVertexUvs[ 0 ][ m ].push( this.tmpUvArray[ this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces[ m ].b ] );
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faceVertexUvs[ 0 ][ m ].push( this.tmpUvArray[ this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces[ m ].c ] );
+
+	}
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.uvsNeedUpdate = true;
+		return true;
+
+	} else if ( line.indexOf( "Material " ) > - 1 ) {
+
+	this.readMaterial( section[ 1 ] );
+	this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Materials.push( this.nowMat );
+	return false;
+
+} else if ( line.indexOf( "TextureFilename" ) > - 1 ) {
+
+	if ( section[ 1 ].length > 0 ) {
+
+		this.nowMat.map = this.Texloader.load( this.baseDir + this.getPlaneStr( section[ 1 ] ) );
+
+	}
+	return false;
+
+} else if ( line.indexOf( "BumpMapFilename" ) > - 1 ) {
+
+	if ( section[ 1 ].length > 0 ) {
+
+		this.nowMat.bumpMap = this.Texloader.load( this.baseDir + this.getPlaneStr( section[ 1 ] ) );
+		this.nowMat.bumpScale = 0.05;
+
+	}
+	return false;
+
+} else if ( line.indexOf( "NormalMapFilename" ) > - 1 ) {
+
+	if ( section[ 1 ].length > 0 ) {
+
+		this.nowMat.normalMap = this.Texloader.load( this.baseDir + this.getPlaneStr( section[ 1 ] ) );
+		this.nowMat.normalScale = new THREE.Vector2( 2, 2 );
+
+	}
+	return false;
+
+} else if ( line.indexOf( "EmissiveMapFilename" ) > - 1 ) {
+
+	if ( section[ 1 ].length > 0 ) {
+
+		this.nowMat.emissiveMap = this.Texloader.load( this.baseDir + this.getPlaneStr( section[ 1 ] ) );
+
+	}
+	return false;
+
+} else if ( line.indexOf( "LightMapFilename" ) > - 1 ) {
+
+	if ( section[ 1 ].length > 0 ) {
+
+		this.nowMat.lightMap = this.Texloader.load( this.baseDir + this.getPlaneStr( section[ 1 ] ) );
+
+	}
+	return false;
+
+} else if ( line.indexOf( "XSkinMeshHeader" ) > - 1 ) {
+
+	return false;
+
+} else if ( line.indexOf( "SkinWeights" ) > - 1 ) {
+
+	this.readSkinWeights( section[ 1 ] );
+	return true;
+
+} else if ( line.indexOf( "AnimationKey" ) > - 1 ) {
+
+	this.readAnimationKeyFrame( section[ 1 ] );
+	return true;
+
+}
+
+		}
+		return false;
+
+	}
+}, {
+	key: 'endElement',
+	value: function endElement( line ) {
+
+		if ( this.nowReadMode == XfileLoadMode$1.Mesh ) {
+
+			this.nowReadMode = XfileLoadMode$1.Element;
+
+		} else if ( this.nowReadMode == XfileLoadMode$1.Mat_Set ) {
+
+			this.nowReadMode = XfileLoadMode$1.Mesh;
+
+		} else if ( this.nowReadMode == XfileLoadMode$1.Mat_detail ) {
+
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Materials.push( this.nowMat );
+			this.nowReadMode = XfileLoadMode$1.Mat_Set;
+
+		} else if ( this.nowReadMode == XfileLoadMode$1.Anim_Reading ) {
+
+		this.nowReadMode = XfileLoadMode$1.Anim_init;
+
+	} else if ( this.nowReadMode < XfileLoadMode$1.Anim_init && this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].FrameStartLv === this.elementLv && this.nowReadMode > XfileLoadMode$1.none ) {
+
+	if ( this.frameHierarchie.length > 0 ) {
+
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].children = [];
+		var keys = Object.keys( this.loadingXdata.FrameInfo_Raw );
+		for ( var m = 0; m < keys.length; m ++ ) {
+
+			if ( this.loadingXdata.FrameInfo_Raw[ keys[ m ] ].ParentName === this.nowFrameName ) {
+
+				this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].children.push( keys[ m ] );
+
+			}
+
+		}
+		this.frameHierarchie.pop();
+
+	}
+	this.MakeOutputGeometry( this.nowFrameName, this.zflg );
+	this.frameStartLv = this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].FrameStartLv;
+	if ( this.frameHierarchie.length > 0 ) {
+
+		this.nowFrameName = this.frameHierarchie[ this.frameHierarchie.length - 1 ];
+		this.frameStartLv = this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].FrameStartLv;
+
+	} else {
+
+		this.nowFrameName = "";
+
+	}
+
+} else if ( this.nowReadMode == XfileLoadMode$1.Anim_init ) {
+
+	this.nowReadMode = XfileLoadMode$1.Element;
+
+}
+		this .elementLv--;
+
+	}
+}, {
+	key: 'beginFrame',
+	value: function beginFrame( line ) {
+
+		this.frameStartLv = this.elementLv;
+		this.nowReadMode = XfileLoadMode$1.Element;
+		var findindex = line.indexOf( "Frame " );
+		this.nowFrameName = line.substr( findindex + 6, line.length - findindex + 1 ).trim();
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ] = new XFrameInfo$1();
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].FrameName = this.nowFrameName;
+		if ( this.frameHierarchie.length > 0 ) {
+
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].ParentName = this.frameHierarchie[ this.frameHierarchie.length - 1 ];
+
+		}
+		this.frameHierarchie.push( this.nowFrameName );
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].FrameStartLv = this.frameStartLv;
+
+	}
+}, {
+	key: 'beginReadMesh',
+	value: function beginReadMesh( line ) {
+
+		if ( this.nowFrameName === "" ) {
+
+			this.frameStartLv = this.elementLv;
+			this.nowFrameName = line.substr( 5, line.length - 6 );
+			if ( this.nowFrameName === "" ) {
+
+				this.nowFrameName = "mesh_" + this.loadingXdata.FrameInfo_Raw.length;
+
+			}
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ] = new XFrameInfo$1();
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].FrameName = this.nowFrameName;
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].FrameStartLv = this.frameStartLv;
+
+		}
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry = new THREE.Geometry();
+		this.geoStartLv = this.elementLv;
+		this.nowReadMode = XfileLoadMode$1.Vartex_init;
+		Bones = [];
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Materials = [];
+
+	}
+}, {
+	key: 'readVertexCount',
+	value: function readVertexCount( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.Vartex_Read;
+		this.tgtLength = parseInt( line.substr( 0, line.length - 1 ), 10 );
+		this.nowReaded = 0;
+
+	}
+}, {
+	key: 'readVertex',
+	value: function readVertex( line ) {
+
+		var data = line.substr( 0, line.length - 2 ).split( ";" );
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.vertices.push( new THREE.Vector3( parseFloat( data[ 0 ] ), parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ) ) );
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.skinIndices.push( new THREE.Vector4( 0, 0, 0, 0 ) );
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.skinWeights.push( new THREE.Vector4( 1, 0, 0, 0 ) );
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].VertexSetedBoneCount.push( 0 );
+		this .nowReaded++;
+		return false;
+
+	}
+}, {
+	key: 'readIndexLength',
+	value: function readIndexLength( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.index_Read;
+		this.tgtLength = parseInt( line.substr( 0, line.length - 1 ), 10 );
+		this.nowReaded = 0;
+
+	}
+}, {
+	key: 'readVertexIndex',
+	value: function readVertexIndex( line ) {
+
+		var firstFind = line.indexOf( ';' ) + 1;
+		var data = line.substr( firstFind ).split( "," );
+		if ( this.zflg ) {
+
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces.push( new THREE.Face3( parseInt( data[ 2 ], 10 ), parseInt( data[ 1 ], 10 ), parseInt( data[ 0 ], 10 ), new THREE.Vector3( 1, 1, 1 ).normalize() ) );
+
+		} else {
+
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces.push( new THREE.Face3( parseInt( data[ 0 ], 10 ), parseInt( data[ 1 ], 10 ), parseInt( data[ 2 ], 10 ), new THREE.Vector3( 1, 1, 1 ).normalize() ) );
+
+		}
+		return false;
+
+	}
+}, {
+	key: 'beginMeshNormal',
+	value: function beginMeshNormal( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.Normal_V_init;
+		this.normalVectors = [];
+		this.facesNormal = [];
+
+	}
+}, {
+	key: 'readMeshNormalCount',
+	value: function readMeshNormalCount( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.Normal_V_Read;
+		this.tgtLength = parseInt( line.substr( 0, line.length - 1 ), 10 );
+		this.nowReaded = 0;
+
+	}
+}, {
+	key: 'readMeshNormalVertex',
+	value: function readMeshNormalVertex( line ) {
+
+		var data = line.split( ";" );
+		this.normalVectors.push( [ parseFloat( data[ 0 ] ), parseFloat( data[ 1 ] ), parseFloat( data[ 2 ] ) ] );
+		this .nowReaded++;
+		if ( this.nowReaded >= this.tgtLength ) {
+
+			this.nowReadMode = XfileLoadMode$1.Normal_I_init;
+			return true;
+
+		}
+		return false;
+
+	}
+}, {
+	key: 'readMeshNormalIndexCount',
+	value: function readMeshNormalIndexCount( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.Normal_I_Read;
+		this.tgtLength = parseInt( line.substr( 0, line.length - 1 ), 10 );
+		this.nowReaded = 0;
+
+	}
+}, {
+	key: 'readMeshNormalIndex',
+	value: function readMeshNormalIndex( line ) {
+
+		var data = line.substr( 2, line.length - 4 ).split( "," );
+		var nowID = parseInt( data[ 0 ], 10 );
+		var v1 = new THREE.Vector3( this.normalVectors[ nowID ][ 0 ], this.normalVectors[ nowID ][ 1 ], this.normalVectors[ nowID ][ 2 ] );
+		nowID = parseInt( data[ 1 ], 10 );
+		var v2 = new THREE.Vector3( this.normalVectors[ nowID ][ 0 ], this.normalVectors[ nowID ][ 1 ], this.normalVectors[ nowID ][ 2 ] );
+		nowID = parseInt( data[ 2 ], 10 );
+		var v3 = new THREE.Vector3( this.normalVectors[ nowID ][ 0 ], this.normalVectors[ nowID ][ 1 ], this.normalVectors[ nowID ][ 2 ] );
+		if ( this.zflg ) {
+
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces[ this.nowReaded ].vertexNormals = [ v3, v2, v1 ];
+
+		} else {
+
+			this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces[ this.nowReaded ].vertexNormals = [ v1, v2, v3 ];
+
+		}
+		this.facesNormal.push( v1.normalize() );
+		this .nowReaded++;
+		if ( this.nowReaded >= this.tgtLength ) {
+
+			this.nowReadMode = XfileLoadMode$1.Element;
+			return true;
+
+		}
+		return false;
+
+	}
+}, {
+	key: 'readUvInit',
+	value: function readUvInit( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.Uv_Read;
+		this.tgtLength = parseInt( line.substr( 0, line.length - 1 ), 10 );
+		this.nowReaded = 0;
+		this.tmpUvArray = [];
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faceVertexUvs[ 0 ] = [];
+
+	}
+}, {
+	key: 'readUv',
+	value: function readUv( line ) {
+
+		var data = line.split( ";" );
+		if ( THREE.XLoader.IsUvYReverse ) {
+
+			this.tmpUvArray.push( new THREE.Vector2( parseFloat( data[ 0 ] ), 1 - parseFloat( data[ 1 ] ) ) );
+
+		} else {
+
+			this.tmpUvArray.push( new THREE.Vector2( parseFloat( data[ 0 ] ), parseFloat( data[ 1 ] ) ) );
+
+		}
+		this .nowReaded++;
+		if ( this.nowReaded >= this.tgtLength ) {
+
+			return true;
+
+		}
+		return false;
+
+	}
+}, {
+	key: 'readMatrixSetLength',
+	value: function readMatrixSetLength( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.Mat_Face_Set;
+		this.tgtLength = parseInt( line.substr( 0, line.length - 1 ), 10 );
+		this.nowReaded = 0;
+
+	}
+}, {
+	key: 'readMaterialBind',
+	value: function readMaterialBind( line ) {
+
+		var data = line.split( "," );
+		this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].Geometry.faces[ this.nowReaded ].materialIndex = parseInt( data[ 0 ] );
+		this .nowReaded++;
+		if ( this.nowReaded >= this.tgtLength ) {
+
+			this.nowReadMode = XfileLoadMode$1.Element;
+			return true;
+
+		}
+		return false;
+
+	}
+}, {
+	key: 'readMaterialInit',
+	value: function readMaterialInit( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.Mat_Set;
+		this.matReadLine = 0;
+		this.nowMat = new THREE.MeshPhongMaterial( { color: Math.random() * 0xffffff } );
+		var matName = line.substr( 9, line.length - 10 );
+		if ( matName !== "" ) {
+
+			this.nowMat.name = matName;
+
+		}
+		if ( this.zflg ) {
+
+			this.nowMat.side = THREE.BackSide;
+
+		} else {
+
+			this.nowMat.side = THREE.FrontSide;
+
+		}
+		this.nowMat.side = THREE.FrontSide;
+
+	}
+}, {
+	key: 'readandSetMaterial',
+	value: function readandSetMaterial( line ) {
+
+		var data = line.split( ";" );
+		this .matReadLine++;
+		switch ( this.matReadLine ) {
+
+			case 1:
+				this.nowMat.color.r = data[ 0 ];
+				this.nowMat.color.g = data[ 1 ];
+				this.nowMat.color.b = data[ 2 ];
+				break;
+			case 2:
+				this.nowMat.shininess = data[ 0 ];
+				break;
+			case 3:
+				this.nowMat.specular.r = data[ 0 ];
+				this.nowMat.specular.g = data[ 1 ];
+				this.nowMat.specular.b = data[ 2 ];
+				break;
+			case 4:
+				this.nowMat.emissive.r = data[ 0 ];
+				this.nowMat.emissive.g = data[ 1 ];
+				this.nowMat.emissive.b = data[ 2 ];
+				break;
+
+		}
+		if ( line.indexOf( "TextureFilename" ) > - 1 ) {
+
+			this.nowReadMode = XfileLoadMode$1.Mat_Set_Texture;
+
+		} else if ( line.indexOf( "BumpMapFilename" ) > - 1 ) {
+
+			this.nowReadMode = XfileLoadMode$1.Mat_Set_BumpTex;
+			this.nowMat.bumpScale = 0.05;
+
+		} else if ( line.indexOf( "NormalMapFilename" ) > - 1 ) {
+
+			this.nowReadMode = XfileLoadMode$1.Mat_Set_NormalTex;
+			this.nowMat.normalScale = new THREE.Vector2( 2, 2 );
+
+		} else if ( line.indexOf( "EmissiveMapFilename" ) > - 1 ) {
+
+		this.nowReadMode = XfileLoadMode$1.Mat_Set_EmissiveTex;
+
+	} else if ( line.indexOf( "LightMapFilename" ) > - 1 ) {
+
+	this.nowReadMode = XfileLoadMode$1.Mat_Set_LightTex;
+
+}
+
+	}
+}, {
+	key: 'readandSetMaterialTexture',
+	value: function readandSetMaterialTexture( line ) {
+
+		var data = line.substr( 1, line.length - 3 );
+		if ( data != undefined && data.length > 0 ) {
+
+			switch ( this.nowReadMode ) {
+
+				case XfileLoadMode$1.Mat_Set_Texture:
+					this.nowMat.map = this.Texloader.load( this.baseDir + data );
+					break;
+				case XfileLoadMode$1.Mat_Set_BumpTex:
+					this.nowMat.bumpMap = this.Texloader.load( this.baseDir + data );
+					break;
+				case XfileLoadMode$1.Mat_Set_NormalTex:
+					this.nowMat.normalMap = this.Texloader.load( this.baseDir + data );
+					break;
+				case XfileLoadMode$1.Mat_Set_EmissiveTex:
+					this.nowMat.emissiveMap = this.Texloader.load( this.baseDir + data );
+					break;
+				case XfileLoadMode$1.Mat_Set_LightTex:
+					this.nowMat.lightMap = this.Texloader.load( this.baseDir + data );
+					break;
+				case XfileLoadMode$1.Mat_Set_EnvTex:
+					this.nowMat.envMap = this.Texloader.load( this.baseDir + data );
+					break;
+
+			}
+
+		}
+		this.nowReadMode = XfileLoadMode$1.Mat_Set;
+		this .endLineCount++;
+		this .elementLv--;
+
+	}
+}, {
+	key: 'readBoneInit',
+	value: function readBoneInit( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.Weit_init;
+		this.BoneInf = new XboneInf();
+
+	}
+}, {
+	key: 'readBoneName',
+	value: function readBoneName( line ) {
+
+		this.BoneInf.boneName = line.trim();
+		this.BoneInf.BoneIndex = this.loadingXdata.FrameInfo_Raw[ this.nowFrameName ].BoneInfs.length;
+		this.nowReaded = 0;
+
+	}
+}, {
+	key: 'readBoneVertexLength',
+	value: function readBoneVertexLength( line ) {
+
+		this.nowReadMode = XfileLoadMode$1.Weit_Read_Index;
+		this.tgtLength = parseInt( line.substr( 0, line.length - 1 ), 10 );
+		this.nowReaded = 0;
+
+	}
+}, {
+	key: 'readandSetBoneVertex',
+	value: function readandSetBoneVertex( line ) {
+
+		this.BoneInf.Indeces.push( parseInt( line.substr( 0, line.length - 1 ), 10 ) );
+		this .nowReaded++;
+		if ( this.nowReaded >= this.tgtLength || line.indexOf( ";" ) > - 1 ) {
+
+			this.nowReadMode = XfileLoadMode$1.Weit_Read_Value;
+			this.nowReaded = 0;
+
+		}
+
+	}
+}, {
+	key: 'readandSetBoneWeightValue',
+	value: function readandSetBoneWeightValue( line ) {
+
+		var nowVal = parseFloat( line.substr( 0, line.length - 1 ) );
+		this.BoneInf.Weights.push( nowVal );
+		this .nowReaded++;
+		if ( this.nowReaded >= this.tgtLength || line.indexOf( ";" ) > - 1 ) {
+
+			this.nowReadMode = XfileLoadMode$1.Weit_Read_Matrx;
+
+		}
+
+	}
+}, {
+	key: 'readandCreateAnimationSet',
+	value: function readandCreateAnimationSet( line ) {
+
+		this.frameStartLv = this.elementLv;
+		this.nowReadMode = XfileLoadMode$1.Anim_init;
+		this.nowAnimationSetName = line.substr( 13, line.length - 14 ).trim();
+		this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ] = [];
+
+	}
+}, {
+	key: 'readAndCreateAnimation',
+	value: function readAndCreateAnimation( line ) {
+
+		this.nowFrameName = line.substr( 10, line.length - 11 ).trim();
+		this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ][ this.nowFrameName ] = new XAnimationInfo$1();
+		this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ][ this.nowFrameName ].animeName = this.nowFrameName;
+		this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ][ this.nowFrameName ].FrameStartLv = this.frameStartLv;
+
+	}
+}, {
+	key: 'readAnimationKeyFrameValue',
+	value: function readAnimationKeyFrameValue( line ) {
+
+		this.keyInfo = null;
+		var data = line.split( ";" );
+		if ( data == null || data.length < 3 ) {
+
+			return;
+
+		}
+		var nowKeyframe = parseInt( data[ 0 ], 10 );
+		var frameFound = false;
+		var tmpM = new THREE.Matrix4();
+		if ( this.nowAnimationKeyType != 4 ) {
+
+			for ( var mm = 0; mm < this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ][ this.nowFrameName ].keyFrames.length; mm ++ ) {
+
+				if ( this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ][ this.nowFrameName ].keyFrames[ mm ].Frame === nowKeyframe ) {
+
+					this.keyInfo = this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ][ this.nowFrameName ].keyFrames[ mm ];
+					frameFound = true;
+					break;
+
+				}
+
+			}
+
+		}
+		if ( ! frameFound ) {
+
+			this.keyInfo = new XKeyFrameInfo();
+			this.keyInfo.matrix = new THREE.Matrix4();
+			this.keyInfo.Frame = nowKeyframe;
+
+		}
+		var data2 = data[ 2 ].split( "," );
+		switch ( this.nowAnimationKeyType ) {
+
+			case 0:
+				tmpM.makeRotationFromQuaternion( new THREE.Quaternion( parseFloat( data2[ 0 ] ), parseFloat( data2[ 1 ] ), parseFloat( data2[ 2 ] ), parseFloat( data2[ 3 ] ) ) );
+				this.keyInfo.matrix.multiply( tmpM );
+				break;
+			case 1:
+				tmpM.makeScale( parseFloat( data2[ 0 ] ), parseFloat( data2[ 1 ] ), parseFloat( data2[ 2 ] ) );
+				this.keyInfo.matrix.multiply( tmpM );
+				break;
+			case 2:
+				tmpM.makeTranslation( parseFloat( data2[ 0 ] ), parseFloat( data2[ 1 ] ), parseFloat( data2[ 2 ] ) );
+				this.keyInfo.matrix.multiply( tmpM );
+				break;
+			case 3:
+			case 4:
+				this.ParseMatrixData( this.keyInfo.matrix, data2 );
+				break;
+
+		}
+		if ( ! frameFound ) {
+
+			this.keyInfo.index = this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ][ this.nowFrameName ].keyFrames.length;
+			this.keyInfo.time = /*1.0 / this.loadingXdata.AnimTicksPerSecond * */this.keyInfo.Frame;
+			this.loadingXdata.AnimationSetInfo[ this.nowAnimationSetName ][ this.nowFrameName ].keyFrames.push( this.keyInfo );
+
+		}
+
+	}
+}, {
+	key: 'readFinalize',
+	value: function readFinalize() {
+
+		this.loadingXdata.FrameInfo = [];
+		var keys = Object.keys( this.loadingXdata.FrameInfo_Raw );
+		for ( var i = 0; i < keys.length; i ++ ) {
+
+			if ( this.loadingXdata.FrameInfo_Raw[ keys[ i ] ].Mesh != null ) {
+
+				this.loadingXdata.FrameInfo.push( this.loadingXdata.FrameInfo_Raw[ keys[ i ] ].Mesh );
+
+			}
+
+		}
+		if ( this.loadingXdata.FrameInfo != null & this.loadingXdata.FrameInfo.length > 0 ) {
+
+			for ( var _i4 = 0; _i4 < this.loadingXdata.FrameInfo.length; _i4 ++ ) {
+
+				if ( this.loadingXdata.FrameInfo[ _i4 ].parent == null ) {
+
+					this.loadingXdata.FrameInfo[ _i4 ].zflag = this.zflg;
+					if ( this.zflg ) {
+
+					this.loadingXdata.FrameInfo[ _i4 ].scale.set( - 1, 1, 1 );
+
+				}
+
+				}
+
+			}
+
+		}
+
+	}
+}, {
+	key: 'ParseMatrixData',
+	value: function ParseMatrixData( targetMatrix, data ) {
+
+		targetMatrix.set( parseFloat( data[ 0 ] ), parseFloat( data[ 4 ] ), parseFloat( data[ 8 ] ), parseFloat( data[ 12 ] ), parseFloat( data[ 1 ] ), parseFloat( data[ 5 ] ), parseFloat( data[ 9 ] ), parseFloat( data[ 13 ] ), parseFloat( data[ 2 ] ), parseFloat( data[ 6 ] ), parseFloat( data[ 10 ] ), parseFloat( data[ 14 ] ), parseFloat( data[ 3 ] ), parseFloat( data[ 7 ] ), parseFloat( data[ 11 ] ), parseFloat( data[ 15 ] ) );
+
+	}
+}, {
+	key: 'MakeOutputGeometry',
+	value: function MakeOutputGeometry( nowFrameName, _zflg ) {
+
+		if ( this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry != null ) {
+
+			this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.computeBoundingBox();
+			this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.computeBoundingSphere();
+			if ( ! this.loadingXdata.faceNormalFromFile ) {
+
+				this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.computeFaceNormals();
+
+			}
+			if ( ! this.loadingXdata.vertexNormalFromFile ) {
+
+				this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.computeVertexNormals();
+
+			}
+			this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.verticesNeedUpdate = true;
+			this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.normalsNeedUpdate = true;
+			this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.colorsNeedUpdate = true;
+			this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.uvsNeedUpdate = true;
+			this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.groupsNeedUpdate = true;
+			var putBones = [];
+			var BoneInverse = [];
+			var BoneDics = [];
+			var rootBone = new THREE.Bone();
+			if ( this.loadingXdata.FrameInfo_Raw[ nowFrameName ].BoneInfs != null && this.loadingXdata.FrameInfo_Raw[ nowFrameName ].BoneInfs.length ) {
+
+				var keys = Object.keys( this.loadingXdata.FrameInfo_Raw );
+				var BoneDics_Name = [];
+				for ( var m = 0; m < keys.length; m ++ ) {
+
+					if ( this.loadingXdata.FrameInfo_Raw[ keys[ m ] ].FrameStartLv <= this.loadingXdata.FrameInfo_Raw[ nowFrameName ].FrameStartLv && nowFrameName != keys[ m ] ) {
+
+					continue;
+
+				}
+					var b = new THREE.Bone();
+					b.name = keys[ m ];
+					b.applyMatrix( this.loadingXdata.FrameInfo_Raw[ keys[ m ] ].FrameTransformMatrix );
+					BoneDics_Name[ b.name ] = putBones.length;
+					putBones.push( b );
+					var ivm = new THREE.Matrix4();
+					ivm.getInverse( this.loadingXdata.FrameInfo_Raw[ keys[ m ] ].FrameTransformMatrix );
+					BoneInverse.push( ivm );
+
+				}
+				for ( var _m = 0; _m < putBones.length; _m ++ ) {
+
+					for ( var dx = 0; dx < this.loadingXdata.FrameInfo_Raw[ putBones[ _m ].name ].children.length; dx ++ ) {
+
+					var nowBoneIndex = BoneDics_Name[ this.loadingXdata.FrameInfo_Raw[ putBones[ _m ].name ].children[ dx ] ];
+					if ( putBones[ nowBoneIndex ] != null ) {
+
+					putBones[ _m ].add( putBones[ nowBoneIndex ] );
+
+				}
+
+				}
+
+				}
+
+			}
+			var mesh = null;
+			var bufferGeometry = new THREE.BufferGeometry();
+			if ( putBones.length > 0 ) {
+
+				if ( this.loadingXdata.FrameInfo_Raw[ putBones[ 0 ].name ].children.length === 0 && nowFrameName != putBones[ 0 ].name ) {
+
+					putBones[ 0 ].add( putBones[ 1 ] );
+					putBones[ 0 ].zflag = _zflg;
+
+				}
+				for ( var _m2 = 0; _m2 < putBones.length; _m2 ++ ) {
+
+					if ( putBones[ _m2 ].parent === null ) {
+
+					putBones[ _m2 ].zflag = _zflg;
+
+				}
+					for ( var bi = 0; bi < this.loadingXdata.FrameInfo_Raw[ nowFrameName ].BoneInfs.length; bi ++ ) {
+
+					if ( putBones[ _m2 ].name === this.loadingXdata.FrameInfo_Raw[ nowFrameName ].BoneInfs[ bi ].boneName ) {
+
+					for ( var vi = 0; vi < this.loadingXdata.FrameInfo_Raw[ nowFrameName ].BoneInfs[ bi ].Indeces.length; vi ++ ) {
+
+					var nowVertexID = this.loadingXdata.FrameInfo_Raw[ nowFrameName ].BoneInfs[ bi ].Indeces[ vi ];
+					var nowVal = this.loadingXdata.FrameInfo_Raw[ nowFrameName ].BoneInfs[ bi ].Weights[ vi ];
+					switch ( this.loadingXdata.FrameInfo_Raw[ nowFrameName ].VertexSetedBoneCount[ nowVertexID ] ) {
+
+					case 0:
+						this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.skinIndices[ nowVertexID ].x = _m2;
+						this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.skinWeights[ nowVertexID ].x = nowVal;
+						break;
+					case 1:
+						this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.skinIndices[ nowVertexID ].y = _m2;
+						this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.skinWeights[ nowVertexID ].y = nowVal;
+						break;
+					case 2:
+						this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.skinIndices[ nowVertexID ].z = _m2;
+						this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.skinWeights[ nowVertexID ].z = nowVal;
+						break;
+					case 3:
+						this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.skinIndices[ nowVertexID ].w = _m2;
+						this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry.skinWeights[ nowVertexID ].w = nowVal;
+						break;
+
+				}
+					this .loadingXdata.FrameInfo_Raw[ nowFrameName ].VertexSetedBoneCount[ nowVertexID ]++;
+
+				}
+					break;
+
+				}
+
+				}
+
+				}
+				for ( var sk = 0; sk < this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Materials.length; sk ++ ) {
+
+					this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Materials[ sk ].skinning = true;
+
+				}
+				mesh = new THREE.SkinnedMesh( bufferGeometry.fromGeometry( this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry ), new THREE.MultiMaterial( this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Materials ) );
+				var skeleton = new THREE.Skeleton( putBones /*, BoneInverse*/ );
+				mesh.add( putBones[ 0 ] );
+				mesh.bind( skeleton );
+
+			} else {
+
+				mesh = new THREE.Mesh( bufferGeometry.fromGeometry( this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry ), new THREE.MultiMaterial( this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Materials ) );
+
+			}
+			mesh.name = nowFrameName;
+			this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Mesh = mesh;
+			this.loadingXdata.FrameInfo_Raw[ nowFrameName ].Geometry = null;
+
+		}
+
+	}
+}, {
+	key: 'animationFinalize',
+	value: function animationFinalize() {
+
+		this.animeKeyNames = Object.keys( this.loadingXdata.AnimationSetInfo );
+		if ( this.animeKeyNames != null && this.animeKeyNames.length > 0 ) {
+
+			this.nowReaded = 0;
+			this.loadingXdata.XAnimationObj = [];
+			this.animationFinalize_step();
+
+		} else {
+
+			this.finalproc();
+
+		}
+
+	}
+}, {
+	key: 'animationFinalize_step',
+	value: function animationFinalize_step() {
+
+		var i = this.nowReaded;
+		var keys = Object.keys( this.loadingXdata.FrameInfo_Raw );
+		var tgtModel = null;
+		for ( var m = 0; m < this.loadingXdata.FrameInfo.length; m ++ ) {
+
+			var keys2 = Object.keys( this.loadingXdata.AnimationSetInfo[ this.animeKeyNames[ i ] ] );
+			if ( this.loadingXdata.AnimationSetInfo[ this.animeKeyNames[ i ] ][ keys2[ 0 ] ].boneName == this.loadingXdata.FrameInfo[ m ].name ) {
+
+				tgtModel = this.loadingXdata.FrameInfo[ m ];
+				break;
+
+			}
+
+		}
+		if ( tgtModel != null ) {
+
+			this.loadingXdata.XAnimationObj[ i ] = new XAnimationObj();
+			this.loadingXdata.XAnimationObj[ i ].fps = this.loadingXdata.AnimTicksPerSecond;
+			this.loadingXdata.XAnimationObj[ i ].name = this.animeKeyNames[ i ];
+			this.loadingXdata.XAnimationObj[ i ].make( this.loadingXdata.AnimationSetInfo[ this.animeKeyNames[ i ] ], tgtModel );
+
+		}
+		this .nowReaded++;
+		if ( this.nowReaded >= this.animeKeyNames.length ) {
+
+			this.loadingXdata.AnimationSetInfo = null;
+			this.finalproc();
+
+		} else {
+
+			this.animationFinalize_step();
+
+		}
+
+	}
+}, {
+	key: 'finalproc',
+	value: function finalproc() {
+
+		var _this3 = this;
+
+		setTimeout( function () {
+
+			_this3.onLoad( _this3.loadingXdata );
+
+		}, 1 );
+
+	}
+} ] );
+	return XLoader;
+
 }();
 
 

+ 26 - 4
examples/js/postprocessing/AdaptiveToneMappingPass.js

@@ -54,6 +54,7 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 		uniforms: {
 			"lastLum": { value: null },
 			"currentLum": { value: null },
+			"minLuminance": { value: 0.01 },
 			"delta": { value: 0.016 },
 			"tau": { value: 1.0 }
 		},
@@ -72,6 +73,7 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 
 			"uniform sampler2D lastLum;",
 			"uniform sampler2D currentLum;",
+			"uniform float minLuminance;",
 			"uniform float delta;",
 			"uniform float tau;",
 
@@ -80,8 +82,8 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 				"vec4 lastLum = texture2D( lastLum, vUv, MIP_LEVEL_1X1 );",
 				"vec4 currentLum = texture2D( currentLum, vUv, MIP_LEVEL_1X1 );",
 
-				"float fLastLum = lastLum.r;",
-				"float fCurrentLum = currentLum.r;",
+				"float fLastLum = max( minLuminance, lastLum.r );",
+				"float fCurrentLum = max( minLuminance, currentLum.r );",
 
 				//The adaption seems to work better in extreme lighting differences
 				//if the input luminance is squared.
@@ -90,7 +92,7 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 				// Adapt the luminance using Pattanaik's technique
 				"float fAdaptedLum = fLastLum + (fCurrentLum - fLastLum) * (1.0 - exp(-delta * tau));",
 				// "fAdaptedLum = sqrt(fAdaptedLum);",
-				"gl_FragColor = vec4( vec3( fAdaptedLum ), 1.0 );",
+				"gl_FragColor.r = fAdaptedLum;",
 			"}"
 		].join( '\n' )
 	};
@@ -165,7 +167,16 @@ THREE.AdaptiveToneMappingPass.prototype = Object.assign( Object.create( THREE.Pa
 
 		this.quad.material = this.materialToneMap;
 		this.materialToneMap.uniforms.tDiffuse.value = readBuffer.texture;
-		renderer.render( this.scene, this.camera, writeBuffer, this.clear );
+
+		if ( this.renderToScreen ) {
+
+			renderer.render( this.scene, this.camera );
+
+		} else {
+
+			renderer.render( this.scene, this.camera, writeBuffer, this.clear );
+
+		}
 
 	},
 
@@ -249,6 +260,17 @@ THREE.AdaptiveToneMappingPass.prototype = Object.assign( Object.create( THREE.Pa
 
 	},
 
+	setMinLuminance: function( minLum ) {
+
+		if ( minLum ) {
+
+			this.materialToneMap.uniforms.minLuminance.value = minLum;
+			this.materialAdaptiveLum.uniforms.minLuminance.value = minLum;
+
+		}
+
+	},
+
 	setMaxLuminance: function( maxLum ) {
 
 		if ( maxLum ) {

+ 4 - 2
examples/js/shaders/ToneMapShader.js

@@ -1,7 +1,7 @@
 /**
  * @author miibond
  *
- * Full-screen tone-mapping shader based on http://www.graphics.cornell.edu/~jaf/publications/sig02_paper.pdf
+ * Full-screen tone-mapping shader based on http://www.cis.rit.edu/people/faculty/ferwerda/publications/sig02_paper.pdf
  */
 
 THREE.ToneMapShader = {
@@ -12,6 +12,7 @@ THREE.ToneMapShader = {
 		"averageLuminance":  { value: 1.0 },
 		"luminanceMap":  { value: null },
 		"maxLuminance":  { value: 16.0 },
+		"minLuminance":  { value: 0.01 },
 		"middleGrey":  { value: 0.6 }
 	},
 
@@ -35,6 +36,7 @@ THREE.ToneMapShader = {
 		"varying vec2 vUv;",
 
 		"uniform float middleGrey;",
+		"uniform float minLuminance;",
 		"uniform float maxLuminance;",
 		"#ifdef ADAPTED_LUMINANCE",
 			"uniform sampler2D luminanceMap;",
@@ -56,7 +58,7 @@ THREE.ToneMapShader = {
 			"float fLumPixel = dot(vColor, LUM_CONVERT);",
 
 			// Apply the modified operator (Eq. 4)
-			"float fLumScaled = (fLumPixel * middleGrey) / fLumAvg;",
+			"float fLumScaled = (fLumPixel * middleGrey) / max( minLuminance, fLumAvg );",
 
 			"float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (maxLuminance * maxLuminance)))) / (1.0 + fLumScaled);",
 			"return fLumCompressed * vColor;",

+ 16 - 12
examples/models/json/scene-animation.json

@@ -16,8 +16,6 @@
                 "visible": true,
                 "type": "Mesh",
                 "material": "541CFE3C-B1BD-37FD-8A82-3870870BB8A8",
-                "castShadow": true,
-                "receiveShadow": true,
                 "geometry": "CAEC0410-6CA0-3646-AF22-DE6D5D34C387"
             },{
                 "name": "cylinder002",
@@ -26,8 +24,6 @@
                 "visible": true,
                 "type": "Mesh",
                 "material": "3701AB15-0042-3531-BDFA-EB0FA575D7D5",
-                "castShadow": true,
-                "receiveShadow": true,
                 "geometry": "0AF705E6-E495-351F-944E-8E96CEB82A7B"
             },{
                 "name": "cylinder003",
@@ -36,28 +32,36 @@
                 "visible": true,
                 "type": "Mesh",
                 "material": "D95A0291-848F-32DE-B7CF-F93015785600",
-                "castShadow": true,
-                "receiveShadow": true,
                 "geometry": "84174F78-6B50-3C0D-A3D3-D1203D616F79"
             }]
+        },{
+            "name": "ambientlight",
+            "uuid": "217f2d71-80f0-44cd-9d97-43e5611050a3",
+            "type": "AmbientLight",
+            "color": 5592405
         },{
             "name": "pointlight",
             "uuid": "FCC1C4DA-037A-33FF-97AE-339CD1CB618C",
             "matrix": [-1,0,0,0,0,1,-0,0,0,-0,-1,0,-22.1326,52.6576,-28.8763,1],
-            "visible": true,
             "type": "PointLight",
             "color": 16777215,
-            "intensity": 1,
-            "distance": 0
+            "intensity": 1
         },{
             "name": "pointlight1",
             "uuid": "D9440A28-5F71-3A2A-94B3-954420962156",
             "matrix": [-1,0,0,0,0,1,-0,0,0,-0,-1,0,18.3723,34.5427,79.0829,1],
-            "visible": true,
             "type": "PointLight",
             "color": 16777215,
-            "intensity": 1,
-            "distance": 0
+            "intensity": 1
+        },{
+            "name": "camera",
+            "uuid": "e2b22508-5e7c-4609-8505-d781754ba105",
+            "matrix": [0.70711, 0, 0.70711, 0, 0, 1, 0, 0, -0.70711, 0, 0.70711, 0, -200, 0, 200, 1],
+            "type": "PerspectiveCamera",
+            "fov": 30,
+            "aspect": 1.77778,
+            "near": 1,
+            "far": 10000
         }]
     },
     "images": [],

+ 53 - 85
examples/webgl_animation_scene.html

@@ -33,156 +33,124 @@
 		<div id="container"></div>
 
 		<div id="info">
-		<a href="http://threejs.org" target="_blank">three.js</a> webgl - scene animation - <a href="https://clara.io/view/96106133-2e99-40cf-8abd-64defd153e61">Three Gears Scene</a> courtesy of David Sarno</div>
+		<a href="http://threejs.org" target="_blank">three.js</a> webgl - scene animation - <a href="https://clara.io/view/96106133-2e99-40cf-8abd-64defd153e61">Three Gears Scene</a> courtesy of David Sarno
+		<br><br>camera orbit/zoom/pan with left/middle/right mouse button</div>
 
 		<script src="../build/three.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
 
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 		<script>
 
-			var SCREEN_WIDTH = window.innerWidth;
-			var SCREEN_HEIGHT = window.innerHeight;
-			var FLOOR = -250;
-
-			var container,stats;
-
-			var camera, scene, sceneAnimationClip;
-			var renderer;
-
-			var mesh, helper;
-
-			var mixer;
-
-			var mouseX = 0, mouseY = 0;
-
-			var windowHalfX = window.innerWidth / 2;
-			var windowHalfY = window.innerHeight / 2;
+			var scene, camera, controls, stats;
+			var renderer, mixer;
 
 			var clock = new THREE.Clock();
+			var url = 'models/json/scene-animation.json';
 
-			document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+			var SCREEN_WIDTH = window.innerWidth;
+			var SCREEN_HEIGHT = window.innerHeight;
 
-			init();
-			animate();
+			var container = document.getElementById( 'container' );
 
-			function init() {
 
-				container = document.getElementById( 'container' );
+			stats = new Stats();
+			container.appendChild( stats.dom );
 
-				camera = new THREE.PerspectiveCamera( 30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
-				camera.position.z = 150;
+			renderer = new THREE.WebGLRenderer( { antialias: true } );
+			renderer.setClearColor( 0xffffff );
+			renderer.setPixelRatio( window.devicePixelRatio );
+			renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
+			container.appendChild( renderer.domElement );
 
-				scene = new THREE.Scene();
 
-				scene.fog = new THREE.Fog( 0xffffff, 2000, 10000 );
+			// Load a scene with objects, lights and camera from a JSON file
 
-				//scene.add( camera );
+			new THREE.ObjectLoader().load( url, function ( loadedScene ) {
 
-				// GROUND
+				scene = loadedScene;
 
-				var geometry = new THREE.PlaneBufferGeometry( 16000, 16000 );
-				var material = new THREE.MeshPhongMaterial( { emissive: 0x000000 } );
+				// If the loaded file contains a perspective camera, use it with adjusted aspect ratio...
 
-				var ground = new THREE.Mesh( geometry, material );
-				ground.position.set( 0, FLOOR, 0 );
-				ground.rotation.x = -Math.PI/2;
-				/*scene.add( ground );*/
+				scene.traverse( function ( sceneChild ) {
 
-				ground.receiveShadow = true;
+					if ( sceneChild.type === 'PerspectiveCamera' ) {
 
+						camera = sceneChild;
+						camera.aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
+						camera.updateProjectionMatrix();
 
-				// RENDERER
+					}
 
-				renderer = new THREE.WebGLRenderer( { antialias: true } );
-				renderer.setClearColor( scene.fog.color );
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
-				renderer.domElement.style.position = "relative";
+				} );
 
-				container.appendChild( renderer.domElement );
+				// ... else create a new camera and use it in the loaded scene
 
-				renderer.gammaInput = true;
-				renderer.gammaOutput = true;
+				if ( camera === undefined ) {
 
-				renderer.shadowMap.enabled = true;
+					camera = new THREE.PerspectiveCamera( 30, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
+					camera.position.set( - 200, 0, 200 );
 
+				}
 
-				// STATS
+				controls = new THREE.OrbitControls( camera );
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
+				// Ground plane and fog: examples for applying additional children and new property values to the loaded scene
 
-				//
+				var geometry = new THREE.PlaneBufferGeometry( 20000, 20000 );
+				var material = new THREE.MeshPhongMaterial( { shininess: 0.1 } );
+				var ground = new THREE.Mesh( geometry, material );
 
-				var loader = new THREE.ObjectLoader();
-				loader.load( "models/json/scene-animation.json", function ( loadedScene ) {
+				ground.position.set( 0, - 250, 0 );
+				ground.rotation.x = - Math.PI / 2;
 
-					sceneAnimationClip = loadedScene.animations[0];
-					scene = loadedScene;
-					scene.add( camera );
-					scene.fog = new THREE.Fog( 0xffffff, 2000, 10000 );
+				scene.add( ground );
 
-					mixer = new THREE.AnimationMixer( scene );
+				scene.fog = new THREE.Fog( 0xffffff, 1000, 10000 );
 
-					mixer.clipAction( sceneAnimationClip ).play();
+				// Initialization of the loaded animations
 
-				} );
+				var animationClip = scene.animations[ 0 ];
+				mixer = new THREE.AnimationMixer( scene );
+				mixer.clipAction( animationClip ).play();
 
-				window.addEventListener( 'resize', onWindowResize, false );
+				animate();
 
-			}
+			} );
 
-			function onWindowResize() {
 
-				windowHalfX = window.innerWidth / 2;
-				windowHalfY = window.innerHeight / 2;
+			window.onresize = function () {
 
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.updateProjectionMatrix();
 
 				renderer.setSize( window.innerWidth, window.innerHeight );
 
-			}
-
-
-			function onDocumentMouseMove( event ) {
+			};
 
-				mouseX = ( event.clientX - windowHalfX );
-				mouseY = ( event.clientY - windowHalfY );
-
-			}
-
-			//
 
 			function animate() {
 
 				requestAnimationFrame( animate );
-
 				render();
-				stats.update();
 
 			}
 
+
 			function render() {
 
 				var delta = 0.75 * clock.getDelta();
 
-				camera.position.x += ( mouseX - camera.position.x ) * .05;
-				camera.position.y = THREE.Math.clamp( camera.position.y + ( - mouseY - camera.position.y ) * .05, 0, 1000 );
-
-				camera.lookAt( scene.position );
-
-				if( mixer ) {
-					//console.log( "updating mixer by " + delta );
-					mixer.update( delta );
-				}
+				mixer.update( delta );
+				stats.update();
 
 				renderer.render( scene, camera );
 
 			}
 
+
 		</script>
 
 	</body>

+ 397 - 116
examples/webgl_animation_skinning_blending.html

@@ -10,25 +10,40 @@
 				font-family:Monospace;
 				font-size:13px;
 				text-align:center;
-
 				background-color: #fff;
 				margin: 0px;
 				overflow: hidden;
 			}
-
 			#info {
 				position: absolute;
 				top: 0px; width: 100%;
 				padding: 5px;
 			}
+			a {
+				color: #bbb;
+			}
+			.ac {  /* prevent dat-gui from being selected */
+				-webkit-user-select: none;
+				-moz-user-select: none;
+				-ms-user-select: none;
+				user-select: none;
+			}
+			.no-pointer-events {
+				pointer-events: none;
+			}
+			.control-disabled {
+				color: #888;
+				text-decoration: line-through;
+			}
 		</style>
 	</head>
 	<body>
 		<div id="container"></div>
 		<div id="info">
 			<a href="http://threejs.org" target="_blank">three.js</a> - Skeletal Animation Blending
-			<br><br> Adjust blend weights to affect the animations that are currently playing.
-			<br> Cross fades (and warping) blend between 2 animations and end with a single animation.
+			(model from <a href="http://realitymeltdown.com" target="_blank">realitymeltdown.com</a>)
+			<br><br>camera orbit/zoom/pan with left/middle/right mouse button
+			<br>Note: crossfades are possible with blend weights being set to (1,0,0), (0,1,0) or (0,0,1)
 		</div>
 
 		<script src="../build/three.js"></script>
@@ -36,220 +51,486 @@
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/controls/OrbitControls.js"></script>
-		<script src="js/BlendCharacter.js"></script>
-		<script src="js/BlendCharacterGui.js"></script>
 		<script src="js/libs/dat.gui.min.js"></script>
 
 		<script>
 
 			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
 
-			var container, stats;
+			var container = document.getElementById( 'container' );
+
+			var scene, renderer, camera, controls, stats;
+			var mesh, skeleton, mixer;
+
+			var crossFadeControls = [];
 
-			var blendMesh, helper, camera, scene, renderer, controls;
+			var idleAction, walkAction, runAction;
+			var idleWeight, walkWeight, runWeight;
+			var actions;
+			var settings;
 
 			var clock = new THREE.Clock();
-			var gui = null;
 
-			var isFrameStepping = false;
-			var timeToStep = 0;
+			var singleStepMode = false;
+			var sizeOfNextStep = 0;
 
-			init();
+			var url = 'models/skinned/marine/marine_anims_core.json';
 
-			function init() {
 
-				container = document.getElementById( 'container' );
+			// Initialize stats (fps display)
 
-				scene = new THREE.Scene();
-				scene.add ( new THREE.AmbientLight( 0xffffff ) );
+			stats = new Stats();
+			container.appendChild( stats.dom );
 
-				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
-				renderer.setClearColor( 0x777777 );
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.autoClear = true;
 
-				container.appendChild( renderer.domElement );
+			// Initialize scene, light and renderer
+
+			scene = new THREE.Scene();
+			scene.add( new THREE.AmbientLight( 0xffffff ) );
+
+			renderer = new THREE.WebGLRenderer( { antialias: true } );
+			renderer.setClearColor( 0x333333 );
+			renderer.setPixelRatio( window.devicePixelRatio );
+			renderer.setSize( window.innerWidth, window.innerHeight );
+
+			container.appendChild( renderer.domElement );
+
+
+			// Load skinned mesh
+
+			new THREE.ObjectLoader().load( url, function ( loadedObject ) {
+
+				loadedObject.traverse( function ( child ) {
+
+					if ( child instanceof THREE.SkinnedMesh ) {
+
+						mesh = child;
+
+					}
+
+				} );
+
+				if ( mesh === undefined ) {
+
+					alert( 'Unable to find a SkinnedMesh in this place:\n\n' + url + '\n\n' );
+					return;
+
+				}
+
+
+				// Add mesh and skeleton helper to scene
+
+				mesh.rotation.y = - 135 * Math.PI / 180;
+				scene.add( mesh );
+
+				skeleton = new THREE.SkeletonHelper( mesh );
+				skeleton.visible = false;
+				scene.add( skeleton );
+
+
+				// Initialize camera and camera controls
+
+				var radius = mesh.geometry.boundingSphere.radius;
+
+				var aspect = window.innerWidth / window.innerHeight;
+				camera = new THREE.PerspectiveCamera( 45, aspect, 1, 10000 );
+				camera.position.set( 0.0, radius, radius * 3.5 );
+
+				controls = new THREE.OrbitControls( camera, renderer.domElement );
+				controls.target.set( 0, radius, 0 );
+				controls.update();
+
 
-				//
+				// Create the control panel
 
-				stats = new Stats();
-				container.appendChild( stats.dom );
+				createPanel();
 
-				//
+
+				// Initialize mixer and clip actions
+
+				mixer = new THREE.AnimationMixer( mesh );
+
+				idleAction = mixer.clipAction( 'idle' );
+				walkAction = mixer.clipAction( 'walk' );
+				runAction = mixer.clipAction( 'run' );
+				actions = [ idleAction, walkAction, runAction ];
+
+				activateAllActions();
+
+
+				// Listen on window resizing and start the render loop
 
 				window.addEventListener( 'resize', onWindowResize, false );
+				animate();
 
-				// listen for messages from the gui
-				window.addEventListener( 'start-animation', onStartAnimation );
-				window.addEventListener( 'stop-animation', onStopAnimation );
-				window.addEventListener( 'pause-animation', onPauseAnimation );
-				window.addEventListener( 'step-animation', onStepAnimation );
-				window.addEventListener( 'weight-animation', onWeightAnimation );
-				window.addEventListener( 'crossfade', onCrossfade );
-				window.addEventListener( 'warp', onWarp );
-				window.addEventListener( 'toggle-show-skeleton', onShowSkeleton );
-				window.addEventListener( 'toggle-show-model', onShowModel );
 
-				blendMesh = new THREE.BlendCharacter();
-				blendMesh.load( "models/skinned/marine/marine_anims_core.json", start );
+			} );
+
+
+			function createPanel() {
+
+				var panel = new dat.GUI( { width: 310 } );
+
+				var folder1 = panel.addFolder( 'Visibility' );
+				var folder2 = panel.addFolder( 'Activation/Deactivation' );
+				var folder3 = panel.addFolder( 'Pausing/Stepping' );
+				var folder4 = panel.addFolder( 'Crossfading' );
+				var folder5 = panel.addFolder( 'Blend Weights' );
+				var folder6 = panel.addFolder( 'General Speed' );
+
+				settings = {
+					'show model':            true,
+					'show skeleton':         false,
+					'deactivate all':        deactivateAllActions,
+					'activate all':          activateAllActions,
+					'pause/continue':        pauseContinue,
+					'make single step':      toSingleStepMode,
+					'modify step size':      0.05,
+					'from walk to idle':     function () { prepareCrossFade( walkAction, idleAction, 1.0 ) },
+					'from idle to walk':     function () { prepareCrossFade( idleAction, walkAction, 0.5 ) },
+					'from walk to run':      function () { prepareCrossFade( walkAction, runAction, 2.5 ) },
+					'from run to walk':      function () { prepareCrossFade( runAction, walkAction, 5.0 ) },
+					'use default duration':  true,
+					'set custom duration':   3.5,
+					'modify idle weight':    0.0,
+					'modify walk weight':    1.0,
+					'modify run weight':     0.0,
+					'modify time scale':     1.0
+				};
+
+				folder1.add( settings, 'show model' ).onChange( showModel );
+				folder1.add( settings, 'show skeleton' ).onChange( showSkeleton );
+				folder2.add( settings, 'deactivate all' );
+				folder2.add( settings, 'activate all' );
+				folder3.add( settings, 'pause/continue' );
+				folder3.add( settings, 'make single step' );
+				folder3.add( settings, 'modify step size', 0.01, 0.1, 0.001 );
+				crossFadeControls.push( folder4.add( settings, 'from walk to idle' ) );
+				crossFadeControls.push( folder4.add( settings, 'from idle to walk' ) );
+				crossFadeControls.push( folder4.add( settings, 'from walk to run' ) );
+				crossFadeControls.push( folder4.add( settings, 'from run to walk' ) );
+				folder4.add( settings, 'use default duration' );
+				folder4.add( settings, 'set custom duration', 0, 10, 0.01 );
+				folder5.add( settings, 'modify idle weight', 0.0, 1.0, 0.01 ).listen().onChange( function ( weight ) { setWeight( idleAction, weight ) } );
+				folder5.add( settings, 'modify walk weight', 0.0, 1.0, 0.01 ).listen().onChange( function ( weight ) { setWeight( walkAction, weight ) } );
+				folder5.add( settings, 'modify run weight', 0.0, 1.0, 0.01 ).listen().onChange( function ( weight ) { setWeight( runAction, weight ) } );
+				folder6.add( settings, 'modify time scale', 0.0, 1.5, 0.01 ).onChange( modifyTimeScale );
+
+				folder1.open();
+				folder2.open();
+				folder3.open();
+				folder4.open();
+				folder5.open();
+				folder6.open();
+
+				crossFadeControls.forEach( function ( control ) {
+
+					control.classList1 = control.domElement.parentElement.parentElement.classList;
+					control.classList2 = control.domElement.previousElementSibling.classList;
+
+					control.setDisabled = function () {
+
+						control.classList1.add( 'no-pointer-events' );
+						control.classList2.add( 'control-disabled' );
+
+					};
+
+					control.setEnabled = function () {
+
+						control.classList1.remove( 'no-pointer-events' );
+						control.classList2.remove( 'control-disabled' );
+
+					};
+
+				} );
 
 			}
 
-			function onWindowResize() {
 
-				camera.aspect = window.innerWidth / window.innerHeight;
-				camera.updateProjectionMatrix();
+			function showModel( visibility ) {
+
+				mesh.visible = visibility;
+
+			}
+
+
+			function showSkeleton( visibility ) {
+
+				skeleton.visible = visibility;
+
+			}
 
-				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			function modifyTimeScale( speed ) {
+
+				mixer.timeScale = speed;
+
+			}
+
+
+			function deactivateAllActions() {
+
+				actions.forEach( function ( action ) {
+
+					action.stop();
+
+				} );
 
 			}
 
-			function onStartAnimation( event ) {
 
-				var data = event.detail;
+			function activateAllActions() {
+
+				setWeight( idleAction, settings[ 'modify idle weight' ] );
+				setWeight( walkAction, settings[ 'modify walk weight' ] );
+				setWeight( runAction, settings[ 'modify run weight' ] );
+
+				actions.forEach( function ( action ) {
+
+					action.play();
+
+				} );
+
+			}
+
+
+			function pauseContinue() {
+
+				if ( singleStepMode ) {
+
+					singleStepMode = false;
+					unPauseAllActions();
 
-				blendMesh.stopAll();
-				blendMesh.unPauseAll();
+				} else {
 
-				// the blend mesh will combine 1 or more animations
-				for ( var i = 0; i < data.anims.length; ++i ) {
+					if ( idleAction.paused ) {
 
-					blendMesh.play(data.anims[i], data.weights[i]);
+						unPauseAllActions();
+
+					} else {
+
+						pauseAllActions();
+
+					}
 
 				}
 
-				isFrameStepping = false;
+			}
+
+
+			function pauseAllActions() {
+
+				actions.forEach( function ( action ) {
+
+					action.paused = true;
+
+				} );
 
 			}
 
-			function onStopAnimation( event ) {
 
-				blendMesh.stopAll();
-				isFrameStepping = false;
+			function unPauseAllActions() {
+
+				actions.forEach( function ( action ) {
+
+					action.paused = false;
+
+				} );
 
 			}
 
-			function onPauseAnimation( event ) {
 
-				( isFrameStepping ) ? blendMesh.unPauseAll(): blendMesh.pauseAll();
+			function toSingleStepMode() {
+
+				unPauseAllActions();
 
-				isFrameStepping = false;
+				singleStepMode = true;
+				sizeOfNextStep = settings[ 'modify step size' ];
 
 			}
 
-			function onStepAnimation( event ) {
 
-				blendMesh.unPauseAll();
-				isFrameStepping = true;
-				timeToStep = event.detail.stepSize;
+			function prepareCrossFade( startAction, endAction, defaultDuration ) {
+
+				// Switch default / custom crossfade duration (according to the user's choice)
+
+				var duration = setCrossFadeDuration( defaultDuration );
+
+				// Make sure that we don't go on in singleStepMode, and that all actions are unpaused
+
+				singleStepMode = false;
+				unPauseAllActions();
+
+				// If the current action is 'idle' (duration 4 sec), execute the crossfade immediately;
+				// else wait until the current action has finished its current loop
+
+				if ( startAction === idleAction ) {
+
+					executeCrossFade( startAction, endAction, duration );
+
+				} else {
+
+					synchronizeCrossFade( startAction, endAction, duration );
+
+				}
+
 			}
 
-			function onWeightAnimation(event) {
 
-				var data = event.detail;
-				for ( var i = 0; i < data.anims.length; ++i ) {
+			function setCrossFadeDuration( defaultDuration ) {
+
+				// Switch default crossfade duration <-> custom crossfade duration
+
+				if ( settings[ 'use default duration' ] ) {
+
+					return defaultDuration;
+
+				} else {
 
-					blendMesh.applyWeight( data.anims[ i ], data.weights[ i ] );
+					return settings[ 'set custom duration' ];
 
 				}
 
 			}
 
-			function onCrossfade(event) {
 
-				var data = event.detail;
+			function synchronizeCrossFade( startAction, endAction, duration ) {
 
-				blendMesh.stopAll();
-				blendMesh.crossfade( data.from, data.to, data.time );
+				mixer.addEventListener( 'loop', onLoopFinished );
 
-				isFrameStepping = false;
+				function onLoopFinished( event ) {
+
+					if ( event.action === startAction ) {
+
+						mixer.removeEventListener( 'loop', onLoopFinished );
+
+						executeCrossFade( startAction, endAction, duration );
+
+					}
+
+				}
 
 			}
 
-			function onWarp( event ) {
 
-				var data = event.detail;
+			function executeCrossFade( startAction, endAction, duration ) {
+
+				// Not only the start action, but also the end action must get a weight of 1 before fading
+				// (concerning the start action this is already guaranteed in this place)
 
-				blendMesh.stopAll();
-				blendMesh.warp( data.from, data.to, data.time );
+				setWeight( endAction, 1 );
+				endAction.time = 0;
 
-				isFrameStepping = false;
+				// Crossfade with warping - you can also try without warping by setting the third parameter to false
+
+				startAction.crossFadeTo( endAction, duration, true );
 
 			}
 
-			function onShowSkeleton( event ) {
 
-				var shouldShow = event.detail.shouldShow;
-				helper.visible = shouldShow;
+			// This function is needed, since animationAction.crossFadeTo() disables its start action and sets
+			// the start action's timeScale to ((start animation's duration) / (end animation's duration))
+
+			function setWeight( action, weight ) {
+
+				action.enabled = true;
+				action.setEffectiveTimeScale( 1 );
+				action.setEffectiveWeight( weight );
 
 			}
 
-			function onShowModel( event ) {
 
-				var shouldShow = event.detail.shouldShow;
-				blendMesh.showModel( shouldShow );
+			// Called by the render loop
+
+			function updateWeightSliders() {
+
+				settings[ 'modify idle weight' ] = idleWeight;
+				settings[ 'modify walk weight' ] = walkWeight;
+				settings[ 'modify run weight' ] = runWeight;
 
 			}
 
-			function start() {
 
-				blendMesh.rotation.y = Math.PI * -135 / 180;
-				scene.add( blendMesh );
+			// Called by the render loop
 
-				var aspect = window.innerWidth / window.innerHeight;
-				var radius = blendMesh.geometry.boundingSphere.radius;
+			function updateCrossFadeControls() {
 
-				camera = new THREE.PerspectiveCamera( 45, aspect, 1, 10000 );
-				camera.position.set( 0.0, radius, radius * 3.5 );
+				crossFadeControls.forEach( function ( control ) {
 
-				controls = new THREE.OrbitControls( camera );
-				controls.target.set( 0, radius, 0 );
-				controls.update();
+					control.setDisabled();
 
-				// Set default weights
-				blendMesh.applyWeight( 'idle', 1 / 3 );
-				blendMesh.applyWeight( 'walk', 1 / 3 );
-				blendMesh.applyWeight( 'run', 1 / 3 );
+				} );
 
-				gui = new BlendCharacterGui(blendMesh);
+				if ( idleWeight === 1 && walkWeight === 0 && runWeight === 0 ) {
 
-				// Create the debug visualization
+					crossFadeControls[ 1 ].setEnabled();
 
-				helper = new THREE.SkeletonHelper( blendMesh );
-				helper.material.linewidth = 3;
-				scene.add( helper );
+				}
 
-				helper.visible = false;
+				if ( idleWeight === 0 && walkWeight === 1 && runWeight === 0 ) {
+
+					crossFadeControls[ 0 ].setEnabled();
+					crossFadeControls[ 2 ].setEnabled();
+
+				}
+
+				if ( idleWeight === 0 && walkWeight === 0 && runWeight === 1 ) {
+
+					crossFadeControls[ 3 ].setEnabled();
+
+				}
+
+			}
+
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
 
-				animate();
 			}
 
+
 			function animate() {
 
-				requestAnimationFrame( animate, renderer.domElement );
+				// Render loop
 
-				stats.begin();
+				requestAnimationFrame( animate );
 
-				// step forward in time based on whether we're stepping and scale
+				idleWeight = idleAction.getEffectiveWeight();
+				walkWeight = walkAction.getEffectiveWeight();
+				runWeight = runAction.getEffectiveWeight();
 
-				var scale = gui.getTimeScale();
-				var delta = clock.getDelta();
-				var stepSize = (!isFrameStepping) ? delta * scale: timeToStep;
+				// Update the panel values if weights are modified from "outside" (by crossfadings)
 
-				// modify blend weights
+				updateWeightSliders();
 
-				blendMesh.update( stepSize );
-				helper.update();
-				gui.update( blendMesh.mixer.time );
+				// Enable/disable crossfade controls according to current weight values
 
-				renderer.render( scene, camera );
-				stats.end();
+				updateCrossFadeControls();
 
-				// if we are stepping, consume time
-				// ( will equal step size next time a single step is desired )
+				// Get the time elapsed since the last frame, used for mixer update (if not in single step mode)
 
-				timeToStep = 0;
+				var mixerUpdateDelta = clock.getDelta();
+
+				// If in single step mode, make one step and then do nothing (until the user clicks again)
+
+				if ( singleStepMode ) {
+
+					mixerUpdateDelta = sizeOfNextStep;
+					sizeOfNextStep = 0;
+
+				}
+
+				// Update the animation mixer, the skeleton and the stats panel, and render this frame
+
+				mixer.update( mixerUpdateDelta );
+				skeleton.update();
+				stats.update();
+
+				renderer.render( scene, camera );
 
 			}
 

+ 340 - 0
examples/webgl_buffergeometry_instancing2.html

@@ -0,0 +1,340 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+	<title>three.js webgl - instancing test</title>
+	<meta charset="utf-8">
+	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+	<style>
+		body {
+			color: #ffffff;
+			font-family: Monospace;
+			font-size: 13px;
+			text-align: center;
+			font-weight: bold;
+			background-color: #000000;
+			margin: 0px;
+			overflow: hidden;
+		}
+
+		#info {
+			position: absolute;
+			top: 0px;
+			width: 100%;
+			padding: 5px;
+		}
+
+		a {
+			color: #ffffff;
+		}
+
+		#oldie a {
+			color: #da0;
+		}
+
+		#notSupported {
+			width: 50%;
+			margin: auto;
+			border: 2px red solid;
+			margin-top: 20px;
+			padding: 10px;
+		}
+	</style>
+</head>
+<body>
+
+	<div id="container"></div>
+	<div id="info">
+		<a href="http://threejs.org" target="_blank">three.js</a> - instancing demo
+		<div id="notSupported" style="display:none">Sorry your graphics card + browser does not support hardware instancing</div>
+	</div>
+
+	<script src="js/libs/dat.gui.min.js"></script>
+	<script src="../build/three.js"></script>
+	<script src="js/Detector.js"></script>
+	<script src="js/libs/stats.min.js"></script>
+
+	<script src="js/controls/TrackballControls.js"></script>
+
+	<script id="vertexShader" type="x-shader/x-vertex">
+		precision highp float;
+
+		attribute vec3 instancePosition;
+		attribute vec4 instanceQuaternion;
+		attribute vec3 instanceScale;
+
+		vec3 applyTRS( vec3 position, vec3 translation, vec4 quaternion, vec3 scale ) {
+
+			position *= scale;
+			position += 2.0 * cross( quaternion.xyz, cross( quaternion.xyz, position ) + quaternion.w * position );
+			return position + translation;
+
+		}
+
+		attribute vec3 color;
+		varying vec3 vColor;
+
+		void main(){
+
+			vColor = color;
+
+			vec3 transformed = applyTRS( position.xyz, instancePosition, instanceQuaternion, instanceScale );
+
+			gl_Position = projectionMatrix * modelViewMatrix * vec4( transformed, 1.0 );
+
+		}
+
+	</script>
+
+	<script id="fragmentShader" type="x-shader/x-fragment">
+
+		precision highp float;
+		varying vec3 vColor;
+
+		void main() {
+
+			gl_FragColor = vec4( vColor, 1.0 );
+
+		}
+
+	</script>
+
+	<script>
+
+		if ( !Detector.webgl ) Detector.addGetWebGLMessage();
+
+		var container, stats;
+
+		var camera, scene, renderer;
+
+		var controls;
+
+		init();
+		animate();
+
+		function init() {
+
+			container = document.getElementById( 'container' );
+
+			camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.01, 100 );
+			camera.position.z = 4;
+
+			controls = new THREE.TrackballControls( camera );
+
+			scene = new THREE.Scene();
+
+			//
+
+			// var geometry = new THREE.BoxBufferGeometry( 0.01, 0.01, 0.01 );
+			var geometry = new THREE.IcosahedronBufferGeometry( 0.1, 1 );
+
+			var colors = [];
+
+			for ( var i = 0, l = geometry.attributes.position.count; i < l; i ++ ) {
+
+				colors.push( Math.random(), Math.random(), Math.random() );
+
+			}
+
+			geometry.addAttribute( 'color', new THREE.Float32BufferAttribute( colors, 3 ) );
+
+			var material = new THREE.MeshBasicMaterial( { color: 0xff0000, vertexColors: THREE.VertexColors } );
+
+			var mesh = new THREE.Mesh( geometry, material );
+			// scene.add( mesh );
+
+			//
+
+			var INSTANCE_COUNT = 100;
+
+			var geometry2 = new THREE.InstancedBufferGeometry().copy( geometry );
+
+			var instancePositions = [];
+			var instanceQuaternions = [];
+			var instanceScales = [];
+
+			// var position = new THREE.Vector3();
+			// var quaternion = new THREE.Quaternion();
+
+			for ( var i = 0; i < INSTANCE_COUNT; i ++ ) {
+
+				var mesh = new THREE.Mesh( geometry, material );
+				scene.add( mesh );
+
+				var position = mesh.position;
+				var quaternion = mesh.quaternion;
+				var scale = mesh.scale;
+
+				position.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
+
+				quaternion.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
+				quaternion.normalize();
+
+				scale.set( Math.random() * 2, Math.random() * 2, Math.random() * 2 );
+
+				instancePositions.push( position.x, position.y, position.z );
+				instanceQuaternions.push( quaternion.x, quaternion.y, quaternion.z, quaternion.w );
+				instanceScales.push( scale.x, scale.y, scale.z );
+
+			}
+
+			var attribute = new THREE.InstancedBufferAttribute( new Float32Array( instancePositions ), 3 );
+			geometry2.addAttribute( 'instancePosition', attribute );
+
+			var attribute = new THREE.InstancedBufferAttribute( new Float32Array( instanceQuaternions ), 4 );
+			geometry2.addAttribute( 'instanceQuaternion', attribute );
+
+			var attribute = new THREE.InstancedBufferAttribute( new Float32Array( instanceScales ), 3 );
+			geometry2.addAttribute( 'instanceScale', attribute );
+
+			var material = new THREE.ShaderMaterial( {
+
+				uniforms: {},
+				vertexShader: document.getElementById( 'vertexShader' ).textContent,
+				fragmentShader: document.getElementById( 'fragmentShader' ).textContent
+
+			} );
+
+			var mesh2 = new THREE.Mesh( geometry2, material );
+			mesh2.position.x = 0.1;
+			scene.add( mesh2 );
+
+
+			/*
+			// geometry
+
+			var triangles = 1;
+			var instances = 65000;
+
+			var geometry = new THREE.InstancedBufferGeometry();
+
+			geometry.maxInstancedCount = instances; // set so its initalized for dat.GUI, will be set in first draw otherwise
+			var gui = new dat.GUI();
+			gui.add( geometry, "maxInstancedCount", 0, instances );
+
+			var vertices = new THREE.BufferAttribute( new Float32Array( triangles * 3 * 3 ), 3 );
+
+			vertices.setXYZ( 0, 0.025, -0.025, 0 );
+			vertices.setXYZ( 1, -0.025, 0.025, 0 );
+			vertices.setXYZ( 2, 0, 0, 0.025 );
+
+			geometry.addAttribute( 'position', vertices );
+
+			var offsets = new THREE.InstancedBufferAttribute( new Float32Array( instances * 3 ), 3, 1 );
+
+			for ( var i = 0, ul = offsets.count; i < ul; i++ ) {
+
+				offsets.setXYZ( i, Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5 );
+
+			}
+
+			geometry.addAttribute( 'offset', offsets );
+
+			var colors = new THREE.InstancedBufferAttribute( new Float32Array( instances * 4 ), 4, 1 );
+
+			for ( var i = 0, ul = colors.count; i < ul; i++ ) {
+
+				colors.setXYZW( i, Math.random(), Math.random(), Math.random(), Math.random() );
+
+			}
+
+			geometry.addAttribute( 'color', colors );
+
+			var vector = new THREE.Vector4();
+
+			var orientationsStart = new THREE.InstancedBufferAttribute( new Float32Array( instances * 4 ), 4, 1 );
+
+			for ( var i = 0, ul = orientationsStart.count; i < ul; i++ ) {
+
+				vector.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
+				vector.normalize();
+
+				orientationsStart.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
+
+			}
+
+			geometry.addAttribute( 'orientationStart', orientationsStart );
+
+			var orientationsEnd = new THREE.InstancedBufferAttribute( new Float32Array( instances * 4 ), 4, 1 );
+
+			for ( var i = 0, ul = orientationsEnd.count; i < ul; i++ ) {
+
+				vector.set( Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1, Math.random() * 2 - 1 );
+				vector.normalize();
+
+				orientationsEnd.setXYZW( i, vector.x, vector.y, vector.z, vector.w );
+
+			}
+
+			geometry.addAttribute( 'orientationEnd', orientationsEnd );
+
+			// material
+
+			var material = new THREE.RawShaderMaterial( {
+
+				uniforms: {
+					time: { value: 1.0 },
+					sineTime: { value: 1.0 }
+				},
+				vertexShader: document.getElementById( 'vertexShader' ).textContent,
+				fragmentShader: document.getElementById( 'fragmentShader' ).textContent,
+				side: THREE.DoubleSide,
+				transparent: true
+
+			} );
+
+			var mesh = new THREE.Mesh( geometry, material );
+			scene.add( mesh );
+			*/
+
+			renderer = new THREE.WebGLRenderer();
+
+			if ( renderer.extensions.get( 'ANGLE_instanced_arrays' ) === false ) {
+				document.getElementById( "notSupported" ).style.display = "";
+				return;
+			}
+
+			renderer.setClearColor( 0x101010 );
+			renderer.setPixelRatio( window.devicePixelRatio );
+			renderer.setSize( window.innerWidth, window.innerHeight );
+			container.appendChild( renderer.domElement );
+
+			stats = new Stats();
+			container.appendChild( stats.dom );
+
+			window.addEventListener( 'resize', onWindowResize, false );
+
+		}
+
+		function onWindowResize( event ) {
+
+			camera.aspect = window.innerWidth / window.innerHeight;
+			camera.updateProjectionMatrix();
+
+			renderer.setSize( window.innerWidth, window.innerHeight );
+
+		}
+
+		//
+
+		function animate() {
+
+			requestAnimationFrame( animate );
+
+			render();
+			stats.update();
+
+		}
+
+		function render() {
+
+			controls.update();
+
+			renderer.render( scene, camera );
+
+		}
+
+	</script>
+
+</body>
+
+</html>

+ 1 - 4
examples/webgl_geometry_spline_editor.html

@@ -98,12 +98,9 @@
 				scene.add( light );
 				spotlight = light;
 
-				// scene.add( new THREE.CameraHelper( light.shadow.camera ) );
-
 				var planeGeometry = new THREE.PlaneGeometry( 2000, 2000 );
 				planeGeometry.rotateX( - Math.PI / 2 );
-				var planeMaterial = new THREE.ShadowMaterial();
-				planeMaterial.opacity = 0.2;
+				var planeMaterial = new THREE.ShadowMaterial( { opacity: 0.2 } );
 
 				var plane = new THREE.Mesh( planeGeometry, planeMaterial );
 				plane.position.y = -200;

+ 7 - 0
examples/webgl_gpu_particle_system.html

@@ -39,6 +39,7 @@
 	<script src="../build/three.js"></script>
 	<script src="./js/controls/TrackballControls.js"></script>
 	<script src="./js/libs/dat.gui.min.js"></script>
+	<script src="./js/libs/stats.min.js"></script>
 	<script src="./js/GPUParticleSystem.js"></script>
 
 	<script>
@@ -109,6 +110,11 @@
 
 			//
 
+			stats = new Stats();
+			container.appendChild( stats.dom );
+
+			//
+
 			renderer = new THREE.WebGLRenderer();
 			renderer.setPixelRatio( window.devicePixelRatio );
 			renderer.setSize( window.innerWidth, window.innerHeight );
@@ -166,6 +172,7 @@
 			particleSystem.update( tick );
 
 			render();
+			stats.update();
 
 		}
 

+ 48 - 25
examples/webgl_interactive_instances_gpu.html

@@ -606,32 +606,24 @@
 			var vert = document.getElementById( 'vertMaterial' ).textContent;
 			var frag = document.getElementById( 'fragMaterial' ).textContent;
 
-			function updateColor( object, material, camera ) {
-
-				this.value.setHex( object.userData.color );
-
-			}
-
 			var material = new THREE.RawShaderMaterial( {
 				vertexShader: vert,
 				fragmentShader: frag,
 				uniforms: {
-					color: new THREE.Uniform( new THREE.Color() ).onUpdate( updateColor )
+					color: {
+						value: new THREE.Color()
+					}
 				}
 			} );
 			materialList.push( material );
 
-			function updatePickingColor( object, camera ) {
-
-				this.value.setHex( object.userData.pickingColor );
-
-			}
-
 			var pickingMaterial = new THREE.RawShaderMaterial( {
 				vertexShader: "#define PICKING\n" + vert,
 				fragmentShader: "#define PICKING\n" + frag,
 				uniforms: {
-					pickingColor: new THREE.Uniform( new THREE.Color() ).onUpdate( updatePickingColor )
+					pickingColor: {
+						value: new THREE.Color()
+					}
 				}
 			} );
 			materialList.push( pickingMaterial );
@@ -648,6 +640,43 @@
 
 			var matrix = new THREE.Matrix4();
 
+			function onBeforeRender( renderer, scene, camera, geometry, material, group ){
+
+				var updateList = [];
+				var u = material.uniforms;
+				var d = this.userData;
+
+				if( u.pickingColor ){
+					u.pickingColor.value.setHex( d.pickingColor );
+					updateList.push( "pickingColor" );
+				}
+
+				if( u.color ){
+					u.color.value.setHex( d.color );
+					updateList.push( "color" );
+				}
+
+				if( updateList.length ){
+
+					var materialProperties = renderer.properties.get( material );
+
+					if( materialProperties.program ){
+
+						var gl = renderer.getContext();
+						var p = materialProperties.program;
+						gl.useProgram( p.program );
+						var pu = p.getUniforms();
+
+						updateList.forEach( function( name ){
+							pu.setValue( gl, name, u[ name ].value );
+						} );
+
+					}
+
+				}
+
+			}
+
 			for ( var i = 0; i < instanceCount; i ++ ) {
 
 				var object = new THREE.Mesh( geo, material );
@@ -669,11 +698,13 @@
 				if ( useOverrideMaterial ) {
 
 					object.userData[ "pickingColor" ] = i + 1;
+					object.onBeforeRender = onBeforeRender;
 
 				}else {
 
 					pickingObject.material = pickingMaterial;
 					pickingObject.userData[ "pickingColor" ] = i + 1;
+					pickingObject.onBeforeRender = onBeforeRender;
 
 				}
 
@@ -718,24 +749,16 @@
 			var vertices = new THREE.BufferAttribute(
 				new Float32Array( instanceCount * posLen ), 3
 			);
-			var vertex = new THREE.Vector3();
 			var matrix = new THREE.Matrix4();
 			for ( var i = 0, ul = instanceCount; i < ul; i ++ ) {
-				var offset = i * posLen;
+
 				randomizeMatrix( matrix );
 				var object = new THREE.Object3D();
 				objectCount ++;
 				object.applyMatrix( matrix );
 				pickingData[ i + 1 ] = object;
-				vertices.set( pos.array, offset );
-
-				for ( var k = 0, l = offset; k < posLen; k += 3, l += 3 ) {
-
-					vertex.fromArray( vertices.array, l );
-					vertex.applyMatrix4( matrix );
-					vertex.toArray( vertices.array, l );
-
-				}
+				vertices.set( pos.array, i * posLen );
+				matrix.applyToVector3Array( vertices.array, i * posLen, posLen )
 
 			}
 			mgeo.addAttribute( 'position', vertices );

+ 0 - 383
examples/webgl_lights_arealight.html

@@ -1,383 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js webgl - lights - rect light</title>
-		<meta charset="utf-8">
-		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<style>
-			body {
-				background-color: #000;
-				margin: 0px;
-				overflow: hidden;
-			}
-
-			#info {
-				position: absolute;
-				top: 0px; width: 100%;
-				color: #ffffff;
-				padding: 5px;
-				font-family: Monospace;
-				font-size: 13px;
-				text-align: center;
-			}
-
-			a {
-				color: #ff0080;
-				text-decoration: none;
-			}
-
-			a:hover {
-				color: #0080ff;
-			}
-		</style>
-	</head>
-	<body>
-
-		<div id="container"></div>
-		<div id="info">
-			<a href="http://threejs.org" target="_blank">three.js</a> - Just to show the rect light and it's edge - by <a href="http://github.com/abelnation" target="_blank">abelnation</a><br />
-			Click and drag to move OrbitControls, center across the edge of the shadow.<br />
-			Click to set random color CTRL-Click for White.<br />
-		</div>
-
-		<script src="../build/three.js"></script>
-		<script src="js/lights/RectAreaLightUniformsLib.js"></script>
-		<script src="../examples/js/libs/dat.gui.min.js"></script>
-		<script src="../examples/js/controls/OrbitControls.js"></script>
-		<script src="js/Detector.js"></script>
-
-		<script>
-
-			var container = document.getElementById( 'container' );
-
-			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
-
-			var rnd = new THREE.WebGLRenderer();
-			var cam = new THREE.PerspectiveCamera( 34, window.innerWidth / window.innerHeight, 0.1, 20000 );
-			var orb = new THREE.OrbitControls( cam, rnd.domElement );
-
-			var scn = new THREE.Scene();
-
-			var matParams = {
-				specular: 0xFFFFFF,
-				shininess: 10000
-			};
-
-			var matFloor = new THREE.MeshPhongMaterial( matParams );
-			var matBox = new THREE.MeshPhongMaterial( matParams );
-			var geoFloor = new THREE.BoxGeometry( 2000, 0.1, 2000 );
-			var geoBox = new THREE.BoxGeometry( Math.PI, Math.sqrt( 2 ), Math.E );
-			var mshFloor = new THREE.Mesh( geoFloor, matFloor );
-			var mshBox = new THREE.Mesh( geoBox, matBox );
-
-			var amb = new THREE.AmbientLight( 0x080808 );
-
-			// TODO (abelnation): temp point light for debugging
-			var dir = new THREE.DirectionalLight( 0xFFFFFF );
-			var dirHelper = new THREE.DirectionalLightHelper( dir );
-
-			var shapes, shapeNames;
-			var rectLight;
-			var rectLightHelper;
-
-			var ray = new THREE.Raycaster();
-			var mouseDown = new THREE.Vector2();
-			var mouse = new THREE.Vector2();
-
-			var gui, guiElements;
-			var param = {};
-
-			function init() {
-
-				var gl = rnd.context;
-
-				// Check for float-RT support
-				// TODO (abelnation): figure out fall-back for float textures
-				if (!gl.getExtension("OES_texture_float")) {
-					alert("OES_texture_float not supported");
-					throw "missing webgl extension";
-				}
-
-				if (!gl.getExtension("OES_texture_float_linear")) {
-					alert("OES_texture_float_linear not supported");
-					throw "missing webgl extension";
-				}
-
-				rnd.shadowMap.enabled = true;
-				rnd.shadowMap.type = THREE.PCFSoftShadowMap;
-				rnd.gammaInput = true;
-				rnd.gammaOutput = true;
-				rnd.antialias = true;
-				rnd.domElement.addEventListener( 'mousedown', onDocumentClick );
-				rnd.domElement.addEventListener( 'mouseup', onDocumentClick );
-
-				// cam.position.set( 0, 100, 0 );
-				cam.position.set( 45, 20, 45 );
-
-				// shapes = {
-				// 	square: THREE.Polygon.makeSquare( 10.0 ),
-				// 	rectangle: THREE.Polygon.makeRectangle( 10.0, 5.0 ),
-				// 	circle: THREE.Polygon.makeCircle( 5.0, 20 ),
-				// 	star: THREE.Polygon.makeStar( 5, 5.0, 2.5 ),
-				// 	triangle: new THREE.Polygon( [
-				// 		new THREE.Vector3( -5.0, -5.0, 0 ),
-				// 		new THREE.Vector3(  0.0,  5.0, 0 ),
-				// 		new THREE.Vector3(  5.0, -5.0, 0 ),
-				// 	] )
-				// };
-				// shapeNames = Object.keys( shapes );
-
-				rectLight = new THREE.RectAreaLight( 0xFFFFFF, undefined, 2, 10 );
-				rectLight.matrixAutoUpdate = true;
-				rectLight.intensity = 70.0;
-				rectLight.position.set( 5, 5, 0 );
-				// rectLight.target = mshBox;
-				rectLightHelper = new THREE.RectAreaLightHelper( rectLight );
-				rectLight.add( rectLightHelper );
-
-				// TODO (abelnation): rect light shadow
-
-				matFloor.color.set( 0x808080 );
-				randomColor( matBox );
-
-				mshFloor.receiveShadow = true;
-				mshFloor.position.set( 0, 0, 0 );
-
-				mshBox.castShadow = true;
-				mshBox.receiveShadow = true;
-				mshBox.position.set( 0, 5, 0 );
-
-				scn.add( cam );
-
-				scn.add( mshFloor );
-				scn.add( mshBox );
-
-				// scn.add( amb );
-
-				// scn.add( dir );
-				// scn.add( dirHelper );
-
-				scn.add( rectLight );
-				// scn.add( rectLightHelper );
-
-				// scn.add( new THREE.AxisHelper( 10 ) );
-
-				document.body.appendChild( rnd.domElement );
-				onResize();
-				window.addEventListener( 'resize', onResize, false );
-
-				orb.addEventListener( 'change', render );
-				orb.update();
-
-			}
-
-			function onResize() {
-
-				rnd.setSize( window.innerWidth, window.innerHeight );
-				cam.aspect = ( window.innerWidth / window.innerHeight );
-				cam.updateProjectionMatrix();
-				orb.target = mshBox.position;
-
-			}
-
-			function tick() {
-
-				update();
-				render();
-
-				requestAnimationFrame( tick );
-
-			}
-
-			function update() {
-
-				var dt = 6000;
-				var qdt = dt / 4.0;
-				var dirSigns = [
-					[ 1,  1 ],
-					[ - 1,  1 ],
-					[ - 1,  1 ],
-					[ 1,  1 ]
-				];
-				var t = ( Date.now() / 1000 );
-
-				// move light in circle around center
-				// change light height with sine curve
-
-				var r = 10.0;
-
-				var lx = r * Math.cos( t );
-				var lz = r * Math.sin( t );
-
-				var ly = 5.0 + 5.0 * Math.sin( t / 3.0 );
-				// var ly = 7.0;
-
-				rectLight.position.set( lx, ly, lz );
-				rectLight.lookAt( mshBox.position );
-				rectLight.updateMatrixWorld();
-
-				// // move box in figure 8 path
-				// // xz is a figure 8
-				// // y is gently rising and falling
-				// 				var r = t * ( 4.0 * Math.PI );
-				// var s = Math.floor( t * dirSigns.length );
-                //
-				// var sign = dirSigns[ s ];
-				// var x = 5.0 * ( Math.cos( r ) + 1.0 ) * sign[ 0 ];
-				// var z = 5.0 * Math.sin( r ) * sign[ 1 ];
-				// var y = 2.5 * Math.cos( 0.5 * r ) + 5.0;
-                //
-				// mshBox.position.set( x, y, z );
-				// mshBox.updateMatrixWorld();
-
-			}
-
-			function render() {
-
-				rectLightHelper.update(); // required
-				rnd.render( scn, cam );
-
-			}
-
-			function clearGui() {
-
-				if ( gui ) gui.destroy();
-
-				gui = new dat.GUI();
-				gui.width = 190;
-				var gStyle = gui.domElement.style;
-				gStyle.position = "absolute";
-				gStyle.top = "48px";
-				gStyle.height = "220px";
-
-				gui.open();
-
-			}
-
-			function buildGui() {
-
-				clearGui();
-
-				param = {
-					'light color': rectLight.color.getHex(),
-					intensity: rectLight.intensity,
-					width: rectLight.width,
-					height: rectLight.height,
-					shininess: matFloor.shininess
-					// shape: shapeNames[0]
-				};
-
-				gui.add( param, 'width', 0.1, 20).onChange( function ( val ) {
-
-					rectLight.width = val;
-
-				} );
-
-				gui.add( param, 'height', 0.1, 20).onChange( function ( val ) {
-
-					rectLight.height = val;
-
-				} );
-
-				// gui.add( param, 'shape', shapeNames ).onChange( function ( val ) {
-                //
-				// 	rectLight.polygon = shapes[ val ].clone();
-                //
-				// } );
-
-				gui.addColor( param, 'light color' ).onChange( function ( val ) {
-
-					rectLight.color.setHex( val );
-
-				} );
-
-				gui.add( param, 'intensity', 0, 100 ).onChange( function ( val ) {
-
-					rectLight.intensity = val;
-
-				} );
-
-				gui.add( param, 'shininess', 0, 100000 ).onChange( function ( val ) {
-
-					matBox.shininess = val;
-					matFloor.shininess = val;
-
-				} );
-
-				// TODO (abelnation): shadow controls
-				// addGui( 'distance', rectLight.distance, function( val ) {
-				// rectLight.distance = val;
-				// render();
-				// }, false, 0, 1000 );
-
-				// addGui( 'penumbra', rectLight.penumbra, function( val ) {
-				// rectLight.penumbra = val;
-				// render();
-				// }, false, 0, 1 );
-
-				// addGui( 'decay', rectLight.decay, function( val ) {
-				// rectLight.decay = val;
-				// render();
-				// }, false, 0, 100 );
-
-			}
-
-			function onDocumentClick( event ) {
-
-				event.preventDefault();
-
-				var rndDom = rnd.domElement;
-
-				if ( event.type === 'mousedown' ) {
-
-					mouseDown.x = ( event.clientX / rndDom.clientWidth ) * 2 - 1;
-					mouseDown.y = - ( event.clientY / rndDom.clientHeight ) * 2 + 1;
-
-				} else {
-
-					mouse.x = ( event.clientX / rndDom.clientWidth ) * 2 - 1;
-					mouse.y = - ( event.clientY / rndDom.clientHeight ) * 2 + 1;
-
-					if ( mouseDown.distanceTo( mouse ) < 0.0075 ) {
-
-						ray.setFromCamera( mouse, cam );
-						var found = ray.intersectObjects( [ mshBox, mshFloor ] );
-
-						if ( found.length > 0 ) {
-
-							if ( event.ctrlKey === false ) randomColor( found[ 0 ].object );
-							else found[ 0 ].object.material.color.set( 0xffffff );
-
-							render();
-
-						}
-
-					}
-
-				}
-
-			}
-
-			function randomColor( target ) {
-
-				if ( target !== undefined ) {
-
-					if ( target.material !== undefined ) target = target.material;
-
-					if ( target.color !== undefined ) {
-
-						target.color.setHex( 0xffffff * Math.random() );
-
-					}
-
-				}
-
-			}
-
-			init();
-			buildGui();
-			tick();
-
-		</script>
-	</body>
-</html>

+ 17 - 29
examples/webgl_loader_collada_keyframe.html

@@ -1,31 +1,32 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgl - collada</title>
+		<title>three.js webgl - collada - keyframe</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
-
 			body {
-				font-family: Monospace;
-				background-color: #000000;
-				margin: 0px;
-				overflow: hidden;
+				background:#777;
+				padding:0;
+				margin:0;
+				font-weight: bold;
+				overflow:hidden;
 			}
 
 			#info {
-				color: #fff;
 				position: absolute;
-				top: 10px;
+				top: 0px;
 				width: 100%;
-				text-align: center;
-				z-index: 100;
-				display:block;
-
+				color: #ffffff;
+				padding: 5px;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
 			}
 
-			a { color: skyblue }
-
+			a {
+				color: #ffffff;
+			}
 		</style>
 	</head>
 	<body>
@@ -104,21 +105,8 @@
 
 				// Grid
 
-				var material = new THREE.LineBasicMaterial( { color: 0x303030 } );
-				var geometry = new THREE.Geometry();
-				var floor = -0.04, step = 1, size = 14;
-
-				for ( var i = 0; i <= size / step * 2; i ++ ) {
-
-					geometry.vertices.push( new THREE.Vector3( - size, floor, i * step - size ) );
-					geometry.vertices.push( new THREE.Vector3(   size, floor, i * step - size ) );
-					geometry.vertices.push( new THREE.Vector3( i * step - size, floor, -size ) );
-					geometry.vertices.push( new THREE.Vector3( i * step - size, floor,  size ) );
-
-				}
-
-				var line = new THREE.LineSegments( geometry, material );
-				scene.add( line );
+				var grid = new THREE.GridHelper( 20, 20 );
+				scene.add( grid );
 
 				// Add the COLLADA
 

+ 17 - 29
examples/webgl_loader_collada_kinematics.html

@@ -1,29 +1,32 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgl - collada</title>
+		<title>three.js webgl - collada - kinematics</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
 			body {
-				font-family: Monospace;
-				background-color: #000000;
-				margin: 0px;
-				overflow: hidden;
+				background:#777;
+				padding:0;
+				margin:0;
+				font-weight: bold;
+				overflow:hidden;
 			}
 
 			#info {
-				color: #fff;
 				position: absolute;
-				top: 10px;
+				top: 0px;
 				width: 100%;
-				text-align: center;
-				z-index: 100;
-				display:block;
-
+				color: #ffffff;
+				padding: 5px;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
 			}
 
-			a { color: skyblue }
+			a {
+				color: #ffffff;
+			}
 		</style>
 	</head>
 	<body>
@@ -93,23 +96,8 @@
 
 				// Grid
 
-				var size = 14, step = 1;
-
-				var geometry = new THREE.Geometry();
-				var material = new THREE.LineBasicMaterial( { color: 0x303030 } );
-
-				for ( var i = - size; i <= size; i += step ) {
-
-					geometry.vertices.push( new THREE.Vector3( - size, - 0.04, i ) );
-					geometry.vertices.push( new THREE.Vector3(   size, - 0.04, i ) );
-
-					geometry.vertices.push( new THREE.Vector3( i, - 0.04, - size ) );
-					geometry.vertices.push( new THREE.Vector3( i, - 0.04,   size ) );
-
-				}
-
-				var line = new THREE.LineSegments( geometry, material );
-				scene.add( line );
+				var grid = new THREE.GridHelper( 20, 20 );
+				scene.add( grid );
 
 				// Add the COLLADA
 

+ 4 - 4
examples/webgl_loader_x.html

@@ -118,11 +118,11 @@
             // ! If [ Texture ] was reversed Y axis, enable the following. 
             // THREE.XLoader.IsUvYReverse = false;
             
-		    // ! And if [ Model ] was reversed X axis, enable the following. 
-            // loader.load([' your model url ', false ], function (object) {
+		    // ! And if [ Model ] was reversed polygons, enable the following. 
+            // loader.load([' your model url ', true ], function (object) {
             
             // read (download) model file
-            loader.load(['models/xfile/SSR06_Born2.x', true], function (object) {
+            loader.load(['models/xfile/SSR06_Born2.x', false], function (object) {
 
                 for (var i = 0; i < object.FrameInfo.length; i++) {
 
@@ -226,7 +226,7 @@
             light.position.set(10, 100, 1).normalize();
             scene.add(light);
 
-            light = new THREE.DirectionalLight(0xaa5555);
+            light = new THREE.DirectionalLight(0x555588);
             light.position.set(-1, -1, -1).normalize();
             scene.add(light);
 

+ 308 - 0
examples/webgl_materials_compile.html

@@ -0,0 +1,308 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - node material</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				color: #fff;
+				font-family:Monospace;
+				font-size:13px;
+				margin: 0px;
+				text-align:center;
+				overflow: hidden;
+			}
+
+			#info {
+				color: #fff;
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				text-align: center;
+				display:block;
+			}
+			
+			#waitScreen {
+				color: #000;
+			    position: absolute;
+			    top: 50%;
+			    left: 50%;
+			    margin-top: -50px;
+			    margin-left: -50px;
+			    width: 100px;
+			    height: 100px;
+			}
+			
+			.hide {
+				display:none;
+			}
+
+			a { color: white }
+		</style>
+	</head>
+	<body>
+
+		<div id="container"></div>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> - Node-Based Material
+			<br /><span class="button" id="preload">change preload</span>
+		</div>
+
+		<div id="waitScreen">
+			Loading ...
+		</div>
+
+		<script src="../build/three.js"></script>
+
+		<script src='js/geometries/TeapotBufferGeometry.js'></script>
+		<script src="js/controls/OrbitControls.js"></script>
+		<script src="js/libs/dat.gui.min.js"></script>
+
+		<!-- NodeLibrary -->
+		<script src="js/nodes/GLNode.js"></script>
+		<script src="js/nodes/RawNode.js"></script>
+		<script src="js/nodes/TempNode.js"></script>
+		<script src="js/nodes/InputNode.js"></script>
+		<script src="js/nodes/ConstNode.js"></script>
+		<script src="js/nodes/VarNode.js"></script>
+		<script src="js/nodes/FunctionNode.js"></script>
+		<script src="js/nodes/FunctionCallNode.js"></script>
+		<script src="js/nodes/AttributeNode.js"></script>
+		<script src="js/nodes/NodeBuilder.js"></script>
+		<script src="js/nodes/NodeLib.js"></script>
+		<script src="js/nodes/NodeMaterial.js"></script>
+
+		<!-- Accessors -->
+		<script src="js/nodes/accessors/PositionNode.js"></script>
+		<script src="js/nodes/accessors/NormalNode.js"></script>
+		<script src="js/nodes/accessors/UVNode.js"></script>
+		<script src="js/nodes/accessors/ScreenUVNode.js"></script>
+		<script src="js/nodes/accessors/ColorsNode.js"></script>
+		<script src="js/nodes/accessors/CameraNode.js"></script>
+		<script src="js/nodes/accessors/ReflectNode.js"></script>
+		<script src="js/nodes/accessors/LightNode.js"></script>
+
+		<!-- Inputs -->
+		<script src="js/nodes/inputs/IntNode.js"></script>
+		<script src="js/nodes/inputs/FloatNode.js"></script>
+		<script src="js/nodes/inputs/ColorNode.js"></script>
+		<script src="js/nodes/inputs/Vector2Node.js"></script>
+		<script src="js/nodes/inputs/Vector3Node.js"></script>
+		<script src="js/nodes/inputs/Vector4Node.js"></script>
+		<script src="js/nodes/inputs/TextureNode.js"></script>
+		<script src="js/nodes/inputs/CubeTextureNode.js"></script>
+
+		<!-- Math -->
+		<script src="js/nodes/math/Math1Node.js"></script>
+		<script src="js/nodes/math/Math2Node.js"></script>
+		<script src="js/nodes/math/Math3Node.js"></script>
+		<script src="js/nodes/math/OperatorNode.js"></script>
+
+		<!-- Utils -->
+		<script src="js/nodes/utils/SwitchNode.js"></script>
+		<script src="js/nodes/utils/JoinNode.js"></script>
+		<script src="js/nodes/utils/TimerNode.js"></script>
+		<script src="js/nodes/utils/RoughnessToBlinnExponentNode.js"></script>
+		<script src="js/nodes/utils/VelocityNode.js"></script>
+		<script src="js/nodes/utils/LuminanceNode.js"></script>
+		<script src="js/nodes/utils/ColorAdjustmentNode.js"></script>
+		<script src="js/nodes/utils/NoiseNode.js"></script>
+		<script src="js/nodes/utils/ResolutionNode.js"></script>
+		<script src="js/nodes/utils/BumpNode.js"></script>
+		<script src="js/nodes/utils/BlurNode.js"></script>
+
+		<!-- Phong Material -->
+		<script src="js/nodes/materials/PhongNode.js"></script>
+		<script src="js/nodes/materials/PhongNodeMaterial.js"></script>
+
+		<script>
+
+		/* global THREE */
+
+		var container = document.getElementById( 'container' );
+
+		var renderer, scene, camera, clock = new THREE.Clock(), fov = 50;
+		var teapot;
+		var controls;
+		var move = false;
+		var rtTexture, rtMaterial;
+		var meshes = [];
+		
+		document.getElementById( "preload" ).addEventListener( 'click', function() {
+
+			var hash = document.location.hash.substr( 1 );
+
+			if ( hash.length === 0 ) {
+				window.location.hash = "#NoPreLoad"
+			} else {
+				window.location.hash = ""
+			}
+			
+			location.reload(true);
+
+		}, false );
+
+		window.addEventListener( 'load', init );
+
+		function init() {
+
+			renderer = new THREE.WebGLRenderer( { antialias: true } );
+			renderer.setPixelRatio( window.devicePixelRatio );
+			renderer.setSize( window.innerWidth, window.innerHeight );
+			container.appendChild( renderer.domElement );
+
+			scene = new THREE.Scene();
+
+			camera = new THREE.PerspectiveCamera( fov, window.innerWidth / window.innerHeight, 1, 1000 );
+			camera.position.x = 0;
+			camera.position.z = - 300;
+			camera.position.y = 200;
+			camera.target = new THREE.Vector3();
+
+			controls = new THREE.OrbitControls( camera, renderer.domElement );
+			controls.minDistance = 50;
+			controls.maxDistance = 400;
+
+			scene.add( new THREE.AmbientLight( 0x464646 ) );
+
+			var light = new THREE.DirectionalLight( 0xffddcc, 1 );
+			light.position.set( 1, 0.75, 0.5 );
+			scene.add( light );
+
+			var light = new THREE.DirectionalLight( 0xccccff, 1 );
+			light.position.set( - 1, 0.75, - 0.5 );
+			scene.add( light );
+
+			teapot = new THREE.TeapotBufferGeometry( 15, 18 );
+
+			var itemsonrow = 10;
+
+			for (var i = 0 ; i<  itemsonrow * itemsonrow; i ++ ){
+				
+				var mesh = new THREE.Mesh( teapot );
+				
+				mesh.position.x = 50 *(i%itemsonrow) -50*itemsonrow/2;
+				mesh.position.z = 50*Math.floor(i/itemsonrow)-150; 
+				updateMaterial(mesh);
+				scene.add( mesh );
+				meshes.push(mesh); 
+			}
+
+			window.addEventListener( 'resize', onWindowResize, false );
+
+			var hash = document.location.hash.substr( 1 );
+
+			if ( hash.length === 0 ) {
+
+				renderer.compile(scene,camera);
+				
+			}
+			
+			document.getElementById("waitScreen").className = "hide";
+			
+			setTimeout(function() {
+				
+				onWindowResize();
+				animate();
+				
+			}, 1);
+
+		}
+
+		function updateMaterial(mesh) {
+
+			move = false;
+
+			if ( mesh.material ) mesh.material.dispose();
+
+			if ( rtTexture ) {
+
+				rtTexture.dispose();
+				rtTexture = null;
+
+			}
+
+			if ( rtMaterial ) {
+
+				rtMaterial.dispose();
+				rtMaterial = null;
+
+			}
+
+			var mtl = new THREE.PhongNodeMaterial();
+
+			var time = new THREE.TimerNode();
+			var speed = new THREE.FloatNode( Math.random() );
+
+			var color = new THREE.ColorNode( Math.random() * 0xFFFFFF );
+
+			var timeSpeed = new THREE.OperatorNode(
+				time,
+				speed,
+				THREE.OperatorNode.MUL
+			);
+
+			var sinCycleInSecs = new THREE.OperatorNode(
+				timeSpeed,
+				new THREE.ConstNode( THREE.ConstNode.PI2 ),
+				THREE.OperatorNode.MUL
+			);
+
+			var cycle = new THREE.Math1Node( sinCycleInSecs, THREE.Math1Node.SIN );
+
+			var cycleColor = new THREE.OperatorNode(
+				cycle,
+				color,
+				THREE.OperatorNode.MUL
+			);
+
+			var cos = new THREE.Math1Node( cycleColor, THREE.Math1Node.SIN );
+
+			mtl.color = new THREE.ColorNode( 0 );
+			mtl.emissive = cos;
+			
+			
+			var transformer = new THREE.FunctionNode( "position + 0.0 * " + Math.random(), "vec3", [ ]);
+			mtl.transform = transformer;
+			// build shader
+			mtl.build();
+
+			// set material
+			mesh.material = mtl;
+
+		}
+
+		function onWindowResize() {
+
+			var width = window.innerWidth, height = window.innerHeight;
+
+			camera.aspect = width / height;
+			camera.updateProjectionMatrix();
+
+			renderer.setSize( width, height );
+
+			if ( rtTexture ) rtTexture.setSize( width, height );
+
+		}
+
+		function animate() {
+
+			var delta = clock.getDelta();
+			for (var i = 0; i < meshes.length; i++ ){
+				
+				var mesh = meshes[i]; 
+				mesh.material.updateFrame( delta );
+			
+			}
+
+			renderer.render( scene, camera );
+
+			requestAnimationFrame( animate );
+
+		}
+
+		</script>
+
+	</body>
+</html>

+ 48 - 46
examples/webgl_physics_convex_break.html

@@ -1,50 +1,52 @@
 <html lang="en">
-    <head>
-        <title>Convex object breaking example</title>
-        <meta charset="utf-8">
-        <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-        <style>
-            body {
-                color: #61443e;
-                font-family:Monospace;
-                font-size:13px;
-                text-align:center;
-
-                background-color: #bfd1e5;
-                margin: 0px;
-                overflow: hidden;
-            }
-
-            #info {
-                position: absolute;
-                top: 0px; width: 100%;
-                padding: 5px;
-            }
-
-            a {
-                color: #a06851;
-            }
-
-        </style>
-    </head>
-    <body>
+	<head>
+		<title>Convex object breaking example</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				color: #61443e;
+				font-family:Monospace;
+				font-size:13px;
+				text-align:center;
+
+				background-color: #bfd1e5;
+				margin: 0px;
+				overflow: hidden;
+			}
+
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				padding: 5px;
+			}
+
+			a {
+				color: #a06851;
+			}
+
+		</style>
+	</head>
+	<body>
+
 	<div id="info">Physics threejs demo with convex objects breaking in real time<br />Press mouse to throw balls and move the camera.</div>
-        <div id="container"><br /><br /><br /><br /><br />Loading...</div>
+	<div id="container"><br /><br /><br /><br /><br />Loading...</div>
 
 	<script src="../build/three.js"></script>
 	<script src="js/libs/ammo.js"></script>
 	<script src="js/controls/OrbitControls.js"></script>
-        <script src="js/Detector.js"></script>
+	<script src="js/Detector.js"></script>
 	<script src="js/libs/stats.min.js"></script>
 	<script src="js/ConvexObjectBreaker.js"></script>
+	<script src="js/QuickHull.js"></script>
 	<script src="js/geometries/ConvexGeometry.js"></script>
 
-        <script>
+		<script>
 
 		// Detects webgl
 		if ( ! Detector.webgl ) {
-		    Detector.addGetWebGLMessage();
-		    document.getElementById( 'container' ).innerHTML = "";
+			Detector.addGetWebGLMessage();
+			document.getElementById( 'container' ).innerHTML = "";
 		}
 
 		// - Global variables -
@@ -82,7 +84,7 @@
 
 		var objectsToRemove = [];
 		for ( var i = 0; i < 500; i++ ) {
-		    objectsToRemove[ i ] = null;
+			objectsToRemove[ i ] = null;
 		}
 		var numObjectsToRemove = 0;
 
@@ -232,9 +234,9 @@
 			quat.set( 0, 0, 0, 1 );
 			for ( var i = 0; i < numStones; i++ ) {
 
-			    pos.set( 0, 2, 15 * ( 0.5 - i / ( numStones + 1 ) ) );
+				pos.set( 0, 2, 15 * ( 0.5 - i / ( numStones + 1 ) ) );
 
-			    createObject( stoneMass, stoneHalfExtents, pos, quat, createMaterial( 0xB0B0B0 ) );
+				createObject( stoneMass, stoneHalfExtents, pos, quat, createMaterial( 0xB0B0B0 ) );
 
 			}
 
@@ -312,16 +314,16 @@
 		function createRigidBody( object, physicsShape, mass, pos, quat, vel, angVel ) {
 
 			if ( pos ) {
-			    object.position.copy( pos );
+				object.position.copy( pos );
 			}
 			else {
-			    pos = object.position;
+				pos = object.position;
 			}
 			if ( quat ) {
-			    object.quaternion.copy( quat );
+				object.quaternion.copy( quat );
 			}
 			else {
-			    quat = object.quaternion;
+				quat = object.quaternion;
 			}
 
 			var transform = new Ammo.btTransform();
@@ -339,10 +341,10 @@
 			body.setFriction( 0.5 );
 
 			if ( vel ) {
-			    body.setLinearVelocity( new Ammo.btVector3( vel.x, vel.y, vel.z ) );
+				body.setLinearVelocity( new Ammo.btVector3( vel.x, vel.y, vel.z ) );
 			}
 			if ( angVel ) {
-			    body.setAngularVelocity( new Ammo.btVector3( angVel.x, angVel.y, angVel.z ) );
+				body.setAngularVelocity( new Ammo.btVector3( angVel.x, angVel.y, angVel.z ) );
 			}
 
 			object.userData.physicsBody = body;
@@ -548,14 +550,14 @@
 
 			for ( var i = 0; i < numObjectsToRemove; i++ ) {
 
-			    removeDebris( objectsToRemove[ i ] );
+				removeDebris( objectsToRemove[ i ] );
 
 			}
 			numObjectsToRemove = 0;
 
 		}
 
-        </script>
+		</script>
 
-    </body>
+	</body>
 </html>

+ 2 - 4
examples/webgl_postprocessing_outline.html

@@ -41,13 +41,11 @@
 		<script src="js/Detector.js"></script>
 
 		<script src="js/shaders/CopyShader.js"></script>
-    <script src="js/postprocessing/EffectComposer.js"></script>
-    <script src="js/postprocessing/MaskPass.js"></script>
-		<script src="js/shaders/CopyShader.js"></script>
+		<script src="js/shaders/FXAAShader.js"></script>
+		<script src="js/postprocessing/EffectComposer.js"></script>
 		<script src="js/postprocessing/RenderPass.js"></script>
     <script src="js/postprocessing/ShaderPass.js"></script>
 		<script src="js/postprocessing/OutlinePass.js"></script>
-		<script src="js/shaders/FXAAShader.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src='js/libs/dat.gui.min.js'></script>
 

+ 2 - 2
examples/webvr_cubes.html

@@ -4,8 +4,8 @@
 		<title>three.js webvr - cubes</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
-		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-04-17 -->
-		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-04-17" content="Aj3fKurj0eOvRSbpJ0NaqkV/AE2Y2KJIepdCGWNmCB/iMgbDV/rhFn8zFu6c6zZZlRGZNR7Xv/BEX544EeqLuQAAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5MjQ3MzYwMH0=">
+		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-05-25 -->
+		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-05-25" content="Atlrg03BdkeS00YJBz6xcPTMf/Kvm+vc4Mhb0JUzhgCXXe64/YztVsRiOc5dA3OXXPCCaTmY3yVplbeQyGTtmQsAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5NTczNjMwN30=">
 		<style>
 			body {
 				font-family: Monospace;

+ 2 - 2
examples/webvr_daydream.html

@@ -4,8 +4,8 @@
 		<title>three.js webvr - daydream</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
-		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-04-17 -->
-		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-04-17" content="Aj3fKurj0eOvRSbpJ0NaqkV/AE2Y2KJIepdCGWNmCB/iMgbDV/rhFn8zFu6c6zZZlRGZNR7Xv/BEX544EeqLuQAAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5MjQ3MzYwMH0=">
+		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-05-25 -->
+		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-05-25" content="Atlrg03BdkeS00YJBz6xcPTMf/Kvm+vc4Mhb0JUzhgCXXe64/YztVsRiOc5dA3OXXPCCaTmY3yVplbeQyGTtmQsAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5NTczNjMwN30=">
 		<style>
 			body {
 				font-family: Monospace;

+ 2 - 2
examples/webvr_panorama.html

@@ -4,8 +4,8 @@
 		<title>three.js webvr - panorama</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
-		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-04-17 -->
-		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-04-17" content="Aj3fKurj0eOvRSbpJ0NaqkV/AE2Y2KJIepdCGWNmCB/iMgbDV/rhFn8zFu6c6zZZlRGZNR7Xv/BEX544EeqLuQAAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5MjQ3MzYwMH0=">
+		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-05-25 -->
+		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-05-25" content="Atlrg03BdkeS00YJBz6xcPTMf/Kvm+vc4Mhb0JUzhgCXXe64/YztVsRiOc5dA3OXXPCCaTmY3yVplbeQyGTtmQsAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5NTczNjMwN30=">
 		<style>
 			html, body {
 				background-color: #000;

+ 2 - 2
examples/webvr_rollercoaster.html

@@ -4,8 +4,8 @@
 		<title>three.js webvr - roller coaster</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
-		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-04-17 -->
-		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-04-17" content="Aj3fKurj0eOvRSbpJ0NaqkV/AE2Y2KJIepdCGWNmCB/iMgbDV/rhFn8zFu6c6zZZlRGZNR7Xv/BEX544EeqLuQAAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5MjQ3MzYwMH0=">
+		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-05-25 -->
+		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-05-25" content="Atlrg03BdkeS00YJBz6xcPTMf/Kvm+vc4Mhb0JUzhgCXXe64/YztVsRiOc5dA3OXXPCCaTmY3yVplbeQyGTtmQsAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5NTczNjMwN30=">
 		<style>
 			body {
 				margin: 0px;

+ 2 - 2
examples/webvr_sandbox.html

@@ -4,8 +4,8 @@
 		<title>three.js webvr - sandbox</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
-		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-04-17 -->
-		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-04-17" content="Aj3fKurj0eOvRSbpJ0NaqkV/AE2Y2KJIepdCGWNmCB/iMgbDV/rhFn8zFu6c6zZZlRGZNR7Xv/BEX544EeqLuQAAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5MjQ3MzYwMH0=">
+		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-05-25 -->
+		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-05-25" content="Atlrg03BdkeS00YJBz6xcPTMf/Kvm+vc4Mhb0JUzhgCXXe64/YztVsRiOc5dA3OXXPCCaTmY3yVplbeQyGTtmQsAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5NTczNjMwN30=">
 		<style>
 			body {
 				margin: 0px;

+ 2 - 2
examples/webvr_video.html

@@ -4,8 +4,8 @@
 		<title>three.js webvr - video</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
-		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-04-17 -->
-		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-04-17" content="Aj3fKurj0eOvRSbpJ0NaqkV/AE2Y2KJIepdCGWNmCB/iMgbDV/rhFn8zFu6c6zZZlRGZNR7Xv/BEX544EeqLuQAAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5MjQ3MzYwMH0=">
+		<!-- Origin Trial Token, feature = WebVR, origin = https://threejs.org, expires = 2017-05-25 -->
+		<meta http-equiv="origin-trial" data-feature="WebVR" data-expires="2017-05-25" content="Atlrg03BdkeS00YJBz6xcPTMf/Kvm+vc4Mhb0JUzhgCXXe64/YztVsRiOc5dA3OXXPCCaTmY3yVplbeQyGTtmQsAAABKeyJvcmlnaW4iOiJodHRwczovL3RocmVlanMub3JnOjQ0MyIsImZlYXR1cmUiOiJXZWJWUiIsImV4cGlyeSI6MTQ5NTczNjMwN30=">
 		<style>
 			body {
 				font-family: Monospace;

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "three",
-  "version": "0.84.0",
+  "version": "0.85.0",
   "description": "JavaScript 3D library",
   "main": "build/three.js",
   "repository": "mrdoob/three.js",

+ 1 - 1
src/constants.js

@@ -1,4 +1,4 @@
-export var REVISION = '85dev';
+export var REVISION = '85';
 export var MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
 export var CullFaceNone = 0;
 export var CullFaceBack = 1;

+ 20 - 8
src/helpers/BoxHelper.js

@@ -6,10 +6,13 @@ import { BufferGeometry } from '../core/BufferGeometry';
 
 /**
  * @author mrdoob / http://mrdoob.com/
+ * @author Mugen87 / http://github.com/Mugen87
  */
 
 function BoxHelper( object, color ) {
 
+	this.object = object;
+
 	if ( color === undefined ) color = 0xffff00;
 
 	var indices = new Uint16Array( [ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ] );
@@ -21,11 +24,9 @@ function BoxHelper( object, color ) {
 
 	LineSegments.call( this, geometry, new LineBasicMaterial( { color: color } ) );
 
-	if ( object !== undefined ) {
-
-		this.update( object );
+	this.matrixAutoUpdate = false;
 
-	}
+	this.update();
 
 }
 
@@ -38,13 +39,15 @@ BoxHelper.prototype.update = ( function () {
 
 	return function update( object ) {
 
-		if ( object && object.isBox3 ) {
+		if ( object !== undefined ) {
 
-			box.copy( object );
+			console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' );
+
+		}
 
-		} else {
+		if ( this.object !== undefined ) {
 
-			box.setFromObject( object );
+			box.setFromObject( this.object );
 
 		}
 
@@ -89,5 +92,14 @@ BoxHelper.prototype.update = ( function () {
 
 } )();
 
+BoxHelper.prototype.setFromObject = function ( object ) {
+
+	this.object = object;
+	this.update();
+
+	return this;
+
+};
+
 
 export { BoxHelper };

+ 0 - 2
src/helpers/FaceNormalsHelper.js

@@ -110,8 +110,6 @@ FaceNormalsHelper.prototype.update = ( function () {
 
 		position.needsUpdate = true;
 
-		return this;
-
 	};
 
 }() );

+ 0 - 2
src/helpers/VertexNormalsHelper.js

@@ -145,8 +145,6 @@ VertexNormalsHelper.prototype.update = ( function () {
 
 		position.needsUpdate = true;
 
-		return this;
-
 	};
 
 }() );

+ 3 - 3
src/lights/SpotLightShadow.js

@@ -20,11 +20,11 @@ SpotLightShadow.prototype = Object.assign( Object.create( LightShadow.prototype
 
 	update: function ( light ) {
 
+		var camera = this.camera;
+
 		var fov = _Math.RAD2DEG * 2 * light.angle;
 		var aspect = this.mapSize.width / this.mapSize.height;
-		var far = light.distance || 500;
-
-		var camera = this.camera;
+		var far = light.distance || camera.far;
 
 		if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) {
 

+ 7 - 1
src/materials/ShadowMaterial.js

@@ -5,9 +5,13 @@ import { UniformsUtils } from '../renderers/shaders/UniformsUtils';
 
 /**
  * @author mrdoob / http://mrdoob.com/
+ *
+ * parameters = {
+ *  opacity: <float>
+ * }
  */
 
-function ShadowMaterial() {
+function ShadowMaterial( parameters ) {
 
 	ShaderMaterial.call( this, {
 		uniforms: UniformsUtils.merge( [
@@ -35,6 +39,8 @@ function ShadowMaterial() {
 		}
 	} );
 
+	this.setValues( parameters );
+
 }
 
 ShadowMaterial.prototype = Object.create( ShaderMaterial.prototype );

+ 86 - 53
src/renderers/WebGLRenderer.js

@@ -688,6 +688,12 @@ function WebGLRenderer( parameters ) {
 
 	};
 
+	function absNumericalSort( a, b ) {
+
+		return Math.abs( b[ 0 ] ) - Math.abs( a[ 0 ] );
+
+	}
+
 	this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) {
 
 		state.setMaterial( material );
@@ -1026,13 +1032,47 @@ function WebGLRenderer( parameters ) {
 
 	}
 
-	// Sorting
+	// Compile
 
-	function absNumericalSort( a, b ) {
+	this.compile = function ( scene, camera ) {
 
-		return Math.abs( b[ 0 ] ) - Math.abs( a[ 0 ] );
+		lights = [];
 
-	}
+		scene.traverse( function ( object ) {
+
+			if ( object.isLight ) {
+
+				lights.push( object );
+
+			}
+
+		} );
+
+		setupLights( lights, camera );
+
+		scene.traverse( function ( object ) {
+
+			if ( object.material ) {
+
+				if ( Array.isArray( object.material ) ) {
+
+					for ( var i = 0; i < object.material.length; i ++ ) {
+
+						initMaterial( object.material[ i ], scene.fog, object );
+
+					}
+
+				} else {
+
+					initMaterial( object.material, scene.fog, object );
+
+				}
+
+			}
+
+		} );
+
+	};
 
 	// Rendering
 
@@ -1304,73 +1344,79 @@ function WebGLRenderer( parameters ) {
 
 		if ( ! object.visible ) return;
 
-		if ( object.isLight ) {
+		var visible = object.layers.test( camera.layers );
 
-			lights.push( object );
+		if ( visible ) {
 
-		} else if ( object.isSprite ) {
+			if ( object.isLight ) {
 
-			if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
+				lights.push( object );
 
-				sprites.push( object );
+			} else if ( object.isSprite ) {
 
-			}
+				if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) {
 
-		} else if ( object.isLensFlare ) {
+					sprites.push( object );
 
-			lensFlares.push( object );
+				}
 
-		} else if ( object.isImmediateRenderObject ) {
+			} else if ( object.isLensFlare ) {
 
-			if ( sortObjects ) {
+				lensFlares.push( object );
 
-				_vector3.setFromMatrixPosition( object.matrixWorld )
-					.applyMatrix4( _projScreenMatrix );
+			} else if ( object.isImmediateRenderObject ) {
 
-			}
+				if ( sortObjects ) {
 
-			currentRenderList.push( object, null, object.material, _vector3.z, null );
+					_vector3.setFromMatrixPosition( object.matrixWorld )
+						.applyMatrix4( _projScreenMatrix );
 
-		} else if ( object.isMesh || object.isLine || object.isPoints ) {
+				}
 
-			if ( object.isSkinnedMesh ) {
+				currentRenderList.push( object, null, object.material, _vector3.z, null );
 
-				object.skeleton.update();
+			} else if ( object.isMesh || object.isLine || object.isPoints ) {
 
-			}
+				if ( object.isSkinnedMesh ) {
 
-			if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
+					object.skeleton.update();
 
-				if ( sortObjects ) {
+				}
 
-					_vector3.setFromMatrixPosition( object.matrixWorld )
-						.applyMatrix4( _projScreenMatrix );
+				if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) {
 
-				}
+					if ( sortObjects ) {
+
+						_vector3.setFromMatrixPosition( object.matrixWorld )
+							.applyMatrix4( _projScreenMatrix );
+
+					}
 
-				var geometry = objects.update( object );
-				var material = object.material;
+					var geometry = objects.update( object );
+					var material = object.material;
 
-				if ( Array.isArray( material ) ) {
+					if ( Array.isArray( material ) ) {
 
-					var groups = geometry.groups;
+						var groups = geometry.groups;
 
-					for ( var i = 0, l = groups.length; i < l; i ++ ) {
+						for ( var i = 0, l = groups.length; i < l; i ++ ) {
 
-						var group = groups[ i ];
-						var groupMaterial = material[ group.materialIndex ];
+							var group = groups[ i ];
+							var groupMaterial = material[ group.materialIndex ];
 
-						if ( groupMaterial && groupMaterial.visible ) {
+							if ( groupMaterial && groupMaterial.visible ) {
 
-							currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group );
+								currentRenderList.push( object, geometry, groupMaterial, _vector3.z, group );
+
+							}
 
 						}
 
-					}
+					} else if ( material.visible ) {
 
-				} else if ( material.visible ) {
+						currentRenderList.push( object, geometry, material, _vector3.z, null );
 
-					currentRenderList.push( object, geometry, material, _vector3.z, null );
+					}
 
 				}
 
@@ -1438,8 +1484,6 @@ function WebGLRenderer( parameters ) {
 
 	function renderObject( object, scene, camera, geometry, material, group ) {
 
-		if ( object.layers.test( camera.layers ) === false ) return;
-
 		object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld );
 		object.normalMatrix.getNormalMatrix( object.modelViewMatrix );
 
@@ -2416,18 +2460,7 @@ function WebGLRenderer( parameters ) {
 				}
 
 				_lights.pointShadowMap[ pointLength ] = shadowMap;
-
-				if ( _lights.pointShadowMatrix[ pointLength ] === undefined ) {
-
-					_lights.pointShadowMatrix[ pointLength ] = new Matrix4();
-
-				}
-
-				// for point lights we set the shadow matrix to be a translation-only matrix
-				// equal to inverse of the light's position
-				_vector3.setFromMatrixPosition( light.matrixWorld ).negate();
-				_lights.pointShadowMatrix[ pointLength ].identity().setPosition( _vector3 );
-
+				_lights.pointShadowMatrix[ pointLength ] = light.shadow.matrix;
 				_lights.point[ pointLength ] = uniforms;
 
 				pointLength ++;

+ 82 - 2
src/renderers/shaders/ShaderChunk/bsdfs.glsl

@@ -355,6 +355,86 @@ vec3 integrateLtcBrdfOverRect( const in GeometricContext geometry, const in mat3
 
 	vec3 Lo_i = vec3( sum, sum, sum );
 
+	return Lo_i/(2.0 * PI);
+
+}
+
+/* From http://advances.realtimerendering.com/s2016/s2016_ltc_rnd.pdf
+Basically its an approximation for the form factor of a clipped rectangle.
+*/
+
+float ClippedSphereFormFactor( const in vec3 f ) {
+	float l = length(f);
+	return max((l*l + f.z)/(l+1.0), 0.0);
+}
+
+/* From http://advances.realtimerendering.com/s2016/s2016_ltc_rnd.pdf
+ Normalization by 2*PI is incorporated in this function itself.
+ This Normalization can be seen in Eq 11 of
+ https://drive.google.com/file/d/0BzvWIdpUpRx_d09ndGVjNVJzZjA/view
+ theta/sin(theta)	is approximated by rational polynomial
+ */
+
+vec3 EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {
+
+	float x = dot(v1, v2);
+
+	float y = abs(x);
+	float a = 0.86267 + (0.49788 + 0.01436*y)*y;
+	float b = 3.45068 + (4.18814 + y)*y;
+	float v = a/b;
+
+	float theta_sintheta = (x > 0.0) ? v : 0.5*inversesqrt(1.0 - x*x) - v;
+
+	return cross(v1, v2)*theta_sintheta;
+}
+
+vec3 integrateLtcBrdfOverRectOptimized( const in GeometricContext geometry, const in mat3 brdfMat, const in vec3 rectPoints[4] ) {
+
+	vec3 N = geometry.normal;
+	vec3 V = geometry.viewDir;
+	vec3 P = geometry.position;
+
+	// construct orthonormal basis around N
+	vec3 T1, T2;
+	T1 = normalize(V - N * dot( V, N ));
+	// TODO (abelnation): I had to negate this cross product to get proper light.  Curious why sample code worked without negation
+	T2 = - cross( N, T1 );
+
+	// rotate area light in (T1, T2, N) basis
+	mat3 brdfWrtSurface = brdfMat * transpose( mat3( T1, T2, N ) );
+
+	// transformed rect relative to surface point
+	vec3 clippedRect[4];
+	clippedRect[0] = brdfWrtSurface * ( rectPoints[0] - P );
+	clippedRect[1] = brdfWrtSurface * ( rectPoints[1] - P );
+	clippedRect[2] = brdfWrtSurface * ( rectPoints[2] - P );
+	clippedRect[3] = brdfWrtSurface * ( rectPoints[3] - P );
+
+	// Find light normal
+	vec3 v1 = clippedRect[1] - clippedRect[0];
+	vec3 v2 = clippedRect[3] - clippedRect[0];
+	vec3 lightNormal = cross(v1, v2);
+
+	bool bSameSide = dot(lightNormal, clippedRect[0]) > 0.0;
+	if( !bSameSide )
+		return vec3(0.0);
+
+	// project clipped rect onto sphere
+	clippedRect[0] = normalize( clippedRect[0] );
+	clippedRect[1] = normalize( clippedRect[1] );
+	clippedRect[2] = normalize( clippedRect[2] );
+	clippedRect[3] = normalize( clippedRect[3] );
+
+	// Accumulate vector form factor
+	vec3 edgeVectorFormFactor = vec3(0.0);
+	edgeVectorFormFactor += EdgeVectorFormFactor( clippedRect[0], clippedRect[1] );
+	edgeVectorFormFactor += EdgeVectorFormFactor( clippedRect[1], clippedRect[2] );
+	edgeVectorFormFactor += EdgeVectorFormFactor( clippedRect[2], clippedRect[3] );
+	edgeVectorFormFactor += EdgeVectorFormFactor( clippedRect[3], clippedRect[0] );
+
+	vec3 Lo_i = vec3( ClippedSphereFormFactor( edgeVectorFormFactor ) );
+
 	return Lo_i;
 
 }
@@ -384,7 +464,7 @@ vec3 Rect_Area_Light_Specular_Reflectance(
 		vec3( t.w,   0, t.x )
 	);
 
-	vec3 specularReflectance = integrateLtcBrdfOverRect( geometry, brdfLtcApproxMat, rectPoints );
+	vec3 specularReflectance = integrateLtcBrdfOverRectOptimized( geometry, brdfLtcApproxMat, rectPoints );
 	specularReflectance *= brdfLtcScalar;
 
 	return specularReflectance;
@@ -399,7 +479,7 @@ vec3 Rect_Area_Light_Diffuse_Reflectance(
 	initRectPoints( lightPos, lightHalfWidth, lightHalfHeight, rectPoints );
 
 	mat3 diffuseBrdfMat = mat3(1);
-	vec3 diffuseReflectance = integrateLtcBrdfOverRect( geometry, diffuseBrdfMat, rectPoints );
+	vec3 diffuseReflectance = integrateLtcBrdfOverRectOptimized( geometry, diffuseBrdfMat, rectPoints );
 
 	return diffuseReflectance;
 

+ 15 - 11
src/renderers/shaders/ShaderChunk/dithering_pars_fragment.glsl

@@ -1,14 +1,18 @@
-// based on https://www.shadertoy.com/view/MslGR8
-vec3 dithering( vec3 color ) {
-	//Calculate grid position
-	float grid_position = fract( dot( gl_FragCoord.xy - vec2( 0.5, 0.5 ) , vec2( 1.0 / 16.0, 10.0 / 36.0 ) + 0.25 ) );
+#if defined( DITHERING )
 
-	//Shift the individual colors differently, thus making it even harder to see the dithering pattern
-	vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );
+	// based on https://www.shadertoy.com/view/MslGR8
+	vec3 dithering( vec3 color ) {
+		//Calculate grid position
+		float grid_position = rand( gl_FragCoord.xy );
 
-	//modify shift acording to grid position.
-	dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );
+		//Shift the individual colors differently, thus making it even harder to see the dithering pattern
+		vec3 dither_shift_RGB = vec3( 0.25 / 255.0, -0.25 / 255.0, 0.25 / 255.0 );
 
-	//shift the color by dither_shift
-	return color + 0.5 / 255.0 + dither_shift_RGB;
-}
+		//modify shift acording to grid position.
+		dither_shift_RGB = mix( 2.0 * dither_shift_RGB, -2.0 * dither_shift_RGB, grid_position );
+
+		//shift the color by dither_shift
+		return color + dither_shift_RGB;
+	}
+
+#endif

+ 3 - 3
src/renderers/shaders/ShaderChunk/lights_phong_pars_fragment.glsl

@@ -35,9 +35,9 @@ struct BlinnPhongMaterial {
 				geometry,
 				rectAreaLight.position, rectAreaLight.halfWidth, rectAreaLight.halfHeight );
 
-		// TODO (abelnation): note why division by 2PI is necessary
-		reflectedLight.directSpecular += lightColor * matSpecColor * spec / PI2;
-		reflectedLight.directDiffuse  += lightColor * matDiffColor * diff / PI2;
+		// division by 2 * PI is moved inside the above calls. This is essential as Eq (11) is having this normalization.
+		reflectedLight.directSpecular += lightColor * matSpecColor * spec;
+		reflectedLight.directDiffuse  += lightColor * matDiffColor * diff;
 
 	}
 #endif

+ 1 - 0
src/renderers/shaders/ShaderChunk/lights_physical_pars_fragment.glsl

@@ -38,6 +38,7 @@ float clearCoatDHRApprox( const in float roughness, const in float dotNL ) {
 				geometry,
 				rectAreaLight.position, rectAreaLight.halfWidth, rectAreaLight.halfHeight );
 
+		// division by 2 * PI is inside the above calls. This is essential as Eq (11) is having this normalization.
 		reflectedLight.directSpecular += lightColor * matSpecColor * spec;
 		reflectedLight.directDiffuse  += lightColor * matDiffColor * diff;
 

+ 3 - 2
src/renderers/shaders/ShaderLib/meshlambert_frag.glsl

@@ -12,6 +12,7 @@ varying vec3 vLightFront;
 
 #include <common>
 #include <packing>
+#include <dithering_pars_fragment>
 #include <color_pars_fragment>
 #include <uv_pars_fragment>
 #include <uv2_pars_fragment>
@@ -75,10 +76,10 @@ void main() {
 
 	gl_FragColor = vec4( outgoingLight, diffuseColor.a );
 
-	#include <dithering_fragment>
-	#include <premultiplied_alpha_fragment>
 	#include <tonemapping_fragment>
 	#include <encodings_fragment>
 	#include <fog_fragment>
+	#include <premultiplied_alpha_fragment>
+	#include <dithering_fragment>
 
 }

+ 3 - 2
src/renderers/shaders/ShaderLib/meshphong_frag.glsl

@@ -8,6 +8,7 @@ uniform float opacity;
 
 #include <common>
 #include <packing>
+#include <dithering_pars_fragment>
 #include <color_pars_fragment>
 #include <uv_pars_fragment>
 #include <uv2_pars_fragment>
@@ -60,10 +61,10 @@ void main() {
 
 	gl_FragColor = vec4( outgoingLight, diffuseColor.a );
 
-	#include <dithering_fragment>
-	#include <premultiplied_alpha_fragment>
 	#include <tonemapping_fragment>
 	#include <encodings_fragment>
 	#include <fog_fragment>
+	#include <premultiplied_alpha_fragment>
+	#include <dithering_fragment>
 
 }

+ 3 - 2
src/renderers/shaders/ShaderLib/meshphysical_frag.glsl

@@ -21,6 +21,7 @@ varying vec3 vViewPosition;
 
 #include <common>
 #include <packing>
+#include <dithering_pars_fragment>
 #include <color_pars_fragment>
 #include <uv_pars_fragment>
 #include <uv2_pars_fragment>
@@ -74,10 +75,10 @@ void main() {
 
 	gl_FragColor = vec4( outgoingLight, diffuseColor.a );
 
-	#include <dithering_fragment>
-	#include <premultiplied_alpha_fragment>
 	#include <tonemapping_fragment>
 	#include <encodings_fragment>
 	#include <fog_fragment>
+	#include <premultiplied_alpha_fragment>
+	#include <dithering_fragment>
 
 }

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

@@ -152,7 +152,7 @@ function replaceLightNums( string, parameters ) {
 
 function parseIncludes( string ) {
 
-	var pattern = /^\s*#include +<([\w\d.]+)>/gm;
+	var pattern = /^[ \t]*#include +<([\w\d.]+)>/gm;
 
 	function replace( match, include ) {
 
@@ -478,7 +478,6 @@ function WebGLProgram( renderer, code, material, parameters ) {
 			( parameters.toneMapping !== NoToneMapping ) ? getToneMappingFunction( "toneMapping", parameters.toneMapping ) : '',
 
 			parameters.dithering ? '#define DITHERING' : '',
-			parameters.dithering ? ShaderChunk[ 'dithering_pars_fragment' ] : '',
 
 			( parameters.outputEncoding || parameters.mapEncoding || parameters.envMapEncoding || parameters.emissiveMapEncoding ) ? ShaderChunk[ 'encodings_pars_fragment' ] : '', // this code is required here because it is used by the various encoding/decoding function defined below
 			parameters.mapEncoding ? getTexelDecodingFunction( 'mapTexelToLinear', parameters.mapEncoding ) : '',

+ 1 - 1
src/renderers/webgl/WebGLRenderLists.js

@@ -152,7 +152,7 @@ function WebGLRenderLists() {
 
 		if ( list === undefined ) {
 
-			console.log( 'THREE.WebGLRenderLists:', hash );
+			// console.log( 'THREE.WebGLRenderLists:', hash );
 
 			list = new WebGLRenderList();
 			lists[ hash ] = list;

+ 29 - 24
src/renderers/webgl/WebGLShadowMap.js

@@ -135,6 +135,10 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 			}
 
 			var shadowCamera = shadow.camera;
+			var shadowMatrix = shadow.matrix;
+
+			_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
+			shadowCamera.position.copy( _lightPositionWorld );
 
 			_shadowMapSize.copy( shadow.mapSize );
 			_shadowMapSize.min( _maxShadowMapSize );
@@ -176,11 +180,34 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 				_shadowMapSize.x *= 4.0;
 				_shadowMapSize.y *= 2.0;
 
+
+				// for point lights we set the shadow matrix to be a translation-only matrix
+				// equal to inverse of the light's position
+
+				shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z );
+
 			} else {
 
 				faceCount = 1;
 				isPointLight = false;
 
+				_lookTarget.setFromMatrixPosition( light.target.matrixWorld );
+				shadowCamera.lookAt( _lookTarget );
+				shadowCamera.updateMatrixWorld();
+				shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
+
+				// compute shadow matrix
+
+				shadowMatrix.set(
+					0.5, 0.0, 0.0, 0.5,
+					0.0, 0.5, 0.0, 0.5,
+					0.0, 0.0, 0.5, 0.5,
+					0.0, 0.0, 0.0, 1.0
+				);
+
+				shadowMatrix.multiply( shadowCamera.projectionMatrix );
+				shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
+
 			}
 
 			if ( shadow.map === null ) {
@@ -201,10 +228,6 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 			}
 
 			var shadowMap = shadow.map;
-			var shadowMatrix = shadow.matrix;
-
-			_lightPositionWorld.setFromMatrixPosition( light.matrixWorld );
-			shadowCamera.position.copy( _lightPositionWorld );
 
 			_renderer.setRenderTarget( shadowMap );
 			_renderer.clear();
@@ -220,32 +243,14 @@ function WebGLShadowMap( _renderer, _lights, _objects, capabilities ) {
 					_lookTarget.add( cubeDirections[ face ] );
 					shadowCamera.up.copy( cubeUps[ face ] );
 					shadowCamera.lookAt( _lookTarget );
+					shadowCamera.updateMatrixWorld();
+					shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
 
 					var vpDimensions = cube2DViewPorts[ face ];
 					_state.viewport( vpDimensions );
 
-				} else {
-
-					_lookTarget.setFromMatrixPosition( light.target.matrixWorld );
-					shadowCamera.lookAt( _lookTarget );
-
 				}
 
-				shadowCamera.updateMatrixWorld();
-				shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
-
-				// compute shadow matrix
-
-				shadowMatrix.set(
-					0.5, 0.0, 0.0, 0.5,
-					0.0, 0.5, 0.0, 0.5,
-					0.0, 0.0, 0.5, 0.5,
-					0.0, 0.0, 0.0, 1.0
-				);
-
-				shadowMatrix.multiply( shadowCamera.projectionMatrix );
-				shadowMatrix.multiply( shadowCamera.matrixWorldInverse );
-
 				// update camera matrices and frustum
 
 				_projScreenMatrix.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );

+ 10 - 1
test/unit/src/math/Math.js

@@ -24,7 +24,7 @@ QUnit.test( "Math.sign/polyfill", function( assert ) {
 	assert.ok( isNaN( Math.sign(new THREE.Vector3()) ) , "If x is NaN<object>, the result is NaN.");
 	assert.ok( isNaN( Math.sign() ) , "If x is NaN<undefined>, the result is NaN.");
 	assert.ok( isNaN( Math.sign('--3') ) , "If x is NaN<'--3'>, the result is NaN.");
-	assert.ok( Math.sign(-0) === -0 , "If x is -0, the result is -0.");
+	assert.ok( isNegativeZero( Math.sign(-0) ) , "If x is -0, the result is -0.");
 	assert.ok( Math.sign(+0) === +0 , "If x is +0, the result is +0.");
 	assert.ok( Math.sign(-Infinity) === -1 , "If x is negative<-Infinity> and not -0, the result is -1.");
 	assert.ok( Math.sign('-3') === -1 , "If x is negative<'-3'> and not -0, the result is -1.");
@@ -32,4 +32,13 @@ QUnit.test( "Math.sign/polyfill", function( assert ) {
 	assert.ok( Math.sign(+Infinity) === +1 , "If x is positive<+Infinity> and not +0, the result is +1.");
 	assert.ok( Math.sign('+3') === +1 , "If x is positive<'+3'> and not +0, the result is +1.");
 
+	// Comparing with -0 is tricky because 0 === -0. But
+	// luckily 1 / -0 === -Infinity so we can use that.
+
+	function isNegativeZero( value ) {
+
+		return value === 0 && 1 / value < 0;
+
+	}
+
 });

+ 1 - 0
utils/exporters/blender/addons/io_three/exporter/material.py

@@ -45,6 +45,7 @@ class Material(base_classes.BaseNode):
 
         if api.material.transparent(self.node):
             self[constants.TRANSPARENT] = True
+            self[constants.OPACITY] = api.material.opacity(self.node)
 
         if api.material.double_sided(self.node):
             self[constants.SIDE] = constants.SIDE_DOUBLE

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно