Browse Source

Merge branch 'dev' of https://github.com/mrdoob/three.js into dev

spite 11 years ago
parent
commit
5f234f8464
100 changed files with 4245 additions and 1553 deletions
  1. 2 3
      README.md
  2. 1 1
      bower.json
  3. 164 279
      build/three.js
  4. 218 232
      build/three.min.js
  5. 12 4
      docs/api/core/Geometry.html
  6. 0 8
      docs/api/core/Object3D.html
  7. 39 1
      docs/api/examples/Lut.html
  8. 1 1
      docs/api/extras/ImageUtils.html
  9. 18 18
      docs/api/extras/geometries/BoxGeometry.html
  10. 2 5
      docs/api/extras/helpers/GridHelper.html
  11. 1 1
      docs/api/loaders/ImageLoader.html
  12. 1 1
      docs/api/loaders/MaterialLoader.html
  13. 0 98
      docs/api/loaders/SceneLoader.html
  14. 1 1
      docs/api/materials/PointCloudMaterial.html
  15. 14 19
      docs/api/materials/ShaderMaterial.html
  16. 0 9
      docs/api/math/Box3.html
  17. 5 3
      docs/api/objects/Line.html
  18. 5 5
      docs/api/objects/Mesh.html
  19. 1 1
      docs/api/objects/PointCloud.html
  20. 59 17
      docs/api/renderers/webgl/WebGLProgram.html
  21. 2 3
      docs/list.js
  22. 3 3
      docs/manual/introduction/Creating-a-scene.html
  23. 2 3
      editor/index.html
  24. 8 2
      editor/js/Editor.js
  25. 12 1
      editor/js/Loader.js
  26. 3 1
      editor/js/Menubar.Edit.js
  27. 36 45
      editor/js/Sidebar.Animation.js
  28. 25 1
      editor/js/Sidebar.Material.js
  29. 34 11
      editor/js/Viewport.js
  30. 1 1
      examples/canvas_camera_orthographic2.html
  31. 1 1
      examples/canvas_geometry_birds.html
  32. 5 7
      examples/canvas_geometry_terrain.html
  33. 1 1
      examples/canvas_interactive_cubes.html
  34. 2 2
      examples/canvas_lines_colors.html
  35. 1 1
      examples/css3d_molecules.html
  36. 11 7
      examples/index.html
  37. 2 4
      examples/js/BlendCharacter.js
  38. 0 182
      examples/js/BufferGeometryUtils.js
  39. 1 1
      examples/js/Car.js
  40. 260 0
      examples/js/SkyShader.js
  41. 0 0
      examples/js/cameras/CombinedCamera.js
  42. 12 5
      examples/js/controls/OrbitControls.js
  43. 535 0
      examples/js/controls/OrthographicTrackballControls.js
  44. 1 1
      examples/js/controls/PathControls.js
  45. 53 41
      examples/js/controls/TrackballControls.js
  46. 3 3
      examples/js/controls/TransformControls.js
  47. 79 0
      examples/js/exporters/STLBinaryExporter.js
  48. 5 5
      examples/js/exporters/TypedGeometryExporter.js
  49. 600 0
      examples/js/libs/msgpack-js.js
  50. 36 0
      examples/js/libs/require.js
  51. 10 10
      examples/js/loaders/AWDLoader.js
  52. 84 60
      examples/js/loaders/ColladaLoader.js
  53. 347 0
      examples/js/loaders/DDSLoader.js
  54. 8 6
      examples/js/loaders/MTLLoader.js
  55. 16 62
      examples/js/loaders/PDBLoader.js
  56. 13 7
      examples/js/loaders/STLLoader.js
  57. 31 0
      examples/js/loaders/SVGLoader.js
  58. 23 8
      examples/js/loaders/SceneLoader.js
  59. 451 0
      examples/js/loaders/TGALoader.js
  60. 18 22
      examples/js/loaders/UTF8Loader.js
  61. 35 19
      examples/js/loaders/ctm/CTMLoader.js
  62. 408 78
      examples/js/math/Lut.js
  63. 1 7
      examples/js/renderers/CSS2DRenderer.js
  64. 0 6
      examples/js/renderers/CSS3DRenderer.js
  65. 9 16
      examples/js/shaders/FXAAShader.js
  66. 300 0
      examples/js/utils/GeometryUtils.js
  67. 0 2
      examples/js/utils/UVsUtils.js
  68. 3 3
      examples/js/wip/CircleTypedGeometry.js
  69. 3 3
      examples/js/wip/IndexedTypedGeometry.js
  70. 3 3
      examples/js/wip/PlaneTypedGeometry.js
  71. 6 6
      examples/js/wip/TypedGeometry.js
  72. 7 7
      examples/misc_controls_fly.html
  73. 11 0
      examples/misc_controls_orbit.html
  74. 1 1
      examples/misc_uv_tests.html
  75. 9 0
      examples/models/json/pressure.json
  76. 11 0
      examples/scenes/robo_pigeon.js
  77. BIN
      examples/scenes/robo_pigeon.pack
  78. BIN
      examples/textures/crate_color8.tga
  79. BIN
      examples/textures/crate_grey8.tga
  80. BIN
      examples/textures/pano.webm
  81. 3 6
      examples/webgl_animation_cloth.html
  82. 2 2
      examples/webgl_animation_skinning_blending.html
  83. 1 3
      examples/webgl_animation_skinning_morph.html
  84. 9 9
      examples/webgl_buffergeometry.html
  85. 40 50
      examples/webgl_buffergeometry_custom_attributes_particles.html
  86. 5 5
      examples/webgl_buffergeometry_lines.html
  87. 5 4
      examples/webgl_buffergeometry_lines_indexed.html
  88. 7 7
      examples/webgl_buffergeometry_particles.html
  89. 2 2
      examples/webgl_buffergeometry_rawshader.html
  90. 10 8
      examples/webgl_buffergeometry_uint.html
  91. 1 1
      examples/webgl_camera.html
  92. 0 4
      examples/webgl_camera_logarithmicdepthbuffer.html
  93. 1 1
      examples/webgl_custom_attributes_lines.html
  94. 7 8
      examples/webgl_custom_attributes_particles.html
  95. 4 4
      examples/webgl_custom_attributes_particles2.html
  96. 3 4
      examples/webgl_custom_attributes_particles3.html
  97. 32 35
      examples/webgl_effects_oculusrift.html
  98. 2 7
      examples/webgl_geometries2.html
  99. 24 25
      examples/webgl_geometry_colors_lookuptable.html
  100. 1 3
      examples/webgl_geometry_extrude_shapes.html

+ 2 - 3
README.md

@@ -37,8 +37,8 @@ This code creates a scene, a camera, and a geometric cube, and it adds the cube
 
 
 		geometry = new THREE.BoxGeometry( 200, 200, 200 );
 		geometry = new THREE.BoxGeometry( 200, 200, 200 );
 		material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
 		material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
+
 		mesh = new THREE.Mesh( geometry, material );
 		mesh = new THREE.Mesh( geometry, material );
-		
 		scene.add( mesh );
 		scene.add( mesh );
 
 
 		renderer = new THREE.CanvasRenderer();
 		renderer = new THREE.CanvasRenderer();
@@ -50,7 +50,6 @@ This code creates a scene, a camera, and a geometric cube, and it adds the cube
 
 
 	function animate() {
 	function animate() {
 
 
-		// note: three.js includes requestAnimationFrame shim
 		requestAnimationFrame( animate );
 		requestAnimationFrame( animate );
 
 
 		mesh.rotation.x += 0.01;
 		mesh.rotation.x += 0.01;
@@ -62,7 +61,7 @@ This code creates a scene, a camera, and a geometric cube, and it adds the cube
 
 
 </script>
 </script>
 ```
 ```
-If everything went well you should see [this](http://jsfiddle.net/Gy4w7/).
+If everything went well you should see [this](http://jsfiddle.net/Q7DLQ/).
 
 
 ### Change log ###
 ### Change log ###
 
 

+ 1 - 1
bower.json

@@ -1,6 +1,6 @@
 {
 {
 	"name": "three.js",
 	"name": "three.js",
-	"version": "0.0.66",
+	"version": "0.0.67",
 	"homepage": "http://threejs.org/",
 	"homepage": "http://threejs.org/",
 	"description": "JavaScript 3D library",
 	"description": "JavaScript 3D library",
 	"main": "build/three.js",
 	"main": "build/three.js",

File diff suppressed because it is too large
+ 164 - 279
build/three.js


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


+ 12 - 4
docs/api/core/Geometry.html

@@ -19,9 +19,11 @@
 
 
 		<code>var geometry = new THREE.Geometry();
 		<code>var geometry = new THREE.Geometry();
 
 
-		geometry.vertices.push( new THREE.Vector3( -10,  10, 0 ) );
-		geometry.vertices.push( new THREE.Vector3( -10, -10, 0 ) );
-		geometry.vertices.push( new THREE.Vector3(  10, -10, 0 ) );
+		geometry.vertices.push(
+			new THREE.Vector3( -10,  10, 0 ),
+			new THREE.Vector3( -10, -10, 0 ),
+			new THREE.Vector3(  10, -10, 0 )
+		);
 
 
 		geometry.faces.push( new THREE.Face3( 0, 1, 2 ) );
 		geometry.faces.push( new THREE.Face3( 0, 1, 2 ) );
 
 
@@ -59,7 +61,7 @@
 		<h3>.[page:Array colors]</h3>
 		<h3>.[page:Array colors]</h3>
 		<div>
 		<div>
 		Array of vertex [page:Color colors], matching number and order of vertices.<br />
 		Array of vertex [page:Color colors], matching number and order of vertices.<br />
-		Used in [page:ParticleSystem] and [page:Line].<br />
+		Used in [page:PointCloud] and [page:Line].<br />
 		[page:Mesh Meshes] use per-face-use-of-vertex colors embedded directly in faces.<br />
 		[page:Mesh Meshes] use per-face-use-of-vertex colors embedded directly in faces.<br />
 		To signal an update in this array, [page:Geometry Geometry.colorsNeedUpdate] needs to be set to true.
 		To signal an update in this array, [page:Geometry Geometry.colorsNeedUpdate] needs to be set to true.
 		</div>
 		</div>
@@ -223,12 +225,18 @@
 		
 		
 		<div>Neither bounding boxes or bounding spheres are computed by default. They need to be explicitly computed, otherwise they are *null*.</div>
 		<div>Neither bounding boxes or bounding spheres are computed by default. They need to be explicitly computed, otherwise they are *null*.</div>
 
 
+		<h3>.merge( [page:Geometry geometry], [page:Matrix4 matrix], [page:Integer materialIndexOffset] )</h3>
+		<div>Merge two geometries or geometry and geometry from object (using object's transform)</div>
+
 		<h3>.mergeVertices()</h3>
 		<h3>.mergeVertices()</h3>
 		<div>
 		<div>
 		Checks for duplicate vertices using hashmap.<br />
 		Checks for duplicate vertices using hashmap.<br />
 		Duplicated vertices are removed and faces' vertices are updated.
 		Duplicated vertices are removed and faces' vertices are updated.
 		</div>
 		</div>
 		
 		
+		<h3>.makeGroups()</h3>
+		<div>Geometry splitting</div>
+		
 		<h3>.clone()</h3>
 		<h3>.clone()</h3>
 		<div>
 		<div>
 		Creates a new clone of the Geometry.
 		Creates a new clone of the Geometry.

+ 0 - 8
docs/api/core/Object3D.html

@@ -218,14 +218,6 @@
 		Executes the callback on this object and all descendants. 
 		Executes the callback on this object and all descendants. 
 		</div>
 		</div>
 
 
-		<h3>.getDescendants( [page:Array array] )</h3>
-		<div>
-		array - optional argument that returns the the array with descendants.<br />
-		</div>
-		<div>
-		Searches whole subgraph recursively to add all objects in the array.
-		</div>
-
 		<h3>.updateMatrix()</h3>
 		<h3>.updateMatrix()</h3>
 		<div>
 		<div>
 		Updates local transform.
 		Updates local transform.

+ 39 - 1
docs/api/examples/Lut.html

@@ -40,6 +40,11 @@
 		<div>
 		<div>
 		The maximum value to be represented with the lookup table. Default is 1.
 		The maximum value to be represented with the lookup table. Default is 1.
 		</div>
 		</div>
+		
+		<h3>.[legend]</h3>
+		<div>
+		The legend of the lookup table.
+		</div>
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 
 
@@ -50,7 +55,40 @@
 		<div>
 		<div>
 		Copies given lut.
 		Copies given lut.
 		</div>
 		</div>
-
+		
+		<h3>.setLegendOn [parameters]</h3>
+		<div>
+		parameters - { layout: value, position: { x: value, y: value, z: value }, dimensions: { width: value, height: value } }
+		layout — Horizontal or vertical layout. Default is vertical.<br />
+		position — The position x,y,z of the legend.<br />
+		dimensions — The dimensions (width and height) of the legend.<br />
+		</div>
+		<div>
+		Sets this Lut with the legend on.
+		</div>
+		
+		<h3>.setLegendOff</h3>
+		<div>
+		</div>
+		<div>
+		Sets this Lut with the legend off.
+		</div>
+    
+    <h3>.setLegendLabels [parameters, callback]</h3>
+		<div>
+		parameters - { fontsize: value, fontface: value, title: value, um: value, ticks: value, decimal: value, notation: value }
+		fontsize — Font size to be used for labels.<br />
+		fontface — Font type to be used for labels.<br />
+		title — The title of the legend.<br />
+		um — The unit of measurements of the legend.<br />
+		ticks — The number of ticks to be displayed.<br />
+		decimal — The number of decimals to be used for legend values.<br />
+		notation — Legend notation: standard (default) or scientific.<br />
+		callback — An optional callback to be used to format the legend labels.<br />
+		</div>
+		<div>
+		Sets the labels of the legend of this Lut.
+		</div>
 
 
 		<h3>.setminV( [page:Float minV] ) [page:Lut this]</h3>
 		<h3>.setminV( [page:Float minV] ) [page:Lut this]</h3>
 		<div>
 		<div>

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

@@ -58,7 +58,7 @@
 		<h3>.loadTexture([page:String url], [page:UVMapping mapping], [page:Function onLoad], [page:Function onError]) [page:todo]</h3>
 		<h3>.loadTexture([page:String url], [page:UVMapping mapping], [page:Function onLoad], [page:Function onError]) [page:todo]</h3>
 		<div>
 		<div>
 		url -- the url of the texture<br />
 		url -- the url of the texture<br />
-		mapping -- Can be an instance of [page:UVMapping Three.UVMapping], [page:CubeReflectionMapping THREE.CubeReflectionMapping], [page:SphericalReflectionMapping THREE.SphericalReflectionMapping] or [page:SphericalRefractionMapping THREE.SphericalRefractionMapping]. Describes how the image is applied to the object.<br />Use undefined instead of null as a default value. See mapping property of [page:Texture texture] for more details.
+		mapping -- Can be an instance of [page:UVMapping THREE.UVMapping], [page:CubeReflectionMapping THREE.CubeReflectionMapping], [page:SphericalReflectionMapping THREE.SphericalReflectionMapping] or [page:SphericalRefractionMapping THREE.SphericalRefractionMapping]. Describes how the image is applied to the object.<br />Use undefined instead of null as a default value. See mapping property of [page:Texture texture] for more details.
 		onLoad -- callback function<br />
 		onLoad -- callback function<br />
 		onError -- callback function
 		onError -- callback function
 		</div>
 		</div>

+ 18 - 18
docs/api/extras/geometries/BoxGeometry.html

@@ -8,39 +8,39 @@
 	</head>
 	</head>
 	<body>
 	<body>
 		[page:Geometry] &rarr;
 		[page:Geometry] &rarr;
-		
+
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
-		<div class="desc">todo</div>
+		<div class="desc">BoxGeometry is the quadrilateral primitive geometry class. It is typically used for creating a cube or irregular quadrilateral of the dimensions provided with the 'width', 'height', and 'depth' constructor arguments.</div>
 
 
 		<h2>Example</h2>
 		<h2>Example</h2>
 
 
-		<code>todo</code>
+		<code>var geometry = new THREE.BoxGeometry( 1, 1, 1 );
+		var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
+		var cube = new THREE.Mesh( geometry, material );
+		scene.add( cube );
+		</code>
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>todo</h3>
-		<div></div>
-
-
-		<h2>Properties</h2>
-
-		<h3>todo</h3>
+		<h3>[name]([page:Float width], [page:Float height], [page:Float depth], [page:Integer widthSegments], [page:Integer heightSegments], [page:Integer depthSegments])</h3>
 		<div>
 		<div>
-		todo
-		</div> 
+		width — Width of the sides on the X axis.<br />
+		height — Height of the sides on the Y axis.<br />
+		depth — Depth of the sides on the Z axis.<br />
+		widthSegments — Optional. Number of segmented faces along the width of the sides. Default is 1.<br />
+		heightSegments — Optional. Number of segmented faces along the height of the sides. Default is 1.<br />
+		depthSegments — Optional. Number of segmented faces along the depth of the sides. Default is 1.
+		</div>
 
 
 
 
-		<h2>Methods</h2>
-		
+		<h2>Properties</h2>
 
 
-		<h3>todo</h3>
-		<div>todo</div>
 		<div>
 		<div>
-		todo
+		Each of the constructor parameters is accessible as a property of the same name. Any modification of these properties after instantiation does not change the geometry.
 		</div>
 		</div>
-		
+
 		<h2>Source</h2>
 		<h2>Source</h2>
 
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 2 - 5
docs/api/extras/helpers/GridHelper.html

@@ -18,11 +18,8 @@
 
 
 		<code>var size = 10;
 		<code>var size = 10;
 		var step = 1;
 		var step = 1;
-		var gridHelper = new THREE.GridHelper( size, step );
-		
-		gridHelper.position = new THREE.Vector3( 10, 10, 0 );
-		gridHelper.rotation = new THREE.Euler( 15, 0, 0 );
-		
+
+		var gridHelper = new THREE.GridHelper( size, step );		
 		scene.add( gridHelper );
 		scene.add( gridHelper );
 		</code>
 		</code>
 
 

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

@@ -14,7 +14,7 @@
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:LoadingManager manager)</h3>
+		<h3>[name]([page:LoadingManager manager])</h3>
         <div>
         <div>
         manager -- The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].
         manager -- The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].
         </div>
         </div>

+ 1 - 1
docs/api/loaders/MaterialLoader.html

@@ -14,7 +14,7 @@
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 
 
-		<h3>[name]([page:LoadingManager manager)</h3>
+		<h3>[name]([page:LoadingManager manager])</h3>
         <div>
         <div>
         manager -- The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].
         manager -- The [page:LoadingManager loadingManager] for the loader to use. Default is [page:LoadingManager THREE.DefaultLoadingManager].
         </div>
         </div>

+ 0 - 98
docs/api/loaders/SceneLoader.html

@@ -1,98 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-	<head>
-		<meta charset="utf-8" />
-		<script src="../../list.js"></script>
-		<script src="../../page.js"></script>
-		<link type="text/css" rel="stylesheet" href="../../page.css" />
-	</head>
-	<body>
-		<h1>[name]</h1>
-
-		<div class="desc">A loader for loading a complete scene out of a JSON file.</div>
-
-
-		<h2>Constructor</h2>
-
-
-		<h3>[name]()</h3>
-		<div>
-		todo
-		</div>
-		
-
-		<h2>Properties</h2>
-
-		<h3>.[page:Function onLoadStart]</h3>
-		<div>Will be called when load starts.</div>
-		<div>The default is a function with empty body.</div>
-
-		<h3>.[page:Function onLoadProgress]</h3>
-		<div>Will be called while load progresses.</div>
-		<div>The default is a function with empty body.</div>
-		
-		<h3>.[page:Function onLoadComplete]</h3>
-		<div>Will be called when each element in the scene completes loading.</div>
-		<div>The default is a function with empty body.</div>
-		
-		<h3>.[page:Function callbackSync]</h3>
-		<div>Will be called when load completes.</div>
-		<div>The default is a function with empty body.</div>
-		
-		<h3>.[page:Function callbackProgress]</h3>
-		<div>Will be called as load progresses.</div>
-		<div>The default is a function with empty body.</div>
-
-
-		<h3>.[page:object hierarchyHandlerMap]</h3>
-		<div>
-		todo
-		</div> 
-
-		<h3>.[page:object geometryHandlerMap]</h3>
-		<div>
-		todo
-		</div> 
-
-		<h2>Methods</h2>
-
-		<h3>.load( [page:String url], [page:Function callbackFinished] )</h3>
-		<div>
-		url — required<br />
-		callbackFinished — required. This function will be called with the loaded model as an instance of [page:Scene scene] when the load is completed.
-		</div>
-
-
-		<h3>.addHierarchyHandler([page:todo typeID], [page:todo loaderClass]) [page:todo]</h3>
-		<div>
-		typeID -- todo <br />
-		loaderClass -- todo
-		</div>
-		<div>
-		todo
-		</div>
-
-		<h3>.parse([page:todo json], [page:todo callbackFinished], [page:todo url]) [page:todo]</h3>
-		<div>
-		json -- todo <br />
-		callbackFinished -- todo <br />
-		url -- todo
-		</div>
-		<div>
-		todo
-		</div>
-
-		<h3>.addGeometryHandler([page:todo typeID], [page:todo loaderClass]) [page:todo]</h3>
-		<div>
-		typeID -- todo <br />
-		loaderClass -- todo
-		</div>
-		<div>
-		todo
-		</div>
-
-		<h2>Source</h2>
-
-		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
-	</body>
-</html>

+ 1 - 1
docs/api/materials/ParticleSystemMaterial.html → docs/api/materials/PointCloudMaterial.html

@@ -11,7 +11,7 @@
 
 
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
-		<div class="desc">The default material used by [page:ParticleSystem particle] systems.</div>
+		<div class="desc">The default material used by [page:PointCloud particle] systems.</div>
 
 
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>

+ 14 - 19
docs/api/materials/ShaderMaterial.html

@@ -14,36 +14,31 @@
 		<div class="desc">Material rendered with custom shaders</div>
 		<div class="desc">Material rendered with custom shaders</div>
 
 
 
 
-		<h2>Constructor</h2>
-
-
-		<h3>[name]([page:Object parameters])</h3>
-		<div>
-		parameters -- An object containing various parameters setting up shaders and their uniforms.
-		</div>
-		<div>
-		<br>
-		Example:<br>
-		<br>
-		uniforms = {
-			time: { type: "f", value: 1.0 },
-			resolution: { type: "v2", value: new THREE.Vector2() }
-		};
+		<h2>Example</h2>
 
 
-		material = new THREE.ShaderMaterial( {
+		<code>
+		var material = new THREE.ShaderMaterial( {
 
 
-			uniforms: uniforms,
+			uniforms: {
+				time: { type: "f", value: 1.0 },
+				resolution: { type: "v2", value: new THREE.Vector2() }
+			},
 			vertexShader: document.getElementById( 'vertexShader' ).textContent,
 			vertexShader: document.getElementById( 'vertexShader' ).textContent,
 			fragmentShader: document.getElementById( 'fragmentShader' ).textContent
 			fragmentShader: document.getElementById( 'fragmentShader' ).textContent
 
 
 		} );
 		} );
+		</code>
 
 
-		</div>
 
 
+		<h2>Constructor</h2>
 
 
-		<h2>Properties</h2>
+		<h3>[name]([page:Object parameters])</h3>
+		<div>
+		parameters -- An object containing various parameters setting up shaders and their uniforms.
+		</div>
 
 
 
 
+		<h2>Properties</h2>
 
 
 		<h3>.[page:object uniforms]</h3>
 		<h3>.[page:object uniforms]</h3>
 		<div>
 		<div>

+ 0 - 9
docs/api/math/Box3.html

@@ -51,15 +51,6 @@
 		Sets the lower and upper (x, y, z) boundaries of this box.
 		Sets the lower and upper (x, y, z) boundaries of this box.
 		</div>
 		</div>
 		
 		
-		<h3>.addPoint([page:Vector3 point]) [page:Box3 this]</h3>
-		<div>
-		point -- [page:Vector3] to add to the box <br />
-		</div>
-		<div>
-		If the *point* is outside the bounds of the box, the bounds are expanded
-		so that the point is within the bounds.
-		</div>
-		
 		<h3>.applyMatrix4([page:Matrix4 matrix]) [page:Box3 this]</h3>
 		<h3>.applyMatrix4([page:Matrix4 matrix]) [page:Box3 this]</h3>
 		<div>
 		<div>
 		matrix -- The [page:Matrix4] to apply
 		matrix -- The [page:Matrix4] to apply

+ 5 - 3
docs/api/objects/Line.html

@@ -22,9 +22,11 @@
 		});
 		});
 		
 		
 		var geometry = new THREE.Geometry();
 		var geometry = new THREE.Geometry();
-		geometry.vertices.push( new THREE.Vector3( -10, 0, 0 ) );
-		geometry.vertices.push( new THREE.Vector3( 0, 10, 0 ) );
-		geometry.vertices.push( new THREE.Vector3( 10, 0, 0 ) );
+		geometry.vertices.push(
+			new THREE.Vector3( -10, 0, 0 ),
+			new THREE.Vector3( 0, 10, 0 ),
+			new THREE.Vector3( 10, 0, 0 )
+		);
 
 
 		var line = new THREE.Line( geometry, material );
 		var line = new THREE.Line( geometry, material );
 		scene.add( line );
 		scene.add( line );

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

@@ -15,14 +15,14 @@
 
 
 
 
 		<h2>Example</h2>
 		<h2>Example</h2>
-		
-		<code>var geometry = new THREE.CubeGeometry( 1, 1, 1 );
+
+		<code>var geometry = new THREE.BoxGeometry( 1, 1, 1 );
 		var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
 		var material = new THREE.MeshBasicMaterial( { color: 0xffff00 } );
 		var mesh = new THREE.Mesh( geometry, material );
 		var mesh = new THREE.Mesh( geometry, material );
 		scene.add( mesh );
 		scene.add( mesh );
 		</code>
 		</code>
 
 
-				
+
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
 
 
 		<h3>[name]( [page:Geometry geometry], [page:Material material] )</h3>
 		<h3>[name]( [page:Geometry geometry], [page:Material material] )</h3>
@@ -53,8 +53,8 @@
 		<div>
 		<div>
 		Returns the index of a morph target defined by name.
 		Returns the index of a morph target defined by name.
 		</div>
 		</div>
-		
-		
+
+
 		<h3>.updateMorphTargets()</h3>
 		<h3>.updateMorphTargets()</h3>
 		<div>
 		<div>
 		Updates the morphtargets to have no influence on the object.
 		Updates the morphtargets to have no influence on the object.

+ 1 - 1
docs/api/objects/ParticleSystem.html → docs/api/objects/PointCloud.html

@@ -32,7 +32,7 @@
 
 
 		<h3>.[page:Material material]</h3>
 		<h3>.[page:Material material]</h3>
 
 
-		<div>An instance of [page:Material], defining the object's appearance. Default is a [page:ParticleSystemMaterial] with randomised colour.</div>
+		<div>An instance of [page:Material], defining the object's appearance. Default is a [page:PointCloudMaterial] with randomised colour.</div>
 
 
 		<h3>.[page:Boolean frustrumCulled]</h3>
 		<h3>.[page:Boolean frustrumCulled]</h3>
 		
 		

+ 59 - 17
docs/api/renderers/webgl/WebGLProgram.html

@@ -9,36 +9,78 @@
 	<body>
 	<body>
 		<h1>[name]</h1>
 		<h1>[name]</h1>
 
 
-		<div class="desc">todo</div>
+		<div class="desc">Constructor for the GLSL program sent to vertex and fragment shaders, including default uniforms and attributes.</div>
 
 
-		<h2>Example</h2>
+		<h2>Constructor</h2>
 
 
-		<code>todo</code>
+		<h3>[name]( [page:WebGLRenderer renderer], [page:Object code], [page:Material material], [page:Object parameters] )</h3>
+		<div>For parameters see [page:WebGLRenderer WebGLRenderer]</div>
+		<div>Standard defaults for vertex shader:<br/><br/>
+		uniform mat4 modelMatrix;<br/>
+		uniform mat4 modelViewMatrix;<br/>
+		uniform mat4 projectionMatrix;<br/>
+		uniform mat4 viewMatrix;<br/>
+		uniform mat3 normalMatrix;<br/>
+		uniform vec3 cameraPosition;<br/><br/>
+		attribute vec3 position;<br/>
+		attribute vec3 normal;<br/>
+		attribute vec2 uv;<br/>
+		attribute vec2 uv2;</div>
+		
+		<div>Conditional defaults for vertex shader:<br/><br/>
+		attribute vec3 color;<br/><br/>
+		attribute vec3 morphTarget0;<br/>
+		attribute vec3 morphTarget1;<br/>
+		attribute vec3 morphTarget2;<br/>
+		attribute vec3 morphTarget3;<br/><br/>
+		attribute vec3 morphNormal0;<br/>
+		attribute vec3 morphNormal1;<br/>
+		attribute vec3 morphNormal2;<br/>
+		attribute vec3 morphNormal3;<br/><br/>
+		attribute vec3 morphTarget4;<br/>
+		attribute vec3 morphTarget5;<br/>
+		attribute vec3 morphTarget6;<br/>
+		attribute vec3 morphTarget7;<br/><br/>
+		attribute vec4 skinIndex;<br/>
+		attribute vec4 skinWeight;</div>
+		
+		<div>Standard defaults for fragment shader:<br/><br/>
+		uniform mat4 viewMatrix;<br/>
+		uniform vec3 cameraPosition;</div>
+		
 
 
-		<h2>Constructor</h2>
+		<h2>Properties</h2>
 
 
+		<h3>.[page:Object uniforms]</h3>
+		<div></div> 
 
 
-		<h3>todo</h3>
-		<div></div>
+		<h3>.[page:Object attributes]</h3>
+		<div></div> 
 
 
+		<h3>.[page:Integer id]</h3>
+		<div></div> 
 
 
-		<h2>Properties</h2>
+		<h3>.[page:Object code]</h3>
+		<div></div> 
+
+		<h3>.[page:Integer usedTimes]</h3>
+		<div></div> 
+
+		<h3>.[page:Object program]</h3>
+		<div></div> 
 
 
-		<h3>todo</h3>
-		<div>
-		todo
-		</div> 
+		<h3>.[page:Object vertexShader]</h3>
+		<div></div> 
+
+		<h3>.[page:Object fragmentShader]</h3>
+		<div></div> 
 
 
 
 
 		<h2>Methods</h2>
 		<h2>Methods</h2>
 		
 		
+		<h3>none</h3>
+		<div></div>
 
 
-		<h3>todo</h3>
-		<div>todo</div>
-		<div>
-		todo
-		</div>
-		
 		<h2>Source</h2>
 		<h2>Source</h2>
 
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 2 - 3
docs/list.js

@@ -53,7 +53,6 @@ var list = {
 			[ "LoadingManager", "api/loaders/LoadingManager" ],
 			[ "LoadingManager", "api/loaders/LoadingManager" ],
 			[ "MaterialLoader", "api/loaders/MaterialLoader" ],
 			[ "MaterialLoader", "api/loaders/MaterialLoader" ],
 			[ "ObjectLoader", "api/loaders/ObjectLoader" ],
 			[ "ObjectLoader", "api/loaders/ObjectLoader" ],
-			[ "SceneLoader", "api/loaders/SceneLoader" ],
 			[ "TextureLoader", "api/loaders/TextureLoader" ],
 			[ "TextureLoader", "api/loaders/TextureLoader" ],
 			[ "XHRLoader", "api/loaders/XHRLoader" ]
 			[ "XHRLoader", "api/loaders/XHRLoader" ]
 		],
 		],
@@ -68,7 +67,7 @@ var list = {
 			[ "MeshLambertMaterial", "api/materials/MeshLambertMaterial" ],
 			[ "MeshLambertMaterial", "api/materials/MeshLambertMaterial" ],
 			[ "MeshNormalMaterial", "api/materials/MeshNormalMaterial" ],
 			[ "MeshNormalMaterial", "api/materials/MeshNormalMaterial" ],
 			[ "MeshPhongMaterial", "api/materials/MeshPhongMaterial" ],
 			[ "MeshPhongMaterial", "api/materials/MeshPhongMaterial" ],
-			[ "ParticleSystemMaterial", "api/materials/ParticleSystemMaterial" ],
+			[ "PointCloudMaterial", "api/materials/PointCloudMaterial" ],
 			[ "RawShaderMaterial", "api/materials/RawShaderMaterial" ],
 			[ "RawShaderMaterial", "api/materials/RawShaderMaterial" ],
 			[ "ShaderMaterial", "api/materials/ShaderMaterial" ],
 			[ "ShaderMaterial", "api/materials/ShaderMaterial" ],
 			[ "SpriteCanvasMaterial", "api/materials/SpriteCanvasMaterial" ],
 			[ "SpriteCanvasMaterial", "api/materials/SpriteCanvasMaterial" ],
@@ -102,7 +101,7 @@ var list = {
 			[ "LOD", "api/objects/LOD" ],
 			[ "LOD", "api/objects/LOD" ],
 			[ "Mesh", "api/objects/Mesh" ],
 			[ "Mesh", "api/objects/Mesh" ],
 			[ "MorphAnimMesh", "api/objects/MorphAnimMesh" ],
 			[ "MorphAnimMesh", "api/objects/MorphAnimMesh" ],
-			[ "ParticleSystem", "api/objects/ParticleSystem" ],
+			[ "PointCloud", "api/objects/PointCloud" ],
 			[ "SkinnedMesh", "api/objects/SkinnedMesh" ],
 			[ "SkinnedMesh", "api/objects/SkinnedMesh" ],
 			[ "Sprite", "api/objects/Sprite" ]
 			[ "Sprite", "api/objects/Sprite" ]
 		],
 		],

+ 3 - 3
docs/manual/introduction/Creating-a-scene.html

@@ -65,7 +65,7 @@
 		<div><em>"That's all good, but where's that cube you promised?"</em> Let's add it now.</div>
 		<div><em>"That's all good, but where's that cube you promised?"</em> Let's add it now.</div>
 
 
 		<code>
 		<code>
-		var geometry = new THREE.CubeGeometry(1,1,1);
+		var geometry = new THREE.BoxGeometry(1,1,1);
 		var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
 		var material = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
 		var cube = new THREE.Mesh( geometry, material );
 		var cube = new THREE.Mesh( geometry, material );
 		scene.add( cube );
 		scene.add( cube );
@@ -73,7 +73,7 @@
 		camera.position.z = 5;
 		camera.position.z = 5;
 		</code>
 		</code>
 
 
-		<div>To create a cube, we need a <strong>CubeGeometry</strong>. This is an object that contains all the points (<strong>vertices</strong>) and fill (<strong>faces</strong>) of the cube. We'll explore this more in the future.</div>
+		<div>To create a cube, we need a <strong>BoxGeometry</strong>. This is an object that contains all the points (<strong>vertices</strong>) and fill (<strong>faces</strong>) of the cube. We'll explore this more in the future.</div>
 
 
 		<div>In addition to the geometry, we need a material to color it. Three.js comes with several materials, but we'll stick to the <strong>MeshBasicMaterial</strong> for now. All materials take an object of properties which will be applied to them. To keep things very simple, we only supply a color attribute of <strong>0x00ff00</strong>, which is green. This works the same way that colors work in CSS or Photoshop (<strong>hex colors</strong>).</div>
 		<div>In addition to the geometry, we need a material to color it. Three.js comes with several materials, but we'll stick to the <strong>MeshBasicMaterial</strong> for now. All materials take an object of properties which will be applied to them. To keep things very simple, we only supply a color attribute of <strong>0x00ff00</strong>, which is green. This works the same way that colors work in CSS or Photoshop (<strong>hex colors</strong>).</div>
 
 
@@ -130,7 +130,7 @@
 					renderer.setSize(window.innerWidth, window.innerHeight);
 					renderer.setSize(window.innerWidth, window.innerHeight);
 					document.body.appendChild(renderer.domElement);
 					document.body.appendChild(renderer.domElement);
 
 
-					var geometry = new THREE.CubeGeometry(1,1,1);
+					var geometry = new THREE.BoxGeometry(1,1,1);
 					var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
 					var material = new THREE.MeshBasicMaterial({color: 0x00ff00});
 					var cube = new THREE.Mesh(geometry, material);
 					var cube = new THREE.Mesh(geometry, material);
 					scene.add(cube);
 					scene.add(cube);

+ 2 - 3
editor/index.html

@@ -18,6 +18,7 @@
 		<script src="../examples/js/loaders/ColladaLoader.js"></script>
 		<script src="../examples/js/loaders/ColladaLoader.js"></script>
 		<script src="../examples/js/loaders/OBJLoader.js"></script>
 		<script src="../examples/js/loaders/OBJLoader.js"></script>
 		<script src="../examples/js/loaders/PLYLoader.js"></script>
 		<script src="../examples/js/loaders/PLYLoader.js"></script>
+		<script src="../examples/js/loaders/SceneLoader.js"></script>
 		<script src="../examples/js/loaders/STLLoader.js"></script>
 		<script src="../examples/js/loaders/STLLoader.js"></script>
 		<script src="../examples/js/loaders/UTF8Loader.js"></script>
 		<script src="../examples/js/loaders/UTF8Loader.js"></script>
 		<script src="../examples/js/loaders/VRMLLoader.js"></script>
 		<script src="../examples/js/loaders/VRMLLoader.js"></script>
@@ -34,10 +35,8 @@
 
 
 		<!-- WIP -->
 		<!-- WIP -->
 
 
-		<script src="../examples/js/BufferGeometryUtils.js"></script>
-
 		<script src="../examples/js/exporters/BufferGeometryExporter.js"></script>
 		<script src="../examples/js/exporters/BufferGeometryExporter.js"></script>
-		<script src="../examples/js/exporters/Geometry2Exporter.js"></script>
+		<script src="../examples/js/exporters/TypedGeometryExporter.js"></script>
 		<script src="../examples/js/exporters/GeometryExporter.js"></script>
 		<script src="../examples/js/exporters/GeometryExporter.js"></script>
 		<script src="../examples/js/exporters/MaterialExporter.js"></script>
 		<script src="../examples/js/exporters/MaterialExporter.js"></script>
 		<script src="../examples/js/exporters/ObjectExporter.js"></script>
 		<script src="../examples/js/exporters/ObjectExporter.js"></script>

+ 8 - 2
editor/js/Editor.js

@@ -6,7 +6,8 @@ var Editor = function () {
 
 
 		// actions
 		// actions
 
 
-		playAnimations: new SIGNALS.Signal(),
+		playAnimation: new SIGNALS.Signal(),
+		stopAnimation: new SIGNALS.Signal(),
 
 
 		// notifications
 		// notifications
 
 
@@ -197,6 +198,10 @@ Editor.prototype = {
 
 
 				helper = new THREE.HemisphereLightHelper( object, 10 );
 				helper = new THREE.HemisphereLightHelper( object, 10 );
 
 
+			} else if ( object instanceof THREE.SkinnedMesh ) {
+
+				helper = new THREE.SkeletonHelper( object );
+
 			} else {
 			} else {
 
 
 				// no helper for this object type
 				// no helper for this object type
@@ -321,6 +326,7 @@ Editor.prototype = {
 			'HemisphereLight': THREE.HemisphereLight,
 			'HemisphereLight': THREE.HemisphereLight,
 			'PointLight': THREE.PointLight,
 			'PointLight': THREE.PointLight,
 			'SpotLight': THREE.SpotLight,
 			'SpotLight': THREE.SpotLight,
+			'SkinnedMesh': THREE.SkinnedMesh,
 			'Mesh': THREE.Mesh,
 			'Mesh': THREE.Mesh,
 			'Sprite': THREE.Sprite,
 			'Sprite': THREE.Sprite,
 			'Object3D': THREE.Object3D
 			'Object3D': THREE.Object3D
@@ -381,7 +387,7 @@ Editor.prototype = {
 			'MeshLambertMaterial': THREE.MeshLambertMaterial,
 			'MeshLambertMaterial': THREE.MeshLambertMaterial,
 			'MeshNormalMaterial': THREE.MeshNormalMaterial,
 			'MeshNormalMaterial': THREE.MeshNormalMaterial,
 			'MeshPhongMaterial': THREE.MeshPhongMaterial,
 			'MeshPhongMaterial': THREE.MeshPhongMaterial,
-			'ParticleSystemMaterial': THREE.ParticleSystemMaterial,
+			'PointCloudMaterial': THREE.PointCloudMaterial,
 			'ShaderMaterial': THREE.ShaderMaterial,
 			'ShaderMaterial': THREE.ShaderMaterial,
 			'SpriteCanvasMaterial': THREE.SpriteCanvasMaterial,
 			'SpriteCanvasMaterial': THREE.SpriteCanvasMaterial,
 			'SpriteMaterial': THREE.SpriteMaterial,
 			'SpriteMaterial': THREE.SpriteMaterial,

+ 12 - 1
editor/js/Loader.js

@@ -339,7 +339,18 @@ var Loader = function ( editor ) {
 			geometry.sourceType = "ascii";
 			geometry.sourceType = "ascii";
 			geometry.sourceFile = file.name;
 			geometry.sourceFile = file.name;
 
 
-			var mesh = new THREE.Mesh( geometry, material );
+			var mesh;
+
+			if ( geometry.animation && geometry.animation.hierarchy ) {
+
+				mesh = new THREE.SkinnedMesh( geometry, material );
+
+			} else {
+
+				mesh = new THREE.Mesh( geometry, material );
+
+			}
+
 			mesh.name = filename;
 			mesh.name = filename;
 
 
 			editor.addObject( mesh );
 			editor.addObject( mesh );

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

@@ -40,6 +40,7 @@ Menubar.Edit = function ( editor ) {
 		// convert to BufferGeometry
 		// convert to BufferGeometry
 		
 		
 		var object = editor.selected;
 		var object = editor.selected;
+
 		if ( object.geometry instanceof THREE.Geometry ) {
 		if ( object.geometry instanceof THREE.Geometry ) {
 
 
 			if ( object.parent === undefined ) return; // avoid flattening the camera or scene
 			if ( object.parent === undefined ) return; // avoid flattening the camera or scene
@@ -48,9 +49,10 @@ Menubar.Edit = function ( editor ) {
 
 
 			delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
 			delete object.__webglInit; // TODO: Remove hack (WebGLRenderer refactoring)
 
 
-			object.geometry = THREE.BufferGeometryUtils.fromGeometry( object.geometry );
+			object.geometry = new THREE.BufferGeometry().fromGeometry( object.geometry );
 
 
 			editor.signals.objectChanged.dispatch( object );
 			editor.signals.objectChanged.dispatch( object );
+
 		}
 		}
 
 
 	}
 	}

+ 36 - 45
editor/js/Sidebar.Animation.js

@@ -5,85 +5,76 @@ Sidebar.Animation = function ( editor ) {
 	var options = {};
 	var options = {};
 	var possibleAnimations = {};
 	var possibleAnimations = {};
 
 
-	var container = new UI.Panel();
+	var container = new UI.CollapsiblePanel();
 	container.setDisplay( 'none' );
 	container.setDisplay( 'none' );
 
 
-	container.add( new UI.Text( 'Animation' ) );
-	container.add( new UI.Break(), new UI.Break() );
-
-	var AnimationsRow = new UI.Panel();
-	var Animations = new UI.Select().setOptions( options ).setWidth( '130px' ).setColor( '#444' ).setFontSize( '12px' );
-	AnimationsRow.add( new UI.Text( 'animations' ).setWidth( '90px' ) );
-	AnimationsRow.add( Animations );
-	container.add( AnimationsRow );
+	container.addStatic( new UI.Text( 'ANIMATION' ) );
 	container.add( new UI.Break() );
 	container.add( new UI.Break() );
 
 
-	var PlayRow = new UI.Panel();
-	var playButton = new UI.Button().setLabel("Play").onClick(play);
-	PlayRow.add( playButton );
-	container.add( PlayRow );
-	container.add( new UI.Break() );
+	var animationsRow = new UI.Panel();
+	container.add( animationsRow );
 
 
-	function play() {
+	var animations = {};
 
 
-		var value = Animations.getValue();
+	signals.objectAdded.add( function ( object ) {
 
 
-		if ( possibleAnimations[ value ] ) {
+		object.traverse( function ( child ) {
 
 
-			var anims = possibleAnimations[value]
+			if ( child instanceof THREE.SkinnedMesh ) {
 
 
-			for ( var i = 0; i < anims.length; i ++ ) {
+				var material = child.material;
 
 
-				anims[ i ].play();
+				if ( material instanceof THREE.MeshFaceMaterial ) {
 
 
-			}
+					for ( var i = 0; i < material.materials.length; i ++ ) {
 
 
-			signals.playAnimations.dispatch( anims );
+						material.materials[ i ].skinning = true;
 
 
-		};
+					}
 
 
-	}
+				} else {
 
 
-	signals.objectAdded.add( function ( object ) {
+					child.material.skinning = true;
 
 
-		if ( object instanceof THREE.Mesh ) {
+				}
 
 
-			if ( object.geometry && object.geometry.animation ) {
+				animations[ child.id ] = new THREE.Animation( child, child.geometry.animation );
 
 
-				var name = object.geometry.animation.name;
-				options[name] = name
+			}
 
 
-				Animations.setOptions( options );
+		} );
 
 
-				THREE.AnimationHandler.add( object.geometry.animation );
+	} );
 
 
-				var animation = new THREE.Animation( object, name, THREE.AnimationHandler.CATMULLROM );
+	signals.objectSelected.add( function ( object ) {
 
 
-				if ( possibleAnimations[ name ] ){
+		container.setDisplay( 'none' );
 
 
-					possibleAnimations[ name ].push( animation );
+		if ( object instanceof THREE.SkinnedMesh ) {
 
 
-				} else {
+			animationsRow.clear();
 
 
-					possibleAnimations[ name ] = [ animation ];
+			var animation = animations[ object.id ];
 
 
-				}
+			var playButton = new UI.Button().setLabel( 'Play' ).onClick( function () {
 
 
-			}
+				animation.play();
 
 
-		}
+				signals.playAnimation.dispatch( animation );
 
 
-	} );
+			} );
+			animationsRow.add( playButton );
 
 
-	signals.objectSelected.add( function ( object ) {
+			var pauseButton = new UI.Button().setLabel( 'Stop' ).onClick( function () {
 
 
-		if ( object && object.geometry && object.geometry.animation ) {
+				animation.stop();
 
 
-			container.setDisplay( 'block' );
+				signals.stopAnimation.dispatch( animation );
 
 
-		} else {
+			} );
+			animationsRow.add( pauseButton );
 
 
-			container.setDisplay( 'none' );
+			container.setDisplay( 'block' );
 
 
 		}
 		}
 
 

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

@@ -12,7 +12,7 @@ Sidebar.Material = function ( editor ) {
 		'MeshLambertMaterial': THREE.MeshLambertMaterial,
 		'MeshLambertMaterial': THREE.MeshLambertMaterial,
 		'MeshNormalMaterial': THREE.MeshNormalMaterial,
 		'MeshNormalMaterial': THREE.MeshNormalMaterial,
 		'MeshPhongMaterial': THREE.MeshPhongMaterial,
 		'MeshPhongMaterial': THREE.MeshPhongMaterial,
-		'ParticleSystemMaterial': THREE.ParticleSystemMaterial,
+		'PointCloudMaterial': THREE.PointCloudMaterial,
 		'ShaderMaterial': THREE.ShaderMaterial,
 		'ShaderMaterial': THREE.ShaderMaterial,
 		'SpriteMaterial': THREE.SpriteMaterial,
 		'SpriteMaterial': THREE.SpriteMaterial,
 		'SpriteCanvasMaterial': THREE.SpriteCanvasMaterial,
 		'SpriteCanvasMaterial': THREE.SpriteCanvasMaterial,
@@ -147,6 +147,17 @@ Sidebar.Material = function ( editor ) {
 	container.add( materialVertexColorsRow );
 	container.add( materialVertexColorsRow );
 
 
 
 
+	// skinning
+
+	var materialSkinningRow = new UI.Panel();
+	var materialSkinning = new UI.Checkbox( false ).onChange( update );
+
+	materialSkinningRow.add( new UI.Text( 'Skinning' ).setWidth( '90px' ) );
+	materialSkinningRow.add( materialSkinning );
+
+	container.add( materialSkinningRow );
+
+
 	// map
 	// map
 
 
 	var materialMapRow = new UI.Panel();
 	var materialMapRow = new UI.Panel();
@@ -370,6 +381,12 @@ Sidebar.Material = function ( editor ) {
 
 
 			}
 			}
 
 
+			if ( material.skinning !== undefined ) {
+
+				material.skinning = materialSkinning.getValue();
+
+			}
+
 			if ( material.map !== undefined ) {
 			if ( material.map !== undefined ) {
 
 
 				var mapEnabled = materialMapEnabled.getValue() === true;
 				var mapEnabled = materialMapEnabled.getValue() === true;
@@ -558,6 +575,7 @@ Sidebar.Material = function ( editor ) {
 			'specular': materialSpecularRow,
 			'specular': materialSpecularRow,
 			'shininess': materialShininessRow,
 			'shininess': materialShininessRow,
 			'vertexColors': materialVertexColorsRow,
 			'vertexColors': materialVertexColorsRow,
+			'skinning': materialSkinningRow,
 			'map': materialMapRow,
 			'map': materialMapRow,
 			'lightMap': materialLightMapRow,
 			'lightMap': materialLightMapRow,
 			'bumpMap': materialBumpMapRow,
 			'bumpMap': materialBumpMapRow,
@@ -641,6 +659,12 @@ Sidebar.Material = function ( editor ) {
 
 
 			}
 			}
 
 
+			if ( material.skinning !== undefined ) {
+
+				materialSkinning.setValue( material.skinning );
+
+			}
+
 			if ( material.map !== undefined ) {
 			if ( material.map !== undefined ) {
 
 
 				materialMapEnabled.setValue( material.map !== null );
 				materialMapEnabled.setValue( material.map !== null );

+ 34 - 11
editor/js/Viewport.js

@@ -429,22 +429,23 @@ var Viewport = function ( editor ) {
 
 
 	} );
 	} );
 
 
-	signals.playAnimations.add( function (animations) {
-		
-		function animate() {
+	var animations = [];
 
 
-			requestAnimationFrame( animate );
-			
-			for ( var i = 0; i < animations.length ; i ++ ) {
+	signals.playAnimation.add( function ( animation ) {
 
 
-				animations[i].update(0.016);
+		animations.push( animation );
 
 
-			} 
+	} );
 
 
-			render();
-		}
+	signals.stopAnimation.add( function ( animation ) {
+
+		var index = animations.indexOf( animation );
+
+		if ( index !== -1 ) {
 
 
-		animate();
+			animations.splice( index, 1 );
+
+		}
 
 
 	} );
 	} );
 
 
@@ -563,6 +564,28 @@ var Viewport = function ( editor ) {
 
 
 		requestAnimationFrame( animate );
 		requestAnimationFrame( animate );
 
 
+		// animations
+
+		if ( THREE.AnimationHandler.animations.length > 0 ) {
+
+			THREE.AnimationHandler.update( 0.016 );
+
+			for ( var i = 0, l = sceneHelpers.children.length; i < l; i ++ ) {
+
+				var helper = sceneHelpers.children[ i ];
+
+				if ( helper instanceof THREE.SkeletonHelper ) {
+
+					helper.update();
+
+				}
+
+			}
+
+			render();
+
+		}
+
 	}
 	}
 
 
 	function render() {
 	function render() {

+ 1 - 1
examples/canvas_camera_orthographic2.html

@@ -21,7 +21,7 @@
 	<body>
 	<body>
 
 
 		<script src="../build/three.min.js"></script>
 		<script src="../build/three.min.js"></script>
-		<script src="../src/extras/cameras/CombinedCamera.js"></script>
+		<script src="js/cameras/CombinedCamera.js"></script>
 
 
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 

+ 1 - 1
examples/canvas_geometry_birds.html

@@ -359,7 +359,6 @@
 
 
 					bird = birds[ i ] = new THREE.Mesh( new Bird(), new THREE.MeshBasicMaterial( { color:Math.random() * 0xffffff, side: THREE.DoubleSide } ) );
 					bird = birds[ i ] = new THREE.Mesh( new Bird(), new THREE.MeshBasicMaterial( { color:Math.random() * 0xffffff, side: THREE.DoubleSide } ) );
 					bird.phase = Math.floor( Math.random() * 62.83 );
 					bird.phase = Math.floor( Math.random() * 62.83 );
-					bird.position = boids[ i ].position;
 					scene.add( bird );
 					scene.add( bird );
 
 
 
 
@@ -429,6 +428,7 @@
 					boid.run( boids );
 					boid.run( boids );
 
 
 					bird = birds[ i ];
 					bird = birds[ i ];
+					bird.position.copy( boids[ i ].position );
 
 
 					color = bird.material.color;
 					color = bird.material.color;
 					color.r = color.g = color.b = ( 500 - bird.position.z ) / 1000;
 					color.r = color.g = color.b = ( 500 - bird.position.z ) / 1000;

+ 5 - 7
examples/canvas_geometry_terrain.html

@@ -72,19 +72,17 @@
 
 
 				var quality = 16, step = 1024 / quality;
 				var quality = 16, step = 1024 / quality;
 
 
-				var plane = new THREE.PlaneGeometry( 2000, 2000, quality - 1, quality - 1 );
-				plane.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
+				var geometry = new THREE.PlaneGeometry( 2000, 2000, quality - 1, quality - 1 );
+				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
 
 
-				var editor = new THREE.GeometryEditor( plane );
-
-				for ( var i = 0, l = editor.vertices.length; i < l; i ++ ) {
+				for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
 
 
 					var x = i % quality, y = Math.floor( i / quality );
 					var x = i % quality, y = Math.floor( i / quality );
-					editor.vertices[ i ].y = data[ ( x * step ) + ( y * step ) * 1024 ] * 2 - 128;
+					geometry.vertices[ i ].y = data[ ( x * step ) + ( y * step ) * 1024 ] * 2 - 128;
 
 
 				}
 				}
 
 
-				mesh = new THREE.Mesh( plane, material );
+				mesh = new THREE.Mesh( geometry, material );
 				scene.add( mesh );
 				scene.add( mesh );
 
 
 				renderer = new THREE.CanvasRenderer();
 				renderer = new THREE.CanvasRenderer();

+ 1 - 1
examples/canvas_interactive_cubes.html

@@ -131,7 +131,7 @@
 					intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
 					intersects[ 0 ].object.material.color.setHex( Math.random() * 0xffffff );
 
 
 					var particle = new THREE.Sprite( particleMaterial );
 					var particle = new THREE.Sprite( particleMaterial );
-					particle.position = intersects[ 0 ].point;
+					particle.position.copy( intersects[ 0 ].point );
 					particle.scale.x = particle.scale.y = 16;
 					particle.scale.x = particle.scale.y = 16;
 					scene.add( particle );
 					scene.add( particle );
 
 

+ 2 - 2
examples/canvas_lines_colors.html

@@ -1,7 +1,7 @@
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html lang="en">
 <html lang="en">
 	<head>
 	<head>
-		<title>three.js webgl - lines - cubes - colors</title>
+		<title>three.js canvas - lines - colors</title>
 		<meta charset="utf-8">
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
 		<style>
@@ -40,7 +40,7 @@
 	<body>
 	<body>
 
 
 		<div id="info">
 		<div id="info">
-			<a href="http://threejs.org" target="_blank">three.js</a> - color lines WebGL demo
+			<a href="http://threejs.org" target="_blank">three.js</a> - color lines
 			[<a href="http://en.wikipedia.org/wiki/Hilbert_curve">Hilbert curve</a> thanks to <a href="http://www.openprocessing.org/visuals/?visualID=15599">Thomas Diewald</a>]
 			[<a href="http://en.wikipedia.org/wiki/Hilbert_curve">Hilbert curve</a> thanks to <a href="http://www.openprocessing.org/visuals/?visualID=15599">Thomas Diewald</a>]
 		</div>
 		</div>
 
 

+ 1 - 1
examples/css3d_molecules.html

@@ -346,7 +346,7 @@
 
 
 				loader.load( url, function ( geometry, geometryBonds ) {
 				loader.load( url, function ( geometry, geometryBonds ) {
 
 
-					var offset = THREE.GeometryUtils.center( geometry );
+					var offset = geometry.center();
 					geometryBonds.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
 					geometryBonds.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
 
 
 					for ( var i = 0; i < geometry.vertices.length; i ++ ) {
 					for ( var i = 0; i < geometry.vertices.length; i ++ ) {

+ 11 - 7
examples/index.html

@@ -75,7 +75,7 @@
 
 
 			#button {
 			#button {
 				position: fixed;
 				position: fixed;
-				bottom: 20px;
+				top: 20px;
 				right: 20px;
 				right: 20px;
 				padding: 8px;
 				padding: 8px;
 				color: #fff;
 				color: #fff;
@@ -157,6 +157,8 @@
 				"webgl_interactive_cubes",
 				"webgl_interactive_cubes",
 				"webgl_interactive_cubes_gpu",
 				"webgl_interactive_cubes_gpu",
 				"webgl_interactive_draggablecubes",
 				"webgl_interactive_draggablecubes",
+				"webgl_interactive_particles",
+				"webgl_interactive_raycasting_pointcloud",
 				"webgl_interactive_voxelpainter",
 				"webgl_interactive_voxelpainter",
 				"webgl_kinect",
 				"webgl_kinect",
 				"webgl_lensflares",
 				"webgl_lensflares",
@@ -169,6 +171,7 @@
 				"webgl_lines_sphere",
 				"webgl_lines_sphere",
 				"webgl_lines_splines",
 				"webgl_lines_splines",
 				"webgl_loader_assimp2json",
 				"webgl_loader_assimp2json",
+				"webgl_loader_awd",
 				"webgl_loader_collada",
 				"webgl_loader_collada",
 				"webgl_loader_collada_keyframe",
 				"webgl_loader_collada_keyframe",
 				"webgl_loader_collada_skinning",
 				"webgl_loader_collada_skinning",
@@ -177,12 +180,11 @@
 				"webgl_loader_gltf",
 				"webgl_loader_gltf",
 				"webgl_loader_json_blender",
 				"webgl_loader_json_blender",
 				"webgl_loader_json_objconverter",
 				"webgl_loader_json_objconverter",
+				"webgl_loader_msgpack",
 				"webgl_loader_obj",
 				"webgl_loader_obj",
 				"webgl_loader_obj_mtl",
 				"webgl_loader_obj_mtl",
-				"webgl_loader_pdb",	
+				"webgl_loader_pdb",
 				"webgl_loader_ply",
 				"webgl_loader_ply",
-				"webgl_loader_scene",
-				"webgl_loader_scene_blender",
 				"webgl_loader_stl",
 				"webgl_loader_stl",
 				"webgl_loader_utf8",
 				"webgl_loader_utf8",
 				"webgl_loader_vrml",
 				"webgl_loader_vrml",
@@ -250,10 +252,12 @@
 				"webgl_rtt",
 				"webgl_rtt",
 				"webgl_sandbox",
 				"webgl_sandbox",
 				"webgl_shader",
 				"webgl_shader",
+				"webgl_shader_lava",
 				"webgl_shader2",
 				"webgl_shader2",
 				"webgl_shaders_ocean",
 				"webgl_shaders_ocean",
-				"webgl_shader_lava",
 				"webgl_shading_physical",
 				"webgl_shading_physical",
+				"webgl_shaders_sky",
+				"webgl_shaders_vector",
 				"webgl_shadowmap",
 				"webgl_shadowmap",
 				"webgl_shadowmap_performance",
 				"webgl_shadowmap_performance",
 				"webgl_sprites",
 				"webgl_sprites",
@@ -351,13 +355,13 @@
 
 
 		var button = document.createElement( 'div' );
 		var button = document.createElement( 'div' );
 		button.id = 'button';
 		button.id = 'button';
-		button.textContent = '#';
+		button.textContent = 'View source';
 		button.addEventListener( 'click', function ( event ) {
 		button.addEventListener( 'click', function ( event ) {
 
 
 			var array = location.href.split( '/' );
 			var array = location.href.split( '/' );
 			array.pop();
 			array.pop();
 
 
-			window.open( array.join( '/' ) + '/' + selected + '.html' );
+			window.open( 'view-source:' + array.join( '/' ) + '/' + selected + '.html' );
 
 
 		}, false );
 		}, false );
 		button.style.display = 'none';
 		button.style.display = 'none';

+ 2 - 4
examples/js/BlendCharacter.js

@@ -8,7 +8,7 @@ THREE.BlendCharacter = function () {
 	this.weightSchedule = [];
 	this.weightSchedule = [];
 	this.warpSchedule = [];
 	this.warpSchedule = [];
 
 
-	this.load = function( url, onLoad ) {
+	this.load = function ( url, onLoad ) {
 
 
 		var scope = this;
 		var scope = this;
 
 
@@ -24,10 +24,8 @@ THREE.BlendCharacter = function () {
 
 
 			for ( var i = 0; i < geometry.animations.length; ++i ) {
 			for ( var i = 0; i < geometry.animations.length; ++i ) {
 
 
-				THREE.AnimationHandler.add( geometry.animations[ i ] );
-
 				var animName = geometry.animations[ i ].name;
 				var animName = geometry.animations[ i ].name;
-				scope.animations[ animName ] = new THREE.Animation( scope, animName );
+				scope.animations[ animName ] = new THREE.Animation( scope, geometry.animations[ i ] );
 
 
 			}
 			}
 
 

+ 0 - 182
examples/js/BufferGeometryUtils.js

@@ -1,182 +0,0 @@
-/**
- * @author spite / http://www.clicktorelease.com/
- * @author mrdoob / http://mrdoob.com/
- */
-
-THREE.BufferGeometryUtils = {
-
-	fromGeometry: function geometryToBufferGeometry( geometry, settings ) {
-
-		if ( geometry instanceof THREE.BufferGeometry ) {
-
-			return geometry;
-
-		}
-
-		settings = settings || { 'vertexColors': THREE.NoColors };
-
-		var vertices = geometry.vertices;
-		var faces = geometry.faces;
-		var faceVertexUvs = geometry.faceVertexUvs;
-		var vertexColors = settings.vertexColors;
-		var hasFaceVertexUv = faceVertexUvs[ 0 ].length > 0;
-		var hasFaceVertexNormals = faces[ 0 ].vertexNormals.length == 3;
-
-		var bufferGeometry = new THREE.BufferGeometry();
-
-		bufferGeometry.attributes = {
-
-			position: {
-				itemSize: 3,
-				array: new Float32Array( faces.length * 3 * 3 )
-			},
-			normal: {
-				itemSize: 3,
-				array: new Float32Array( faces.length * 3 * 3 )
-			}
-
-		}
-
-		var positions = bufferGeometry.attributes.position.array;
-		var normals = bufferGeometry.attributes.normal.array;
-
-		if ( vertexColors !== THREE.NoColors ) {
-
-			bufferGeometry.attributes.color = {
-				itemSize: 3,
-				array: new Float32Array( faces.length * 3 * 3 )
-			};
-
-			var colors = bufferGeometry.attributes.color.array;
-
-		}
-
-		if ( hasFaceVertexUv === true ) {
-
-			bufferGeometry.attributes.uv = {
-				itemSize: 2,
-				array: new Float32Array( faces.length * 3 * 2 )
-			};
-
-			var uvs = bufferGeometry.attributes.uv.array;
-
-		}
-
-		for ( var i = 0, i2 = 0, i3 = 0; i < faces.length; i ++, i2 += 6, i3 += 9 ) {
-
-			var face = faces[ i ];
-
-			var a = vertices[ face.a ];
-			var b = vertices[ face.b ];
-			var c = vertices[ face.c ];
-
-			positions[ i3     ] = a.x;
-			positions[ i3 + 1 ] = a.y;
-			positions[ i3 + 2 ] = a.z;
-			
-			positions[ i3 + 3 ] = b.x;
-			positions[ i3 + 4 ] = b.y;
-			positions[ i3 + 5 ] = b.z;
-			
-			positions[ i3 + 6 ] = c.x;
-			positions[ i3 + 7 ] = c.y;
-			positions[ i3 + 8 ] = c.z;
-
-			if ( hasFaceVertexNormals === true ) {
-
-				var na = face.vertexNormals[ 0 ];
-				var nb = face.vertexNormals[ 1 ];
-				var nc = face.vertexNormals[ 2 ];
-
-				normals[ i3     ] = na.x;
-				normals[ i3 + 1 ] = na.y;
-				normals[ i3 + 2 ] = na.z;
-
-				normals[ i3 + 3 ] = nb.x;
-				normals[ i3 + 4 ] = nb.y;
-				normals[ i3 + 5 ] = nb.z;
-
-				normals[ i3 + 6 ] = nc.x;
-				normals[ i3 + 7 ] = nc.y;
-				normals[ i3 + 8 ] = nc.z;
-
-			} else {
-
-				var n = face.normal;
-
-				normals[ i3     ] = n.x;
-				normals[ i3 + 1 ] = n.y;
-				normals[ i3 + 2 ] = n.z;
-
-				normals[ i3 + 3 ] = n.x;
-				normals[ i3 + 4 ] = n.y;
-				normals[ i3 + 5 ] = n.z;
-
-				normals[ i3 + 6 ] = n.x;
-				normals[ i3 + 7 ] = n.y;
-				normals[ i3 + 8 ] = n.z;
-
-			}
-
-			if ( vertexColors === THREE.FaceColors ) {
-
-				var fc = face.color;
-
-				colors[ i3     ] = fc.r;
-				colors[ i3 + 1 ] = fc.g;
-				colors[ i3 + 2 ] = fc.b;
-
-				colors[ i3 + 3 ] = fc.r;
-				colors[ i3 + 4 ] = fc.g;
-				colors[ i3 + 5 ] = fc.b;
-
-				colors[ i3 + 6 ] = fc.r;
-				colors[ i3 + 7 ] = fc.g;
-				colors[ i3 + 8 ] = fc.b;
-
-			} else if ( vertexColors === THREE.VertexColors ) {
-
-				var vca = face.vertexColors[ 0 ];
-				var vcb = face.vertexColors[ 1 ];
-				var vcc = face.vertexColors[ 2 ];
-
-				colors[ i3     ] = vca.r;
-				colors[ i3 + 1 ] = vca.g;
-				colors[ i3 + 2 ] = vca.b;
-
-				colors[ i3 + 3 ] = vcb.r;
-				colors[ i3 + 4 ] = vcb.g;
-				colors[ i3 + 5 ] = vcb.b;
-
-				colors[ i3 + 6 ] = vcc.r;
-				colors[ i3 + 7 ] = vcc.g;
-				colors[ i3 + 8 ] = vcc.b;
-
-			}
-
-			if ( hasFaceVertexUv === true ) {
-
-				var uva = faceVertexUvs[ 0 ][ i ][ 0 ];
-				var uvb = faceVertexUvs[ 0 ][ i ][ 1 ];
-				var uvc = faceVertexUvs[ 0 ][ i ][ 2 ];
-
-				uvs[ i2     ] = uva.x;
-				uvs[ i2 + 1 ] = uva.y;
-			
-				uvs[ i2 + 2 ] = uvb.x;
-				uvs[ i2 + 3 ] = uvb.y;
-			
-				uvs[ i2 + 4 ] = uvc.x;
-				uvs[ i2 + 5 ] = uvc.y;
-
-			}
-
-		}
-
-		bufferGeometry.computeBoundingSphere();
-
-		return bufferGeometry;
-
-	}
-
-}

+ 1 - 1
examples/js/Car.js

@@ -274,7 +274,7 @@ THREE.Car = function () {
 
 
 				scope.wheelDiameter = bb.max.y - bb.min.y;
 				scope.wheelDiameter = bb.max.y - bb.min.y;
 
 
-				THREE.GeometryUtils.center( scope.wheelGeometry );
+				scope.wheelGeometry.center();
 
 
 			}
 			}
 
 

+ 260 - 0
examples/js/SkyShader.js

@@ -0,0 +1,260 @@
+/**
+ * @author zz85 / https://github.com/zz85
+ * 
+ * Based on "A Practical Analytic Model for Daylight" 
+ * aka The Preetham Model, the de facto standard analytic skydome model
+ * http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
+ * 
+ * First implemented by Simon Wallner
+ * http://www.simonwallner.at/projects/atmospheric-scattering
+ * 
+ * Improved by Martin Upitis
+ * http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
+ * 
+ * Three.js integration by zz85 http://twitter.com/blurspline
+*/
+
+THREE.ShaderLib['sky'] = {
+
+	uniforms: {
+
+		luminance:	 { type: "f", value:1 },
+		turbidity:	 { type: "f", value:2 },
+		reileigh:	 { type: "f", value:1 },
+		mieCoefficient:	 { type: "f", value:0.005 },
+		mieDirectionalG: { type: "f", value:0.8 },
+		sunPosition: 	 { type: "v3", value: new THREE.Vector3() }
+
+	},
+
+	vertexShader: [
+
+		"varying vec3 vWorldPosition;",
+		"varying vec2 vUv;",
+
+		"void main() {",
+
+			"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
+			"vWorldPosition = worldPosition.xyz;",
+			"vUv = uv;",
+
+			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
+
+		"}",
+
+	].join("\n"),
+
+	fragmentShader: [
+
+
+		"uniform sampler2D skySampler;",
+		"uniform vec3 sunPosition;",
+		"varying vec3 vWorldPosition;",
+		"varying vec2 vUv;",
+
+
+		"vec3 cameraPos = vec3(0., 0., 0.);",
+		"// uniform sampler2D sDiffuse;",
+		"// const float turbidity = 10.0; //",
+		"// const float reileigh = 2.; //",
+		"// const float luminance = 1.0; //",
+		"// const float mieCoefficient = 0.005;",
+		"// const float mieDirectionalG = 0.8;",
+
+		"uniform float luminance;",
+		"uniform float turbidity;",
+		"uniform float reileigh;",
+		"uniform float mieCoefficient;",
+		"uniform float mieDirectionalG;",
+
+
+		"vec3 sunDirection = normalize(sunPosition);",
+		"float reileighCoefficient = reileigh;",
+
+		"// constants for atmospheric scattering",
+		"const float e = 2.71828182845904523536028747135266249775724709369995957;",
+		"const float pi = 3.141592653589793238462643383279502884197169;",
+
+		"const float n = 1.0003; // refractive index of air",
+		"const float N = 2.545E25; // number of molecules per unit volume for air at",
+								"// 288.15K and 1013mb (sea level -45 celsius)",
+		"const float pn = 0.035;	// depolatization factor for standard air",
+
+		"// wavelength of used primaries, according to preetham",
+		"const vec3 lambda = vec3(680E-9, 550E-9, 450E-9);",
+
+		"// mie stuff",
+		"// K coefficient for the primaries",
+		"const vec3 K = vec3(0.686, 0.678, 0.666);",
+		"const float v = 4.0;",
+
+		"// optical length at zenith for molecules",
+		"const float rayleighZenithLength = 8.4E3;",
+		"const float mieZenithLength = 1.25E3;",
+		"const vec3 up = vec3(0.0, 1.0, 0.0);",
+
+		"const float EE = 1000.0;",
+		"const float sunAngularDiameterCos = 0.999956676946448443553574619906976478926848692873900859324;",
+		"// 66 arc seconds -> degrees, and the cosine of that",
+
+		"// earth shadow hack",
+		"const float cutoffAngle = pi/1.95;",
+		"const float steepness = 1.5;",
+
+
+		"vec3 totalRayleigh(vec3 lambda)",
+		"{",
+			"return (8.0 * pow(pi, 3.0) * pow(pow(n, 2.0) - 1.0, 2.0) * (6.0 + 3.0 * pn)) / (3.0 * N * pow(lambda, vec3(4.0)) * (6.0 - 7.0 * pn));",
+		"}",
+
+		"float rayleighPhase(float cosTheta)",
+		"{	 ",
+			"return (3.0 / (16.0*pi)) * (1.0 + pow(cosTheta, 2.0));",
+		"//	return (1.0 / (3.0*pi)) * (1.0 + pow(cosTheta, 2.0));",
+		"//	return (3.0 / 4.0) * (1.0 + pow(cosTheta, 2.0));",
+		"}",
+
+		"vec3 totalMie(vec3 lambda, vec3 K, float T)",
+		"{",
+			"float c = (0.2 * T ) * 10E-18;",
+			"return 0.434 * c * pi * pow((2.0 * pi) / lambda, vec3(v - 2.0)) * K;",
+		"}",
+
+		"float hgPhase(float cosTheta, float g)",
+		"{",
+			"return (1.0 / (4.0*pi)) * ((1.0 - pow(g, 2.0)) / pow(1.0 - 2.0*g*cosTheta + pow(g, 2.0), 1.5));",
+		"}",
+
+		"float sunIntensity(float zenithAngleCos)",
+		"{",
+			"return EE * max(0.0, 1.0 - exp(-((cutoffAngle - acos(zenithAngleCos))/steepness)));",
+		"}",
+
+		"// float logLuminance(vec3 c)",
+		"// {",
+		"// 	return log(c.r * 0.2126 + c.g * 0.7152 + c.b * 0.0722);",
+		"// }",
+
+		"// Filmic ToneMapping http://filmicgames.com/archives/75",
+		"float A = 0.15;",
+		"float B = 0.50;",
+		"float C = 0.10;",
+		"float D = 0.20;",
+		"float E = 0.02;",
+		"float F = 0.30;",
+		"float W = 1000.0;",
+
+		"vec3 Uncharted2Tonemap(vec3 x)",
+		"{",
+		   "return ((x*(A*x+C*B)+D*E)/(x*(A*x+B)+D*F))-E/F;",
+		"}",
+
+
+		"void main() ",
+		"{",
+			"float sunfade = 1.0-clamp(1.0-exp((sunPosition.y/450000.0)),0.0,1.0);",
+
+			"// luminance =  1.0 ;// vWorldPosition.y / 450000. + 0.5; //sunPosition.y / 450000. * 1. + 0.5;",
+
+			 "// gl_FragColor = vec4(sunfade, sunfade, sunfade, 1.0);",
+			
+			"reileighCoefficient = reileighCoefficient - (1.0* (1.0-sunfade));",
+			
+			"float sunE = sunIntensity(dot(sunDirection, up));",
+
+			"// extinction (absorbtion + out scattering) ",
+			"// rayleigh coefficients",
+			"vec3 betaR = totalRayleigh(lambda) * reileighCoefficient;",
+
+			"// mie coefficients",
+			"vec3 betaM = totalMie(lambda, K, turbidity) * mieCoefficient;",
+
+			"// optical length",
+			"// cutoff angle at 90 to avoid singularity in next formula.",
+			"float zenithAngle = acos(max(0.0, dot(up, normalize(vWorldPosition - cameraPos))));",
+			"float sR = rayleighZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));",
+			"float sM = mieZenithLength / (cos(zenithAngle) + 0.15 * pow(93.885 - ((zenithAngle * 180.0) / pi), -1.253));",
+
+
+
+			"// combined extinction factor	",
+			"vec3 Fex = exp(-(betaR * sR + betaM * sM));",
+
+			"// in scattering",
+			"float cosTheta = dot(normalize(vWorldPosition - cameraPos), sunDirection);",
+
+			"float rPhase = rayleighPhase(cosTheta*0.5+0.5);",
+			"vec3 betaRTheta = betaR * rPhase;",
+
+			"float mPhase = hgPhase(cosTheta, mieDirectionalG);",
+			"vec3 betaMTheta = betaM * mPhase;",
+
+
+			"vec3 Lin = pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * (1.0 - Fex),vec3(1.5));",
+			"Lin *= mix(vec3(1.0),pow(sunE * ((betaRTheta + betaMTheta) / (betaR + betaM)) * Fex,vec3(1.0/2.0)),clamp(pow(1.0-dot(up, sunDirection),5.0),0.0,1.0));",
+
+			"//nightsky",
+			"vec3 direction = normalize(vWorldPosition - cameraPos);",
+			"float theta = acos(direction.y); // elevation --> y-axis, [-pi/2, pi/2]",
+			"float phi = atan(direction.z, direction.x); // azimuth --> x-axis [-pi/2, pi/2]",
+			"vec2 uv = vec2(phi, theta) / vec2(2.0*pi, pi) + vec2(0.5, 0.0);",
+			"// vec3 L0 = texture2D(skySampler, uv).rgb+0.1 * Fex;",
+			"vec3 L0 = vec3(0.1) * Fex;",
+			
+			"// composition + solar disc",
+			"//if (cosTheta > sunAngularDiameterCos)",
+			"float sundisk = smoothstep(sunAngularDiameterCos,sunAngularDiameterCos+0.00002,cosTheta);",
+			"// if (normalize(vWorldPosition - cameraPos).y>0.0)",
+			"L0 += (sunE * 19000.0 * Fex)*sundisk;",
+
+
+			"vec3 whiteScale = 1.0/Uncharted2Tonemap(vec3(W));",
+			
+			"vec3 texColor = (Lin+L0);   ",
+			"texColor *= 0.04 ;",
+			"texColor += vec3(0.0,0.001,0.0025)*0.3;",
+			
+			"float g_fMaxLuminance = 1.0;",
+			"float fLumScaled = 0.1 / luminance;     ",
+			"float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (g_fMaxLuminance * g_fMaxLuminance)))) / (1.0 + fLumScaled); ",
+
+			"float ExposureBias = fLumCompressed;",
+		   
+			"vec3 curr = Uncharted2Tonemap((log2(2.0/pow(luminance,4.0)))*texColor);",
+			"vec3 color = curr*whiteScale;",
+
+			"vec3 retColor = pow(color,vec3(1.0/(1.2+(1.2*sunfade))));",
+
+			
+			"gl_FragColor.rgb = retColor;",
+				
+			"gl_FragColor.a = 1.0;",
+		"}",
+
+	].join("\n")
+
+};
+
+THREE.Sky = function () {
+
+	var skyShader = THREE.ShaderLib[ "sky" ];
+	var skyUniforms = THREE.UniformsUtils.clone( skyShader.uniforms );
+
+	var skyMat = new THREE.ShaderMaterial( { 
+		fragmentShader: skyShader.fragmentShader, 
+		vertexShader: skyShader.vertexShader, 
+		uniforms: skyUniforms,
+		side: THREE.BackSide
+	} );
+
+	var skyGeo = new THREE.SphereGeometry( 450000, 32, 15 );
+	var skyMesh = new THREE.Mesh( skyGeo, skyMat );
+
+
+	// Expose variables
+	this.mesh = skyMesh;
+	this.uniforms = skyUniforms;
+
+
+};
+

+ 0 - 0
src/extras/cameras/CombinedCamera.js → examples/js/cameras/CombinedCamera.js


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

@@ -98,6 +98,7 @@ THREE.OrbitControls = function ( object, domElement ) {
 	var pan = new THREE.Vector3();
 	var pan = new THREE.Vector3();
 
 
 	var lastPosition = new THREE.Vector3();
 	var lastPosition = new THREE.Vector3();
+	var lastQuaternion = new THREE.Quaternion();
 
 
 	var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
 	var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
 
 
@@ -284,11 +285,17 @@ THREE.OrbitControls = function ( object, domElement ) {
 		scale = 1;
 		scale = 1;
 		pan.set( 0, 0, 0 );
 		pan.set( 0, 0, 0 );
 
 
-		if ( lastPosition.distanceToSquared( this.object.position ) > EPS ) {
+		// update condition is:
+		// min(camera displacement, camera rotation in radians)^2 > EPS
+		// using small-angle approximation cos(x/2) = 1 - x^2 / 8
+
+		if ( lastPosition.distanceToSquared( this.object.position ) > EPS
+		    || 8 * (1 - lastQuaternion.dot(this.object.quaternion)) > EPS ) {
 
 
 			this.dispatchEvent( changeEvent );
 			this.dispatchEvent( changeEvent );
 
 
 			lastPosition.copy( this.object.position );
 			lastPosition.copy( this.object.position );
+			lastQuaternion.copy (this.object.quaternion );
 
 
 		}
 		}
 
 
@@ -346,8 +353,8 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 
 		}
 		}
 
 
-		scope.domElement.addEventListener( 'mousemove', onMouseMove, false );
-		scope.domElement.addEventListener( 'mouseup', onMouseUp, false );
+		document.addEventListener( 'mousemove', onMouseMove, false );
+		document.addEventListener( 'mouseup', onMouseUp, false );
 		scope.dispatchEvent( startEvent );
 		scope.dispatchEvent( startEvent );
 
 
 	}
 	}
@@ -415,8 +422,8 @@ THREE.OrbitControls = function ( object, domElement ) {
 
 
 		if ( scope.enabled === false ) return;
 		if ( scope.enabled === false ) return;
 
 
-		scope.domElement.removeEventListener( 'mousemove', onMouseMove, false );
-		scope.domElement.removeEventListener( 'mouseup', onMouseUp, false );
+		document.removeEventListener( 'mousemove', onMouseMove, false );
+		document.removeEventListener( 'mouseup', onMouseUp, false );
 		scope.dispatchEvent( endEvent );
 		scope.dispatchEvent( endEvent );
 		state = STATE.NONE;
 		state = STATE.NONE;
 
 

+ 535 - 0
examples/js/controls/OrthographicTrackballControls.js

@@ -0,0 +1,535 @@
+/**
+ * @author Eberhard Graether / http://egraether.com/
+ * @author Patrick Fuller / http://patrick-fuller.com
+ */
+
+THREE.OrthographicTrackballControls = function ( object, domElement ) {
+
+	var _this = this;
+	var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM: 4, TOUCH_PAN: 5 };
+
+	this.object = object;
+	this.domElement = ( domElement !== undefined ) ? domElement : document;
+
+	// API
+
+	this.enabled = true;
+
+	this.screen = { width: 0, height: 0, offsetLeft: 0, offsetTop: 0 };
+	this.radius = ( this.screen.width + this.screen.height ) / 4;
+
+	this.rotateSpeed = 1.0;
+	this.zoomSpeed = 1.2;
+	this.panSpeed = 0.3;
+
+	this.noRotate = false;
+	this.noZoom = false;
+	this.noPan = false;
+
+	this.staticMoving = false;
+	this.dynamicDampingFactor = 0.2;
+
+	this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
+
+	// internals
+
+	this.target = new THREE.Vector3();
+
+	var lastPosition = new THREE.Vector3();
+
+	var _state = STATE.NONE,
+	_prevState = STATE.NONE,
+
+	_eye = new THREE.Vector3(),
+
+	_rotateStart = new THREE.Vector3(),
+	_rotateEnd = new THREE.Vector3(),
+
+	_zoomStart = new THREE.Vector2(),
+	_zoomEnd = new THREE.Vector2(),
+	_zoomFactor = 1,
+
+	_touchZoomDistanceStart = 0,
+	_touchZoomDistanceEnd = 0,
+
+	_panStart = new THREE.Vector2(),
+	_panEnd = new THREE.Vector2();
+
+	// for reset
+
+	this.target0 = this.target.clone();
+	this.position0 = this.object.position.clone();
+	this.up0 = this.object.up.clone();
+
+	this.left0 = this.object.left;
+	this.right0 = this.object.right;
+	this.top0 = this.object.top;
+	this.bottom0 = this.object.bottom;
+	this.center0 = new THREE.Vector2((this.left0 + this.right0) / 2.0, (this.top0 + this.bottom0) / 2.0);
+
+	// events
+
+	var changeEvent = { type: 'change' };
+
+
+	// methods
+
+	this.handleResize = function () {
+
+		this.screen.width = window.innerWidth;
+		this.screen.height = window.innerHeight;
+
+		this.screen.offsetLeft = 0;
+		this.screen.offsetTop = 0;
+
+		this.radius = ( this.screen.width + this.screen.height ) / 4;
+
+	};
+
+	this.handleEvent = function ( event ) {
+
+		if ( typeof this[ event.type ] == 'function' ) {
+
+			this[ event.type ]( event );
+
+		}
+
+	};
+
+	this.getMouseOnScreen = function ( clientX, clientY ) {
+
+		return new THREE.Vector2(
+			( clientX - _this.screen.offsetLeft ) / _this.radius * 0.5,
+			( clientY - _this.screen.offsetTop ) / _this.radius * 0.5
+		);
+
+	};
+
+	this.getMouseProjectionOnBall = function ( clientX, clientY ) {
+
+		var mouseOnBall = new THREE.Vector3(
+			( clientX - _this.screen.width * 0.5 - _this.screen.offsetLeft ) / _this.radius,
+			( _this.screen.height * 0.5 + _this.screen.offsetTop - clientY ) / _this.radius,
+			0.0
+		);
+
+		var length = mouseOnBall.length();
+
+		if ( length > 1.0 ) {
+
+			mouseOnBall.normalize();
+
+		} else {
+
+			mouseOnBall.z = Math.sqrt( 1.0 - length * length );
+
+		}
+
+		_eye.copy( _this.object.position ).sub( _this.target );
+
+		var projection = _this.object.up.clone().setLength( mouseOnBall.y );
+		projection.add( _this.object.up.clone().cross( _eye ).setLength( mouseOnBall.x ) );
+		projection.add( _eye.setLength( mouseOnBall.z ) );
+
+		return projection;
+
+	};
+
+	this.rotateCamera = function () {
+
+		var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
+
+		if ( angle ) {
+
+			var axis = ( new THREE.Vector3() ).crossVectors( _rotateStart, _rotateEnd ).normalize(),
+				quaternion = new THREE.Quaternion();
+
+			angle *= _this.rotateSpeed;
+
+			quaternion.setFromAxisAngle( axis, -angle );
+
+			_eye.applyQuaternion( quaternion );
+			_this.object.up.applyQuaternion( quaternion );
+
+			_rotateEnd.applyQuaternion( quaternion );
+
+			if ( _this.staticMoving ) {
+
+				_rotateStart.copy( _rotateEnd );
+
+			} else {
+
+				quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
+				_rotateStart.applyQuaternion( quaternion );
+
+			}
+
+		}
+
+	};
+
+	this.zoomCamera = function () {
+
+		if ( _state === STATE.TOUCH_ZOOM ) {
+
+			var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
+			_touchZoomDistanceStart = _touchZoomDistanceEnd;
+			_zoomFactor *= factor;
+
+			_this.object.left = _zoomFactor * _this.left0 + ( 1 - _zoomFactor ) *  _this.center0.x;
+			_this.object.right = _zoomFactor * _this.right0 + ( 1 - _zoomFactor ) *  _this.center0.x;
+			_this.object.top = _zoomFactor * _this.top0 + ( 1 - _zoomFactor ) *  _this.center0.y;
+			_this.object.bottom = _zoomFactor * _this.bottom0 + ( 1 - _zoomFactor ) *  _this.center0.y;
+
+		} else {
+
+			var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
+
+			if ( factor !== 1.0 && factor > 0.0 ) {
+				_zoomFactor *= factor;
+
+				_this.object.left = _zoomFactor * _this.left0 + ( 1 - _zoomFactor ) *  _this.center0.x;
+				_this.object.right = _zoomFactor * _this.right0 + ( 1 - _zoomFactor ) *  _this.center0.x;
+				_this.object.top = _zoomFactor * _this.top0 + ( 1 - _zoomFactor ) *  _this.center0.y;
+				_this.object.bottom = _zoomFactor * _this.bottom0 + ( 1 - _zoomFactor ) *  _this.center0.y;
+
+				if ( _this.staticMoving ) {
+
+					_zoomStart.copy( _zoomEnd );
+
+				} else {
+
+					_zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
+
+				}
+
+			}
+
+		}
+
+	};
+
+	this.panCamera = function () {
+
+		var mouseChange = _panEnd.clone().sub( _panStart );
+
+		if ( mouseChange.lengthSq() ) {
+
+			mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
+
+			var pan = _eye.clone().cross( _this.object.up ).setLength( mouseChange.x );
+			pan.add( _this.object.up.clone().setLength( mouseChange.y ) );
+
+			_this.object.position.add( pan );
+			_this.target.add( pan );
+
+			if ( _this.staticMoving ) {
+
+				_panStart = _panEnd;
+
+			} else {
+
+				_panStart.add( mouseChange.subVectors( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
+
+			}
+
+		}
+
+	};
+
+	this.update = function () {
+
+		_eye.subVectors( _this.object.position, _this.target );
+
+		if ( !_this.noRotate ) {
+
+			_this.rotateCamera();
+
+		}
+
+		if ( !_this.noZoom ) {
+
+			_this.zoomCamera();
+			_this.object.updateProjectionMatrix();
+
+		}
+
+		if ( !_this.noPan ) {
+
+			_this.panCamera();
+
+		}
+
+		_this.object.position.addVectors( _this.target, _eye );
+
+		_this.object.lookAt( _this.target );
+
+		if ( lastPosition.distanceToSquared( _this.object.position ) > 0 ) {
+
+			_this.dispatchEvent( changeEvent );
+
+			lastPosition.copy( _this.object.position );
+
+		}
+
+	};
+
+	this.reset = function () {
+
+		_state = STATE.NONE;
+		_prevState = STATE.NONE;
+
+		_this.target.copy( _this.target0 );
+		_this.object.position.copy( _this.position0 );
+		_this.object.up.copy( _this.up0 );
+
+		_eye.subVectors( _this.object.position, _this.target );
+
+		_this.object.left = _this.left0;
+		_this.object.right = _this.right0;
+		_this.object.top = _this.top0;
+		_this.object.bottom = _this.bottom0;
+
+		_this.object.lookAt( _this.target );
+
+		_this.dispatchEvent( changeEvent );
+
+		lastPosition.copy( _this.object.position );
+
+	};
+
+	// listeners
+
+	function keydown( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		window.removeEventListener( 'keydown', keydown );
+
+		_prevState = _state;
+
+		if ( _state !== STATE.NONE ) {
+
+			return;
+
+		} else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {
+
+			_state = STATE.ROTATE;
+
+		} else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {
+
+			_state = STATE.ZOOM;
+
+		} else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {
+
+			_state = STATE.PAN;
+
+		}
+
+	}
+
+	function keyup( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		_state = _prevState;
+
+		window.addEventListener( 'keydown', keydown, false );
+
+	}
+
+	function mousedown( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( _state === STATE.NONE ) {
+
+			_state = event.button;
+
+		}
+
+		if ( _state === STATE.ROTATE && !_this.noRotate ) {
+
+			_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
+
+		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
+
+			_zoomStart = _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+
+		} else if ( _state === STATE.PAN && !_this.noPan ) {
+
+			_panStart = _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+
+		}
+
+		document.addEventListener( 'mousemove', mousemove, false );
+		document.addEventListener( 'mouseup', mouseup, false );
+
+	}
+
+	function mousemove( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		if ( _state === STATE.ROTATE && !_this.noRotate ) {
+
+			_rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
+
+		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
+
+			_zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+
+		} else if ( _state === STATE.PAN && !_this.noPan ) {
+
+			_panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
+
+		}
+
+	}
+
+	function mouseup( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		_state = STATE.NONE;
+
+		document.removeEventListener( 'mousemove', mousemove );
+		document.removeEventListener( 'mouseup', mouseup );
+
+	}
+
+	function mousewheel( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		var delta = 0;
+
+		if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
+
+			delta = event.wheelDelta / 40;
+
+		} else if ( event.detail ) { // Firefox
+
+			delta = - event.detail / 3;
+
+		}
+
+		_zoomStart.y += delta * 0.01;
+
+	}
+
+	function touchstart( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_state = STATE.TOUCH_ROTATE;
+				_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				break;
+
+			case 2:
+				_state = STATE.TOUCH_ZOOM;
+				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+				_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
+				break;
+
+			case 3:
+				_state = STATE.TOUCH_PAN;
+				_panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				break;
+
+			default:
+				_state = STATE.NONE;
+
+		}
+
+	}
+
+	function touchmove( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		event.preventDefault();
+		event.stopPropagation();
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				break;
+
+			case 2:
+				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
+				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
+				_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy )
+				break;
+
+			case 3:
+				_panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				break;
+
+			default:
+				_state = STATE.NONE;
+
+		}
+
+	}
+
+	function touchend( event ) {
+
+		if ( _this.enabled === false ) return;
+
+		switch ( event.touches.length ) {
+
+			case 1:
+				_rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				break;
+
+			case 2:
+				_touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
+				break;
+
+			case 3:
+				_panStart = _panEnd = _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
+				break;
+
+		}
+
+		_state = STATE.NONE;
+
+	}
+
+	this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
+
+	this.domElement.addEventListener( 'mousedown', mousedown, false );
+
+	this.domElement.addEventListener( 'mousewheel', mousewheel, false );
+	this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false ); // firefox
+
+	this.domElement.addEventListener( 'touchstart', touchstart, false );
+	this.domElement.addEventListener( 'touchend', touchend, false );
+	this.domElement.addEventListener( 'touchmove', touchmove, false );
+
+	window.addEventListener( 'keydown', keydown, false );
+	window.addEventListener( 'keyup', keyup, false );
+
+	this.handleResize();
+
+};
+
+THREE.OrthographicTrackballControls.prototype = Object.create( THREE.EventDispatcher.prototype );

+ 1 - 1
examples/js/controls/PathControls.js

@@ -249,7 +249,7 @@ THREE.PathControls = function ( object, domElement ) {
 			particleGeo = createSplineGeometry( spline, 10 ),
 			particleGeo = createSplineGeometry( spline, 10 ),
 			lineMat = new THREE.LineBasicMaterial( { color: 0xff0000, linewidth: 3 } ),
 			lineMat = new THREE.LineBasicMaterial( { color: 0xff0000, linewidth: 3 } ),
 			lineObj = new THREE.Line( lineGeo, lineMat ),
 			lineObj = new THREE.Line( lineGeo, lineMat ),
-			particleObj = new THREE.ParticleSystem( particleGeo, new THREE.ParticleSystemMaterial( { color: 0xffaa00, size: 3 } ) );
+			particleObj = new THREE.PointCloud( particleGeo, new THREE.PointCloudMaterial( { color: 0xffaa00, size: 3 } ) );
 
 
 		lineObj.scale.set( 1, 1, 1 );
 		lineObj.scale.set( 1, 1, 1 );
 		parent.add( lineObj );
 		parent.add( lineObj );

+ 53 - 41
examples/js/controls/TrackballControls.js

@@ -6,7 +6,7 @@
 THREE.TrackballControls = function ( object, domElement ) {
 THREE.TrackballControls = function ( object, domElement ) {
 
 
 	var _this = this;
 	var _this = this;
-	var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM: 4, TOUCH_PAN: 5 };
+	var STATE = { NONE: -1, ROTATE: 0, ZOOM: 1, PAN: 2, TOUCH_ROTATE: 3, TOUCH_ZOOM_PAN: 4 };
 
 
 	this.object = object;
 	this.object = object;
 	this.domElement = ( domElement !== undefined ) ? domElement : document;
 	this.domElement = ( domElement !== undefined ) ? domElement : document;
@@ -107,22 +107,30 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 	};
 	};
 
 
-	this.getMouseOnScreen = function ( pageX, pageY, vector ) {
+	var getMouseOnScreen = ( function () {
 
 
-		return vector.set(
-			( pageX - _this.screen.left ) / _this.screen.width,
-			( pageY - _this.screen.top ) / _this.screen.height
-		);
+		var vector = new THREE.Vector2();
 
 
-	};
+		return function ( pageX, pageY ) {
+
+			vector.set(
+				( pageX - _this.screen.left ) / _this.screen.width,
+				( pageY - _this.screen.top ) / _this.screen.height
+			);
+
+			return vector;
 
 
-	this.getMouseProjectionOnBall = (function(){
+		};
 
 
-		var objectUp = new THREE.Vector3(),
-		    mouseOnBall = new THREE.Vector3();
+	}() );
 
 
+	var getMouseProjectionOnBall = ( function () {
 
 
-		return function ( pageX, pageY, projection ) {
+		var vector = new THREE.Vector3();
+		var objectUp = new THREE.Vector3();
+		var mouseOnBall = new THREE.Vector3();
+
+		return function ( pageX, pageY ) {
 
 
 			mouseOnBall.set(
 			mouseOnBall.set(
 				( pageX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),
 				( pageX - _this.screen.width * 0.5 - _this.screen.left ) / (_this.screen.width*.5),
@@ -156,14 +164,15 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 			_eye.copy( _this.object.position ).sub( _this.target );
 			_eye.copy( _this.object.position ).sub( _this.target );
 
 
-			projection.copy( _this.object.up ).setLength( mouseOnBall.y )
-			projection.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );
-			projection.add( _eye.setLength( mouseOnBall.z ) );
+			vector.copy( _this.object.up ).setLength( mouseOnBall.y )
+			vector.add( objectUp.copy( _this.object.up ).cross( _eye ).setLength( mouseOnBall.x ) );
+			vector.add( _eye.setLength( mouseOnBall.z ) );
 
 
-			return projection;
-		}
+			return vector;
 
 
-	}());
+		};
+
+	}() );
 
 
 	this.rotateCamera = (function(){
 	this.rotateCamera = (function(){
 
 
@@ -206,7 +215,7 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 	this.zoomCamera = function () {
 	this.zoomCamera = function () {
 
 
-		if ( _state === STATE.TOUCH_ZOOM ) {
+		if ( _state === STATE.TOUCH_ZOOM_PAN ) {
 
 
 			var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
 			var factor = _touchZoomDistanceStart / _touchZoomDistanceEnd;
 			_touchZoomDistanceStart = _touchZoomDistanceEnd;
 			_touchZoomDistanceStart = _touchZoomDistanceEnd;
@@ -403,25 +412,25 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 
 
-			_this.getMouseProjectionOnBall( event.pageX, event.pageY, _rotateStart );
-			_rotateEnd.copy(_rotateStart)
+			_rotateStart.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
+			_rotateEnd.copy( _rotateStart );
 
 
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 
 
-			_this.getMouseOnScreen( event.pageX, event.pageY, _zoomStart );
+			_zoomStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 			_zoomEnd.copy(_zoomStart);
 			_zoomEnd.copy(_zoomStart);
 
 
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 
 
-			_this.getMouseOnScreen( event.pageX, event.pageY, _panStart );
+			_panStart.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 			_panEnd.copy(_panStart)
 			_panEnd.copy(_panStart)
 
 
 		}
 		}
 
 
 		document.addEventListener( 'mousemove', mousemove, false );
 		document.addEventListener( 'mousemove', mousemove, false );
 		document.addEventListener( 'mouseup', mouseup, false );
 		document.addEventListener( 'mouseup', mouseup, false );
-		_this.dispatchEvent( startEvent );
 
 
+		_this.dispatchEvent( startEvent );
 
 
 	}
 	}
 
 
@@ -434,15 +443,15 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 		if ( _state === STATE.ROTATE && !_this.noRotate ) {
 
 
-			_this.getMouseProjectionOnBall( event.pageX, event.pageY, _rotateEnd );
+			_rotateEnd.copy( getMouseProjectionOnBall( event.pageX, event.pageY ) );
 
 
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 		} else if ( _state === STATE.ZOOM && !_this.noZoom ) {
 
 
-			_this.getMouseOnScreen( event.pageX, event.pageY, _zoomEnd );
+			_zoomEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 
 
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 		} else if ( _state === STATE.PAN && !_this.noPan ) {
 
 
-			_this.getMouseOnScreen( event.pageX, event.pageY, _panEnd );
+			_panEnd.copy( getMouseOnScreen( event.pageX, event.pageY ) );
 
 
 		}
 		}
 
 
@@ -496,19 +505,20 @@ THREE.TrackballControls = function ( object, domElement ) {
 
 
 			case 1:
 			case 1:
 				_state = STATE.TOUCH_ROTATE;
 				_state = STATE.TOUCH_ROTATE;
-				_rotateEnd.copy( _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _rotateStart ));
+				_rotateStart.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_rotateEnd.copy( _rotateStart );
 				break;
 				break;
 
 
 			case 2:
 			case 2:
-				_state = STATE.TOUCH_ZOOM;
+				_state = STATE.TOUCH_ZOOM_PAN;
 				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
 				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
 				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
 				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
 				_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
 				_touchZoomDistanceEnd = _touchZoomDistanceStart = Math.sqrt( dx * dx + dy * dy );
-				break;
 
 
-			case 3:
-				_state = STATE.TOUCH_PAN;
-				_panEnd.copy( _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _panStart ));
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panStart.copy( getMouseOnScreen( x, y ) );
+				_panEnd.copy( _panStart );
 				break;
 				break;
 
 
 			default:
 			default:
@@ -530,17 +540,17 @@ THREE.TrackballControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 		switch ( event.touches.length ) {
 
 
 			case 1:
 			case 1:
-				_this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _rotateEnd );
+				_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
 				break;
 				break;
 
 
 			case 2:
 			case 2:
 				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
 				var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
 				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
 				var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
-				_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy )
-				break;
+				_touchZoomDistanceEnd = Math.sqrt( dx * dx + dy * dy );
 
 
-			case 3:
-				_this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _panEnd );
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panEnd.copy( getMouseOnScreen( x, y ) );
 				break;
 				break;
 
 
 			default:
 			default:
@@ -557,15 +567,17 @@ THREE.TrackballControls = function ( object, domElement ) {
 		switch ( event.touches.length ) {
 		switch ( event.touches.length ) {
 
 
 			case 1:
 			case 1:
-				_rotateStart.copy( _this.getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _rotateEnd ));
+				_rotateEnd.copy( getMouseProjectionOnBall( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY ) );
+				_rotateStart.copy( _rotateEnd );
 				break;
 				break;
 
 
 			case 2:
 			case 2:
 				_touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
 				_touchZoomDistanceStart = _touchZoomDistanceEnd = 0;
-				break;
 
 
-			case 3:
-				_panStart.copy( _this.getMouseOnScreen( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY, _panEnd ));
+				var x = ( event.touches[ 0 ].pageX + event.touches[ 1 ].pageX ) / 2;
+				var y = ( event.touches[ 0 ].pageY + event.touches[ 1 ].pageY ) / 2;
+				_panEnd.copy( getMouseOnScreen( x, y ) );
+				_panStart.copy( _panEnd );
 				break;
 				break;
 
 
 		}
 		}

+ 3 - 3
examples/js/controls/TransformControls.js

@@ -720,7 +720,7 @@
 
 
 			event.preventDefault();
 			event.preventDefault();
 
 
-			var pointer = event.touches ? event.touches[ 0 ] : event;
+			var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
 
 
 			var intersect = intersectObjects( pointer, scope.gizmo[_mode].pickers.children );
 			var intersect = intersectObjects( pointer, scope.gizmo[_mode].pickers.children );
 
 
@@ -747,7 +747,7 @@
 			event.preventDefault();
 			event.preventDefault();
 			event.stopPropagation();
 			event.stopPropagation();
 
 
-			var pointer = event.touches ? event.touches[ 0 ] : event;
+			var pointer = event.changedTouches ? event.changedTouches[ 0 ] : event;
 
 
 			if ( pointer.button === 0 || pointer.button === undefined ) {
 			if ( pointer.button === 0 || pointer.button === undefined ) {
 
 
@@ -791,7 +791,7 @@
 			event.preventDefault();
 			event.preventDefault();
 			event.stopPropagation();
 			event.stopPropagation();
 
 
-			var pointer = event.touches? event.touches[0] : event;
+			var pointer = event.changedTouches? event.changedTouches[0] : event;
 
 
 			var planeIntersect = intersectObjects( pointer, [scope.gizmo[_mode].activePlane] );
 			var planeIntersect = intersectObjects( pointer, [scope.gizmo[_mode].activePlane] );
 
 

+ 79 - 0
examples/js/exporters/STLBinaryExporter.js

@@ -0,0 +1,79 @@
+/**
+ * @author kovacsv / http://kovacsv.hu/
+ * @author mrdoob / http://mrdoob.com/
+ * @author mudcube / http://mudcu.be/
+ */
+ 
+THREE.STLBinaryExporter = function () {};
+
+THREE.STLBinaryExporter.prototype = {
+
+	constructor: THREE.STLBinaryExporter,
+
+	parse: ( function () {
+
+		var vector = new THREE.Vector3();
+		var normalMatrixWorld = new THREE.Matrix3();
+
+		return function ( scene ) {
+
+			var triangles = 0;
+			scene.traverse( function ( object ) {
+				if ( !(object instanceof THREE.Mesh) ) return;
+				triangles += object.geometry.faces.length;
+			});
+
+			var offset = 80; // skip header
+			var bufferLength = triangles * 2 + triangles * 3 * 4 * 4 + 80 + 4;
+			var arrayBuffer = new ArrayBuffer(bufferLength);
+			var output = new DataView(arrayBuffer);
+			output.setUint32(offset, triangles, true); offset += 4;
+
+			scene.traverse( function ( object ) {
+
+				if ( !(object instanceof THREE.Mesh) ) return;
+				if ( !(object.geometry instanceof THREE.Geometry )) return;
+
+				var geometry = object.geometry;
+				var matrixWorld = object.matrixWorld;
+
+				var vertices = geometry.vertices;
+				var faces = geometry.faces;
+
+				normalMatrixWorld.getNormalMatrix( matrixWorld );
+
+				for ( var i = 0, l = faces.length; i < l; i ++ ) {
+
+					var face = faces[ i ];
+
+					vector.copy( face.normal ).applyMatrix3( normalMatrixWorld ).normalize();
+
+					output.setFloat32(offset, vector.x, true); offset += 4; // normal
+					output.setFloat32(offset, vector.y, true); offset += 4;
+					output.setFloat32(offset, vector.z, true); offset += 4;
+
+					var indices = [ face.a, face.b, face.c ];
+
+					for ( var j = 0; j < 3; j ++ ) {
+
+						vector.copy( vertices[ indices[ j ] ] ).applyMatrix4( matrixWorld );
+
+						output.setFloat32(offset, vector.x, true); offset += 4; // vertices
+						output.setFloat32(offset, vector.y, true); offset += 4;
+						output.setFloat32(offset, vector.z, true); offset += 4;
+
+					}
+
+					output.setUint16(offset, 0, true); offset += 2; // attribute byte count					
+
+				}
+
+			} );
+			
+			return output;
+
+		};
+
+	}() )
+
+};

+ 5 - 5
examples/js/exporters/Geometry2Exporter.js → examples/js/exporters/TypedGeometryExporter.js

@@ -2,19 +2,19 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-THREE.Geometry2Exporter = function () {};
+THREE.TypedGeometryExporter = function () {};
 
 
-THREE.Geometry2Exporter.prototype = {
+THREE.TypedGeometryExporter.prototype = {
 
 
-	constructor: THREE.Geometry2Exporter,
+	constructor: THREE.TypedGeometryExporter,
 
 
 	parse: function ( geometry ) {
 	parse: function ( geometry ) {
 
 
 		var output = {
 		var output = {
 			metadata: {
 			metadata: {
 				version: 4.0,
 				version: 4.0,
-				type: 'Geometry2',
-				generator: 'Geometry2Exporter'
+				type: 'TypedGeometry',
+				generator: 'TypedGeometryExporter'
 			}
 			}
 		};
 		};
 
 

+ 600 - 0
examples/js/libs/msgpack-js.js

@@ -0,0 +1,600 @@
+( // Module boilerplate to support browser globals and browserify and AMD.
+  typeof define === "function" ? function (m) { define("msgpack-js", m); } :
+  typeof exports === "object" ? function (m) { module.exports = m(); } :
+  function(m){ this.msgpack = m(); }
+)(function () {
+"use strict";
+
+var exports = {};
+
+exports.inspect = inspect;
+function inspect(buffer) {
+  if (buffer === undefined) return "undefined";
+  var view;
+  var type;
+  if (buffer instanceof ArrayBuffer) {
+    type = "ArrayBuffer";
+    view = new DataView(buffer);
+  }
+  else if (buffer instanceof DataView) {
+    type = "DataView";
+    view = buffer;
+  }
+  if (!view) return JSON.stringify(buffer);
+  var bytes = [];
+  for (var i = 0; i < buffer.byteLength; i++) {
+    if (i > 20) {
+      bytes.push("...");
+      break;
+    }
+    var byte = view.getUint8(i).toString(16);
+    if (byte.length === 1) byte = "0" + byte;
+    bytes.push(byte);
+  }
+  return "<" + type + " " + bytes.join(" ") + ">";
+}
+
+// Encode string as utf8 into dataview at offset
+exports.utf8Write = utf8Write;
+function utf8Write(view, offset, string) {
+  var byteLength = view.byteLength;
+  for(var i = 0, l = string.length; i < l; i++) {
+    var codePoint = string.charCodeAt(i);
+
+    // One byte of UTF-8
+    if (codePoint < 0x80) {
+      view.setUint8(offset++, codePoint >>> 0 & 0x7f | 0x00);
+      continue;
+    }
+
+    // Two bytes of UTF-8
+    if (codePoint < 0x800) {
+      view.setUint8(offset++, codePoint >>> 6 & 0x1f | 0xc0);
+      view.setUint8(offset++, codePoint >>> 0 & 0x3f | 0x80);
+      continue;
+    }
+
+    // Three bytes of UTF-8.  
+    if (codePoint < 0x10000) {
+      view.setUint8(offset++, codePoint >>> 12 & 0x0f | 0xe0);
+      view.setUint8(offset++, codePoint >>> 6  & 0x3f | 0x80);
+      view.setUint8(offset++, codePoint >>> 0  & 0x3f | 0x80);
+      continue;
+    }
+
+    // Four bytes of UTF-8
+    if (codePoint < 0x110000) {
+      view.setUint8(offset++, codePoint >>> 18 & 0x07 | 0xf0);
+      view.setUint8(offset++, codePoint >>> 12 & 0x3f | 0x80);
+      view.setUint8(offset++, codePoint >>> 6  & 0x3f | 0x80);
+      view.setUint8(offset++, codePoint >>> 0  & 0x3f | 0x80);
+      continue;
+    }
+    throw new Error("bad codepoint " + codePoint);
+  }
+}
+
+exports.utf8Read = utf8Read;
+function utf8Read(view, offset, length) {
+  var string = "";
+  for (var i = offset, end = offset + length; i < end; i++) {
+    var byte = view.getUint8(i);
+    // One byte character
+    if ((byte & 0x80) === 0x00) {
+      string += String.fromCharCode(byte);
+      continue;
+    }
+    // Two byte character
+    if ((byte & 0xe0) === 0xc0) {
+      string += String.fromCharCode(
+        ((byte & 0x0f) << 6) | 
+        (view.getUint8(++i) & 0x3f)
+      );
+      continue;
+    }
+    // Three byte character
+    if ((byte & 0xf0) === 0xe0) {
+      string += String.fromCharCode(
+        ((byte & 0x0f) << 12) |
+        ((view.getUint8(++i) & 0x3f) << 6) |
+        ((view.getUint8(++i) & 0x3f) << 0)
+      );
+      continue;
+    }
+    // Four byte character
+    if ((byte & 0xf8) === 0xf0) {
+      string += String.fromCharCode(
+        ((byte & 0x07) << 18) |
+        ((view.getUint8(++i) & 0x3f) << 12) |
+        ((view.getUint8(++i) & 0x3f) << 6) |
+        ((view.getUint8(++i) & 0x3f) << 0)
+      );
+      continue;
+    }
+    throw new Error("Invalid byte " + byte.toString(16));
+  }
+  return string;
+}
+
+exports.utf8ByteCount = utf8ByteCount;
+function utf8ByteCount(string) {
+  var count = 0;
+  for(var i = 0, l = string.length; i < l; i++) {
+    var codePoint = string.charCodeAt(i);
+    if (codePoint < 0x80) {
+      count += 1;
+      continue;
+    }
+    if (codePoint < 0x800) {
+      count += 2;
+      continue;
+    }
+    if (codePoint < 0x10000) {
+      count += 3;
+      continue;
+    }
+    if (codePoint < 0x110000) {
+      count += 4;
+      continue;
+    }
+    throw new Error("bad codepoint " + codePoint);
+  }
+  return count;
+}
+
+exports.encode = function (value) {
+  var buffer = new ArrayBuffer(sizeof(value));
+  var view = new DataView(buffer);
+  encode(value, view, 0);
+  return buffer;
+}
+
+exports.decode = decode;
+
+// http://wiki.msgpack.org/display/MSGPACK/Format+specification
+// I've extended the protocol to have two new types that were previously reserved.
+//   buffer 16  11011000  0xd8
+//   buffer 32  11011001  0xd9
+// These work just like raw16 and raw32 except they are node buffers instead of strings.
+//
+// Also I've added a type for `undefined`
+//   undefined  11000100  0xc4
+
+function Decoder(view, offset) {
+  this.offset = offset || 0;
+  this.view = view;
+}
+Decoder.prototype.map = function (length) {
+  var value = {};
+  for (var i = 0; i < length; i++) {
+    var key = this.parse();
+    value[key] = this.parse();
+  }
+  return value;
+};
+Decoder.prototype.buf = function (length) {
+  var value = new ArrayBuffer(length);
+  (new Uint8Array(value)).set(new Uint8Array(this.view.buffer, this.offset, length), 0);
+  this.offset += length;
+  return value;
+};
+Decoder.prototype.raw = function (length) {
+  var value = utf8Read(this.view, this.offset, length);
+  this.offset += length;
+  return value;
+};
+Decoder.prototype.array = function (length) {
+  var value = new Array(length);
+  for (var i = 0; i < length; i++) {
+    value[i] = this.parse();
+  }
+  return value;
+};
+Decoder.prototype.parse = function () {
+  var type = this.view.getUint8(this.offset);
+  var value, length;
+  // FixRaw
+  if ((type & 0xe0) === 0xa0) {
+    length = type & 0x1f;
+    this.offset++;
+    return this.raw(length);
+  }
+  // FixMap
+  if ((type & 0xf0) === 0x80) {
+    length = type & 0x0f;
+    this.offset++;
+    return this.map(length);
+  }
+  // FixArray
+  if ((type & 0xf0) === 0x90) {
+    length = type & 0x0f;
+    this.offset++;
+    return this.array(length);
+  }
+  // Positive FixNum
+  if ((type & 0x80) === 0x00) {
+    this.offset++;
+    return type;
+  }
+  // Negative Fixnum
+  if ((type & 0xe0) === 0xe0) {
+    value = this.view.getInt8(this.offset);
+    this.offset++;
+    return value;
+  }
+  switch (type) {
+  // raw 16
+  case 0xda:
+    length = this.view.getUint16(this.offset + 1);
+    this.offset += 3;
+    return this.raw(length);
+  // raw 32
+  case 0xdb:
+    length = this.view.getUint32(this.offset + 1);
+    this.offset += 5;
+    return this.raw(length);
+  // nil
+  case 0xc0:
+    this.offset++;
+    return null;
+  // false
+  case 0xc2:
+    this.offset++;
+    return false;
+  // true
+  case 0xc3:
+    this.offset++;
+    return true;
+  // undefined
+  case 0xc4:
+    this.offset++;
+    return undefined;
+  // uint8
+  case 0xcc:
+    value = this.view.getUint8(this.offset + 1);
+    this.offset += 2;
+    return value;
+  // uint 16
+  case 0xcd:
+    value = this.view.getUint16(this.offset + 1);
+    this.offset += 3;
+    return value;
+  // uint 32
+  case 0xce:
+    value = this.view.getUint32(this.offset + 1);
+    this.offset += 5;
+    return value;
+  // int 8
+  case 0xd0:
+    value = this.view.getInt8(this.offset + 1);
+    this.offset += 2;
+    return value;
+  // int 16
+  case 0xd1:
+    value = this.view.getInt16(this.offset + 1);
+    this.offset += 3;
+    return value;
+  // int 32
+  case 0xd2:
+    value = this.view.getInt32(this.offset + 1);
+    this.offset += 5;
+    return value;
+  // map 16
+  case 0xde:
+    length = this.view.getUint16(this.offset + 1);
+    this.offset += 3;
+    return this.map(length);
+  // map 32
+  case 0xdf:
+    length = this.view.getUint32(this.offset + 1);
+    this.offset += 5;
+    return this.map(length);
+  // array 16
+  case 0xdc:
+    length = this.view.getUint16(this.offset + 1);
+    this.offset += 3;
+    return this.array(length);
+  // array 32
+  case 0xdd:
+    length = this.view.getUint32(this.offset + 1);
+    this.offset += 5;
+    return this.array(length);
+  // buffer 16
+  case 0xd8:
+    length = this.view.getUint16(this.offset + 1);
+    this.offset += 3;
+    return this.buf(length);
+  // buffer 32
+  case 0xd9:
+    length = this.view.getUint32(this.offset + 1);
+    this.offset += 5;
+    return this.buf(length);
+  // float
+  case 0xca:
+    value = this.view.getFloat32(this.offset + 1);
+    this.offset += 5;
+    return value;
+  // double
+  case 0xcb:
+    value = this.view.getFloat64(this.offset + 1);
+    this.offset += 9;
+    return value;
+  }
+  throw new Error("Unknown type 0x" + type.toString(16));
+};
+function decode(buffer) {
+  var view = new DataView(buffer);
+  var decoder = new Decoder(view);
+  var value = decoder.parse();
+  if (decoder.offset !== buffer.byteLength) throw new Error((buffer.byteLength - decoder.offset) + " trailing bytes");
+  return value;
+}
+
+function encode(value, view, offset) {
+  var type = typeof value;
+
+  // Strings Bytes
+  if (type === "string") {
+    var length = utf8ByteCount(value);
+    // fix raw
+    if (length < 0x20) {
+      view.setUint8(offset, length | 0xa0);
+      utf8Write(view, offset + 1, value);
+      return 1 + length;
+    }
+    // raw 16
+    if (length < 0x10000) {
+      view.setUint8(offset, 0xda);
+      view.setUint16(offset + 1, length);
+      utf8Write(view, offset + 3, value);
+      return 3 + length;
+    }
+    // raw 32
+    if (length < 0x100000000) {
+      view.setUint8(offset, 0xdb);
+      view.setUint32(offset + 1, length);
+      utf8Write(view, offset + 5, value);
+      return 5 + length;
+    }
+  }
+
+  if (value instanceof ArrayBuffer) {
+    var length = value.byteLength;
+    // buffer 16
+    if (length < 0x10000) {
+      view.setUint8(offset, 0xd8);
+      view.setUint16(offset + 1, length);
+      (new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 3);
+      return 3 + length;
+    }
+    // buffer 32
+    if (length < 0x100000000) {
+      view.setUint8(offset, 0xd9);
+      view.setUint32(offset + 1, length);
+      (new Uint8Array(view.buffer)).set(new Uint8Array(value), offset + 5);
+      return 5 + length;
+    }
+  }
+  
+  if (type === "number") {
+    // Floating Point
+    if ((value << 0) !== value) {
+      view.setUint8(offset, 0xcb);
+      view.setFloat64(offset + 1, value);
+      return 9;
+    }
+
+    // Integers
+    if (value >=0) {
+      // positive fixnum
+      if (value < 0x80) {
+        view.setUint8(offset, value);
+        return 1;
+      }
+      // uint 8
+      if (value < 0x100) {
+        view.setUint8(offset, 0xcc);
+        view.setUint8(offset + 1, value);
+        return 2;
+      }
+      // uint 16
+      if (value < 0x10000) {
+        view.setUint8(offset, 0xcd);
+        view.setUint16(offset + 1, value);
+        return 3;
+      }
+      // uint 32
+      if (value < 0x100000000) {
+        view.setUint8(offset, 0xce);
+        view.setUint32(offset + 1, value);
+        return 5;
+      }
+      throw new Error("Number too big 0x" + value.toString(16));
+    }
+    // negative fixnum
+    if (value >= -0x20) {
+      view.setInt8(offset, value);
+      return 1;
+    }
+    // int 8
+    if (value >= -0x80) {
+      view.setUint8(offset, 0xd0);
+      view.setInt8(offset + 1, value);
+      return 2;
+    }
+    // int 16
+    if (value >= -0x8000) {
+      view.setUint8(offset, 0xd1);
+      view.setInt16(offset + 1, value);
+      return 3;
+    }
+    // int 32
+    if (value >= -0x80000000) {
+      view.setUint8(offset, 0xd2);
+      view.setInt32(offset + 1, value);
+      return 5;
+    }
+    throw new Error("Number too small -0x" + (-value).toString(16).substr(1));
+  }
+  
+  // undefined
+  if (type === "undefined") {
+    view.setUint8(offset, 0xc4);
+    return 1;
+  }
+  
+  // null
+  if (value === null) {
+    view.setUint8(offset, 0xc0);
+    return 1;
+  }
+
+  // Boolean
+  if (type === "boolean") {
+    view.setUint8(offset, value ? 0xc3 : 0xc2);
+    return 1;
+  }
+  
+  // Container Types
+  if (type === "object") {
+    var length, size = 0;
+    var isArray = Array.isArray(value);
+
+    if (isArray) {
+      length = value.length;
+    }
+    else {
+      var keys = Object.keys(value);
+      length = keys.length;
+    }
+
+    var size;
+    if (length < 0x10) {
+      view.setUint8(offset, length | (isArray ? 0x90 : 0x80));
+      size = 1;
+    }
+    else if (length < 0x10000) {
+      view.setUint8(offset, isArray ? 0xdc : 0xde);
+      view.setUint16(offset + 1, length);
+      size = 3;
+    }
+    else if (length < 0x100000000) {
+      view.setUint8(offset, isArray ? 0xdd : 0xdf);
+      view.setUint32(offset + 1, length);
+      size = 5;
+    }
+
+    if (isArray) {
+      for (var i = 0; i < length; i++) {
+        size += encode(value[i], view, offset + size);
+      }
+    }
+    else {
+      for (var i = 0; i < length; i++) {
+        var key = keys[i];
+        size += encode(key, view, offset + size);
+        size += encode(value[key], view, offset + size);
+      }
+    }
+    
+    return size;
+  }
+  throw new Error("Unknown type " + type);
+}
+
+function sizeof(value) {
+  var type = typeof value;
+
+  // Raw Bytes
+  if (type === "string") {
+    var length = utf8ByteCount(value);
+    if (length < 0x20) {
+      return 1 + length;
+    }
+    if (length < 0x10000) {
+      return 3 + length;
+    }
+    if (length < 0x100000000) {
+      return 5 + length;
+    }
+  }
+  
+  if (value instanceof ArrayBuffer) {
+    var length = value.byteLength;
+    if (length < 0x10000) {
+      return 3 + length;
+    }
+    if (length < 0x100000000) {
+      return 5 + length;
+    }
+  }
+  
+  if (type === "number") {
+    // Floating Point
+    // double
+    if (value << 0 !== value) return 9;
+
+    // Integers
+    if (value >=0) {
+      // positive fixnum
+      if (value < 0x80) return 1;
+      // uint 8
+      if (value < 0x100) return 2;
+      // uint 16
+      if (value < 0x10000) return 3;
+      // uint 32
+      if (value < 0x100000000) return 5;
+      // uint 64
+      if (value < 0x10000000000000000) return 9;
+      throw new Error("Number too big 0x" + value.toString(16));
+    }
+    // negative fixnum
+    if (value >= -0x20) return 1;
+    // int 8
+    if (value >= -0x80) return 2;
+    // int 16
+    if (value >= -0x8000) return 3;
+    // int 32
+    if (value >= -0x80000000) return 5;
+    // int 64
+    if (value >= -0x8000000000000000) return 9;
+    throw new Error("Number too small -0x" + value.toString(16).substr(1));
+  }
+  
+  // Boolean, null, undefined
+  if (type === "boolean" || type === "undefined" || value === null) return 1;
+  
+  // Container Types
+  if (type === "object") {
+    var length, size = 0;
+    if (Array.isArray(value)) {
+      length = value.length;
+      for (var i = 0; i < length; i++) {
+        size += sizeof(value[i]);
+      }
+    }
+    else {
+      var keys = Object.keys(value);
+      length = keys.length;
+      for (var i = 0; i < length; i++) {
+        var key = keys[i];
+        size += sizeof(key) + sizeof(value[key]);
+      }
+    }
+    if (length < 0x10) {
+      return 1 + size;
+    }
+    if (length < 0x10000) {
+      return 3 + size;
+    }
+    if (length < 0x100000000) {
+      return 5 + size;
+    }
+    throw new Error("Array or object too long 0x" + length.toString(16));
+  }
+  throw new Error("Unknown type " + type);
+}
+
+return exports;
+
+});

+ 36 - 0
examples/js/libs/require.js

@@ -0,0 +1,36 @@
+/*
+ RequireJS 2.1.11 Copyright (c) 2010-2014, The Dojo Foundation All Rights Reserved.
+ Available via the MIT or new BSD license.
+ see: http://github.com/jrburke/requirejs for details
+*/
+var requirejs,require,define;
+(function(ca){function G(b){return"[object Function]"===M.call(b)}function H(b){return"[object Array]"===M.call(b)}function v(b,c){if(b){var d;for(d=0;d<b.length&&(!b[d]||!c(b[d],d,b));d+=1);}}function U(b,c){if(b){var d;for(d=b.length-1;-1<d&&(!b[d]||!c(b[d],d,b));d-=1);}}function s(b,c){return ga.call(b,c)}function j(b,c){return s(b,c)&&b[c]}function B(b,c){for(var d in b)if(s(b,d)&&c(b[d],d))break}function V(b,c,d,g){c&&B(c,function(c,h){if(d||!s(b,h))g&&"object"===typeof c&&c&&!H(c)&&!G(c)&&!(c instanceof
+RegExp)?(b[h]||(b[h]={}),V(b[h],c,d,g)):b[h]=c});return b}function t(b,c){return function(){return c.apply(b,arguments)}}function da(b){throw b;}function ea(b){if(!b)return b;var c=ca;v(b.split("."),function(b){c=c[b]});return c}function C(b,c,d,g){c=Error(c+"\nhttp://requirejs.org/docs/errors.html#"+b);c.requireType=b;c.requireModules=g;d&&(c.originalError=d);return c}function ha(b){function c(a,e,b){var f,n,c,d,g,h,i,I=e&&e.split("/");n=I;var m=l.map,k=m&&m["*"];if(a&&"."===a.charAt(0))if(e){n=
+I.slice(0,I.length-1);a=a.split("/");e=a.length-1;l.nodeIdCompat&&R.test(a[e])&&(a[e]=a[e].replace(R,""));n=a=n.concat(a);d=n.length;for(e=0;e<d;e++)if(c=n[e],"."===c)n.splice(e,1),e-=1;else if(".."===c)if(1===e&&(".."===n[2]||".."===n[0]))break;else 0<e&&(n.splice(e-1,2),e-=2);a=a.join("/")}else 0===a.indexOf("./")&&(a=a.substring(2));if(b&&m&&(I||k)){n=a.split("/");e=n.length;a:for(;0<e;e-=1){d=n.slice(0,e).join("/");if(I)for(c=I.length;0<c;c-=1)if(b=j(m,I.slice(0,c).join("/")))if(b=j(b,d)){f=b;
+g=e;break a}!h&&(k&&j(k,d))&&(h=j(k,d),i=e)}!f&&h&&(f=h,g=i);f&&(n.splice(0,g,f),a=n.join("/"))}return(f=j(l.pkgs,a))?f:a}function d(a){z&&v(document.getElementsByTagName("script"),function(e){if(e.getAttribute("data-requiremodule")===a&&e.getAttribute("data-requirecontext")===i.contextName)return e.parentNode.removeChild(e),!0})}function g(a){var e=j(l.paths,a);if(e&&H(e)&&1<e.length)return e.shift(),i.require.undef(a),i.require([a]),!0}function u(a){var e,b=a?a.indexOf("!"):-1;-1<b&&(e=a.substring(0,
+b),a=a.substring(b+1,a.length));return[e,a]}function m(a,e,b,f){var n,d,g=null,h=e?e.name:null,l=a,m=!0,k="";a||(m=!1,a="_@r"+(M+=1));a=u(a);g=a[0];a=a[1];g&&(g=c(g,h,f),d=j(p,g));a&&(g?k=d&&d.normalize?d.normalize(a,function(a){return c(a,h,f)}):c(a,h,f):(k=c(a,h,f),a=u(k),g=a[0],k=a[1],b=!0,n=i.nameToUrl(k)));b=g&&!d&&!b?"_unnormalized"+(Q+=1):"";return{prefix:g,name:k,parentMap:e,unnormalized:!!b,url:n,originalName:l,isDefine:m,id:(g?g+"!"+k:k)+b}}function q(a){var e=a.id,b=j(k,e);b||(b=k[e]=new i.Module(a));
+return b}function r(a,e,b){var f=a.id,n=j(k,f);if(s(p,f)&&(!n||n.defineEmitComplete))"defined"===e&&b(p[f]);else if(n=q(a),n.error&&"error"===e)b(n.error);else n.on(e,b)}function w(a,e){var b=a.requireModules,f=!1;if(e)e(a);else if(v(b,function(e){if(e=j(k,e))e.error=a,e.events.error&&(f=!0,e.emit("error",a))}),!f)h.onError(a)}function x(){S.length&&(ia.apply(A,[A.length,0].concat(S)),S=[])}function y(a){delete k[a];delete W[a]}function F(a,e,b){var f=a.map.id;a.error?a.emit("error",a.error):(e[f]=
+!0,v(a.depMaps,function(f,c){var d=f.id,g=j(k,d);g&&(!a.depMatched[c]&&!b[d])&&(j(e,d)?(a.defineDep(c,p[d]),a.check()):F(g,e,b))}),b[f]=!0)}function D(){var a,e,b=(a=1E3*l.waitSeconds)&&i.startTime+a<(new Date).getTime(),f=[],c=[],h=!1,k=!0;if(!X){X=!0;B(W,function(a){var i=a.map,m=i.id;if(a.enabled&&(i.isDefine||c.push(a),!a.error))if(!a.inited&&b)g(m)?h=e=!0:(f.push(m),d(m));else if(!a.inited&&(a.fetched&&i.isDefine)&&(h=!0,!i.prefix))return k=!1});if(b&&f.length)return a=C("timeout","Load timeout for modules: "+
+f,null,f),a.contextName=i.contextName,w(a);k&&v(c,function(a){F(a,{},{})});if((!b||e)&&h)if((z||fa)&&!Y)Y=setTimeout(function(){Y=0;D()},50);X=!1}}function E(a){s(p,a[0])||q(m(a[0],null,!0)).init(a[1],a[2])}function K(a){var a=a.currentTarget||a.srcElement,e=i.onScriptLoad;a.detachEvent&&!Z?a.detachEvent("onreadystatechange",e):a.removeEventListener("load",e,!1);e=i.onScriptError;(!a.detachEvent||Z)&&a.removeEventListener("error",e,!1);return{node:a,id:a&&a.getAttribute("data-requiremodule")}}function L(){var a;
+for(x();A.length;){a=A.shift();if(null===a[0])return w(C("mismatch","Mismatched anonymous define() module: "+a[a.length-1]));E(a)}}var X,$,i,N,Y,l={waitSeconds:7,baseUrl:"./",paths:{},bundles:{},pkgs:{},shim:{},config:{}},k={},W={},aa={},A=[],p={},T={},ba={},M=1,Q=1;N={require:function(a){return a.require?a.require:a.require=i.makeRequire(a.map)},exports:function(a){a.usingExports=!0;if(a.map.isDefine)return a.exports?p[a.map.id]=a.exports:a.exports=p[a.map.id]={}},module:function(a){return a.module?
+a.module:a.module={id:a.map.id,uri:a.map.url,config:function(){return j(l.config,a.map.id)||{}},exports:a.exports||(a.exports={})}}};$=function(a){this.events=j(aa,a.id)||{};this.map=a;this.shim=j(l.shim,a.id);this.depExports=[];this.depMaps=[];this.depMatched=[];this.pluginMaps={};this.depCount=0};$.prototype={init:function(a,e,b,f){f=f||{};if(!this.inited){this.factory=e;if(b)this.on("error",b);else this.events.error&&(b=t(this,function(a){this.emit("error",a)}));this.depMaps=a&&a.slice(0);this.errback=
+b;this.inited=!0;this.ignore=f.ignore;f.enabled||this.enabled?this.enable():this.check()}},defineDep:function(a,e){this.depMatched[a]||(this.depMatched[a]=!0,this.depCount-=1,this.depExports[a]=e)},fetch:function(){if(!this.fetched){this.fetched=!0;i.startTime=(new Date).getTime();var a=this.map;if(this.shim)i.makeRequire(this.map,{enableBuildCallback:!0})(this.shim.deps||[],t(this,function(){return a.prefix?this.callPlugin():this.load()}));else return a.prefix?this.callPlugin():this.load()}},load:function(){var a=
+this.map.url;T[a]||(T[a]=!0,i.load(this.map.id,a))},check:function(){if(this.enabled&&!this.enabling){var a,e,b=this.map.id;e=this.depExports;var f=this.exports,c=this.factory;if(this.inited)if(this.error)this.emit("error",this.error);else{if(!this.defining){this.defining=!0;if(1>this.depCount&&!this.defined){if(G(c)){if(this.events.error&&this.map.isDefine||h.onError!==da)try{f=i.execCb(b,c,e,f)}catch(d){a=d}else f=i.execCb(b,c,e,f);this.map.isDefine&&void 0===f&&((e=this.module)?f=e.exports:this.usingExports&&
+(f=this.exports));if(a)return a.requireMap=this.map,a.requireModules=this.map.isDefine?[this.map.id]:null,a.requireType=this.map.isDefine?"define":"require",w(this.error=a)}else f=c;this.exports=f;if(this.map.isDefine&&!this.ignore&&(p[b]=f,h.onResourceLoad))h.onResourceLoad(i,this.map,this.depMaps);y(b);this.defined=!0}this.defining=!1;this.defined&&!this.defineEmitted&&(this.defineEmitted=!0,this.emit("defined",this.exports),this.defineEmitComplete=!0)}}else this.fetch()}},callPlugin:function(){var a=
+this.map,b=a.id,d=m(a.prefix);this.depMaps.push(d);r(d,"defined",t(this,function(f){var d,g;g=j(ba,this.map.id);var J=this.map.name,u=this.map.parentMap?this.map.parentMap.name:null,p=i.makeRequire(a.parentMap,{enableBuildCallback:!0});if(this.map.unnormalized){if(f.normalize&&(J=f.normalize(J,function(a){return c(a,u,!0)})||""),f=m(a.prefix+"!"+J,this.map.parentMap),r(f,"defined",t(this,function(a){this.init([],function(){return a},null,{enabled:!0,ignore:!0})})),g=j(k,f.id)){this.depMaps.push(f);
+if(this.events.error)g.on("error",t(this,function(a){this.emit("error",a)}));g.enable()}}else g?(this.map.url=i.nameToUrl(g),this.load()):(d=t(this,function(a){this.init([],function(){return a},null,{enabled:!0})}),d.error=t(this,function(a){this.inited=!0;this.error=a;a.requireModules=[b];B(k,function(a){0===a.map.id.indexOf(b+"_unnormalized")&&y(a.map.id)});w(a)}),d.fromText=t(this,function(f,c){var g=a.name,J=m(g),k=O;c&&(f=c);k&&(O=!1);q(J);s(l.config,b)&&(l.config[g]=l.config[b]);try{h.exec(f)}catch(j){return w(C("fromtexteval",
+"fromText eval for "+b+" failed: "+j,j,[b]))}k&&(O=!0);this.depMaps.push(J);i.completeLoad(g);p([g],d)}),f.load(a.name,p,d,l))}));i.enable(d,this);this.pluginMaps[d.id]=d},enable:function(){W[this.map.id]=this;this.enabling=this.enabled=!0;v(this.depMaps,t(this,function(a,b){var c,f;if("string"===typeof a){a=m(a,this.map.isDefine?this.map:this.map.parentMap,!1,!this.skipMap);this.depMaps[b]=a;if(c=j(N,a.id)){this.depExports[b]=c(this);return}this.depCount+=1;r(a,"defined",t(this,function(a){this.defineDep(b,
+a);this.check()}));this.errback&&r(a,"error",t(this,this.errback))}c=a.id;f=k[c];!s(N,c)&&(f&&!f.enabled)&&i.enable(a,this)}));B(this.pluginMaps,t(this,function(a){var b=j(k,a.id);b&&!b.enabled&&i.enable(a,this)}));this.enabling=!1;this.check()},on:function(a,b){var c=this.events[a];c||(c=this.events[a]=[]);c.push(b)},emit:function(a,b){v(this.events[a],function(a){a(b)});"error"===a&&delete this.events[a]}};i={config:l,contextName:b,registry:k,defined:p,urlFetched:T,defQueue:A,Module:$,makeModuleMap:m,
+nextTick:h.nextTick,onError:w,configure:function(a){a.baseUrl&&"/"!==a.baseUrl.charAt(a.baseUrl.length-1)&&(a.baseUrl+="/");var b=l.shim,c={paths:!0,bundles:!0,config:!0,map:!0};B(a,function(a,b){c[b]?(l[b]||(l[b]={}),V(l[b],a,!0,!0)):l[b]=a});a.bundles&&B(a.bundles,function(a,b){v(a,function(a){a!==b&&(ba[a]=b)})});a.shim&&(B(a.shim,function(a,c){H(a)&&(a={deps:a});if((a.exports||a.init)&&!a.exportsFn)a.exportsFn=i.makeShimExports(a);b[c]=a}),l.shim=b);a.packages&&v(a.packages,function(a){var b,
+a="string"===typeof a?{name:a}:a;b=a.name;a.location&&(l.paths[b]=a.location);l.pkgs[b]=a.name+"/"+(a.main||"main").replace(ja,"").replace(R,"")});B(k,function(a,b){!a.inited&&!a.map.unnormalized&&(a.map=m(b))});if(a.deps||a.callback)i.require(a.deps||[],a.callback)},makeShimExports:function(a){return function(){var b;a.init&&(b=a.init.apply(ca,arguments));return b||a.exports&&ea(a.exports)}},makeRequire:function(a,e){function g(f,c,d){var j,l;e.enableBuildCallback&&(c&&G(c))&&(c.__requireJsBuild=
+!0);if("string"===typeof f){if(G(c))return w(C("requireargs","Invalid require call"),d);if(a&&s(N,f))return N[f](k[a.id]);if(h.get)return h.get(i,f,a,g);j=m(f,a,!1,!0);j=j.id;return!s(p,j)?w(C("notloaded",'Module name "'+j+'" has not been loaded yet for context: '+b+(a?"":". Use require([])"))):p[j]}L();i.nextTick(function(){L();l=q(m(null,a));l.skipMap=e.skipMap;l.init(f,c,d,{enabled:!0});D()});return g}e=e||{};V(g,{isBrowser:z,toUrl:function(b){var e,d=b.lastIndexOf("."),g=b.split("/")[0];if(-1!==
+d&&(!("."===g||".."===g)||1<d))e=b.substring(d,b.length),b=b.substring(0,d);return i.nameToUrl(c(b,a&&a.id,!0),e,!0)},defined:function(b){return s(p,m(b,a,!1,!0).id)},specified:function(b){b=m(b,a,!1,!0).id;return s(p,b)||s(k,b)}});a||(g.undef=function(b){x();var c=m(b,a,!0),e=j(k,b);d(b);delete p[b];delete T[c.url];delete aa[b];U(A,function(a,c){a[0]===b&&A.splice(c,1)});e&&(e.events.defined&&(aa[b]=e.events),y(b))});return g},enable:function(a){j(k,a.id)&&q(a).enable()},completeLoad:function(a){var b,
+c,f=j(l.shim,a)||{},d=f.exports;for(x();A.length;){c=A.shift();if(null===c[0]){c[0]=a;if(b)break;b=!0}else c[0]===a&&(b=!0);E(c)}c=j(k,a);if(!b&&!s(p,a)&&c&&!c.inited){if(l.enforceDefine&&(!d||!ea(d)))return g(a)?void 0:w(C("nodefine","No define call for "+a,null,[a]));E([a,f.deps||[],f.exportsFn])}D()},nameToUrl:function(a,b,c){var f,d,g;(f=j(l.pkgs,a))&&(a=f);if(f=j(ba,a))return i.nameToUrl(f,b,c);if(h.jsExtRegExp.test(a))f=a+(b||"");else{f=l.paths;a=a.split("/");for(d=a.length;0<d;d-=1)if(g=a.slice(0,
+d).join("/"),g=j(f,g)){H(g)&&(g=g[0]);a.splice(0,d,g);break}f=a.join("/");f+=b||(/^data\:|\?/.test(f)||c?"":".js");f=("/"===f.charAt(0)||f.match(/^[\w\+\.\-]+:/)?"":l.baseUrl)+f}return l.urlArgs?f+((-1===f.indexOf("?")?"?":"&")+l.urlArgs):f},load:function(a,b){h.load(i,a,b)},execCb:function(a,b,c,d){return b.apply(d,c)},onScriptLoad:function(a){if("load"===a.type||ka.test((a.currentTarget||a.srcElement).readyState))P=null,a=K(a),i.completeLoad(a.id)},onScriptError:function(a){var b=K(a);if(!g(b.id))return w(C("scripterror",
+"Script error for: "+b.id,a,[b.id]))}};i.require=i.makeRequire();return i}var h,x,y,D,K,E,P,L,q,Q,la=/(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,ma=/[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,R=/\.js$/,ja=/^\.\//;x=Object.prototype;var M=x.toString,ga=x.hasOwnProperty,ia=Array.prototype.splice,z=!!("undefined"!==typeof window&&"undefined"!==typeof navigator&&window.document),fa=!z&&"undefined"!==typeof importScripts,ka=z&&"PLAYSTATION 3"===navigator.platform?/^complete$/:/^(complete|loaded)$/,
+Z="undefined"!==typeof opera&&"[object Opera]"===opera.toString(),F={},r={},S=[],O=!1;if("undefined"===typeof define){if("undefined"!==typeof requirejs){if(G(requirejs))return;r=requirejs;requirejs=void 0}"undefined"!==typeof require&&!G(require)&&(r=require,require=void 0);h=requirejs=function(b,c,d,g){var u,m="_";!H(b)&&"string"!==typeof b&&(u=b,H(c)?(b=c,c=d,d=g):b=[]);u&&u.context&&(m=u.context);(g=j(F,m))||(g=F[m]=h.s.newContext(m));u&&g.configure(u);return g.require(b,c,d)};h.config=function(b){return h(b)};
+h.nextTick="undefined"!==typeof setTimeout?function(b){setTimeout(b,4)}:function(b){b()};require||(require=h);h.version="2.1.11";h.jsExtRegExp=/^\/|:|\?|\.js$/;h.isBrowser=z;x=h.s={contexts:F,newContext:ha};h({});v(["toUrl","undef","defined","specified"],function(b){h[b]=function(){var c=F._;return c.require[b].apply(c,arguments)}});if(z&&(y=x.head=document.getElementsByTagName("head")[0],D=document.getElementsByTagName("base")[0]))y=x.head=D.parentNode;h.onError=da;h.createNode=function(b){var c=
+b.xhtml?document.createElementNS("http://www.w3.org/1999/xhtml","html:script"):document.createElement("script");c.type=b.scriptType||"text/javascript";c.charset="utf-8";c.async=!0;return c};h.load=function(b,c,d){var g=b&&b.config||{};if(z)return g=h.createNode(g,c,d),g.setAttribute("data-requirecontext",b.contextName),g.setAttribute("data-requiremodule",c),g.attachEvent&&!(g.attachEvent.toString&&0>g.attachEvent.toString().indexOf("[native code"))&&!Z?(O=!0,g.attachEvent("onreadystatechange",b.onScriptLoad)):
+(g.addEventListener("load",b.onScriptLoad,!1),g.addEventListener("error",b.onScriptError,!1)),g.src=d,L=g,D?y.insertBefore(g,D):y.appendChild(g),L=null,g;if(fa)try{importScripts(d),b.completeLoad(c)}catch(j){b.onError(C("importscripts","importScripts failed for "+c+" at "+d,j,[c]))}};z&&!r.skipDataMain&&U(document.getElementsByTagName("script"),function(b){y||(y=b.parentNode);if(K=b.getAttribute("data-main"))return q=K,r.baseUrl||(E=q.split("/"),q=E.pop(),Q=E.length?E.join("/")+"/":"./",r.baseUrl=
+Q),q=q.replace(R,""),h.jsExtRegExp.test(q)&&(q=K),r.deps=r.deps?r.deps.concat(q):[q],!0});define=function(b,c,d){var g,h;"string"!==typeof b&&(d=c,c=b,b=null);H(c)||(d=c,c=null);!c&&G(d)&&(c=[],d.length&&(d.toString().replace(la,"").replace(ma,function(b,d){c.push(d)}),c=(1===d.length?["require"]:["require","exports","module"]).concat(c)));if(O){if(!(g=L))P&&"interactive"===P.readyState||U(document.getElementsByTagName("script"),function(b){if("interactive"===b.readyState)return P=b}),g=P;g&&(b||
+(b=g.getAttribute("data-requiremodule")),h=F[g.getAttribute("data-requirecontext")])}(h?h.defQueue:S).push([b,c,d])};define.amd={jQuery:!0};h.exec=function(b){return eval(b)};h(r)}})(this);

+ 10 - 10
examples/js/loaders/AWDLoader.js

@@ -735,8 +735,8 @@ THREE.AWDLoader = (function (){
         // ------------------
         // ------------------
         if ( str_type === 1 ) {
         if ( str_type === 1 ) {
 
 
-          attrib = new THREE.Float32Attribute( str_len/12, 3 );
-          buffer = attrib.array;
+          buffer = new Float32Array( ( str_len / 12 ) * 3 );
+          attrib = new THREE.BufferAttribute( buffer, 3 );
 
 
           geom.addAttribute( 'position', attrib );
           geom.addAttribute( 'position', attrib );
           idx = 0;
           idx = 0;
@@ -754,7 +754,8 @@ THREE.AWDLoader = (function (){
         // -----------------
         // -----------------
         else if (str_type === 2) {
         else if (str_type === 2) {
 
 
-          attrib = new THREE.Uint16Attribute( str_len/2, 1 );
+          buffer = new Uint16Array( str_len / 2 );
+          attrib = new THREE.BufferAttribute( buffer, 1 );
           geom.addAttribute( 'index', attrib );
           geom.addAttribute( 'index', attrib );
 
 
           geom.offsets.push({
           geom.offsets.push({
@@ -763,7 +764,6 @@ THREE.AWDLoader = (function (){
             count: str_len/2
             count: str_len/2
           });
           });
 
 
-          buffer = attrib.array;
           idx = 0;
           idx = 0;
 
 
           while (this._ptr < str_end) {
           while (this._ptr < str_end) {
@@ -778,8 +778,8 @@ THREE.AWDLoader = (function (){
         // -------------------
         // -------------------
         else if (str_type === 3) {
         else if (str_type === 3) {
 
 
-          attrib = new THREE.Float32Attribute( str_len/8, 2 );
-          buffer = attrib.array;
+          buffer = new Float32Array( ( str_len / 8 ) * 2 );
+          attrib = new THREE.BufferAttribute( buffer, 2 );
 
 
           geom.addAttribute( 'uv', attrib );
           geom.addAttribute( 'uv', attrib );
           idx = 0;
           idx = 0;
@@ -794,10 +794,10 @@ THREE.AWDLoader = (function (){
         // NORMALS
         // NORMALS
         else if (str_type === 4) {
         else if (str_type === 4) {
 
 
-          attrib = new THREE.Float32Attribute( str_len/12, 3 );
+          buffer = new Float32Array( ( str_len / 12 ) * 3 );
+          attrib = new THREE.BufferAttribute( buffer, 3 );
           geom.addAttribute( 'normal', attrib );
           geom.addAttribute( 'normal', attrib );
-          buffer = attrib.array
-          idx = 0
+          idx = 0;
 
 
           while (this._ptr < str_end) {
           while (this._ptr < str_end) {
             buffer[idx]   = -this.readF32();
             buffer[idx]   = -this.readF32();
@@ -1222,4 +1222,4 @@ THREE.AWDLoader = (function (){
 
 
   return AWDLoader;
   return AWDLoader;
 
 
-})();
+})();

+ 84 - 60
examples/js/loaders/ColladaLoader.js

@@ -1,7 +1,7 @@
 /**
 /**
- * @author Tim Knip / http://www.floorplanner.com/ / tim at floorplanner.com
- * @author Tony Parisi / http://www.tonyparisi.com/ 
- */
+* @author Tim Knip / http://www.floorplanner.com/ / tim at floorplanner.com
+* @author Tony Parisi / http://www.tonyparisi.com/
+*/
 
 
 THREE.ColladaLoader = function () {
 THREE.ColladaLoader = function () {
 
 
@@ -141,7 +141,7 @@ THREE.ColladaLoader = function () {
 		controllers = parseLib( "library_controllers controller", Controller, "controller" );
 		controllers = parseLib( "library_controllers controller", Controller, "controller" );
 		animations = parseLib( "library_animations animation", Animation, "animation" );
 		animations = parseLib( "library_animations animation", Animation, "animation" );
 		visualScenes = parseLib( "library_visual_scenes visual_scene", VisualScene, "visual_scene" );
 		visualScenes = parseLib( "library_visual_scenes visual_scene", VisualScene, "visual_scene" );
-		
+
 		morphs = [];
 		morphs = [];
 		skins = [];
 		skins = [];
 
 
@@ -260,9 +260,9 @@ THREE.ColladaLoader = function () {
 	}
 	}
 
 
 	function parseScene() {
 	function parseScene() {
-	
+
 		var sceneElement = COLLADA.querySelectorAll('scene instance_visual_scene')[0];
 		var sceneElement = COLLADA.querySelectorAll('scene instance_visual_scene')[0];
-		
+
 		if ( sceneElement ) {
 		if ( sceneElement ) {
 
 
 			var url = sceneElement.getAttribute( 'url' ).replace( /^#/, '' );
 			var url = sceneElement.getAttribute( 'url' ).replace( /^#/, '' );
@@ -351,11 +351,11 @@ THREE.ColladaLoader = function () {
 		for ( var id in animations ) {
 		for ( var id in animations ) {
 
 
 			var animation = animations[ id ];
 			var animation = animations[ id ];
-			ID = ID || animation.id; 
+			ID = ID || animation.id;
 			for ( var i = 0; i < animation.sampler.length; i ++ ) {
 			for ( var i = 0; i < animation.sampler.length; i ++ ) {
 
 
 				var sampler = animation.sampler[ i ];
 				var sampler = animation.sampler[ i ];
-				
+
 				sampler.create();
 				sampler.create();
 
 
 				start = Math.min( start, sampler.startTime );
 				start = Math.min( start, sampler.startTime );
@@ -502,9 +502,9 @@ THREE.ColladaLoader = function () {
 	function setupSkinningMatrices ( bones, skin ) {
 	function setupSkinningMatrices ( bones, skin ) {
 
 
 		// FIXME: this is dumb...
 		// FIXME: this is dumb...
-		
+
 		for ( var i = 0; i < bones.length; i ++ ) {
 		for ( var i = 0; i < bones.length; i ++ ) {
-		
+
 			var bone = bones[ i ];
 			var bone = bones[ i ];
 			var found = -1;
 			var found = -1;
 
 
@@ -534,7 +534,7 @@ THREE.ColladaLoader = function () {
 				bone.weights = [];
 				bone.weights = [];
 
 
 				for ( var j = 0; j < skin.weights.length; j ++ ) {
 				for ( var j = 0; j < skin.weights.length; j ++ ) {
-					
+
 					for (var k = 0; k < skin.weights[ j ].length; k ++ ) {
 					for (var k = 0; k < skin.weights[ j ].length; k ++ ) {
 
 
 						var w = skin.weights[ j ][ k ];
 						var w = skin.weights[ j ][ k ];
@@ -573,9 +573,9 @@ THREE.ColladaLoader = function () {
 			bone.matrix = node.matrix;
 			bone.matrix = node.matrix;
 			var data = [new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3()];
 			var data = [new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3()];
 			bone.matrix.decompose(data[0],data[1],data[2]);
 			bone.matrix.decompose(data[0],data[1],data[2]);
-							
+
 			bone.pos = [data[0].x,data[0].y,data[0].z];
 			bone.pos = [data[0].x,data[0].y,data[0].z];
-							
+
 			bone.scl = [data[2].x,data[2].y,data[2].z];
 			bone.scl = [data[2].x,data[2].y,data[2].z];
 			bone.rotq = [data[1].x,data[1].y,data[1].z,data[1].w];
 			bone.rotq = [data[1].x,data[1].y,data[1].z,data[1].w];
 			list.push(bone);
 			list.push(bone);
@@ -620,7 +620,7 @@ THREE.ColladaLoader = function () {
 
 
 				o = geometry.vertices[vidx];
 				o = geometry.vertices[vidx];
 				s = skinned[vidx];
 				s = skinned[vidx];
-				
+
 				v.x = o.x;
 				v.x = o.x;
 				v.y = o.y;
 				v.y = o.y;
 				v.z = o.z;
 				v.z = o.z;
@@ -645,8 +645,8 @@ THREE.ColladaLoader = function () {
 	function applySkin ( geometry, instanceCtrl, frame ) {
 	function applySkin ( geometry, instanceCtrl, frame ) {
 
 
 		// TODO: get this from the renderer or options
 		// TODO: get this from the renderer or options
-		var maxbones = 30;
-		
+		var maxbones = 64;
+
 		var skinController = controllers[ instanceCtrl.url ];
 		var skinController = controllers[ instanceCtrl.url ];
 
 
 		frame = frame !== undefined ? frame : 40;
 		frame = frame !== undefined ? frame : 40;
@@ -668,7 +668,7 @@ THREE.ColladaLoader = function () {
 		var animationBounds = calcAnimationBounds();
 		var animationBounds = calcAnimationBounds();
 		var skeleton = daeScene.getChildById( instanceCtrl.skeleton[0], true ) ||
 		var skeleton = daeScene.getChildById( instanceCtrl.skeleton[0], true ) ||
 					   daeScene.getChildBySid( instanceCtrl.skeleton[0], true );
 					   daeScene.getChildBySid( instanceCtrl.skeleton[0], true );
-		
+
 		//flatten the skeleton into a list of bones
 		//flatten the skeleton into a list of bones
 		var bonelist = flattenSkeleton(skeleton);
 		var bonelist = flattenSkeleton(skeleton);
 		var joints = skinController.skin.joints;
 		var joints = skinController.skin.joints;
@@ -723,7 +723,7 @@ THREE.ColladaLoader = function () {
 
 
 			var indicies = new THREE.Vector4(weights[i][0]?weights[i][0].joint:0,weights[i][1]?weights[i][1].joint:0,weights[i][2]?weights[i][2].joint:0,weights[i][3]?weights[i][3].joint:0);
 			var indicies = new THREE.Vector4(weights[i][0]?weights[i][0].joint:0,weights[i][1]?weights[i][1].joint:0,weights[i][2]?weights[i][2].joint:0,weights[i][3]?weights[i][3].joint:0);
 			var weight = new THREE.Vector4(weights[i][0]?weights[i][0].weight:0,weights[i][1]?weights[i][1].weight:0,weights[i][2]?weights[i][2].weight:0,weights[i][3]?weights[i][3].weight:0);
 			var weight = new THREE.Vector4(weights[i][0]?weights[i][0].weight:0,weights[i][1]?weights[i][1].weight:0,weights[i][2]?weights[i][2].weight:0,weights[i][3]?weights[i][3].weight:0);
-			
+
 			skinIndices.push(indicies);
 			skinIndices.push(indicies);
 			skinWeights.push(weight);
 			skinWeights.push(weight);
 
 
@@ -733,7 +733,7 @@ THREE.ColladaLoader = function () {
 		geometry.skinWeights = skinWeights;
 		geometry.skinWeights = skinWeights;
 		geometry.bones = sortedbones;
 		geometry.bones = sortedbones;
 		// process animation, or simply pose the rig if no animation
 		// process animation, or simply pose the rig if no animation
-		
+
 		//create an animation for the animated bones
 		//create an animation for the animated bones
 		//NOTE: this has no effect when using morphtargets
 		//NOTE: this has no effect when using morphtargets
 		var animationdata = {"name":animationBounds.ID,"fps":30,"length":animationBounds.frames/30,"hierarchy":[]};
 		var animationdata = {"name":animationBounds.ID,"fps":30,"length":animationBounds.frames/30,"hierarchy":[]};
@@ -744,6 +744,8 @@ THREE.ColladaLoader = function () {
 
 
 		}
 		}
 
 
+		console.log( 'ColladaLoader:', animationBounds.ID + ' has ' + sortedbones.length + ' bones.' );
+
 		//if using hardware skinning, move the vertices into the binding pose
 		//if using hardware skinning, move the vertices into the binding pose
 		if(sortedbones.length < maxbones) {
 		if(sortedbones.length < maxbones) {
 
 
@@ -773,15 +775,15 @@ THREE.ColladaLoader = function () {
 							var key = {};
 							var key = {};
 							key.time = (frame/30);
 							key.time = (frame/30);
 							key.matrix = bones[i].animatrix;
 							key.matrix = bones[i].animatrix;
-							
+
 							if(frame == 0)
 							if(frame == 0)
 								bones[i].matrix = key.matrix;
 								bones[i].matrix = key.matrix;
-							
+
 							var data = [new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3()];
 							var data = [new THREE.Vector3(),new THREE.Quaternion(),new THREE.Vector3()];
 							key.matrix.decompose(data[0],data[1],data[2]);
 							key.matrix.decompose(data[0],data[1],data[2]);
-							
+
 							key.pos = [data[0].x,data[0].y,data[0].z];
 							key.pos = [data[0].x,data[0].y,data[0].z];
-							
+
 							key.scl = [data[2].x,data[2].y,data[2].z];
 							key.scl = [data[2].x,data[2].y,data[2].z];
 							key.rot = data[1];
 							key.rot = data[1];
 
 
@@ -798,7 +800,7 @@ THREE.ColladaLoader = function () {
 			} else {
 			} else {
 
 
 				// otherwise, process the animation into morphtargets
 				// otherwise, process the animation into morphtargets
-				
+
 				for ( i = 0; i < geometry.vertices.length; i++ ) {
 				for ( i = 0; i < geometry.vertices.length; i++ ) {
 
 
 					skinned.push( new THREE.Vector3() );
 					skinned.push( new THREE.Vector3() );
@@ -832,7 +834,7 @@ THREE.ColladaLoader = function () {
 
 
 				}
 				}
 
 
-			geometry.morphTargets.push( { name: "target_" + frame, vertices: skinned } );
+				geometry.morphTargets.push( { name: "target_" + frame, vertices: skinned } );
 
 
 			}
 			}
 
 
@@ -997,7 +999,7 @@ THREE.ColladaLoader = function () {
 
 
 				if ( skinController !== undefined ) {
 				if ( skinController !== undefined ) {
 
 
-					
+
 					applySkin( geom, skinController );
 					applySkin( geom, skinController );
 
 
 					if(geom.morphTargets.length > 0) {
 					if(geom.morphTargets.length > 0) {
@@ -1010,8 +1012,8 @@ THREE.ColladaLoader = function () {
 						material.morphTargets = false;
 						material.morphTargets = false;
 						material.skinning = true;
 						material.skinning = true;
 
 
-					}				
-					
+					}
+
 
 
 					mesh = new THREE.SkinnedMesh( geom, material, false );
 					mesh = new THREE.SkinnedMesh( geom, material, false );
 
 
@@ -1021,8 +1023,8 @@ THREE.ColladaLoader = function () {
 					//mesh.skinInstanceController = skinController;
 					//mesh.skinInstanceController = skinController;
 					mesh.name = 'skin_' + skins.length;
 					mesh.name = 'skin_' + skins.length;
 
 
-					
-					
+
+
 					//mesh.animationHandle.setKey(0);
 					//mesh.animationHandle.setKey(0);
 					skins.push( mesh );
 					skins.push( mesh );
 
 
@@ -1060,7 +1062,7 @@ THREE.ColladaLoader = function () {
 			var instance_camera = node.cameras[i];
 			var instance_camera = node.cameras[i];
 			var cparams = cameras[instance_camera.url];
 			var cparams = cameras[instance_camera.url];
 
 
-			var cam = new THREE.PerspectiveCamera(cparams.yfov, parseFloat(cparams.aspect_ratio), 
+			var cam = new THREE.PerspectiveCamera(cparams.yfov, parseFloat(cparams.aspect_ratio),
 					parseFloat(cparams.znear), parseFloat(cparams.zfar));
 					parseFloat(cparams.znear), parseFloat(cparams.zfar));
 
 
 			obj.add(cam);
 			obj.add(cam);
@@ -1076,7 +1078,7 @@ THREE.ColladaLoader = function () {
 
 
 				var color = lparams.color.getHex();
 				var color = lparams.color.getHex();
 				var intensity = lparams.intensity;
 				var intensity = lparams.intensity;
-				var distance = 0;
+				var distance = lparams.distance;
 				var angle = lparams.falloff_angle;
 				var angle = lparams.falloff_angle;
 				var exponent; // Intentionally undefined, don't know what this is yet
 				var exponent; // Intentionally undefined, don't know what this is yet
 
 
@@ -1121,7 +1123,7 @@ THREE.ColladaLoader = function () {
 
 
 		if ( options.centerGeometry && obj.geometry ) {
 		if ( options.centerGeometry && obj.geometry ) {
 
 
-			var delta = THREE.GeometryUtils.center( obj.geometry );
+			var delta = obj.geometry.center();
 			delta.multiply( obj.scale );
 			delta.multiply( obj.scale );
 			delta.applyQuaternion( obj.quaternion );
 			delta.applyQuaternion( obj.quaternion );
 
 
@@ -2442,14 +2444,14 @@ THREE.ColladaLoader = function () {
 					break;
 					break;
 
 
 				case 'bind_material':
 				case 'bind_material':
-			
+
 					var instances = child.querySelectorAll('instance_material');
 					var instances = child.querySelectorAll('instance_material');
-					
+
 					for ( var j = 0; j < instances.length; j ++ ){
 					for ( var j = 0; j < instances.length; j ++ ){
 
 
 						var instance = instances[j];
 						var instance = instances[j];
 						this.instance_material.push( (new InstanceMaterial()).parse(instance) );
 						this.instance_material.push( (new InstanceMaterial()).parse(instance) );
-						
+
 					}
 					}
 
 
 
 
@@ -2503,7 +2505,7 @@ THREE.ColladaLoader = function () {
 			if ( child.nodeName == 'bind_material' ) {
 			if ( child.nodeName == 'bind_material' ) {
 
 
 				var instances = child.querySelectorAll('instance_material');
 				var instances = child.querySelectorAll('instance_material');
-					
+
 				for ( var j = 0; j < instances.length; j ++ ) {
 				for ( var j = 0; j < instances.length; j ++ ) {
 
 
 					var instance = instances[j];
 					var instance = instances[j];
@@ -2652,7 +2654,7 @@ THREE.ColladaLoader = function () {
 		var source, numParams;
 		var source, numParams;
 		var vcIndex = 0, vcount = 3, maxOffset = 0;
 		var vcIndex = 0, vcount = 3, maxOffset = 0;
 		var texture_sets = [];
 		var texture_sets = [];
-		
+
 		for ( j = 0; j < inputs.length; j ++ ) {
 		for ( j = 0; j < inputs.length; j ++ ) {
 
 
 			input = inputs[ j ];
 			input = inputs[ j ];
@@ -2821,7 +2823,7 @@ THREE.ColladaLoader = function () {
 				} else if ( vcount === 4 ) {
 				} else if ( vcount === 4 ) {
 
 
 					faces.push( new THREE.Face3( vs[0], vs[1], vs[3], [ns[0], ns[1], ns[3]], cs.length ? [cs[0], cs[1], cs[3]] : new THREE.Color() ) );
 					faces.push( new THREE.Face3( vs[0], vs[1], vs[3], [ns[0], ns[1], ns[3]], cs.length ? [cs[0], cs[1], cs[3]] : new THREE.Color() ) );
-					
+
 					faces.push( new THREE.Face3( vs[1], vs[2], vs[3], [ns[1], ns[2], ns[3]], cs.length ? [cs[1], cs[2], cs[3]] : new THREE.Color() ) );
 					faces.push( new THREE.Face3( vs[1], vs[2], vs[3], [ns[1], ns[2], ns[3]], cs.length ? [cs[1], cs[2], cs[3]] : new THREE.Color() ) );
 
 
 				} else if ( vcount > 4 && options.subdivideFaces ) {
 				} else if ( vcount > 4 && options.subdivideFaces ) {
@@ -3242,7 +3244,7 @@ THREE.ColladaLoader = function () {
 			this.opaque = element.getAttribute('opaque');
 			this.opaque = element.getAttribute('opaque');
 
 
 		}
 		}
-		
+
 		for ( var i = 0; i < element.childNodes.length; i ++ ) {
 		for ( var i = 0; i < element.childNodes.length; i ++ ) {
 
 
 			var child = element.childNodes[ i ];
 			var child = element.childNodes[ i ];
@@ -3321,17 +3323,17 @@ THREE.ColladaLoader = function () {
 
 
 				case 'wrapU':
 				case 'wrapU':
 				case 'wrapV':
 				case 'wrapV':
-					
+
 					// some dae have a value of true which becomes NaN via parseInt
 					// some dae have a value of true which becomes NaN via parseInt
 
 
 					if ( child.textContent.toUpperCase() === 'TRUE' ) {
 					if ( child.textContent.toUpperCase() === 'TRUE' ) {
-					
+
 						this.texOpts[ child.nodeName ] = 1;
 						this.texOpts[ child.nodeName ] = 1;
-					
+
 					} else {
 					} else {
-					
+
 						this.texOpts[ child.nodeName ] = parseInt( child.textContent );
 						this.texOpts[ child.nodeName ] = parseInt( child.textContent );
-					
+
 					}
 					}
 					break;
 					break;
 
 
@@ -3387,7 +3389,7 @@ THREE.ColladaLoader = function () {
 						} else if ( bumpType.toLowerCase() === "normalmap" ) {
 						} else if ( bumpType.toLowerCase() === "normalmap" ) {
 							this[ 'normal' ] = ( new ColorOrTexture() ).parse( child );
 							this[ 'normal' ] = ( new ColorOrTexture() ).parse( child );
 						} else {
 						} else {
-							console.error( "Shader.prototype.parse: Invalid value for attribute 'bumptype' (" + bumpType + 
+							console.error( "Shader.prototype.parse: Invalid value for attribute 'bumptype' (" + bumpType +
 								           ") - valid bumptypes are 'HEIGHTFIELD' and 'NORMALMAP' - defaulting to 'HEIGHTFIELD'" );
 								           ") - valid bumptypes are 'HEIGHTFIELD' and 'NORMALMAP' - defaulting to 'HEIGHTFIELD'" );
 							this[ 'bump' ] = ( new ColorOrTexture() ).parse( child );
 							this[ 'bump' ] = ( new ColorOrTexture() ).parse( child );
 						}
 						}
@@ -3431,11 +3433,8 @@ THREE.ColladaLoader = function () {
 		if (this['transparency'] !== undefined && this['transparent'] !== undefined) {
 		if (this['transparency'] !== undefined && this['transparent'] !== undefined) {
 			// convert transparent color RBG to average value
 			// convert transparent color RBG to average value
 			var transparentColor = this['transparent'];
 			var transparentColor = this['transparent'];
-			var transparencyLevel = (this.transparent.color.r +
-										this.transparent.color.g + 
-										this.transparent.color.b)
-										/ 3 * this.transparency;
-			
+			var transparencyLevel = (this.transparent.color.r + this.transparent.color.g + this.transparent.color.b) / 3 * this.transparency;
+
 			if (transparencyLevel > 0) {
 			if (transparencyLevel > 0) {
 				transparent = true;
 				transparent = true;
 				props[ 'transparent' ] = true;
 				props[ 'transparent' ] = true;
@@ -3444,16 +3443,16 @@ THREE.ColladaLoader = function () {
 			}
 			}
 
 
 		}
 		}
-		
+
 		var keys = {
 		var keys = {
-			'diffuse':'map', 
+			'diffuse':'map',
 			'ambient':'lightMap' ,
 			'ambient':'lightMap' ,
 			'specular':'specularMap',
 			'specular':'specularMap',
 			'emission':'emissionMap',
 			'emission':'emissionMap',
 			'bump':'bumpMap',
 			'bump':'bumpMap',
 			'normal':'normalMap'
 			'normal':'normalMap'
 			};
 			};
-		
+
 		for ( var prop in this ) {
 		for ( var prop in this ) {
 
 
 			switch ( prop ) {
 			switch ( prop ) {
@@ -3481,7 +3480,28 @@ THREE.ColladaLoader = function () {
 
 
 								if (image) {
 								if (image) {
 
 
-									var texture = THREE.ImageUtils.loadTexture(baseUrl + image.init_from);
+									var url = baseUrl + image.init_from;
+
+									var texture;
+									var loader = THREE.Loader.Handlers.get( url );
+
+									if ( loader !== null ) {
+
+										texture = loader.load( url );
+
+									} else {
+
+										texture = new THREE.Texture();
+										loader = new THREE.ImageLoader();
+										loader.load( url, function ( image ) {
+
+											texture.image = image;
+											texture.needsUpdate = true;
+
+										} );
+
+									}
+									
 									texture.wrapS = cot.texOpts.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
 									texture.wrapS = cot.texOpts.wrapU ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
 									texture.wrapT = cot.texOpts.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
 									texture.wrapT = cot.texOpts.wrapV ? THREE.RepeatWrapping : THREE.ClampToEdgeWrapping;
 									texture.offset.x = cot.texOpts.offsetU;
 									texture.offset.x = cot.texOpts.offsetU;
@@ -3833,7 +3853,7 @@ THREE.ColladaLoader = function () {
 					this.shader = ( new Shader( child.nodeName, this ) ).parse( child );
 					this.shader = ( new Shader( child.nodeName, this ) ).parse( child );
 					break;
 					break;
 				case 'extra':
 				case 'extra':
-					this.parseExtra(child);	
+					this.parseExtra(child);
 					break;
 					break;
 				default:
 				default:
 					break;
 					break;
@@ -3843,7 +3863,7 @@ THREE.ColladaLoader = function () {
 		}
 		}
 
 
 	};
 	};
-	
+
 	Effect.prototype.parseExtra = function ( element ) {
 	Effect.prototype.parseExtra = function ( element ) {
 
 
 		for ( var i = 0; i < element.childNodes.length; i ++ ) {
 		for ( var i = 0; i < element.childNodes.length; i ++ ) {
@@ -3864,7 +3884,7 @@ THREE.ColladaLoader = function () {
 		}
 		}
 
 
 	};
 	};
-	
+
 	Effect.prototype.parseExtraTechnique= function ( element ) {
 	Effect.prototype.parseExtraTechnique= function ( element ) {
 
 
 		for ( var i = 0; i < element.childNodes.length; i ++ ) {
 		for ( var i = 0; i < element.childNodes.length; i ++ ) {
@@ -4185,7 +4205,7 @@ THREE.ColladaLoader = function () {
 			if ( member && type == 'translate' ) {
 			if ( member && type == 'translate' ) {
 				data = getConvertedTranslation( member, data );
 				data = getConvertedTranslation( member, data );
 			}
 			}
-			
+
 		}
 		}
 
 
 		return data;
 		return data;
@@ -4515,6 +4535,10 @@ THREE.ColladaLoader = function () {
 
 
 								this.falloff_angle = parseFloat( child.textContent );
 								this.falloff_angle = parseFloat( child.textContent );
 								break;
 								break;
+
+							case 'quadratic_attenuation':
+								var f = parseFloat( child.textContent );
+								this.distance = f ? Math.sqrt( 1/f ) : 0;
 						}
 						}
 
 
 					}
 					}
@@ -4726,7 +4750,7 @@ THREE.ColladaLoader = function () {
 		obj.doubleSided = false;
 		obj.doubleSided = false;
 
 
 		var node = element.querySelectorAll('extra double_sided')[0];
 		var node = element.querySelectorAll('extra double_sided')[0];
-	
+
 		if ( node ) {
 		if ( node ) {
 
 
 			if ( node && parseInt( node.textContent, 10 ) === 1 ) {
 			if ( node && parseInt( node.textContent, 10 ) === 1 ) {

+ 347 - 0
examples/js/loaders/DDSLoader.js

@@ -0,0 +1,347 @@
+/*
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.DDSLoader = function () {};
+
+THREE.DDSLoader.prototype = {
+
+	constructor: THREE.DDSLoader,
+
+	load: function ( url, onLoad, onError ) {
+
+		var scope = this;
+
+		var images = [];
+
+		var texture = new THREE.CompressedTexture();
+		texture.image = images;
+
+		// no flipping for cube textures
+		// (also flipping doesn't work for compressed textures )
+
+		texture.flipY = false;
+
+		// can't generate mipmaps for compressed textures
+		// mips must be embedded in DDS files
+
+		texture.generateMipmaps = false;
+
+		if ( url instanceof Array ) {
+
+			var loaded = 0;
+
+			var loader = new THREE.XHRLoader();
+			loader.setResponseType( 'arraybuffer' );
+
+			var loadTexture = function ( i ) {
+		
+				loader.load( url[ i ], function ( buffer ) {
+
+					var dds = scope.parse( buffer, true );
+
+					images[ i ] = {
+						width: dds.width,
+						height: dds.height,
+						format: dds.format,
+						mipmaps: dds.mipmaps
+					}
+
+					loaded += 1;
+
+					if ( loaded === 6 ) {
+
+						texture.format = dds.format;
+						texture.needsUpdate = true;
+
+						if ( onLoad ) onLoad( texture );
+
+					}
+
+				} );
+
+			}
+
+			for ( var i = 0, il = url.length; i < il; ++ i ) {
+
+				loadTexture( i );
+
+			}
+
+		} else {
+
+			// compressed cubemap texture stored in a single DDS file
+
+			var loader = new THREE.XHRLoader();
+			loader.setResponseType( 'arraybuffer' );
+			loader.load( url, function ( buffer ) {
+
+				var dds = scope.parse( buffer, true );
+
+				if ( dds.isCubemap ) {
+
+					var faces = dds.mipmaps.length / dds.mipmapCount;
+
+					for ( var f = 0; f < faces; f ++ ) {
+
+						images[ f ] = { mipmaps : [] };
+
+						for ( var i = 0; i < dds.mipmapCount; i ++ ) {
+
+							images[ f ].mipmaps.push( dds.mipmaps[ f * dds.mipmapCount + i ] );
+							images[ f ].format = dds.format;
+							images[ f ].width = dds.width;
+							images[ f ].height = dds.height;
+
+						}
+
+					}
+
+				} else {
+
+					texture.image.width = dds.width;
+					texture.image.height = dds.height;
+					texture.mipmaps = dds.mipmaps;
+
+				}
+
+				texture.format = dds.format;
+				texture.needsUpdate = true;
+
+				if ( onLoad ) onLoad( texture );
+
+			} );
+
+		}
+
+		return texture;
+
+	},
+
+	parse: function ( buffer, loadMipmaps ) {
+
+		var dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 };
+
+		// Adapted from @toji's DDS utils
+		//	https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js
+
+		// All values and structures referenced from:
+		// http://msdn.microsoft.com/en-us/library/bb943991.aspx/
+
+		var DDS_MAGIC = 0x20534444;
+
+		var DDSD_CAPS = 0x1,
+			DDSD_HEIGHT = 0x2,
+			DDSD_WIDTH = 0x4,
+			DDSD_PITCH = 0x8,
+			DDSD_PIXELFORMAT = 0x1000,
+			DDSD_MIPMAPCOUNT = 0x20000,
+			DDSD_LINEARSIZE = 0x80000,
+			DDSD_DEPTH = 0x800000;
+
+		var DDSCAPS_COMPLEX = 0x8,
+			DDSCAPS_MIPMAP = 0x400000,
+			DDSCAPS_TEXTURE = 0x1000;
+
+		var DDSCAPS2_CUBEMAP = 0x200,
+			DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
+			DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
+			DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
+			DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
+			DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
+			DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
+			DDSCAPS2_VOLUME = 0x200000;
+
+		var DDPF_ALPHAPIXELS = 0x1,
+			DDPF_ALPHA = 0x2,
+			DDPF_FOURCC = 0x4,
+			DDPF_RGB = 0x40,
+			DDPF_YUV = 0x200,
+			DDPF_LUMINANCE = 0x20000;
+
+		function fourCCToInt32( value ) {
+
+			return value.charCodeAt(0) +
+				(value.charCodeAt(1) << 8) +
+				(value.charCodeAt(2) << 16) +
+				(value.charCodeAt(3) << 24);
+
+		}
+
+		function int32ToFourCC( value ) {
+
+			return String.fromCharCode(
+				value & 0xff,
+				(value >> 8) & 0xff,
+				(value >> 16) & 0xff,
+				(value >> 24) & 0xff
+			);
+		}
+
+		function loadARGBMip( buffer, dataOffset, width, height ) {
+			var dataLength = width*height*4;
+			var srcBuffer = new Uint8Array( buffer, dataOffset, dataLength );
+			var byteArray = new Uint8Array( dataLength );
+			var dst = 0;
+			var src = 0;
+			for ( var y = 0; y < height; y++ ) {
+				for ( var x = 0; x < width; x++ ) {
+					var b = srcBuffer[src]; src++;
+					var g = srcBuffer[src]; src++;
+					var r = srcBuffer[src]; src++;
+					var a = srcBuffer[src]; src++;
+					byteArray[dst] = r; dst++;	//r
+					byteArray[dst] = g; dst++;	//g
+					byteArray[dst] = b; dst++;	//b
+					byteArray[dst] = a; dst++;	//a
+				}
+			}
+			return byteArray;
+		}
+
+		var FOURCC_DXT1 = fourCCToInt32("DXT1");
+		var FOURCC_DXT3 = fourCCToInt32("DXT3");
+		var FOURCC_DXT5 = fourCCToInt32("DXT5");
+
+		var headerLengthInt = 31; // The header length in 32 bit ints
+
+		// Offsets into the header array
+
+		var off_magic = 0;
+
+		var off_size = 1;
+		var off_flags = 2;
+		var off_height = 3;
+		var off_width = 4;
+
+		var off_mipmapCount = 7;
+
+		var off_pfFlags = 20;
+		var off_pfFourCC = 21;
+		var off_RGBBitCount = 22;
+		var off_RBitMask = 23;
+		var off_GBitMask = 24;
+		var off_BBitMask = 25;
+		var off_ABitMask = 26;
+
+		var off_caps = 27;
+		var off_caps2 = 28;
+		var off_caps3 = 29;
+		var off_caps4 = 30;
+
+		// Parse header
+
+		var header = new Int32Array( buffer, 0, headerLengthInt );
+
+		if ( header[ off_magic ] !== DDS_MAGIC ) {
+
+			console.error( 'THREE.DDSLoader.parse: Invalid magic number in DDS header.' );
+			return dds;
+
+		}
+
+		if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) {
+
+			console.error( 'THREE.DDSLoader.parse: Unsupported format, must contain a FourCC code.' );
+			return dds;
+
+		}
+
+		var blockBytes;
+
+		var fourCC = header[ off_pfFourCC ];
+
+		var isRGBAUncompressed = false;
+
+		switch ( fourCC ) {
+
+			case FOURCC_DXT1:
+
+				blockBytes = 8;
+				dds.format = THREE.RGB_S3TC_DXT1_Format;
+				break;
+
+			case FOURCC_DXT3:
+
+				blockBytes = 16;
+				dds.format = THREE.RGBA_S3TC_DXT3_Format;
+				break;
+
+			case FOURCC_DXT5:
+
+				blockBytes = 16;
+				dds.format = THREE.RGBA_S3TC_DXT5_Format;
+				break;
+
+			default:
+
+				if( header[off_RGBBitCount] ==32 
+					&& header[off_RBitMask]&0xff0000
+					&& header[off_GBitMask]&0xff00 
+					&& header[off_BBitMask]&0xff
+					&& header[off_ABitMask]&0xff000000  ) {
+					isRGBAUncompressed = true;
+					blockBytes = 64;
+					dds.format = THREE.RGBAFormat;
+				} else {
+					console.error( 'THREE.DDSLoader.parse: Unsupported FourCC code ', int32ToFourCC( fourCC ) );
+					return dds;
+				}
+		}
+
+		dds.mipmapCount = 1;
+
+		if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) {
+
+			dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] );
+
+		}
+
+		//TODO: Verify that all faces of the cubemap are present with DDSCAPS2_CUBEMAP_POSITIVEX, etc.
+
+		dds.isCubemap = header[ off_caps2 ] & DDSCAPS2_CUBEMAP ? true : false;
+
+		dds.width = header[ off_width ];
+		dds.height = header[ off_height ];
+
+		var dataOffset = header[ off_size ] + 4;
+
+		// Extract mipmaps buffers
+
+		var width = dds.width;
+		var height = dds.height;
+
+		var faces = dds.isCubemap ? 6 : 1;
+
+		for ( var face = 0; face < faces; face ++ ) {
+
+			for ( var i = 0; i < dds.mipmapCount; i ++ ) {
+
+				if( isRGBAUncompressed ) {
+					var byteArray = loadARGBMip( buffer, dataOffset, width, height );
+					var dataLength = byteArray.length;
+				} else {
+					var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes;
+					var byteArray = new Uint8Array( buffer, dataOffset, dataLength );
+				}
+				
+				var mipmap = { "data": byteArray, "width": width, "height": height };
+				dds.mipmaps.push( mipmap );
+
+				dataOffset += dataLength;
+
+				width = Math.max( width * 0.5, 1 );
+				height = Math.max( height * 0.5, 1 );
+
+			}
+
+			width = dds.width;
+			height = dds.height;
+
+		}
+
+		return dds;
+
+	}
+
+};

+ 8 - 6
examples/js/loaders/MTLLoader.js

@@ -363,18 +363,18 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 
 
 	loadTexture: function ( url, mapping, onLoad, onError ) {
 	loadTexture: function ( url, mapping, onLoad, onError ) {
 
 
-		var isCompressed = /\.dds$/i.test( url );
+		var texture;
+		var loader = THREE.Loader.Handlers.get( url );
 
 
-		if ( isCompressed ) {
+		if ( loader !== null ) {
 
 
-			var texture = THREE.ImageUtils.loadCompressedTexture( url, mapping, onLoad, onError );
+			texture = loader.load( url, onLoad );
 
 
 		} else {
 		} else {
 
 
-			var image = new Image();
-			var texture = new THREE.Texture( image, mapping );
+			texture = new THREE.Texture();
 
 
-			var loader = new THREE.ImageLoader();
+			loader = new THREE.ImageLoader();
 			loader.crossOrigin = this.crossOrigin;
 			loader.crossOrigin = this.crossOrigin;
 			loader.load( url, function ( image ) {
 			loader.load( url, function ( image ) {
 
 
@@ -387,6 +387,8 @@ THREE.MTLLoader.MaterialCreator.prototype = {
 
 
 		}
 		}
 
 
+		texture.mapping = mapping;
+
 		return texture;
 		return texture;
 
 
 	}
 	}

+ 16 - 62
examples/js/loaders/PDBLoader.js

@@ -2,75 +2,28 @@
  * @author alteredq / http://alteredqualia.com/
  * @author alteredq / http://alteredqualia.com/
  */
  */
 
 
-THREE.PDBLoader = function () {};
+THREE.PDBLoader = function ( manager ) {
 
 
-THREE.PDBLoader.prototype = {
-
-	constructor: THREE.OBJLoader,
-
-	load: function ( url, callback ) {
-
-		var worker, scope = this;
-
-		this.loadAjaxPDB( this, url, callback );
-
-	},
-
-	loadAjaxPDB: function ( context, url, callback, callbackProgress ) {
-
-		var xhr = new XMLHttpRequest();
-
-		var length = 0;
-
-		xhr.onreadystatechange = function () {
-
-			if ( xhr.readyState === xhr.DONE ) {
-
-				if ( xhr.status === 200 || xhr.status === 0 ) {
-
-					if ( xhr.responseText ) {
-
-						var json = context.parsePDB( xhr.responseText );
-						context.createModel( json, callback );
-
-					} else {
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
 
 
-						console.warn( "THREE.PDBLoader: [" + url + "] seems to be unreachable or file there is empty" );
+};
 
 
-					}
-
-				} else {
-
-					console.error( "THREE.PDBLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
-
-				}
-
-			} else if ( xhr.readyState === xhr.LOADING ) {
-
-				if ( callbackProgress ) {
-
-					if ( length === 0 ) {
-
-						length = xhr.getResponseHeader( "Content-Length" );
-
-					}
-
-					callbackProgress( { total: length, loaded: xhr.responseText.length } );
+THREE.PDBLoader.prototype = {
 
 
-				}
+	constructor: THREE.OBJLoader,
 
 
-			} else if ( xhr.readyState === xhr.HEADERS_RECEIVED ) {
+	load: function ( url, onLoad ) {
 
 
-				length = xhr.getResponseHeader( "Content-Length" );
+		var scope = this;
 
 
-			}
+		var loader = new THREE.XHRLoader( scope.manager );
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.load( url, function ( text ) {
 
 
-		};
+			var json = scope.parsePDB( text );
+			scope.createModel( json, onLoad );
 
 
-		xhr.open( "GET", url, true );
-		if ( xhr.overrideMimeType ) xhr.overrideMimeType( "text/plain; charset=x-user-defined" );
-		xhr.setRequestHeader( "Content-Type", "text/plain" );
-		xhr.send( null );
+		} );
 
 
 	},
 	},
 
 
@@ -114,7 +67,7 @@ THREE.PDBLoader.prototype = {
 					// doesn't really work as almost all PDBs
 					// doesn't really work as almost all PDBs
 					// have just normal bonds appearing multiple
 					// have just normal bonds appearing multiple
 					// times instead of being double/triple bonds
 					// times instead of being double/triple bonds
-					//bonds[bhash[h]][2] += 1;
+					// bonds[bhash[h]][2] += 1;
 
 
 				}
 				}
 
 
@@ -194,6 +147,7 @@ THREE.PDBLoader.prototype = {
 			var r = atom[ 3 ][ 0 ] / 255;
 			var r = atom[ 3 ][ 0 ] / 255;
 			var g = atom[ 3 ][ 1 ] / 255;
 			var g = atom[ 3 ][ 1 ] / 255;
 			var b = atom[ 3 ][ 2 ] / 255;
 			var b = atom[ 3 ][ 2 ] / 255;
+
 			var color = new THREE.Color();
 			var color = new THREE.Color();
 			color.setRGB( r, g, b );
 			color.setRGB( r, g, b );
 
 
@@ -218,7 +172,7 @@ THREE.PDBLoader.prototype = {
 
 
 		}
 		}
 
 
-		callback( geometryAtoms, geometryBonds );
+		callback( geometryAtoms, geometryBonds, json );
 
 
 	}
 	}
 
 

+ 13 - 7
examples/js/loaders/STLLoader.js

@@ -108,7 +108,10 @@ THREE.STLLoader.prototype.parseBinary = function ( data ) {
 
 
 	var offset = 0;
 	var offset = 0;
 
 
-	var geometry = new THREE.Geometry2( faces );
+	var geometry = new THREE.BufferGeometry();
+
+	var vertices = new Float32Array( faces * 3 * 3 );
+	var normals = new Float32Array( faces * 3 * 3 );
 
 
 	for ( var face = 0; face < faces; face ++ ) {
 	for ( var face = 0; face < faces; face ++ ) {
 
 
@@ -118,13 +121,13 @@ THREE.STLLoader.prototype.parseBinary = function ( data ) {
 
 
 			var vertexstart = start + i * 12;
 			var vertexstart = start + i * 12;
 
 
-			geometry.vertices[ offset     ] = reader.getFloat32( vertexstart, true );
-			geometry.vertices[ offset + 1 ] = reader.getFloat32( vertexstart + 4, true );
-			geometry.vertices[ offset + 2 ] = reader.getFloat32( vertexstart + 8, true );
+			vertices[ offset     ] = reader.getFloat32( vertexstart, true );
+			vertices[ offset + 1 ] = reader.getFloat32( vertexstart + 4, true );
+			vertices[ offset + 2 ] = reader.getFloat32( vertexstart + 8, true );
 
 
-			geometry.normals[ offset     ] = reader.getFloat32( start    , true );
-			geometry.normals[ offset + 1 ] = reader.getFloat32( start + 4, true );
-			geometry.normals[ offset + 2 ] = reader.getFloat32( start + 8, true );
+			normals[ offset     ] = reader.getFloat32( start    , true );
+			normals[ offset + 1 ] = reader.getFloat32( start + 4, true );
+			normals[ offset + 2 ] = reader.getFloat32( start + 8, true );
 
 
 			offset += 3;
 			offset += 3;
 
 
@@ -132,6 +135,9 @@ THREE.STLLoader.prototype.parseBinary = function ( data ) {
 
 
 	}
 	}
 
 
+	geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
+	geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+
 	return geometry;
 	return geometry;
 
 
 };
 };

+ 31 - 0
examples/js/loaders/SVGLoader.js

@@ -0,0 +1,31 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author zz85 / http://joshuakoo.com/
+ */
+
+THREE.SVGLoader = function ( manager ) {
+
+	this.manager = ( manager !== undefined ) ? manager : THREE.DefaultLoadingManager;
+
+};
+
+THREE.SVGLoader.prototype = {
+
+	constructor: THREE.MaterialLoader,
+
+	load: function ( url, onLoad, onProgress, onError ) {
+
+		var parser = new DOMParser();
+
+		var loader = new THREE.XHRLoader();
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.load( url, function ( svgString ) {
+
+			var doc = parser.parseFromString( svgString, 'image/svg+xml' );  // application/xml
+
+			onLoad( doc.firstChild );
+
+		} );
+
+	}
+};

+ 23 - 8
src/loaders/SceneLoader.js → examples/js/loaders/SceneLoader.js

@@ -944,22 +944,25 @@ THREE.SceneLoader.prototype = {
 
 
 			}
 			}
 
 
+			var texture;
+
 			if ( textureJSON.url instanceof Array ) {
 			if ( textureJSON.url instanceof Array ) {
 
 
 				var count = textureJSON.url.length;
 				var count = textureJSON.url.length;
 				var url_array = [];
 				var url_array = [];
 
 
-				for( var i = 0; i < count; i ++ ) {
+				for ( var i = 0; i < count; i ++ ) {
 
 
 					url_array[ i ] = get_url( textureJSON.url[ i ], data.urlBaseType );
 					url_array[ i ] = get_url( textureJSON.url[ i ], data.urlBaseType );
 
 
 				}
 				}
 
 
-				var isCompressed = /\.dds$/i.test( url_array[ 0 ] );
+				var loader = THREE.Loader.Handlers.get( url_array[ 0 ] );
 
 
-				if ( isCompressed ) {
+				if ( loader !== null ) {
 
 
-					texture = THREE.ImageUtils.loadCompressedTextureCube( url_array, textureJSON.mapping, generateTextureCallback( count ) );
+					texture = loader.load( url_array, generateTextureCallback( count ) );
+					texture.mapping = textureJSON.mapping;
 
 
 				} else {
 				} else {
 
 
@@ -969,20 +972,32 @@ THREE.SceneLoader.prototype = {
 
 
 			} else {
 			} else {
 
 
-				var isCompressed = /\.dds$/i.test( textureJSON.url );
 				var fullUrl = get_url( textureJSON.url, data.urlBaseType );
 				var fullUrl = get_url( textureJSON.url, data.urlBaseType );
 				var textureCallback = generateTextureCallback( 1 );
 				var textureCallback = generateTextureCallback( 1 );
 
 
-				if ( isCompressed ) {
+				var loader = THREE.Loader.Handlers.get( fullUrl );
+
+				if ( loader !== null ) {
 
 
-					texture = THREE.ImageUtils.loadCompressedTexture( fullUrl, textureJSON.mapping, textureCallback );
+					texture = loader.load( fullUrl, textureCallback );
 
 
 				} else {
 				} else {
 
 
-					texture = THREE.ImageUtils.loadTexture( fullUrl, textureJSON.mapping, textureCallback );
+					texture = new THREE.Texture();
+					loader = new THREE.ImageLoader();
+					loader.load( fullUrl, function ( image ) {
+
+						texture.image = image;
+						texture.needsUpdate = true;
+
+						textureCallback();
+
+					} );
 
 
 				}
 				}
 
 
+				texture.mapping = textureJSON.mapping;
+
 				if ( THREE[ textureJSON.minFilter ] !== undefined )
 				if ( THREE[ textureJSON.minFilter ] !== undefined )
 					texture.minFilter = THREE[ textureJSON.minFilter ];
 					texture.minFilter = THREE[ textureJSON.minFilter ];
 
 

+ 451 - 0
examples/js/loaders/TGALoader.js

@@ -0,0 +1,451 @@
+/*
+ * @author Daosheng Mu / https://github.com/DaoshengMu/
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.TGALoader = function () {};
+
+THREE.TGALoader.prototype = {
+
+	constructor: THREE.TGALoader,
+
+	load: function ( url, onLoad, onError ) {
+		
+		var scope = this;
+		
+		var texture = new THREE.DataTexture();
+
+		var loader = new THREE.XHRLoader();
+		loader.setResponseType( 'arraybuffer' );
+		loader.load( url, function ( buffer ) {
+
+			texture.image = scope.parse( buffer );
+			texture.needsUpdate = true;
+
+			if ( onLoad ) onLoad( texture );
+
+		} );
+
+		return texture;
+
+	},
+
+	// reference from vthibault, https://github.com/vthibault/roBrowser/blob/master/src/Loaders/Targa.js
+	parse: function ( buffer ) {
+			   
+		// TGA Constants
+		var TGA_TYPE_NO_DATA = 0,
+		TGA_TYPE_INDEXED = 1,
+		TGA_TYPE_RGB = 2,
+		TGA_TYPE_GREY = 3,
+		TGA_TYPE_RLE_INDEXED = 9,
+		TGA_TYPE_RLE_RGB = 10,
+		TGA_TYPE_RLE_GREY = 11,
+
+		TGA_ORIGIN_MASK = 0x30,
+		TGA_ORIGIN_SHIFT = 0x04,
+		TGA_ORIGIN_BL = 0x00,
+		TGA_ORIGIN_BR = 0x01,
+		TGA_ORIGIN_UL = 0x02,
+		TGA_ORIGIN_UR = 0x03;
+
+		
+		if ( buffer.length < 19 )
+			console.error( 'THREE.TGALoader.parse: Not enough data to contain header.' );
+		
+		var content = new Uint8Array( buffer ),
+			offset = 0,
+			header = {
+				id_length:       content[ offset ++ ], 
+				colormap_type:   content[ offset ++ ],
+				image_type:      content[ offset ++ ],
+				colormap_index:  content[ offset ++ ] | content[ offset ++ ] << 8,
+				colormap_length: content[ offset ++ ] | content[ offset ++ ] << 8,
+				colormap_size:   content[ offset ++ ],
+
+				origin: [
+					content[ offset ++ ] | content[ offset ++ ] << 8,
+					content[ offset ++ ] | content[ offset ++ ] << 8
+				],
+				width:      content[ offset ++ ] | content[ offset ++ ] << 8,
+				height:     content[ offset ++ ] | content[ offset ++ ] << 8,
+				pixel_size: content[ offset ++ ],
+				flags:      content[ offset ++ ]
+			};
+				
+		function tgaCheckHeader( header ) {
+
+			switch( header.image_type ) {
+
+				// Check indexed type
+				case TGA_TYPE_INDEXED:
+				case TGA_TYPE_RLE_INDEXED:
+					if ( header.colormap_length > 256 || header.colormap_size !== 24 || header.colormap_type !== 1) {
+						console.error('THREE.TGALoader.parse.tgaCheckHeader: Invalid type colormap data for indexed type');
+					}
+					break;
+
+				// Check colormap type
+				case TGA_TYPE_RGB:
+				case TGA_TYPE_GREY:
+				case TGA_TYPE_RLE_RGB:
+				case TGA_TYPE_RLE_GREY:
+					if (header.colormap_type) {
+						console.error('THREE.TGALoader.parse.tgaCheckHeader: Invalid type colormap data for colormap type');
+					}
+					break;
+
+				// What the need of a file without data ?
+				case TGA_TYPE_NO_DATA:
+					console.error('THREE.TGALoader.parse.tgaCheckHeader: No data');
+
+				// Invalid type ?
+				default:
+					console.error('THREE.TGALoader.parse.tgaCheckHeader: Invalid type " '+ header.image_type + '"');
+
+			}
+
+			// Check image width and height
+			if ( header.width <= 0 || header.height <=0 ) {
+				console.error( 'THREE.TGALoader.parse.tgaCheckHeader: Invalid image size' );
+			}
+
+			// Check image pixel size 
+			if (header.pixel_size !== 8  &&
+				header.pixel_size !== 16 &&
+				header.pixel_size !== 24 &&
+				header.pixel_size !== 32) {
+				console.error('THREE.TGALoader.parse.tgaCheckHeader: Invalid pixel size "' + header.pixel_size + '"');
+			}
+
+		}
+
+		// Check tga if it is valid format
+		tgaCheckHeader( header );
+
+		if ( header.id_length + offset > buffer.length ) {
+			console.error('THREE.TGALoader.parse: No data');
+		}
+
+		// Skip the needn't data
+		offset += header.id_length;
+
+		// Get targa information about RLE compression and palette
+		var use_rle = false, 
+			use_pal = false, 
+			use_grey = false;
+	
+		switch ( header.image_type ) {
+
+			case TGA_TYPE_RLE_INDEXED:
+				use_rle = true;
+				use_pal = true;
+				break;
+
+			case TGA_TYPE_INDEXED:
+				use_pal = true;
+				break;
+				
+			case TGA_TYPE_RLE_RGB:
+				use_rle = true;
+				break;
+
+			case TGA_TYPE_RGB:
+				break;
+
+			case TGA_TYPE_RLE_GREY:
+				use_rle = true;
+				use_grey = true;
+				break;
+
+			case TGA_TYPE_GREY:
+				use_grey = true;
+				break;
+
+		}
+		
+		// Parse tga image buffer
+		function tgaParse( use_rle, use_pal, header, offset, data ) {
+			
+			var pixel_data,
+				pixel_size,
+				pixel_total,
+				palettes;
+		
+				pixel_size = header.pixel_size >> 3;
+				pixel_total = header.width * header.height * pixel_size;
+				
+			 // Read palettes
+			 if ( use_pal ) {
+				 palettes = data.subarray( offset, offset += header.colormap_length * ( header.colormap_size >> 3 ) );
+			 }
+			 
+			 // Read RLE
+			 if ( use_rle ) {
+				 pixel_data = new Uint8Array(pixel_total);
+				 
+				var c, count, i;
+				var shift = 0;
+				var pixels = new Uint8Array(pixel_size);
+
+				while (shift < pixel_total) {
+					c     = data[offset++];
+					count = (c & 0x7f) + 1;
+
+					// RLE pixels.
+					if (c & 0x80) {
+						// Bind pixel tmp array
+						for (i = 0; i < pixel_size; ++i) {
+								pixels[i] = data[offset++];
+						}
+
+						// Copy pixel array
+						for (i = 0; i < count; ++i) {
+								pixel_data.set(pixels, shift + i * pixel_size);
+						}
+
+						shift += pixel_size * count;
+
+					} else {
+						// Raw pixels.
+						count *= pixel_size;
+						for (i = 0; i < count; ++i) {
+								pixel_data[shift + i] = data[offset++];
+						}
+						shift += count;
+					}
+				}
+			 } else {
+				// RAW Pixels
+				pixel_data = data.subarray(
+					 offset, offset += (use_pal ? header.width * header.height : pixel_total)
+				);
+			 }
+			
+			 return { 
+				pixel_data: pixel_data, 
+				palettes: palettes 
+			 };
+		}
+		
+		function tgaGetImageData8bits(imageData, y_start, y_step, y_end, x_start, x_step, x_end, image, palettes) {
+
+			var colormap = palettes;
+			var color, i = 0, x, y;
+					var width = header.width;
+					
+			for (y = y_start; y !== y_end; y += y_step) {
+				for (x = x_start; x !== x_end; x += x_step, i++) {
+					color = image[i];
+					imageData[(x + width * y) * 4 + 3] = 255;
+					imageData[(x + width * y) * 4 + 2] = colormap[(color * 3) + 0];
+					imageData[(x + width * y) * 4 + 1] = colormap[(color * 3) + 1];
+					imageData[(x + width * y) * 4 + 0] = colormap[(color * 3) + 2];
+				}
+			}
+
+			return imageData;
+
+		};
+
+		function tgaGetImageData16bits(imageData, y_start, y_step, y_end, x_start, x_step, x_end, image) {
+
+			var color, i = 0, x, y;
+			var width = header.width;
+
+			for (y = y_start; y !== y_end; y += y_step) {
+				for (x = x_start; x !== x_end; x += x_step, i += 2) {
+					color = image[i + 0] + (image[i + 1] << 8); // Inversed ?
+					imageData[(x + width * y) * 4 + 0] = (color & 0x7C00) >> 7;
+					imageData[(x + width * y) * 4 + 1] = (color & 0x03E0) >> 2;
+					imageData[(x + width * y) * 4 + 2] = (color & 0x001F) >> 3;
+					imageData[(x + width * y) * 4 + 3] = (color & 0x8000) ? 0 : 255;
+				}
+			}
+
+			return imageData;
+
+		};
+
+		function tgaGetImageData24bits(imageData, y_start, y_step, y_end, x_start, x_step, x_end, image) {
+
+			var i = 0, x, y;
+			var width = header.width;
+
+			for (y = y_start; y !== y_end; y += y_step) {
+				for (x = x_start; x !== x_end; x += x_step, i += 3) {
+					imageData[(x + width * y) * 4 + 3] = 255;
+					imageData[(x + width * y) * 4 + 2] = image[i + 0];
+					imageData[(x + width * y) * 4 + 1] = image[i + 1];
+					imageData[(x + width * y) * 4 + 0] = image[i + 2];
+				}
+			}
+
+			return imageData;
+
+		};
+		
+		function tgaGetImageData32bits(imageData, y_start, y_step, y_end, x_start, x_step, x_end, image) {		
+
+			var i = 0, x, y;
+			var width = header.width;
+
+			for (y = y_start; y !== y_end; y += y_step) {
+				for (x = x_start; x !== x_end; x += x_step, i += 4) {
+					imageData[(x + width * y) * 4 + 2] = image[i + 0];
+					imageData[(x + width * y) * 4 + 1] = image[i + 1];
+					imageData[(x + width * y) * 4 + 0] = image[i + 2];
+					imageData[(x + width * y) * 4 + 3] = image[i + 3];
+				}
+			}
+
+			return imageData;
+
+		};
+
+		function tgaGetImageDataGrey8bits( imageData, y_start, y_step, y_end, x_start, x_step, x_end, image ) {
+
+			var color, i = 0, x, y;
+			var width = header.width;
+
+			for (y = y_start; y !== y_end; y += y_step) {
+				for (x = x_start; x !== x_end; x += x_step, i++) {
+					color = image[i];
+					imageData[(x + width * y) * 4 + 0] = color;
+					imageData[(x + width * y) * 4 + 1] = color;
+					imageData[(x + width * y) * 4 + 2] = color;
+					imageData[(x + width * y) * 4 + 3] = 255;
+				}
+			}
+
+			return imageData;
+
+		};
+
+		function tgaGetImageDataGrey16bits(imageData, y_start, y_step, y_end, x_start, x_step, x_end, image) {		
+
+			var i = 0, x, y;
+			var width = header.width;
+
+			for (y = y_start; y !== y_end; y += y_step) {
+				for (x = x_start; x !== x_end; x += x_step, i += 2) {
+					imageData[(x + width * y) * 4 + 0] = image[i + 0];
+					imageData[(x + width * y) * 4 + 1] = image[i + 0];
+					imageData[(x + width * y) * 4 + 2] = image[i + 0];
+					imageData[(x + width * y) * 4 + 3] = image[i + 1];
+				}
+			}
+
+			return imageData;
+
+		};
+	
+		function getTgaRGBA( width, height, image, palette ) {
+
+			var x_start,
+				y_start,
+				x_step,
+				y_step,
+				x_end,
+				y_end,                    
+				data = new Uint8Array(width * height * 4);
+				
+			switch( (header.flags & TGA_ORIGIN_MASK) >> TGA_ORIGIN_SHIFT ) {
+				default:
+				case TGA_ORIGIN_UL:
+					x_start = 0;
+					x_step = 1;
+					x_end = width;
+					y_start = 0;
+					y_step = 1;
+					y_end = height;
+					break;
+					
+				case TGA_ORIGIN_BL:
+					x_start = 0;
+					x_step = 1;
+					x_end = width;
+					y_start = height - 1;
+					y_step = -1;
+					y_end = -1;
+					break;
+					
+				case TGA_ORIGIN_UR:
+					x_start = width - 1;
+					x_step = -1;
+					x_end = -1;
+					y_start = 0;
+					y_step = 1;
+					y_end = height;
+					break;
+					
+				case TGA_ORIGIN_BR:
+					x_start = width - 1;
+					x_step = -1;
+					x_end = -1;
+					y_start = height - 1;
+					y_step = -1;
+					y_end = -1;
+					break;
+
+			}	
+				
+			if ( use_grey ) {
+				
+				switch( header.pixel_size ) {
+					case 8:
+						tgaGetImageDataGrey8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );
+						break;
+					case 16:
+						tgaGetImageDataGrey16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );
+						break;
+					default:
+						console.error( 'THREE.TGALoader.parse.getTgaRGBA: not support this format' );
+						break;
+				}
+				
+			} else {
+				
+				switch( header.pixel_size ) {
+					case 8:
+						tgaGetImageData8bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image, palette );
+						break;
+						
+					case 16:
+						tgaGetImageData16bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );
+						break;
+						
+					case 24:
+						tgaGetImageData24bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );
+						break;
+
+					case 32:
+						tgaGetImageData32bits( data, y_start, y_step, y_end, x_start, x_step, x_end, image );
+						break;
+						
+					default:
+						console.error( 'THREE.TGALoader.parse.getTgaRGBA: not support this format' );
+						break;  
+				}
+
+			}
+
+			// Load image data according to specific method
+			// var func = 'tgaGetImageData' + (use_grey ? 'Grey' : '') + (header.pixel_size) + 'bits';
+			// func(data, y_start, y_step, y_end, x_start, x_step, x_end, width, image, palette );
+			return data;
+
+		}
+		
+		var result = tgaParse( use_rle, use_pal, header, offset, content );
+		var rgbaData = getTgaRGBA( header.width, header.height, result.pixel_data, result.palettes );
+		
+		return {
+			width: header.width,
+			height: header.height,
+			data: rgbaData
+		};
+
+	}
+
+};

+ 18 - 22
examples/js/loaders/UTF8Loader.js

@@ -28,19 +28,15 @@ THREE.UTF8Loader.prototype.load = function ( jsonUrl, callback, options ) {
 THREE.UTF8Loader.BufferGeometryCreator = function () {
 THREE.UTF8Loader.BufferGeometryCreator = function () {
 };
 };
 
 
-THREE.UTF8Loader.BufferGeometryCreator.prototype.create = function ( attribArray, indexArray ) {
+THREE.UTF8Loader.BufferGeometryCreator.prototype.create = function ( attribArray, indices ) {
 
 
-	var ntris = indexArray.length / 3;
+	var ntris = indices.length / 3;
 
 
 	var geometry = new THREE.BufferGeometry();
 	var geometry = new THREE.BufferGeometry();
 
 
-    var positions = new THREE.Float32Attribute( ntris * 3, 3 );
-    var normals = new THREE.Float32Attribute( ntris * 3, 3 );
-    var uvs = new THREE.Float32Attribute( ntris * 3, 2 );
-
-	var positionsArray = positions.array;
-	var normalsArray = normals.array;
-	var uvsArray = uvs.array;
+	var positions = new Float32Array( ntris * 3 * 3 );
+	var normals = new Float32Array( ntris * 3 * 3 );
+	var uvs = new Float32Array( ntris * 3 * 2 );
 
 
 	var i, j, offset;
 	var i, j, offset;
 	var x, y, z;
 	var x, y, z;
@@ -60,9 +56,9 @@ THREE.UTF8Loader.BufferGeometryCreator.prototype.create = function ( attribArray
 		y = attribArray[ i + 1 ];
 		y = attribArray[ i + 1 ];
 		z = attribArray[ i + 2 ];
 		z = attribArray[ i + 2 ];
 
 
-		positionsArray[ j++ ] = x;
-		positionsArray[ j++ ] = y;
-		positionsArray[ j++ ] = z;
+		positions[ j++ ] = x;
+		positions[ j++ ] = y;
+		positions[ j++ ] = z;
 
 
 	}
 	}
 
 
@@ -76,8 +72,8 @@ THREE.UTF8Loader.BufferGeometryCreator.prototype.create = function ( attribArray
 		u = attribArray[ i ];
 		u = attribArray[ i ];
 		v = attribArray[ i + 1 ];
 		v = attribArray[ i + 1 ];
 
 
-		uvsArray[ j++ ] = u;
-		uvsArray[ j++ ] = v;
+		uvs[ j++ ] = u;
+		uvs[ j++ ] = v;
 
 
 	}
 	}
 
 
@@ -92,18 +88,18 @@ THREE.UTF8Loader.BufferGeometryCreator.prototype.create = function ( attribArray
 		y = attribArray[ i + 1 ];
 		y = attribArray[ i + 1 ];
 		z = attribArray[ i + 2 ];
 		z = attribArray[ i + 2 ];
 
 
-		normalsArray[ j++ ] = x;
-		normalsArray[ j++ ] = y;
-		normalsArray[ j++ ] = z;
+		normals[ j++ ] = x;
+		normals[ j++ ] = y;
+		normals[ j++ ] = z;
 
 
 	}
 	}
 
 
-    geometry.addAttribute( 'index', indexArray, 1 );
-    geometry.addAttribute( 'position', positions );
-    geometry.addAttribute( 'normal', normals );
-    geometry.addAttribute( 'uv', uvs );
+    geometry.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
+    geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+    geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+    geometry.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
 
 
-    geometry.offsets.push( { start: 0, count: indexArray.length, index: 0 } );
+    geometry.offsets.push( { start: 0, count: indices.length, index: 0 } );
 
 
 	geometry.computeBoundingSphere();
 	geometry.computeBoundingSphere();
 
 

+ 35 - 19
examples/js/loaders/ctm/CTMLoader.js

@@ -190,38 +190,54 @@ THREE.CTMLoader.prototype.load = function( url, callback, parameters ) {
 
 
 THREE.CTMLoader.prototype.createModel = function ( file, callback ) {
 THREE.CTMLoader.prototype.createModel = function ( file, callback ) {
 
 
-	var Model = function ( ) {
+	var Model = function () {
 
 
 		THREE.BufferGeometry.call( this );
 		THREE.BufferGeometry.call( this );
 
 
 		this.materials = [];
 		this.materials = [];
 
 
-		// init GL buffers
-		var vertexIndexArray = file.body.indices,
-		vertexPositionArray = file.body.vertices,
-		vertexNormalArray = file.body.normals;
+		var indices = file.body.indices,
+		positions = file.body.vertices,
+		normals = file.body.normals;
 
 
-		var vertexUvArray, vertexColorArray;
+		var uvs, colors;
+
+		var uvMaps = file.body.uvMaps;
+
+		if ( uvMaps !== undefined && uvMaps.length > 0 ) {
+
+			uvs = uvMaps[ 0 ].uv;
+
+		}
+
+		var attrMaps = file.body.attrMaps;
+
+		if ( attrMaps !== undefined && attrMaps.length > 0 && attrMaps[ 0 ].name === 'Color' ) {
+
+			colors = attrMaps[ 0 ].attr;
 
 
-		if ( file.body.uvMaps !== undefined && file.body.uvMaps.length > 0 ) {
-			vertexUvArray = file.body.uvMaps[ 0 ].uv;
 		}
 		}
 
 
-		if ( file.body.attrMaps !== undefined && file.body.attrMaps.length > 0 && file.body.attrMaps[ 0 ].name === "Color" ) {
-			vertexColorArray = file.body.attrMaps[ 0 ].attr;
+		this.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
+		this.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+
+		if ( normals !== undefined ) {
+
+			this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+
 		}
 		}
 
 
-		this.addAttribute( 'index', vertexIndexArray, 1 );
-		this.addAttribute( 'position', vertexPositionArray, 3 );
+		if ( uvs !== undefined ) {
+
+			this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
 
 
-		if ( vertexNormalArray !== undefined ) 
-			this.addAttribute( 'normal', vertexNormalArray, 3 );
+		}
+
+		if ( colors !== undefined ) {
 
 
-		if ( vertexUvArray !== undefined ) 
-			this.addAttribute( 'uv', vertexUvArray, 2 );
+			this.addAttribute( 'color', new THREE.BufferAttribute( colors, 4 ) );
 
 
-		if ( vertexColorArray !== undefined ) 
-			this.addAttribute( 'color', vertexColorArray, 4 );
+		}
 
 
 	}
 	}
 
 
@@ -238,4 +254,4 @@ THREE.CTMLoader.prototype.createModel = function ( file, callback ) {
 
 
 	callback( geometry );
 	callback( geometry );
 
 
-};
+};

+ 408 - 78
examples/js/math/Lut.js

@@ -4,51 +4,53 @@
 
 
 THREE.Lut = function ( colormap, numberofcolors ) {
 THREE.Lut = function ( colormap, numberofcolors ) {
 
 
-  this.lut = new Array();
-  this.map = THREE.ColorMapKeywords[ colormap ];
-  this.n = numberofcolors;
-  
-  var step = 1. / this.n;
-  
-  for ( var i = 0; i <= 1; i+=step ) {
-  
-    for ( var j = 0; j < this.map.length - 1; j++ ) {
-    
-      if ( i >= this.map[ j ][ 0 ] && i < this.map[ j+1 ][ 0 ] ) {
-      
-        var min = this.map[ j ][ 0 ];
-        var max = this.map[ j+1 ][ 0 ];	
-        var color = new THREE.Color( 0xffffff ); 
-        var minColor = new THREE.Color( 0xffffff ).setHex( this.map[ j ][ 1 ] );
-        var maxColor = new THREE.Color( 0xffffff ).setHex( this.map[ j+1 ][ 1 ] );	
-        			
-        color = minColor.lerp( maxColor, ( i - min ) / ( max - min ) );
-        
-        this.lut.push(color);
-        
-      }
-      
-    }
-    
-  }
-  
-  return this.set( this );
-  
+	this.lut = new Array();
+	this.map = THREE.ColorMapKeywords[ colormap ];
+	this.n = numberofcolors;
+	this.mapname = colormap;
+
+	var step = 1.0 / this.n;
+
+	for ( var i = 0; i <= 1; i += step ) {
+
+		for ( var j = 0; j < this.map.length - 1; j ++ ) {
+
+			if ( i >= this.map[ j ][ 0 ] && i < this.map[ j + 1 ][ 0 ] ) {
+
+				var min = this.map[ j ][ 0 ];
+				var max = this.map[ j + 1 ][ 0 ];
+
+				var color = new THREE.Color( 0xffffff );
+				var minColor = new THREE.Color( 0xffffff ).setHex( this.map[ j ][ 1 ] );
+				var maxColor = new THREE.Color( 0xffffff ).setHex( this.map[ j + 1 ][ 1 ] );
+
+				color = minColor.lerp( maxColor, ( i - min ) / ( max - min ) );
+
+				this.lut.push(color);
+
+			}
+
+		}
+
+	}
+
+	return this.set( this );
+
 };
 };
 
 
 THREE.Lut.prototype = {
 THREE.Lut.prototype = {
 
 
 	constructor: THREE.Lut,
 	constructor: THREE.Lut,
-  
-        lut: [], map: [], mapname: 'rainbow' , n: 256, minV: 0, maxV: 1,
-  
+
+	lut: [], map: [], mapname: 'rainbow' , n: 256, minV: 0, maxV: 1, legend: null,
+
 	set: function ( value ) {
 	set: function ( value ) {
 
 
 		if ( value instanceof THREE.Lut ) {
 		if ( value instanceof THREE.Lut ) {
 
 
 			this.copy( value );
 			this.copy( value );
 
 
-		} 
+		}
 
 
 		return this;
 		return this;
 
 
@@ -57,7 +59,7 @@ THREE.Lut.prototype = {
 	setMin: function ( min ) {
 	setMin: function ( min ) {
 
 
 		this.minV = min;
 		this.minV = min;
-		
+
 		return this;
 		return this;
 
 
 	},
 	},
@@ -65,77 +67,405 @@ THREE.Lut.prototype = {
 	setMax: function ( max ) {
 	setMax: function ( max ) {
 
 
 		this.maxV = max;
 		this.maxV = max;
-		
+
 		return this;
 		return this;
 
 
 	},
 	},
-	
+
 	changeNumberOfColors: function ( numberofcolors ) {
 	changeNumberOfColors: function ( numberofcolors ) {
 
 
 		this.n = numberofcolors;
 		this.n = numberofcolors;
-		
+
 		return new THREE.Lut( this.mapname, this.n );
 		return new THREE.Lut( this.mapname, this.n );
 
 
 	},
 	},
-	
+
 	changeColorMap: function ( colormap ) {
 	changeColorMap: function ( colormap ) {
-    
-                this.mapname = colormap;
-		
+
+		this.mapname = colormap;
+
 		return new THREE.Lut( this.mapname, this.n );
 		return new THREE.Lut( this.mapname, this.n );
 
 
 	},
 	},
-  
-        copy: function ( lut ) {
+
+	copy: function ( lut ) {
 
 
 		this.lut = lut.lut;
 		this.lut = lut.lut;
 		this.mapname = lut.mapname;
 		this.mapname = lut.mapname;
 		this.map = lut.map;
 		this.map = lut.map;
 		this.n = lut.n;
 		this.n = lut.n;
-                this.minV = lut.minV;
-                this.maxV = lut.maxV;
+		this.minV = lut.minV;
+		this.maxV = lut.maxV;
 
 
 		return this;
 		return this;
 
 
 	},
 	},
-  
+
 	getColor: function ( alpha ) {
 	getColor: function ( alpha ) {
-                
-                
-                if ( alpha <= this.minV ) {
-                
-                            alpha = this.minV;
-                
-                }
-                
-                else if ( alpha >= this.maxV ) {
-                
-                            alpha = this.maxV;               
-                
-                }
-                
-                
-                alpha = ( alpha - this.minV ) / ( this.maxV - this.minV );
-                
-                var colorPosition = Math.round ( alpha * this.n );
-                colorPosition == this.n ? colorPosition -= 1 : colorPosition;
-		
-                return this.lut[ colorPosition ];
-		
+
+		if ( alpha <= this.minV ) {
+
+			alpha = this.minV;
+
+		} else if ( alpha >= this.maxV ) {
+
+			alpha = this.maxV;
+
+		}
+
+		alpha = ( alpha - this.minV ) / ( this.maxV - this.minV );
+
+		var colorPosition = Math.round ( alpha * this.n );
+		colorPosition == this.n ? colorPosition -= 1 : colorPosition;
+
+		return this.lut[ colorPosition ];
+
+	},
+
+	addColorMap: function ( colormapName, arrayOfColors ) {
+
+		THREE.ColorMapKeywords[ colormapName ] = arrayOfColors;
+
+	},
+
+	setLegendOn: function ( parameters ) {
+
+		if ( parameters === undefined ) { parameters = {}; }
+
+		this.legend = {};
+
+		this.legend.layout = parameters.hasOwnProperty( 'layout' ) ? parameters[ 'layout' ] : 'vertical';
+
+		this.legend.position = parameters.hasOwnProperty( 'position' ) ? parameters[ 'position' ] : { 'x': 21.5, 'y': 8, 'z': 5 };
+
+		this.legend.dimensions = parameters.hasOwnProperty( 'dimensions' ) ? parameters[ 'dimensions' ] : { 'width': 0.5, 'height': 3 };
+
+		this.legend.canvas = document.createElement( 'canvas' );
+
+		this.legend.canvas.setAttribute( 'id', 'legend' );
+		this.legend.canvas.setAttribute( 'hidden', true );
+
+		document.body.appendChild( this.legend.canvas );
+
+		this.legend.ctx = this.legend.canvas.getContext( '2d' );
+
+		this.legend.canvas.setAttribute( 'width',  1 );
+		this.legend.canvas.setAttribute( 'height', this.n );
+
+		this.legend.texture = new THREE.Texture( this.legend.canvas );
+
+		imageData = this.legend.ctx.getImageData( 0, 0, 1, this.n );
+
+		data = imageData.data;
+		len = data.length;
+
+		this.map = THREE.ColorMapKeywords[ this.mapname ];
+
+		var k = 0;
+
+		var step = 1.0 / this.n;
+
+		for ( var i = 1; i >= 0; i-=step ) {
+
+			for ( var j = this.map.length - 1; j >= 0; j-- ) {
+
+				if ( i < this.map[ j ][ 0 ] && i >= this.map[ j - 1 ][ 0 ]  ) {
+
+					var min = this.map[ j - 1 ][ 0 ];
+					var max = this.map[ j ][ 0 ];
+					var color = new THREE.Color( 0xffffff );
+					var minColor = new THREE.Color( 0xffffff ).setHex( this.map[ j - 1][ 1 ] );
+					var maxColor = new THREE.Color( 0xffffff ).setHex( this.map[ j ][ 1 ] );
+					color = minColor.lerp( maxColor, ( i - min ) / ( max - min ) );
+
+					data[ k * 4     ] = Math.round( color.r * 255 );
+					data[ k * 4 + 1 ] = Math.round( color.g * 255 );
+					data[ k * 4 + 2 ] = Math.round( color.b * 255 );
+					data[ k * 4 + 3 ] = 255;
+
+					k+=1;
+
+				}
+
+			}
+
+		}
+
+		this.legend.ctx.putImageData( imageData, 0, 0 );
+		this.legend.texture.needsUpdate = true;
+
+		this.legend.legendGeometry = new THREE.PlaneGeometry( this.legend.dimensions.width , this.legend.dimensions.height );
+		this.legend.legendMaterial = new THREE.MeshBasicMaterial( { map : this.legend.texture, side : THREE.DoubleSide } );
+
+		this.legend.mesh = new THREE.Mesh( this.legend.legendGeometry, this.legend.legendMaterial );
+
+		if ( this.legend.layout == 'horizontal') {
+
+			this.legend.mesh.rotation.z = - 90 * ( Math.PI / 180 );
+
+		}
+
+		this.legend.mesh.position.copy( this.legend.position );
+
+		return this.legend.mesh;
+
 	},
 	},
 
 
-        addColorMap: function ( colormapName, arrayOfColors ) {
-        
-                THREE.ColorMapKeywords[ colormapName ] = arrayOfColors;
+	setLegendOff: function () {
+
+		this.legend = null;
+
+		return this.legend;
+
+	},
+
+	setLegendLayout: function ( layout ) {
+
+		if ( ! this.legend ) { return false; }
+
+		if ( this.legend.layout == layout ) { return false; }
+
+		if ( layout != 'horizontal' && layout != 'vertical' ) { return false; }
+
+		this.layout = layout;
+
+		if ( layout == 'horizontal' ) {
+
+			this.legend.mesh.rotation.z = 90 * ( Math.PI / 180 );
+
+		}
+
+		if ( layout == 'vertical' ) {
+
+			this.legend.mesh.rotation.z = -90 * ( Math.PI / 180 );
+
+		}
+
+		return this.legend.mesh;
+
+	},
+
+	setLegendPosition: function ( position ) {
+
+		this.legend.position = new THREE.Vector3( position.x, position.y, position.z );
+
+		return this.legend;
+
+	},
+
+	setLegendLabels: function ( parameters, callback ) {
+
+		if ( ! this.legend ) { return false; }
+
+		if ( typeof parameters === 'function') { callback = parameters; }
+
+		if ( parameters === undefined ) { parameters = {}; }
+
+		this.legend.labels = {};
+
+		this.legend.labels.fontsize = parameters.hasOwnProperty( 'fontsize' ) ? parameters[ 'fontsize' ] : 24;
+
+		this.legend.labels.fontface = parameters.hasOwnProperty( 'fontface' ) ? parameters[ 'fontface' ] : 'Arial';
+
+		this.legend.labels.title = parameters.hasOwnProperty( 'title' ) ? parameters[ 'title' ] : '';
+
+		this.legend.labels.um = parameters.hasOwnProperty( 'um' ) ? ' [ '+ parameters[ 'um' ] + ' ]': '';
+
+		this.legend.labels.ticks = parameters.hasOwnProperty( 'ticks' ) ? parameters[ 'ticks' ] : 0;
+
+		this.legend.labels.decimal = parameters.hasOwnProperty( 'decimal' ) ? parameters[ 'decimal' ] : 2;
+
+		this.legend.labels.notation = parameters.hasOwnProperty( 'notation' ) ? parameters[ 'notation' ] : 'standard';
+
+		var backgroundColor = { r: 255, g: 100, b: 100, a: 0.8 };
+		var borderColor =  { r: 255, g: 0, b: 0, a: 1.0 };
+		var borderThickness = 4;
+
+		var canvasTitle = document.createElement( 'canvas' );
+		var contextTitle = canvasTitle.getContext( '2d' );
+
+		contextTitle.font = 'Normal ' + this.legend.labels.fontsize * 1.2 + 'px ' + this.legend.labels.fontface;
+
+		var metrics = contextTitle.measureText( this.legend.labels.title.toString() + this.legend.labels.um.toString() );
+		var textWidth = metrics.width;
+
+		contextTitle.fillStyle   = 'rgba(' + backgroundColor.r + ',' + backgroundColor.g + ',' + backgroundColor.b + ',' + backgroundColor.a + ')';
+
+		contextTitle.strokeStyle = 'rgba(' + borderColor.r + ',' + borderColor.g + ',' + borderColor.b + ',' + borderColor.a + ')';
+
+		contextTitle.lineWidth = borderThickness;
+
+		contextTitle.fillStyle = 'rgba( 0, 0, 0, 1.0 )';
+
+		contextTitle.fillText( this.legend.labels.title.toString() + this.legend.labels.um.toString(), borderThickness, this.legend.labels.fontsize + borderThickness );
+
+		var txtTitle = new THREE.Texture( canvasTitle );
+
+		txtTitle.needsUpdate = true;
+
+		var spriteMaterialTitle = new THREE.SpriteMaterial( { map: txtTitle, useScreenCoordinates: false } );
+
+		var spriteTitle = new THREE.Sprite( spriteMaterialTitle );
+
+		spriteTitle.scale.set( 2, 1, 1.0 );
+
+		if ( this.legend.layout == 'vertical' ) {
+
+			spriteTitle.position.set( this.legend.position.x + this.legend.dimensions.width, this.legend.position.y + ( this.legend.dimensions.height * 0.45 ), this.legend.position.z );
+
+		}
+
+		if ( this.legend.layout == 'horizontal' ) {
+
+			spriteTitle.position.set( this.legend.position.x * 1.015, this.legend.position.y + ( this.legend.dimensions.height * 0.03 ), this.legend.position.z );
+
+		}
+
+		if ( this.legend.labels.ticks > 0 ) {
+
+			var ticks = {};
+			var lines = {};
+
+			if ( this.legend.layout == 'vertical' ) {
+
+				var topPositionY = this.legend.position.y + ( this.legend.dimensions.height * 0.36 );
+				var bottomPositionY = this.legend.position.y - ( this.legend.dimensions.height * 0.61 );
+
+			}
+
+			if ( this.legend.layout == 'horizontal' ) {
+
+				var topPositionX = this.legend.position.x + ( this.legend.dimensions.height * 0.75 );
+				var bottomPositionX = this.legend.position.x - ( this.legend.dimensions.width * 1.2  ) ;
+
+			}
+
+			for ( var i = 0; i < this.legend.labels.ticks; i++ ) {
+
+				var value = ( this.maxV - this.minV ) / ( this.legend.labels.ticks - 1  ) * i ;
+
+				if ( callback ) {
+
+					value = callback ( value );
+
+				}
+
+				else {
+
+					if ( this.legend.labels.notation == 'scientific' ) {
+
+						value = value.toExponential( this.legend.labels.decimal );
+
+					}
+
+					else {
+
+						value = value.toFixed( this.legend.labels.decimal );
+
+					}
+
+				}
+
+				var canvasTick = document.createElement( 'canvas' );
+				var contextTick = canvasTick.getContext( '2d' );
+
+				contextTick.font = 'Normal ' + this.legend.labels.fontsize + 'px ' + this.legend.labels.fontface;
+
+				var metrics = contextTick.measureText( value.toString() );
+				var textWidth = metrics.width;
+
+				contextTick.fillStyle   = 'rgba(' + backgroundColor.r + ',' + backgroundColor.g + ',' + backgroundColor.b + ',' + backgroundColor.a + ')';
+
+				contextTick.strokeStyle = 'rgba(' + borderColor.r + ',' + borderColor.g + ',' + borderColor.b + ',' + borderColor.a + ')';
+
+				contextTick.lineWidth = borderThickness;
+
+				contextTick.fillStyle = 'rgba( 0, 0, 0, 1.0 )';
+
+				contextTick.fillText( value.toString(), borderThickness, this.legend.labels.fontsize + borderThickness );
+
+				var txtTick = new THREE.Texture( canvasTick );
+
+				txtTick.needsUpdate = true;
+
+				var spriteMaterialTick = new THREE.SpriteMaterial( { map: txtTick, useScreenCoordinates: false } );
+
+				var spriteTick = new THREE.Sprite( spriteMaterialTick );
+
+				spriteTick.scale.set( 2, 1, 1.0 );
+
+				if ( this.legend.layout == 'vertical' ) {
+
+					var position = bottomPositionY + ( topPositionY - bottomPositionY ) * ( value / ( this.maxV - this.minV ) );
+
+					spriteTick.position.set( this.legend.position.x + ( this.legend.dimensions.width * 2.7 ), position, this.legend.position.z );
+
+				}
+
+				if ( this.legend.layout == 'horizontal' ) {
+
+					var position = bottomPositionX + ( topPositionX - bottomPositionX ) * ( value / ( this.maxV - this.minV ) );
+
+					if ( this.legend.labels.ticks > 5 ) {
+
+						if ( i % 2 === 0 ) { var offset = 1.7; }
+
+						else { var offset = 2.1; }
+
+					}
+
+					else { var offset = 1.7; }
+
+					spriteTick.position.set( position, this.legend.position.y - this.legend.dimensions.width * offset, this.legend.position.z );
+
+				}
+
+				var material = new THREE.LineBasicMaterial( { color: 0x000000, linewidth: 2 } );
+
+				var geometry = new THREE.Geometry();
+
+
+				if ( this.legend.layout == 'vertical' ) {
+
+					var linePosition = ( this.legend.position.y - ( this.legend.dimensions.height * 0.5 ) + 0.01 ) + ( this.legend.dimensions.height ) * ( value / ( this.maxV - this.minV ) * 0.99 );
+
+					geometry.vertices.push( new THREE.Vector3( this.legend.position.x + this.legend.dimensions.width * 0.55, linePosition , this.legend.position.z  ) );
+
+					geometry.vertices.push( new THREE.Vector3( this.legend.position.x + this.legend.dimensions.width * 0.7, linePosition, this.legend.position.z  ) );
+
+				}
+
+				if ( this.legend.layout == 'horizontal' ) {
+
+					var linePosition = ( this.legend.position.x - ( this.legend.dimensions.height * 0.5 ) + 0.01 ) + ( this.legend.dimensions.height ) * ( value / ( this.maxV - this.minV ) * 0.99 );
+
+					geometry.vertices.push( new THREE.Vector3( linePosition, this.legend.position.y - this.legend.dimensions.width * 0.55, this.legend.position.z  ) );
+
+					geometry.vertices.push( new THREE.Vector3( linePosition, this.legend.position.y - this.legend.dimensions.width * 0.7, this.legend.position.z  ) );
+
+				}
+
+				var line = new THREE.Line( geometry, material );
+
+				lines[ i ] = line;
+				ticks[ i ] = spriteTick;
+
+			}
+
+		}
+
+		return { 'title': spriteTitle,  'ticks': ticks, 'lines': lines };
+
+	}
 
 
-        },
-	
 };
 };
 
 
+
 THREE.ColorMapKeywords = {
 THREE.ColorMapKeywords = {
 
 
-                "rainbow": [ [ 0.0, '0x0000FF' ], [ 0.2, '0x00FFFF' ], [ 0.5, '0x00FF00' ], [ 0.8, '0xFFFF00'],  [1.0, '0xFF0000' ] ],
-                "cooltowarm": [ [ 0.0, '0x3C4EC2' ], [ 0.2, '0x9BBCFF' ], [ 0.5, '0xDCDCDC' ], [ 0.8, '0xF6A385'],  [1.0, '0xB40426' ] ],
-                "blackbody" : [ [ 0.0, '0x000000' ], [ 0.2, '0x780000' ], [ 0.5, '0xE63200' ], [ 0.8, '0xFFFF00'],  [1.0, '0xFFFFFF' ] ]
+  "rainbow":    [ [ 0.0, '0x0000FF' ], [ 0.2, '0x00FFFF' ], [ 0.5, '0x00FF00' ], [ 0.8, '0xFFFF00'],  [1.0, '0xFF0000' ] ],
+  "cooltowarm": [ [ 0.0, '0x3C4EC2' ], [ 0.2, '0x9BBCFF' ], [ 0.5, '0xDCDCDC' ], [ 0.8, '0xF6A385'],  [1.0, '0xB40426' ] ],
+  "blackbody" : [ [ 0.0, '0x000000' ], [ 0.2, '0x780000' ], [ 0.5, '0xE63200' ], [ 0.8, '0xFFFF00'],  [1.0, '0xFFFFFF' ] ],
+  "grayscale" : [ [ 0.0, '0x000000' ], [ 0.2, '0x404040' ], [ 0.5, '0x7F7F80' ], [ 0.8, '0xBFBFBF'],  [1.0, '0xFFFFFF' ] ]
 
 
-}
+};

+ 1 - 7
examples/js/renderers/CSS2DRenderer.js

@@ -15,12 +15,6 @@ THREE.CSS2DObject = function ( element ) {
 
 
 			this.element.parentNode.removeChild( this.element );
 			this.element.parentNode.removeChild( this.element );
 
 
-			for ( var i = 0, l = this.children.length; i < l; i ++ ) {
-
-				this.children[ i ].dispatchEvent( event );
-
-			}
-
 		}
 		}
 
 
 	} );
 	} );
@@ -33,7 +27,7 @@ THREE.CSS2DObject.prototype = Object.create( THREE.Object3D.prototype );
 
 
 THREE.CSS2DRenderer = function () {
 THREE.CSS2DRenderer = function () {
 
 
-	console.log( 'THREE.CSS3DRenderer', THREE.REVISION );
+	console.log( 'THREE.CSS2DRenderer', THREE.REVISION );
 
 
 	var _width, _height;
 	var _width, _height;
 	var _widthHalf, _heightHalf;
 	var _widthHalf, _heightHalf;

+ 0 - 6
examples/js/renderers/CSS3DRenderer.js

@@ -16,12 +16,6 @@ THREE.CSS3DObject = function ( element ) {
 
 
 			this.element.parentNode.removeChild( this.element );
 			this.element.parentNode.removeChild( this.element );
 
 
-			for ( var i = 0, l = this.children.length; i < l; i ++ ) {
-
-				this.children[ i ].dispatchEvent( event );
-
-			}
-
 		}
 		}
 
 
 	} );
 	} );

+ 9 - 16
examples/js/shaders/FXAAShader.js

@@ -49,8 +49,6 @@ THREE.FXAAShader = {
 			"vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;",
 			"vec3 rgbSE = texture2D( tDiffuse, ( gl_FragCoord.xy + vec2( 1.0, 1.0 ) ) * resolution ).xyz;",
 			"vec4 rgbaM  = texture2D( tDiffuse,  gl_FragCoord.xy  * resolution );",
 			"vec4 rgbaM  = texture2D( tDiffuse,  gl_FragCoord.xy  * resolution );",
 			"vec3 rgbM  = rgbaM.xyz;",
 			"vec3 rgbM  = rgbaM.xyz;",
-			"float opacity  = rgbaM.w;",
-
 			"vec3 luma = vec3( 0.299, 0.587, 0.114 );",
 			"vec3 luma = vec3( 0.299, 0.587, 0.114 );",
 
 
 			"float lumaNW = dot( rgbNW, luma );",
 			"float lumaNW = dot( rgbNW, luma );",
@@ -71,25 +69,20 @@ THREE.FXAAShader = {
 			"dir = min( vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX),",
 			"dir = min( vec2( FXAA_SPAN_MAX,  FXAA_SPAN_MAX),",
 				  "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),",
 				  "max( vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),",
 						"dir * rcpDirMin)) * resolution;",
 						"dir * rcpDirMin)) * resolution;",
-
-			"vec3 rgbA = texture2D( tDiffuse, gl_FragCoord.xy  * resolution + dir * ( 1.0 / 3.0 - 0.5 ) ).xyz;",
-			"rgbA += texture2D( tDiffuse, gl_FragCoord.xy  * resolution + dir * ( 2.0 / 3.0 - 0.5 ) ).xyz;",
-			"rgbA *= 0.5;",
-
-			"vec3 rgbB = texture2D( tDiffuse, gl_FragCoord.xy  * resolution + dir * -0.5 ).xyz;",
-			"rgbB += texture2D( tDiffuse, gl_FragCoord.xy  * resolution + dir * 0.5 ).xyz;",
-			"rgbB *= 0.25;",
-			"rgbB += rgbA * 0.5;",
-
-			"float lumaB = dot( rgbB, luma );",
+			"vec4 rgbA = (1.0/2.0) * (",
+        	"texture2D(tDiffuse,  gl_FragCoord.xy  * resolution + dir * (1.0/3.0 - 0.5)) +",
+			"texture2D(tDiffuse,  gl_FragCoord.xy  * resolution + dir * (2.0/3.0 - 0.5)));",
+    		"vec4 rgbB = rgbA * (1.0/2.0) + (1.0/4.0) * (",
+			"texture2D(tDiffuse,  gl_FragCoord.xy  * resolution + dir * (0.0/3.0 - 0.5)) +",
+      		"texture2D(tDiffuse,  gl_FragCoord.xy  * resolution + dir * (3.0/3.0 - 0.5)));",
+    		"float lumaB = dot(rgbB, vec4(luma, 0.0));",
 
 
 			"if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {",
 			"if ( ( lumaB < lumaMin ) || ( lumaB > lumaMax ) ) {",
 
 
-				"gl_FragColor = vec4( rgbA, opacity );",
+				"gl_FragColor = rgbA;",
 
 
 			"} else {",
 			"} else {",
-
-				"gl_FragColor = vec4( rgbB, opacity );",
+				"gl_FragColor = rgbB;",
 
 
 			"}",
 			"}",
 
 

+ 300 - 0
examples/js/utils/GeometryUtils.js

@@ -0,0 +1,300 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ * @author alteredq / http://alteredqualia.com/
+ */
+
+THREE.GeometryUtils = {
+
+	// Merge two geometries or geometry and geometry from object (using object's transform)
+
+	merge: function ( geometry1, geometry2, materialIndexOffset ) {
+
+		console.warn( 'THREE.GeometryUtils: .merge() has been moved to Geometry. Use geometry.merge( geometry2, matrix, materialIndexOffset ) instead.' );
+
+		var matrix;
+
+		if ( geometry2 instanceof THREE.Mesh ) {
+
+			geometry2.matrixAutoUpdate && geometry2.updateMatrix();
+
+			matrix = geometry2.matrix;
+			geometry2 = geometry2.geometry;
+
+		}
+
+		geometry1.merge( geometry2, matrix, materialIndexOffset );
+
+	},
+
+	// Get random point in triangle (via barycentric coordinates)
+	// 	(uniform distribution)
+	// 	http://www.cgafaq.info/wiki/Random_Point_In_Triangle
+
+	randomPointInTriangle: function () {
+
+		var vector = new THREE.Vector3();
+
+		return function ( vectorA, vectorB, vectorC ) {
+
+			var point = new THREE.Vector3();
+
+			var a = THREE.Math.random16();
+			var b = THREE.Math.random16();
+
+			if ( ( a + b ) > 1 ) {
+
+				a = 1 - a;
+				b = 1 - b;
+
+			}
+
+			var c = 1 - a - b;
+
+			point.copy( vectorA );
+			point.multiplyScalar( a );
+
+			vector.copy( vectorB );
+			vector.multiplyScalar( b );
+
+			point.add( vector );
+
+			vector.copy( vectorC );
+			vector.multiplyScalar( c );
+
+			point.add( vector );
+
+			return point;
+
+		};
+
+	}(),
+
+	// Get random point in face (triangle)
+	// (uniform distribution)
+
+	randomPointInFace: function ( face, geometry, useCachedAreas ) {
+
+		var vA, vB, vC;
+
+		vA = geometry.vertices[ face.a ];
+		vB = geometry.vertices[ face.b ];
+		vC = geometry.vertices[ face.c ];
+
+		return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
+
+	},
+
+	// Get uniformly distributed random points in mesh
+	// 	- create array with cumulative sums of face areas
+	//  - pick random number from 0 to total area
+	//  - find corresponding place in area array by binary search
+	//	- get random point in face
+
+	randomPointsInGeometry: function ( geometry, n ) {
+
+		var face, i,
+			faces = geometry.faces,
+			vertices = geometry.vertices,
+			il = faces.length,
+			totalArea = 0,
+			cumulativeAreas = [],
+			vA, vB, vC, vD;
+
+		// precompute face areas
+
+		for ( i = 0; i < il; i ++ ) {
+
+			face = faces[ i ];
+
+			vA = vertices[ face.a ];
+			vB = vertices[ face.b ];
+			vC = vertices[ face.c ];
+
+			face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC );
+
+			totalArea += face._area;
+
+			cumulativeAreas[ i ] = totalArea;
+
+		}
+
+		// binary search cumulative areas array
+
+		function binarySearchIndices( value ) {
+
+			function binarySearch( start, end ) {
+
+				// return closest larger index
+				// if exact number is not found
+
+				if ( end < start )
+					return start;
+
+				var mid = start + Math.floor( ( end - start ) / 2 );
+
+				if ( cumulativeAreas[ mid ] > value ) {
+
+					return binarySearch( start, mid - 1 );
+
+				} else if ( cumulativeAreas[ mid ] < value ) {
+
+					return binarySearch( mid + 1, end );
+
+				} else {
+
+					return mid;
+
+				}
+
+			}
+
+			var result = binarySearch( 0, cumulativeAreas.length - 1 )
+			return result;
+
+		}
+
+		// pick random face weighted by face area
+
+		var r, index,
+			result = [];
+
+		var stats = {};
+
+		for ( i = 0; i < n; i ++ ) {
+
+			r = THREE.Math.random16() * totalArea;
+
+			index = binarySearchIndices( r );
+
+			result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );
+
+			if ( ! stats[ index ] ) {
+
+				stats[ index ] = 1;
+
+			} else {
+
+				stats[ index ] += 1;
+
+			}
+
+		}
+
+		return result;
+
+	},
+
+	randomPointsInBufferGeometry: function ( geometry, n ) {
+
+		var i,
+			vertices = geometry.attributes.position.array,
+			totalArea = 0,
+			cumulativeAreas = [],
+			vA, vB, vC;
+
+		// precompute face areas
+		vA = new THREE.Vector3();
+		vB = new THREE.Vector3();
+		vC = new THREE.Vector3();
+
+		// geometry._areas = [];
+		var il = vertices.length / 9;
+
+		for ( i = 0; i < il; i ++ ) {
+
+			vA.set( vertices[i * 9 + 0], vertices[i * 9 + 1], vertices[i * 9 + 2] );
+			vB.set( vertices[i * 9 + 3], vertices[i * 9 + 4], vertices[i * 9 + 5] );
+			vC.set( vertices[i * 9 + 6], vertices[i * 9 + 7], vertices[i * 9 + 8] );
+
+			area = THREE.GeometryUtils.triangleArea( vA, vB, vC );
+			totalArea += area;
+
+			cumulativeAreas.push(totalArea);
+		}
+
+		// binary search cumulative areas array
+
+		function binarySearchIndices( value ) {
+
+			function binarySearch( start, end ) {
+
+				// return closest larger index
+				// if exact number is not found
+
+				if ( end < start )
+					return start;
+
+				var mid = start + Math.floor( ( end - start ) / 2 );
+
+				if ( cumulativeAreas[ mid ] > value ) {
+
+					return binarySearch( start, mid - 1 );
+
+				} else if ( cumulativeAreas[ mid ] < value ) {
+
+					return binarySearch( mid + 1, end );
+
+				} else {
+
+					return mid;
+
+				}
+
+			}
+
+			var result = binarySearch( 0, cumulativeAreas.length - 1 )
+			return result;
+
+		}
+
+		// pick random face weighted by face area
+
+		var r, index,
+			result = [];
+
+		for ( i = 0; i < n; i ++ ) {
+
+			r = THREE.Math.random16() * totalArea;
+
+			index = binarySearchIndices( r );
+
+			// result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );
+			vA.set( vertices[index * 9 + 0], vertices[index * 9 + 1], vertices[index * 9 + 2] );
+			vB.set( vertices[index * 9 + 3], vertices[index * 9 + 4], vertices[index * 9 + 5] );
+			vC.set( vertices[index * 9 + 6], vertices[index * 9 + 7], vertices[index * 9 + 8] );
+			result[ i ] = THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
+
+		}
+
+		return result;
+
+	},
+
+	// Get triangle area (half of parallelogram)
+	// http://mathworld.wolfram.com/TriangleArea.html
+
+	triangleArea: function () {
+
+		var vector1 = new THREE.Vector3();
+		var vector2 = new THREE.Vector3();
+
+		return function ( vectorA, vectorB, vectorC ) {
+
+			vector1.subVectors( vectorB, vectorA );
+			vector2.subVectors( vectorC, vectorA );
+			vector1.cross( vector2 );
+
+			return 0.5 * vector1.length();
+
+		};
+
+	}(),
+
+	center: function ( geometry ) {
+
+		console.warn( 'THREE.GeometryUtils: .center() has been moved to Geometry. Use geometry.center() instead.' );
+		return geometry.center();
+
+	}
+
+};

+ 0 - 2
examples/js/UVsUtils.js → examples/js/utils/UVsUtils.js

@@ -1,8 +1,6 @@
 /*
 /*
  * @author gyuque / http://github.com/gyuque
  * @author gyuque / http://github.com/gyuque
- *
  * Cylinder Mapping for ExtrudeGeometry
  * Cylinder Mapping for ExtrudeGeometry
- *
  */
  */
 
 
 THREE.UVsUtils = {
 THREE.UVsUtils = {

+ 3 - 3
examples/js/wip/CircleGeometry2.js → examples/js/wip/CircleTypedGeometry.js

@@ -3,7 +3,7 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-THREE.CircleGeometry2 = function ( radius, segments, thetaStart, thetaLength ) {
+THREE.CircleTypedGeometry = function ( radius, segments, thetaStart, thetaLength ) {
 
 
 	this.parameters = {
 	this.parameters = {
 		radius: radius,
 		radius: radius,
@@ -64,7 +64,7 @@ THREE.CircleGeometry2 = function ( radius, segments, thetaStart, thetaLength ) {
 
 
 	}
 	}
 
 
-	THREE.IndexedGeometry2.call( this );
+	THREE.IndexedTypedGeometry.call( this );
 
 
 	this.setArrays( indices, vertices, normals, uvs );
 	this.setArrays( indices, vertices, normals, uvs );
 
 
@@ -72,4 +72,4 @@ THREE.CircleGeometry2 = function ( radius, segments, thetaStart, thetaLength ) {
 
 
 };
 };
 
 
-THREE.CircleGeometry2.prototype = Object.create( THREE.IndexedGeometry2.prototype );
+THREE.CircleTypedGeometry.prototype = Object.create( THREE.IndexedTypedGeometry.prototype );

+ 3 - 3
examples/js/wip/IndexedGeometry2.js → examples/js/wip/IndexedTypedGeometry.js

@@ -2,15 +2,15 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-THREE.IndexedGeometry2 = function () {
+THREE.IndexedTypedGeometry = function () {
 
 
 	THREE.BufferGeometry.call( this );
 	THREE.BufferGeometry.call( this );
 
 
 };
 };
 
 
-THREE.IndexedGeometry2.prototype = Object.create( THREE.BufferGeometry.prototype );
+THREE.IndexedTypedGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
 
 
-THREE.IndexedGeometry2.prototype.setArrays = function ( indices, vertices, normals, uvs ) {
+THREE.IndexedTypedGeometry.prototype.setArrays = function ( indices, vertices, normals, uvs ) {
 
 
 	this.indices = indices;
 	this.indices = indices;
 	this.vertices = vertices;
 	this.vertices = vertices;

+ 3 - 3
examples/js/wip/PlaneGeometry2.js → examples/js/wip/PlaneTypedGeometry.js

@@ -3,7 +3,7 @@
  * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as
  * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as
  */
  */
 
 
-THREE.PlaneGeometry2 = function ( width, height, widthSegments, heightSegments ) {
+THREE.PlaneTypedGeometry = function ( width, height, widthSegments, heightSegments ) {
 
 
 	this.parameters = {
 	this.parameters = {
 		width: width,
 		width: width,
@@ -81,11 +81,11 @@ THREE.PlaneGeometry2 = function ( width, height, widthSegments, heightSegments )
 
 
 	}
 	}
 
 
-	THREE.IndexedGeometry2.call( this );
+	THREE.IndexedTypedGeometry.call( this );
 
 
 	this.setArrays( indices, vertices, normals, uvs );
 	this.setArrays( indices, vertices, normals, uvs );
 	this.computeBoundingSphere();
 	this.computeBoundingSphere();
 
 
 };
 };
 
 
-THREE.PlaneGeometry2.prototype = Object.create( THREE.IndexedGeometry2.prototype );
+THREE.PlaneTypedGeometry.prototype = Object.create( THREE.IndexedTypedGeometry.prototype );

+ 6 - 6
examples/js/wip/Geometry2.js → examples/js/wip/TypedGeometry.js

@@ -2,7 +2,7 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-THREE.Geometry2 = function ( size ) {
+THREE.TypedGeometry = function ( size ) {
 
 
 	THREE.BufferGeometry.call( this );
 	THREE.BufferGeometry.call( this );
 
 
@@ -20,9 +20,9 @@ THREE.Geometry2 = function ( size ) {
 
 
 };
 };
 
 
-THREE.Geometry2.prototype = Object.create( THREE.BufferGeometry.prototype );
+THREE.TypedGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
 
 
-THREE.Geometry2.prototype.setArrays = function ( vertices, normals, uvs ) {
+THREE.TypedGeometry.prototype.setArrays = function ( vertices, normals, uvs ) {
 
 
 	this.vertices = vertices;
 	this.vertices = vertices;
 	this.normals = normals;
 	this.normals = normals;
@@ -36,7 +36,7 @@ THREE.Geometry2.prototype.setArrays = function ( vertices, normals, uvs ) {
 
 
 };
 };
 
 
-THREE.Geometry2.prototype.merge = ( function () {
+THREE.TypedGeometry.prototype.merge = ( function () {
 
 
 	var offset = 0;
 	var offset = 0;
 	var normalMatrix = new THREE.Matrix3();
 	var normalMatrix = new THREE.Matrix3();
@@ -52,7 +52,7 @@ THREE.Geometry2.prototype.merge = ( function () {
 		var normals = this.attributes[ 'normal' ].array;
 		var normals = this.attributes[ 'normal' ].array;
 		var uvs = this.attributes[ 'uv' ].array;
 		var uvs = this.attributes[ 'uv' ].array;
 
 
-		if ( geometry instanceof THREE.Geometry2 ) {
+		if ( geometry instanceof THREE.TypedGeometry ) {
 
 
 			var vertices2 = geometry.attributes[ 'position' ].array;
 			var vertices2 = geometry.attributes[ 'position' ].array;
 			var normals2 = geometry.attributes[ 'normal' ].array;
 			var normals2 = geometry.attributes[ 'normal' ].array;
@@ -73,7 +73,7 @@ THREE.Geometry2.prototype.merge = ( function () {
 
 
 			}
 			}
 
 
-		} else if ( geometry instanceof THREE.IndexedGeometry2 ) {
+		} else if ( geometry instanceof THREE.IndexedTypedGeometry ) {
 
 
 			var indices2 = geometry.attributes[ 'index' ].array;
 			var indices2 = geometry.attributes[ 'index' ].array;
 			var vertices2 = geometry.attributes[ 'position' ].array;
 			var vertices2 = geometry.attributes[ 'position' ].array;

+ 7 - 7
examples/misc_controls_fly.html

@@ -206,17 +206,17 @@
 
 
 				var stars;
 				var stars;
 				var starsMaterials = [
 				var starsMaterials = [
-					new THREE.ParticleSystemMaterial( { color: 0x555555, size: 2, sizeAttenuation: false } ),
-					new THREE.ParticleSystemMaterial( { color: 0x555555, size: 1, sizeAttenuation: false } ),
-					new THREE.ParticleSystemMaterial( { color: 0x333333, size: 2, sizeAttenuation: false } ),
-					new THREE.ParticleSystemMaterial( { color: 0x3a3a3a, size: 1, sizeAttenuation: false } ),
-					new THREE.ParticleSystemMaterial( { color: 0x1a1a1a, size: 2, sizeAttenuation: false } ),
-					new THREE.ParticleSystemMaterial( { color: 0x1a1a1a, size: 1, sizeAttenuation: false } )
+					new THREE.PointCloudMaterial( { color: 0x555555, size: 2, sizeAttenuation: false } ),
+					new THREE.PointCloudMaterial( { color: 0x555555, size: 1, sizeAttenuation: false } ),
+					new THREE.PointCloudMaterial( { color: 0x333333, size: 2, sizeAttenuation: false } ),
+					new THREE.PointCloudMaterial( { color: 0x3a3a3a, size: 1, sizeAttenuation: false } ),
+					new THREE.PointCloudMaterial( { color: 0x1a1a1a, size: 2, sizeAttenuation: false } ),
+					new THREE.PointCloudMaterial( { color: 0x1a1a1a, size: 1, sizeAttenuation: false } )
 				];
 				];
 
 
 				for ( i = 10; i < 30; i ++ ) {
 				for ( i = 10; i < 30; i ++ ) {
 
 
-					stars = new THREE.ParticleSystem( starsGeometry[ i % 2 ], starsMaterials[ i % 6 ] );
+					stars = new THREE.PointCloud( starsGeometry[ i % 2 ], starsMaterials[ i % 6 ] );
 
 
 					stars.rotation.x = Math.random() * 6;
 					stars.rotation.x = Math.random() * 6;
 					stars.rotation.y = Math.random() * 6;
 					stars.rotation.y = Math.random() * 6;

+ 11 - 0
examples/misc_controls_orbit.html

@@ -55,12 +55,20 @@
 			init();
 			init();
 			render();
 			render();
 
 
+			function animate() {
+
+				requestAnimationFrame(animate);
+				controls.update();
+
+			}
+
 			function init() {
 			function init() {
 
 
 				camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
 				camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
 				camera.position.z = 500;
 				camera.position.z = 500;
 
 
 				controls = new THREE.OrbitControls( camera );
 				controls = new THREE.OrbitControls( camera );
+				controls.damping = 0.2;
 				controls.addEventListener( 'change', render );
 				controls.addEventListener( 'change', render );
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
@@ -117,6 +125,9 @@
 
 
 				window.addEventListener( 'resize', onWindowResize, false );
 				window.addEventListener( 'resize', onWindowResize, false );
 
 
+				controls.addEventListener('change', render);
+				animate();
+
 			}
 			}
 
 
 			function onWindowResize() {
 			function onWindowResize() {

+ 1 - 1
examples/misc_uv_tests.html

@@ -6,7 +6,7 @@
 	</head>
 	</head>
 	<body>
 	<body>
 		<script src="../build/three.min.js"></script>
 		<script src="../build/three.min.js"></script>
-		<script src="js/UVsUtils.js"></script>
+		<script src="js/utils/UVsUtils.js"></script>
 		<script>
 		<script>
 			/* 
 			/* 
 			 * This is to help debug UVs problems in geometry, 
 			 * This is to help debug UVs problems in geometry, 

File diff suppressed because it is too large
+ 9 - 0
examples/models/json/pressure.json


File diff suppressed because it is too large
+ 11 - 0
examples/scenes/robo_pigeon.js


BIN
examples/scenes/robo_pigeon.pack


BIN
examples/textures/crate_color8.tga


BIN
examples/textures/crate_grey8.tga


BIN
examples/textures/pano.webm


+ 3 - 6
examples/webgl_animation_cloth.html

@@ -231,15 +231,12 @@
 
 
 				// ground
 				// ground
 
 
-				var initColor = new THREE.Color( 0x497f13 );
-				var initTexture = THREE.ImageUtils.generateDataTexture( 1, 1, initColor );
-
-				var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: initTexture } );
-
-				var groundTexture = THREE.ImageUtils.loadTexture( "textures/terrain/grasslight-big.jpg", undefined, function() { groundMaterial.map = groundTexture } );
+				var groundTexture = THREE.ImageUtils.loadTexture( "textures/terrain/grasslight-big.jpg" );
 				groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
 				groundTexture.wrapS = groundTexture.wrapT = THREE.RepeatWrapping;
 				groundTexture.repeat.set( 25, 25 );
 				groundTexture.repeat.set( 25, 25 );
 				groundTexture.anisotropy = 16;
 				groundTexture.anisotropy = 16;
+				
+				var groundMaterial = new THREE.MeshPhongMaterial( { color: 0xffffff, specular: 0x111111, map: groundTexture } );
 
 
 				var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 20000, 20000 ), groundMaterial );
 				var mesh = new THREE.Mesh( new THREE.PlaneGeometry( 20000, 20000 ), groundMaterial );
 				mesh.position.y = -250;
 				mesh.position.y = -250;

+ 2 - 2
examples/webgl_animation_skinning_blending.html

@@ -35,7 +35,7 @@
 
 
 		<script src="js/Detector.js"></script>
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
-		<script src="js/Controls/OrbitControls.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
 		<script src="js/BlendCharacter.js"></script>
 		<script src="js/BlendCharacter.js"></script>
 		<script src="js/BlendCharacterGui.js"></script>
 		<script src="js/BlendCharacterGui.js"></script>
 		<script src="js/libs/dat.gui.min.js"></script>
 		<script src="js/libs/dat.gui.min.js"></script>
@@ -64,7 +64,7 @@
 				scene.add ( new THREE.AmbientLight( 0xaaaaaa ) );
 				scene.add ( new THREE.AmbientLight( 0xaaaaaa ) );
 
 
 				var light = new THREE.DirectionalLight( 0xffffff, 1.5 );
 				var light = new THREE.DirectionalLight( 0xffffff, 1.5 );
-				light.position = new THREE.Vector3( 0, 0, 1000.0 );
+				light.position.set( 0, 0, 1000 );
 				scene.add( light );
 				scene.add( light );
 
 
 				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );
 				renderer = new THREE.WebGLRenderer( { antialias: true, alpha: false } );

+ 1 - 3
examples/webgl_animation_skinning_morph.html

@@ -207,8 +207,6 @@
 				geometry.computeBoundingBox();
 				geometry.computeBoundingBox();
 				var bb = geometry.boundingBox;
 				var bb = geometry.boundingBox;
 
 
-				THREE.AnimationHandler.add( geometry.animation );
-
 				var path = "textures/cube/Park2/";
 				var path = "textures/cube/Park2/";
 				var format = '.jpg';
 				var format = '.jpg';
 				var urls = [
 				var urls = [
@@ -261,7 +259,7 @@
 				helper.visible = false;
 				helper.visible = false;
 				scene.add( helper );
 				scene.add( helper );
 
 
-				var animation = new THREE.Animation( mesh, geometry.animation.name );
+				var animation = new THREE.Animation( mesh, geometry.animation );
 				animation.play();
 				animation.play();
 
 
 			}
 			}

+ 9 - 9
examples/webgl_buffergeometry.html

@@ -82,11 +82,6 @@
 
 
 				var geometry = new THREE.BufferGeometry();
 				var geometry = new THREE.BufferGeometry();
 
 
-				geometry.addAttribute( 'index', new Uint16Array( triangles * 3 ), 1 );
-				geometry.addAttribute( 'position', new Float32Array( triangles * 3 * 3 ), 3 );
-				geometry.addAttribute( 'normal', new Float32Array( triangles * 3 * 3 ), 3 );
-				geometry.addAttribute( 'color', new Float32Array( triangles * 3 * 3 ), 3 );
-
 				// break geometry into
 				// break geometry into
 				// chunks of 21,845 triangles (3 unique vertices per triangle)
 				// chunks of 21,845 triangles (3 unique vertices per triangle)
 				// for indices to fit into 16 bit integer number
 				// for indices to fit into 16 bit integer number
@@ -94,7 +89,7 @@
 
 
 				var chunkSize = 21845;
 				var chunkSize = 21845;
 
 
-				var indices = geometry.getAttribute( 'index' ).array;
+				var indices = new Uint16Array( triangles * 3 );
 
 
 				for ( var i = 0; i < indices.length; i ++ ) {
 				for ( var i = 0; i < indices.length; i ++ ) {
 
 
@@ -102,9 +97,9 @@
 
 
 				}
 				}
 
 
-				var positions = geometry.getAttribute( 'position' ).array;
-				var normals = geometry.getAttribute( 'normal' ).array;
-				var colors = geometry.getAttribute( 'color' ).array;
+				var positions = new Float32Array( triangles * 3 * 3 );
+				var normals = new Float32Array( triangles * 3 * 3 );
+				var colors = new Float32Array( triangles * 3 * 3 );
 
 
 				var color = new THREE.Color();
 				var color = new THREE.Color();
 
 
@@ -200,6 +195,11 @@
 
 
 				}
 				}
 
 
+				geometry.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
+				geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+				geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
+
 				var offsets = triangles / chunkSize;
 				var offsets = triangles / chunkSize;
 
 
 				for ( var i = 0; i < offsets; i ++ ) {
 				for ( var i = 0; i < offsets; i ++ ) {

+ 40 - 50
examples/webgl_buffergeometry_custom_attributes_particles.html

@@ -1,41 +1,37 @@
 <!DOCTYPE html>
 <!DOCTYPE html>
 <html lang="en">
 <html lang="en">
 	<head>
 	<head>
-		<title>three.js webgl - buffer geometry custom attributes [particles]</title>
+		<title>three.js webgl - buffer geometry custom attributes - particles</title>
 		<meta charset="utf-8">
 		<meta charset="utf-8">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
 		<style>
 			body {
 			body {
 				color: #ffffff;
 				color: #ffffff;
-				font-family:Monospace;
-				font-size:13px;
-				text-align:center;
-				font-weight: bold;
-
 				background-color: #000000;
 				background-color: #000000;
 				margin: 0px;
 				margin: 0px;
 				overflow: hidden;
 				overflow: hidden;
 			}
 			}
 			#info {
 			#info {
-				color: #fff;
-				background-color: rgba( 0, 0, 0, 0.75 );
-				position: relative;
-				top: 0px; width: 100%;
+				position: absolute;
+				top: 0px;
+				width: 100%;
 				padding: 5px;
 				padding: 5px;
-				z-index:100;
-				width:33em;
-				margin:0 auto -2em;
+				font-family: Monospace;
+				font-size: 13px;
+				text-align: center;
+				font-weight: bold;
+			}
+			a {
+				color: #fff;
 			}
 			}
-			a { color: #ff0000 }
 		</style>
 		</style>
 	</head>
 	</head>
 
 
 	<body>
 	<body>
-		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> - buffergeometry custom attributes example - particles</div>
 		<div id="container"></div>
 		<div id="container"></div>
+		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> webgl - buffergeometry custom attributes - particles</div>
 
 
 		<script src="../build/three.min.js"></script>
 		<script src="../build/three.min.js"></script>
-		<script src="../src/renderers/WebGLRenderer.js"></script>
 
 
 		<script src="js/Detector.js"></script>
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
@@ -53,7 +49,6 @@
 
 
 				vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
 				vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
 
 
-				//gl_PointSize = size;
 				gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );
 				gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );
 
 
 				gl_Position = projectionMatrix * mvPosition;
 				gl_Position = projectionMatrix * mvPosition;
@@ -72,6 +67,7 @@
 			void main() {
 			void main() {
 
 
 				gl_FragColor = vec4( color * vColor, 1.0 );
 				gl_FragColor = vec4( color * vColor, 1.0 );
+
 				gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
 				gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
 
 
 			}
 			}
@@ -85,10 +81,7 @@
 
 
 		var renderer, scene, camera, stats;
 		var renderer, scene, camera, stats;
 
 
-		var sphere, uniforms, geometry;
-
-		var noise = [];
-		var values_size;
+		var particleSystem, uniforms, geometry;
 
 
 		var particles = 100000;
 		var particles = 100000;
 
 
@@ -107,7 +100,7 @@
 
 
 			var attributes = {
 			var attributes = {
 
 
-				size: {	type: 'f', value: null },
+				size:        { type: 'f', value: null },
 				customColor: { type: 'c', value: null }
 				customColor: { type: 'c', value: null }
 
 
 			};
 			};
@@ -115,20 +108,20 @@
 			uniforms = {
 			uniforms = {
 
 
 				color:     { type: "c", value: new THREE.Color( 0xffffff ) },
 				color:     { type: "c", value: new THREE.Color( 0xffffff ) },
-				texture:   { type: "t", value: THREE.ImageUtils.loadTexture( "textures/sprites/spark1.png" ) },
+				texture:   { type: "t", value: THREE.ImageUtils.loadTexture( "textures/sprites/spark1.png" ) }
 
 
 			};
 			};
 
 
 			var shaderMaterial = new THREE.ShaderMaterial( {
 			var shaderMaterial = new THREE.ShaderMaterial( {
 
 
-				uniforms: 		uniforms,
+				uniforms:       uniforms,
 				attributes:     attributes,
 				attributes:     attributes,
 				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
 				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
 				fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
 				fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
 
 
-				blending: 		THREE.AdditiveBlending,
-				depthTest: 		false,
-				transparent:	true
+				blending:       THREE.AdditiveBlending,
+				depthTest:      false,
+				transparent:    true
 
 
 			});
 			});
 
 
@@ -137,32 +130,21 @@
 
 
 			geometry = new THREE.BufferGeometry();
 			geometry = new THREE.BufferGeometry();
 
 
-			geometry.addAttribute( 'position', new Float32Array( particles * 3 ), 3 );
-			geometry.addAttribute( 'customColor', new Float32Array( particles * 3 ), 3 );
-			geometry.addAttribute( 'size', new Float32Array( particles ), 1 );
-
-			var positions = geometry.getAttribute( 'position' ).array;
-			var values_color = geometry.getAttribute( 'customColor' ).array;
-			values_size = geometry.getAttribute( 'size' ).array;
-
-			sphere = new THREE.ParticleSystem( geometry, shaderMaterial );
-
-			// sphere.sortParticles = true;
+			var positions = new Float32Array( particles * 3 );
+			var values_color = new Float32Array( particles * 3 );
+			var values_size = new Float32Array( particles );
 
 
-			var color = new THREE.Color( 0xffaa00 );;
+			var color = new THREE.Color();
 
 
 			for( var v = 0; v < particles; v++ ) {
 			for( var v = 0; v < particles; v++ ) {
 
 
-				values_size[ v ] = 10;
+				values_size[ v ] = 20;
 
 
-				positions[ v * 3 + 0 ] = (Math.random() * 2 - 1) * radius;
-				positions[ v * 3 + 1 ] = (Math.random() * 2 - 1) * radius;
-				positions[ v * 3 + 2 ] = (Math.random() * 2 - 1) * radius;
+				positions[ v * 3 + 0 ] = ( Math.random() * 2 - 1 ) * radius;
+				positions[ v * 3 + 1 ] = ( Math.random() * 2 - 1 ) * radius;
+				positions[ v * 3 + 2 ] = ( Math.random() * 2 - 1 ) * radius;
 
 
-				if ( positions[ v * 3 + 0 ] < 0 )
-					color.setHSL( 0.5 + 0.1 * ( v / particles ), 0.7, 0.1 );
-				else
-					color.setHSL( 0.0 + 0.1 * ( v / particles ), 0.9, 0.1 );
+				color.setHSL( v / particles, 1.0, 0.5 );
 
 
 				values_color[ v * 3 + 0 ] = color.r;
 				values_color[ v * 3 + 0 ] = color.r;
 				values_color[ v * 3 + 1 ] = color.g;
 				values_color[ v * 3 + 1 ] = color.g;
@@ -170,7 +152,13 @@
 
 
 			}
 			}
 
 
-			scene.add( sphere );
+			geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+			geometry.addAttribute( 'customColor', new THREE.BufferAttribute( values_color, 3 ) );
+			geometry.addAttribute( 'size', new THREE.BufferAttribute( values_size, 1 ) );
+
+			particleSystem = new THREE.PointCloud( geometry, shaderMaterial );
+
+			scene.add( particleSystem );
 
 
 			renderer = new THREE.WebGLRenderer();
 			renderer = new THREE.WebGLRenderer();
 			renderer.setSize( WIDTH, HEIGHT );
 			renderer.setSize( WIDTH, HEIGHT );
@@ -211,11 +199,13 @@
 
 
 			var time = Date.now() * 0.005;
 			var time = Date.now() * 0.005;
 
 
-			sphere.rotation.z = 0.01 * time;
+			particleSystem.rotation.z = 0.01 * time;
+
+			var size = geometry.attributes.size.array;
 
 
 			for( var i = 0; i < particles; i++ ) {
 			for( var i = 0; i < particles; i++ ) {
 
 
-				values_size[ i ] = 14 + 13 * Math.sin( 0.1 * i + time );
+				size[ i ] = 10 * ( 1 + Math.sin( 0.1 * i + time ) );
 
 
 			}
 			}
 
 

+ 5 - 5
examples/webgl_buffergeometry_lines.html

@@ -69,11 +69,8 @@
 				var geometry = new THREE.BufferGeometry();
 				var geometry = new THREE.BufferGeometry();
 				var material = new THREE.LineBasicMaterial({ vertexColors: true });
 				var material = new THREE.LineBasicMaterial({ vertexColors: true });
 
 
-				geometry.addAttribute( 'position', new Float32Array( segments * 3 ), 3 );
-				geometry.addAttribute( 'color', new Float32Array( segments * 3 ), 3 );
-
-				var positions = geometry.getAttribute( 'position' ).array;
-				var colors = geometry.getAttribute( 'color' ).array;
+				var positions = new Float32Array( segments * 3 );
+				var colors = new Float32Array( segments * 3 );
 
 
 				var r = 800;
 				var r = 800;
 
 
@@ -97,6 +94,9 @@
 
 
 				}
 				}
 
 
+				geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
+
 				geometry.computeBoundingSphere();
 				geometry.computeBoundingSphere();
 
 
 				mesh = new THREE.Line( geometry, material );
 				mesh = new THREE.Line( geometry, material );

+ 5 - 4
examples/webgl_buffergeometry_lines_indexed.html

@@ -69,7 +69,8 @@
 				var colors = [];
 				var colors = [];
 				var indices_array = [];
 				var indices_array = [];
 
 
-				// --------------------------------
+				//
+
 				var iteration_count = 4;
 				var iteration_count = 4;
 				var rangle = 60 * Math.PI / 180.0;
 				var rangle = 60 * Math.PI / 180.0;
 
 
@@ -181,9 +182,9 @@
 				);
 				);
 				// --------------------------------
 				// --------------------------------
 
 
-				geometry.addAttribute( 'index', new Uint16Array( indices_array ), 1 );
-				geometry.addAttribute( 'position', new Float32Array( positions ), 3 );
-				geometry.addAttribute( 'color', new Float32Array( colors ), 3 );
+				geometry.addAttribute( 'index', new THREE.BufferAttribute( new Uint16Array( indices_array ), 1 ) );
+				geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( positions ), 3 ) );
+				geometry.addAttribute( 'color', new THREE.BufferAttribute( new Float32Array( colors ), 3 ) );
 				geometry.computeBoundingSphere();
 				geometry.computeBoundingSphere();
 
 
 				mesh = new THREE.Line( geometry, material, THREE.LinePieces );
 				mesh = new THREE.Line( geometry, material, THREE.LinePieces );

+ 7 - 7
examples/webgl_buffergeometry_particles.html

@@ -69,11 +69,8 @@
 
 
 				var geometry = new THREE.BufferGeometry();
 				var geometry = new THREE.BufferGeometry();
 
 
-				geometry.addAttribute( 'position', new Float32Array( particles * 3 ), 3 );
-				geometry.addAttribute( 'color', new Float32Array( particles * 3 ), 3 );
-
-				var positions = geometry.getAttribute( 'position' ).array;
-				var colors = geometry.getAttribute( 'color' ).array;
+				var positions = new Float32Array( particles * 3 );
+				var colors = new Float32Array( particles * 3 );
 
 
 				var color = new THREE.Color();
 				var color = new THREE.Color();
 
 
@@ -105,13 +102,16 @@
 
 
 				}
 				}
 
 
+				geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
+
 				geometry.computeBoundingSphere();
 				geometry.computeBoundingSphere();
 
 
 				//
 				//
 
 
-				var material = new THREE.ParticleSystemMaterial( { size: 15, vertexColors: true } );
+				var material = new THREE.PointCloudMaterial( { size: 15, vertexColors: true } );
 
 
-				particleSystem = new THREE.ParticleSystem( geometry, material );
+				particleSystem = new THREE.PointCloud( geometry, material );
 				scene.add( particleSystem );
 				scene.add( particleSystem );
 
 
 				//
 				//

+ 2 - 2
examples/webgl_buffergeometry_rawshader.html

@@ -113,7 +113,7 @@
 
 
 				var geometry = new THREE.BufferGeometry();
 				var geometry = new THREE.BufferGeometry();
 
 
-				var vertices = new THREE.Float32Attribute( triangles * 3, 3 );
+				var vertices = new THREE.BufferAttribute( new Float32Array( triangles * 3 * 3 ), 3 );
 
 
 				for ( var i = 0; i < vertices.length; i ++ ) {
 				for ( var i = 0; i < vertices.length; i ++ ) {
 
 
@@ -123,7 +123,7 @@
 
 
 				geometry.addAttribute( 'position', vertices );
 				geometry.addAttribute( 'position', vertices );
 
 
-				var colors = new THREE.Float32Attribute( triangles * 3, 4 );
+				var colors = new THREE.BufferAttribute(new Float32Array( triangles * 3 * 4 ), 4 );
 
 
 				for ( var i = 0; i < colors.length; i ++ ) {
 				for ( var i = 0; i < colors.length; i ++ ) {
 
 

+ 10 - 8
examples/webgl_buffergeometry_uint.html

@@ -82,12 +82,9 @@
 
 
 				var geometry = new THREE.BufferGeometry();
 				var geometry = new THREE.BufferGeometry();
 
 
-				geometry.addAttribute( 'index', new Uint32Array( triangles * 3 ), 1 );
-				geometry.addAttribute( 'position', new Float32Array( triangles * 3 * 3 ), 3 );
-				geometry.addAttribute( 'normal', new Float32Array( triangles * 3 * 3 ), 3 );
-				geometry.addAttribute( 'color', new Float32Array( triangles * 3 * 3 ), 3 );
 
 
-				var indices = geometry.getAttribute( 'index' ).array;
+
+				var indices = new Uint32Array( triangles * 3 );
 
 
 				for ( var i = 0; i < indices.length; i ++ ) {
 				for ( var i = 0; i < indices.length; i ++ ) {
 
 
@@ -95,9 +92,9 @@
 
 
 				}
 				}
 
 
-				var positions = geometry.getAttribute( 'position' ).array;
-				var normals = geometry.getAttribute( 'normal' ).array;
-				var colors = geometry.getAttribute( 'color' ).array;
+				var positions = new Float32Array( triangles * 3 * 3 );
+				var normals = new Float32Array( triangles * 3 * 3 );
+				var colors = new Float32Array( triangles * 3 * 3 );
 
 
 				var color = new THREE.Color();
 				var color = new THREE.Color();
 
 
@@ -193,6 +190,11 @@
 
 
 				}
 				}
 
 
+				geometry.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
+				geometry.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				geometry.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+				geometry.addAttribute( 'color', new THREE.BufferAttribute( colors, 3 ) );
+
 				geometry.computeBoundingSphere();
 				geometry.computeBoundingSphere();
 
 
 				var material = new THREE.MeshPhongMaterial( {
 				var material = new THREE.MeshPhongMaterial( {

+ 1 - 1
examples/webgl_camera.html

@@ -130,7 +130,7 @@
 
 
 				}
 				}
 
 
-				var particles = new THREE.ParticleSystem( geometry, new THREE.ParticleSystemMaterial( { color: 0x888888 } ) );
+				var particles = new THREE.PointCloud( geometry, new THREE.PointCloudMaterial( { color: 0x888888 } ) );
 				scene.add( particles );
 				scene.add( particles );
 
 
 				//
 				//

+ 0 - 4
examples/webgl_camera_logarithmicdepthbuffer.html

@@ -168,10 +168,6 @@
 				light.position.set(100,100,100);
 				light.position.set(100,100,100);
 				scene.add(light);
 				scene.add(light);
 
 
-				var pointlight = new THREE.PointLight(0xffccaa, .1);
-				pointlight.position = camera.position;
-				scene.add(pointlight);
-
 				var materialargs = {
 				var materialargs = {
 					color: 0xffffff,
 					color: 0xffffff,
 					specular: 0xffaa00,
 					specular: 0xffaa00,

+ 1 - 1
examples/webgl_custom_attributes_lines.html

@@ -163,7 +163,7 @@
 
 
 			geometry.dynamic = true;
 			geometry.dynamic = true;
 
 
-			THREE.GeometryUtils.center( geometry );
+			geometry.center();
 
 
 			object = new THREE.Line( geometry, shaderMaterial, THREE.LineStrip );
 			object = new THREE.Line( geometry, shaderMaterial, THREE.LineStrip );
 
 

+ 7 - 8
examples/webgl_custom_attributes_particles.html

@@ -119,14 +119,14 @@
 
 
 			var shaderMaterial = new THREE.ShaderMaterial( {
 			var shaderMaterial = new THREE.ShaderMaterial( {
 
 
-				uniforms: 		uniforms,
+				uniforms:       uniforms,
 				attributes:     attributes,
 				attributes:     attributes,
 				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
 				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
 				fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
 				fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
 
 
-				blending: 		THREE.AdditiveBlending,
-				depthTest: 		false,
-				transparent:	true
+				blending:       THREE.AdditiveBlending,
+				depthTest:      false,
+				transparent:    true
 
 
 			});
 			});
 
 
@@ -134,7 +134,7 @@
 			var radius = 200;
 			var radius = 200;
 			var geometry = new THREE.Geometry();
 			var geometry = new THREE.Geometry();
 
 
-			for ( var i = 0; i < 100000; i++ ) {
+			for ( var i = 0; i < 100000; i ++ ) {
 
 
 				var vertex = new THREE.Vector3();
 				var vertex = new THREE.Vector3();
 				vertex.x = Math.random() * 2 - 1;
 				vertex.x = Math.random() * 2 - 1;
@@ -146,7 +146,7 @@
 
 
 			}
 			}
 
 
-			sphere = new THREE.ParticleSystem( geometry, shaderMaterial );
+			sphere = new THREE.PointCloud( geometry, shaderMaterial );
 
 
 			sphere.dynamic = true;
 			sphere.dynamic = true;
 			//sphere.sortParticles = true;
 			//sphere.sortParticles = true;
@@ -155,8 +155,7 @@
 			var values_size = attributes.size.value;
 			var values_size = attributes.size.value;
 			var values_color = attributes.customColor.value;
 			var values_color = attributes.customColor.value;
 
 
-
-			for( var v = 0; v < vertices.length; v++ ) {
+			for ( var v = 0; v < vertices.length; v++ ) {
 
 
 				values_size[ v ] = 10;
 				values_size[ v ] = 10;
 				values_color[ v ] = new THREE.Color( 0xffaa00 );
 				values_color[ v ] = new THREE.Color( 0xffaa00 );

+ 4 - 4
examples/webgl_custom_attributes_particles2.html

@@ -117,11 +117,11 @@
 
 
 			var shaderMaterial = new THREE.ShaderMaterial( {
 			var shaderMaterial = new THREE.ShaderMaterial( {
 
 
-				uniforms: 		uniforms,
+				uniforms:       uniforms,
 				attributes:     attributes,
 				attributes:     attributes,
 				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
 				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
 				fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
 				fragmentShader: document.getElementById( 'fragmentshader' ).textContent,
-				transparent:	true
+				transparent:    true
 
 
 			});
 			});
 
 
@@ -134,7 +134,7 @@
 			var geometry2 = new THREE.BoxGeometry( 0.8 * radius, 0.8 * radius, 0.8 * radius, 10, 10, 10 );
 			var geometry2 = new THREE.BoxGeometry( 0.8 * radius, 0.8 * radius, 0.8 * radius, 10, 10, 10 );
 			geometry.merge( geometry2 );
 			geometry.merge( geometry2 );
 
 
-			sphere = new THREE.ParticleSystem( geometry, shaderMaterial );
+			sphere = new THREE.PointCloud( geometry, shaderMaterial );
 
 
 			sphere.dynamic = true;
 			sphere.dynamic = true;
 			sphere.sortParticles = true;
 			sphere.sortParticles = true;
@@ -143,7 +143,7 @@
 			var values_size = attributes.size.value;
 			var values_size = attributes.size.value;
 			var values_color = attributes.ca.value;
 			var values_color = attributes.ca.value;
 
 
-			for( var v = 0; v < vertices.length; v++ ) {
+			for ( var v = 0; v < vertices.length; v ++ ) {
 
 
 				values_size[ v ] = 10;
 				values_size[ v ] = 10;
 				values_color[ v ] = new THREE.Color( 0xffffff );
 				values_color[ v ] = new THREE.Color( 0xffffff );

+ 3 - 4
examples/webgl_custom_attributes_particles3.html

@@ -125,7 +125,7 @@
 
 
 			var shaderMaterial = new THREE.ShaderMaterial( {
 			var shaderMaterial = new THREE.ShaderMaterial( {
 
 
-				uniforms: 		uniforms,
+				uniforms:       uniforms,
 				attributes:     attributes,
 				attributes:     attributes,
 				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
 				vertexShader:   document.getElementById( 'vertexshader' ).textContent,
 				fragmentShader: document.getElementById( 'fragmentshader' ).textContent
 				fragmentShader: document.getElementById( 'fragmentshader' ).textContent
@@ -193,8 +193,7 @@
 
 
 			// particle system
 			// particle system
 
 
-			object = new THREE.ParticleSystem( geometry, shaderMaterial );
-			object.dynamic = true;
+			object = new THREE.PointCloud( geometry, shaderMaterial );
 
 
 			// custom attributes
 			// custom attributes
 
 
@@ -203,7 +202,7 @@
 			var values_size = attributes.size.value;
 			var values_size = attributes.size.value;
 			var values_color = attributes.ca.value;
 			var values_color = attributes.ca.value;
 
 
-			for( var v = 0; v < vertices.length; v ++ ) {
+			for ( var v = 0; v < vertices.length; v ++ ) {
 
 
 				values_size[ v ] = 10;
 				values_size[ v ] = 10;
 				values_color[ v ] = new THREE.Color( 0xffffff );
 				values_color[ v ] = new THREE.Color( 0xffffff );

+ 32 - 35
examples/webgl_effects_oculusrift.html

@@ -50,6 +50,10 @@
 		<script src="js/effects/OculusRiftEffect.js"></script>
 		<script src="js/effects/OculusRiftEffect.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 
+		<script src="js/wip/TypedGeometry.js"></script>
+		<script src="js/wip/IndexedTypedGeometry.js"></script>
+		<script src="js/wip/PlaneTypedGeometry.js"></script>
+
 		<script>
 		<script>
 
 
 			if ( ! Detector.webgl ) {
 			if ( ! Detector.webgl ) {
@@ -93,44 +97,38 @@
 
 
 				var matrix = new THREE.Matrix4();
 				var matrix = new THREE.Matrix4();
 
 
-				var pxGeometry = new THREE.PlaneGeometry( 100, 100 );
-				pxGeometry.faceVertexUvs[ 0 ][ 0 ][ 0 ].y = 0.5;
-				pxGeometry.faceVertexUvs[ 0 ][ 0 ][ 2 ].y = 0.5;
-				pxGeometry.faceVertexUvs[ 0 ][ 1 ][ 2 ].y = 0.5;
+				var pxGeometry = new THREE.PlaneTypedGeometry( 100, 100 );
+				pxGeometry.uvs[ 1 ] = 0.5;
+				pxGeometry.uvs[ 3 ] = 0.5;
 				pxGeometry.applyMatrix( matrix.makeRotationY( Math.PI / 2 ) );
 				pxGeometry.applyMatrix( matrix.makeRotationY( Math.PI / 2 ) );
 				pxGeometry.applyMatrix( matrix.makeTranslation( 50, 0, 0 ) );
 				pxGeometry.applyMatrix( matrix.makeTranslation( 50, 0, 0 ) );
 
 
-				var nxGeometry = new THREE.PlaneGeometry( 100, 100 );
-				nxGeometry.faceVertexUvs[ 0 ][ 0 ][ 0 ].y = 0.5;
-				nxGeometry.faceVertexUvs[ 0 ][ 0 ][ 2 ].y = 0.5;
-				nxGeometry.faceVertexUvs[ 0 ][ 1 ][ 2 ].y = 0.5;
+				var nxGeometry = new THREE.PlaneTypedGeometry( 100, 100 );
+				nxGeometry.uvs[ 1 ] = 0.5;
+				nxGeometry.uvs[ 3 ] = 0.5;
 				nxGeometry.applyMatrix( matrix.makeRotationY( - Math.PI / 2 ) );
 				nxGeometry.applyMatrix( matrix.makeRotationY( - Math.PI / 2 ) );
 				nxGeometry.applyMatrix( matrix.makeTranslation( - 50, 0, 0 ) );
 				nxGeometry.applyMatrix( matrix.makeTranslation( - 50, 0, 0 ) );
 
 
-				var pyGeometry = new THREE.PlaneGeometry( 100, 100 );
-				pyGeometry.faceVertexUvs[ 0 ][ 0 ][ 1 ].y = 0.5;
-				pyGeometry.faceVertexUvs[ 0 ][ 1 ][ 0 ].y = 0.5;
-				pyGeometry.faceVertexUvs[ 0 ][ 1 ][ 1 ].y = 0.5;
+				var pyGeometry = new THREE.PlaneTypedGeometry( 100, 100 );
+				pyGeometry.uvs[ 5 ] = 0.5;
+				pyGeometry.uvs[ 7 ] = 0.5;
 				pyGeometry.applyMatrix( matrix.makeRotationX( - Math.PI / 2 ) );
 				pyGeometry.applyMatrix( matrix.makeRotationX( - Math.PI / 2 ) );
 				pyGeometry.applyMatrix( matrix.makeTranslation( 0, 50, 0 ) );
 				pyGeometry.applyMatrix( matrix.makeTranslation( 0, 50, 0 ) );
 
 
-				var pzGeometry = new THREE.PlaneGeometry( 100, 100 );
-				pzGeometry.faceVertexUvs[ 0 ][ 0 ][ 0 ].y = 0.5;
-				pzGeometry.faceVertexUvs[ 0 ][ 0 ][ 2 ].y = 0.5;
-				pzGeometry.faceVertexUvs[ 0 ][ 1 ][ 2 ].y = 0.5;
+				var pzGeometry = new THREE.PlaneTypedGeometry( 100, 100 );
+				pzGeometry.uvs[ 1 ] = 0.5;
+				pzGeometry.uvs[ 3 ] = 0.5;
 				pzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, 50 ) );
 				pzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, 50 ) );
 
 
-				var nzGeometry = new THREE.PlaneGeometry( 100, 100 );
-				nzGeometry.faceVertexUvs[ 0 ][ 0 ][ 0 ].y = 0.5;
-				nzGeometry.faceVertexUvs[ 0 ][ 0 ][ 2 ].y = 0.5;
-				nzGeometry.faceVertexUvs[ 0 ][ 1 ][ 2 ].y = 0.5;
+				var nzGeometry = new THREE.PlaneTypedGeometry( 100, 100 );
+				nzGeometry.uvs[ 1 ] = 0.5;
+				nzGeometry.uvs[ 3 ] = 0.5;
 				nzGeometry.applyMatrix( matrix.makeRotationY( Math.PI ) );
 				nzGeometry.applyMatrix( matrix.makeRotationY( Math.PI ) );
 				nzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, -50 ) );
 				nzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, -50 ) );
 
 
 				//
 				//
 
 
-				var geometry = new THREE.Geometry();
-				var dummy = new THREE.Mesh();
+				var geometry = new THREE.TypedGeometry( worldWidth * worldDepth * 2 * 5 ); // 2 triangles, 5 possible sides
 
 
 				for ( var z = 0; z < worldDepth; z ++ ) {
 				for ( var z = 0; z < worldDepth; z ++ ) {
 
 
@@ -138,43 +136,40 @@
 
 
 						var h = getY( x, z );
 						var h = getY( x, z );
 
 
-						dummy.position.x = x * 100 - worldHalfWidth * 100;
-						dummy.position.y = h * 100;
-						dummy.position.z = z * 100 - worldHalfDepth * 100;
+						matrix.makeTranslation(
+							x * 100 - worldHalfWidth * 100,
+							h * 100,
+							z * 100 - worldHalfDepth * 100
+						);
 
 
 						var px = getY( x + 1, z );
 						var px = getY( x + 1, z );
 						var nx = getY( x - 1, z );
 						var nx = getY( x - 1, z );
 						var pz = getY( x, z + 1 );
 						var pz = getY( x, z + 1 );
 						var nz = getY( x, z - 1 );
 						var nz = getY( x, z - 1 );
 
 
-						dummy.geometry = pyGeometry;
-						THREE.GeometryUtils.merge( geometry, dummy );
+						geometry.merge( pyGeometry, matrix );
 
 
 						if ( ( px != h && px != h + 1 ) || x == 0 ) {
 						if ( ( px != h && px != h + 1 ) || x == 0 ) {
 
 
-							dummy.geometry = pxGeometry;
-							THREE.GeometryUtils.merge( geometry, dummy );
+							geometry.merge( pxGeometry, matrix );
 
 
 						}
 						}
 
 
 						if ( ( nx != h && nx != h + 1 ) || x == worldWidth - 1 ) {
 						if ( ( nx != h && nx != h + 1 ) || x == worldWidth - 1 ) {
 
 
-							dummy.geometry = nxGeometry;
-							THREE.GeometryUtils.merge( geometry, dummy );
+							geometry.merge( nxGeometry, matrix );
 
 
 						}
 						}
 
 
 						if ( ( pz != h && pz != h + 1 ) || z == worldDepth - 1 ) {
 						if ( ( pz != h && pz != h + 1 ) || z == worldDepth - 1 ) {
 
 
-							dummy.geometry = pzGeometry;
-							THREE.GeometryUtils.merge( geometry, dummy );
+							geometry.merge( pzGeometry, matrix );
 
 
 						}
 						}
 
 
 						if ( ( nz != h && nz != h + 1 ) || z == 0 ) {
 						if ( ( nz != h && nz != h + 1 ) || z == 0 ) {
 
 
-							dummy.geometry = nzGeometry;
-							THREE.GeometryUtils.merge( geometry, dummy );
+							geometry.merge( nzGeometry, matrix );
 
 
 						}
 						}
 
 
@@ -182,6 +177,8 @@
 
 
 				}
 				}
 
 
+				geometry.computeBoundingSphere();
+
 				var texture = THREE.ImageUtils.loadTexture( 'textures/minecraft/atlas.png' );
 				var texture = THREE.ImageUtils.loadTexture( 'textures/minecraft/atlas.png' );
 				texture.magFilter = THREE.NearestFilter;
 				texture.magFilter = THREE.NearestFilter;
 				texture.minFilter = THREE.LinearMipMapLinearFilter;
 				texture.minFilter = THREE.LinearMipMapLinearFilter;

+ 2 - 7
examples/webgl_geometries2.html

@@ -20,19 +20,14 @@
 		<script src="js/Detector.js"></script>
 		<script src="js/Detector.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 		<script src="js/libs/stats.min.js"></script>
 
 
-		<!--
-		<script src="../src/core/Geometry.js"></script>
-		<script src="../src/extras/geometries/ParametricGeometry.js"></script>
-		-->
-
 		<script src="js/CurveExtras.js"></script>
 		<script src="js/CurveExtras.js"></script>
-		<script src="js/UVsUtils.js"></script>
 		<script src="js/ParametricGeometries.js"></script>
 		<script src="js/ParametricGeometries.js"></script>
+		<script src="js/utils/UVsUtils.js"></script>
+
 		<script>
 		<script>
 
 
 			/* Testing the new Parametric Surfaces Geometries*/
 			/* Testing the new Parametric Surfaces Geometries*/
 
 
-
 			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
 			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
 
 
 			var container, stats;
 			var container, stats;

File diff suppressed because it is too large
+ 24 - 25
examples/webgl_geometry_colors_lookuptable.html


+ 1 - 3
examples/webgl_geometry_extrude_shapes.html

@@ -61,13 +61,11 @@
 				scene.add( new THREE.AmbientLight( 0x222222 ) );
 				scene.add( new THREE.AmbientLight( 0x222222 ) );
 
 
 				var light = new THREE.PointLight( 0xffffff );
 				var light = new THREE.PointLight( 0xffffff );
-				light.position = camera.position;
+				light.position.copy( camera.position );
 				scene.add( light );
 				scene.add( light );
 
 
-
 				//
 				//
 
 
-
 				var closedSpline = new THREE.ClosedSplineCurve3( [
 				var closedSpline = new THREE.ClosedSplineCurve3( [
 					new THREE.Vector3( -60, -100,  60 ),
 					new THREE.Vector3( -60, -100,  60 ),
 					new THREE.Vector3( -60,   20,  60 ),
 					new THREE.Vector3( -60,   20,  60 ),

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