فهرست منبع

Merge branch 'master' into dev

Tony Parisi 9 سال پیش
والد
کامیت
a2a64b4337
100فایلهای تغییر یافته به همراه4222 افزوده شده و 1092 حذف شده
  1. 1 1
      .github/ISSUE_TEMPLATE.md
  2. 114 81
      build/three.js
  3. 51 51
      build/three.min.js
  4. 52 0
      docs/api/extras/geometries/LatheBufferGeometry.html
  5. 6 5
      docs/api/extras/geometries/LatheGeometry.html
  6. 57 0
      docs/api/extras/geometries/TorusKnotBufferGeometry.html
  7. 9 8
      docs/api/extras/geometries/TorusKnotGeometry.html
  8. 14 4
      docs/api/lights/AmbientLight.html
  9. 1 0
      docs/api/lights/DirectionalLight.html
  10. 6 5
      docs/api/lights/HemisphereLight.html
  11. 15 6
      docs/api/lights/PointLight.html
  12. 9 0
      docs/api/lights/SpotLight.html
  13. 0 5
      docs/api/renderers/WebGLRenderTarget.html
  14. 1 1
      docs/index.html
  15. 2 0
      docs/list.js
  16. 4 9
      docs/manual/introduction/Creating-a-scene.html
  17. 1 0
      docs/page.css
  18. 10 10
      docs/scenes/bones-browser.html
  19. 21 19
      docs/scenes/geometry-browser.html
  20. 115 10
      docs/scenes/js/geometry.js
  21. 12 12
      docs/scenes/material-browser.html
  22. 3 4
      editor/js/Menubar.Add.js
  23. 10 2
      editor/js/Sidebar.Geometry.LatheGeometry.js
  24. 12 23
      editor/js/Sidebar.Geometry.TorusKnotGeometry.js
  25. 0 4
      editor/js/libs/tern-threejs/threejs.js
  26. 2 1
      examples/canvas_ascii_effect.html
  27. 2 1
      examples/canvas_camera_orthographic.html
  28. 2 1
      examples/canvas_camera_orthographic2.html
  29. 2 1
      examples/canvas_geometry_birds.html
  30. 2 1
      examples/canvas_geometry_cube.html
  31. 3 1
      examples/files.js
  32. 6 8
      examples/js/ParametricGeometries.js
  33. 448 0
      examples/js/Volume.js
  34. 217 0
      examples/js/VolumeSlice.js
  35. 8 2
      examples/js/WebVR.js
  36. 4 12
      examples/js/controls/OrbitControls.js
  37. 15 0
      examples/js/libs/inflate.min.js
  38. 51 0
      examples/js/libs/zlib_and_gzip.min.js
  39. 4 0
      examples/js/libs/zlib_and_gzip.min.js.map
  40. 1 1
      examples/js/loaders/HDRCubeTextureLoader.js
  41. 591 0
      examples/js/loaders/NRRDLoader.js
  42. 571 16
      examples/js/loaders/VTKLoader.js
  43. 10 0
      examples/js/pmrem/PMREMCubeUVPacker.js
  44. 25 20
      examples/js/pmrem/PMREMGenerator.js
  45. 1 1
      examples/js/postprocessing/EffectComposer.js
  46. BIN
      examples/models/nrrd/I.nrrd
  47. 80 0
      examples/models/vtk/cube_ascii.vtp
  48. 54 0
      examples/models/vtk/cube_binary.vtp
  49. 54 0
      examples/models/vtk/cube_no_compression.vtp
  50. BIN
      examples/models/vtk/liver.vtk
  51. BIN
      examples/textures/hardwood2_bump.jpg
  52. BIN
      examples/textures/hardwood2_diffuse.jpg
  53. BIN
      examples/textures/hardwood2_roughness.jpg
  54. 14 14
      examples/webgl_animation_cloth.html
  55. 3 1
      examples/webgl_animation_skinning_blending.html
  56. 2 1
      examples/webgl_animation_skinning_morph.html
  57. 1 2
      examples/webgl_effects_stereo.html
  58. 3 5
      examples/webgl_geometries2.html
  59. 315 0
      examples/webgl_lights_physical.html
  60. 22 45
      examples/webgl_lights_pointlights2.html
  61. 4 4
      examples/webgl_loader_msgpack.html
  62. 276 0
      examples/webgl_loader_nrrd.html
  63. 58 4
      examples/webgl_loader_vtk.html
  64. 3 3
      examples/webgl_materials_displacementmap.html
  65. 27 27
      examples/webgl_materials_envmaps_hdr.html
  66. 1 1
      examples/webgl_materials_nodes.html
  67. 44 13
      examples/webgl_materials_standard.html
  68. 2 1
      examples/webgl_materials_texture_manualmipmap.html
  69. 9 18
      examples/webgl_materials_transparency.html
  70. 2 1
      examples/webgl_materials_variations_phong.html
  71. 52 34
      examples/webgl_morphtargets_human.html
  72. 15 15
      examples/webgl_particles_general.html
  73. 2 1
      examples/webgl_postprocessing_advanced.html
  74. 2 1
      examples/webgl_postprocessing_dof.html
  75. 2 1
      examples/webgl_postprocessing_godrays.html
  76. 3 2
      examples/webgl_postprocessing_msaa.html
  77. 3 1
      examples/webgl_postprocessing_smaa.html
  78. 2 1
      examples/webgl_postprocessing_ssao.html
  79. 2 1
      examples/webgl_shading_physical.html
  80. 21 56
      examples/webgl_shadowmap.html
  81. 2 1
      examples/webgl_shadowmap_performance.html
  82. 2 2
      examples/webgl_shadowmap_viewer.html
  83. 4 3
      examples/webgl_tonemapping.html
  84. 80 92
      examples/webvr_cubes.html
  85. 156 0
      examples/webvr_panorama.html
  86. 11 6
      examples/webvr_rollercoaster.html
  87. 0 227
      examples/webvr_stereo_pano.html
  88. 18 2
      examples/webvr_video.html
  89. 1 1
      package.json
  90. 1 2
      src/Three.js
  91. 156 0
      src/extras/geometries/LatheBufferGeometry.js
  92. 3 76
      src/extras/geometries/LatheGeometry.js
  93. 164 0
      src/extras/geometries/TorusKnotBufferGeometry.js
  94. 6 92
      src/extras/geometries/TorusKnotGeometry.js
  95. 20 0
      src/lights/PointLight.js
  96. 20 0
      src/lights/SpotLight.js
  97. 1 1
      src/loaders/CubeTextureLoader.js
  98. 4 4
      src/loaders/ObjectLoader.js
  99. 2 2
      src/materials/LineBasicMaterial.js
  100. 2 2
      src/materials/LineDashedMaterial.js

+ 1 - 1
.github/ISSUE_TEMPLATE.md

@@ -5,7 +5,7 @@
 ##### Three.js version
 
 - [ ] Dev
-- [ ] r74
+- [ ] r75
 - [ ] ...
 
 ##### Browser

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 114 - 81
build/three.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 51 - 51
build/three.min.js


+ 52 - 0
docs/api/extras/geometries/LatheBufferGeometry.html

@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:BufferGeometry] &rarr;
+
+		<h1>[name]</h1>
+
+		<div class="desc">This is the [page:BufferGeometry] port of [page:LatheGeometry].</div>
+
+
+		<h2>Example</h2>
+
+		<iframe src='scenes/geometry-browser.html#LatheBufferGeometry'></iframe>
+
+		<code>
+		var points = [];
+		for ( var i = 0; i < 10; i ++ ) {
+			points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) );
+		}
+		var geometry = new THREE.LatheBufferGeometry( points );
+		var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
+		var lathe = new THREE.Mesh( geometry, material );
+		scene.add( lathe );
+		</code>
+
+		<h2>Constructor</h2>
+
+
+		<h3>[name]([page:Array points], [page:Integer segments], [page:Float phiStart], [page:Float phiLength])</h3>
+		<div>
+		points — Array of Vector2s. The x-coordinate of each point must be greater than zero.<br />
+		segments — the number of circumference segments to generate. Default is 12.<br />
+		phiStart — the starting angle in radians. Default is 0.<br />
+		phiLength — the radian (0 to 2PI) range of the lathed section 2PI is a closed lathe, less than 2PI is a portion. Default is 2PI.
+		</div>
+		<div>
+		This creates a LatheBufferGeometry based on the parameters.
+		</div>
+
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 6 - 5
docs/api/extras/geometries/LatheGeometry.html

@@ -17,11 +17,12 @@
 
 		<h2>Example</h2>
 
+		<iframe src='scenes/geometry-browser.html#LatheGeometry'></iframe>
+
 		<code>
 		var points = [];
 		for ( var i = 0; i < 10; i ++ ) {
-			points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 15 + 50, ( i - 5 ) * 2 ) );
-
+			points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) );
 		}
 		var geometry = new THREE.LatheGeometry( points );
 		var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
@@ -34,13 +35,13 @@
 
 		<h3>[name]([page:Array points], [page:Integer segments], [page:Float phiStart], [page:Float phiLength])</h3>
 		<div>
-		points — Array of Vector2s.<br />
+		points — Array of Vector2s. The x-coordinate of each point must be greater than zero.<br />
 		segments — the number of circumference segments to generate. Default is 12.<br />
 		phiStart — the starting angle in radians. Default is 0.<br />
-		phiLength — the radian (0 to 2*PI) range of the lathed section 2*PI is a closed lathe, less than 2PI is a portion. Default is 2*PI
+		phiLength — the radian (0 to 2PI) range of the lathed section 2PI is a closed lathe, less than 2PI is a portion. Default is 2PI.
 		</div>
 		<div>
-		This creates a LatheGeometry based on the parameters.
+		This creates a LatheBufferGeometry based on the parameters.
 		</div>
 
 

+ 57 - 0
docs/api/extras/geometries/TorusKnotBufferGeometry.html

@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<meta charset="utf-8" />
+		<base href="../../../" />
+		<script src="list.js"></script>
+		<script src="page.js"></script>
+		<link type="text/css" rel="stylesheet" href="page.css" />
+	</head>
+	<body>
+		[page:BufferGeometry] &rarr;
+
+		<h1>[name]</h1>
+
+		<div class="desc">This is the [page:BufferGeometry] port of [page:TorusKnotGeometry].</div>
+
+		<iframe src='scenes/geometry-browser.html#TorusKnotBufferGeometry'></iframe>
+
+
+		<h2>Example</h2>
+
+		<code>var geometry = new THREE.TorusKnotBufferGeometry( 10, 3, 100, 16 );
+		var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
+		var torusKnot = new THREE.Mesh( geometry, material );
+		scene.add( torusKnot );
+		</code>
+
+
+		<h2>Constructor</h2>
+
+
+		<h3>[name]([page:Float radius], [page:Float tube], [page:Integer tubularSegments], [page:Integer radialSegments], [page:Integer p], [page:Integer q])</h3>
+		<div>
+			<ul>
+				<li>radius — Default is 100.</li>
+				<li>tube — Diameter of the tube. Default is 40.</li>
+				<li>tubularSegments — Default is 64.</li>
+				<li>radialSegments — Default is 8.</li>
+				<li>p — This value determines, how many times the geometry winds around its axis of rotational symmetry. Default is 2.</li>
+				<li>q — This value determines, how many times the geometry winds around a circle in the interior of the torus. Default is 3.</li>
+			</ul>
+		</div>
+
+
+		<h2>Properties</h2>
+
+
+		<div>
+		Each of the contructor parameters is accessible as a property of the same name. Any modification of these properties after instantiation does not change the geometry.
+		</div>
+
+
+		<h2>Source</h2>
+
+		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
+	</body>
+</html>

+ 9 - 8
docs/api/extras/geometries/TorusKnotGeometry.html

@@ -29,15 +29,16 @@
 		<h2>Constructor</h2>
 
 
-		<h3>[name]([page:Float radius], [page:Float tube], [page:Integer radialSegments], [page:Integer tubularSegments], [page:Integer p], [page:Integer q], [page:Float heightScale])</h3>
+		<h3>[name]([page:Float radius], [page:Float tube], [page:Integer tubularSegments], [page:Integer radialSegments], [page:Integer p], [page:Integer q])</h3>
 		<div>
-		radius — Default is 100. <br />
-		tube — Default is 40. <br />
-		radialSegments — Default is 64. <br />
-		tubularSegments — Default is 8. <br />
-		p — Default is 2. <br />
-		q — Default is 3. <br />
-		heightScale — Default is 1.
+			<ul>
+				<li>radius — Default is 100.</li>
+				<li>tube — Diameter of the tube. Default is 40.</li>
+				<li>tubularSegments — Default is 64.</li>
+				<li>radialSegments — Default is 8.</li>
+				<li>p — This value determines, how many times the geometry winds around its axis of rotational symmetry. Default is 2.</li>
+				<li>q — This value determines, how many times the geometry winds around a circle in the interior of the torus. Default is 3.</li>
+			</ul>
 		</div>
 
 

+ 14 - 4
docs/api/lights/AmbientLight.html

@@ -24,7 +24,7 @@
 		<div>[example:canvas_sandbox sandbox ]</div>
 		<div>[example:webgl_animation_cloth animation / cloth ]</div>
 		<div>[example:webgl_animation_skinning_blending animation / skinning / blending ]</div>
-		
+
 <code>var light = new THREE.AmbientLight( 0x404040 ); // soft white light
 scene.add( light );</code>
 
@@ -39,19 +39,29 @@ scene.add( light );</code>
 		This creates an Ambientlight with a color.
 		</div>
 
+		<h2>Properties</h2>
+
+		<h3>[property:Float intensity]</h3>
+		<div>
+			Light's intensity.<br />
+			In "physically correct" mode, the product of color * intensity is interpreted as luminous irradiance measured in lux at the material surface.<br/>
+			Default — *1.0*.
+		</div>
+
+
 		<h2>Methods</h2>
-		
+
 		<h3>[method:AmbientLight clone]()</h3>
 		<div>
 		<br />
 		It returns a clone of Ambientlight.
 		</div>
-		
+
 		<h3>[method:JSON toJSON]()</h3>
 		<div>
 		Return Ambientlight data in JSON format.
 		</div>
-		
+
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 1 - 0
docs/api/lights/DirectionalLight.html

@@ -60,6 +60,7 @@ scene.add( directionalLight );</code>
 		<h3>[property:Float intensity]</h3>
 		<div>
 			Light's intensity.<br />
+			In "physically correct" mode, the product of intensity * color is interpreted as luminous irradiance measured in lux at the material's surface.<br/>
 			Default — *1.0*.
 		</div>
 

+ 6 - 5
docs/api/lights/HemisphereLight.html

@@ -13,16 +13,16 @@
 		<h1>[name]</h1>
 
 		<div class="desc">A light source positioned directly above the scene.</div>
-		
+
 		<h2>Example</h2>
-		
+
 		<div>[example:webgl_lights_hemisphere lights / hemisphere ]</div>
 		<div>[example:misc_controls_pointerlock controls / pointerlock ]</div>
 		<div>[example:webgl_decals decals ]</div>
 		<div>[example:webgl_loader_collada_kinematics loader / collada / kinematics ]</div>
 		<div>[example:webgl_materials_lightmap materials / lightmap ]</div>
 		<div>[example:webgl_shaders_ocean shaders / ocean ]</div>
-		
+
 <code>var light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
 scene.add( light );</code>
 
@@ -47,17 +47,18 @@ scene.add( light );</code>
 		<h3>[property:Float intensity]</h3>
 		<div>
 			Light's intensity.<br />
+			In "physically correct" mode, the product of intensity * color (or intensity * groundColor) is interpreted as luminous irradiance measured in lux at the material's surface.<br/>
 			Default — *1.0*.
 		</div>
 
 		<h2>Methods</h2>
-		
+
 		<h3>[method:HemisphereLight clone]()</h3>
 		<div>
 		<br />
 		It returns a clone of HemisphereLight.
 		</div>
-		
+
 		<h3>[method:JSON toJSON]()</h3>
 		<div>
 		Return HemisphereLight data in JSON format.

+ 15 - 6
docs/api/lights/PointLight.html

@@ -28,7 +28,7 @@
 		<div>[example:webgl_geometry_large_mesh geometry / large / mesh ]</div>
 		<div>[example:webgl_geometry_text geometry / text ]</div>
 		<div>[example:webgl_lensflares lensflares ]</div>
-		
+
 		<code>var light = new THREE.PointLight( 0xff0000, 1, 100 );
 light.position.set( 50, 50, 50 );
 scene.add( light );</code>
@@ -46,7 +46,7 @@ scene.add( light );</code>
 		</div>
 		<div>
 		Creates a light at a specific position in the scene.  The light shines in all directions (roughly similar to a light bulb.)
-	
+
 		</div>
 
 
@@ -55,29 +55,38 @@ scene.add( light );</code>
 		<h3>[property:Float intensity]</h3>
 		<div>
 			Light's intensity.<br />
+			In "physically correct" mode, the product of color * intensity is interpreted as luminous intensity measured in candela.<br/>
 			Default - *1.0*.
 		</div>
 
+		<h3>[property:Float power]</h3>
+		<div>
+			Light's power.<br />
+			In "physically correct" mode, the luminous power of the light measured in lumens.<br/>
+			Default - *4PI*.
+		</div>
+
 		<h3>[property:Float distance]</h3>
 		<div>
 			If non-zero, light will attenuate linearly from maximum intensity at light *position* down to zero at *distance*.<br />
 			Default — *0.0*.
 		</div>
-		
+
 		<h3>[property:Float decay]</h3>
 		<div>
 			The amount the light dims along the distance of the light<br />
+			In "physically correct" mode, decay = 2 leads to physically realistic light falloff.<br/>
 			Default — *1*.
 		</div>
-		
+
 		<h2>Methods</h2>
-		
+
 		<h3>[method:PointLight clone]()</h3>
 		<div>
 		<br />
 		It returns a clone of PointLight.
 		</div>
-		
+
 		<h3>[method:JSON toJSON]()</h3>
 		<div>
 		Return PointLight data in JSON format.

+ 9 - 0
docs/api/lights/SpotLight.html

@@ -77,9 +77,17 @@
 		<h3>[property:Float intensity]</h3>
 		<div>
 			Light's intensity.<br />
+			In "physically correct" mode, the product of color * intensity is interpreted as luminous intensity measured in candela.<br/>
 			Default — *1.0*.
 		</div>
 
+		<h3>[property:Float power]</h3>
+		<div>
+			Light's power.<br />
+			In "physically correct" mode, the luminous power of the light measured in lumens.<br/>
+			Default - *4PI*.
+		</div>
+
 		<h3>[property:Float distance]</h3>
 		<div>
 			If non-zero, light will attenuate linearly from maximum intensity at light *position* down to zero at *distance*.<br />
@@ -101,6 +109,7 @@
 		<h3>[property:Float decay]</h3>
 		<div>
 			The amount the light dims along the distance of the light<br />
+			In "physically correct" mode, decay = 2 leads to physically realistic light falloff.<br/>
 			Default — *1*.
 		</div>
 

+ 0 - 5
docs/api/renderers/WebGLRenderTarget.html

@@ -88,11 +88,6 @@
 		Whether to generate mipmaps (if possible) for a texture. True by default.
 		</div>
 
-		<h3>[property:WebGLRenderTarget shareDepthFrom]</h3>
-		<div>
-		Shares the depth from another WebGLRenderTarget. Default is null.
-		</div>
-
 		
 		<h2>Methods</h2>
 		

+ 1 - 1
docs/index.html

@@ -1,4 +1,4 @@
-<!doctype html>
+<!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8">

+ 2 - 0
docs/list.js

@@ -200,6 +200,7 @@ var list = {
 			[ "DodecahedronGeometry", "api/extras/geometries/DodecahedronGeometry" ],
 			[ "ExtrudeGeometry", "api/extras/geometries/ExtrudeGeometry" ],
 			[ "IcosahedronGeometry", "api/extras/geometries/IcosahedronGeometry" ],
+			[ "LatheBufferGeometry", "api/extras/geometries/LatheBufferGeometry" ],
 			[ "LatheGeometry", "api/extras/geometries/LatheGeometry" ],
 			[ "OctahedronGeometry", "api/extras/geometries/OctahedronGeometry" ],
 			[ "ParametricGeometry", "api/extras/geometries/ParametricGeometry" ],
@@ -215,6 +216,7 @@ var list = {
 			[ "TextGeometry", "api/extras/geometries/TextGeometry" ],
 			[ "TorusBufferGeometry", "api/extras/geometries/TorusBufferGeometry" ],
 			[ "TorusGeometry", "api/extras/geometries/TorusGeometry" ],
+			[ "TorusKnotBufferGeometry", "api/extras/geometries/TorusKnotBufferGeometry" ],
 			[ "TorusKnotGeometry", "api/extras/geometries/TorusKnotGeometry" ],
 			[ "TubeGeometry", "api/extras/geometries/TubeGeometry" ]
 		],

+ 4 - 9
docs/manual/introduction/Creating-a-scene.html

@@ -8,17 +8,12 @@
 		<link type="text/css" rel="stylesheet" href="page.css" />
 	</head>
 	<body>
-		<h1>[name]</h1>
+		<h1>[name]</h1><br />
 
 		<div>The goal of this section is to give a brief introduction to Three.js. We will start by setting up a scene, with a spinning cube. A working example is provided at the bottom of the page in case you get stuck and need help.</div>
 
-		<h2>What is Three.js?</h2>
-
-		<div>Let's try to describe it briefly:</div>
-
-		<div>Three.js is a library that makes WebGL - 3D in the browser - easy to use. While a simple cube in raw WebGL would turn out hundreds of lines of Javascript and shader code, a Three.js equivalent is only a fraction of that.</div>
-
 		<h2>Before we start</h2>
+
 		<div>Before you can use Three.js, you need somewhere to display it. Save the following HTML to a file on your computer, along with a copy of <a href="http://threejs.org/build/three.js">three.js</a> in the js/ directory, and open it in your browser.</div>
 
 		<code>
@@ -65,9 +60,9 @@
 		<div>Next up is the renderer. This is where the magic happens. In addition to the WebGLRenderer we use here, Three.js comes with a few others, often used as fallbacks for users with older browsers or for those who don't have WebGL support for some reason.</div>
 
 		<div>In addition to creating the renderer instance, we also need to set the size at which we want it to render our app. It's a good idea to use the width and height of the area we want to fill with our app - in this case, the width and height of the browser window. For performance intensive apps, you can also give <strong>setSize</strong> smaller values, like <strong>window.innerWidth/2</strong> and <strong>window.innerHeight/2</strong>, which will make the app render at half size.</div>
-		
+
 		<div>If you wish to keep the size of your app but render it at a lower resolution, you can do so by calling <strong>setSize</strong> with false as <strong>updateStyle</strong>. For example, <strong>setSize(window.innerWidth/2, window.innerHeight/2, false)</strong> will render your app at half resolution, given that your &lt;canvas&gt; has 100% width and height.</div>
-		
+
 		<div>Last but not least, we add the <strong>renderer</strong> element to our HTML document. This is a &lt;canvas&gt; element the renderer uses to display the scene to us.</div>
 
 		<div><em>"That's all good, but where's that cube you promised?"</em> Let's add it now.</div>

+ 1 - 0
docs/page.css

@@ -11,6 +11,7 @@ body {
 	font-family: 'inconsolata';
 	font-size: 15px;
 	line-height: 18px;
+	tab-size: 4;
 	overflow: auto;
 }
 

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

@@ -1,4 +1,4 @@
-<!doctype html>
+<!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8">
@@ -57,7 +57,7 @@
 				camera.position.y = 30;
 
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
-				renderer.setPixelRatio( window.devicePixelRatio );				
+				renderer.setPixelRatio( window.devicePixelRatio );
 				renderer.setSize( window.innerWidth, window.innerHeight );
 				document.body.appendChild( renderer.domElement );
 
@@ -74,7 +74,7 @@
 
 				lights[ 0 ].position.set( 0, 200, 0 );
 				lights[ 1 ].position.set( 100, 200, 100 );
-				lights[ 2 ].position.set( -100, -200, -100 );
+				lights[ 2 ].position.set( - 100, - 200, - 100 );
 
 				scene.add( lights[ 0 ] );
 				scene.add( lights[ 1 ] );
@@ -128,7 +128,7 @@
 
 				var prevBone = new THREE.Bone();
 				bones.push( prevBone );
-				prevBone.position.y = -sizing.halfHeight;
+				prevBone.position.y = - sizing.halfHeight;
 
 				for ( var i = 0; i < sizing.segmentCount; i ++ ) {
 
@@ -187,13 +187,13 @@
 
 					folder = gui.addFolder( "Bone " + i );
 
-					folder.add( bone.position, 'x', -10 + bone.position.x, 10 + bone.position.x );
-					folder.add( bone.position, 'y', -10 + bone.position.y, 10 + bone.position.y );
-					folder.add( bone.position, 'z', -10 + bone.position.z, 10 + bone.position.z );
+					folder.add( bone.position, 'x', - 10 + bone.position.x, 10 + bone.position.x );
+					folder.add( bone.position, 'y', - 10 + bone.position.y, 10 + bone.position.y );
+					folder.add( bone.position, 'z', - 10 + bone.position.z, 10 + bone.position.z );
 
-					folder.add( bone.rotation, 'x', -Math.PI * 0.5, Math.PI * 0.5 );
-					folder.add( bone.rotation, 'y', -Math.PI * 0.5, Math.PI * 0.5 );
-					folder.add( bone.rotation, 'z', -Math.PI * 0.5, Math.PI * 0.5 );
+					folder.add( bone.rotation, 'x', - Math.PI * 0.5, Math.PI * 0.5 );
+					folder.add( bone.rotation, 'y', - Math.PI * 0.5, Math.PI * 0.5 );
+					folder.add( bone.rotation, 'z', - Math.PI * 0.5, Math.PI * 0.5 );
 
 					folder.add( bone.scale, 'x', 0, 2 );
 					folder.add( bone.scale, 'y', 0, 2 );

+ 21 - 19
docs/scenes/geometry-browser.html

@@ -1,4 +1,4 @@
-<!doctype html>
+<!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8">
@@ -42,11 +42,11 @@
 
 		<script>
 
-			document.getElementById('newWindow').href += window.location.hash;
+			document.getElementById( 'newWindow' ).href += window.location.hash;
 
 			var gui = new dat.GUI();
 			var scene = new THREE.Scene();
-			var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 50 );
+			var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 50 );
 			camera.position.z = 30;
 
 			var renderer = new THREE.WebGLRenderer( { antialias: true } );
@@ -61,17 +61,17 @@
 			scene.add( ambientLight );
 
 			var lights = [];
-			lights[0] = new THREE.PointLight( 0xffffff, 1, 0 );
-			lights[1] = new THREE.PointLight( 0xffffff, 1, 0 );
-			lights[2] = new THREE.PointLight( 0xffffff, 1, 0 );
+			lights[ 0 ] = new THREE.PointLight( 0xffffff, 1, 0 );
+			lights[ 1 ] = new THREE.PointLight( 0xffffff, 1, 0 );
+			lights[ 2 ] = new THREE.PointLight( 0xffffff, 1, 0 );
 
-			lights[0].position.set( 0, 200, 0 );
-			lights[1].position.set( 100, 200, 100 );
-			lights[2].position.set( -100, -200, -100 );
+			lights[ 0 ].position.set( 0, 200, 0 );
+			lights[ 1 ].position.set( 100, 200, 100 );
+			lights[ 2 ].position.set( - 100, - 200, - 100 );
 
-			scene.add( lights[0] );
-			scene.add( lights[1] );
-			scene.add( lights[2] );
+			scene.add( lights[ 0 ] );
+			scene.add( lights[ 1 ] );
+			scene.add( lights[ 2 ] );
 
 			var mesh = new THREE.Object3D()
 
@@ -79,26 +79,26 @@
 
 				new THREE.Geometry(),
 
-				new THREE.LineBasicMaterial({
+				new THREE.LineBasicMaterial( {
 					color: 0xffffff,
 					transparent: true,
 					opacity: 0.5
-				})
+				} )
 
-			));
+			) );
 
 			mesh.add( new THREE.Mesh(
 
 				new THREE.Geometry(),
 
-				new THREE.MeshPhongMaterial({
+				new THREE.MeshPhongMaterial( {
 					color: 0x156289,
 					emissive: 0x072534,
 					side: THREE.DoubleSide,
 					shading: THREE.FlatShading
-				})
+				} )
 
-			));
+			) );
 
 			var options = chooseFromHash( mesh );
 
@@ -112,9 +112,11 @@
 
 				var time = Date.now() * 0.001;
 
-				if( !options.fixed ) {
+				if ( ! options.fixed ) {
+
 					mesh.rotation.x += 0.005;
 					mesh.rotation.y += 0.005;
+
 				}
 
 				renderer.render( scene, camera );

+ 115 - 10
docs/scenes/js/geometry.js

@@ -365,6 +365,78 @@ var guis = {
 
 	},
 
+	LatheBufferGeometry : function() {
+
+		var points = [];
+
+		for ( var i = 0; i < 10; i ++ ) {
+
+			points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) );
+
+		}
+
+		var data = {
+			segments : 12,
+			phiStart : 0,
+			phiLength : twoPi,
+		};
+
+		function generateGeometry() {
+
+			var geometry = new THREE.LatheBufferGeometry(
+				points, data.segments, data.phiStart, data.phiLength
+			);
+
+			updateGroupGeometry( mesh, geometry );
+
+		}
+
+		var folder = gui.addFolder( 'THREE.LatheBufferGeometry' );
+
+		folder.add( data, 'segments', 1, 30 ).step( 1 ).onChange( generateGeometry );
+		folder.add( data, 'phiStart', 0, twoPi ).onChange( generateGeometry );
+		folder.add( data, 'phiLength', 0, twoPi ).onChange( generateGeometry );
+
+		generateGeometry();
+
+	},
+
+	LatheGeometry : function() {
+
+		var points = [];
+
+		for ( var i = 0; i < 10; i ++ ) {
+
+			points.push( new THREE.Vector2( Math.sin( i * 0.2 ) * 10 + 5, ( i - 5 ) * 2 ) );
+
+		}
+
+		var data = {
+			segments : 12,
+			phiStart : 0,
+			phiLength : twoPi,
+		};
+
+		function generateGeometry() {
+
+			var geometry = new THREE.LatheGeometry(
+				points, data.segments, data.phiStart, data.phiLength
+			);
+
+			updateGroupGeometry( mesh, geometry );
+
+		}
+
+		var folder = gui.addFolder( 'THREE.LatheGeometry' );
+
+		folder.add( data, 'segments', 1, 30 ).step( 1 ).onChange( generateGeometry );
+		folder.add( data, 'phiStart', 0, twoPi ).onChange( generateGeometry );
+		folder.add( data, 'phiLength', 0, twoPi ).onChange( generateGeometry );
+
+		generateGeometry();
+
+	},
+
 	OctahedronGeometry : function() {
 
 		var data = {
@@ -747,38 +819,71 @@ var guis = {
 
 	},
 
+	TorusKnotBufferGeometry : function( mesh ) {
+
+		var data = {
+			radius : 10,
+			tube : 3,
+			tubularSegments : 64,
+			radialSegments : 8,
+			p : 2,
+			q : 3
+		};
+
+		function generateGeometry() {
+
+			updateGroupGeometry( mesh,
+				new THREE.TorusKnotBufferGeometry(
+					data.radius, data.tube, data.tubularSegments, data.radialSegments,
+					data.p, data.q
+				)
+			);
+
+		}
+
+		var folder = gui.addFolder( 'THREE.TorusKnotBufferGeometry' );
+
+		folder.add( data, 'radius', 1, 20 ).onChange( generateGeometry );
+		folder.add( data, 'tube', 0.1, 10 ).onChange( generateGeometry );
+		folder.add( data, 'tubularSegments', 3, 300 ).step( 1 ).onChange( generateGeometry );
+		folder.add( data, 'radialSegments', 3, 20 ).step( 1 ).onChange( generateGeometry );
+		folder.add( data, 'p', 1, 20 ).step( 1 ).onChange( generateGeometry );
+		folder.add( data, 'q', 1, 20 ).step( 1 ).onChange( generateGeometry );
+
+		generateGeometry();
+
+	},
+
 	TorusKnotGeometry : function( mesh ) {
 
 		var data = {
 			radius : 10,
 			tube : 3,
-			radialSegments : 64,
-			tubularSegments : 8,
+			tubularSegments : 64,
+			radialSegments : 8,
 			p : 2,
-			q : 3,
-			heightScale : 1
+			q : 3
 		};
 
 		function generateGeometry() {
 
 			updateGroupGeometry( mesh,
 				new THREE.TorusKnotGeometry(
-					data.radius, data.tube, data.radialSegments, data.tubularSegments,
-					data.p, data.q, data.heightScale
+					data.radius, data.tube, data.tubularSegments, data.radialSegments,
+					data.p, data.q
 				)
 			);
 
 		}
 
-		var folder = gui.addFolder( 'THREE.TorusGeometry' );
+		var folder = gui.addFolder( 'THREE.TorusKnotGeometry' );
 
 		folder.add( data, 'radius', 1, 20 ).onChange( generateGeometry );
 		folder.add( data, 'tube', 0.1, 10 ).onChange( generateGeometry );
-		folder.add( data, 'radialSegments', 3, 300 ).step( 1 ).onChange( generateGeometry );
-		folder.add( data, 'tubularSegments', 3, 20 ).step( 1 ).onChange( generateGeometry );
+		folder.add( data, 'tubularSegments', 3, 300 ).step( 1 ).onChange( generateGeometry );
+		folder.add( data, 'radialSegments', 3, 20 ).step( 1 ).onChange( generateGeometry );
 		folder.add( data, 'p', 1, 20 ).step( 1 ).onChange( generateGeometry );
 		folder.add( data, 'q', 1, 20 ).step( 1 ).onChange( generateGeometry );
-		folder.add( data, 'heightScale', 1, 20 ).onChange( generateGeometry );
 
 		generateGeometry();
 

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

@@ -1,4 +1,4 @@
-<!doctype html>
+<!DOCTYPE html>
 <html lang="en">
 	<head>
 		<meta charset="utf-8">
@@ -40,11 +40,11 @@
 
 		<script>
 
-			document.getElementById('newWindow').href += window.location.hash;
+			document.getElementById( 'newWindow' ).href += window.location.hash;
 
 			var gui = new dat.GUI();
 			var scene = new THREE.Scene();
-			var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 50 );
+			var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 50 );
 			camera.position.z = 30;
 
 			var renderer = new THREE.WebGLRenderer( { antialias: true } );
@@ -56,17 +56,17 @@
 			scene.add( ambientLight );
 
 			var lights = [];
-			lights[0] = new THREE.PointLight( 0xffffff, 1, 0 );
-			lights[1] = new THREE.PointLight( 0xffffff, 1, 0 );
-			lights[2] = new THREE.PointLight( 0xffffff, 1, 0 );
+			lights[ 0 ] = new THREE.PointLight( 0xffffff, 1, 0 );
+			lights[ 1 ] = new THREE.PointLight( 0xffffff, 1, 0 );
+			lights[ 2 ] = new THREE.PointLight( 0xffffff, 1, 0 );
 
-			lights[0].position.set( 0, 200, 0 );
-			lights[1].position.set( 100, 200, 100 );
-			lights[2].position.set( -100, -200, -100 );
+			lights[ 0 ].position.set( 0, 200, 0 );
+			lights[ 1 ].position.set( 100, 200, 100 );
+			lights[ 2 ].position.set( - 100, - 200, - 100 );
 
-			scene.add( lights[0] );
-			scene.add( lights[1] );
-			scene.add( lights[2] );
+			scene.add( lights[ 0 ] );
+			scene.add( lights[ 1 ] );
+			scene.add( lights[ 2 ] );
 
 			guiScene( gui, scene, camera );
 

+ 3 - 4
editor/js/Menubar.Add.js

@@ -198,13 +198,12 @@ Menubar.Add = function ( editor ) {
 
 		var radius = 2;
 		var tube = 0.8;
-		var radialSegments = 64;
-		var tubularSegments = 12;
+		var tubularSegments = 64;
+		var radialSegments = 12;
 		var p = 2;
 		var q = 3;
-		var heightScale = 1;
 
-		var geometry = new THREE.TorusKnotGeometry( radius, tube, radialSegments, tubularSegments, p, q, heightScale );
+		var geometry = new THREE.TorusKnotGeometry( radius, tube, tubularSegments, radialSegments, p, q );
 		var mesh = new THREE.Mesh( geometry, new THREE.MeshStandardMaterial() );
 		mesh.name = 'TorusKnot ' + ( ++ meshCount );
 

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

@@ -63,9 +63,17 @@ Sidebar.Geometry.LatheGeometry = function( editor, object ) {
 
 	var addPointButton = new UI.Button( '+' ).onClick( function() {
 
-		var point = pointsUI[ pointsUI.length - 1 ];
+		if( pointsUI.length === 0 ){
 
-		pointsList.add( createPointRow( point.x.getValue(), point.y.getValue() ) );
+			pointsList.add( createPointRow( 0, 0 ) );
+
+		} else {
+
+			var point = pointsUI[ pointsUI.length - 1 ];
+
+			pointsList.add( createPointRow( point.x.getValue(), point.y.getValue() ) );
+
+		}
 
 		update();
 

+ 12 - 23
editor/js/Sidebar.Geometry.TorusKnotGeometry.js

@@ -30,16 +30,6 @@ Sidebar.Geometry.TorusKnotGeometry = function ( editor, object ) {
 
 	container.add( tubeRow );
 
-	// radialSegments
-
-	var radialSegmentsRow = new UI.Row();
-	var radialSegments = new UI.Integer( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
-
-	radialSegmentsRow.add( new UI.Text( 'Radial segments' ).setWidth( '90px' ) );
-	radialSegmentsRow.add( radialSegments );
-
-	container.add( radialSegmentsRow );
-
 	// tubularSegments
 
 	var tubularSegmentsRow = new UI.Row();
@@ -50,6 +40,16 @@ Sidebar.Geometry.TorusKnotGeometry = function ( editor, object ) {
 
 	container.add( tubularSegmentsRow );
 
+	// radialSegments
+
+	var radialSegmentsRow = new UI.Row();
+	var radialSegments = new UI.Integer( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
+
+	radialSegmentsRow.add( new UI.Text( 'Radial segments' ).setWidth( '90px' ) );
+	radialSegmentsRow.add( radialSegments );
+
+	container.add( radialSegmentsRow );
+
 	// p
 
 	var pRow = new UI.Row();
@@ -70,16 +70,6 @@ Sidebar.Geometry.TorusKnotGeometry = function ( editor, object ) {
 
 	container.add( qRow );
 
-	// heightScale
-
-	var heightScaleRow = new UI.Row();
-	var heightScale = new UI.Number( parameters.heightScale ).onChange( update );
-
-	pRow.add( new UI.Text( 'Height scale' ).setWidth( '90px' ) );
-	pRow.add( heightScale );
-
-	container.add( heightScaleRow );
-
 
 	//
 
@@ -88,11 +78,10 @@ Sidebar.Geometry.TorusKnotGeometry = function ( editor, object ) {
 		editor.execute( new SetGeometryCommand( object, new THREE.TorusKnotGeometry(
 			radius.getValue(),
 			tube.getValue(),
-			radialSegments.getValue(),
 			tubularSegments.getValue(),
+			radialSegments.getValue(),
 			p.getValue(),
-			q.getValue(),
-			heightScale.getValue()
+			q.getValue()
 		) ) );
 
 	}

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

@@ -5292,10 +5292,6 @@
           "!type": "boolean",
           "!doc": "Whether to generate mipmaps (if possible) for a texture. True by default."
         },
-        "shareDepthFrom": {
-          "!type": "+THREE.WebGLRenderTarget",
-          "!doc": "Shares the depth from another WebGLRenderTarget. Default is null."
-        },
         "setSize": {
           "!type": "fn(width: number, height: number)",
           "!doc": "Sets the size of the renderTarget."

+ 2 - 1
examples/canvas_ascii_effect.html

@@ -116,8 +116,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 2 - 1
examples/canvas_camera_orthographic.html

@@ -145,8 +145,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 2 - 1
examples/canvas_camera_orthographic2.html

@@ -208,8 +208,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 2 - 1
examples/canvas_geometry_birds.html

@@ -420,8 +420,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 2 - 1
examples/canvas_geometry_cube.html

@@ -193,8 +193,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 3 - 1
examples/files.js

@@ -57,6 +57,7 @@ var files = {
 		"webgl_kinect",
 		"webgl_lensflares",
 		"webgl_lights_hemisphere",
+		"webgl_lights_physical",
 		"webgl_lights_pointlights",
 		"webgl_lights_pointlights2",
 		"webgl_lines_colors",
@@ -88,6 +89,7 @@ var files = {
 		"webgl_loader_msgpack",
 		"webgl_loader_obj",
 		"webgl_loader_obj_mtl",
+		"webgl_loader_nrrd",
 		"webgl_loader_pcd",
 		"webgl_loader_pdb",
 		"webgl_loader_ply",
@@ -235,8 +237,8 @@ var files = {
 	],
 	"webvr": [
 		"webvr_cubes",
+		"webvr_panorama",
 		"webvr_rollercoaster",
-		"webvr_stereo_pano",
 		"webvr_video"
 	],
 	"css3d": [

+ 6 - 8
examples/js/ParametricGeometries.js

@@ -170,18 +170,16 @@ THREE.ParametricGeometries.TubeGeometry.prototype.constructor = THREE.Parametric
   * Parametric Replacement for TorusKnotGeometry
   *
   *********************************************/
-THREE.ParametricGeometries.TorusKnotGeometry = function ( radius, tube, segmentsR, segmentsT, p, q, heightScale ) {
+THREE.ParametricGeometries.TorusKnotGeometry = function ( radius, tube, segmentsT, segmentsR, p, q ) {
 
 	var scope = this;
 
 	this.radius = radius || 200;
 	this.tube = tube || 40;
-	this.segmentsR = segmentsR || 64;
-	this.segmentsT = segmentsT || 8;
+	this.segmentsT = segmentsT || 64;
+	this.segmentsR = segmentsR || 8;
 	this.p = p || 2;
 	this.q = q || 3;
-	this.heightScale = heightScale || 1;
-
 
 	var TorusKnotCurve = THREE.Curve.create(
 
@@ -198,13 +196,13 @@ THREE.ParametricGeometries.TorusKnotGeometry = function ( radius, tube, segments
 				ty = ( 1 + r * Math.cos( q * t ) ) * Math.sin( p * t ),
 				tz = r * Math.sin( q * t );
 
-			return new THREE.Vector3( tx, ty * heightScale, tz ).multiplyScalar( radius );
+			return new THREE.Vector3( tx, ty, tz ).multiplyScalar( radius );
 
 		}
 
 	);
-	var segments = segmentsR;
-	var radiusSegments = segmentsT;
+	var segments = segmentsT;
+	var radiusSegments = segmentsR;
 	var extrudePath = new TorusKnotCurve();
 
 	THREE.ParametricGeometries.TubeGeometry.call( this, extrudePath, segments, tube, radiusSegments, true, false );

+ 448 - 0
examples/js/Volume.js

@@ -0,0 +1,448 @@
+/**
+ * This class had been written to handle the output of the NRRD loader.
+ * It contains a volume of data and informations about it.
+ * For now it only handles 3 dimensional data.
+ * See the webgl_loader_nrrd.html example and the loaderNRRD.js file to see how to use this class.
+ * @class
+ * @author Valentin Demeusy / https://github.com/stity
+ * @param   {number}        xLength         Width of the volume
+ * @param   {number}        yLength         Length of the volume
+ * @param   {number}        zLength         Depth of the volume
+ * @param   {string}        type            The type of data (uint8, uint16, ...)
+ * @param   {ArrayBuffer}   arrayBuffer     The buffer with volume data
+ */
+THREE.Volume = function( xLength, yLength, zLength, type, arrayBuffer ) {
+
+	if ( arguments.length > 0 ) {
+
+		/**
+		 * @member {number} xLength Width of the volume in the IJK coordinate system
+		 */
+		this.xLength = Number( xLength ) || 1;
+		/**
+		 * @member {number} yLength Height of the volume in the IJK coordinate system
+		 */
+		this.yLength = Number( yLength ) || 1;
+		/**
+		 * @member {number} zLength Depth of the volume in the IJK coordinate system
+		 */
+		this.zLength = Number( zLength ) || 1;
+
+		/**
+		 * @member {TypedArray} data Data of the volume
+		 */
+
+		switch ( type ) {
+
+			case 'Uint8' :
+			case 'uint8' :
+			case 'uchar' :
+			case 'unsigned char' :
+			case 'uint8_t' :
+				this.data = new Uint8Array( arrayBuffer );
+				break;
+			case 'Int8' :
+			case 'int8' :
+			case 'signed char' :
+			case 'int8_t' :
+				this.data = new Int8Array( arrayBuffer );
+				break;
+			case 'Int16' :
+			case 'int16' :
+			case 'short' :
+			case 'short int' :
+			case 'signed short' :
+			case 'signed short int' :
+			case 'int16_t' :
+				this.data = new Int16Array( arrayBuffer );
+				break;
+			case 'Uint16' :
+			case 'uint16' :
+			case 'ushort' :
+			case 'unsigned short' :
+			case 'unsigned short int' :
+			case 'uint16_t' :
+				this.data = new Uint16Array( arrayBuffer );
+				break;
+			case 'Int32' :
+			case 'int32' :
+			case 'int' :
+			case 'signed int' :
+			case 'int32_t' :
+				this.data = new Int32Array( arrayBuffer );
+				break;
+			case 'Uint32' :
+			case 'uint32' :
+			case 'uint' :
+			case 'unsigned int' :
+			case 'uint32' :
+			case 'uint32_t' :
+				this.data = new Uint32Array( arrayBuffer );
+				break;
+			case 'longlong' :
+			case 'long long' :
+			case 'long long int' :
+			case 'signed long long' :
+			case 'signed long long int' :
+			case 'int64' :
+			case 'int64_t' :
+			case 'ulonglong' :
+			case 'unsigned long long' :
+			case 'unsigned long long int' :
+			case 'uint64' :
+			case 'uint64_t' :
+				throw 'Error in THREE.Volume constructor : this type is not supported in JavaScript';
+				break;
+			case 'Float32' :
+			case 'float32' :
+			case 'float' :
+				this.data = new Float32Array( arrayBuffer );
+				break;
+			case 'Float64' :
+			case 'float64' :
+			case 'double' :
+				this.data = new Float64Array( arrayBuffer );
+				break;
+			default :
+				this.data = new Uint8Array( arrayBuffer );
+
+		}
+
+		if ( this.data.length !== this.xLength * this.yLength * this.zLength ) {
+
+			throw 'Error in THREE.Volume constructor, lengths are not matching arrayBuffer size';
+
+		}
+
+	}
+
+	/**
+	 * @member {Array}  spacing Spacing to apply to the volume from IJK to RAS coordinate system
+	 */
+	this.spacing = [ 1, 1, 1 ];
+	/**
+	 * @member {Array}  offset Offset of the volume in the RAS coordinate system
+	 */
+	this.offset = [ 0, 0, 0 ];
+	/**
+	 * @member {THREE.Martrix3} matrix The IJK to RAS matrix
+	 */
+	this.matrix = new THREE.Matrix3();
+	this.matrix.identity();
+	/**
+	 * @member {THREE.Martrix3} inverseMatrix The RAS to IJK matrix
+	 */
+	/**
+	 * @member {number} lowerThreshold The voxels with values under this threshold won't appear in the slices.
+	 *                      If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
+	 */
+	var lowerThreshold = - Infinity;
+	Object.defineProperty( this, 'lowerThreshold', {
+		get : function() {
+
+			return lowerThreshold;
+
+		},
+		set : function( value ) {
+
+			lowerThreshold = value;
+			this.sliceList.forEach( function( slice ) {
+
+				slice.geometryNeedsUpdate = true
+
+			} );
+
+		}
+	} );
+	/**
+	 * @member {number} upperThreshold The voxels with values over this threshold won't appear in the slices.
+	 *                      If changed, geometryNeedsUpdate is automatically set to true on all the slices associated to this volume
+	 */
+	var upperThreshold = Infinity;
+	Object.defineProperty( this, 'upperThreshold', {
+		get : function() {
+
+			return upperThreshold;
+
+		},
+		set : function( value ) {
+
+			upperThreshold = value;
+			this.sliceList.forEach( function( slice ) {
+
+				slice.geometryNeedsUpdate = true;
+
+			} );
+
+		}
+	} );
+
+
+	/**
+	 * @member {Array} sliceList The list of all the slices associated to this volume
+	 */
+	this.sliceList = [];
+
+
+	/**
+	 * @member {Array} RASDimensions This array holds the dimensions of the volume in the RAS space
+	 */
+
+}
+
+THREE.Volume.prototype = {
+
+	constructor : THREE.Volume,
+
+	/**
+	 * @member {Function} getData Shortcut for data[access(i,j,k)]
+	 * @memberof THREE.Volume
+	 * @param {number} i    First coordinate
+	 * @param {number} j    Second coordinate
+	 * @param {number} k    Third coordinate
+	 * @returns {number}  value in the data array
+	 */
+	getData : function( i, j, k ) {
+
+		return this.data[ k * this.xLength * this.yLength + j * this.xLength + i ];
+
+	},
+
+	/**
+	 * @member {Function} access compute the index in the data array corresponding to the given coordinates in IJK system
+	 * @memberof THREE.Volume
+	 * @param {number} i    First coordinate
+	 * @param {number} j    Second coordinate
+	 * @param {number} k    Third coordinate
+	 * @returns {number}  index
+	 */
+	access : function( i, j, k ) {
+
+		return k * this.xLength * this.yLength + j * this.xLength + i;
+
+	},
+
+	/**
+	 * @member {Function} reverseAccess Retrieve the IJK coordinates of the voxel corresponding of the given index in the data
+	 * @memberof THREE.Volume
+	 * @param {number} index index of the voxel
+	 * @returns {Array}  [x,y,z]
+	 */
+	reverseAccess : function( index ) {
+
+		var z = Math.floor( index / ( this.yLength * this.xLength ) );
+		var y = Math.floor( ( index - z * this.yLength * this.xLength ) / this.xLength );
+		var x = index - z * this.yLength * this.xLength - y * this.xLength;
+		return [ x, y, z ];
+
+	},
+
+	/**
+	 * @member {Function} map Apply a function to all the voxels, be careful, the value will be replaced
+	 * @memberof THREE.Volume
+	 * @param {Function} functionToMap A function to apply to every voxel, will be called with the following parameters :
+	 *                                 value of the voxel
+	 *                                 index of the voxel
+	 *                                 the data (TypedArray)
+	 * @param {Object}   context    You can specify a context in which call the function, default if this Volume
+	 * @returns {THREE.Volume}   this
+	 */
+	map : function( functionToMap, context ) {
+
+		var length = this.data.length;
+		context = context || this;
+
+		for ( var i = 0; i < length; i ++ ) {
+
+			this.data[ i ] = functionToMap.call( context, this.data[ i ], i, this.data );
+
+		}
+
+		return this;
+
+	},
+
+	/**
+	 * @member {Function} extractPerpendicularPlane Compute the orientation of the slice and returns all the information relative to the geometry such as sliceAccess, the plane matrix (orientation and position in RAS coordinate) and the dimensions of the plane in both coordinate system.
+	 * @memberof THREE.Volume
+	 * @param {string}            axis  the normal axis to the slice 'x' 'y' or 'z'
+	 * @param {number}            index the index of the slice
+	 * @returns {Object} an object containing all the usefull information on the geometry of the slice
+	 */
+	extractPerpendicularPlane : function( axis, RASIndex ) {
+
+		var iLength,
+		jLength,
+		sliceAccess,
+		planeMatrix = ( new THREE.Matrix4() ).identity(),
+		volume = this,
+		planeWidth,
+		planeHeight,
+		firstSpacing,
+		secondSpacing,
+		positionOffset,
+		IJKIndex;
+
+		var axisInIJK = new THREE.Vector3(),
+		firstDirection = new THREE.Vector3(),
+		secondDirection = new THREE.Vector3();
+
+		var dimensions = new THREE.Vector3( this.xLength, this.yLength, this.zLength );
+
+
+		switch ( axis ) {
+
+			case 'x' :
+				axisInIJK.set( 1, 0, 0 );
+				firstDirection.set( 0, 0, - 1 );
+				secondDirection.set( 0, - 1, 0 );
+				firstSpacing = this.spacing[ 2 ];
+				secondSpacing = this.spacing[ 1 ];
+				IJKIndex = new THREE.Vector3( RASIndex, 0, 0 );
+
+				planeMatrix.multiply( ( new THREE.Matrix4() ).makeRotationY( Math.PI / 2 ) );
+				positionOffset = ( volume.RASDimensions[ 0 ] - 1 ) / 2;
+				planeMatrix.setPosition( new THREE.Vector3( RASIndex - positionOffset, 0, 0 ) );
+				break;
+			case 'y' :
+				axisInIJK.set( 0, 1, 0 );
+				firstDirection.set( 1, 0, 0 );
+				secondDirection.set( 0, 0, 1 );
+				firstSpacing = this.spacing[ 0 ];
+				secondSpacing = this.spacing[ 2 ];
+				IJKIndex = new THREE.Vector3( 0, RASIndex, 0 );
+
+				planeMatrix.multiply( ( new THREE.Matrix4() ).makeRotationX( - Math.PI / 2 ) );
+				positionOffset = ( volume.RASDimensions[ 1 ] - 1 ) / 2;
+				planeMatrix.setPosition( new THREE.Vector3( 0, RASIndex - positionOffset, 0 ) );
+				break;
+			case 'z' :
+			default :
+				axisInIJK.set( 0, 0, 1 );
+				firstDirection.set( 1, 0, 0 );
+				secondDirection.set( 0, - 1, 0 );
+				firstSpacing = this.spacing[ 0 ];
+				secondSpacing = this.spacing[ 1 ];
+				IJKIndex = new THREE.Vector3( 0, 0, RASIndex );
+
+				positionOffset = ( volume.RASDimensions[ 2 ] - 1 ) / 2;
+				planeMatrix.setPosition( new THREE.Vector3( 0, 0, RASIndex - positionOffset ) );
+				break;
+		}
+
+		firstDirection.applyMatrix4( volume.inverseMatrix ).normalize();
+		firstDirection.argVar = 'i';
+		secondDirection.applyMatrix4( volume.inverseMatrix ).normalize();
+		secondDirection.argVar = 'j';
+		axisInIJK.applyMatrix4( volume.inverseMatrix ).normalize();
+		iLength = Math.floor( Math.abs( firstDirection.dot( dimensions ) ) );
+		jLength = Math.floor( Math.abs( secondDirection.dot( dimensions ) ) );
+		planeWidth = Math.abs( iLength * firstSpacing );
+		planeHeight = Math.abs( jLength * secondSpacing );
+
+		IJKIndex = Math.abs( Math.round( IJKIndex.applyMatrix4( volume.inverseMatrix ).dot( axisInIJK ) ) );
+		var base = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ];
+		var iDirection = [ firstDirection, secondDirection, axisInIJK ].find( function( x ) {
+
+			return Math.abs( x.dot( base[ 0 ] ) ) > 0.9;
+
+		} );
+		var jDirection = [ firstDirection, secondDirection, axisInIJK ].find( function( x ) {
+
+			return Math.abs( x.dot( base[ 1 ] ) ) > 0.9;
+
+		} );
+		var kDirection = [ firstDirection, secondDirection, axisInIJK ].find( function( x ) {
+
+			return Math.abs( x.dot( base[ 2 ] ) ) > 0.9;
+
+		} );
+		var argumentsWithInversion = [ 'volume.xLength-1-', 'volume.yLength-1-', 'volume.zLength-1-' ];
+		var arguments = [ 'i', 'j', 'k' ];
+		var argArray = [ iDirection, jDirection, kDirection ].map( function( direction, n ) {
+
+			return ( direction.dot( base[ n ] ) > 0 ? '' : argumentsWithInversion[ n ] ) + ( direction === axisInIJK ? 'IJKIndex' : direction.argVar )
+
+		} );
+		var argString = argArray.join( ',' );
+		sliceAccess = eval( '(function sliceAccess (i,j) {return volume.access( ' + argString + ');})' );
+
+
+		return {
+			iLength : iLength,
+			jLength : jLength,
+			sliceAccess : sliceAccess,
+			matrix : planeMatrix,
+			planeWidth : planeWidth,
+			planeHeight : planeHeight
+		}
+
+	},
+
+	/**
+	 * @member {Function} extractSlice Returns a slice corresponding to the given axis and index
+	 *                        The coordinate are given in the Right Anterior Superior coordinate format
+	 * @memberof THREE.Volume
+	 * @param {string}            axis  the normal axis to the slice 'x' 'y' or 'z'
+	 * @param {number}            index the index of the slice
+	 * @returns {THREE.VolumeSlice} the extracted slice
+	 */
+	extractSlice : function( axis, index ) {
+
+		var slice = new THREE.VolumeSlice( this, index, axis );
+		this.sliceList.push( slice );
+		return slice;
+
+	},
+
+	/**
+	 * @member {Function} repaintAllSlices Call repaint on all the slices extracted from this volume
+	 * @see THREE.VolumeSlice.repaint
+	 * @memberof THREE.Volume
+	 * @returns {THREE.Volume} this
+	 */
+	repaintAllSlices : function() {
+
+		this.sliceList.forEach( function( slice ) {
+
+			slice.repaint();
+
+		} );
+
+		return this;
+
+	},
+
+	/**
+	 * @member {Function} computeMinMax Compute the minimum and the maximum of the data in the volume
+	 * @memberof THREE.Volume
+	 * @returns {Array} [min,max]
+	 */
+	computeMinMax : function() {
+
+		var min = Infinity;
+		var max = - Infinity;
+
+		// buffer the length
+		var datasize = this.data.length;
+
+		var i = 0;
+		for ( i = 0; i < datasize; i ++ ) {
+
+			if ( ! isNaN( this.data[ i ] ) ) {
+
+				var value = this.data[ i ];
+				min = Math.min( min, value );
+				max = Math.max( max, value );
+
+			}
+
+		}
+		this.min = min;
+		this.max = max;
+
+		return [ min, max ];
+
+	}
+
+}

+ 217 - 0
examples/js/VolumeSlice.js

@@ -0,0 +1,217 @@
+/**
+ * This class has been made to hold a slice of a volume data
+ * @class
+ * @author Valentin Demeusy / https://github.com/stity
+ * @param   {THREE.Volume} volume    The associated volume
+ * @param   {number}       [index=0] The index of the slice
+ * @param   {string}       [axis='z']      For now only 'x', 'y' or 'z' but later it will change to a normal vector
+ * @see THREE.Volume
+ */
+THREE.VolumeSlice = function( volume, index, axis ) {
+
+	var slice = this;
+	/**
+	 * @member {THREE.Volume} volume The associated volume
+	 */
+	this.volume = volume;
+	/**
+	 * @member {Number} index The index of the slice, if changed, will automatically call updateGeometry at the next repaint
+	 */
+	index = index || 0;
+	Object.defineProperty( this, 'index', {
+		get : function() {
+
+			return index;
+
+		},
+		set : function( value ) {
+
+			index = value;
+			slice.geometryNeedsUpdate = true;
+			return index;
+
+		}
+	} );
+	/**
+	 * @member {String} axis The normal axis
+	 */
+	this.axis = axis || 'z';
+
+	/**
+	 * @member {HTMLCanvasElement} canvas The final canvas used for the texture
+	 */
+	/**
+	 * @member {CanvasRenderingContext2D} ctx Context of the canvas
+	 */
+	this.canvas = document.createElement( 'canvas' );
+	/**
+	 * @member {HTMLCanvasElement} canvasBuffer The intermediary canvas used to paint the data
+	 */
+	/**
+	 * @member {CanvasRenderingContext2D} ctxBuffer Context of the canvas buffer
+	 */
+	this.canvasBuffer = document.createElement( 'canvas' );
+	this.updateGeometry();
+
+
+	var canvasMap = new THREE.Texture( this.canvas );
+	canvasMap.minFilter = THREE.LinearFilter;
+	canvasMap.wrapS = canvasMap.wrapT = THREE.ClampToEdgeWrapping;
+	var material = new THREE.MeshBasicMaterial( { map: canvasMap, side: THREE.DoubleSide, transparent : true } );
+	/**
+	 * @member {THREE.Mesh} mesh The mesh ready to get used in the scene
+	 */
+	this.mesh = new THREE.Mesh( this.geometry, material );
+	/**
+	 * @member {Boolean} geometryNeedsUpdate If set to true, updateGeometry will be triggered at the next repaint
+	 */
+	this.geometryNeedsUpdate = true;
+	this.repaint();
+
+	/**
+	 * @member {Number} iLength Width of slice in the original coordinate system, corresponds to the width of the buffer canvas
+	 */
+
+	/**
+	 * @member {Number} jLength Height of slice in the original coordinate system, corresponds to the height of the buffer canvas
+	 */
+
+	/**
+	 * @member {Function} sliceAccess Function that allow the slice to access right data
+	 * @see THREE.Volume.extractPerpendicularPlane
+	 * @param {Number} i The first coordinate
+	 * @param {Number} j The second coordinate
+	 * @returns {Number} the index corresponding to the voxel in volume.data of the given position in the slice
+	 */
+
+
+}
+
+THREE.VolumeSlice.prototype = {
+
+	constructor : THREE.VolumeSlice,
+
+	/**
+	 * @member {Function} repaint Refresh the texture and the geometry if geometryNeedsUpdate is set to true
+	 * @memberof THREE.VolumeSlice
+	 */
+	repaint : function() {
+
+		if ( this.geometryNeedsUpdate ) {
+
+			this.updateGeometry();
+
+		}
+
+		var iLength = this.iLength,
+		jLength = this.jLength,
+		sliceAccess = this.sliceAccess,
+		volume = this.volume,
+		axis = this.axis,
+		index = this.index,
+		canvas = this.canvasBuffer,
+		ctx = this.ctxBuffer;
+
+
+		// get the imageData and pixel array from the canvas
+		var imgData = ctx.getImageData( 0, 0, iLength, jLength );
+		var data = imgData.data;
+		var volumeData = volume.data;
+		var upperThreshold = volume.upperThreshold;
+		var lowerThreshold = volume.lowerThreshold;
+		var windowLow = volume.windowLow;
+		var windowHigh = volume.windowHigh;
+
+		// manipulate some pixel elements
+		var pixelCount = 0;
+
+		if ( volume.dataType === 'label' ) {
+
+			//this part is currently useless but will be used when colortables will be handled
+			for ( var j = 0; j < jLength; j ++ ) {
+
+				for ( var i = 0; i < iLength; i ++ ) {
+
+					var label = volumeData[ sliceAccess( i, j ) ];
+					label = label >= this.colorMap.length ? ( label % this.colorMap.length ) + 1 : label;
+					var color = this.colorMap[ label ];
+					data[ 4 * pixelCount ] = ( color >> 24 ) & 0xff;
+					data[ 4 * pixelCount + 1 ] = ( color >> 16 ) & 0xff;
+					data[ 4 * pixelCount + 2 ] = ( color >> 8 ) & 0xff;
+					data[ 4 * pixelCount + 3 ] = color & 0xff;
+					pixelCount ++;
+
+				}
+
+			}
+
+		}
+		else {
+
+			for ( var j = 0; j < jLength; j ++ ) {
+
+				for ( var i = 0; i < iLength; i ++ ) {
+
+					var value = volumeData[ sliceAccess( i, j ) ];
+					var alpha = 0xff;
+					//apply threshold
+					alpha = upperThreshold >= value ? ( lowerThreshold <= value ? alpha : 0 ) : 0;
+					//apply window level
+					value = Math.floor( 255 * ( value - windowLow ) / ( windowHigh - windowLow ) );
+					value = value > 255 ? 255 : ( value < 0 ? 0 : value | 0 );
+
+					data[ 4 * pixelCount ] = value;
+					data[ 4 * pixelCount + 1 ] = value;
+					data[ 4 * pixelCount + 2 ] = value;
+					data[ 4 * pixelCount + 3 ] = alpha;
+					pixelCount ++;
+
+				}
+
+			}
+
+		}
+		ctx.putImageData( imgData, 0, 0 );
+		this.ctx.drawImage( canvas, 0, 0, iLength, jLength, 0, 0, this.canvas.width, this.canvas.height );
+
+
+		this.mesh.material.map.needsUpdate = true;
+
+	},
+
+	/**
+	 * @member {Function} Refresh the geometry according to axis and index
+	 * @see THREE.Volume.extractPerpendicularPlane
+	 * @memberof THREE.VolumeSlice
+	 */
+	updateGeometry : function() {
+
+		var extracted = this.volume.extractPerpendicularPlane( this.axis, this.index );
+		this.sliceAccess = extracted.sliceAccess;
+		this.jLength = extracted.jLength;
+		this.iLength = extracted.iLength;
+		this.matrix = extracted.matrix;
+
+		this.canvas.width = extracted.planeWidth;
+		this.canvas.height = extracted.planeHeight;
+		this.canvasBuffer.width = this.iLength;
+		this.canvasBuffer.height = this.jLength;
+		this.ctx = this.canvas.getContext( '2d' );
+		this.ctxBuffer = this.canvasBuffer.getContext( '2d' );
+
+		this.geometry = new THREE.PlaneGeometry( extracted.planeWidth, extracted.planeHeight );
+
+		if ( this.mesh ) {
+
+			this.mesh.geometry = this.geometry;
+			//reset mesh matrix
+			this.mesh.matrix = ( new THREE.Matrix4() ).identity();
+			this.mesh.applyMatrix( this.matrix );
+
+		}
+
+		this.geometryNeedsUpdate = false;
+
+	}
+
+}

+ 8 - 2
examples/js/WebVR.js

@@ -5,9 +5,15 @@
 
 var WEBVR = {
 
+	isLatestAvailable: function () {
+
+		return navigator.getVRDisplays !== undefined;
+
+	},
+
 	isAvailable: function () {
 
-		return navigator.getVRDisplays;
+		return navigator.getVRDisplays !== undefined || navigator.getVRDevices !== undefined;
 
 	},
 
@@ -51,7 +57,7 @@ var WEBVR = {
 			error.style.backgroundColor = '#fff';
 			error.style.color = '#000';
 			error.style.padding = '10px 20px';
-			error.style.margin = '40px';
+			error.style.margin = '50px';
 			error.style.display = 'inline-block';
 			error.innerHTML = message;
 			container.appendChild( error );

+ 4 - 12
examples/js/controls/OrbitControls.js

@@ -295,11 +295,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 		return function panLeft( distance, objectMatrix ) {
 
-			var te = objectMatrix.elements;
-
-			// get X column of objectMatrix
-			v.set( te[ 0 ], te[ 1 ], te[ 2 ] );
-
+			v.setFromMatrixColumn( objectMatrix, 0 ); // get X column of objectMatrix
 			v.multiplyScalar( - distance );
 
 			panOffset.add( v );
@@ -314,11 +310,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 		return function panUp( distance, objectMatrix ) {
 
-			var te = objectMatrix.elements;
-
-			// get Y column of objectMatrix
-			v.set( te[ 4 ], te[ 5 ], te[ 6 ] );
-
+			v.setFromMatrixColumn( objectMatrix, 1 ); // get Y column of objectMatrix
 			v.multiplyScalar( distance );
 
 			panOffset.add( v );
@@ -353,8 +345,8 @@ THREE.OrbitControls = function ( object, domElement ) {
 			} else if ( scope.object instanceof THREE.OrthographicCamera ) {
 
 				// orthographic
-				panLeft( deltaX * ( scope.object.right - scope.object.left ) / element.clientWidth, scope.object.matrix );
-				panUp( deltaY * ( scope.object.top - scope.object.bottom ) / element.clientHeight, scope.object.matrix );
+				panLeft( deltaX * ( scope.object.right - scope.object.left ) / scope.object.zoom / element.clientWidth, scope.object.matrix );
+				panUp( deltaY * ( scope.object.top - scope.object.bottom ) / scope.object.zoom / element.clientHeight, scope.object.matrix );
 
 			} else {
 

+ 15 - 0
examples/js/libs/inflate.min.js

@@ -0,0 +1,15 @@
+/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';var m=this;function q(c,d){var a=c.split("."),b=m;!(a[0]in b)&&b.execScript&&b.execScript("var "+a[0]);for(var e;a.length&&(e=a.shift());)!a.length&&void 0!==d?b[e]=d:b=b[e]?b[e]:b[e]={}};var s="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function t(c){var d=c.length,a=0,b=Number.POSITIVE_INFINITY,e,f,g,h,k,l,p,n,r,K;for(n=0;n<d;++n)c[n]>a&&(a=c[n]),c[n]<b&&(b=c[n]);e=1<<a;f=new (s?Uint32Array:Array)(e);g=1;h=0;for(k=2;g<=a;){for(n=0;n<d;++n)if(c[n]===g){l=0;p=h;for(r=0;r<g;++r)l=l<<1|p&1,p>>=1;K=g<<16|n;for(r=l;r<e;r+=k)f[r]=K;++h}++g;h<<=1;k<<=1}return[f,a,b]};function u(c,d){this.g=[];this.h=32768;this.d=this.f=this.a=this.l=0;this.input=s?new Uint8Array(c):c;this.m=!1;this.i=v;this.s=!1;if(d||!(d={}))d.index&&(this.a=d.index),d.bufferSize&&(this.h=d.bufferSize),d.bufferType&&(this.i=d.bufferType),d.resize&&(this.s=d.resize);switch(this.i){case w:this.b=32768;this.c=new (s?Uint8Array:Array)(32768+this.h+258);break;case v:this.b=0;this.c=new (s?Uint8Array:Array)(this.h);this.e=this.A;this.n=this.w;this.j=this.z;break;default:throw Error("invalid inflate mode");
+}}var w=0,v=1,x={u:w,t:v};
+u.prototype.k=function(){for(;!this.m;){var c=y(this,3);c&1&&(this.m=!0);c>>>=1;switch(c){case 0:var d=this.input,a=this.a,b=this.c,e=this.b,f=d.length,g=void 0,h=void 0,k=b.length,l=void 0;this.d=this.f=0;if(a+1>=f)throw Error("invalid uncompressed block header: LEN");g=d[a++]|d[a++]<<8;if(a+1>=f)throw Error("invalid uncompressed block header: NLEN");h=d[a++]|d[a++]<<8;if(g===~h)throw Error("invalid uncompressed block header: length verify");if(a+g>d.length)throw Error("input buffer is broken");switch(this.i){case w:for(;e+
+g>b.length;){l=k-e;g-=l;if(s)b.set(d.subarray(a,a+l),e),e+=l,a+=l;else for(;l--;)b[e++]=d[a++];this.b=e;b=this.e();e=this.b}break;case v:for(;e+g>b.length;)b=this.e({p:2});break;default:throw Error("invalid inflate mode");}if(s)b.set(d.subarray(a,a+g),e),e+=g,a+=g;else for(;g--;)b[e++]=d[a++];this.a=a;this.b=e;this.c=b;break;case 1:this.j(z,A);break;case 2:B(this);break;default:throw Error("unknown BTYPE: "+c);}}return this.n()};
+var C=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],D=s?new Uint16Array(C):C,E=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],F=s?new Uint16Array(E):E,G=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],H=s?new Uint8Array(G):G,I=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],J=s?new Uint16Array(I):I,L=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,
+13],M=s?new Uint8Array(L):L,N=new (s?Uint8Array:Array)(288),O,P;O=0;for(P=N.length;O<P;++O)N[O]=143>=O?8:255>=O?9:279>=O?7:8;var z=t(N),Q=new (s?Uint8Array:Array)(30),R,S;R=0;for(S=Q.length;R<S;++R)Q[R]=5;var A=t(Q);function y(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h;b<d;){if(f>=g)throw Error("input buffer is broken");a|=e[f++]<<b;b+=8}h=a&(1<<d)-1;c.f=a>>>d;c.d=b-d;c.a=f;return h}
+function T(c,d){for(var a=c.f,b=c.d,e=c.input,f=c.a,g=e.length,h=d[0],k=d[1],l,p;b<k&&!(f>=g);)a|=e[f++]<<b,b+=8;l=h[a&(1<<k)-1];p=l>>>16;c.f=a>>p;c.d=b-p;c.a=f;return l&65535}
+function B(c){function d(a,c,b){var d,e=this.q,f,g;for(g=0;g<a;)switch(d=T(this,c),d){case 16:for(f=3+y(this,2);f--;)b[g++]=e;break;case 17:for(f=3+y(this,3);f--;)b[g++]=0;e=0;break;case 18:for(f=11+y(this,7);f--;)b[g++]=0;e=0;break;default:e=b[g++]=d}this.q=e;return b}var a=y(c,5)+257,b=y(c,5)+1,e=y(c,4)+4,f=new (s?Uint8Array:Array)(D.length),g,h,k,l;for(l=0;l<e;++l)f[D[l]]=y(c,3);if(!s){l=e;for(e=f.length;l<e;++l)f[D[l]]=0}g=t(f);h=new (s?Uint8Array:Array)(a);k=new (s?Uint8Array:Array)(b);c.q=0;
+c.j(t(d.call(c,a,g,h)),t(d.call(c,b,g,k)))}u.prototype.j=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length-258,f,g,h,k;256!==(f=T(this,c));)if(256>f)b>=e&&(this.b=b,a=this.e(),b=this.b),a[b++]=f;else{g=f-257;k=F[g];0<H[g]&&(k+=y(this,H[g]));f=T(this,d);h=J[f];0<M[f]&&(h+=y(this,M[f]));b>=e&&(this.b=b,a=this.e(),b=this.b);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b};
+u.prototype.z=function(c,d){var a=this.c,b=this.b;this.o=c;for(var e=a.length,f,g,h,k;256!==(f=T(this,c));)if(256>f)b>=e&&(a=this.e(),e=a.length),a[b++]=f;else{g=f-257;k=F[g];0<H[g]&&(k+=y(this,H[g]));f=T(this,d);h=J[f];0<M[f]&&(h+=y(this,M[f]));b+k>e&&(a=this.e(),e=a.length);for(;k--;)a[b]=a[b++-h]}for(;8<=this.d;)this.d-=8,this.a--;this.b=b};
+u.prototype.e=function(){var c=new (s?Uint8Array:Array)(this.b-32768),d=this.b-32768,a,b,e=this.c;if(s)c.set(e.subarray(32768,c.length));else{a=0;for(b=c.length;a<b;++a)c[a]=e[a+32768]}this.g.push(c);this.l+=c.length;if(s)e.set(e.subarray(d,d+32768));else for(a=0;32768>a;++a)e[a]=e[d+a];this.b=32768;return e};
+u.prototype.A=function(c){var d,a=this.input.length/this.a+1|0,b,e,f,g=this.input,h=this.c;c&&("number"===typeof c.p&&(a=c.p),"number"===typeof c.v&&(a+=c.v));2>a?(b=(g.length-this.a)/this.o[2],f=258*(b/2)|0,e=f<h.length?h.length+f:h.length<<1):e=h.length*a;s?(d=new Uint8Array(e),d.set(h)):d=h;return this.c=d};
+u.prototype.n=function(){var c=0,d=this.c,a=this.g,b,e=new (s?Uint8Array:Array)(this.l+(this.b-32768)),f,g,h,k;if(0===a.length)return s?this.c.subarray(32768,this.b):this.c.slice(32768,this.b);f=0;for(g=a.length;f<g;++f){b=a[f];h=0;for(k=b.length;h<k;++h)e[c++]=b[h]}f=32768;for(g=this.b;f<g;++f)e[c++]=d[f];this.g=[];return this.buffer=e};
+u.prototype.w=function(){var c,d=this.b;s?this.s?(c=new Uint8Array(d),c.set(this.c.subarray(0,d))):c=this.c.subarray(0,d):(this.c.length>d&&(this.c.length=d),c=this.c);return this.buffer=c};function U(c,d){var a,b;this.input=c;this.a=0;if(d||!(d={}))d.index&&(this.a=d.index),d.verify&&(this.B=d.verify);a=c[this.a++];b=c[this.a++];switch(a&15){case V:this.method=V;break;default:throw Error("unsupported compression method");}if(0!==((a<<8)+b)%31)throw Error("invalid fcheck flag:"+((a<<8)+b)%31);if(b&32)throw Error("fdict flag is not supported");this.r=new u(c,{index:this.a,bufferSize:d.bufferSize,bufferType:d.bufferType,resize:d.resize})}
+U.prototype.k=function(){var c=this.input,d,a;d=this.r.k();this.a=this.r.a;if(this.B){a=(c[this.a++]<<24|c[this.a++]<<16|c[this.a++]<<8|c[this.a++])>>>0;var b=d;if("string"===typeof b){var e=b.split(""),f,g;f=0;for(g=e.length;f<g;f++)e[f]=(e[f].charCodeAt(0)&255)>>>0;b=e}for(var h=1,k=0,l=b.length,p,n=0;0<l;){p=1024<l?1024:l;l-=p;do h+=b[n++],k+=h;while(--p);h%=65521;k%=65521}if(a!==(k<<16|h)>>>0)throw Error("invalid adler-32 checksum");}return d};var V=8;q("Zlib.Inflate",U);q("Zlib.Inflate.prototype.decompress",U.prototype.k);var W={ADAPTIVE:x.t,BLOCK:x.u},X,Y,Z,$;if(Object.keys)X=Object.keys(W);else for(Y in X=[],Z=0,W)X[Z++]=Y;Z=0;for($=X.length;Z<$;++Z)Y=X[Z],q("Zlib.Inflate.BufferType."+Y,W[Y]);}).call(this);

+ 51 - 0
examples/js/libs/zlib_and_gzip.min.js

@@ -0,0 +1,51 @@
+/** @license zlib.js 2012 - imaya [ https://github.com/imaya/zlib.js ] The MIT License */(function() {'use strict';function q(b){throw b;}var t=void 0,u=!0,aa=this;function A(b,a){var c=b.split("."),d=aa;!(c[0]in d)&&d.execScript&&d.execScript("var "+c[0]);for(var e;c.length&&(e=c.shift());)!c.length&&a!==t?d[e]=a:d=d[e]?d[e]:d[e]={}};var B="undefined"!==typeof Uint8Array&&"undefined"!==typeof Uint16Array&&"undefined"!==typeof Uint32Array&&"undefined"!==typeof DataView;function F(b,a){this.index="number"===typeof a?a:0;this.m=0;this.buffer=b instanceof(B?Uint8Array:Array)?b:new (B?Uint8Array:Array)(32768);2*this.buffer.length<=this.index&&q(Error("invalid index"));this.buffer.length<=this.index&&this.f()}F.prototype.f=function(){var b=this.buffer,a,c=b.length,d=new (B?Uint8Array:Array)(c<<1);if(B)d.set(b);else for(a=0;a<c;++a)d[a]=b[a];return this.buffer=d};
+F.prototype.d=function(b,a,c){var d=this.buffer,e=this.index,f=this.m,g=d[e],k;c&&1<a&&(b=8<a?(H[b&255]<<24|H[b>>>8&255]<<16|H[b>>>16&255]<<8|H[b>>>24&255])>>32-a:H[b]>>8-a);if(8>a+f)g=g<<a|b,f+=a;else for(k=0;k<a;++k)g=g<<1|b>>a-k-1&1,8===++f&&(f=0,d[e++]=H[g],g=0,e===d.length&&(d=this.f()));d[e]=g;this.buffer=d;this.m=f;this.index=e};F.prototype.finish=function(){var b=this.buffer,a=this.index,c;0<this.m&&(b[a]<<=8-this.m,b[a]=H[b[a]],a++);B?c=b.subarray(0,a):(b.length=a,c=b);return c};
+var ba=new (B?Uint8Array:Array)(256),ca;for(ca=0;256>ca;++ca){for(var K=ca,da=K,ea=7,K=K>>>1;K;K>>>=1)da<<=1,da|=K&1,--ea;ba[ca]=(da<<ea&255)>>>0}var H=ba;function ja(b,a,c){var d,e="number"===typeof a?a:a=0,f="number"===typeof c?c:b.length;d=-1;for(e=f&7;e--;++a)d=d>>>8^O[(d^b[a])&255];for(e=f>>3;e--;a+=8)d=d>>>8^O[(d^b[a])&255],d=d>>>8^O[(d^b[a+1])&255],d=d>>>8^O[(d^b[a+2])&255],d=d>>>8^O[(d^b[a+3])&255],d=d>>>8^O[(d^b[a+4])&255],d=d>>>8^O[(d^b[a+5])&255],d=d>>>8^O[(d^b[a+6])&255],d=d>>>8^O[(d^b[a+7])&255];return(d^4294967295)>>>0}
+var ka=[0,1996959894,3993919788,2567524794,124634137,1886057615,3915621685,2657392035,249268274,2044508324,3772115230,2547177864,162941995,2125561021,3887607047,2428444049,498536548,1789927666,4089016648,2227061214,450548861,1843258603,4107580753,2211677639,325883990,1684777152,4251122042,2321926636,335633487,1661365465,4195302755,2366115317,997073096,1281953886,3579855332,2724688242,1006888145,1258607687,3524101629,2768942443,901097722,1119000684,3686517206,2898065728,853044451,1172266101,3705015759,
+2882616665,651767980,1373503546,3369554304,3218104598,565507253,1454621731,3485111705,3099436303,671266974,1594198024,3322730930,2970347812,795835527,1483230225,3244367275,3060149565,1994146192,31158534,2563907772,4023717930,1907459465,112637215,2680153253,3904427059,2013776290,251722036,2517215374,3775830040,2137656763,141376813,2439277719,3865271297,1802195444,476864866,2238001368,4066508878,1812370925,453092731,2181625025,4111451223,1706088902,314042704,2344532202,4240017532,1658658271,366619977,
+2362670323,4224994405,1303535960,984961486,2747007092,3569037538,1256170817,1037604311,2765210733,3554079995,1131014506,879679996,2909243462,3663771856,1141124467,855842277,2852801631,3708648649,1342533948,654459306,3188396048,3373015174,1466479909,544179635,3110523913,3462522015,1591671054,702138776,2966460450,3352799412,1504918807,783551873,3082640443,3233442989,3988292384,2596254646,62317068,1957810842,3939845945,2647816111,81470997,1943803523,3814918930,2489596804,225274430,2053790376,3826175755,
+2466906013,167816743,2097651377,4027552580,2265490386,503444072,1762050814,4150417245,2154129355,426522225,1852507879,4275313526,2312317920,282753626,1742555852,4189708143,2394877945,397917763,1622183637,3604390888,2714866558,953729732,1340076626,3518719985,2797360999,1068828381,1219638859,3624741850,2936675148,906185462,1090812512,3747672003,2825379669,829329135,1181335161,3412177804,3160834842,628085408,1382605366,3423369109,3138078467,570562233,1426400815,3317316542,2998733608,733239954,1555261956,
+3268935591,3050360625,752459403,1541320221,2607071920,3965973030,1969922972,40735498,2617837225,3943577151,1913087877,83908371,2512341634,3803740692,2075208622,213261112,2463272603,3855990285,2094854071,198958881,2262029012,4057260610,1759359992,534414190,2176718541,4139329115,1873836001,414664567,2282248934,4279200368,1711684554,285281116,2405801727,4167216745,1634467795,376229701,2685067896,3608007406,1308918612,956543938,2808555105,3495958263,1231636301,1047427035,2932959818,3654703836,1088359270,
+936918E3,2847714899,3736837829,1202900863,817233897,3183342108,3401237130,1404277552,615818150,3134207493,3453421203,1423857449,601450431,3009837614,3294710456,1567103746,711928724,3020668471,3272380065,1510334235,755167117],O=B?new Uint32Array(ka):ka;function P(){}P.prototype.getName=function(){return this.name};P.prototype.getData=function(){return this.data};P.prototype.Y=function(){return this.Z};A("Zlib.GunzipMember",P);A("Zlib.GunzipMember.prototype.getName",P.prototype.getName);A("Zlib.GunzipMember.prototype.getData",P.prototype.getData);A("Zlib.GunzipMember.prototype.getMtime",P.prototype.Y);function la(b){this.buffer=new (B?Uint16Array:Array)(2*b);this.length=0}la.prototype.getParent=function(b){return 2*((b-2)/4|0)};la.prototype.push=function(b,a){var c,d,e=this.buffer,f;c=this.length;e[this.length++]=a;for(e[this.length++]=b;0<c;)if(d=this.getParent(c),e[c]>e[d])f=e[c],e[c]=e[d],e[d]=f,f=e[c+1],e[c+1]=e[d+1],e[d+1]=f,c=d;else break;return this.length};
+la.prototype.pop=function(){var b,a,c=this.buffer,d,e,f;a=c[0];b=c[1];this.length-=2;c[0]=c[this.length];c[1]=c[this.length+1];for(f=0;;){e=2*f+2;if(e>=this.length)break;e+2<this.length&&c[e+2]>c[e]&&(e+=2);if(c[e]>c[f])d=c[f],c[f]=c[e],c[e]=d,d=c[f+1],c[f+1]=c[e+1],c[e+1]=d;else break;f=e}return{index:b,value:a,length:this.length}};function ma(b){var a=b.length,c=0,d=Number.POSITIVE_INFINITY,e,f,g,k,h,l,s,p,m,n;for(p=0;p<a;++p)b[p]>c&&(c=b[p]),b[p]<d&&(d=b[p]);e=1<<c;f=new (B?Uint32Array:Array)(e);g=1;k=0;for(h=2;g<=c;){for(p=0;p<a;++p)if(b[p]===g){l=0;s=k;for(m=0;m<g;++m)l=l<<1|s&1,s>>=1;n=g<<16|p;for(m=l;m<e;m+=h)f[m]=n;++k}++g;k<<=1;h<<=1}return[f,c,d]};function na(b,a){this.k=qa;this.I=0;this.input=B&&b instanceof Array?new Uint8Array(b):b;this.b=0;a&&(a.lazy&&(this.I=a.lazy),"number"===typeof a.compressionType&&(this.k=a.compressionType),a.outputBuffer&&(this.a=B&&a.outputBuffer instanceof Array?new Uint8Array(a.outputBuffer):a.outputBuffer),"number"===typeof a.outputIndex&&(this.b=a.outputIndex));this.a||(this.a=new (B?Uint8Array:Array)(32768))}var qa=2,ra={NONE:0,v:1,o:qa,ba:3},sa=[],S;
+for(S=0;288>S;S++)switch(u){case 143>=S:sa.push([S+48,8]);break;case 255>=S:sa.push([S-144+400,9]);break;case 279>=S:sa.push([S-256+0,7]);break;case 287>=S:sa.push([S-280+192,8]);break;default:q("invalid literal: "+S)}
+na.prototype.g=function(){var b,a,c,d,e=this.input;switch(this.k){case 0:c=0;for(d=e.length;c<d;){a=B?e.subarray(c,c+65535):e.slice(c,c+65535);c+=a.length;var f=a,g=c===d,k=t,h=t,l=t,s=t,p=t,m=this.a,n=this.b;if(B){for(m=new Uint8Array(this.a.buffer);m.length<=n+f.length+5;)m=new Uint8Array(m.length<<1);m.set(this.a)}k=g?1:0;m[n++]=k|0;h=f.length;l=~h+65536&65535;m[n++]=h&255;m[n++]=h>>>8&255;m[n++]=l&255;m[n++]=l>>>8&255;if(B)m.set(f,n),n+=f.length,m=m.subarray(0,n);else{s=0;for(p=f.length;s<p;++s)m[n++]=
+f[s];m.length=n}this.b=n;this.a=m}break;case 1:var r=new F(B?new Uint8Array(this.a.buffer):this.a,this.b);r.d(1,1,u);r.d(1,2,u);var v=ta(this,e),x,Q,y;x=0;for(Q=v.length;x<Q;x++)if(y=v[x],F.prototype.d.apply(r,sa[y]),256<y)r.d(v[++x],v[++x],u),r.d(v[++x],5),r.d(v[++x],v[++x],u);else if(256===y)break;this.a=r.finish();this.b=this.a.length;break;case qa:var E=new F(B?new Uint8Array(this.a.buffer):this.a,this.b),Ka,R,X,Y,Z,pb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],fa,La,ga,Ma,oa,wa=Array(19),
+Na,$,pa,C,Oa;Ka=qa;E.d(1,1,u);E.d(Ka,2,u);R=ta(this,e);fa=ua(this.W,15);La=va(fa);ga=ua(this.V,7);Ma=va(ga);for(X=286;257<X&&0===fa[X-1];X--);for(Y=30;1<Y&&0===ga[Y-1];Y--);var Pa=X,Qa=Y,J=new (B?Uint32Array:Array)(Pa+Qa),w,L,z,ha,I=new (B?Uint32Array:Array)(316),G,D,M=new (B?Uint8Array:Array)(19);for(w=L=0;w<Pa;w++)J[L++]=fa[w];for(w=0;w<Qa;w++)J[L++]=ga[w];if(!B){w=0;for(ha=M.length;w<ha;++w)M[w]=0}w=G=0;for(ha=J.length;w<ha;w+=L){for(L=1;w+L<ha&&J[w+L]===J[w];++L);z=L;if(0===J[w])if(3>z)for(;0<
+z--;)I[G++]=0,M[0]++;else for(;0<z;)D=138>z?z:138,D>z-3&&D<z&&(D=z-3),10>=D?(I[G++]=17,I[G++]=D-3,M[17]++):(I[G++]=18,I[G++]=D-11,M[18]++),z-=D;else if(I[G++]=J[w],M[J[w]]++,z--,3>z)for(;0<z--;)I[G++]=J[w],M[J[w]]++;else for(;0<z;)D=6>z?z:6,D>z-3&&D<z&&(D=z-3),I[G++]=16,I[G++]=D-3,M[16]++,z-=D}b=B?I.subarray(0,G):I.slice(0,G);oa=ua(M,7);for(C=0;19>C;C++)wa[C]=oa[pb[C]];for(Z=19;4<Z&&0===wa[Z-1];Z--);Na=va(oa);E.d(X-257,5,u);E.d(Y-1,5,u);E.d(Z-4,4,u);for(C=0;C<Z;C++)E.d(wa[C],3,u);C=0;for(Oa=b.length;C<
+Oa;C++)if($=b[C],E.d(Na[$],oa[$],u),16<=$){C++;switch($){case 16:pa=2;break;case 17:pa=3;break;case 18:pa=7;break;default:q("invalid code: "+$)}E.d(b[C],pa,u)}var Ra=[La,fa],Sa=[Ma,ga],N,Ta,ia,za,Ua,Va,Wa,Xa;Ua=Ra[0];Va=Ra[1];Wa=Sa[0];Xa=Sa[1];N=0;for(Ta=R.length;N<Ta;++N)if(ia=R[N],E.d(Ua[ia],Va[ia],u),256<ia)E.d(R[++N],R[++N],u),za=R[++N],E.d(Wa[za],Xa[za],u),E.d(R[++N],R[++N],u);else if(256===ia)break;this.a=E.finish();this.b=this.a.length;break;default:q("invalid compression type")}return this.a};
+function xa(b,a){this.length=b;this.Q=a}
+var ya=function(){function b(a){switch(u){case 3===a:return[257,a-3,0];case 4===a:return[258,a-4,0];case 5===a:return[259,a-5,0];case 6===a:return[260,a-6,0];case 7===a:return[261,a-7,0];case 8===a:return[262,a-8,0];case 9===a:return[263,a-9,0];case 10===a:return[264,a-10,0];case 12>=a:return[265,a-11,1];case 14>=a:return[266,a-13,1];case 16>=a:return[267,a-15,1];case 18>=a:return[268,a-17,1];case 22>=a:return[269,a-19,2];case 26>=a:return[270,a-23,2];case 30>=a:return[271,a-27,2];case 34>=a:return[272,
+a-31,2];case 42>=a:return[273,a-35,3];case 50>=a:return[274,a-43,3];case 58>=a:return[275,a-51,3];case 66>=a:return[276,a-59,3];case 82>=a:return[277,a-67,4];case 98>=a:return[278,a-83,4];case 114>=a:return[279,a-99,4];case 130>=a:return[280,a-115,4];case 162>=a:return[281,a-131,5];case 194>=a:return[282,a-163,5];case 226>=a:return[283,a-195,5];case 257>=a:return[284,a-227,5];case 258===a:return[285,a-258,0];default:q("invalid length: "+a)}}var a=[],c,d;for(c=3;258>=c;c++)d=b(c),a[c]=d[2]<<24|d[1]<<
+16|d[0];return a}(),Aa=B?new Uint32Array(ya):ya;
+function ta(b,a){function c(a,c){var b=a.Q,d=[],e=0,f;f=Aa[a.length];d[e++]=f&65535;d[e++]=f>>16&255;d[e++]=f>>24;var g;switch(u){case 1===b:g=[0,b-1,0];break;case 2===b:g=[1,b-2,0];break;case 3===b:g=[2,b-3,0];break;case 4===b:g=[3,b-4,0];break;case 6>=b:g=[4,b-5,1];break;case 8>=b:g=[5,b-7,1];break;case 12>=b:g=[6,b-9,2];break;case 16>=b:g=[7,b-13,2];break;case 24>=b:g=[8,b-17,3];break;case 32>=b:g=[9,b-25,3];break;case 48>=b:g=[10,b-33,4];break;case 64>=b:g=[11,b-49,4];break;case 96>=b:g=[12,b-
+65,5];break;case 128>=b:g=[13,b-97,5];break;case 192>=b:g=[14,b-129,6];break;case 256>=b:g=[15,b-193,6];break;case 384>=b:g=[16,b-257,7];break;case 512>=b:g=[17,b-385,7];break;case 768>=b:g=[18,b-513,8];break;case 1024>=b:g=[19,b-769,8];break;case 1536>=b:g=[20,b-1025,9];break;case 2048>=b:g=[21,b-1537,9];break;case 3072>=b:g=[22,b-2049,10];break;case 4096>=b:g=[23,b-3073,10];break;case 6144>=b:g=[24,b-4097,11];break;case 8192>=b:g=[25,b-6145,11];break;case 12288>=b:g=[26,b-8193,12];break;case 16384>=
+b:g=[27,b-12289,12];break;case 24576>=b:g=[28,b-16385,13];break;case 32768>=b:g=[29,b-24577,13];break;default:q("invalid distance")}f=g;d[e++]=f[0];d[e++]=f[1];d[e++]=f[2];var h,k;h=0;for(k=d.length;h<k;++h)m[n++]=d[h];v[d[0]]++;x[d[3]]++;r=a.length+c-1;p=null}var d,e,f,g,k,h={},l,s,p,m=B?new Uint16Array(2*a.length):[],n=0,r=0,v=new (B?Uint32Array:Array)(286),x=new (B?Uint32Array:Array)(30),Q=b.I,y;if(!B){for(f=0;285>=f;)v[f++]=0;for(f=0;29>=f;)x[f++]=0}v[256]=1;d=0;for(e=a.length;d<e;++d){f=k=0;
+for(g=3;f<g&&d+f!==e;++f)k=k<<8|a[d+f];h[k]===t&&(h[k]=[]);l=h[k];if(!(0<r--)){for(;0<l.length&&32768<d-l[0];)l.shift();if(d+3>=e){p&&c(p,-1);f=0;for(g=e-d;f<g;++f)y=a[d+f],m[n++]=y,++v[y];break}0<l.length?(s=Ba(a,d,l),p?p.length<s.length?(y=a[d-1],m[n++]=y,++v[y],c(s,0)):c(p,-1):s.length<Q?p=s:c(s,0)):p?c(p,-1):(y=a[d],m[n++]=y,++v[y])}l.push(d)}m[n++]=256;v[256]++;b.W=v;b.V=x;return B?m.subarray(0,n):m}
+function Ba(b,a,c){var d,e,f=0,g,k,h,l,s=b.length;k=0;l=c.length;a:for(;k<l;k++){d=c[l-k-1];g=3;if(3<f){for(h=f;3<h;h--)if(b[d+h-1]!==b[a+h-1])continue a;g=f}for(;258>g&&a+g<s&&b[d+g]===b[a+g];)++g;g>f&&(e=d,f=g);if(258===g)break}return new xa(f,a-e)}
+function ua(b,a){var c=b.length,d=new la(572),e=new (B?Uint8Array:Array)(c),f,g,k,h,l;if(!B)for(h=0;h<c;h++)e[h]=0;for(h=0;h<c;++h)0<b[h]&&d.push(h,b[h]);f=Array(d.length/2);g=new (B?Uint32Array:Array)(d.length/2);if(1===f.length)return e[d.pop().index]=1,e;h=0;for(l=d.length/2;h<l;++h)f[h]=d.pop(),g[h]=f[h].value;k=Ca(g,g.length,a);h=0;for(l=f.length;h<l;++h)e[f[h].index]=k[h];return e}
+function Ca(b,a,c){function d(b){var c=h[b][l[b]];c===a?(d(b+1),d(b+1)):--g[c];++l[b]}var e=new (B?Uint16Array:Array)(c),f=new (B?Uint8Array:Array)(c),g=new (B?Uint8Array:Array)(a),k=Array(c),h=Array(c),l=Array(c),s=(1<<c)-a,p=1<<c-1,m,n,r,v,x;e[c-1]=a;for(n=0;n<c;++n)s<p?f[n]=0:(f[n]=1,s-=p),s<<=1,e[c-2-n]=(e[c-1-n]/2|0)+a;e[0]=f[0];k[0]=Array(e[0]);h[0]=Array(e[0]);for(n=1;n<c;++n)e[n]>2*e[n-1]+f[n]&&(e[n]=2*e[n-1]+f[n]),k[n]=Array(e[n]),h[n]=Array(e[n]);for(m=0;m<a;++m)g[m]=c;for(r=0;r<e[c-1];++r)k[c-
+1][r]=b[r],h[c-1][r]=r;for(m=0;m<c;++m)l[m]=0;1===f[c-1]&&(--g[0],++l[c-1]);for(n=c-2;0<=n;--n){v=m=0;x=l[n+1];for(r=0;r<e[n];r++)v=k[n+1][x]+k[n+1][x+1],v>b[m]?(k[n][r]=v,h[n][r]=a,x+=2):(k[n][r]=b[m],h[n][r]=m,++m);l[n]=0;1===f[n]&&d(n)}return g}
+function va(b){var a=new (B?Uint16Array:Array)(b.length),c=[],d=[],e=0,f,g,k,h;f=0;for(g=b.length;f<g;f++)c[b[f]]=(c[b[f]]|0)+1;f=1;for(g=16;f<=g;f++)d[f]=e,e+=c[f]|0,e<<=1;f=0;for(g=b.length;f<g;f++){e=d[b[f]];d[b[f]]+=1;k=a[f]=0;for(h=b[f];k<h;k++)a[f]=a[f]<<1|e&1,e>>>=1}return a};function Da(b,a){this.input=b;this.b=this.c=0;this.i={};a&&(a.flags&&(this.i=a.flags),"string"===typeof a.filename&&(this.filename=a.filename),"string"===typeof a.comment&&(this.A=a.comment),a.deflateOptions&&(this.l=a.deflateOptions));this.l||(this.l={})}
+Da.prototype.g=function(){var b,a,c,d,e,f,g,k,h=new (B?Uint8Array:Array)(32768),l=0,s=this.input,p=this.c,m=this.filename,n=this.A;h[l++]=31;h[l++]=139;h[l++]=8;b=0;this.i.fname&&(b|=Ea);this.i.fcomment&&(b|=Fa);this.i.fhcrc&&(b|=Ga);h[l++]=b;a=(Date.now?Date.now():+new Date)/1E3|0;h[l++]=a&255;h[l++]=a>>>8&255;h[l++]=a>>>16&255;h[l++]=a>>>24&255;h[l++]=0;h[l++]=Ha;if(this.i.fname!==t){g=0;for(k=m.length;g<k;++g)f=m.charCodeAt(g),255<f&&(h[l++]=f>>>8&255),h[l++]=f&255;h[l++]=0}if(this.i.comment){g=
+0;for(k=n.length;g<k;++g)f=n.charCodeAt(g),255<f&&(h[l++]=f>>>8&255),h[l++]=f&255;h[l++]=0}this.i.fhcrc&&(c=ja(h,0,l)&65535,h[l++]=c&255,h[l++]=c>>>8&255);this.l.outputBuffer=h;this.l.outputIndex=l;e=new na(s,this.l);h=e.g();l=e.b;B&&(l+8>h.buffer.byteLength?(this.a=new Uint8Array(l+8),this.a.set(new Uint8Array(h.buffer)),h=this.a):h=new Uint8Array(h.buffer));d=ja(s,t,t);h[l++]=d&255;h[l++]=d>>>8&255;h[l++]=d>>>16&255;h[l++]=d>>>24&255;k=s.length;h[l++]=k&255;h[l++]=k>>>8&255;h[l++]=k>>>16&255;h[l++]=
+k>>>24&255;this.c=p;B&&l<h.length&&(this.a=h=h.subarray(0,l));return h};var Ha=255,Ga=2,Ea=8,Fa=16;A("Zlib.Gzip",Da);A("Zlib.Gzip.prototype.compress",Da.prototype.g);function T(b,a){this.p=[];this.q=32768;this.e=this.j=this.c=this.u=0;this.input=B?new Uint8Array(b):b;this.w=!1;this.r=Ia;this.M=!1;if(a||!(a={}))a.index&&(this.c=a.index),a.bufferSize&&(this.q=a.bufferSize),a.bufferType&&(this.r=a.bufferType),a.resize&&(this.M=a.resize);switch(this.r){case Ja:this.b=32768;this.a=new (B?Uint8Array:Array)(32768+this.q+258);break;case Ia:this.b=0;this.a=new (B?Uint8Array:Array)(this.q);this.f=this.U;this.B=this.R;this.s=this.T;break;default:q(Error("invalid inflate mode"))}}
+var Ja=0,Ia=1,Ya={O:Ja,N:Ia};
+T.prototype.h=function(){for(;!this.w;){var b=U(this,3);b&1&&(this.w=u);b>>>=1;switch(b){case 0:var a=this.input,c=this.c,d=this.a,e=this.b,f=a.length,g=t,k=t,h=d.length,l=t;this.e=this.j=0;c+1>=f&&q(Error("invalid uncompressed block header: LEN"));g=a[c++]|a[c++]<<8;c+1>=f&&q(Error("invalid uncompressed block header: NLEN"));k=a[c++]|a[c++]<<8;g===~k&&q(Error("invalid uncompressed block header: length verify"));c+g>a.length&&q(Error("input buffer is broken"));switch(this.r){case Ja:for(;e+g>d.length;){l=
+h-e;g-=l;if(B)d.set(a.subarray(c,c+l),e),e+=l,c+=l;else for(;l--;)d[e++]=a[c++];this.b=e;d=this.f();e=this.b}break;case Ia:for(;e+g>d.length;)d=this.f({F:2});break;default:q(Error("invalid inflate mode"))}if(B)d.set(a.subarray(c,c+g),e),e+=g,c+=g;else for(;g--;)d[e++]=a[c++];this.c=c;this.b=e;this.a=d;break;case 1:this.s(Za,$a);break;case 2:ab(this);break;default:q(Error("unknown BTYPE: "+b))}}return this.B()};
+var bb=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],cb=B?new Uint16Array(bb):bb,db=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],eb=B?new Uint16Array(db):db,fb=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],gb=B?new Uint8Array(fb):fb,hb=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],ib=B?new Uint16Array(hb):hb,jb=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,
+10,11,11,12,12,13,13],kb=B?new Uint8Array(jb):jb,lb=new (B?Uint8Array:Array)(288),V,mb;V=0;for(mb=lb.length;V<mb;++V)lb[V]=143>=V?8:255>=V?9:279>=V?7:8;var Za=ma(lb),nb=new (B?Uint8Array:Array)(30),ob,qb;ob=0;for(qb=nb.length;ob<qb;++ob)nb[ob]=5;var $a=ma(nb);function U(b,a){for(var c=b.j,d=b.e,e=b.input,f=b.c,g=e.length,k;d<a;)f>=g&&q(Error("input buffer is broken")),c|=e[f++]<<d,d+=8;k=c&(1<<a)-1;b.j=c>>>a;b.e=d-a;b.c=f;return k}
+function rb(b,a){for(var c=b.j,d=b.e,e=b.input,f=b.c,g=e.length,k=a[0],h=a[1],l,s;d<h&&!(f>=g);)c|=e[f++]<<d,d+=8;l=k[c&(1<<h)-1];s=l>>>16;b.j=c>>s;b.e=d-s;b.c=f;return l&65535}
+function ab(b){function a(a,b,c){var d,e=this.J,f,g;for(g=0;g<a;)switch(d=rb(this,b),d){case 16:for(f=3+U(this,2);f--;)c[g++]=e;break;case 17:for(f=3+U(this,3);f--;)c[g++]=0;e=0;break;case 18:for(f=11+U(this,7);f--;)c[g++]=0;e=0;break;default:e=c[g++]=d}this.J=e;return c}var c=U(b,5)+257,d=U(b,5)+1,e=U(b,4)+4,f=new (B?Uint8Array:Array)(cb.length),g,k,h,l;for(l=0;l<e;++l)f[cb[l]]=U(b,3);if(!B){l=e;for(e=f.length;l<e;++l)f[cb[l]]=0}g=ma(f);k=new (B?Uint8Array:Array)(c);h=new (B?Uint8Array:Array)(d);
+b.J=0;b.s(ma(a.call(b,c,g,k)),ma(a.call(b,d,g,h)))}T.prototype.s=function(b,a){var c=this.a,d=this.b;this.C=b;for(var e=c.length-258,f,g,k,h;256!==(f=rb(this,b));)if(256>f)d>=e&&(this.b=d,c=this.f(),d=this.b),c[d++]=f;else{g=f-257;h=eb[g];0<gb[g]&&(h+=U(this,gb[g]));f=rb(this,a);k=ib[f];0<kb[f]&&(k+=U(this,kb[f]));d>=e&&(this.b=d,c=this.f(),d=this.b);for(;h--;)c[d]=c[d++-k]}for(;8<=this.e;)this.e-=8,this.c--;this.b=d};
+T.prototype.T=function(b,a){var c=this.a,d=this.b;this.C=b;for(var e=c.length,f,g,k,h;256!==(f=rb(this,b));)if(256>f)d>=e&&(c=this.f(),e=c.length),c[d++]=f;else{g=f-257;h=eb[g];0<gb[g]&&(h+=U(this,gb[g]));f=rb(this,a);k=ib[f];0<kb[f]&&(k+=U(this,kb[f]));d+h>e&&(c=this.f(),e=c.length);for(;h--;)c[d]=c[d++-k]}for(;8<=this.e;)this.e-=8,this.c--;this.b=d};
+T.prototype.f=function(){var b=new (B?Uint8Array:Array)(this.b-32768),a=this.b-32768,c,d,e=this.a;if(B)b.set(e.subarray(32768,b.length));else{c=0;for(d=b.length;c<d;++c)b[c]=e[c+32768]}this.p.push(b);this.u+=b.length;if(B)e.set(e.subarray(a,a+32768));else for(c=0;32768>c;++c)e[c]=e[a+c];this.b=32768;return e};
+T.prototype.U=function(b){var a,c=this.input.length/this.c+1|0,d,e,f,g=this.input,k=this.a;b&&("number"===typeof b.F&&(c=b.F),"number"===typeof b.P&&(c+=b.P));2>c?(d=(g.length-this.c)/this.C[2],f=258*(d/2)|0,e=f<k.length?k.length+f:k.length<<1):e=k.length*c;B?(a=new Uint8Array(e),a.set(k)):a=k;return this.a=a};
+T.prototype.B=function(){var b=0,a=this.a,c=this.p,d,e=new (B?Uint8Array:Array)(this.u+(this.b-32768)),f,g,k,h;if(0===c.length)return B?this.a.subarray(32768,this.b):this.a.slice(32768,this.b);f=0;for(g=c.length;f<g;++f){d=c[f];k=0;for(h=d.length;k<h;++k)e[b++]=d[k]}f=32768;for(g=this.b;f<g;++f)e[b++]=a[f];this.p=[];return this.buffer=e};
+T.prototype.R=function(){var b,a=this.b;B?this.M?(b=new Uint8Array(a),b.set(this.a.subarray(0,a))):b=this.a.subarray(0,a):(this.a.length>a&&(this.a.length=a),b=this.a);return this.buffer=b};function sb(b){this.input=b;this.c=0;this.t=[];this.D=!1}sb.prototype.X=function(){this.D||this.h();return this.t.slice()};
+sb.prototype.h=function(){for(var b=this.input.length;this.c<b;){var a=new P,c=t,d=t,e=t,f=t,g=t,k=t,h=t,l=t,s=t,p=this.input,m=this.c;a.G=p[m++];a.H=p[m++];(31!==a.G||139!==a.H)&&q(Error("invalid file signature:"+a.G+","+a.H));a.z=p[m++];switch(a.z){case 8:break;default:q(Error("unknown compression method: "+a.z))}a.n=p[m++];l=p[m++]|p[m++]<<8|p[m++]<<16|p[m++]<<24;a.Z=new Date(1E3*l);a.fa=p[m++];a.ea=p[m++];0<(a.n&4)&&(a.aa=p[m++]|p[m++]<<8,m+=a.aa);if(0<(a.n&Ea)){h=[];for(k=0;0<(g=p[m++]);)h[k++]=
+String.fromCharCode(g);a.name=h.join("")}if(0<(a.n&Fa)){h=[];for(k=0;0<(g=p[m++]);)h[k++]=String.fromCharCode(g);a.A=h.join("")}0<(a.n&Ga)&&(a.S=ja(p,0,m)&65535,a.S!==(p[m++]|p[m++]<<8)&&q(Error("invalid header crc16")));c=p[p.length-4]|p[p.length-3]<<8|p[p.length-2]<<16|p[p.length-1]<<24;p.length-m-4-4<512*c&&(f=c);d=new T(p,{index:m,bufferSize:f});a.data=e=d.h();m=d.c;a.ca=s=(p[m++]|p[m++]<<8|p[m++]<<16|p[m++]<<24)>>>0;ja(e,t,t)!==s&&q(Error("invalid CRC-32 checksum: 0x"+ja(e,t,t).toString(16)+
+" / 0x"+s.toString(16)));a.da=c=(p[m++]|p[m++]<<8|p[m++]<<16|p[m++]<<24)>>>0;(e.length&4294967295)!==c&&q(Error("invalid input size: "+(e.length&4294967295)+" / "+c));this.t.push(a);this.c=m}this.D=u;var n=this.t,r,v,x=0,Q=0,y;r=0;for(v=n.length;r<v;++r)Q+=n[r].data.length;if(B){y=new Uint8Array(Q);for(r=0;r<v;++r)y.set(n[r].data,x),x+=n[r].data.length}else{y=[];for(r=0;r<v;++r)y[r]=n[r].data;y=Array.prototype.concat.apply([],y)}return y};A("Zlib.Gunzip",sb);A("Zlib.Gunzip.prototype.decompress",sb.prototype.h);A("Zlib.Gunzip.prototype.getMembers",sb.prototype.X);function tb(b){if("string"===typeof b){var a=b.split(""),c,d;c=0;for(d=a.length;c<d;c++)a[c]=(a[c].charCodeAt(0)&255)>>>0;b=a}for(var e=1,f=0,g=b.length,k,h=0;0<g;){k=1024<g?1024:g;g-=k;do e+=b[h++],f+=e;while(--k);e%=65521;f%=65521}return(f<<16|e)>>>0};function ub(b,a){var c,d;this.input=b;this.c=0;if(a||!(a={}))a.index&&(this.c=a.index),a.verify&&(this.$=a.verify);c=b[this.c++];d=b[this.c++];switch(c&15){case vb:this.method=vb;break;default:q(Error("unsupported compression method"))}0!==((c<<8)+d)%31&&q(Error("invalid fcheck flag:"+((c<<8)+d)%31));d&32&&q(Error("fdict flag is not supported"));this.L=new T(b,{index:this.c,bufferSize:a.bufferSize,bufferType:a.bufferType,resize:a.resize})}
+ub.prototype.h=function(){var b=this.input,a,c;a=this.L.h();this.c=this.L.c;this.$&&(c=(b[this.c++]<<24|b[this.c++]<<16|b[this.c++]<<8|b[this.c++])>>>0,c!==tb(a)&&q(Error("invalid adler-32 checksum")));return a};var vb=8;function wb(b,a){this.input=b;this.a=new (B?Uint8Array:Array)(32768);this.k=W.o;var c={},d;if((a||!(a={}))&&"number"===typeof a.compressionType)this.k=a.compressionType;for(d in a)c[d]=a[d];c.outputBuffer=this.a;this.K=new na(this.input,c)}var W=ra;
+wb.prototype.g=function(){var b,a,c,d,e,f,g,k=0;g=this.a;b=vb;switch(b){case vb:a=Math.LOG2E*Math.log(32768)-8;break;default:q(Error("invalid compression method"))}c=a<<4|b;g[k++]=c;switch(b){case vb:switch(this.k){case W.NONE:e=0;break;case W.v:e=1;break;case W.o:e=2;break;default:q(Error("unsupported compression type"))}break;default:q(Error("invalid compression method"))}d=e<<6|0;g[k++]=d|31-(256*c+d)%31;f=tb(this.input);this.K.b=k;g=this.K.g();k=g.length;B&&(g=new Uint8Array(g.buffer),g.length<=
+k+4&&(this.a=new Uint8Array(g.length+4),this.a.set(g),g=this.a),g=g.subarray(0,k+4));g[k++]=f>>24&255;g[k++]=f>>16&255;g[k++]=f>>8&255;g[k++]=f&255;return g};function xb(b,a){var c,d,e,f;if(Object.keys)c=Object.keys(a);else for(d in c=[],e=0,a)c[e++]=d;e=0;for(f=c.length;e<f;++e)d=c[e],A(b+"."+d,a[d])};A("Zlib.Inflate",ub);A("Zlib.Inflate.prototype.decompress",ub.prototype.h);xb("Zlib.Inflate.BufferType",{ADAPTIVE:Ya.N,BLOCK:Ya.O});A("Zlib.Deflate",wb);A("Zlib.Deflate.compress",function(b,a){return(new wb(b,a)).g()});A("Zlib.Deflate.prototype.compress",wb.prototype.g);xb("Zlib.Deflate.CompressionType",{NONE:W.NONE,FIXED:W.v,DYNAMIC:W.o});}).call(this); //@ sourceMappingURL=zlib_and_gzip.min.js.map

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 4 - 0
examples/js/libs/zlib_and_gzip.min.js.map


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

@@ -12,7 +12,7 @@ THREE.HDRCubeTextureLoader = function (manager) {
 }
 
 THREE.HDRCubeTextureLoader.prototype.load = function(type, urls, onLoad, onProgress, onError) {
-  var texture = new THREE.CubeTexture( [] );
+  var texture = new THREE.CubeTexture();
 
   texture.type = type;
   texture.encoding = (type === THREE.UnsignedByteType) ? THREE.RGBEEncoding : THREE.LinearEncoding;

+ 591 - 0
examples/js/loaders/NRRDLoader.js

@@ -0,0 +1,591 @@
+THREE.NRRDLoader = function( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+
+
+};
+
+THREE.NRRDLoader.prototype = {
+
+	constructor: THREE.NRRDLoader,
+
+	load: function( url, onLoad, onProgress, onError ) {
+
+		var scope = this;
+
+		var loader = new THREE.XHRLoader( scope.manager );
+		loader.setResponseType( 'arraybuffer' );
+		loader.load( url, function( data ) {
+
+			onLoad( scope.parse( data ) );
+
+		}, onProgress, onError );
+
+	},
+
+	//this parser is largely inspired from the XTK NRRD parser : https://github.com/xtk/X
+	parse: function( data ) {
+
+
+		var _data = data;
+
+		var _dataPointer = 0;
+
+		var _nativeLittleEndian = new Int8Array( new Int16Array( [ 1 ] ).buffer )[ 0 ] > 0;
+
+		var _littleEndian = true;
+
+		var _lastMin = - Infinity;
+
+		var _lastMax = Infinity;
+
+		var headerObject = {};
+
+		function scan( type, chunks ) {
+
+			if ( chunks === undefined || chunks === null ) {
+
+				chunks = 1;
+
+			}
+
+			var _chunkSize = 1;
+			var _array_type = Uint8Array;
+
+			switch ( type ) {
+
+			// 1 byte data types
+				case 'uchar':
+					break;
+				case 'schar':
+					_array_type = Int8Array;
+					break;
+					// 2 byte data types
+				case 'ushort':
+					_array_type = Uint16Array;
+					_chunkSize = 2;
+					break;
+				case 'sshort':
+					_array_type = Int16Array;
+					_chunkSize = 2;
+					break;
+					// 4 byte data types
+				case 'uint':
+					_array_type = Uint32Array;
+					_chunkSize = 4;
+					break;
+				case 'sint':
+					_array_type = Int32Array;
+					_chunkSize = 4;
+					break;
+				case 'float':
+					_array_type = Float32Array;
+					_chunkSize = 4;
+					break;
+				case 'complex':
+					_array_type = Float64Array;
+					_chunkSize = 8;
+					break;
+				case 'double':
+					_array_type = Float64Array;
+					_chunkSize = 8;
+					break;
+
+			}
+
+			// increase the data pointer in-place
+			var _bytes = new _array_type( _data.slice( _dataPointer,
+			_dataPointer += chunks * _chunkSize ) );
+
+			// if required, flip the endianness of the bytes
+			if ( _nativeLittleEndian != _littleEndian ) {
+
+				// we need to flip here since the format doesn't match the native endianness
+				_bytes = flipEndianness( _bytes, _chunkSize );
+
+			}
+
+			if ( chunks == 1 ) {
+
+				// if only one chunk was requested, just return one value
+				return _bytes[ 0 ];
+
+			}
+
+			// return the byte array
+			return _bytes;
+
+		}
+
+		//Flips typed array endianness in-place. Based on https://github.com/kig/DataStream.js/blob/master/DataStream.js.
+
+		function flipEndianness( array, chunkSize ) {
+
+			var u8 = new Uint8Array( array.buffer, array.byteOffset, array.byteLength );
+			for ( var i = 0; i < array.byteLength; i += chunkSize ) {
+
+				for ( var j = i + chunkSize - 1, k = i; j > k; j --, k ++ ) {
+
+					var tmp = u8[ k ];
+					u8[ k ] = u8[ j ];
+					u8[ j ] = tmp;
+
+				}
+
+			}
+
+			return array;
+
+		}
+
+		//parse the header
+		function parseHeader( header ) {
+
+			var data, field, fn, i, l, lines, m, _i, _len;
+			lines = header.split( /\r?\n/ );
+			for ( _i = 0, _len = lines.length; _i < _len; _i ++ ) {
+
+				l = lines[ _i ];
+				if ( l.match( /NRRD\d+/ ) ) {
+
+					headerObject.isNrrd = true;
+
+				} else if ( l.match( /^#/ ) ) {
+				} else if ( m = l.match( /(.*):(.*)/ ) ) {
+
+					field = m[ 1 ].trim();
+					data = m[ 2 ].trim();
+					fn = THREE.NRRDLoader.prototype.fieldFunctions[ field ];
+					if ( fn ) {
+
+						fn.call( headerObject, data );
+
+					} else {
+
+						headerObject[ field ] = data;
+
+					}
+
+				}
+
+			}
+			if ( ! headerObject.isNrrd ) {
+
+				throw new Error( 'Not an NRRD file' );
+
+			}
+			if ( headerObject.encoding === 'bz2' || headerObject.encoding === 'bzip2' ) {
+
+				throw new Error( 'Bzip is not supported' );
+
+			}
+			if ( ! headerObject.vectors ) {
+
+				//if no space direction is set, let's use the identity
+				headerObject.vectors = [ new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ) ];
+				//apply spacing if defined
+				if ( headerObject.spacings ) {
+
+					for ( i = 0; i <= 2; i ++ ) {
+
+						if ( ! isNaN( headerObject.spacings[ i ] ) ) {
+
+							headerObject.vectors[ i ].multiplyScalar( headerObject.spacings[ i ] );
+
+						}
+
+					}
+
+				}
+
+			}
+
+		}
+
+		//parse the data when registred as one of this type : 'text', 'ascii', 'txt'
+		function parseDataAsText( data, start, end ) {
+
+			var number = '';
+			start = start || 0;
+			end = end || data.length;
+			var lastSpace = start;
+			var value;
+			//length of the result is the product of the sizes
+			var lengthOfTheResult = headerObject.sizes.reduce( function( previous, current ) {
+
+				return previous * current;
+
+			}, 1 );
+
+			var base = 10;
+			if ( headerObject.encoding === 'hex' ) {
+
+				base = 16;
+
+			}
+
+			var result = new headerObject.__array( lengthOfTheResult );
+			var resultIndex = 0;
+			var parsingFunction = parseInt;
+			if ( headerObject.__array === Float32Array || headerObject.__array === Float64Array ) {
+
+				parsingFunction = parseFloat;
+
+			}
+			for ( var i = start; i < end; i ++ ) {
+
+				value = data[ i ];
+				//if value is not a space
+				if ( ( value < 9 || value > 13 ) && value !== 32 ) {
+
+					number += String.fromCharCode( value );
+
+				}
+				else {
+
+					if ( number !== '' ) {
+
+						result[ resultIndex ] = parsingFunction( number, base );
+						resultIndex ++;
+
+					}
+					number = '';
+
+				}
+
+			}
+			if ( number !== '' ) {
+
+				result[ resultIndex ] = parsingFunction( number, base );
+				resultIndex ++;
+
+			}
+			return result;
+
+		}
+
+		var _bytes = scan( 'uchar', data.byteLength );
+		var _length = _bytes.length;
+		var _header = null;
+		var _data_start = 0;
+		var i;
+		for ( i = 1; i < _length; i ++ ) {
+
+			if ( _bytes[ i - 1 ] == 10 && _bytes[ i ] == 10 ) {
+
+				// we found two line breaks in a row
+				// now we know what the header is
+				_header = this.parseChars( _bytes, 0, i - 2 );
+				// this is were the data starts
+				_data_start = i + 1;
+				break;
+
+			}
+
+		}
+		// parse the header
+		parseHeader( _header );
+
+		var _data = _bytes.subarray( _data_start ); // the data without header
+		if ( headerObject.encoding === 'gzip' || headerObject.encoding === 'gz' ) {
+
+			// we need to decompress the datastream
+			// here we start the unzipping and get a typed Uint8Array back
+			var inflate = new Zlib.Gunzip( new Uint8Array( _data ) );
+			_data = inflate.decompress();
+
+		}
+		else if ( headerObject.encoding === 'ascii' || headerObject.encoding === 'text' || headerObject.encoding === 'txt' || headerObject.encoding === 'hex' ) {
+
+			_data = parseDataAsText( _data );
+
+		}
+		// .. let's use the underlying array buffer
+		_data = _data.buffer;
+
+		var volume = new THREE.Volume();
+		volume.header = headerObject;
+		//
+		// parse the (unzipped) data to a datastream of the correct type
+		//
+		volume.data = new headerObject.__array( _data );
+		// get the min and max intensities
+		var min_max = volume.computeMinMax();
+		var min = min_max[ 0 ];
+		var max = min_max[ 1 ];
+		// attach the scalar range to the volume
+		volume.windowLow = min;
+		volume.windowHigh = max;
+
+		// get the image dimensions
+		volume.dimensions = [ headerObject.sizes[ 0 ], headerObject.sizes[ 1 ], headerObject.sizes[ 2 ] ];
+		volume.xLength = volume.dimensions[ 0 ];
+		volume.yLength = volume.dimensions[ 1 ];
+		volume.zLength = volume.dimensions[ 2 ];
+		// spacing
+		var spacingX = ( new THREE.Vector3( headerObject.vectors[ 0 ][ 0 ], headerObject.vectors[ 0 ][ 1 ],
+		headerObject.vectors[ 0 ][ 2 ] ) ).length();
+		var spacingY = ( new THREE.Vector3( headerObject.vectors[ 1 ][ 0 ], headerObject.vectors[ 1 ][ 1 ],
+		headerObject.vectors[ 1 ][ 2 ] ) ).length();
+		var spacingZ = ( new THREE.Vector3( headerObject.vectors[ 2 ][ 0 ], headerObject.vectors[ 2 ][ 1 ],
+		headerObject.vectors[ 2 ][ 2 ] ) ).length();
+		volume.spacing = [ spacingX, spacingY, spacingZ ];
+
+
+		// Create IJKtoRAS matrix
+		volume.matrix = new THREE.Matrix4();
+
+		var _spaceX = 1;
+		var _spaceY = 1;
+		var _spaceZ = 1;
+
+		if ( headerObject.space == "left-posterior-superior" ) {
+
+			_spaceX = - 1;
+			_spaceY = - 1;
+
+		}
+		else if ( headerObject.space === 'left-anterior-superior' ) {
+
+			_spaceX = - 1
+
+		}
+
+
+		if ( ! headerObject.vectors ) {
+
+			volume.matrix.set( _spaceX, 0, 0, 0,
+			0, _spaceY, 0, 0,
+			0, 0, _spaceZ, 0,
+			0, 0, 0, 1 );
+
+		}
+		else {
+
+			var v = headerObject.vectors;
+			var origin = headerObject.space_origin;
+
+			if ( ! origin ) {
+
+				origin = [ 0, 0, 0 ];
+
+			}
+
+			volume.matrix.set( _spaceX * v[ 0 ][ 0 ], _spaceX * v[ 1 ][ 0 ], _spaceX * v[ 2 ][ 0 ], 0,
+			_spaceY * v[ 0 ][ 1 ], _spaceY * v[ 1 ][ 1 ], _spaceY * v[ 2 ][ 1 ], 0,
+			_spaceZ * v[ 0 ][ 2 ], _spaceZ * v[ 1 ][ 2 ], _spaceZ * v[ 2 ][ 2 ], 0,
+			0, 0, 0, 1 );
+
+		}
+
+		volume.inverseMatrix = new THREE.Matrix4();
+		volume.inverseMatrix.getInverse( volume.matrix );
+		volume.RASDimensions = ( new THREE.Vector3( volume.xLength, volume.yLength, volume.zLength ) ).applyMatrix4( volume.matrix ).round().toArray().map( Math.abs );
+
+		// .. and set the default threshold
+		// only if the threshold was not already set
+		if ( volume.lowerThreshold === - Infinity ) {
+
+			volume.lowerThreshold = min;
+
+		}
+		if ( volume.upperThreshold === Infinity ) {
+
+			volume.upperThreshold = max;
+
+		}
+
+		return volume;
+
+	},
+
+	parseChars: function( array, start, end ) {
+
+		// without borders, use the whole array
+		if ( start === undefined ) {
+
+			start = 0;
+
+		}
+		if ( end === undefined ) {
+
+			end = array.length;
+
+		}
+
+		var output = '';
+		// create and append the chars
+		var i = 0;
+		for ( i = start; i < end; ++ i ) {
+
+			output += String.fromCharCode( array[ i ] );
+
+		}
+
+		return output;
+
+	},
+
+	fieldFunctions: {
+
+		type: function( data ) {
+
+			switch ( data ) {
+				case 'uchar':
+				case 'unsigned char':
+				case 'uint8':
+				case 'uint8_t':
+					this.__array = Uint8Array;
+					break;
+				case 'signed char':
+				case 'int8':
+				case 'int8_t':
+					this.__array = Int8Array;
+					break;
+				case 'short':
+				case 'short int':
+				case 'signed short':
+				case 'signed short int':
+				case 'int16':
+				case 'int16_t':
+					this.__array = Int16Array;
+					break;
+				case 'ushort':
+				case 'unsigned short':
+				case 'unsigned short int':
+				case 'uint16':
+				case 'uint16_t':
+					this.__array = Uint16Array;
+					break;
+				case 'int':
+				case 'signed int':
+				case 'int32':
+				case 'int32_t':
+					this.__array = Int32Array;
+					break;
+				case 'uint':
+				case 'unsigned int':
+				case 'uint32':
+				case 'uint32_t':
+					this.__array = Uint32Array;
+					break;
+				case 'float':
+					this.__array = Float32Array;
+					break;
+				case 'double':
+					this.__array = Float64Array;
+					break;
+				default:
+					throw new Error( 'Unsupported NRRD data type: ' + data );
+			}
+			return this.type = data;
+
+		},
+
+		endian: function( data ) {
+
+			return this.endian = data;
+
+		},
+
+		encoding: function( data ) {
+
+			return this.encoding = data;
+
+		},
+
+		dimension: function( data ) {
+
+			return this.dim = parseInt( data, 10 );
+
+		},
+
+		sizes: function( data ) {
+
+			var i;
+			return this.sizes = ( function() {
+
+				var _i, _len, _ref, _results;
+				_ref = data.split( /\s+/ );
+				_results = [];
+				for ( _i = 0, _len = _ref.length; _i < _len; _i ++ ) {
+
+					i = _ref[ _i ];
+					_results.push( parseInt( i, 10 ) );
+
+				}
+				return _results;
+
+			} )();
+
+		},
+
+		space: function( data ) {
+
+			return this.space = data;
+
+		},
+
+		'space origin' : function( data ) {
+
+			return this.space_origin = data.split( "(" )[ 1 ].split( ")" )[ 0 ].split( "," );
+
+		},
+
+		'space directions' : function( data ) {
+
+			var f, parts, v;
+			parts = data.match( /\(.*?\)/g );
+			return this.vectors = ( function() {
+
+				var _i, _len, _results;
+				_results = [];
+				for ( _i = 0, _len = parts.length; _i < _len; _i ++ ) {
+
+					v = parts[ _i ];
+					_results.push( ( function() {
+
+						var _j, _len2, _ref, _results2;
+						_ref = v.slice( 1, - 1 ).split( /,/ );
+						_results2 = [];
+						for ( _j = 0, _len2 = _ref.length; _j < _len2; _j ++ ) {
+
+							f = _ref[ _j ];
+							_results2.push( parseFloat( f ) );
+
+						}
+						return _results2;
+
+					} )() );
+
+				}
+				return _results;
+
+			} )();
+
+		},
+
+		spacings: function( data ) {
+
+			var f, parts;
+			parts = data.split( /\s+/ );
+			return this.spacings = ( function() {
+
+				var _i, _len, _results;
+				_results = [];
+				for ( _i = 0, _len = parts.length; _i < _len; _i ++ ) {
+
+					f = parts[ _i ];
+					_results.push( parseFloat( f ) );
+
+				}
+				return _results;
+
+			} )();
+
+		}
+	}
+
+};
+
+THREE.EventDispatcher.prototype.apply( THREE.NRRDLoader.prototype );

+ 571 - 16
examples/js/loaders/VTKLoader.js

@@ -369,11 +369,11 @@ THREE.VTKLoader.prototype = {
 				state = findString ( buffer, index );
 				line = state.parsedString;
 
-				if ( line.indexOf ( "POINTS" ) === 0 ) {
+				if ( line.indexOf ( 'POINTS' ) === 0 ) {
 
 					vtk.push ( line );
 					// Add the points
-					numberOfPoints = parseInt ( line.split( " " )[ 1 ], 10 );
+					numberOfPoints = parseInt ( line.split( ' ' )[ 1 ], 10 );
 
 					// Each point is 3 4-byte floats
 					count = numberOfPoints * 4 * 3;
@@ -392,10 +392,10 @@ THREE.VTKLoader.prototype = {
 					// increment our next pointer
 					state.next = state.next + count + 1;
 
-				} else if ( line.indexOf ( "TRIANGLE_STRIPS" ) === 0 ) {
+				} else if ( line.indexOf ( 'TRIANGLE_STRIPS' ) === 0 ) {
 
-					var numberOfStrips = parseInt ( line.split( " " )[ 1 ], 10 );
-					var size = parseInt ( line.split ( " " )[ 2 ], 10 );
+					var numberOfStrips = parseInt ( line.split( ' ' )[ 1 ], 10 );
+					var size = parseInt ( line.split ( ' ' )[ 2 ], 10 );
 					// 4 byte integers
 					count = size * 4;
 
@@ -440,10 +440,10 @@ THREE.VTKLoader.prototype = {
 					// increment our next pointer
 					state.next = state.next + count + 1;
 
-				} else if ( line.indexOf ( "POLYGONS" ) === 0 ) {
+				} else if ( line.indexOf ( 'POLYGONS' ) === 0 ) {
 
-					var numberOfStrips = parseInt ( line.split( " " )[ 1 ], 10 );
-					var size = parseInt ( line.split ( " " )[ 2 ], 10 );
+					var numberOfStrips = parseInt ( line.split( ' ' )[ 1 ], 10 );
+					var size = parseInt ( line.split ( ' ' )[ 2 ], 10 );
 					// 4 byte integers
 					count = size * 4;
 
@@ -477,9 +477,9 @@ THREE.VTKLoader.prototype = {
 					// increment our next pointer
 					state.next = state.next + count + 1;
 
-				} else if ( line.indexOf ( "POINT_DATA" ) === 0 ) {
+				} else if ( line.indexOf ( 'POINT_DATA' ) === 0 ) {
 
-					numberOfPoints = parseInt ( line.split( " " )[ 1 ], 10 );
+					numberOfPoints = parseInt ( line.split( ' ' )[ 1 ], 10 );
 
 					// Grab the next line
 					state = findString ( buffer, state.next );
@@ -528,22 +528,577 @@ THREE.VTKLoader.prototype = {
 
 		}
 
-		// get the 5 first lines of the files to check if there is the key word binary
+		function parseXML( stringFile ) {
 
-		var meta = String.fromCharCode.apply( null, new Uint8Array( data, 0, 250 ) ).split( '\n' );
+			// Changes XML to JSON, based on https://davidwalsh.name/convert-xml-json
+
+			function xmlToJson( xml ) {
+
+				// Create the return object
+				var obj = {};
+
+				if ( xml.nodeType == 1 ) { // element
+
+					// do attributes
+
+					if ( xml.attributes ) {
+
+						if ( xml.attributes.length > 0 ) {
+
+							obj[ 'attributes' ] = {};
+
+							for ( var j = 0; j < xml.attributes.length; j ++ ) {
+
+								var attribute = xml.attributes.item( j );
+								obj[ 'attributes' ][ attribute.nodeName ] = attribute.nodeValue.trim();
+
+							}
+
+						}
+
+					}
+
+				} else if ( xml.nodeType == 3 ) { // text
+
+					obj = xml.nodeValue.trim();
+
+				}
+
+				// do children
+				if ( xml.hasChildNodes() ) {
+
+					for ( var i = 0; i < xml.childNodes.length; i ++ ) {
+
+						var item = xml.childNodes.item( i );
+						var nodeName = item.nodeName;
+
+						if ( typeof( obj[ nodeName ] ) === 'undefined' ) {
+
+							var tmp = xmlToJson( item );
+
+							if ( tmp !== '' ) obj[ nodeName ] = tmp;
+
+						} else {
+
+							if ( typeof( obj[ nodeName ].push ) === 'undefined' ) {
+
+								var old = obj[ nodeName ];
+								obj[ nodeName ] = [ old ];
+
+							}
+
+							var tmp = xmlToJson( item );
+
+							if ( tmp !== '' ) obj[ nodeName ].push( tmp );
+
+						}
+
+					}
+
+				}
+
+				return obj;
+
+			}
+
+			// Taken from Base64-js
+			function Base64toByteArray( b64 ) {
+
+				var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array;
+				var i;
+				var lookup = [];
+				var revLookup = [];
+				var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
+				var len = code.length;
+
+				for ( i = 0; i < len; i ++ ) {
+
+					lookup[ i ] = code[ i ];
+
+				}
+
+				for ( i = 0; i < len; ++ i ) {
+
+					revLookup[ code.charCodeAt( i ) ] = i;
+
+				}
+
+				revLookup[ '-'.charCodeAt( 0 ) ] = 62;
+				revLookup[ '_'.charCodeAt( 0 ) ] = 63;
+
+				var j, l, tmp, placeHolders, arr;
+				var len = b64.length;
+
+				if ( len % 4 > 0 ) {
+
+					throw new Error( 'Invalid string. Length must be a multiple of 4' );
+
+				}
+
+				placeHolders = b64[ len - 2 ] === '=' ? 2 : b64[ len - 1 ] === '=' ? 1 : 0;
+				arr = new Arr( len * 3 / 4 - placeHolders );
+				l = placeHolders > 0 ? len - 4 : len;
+
+				var L = 0;
+
+				for ( i = 0, j = 0; i < l; i += 4, j += 3 ) {
+
+					tmp = ( revLookup[ b64.charCodeAt( i ) ] << 18 ) | ( revLookup[ b64.charCodeAt( i + 1 ) ] << 12 ) | ( revLookup[ b64.charCodeAt( i + 2 ) ] << 6 ) | revLookup[ b64.charCodeAt( i + 3 ) ];
+					arr[ L ++ ] = ( tmp & 0xFF0000 ) >> 16;
+					arr[ L ++ ] = ( tmp & 0xFF00 ) >> 8;
+					arr[ L ++ ] = tmp & 0xFF;
+
+				}
+
+				if ( placeHolders === 2 ) {
+
+					tmp = ( revLookup[ b64.charCodeAt( i ) ] << 2 ) | ( revLookup[ b64.charCodeAt( i + 1 ) ] >> 4 );
+					arr[ L ++ ] = tmp & 0xFF;
+
+				} else if ( placeHolders === 1 ) {
+
+					tmp = ( revLookup[ b64.charCodeAt( i ) ] << 10 ) | ( revLookup[ b64.charCodeAt( i + 1 ) ] << 4 ) | ( revLookup[ b64.charCodeAt( i + 2 ) ] >> 2 );
+					arr[ L ++ ] = ( tmp >> 8 ) & 0xFF;
+					arr[ L ++ ] = tmp & 0xFF;
+
+				}
+
+				return arr;
+
+			}
+
+			function parseDataArray( ele, compressed ) {
+
+				// Check the format
+
+				if ( ele.attributes.format == 'binary' ) {
+
+					if ( compressed ) {
+
+						// Split the blob_header and compressed Data
+						if ( ele[ '#text' ].indexOf( '==' ) != - 1 ) {
+
+							var data = ele[ '#text' ].split( '==' );
+
+							// console.log( data );
+
+							if ( data.length == 2 ) {
+
+								var blob = data.shift();
+								var content = data.shift();
+
+								if ( content === '' ) {
+
+									content = blob + '==';
+
+								}
+
+							} else if ( data.length > 2 ) {
+
+								var blob = data.shift();
+								var content = data.shift();
+								content = content + '==';
+
+							} else if ( data.length < 2 ) {
+
+								var content = data.shift();
+								content = content + '==';
+
+							}
+
+							// Convert to bytearray
+							var arr = Base64toByteArray( content );
+
+							// decompress
+							var inflate = new Zlib.Inflate( arr, { resize: true, verify: true } );
+							var content = inflate.decompress();
+
+						} else {
+
+							var content = Base64toByteArray( ele[ '#text' ] );
+
+						}
+
+					} else {
+
+						var content = Base64toByteArray( ele[ '#text' ] );
+
+					}
+
+					var content = content.buffer;
+
+				} else {
+
+					if ( ele[ '#text' ] ) {
+
+						var content = ele[ '#text' ].replace( /\n/g, ' ' ).split( ' ' ).filter( function ( el, idx, arr ) {
+
+							if ( el !== '' ) return el;
+
+						} );
+
+					} else {
+
+						var content = new Int32Array( 0 ).buffer;
+
+					}
+
+				}
+
+				delete ele[ '#text' ];
+
+				// Get the content and optimize it
+
+				if ( ele.attributes.type == 'Float32' ) {
+
+					var txt = new Float32Array( content );
+
+					if ( ele.attributes.format == 'binary' ) {
+
+						if ( ! compressed ) {
+
+							txt = txt.filter( function( el, idx, arr ) {
+
+								if ( idx !== 0 ) return true;
+
+							} );
+
+						}
+
+					}
+
+				} else if ( ele.attributes.type === 'Int64' ) {
+
+					var txt = new Int32Array( content );
+
+					if ( ele.attributes.format == 'binary' ) {
+
+						if ( ! compressed ) {
+
+							txt = txt.filter( function ( el, idx, arr ) {
+
+								if ( idx !== 0 ) return true;
+
+							} );
+
+						}
+
+						txt = txt.filter( function ( el, idx, arr ) {
+
+							if ( idx % 2 !== 1 ) return true;
+
+						} );
+
+					}
+
+				}
+
+				// console.log( txt );
 
+				return txt;
 
-		if ( meta[ 2 ].includes( 'ASCII' ) ) {
+			}
+
+			// Main part
+			// Get Dom
+			var dom = null;
+
+			if ( window.DOMParser ) {
+
+				try {
+
+					dom = ( new DOMParser() ).parseFromString( stringFile, 'text/xml' );
+
+				} catch ( e ) {
+
+					dom = null;
+
+				}
+
+			} else if ( window.ActiveXObject ) {
+
+				try {
+
+					dom = new ActiveXObject( 'Microsoft.XMLDOM' );
+					dom.async = false;
+
+					if ( ! dom.loadXML( xml ) ) {
+
+						throw new Error( dom.parseError.reason + dom.parseError.srcText );
+
+					}
+
+				} catch ( e ) {
+
+					dom = null;
+
+				}
+
+			} else {
+
+				throw new Error( 'Cannot parse xml string!' );
+
+			}
+
+			// Get the doc
+			var doc = dom.documentElement;
+			// Convert to json
+			var json = xmlToJson( doc );
+			var points = [];
+			var normals = [];
+			var indices = [];
+
+			if ( json.PolyData ) {
+
+				var piece = json.PolyData.Piece;
+				var compressed = json.attributes.hasOwnProperty( 'compressor' );
+
+				// Can be optimized
+				// Loop through the sections
+				var sections = [ 'PointData', 'Points', 'Strips', 'Polys' ];// +['CellData', 'Verts', 'Lines'];
+				var sectionIndex = 0, numberOfSections = sections.length;
+
+				while ( sectionIndex < numberOfSections ) {
+
+					var section = piece[ sections[ sectionIndex ] ];
+
+					// If it has a DataArray in it
+
+					if ( section.DataArray ) {
+
+						// Depending on the number of DataArrays
+
+						if ( Object.prototype.toString.call( section.DataArray ) === '[object Array]' ) {
+
+							var arr = section.DataArray;
+
+						} else {
+
+							var arr = [ section.DataArray ];
+
+						}
+
+						var dataArrayIndex = 0, numberOfDataArrays = arr.length;
+
+						while ( dataArrayIndex < numberOfDataArrays ) {
+
+							// Parse the DataArray
+							arr[ dataArrayIndex ].text = parseDataArray( arr[ dataArrayIndex ], compressed );
+							dataArrayIndex ++;
+
+						}
+
+						switch ( sections[ sectionIndex ] ) {
+
+							// if iti is point data
+							case 'PointData':
+
+								var numberOfPoints = parseInt( piece.attributes.NumberOfPoints );
+								var normalsName = section.attributes.Normals;
+
+								if ( numberOfPoints > 0 ) {
+
+									for ( var i = 0, len = arr.length; i < len; i ++ ) {
+
+										if ( normalsName == arr[ i ].attributes.Name ) {
+
+											var components = arr[ i ].attributes.NumberOfComponents;
+											normals = new Float32Array( numberOfPoints * components );
+											normals.set( arr[ i ].text, 0 );
+
+										}
+
+									}
+
+								}
+
+								// console.log('Normals', normals);
+
+								break;
+
+							// if it is points
+							case 'Points':
+
+								var numberOfPoints = parseInt( piece.attributes.NumberOfPoints );
+
+								if ( numberOfPoints > 0 ) {
+
+									var components = section.DataArray.attributes.NumberOfComponents;
+									points = new Float32Array( numberOfPoints * components );
+									points.set( section.DataArray.text, 0 );
+
+								}
+
+								// console.log('Points', points);
+
+								break;
+
+							// if it is strips
+							case 'Strips':
+
+								var numberOfStrips = parseInt( piece.attributes.NumberOfStrips );
+
+								if ( numberOfStrips > 0 ) {
+
+									var connectivity = new Int32Array( section.DataArray[ 0 ].text.length );
+									var offset = new Int32Array( section.DataArray[ 1 ].text.length );
+									connectivity.set( section.DataArray[ 0 ].text, 0 );
+									offset.set( section.DataArray[ 1 ].text, 0 );
+
+									var size = numberOfStrips + connectivity.length;
+									indices = new Uint32Array( 3 * size - 9 * numberOfStrips );
+
+									var indicesIndex = 0;
+
+									for ( var i = 0,len = numberOfStrips; i < len; i ++ ) {
+
+										var strip = [];
+
+										for ( var s = 0, len1 = offset[ i ], len0 = 0; s < len1 - len0; s ++ ) {
+
+											strip.push ( connectivity[ s ] );
+
+											if ( i > 0 ) len0 = offset[ i - 1 ];
+
+										}
+
+										for ( var j = 0, len1 = offset[ i ], len0 = 0; j < len1 - len0 - 2; j ++ ) {
+
+											if ( j % 2 ) {
+
+												indices[ indicesIndex ++ ] = strip[ j ];
+												indices[ indicesIndex ++ ] = strip[ j + 2 ];
+												indices[ indicesIndex ++ ] = strip[ j + 1 ];
+
+											} else {
+
+												indices[ indicesIndex ++ ] = strip[ j ];
+												indices[ indicesIndex ++ ] = strip[ j + 1 ];
+												indices[ indicesIndex ++ ] = strip[ j + 2 ];
+
+											}
+
+											if ( i > 0 ) len0 = offset[ i - 1 ];
+
+										}
+
+									}
+
+								}
+
+								//console.log('Strips', indices);
+
+								break;
+
+							// if it is polys
+							case 'Polys':
+
+								var numberOfPolys = parseInt( piece.attributes.NumberOfPolys );
+
+								if ( numberOfPolys > 0 ) {
+
+									var connectivity = new Int32Array( section.DataArray[ 0 ].text.length );
+									var offset = new Int32Array( section.DataArray[ 1 ].text.length );
+									connectivity.set( section.DataArray[ 0 ].text, 0 );
+									offset.set( section.DataArray[ 1 ].text, 0 );
+
+									var size = numberOfPolys + connectivity.length;
+									indices = new Uint32Array( 3 * size - 9 * numberOfPolys );
+									var indicesIndex = 0, connectivityIndex = 0;
+									var i = 0,len = numberOfPolys, len0 = 0;
+
+									while ( i < len ) {
+
+										var poly = [];
+										var s = 0, len1 = offset[ i ];
+
+										while ( s < len1 - len0 ) {
+
+											poly.push( connectivity[ connectivityIndex ++ ] );
+											s ++;
+
+										}
+
+										var j = 1;
+
+										while ( j < len1 - len0 - 1 ) {
+
+											indices[ indicesIndex ++ ] = poly[ 0 ];
+											indices[ indicesIndex ++ ] = poly[ j ];
+											indices[ indicesIndex ++ ] = poly[ j + 1 ];
+											j ++;
+
+										}
+
+										i ++;
+										len0 = offset[ i - 1 ];
+
+									}
+
+								}
+								//console.log('Polys', indices);
+								break;
+
+							default:
+								break;
+
+						}
+
+					}
+
+					sectionIndex ++;
+
+				}
+
+				var geometry = new THREE.BufferGeometry();
+				geometry.setIndex( new THREE.BufferAttribute( indices, 1 ) );
+				geometry.addAttribute( 'position', new THREE.BufferAttribute( points, 3 ) );
+
+				if ( normals.length == points.length ) {
+
+					geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+
+				}
+
+				// console.log( json );
+
+				return geometry;
+
+			} else {
+
+				// TODO for vtu,vti,and other xml formats
+
+			}
+
+		}
+
+		function getStringFile( data ) {
 
 			var stringFile = '';
 			var charArray = new Uint8Array( data );
-			for ( var i = 0; i < charArray.length; i ++ ) {
+			var i = 0;
+			var len = charArray.length;
+
+			while ( len -- ) {
 
-				stringFile += String.fromCharCode( charArray[ i ] );
+				stringFile += String.fromCharCode( charArray[ i ++ ] );
 
 			}
 
-			return parseASCII( stringFile );
+			return stringFile;
+
+		}
+
+		// get the 5 first lines of the files to check if there is the key word binary
+		var meta = String.fromCharCode.apply( null, new Uint8Array( data, 0, 250 ) ).split( '\n' );
+
+		if ( meta[ 0 ].indexOf( 'xml' ) !== - 1 ) {
+
+			return parseXML( getStringFile( data ) );
+
+		} else if ( meta[ 2 ].includes( 'ASCII' ) ) {
+
+			return parseASCII( getStringFile( data ) );
 
 		} else {
 

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

@@ -1,6 +1,16 @@
 /**
  * @author Prashant Sharma / spidersharma03
  * @author Ben Houston / bhouston, https://clara.io
+ *
+ * This class takes the cube lods(corresponding to different roughness values), and creates a single cubeUV
+ * Texture. The format for a given roughness set of faces is simply::
+ * +X+Y+Z
+ * -X-Y-Z
+ * For every roughness a mip map chain is also saved, which is essential to remove the texture artifacts due to
+ * minification.
+ * Right now for every face a PlaneMesh is drawn, which leads to a lot of geometry draw calls, but can be replaced
+ * later by drawing a single buffer and by sending the appropriate faceIndex via vertex attributes.
+ * The arrangement of the faces is fixed, as assuming this arrangement, the sampling function has been written.
  */
 
 

+ 25 - 20
examples/js/pmrem/PMREMGenerator.js

@@ -1,29 +1,20 @@
 /**
  * @author Prashant Sharma / spidersharma03
  * @author Ben Houston / bhouston, https://clara.io
+ *
+ * To avoid cube map seams, I create an extra pixel around each face. This way when the cube map is
+ * sampled by an application later(with a little care by sampling the centre of the texel), the extra 1 border
+ *  of pixels makes sure that there is no seams artifacts present. This works perfectly for cubeUV format as
+ *  well where the 6 faces can be arranged in any manner whatsoever.
+ * Code in the beginning of fragment shader's main function does this job for a given resolution.
+ *  Run Scene_PMREM_Test.html in the examples directory to see the sampling from the cube lods generated
+ *  by this class.
  */
 
- THREE.PMREMGenerator = function( sourceTexture ) {
-	if ( sourceTexture instanceof THREE.CubeTexture ) {
+THREE.PMREMGenerator = function( sourceTexture ) {
 
-		if ( sourceTexture.images[ 0 ] === undefined )
-		  console.error( "sourceTexture Not Initialized" );
-      if(sourceTexture.images[ 0 ] instanceof THREE.DataTexture) {
-          this.resolution = sourceTexture.images[ 0 ].image.width;
-      }
-      else {
-          this.resolution = sourceTexture.images[ 0 ].width;
-      }
-
-	}
-	else if ( sourceTexture instanceof THREE.WebGLRenderTargetCube ) {
-		if ( sourceTexture === undefined ) console.error( "Render Target Not Initialized" );
-		this.resolution = sourceTexture.width;
-	}
-	else {
-		console.error( "Wrong Input to PMREMGenerator" );
-	}
 	this.sourceTexture = sourceTexture;
+  this.resolution = 256; // NODE: 256 is currently hard coded in the glsl code for performance reasons
 
   var monotonicEncoding = ( sourceTexture.encoding === THREE.LinearEncoding ) ||
     ( sourceTexture.encoding === THREE.GammaEncoding ) || ( sourceTexture.encoding === THREE.sRGBEncoding );
@@ -37,6 +28,7 @@
 	var size = this.resolution;
   var params = { format: this.sourceTexture.format, magFilter: this.sourceTexture.magFilter, minFilter: this.sourceTexture.minFilter, type: this.sourceTexture.type };
 
+  // how many LODs fit in the given CubeUV Texture.
 	this.numLods = Math.log2( size ) - 2;
   for ( var i = 0; i < this.numLods; i ++ ) {
 		var renderTarget = new THREE.WebGLRenderTargetCube( size, size, params );
@@ -66,6 +58,19 @@ THREE.PMREMGenerator.prototype = {
 
 	constructor : THREE.PMREMGenerator,
 
+  /*
+   * Prashant Sharma / spidersharma03: More thought and work is needed here.
+   * Right now it's a kind of a hack to use the previously convolved map to convolve the current one.
+   * I tried to use the original map to convolve all the lods, but for many textures(specially the high frequency)
+   * even a high number of samples(1024) dosen't lead to satisfactory results.
+   * By using the previous convolved maps, a lower number of samples are generally sufficient(right now 32, which
+   * gives okay results unless we see the reflection very carefully, or zoom in too much), however the math
+   * goes wrong as the distribution function tries to sample a larger area than what it should be. So I simply scaled
+   * the roughness by 0.9(totally empirical) to try to visually match the original result.
+   * The condition "if(i <5)" is also an attemt to make the result match the original result.
+   * This method requires the most amount of thinking I guess. Here is a paper which we could try to implement in future::
+   * http://http.developer.nvidia.com/GPUGems3/gpugems3_ch20.html
+   */
 	update: function( renderer ) {
 
 		this.shader.uniforms[ "envMap" ].value = this.sourceTexture;
@@ -78,7 +83,7 @@ THREE.PMREMGenerator.prototype = {
 		for ( var i = 0; i < this.numLods; i ++ ) {
 
 			var r = i / ( this.numLods - 1 );
-			this.shader.uniforms[ "roughness" ].value = r * 0.9;
+			this.shader.uniforms[ "roughness" ].value = r * 0.9; // see comment above, pragmatic choice
 			var size = this.cubeLods[ i ].width;
 			this.shader.uniforms[ "mapSize" ].value = size;
 			this.renderToCubeMapTarget( renderer, this.cubeLods[ i ] );

+ 1 - 1
examples/js/postprocessing/EffectComposer.js

@@ -112,7 +112,7 @@ THREE.EffectComposer.prototype = {
 			var size = this.renderer.getSize();
 
 			renderTarget = this.renderTarget1.clone();
-			renderTarget.setSize( width, height );
+			renderTarget.setSize( size.width, size.height );
 
 		}
 

BIN
examples/models/nrrd/I.nrrd


+ 80 - 0
examples/models/vtk/cube_ascii.vtp

@@ -0,0 +1,80 @@
+<?xml version="1.0"?>
+<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
+  <PolyData>
+    <Piece NumberOfPoints="24" NumberOfVerts="0" NumberOfLines="0" NumberOfStrips="0" NumberOfPolys="6">
+      <PointData Normals="Normals" TCoords="TCoords">
+        <DataArray type="Float32" Name="Normals" NumberOfComponents="3" format="ascii" RangeMin="1" RangeMax="1">
+          -1 0 0 -1 0 0
+          -1 0 0 -1 0 0
+          1 0 0 1 0 0
+          1 0 0 1 0 0
+          0 -1 0 0 -1 0
+          0 -1 0 0 -1 0
+          0 1 0 0 1 0
+          0 1 0 0 1 0
+          0 0 -1 0 0 -1
+          0 0 -1 0 0 -1
+          0 0 1 0 0 1
+          0 0 1 0 0 1
+        </DataArray>
+        <DataArray type="Float32" Name="TCoords" NumberOfComponents="2" format="ascii" RangeMin="0.70710678119" RangeMax="2.1213203436">
+          -0.5 -0.5 1.5 -0.5 -0.5 1.5
+          1.5 1.5 0.5 -0.5 -1.5 -0.5
+          0.5 1.5 -1.5 1.5 0.5 0.5
+          0.5 -1.5 -1.5 0.5 -1.5 -1.5
+          -0.5 0.5 -0.5 -1.5 1.5 0.5
+          1.5 -1.5 0.5 -0.5 -1.5 -0.5
+          0.5 1.5 -1.5 1.5 -0.5 -0.5
+          1.5 -0.5 -0.5 1.5 1.5 1.5
+        </DataArray>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="ascii" RangeMin="1.7320508076" RangeMax="1.7320508076">
+          -1 -1 -1 -1 -1 1
+          -1 1 -1 -1 1 1
+          1 -1 -1 1 -1 1
+          1 1 -1 1 1 1
+          -1 -1 -1 -1 -1 1
+          1 -1 -1 1 -1 1
+          -1 1 -1 -1 1 1
+          1 1 -1 1 1 1
+          -1 -1 -1 1 -1 -1
+          -1 1 -1 1 1 -1
+          -1 -1 1 1 -1 1
+          -1 1 1 1 1 1
+        </DataArray>
+      </Points>
+      <Verts>
+        <DataArray type="Int64" Name="connectivity" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+      </Verts>
+      <Lines>
+        <DataArray type="Int64" Name="connectivity" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+      </Lines>
+      <Strips>
+        <DataArray type="Int64" Name="connectivity" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii" RangeMin="1e+299" RangeMax="-1e+299">
+        </DataArray>
+      </Strips>
+      <Polys>
+        <DataArray type="Int64" Name="connectivity" format="ascii" RangeMin="0" RangeMax="23">
+          0 1 3 2 4 6
+          7 5 8 10 11 9
+          12 13 15 14 16 18
+          19 17 20 21 23 22
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="ascii" RangeMin="4" RangeMax="24">
+          4 8 12 16 20 24
+        </DataArray>
+      </Polys>
+    </Piece>
+  </PolyData>
+</VTKFile>

+ 54 - 0
examples/models/vtk/cube_binary.vtp

@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian" header_type="UInt32" compressor="vtkZLibDataCompressor">
+  <PolyData>
+    <Piece NumberOfPoints="24" NumberOfVerts="0" NumberOfLines="0" NumberOfStrips="0" NumberOfPolys="6">
+      <PointData Normals="Normals" TCoords="TCoords">
+        <DataArray type="Float32" Name="Normals" NumberOfComponents="3" format="binary" RangeMin="1" RangeMax="1">
+          AQAAAACAAAAgAQAAGQAAAA==eJxjYGjYzwAHRLHtSWMTbe6gtAMA+HsX6Q==
+        </DataArray>
+        <DataArray type="Float32" Name="TCoords" NumberOfComponents="2" format="binary" RangeMin="0.70710678119" RangeMax="2.1213203436">
+          AQAAAACAAADAAAAANAAAAA==eJxjYGDYzwDGB+wZUNgwzAAVPwCVY4DJ7UeSh+IDMHXI7P2oZsD0wMwgaD5e9wEAQ9Ep0Q==
+        </DataArray>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="binary" RangeMin="1.7320508076" RangeMax="1.7320508076">
+          AQAAAACAAAAgAQAALAAAAA==eJxjYGjYz4CJ7dFoGNseixg2OWxq0c3HZQ4+ewmZj4uPSy02e1EwADNPR7k=
+        </DataArray>
+      </Points>
+      <Verts>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+      </Verts>
+      <Lines>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+      </Lines>
+      <Strips>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAACAAAAAAAAA
+        </DataArray>
+      </Strips>
+      <Polys>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="0" RangeMax="23">
+          AQAAAACAAADAAAAANgAAAA==eJwtxUkCQCAAAMCSfQuF///UwcxlQvhFJzdu3Xtw59GzF09evTl79+HLxaerb79+/AFJAAEV
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="4" RangeMax="24">
+          AQAAAACAAAAwAAAAGAAAAA==eJxjYYAADijNA6UFoLQIlJaA0gAHMABV
+        </DataArray>
+      </Polys>
+    </Piece>
+  </PolyData>
+</VTKFile>

+ 54 - 0
examples/models/vtk/cube_no_compression.vtp

@@ -0,0 +1,54 @@
+<?xml version="1.0"?>
+<VTKFile type="PolyData" version="0.1" byte_order="LittleEndian" header_type="UInt32">
+  <PolyData>
+    <Piece NumberOfPoints="24" NumberOfVerts="0" NumberOfLines="0" NumberOfStrips="0" NumberOfPolys="6">
+      <PointData Normals="Normals" TCoords="TCoords">
+        <DataArray type="Float32" Name="Normals" NumberOfComponents="3" format="binary" RangeMin="1" RangeMax="1">
+          IAEAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgL8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIC/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAvwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPwAAAAAAAAAAAACAPw==
+        </DataArray>
+        <DataArray type="Float32" Name="TCoords" NumberOfComponents="2" format="binary" RangeMin="0.70710678119" RangeMax="2.1213203436">
+          wAAAAAAAAL8AAAC/AADAPwAAAL8AAAC/AADAPwAAwD8AAMA/AAAAPwAAAL8AAMC/AAAAvwAAAD8AAMA/AADAvwAAwD8AAAA/AAAAPwAAAD8AAMC/AADAvwAAAD8AAMC/AADAvwAAAL8AAAA/AAAAvwAAwL8AAMA/AAAAPwAAwD8AAMC/AAAAPwAAAL8AAMC/AAAAvwAAAD8AAMA/AADAvwAAwD8AAAC/AAAAvwAAwD8AAAC/AAAAvwAAwD8AAMA/AADAPw==
+        </DataArray>
+      </PointData>
+      <CellData>
+      </CellData>
+      <Points>
+        <DataArray type="Float32" Name="Points" NumberOfComponents="3" format="binary" RangeMin="1.7320508076" RangeMax="1.7320508076">
+          IAEAAAAAgL8AAIC/AACAvwAAgL8AAIC/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAPwAAgL8AAIC/AACAvwAAgL8AAIC/AACAPwAAgD8AAIC/AACAvwAAgD8AAIC/AACAPwAAgL8AAIA/AACAvwAAgL8AAIA/AACAPwAAgD8AAIA/AACAvwAAgD8AAIA/AACAPwAAgL8AAIC/AACAvwAAgD8AAIC/AACAvwAAgL8AAIA/AACAvwAAgD8AAIA/AACAvwAAgL8AAIC/AACAPwAAgD8AAIC/AACAPwAAgL8AAIA/AACAPwAAgD8AAIA/AACAPw==
+        </DataArray>
+      </Points>
+      <Verts>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+      </Verts>
+      <Lines>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+      </Lines>
+      <Strips>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="1e+299" RangeMax="-1e+299">
+          AAAAAA==
+        </DataArray>
+      </Strips>
+      <Polys>
+        <DataArray type="Int64" Name="connectivity" format="binary" RangeMin="0" RangeMax="23">
+          wAAAAAAAAAAAAAAAAQAAAAAAAAADAAAAAAAAAAIAAAAAAAAABAAAAAAAAAAGAAAAAAAAAAcAAAAAAAAABQAAAAAAAAAIAAAAAAAAAAoAAAAAAAAACwAAAAAAAAAJAAAAAAAAAAwAAAAAAAAADQAAAAAAAAAPAAAAAAAAAA4AAAAAAAAAEAAAAAAAAAASAAAAAAAAABMAAAAAAAAAEQAAAAAAAAAUAAAAAAAAABUAAAAAAAAAFwAAAAAAAAAWAAAAAAAAAA==
+        </DataArray>
+        <DataArray type="Int64" Name="offsets" format="binary" RangeMin="4" RangeMax="24">
+          MAAAAAQAAAAAAAAACAAAAAAAAAAMAAAAAAAAABAAAAAAAAAAFAAAAAAAAAAYAAAAAAAAAA==
+        </DataArray>
+      </Polys>
+    </Piece>
+  </PolyData>
+</VTKFile>

BIN
examples/models/vtk/liver.vtk


BIN
examples/textures/hardwood2_bump.jpg


BIN
examples/textures/hardwood2_diffuse.jpg


BIN
examples/textures/hardwood2_roughness.jpg


+ 14 - 14
examples/webgl_animation_cloth.html

@@ -91,7 +91,7 @@
 			/* testing cloth simulation */
 
 			var pinsFormation = [];
-			var pins = [6];
+			var pins = [ 6 ];
 
 			pinsFormation.push( pins );
 
@@ -112,7 +112,7 @@
 
 			function togglePins() {
 
-				pins = pinsFormation[ ~~( Math.random() * pinsFormation.length ) ];
+				pins = pinsFormation[ ~~ ( Math.random() * pinsFormation.length ) ];
 
 			}
 
@@ -165,10 +165,10 @@
 
 				var d = 300;
 
-				light.shadow.camera.left = -d;
+				light.shadow.camera.left = - d;
 				light.shadow.camera.right = d;
 				light.shadow.camera.top = d;
-				light.shadow.camera.bottom = -d;
+				light.shadow.camera.bottom = - d;
 
 				light.shadow.camera.far = 1000;
 
@@ -230,7 +230,7 @@
 				var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );
 
 				var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 20000, 20000 ), groundMaterial );
-				mesh.position.y = -250;
+				mesh.position.y = - 250;
 				mesh.rotation.x = - Math.PI / 2;
 				mesh.receiveShadow = true;
 				scene.add( mesh );
@@ -241,21 +241,21 @@
 				var poleMat = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, shininess: 100 } );
 
 				var mesh = new THREE.Mesh( poleGeo, poleMat );
-				mesh.position.x = -125;
-				mesh.position.y = -62;
+				mesh.position.x = - 125;
+				mesh.position.y = - 62;
 				mesh.receiveShadow = true;
 				mesh.castShadow = true;
 				scene.add( mesh );
 
 				var mesh = new THREE.Mesh( poleGeo, poleMat );
 				mesh.position.x = 125;
-				mesh.position.y = -62;
+				mesh.position.y = - 62;
 				mesh.receiveShadow = true;
 				mesh.castShadow = true;
 				scene.add( mesh );
 
 				var mesh = new THREE.Mesh( new THREE.BoxGeometry( 255, 5, 5 ), poleMat );
-				mesh.position.y = -250 + 750/2;
+				mesh.position.y = - 250 + ( 750 / 2 );
 				mesh.position.x = 0;
 				mesh.receiveShadow = true;
 				mesh.castShadow = true;
@@ -263,15 +263,15 @@
 
 				var gg = new THREE.BoxGeometry( 10, 10, 10 );
 				var mesh = new THREE.Mesh( gg, poleMat );
-				mesh.position.y = -250;
+				mesh.position.y = - 250;
 				mesh.position.x = 125;
 				mesh.receiveShadow = true;
 				mesh.castShadow = true;
 				scene.add( mesh );
 
 				var mesh = new THREE.Mesh( gg, poleMat );
-				mesh.position.y = -250;
-				mesh.position.x = -125;
+				mesh.position.y = - 250;
+				mesh.position.x = - 125;
 				mesh.receiveShadow = true;
 				mesh.castShadow = true;
 				scene.add( mesh );
@@ -301,7 +301,7 @@
 
 				window.addEventListener( 'resize', onWindowResize, false );
 
-				sphere.visible = !true
+				sphere.visible = ! true
 
 			}
 
@@ -327,7 +327,7 @@
 				windStrength = Math.cos( time / 7000 ) * 20 + 40;
 				windForce.set( Math.sin( time / 2000 ), Math.cos( time / 3000 ), Math.sin( time / 1000 ) ).normalize().multiplyScalar( windStrength );
 
-				simulate(time);
+				simulate( time );
 				render();
 				stats.update();
 

+ 3 - 1
examples/webgl_animation_skinning_blending.html

@@ -235,6 +235,8 @@
 
 				requestAnimationFrame( animate, renderer.domElement );
 
+				stats.begin();
+
 				// step forward in time based on whether we're stepping and scale
 
 				var scale = gui.getTimeScale();
@@ -248,7 +250,7 @@
 				gui.update( blendMesh.mixer.time );
 
 				renderer.render( scene, camera );
-				stats.update();
+				stats.end();
 
 				// if we are stepping, consume time
 				// ( will equal step size next time a single step is desired )

+ 2 - 1
examples/webgl_animation_skinning_morph.html

@@ -635,8 +635,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 				if ( showMemInfo ) {
 

+ 1 - 2
examples/webgl_effects_stereo.html

@@ -88,7 +88,7 @@
 
 				var textureCube = new THREE.CubeTextureLoader().load( urls );
 				textureCube.mapping = THREE.CubeRefractionMapping;
-				
+
 				var material = new THREE.MeshBasicMaterial( { color: 0xffffff, envMap: textureCube, refractionRatio: 0.95 } );
 
 				for ( var i = 0; i < 500; i ++ ) {
@@ -128,7 +128,6 @@
 				container.appendChild( renderer.domElement );
 
 				effect = new THREE.StereoEffect( renderer );
-				effect.eyeSeparation = 10;
 				effect.setSize( window.innerWidth, window.innerHeight );
 
 				//

+ 3 - 5
examples/webgl_geometries2.html

@@ -63,19 +63,17 @@
 					new THREE.MeshBasicMaterial( { color: 0xffffff, wireframe: true, transparent: true, opacity: 0.1, side: THREE.DoubleSide } )
 				];
 
-
-				var heightScale = 1;
 				var p = 2;
 				var q = 3;
-				var radius = 150, tube = 10, segmentsR = 50, segmentsT = 20;
+				var radius = 150, tube = 10, segmentsT = 50, segmentsR = 20;
 
 				var GrannyKnot =  new THREE.Curves.GrannyKnot();
 
-				var torus2 = new THREE.ParametricGeometries.TorusKnotGeometry( radius, tube, segmentsR, segmentsT, p , q, heightScale );
+				var torus2 = new THREE.ParametricGeometries.TorusKnotGeometry( radius, tube, segmentsT, segmentsR, p , q );
 				var sphere2 = new THREE.ParametricGeometries.SphereGeometry( 75, 20, 10 );
 				var tube2 = new THREE.ParametricGeometries.TubeGeometry( GrannyKnot, 150, 2, 8, true, false );
 
-				// var torus = new THREE.TorusKnotGeometry( radius, tube, segmentsR, segmentsT, p , q, heightScale );
+				// var torus = new THREE.TorusKnotGeometry( radius, tube, segmentsR, segmentsT, p , q );
 				// var sphere = new THREE.SphereGeometry( 75, 20, 10 );
 				// var tube = new THREE.TubeGeometry( GrannyKnot, 150, 2, 8, true, false );
 

+ 315 - 0
examples/webgl_lights_physical.html

@@ -0,0 +1,315 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - lights - physical lights</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> - Physically accurate lighting example using a incandescent bulb - by <a href="http://clara.io" target="_blank">Ben Houston</a><br />
+			Using real world scale: Brick cube is 1 meter in size.  Light is 2 meters from floor.  Globe is 25 cm in diameter.<br/>
+			Using Reinhard inline tonemapping with real-world light falloff (decay = 2).
+		</div>
+
+		<script src="../build/three.min.js"></script>
+		<script src="../examples/js/libs/stats.min.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>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var camera, scene, renderer,
+			bulbLight, bulbMat, ambientLight,
+			object, loader, stats;
+			var ballMat, cubeMat, floorMat;
+
+
+			// ref for lumens: http://www.power-sure.com/lumens.htm
+			var bulbLuminousPowers = {
+				"110000 lm (1000W)": 110000,
+				"3500 lm (300W)": 3500,
+				"1700 lm (100W)": 1700,
+				"800 lm (60W)": 800,
+				"400 lm (40W)": 400,
+				"180 lm (25W)": 180,
+				"20 lm (4W)": 20,
+				"Off": 0
+			};
+
+			// ref for solar irradiances: https://en.wikipedia.org/wiki/Lux
+			var hemiLuminousIrradiances = {
+				"0.0001 lx (Moonless Night)": 0.0001,
+				"0.002 lx (Night Airglow)": 0.002,
+				"0.5 lx (Full Moon)": 0.5,
+				"3.4 lx (City Twilight)": 3.4,
+				"50 lx (Living Room)": 50,
+				"100 lx (Very Overcast)": 100,
+				"350 lx (Office Room)": 350,
+				"400 lx (Sunrise/Sunset)": 400,
+				"1000 lx (Overcast)": 1000,
+				"18000 lx (Daylight)": 18000,
+				"50000 lx (Direct Sun)": 50000,
+			};
+
+			var params = {
+				shadows: true,
+				exposure: 0.68,
+				bulbPower: Object.keys( bulbLuminousPowers )[2],
+				hemiIrradiance: Object.keys( hemiLuminousIrradiances )[0]
+			};
+
+
+			var clock = new THREE.Clock();
+
+			init();
+			animate();
+
+			function init() {
+
+				var container = document.getElementById( 'container' );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+
+				container.appendChild( stats.domElement );
+
+
+				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 0.1, 100 );
+				camera.position.x = -4;
+				camera.position.z = 4;
+				camera.position.y = 3;
+
+				scene = new THREE.Scene();
+
+				var bulbGeometry = new THREE.SphereGeometry( 0.02, 16, 8 );
+				bulbLight = new THREE.PointLight( 0xffee88, 1, 100, 2 );
+
+				bulbMat = new THREE.MeshStandardMaterial( {
+					emissive: 0xffffee,
+					emissiveIntensity: 1,
+					color: 0x000000
+				});
+				bulbLight.add( new THREE.Mesh( bulbGeometry, bulbMat ) );
+				bulbLight.position.set( 0, 2, 0 );
+				bulbLight.castShadow = true;
+				scene.add( bulbLight );
+
+				hemiLight = new THREE.HemisphereLight( 0xddeeff, 0x0f0e0d, 0.02 );
+				scene.add( hemiLight );
+
+				floorMat = new THREE.MeshStandardMaterial( {
+					roughness: 0.8,
+					color: 0xffffff,
+					metalness: 0.2,
+					bumpScale: 0.0005,
+				});
+				var textureLoader = new THREE.TextureLoader();
+				textureLoader.load( "../examples/textures/hardwood2_diffuse.jpg", function( map ) {
+					map.wrapS = THREE.RepeatWrapping;
+					map.wrapT = THREE.RepeatWrapping;
+					map.anisotropy = 4;
+					map.repeat.set( 10, 24 );
+					floorMat.map = map;
+					floorMat.needsUpdate = true;
+				} );
+				textureLoader.load( "../examples/textures/hardwood2_bump.jpg", function( map ) {
+					map.wrapS = THREE.RepeatWrapping;
+					map.wrapT = THREE.RepeatWrapping;
+					map.anisotropy = 4;
+					map.repeat.set( 10, 24 );
+					floorMat.bumpMap = map;
+					floorMat.needsUpdate = true;
+				} );
+				textureLoader.load( "../examples/textures/hardwood2_roughness.jpg", function( map ) {
+					map.wrapS = THREE.RepeatWrapping;
+					map.wrapT = THREE.RepeatWrapping;
+					map.anisotropy = 4;
+					map.repeat.set( 10, 24 );
+					floorMat.roughnessMap = map;
+					floorMat.needsUpdate = true;
+				} );
+
+				cubeMat = new THREE.MeshStandardMaterial( {
+					roughness: 0.7,
+					color: 0xffffff,
+					bumpScale: 0.002,
+					metalness: 0.2
+				});
+				textureLoader.load( "../examples/textures/brick_diffuse.jpg", function( map ) {
+					map.wrapS = THREE.RepeatWrapping;
+					map.wrapT = THREE.RepeatWrapping;
+					map.anisotropy = 4;
+					map.repeat.set( 1, 1 );
+					cubeMat.map = map;
+					cubeMat.needsUpdate = true;
+				} );
+				textureLoader.load( "../examples/textures/brick_bump.jpg", function( map ) {
+					map.wrapS = THREE.RepeatWrapping;
+					map.wrapT = THREE.RepeatWrapping;
+					map.anisotropy = 4;
+					map.repeat.set( 1, 1 );
+					cubeMat.bumpMap = map;
+					cubeMat.needsUpdate = true;
+				} );
+
+				ballMat = new THREE.MeshStandardMaterial( {
+					roughness: 0,
+					metalness: 0.0,
+					color: 0xffffff
+				});
+				textureLoader.load( "../examples/textures/planets/earth_atmos_2048.jpg", function( map ) {
+					map.wrapS = THREE.RepeatWrapping;
+					map.wrapT = THREE.RepeatWrapping;
+					map.anisotropy = 4;
+					map.repeat.set( 1, 1 );
+					ballMat.map = map;
+					ballMat.needsUpdate = true;
+				} );
+				textureLoader.load( "../examples/textures/planets/earth_specular_2048.jpg", function( map ) {
+					map.wrapS = THREE.RepeatWrapping;
+					map.wrapT = THREE.RepeatWrapping;
+					map.anisotropy = 4;
+					map.repeat.set( 1, 1 );
+					ballMat.roughnessMap = map;
+					ballMat.needsUpdate = true;
+				} );
+
+				var floorGeometry = new THREE.PlaneBufferGeometry( 20, 20 );
+				var floorMesh = new THREE.Mesh( floorGeometry, floorMat );
+				floorMesh.receiveShadow = true;
+				floorMesh.rotation.x = -Math.PI / 2.0;
+				scene.add( floorMesh );
+
+				var ballGeometry = new THREE.SphereGeometry( 0.1213, 32, 32 );
+				var ballMesh = new THREE.Mesh( ballGeometry, ballMat );
+				ballMesh.position.set( 1, 0.1213, 1 );
+				ballMesh.castShadow = true;
+				scene.add( ballMesh );
+
+				var boxGeometry = new THREE.BoxGeometry( 0.5, 0.5, 0.5 );
+				var boxMesh = new THREE.Mesh( boxGeometry, cubeMat );
+				boxMesh.position.set( -0.5, 0.25, -1 );
+				boxMesh.castShadow = true;
+				scene.add( boxMesh );
+
+				var boxMesh2 = new THREE.Mesh( boxGeometry, cubeMat );
+				boxMesh2.position.set( 0, 0.25, -5 );
+				boxMesh2.castShadow = true;
+				scene.add( boxMesh2 );
+
+				var boxMesh3 = new THREE.Mesh( boxGeometry, cubeMat );
+				boxMesh3.position.set( 7, 0.25, 0 );
+				boxMesh3.castShadow = true;
+				scene.add( boxMesh3 );
+
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.physicallyCorrectLights = true;
+				renderer.gammaInput = true;
+				renderer.gammaOutput = true;
+				renderer.shadowMap.enabled = true;
+				renderer.toneMapping = THREE.ReinhardToneMapping;
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				container.appendChild( renderer.domElement );
+
+
+				var controls = new THREE.OrbitControls( camera, renderer.domElement );
+				controls.target.set( 0, 0, 0 );
+				controls.update();
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+
+				var gui = new dat.GUI();
+
+				gui.add( params, 'hemiIrradiance', Object.keys( hemiLuminousIrradiances ) );
+				gui.add( params, 'bulbPower', Object.keys( bulbLuminousPowers ) );
+				gui.add( params, 'exposure', 0, 1 );
+				gui.add( params, 'shadows' );
+				gui.open();
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			//
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+
+			}
+
+			var previousShadowMap = false;
+
+			function render() {
+
+				renderer.toneMappingExposure = Math.pow( params.exposure, 5.0 ); // to allow for very bright scenes.
+				renderer.shadowMap.enabled = params.shadows;
+				bulbLight.castShadow = params.shadows;
+				if( params.shadows !== previousShadowMap ) {
+					ballMat.needsUpdate = true;
+					cubeMat.needsUpdate = true;
+					floorMat.needsUpdate = true;
+					previousShadowMap = params.shadows;
+				}
+				bulbLight.power = bulbLuminousPowers[ params.bulbPower ];
+				bulbMat.emissiveIntensity = bulbLight.intensity / Math.pow( 0.02, 2.0 ); // convert from intensity to irradiance at bulb surface
+
+				hemiLight.intensity = hemiLuminousIrradiances[ params.hemiIrradiance ];
+				var time = Date.now() * 0.0005;
+				var delta = clock.getDelta();
+
+				bulbLight.position.y = Math.cos( time ) * 0.75 + 1.25;
+
+				renderer.render( scene, camera );
+
+				stats.update();
+
+			}
+
+		</script>
+	</body>
+</html>

+ 22 - 45
examples/webgl_lights_pointlights2.html

@@ -82,39 +82,22 @@
 
 				// CONTROLS
 
-				var fly = false;
+				controls = new THREE.TrackballControls( camera );
 
-				if ( !fly ) {
+				controls.rotateSpeed = 1.0;
+				controls.zoomSpeed = 1.2;
+				controls.panSpeed = 0.8;
 
-					controls = new THREE.TrackballControls( camera );
-					controls.target.set( 0, 0, 0 );
+				controls.noZoom = false;
+				controls.noPan = false;
 
-					controls.rotateSpeed = 1.0;
-					controls.zoomSpeed = 1.2;
-					controls.panSpeed = 0.8;
-
-					controls.noZoom = false;
-					controls.noPan = false;
-
-					controls.staticMoving = false;
-					controls.dynamicDampingFactor = 0.15;
-
-					controls.keys = [ 65, 83, 68 ];
-
-				} else {
-
-					controls = new THREE.FirstPersonControls( camera );
-
-					controls.movementSpeed = 25;
-					controls.lookSpeed = 0.05;
-					controls.lookVertical = true;
-
-					controls.lon = -90;
-
-				}
+				controls.staticMoving = false;
+				controls.dynamicDampingFactor = 0.15;
 
+				controls.keys = [ 65, 83, 68 ];
 
 				// TEXTURES
+
 				var textureLoader = new THREE.TextureLoader();
 
 				var texture = textureLoader.load( "textures/disturb.jpg" );
@@ -122,20 +105,15 @@
 				texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
 				texture.format = THREE.RGBFormat;
 
-				var texture2 = textureLoader.load( "textures/planets/moon_1024.jpg" );
-				texture2.repeat.set( 2, 1 );
-				texture2.wrapS = texture2.wrapT = THREE.RepeatWrapping;
-				texture2.format = THREE.RGBFormat;
-
 				// MATERIALS
 
 				var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, map: texture } );
-				var objectMaterial = new THREE.MeshStandardMaterial( { color: 0x000000, map: texture2, roughness: 0.2, metalness: 1.0 } );
+				var objectMaterial = new THREE.MeshStandardMaterial( { color: 0xffffff, roughness: 0.5, metalness: 1.0 } );
 
 				// GROUND
 
 				var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 800, 400, 2, 2 ), groundMaterial );
-				mesh.position.y = -5;
+				mesh.position.y = - 5;
 				mesh.rotation.x = - Math.PI / 2;
 				scene.add( mesh );
 
@@ -164,41 +142,40 @@
 
 				// LIGHTS
 
-				scene.add( new THREE.AmbientLight( 0x111111 ) );
-
 				var intensity = 2.5;
 				var distance = 100;
+				var decay = 2.0;
+
 				var c1 = 0xff0040, c2 = 0x0040ff, c3 = 0x80ff80, c4 = 0xffaa00, c5 = 0x00ffaa, c6 = 0xff1100;
-				//var c1 = 0xffffff, c2 = 0xffffff, c3 = 0xffffff, c4 = 0xffffff, c5 = 0xffffff, c6 = 0xffffff;
 
 				var sphere = new THREE.SphereGeometry( 0.25, 16, 8 );
 
-				light1 = new THREE.PointLight( c1, intensity, distance );
+				light1 = new THREE.PointLight( c1, intensity, distance, decay );
 				light1.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: c1 } ) ) );
 				scene.add( light1 );
 
-				light2 = new THREE.PointLight( c2, intensity, distance );
+				light2 = new THREE.PointLight( c2, intensity, distance, decay );
 				light2.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: c2 } ) ) );
 				scene.add( light2 );
 
-				light3 = new THREE.PointLight( c3, intensity, distance );
+				light3 = new THREE.PointLight( c3, intensity, distance, decay );
 				light3.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: c3 } ) ) );
 				scene.add( light3 );
 
-				light4 = new THREE.PointLight( c4, intensity, distance );
+				light4 = new THREE.PointLight( c4, intensity, distance, decay );
 				light4.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: c4 } ) ) );
 				scene.add( light4 );
 
-				light5 = new THREE.PointLight( c5, intensity, distance );
+				light5 = new THREE.PointLight( c5, intensity, distance, decay );
 				light5.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: c5 } ) ) );
 				scene.add( light5 );
 
-				light6 = new THREE.PointLight( c6, intensity, distance );
+				light6 = new THREE.PointLight( c6, intensity, distance, decay );
 				light6.add( new THREE.Mesh( sphere, new THREE.MeshBasicMaterial( { color: c6 } ) ) );
 				scene.add( light6 );
 
-				var dlight = new THREE.DirectionalLight( 0xffffff, 0.1 );
-				dlight.position.set( 0.5, -1, 0 ).normalize();
+				var dlight = new THREE.DirectionalLight( 0xffffff, 0.05 );
+				dlight.position.set( 0.5, 1, 0 ).normalize();
 				scene.add( dlight );
 
 				// RENDERER

+ 4 - 4
examples/webgl_loader_msgpack.html

@@ -1,4 +1,4 @@
-<!doctype html>
+<!DOCTYPE html>
 <!--
 Requires msgpack-js.js
 
@@ -22,7 +22,7 @@ https://github.com/creationix/msgpack-js-browser
 				background: #1b1c1e;
 				background-image: linear-gradient(#7d8fa3, #1b1c1e);
 			}
-		
+
 			#info {
 				color: #fff;
 				position: absolute;
@@ -43,13 +43,13 @@ https://github.com/creationix/msgpack-js-browser
 	</head>
 	<body>
 		<div id='info'>
-			<p>Robo Pigeon, from <a href='http://www.tearsofsteel.org' target='_blank'>Tears of Steel</a>, is licensed under 
+			<p>Robo Pigeon, from <a href='http://www.tearsofsteel.org' target='_blank'>Tears of Steel</a>, is licensed under
 			<a href='http://creativecommons.org/licenses/by/3.0/' target='_blank'>Creative Commons Attribution 3.0</a>.
 			</p>
 		</div>
 		<div id='viewport'></div>
 		<script>
-			
+
 			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
 
 			requirejs.config( { baseUrl: 'js/libs' } );

+ 276 - 0
examples/webgl_loader_nrrd.html

@@ -0,0 +1,276 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <title>three.js webgl - loaders - vtk loader</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: #000;
+                color: #fff;
+                margin: 0px;
+                overflow: hidden;
+            }
+            #info {
+                color: #fff;
+                position: absolute;
+                top: 10px;
+                width: 100%;
+                text-align: center;
+                z-index: 5;
+                display:block;
+            }
+            .dg {
+                z-index: 10 !important;
+            }
+            #info a, .button { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
+            #inset  {
+                width: 150px;
+                height: 150px;
+                background-color: transparent; /* or transparent; will show through only if renderer alpha: true */
+                border: none; /* or none; */
+                margin: 0;
+                padding: 0px;
+                position: absolute;
+                left: 20px;
+                bottom: 20px;
+                z-index: 100;
+            }
+        </style>
+    </head>
+
+    <body>
+        <div id="info">
+            <a href="http://threejs.org" target="_blank">three.js</a> -
+            nrrd format loader test
+        </div>
+        <div id="inset"></div>
+
+        <script src="../build/three.js"></script>
+
+        <script src="js/controls/TrackballControls.js"></script>
+
+        <script src="js/Volume.js"></script>
+        <script src="js/VolumeSlice.js"></script>
+        <script src="js/loaders/NRRDLoader.js"></script>
+        <script src="js/loaders/VTKLoader.js"></script>
+
+        <script src="js/Detector.js"></script>
+        <script src="js/libs/stats.min.js"></script>
+        <script src="js/libs/zlib_and_gzip.min.js"></script>
+        <script src="js/libs/dat.gui.min.js"></script>
+
+        <script>
+
+            if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+            var container,
+                stats,
+                camera,
+                controls,
+                scene,
+                renderer,
+                gui,
+                container2,
+                renderer2,
+                camera2,
+                axes2,
+                scene2;
+
+            init();
+            animate();
+
+            function init() {
+
+                camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 0.01, 1e10 );
+                camera.position.z = 300;
+
+
+
+                scene = new THREE.Scene();
+
+                scene.add( camera );
+
+                // light
+
+                var dirLight = new THREE.DirectionalLight( 0xffffff );
+                dirLight.position.set( 200, 200, 1000 ).normalize();
+
+                camera.add( dirLight );
+                camera.add( dirLight.target );
+
+                var loader = new THREE.NRRDLoader();
+                loader.load( "models/nrrd/I.nrrd", function ( volume ) {
+                    var geometry,
+                        canvas,
+                        canvasMap,
+                        material,
+                        plane,
+                        sliceZ,
+                        sliceY,
+                        sliceX;
+
+                    //box helper to see the extend of the volume
+                    var geometry = new THREE.BoxGeometry( volume.xLength, volume.yLength, volume.zLength );
+                    var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
+                    var cube = new THREE.Mesh( geometry, material );
+                    cube.visible = false;
+                    var box = new THREE.BoxHelper( cube );
+                    scene.add( box );
+                    box.applyMatrix(volume.matrix);
+                    scene.add( cube );
+
+                    //z plane
+
+                    var indexZ = 0;
+                    sliceZ = volume.extractSlice('z',Math.floor(volume.RASDimensions[2]/4));
+                    scene.add( sliceZ.mesh );
+
+                    //y plane
+                    var indexY = 0;
+                    sliceY = volume.extractSlice('y',Math.floor(volume.RASDimensions[1]/2));
+                    scene.add( sliceY.mesh );
+
+                    //x plane
+                    var indexX = 0;
+                    sliceX = volume.extractSlice('x',Math.floor(volume.RASDimensions[0]/2));
+                    scene.add( sliceX.mesh );
+
+                    gui.add( sliceX, "index", 0, volume.RASDimensions[0], 1 ).name( "indexX" ).onChange( function () {sliceX.repaint.call(sliceX);} );
+                    gui.add( sliceY, "index", 0, volume.RASDimensions[1], 1 ).name( "indexY" ).onChange( function () {sliceY.repaint.call(sliceY);} );
+                    gui.add( sliceZ, "index", 0, volume.RASDimensions[2], 1 ).name( "indexZ" ).onChange( function () {sliceZ.repaint.call(sliceZ);} );
+
+                    gui.add( volume, "lowerThreshold", volume.min, volume.max, 1).name( "Lower Threshold").onChange( function () {
+                        volume.repaintAllSlices();
+                    });
+                    gui.add( volume, "upperThreshold", volume.min, volume.max, 1).name( "Upper Threshold").onChange( function () {
+                        volume.repaintAllSlices();
+                    });
+                    gui.add( volume, "windowLow", volume.min, volume.max, 1).name( "Window Low").onChange( function () {
+                        volume.repaintAllSlices();
+                    });
+                    gui.add( volume, "windowHigh", volume.min, volume.max, 1).name( "Window High").onChange( function () {
+                        volume.repaintAllSlices();
+                    });
+
+                } );
+
+                var vtkmaterial = new THREE.MeshLambertMaterial( {wireframe : false, morphTargets : false, side : THREE.DoubleSide, color : 0xff0000} );
+
+                var vtkloader = new THREE.VTKLoader();
+                vtkloader.load( "models/vtk/liver.vtk", function ( geometry ) {
+
+                    geometry.computeVertexNormals();
+
+                    var mesh = new THREE.Mesh( geometry, vtkmaterial );
+                    scene.add( mesh );
+                    var visibilityControl = {
+                        visible : true
+                    };
+                    gui.add(visibilityControl, "visible").name( "Model Visible").onChange( function () {
+                        mesh.visible = visibilityControl.visible;
+                        renderer.render( scene, camera );
+                    });
+
+                } );
+                // renderer
+
+                renderer = new THREE.WebGLRenderer( { antialias: false, alpha: true } );
+                renderer.setPixelRatio( window.devicePixelRatio );
+                renderer.setSize( window.innerWidth, window.innerHeight );
+
+                container = document.createElement( 'div' );
+                document.body.appendChild( container );
+                container.appendChild( renderer.domElement );
+
+                controls = new THREE.TrackballControls( camera, renderer.domElement );
+                controls.rotateSpeed = 5.0;
+                controls.zoomSpeed = 5;
+                controls.panSpeed = 2;
+                controls.noZoom = false;
+                controls.noPan = false;
+                controls.staticMoving = true;
+                controls.dynamicDampingFactor = 0.3;
+
+                stats = new Stats();
+                stats.domElement.style.position = 'absolute';
+                stats.domElement.style.top = '0px';
+                container.appendChild( stats.domElement );
+
+                var gui = new dat.GUI();
+
+                setupInset();
+
+                window.addEventListener( 'resize', onWindowResize, false );
+
+            }
+
+            function onWindowResize() {
+
+                camera.aspect = window.innerWidth / window.innerHeight;
+                camera.updateProjectionMatrix();
+
+                renderer.setSize( window.innerWidth, window.innerHeight );
+
+                controls.handleResize();
+
+            }
+
+            function animate() {
+
+                requestAnimationFrame( animate );
+
+                controls.update();
+
+                //copy position of the camera into inset
+                camera2.position.copy( camera.position );
+                camera2.position.sub( controls.target );
+                camera2.position.setLength( 300 );
+                camera2.lookAt( scene2.position );
+
+                renderer.render( scene, camera );
+                renderer2.render( scene2, camera2);
+
+                stats.update();
+
+            }
+
+            function rotateAroundWorldAxis(object, axis, radians) {
+                var rotWorldMatrix = new THREE.Matrix4();
+                rotWorldMatrix.makeRotationAxis(axis.normalize(), radians);
+
+                object.applyMatrix(rotWorldMatrix);
+
+            }
+
+            function setupInset () {
+                var insetWidth = 150,
+                    insetHeight = 150;
+                container2 = document.getElementById('inset');
+                container2.width = insetWidth;
+                container2.height = insetHeight;
+
+                // renderer
+                renderer2 = new THREE.WebGLRenderer({alpha : true});
+                renderer2.setClearColor( 0x000000, 0 );
+                renderer2.setSize( insetWidth, insetHeight );
+                container2.appendChild( renderer2.domElement );
+
+                // scene
+                scene2 = new THREE.Scene();
+
+                // camera
+                camera2 = new THREE.PerspectiveCamera( 50, insetWidth / insetHeight, 1, 1000 );
+                camera2.up = camera.up; // important!
+
+                // axes
+                axes2 = new THREE.AxisHelper( 100 );
+                scene2.add( axes2 );
+            }
+
+
+        </script>
+
+    </body>
+</html>

+ 58 - 4
examples/webgl_loader_vtk.html

@@ -28,10 +28,11 @@
 	<body>
 		<div id="info">
 		<a href="http://threejs.org" target="_blank">three.js</a> -
-		vtk format loader test -
-		model from <a href="http://www.cc.gatech.edu/projects/large_models/" target="_blank">The GeorgiaTech Lagre Geometric Model Archive</a>,
+		vtk formats loader test<br />
+		Legacy vtk model from <a href="http://www.cc.gatech.edu/projects/large_models/" target="_blank">The GeorgiaTech Lagre Geometric Model Archive</a>,
 		</div>
 
+		<script src='js/libs/inflate.min.js'></script>
 		<script src="../build/three.min.js"></script>
 
 		<script src="js/controls/TrackballControls.js"></script>
@@ -83,15 +84,68 @@
 				camera.add( dirLight );
 				camera.add( dirLight.target );
 
-				var material = new THREE.MeshLambertMaterial( { color:0xffffff, side: THREE.DoubleSide } );
+				var material = new THREE.MeshLambertMaterial( { color: 0xffffff, side: THREE.DoubleSide } );
 
 				var loader = new THREE.VTKLoader();
 				loader.load( "models/vtk/bunny.vtk", function ( geometry ) {
 
+					geometry.center();
 					geometry.computeVertexNormals();
 
 					var mesh = new THREE.Mesh( geometry, material );
-					mesh.position.setY( - 0.09 );
+					mesh.position.set( - 0.075, 0.005, 0 );
+					mesh.scale.multiplyScalar( 0.2 );
+					scene.add( mesh );
+
+				} );
+
+				var loader1 = new THREE.VTKLoader();
+				loader1.load( 'models/vtk/cube_ascii.vtp', function ( geometry ) {
+
+					geometry.computeVertexNormals();
+					geometry.center();
+
+					var material = new THREE.MeshLambertMaterial( { color: 0x00ff00, side: THREE.DoubleSide } );
+					var mesh = new THREE.Mesh( geometry, material );
+
+					mesh.position.set( - 0.025, 0, 0 );
+					mesh.scale.multiplyScalar( 0.01 );
+
+
+					scene.add( mesh );
+
+				} );
+
+				var loader2 = new THREE.VTKLoader();
+				loader2.load( 'models/vtk/cube_binary.vtp', function ( geometry ) {
+
+					geometry.computeVertexNormals();
+					geometry.center();
+
+					var material = new THREE.MeshLambertMaterial( { color: 0x0000ff, side: THREE.DoubleSide } );
+					var mesh = new THREE.Mesh( geometry, material );
+
+					mesh.position.set( 0.025, 0, 0 );
+					mesh.scale.multiplyScalar( 0.01 );
+
+
+					scene.add( mesh );
+
+				} );
+
+				var loader3 = new THREE.VTKLoader();
+				loader3.load( 'models/vtk/cube_no_compression.vtp', function ( geometry ) {
+
+					geometry.computeVertexNormals();
+					geometry.center();
+
+					var material = new THREE.MeshLambertMaterial( { color: 0xff0000, side: THREE.DoubleSide } );
+					var mesh = new THREE.Mesh( geometry, material );
+
+					mesh.position.set( 0.075, 0, 0 );
+					mesh.scale.multiplyScalar( 0.01 );
+
+
 					scene.add( mesh );
 
 				} );

+ 3 - 3
examples/webgl_materials_displacementmap.html

@@ -236,7 +236,7 @@
 
 				loader.load( "obj/ninja/NinjaLo_bin.js", function( geometry ) {
 
-					geometry.faceVertexUvs[ 1 ] = geometry.faceVertexUvs[ 0 ]; // 2nd set of UVs required for aoMap and displacementMap with MeshPhongMaterial
+					geometry.faceVertexUvs[ 1 ] = geometry.faceVertexUvs[ 0 ]; // 2nd set of UVs required for aoMap
 
 					mesh = new THREE.Mesh( geometry, material );
 					mesh.scale.multiplyScalar( 25 );
@@ -284,9 +284,9 @@
 
 				controls.update();
 
+				stats.begin();
 				render();
-
-				stats.update();
+				stats.end();
 
 			}
 

+ 27 - 27
examples/webgl_materials_envmaps_hdr.html

@@ -32,28 +32,27 @@
 			Created by Prashant Sharma and <a href="http://clara.io/" target="_blank">Ben Houston</a>.</div>
 
 		<script src="../build/three.min.js"></script>
-		<script src="../examples/js/controls/OrbitControls.js"></script>
-		<script src="../src/loaders/BinaryTextureLoader.js"></script>
-		<script src="../examples/js/loaders/RGBELoader.js"></script>
-		<script src="../examples/js/loaders/HDRCubeTextureLoader.js"></script>
-
-		<script src="../examples/js/Detector.js"></script>
-		<script src="../examples/js/libs/stats.min.js"></script>
-
-		<script src="../examples/js/Half.js"></script>
-		<script src="../examples/js/Encodings.js"></script>
-		<script src="../examples/js/pmrem/PMREMGenerator.js"></script>
-		<script src="../examples/js/pmrem/PMREMCubeUVPacker.js"></script>
-		<script src="../examples/js/libs/dat.gui.min.js"></script>
-
-		<script src="../examples/js/postprocessing/EffectComposer.js"></script>
-		<script src="../examples/js/postprocessing/RenderPass.js"></script>
-		<script src="../examples/js/postprocessing/MaskPass.js"></script>
-		<script src="../examples/js/postprocessing/ShaderPass.js"></script>
-		<script src="../examples/js/shaders/CopyShader.js"></script>
-		<script src="../examples/js/shaders/FXAAShader.js"></script>
-		<script src="../examples/js/postprocessing/BloomPass.js"></script>
-		<script src="../examples/js/shaders/ConvolutionShader.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
+		<script src="js/loaders/RGBELoader.js"></script>
+		<script src="js/loaders/HDRCubeTextureLoader.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script src="js/Half.js"></script>
+		<script src="js/Encodings.js"></script>
+		<script src="js/pmrem/PMREMGenerator.js"></script>
+		<script src="js/pmrem/PMREMCubeUVPacker.js"></script>
+		<script src="js/libs/dat.gui.min.js"></script>
+
+		<script src="js/postprocessing/EffectComposer.js"></script>
+		<script src="js/postprocessing/RenderPass.js"></script>
+		<script src="js/postprocessing/MaskPass.js"></script>
+		<script src="js/postprocessing/ShaderPass.js"></script>
+		<script src="js/shaders/CopyShader.js"></script>
+		<script src="js/shaders/FXAAShader.js"></script>
+		<script src="js/postprocessing/BloomPass.js"></script>
+		<script src="js/shaders/ConvolutionShader.js"></script>
 
 		<script>
 
@@ -125,7 +124,7 @@
 				scene.add( planeMesh1 );
 
 				var textureLoader = new THREE.TextureLoader();
-				textureLoader.load( "../examples/textures/roughness_map.jpg", function( map ) {
+				textureLoader.load( "./textures/roughness_map.jpg", function( map ) {
 					map.wrapS = THREE.RepeatWrapping;
 					map.wrapT = THREE.RepeatWrapping;
 					map.anisotropy = 4;
@@ -143,7 +142,7 @@
 					];
 				};
 
-				var hdrUrls = genCubeUrls( "../examples/textures/cube/pisaHDR/", ".hdr" );
+				var hdrUrls = genCubeUrls( "./textures/cube/pisaHDR/", ".hdr" );
 				new THREE.HDRCubeTextureLoader().load( THREE.UnsignedByteType, hdrUrls, function ( hdrCubeMap ) {
 
 					var pmremGenerator = new THREE.PMREMGenerator( hdrCubeMap );
@@ -158,7 +157,7 @@
 					standardMaterial.needsUpdate = true;
 				} );
 
-				var ldrUrls = genCubeUrls( "../examples/textures/cube/pisa/", ".png" );
+				var ldrUrls = genCubeUrls( "./textures/cube/pisa/", ".png" );
 				new THREE.CubeTextureLoader().load( ldrUrls, function ( ldrCubeMap ) {
 
 					ldrCubeMap.encoding = THREE.GammaEncoding;
@@ -173,7 +172,7 @@
 				} );
 
 
-				var rgbmUrls = genCubeUrls( "../examples/textures/cube/pisaRGBM16/", ".png" );
+				var rgbmUrls = genCubeUrls( "./textures/cube/pisaRGBM16/", ".png" );
 				new THREE.CubeTextureLoader().load( rgbmUrls, function ( rgbmCubeMap ) {
 
 					rgbmCubeMap.encoding = THREE.RGBM16Encoding;
@@ -257,8 +256,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 1 - 1
examples/webgl_materials_nodes.html

@@ -1,4 +1,4 @@
-<!doctype html>
+<!DOCTYPE html>
 <html lang="en">
 	<head>
 		<title>WebGL NodeMaterial</title>

+ 44 - 13
examples/webgl_materials_standard.html

@@ -51,6 +51,12 @@
 
 		<script src="js/controls/TrackballControls.js"></script>
 		<script src="js/loaders/OBJLoader.js"></script>
+		<script src="js/loaders/RGBELoader.js"></script>
+		<script src="js/loaders/HDRCubeTextureLoader.js"></script>
+		<script src="js/Half.js"></script>
+		<script src="js/Encodings.js"></script>
+		<script src="js/pmrem/PMREMGenerator.js"></script>
+		<script src="js/pmrem/PMREMCubeUVPacker.js"></script>
 
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
@@ -87,6 +93,21 @@
 
 				controls = new THREE.TrackballControls( camera );
 
+				//
+
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setClearColor( 0x202020 );
+				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				container.appendChild( renderer.domElement );
+
+				renderer.autoClear = false;
+				renderer.gammaInput = true;
+				renderer.gammaOutput = true;
+				renderer.toneMapping = THREE.ReinhardToneMapping;
+				renderer.toneMappingExposure = 3;
+
+
 				scene = new THREE.Scene();
 
 				sceneCube = new THREE.Scene();
@@ -111,7 +132,7 @@
 				var shader = THREE.ShaderLib[ "cube" ];
 				shader.uniforms[ "tCube" ].value = textureCube;
 
-				var material = new THREE.ShaderMaterial( {
+				var materialBG = new THREE.ShaderMaterial( {
 
 					fragmentShader: shader.fragmentShader,
 					vertexShader: shader.vertexShader,
@@ -121,7 +142,7 @@
 
 				} ),
 
-				mesh = new THREE.Mesh( new THREE.BoxGeometry( 100, 100, 100 ), material );
+				mesh = new THREE.Mesh( new THREE.BoxGeometry( 100, 100, 100 ), materialBG );
 				sceneCube.add( mesh );
 
 				//
@@ -129,10 +150,10 @@
 				var path = 'models/obj/cerberus/';
 
 				var loader = new THREE.OBJLoader();
+				var material = new THREE.MeshStandardMaterial();
 				loader.load( path + 'Cerberus.obj', function ( group ) {
 
 					// var material = new THREE.MeshBasicMaterial( { wireframe: true } );
-					var material = new THREE.MeshStandardMaterial();
 
 					var loader = new THREE.TextureLoader();
 
@@ -143,7 +164,6 @@
 					material.roughnessMap = loader.load( path + 'Cerberus_R.jpg' );
 					material.metalnessMap = loader.load( path + 'Cerberus_M.jpg' );
 					material.normalMap = loader.load( path + 'Cerberus_N.jpg' );
-					material.envMap = textureCube;
 
 					material.map.wrapS = THREE.RepeatWrapping;
 					material.roughnessMap.wrapS = THREE.RepeatWrapping;
@@ -166,17 +186,28 @@
 
 				} );
 
-				//
+				var genCubeUrls = function( prefix, postfix ) {
+					return [
+						prefix + 'px' + postfix, prefix + 'nx' + postfix,
+						prefix + 'py' + postfix, prefix + 'ny' + postfix,
+						prefix + 'pz' + postfix, prefix + 'nz' + postfix
+					];
+				};
 
-				renderer = new THREE.WebGLRenderer( { antialias: true } );
-				renderer.setClearColor( 0x202020 );
-				renderer.setPixelRatio( window.devicePixelRatio );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				container.appendChild( renderer.domElement );
+				var hdrUrls = genCubeUrls( "./textures/cube/pisaHDR/", ".hdr" );
+				new THREE.HDRCubeTextureLoader().load( THREE.UnsignedByteType, hdrUrls, function ( hdrCubeMap ) {
 
-				renderer.autoClear = false;
-				renderer.gammaInput = true;
-				renderer.gammaOutput = true;
+					var pmremGenerator = new THREE.PMREMGenerator( hdrCubeMap );
+					pmremGenerator.update( renderer );
+
+					var pmremCubeUVPacker = new THREE.PMREMCubeUVPacker( pmremGenerator.cubeLods );
+					pmremCubeUVPacker.update( renderer );
+
+					hdrCubeRenderTarget = pmremCubeUVPacker.CubeUVRenderTarget;
+
+					material.envMap = hdrCubeRenderTarget;
+					material.needsUpdate = true;
+				} );
 
 				//
 

+ 2 - 1
examples/webgl_materials_texture_manualmipmap.html

@@ -240,8 +240,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 9 - 18
examples/webgl_materials_transparency.html

@@ -54,9 +54,8 @@
 
 			var container, stats;
 			var params = {
-				opacity: 0.2,
 				roughness: 1.0,
-				bumpScale: 0.3
+				opacity: 0.5
 			};
 			var camera, scene, renderer, controls, objects = [];
 			var composer;
@@ -79,28 +78,25 @@
 
 				standardMaterial = new THREE.MeshStandardMaterial( {
 					map: null,
-					bumpScale: - 0.05,
-					color: 0x0304ff,
 					metalness: 0.9,
-					roughness: 0.5,
+					roughness: 1.0,
 					shading: THREE.SmoothShading,
 					blending: THREE.NormalBlending,
 					transparent: true
 				} );
 				var geometry = new THREE.SphereGeometry( 18, 30, 30 );
 				var torusMesh1 = new THREE.Mesh( geometry, standardMaterial );
-				torusMesh1.position.x = 20.0;
+				torusMesh1.position.x = - 20.0;
 				torusMesh1.castShadow = true;
 				scene.add( torusMesh1 );
 				objects.push( torusMesh1 );
 
 				standardMaterialPremultiplied = new THREE.MeshStandardMaterial( {
 					map: null,
-					bumpScale: - 0.05,
-					color: 0x0304ff,
 					metalness: 0.9,
-					roughness: 0.5,
+					roughness: 1.0,
 					shading: THREE.SmoothShading,
+					premultipliedAlpha: true,
 					transparent: true
 				} );
 
@@ -113,17 +109,15 @@
 					map.repeat.set( 2, 2 );
 					standardMaterial.map = map;
 					standardMaterial.roughnessMap = map;
-					//standardMaterial.bumpMap = map;
 					standardMaterial.needsUpdate = true;
 					standardMaterialPremultiplied.map = map;
 					standardMaterialPremultiplied.roughnessMap = map;
-					//standardMaterialPremultiplied.bumpMap = map;
 					standardMaterialPremultiplied.needsUpdate = true;
 
 				} );
 
 				var torusMesh2 = new THREE.Mesh( geometry, standardMaterialPremultiplied );
-				torusMesh2.position.x = - 20.0;
+				torusMesh2.position.x = 20.0;
 				torusMesh2.castShadow = true;
 				scene.add( torusMesh2 );
 				objects.push( torusMesh2 );
@@ -151,7 +145,7 @@
 				var spotLight = new THREE.SpotLight( 0xffffff );
 				spotLight.position.set( 50, 100, 50 );
 				spotLight.angle = Math.PI / 7;
-				spotLight.penumbra = 0.8
+				spotLight.penumbra = 0.8;
 				spotLight.intensity = 5;
 				spotLight.castShadow = true;
 				scene.add( spotLight );
@@ -189,7 +183,6 @@
 				var gui = new dat.GUI();
 
 				gui.add( params, 'roughness', 0, 1 );
-				gui.add( params, 'bumpScale', - 1, 1 );
 				gui.add( params, 'opacity', 0, 1 );
 				gui.open();
 
@@ -214,8 +207,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 
@@ -227,9 +221,6 @@
 					standardMaterial.roughness = params.roughness;
 					standardMaterialPremultiplied.roughness = params.roughness;
 
-					standardMaterial.bumpScale = - 0.05 * params.bumpScale;
-					standardMaterialPremultiplied.bumpScale = - 0.05 * params.bumpScale;
-
 					standardMaterial.opacity = params.opacity;
 					standardMaterialPremultiplied.opacity = params.opacity;
 

+ 2 - 1
examples/webgl_materials_variations_phong.html

@@ -215,8 +215,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 52 - 34
examples/webgl_morphtargets_human.html

@@ -1,4 +1,4 @@
-<!doctype html>
+<!DOCTYPE html>
 <html lang="en">
 	<head>
 		<title>three.js webgl - morph target - human</title>
@@ -29,7 +29,7 @@
 	</head>
 
 	<body>
-		
+
 		<div id="container"></div>
 
 		<div id="info">
@@ -37,17 +37,17 @@
 		</div>
 
 		<script src="../build/three.min.js"></script>
-		
+
 		<script src="js/UCSCharacter.js"></script>
 
 		<script src="js/Detector.js"></script>
-		
+
 		<script src='js/libs/dat.gui.min.js'></script>
-				
+
 		<script src="js/controls/OrbitControls.js"></script>
-		
+
 		<script>
-			
+
 			var SCREEN_WIDTH = window.innerWidth;
 			var SCREEN_HEIGHT = window.innerHeight;
 
@@ -55,7 +55,7 @@
 
 			var camera, scene;
 			var renderer;
-			
+
 			var mesh;
 
 			var mouseX = 0, mouseY = 0;
@@ -64,9 +64,9 @@
 			var windowHalfY = window.innerHeight / 2;
 
 			var clock = new THREE.Clock();
-			
+
 			var gui, skinConfig, morphConfig;
-				
+
 			document.addEventListener( 'mousemove', onDocumentMouseMove, false );
 
 			init();
@@ -92,7 +92,7 @@
 				//
 
 				var light = new THREE.DirectionalLight( 0xffffff, 1 );
-				light.position.set( 0, -1, 0 );
+				light.position.set( 0, - 1, 0 );
 				scene.add( light );
 
 				// RENDERER
@@ -106,7 +106,8 @@
 				// CHARACTER
 
 				character = new THREE.UCSCharacter();
-				character.onLoadComplete = function() {
+				character.onLoadComplete = function () {
+
 					console.log( "Load Complete" );
 					console.log( character.numSkins + " skins and " + character.numMorphs + " morphtargets loaded." );
 					gui = new dat.GUI();
@@ -114,10 +115,11 @@
 					setupMorphsGUI();
 					gui.width = 300;
 					gui.open();
+
 				};
-				
+
 				var loader = new THREE.XHRLoader();
-				loader.load("models/skinned/UCS_config.json", function ( text ) {
+				loader.load( 'models/skinned/UCS_config.json', function ( text ) {
 
 					var config = JSON.parse( text );
 					character.loadParts( config );
@@ -126,65 +128,81 @@
 				} );
 
 				window.addEventListener( 'resize', onWindowResize, false );
-				
+
 				controls = new THREE.OrbitControls( camera, renderer.domElement );
-				controls.center.set( 0, 3000, 0);
+				controls.center.set( 0, 3000, 0 );
 
 				controls.addEventListener( 'change', render );
 
 			}
-			
+
 			function setupSkinsGUI() {
-			
+
 				var skinGui = gui.addFolder( "Skins" );
-				
+
 				skinConfig = {
 					wireframe: false
 				};
-				
-				var skinCallback = function( index ) {
+
+				var skinCallback = function ( index ) {
+
 					return function () {
+
 						character.setSkin( index );
+
 					};
+
 				};
 
-				for ( var i = 0; i < character.numSkins; i++ ) {
+				for ( var i = 0; i < character.numSkins; i ++ ) {
+
 					var name = character.skins[ i ].name;
 					skinConfig[ name ] = skinCallback( i );
+
 				}
-				
-				for ( var i = 0; i < character.numSkins; i++ ) {
-					skinGui.add( skinConfig, character.skins[i].name );
+
+				for ( var i = 0; i < character.numSkins; i ++ ) {
+
+					skinGui.add( skinConfig, character.skins[ i ].name );
+
 				}
-				
+
 				skinGui.open();
 
 			}
-			
+
 			function setupMorphsGUI() {
-				
+
 				var morphGui = gui.addFolder( "Morphs" );
-				
+
 				morphConfig = {
 				};
-				
+
 				var morphCallback = function( index ) {
+
 					return function () {
+
 						character.updateMorphs( morphConfig );
+
 					}
+
 				};
-				
+
 				for ( var i = 0; i < character.numMorphs; i ++ ) {
+
 					var morphName = character.morphs[ i ];
 					morphConfig[ morphName ] = 0;
+
 				}
-				
+
 				for ( var i = 0; i < character.numMorphs; i ++ ) {
+
 					morphGui.add( morphConfig, character.morphs[ i ] ).min( 0 ).max( 100 ).onChange( morphCallback( i ) );
+
 				}
-				
+
 				morphGui.open();
-			
+
 			}
 
 			function onWindowResize() {

+ 15 - 15
examples/webgl_particles_general.html

@@ -1,9 +1,9 @@
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US">
 <head>
-    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 
-    <script src="../build/three.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/OrbitControls.js"></script>
@@ -11,7 +11,7 @@
 	<script src='js/libs/dat.gui.min.js'></script>
 	<script src="js/libs/photons.min.js"></script>
 
-    <style>
+	<style>
 		body {
 			font-family: Monospace;
 			background-color: #000;
@@ -29,7 +29,7 @@
 		}
 		#info a { color: #f00; font-weight: bold; text-decoration: underline; cursor: pointer }
 	</style>
-    <title>Three.js Particle System</title>
+	<title>Three.js Particle System</title>
 </head>
 <body>
 
@@ -113,7 +113,7 @@
 
 		smokeType = ParticleSystemIDs.Smoke1;
 
-    var textureLoader = new THREE.TextureLoader();
+		var textureLoader = new THREE.TextureLoader();
 
 		var smoke1Atlas = new PHOTONS.Atlas( textureLoader.load( 'textures/campfire/smokeparticle.png' ), true );
 		var smoke2Atlas = PHOTONS.Atlas.createGridAtlas( textureLoader.load( 'textures/campfire/smokeparticles.png' ), 0.0, 1.0, 1.0, 0.0, 4.0, 4.0, false, true );
@@ -161,7 +161,7 @@
 						"vec3 lightPosition = pointLights[ i ].position;",
 						"vec3 lVector = lightPosition + viewPosition.xyz;",
 						"vec3 lightDir = normalize( lVector );",
-						"float attenuation = calcLightAttenuation( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
+						"float attenuation = punctualLightIntensityToIrradianceFactor( length( lVector ), pointLights[ i ].distance, pointLights[ i ].decay );",
 						"totalDiffuseLight += lightColor * attenuation;",
 					"}",
 				"#endif",
@@ -489,7 +489,7 @@
 
 		window.addEventListener( 'resize', onWindowResize, false );
 
-	    }
+	}
 
 	function initRenderer() {
 
@@ -511,11 +511,11 @@
 		pointLight = new THREE.PointLight( 0xffffff, 2, 1000, 1 );
 		pointLight.position.set( 0, 40, 0 );
 		pointLight.castShadow = true;
-		pointLight.shadowCameraNear = 1;
-		pointLight.shadowCameraFar = 1000;
-		pointLight.shadowMapWidth = 4096;
-		pointLight.shadowMapHeight = 2048;
-		pointLight.shadowBias = - 0.5;
+		pointLight.shadow.camera.near = 1;
+		pointLight.shadow.camera.far = 1000;
+		pointLight.shadow.mapSize.width = 4096;
+		pointLight.shadow.mapSize.height = 2048;
+		pointLight.shadow.bias = - 0.5;
 		scene.add( pointLight );
 
 	}
@@ -715,7 +715,7 @@
 		controls.target.set( 0, 0, 0 );
 		controls.update();
 
-	    }
+	}
 
 	function onWindowResize() {
 
@@ -860,8 +860,8 @@
 
 	function animate() {
 
-		    requestAnimationFrame( animate );
-		    update();
+		requestAnimationFrame( animate );
+		update();
 		render();
 
 	}

+ 2 - 1
examples/webgl_postprocessing_advanced.html

@@ -359,8 +359,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 2 - 1
examples/webgl_postprocessing_dof.html

@@ -278,8 +278,9 @@
 
 				requestAnimationFrame( animate, renderer.domElement );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 2 - 1
examples/webgl_postprocessing_godrays.html

@@ -255,8 +255,9 @@
 
 				requestAnimationFrame( animate, renderer.domElement );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 3 - 2
examples/webgl_postprocessing_msaa.html

@@ -164,6 +164,8 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
+
 				for ( var i = 0; i < scene.children.length; i ++ ) {
 
 					var child = scene.children[ i ];
@@ -174,8 +176,7 @@
 				}
 
 				composer.render();
-
-				stats.update();
+				stats.end();
 
 			}
 

+ 3 - 1
examples/webgl_postprocessing_smaa.html

@@ -108,6 +108,8 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
+
 				for ( var i = 0; i < scene.children.length; i ++ ) {
 
 					var child = scene.children[ i ];
@@ -119,7 +121,7 @@
 
 				composer.render();
 
-				stats.update();
+				stats.end();
 
 			}
 

+ 2 - 1
examples/webgl_postprocessing_ssao.html

@@ -191,8 +191,9 @@ Spiral sampling http://web.archive.org/web/20120421191837/http://www.cgafaq.info
 			function animate() {
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 			}
 
 			function render() {

+ 2 - 1
examples/webgl_shading_physical.html

@@ -429,8 +429,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 21 - 56
examples/webgl_shadowmap.html

@@ -37,6 +37,7 @@
 		<script src="js/controls/FirstPersonControls.js"></script>
 
 		<script src="js/shaders/UnpackDepthRGBAShader.js"></script>
+		<script src="js/utils/ShadowMapViewer.js"></script>
 
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
@@ -51,18 +52,17 @@
 
 			var SCREEN_WIDTH = window.innerWidth;
 			var SCREEN_HEIGHT = window.innerHeight;
-			var FLOOR = -250;
+			var FLOOR = - 250;
 
 			var camera, controls, scene, renderer;
 			var container, stats;
 
 			var NEAR = 10, FAR = 3000;
 
-			var sceneHUD, cameraOrtho, hudMesh;
-
 			var mixer, morphs = [];
 
 			var light;
+			var lightShadowMapViewer;
 
 			var clock = new THREE.Clock();
 
@@ -167,25 +167,17 @@
 
 				renderer.setSize( SCREEN_WIDTH, SCREEN_HEIGHT );
 
-				var aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
-				cameraOrtho.left = - aspect;
-				cameraOrtho.right = aspect;
-				cameraOrtho.top = 1;
-				cameraOrtho.bottom = - 1;
-				cameraOrtho.updateProjectionMatrix();
-
-				hudMesh.position.x = cameraOrtho.left + HUD_MARGIN;
-				hudMesh.position.y = cameraOrtho.bottom + HUD_MARGIN;
-
 				controls.handleResize();
 
 			}
 
 			function onKeyDown ( event ) {
 
-				switch( event.keyCode ) {
+				switch ( event.keyCode ) {
 
-					case 84: /*t*/ showHUD = !showHUD; break;
+					case 84:	/*t*/
+						showHUD = ! showHUD;
+						break;
 
 				}
 
@@ -193,38 +185,12 @@
 
 			function createHUD() {
 
-				var aspect = SCREEN_WIDTH / SCREEN_HEIGHT;
-
-				cameraOrtho = new THREE.OrthographicCamera( - aspect, aspect,  1, - 1, 1, 10 );
-				cameraOrtho.position.z = 5;
-
-				var shader = THREE.UnpackDepthRGBAShader;
-				var uniforms = new THREE.UniformsUtils.clone( shader.uniforms );
-
-				uniforms.tDiffuse.value = light.shadowMap;
-
-				var hudMaterial = new THREE.ShaderMaterial( {
-					uniforms: uniforms,
-					vertexShader: shader.vertexShader,
-					fragmentShader: shader.fragmentShader
-				} );
-
-				var hudHeight = 2 / 3;
-
-				var hudWidth = hudHeight * SHADOW_MAP_WIDTH / SHADOW_MAP_HEIGHT;
-
-				var hudGeo = new THREE.PlaneBufferGeometry( hudWidth, hudHeight );
-				hudGeo.translate( hudWidth / 2, hudHeight / 2, 0 );
-
-				hudMesh = new THREE.Mesh( hudGeo, hudMaterial );
-
-				hudMesh.position.x = cameraOrtho.left + HUD_MARGIN;
-				hudMesh.position.y = cameraOrtho.bottom + HUD_MARGIN;
-
-				sceneHUD = new THREE.Scene();
-				sceneHUD.add( hudMesh );
-
-				cameraOrtho.lookAt( sceneHUD.position );
+				lightShadowMapViewer = new THREE.ShadowMapViewer( light );
+				lightShadowMapViewer.position.x = 10;
+				lightShadowMapViewer.position.y = SCREEN_HEIGHT - ( SHADOW_MAP_HEIGHT / 4 ) - 10;
+				lightShadowMapViewer.size.width = SHADOW_MAP_WIDTH / 4;
+				lightShadowMapViewer.size.height = SHADOW_MAP_HEIGHT / 4;
+				lightShadowMapViewer.update();
 
 			}
 
@@ -263,10 +229,10 @@
 						bevelSize: 5,
 						bevelEnabled: true
 
-					});
+					} );
 
 					textGeo.computeBoundingBox();
-					var centerOffset = -0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
+					var centerOffset = - 0.5 * ( textGeo.boundingBox.max.x - textGeo.boundingBox.min.x );
 
 					var textMaterial = new THREE.MeshPhongMaterial( { color: 0xff0000, specular: 0xffffff } );
 
@@ -329,7 +295,7 @@
 							play();
 
 					mesh.position.set( x, y, z );
-					mesh.rotation.y = Math.PI/2;
+					mesh.rotation.y = Math.PI / 2;
 
 					mesh.castShadow = true;
 					mesh.receiveShadow = true;
@@ -348,9 +314,9 @@
 					addMorph( geometry, 550, 1, 100 - Math.random() * 1000, FLOOR, 450, true );
 					addMorph( geometry, 550, 1, 100 - Math.random() * 1000, FLOOR, 600, true );
 
-					addMorph( geometry, 550, 1, 100 - Math.random() * 1000, FLOOR, -300, true );
-					addMorph( geometry, 550, 1, 100 - Math.random() * 1000, FLOOR, -450, true );
-					addMorph( geometry, 550, 1, 100 - Math.random() * 1000, FLOOR, -600, true );
+					addMorph( geometry, 550, 1, 100 - Math.random() * 1000, FLOOR, - 300, true );
+					addMorph( geometry, 550, 1, 100 - Math.random() * 1000, FLOOR, - 450, true );
+					addMorph( geometry, 550, 1, 100 - Math.random() * 1000, FLOOR, - 600, true );
 
 				} );
 
@@ -397,7 +363,7 @@
 
 					if ( morph.position.x  > 2000 )  {
 
-						morph.position.x = -1000 - Math.random() * 500;
+						morph.position.x = - 1000 - Math.random() * 500;
 
 					}
 
@@ -412,8 +378,7 @@
 
 				if ( showHUD ) {
 
-					renderer.clearDepth();
-					renderer.render( sceneHUD, cameraOrtho );
+					lightShadowMapViewer.render( renderer );
 
 				}
 

+ 2 - 1
examples/webgl_shadowmap_performance.html

@@ -369,8 +369,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 2 - 2
examples/webgl_shadowmap_viewer.html

@@ -91,9 +91,9 @@
 				dirLight.shadowCameraNear = 1;
 				dirLight.shadowCameraFar = 10;
 				dirLight.shadowCameraRight = 15;
-				dirLight.shadowCameraLeft = -15;
+				dirLight.shadowCameraLeft = - 15;
 				dirLight.shadowCameraTop	= 15;
-				dirLight.shadowCameraBottom = -15;
+				dirLight.shadowCameraBottom = - 15;
 				dirLight.shadowMapWidth = 1024;
 				dirLight.shadowMapHeight = 1024;
 				scene.add( dirLight );

+ 4 - 3
examples/webgl_tonemapping.html

@@ -105,8 +105,8 @@
 					metalness: 0.9,
 					roughness: 0.8,
 					shading: THREE.SmoothShading,
-					transparent: true,
-					blending: THREE.PremultipliedAlphaBlending
+					premultipliedAlpha: true,
+					transparent: true
 				} );
 
 				var textureLoader = new THREE.TextureLoader();
@@ -252,8 +252,9 @@
 
 				requestAnimationFrame( animate );
 
+				stats.begin();
 				render();
-				stats.update();
+				stats.end();
 
 			}
 

+ 80 - 92
examples/webvr_cubes.html

@@ -1,62 +1,43 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgl - webvr cubes</title>
+		<title>three.js webvr - cubes</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: #f0f0f0;
+				background-color: #101010;
+				color: #fff;
 				margin: 0px;
 				overflow: hidden;
 			}
-
-			.menu {
-				position: fixed;
-				bottom: 20px;
-				right: 20px;
-			}
-
-			.button {
-				display: inline-block;
-				padding: 8px;
-				color: #FFF;
-				background-color: #555;
-			}
-
-			.button.enabled {
-				background-color: rgb(18, 36, 70);
-			}
-
-			.button:hover {
-				cursor: pointer;
-				background-color: rgb(18, 36, 70);
+			a {
+				color: #f00;
 			}
-
-			.button.error {
-				pointer-events: none;
-				background-color: red;
-			}
-
 		</style>
 	</head>
 	<body>
-		<div class="menu">
-			<div class="button full-screen">Start VR Mode</div>
-		</div>
 
 		<script src="../build/three.min.js"></script>
+
+		<script src="js/WebVR.js"></script>
 		<script src="js/effects/VREffect.js"></script>
 		<script src="js/controls/VRControls.js"></script>
-		<script src="js/libs/stats.min.js"></script>
 
 		<script>
 
-			var container, stats;
+			if ( WEBVR.isLatestAvailable() === false ) {
+
+				document.body.appendChild( WEBVR.getMessage() );
+
+			}
+
+			//
+
+			var container;
 			var camera, scene, raycaster, renderer;
-			var vrEffect;
-			var vrControls;
+			var effect, controls;
 
 			var cubes = [];
 			var INTERSECTED;
@@ -79,33 +60,43 @@
 				info.innerHTML = '<a href="http://threejs.org" target="_blank">three.js</a> webgl - interactive cubes';
 				container.appendChild( info );
 
-				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 10000 );
-
 				scene = new THREE.Scene();
 
+				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.1, 1000 );
+				scene.add( camera );
+
 				crosshair = new THREE.Mesh(
-					new THREE.RingGeometry( 0.5, 1, 32 ),
+					new THREE.RingGeometry( 0.02, 0.04, 32 ),
 					new THREE.MeshBasicMaterial( {
-						color: 0x00bb00,
-						transparent: true,
-						opacity: 0.5
+						color: 0xffffff,
+						opacity: 0.5,
+						transparent: true
 					} )
 				);
-				scene.add( crosshair );
+				crosshair.position.z = - 2;
+				camera.add( crosshair );
 
-				var light = new THREE.DirectionalLight( 0xffffff, 1 );
+				var mesh = new THREE.Mesh(
+					new THREE.BoxGeometry( 200, 200, 200, 10, 10, 10 ),
+					new THREE.MeshBasicMaterial( { color: 0x202020, wireframe: true } )
+				);
+				scene.add( mesh );
+
+				scene.add( new THREE.HemisphereLight( 0x404020, 0x202040, 0.5 ) );
+
+				var light = new THREE.DirectionalLight( 0xffffff );
 				light.position.set( 1, 1, 1 ).normalize();
 				scene.add( light );
 
-				var geometry = new THREE.BoxGeometry( 20, 20, 20 );
+				var geometry = new THREE.BoxGeometry( 5, 5, 5 );
 
-				for ( var i = 0; i < 2000; i ++ ) {
+				for ( var i = 0; i < 200; i ++ ) {
 
 					var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: Math.random() * 0xffffff } ) );
 
-					object.position.x = Math.random() * 800 - 400;
-					object.position.y = Math.random() * 800 - 400;
-					object.position.z = Math.random() * 800 - 400;
+					object.position.x = Math.random() * 200 - 100;
+					object.position.y = Math.random() * 200 - 100;
+					object.position.z = Math.random() * 200 - 100;
 
 					object.rotation.x = Math.random() * 2 * Math.PI;
 					object.rotation.y = Math.random() * 2 * Math.PI;
@@ -115,6 +106,11 @@
 					object.scale.y = Math.random() + 0.5;
 					object.scale.z = Math.random() + 0.5;
 
+					object.userData.velocity = new THREE.Vector3();
+					object.userData.velocity.x = Math.random() * 0.4 - 0.2;
+					object.userData.velocity.y = Math.random() * 0.4 - 0.2;
+					object.userData.velocity.z = Math.random() * 0.4 - 0.2;
+
 					scene.add( object );
 					cubes.push( object );
 
@@ -123,41 +119,21 @@
 				raycaster = new THREE.Raycaster();
 
 				renderer = new THREE.WebGLRenderer( { antialias: true } );
+				renderer.setClearColor( 0x101010 );
 				renderer.setPixelRatio( window.devicePixelRatio );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.sortObjects = false;
+				container.appendChild( renderer.domElement );
 
-				var fullScreenButton = document.querySelector( '.full-screen' );
+				controls = new THREE.VRControls( camera );
+				effect = new THREE.VREffect( renderer );
 
-				if ( navigator.getVRDisplays === undefined && navigator.getVRDevices === undefined ) {
+				if ( WEBVR.isAvailable() === true ) {
 
-					fullScreenButton.innerHTML = 'Your browser doesn\'t support WebVR';
-					fullScreenButton.classList.add('error');
+					document.body.appendChild( WEBVR.getButton( effect ) );
 
 				}
 
-				vrControls = new THREE.VRControls( camera );
-				vrEffect = new THREE.VREffect( renderer, function ( error ) {
-
-					fullScreenButton.innerHTML = error;
-					fullScreenButton.classList.add('error');
-
-				} );
-
-				fullScreenButton.onclick = function() {
-
-					vrEffect.setFullScreen( true );
-
-				};
-
-				renderer.setClearColor( 0xf0f0f0 );
-				renderer.setSize( window.innerWidth, window.innerHeight );
-				renderer.sortObjects = false;
-				container.appendChild( renderer.domElement );
-
-				stats = new Stats();
-				stats.domElement.style.position = 'absolute';
-				stats.domElement.style.top = '0px';
-				container.appendChild( stats.domElement );
-
 				//
 
 				window.addEventListener( 'resize', onWindowResize, false );
@@ -169,7 +145,7 @@
 				camera.aspect = window.innerWidth / window.innerHeight;
 				camera.updateProjectionMatrix();
 
-				vrEffect.setSize( window.innerWidth, window.innerHeight );
+				effect.setSize( window.innerWidth, window.innerHeight );
 
 			}
 
@@ -178,9 +154,7 @@
 			function animate() {
 
 				requestAnimationFrame( animate );
-
 				render();
-				stats.update();
 
 			}
 
@@ -212,26 +186,40 @@
 
 				}
 
-				vrControls.update();
+				controls.update();
 
-				crosshair.quaternion.copy( camera.quaternion );
-				crosshair.position.set( 0, 0, 0 );
+				for ( var i = 0; i < cubes.length; i ++ ) {
 
-				if ( INTERSECTED ) {
+					var cube = cubes[ i ];
 
-					crosshair.translateZ(
-						-scene.position.distanceTo( INTERSECTED.position ) +
-						INTERSECTED.geometry.boundingSphere.radius + 5
-					);
+					cube.position.add( cube.userData.velocity );
 
-				}
-				else {
+					if ( cube.position.x < - 100 || cube.position.x > 100 ) {
+
+						cube.position.x = THREE.Math.clamp( cube.position.x, - 100, 100 );
+						cube.userData.velocity.x = - cube.userData.velocity.x;
+
+					}
+
+					if ( cube.position.y < - 100 || cube.position.y > 100 ) {
+
+						cube.position.y = THREE.Math.clamp( cube.position.y, - 100, 100 );
+						cube.userData.velocity.y = - cube.userData.velocity.y;
+
+					}
+
+					if ( cube.position.z < - 100 || cube.position.z > 100 ) {
+
+						cube.position.z = THREE.Math.clamp( cube.position.z, - 100, 100 );
+						cube.userData.velocity.z = - cube.userData.velocity.z;
+
+					}
 
-					crosshair.translateZ(-40);
+					cube.rotation.x += 0.01;
 
 				}
 
-				vrEffect.render( scene, camera );
+				effect.render( scene, camera );
 
 			}
 

+ 156 - 0
examples/webvr_panorama.html

@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webvr - panorama</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<meta name="viewmode" content="projection=stereo">
+		<style>
+			html, body {
+				background-color: #000;
+				margin: 0px;
+				padding: 0px;
+				overflow: hidden;
+			}
+		</style>
+
+	</head>
+	<body>
+		<script src="../build/three.min.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
+
+		<script src="js/WebVR.js"></script>
+		<script src="js/controls/VRControls.js"></script>
+		<script src="js/effects/VREffect.js"></script>
+
+		<script>
+
+		if ( WEBVR.isLatestAvailable() === false ) {
+
+			document.body.appendChild( WEBVR.getMessage() );
+
+		}
+
+		//
+
+		var camera;
+		var effect, controls;
+		var renderer;
+		var scene;
+
+		init();
+		animate();
+
+		function init() {
+
+			renderer = new THREE.WebGLRenderer();
+			renderer.setPixelRatio( window.devicePixelRatio );
+			renderer.setSize( window.innerWidth, window.innerHeight );
+			document.body.appendChild( renderer.domElement );
+
+			scene = new THREE.Scene();
+
+			camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 100 );
+			camera.layers.enable( 1 );
+
+			controls = new THREE.VRControls( camera );
+			effect = new THREE.VREffect( renderer );
+
+			if ( WEBVR.isAvailable() === true ) {
+
+				document.body.appendChild( WEBVR.getButton( effect ) );
+
+			}
+
+			var textures = getTexturesFromAtlasFile( "textures/cube/sun_temple_stripe_stereo.jpg", 12 );
+
+			var materials = [];
+
+			for ( var i = 0; i < 6; i ++ ) {
+
+				materials.push( new THREE.MeshBasicMaterial( { map: textures[ i ] } ) );
+
+			}
+
+			var skyBox = new THREE.Mesh( new THREE.CubeGeometry( 1, 1, 1 ), new THREE.MeshFaceMaterial( materials ) );
+			skyBox.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, - 1 ) );
+			skyBox.layers.set( 1 );
+			scene.add( skyBox );
+
+
+			var materialsR = [];
+
+			for ( var i = 6; i < 12; i ++ ) {
+
+				materialsR.push( new THREE.MeshBasicMaterial( { map: textures[ i ] } ) );
+
+			}
+
+			var skyBoxR = new THREE.Mesh( new THREE.CubeGeometry( 1, 1, 1 ), new THREE.MeshFaceMaterial( materialsR ) );
+			skyBoxR.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, - 1 ) );
+			skyBoxR.layers.set( 2 );
+			scene.add( skyBoxR );
+
+			window.addEventListener( 'resize', onWindowResize, false );
+
+		}
+
+		function getTexturesFromAtlasFile( atlasImgUrl, tilesNum ) {
+
+			var textures = [];
+
+			for ( var i = 0; i < tilesNum; i ++ ) {
+
+				textures[ i ] = new THREE.Texture();
+
+			}
+
+			var imageObj = new Image();
+
+			imageObj.onload = function() {
+
+				var canvas, context;
+				var tileWidth = imageObj.height;
+
+				for ( var i = 0; i < textures.length; i ++ ) {
+
+					canvas = document.createElement( 'canvas' );
+					context = canvas.getContext( '2d' );
+					canvas.height = tileWidth;
+					canvas.width = tileWidth;
+					context.drawImage( imageObj, tileWidth * i, 0, tileWidth, tileWidth, 0, 0, tileWidth, tileWidth );
+					textures[ i ].image = canvas
+					textures[ i ].needsUpdate = true;
+
+				}
+
+			};
+
+			imageObj.src = atlasImgUrl;
+
+			return textures;
+
+		}
+
+		function onWindowResize() {
+
+			camera.aspect = window.innerWidth / window.innerHeight;
+			camera.updateProjectionMatrix();
+
+			effect.setSize( window.innerWidth, window.innerHeight );
+
+		}
+
+		function animate() {
+
+			controls.update();
+
+			effect.render( scene, camera );
+
+			requestAnimationFrame( animate );
+
+		}
+
+		</script>
+	</body>
+</html>

+ 11 - 6
examples/webvr_rollercoaster.html

@@ -1,8 +1,9 @@
-<html>
+<!DOCTYPE html>
+<html lang="en">
 	<head>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
-		<title>Roller Coaster</title>
+		<title>three.js webvr - roller coaster</title>
 		<style>
 			body {
 				margin: 0px;
@@ -28,7 +29,7 @@
 
 		<script>
 
-			if ( WEBVR.isAvailable() === false ) {
+			if ( WEBVR.isLatestAvailable() === false ) {
 
 				document.body.appendChild( WEBVR.getMessage() );
 
@@ -173,10 +174,14 @@
 
 			//
 
-			var effect = new THREE.VREffect( renderer );
 			var controls = new THREE.VRControls( camera );
+			var effect = new THREE.VREffect( renderer );
+
+			if ( WEBVR.isAvailable() === true ) {
 
-			document.body.appendChild( WEBVR.getButton( effect ) );
+				document.body.appendChild( WEBVR.getButton( effect ) );
+
+			}
 
 			//
 
@@ -199,7 +204,7 @@
 			var velocity = 0;
 			var progress = 0;
 
-			var animate = function ( time ) {
+			function animate( time ) {
 
 				requestAnimationFrame( animate );
 

+ 0 - 227
examples/webvr_stereo_pano.html

@@ -1,227 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<title>three.js webgl - stereo pano demo</title>
-		<meta charset="utf-8">
-		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-		<meta name="viewmode" content="projection=stereo">
-		<style>
-			html, body {
-				background-color: #000;
-				margin: 0px;
-				padding: 0px;
-				overflow: hidden;
-			}
-
-			#VrMode {
-				position: absolute;
-				top: 0;
-				left: 0;
-				margin: 10px;
-				background: black;
-				border: 0;
-				color: #fff;
-				padding: 10px;
-				font-size: 1rem;
-			}
-
-		</style>
-
-	</head>
-	<body>
-		<button id="VrMode">VR MODE</button>
-		<script src="../build/three.min.js"></script>
-		<script src="js/controls/OrbitControls.js"></script>
-		<script src="js/controls/VRControls.js"></script>
-		<script src="js/effects/VREffect.js"></script>
-
-		<script>
-
-		var camera;
-		var vrControls;
-		var effect;
-		var renderer;
-		var scene;
-		var vrMode = false;
-
-		function init() {
-
-			renderer = new THREE.WebGLRenderer( { antialias: true } );
-			renderer.setPixelRatio( window.devicePixelRatio ? window.devicePixelRatio : 1 );
-			document.body.appendChild( renderer.domElement );
-
-			scene = new THREE.Scene();
-
-			camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 1, 10000 );
-			camera.position.z = 0.0001;
-			camera.layers.enable(1);
-
-			effect = new THREE.VREffect( renderer );
-
-
-			if ( navigator.getVRDisplays || navigator.getVRDevices ) {
-
-				vrControls = new THREE.VRControls( camera, vrFallback );
-
-			} else {
-
-				vrFallback();
-
-			}
-
-
-			var textures = getTexturesFromAtlasFile( "textures/cube/sun_temple_stripe_stereo.jpg", 12 );
-
-
-			var materials = [];
-
-			for ( var i = 0; i < 6; i ++ ) {
-
-					materials.push( new THREE.MeshBasicMaterial( { map: textures[i] } ) );
-
-			}
-
-			var skyBox = new THREE.Mesh( new THREE.CubeGeometry( 1024, 1024, 1024 ), new THREE.MeshFaceMaterial( materials ) );
-			skyBox.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, -1 ) );
-			skyBox.layers.set( 1 );
-			scene.add( skyBox );
-
-
-			var materialsR = [];
-
-			for ( var i = 6; i < 12; i ++ ) {
-
-					materialsR.push( new THREE.MeshBasicMaterial( { map: textures[i] } ) );
-
-			}
-
-			var skyBoxR = new THREE.Mesh( new THREE.CubeGeometry( 1024, 1024, 1024 ), new THREE.MeshFaceMaterial( materialsR ) );
-			skyBoxR.applyMatrix( new THREE.Matrix4().makeScale( 1, 1, -1 ) );
-			skyBoxR.layers.set( 2 );
-			scene.add( skyBoxR );
-
-			animate();
-			onWindowResize();
-
-		}
-
-		function getTexturesFromAtlasFile( atlasImgUrl, tilesNum ) {
-
-			var textures = [];
-
-			for ( var i=0; i < tilesNum; i++ ) {
-
-				textures[i] = new THREE.Texture();
-
-			}
-
-			var imageObj = new Image();
-
-			imageObj.onload = function() {
-
-				var canvas, context;
-				var tileWidth = imageObj.height;
-
-				for ( var i = 0; i < textures.length; i++ ) {
-
-					canvas = document.createElement( 'canvas' );
-					context = canvas.getContext( '2d' );
-					canvas.height = tileWidth;
-					canvas.width = tileWidth;
-					context.drawImage( imageObj, tileWidth * i, 0, tileWidth, tileWidth, 0, 0, tileWidth, tileWidth );
-					textures[i].image = canvas
-					textures[i].needsUpdate = true;
-
-				}
-
-			};
-
-			imageObj.src = atlasImgUrl;
-
-			return textures;
-
-		}
-
-		function vrFallback() {
-
-				vrControls = new THREE.OrbitControls( camera );
-				document.querySelector( '#VrMode' ).style.textDecoration = "line-through";
-
-		}
-
-		function requestFullscreen() {
-
-				effect.setFullScreen( true );
-
-		}
-
-		function onWindowResize() {
-
-			camera.aspect = window.innerWidth / window.innerHeight;
-			camera.updateProjectionMatrix();
-
-			if (vrMode) {
-
-				effect.setSize(window.innerWidth, window.innerHeight);
-
-			} else {
-
-				renderer.setSize(window.innerWidth, window.innerHeight);
-				
-			}
-
-		}
-
-		function onFullscreenChange(e) {
-
-			var fsElement = document.fullscreenElement ||
-				document.mozFullScreenElement ||
-				document.webkitFullscreenElement;
-
-			if ( !fsElement ) {
-
-				vrMode = false;
-
-			} else {
-
-				window.screen.orientation.lock( 'landscape' );
-
-			}
-
-		}
-
-		function animate() {
-
-			if ( vrMode ) {
-
-				effect.render( scene, camera );
-
-			} else {
-
-				renderer.setViewport( 0, 0, window.innerWidth, window.innerHeight );
-				renderer.render( scene, camera );
-
-			}
-
-			vrControls.update();
-			requestAnimationFrame( animate );
-
-		}
-
-		document.querySelector( '#VrMode' ).addEventListener( 'click', function() {
-
-			vrMode = vrMode ? false : true;
-			requestFullscreen();
-			onWindowResize();
-
-		} );
-
-		document.addEventListener( 'fullscreenchange', onFullscreenChange );
-		document.addEventListener( 'mozfullscreenchange', onFullscreenChange );
-		window.addEventListener( 'resize', onWindowResize, false );
-
-		init();
-
-		</script>
-	</body>
-</html>

+ 18 - 2
examples/webvr_video.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
 	<head>
-		<title>three.js webgl - webvr video</title>
+		<title>three.js webvr - video</title>
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
@@ -31,11 +31,21 @@
 		</div>
 
 		<script src="../build/three.min.js"></script>
+
+		<script src="js/WebVR.js"></script>
 		<script src="js/effects/VREffect.js"></script>
 		<script src="js/controls/VRControls.js"></script>
 
 		<script>
 
+			if ( WEBVR.isLatestAvailable() === false ) {
+
+				document.body.appendChild( WEBVR.getMessage() );
+
+			}
+
+			//
+
 			var camera, scene, renderer;
 			var video, texture;
 
@@ -50,7 +60,6 @@
 				container.addEventListener( 'click', function () {
 
 					video.play();
-					effect.setFullScreen( true );
 
 				} );
 
@@ -136,6 +145,13 @@
 				effect.scale = 0; // video doesn't need eye separation
 				effect.setSize( window.innerWidth, window.innerHeight );
 
+				if ( WEBVR.isAvailable() === true ) {
+
+					document.body.appendChild( WEBVR.getButton( effect ) );
+
+				}
+
+
 				//
 
 				window.addEventListener( 'resize', onWindowResize, false );

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "three.js",
-  "version": "0.74.0",
+  "version": "0.75.0",
   "description": "JavaScript 3D library",
   "main": "build/three.js",
   "directories": {

+ 1 - 2
src/Three.js

@@ -2,7 +2,7 @@
  * @author mrdoob / http://mrdoob.com/
  */
 
-var THREE = { REVISION: '75dev' };
+var THREE = { REVISION: '75' };
 
 //
 
@@ -156,7 +156,6 @@ THREE.AdditiveBlending = 2;
 THREE.SubtractiveBlending = 3;
 THREE.MultiplyBlending = 4;
 THREE.CustomBlending = 5;
-THREE.PremultipliedAlphaBlending = 6;
 
 // custom blending equations
 // (numbers start from 100 not to clash with other

+ 156 - 0
src/extras/geometries/LatheBufferGeometry.js

@@ -0,0 +1,156 @@
+/**
+ * @author Mugen87 / https://github.com/Mugen87
+ */
+
+ // points - to create a closed torus, one must use a set of points
+ //    like so: [ a, b, c, d, a ], see first is the same as last.
+ // segments - the number of circumference segments to create
+ // phiStart - the starting radian
+ // phiLength - the radian (0 to 2PI) range of the lathed section
+ //    2PI is a closed lathe, less than 2PI is a portion.
+
+THREE.LatheBufferGeometry = function ( points, segments, phiStart, phiLength ) {
+
+	THREE.BufferGeometry.call( this );
+
+	this.type = 'LatheBufferGeometry';
+
+	this.parameters = {
+		points: points,
+		segments: segments,
+		phiStart: phiStart,
+		phiLength: phiLength
+	};
+
+	segments = Math.floor( segments ) || 12;
+	phiStart = phiStart || 0;
+	phiLength = phiLength || Math.PI * 2;
+
+	// clamp phiLength so it's in range of [ 0, 2PI ]
+	phiLength = THREE.Math.clamp( phiLength, 0, Math.PI * 2 );
+
+	// these are used to calculate buffer length
+	var vertexCount = ( segments + 1 ) * points.length;
+	var indexCount = segments * points.length * 2 * 3;
+
+	// buffers
+	var indices = new THREE.BufferAttribute( new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount ) , 1 );
+	var vertices = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
+	var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 );
+
+	// helper variables
+	var index = 0, indexOffset = 0, base;
+	var inversePointLength = 1.0 / ( points.length - 1 );
+	var inverseSegments = 1.0 / segments;
+	var vertex = new THREE.Vector3();
+	var uv = new THREE.Vector2();
+	var i, j;
+
+	// generate vertices and uvs
+
+	for ( i = 0; i <= segments; i ++ ) {
+
+		var phi = phiStart + i * inverseSegments * phiLength;
+
+		var sin = Math.sin( phi );
+		var cos = Math.cos( phi );
+
+		for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
+
+			// vertex
+			vertex.x = points[ j ].x * sin;
+			vertex.y = points[ j ].y;
+			vertex.z = points[ j ].x * cos;
+			vertices.setXYZ( index, vertex.x, vertex.y, vertex.z );
+
+			// uv
+			uv.x = i / segments;
+			uv.y = j / ( points.length - 1 );
+			uvs.setXY( index, uv.x, uv.y );
+
+			// increase index
+			index ++;
+
+		}
+
+	}
+
+	// generate indices
+
+	for ( i = 0; i < segments; i ++ ) {
+
+		for ( j = 0; j < ( points.length - 1 ); j ++ ) {
+
+			base = j + i * points.length;
+
+			// indices
+			var a = base;
+			var b = base + points.length;
+			var c = base + points.length + 1;
+			var d = base + 1;
+
+			// face one
+			indices.setX( indexOffset, a ); indexOffset++;
+			indices.setX( indexOffset, b ); indexOffset++;
+			indices.setX( indexOffset, d ); indexOffset++;
+
+			// face two
+			indices.setX( indexOffset, b ); indexOffset++;
+			indices.setX( indexOffset, c ); indexOffset++;
+			indices.setX( indexOffset, d ); indexOffset++;
+
+		}
+
+	}
+
+	// build geometry
+
+	this.setIndex( indices );
+	this.addAttribute( 'position', vertices );
+	this.addAttribute( 'uv', uvs );
+
+	// generate normals
+
+	this.computeVertexNormals();
+
+	// if the geometry is closed, we need to average the normals along the seam.
+	// because the corresponding vertices are identical (but still have different UVs).
+
+	if( phiLength === Math.PI * 2 ) {
+
+		var normals = this.attributes.normal.array;
+		var n1 = new THREE.Vector3();
+		var n2 = new THREE.Vector3();
+		var n = new THREE.Vector3();
+
+		// this is the buffer offset for the last line of vertices
+		base = segments * points.length * 3;
+
+		for( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
+
+			// select the normal of the vertex in the first line
+			n1.x = normals[ j + 0 ];
+			n1.y = normals[ j + 1 ];
+			n1.z = normals[ j + 2 ];
+
+			// select the normal of the vertex in the last line
+			n2.x = normals[ base + j + 0 ];
+			n2.y = normals[ base + j + 1 ];
+			n2.z = normals[ base + j + 2 ];
+
+			// average normals
+			n.addVectors( n1, n2 ).normalize();
+
+			// assign the new values to both normals
+			normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
+			normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
+			normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
+
+		} // next row
+
+	}
+
+};
+
+THREE.LatheBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
+THREE.LatheBufferGeometry.prototype.constructor = THREE.LatheBufferGeometry;

+ 3 - 76
src/extras/geometries/LatheGeometry.js

@@ -8,8 +8,8 @@
 //    like so: [ a, b, c, d, a ], see first is the same as last.
 // segments - the number of circumference segments to create
 // phiStart - the starting radian
-// phiLength - the radian (0 to 2*PI) range of the lathed section
-//    2*pi is a closed lathe, less than 2PI is a portion.
+// phiLength - the radian (0 to 2PI) range of the lathed section
+//    2PI is a closed lathe, less than 2PI is a portion.
 
 THREE.LatheGeometry = function ( points, segments, phiStart, phiLength ) {
 
@@ -24,81 +24,8 @@ THREE.LatheGeometry = function ( points, segments, phiStart, phiLength ) {
 		phiLength: phiLength
 	};
 
-	segments = segments || 12;
-	phiStart = phiStart || 0;
-	phiLength = phiLength || 2 * Math.PI;
-
-	var inversePointLength = 1.0 / ( points.length - 1 );
-	var inverseSegments = 1.0 / segments;
-
-	for ( var i = 0, il = segments; i <= il; i ++ ) {
-
-		var phi = phiStart + i * inverseSegments * phiLength;
-
-		var sin = Math.sin( phi );
-		var cos = Math.cos( phi );
-
-		for ( var j = 0, jl = points.length; j < jl; j ++ ) {
-
-			var point = points[ j ];
-
-			var vertex = new THREE.Vector3();
-
-			vertex.x = point.x * sin;
-			vertex.y = point.y;
-			vertex.z = point.x * cos;
-
-			this.vertices.push( vertex );
-
-		}
-
-	}
-
-	var np = points.length;
-
-	for ( var i = 0, il = segments; i < il; i ++ ) {
-
-		for ( var j = 0, jl = points.length - 1; j < jl; j ++ ) {
-
-			var base = j + np * i;
-			var a = base;
-			var b = base + np;
-			var c = base + 1 + np;
-			var d = base + 1;
-
-			var u0 = i * inverseSegments;
-			var v0 = j * inversePointLength;
-			var u1 = u0 + inverseSegments;
-			var v1 = v0 + inversePointLength;
-
-			this.faces.push( new THREE.Face3( a, b, d ) );
-
-			this.faceVertexUvs[ 0 ].push( [
-
-				new THREE.Vector2( u0, v0 ),
-				new THREE.Vector2( u1, v0 ),
-				new THREE.Vector2( u0, v1 )
-
-			] );
-
-			this.faces.push( new THREE.Face3( b, c, d ) );
-
-			this.faceVertexUvs[ 0 ].push( [
-
-				new THREE.Vector2( u1, v0 ),
-				new THREE.Vector2( u1, v1 ),
-				new THREE.Vector2( u0, v1 )
-
-			] );
-
-
-		}
-
-	}
-
+	this.fromBufferGeometry( new THREE.LatheBufferGeometry( points, segments, phiStart, phiLength ) );
 	this.mergeVertices();
-	this.computeFaceNormals();
-	this.computeVertexNormals();
 
 };
 

+ 164 - 0
src/extras/geometries/TorusKnotBufferGeometry.js

@@ -0,0 +1,164 @@
+/**
+ * @author Mugen87 / https://github.com/Mugen87
+ *
+ * see: http://www.blackpawn.com/texts/pqtorus/
+ */
+THREE.TorusKnotBufferGeometry = function ( radius, tube, tubularSegments, radialSegments, p, q ) {
+
+	THREE.BufferGeometry.call( this );
+
+	this.type = 'TorusKnotBufferGeometry';
+
+	this.parameters = {
+		radius: radius,
+		tube: tube,
+		tubularSegments: tubularSegments,
+		radialSegments: radialSegments,
+		p: p,
+		q: q
+	};
+
+	radius = radius || 100;
+	tube = tube || 40;
+	tubularSegments = Math.floor( tubularSegments ) || 64;
+	radialSegments = Math.floor( radialSegments ) || 8;
+	p = p || 2;
+	q = q || 3;
+
+	// used to calculate buffer length
+	var vertexCount = ( ( radialSegments + 1 ) * ( tubularSegments + 1 ) );
+	var indexCount = radialSegments * tubularSegments * 2 * 3;
+
+	// buffers
+	var indices = new THREE.BufferAttribute( new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount ) , 1 );
+	var vertices = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
+	var normals = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
+	var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 );
+
+	// helper variables
+	var i, j, index = 0, indexOffset = 0;
+
+	var vertex = new THREE.Vector3();
+	var normal = new THREE.Vector3();
+	var uv = new THREE.Vector2();
+
+	var P1 = new THREE.Vector3();
+	var P2 = new THREE.Vector3();
+
+	var B = new THREE.Vector3();
+	var T = new THREE.Vector3();
+	var N = new THREE.Vector3();
+
+	// generate vertices, normals and uvs
+
+	for ( i = 0; i <= tubularSegments; ++ i ) {
+
+		// the radian "u" is used to calculate the position on the torus curve of the current tubular segement
+
+		var u = i / tubularSegments * p * Math.PI * 2;
+
+		// now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead.
+		// these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions
+
+		calculatePositionOnCurve( u, p, q, radius, P1 );
+		calculatePositionOnCurve( u + 0.01, p, q, radius, P2 );
+
+		// calculate orthonormal basis
+
+		T.subVectors( P2, P1 );
+		N.addVectors( P2, P1 );
+		B.crossVectors( T, N );
+		N.crossVectors( B, T );
+
+		// normalize B, N. T can be ignored, we don't use it
+
+		B.normalize();
+		N.normalize();
+
+		for ( j = 0; j <= radialSegments; ++ j ) {
+
+			// now calculate the vertices. they are nothing more than an extrusion of the torus curve.
+			// because we extrude a shape in the xy-plane, there is no need to calculate a z-value.
+
+			var v = j / radialSegments * Math.PI * 2;
+			var cx = - tube * Math.cos( v );
+			var cy = tube * Math.sin( v );
+
+			// now calculate the final vertex position.
+			// first we orient the extrusion with our basis vectos, then we add it to the current position on the curve
+
+			vertex.x = P1.x + ( cx * N.x + cy * B.x );
+			vertex.y = P1.y + ( cx * N.y + cy * B.y );
+			vertex.z = P1.z + ( cx * N.z + cy * B.z );
+
+			// vertex
+			vertices.setXYZ( index, vertex.x, vertex.y, vertex.z );
+
+			// normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal)
+			normal.subVectors( vertex, P1 ).normalize();
+			normals.setXYZ( index, normal.x, normal.y, normal.z );
+
+			// uv
+			uv.x = i / tubularSegments;
+			uv.y = j / radialSegments;
+			uvs.setXY( index, uv.x, uv.y );
+
+			// increase index
+			index ++;
+
+		}
+
+	}
+
+	// generate indices
+
+	for ( j = 1; j <= tubularSegments; j ++ ) {
+
+		for ( i = 1; i <= radialSegments; i ++ ) {
+
+			// indices
+			var a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 );
+			var b = ( radialSegments + 1 ) * j + ( i - 1 );
+			var c = ( radialSegments + 1 ) * j + i;
+			var d = ( radialSegments + 1 ) * ( j - 1 ) + i;
+
+			// face one
+			indices.setX( indexOffset, a ); indexOffset++;
+			indices.setX( indexOffset, b ); indexOffset++;
+			indices.setX( indexOffset, d ); indexOffset++;
+
+			// face two
+			indices.setX( indexOffset, b ); indexOffset++;
+			indices.setX( indexOffset, c ); indexOffset++;
+			indices.setX( indexOffset, d ); indexOffset++;
+
+		}
+
+	}
+
+	// build geometry
+
+	this.setIndex( indices );
+	this.addAttribute( 'position', vertices );
+	this.addAttribute( 'normal', normals );
+	this.addAttribute( 'uv', uvs );
+
+	// this function calculates the current position on the torus curve
+
+	function calculatePositionOnCurve( u, p, q, radius, position ) {
+
+		var cu = Math.cos( u );
+		var su = Math.sin( u );
+		var quOverP = q / p * u;
+		var cs = Math.cos( quOverP );
+
+		position.x = radius * ( 2 + cs ) * 0.5 * cu;
+		position.y = radius * ( 2 + cs ) * su * 0.5;
+		position.z = radius * Math.sin( quOverP ) * 0.5;
+
+	}
+
+};
+
+THREE.TorusKnotBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
+THREE.TorusKnotBufferGeometry.prototype.constructor = THREE.TorusKnotBufferGeometry;

+ 6 - 92
src/extras/geometries/TorusKnotGeometry.js

@@ -1,9 +1,8 @@
 /**
  * @author oosmoxiecode
- * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473
  */
 
-THREE.TorusKnotGeometry = function ( radius, tube, radialSegments, tubularSegments, p, q, heightScale ) {
+THREE.TorusKnotGeometry = function ( radius, tube, tubularSegments, radialSegments, p, q, heightScale ) {
 
 	THREE.Geometry.call( this );
 
@@ -12,101 +11,16 @@ THREE.TorusKnotGeometry = function ( radius, tube, radialSegments, tubularSegmen
 	this.parameters = {
 		radius: radius,
 		tube: tube,
-		radialSegments: radialSegments,
 		tubularSegments: tubularSegments,
+		radialSegments: radialSegments,
 		p: p,
-		q: q,
-		heightScale: heightScale
+		q: q
 	};
 
-	radius = radius || 100;
-	tube = tube || 40;
-	radialSegments = radialSegments || 64;
-	tubularSegments = tubularSegments || 8;
-	p = p || 2;
-	q = q || 3;
-	heightScale = heightScale || 1;
-
-	var grid = new Array( radialSegments );
-	var tang = new THREE.Vector3();
-	var n = new THREE.Vector3();
-	var bitan = new THREE.Vector3();
-
-	for ( var i = 0; i < radialSegments; ++ i ) {
-
-		grid[ i ] = new Array( tubularSegments );
-		var u = i / radialSegments * 2 * p * Math.PI;
-		var p1 = getPos( u, q, p, radius, heightScale );
-		var p2 = getPos( u + 0.01, q, p, radius, heightScale );
-		tang.subVectors( p2, p1 );
-		n.addVectors( p2, p1 );
-
-		bitan.crossVectors( tang, n );
-		n.crossVectors( bitan, tang );
-		bitan.normalize();
-		n.normalize();
-
-		for ( var j = 0; j < tubularSegments; ++ j ) {
-
-			var v = j / tubularSegments * 2 * Math.PI;
-			var cx = - tube * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
-			var cy = tube * Math.sin( v );
-
-			var pos = new THREE.Vector3();
-			pos.x = p1.x + cx * n.x + cy * bitan.x;
-			pos.y = p1.y + cx * n.y + cy * bitan.y;
-			pos.z = p1.z + cx * n.z + cy * bitan.z;
-
-			grid[ i ][ j ] = this.vertices.push( pos ) - 1;
-
-		}
-
-	}
-
-	for ( var i = 0; i < radialSegments; ++ i ) {
-
-		for ( var j = 0; j < tubularSegments; ++ j ) {
-
-			var ip = ( i + 1 ) % radialSegments;
-			var jp = ( j + 1 ) % tubularSegments;
-
-			var a = grid[ i ][ j ];
-			var b = grid[ ip ][ j ];
-			var c = grid[ ip ][ jp ];
-			var d = grid[ i ][ jp ];
-
-			var uva = new THREE.Vector2( i / radialSegments, j / tubularSegments );
-			var uvb = new THREE.Vector2( ( i + 1 ) / radialSegments, j / tubularSegments );
-			var uvc = new THREE.Vector2( ( i + 1 ) / radialSegments, ( j + 1 ) / tubularSegments );
-			var uvd = new THREE.Vector2( i / radialSegments, ( j + 1 ) / tubularSegments );
-
-			this.faces.push( new THREE.Face3( a, b, d ) );
-			this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
-
-			this.faces.push( new THREE.Face3( b, c, d ) );
-			this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
-
-		}
-
-	}
-
-	this.computeFaceNormals();
-	this.computeVertexNormals();
-
-	function getPos( u, in_q, in_p, radius, heightScale ) {
-
-		var cu = Math.cos( u );
-		var su = Math.sin( u );
-		var quOverP = in_q / in_p * u;
-		var cs = Math.cos( quOverP );
-
-		var tx = radius * ( 2 + cs ) * 0.5 * cu;
-		var ty = radius * ( 2 + cs ) * su * 0.5;
-		var tz = heightScale * radius * Math.sin( quOverP ) * 0.5;
-
-		return new THREE.Vector3( tx, ty, tz );
+	if( heightScale !== undefined ) console.warn( 'THREE.TorusKnotGeometry: heightScale has been deprecated. Use .scale( x, y, z ) instead.' );
 
-	}
+	this.fromBufferGeometry( new THREE.TorusKnotBufferGeometry( radius, tube, tubularSegments, radialSegments, p, q ) );
+	this.mergeVertices();
 
 };
 

+ 20 - 0
src/lights/PointLight.js

@@ -19,6 +19,26 @@ THREE.PointLight = function ( color, intensity, distance, decay ) {
 THREE.PointLight.prototype = Object.create( THREE.Light.prototype );
 THREE.PointLight.prototype.constructor = THREE.PointLight;
 
+Object.defineProperty( THREE.PointLight.prototype, "power", {
+
+	get: function () {
+
+		// intensity = power per solid angle.
+		// ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+		return this.intensity * 4 * Math.PI;
+
+	},
+
+	set: function ( power ) {
+
+		// intensity = power per solid angle.
+		// ref: equation (15) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+		this.intensity = power / ( 4 * Math.PI );
+
+	}
+
+} );
+
 THREE.PointLight.prototype.copy = function ( source ) {
 
 	THREE.Light.prototype.copy.call( this, source );

+ 20 - 0
src/lights/SpotLight.js

@@ -25,6 +25,26 @@ THREE.SpotLight = function ( color, intensity, distance, angle, penumbra, decay
 THREE.SpotLight.prototype = Object.create( THREE.Light.prototype );
 THREE.SpotLight.prototype.constructor = THREE.SpotLight;
 
+Object.defineProperty( THREE.SpotLight.prototype, "power", {
+
+	get: function () {
+
+		// intensity = power per solid angle.
+		// ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+		return this.intensity * Math.PI;
+
+	},
+
+	set: function ( power ) {
+
+		// intensity = power per solid angle.
+		// ref: equation (17) from http://www.frostbite.com/wp-content/uploads/2014/11/course_notes_moving_frostbite_to_pbr.pdf
+		this.intensity = power / Math.PI;
+
+	}
+
+} );
+
 THREE.SpotLight.prototype.copy = function ( source ) {
 
 	THREE.Light.prototype.copy.call( this, source );

+ 1 - 1
src/loaders/CubeTextureLoader.js

@@ -14,7 +14,7 @@ THREE.CubeTextureLoader.prototype = {
 
 	load: function ( urls, onLoad, onProgress, onError ) {
 
-		var texture = new THREE.CubeTexture( [] );
+		var texture = new THREE.CubeTexture();
 
 		var loader = new THREE.ImageLoader( this.manager );
 		loader.setCrossOrigin( this.crossOrigin );

+ 4 - 4
src/loaders/ObjectLoader.js

@@ -225,15 +225,15 @@ THREE.ObjectLoader.prototype = {
 						break;
 
 					case 'TorusKnotGeometry':
+					case 'TorusKnotBufferGeometry':
 
-						geometry = new THREE.TorusKnotGeometry(
+						geometry = new THREE[ data.type ](
 							data.radius,
 							data.tube,
-							data.radialSegments,
 							data.tubularSegments,
+							data.radialSegments,
 							data.p,
-							data.q,
-							data.heightScale
+							data.q
 						);
 
 						break;

+ 2 - 2
src/materials/LineBasicMaterial.js

@@ -10,7 +10,7 @@
  *  linecap: "round",
  *  linejoin: "round",
  *
- *  blending: THREE.PremultipliedAlphaBlending,
+ *  blending: THREE.NormalBlending,
  *  depthTest: <bool>,
  *  depthWrite: <bool>,
  *
@@ -32,7 +32,7 @@ THREE.LineBasicMaterial = function ( parameters ) {
 	this.linecap = 'round';
 	this.linejoin = 'round';
 
-	this.blending = THREE.PremultipliedAlphaBlending;
+	this.blending = THREE.NormalBlending;
 
 	this.vertexColors = THREE.NoColors;
 

+ 2 - 2
src/materials/LineDashedMaterial.js

@@ -11,7 +11,7 @@
  *  dashSize: <float>,
  *  gapSize: <float>,
  *
- *  blending: THREE.PremultipliedAlphaBlending,
+ *  blending: THREE.NormalBlending,
  *  depthTest: <bool>,
  *  depthWrite: <bool>,
  *
@@ -35,7 +35,7 @@ THREE.LineDashedMaterial = function ( parameters ) {
 	this.dashSize = 3;
 	this.gapSize = 1;
 
-	this.blending = THREE.PremultipliedAlphaBlending;
+	this.blending = THREE.NormalBlending;
 
 	this.vertexColors = THREE.NoColors;
 

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است