Browse Source

Merge remote-tracking branch 'upstream/dev' into adsk-dev

Daniel Taub 11 years ago
parent
commit
793e335d18
92 changed files with 1425 additions and 1316 deletions
  1. 214 255
      build/three.js
  2. 210 208
      build/three.min.js
  3. 1 1
      docs/api/math/Frustum.html
  4. 23 19
      editor/css/main.css
  5. 8 0
      editor/index.html
  6. 25 18
      editor/js/Editor.js
  7. 5 1
      editor/js/Menubar.Add.js
  8. 8 8
      editor/js/Sidebar.Geometry.BoxGeometry.js
  9. 4 4
      editor/js/Sidebar.Geometry.BufferGeometry.js
  10. 4 4
      editor/js/Sidebar.Geometry.CircleGeometry.js
  11. 8 8
      editor/js/Sidebar.Geometry.CylinderGeometry.js
  12. 3 3
      editor/js/Sidebar.Geometry.Geometry.js
  13. 3 3
      editor/js/Sidebar.Geometry.IcosahedronGeometry.js
  14. 3 3
      editor/js/Sidebar.Geometry.Modifiers.js
  15. 6 6
      editor/js/Sidebar.Geometry.PlaneGeometry.js
  16. 9 9
      editor/js/Sidebar.Geometry.SphereGeometry.js
  17. 7 7
      editor/js/Sidebar.Geometry.TorusGeometry.js
  18. 9 9
      editor/js/Sidebar.Geometry.TorusKnotGeometry.js
  19. 0 1
      editor/js/Sidebar.Geometry.js
  20. 5 0
      editor/js/Sidebar.Scene.js
  21. 79 0
      editor/js/Viewport.Info.js
  22. 14 57
      editor/js/Viewport.js
  23. 24 42
      editor/js/libs/ui.js
  24. 2 4
      examples/js/Mirror.js
  25. 1 1
      examples/js/Ocean.js
  26. 6 3
      examples/js/controls/OrbitControls.js
  27. 15 14
      examples/js/effects/VREffect.js
  28. 21 1
      examples/js/loaders/AssimpJSONLoader.js
  29. 15 43
      examples/js/loaders/VTKLoader.js
  30. 1 1
      examples/js/loaders/ctm/CTMLoader.js
  31. 7 31
      examples/js/loaders/gltf/glTFLoader.js
  32. 1 1
      examples/js/postprocessing/BloomPass.js
  33. 1 1
      examples/js/postprocessing/BokehPass.js
  34. 1 1
      examples/js/postprocessing/DotScreenPass.js
  35. 1 1
      examples/js/postprocessing/FilmPass.js
  36. 1 1
      examples/js/postprocessing/GlitchPass.js
  37. 1 1
      examples/js/postprocessing/SavePass.js
  38. 1 1
      examples/js/postprocessing/ShaderPass.js
  39. 1 1
      examples/js/postprocessing/TexturePass.js
  40. 6 2
      examples/js/renderers/SVGRenderer.js
  41. 18 20
      examples/js/wip/TypedGeometry.js
  42. 8 12
      examples/misc_controls_pointerlock.html
  43. 11 55
      examples/misc_sound.html
  44. 5 1
      examples/models/assimp/interior/interior.assimp.json
  45. 5 1
      examples/models/assimp/jeep/jeep.assimp.json
  46. BIN
      examples/models/skinned/simple/simple.blend
  47. 54 0
      examples/models/skinned/simple/simple.js
  48. 2 2
      examples/webgl_effects_vr.html
  49. 0 1
      examples/webgl_geometry_dynamic.html
  50. 12 12
      examples/webgl_geometry_minecraft_ao.html
  51. 2 2
      examples/webgl_geometry_normals.html
  52. 2 2
      examples/webgl_geometry_subdivision.html
  53. 5 3
      examples/webgl_geometry_terrain.html
  54. 5 3
      examples/webgl_geometry_terrain_fog.html
  55. 5 3
      examples/webgl_geometry_terrain_raycast.html
  56. 2 2
      examples/webgl_loader_assimp2json.html
  57. 1 4
      examples/webgl_loader_obj.html
  58. 1 4
      examples/webgl_loader_vtk.html
  59. 40 32
      examples/webgl_materials_cubemap_dynamic.html
  60. 1 8
      examples/webgl_materials_video.html
  61. 6 20
      examples/webgl_nearestneighbour.html
  62. 104 0
      examples/webgl_skinning_simple.html
  63. 7 1
      examples/webgl_terrain_dynamic.html
  64. 0 1
      examples/webgl_test_memory.html
  65. 3 20
      examples/webgl_video_panorama_equirectangular.html
  66. 17 0
      src/Three.js
  67. 2 6
      src/cameras/PerspectiveCamera.js
  68. 6 0
      src/core/BufferAttribute.js
  69. 41 68
      src/core/BufferGeometry.js
  70. 2 2
      src/core/Geometry.js
  71. 11 34
      src/core/Object3D.js
  72. 2 0
      src/core/Projector.js
  73. 74 0
      src/extras/audio/Audio.js
  74. 47 0
      src/extras/audio/AudioListener.js
  75. 1 2
      src/extras/geometries/ExtrudeGeometry.js
  76. 7 5
      src/extras/geometries/PlaneBufferGeometry.js
  77. 4 61
      src/extras/geometries/PlaneGeometry.js
  78. 2 0
      src/extras/renderers/plugins/LensFlarePlugin.js
  79. 3 1
      src/extras/renderers/plugins/ShadowMapPlugin.js
  80. 4 0
      src/materials/Material.js
  81. 0 6
      src/math/Math.js
  82. 89 131
      src/renderers/WebGLRenderer.js
  83. 8 8
      src/renderers/shaders/UniformsUtils.js
  84. 1 0
      src/renderers/webgl/WebGLProgram.js
  85. 29 0
      src/textures/VideoTexture.js
  86. 1 0
      utils/build/externs/common.js
  87. 1 0
      utils/build/includes/canvas.json
  88. 1 0
      utils/build/includes/common.json
  89. 3 0
      utils/build/includes/extras.json
  90. 1 0
      utils/build/includes/webgl.json
  91. 7 5
      utils/exporters/blender/2.65/scripts/addons/io_mesh_threejs/export_threejs.py
  92. 8 4
      utils/exporters/maya/plug-ins/threeJsFileTranslator.py

File diff suppressed because it is too large
+ 214 - 255
build/three.js


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


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

@@ -43,7 +43,7 @@
 
 		<h3>.intersectsObject( [page:Object3D object] ) [page:Boolean]</h3>
 		<div>
-		Checks whether the object is inside the Frustum.
+		Checks whether the object's bounding sphere is intersecting the Frustum.
 		</div>
 
 		<h3>.clone() [page:Frustum]</h3>

+ 23 - 19
editor/css/main.css

@@ -3,7 +3,7 @@
 }
 
 body {
-	font-family: Arial, sans-serif;
+	font-family: Helvetica, Arial, sans-serif;
 	font-size: 14px;
 	margin: 0;
 	overflow: hidden;
@@ -44,27 +44,31 @@ textarea, input { outline: none; } /* osx */
 	user-select: none;
 }
 
-.CollapsiblePanel .CollapsiblePanelButton {
-	float: left;
-	margin-right: 6px;
-	width: 0px;
-	height: 0px;
-	border: 6px solid transparent;
-}
+	.Panel.Collapsible .Static {
+		margin: 0px;
+	}
 
-.CollapsiblePanel.collapsed .CollapsiblePanelButton {
-	margin-top: 2px;
-	border-left-color: #bbb;
-}
+	.Panel.Collapsible .Static .Button {
+		float: left;
+		margin-right: 6px;
+		width: 0px;
+		height: 0px;
+		border: 6px solid transparent;
+	}
 
-.CollapsiblePanel:not(.collapsed) .CollapsiblePanelButton {
-	margin-top: 6px;
-	border-top-color: #bbb;
-}
+	.Panel.Collapsible.collapsed .Static .Button {
+		margin-top: 2px;
+		border-left-color: #bbb;
+	}
 
-.CollapsiblePanel.collapsed .CollapsibleContent {
-	display: none;
-}
+	.Panel.Collapsible:not(.collapsed) .Static .Button {
+		margin-top: 6px;
+		border-top-color: #bbb;
+	}
+
+	.Panel.Collapsible.collapsed .Content {
+		display: none;
+	}
 
 /* scene types */
 

+ 8 - 0
editor/index.html

@@ -82,12 +82,19 @@
 		<script src="js/Sidebar.Script.js"></script>
 		<script src="js/Toolbar.js"></script>
 		<script src="js/Viewport.js"></script>
+		<script src="js/Viewport.Info.js"></script>
 
 		<script>
 
 			window.URL = window.URL || window.webkitURL;
 			window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
 
+			Number.prototype.format = function (){
+				return this.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
+			};
+
+			//
+
 			var editor = new Editor();
 
 			var viewport = new Viewport( editor ).setId( 'viewport' );
@@ -153,6 +160,7 @@
 
 				var signals = editor.signals;
 
+				signals.geometryChanged.add( saveState );
 				signals.objectAdded.add( saveState );
 				signals.objectChanged.add( saveState );
 				signals.objectRemoved.add( saveState );

+ 25 - 18
editor/js/Editor.js

@@ -29,7 +29,11 @@ var Editor = function () {
 
 		cameraChanged: new SIGNALS.Signal(),
 
+		geometryChanged: new SIGNALS.Signal(),
+
 		objectSelected: new SIGNALS.Signal(),
+		objectFocused: new SIGNALS.Signal(),
+
 		objectAdded: new SIGNALS.Signal(),
 		objectChanged: new SIGNALS.Signal(),
 		objectRemoved: new SIGNALS.Signal(),
@@ -51,7 +55,7 @@ var Editor = function () {
 	this.storage = new Storage();
 	this.loader = new Loader( this );
 
-	this.camera = new THREE.PerspectiveCamera( 50, 1, 1, 5000 );
+	this.camera = new THREE.PerspectiveCamera( 50, 1, 1, 100000 );
 	this.scene = new THREE.Scene();
 	this.scene.name = 'Scene';
 	
@@ -281,35 +285,26 @@ Editor.prototype = {
 
 	select: function ( object ) {
 
-		this.selected = object;
+		if ( this.selected === object ) return;
 
-		if ( object !== null ) {
+		var uuid = null;
 
-			this.config.setKey( 'selected', object.uuid );
-
-		} else {
+		if ( object !== null ) {
 
-			this.config.setKey( 'selected', null );
+			uuid = object.uuid;
 
 		}
 
+		this.selected = object;
+
+		this.config.setKey( 'selected', uuid );
 		this.signals.objectSelected.dispatch( object );
 
 	},
 
 	selectById: function ( id ) {
 
-		var scope = this;
-
-		this.scene.traverse( function ( child ) {
-
-			if ( child.id === id ) {
-
-				scope.select( child );
-
-			}
-
-		} );
+		this.select( this.scene.getObjectById( id, true ) );
 
 	},
 
@@ -333,6 +328,18 @@ Editor.prototype = {
 
 		this.select( null );
 
+	},
+
+	focus: function ( object ) {
+
+		this.signals.objectFocused.dispatch( object );
+
+	},
+
+	focusById: function ( id ) {
+
+		this.focus( this.scene.getObjectById( id, true ) );
+
 	}
 
 }

+ 5 - 1
editor/js/Menubar.Add.js

@@ -140,8 +140,12 @@ Menubar.Add = function ( editor ) {
 		var radius = 75;
 		var widthSegments = 32;
 		var heightSegments = 16;
+		var phiStart = 0;
+		var phiLength = Math.PI * 2;
+		var thetaStart = 0;
+		var thetaLength = Math.PI;
 
-		var geometry = new THREE.SphereGeometry( radius, widthSegments, heightSegments );
+		var geometry = new THREE.SphereGeometry( radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength );
 		var mesh = new THREE.Mesh( geometry, new THREE.MeshPhongMaterial() );
 		mesh.name = 'Sphere ' + ( ++ meshCount );
 

+ 8 - 8
editor/js/Sidebar.Geometry.BoxGeometry.js

@@ -2,12 +2,12 @@ Sidebar.Geometry.BoxGeometry = function ( signals, object ) {
 
 	var container = new UI.Panel();
 
-	var geometry = object.geometry;
+	var parameters = object.geometry.parameters;
 
 	// width
 
 	var widthRow = new UI.Panel();
-	var width = new UI.Number( geometry.parameters.width ).onChange( update );
+	var width = new UI.Number( parameters.width ).onChange( update );
 
 	widthRow.add( new UI.Text( 'Width' ).setWidth( '90px' ) );
 	widthRow.add( width );
@@ -17,7 +17,7 @@ Sidebar.Geometry.BoxGeometry = function ( signals, object ) {
 	// height
 
 	var heightRow = new UI.Panel();
-	var height = new UI.Number( geometry.parameters.height ).onChange( update );
+	var height = new UI.Number( parameters.height ).onChange( update );
 
 	heightRow.add( new UI.Text( 'Height' ).setWidth( '90px' ) );
 	heightRow.add( height );
@@ -27,7 +27,7 @@ Sidebar.Geometry.BoxGeometry = function ( signals, object ) {
 	// depth
 
 	var depthRow = new UI.Panel();
-	var depth = new UI.Number( geometry.parameters.depth ).onChange( update );
+	var depth = new UI.Number( parameters.depth ).onChange( update );
 
 	depthRow.add( new UI.Text( 'Depth' ).setWidth( '90px' ) );
 	depthRow.add( depth );
@@ -37,7 +37,7 @@ Sidebar.Geometry.BoxGeometry = function ( signals, object ) {
 	// widthSegments
 
 	var widthSegmentsRow = new UI.Panel();
-	var widthSegments = new UI.Integer( geometry.parameters.widthSegments ).setRange( 1, Infinity ).onChange( update );
+	var widthSegments = new UI.Integer( parameters.widthSegments ).setRange( 1, Infinity ).onChange( update );
 
 	widthSegmentsRow.add( new UI.Text( 'Width segments' ).setWidth( '90px' ) );
 	widthSegmentsRow.add( widthSegments );
@@ -47,7 +47,7 @@ Sidebar.Geometry.BoxGeometry = function ( signals, object ) {
 	// heightSegments
 
 	var heightSegmentsRow = new UI.Panel();
-	var heightSegments = new UI.Integer( geometry.parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
+	var heightSegments = new UI.Integer( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
 
 	heightSegmentsRow.add( new UI.Text( 'Height segments' ).setWidth( '90px' ) );
 	heightSegmentsRow.add( heightSegments );
@@ -57,7 +57,7 @@ Sidebar.Geometry.BoxGeometry = function ( signals, object ) {
 	// depthSegments
 
 	var depthSegmentsRow = new UI.Panel();
-	var depthSegments = new UI.Integer( geometry.parameters.depthSegments ).setRange( 1, Infinity ).onChange( update );
+	var depthSegments = new UI.Integer( parameters.depthSegments ).setRange( 1, Infinity ).onChange( update );
 
 	depthSegmentsRow.add( new UI.Text( 'Height segments' ).setWidth( '90px' ) );
 	depthSegmentsRow.add( depthSegments );
@@ -82,7 +82,7 @@ Sidebar.Geometry.BoxGeometry = function ( signals, object ) {
 		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
-		signals.objectChanged.dispatch( object );
+		signals.geometryChanged.dispatch( object );
 
 	}
 

+ 4 - 4
editor/js/Sidebar.Geometry.BufferGeometry.js

@@ -34,15 +34,15 @@ Sidebar.Geometry.BufferGeometry = function ( signals ) {
 
 			container.setDisplay( 'block' );
 
-			vertices.setValue( geometry.attributes.position.array.length / 3 );
+			vertices.setValue( ( geometry.attributes.position.array.length / 3 ).format() );
 
 			if ( geometry.attributes.index !== undefined ) {
 
-				faces.setValue( geometry.attributes.index.array.length / 3 );
+				faces.setValue( ( geometry.attributes.index.array.length / 3 ).format() );
 
 			} else {
 
-				faces.setValue( geometry.attributes.position.array.length / 9 );
+				faces.setValue( ( geometry.attributes.position.array.length / 9 ).format() );
 
 			}
 
@@ -55,7 +55,7 @@ Sidebar.Geometry.BufferGeometry = function ( signals ) {
 	};
 
 	signals.objectSelected.add( update );
-	signals.objectChanged.add( update );
+	signals.geometryChanged.add( update );
 
 	return container;
 

+ 4 - 4
editor/js/Sidebar.Geometry.CircleGeometry.js

@@ -2,12 +2,12 @@ Sidebar.Geometry.CircleGeometry = function ( signals, object ) {
 
 	var container = new UI.Panel();
 
-	var geometry = object.geometry;
+	var parameters = object.geometry.parameters;
 
 	// radius
 
 	var radiusRow = new UI.Panel();
-	var radius = new UI.Number( geometry.parameters.radius ).onChange( update );
+	var radius = new UI.Number( parameters.radius ).onChange( update );
 
 	radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) );
 	radiusRow.add( radius );
@@ -17,7 +17,7 @@ Sidebar.Geometry.CircleGeometry = function ( signals, object ) {
 	// segments
 
 	var segmentsRow = new UI.Panel();
-	var segments = new UI.Integer( geometry.parameters.segments ).setRange( 3, Infinity ).onChange( update );
+	var segments = new UI.Integer( parameters.segments ).setRange( 3, Infinity ).onChange( update );
 
 	segmentsRow.add( new UI.Text( 'Segments' ).setWidth( '90px' ) );
 	segmentsRow.add( segments );
@@ -37,7 +37,7 @@ Sidebar.Geometry.CircleGeometry = function ( signals, object ) {
 		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
-		signals.objectChanged.dispatch( object );
+		signals.geometryChanged.dispatch( object );
 
 	}
 

+ 8 - 8
editor/js/Sidebar.Geometry.CylinderGeometry.js

@@ -2,12 +2,12 @@ Sidebar.Geometry.CylinderGeometry = function ( signals, object ) {
 
 	var container = new UI.Panel();
 
-	var geometry = object.geometry;
+	var parameters = object.geometry.parameters;
 
 	// radiusTop
 
 	var radiusTopRow = new UI.Panel();
-	var radiusTop = new UI.Number( geometry.parameters.radiusTop ).onChange( update );
+	var radiusTop = new UI.Number( parameters.radiusTop ).onChange( update );
 
 	radiusTopRow.add( new UI.Text( 'Radius top' ).setWidth( '90px' ) );
 	radiusTopRow.add( radiusTop );
@@ -17,7 +17,7 @@ Sidebar.Geometry.CylinderGeometry = function ( signals, object ) {
 	// radiusBottom
 
 	var radiusBottomRow = new UI.Panel();
-	var radiusBottom = new UI.Number( geometry.parameters.radiusBottom ).onChange( update );
+	var radiusBottom = new UI.Number( parameters.radiusBottom ).onChange( update );
 
 	radiusBottomRow.add( new UI.Text( 'Radius bottom' ).setWidth( '90px' ) );
 	radiusBottomRow.add( radiusBottom );
@@ -27,7 +27,7 @@ Sidebar.Geometry.CylinderGeometry = function ( signals, object ) {
 	// height
 
 	var heightRow = new UI.Panel();
-	var height = new UI.Number( geometry.parameters.height ).onChange( update );
+	var height = new UI.Number( parameters.height ).onChange( update );
 
 	heightRow.add( new UI.Text( 'Height' ).setWidth( '90px' ) );
 	heightRow.add( height );
@@ -37,7 +37,7 @@ Sidebar.Geometry.CylinderGeometry = function ( signals, object ) {
 	// radialSegments
 
 	var radialSegmentsRow = new UI.Panel();
-	var radialSegments = new UI.Integer( geometry.parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
+	var radialSegments = new UI.Integer( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
 
 	radialSegmentsRow.add( new UI.Text( 'Radial segments' ).setWidth( '90px' ) );
 	radialSegmentsRow.add( radialSegments );
@@ -47,7 +47,7 @@ Sidebar.Geometry.CylinderGeometry = function ( signals, object ) {
 	// heightSegments
 
 	var heightSegmentsRow = new UI.Panel();
-	var heightSegments = new UI.Integer( geometry.parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
+	var heightSegments = new UI.Integer( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
 
 	heightSegmentsRow.add( new UI.Text( 'Height segments' ).setWidth( '90px' ) );
 	heightSegmentsRow.add( heightSegments );
@@ -57,7 +57,7 @@ Sidebar.Geometry.CylinderGeometry = function ( signals, object ) {
 	// openEnded
 
 	var openEndedRow = new UI.Panel();
-	var openEnded = new UI.Checkbox( geometry.parameters.openEnded ).onChange( update );
+	var openEnded = new UI.Checkbox( parameters.openEnded ).onChange( update );
 
 	openEndedRow.add( new UI.Text( 'Open ended' ).setWidth( '90px' ) );
 	openEndedRow.add( openEnded );
@@ -82,7 +82,7 @@ Sidebar.Geometry.CylinderGeometry = function ( signals, object ) {
 		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
-		signals.objectChanged.dispatch( object );
+		signals.geometryChanged.dispatch( object );
 
 	}
 

+ 3 - 3
editor/js/Sidebar.Geometry.Geometry.js

@@ -34,8 +34,8 @@ Sidebar.Geometry.Geometry = function ( signals ) {
 
 			container.setDisplay( 'block' );
 
-			vertices.setValue( geometry.vertices.length );
-			faces.setValue( geometry.faces.length );
+			vertices.setValue( ( geometry.vertices.length ).format() );
+			faces.setValue( ( geometry.faces.length ).format() );
 
 		} else {
 
@@ -46,7 +46,7 @@ Sidebar.Geometry.Geometry = function ( signals ) {
 	};
 
 	signals.objectSelected.add( update );
-	signals.objectChanged.add( update );
+	signals.geometryChanged.add( update );
 
 	return container;
 

+ 3 - 3
editor/js/Sidebar.Geometry.IcosahedronGeometry.js

@@ -2,12 +2,12 @@ Sidebar.Geometry.IcosahedronGeometry = function ( signals, object ) {
 
 	var container = new UI.Panel();
 
-	var geometry = object.geometry;
+	var parameters = object.geometry.parameters;
 
 	// radius
 
 	var radiusRow = new UI.Panel();
-	var radius = new UI.Number( geometry.parameters.radius ).onChange( update );
+	var radius = new UI.Number( parameters.radius ).onChange( update );
 
 	radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) );
 	radiusRow.add( radius );
@@ -17,7 +17,7 @@ Sidebar.Geometry.IcosahedronGeometry = function ( signals, object ) {
 	// detail
 
 	var detailRow = new UI.Panel();
-	var detail = new UI.Integer( geometry.parameters.detail ).setRange( 0, Infinity ).onChange( update );
+	var detail = new UI.Integer( parameters.detail ).setRange( 0, Infinity ).onChange( update );
 
 	detailRow.add( new UI.Text( 'Detail' ).setWidth( '90px' ) );
 	detailRow.add( detail );

+ 3 - 3
editor/js/Sidebar.Geometry.Modifiers.js

@@ -21,7 +21,7 @@ Sidebar.Geometry.Modifiers = function ( signals, object ) {
 
 		}
 
-		signals.objectChanged.dispatch( object );
+		signals.geometryChanged.dispatch( object );
 
 	} );
 
@@ -40,7 +40,7 @@ Sidebar.Geometry.Modifiers = function ( signals, object ) {
 
 			object.geometry = new THREE.Geometry().fromBufferGeometry( object.geometry );
 
-			signals.objectChanged.dispatch( object );
+			signals.geometryChanged.dispatch( object );
 
 		} );
 		container.add( button );
@@ -54,7 +54,7 @@ Sidebar.Geometry.Modifiers = function ( signals, object ) {
 
 			object.geometry = new THREE.BufferGeometry().fromGeometry( object.geometry );
 
-			signals.objectChanged.dispatch( object );
+			signals.geometryChanged.dispatch( object );
 
 		} );
 		container.add( button );

+ 6 - 6
editor/js/Sidebar.Geometry.PlaneGeometry.js

@@ -2,12 +2,12 @@ Sidebar.Geometry.PlaneGeometry = function ( signals, object ) {
 
 	var container = new UI.Panel();
 
-	var geometry = object.geometry;
+	var parameters = object.geometry.parameters;
 
 	// width
 
 	var widthRow = new UI.Panel();
-	var width = new UI.Number( geometry.parameters.width ).onChange( update );
+	var width = new UI.Number( parameters.width ).onChange( update );
 
 	widthRow.add( new UI.Text( 'Width' ).setWidth( '90px' ) );
 	widthRow.add( width );
@@ -17,7 +17,7 @@ Sidebar.Geometry.PlaneGeometry = function ( signals, object ) {
 	// height
 
 	var heightRow = new UI.Panel();
-	var height = new UI.Number( geometry.parameters.height ).onChange( update );
+	var height = new UI.Number( parameters.height ).onChange( update );
 
 	heightRow.add( new UI.Text( 'Height' ).setWidth( '90px' ) );
 	heightRow.add( height );
@@ -27,7 +27,7 @@ Sidebar.Geometry.PlaneGeometry = function ( signals, object ) {
 	// widthSegments
 
 	var widthSegmentsRow = new UI.Panel();
-	var widthSegments = new UI.Integer( geometry.parameters.widthSegments ).setRange( 1, Infinity ).onChange( update );
+	var widthSegments = new UI.Integer( parameters.widthSegments ).setRange( 1, Infinity ).onChange( update );
 
 	widthSegmentsRow.add( new UI.Text( 'Width segments' ).setWidth( '90px' ) );
 	widthSegmentsRow.add( widthSegments );
@@ -37,7 +37,7 @@ Sidebar.Geometry.PlaneGeometry = function ( signals, object ) {
 	// heightSegments
 
 	var heightSegmentsRow = new UI.Panel();
-	var heightSegments = new UI.Integer( geometry.parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
+	var heightSegments = new UI.Integer( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
 
 	heightSegmentsRow.add( new UI.Text( 'Height segments' ).setWidth( '90px' ) );
 	heightSegmentsRow.add( heightSegments );
@@ -61,7 +61,7 @@ Sidebar.Geometry.PlaneGeometry = function ( signals, object ) {
 		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
-		signals.objectChanged.dispatch( object );
+		signals.geometryChanged.dispatch( object );
 
 	}
 

+ 9 - 9
editor/js/Sidebar.Geometry.SphereGeometry.js

@@ -2,12 +2,12 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 
 	var container = new UI.Panel();
 
-	var geometry = object.geometry;
+	var parameters = object.geometry.parameters;
 
 	// radius
 
 	var radiusRow = new UI.Panel();
-	var radius = new UI.Number( geometry.parameters.radius ).onChange( update );
+	var radius = new UI.Number( parameters.radius ).onChange( update );
 
 	radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) );
 	radiusRow.add( radius );
@@ -17,7 +17,7 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 	// widthSegments
 
 	var widthSegmentsRow = new UI.Panel();
-	var widthSegments = new UI.Integer( geometry.parameters.widthSegments ).setRange( 1, Infinity ).onChange( update );
+	var widthSegments = new UI.Integer( parameters.widthSegments ).setRange( 1, Infinity ).onChange( update );
 
 	widthSegmentsRow.add( new UI.Text( 'Width segments' ).setWidth( '90px' ) );
 	widthSegmentsRow.add( widthSegments );
@@ -27,7 +27,7 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 	// heightSegments
 
 	var heightSegmentsRow = new UI.Panel();
-	var heightSegments = new UI.Integer( geometry.parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
+	var heightSegments = new UI.Integer( parameters.heightSegments ).setRange( 1, Infinity ).onChange( update );
 
 	heightSegmentsRow.add( new UI.Text( 'Height segments' ).setWidth( '90px' ) );
 	heightSegmentsRow.add( heightSegments );
@@ -37,7 +37,7 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 	// phiStart
 
 	var phiStartRow = new UI.Panel();
-	var phiStart = new UI.Number( geometry.parameters.phiStart ).onChange( update );
+	var phiStart = new UI.Number( parameters.phiStart ).onChange( update );
 
 	phiStartRow.add( new UI.Text( 'Phi start' ).setWidth( '90px' ) );
 	phiStartRow.add( phiStart );
@@ -47,7 +47,7 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 	// phiLength
 
 	var phiLengthRow = new UI.Panel();
-	var phiLength = new UI.Number( geometry.parameters.phiLength ).onChange( update );
+	var phiLength = new UI.Number( parameters.phiLength ).onChange( update );
 
 	phiLengthRow.add( new UI.Text( 'Phi length' ).setWidth( '90px' ) );
 	phiLengthRow.add( phiLength );
@@ -57,7 +57,7 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 	// thetaStart
 
 	var thetaStartRow = new UI.Panel();
-	var thetaStart = new UI.Number( geometry.parameters.thetaStart ).onChange( update );
+	var thetaStart = new UI.Number( parameters.thetaStart ).onChange( update );
 
 	thetaStartRow.add( new UI.Text( 'Theta start' ).setWidth( '90px' ) );
 	thetaStartRow.add( thetaStart );
@@ -67,7 +67,7 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 	// thetaLength
 
 	var thetaLengthRow = new UI.Panel();
-	var thetaLength = new UI.Number( geometry.parameters.thetaLength ).onChange( update );
+	var thetaLength = new UI.Number( parameters.thetaLength ).onChange( update );
 
 	thetaLengthRow.add( new UI.Text( 'Theta length' ).setWidth( '90px' ) );
 	thetaLengthRow.add( thetaLength );
@@ -94,7 +94,7 @@ Sidebar.Geometry.SphereGeometry = function ( signals, object ) {
 		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
-		signals.objectChanged.dispatch( object );
+		signals.geometryChanged.dispatch( object );
 
 	}
 

+ 7 - 7
editor/js/Sidebar.Geometry.TorusGeometry.js

@@ -2,12 +2,12 @@ Sidebar.Geometry.TorusGeometry = function ( signals, object ) {
 
 	var container = new UI.Panel();
 
-	var geometry = object.geometry;
+	var parameters = object.geometry.parameters;
 
 	// radius
 
 	var radiusRow = new UI.Panel();
-	var radius = new UI.Number( geometry.parameters.radius ).onChange( update );
+	var radius = new UI.Number( parameters.radius ).onChange( update );
 
 	radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) );
 	radiusRow.add( radius );
@@ -17,7 +17,7 @@ Sidebar.Geometry.TorusGeometry = function ( signals, object ) {
 	// tube
 
 	var tubeRow = new UI.Panel();
-	var tube = new UI.Number( geometry.parameters.tube ).onChange( update );
+	var tube = new UI.Number( parameters.tube ).onChange( update );
 
 	tubeRow.add( new UI.Text( 'Tube' ).setWidth( '90px' ) );
 	tubeRow.add( tube );
@@ -27,7 +27,7 @@ Sidebar.Geometry.TorusGeometry = function ( signals, object ) {
 	// radialSegments
 
 	var radialSegmentsRow = new UI.Panel();
-	var radialSegments = new UI.Integer( geometry.parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
+	var radialSegments = new UI.Integer( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
 
 	radialSegmentsRow.add( new UI.Text( 'Radial segments' ).setWidth( '90px' ) );
 	radialSegmentsRow.add( radialSegments );
@@ -37,7 +37,7 @@ Sidebar.Geometry.TorusGeometry = function ( signals, object ) {
 	// tubularSegments
 
 	var tubularSegmentsRow = new UI.Panel();
-	var tubularSegments = new UI.Integer( geometry.parameters.tubularSegments ).setRange( 1, Infinity ).onChange( update );
+	var tubularSegments = new UI.Integer( parameters.tubularSegments ).setRange( 1, Infinity ).onChange( update );
 
 	tubularSegmentsRow.add( new UI.Text( 'Tubular segments' ).setWidth( '90px' ) );
 	tubularSegmentsRow.add( tubularSegments );
@@ -47,7 +47,7 @@ Sidebar.Geometry.TorusGeometry = function ( signals, object ) {
 	// arc
 
 	var arcRow = new UI.Panel();
-	var arc = new UI.Number( geometry.parameters.arc ).onChange( update );
+	var arc = new UI.Number( parameters.arc ).onChange( update );
 
 	arcRow.add( new UI.Text( 'Arc' ).setWidth( '90px' ) );
 	arcRow.add( arc );
@@ -72,7 +72,7 @@ Sidebar.Geometry.TorusGeometry = function ( signals, object ) {
 		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
-		signals.objectChanged.dispatch( object );
+		signals.geometryChanged.dispatch( object );
 
 	}
 

+ 9 - 9
editor/js/Sidebar.Geometry.TorusKnotGeometry.js

@@ -2,12 +2,12 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 
 	var container = new UI.Panel();
 
-	var geometry = object.geometry;
+	var parameters = object.geometry.parameters;
 
 	// radius
 
 	var radiusRow = new UI.Panel();
-	var radius = new UI.Number( geometry.parameters.radius ).onChange( update );
+	var radius = new UI.Number( parameters.radius ).onChange( update );
 
 	radiusRow.add( new UI.Text( 'Radius' ).setWidth( '90px' ) );
 	radiusRow.add( radius );
@@ -17,7 +17,7 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 	// tube
 
 	var tubeRow = new UI.Panel();
-	var tube = new UI.Number( geometry.parameters.tube ).onChange( update );
+	var tube = new UI.Number( parameters.tube ).onChange( update );
 
 	tubeRow.add( new UI.Text( 'Tube' ).setWidth( '90px' ) );
 	tubeRow.add( tube );
@@ -27,7 +27,7 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 	// radialSegments
 
 	var radialSegmentsRow = new UI.Panel();
-	var radialSegments = new UI.Integer( geometry.parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
+	var radialSegments = new UI.Integer( parameters.radialSegments ).setRange( 1, Infinity ).onChange( update );
 
 	radialSegmentsRow.add( new UI.Text( 'Radial segments' ).setWidth( '90px' ) );
 	radialSegmentsRow.add( radialSegments );
@@ -37,7 +37,7 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 	// tubularSegments
 
 	var tubularSegmentsRow = new UI.Panel();
-	var tubularSegments = new UI.Integer( geometry.parameters.tubularSegments ).setRange( 1, Infinity ).onChange( update );
+	var tubularSegments = new UI.Integer( parameters.tubularSegments ).setRange( 1, Infinity ).onChange( update );
 
 	tubularSegmentsRow.add( new UI.Text( 'Tubular segments' ).setWidth( '90px' ) );
 	tubularSegmentsRow.add( tubularSegments );
@@ -47,7 +47,7 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 	// p
 
 	var pRow = new UI.Panel();
-	var p = new UI.Number( geometry.parameters.p ).onChange( update );
+	var p = new UI.Number( parameters.p ).onChange( update );
 
 	pRow.add( new UI.Text( 'P' ).setWidth( '90px' ) );
 	pRow.add( p );
@@ -57,7 +57,7 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 	// q
 
 	var qRow = new UI.Panel();
-	var q = new UI.Number( geometry.parameters.q ).onChange( update );
+	var q = new UI.Number( parameters.q ).onChange( update );
 
 	pRow.add( new UI.Text( 'Q' ).setWidth( '90px' ) );
 	pRow.add( q );
@@ -67,7 +67,7 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 	// heightScale
 
 	var heightScaleRow = new UI.Panel();
-	var heightScale = new UI.Number( geometry.parameters.heightScale ).onChange( update );
+	var heightScale = new UI.Number( parameters.heightScale ).onChange( update );
 
 	pRow.add( new UI.Text( 'Height scale' ).setWidth( '90px' ) );
 	pRow.add( heightScale );
@@ -94,7 +94,7 @@ Sidebar.Geometry.TorusKnotGeometry = function ( signals, object ) {
 		object.geometry.buffersNeedUpdate = true;
 		object.geometry.computeBoundingSphere();
 
-		signals.objectChanged.dispatch( object );
+		signals.geometryChanged.dispatch( object );
 
 	}
 

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

@@ -142,7 +142,6 @@ Sidebar.Geometry = function ( editor ) {
 	}
 
 	signals.objectSelected.add( build );
-	signals.objectChanged.add( build );
 
 	return container;
 

+ 5 - 0
editor/js/Sidebar.Scene.js

@@ -24,6 +24,11 @@ Sidebar.Scene = function ( editor ) {
 
 		ignoreObjectSelectedSignal = false;
 
+	} );
+	outliner.onDblClick( function () {
+
+		editor.focusById( parseInt( outliner.getValue() ) );
+
 	} );
 	container.add( outliner );
 	container.add( new UI.Break() );

+ 79 - 0
editor/js/Viewport.Info.js

@@ -0,0 +1,79 @@
+Viewport.Info = function ( editor ) {
+
+	var signals = editor.signals;
+
+	var container = new UI.Panel();
+	container.setPosition( 'absolute' );
+	container.setLeft( '10px' );
+	container.setBottom( '10px' );
+	container.setFontSize( '12px' );
+	container.setColor( '#fff' );
+
+	var objectsText = new UI.Text( '0' ).setMarginLeft( '6px' );
+	var verticesText = new UI.Text( '0' ).setMarginLeft( '6px' );
+	var trianglesText = new UI.Text( '0' ).setMarginLeft( '6px' );
+
+	container.add( new UI.Text( 'objects' ), objectsText, new UI.Break() );
+	container.add( new UI.Text( 'vertices' ), verticesText, new UI.Break() );
+	container.add( new UI.Text( 'triangles' ), trianglesText, new UI.Break() );
+
+	signals.objectAdded.add( update );
+	signals.objectRemoved.add( update );
+	signals.geometryChanged.add( update );
+
+	//
+
+	function update() {
+
+		var scene = editor.scene;
+
+		var objects = 0, vertices = 0, triangles = 0;
+
+		for ( var i = 0, l = scene.children.length; i < l; i ++ ) {
+
+			var object = scene.children[ i ];
+
+			object.traverseVisible( function ( object ) {
+
+				objects ++;
+
+				if ( object instanceof THREE.Mesh ) {
+
+					var geometry = object.geometry;
+
+					if ( geometry instanceof THREE.Geometry ) {
+
+						vertices += geometry.vertices.length;
+						triangles += geometry.faces.length;
+
+					} else if ( geometry instanceof THREE.BufferGeometry ) {
+
+						vertices += geometry.attributes.position.array.length / 3;
+
+						if ( geometry.attributes.index !== undefined ) {
+
+							triangles += geometry.attributes.index.array.length / 3;
+
+						} else {
+
+							triangles += geometry.attributes.position.array.length / 9;
+
+						}
+
+					}
+
+				}
+
+			} );
+
+		}
+
+		objectsText.setValue( objects.format() );
+		verticesText.setValue( vertices.format() );
+		trianglesText.setValue( triangles.format() );
+
+	}
+
+	return container;
+
+}

+ 14 - 57
editor/js/Viewport.js

@@ -5,14 +5,7 @@ var Viewport = function ( editor ) {
 	var container = new UI.Panel();
 	container.setPosition( 'absolute' );
 
-	var info = new UI.Text();
-	info.setPosition( 'absolute' );
-	info.setRight( '5px' );
-	info.setBottom( '5px' );
-	info.setFontSize( '12px' );
-	info.setColor( '#ffffff' );
-	info.setValue( 'objects: 0, vertices: 0, faces: 0' );
-	container.add( info );
+	container.add( new Viewport.Info( editor ) );
 
 	var scene = editor.scene;
 	var sceneHelpers = editor.sceneHelpers;
@@ -159,9 +152,11 @@ var Viewport = function ( editor ) {
 
 		var intersects = getIntersects( event, objects );
 
-		if ( intersects.length > 0 && intersects[ 0 ].object === editor.selected ) {
+		if ( intersects.length > 0 ) {
 
-			controls.focus( editor.selected );
+			var intersect = intersects[ 0 ];
+
+			signals.objectFocused.dispatch( intersect.object );
 
 		}
 
@@ -174,7 +169,7 @@ var Viewport = function ( editor ) {
 	// otherwise controls.enabled doesn't work.
 
 	var controls = new THREE.EditorControls( camera, container.dom );
-	controls.center.fromArray( editor.config.getKey( 'camera/target' ) )
+	controls.center.fromArray( editor.config.getKey( 'camera/target' ) );
 	controls.addEventListener( 'change', function () {
 
 		transformControls.update();
@@ -242,7 +237,6 @@ var Viewport = function ( editor ) {
 	signals.sceneGraphChanged.add( function () {
 
 		render();
-		updateInfo();
 
 	} );
 
@@ -294,6 +288,14 @@ var Viewport = function ( editor ) {
 
 	} );
 
+	signals.objectFocused.add( function ( object ) {
+
+		controls.focus( object );
+
+	} );
+
+	signals.geometryChanged.add( render );
+
 	signals.objectAdded.add( function ( object ) {
 
 		var materialsNeedUpdate = false;
@@ -328,8 +330,6 @@ var Viewport = function ( editor ) {
 
 			}
 
-			updateInfo();
-
 		}
 
 		render();
@@ -488,49 +488,6 @@ var Viewport = function ( editor ) {
 
 	//
 
-	function updateInfo() {
-
-		var objects = 0;
-		var vertices = 0;
-		var faces = 0;
-
-		scene.traverse( function ( object ) {
-
-			if ( object instanceof THREE.Mesh ) {
-
-				objects ++;
-
-				var geometry = object.geometry;
-
-				if ( geometry instanceof THREE.Geometry ) {
-
-					vertices += geometry.vertices.length;
-					faces += geometry.faces.length;
-
-				} else if ( geometry instanceof THREE.BufferGeometry ) {
-
-					vertices += geometry.attributes.position.array.length / 3;
-
-					if ( geometry.attributes.index !== undefined ) {
-
-						faces += geometry.attributes.index.array.length / 3;
-
-					} else {
-
-						faces += geometry.attributes.position.array.length / 9;
-
-					}
-
-				}
-
-			}
-
-		} );
-
-		info.setValue( 'objects: ' + objects + ', vertices: ' + vertices + ', faces: ' + faces );
-
-	}
-
 	function updateMaterials() {
 
 		editor.scene.traverse( function ( node ) {

+ 24 - 42
editor/js/libs/ui.js

@@ -69,7 +69,7 @@ properties.forEach( function ( property ) {
 
 // events
 
-var events = [ 'KeyUp', 'KeyDown', 'MouseOver', 'MouseOut', 'Click', 'Change' ];
+var events = [ 'KeyUp', 'KeyDown', 'MouseOver', 'MouseOut', 'Click', 'DblClick', 'Change' ];
 
 events.forEach( function ( event ) {
 
@@ -164,22 +164,24 @@ UI.CollapsiblePanel = function () {
 
 	UI.Panel.call( this );
 
-	this.dom.className = 'Panel CollapsiblePanel';
-
-	this.button = document.createElement( 'div' );
-	this.button.className = 'CollapsiblePanelButton';
-	this.dom.appendChild( this.button );
+	this.setClass( 'Panel Collapsible' );
 
 	var scope = this;
-	this.button.addEventListener( 'click', function ( event ) {
 
+	this.static = new UI.Panel();
+	this.static.setClass( 'Static' );
+	this.static.onClick( function () {
 		scope.toggle();
+	} );
+	this.dom.appendChild( this.static.dom );
 
-	}, false );
+	this.contents = new UI.Panel();
+	this.contents.setClass( 'Content' );
+	this.dom.appendChild( this.contents.dom );
 
-	this.content = document.createElement( 'div' );
-	this.content.className = 'CollapsibleContent';
-	this.dom.appendChild( this.content );
+	var button = new UI.Panel();
+	button.setClass( 'Button' );
+	this.static.add( button );
 
 	this.isCollapsed = false;
 
@@ -191,63 +193,43 @@ UI.CollapsiblePanel.prototype = Object.create( UI.Panel.prototype );
 
 UI.CollapsiblePanel.prototype.addStatic = function () {
 
-	for ( var i = 0; i < arguments.length; i ++ ) {
+	this.static.add.apply( this.static, arguments );
+	return this;
 
-		this.dom.insertBefore( arguments[ i ].dom, this.content );
+};
 
-	}
+UI.CollapsiblePanel.prototype.removeStatic = function () {
 
+	this.static.remove.apply( this.static, arguments );
 	return this;
 
 };
 
-UI.CollapsiblePanel.prototype.removeStatic = UI.Panel.prototype.remove;
-
 UI.CollapsiblePanel.prototype.clearStatic = function () {
 
-	this.dom.childNodes.forEach( function ( child ) {
-
-		if ( child !== this.content ) {
-
-			this.dom.removeChild( child );
-
-		}
-
-	});
+	this.static.clear();
+	return this;
 
 };
 
 UI.CollapsiblePanel.prototype.add = function () {
 
-	for ( var i = 0; i < arguments.length; i ++ ) {
-
-		this.content.appendChild( arguments[ i ].dom );
-
-	}
-
+	this.contents.add.apply( this.contents, arguments );
 	return this;
 
 };
 
 UI.CollapsiblePanel.prototype.remove = function () {
 
-	for ( var i = 0; i < arguments.length; i ++ ) {
-
-		this.content.removeChild( arguments[ i ].dom );
-
-	}
-
+	this.contents.remove.apply( this.contents, arguments );
 	return this;
 
 };
 
 UI.CollapsiblePanel.prototype.clear = function () {
 
-	while ( this.content.children.length ) {
-
-		this.content.removeChild( this.content.lastChild );
-
-	}
+	this.contents.clear();
+	return this;
 
 };
 

+ 2 - 4
examples/js/Mirror.js

@@ -171,8 +171,6 @@ THREE.Mirror.prototype.renderWithMirror = function ( otherMirror ) {
 
 THREE.Mirror.prototype.updateTextureMatrix = function () {
 
-	var sign = THREE.Math.sign;
-
 	this.updateMatrixWorld();
 	this.camera.updateMatrixWorld();
 
@@ -228,8 +226,8 @@ THREE.Mirror.prototype.updateTextureMatrix = function () {
 	var q = new THREE.Vector4();
 	var projectionMatrix = this.mirrorCamera.projectionMatrix;
 
-	q.x = ( sign(this.clipPlane.x) + projectionMatrix.elements[8] ) / projectionMatrix.elements[0];
-	q.y = ( sign(this.clipPlane.y) + projectionMatrix.elements[9] ) / projectionMatrix.elements[5];
+	q.x = ( Math.sign(this.clipPlane.x) + projectionMatrix.elements[8] ) / projectionMatrix.elements[0];
+	q.y = ( Math.sign(this.clipPlane.y) + projectionMatrix.elements[9] ) / projectionMatrix.elements[5];
 	q.z = - 1.0;
 	q.w = ( 1.0 + projectionMatrix.elements[10] ) / projectionMatrix.elements[14];
 

+ 1 - 1
examples/js/Ocean.js

@@ -203,7 +203,7 @@
 
 THREE.Ocean.prototype.generateMesh = function () {
 
-	var geometry = new THREE.PlaneGeometry( this.geometrySize, this.geometrySize, this.geometryResolution, this.geometryResolution );
+	var geometry = new THREE.PlaneBufferGeometry( this.geometrySize, this.geometrySize, this.geometryResolution, this.geometryResolution );
 
 	geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
 

+ 6 - 3
examples/js/controls/OrbitControls.js

@@ -75,6 +75,9 @@ THREE.OrbitControls = function ( object, domElement ) {
 	// The four arrow keys
 	this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
 
+	// Mouse buttons
+	this.mouseButtons = { ORBIT: THREE.MOUSE.LEFT, ZOOM: THREE.MOUSE.MIDDLE, PAN: THREE.MOUSE.RIGHT };
+
 	////////////
 	// internals
 
@@ -338,21 +341,21 @@ THREE.OrbitControls = function ( object, domElement ) {
 		if ( scope.enabled === false ) return;
 		event.preventDefault();
 
-		if ( event.button === 0 ) {
+		if ( event.button === scope.mouseButtons.ORBIT ) {
 			if ( scope.noRotate === true ) return;
 
 			state = STATE.ROTATE;
 
 			rotateStart.set( event.clientX, event.clientY );
 
-		} else if ( event.button === 1 ) {
+		} else if ( event.button === scope.mouseButtons.ZOOM ) {
 			if ( scope.noZoom === true ) return;
 
 			state = STATE.DOLLY;
 
 			dollyStart.set( event.clientX, event.clientY );
 
-		} else if ( event.button === 2 ) {
+		} else if ( event.button === scope.mouseButtons.PAN ) {
 			if ( scope.noPan === true ) return;
 
 			state = STATE.PAN;

+ 15 - 14
examples/js/effects/VREffect.js

@@ -22,6 +22,10 @@
  *
  */
 THREE.VREffect = function ( renderer, done ) {
+
+	var cameraLeft = new THREE.PerspectiveCamera();
+	var cameraRight = new THREE.PerspectiveCamera();
+
 	this._renderer = renderer;
 
 	this._init = function() {
@@ -72,36 +76,33 @@ THREE.VREffect = function ( renderer, done ) {
 			return;
 		}
 		// Regular render mode if not HMD
-		renderer.render.apply( this._renderer , arguments );
+		renderer.render.apply( this._renderer, arguments );
 	};
 
 	this.renderStereo = function( scene, camera, renderTarget, forceClear ) {
-		var cameraLeft;
-		var cameraRight;
+
 		var leftEyeTranslation = this.leftEyeTranslation;
 		var rightEyeTranslation = this.rightEyeTranslation;
 		var renderer = this._renderer;
 		var rendererWidth = renderer.domElement.width / renderer.devicePixelRatio;
 		var rendererHeight = renderer.domElement.height / renderer.devicePixelRatio;
 		var eyeDivisionLine = rendererWidth / 2;
+
 		renderer.enableScissorTest( true );
 		renderer.clear();
 
-		// Grab camera matrix from user.
-		// This is interpreted as the head base.
-		if ( camera.matrixAutoUpdate ) {
-			camera.updateMatrix();
+		if ( camera.parent === undefined ) {
+			camera.updateMatrixWorld();
 		}
-		var eyeWorldMatrix = camera.matrixWorld.clone();
 
-		cameraLeft = camera.clone();
-		cameraRight = camera.clone();
 		cameraLeft.projectionMatrix = this.FovToProjection( this.leftEyeFOV );
 		cameraRight.projectionMatrix = this.FovToProjection( this.rightEyeFOV );
-		cameraLeft.position.add(new THREE.Vector3(
-			leftEyeTranslation.x, leftEyeTranslation.y, leftEyeTranslation.z) );
-		cameraRight.position.add(new THREE.Vector3(
-			rightEyeTranslation.x, rightEyeTranslation.y, rightEyeTranslation.z) );
+
+		camera.matrixWorld.decompose( cameraLeft.position, cameraLeft.quaternion, cameraLeft.scale );
+		camera.matrixWorld.decompose( cameraRight.position, cameraRight.quaternion, cameraRight.scale );
+
+		cameraLeft.translateX( leftEyeTranslation.x );
+		cameraRight.translateX( rightEyeTranslation.x );
 
 		// render left eye
 		renderer.setViewport( 0, 0, eyeDivisionLine, rendererHeight );

+ 21 - 1
examples/js/loaders/AssimpJSONLoader.js

@@ -31,7 +31,27 @@ THREE.AssimpJSONLoader.prototype = {
 		var loader = new THREE.XHRLoader( this.manager );
 		loader.setCrossOrigin( this.crossOrigin );
 		loader.load( url, function ( text ) {
-			var scene = scope.parse( JSON.parse( text ) );
+			var json = JSON.parse( text ), scene, metadata;
+
+			// Check __metadata__ meta header if present
+			// This header is used to disambiguate between
+			// different JSON-based file formats.
+			metadata = json.__metadata__;
+			if ( typeof metadata !== 'undefined' )
+			{
+				// Check if assimp2json at all
+				if ( metadata.format !== 'assimp2json' ) {
+					onError('Not an assimp2json scene');
+					return;
+				}
+				// Check major format version
+				else if ( metadata.version < 100 && metadata.version >= 200 ) {
+					onError('Unsupported assimp2json file format version');
+					return;
+				}
+			}
+
+			scene = scope.parse( json );
 			onLoad( scene );
 		} );
 	},

+ 15 - 43
examples/js/loaders/VTKLoader.js

@@ -8,53 +8,24 @@ THREE.VTKLoader.prototype = {
 
 	constructor: THREE.VTKLoader,
 
-	load: function ( url, callback ) {
+	load: function ( url, onLoad, onProgress, onError ) {
 
 		var scope = this;
-		var request = new XMLHttpRequest();
 
-		request.addEventListener( 'load', function ( event ) {
+		var loader = new THREE.XHRLoader( scope.manager );
+		loader.setCrossOrigin( this.crossOrigin );
+		loader.load( url, function ( text ) {
 
-			var geometry = scope.parse( event.target.responseText );
+			onLoad( scope.parse( text ) );
 
-			scope.dispatchEvent( { type: 'load', content: geometry } );
-
-			if ( callback ) callback( geometry );
-
-		}, false );
-
-		request.addEventListener( 'progress', function ( event ) {
-
-			scope.dispatchEvent( { type: 'progress', loaded: event.loaded, total: event.total } );
-
-		}, false );
-
-		request.addEventListener( 'error', function () {
-
-			scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
-
-		}, false );
-
-		request.open( 'GET', url, true );
-		request.send( null );
+		} );
 
 	},
 
 	parse: function ( data ) {
 
-		var geometry = new THREE.Geometry();
-
-		var vertex = function ( x, y, z ) {
-
-			geometry.vertices.push( new THREE.Vector3( x, y, z ) );
-
-		}
-
-		var face3 = function ( a, b, c ) {
-
-			geometry.faces.push( new THREE.Face3( a, b, c ) );
-
-		}
+		var indices = [];
+		var positions = [];
 
 		var pattern, result;
 
@@ -66,7 +37,7 @@ THREE.VTKLoader.prototype = {
 
 			// ["1.0 2.0 3.0", "1.0", "2.0", "3.0"]
 
-			vertex( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
+			positions.push( parseFloat( result[ 1 ] ), parseFloat( result[ 2 ] ), parseFloat( result[ 3 ] ) );
 
 		}
 
@@ -78,7 +49,7 @@ THREE.VTKLoader.prototype = {
 
 			// ["3 1 2 3", "1", "2", "3"]
 
-			face3( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 3 ] ) );
+			indices.push( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 3 ] ) );
 
 		}
 
@@ -90,14 +61,15 @@ THREE.VTKLoader.prototype = {
 
 			// ["4 1 2 3 4", "1", "2", "3", "4"]
 
-			face3( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 4 ] ) );
-			face3( parseInt( result[ 2 ] ), parseInt( result[ 3 ] ), parseInt( result[ 4 ] ) );
+			indices.push( parseInt( result[ 1 ] ), parseInt( result[ 2 ] ), parseInt( result[ 4 ] ) );
+			indices.push( parseInt( result[ 2 ] ), parseInt( result[ 3 ] ), parseInt( result[ 4 ] ) );
 
 		}
 
-		geometry.computeFaceNormals();
+		var geometry = new THREE.BufferGeometry();
+		geometry.addAttribute( 'index', new THREE.BufferAttribute( new ( indices.length > 65535 ? Uint32Array : Uint16Array )( indices ), 1 ) );
+		geometry.addAttribute( 'position', new THREE.BufferAttribute( new Float32Array( positions ), 3 ) );
 		geometry.computeVertexNormals();
-		geometry.computeBoundingSphere();
 
 		return geometry;
 

+ 1 - 1
examples/js/loaders/ctm/CTMLoader.js

@@ -248,7 +248,7 @@ THREE.CTMLoader.prototype.createModel = function ( file, callback ) {
 	geometry.computeOffsets();
 
 	// compute vertex normals if not present in the CTM model
-	if ( geometry.attributes[ "normal" ] === undefined ) {
+	if ( geometry.attributes.normal === undefined ) {
 		geometry.computeVertexNormals();
 	}
 

+ 7 - 31
examples/js/loaders/gltf/glTFLoader.js

@@ -102,18 +102,9 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
     ClassicGeometry.prototype.buildBufferGeometry = function() {
         // Build indexed mesh
         var geometry = this.geometry;
-        geometry.attributes.index = {
-        		itemSize: 1,
-        		array : this.indexArray
-        };
-
-		var offset = {
-				start: 0,
-				index: 0,
-				count: this.indexArray.length
-			};
 
-		geometry.offsets.push( offset );
+        geometry.addAttribute( 'index', new THREE.BufferAttribute( this.indexArray, 1 ) );
+        geometry.addDrawCall( 0, this.indexArray.length, 0 );
 
         geometry.computeBoundingSphere();
     }
@@ -226,16 +217,10 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
         if(semantic == "POSITION") {
             // TODO: Should be easy to take strides into account here
             floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
-            geom.geometry.attributes.position = {
-            		itemSize: 3,
-            		array : floatArray
-            };
+            geom.geometry.addAttribute( 'position', new THREE.BufferAttribute( floatArray, 3 ) );
         } else if(semantic == "NORMAL") {
             floatArray = new Float32Array(glResource, 0, attribute.count * componentsPerElementForGLType(attribute.type));
-            geom.geometry.attributes.normal = {
-            		itemSize: 3,
-            		array : floatArray
-            };
+            geom.geometry.addAttribute( 'normal', new THREE.BufferAttribute( floatArray, 3 ) );
         } else if ((semantic == "TEXCOORD_0") || (semantic == "TEXCOORD" )) {
         	
         	nComponents = componentsPerElementForGLType(attribute.type);
@@ -244,26 +229,17 @@ THREE.glTFLoader.prototype.load = function( url, callback ) {
             for (i = 0; i < floatArray.length / 2; i++) {
             	floatArray[i*2+1] = 1.0 - floatArray[i*2+1];
             }
-            geom.geometry.attributes.uv = {
-            		itemSize: nComponents,
-            		array : floatArray
-            };
+            geom.geometry.addAttribute( 'uv', new THREE.BufferAttribute( floatArray, nComponents ) );
         }
         else if (semantic == "WEIGHT") {
         	nComponents = componentsPerElementForGLType(attribute.type);
             floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
-            geom.geometry.attributes.skinWeight = {
-            		itemSize: nComponents,
-            		array : floatArray
-            };        	
+            geom.geometry.addAttribute( 'skinWeight', new THREE.BufferAttribute( floatArray, nComponents ) );
         }
         else if (semantic == "JOINT") {
         	nComponents = componentsPerElementForGLType(attribute.type);
             floatArray = new Float32Array(glResource, 0, attribute.count * nComponents);
-            geom.geometry.attributes.skinIndex = {
-            		itemSize: nComponents,
-            		array : floatArray
-            };        	
+            geom.geometry.addAttribute( 'skinIndex', new THREE.BufferAttribute( floatArray, nComponents ) );
         }
     }
     

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

@@ -69,7 +69,7 @@ THREE.BloomPass = function ( strength, kernelSize, sigma, resolution ) {
 	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.scene  = new THREE.Scene();
 
-	this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
 	this.scene.add( this.quad );
 
 };

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

@@ -61,7 +61,7 @@ THREE.BokehPass = function ( scene, camera, params ) {
 	this.camera2 = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.scene2  = new THREE.Scene();
 
-	this.quad2 = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.quad2 = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
 	this.scene2.add( this.quad2 );
 
 };

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

@@ -31,7 +31,7 @@ THREE.DotScreenPass = function ( center, angle, scale ) {
 	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.scene  = new THREE.Scene();
 
-	this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
 	this.scene.add( this.quad );
 
 };

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

@@ -32,7 +32,7 @@ THREE.FilmPass = function ( noiseIntensity, scanlinesIntensity, scanlinesCount,
 	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.scene  = new THREE.Scene();
 
-	this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
 	this.scene.add( this.quad );
 
 };

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

@@ -31,7 +31,7 @@ THREE.GlitchPass = function ( dt_size ) {
 	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.scene  = new THREE.Scene();
 
-	this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
 	this.scene.add( this.quad );
 	
 	this.goWild=false;

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

@@ -38,7 +38,7 @@ THREE.SavePass = function ( renderTarget ) {
 	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.scene  = new THREE.Scene();
 
-	this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
 	this.scene.add( this.quad );
 
 };

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

@@ -26,7 +26,7 @@ THREE.ShaderPass = function ( shader, textureID ) {
 	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.scene  = new THREE.Scene();
 
-	this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
 	this.scene.add( this.quad );
 
 };

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

@@ -29,7 +29,7 @@ THREE.TexturePass = function ( texture, opacity ) {
 	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.scene  = new THREE.Scene();
 
-	this.quad = new THREE.Mesh( new THREE.PlaneGeometry( 2, 2 ), null );
+	this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null );
 	this.scene.add( this.quad );
 
 };

+ 6 - 2
examples/js/renderers/SVGRenderer.js

@@ -38,6 +38,8 @@ THREE.SVGRenderer = function () {
 	_w, // z-buffer to w-buffer
 	_vector3 = new THREE.Vector3(), // Needed for PointLight
 	_centroid = new THREE.Vector3(),
+	_normal = new THREE.Vector3(),
+	_normalViewMatrix = new THREE.Matrix3(),
 
 	_viewMatrix = new THREE.Matrix4(),
 	_viewProjectionMatrix = new THREE.Matrix4(),
@@ -137,6 +139,8 @@ THREE.SVGRenderer = function () {
 		_elements = _renderData.elements;
 		_lights = _renderData.lights;
 
+		_normalViewMatrix.getNormalMatrix( camera.matrixWorldInverse );
+
 		calculateLights( _lights );
 
 		for ( var e = 0, el = _elements.length; e < el; e ++ ) {
@@ -383,9 +387,9 @@ THREE.SVGRenderer = function () {
 
 		} else if ( material instanceof THREE.MeshNormalMaterial ) {
 
-			var normal = element.normalModelView;
+			_normal.copy( element.normalModel ).applyMatrix3( _normalViewMatrix );
 
-			_color.setRGB( normal.x, normal.y, normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );
+			_color.setRGB( _normal.x, _normal.y, _normal.z ).multiplyScalar( 0.5 ).addScalar( 0.5 );
 
 		}
 

+ 18 - 20
examples/js/wip/TypedGeometry.js

@@ -8,13 +8,11 @@ THREE.TypedGeometry = function ( size ) {
 
 	if ( size !== undefined ) {
 
-		this.vertices = new Float32Array( size * 3 * 3 );
-		this.normals = new Float32Array( size * 3 * 3 );
-		this.uvs = new Float32Array( size * 3 * 2 );
-
-		this.attributes[ 'position' ] = { array: this.vertices, itemSize: 3 };
-		this.attributes[ 'normal' ] = { array: this.normals, itemSize: 3 };
-		this.attributes[ 'uv' ] = { array: this.uvs, itemSize: 2 };
+		this.setArrays( 
+			new Float32Array( size * 3 * 3 ),
+			new Float32Array( size * 3 * 3 ),
+			new Float32Array( size * 3 * 2 )
+		);
 
 	}
 
@@ -28,9 +26,9 @@ THREE.TypedGeometry.prototype.setArrays = function ( vertices, normals, uvs ) {
 	this.normals = normals;
 	this.uvs = uvs;
 
-	this.attributes[ 'position' ] = { array: vertices, itemSize: 3 };
-	this.attributes[ 'normal' ] = { array: normals, itemSize: 3 };
-	this.attributes[ 'uv' ] = { array: uvs, itemSize: 2 };
+	this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
+	this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+	this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
 
 	return this;
 
@@ -48,15 +46,15 @@ THREE.TypedGeometry.prototype.merge = ( function () {
 		var offset2 = offset * 2;
 		var offset3 = offset * 3;
 
-		var vertices = this.attributes[ 'position' ].array;
-		var normals = this.attributes[ 'normal' ].array;
-		var uvs = this.attributes[ 'uv' ].array;
+		var vertices = this.attributes.position.array;
+		var normals = this.attributes.normal.array;
+		var uvs = this.attributes.uv.array;
 
 		if ( geometry instanceof THREE.TypedGeometry ) {
 
-			var vertices2 = geometry.attributes[ 'position' ].array;
-			var normals2 = geometry.attributes[ 'normal' ].array;
-			var uvs2 = geometry.attributes[ 'uv' ].array;
+			var vertices2 = geometry.attributes.position.array;
+			var normals2 = geometry.attributes.normal.array;
+			var uvs2 = geometry.attributes.uv.array;
 
 			for ( var i = 0, l = vertices2.length; i < l; i += 3 ) {
 
@@ -75,10 +73,10 @@ THREE.TypedGeometry.prototype.merge = ( function () {
 
 		} else if ( geometry instanceof THREE.IndexedTypedGeometry ) {
 
-			var indices2 = geometry.attributes[ 'index' ].array;
-			var vertices2 = geometry.attributes[ 'position' ].array;
-			var normals2 = geometry.attributes[ 'normal' ].array;
-			var uvs2 = geometry.attributes[ 'uv' ].array;
+			var indices2 = geometry.attributes.index.array;
+			var vertices2 = geometry.attributes.position.array;
+			var normals2 = geometry.attributes.normal.array;
+			var uvs2 = geometry.attributes.uv.array;
 
 			for ( var i = 0, l = indices2.length; i < l; i ++ ) {
 

+ 8 - 12
examples/misc_controls_pointerlock.html

@@ -181,12 +181,8 @@
 				scene = new THREE.Scene();
 				scene.fog = new THREE.Fog( 0xffffff, 0, 750 );
 
-				var light = new THREE.DirectionalLight( 0xffffff, 1.5 );
-				light.position.set( 1, 1, 1 );
-				scene.add( light );
-
-				var light = new THREE.DirectionalLight( 0xffffff, 0.75 );
-				light.position.set( -1, - 0.5, -1 );
+				var light = new THREE.HemisphereLight( 0xeeeeff, 0x777788, 0.75 );
+				light.position.set( 0.5, 1, 0.75 );
 				scene.add( light );
 
 				controls = new THREE.PointerLockControls( camera );
@@ -211,9 +207,9 @@
 				for ( var i = 0, l = geometry.faces.length; i < l; i ++ ) {
 
 					var face = geometry.faces[ i ];
-					face.vertexColors[ 0 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
-					face.vertexColors[ 1 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
-					face.vertexColors[ 2 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
+					face.vertexColors[ 0 ] = new THREE.Color().setHSL( Math.random() * 0.3 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
+					face.vertexColors[ 1 ] = new THREE.Color().setHSL( Math.random() * 0.3 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
+					face.vertexColors[ 2 ] = new THREE.Color().setHSL( Math.random() * 0.3 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
 
 				}
 
@@ -229,9 +225,9 @@
 				for ( var i = 0, l = geometry.faces.length; i < l; i ++ ) {
 
 					var face = geometry.faces[ i ];
-					face.vertexColors[ 0 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
-					face.vertexColors[ 1 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
-					face.vertexColors[ 2 ] = new THREE.Color().setHSL( Math.random() * 0.2 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
+					face.vertexColors[ 0 ] = new THREE.Color().setHSL( Math.random() * 0.3 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
+					face.vertexColors[ 1 ] = new THREE.Color().setHSL( Math.random() * 0.3 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
+					face.vertexColors[ 2 ] = new THREE.Color().setHSL( Math.random() * 0.3 + 0.5, 0.75, Math.random() * 0.25 + 0.75 );
 
 				}
 

+ 11 - 55
examples/misc_sound.html

@@ -59,49 +59,8 @@
 			var mesh;
 			var material_sphere1, material_sphere2;
 
-			var sound1, sound2;
-
 			var clock = new THREE.Clock();
 
-			var Sound = function ( sources, radius, volume ) {
-
-				var audio = document.createElement( 'audio' );
-
-				for ( var i = 0; i < sources.length; i ++ ) {
-
-					var source = document.createElement( 'source' );
-					source.src = sources[ i ];
-
-					audio.appendChild( source );
-
-				}
-
-				this.position = new THREE.Vector3();
-
-				this.play = function () {
-
-					audio.play();
-
-				}
-
-				this.update = function ( camera ) {
-
-					var distance = this.position.distanceTo( camera.position );
-
-					if ( distance <= radius ) {
-
-						audio.volume = volume * ( 1 - distance / radius );
-
-					} else {
-
-						audio.volume = 0;
-
-					}
-
-				}
-
-			}
-
 			init();
 			animate();
 
@@ -112,6 +71,9 @@
 				camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 10000 );
 				camera.position.set( 0, 25, 0 );
 
+				var listener = new THREE.AudioListener();
+				camera.add( listener );
+
 				controls = new THREE.FirstPersonControls( camera );
 
 				controls.movementSpeed = 70;
@@ -133,28 +95,25 @@
 
 				// sound spheres
 
-				var s = 1;
-
 				var mesh1 = new THREE.Mesh( sphere, material_sphere1 );
 				mesh1.position.set( -250, 30, 0 );
-				mesh1.scale.set( s, s, s );
 				scene.add( mesh1 );
 
-				sound1 = new Sound( [ 'sounds/358232_j_s_song.mp3', 'sounds/358232_j_s_song.ogg' ], 275, 1 );
-				sound1.position.copy( mesh1.position );
-				sound1.play();
+				var sound1 = new THREE.Audio( listener );
+				sound1.load( 'sounds/358232_j_s_song.ogg' );
+				sound1.setRefDistance( 20 );
+				mesh1.add( sound1 );
 
 				//
 
 				var mesh2 = new THREE.Mesh( sphere, material_sphere2 );
 				mesh2.position.set( 250, 30, 0 );
-				mesh2.scale.set( s, s, s );
 				scene.add( mesh2 );
 
-				sound2 = new Sound( [ 'sounds/376737_Skullbeatz___Bad_Cat_Maste.mp3', 'sounds/376737_Skullbeatz___Bad_Cat_Maste.ogg' ], 275, 1 );
-				sound2.position.copy( mesh2.position );
-				sound2.play();
-
+				var sound2 = new THREE.Audio( listener );
+				sound2.load( 'sounds/376737_Skullbeatz___Bad_Cat_Maste.ogg' );
+				sound2.setRefDistance( 20 );
+				mesh2.add( sound2 );
 
 				// ground
 
@@ -210,9 +169,6 @@
 
 				renderer.render( scene, camera );
 
-				sound1.update( camera );
-				sound2.update( camera );
-
 			}
 
 		</script>

+ 5 - 1
examples/models/assimp/interior/interior.3ds.json → examples/models/assimp/interior/interior.assimp.json

@@ -1,5 +1,9 @@
 {
-	 "rootnode": {
+	 "__metadata__": {
+	 	 "format" : "assimp2json"
+	 	,"version": 100
+	}
+	,"rootnode": {
 		 "name": "<3DSRoot>"
 		,"transformation": [
 			 1

+ 5 - 1
examples/models/assimp/jeep/jeep1.ms3d.json → examples/models/assimp/jeep/jeep.assimp.json

@@ -1,5 +1,9 @@
 {
-	 "rootnode": {
+	 "__metadata__": {
+	 	 "format" : "assimp2json"
+	 	,"version": 100
+	}
+	,"rootnode": {
 		 "name": "<MS3DRoot>"
 		,"transformation": [
 			 1

BIN
examples/models/skinned/simple/simple.blend


File diff suppressed because it is too large
+ 54 - 0
examples/models/skinned/simple/simple.js


+ 2 - 2
examples/webgl_effects_vr.html

@@ -36,7 +36,7 @@
 	<body>
 		<div class="button">Start VR Mode</div>
 
-		<script src="../build/three.js"></script>
+		<script src="../build/three.min.js"></script>
 		<script src="js/effects/VREffect.js"></script>
 		<script src="js/controls/VRControls.js"></script>
 		<script src="js/libs/stats.min.js"></script>
@@ -105,7 +105,7 @@
 				projector = new THREE.Projector();
 				raycaster = new THREE.Raycaster();
 
-				renderer = new THREE.WebGLRenderer();
+				renderer = new THREE.WebGLRenderer( { antialias: true } );
 
 				var fullScreenButton = document.querySelector( '.button' );
 				fullScreenButton.onclick = function() {

+ 0 - 1
examples/webgl_geometry_dynamic.html

@@ -87,7 +87,6 @@
 
 				geometry = new THREE.PlaneGeometry( 20000, 20000, worldWidth - 1, worldDepth - 1 );
 				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
-				geometry.dynamic = true;
 
 				var i, j, il, jl;
 

+ 12 - 12
examples/webgl_geometry_minecraft_ao.html

@@ -103,8 +103,8 @@
 				var matrix = new THREE.Matrix4();
 
 				var pxGeometry = new THREE.PlaneGeometry( 100, 100 );
-				pxGeometry.faces[ 0 ].vertexColors.push( light, shadow, light );
-				pxGeometry.faces[ 1 ].vertexColors.push( shadow, shadow, light );
+				pxGeometry.faces[ 0 ].vertexColors = [ light, shadow, light ];
+				pxGeometry.faces[ 1 ].vertexColors = [ shadow, shadow, light ];
 				pxGeometry.faceVertexUvs[ 0 ][ 0 ][ 0 ].y = 0.5;
 				pxGeometry.faceVertexUvs[ 0 ][ 0 ][ 2 ].y = 0.5;
 				pxGeometry.faceVertexUvs[ 0 ][ 1 ][ 2 ].y = 0.5;
@@ -112,8 +112,8 @@
 				pxGeometry.applyMatrix( matrix.makeTranslation( 50, 0, 0 ) );
 
 				var nxGeometry = new THREE.PlaneGeometry( 100, 100 );
-				nxGeometry.faces[ 0 ].vertexColors.push( light, shadow, light );
-				nxGeometry.faces[ 1 ].vertexColors.push( shadow, shadow, light );
+				nxGeometry.faces[ 0 ].vertexColors = [ light, shadow, light ];
+				nxGeometry.faces[ 1 ].vertexColors = [ shadow, shadow, light ];
 				nxGeometry.faceVertexUvs[ 0 ][ 0 ][ 0 ].y = 0.5;
 				nxGeometry.faceVertexUvs[ 0 ][ 0 ][ 2 ].y = 0.5;
 				nxGeometry.faceVertexUvs[ 0 ][ 1 ][ 2 ].y = 0.5;
@@ -121,8 +121,8 @@
 				nxGeometry.applyMatrix( matrix.makeTranslation( - 50, 0, 0 ) );
 
 				var pyGeometry = new THREE.PlaneGeometry( 100, 100 );
-				pyGeometry.faces[ 0 ].vertexColors.push( light, light, light );
-				pyGeometry.faces[ 1 ].vertexColors.push( light, light, light );
+				pyGeometry.faces[ 0 ].vertexColors = [ light, light, light ];
+				pyGeometry.faces[ 1 ].vertexColors = [ light, light, light ];
 				pyGeometry.faceVertexUvs[ 0 ][ 0 ][ 1 ].y = 0.5;
 				pyGeometry.faceVertexUvs[ 0 ][ 1 ][ 0 ].y = 0.5;
 				pyGeometry.faceVertexUvs[ 0 ][ 1 ][ 1 ].y = 0.5;
@@ -130,8 +130,8 @@
 				pyGeometry.applyMatrix( matrix.makeTranslation( 0, 50, 0 ) );
 
 				var py2Geometry = new THREE.PlaneGeometry( 100, 100 );
-				py2Geometry.faces[ 0 ].vertexColors.push( light, light, light );
-				py2Geometry.faces[ 1 ].vertexColors.push( light, light, light );
+				py2Geometry.faces[ 0 ].vertexColors = [ light, light, light ];
+				py2Geometry.faces[ 1 ].vertexColors = [ light, light, light ];
 				py2Geometry.faceVertexUvs[ 0 ][ 0 ][ 1 ].y = 0.5;
 				py2Geometry.faceVertexUvs[ 0 ][ 1 ][ 0 ].y = 0.5;
 				py2Geometry.faceVertexUvs[ 0 ][ 1 ][ 1 ].y = 0.5;
@@ -140,16 +140,16 @@
 				py2Geometry.applyMatrix( matrix.makeTranslation( 0, 50, 0 ) );
 
 				var pzGeometry = new THREE.PlaneGeometry( 100, 100 );
-				pzGeometry.faces[ 0 ].vertexColors.push( light, shadow, light );
-				pzGeometry.faces[ 1 ].vertexColors.push( shadow, shadow, light );
+				pzGeometry.faces[ 0 ].vertexColors = [ light, shadow, light ];
+				pzGeometry.faces[ 1 ].vertexColors = [ shadow, shadow, light ];
 				pzGeometry.faceVertexUvs[ 0 ][ 0 ][ 0 ].y = 0.5;
 				pzGeometry.faceVertexUvs[ 0 ][ 0 ][ 2 ].y = 0.5;
 				pzGeometry.faceVertexUvs[ 0 ][ 1 ][ 2 ].y = 0.5;
 				pzGeometry.applyMatrix( matrix.makeTranslation( 0, 0, 50 ) );
 
 				var nzGeometry = new THREE.PlaneGeometry( 100, 100 );
-				nzGeometry.faces[ 0 ].vertexColors.push( light, shadow, light );
-				nzGeometry.faces[ 1 ].vertexColors.push( shadow, shadow, light );
+				nzGeometry.faces[ 0 ].vertexColors = [ light, shadow, light ];
+				nzGeometry.faces[ 1 ].vertexColors = [ shadow, shadow, light ];
 				nzGeometry.faceVertexUvs[ 0 ][ 0 ][ 0 ].y = 0.5;
 				nzGeometry.faceVertexUvs[ 0 ][ 0 ][ 2 ].y = 0.5;
 				nzGeometry.faceVertexUvs[ 0 ][ 1 ][ 2 ].y = 0.5;

+ 2 - 2
examples/webgl_geometry_normals.html

@@ -287,8 +287,6 @@
 				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
 				camera.position.z = 500;
 
-				controls = new THREE.OrbitControls( camera );
-
 				scene = new THREE.Scene();
 
 				var light = new THREE.PointLight( 0xffffff, 1.5 );
@@ -310,6 +308,8 @@
 
 				//
 
+				controls = new THREE.OrbitControls( camera, renderer.domElement );
+
 				window.addEventListener( 'resize', onWindowResize, false );
 
 			}

+ 2 - 2
examples/webgl_geometry_subdivision.html

@@ -280,8 +280,6 @@
 				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
 				camera.position.z = 500;
 
-				controls = new THREE.OrbitControls( camera );
-
 				scene = new THREE.Scene();
 
 				var light = new THREE.PointLight( 0xffffff, 1.5 );
@@ -303,6 +301,8 @@
 
 				//
 
+				controls = new THREE.OrbitControls( camera, renderer.domElement );
+
 				window.addEventListener( 'resize', onWindowResize, false );
 
 			}

+ 5 - 3
examples/webgl_geometry_terrain.html

@@ -81,12 +81,14 @@
 
 				camera.position.y = data[ worldHalfWidth + worldHalfDepth * worldWidth ] * 10 + 500;
 
-				var geometry = new THREE.PlaneGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 );
+				var geometry = new THREE.PlaneBufferGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 );
 				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
 
-				for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
+				var vertices = geometry.attributes.position.array;
 
-					geometry.vertices[ i ].y = data[ i ] * 10;
+				for ( var i = 0, j = 0, l = vertices.length; i < l; i ++, j += 3 ) {
+
+					vertices[ j + 1 ] = data[ i ] * 10;
 
 				}
 

+ 5 - 3
examples/webgl_geometry_terrain_fog.html

@@ -83,12 +83,14 @@
 
 				camera.position.y = data[ worldHalfWidth + worldHalfDepth * worldWidth ] * 10 + 500;
 
-				var geometry = new THREE.PlaneGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 );
+				var geometry = new THREE.PlaneBufferGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 );
 				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
 
-				for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
+				var vertices = geometry.attributes.position.array;
 
-					geometry.vertices[ i ].y = data[ i ] * 10;
+				for ( var i = 0, j = 0, l = vertices.length; i < l; i ++, j += 3 ) {
+
+					vertices[ j + 1 ] = data[ i ] * 10;
 
 				}
 

+ 5 - 3
examples/webgl_geometry_terrain_raycast.html

@@ -86,12 +86,14 @@
 				camera.position.y =  controls.center.y + 2000;
 				camera.position.x = 2000;
 
-				var geometry = new THREE.PlaneGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 );
+				var geometry = new THREE.PlaneBufferGeometry( 7500, 7500, worldWidth - 1, worldDepth - 1 );
 				geometry.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
 
-				for ( var i = 0, l = geometry.vertices.length; i < l; i ++ ) {
+				var vertices = geometry.attributes.position.array;
 
-					geometry.vertices[ i ].y = data[ i ] * 10;
+				for ( var i = 0, j = 0, l = vertices.length; i < l; i ++, j += 3 ) {
+
+					vertices[ j + 1 ] = data[ i ] * 10;
 
 				}
 

+ 2 - 2
examples/webgl_loader_assimp2json.html

@@ -82,7 +82,7 @@
 
 			// Load jeep model using the AssimpJSONLoader
 			var loader1 = new THREE.AssimpJSONLoader();
-			loader1.load( 'models/assimp/jeep/jeep1.ms3d.json', function ( assimpjson ) {
+			loader1.load( 'models/assimp/jeep/jeep.assimp.json', function ( assimpjson ) {
 
 				assimpjson.scale.x = assimpjson.scale.y = assimpjson.scale.z = 0.2;
 				assimpjson.updateMatrix();
@@ -93,7 +93,7 @@
 
 			// load interior model
 			var loader2 = new THREE.AssimpJSONLoader();
-			loader2.load( 'models/assimp/interior/interior.3ds.json', function ( assimpjson ) {
+			loader2.load( 'models/assimp/interior/interior.assimp.json', function ( assimpjson ) {
 
 				assimpjson.scale.x = assimpjson.scale.y = assimpjson.scale.z = 1;
 				assimpjson.updateMatrix();

+ 1 - 4
examples/webgl_loader_obj.html

@@ -33,12 +33,9 @@
 		<script src="../build/three.min.js"></script>
 		<script src="js/loaders/OBJLoader.js"></script>
 
-		<script src="js/Detector.js"></script>
-		<script src="js/libs/stats.min.js"></script>
-
 		<script>
 
-			var container, stats;
+			var container;
 
 			var camera, scene, renderer;
 

+ 1 - 4
examples/webgl_loader_vtk.html

@@ -86,16 +86,13 @@
 				var material = new THREE.MeshLambertMaterial( { color:0xffffff, side: THREE.DoubleSide } );
 
 				var loader = new THREE.VTKLoader();
-				loader.addEventListener( 'load', function ( event ) {
-
-					var geometry = event.content;
+				loader.load( "models/vtk/bunny.vtk", function ( geometry ) {
 
 					var mesh = new THREE.Mesh( geometry, material );
 					mesh.position.setY( - 0.09 );
 					scene.add( mesh );
 
 				} );
-				loader.load( "models/vtk/bunny.vtk" );
 
 				// renderer
 

+ 40 - 32
examples/webgl_materials_cubemap_dynamic.html

@@ -396,7 +396,12 @@
 
 				renderer.autoClear = false;
 
-				var renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
+				var renderTargetParameters = {
+					minFilter: THREE.LinearFilter,
+					magFilter: THREE.LinearFilter,
+					format: THREE.RGBFormat,
+					stencilBuffer: false
+				};
 				renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
 
 				effectSave = new THREE.SavePass( new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters ) );
@@ -495,7 +500,7 @@
 				groundBasic = new THREE.MeshBasicMaterial( { color: 0xffffff, map: texture } );
 				groundBasic.color.setHSL( 0.1, 0.9, 0.7 );
 
-				ground = new THREE.Mesh( new THREE.PlaneGeometry( 50000, 50000 ), groundBasic );
+				ground = new THREE.Mesh( new THREE.PlaneBufferGeometry( 50000, 50000 ), groundBasic );
 				ground.position.y = - 215;
 				ground.rotation.x = - Math.PI / 2;
 				scene.add( ground );
@@ -525,45 +530,42 @@
 
 			//
 
-			function addObject( geometry, color, x, y, z, sy ) {
+			var canvas = document.createElement( 'canvas' );
+			canvas.width = 128;
+			canvas.height = 128;
 
-				var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: color, ambient: color } ) );
-				object.position.set( x, y, z );
-				object.castShadow = true;
-				object.receiveShadow = true;
-				scene.add( object );
+			var context = canvas.getContext( '2d' );
+			var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 );
+			gradient.addColorStop( 0.1, 'rgba(0,0,0,1)' );
+			gradient.addColorStop( 1, 'rgba(0,0,0,0)' );
 
-				//
-
-				var canvas = document.createElement( 'canvas' );
-				canvas.width = 128;
-				canvas.height = 128;
+			context.fillStyle = gradient;
+			context.fillRect( 0, 0, canvas.width, canvas.height );
 
-				var context = canvas.getContext( '2d' );
-				var gradient = context.createRadialGradient( canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2 );
-				gradient.addColorStop( 0.1, 'rgba(0,0,0,1)' );
-				gradient.addColorStop( 1, 'rgba(0,0,0,0)' );
+			//
 
-				context.fillStyle = gradient;
-				context.fillRect( 0, 0, canvas.width, canvas.height );
+			var shadowTexture = new THREE.Texture( canvas );
+			shadowTexture.needsUpdate = true;
 
-				//
+			var shadowPlane = new THREE.PlaneBufferGeometry( 400, 400 );
+			var shadowMaterial = new THREE.MeshBasicMaterial( {
 
-				var shadowTexture = new THREE.Texture( canvas );
-				shadowTexture.needsUpdate = true;
+				opacity: 0.35, transparent: true, map: shadowTexture,
+				polygonOffset: false, polygonOffsetFactor: -0.5, polygonOffsetUnits: 1
 
-				var shadowPlane = new THREE.PlaneGeometry( 400, 400 );
-				var shadowMaterial = new THREE.MeshBasicMaterial( {
+			} );
 
-					opacity: 0.35, transparent: true, map: shadowTexture,
-					polygonOffset: false, polygonOffsetFactor: -0.5, polygonOffsetUnits: 1
+			function addObject( geometry, color, x, y, z, sy ) {
 
-				} );
+				var object = new THREE.Mesh( geometry, new THREE.MeshLambertMaterial( { color: color, ambient: color } ) );
+				object.position.set( x, y, z );
+				object.castShadow = true;
+				object.receiveShadow = true;
+				scene.add( object );
 
 				var shadow = new THREE.Mesh( shadowPlane, shadowMaterial );
 				shadow.position.y = sy;
 				shadow.rotation.x = - Math.PI / 2;
-
 				object.add( shadow );
 
 			}
@@ -572,7 +574,12 @@
 
 			function generateDropShadowTexture( object, width, height, bluriness ) {
 
-				var renderTargetParameters = { minFilter: THREE.LinearMipmapLinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat, stencilBuffer: false };
+				var renderTargetParameters = {
+					minFilter: THREE.LinearMipmapLinearFilter,
+					magFilter: THREE.LinearFilter,
+					format: THREE.RGBAFormat,
+					stencilBuffer: false
+				};
 				var shadowTarget = new THREE.WebGLRenderTarget( width, height, renderTargetParameters );
 
 				var shadowMaterial = new THREE.MeshBasicMaterial( { color: 0x000000 } );
@@ -639,7 +646,6 @@
 
 			}
 
-
 			//
 
 			function addCar( object, x, y, z, s ) {
@@ -672,7 +678,7 @@
 				var shadowWidth  =        ss * ( bb.max.z - bb.min.z );
 				var shadowHeight = 1.25 * ss * ( bb.max.x - bb.min.x );
 
-				var shadowPlane = new THREE.PlaneGeometry( shadowWidth, shadowHeight );
+				var shadowPlane = new THREE.PlaneBufferGeometry( shadowWidth, shadowHeight );
 				var shadowMaterial = new THREE.MeshBasicMaterial( {
 					color: 0xffffff, opacity: 0.5, transparent: true, map: shadowTexture,
 					polygonOffset: false, polygonOffsetFactor: -0.5, polygonOffsetUnits: 1
@@ -979,7 +985,9 @@
 
 				camera.lookAt( cameraTarget );
 
-				renderer.clearTarget( null );
+				renderer.setRenderTarget( null );
+
+				renderer.clear();
 				composer.render( 0.1 );
 
 				renderer.shadowMapEnabled = false;

+ 1 - 8
examples/webgl_materials_video.html

@@ -105,11 +105,10 @@
 
 				video = document.getElementById( 'video' );
 
-				texture = new THREE.Texture( video );
+				texture = new THREE.VideoTexture( video );
 				texture.minFilter = THREE.LinearFilter;
 				texture.magFilter = THREE.LinearFilter;
 				texture.format = THREE.RGBFormat;
-				texture.generateMipmaps = false;
 
 				//
 
@@ -252,12 +251,6 @@
 
 				camera.lookAt( scene.position );
 
-				if ( video.readyState === video.HAVE_ENOUGH_DATA ) {
-
-					if ( texture ) texture.needsUpdate = true;
-
-				}
-
 				for ( i = 0; i < cube_count; i ++ ) {
 
 					material = materials[ i ];

+ 6 - 20
examples/webgl_nearestneighbour.html

@@ -139,26 +139,15 @@
 				var distanceFunction = function(a, b){
 					return Math.pow(a[0] - b[0], 2) +  Math.pow(a[1] - b[1], 2) +  Math.pow(a[2] - b[2], 2);
 				};
+
+				positions = new Float32Array( amountOfParticles * 3 );
+				alphas = new Float32Array( amountOfParticles );
 				
 				_particleGeom = new THREE.BufferGeometry();
-				_particleGeom.attributes = {
-
-					position: {
-						itemSize: 3,
-						array: new Float32Array( amountOfParticles * 3 )
-					},
-					
-					alpha: {
-						itemSize: 1,
-						array: new Float32Array( amountOfParticles )
-					}
-
-				};
-				positions = _particleGeom.attributes.position.array;
-				alphas = _particleGeom.attributes.alpha.array;
+				_particleGeom.addAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) );
+				_particleGeom.addAttribute( 'alpha', new THREE.BufferAttribute( alphas, 1 ) );
 				
 				particles = new THREE.PointCloud( _particleGeom, pointShaderMaterial );
-				particles.dynamic = true;
 				
 				for (var x = 0; x < amountOfParticles; x++) {
 					positions[ x * 3 + 0 ] = Math.random() * 1000;
@@ -220,10 +209,7 @@
 				
 				for ( i = 0, il = imagePositionsInRange.length; i < il; i ++ ) {
 					var object = imagePositionsInRange[i];
-					var objectPoint = new THREE.Vector3(0,0,0);
-					objectPoint.x = object[0].obj[0];
-					objectPoint.y = object[0].obj[1];
-					objectPoint.z = object[0].obj[2];
+					var objectPoint = new THREE.Vector3().fromArray( object[ 0 ].obj );
 					
 					if (_frustum.containsPoint(objectPoint)){
 					

+ 104 - 0
examples/webgl_skinning_simple.html

@@ -0,0 +1,104 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js - skinning - simple</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #f0f0f0;
+				margin: 0px;
+				overflow: hidden;
+			}
+		</style>
+	</head>
+	<body>
+
+		<script src="../build/three.min.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+		<script src="js/controls/OrbitControls.js"></script>
+
+		<script>
+
+			var container, stats, controls;
+			var camera, scene, renderer, loader, clock, light;
+			var skinnedMesh, animation, groundMaterial, planeGeometry;
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
+				camera.position.set( 10, 0, 10 );
+
+				scene = new THREE.Scene();
+				loader = new THREE.JSONLoader();
+				clock = new THREE.Clock;
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setSize(window.innerWidth, window.innerHeight);
+				container.appendChild( renderer.domElement );
+
+				controls = new THREE.OrbitControls( camera, renderer.domElement );
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild(stats.domElement);
+
+				groundMaterial = new THREE.MeshPhongMaterial( { emissive: 0xbbbbbb } );
+				planeGeometry = new THREE.PlaneGeometry( 16000, 16000 );
+				ground = new THREE.Mesh( planeGeometry, groundMaterial );
+				ground.position.set( 0, -5, 0 );
+				ground.rotation.x = -Math.PI/2;
+				scene.add( ground );
+
+				light = new THREE.HemisphereLight( 0xffffff, 0x003300, 1 );
+				light.position.set( - 80, 500, 50 );
+				scene.add( light );
+
+				loader.load( './models/skinned/simple/simple.js', function ( geometry, materials ) {
+
+					for ( var k in materials ) {
+
+						materials[k].skinning = true;
+
+					}
+
+					skinnedMesh = new THREE.SkinnedMesh(geometry, new THREE.MeshFaceMaterial(materials));
+					skinnedMesh.scale.set( 1, 1, 1 );
+					scene.add( skinnedMesh );
+					animation = new THREE.Animation( skinnedMesh, skinnedMesh.geometry.animations[ 0 ] );
+					animation.play();
+
+				});
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				THREE.AnimationHandler.update( clock.getDelta() );
+
+				controls.update();
+
+				render();
+				stats.update();
+
+			}
+
+			function render() {
+
+				renderer.render( scene, camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 7 - 1
examples/webgl_terrain_dynamic.html

@@ -317,7 +317,10 @@
 				var pars = { minFilter: THREE.LinearMipmapLinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat };
 
 				heightMap  = new THREE.WebGLRenderTarget( rx, ry, pars );
+				heightMap.generateMipmaps = false;
+
 				normalMap = new THREE.WebGLRenderTarget( rx, ry, pars );
+				normalMap.generateMipmaps = false;
 
 				uniformsNoise = {
 
@@ -338,6 +341,7 @@
 				// TEXTURES
 
 				var specularMap = new THREE.WebGLRenderTarget( 2048, 2048, pars );
+				specularMap.generateMipmaps = false;
 
 				var diffuseTexture1 = THREE.ImageUtils.loadTexture( "textures/terrain/grasslight-big.jpg", null, function () {
 
@@ -414,7 +418,7 @@
 
 				// TERRAIN MESH
 
-				var geometryTerrain = new THREE.PlaneGeometry( 6000, 6000, 256, 256 );
+				var geometryTerrain = new THREE.PlaneBufferGeometry( 6000, 6000, 256, 256 );
 				geometryTerrain.computeTangents();
 
 				terrain = new THREE.Mesh( geometryTerrain, mlib[ "terrain" ] );
@@ -454,7 +458,9 @@
 				renderer.autoClear = false;
 
 				renderTargetParameters = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat, stencilBuffer: false };
+
 				renderTarget = new THREE.WebGLRenderTarget( SCREEN_WIDTH, SCREEN_HEIGHT, renderTargetParameters );
+				renderTarget.generateMipmaps = false;
 
 				effectBloom = new THREE.BloomPass( 0.6 );
 				var effectBleach = new THREE.ShaderPass( THREE.BleachBypassShader );

+ 0 - 1
examples/webgl_test_memory.html

@@ -88,7 +88,6 @@
 
 				// clean up
 
-				mesh.dispose();
 				geometry.dispose();
 				material.dispose();
 				texture.dispose();

+ 3 - 20
examples/webgl_video_panorama_equirectangular.html

@@ -37,8 +37,6 @@
 
 			var camera, scene, renderer;
 
-			var videoTexture;
-
 			var texture_placeholder,
 			isUserInteracting = false,
 			onMouseDownMouseX = 0, onMouseDownMouseY = 0,
@@ -63,19 +61,16 @@
 				var geometry = new THREE.SphereGeometry( 500, 60, 40 );
 				geometry.applyMatrix( new THREE.Matrix4().makeScale( -1, 1, 1 ) );
 
-				video = document.createElement('video');
+				var video = document.createElement( 'video' );
 				video.width = 640;
 				video.height = 360;
 				video.autoplay = true;
 				video.loop = true; 
-
-				video.crossOrigin='anonymous'
 				video.src = "textures/pano.webm";
 
-				videoTexture = new THREE.Texture( video );
-				videoTexture.generateMipmaps = false;
+				var texture = new THREE.VideoTexture( video );
 
-				var material   = new THREE.MeshBasicMaterial( { map : videoTexture } );
+				var material   = new THREE.MeshBasicMaterial( { map : texture } );
 
 				mesh = new THREE.Mesh( geometry, material );
 				
@@ -172,18 +167,6 @@
 
 			function update() {
 
-
-				if( video.readyState === video.HAVE_ENOUGH_DATA ){
-				  videoTexture.needsUpdate = true;
-				}
-
-
-			        //if ( isUserInteracting === false ) {
-
-				//	lon += 0.5;
-
-				//}
-
 				lat = Math.max( - 85, Math.min( 85, lat ) );
 				phi = THREE.Math.degToRad( 90 - lat );
 				theta = THREE.Math.degToRad( lon );

+ 17 - 0
src/Three.js

@@ -5,12 +5,29 @@
 var THREE = { REVISION: '69dev' };
 
 // browserify support
+
 if ( typeof module === 'object' ) {
 
 	module.exports = THREE;
 
 }
 
+// polyfills
+
+if ( Math.sign === undefined ) {
+
+	Math.sign = function ( x ) {
+
+		return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : 0;
+
+	};
+	
+}
+
+// https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent.button
+
+THREE.MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2 };
+
 // GL STATE CONSTANTS
 
 THREE.CullFaceNone = 0;

+ 2 - 6
src/cameras/PerspectiveCamera.js

@@ -119,14 +119,10 @@ THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function () {
 
 THREE.PerspectiveCamera.prototype.clone = function () {
 
-	var camera = new THREE.PerspectiveCamera();
+	var camera = new THREE.PerspectiveCamera( this.fov, this.aspect, this.near, this.far );
 
 	THREE.Camera.prototype.clone.call( this, camera );
 
-	camera.fov = this.fov;
-	camera.aspect = this.aspect;
-	camera.near = this.near;
-	camera.far = this.far;
-
 	return camera;
+
 };

+ 6 - 0
src/core/BufferAttribute.js

@@ -100,6 +100,12 @@ THREE.BufferAttribute.prototype = {
 
 		return this;
 
+	},
+
+	clone: function () {
+
+		return new THREE.BufferAttribute( new this.array.constructor( this.array ), this.itemSize );
+
 	}
 
 };

+ 41 - 68
src/core/BufferGeometry.js

@@ -12,6 +12,8 @@ THREE.BufferGeometry = function () {
 	this.type = 'BufferGeometry';
 
 	this.attributes = {};
+	this.attributesKeys = [];
+
 	this.drawcalls = [];
 	this.offsets = this.drawcalls; // backwards compatibility
 
@@ -37,6 +39,7 @@ THREE.BufferGeometry.prototype = {
 		}
 
 		this.attributes[ name ] = attribute;
+		this.attributesKeys = Object.keys( this.attributes );
 
 	},
 
@@ -242,7 +245,7 @@ THREE.BufferGeometry.prototype = {
 
 			}
 
-			var positions = this.attributes[ 'position' ].array;
+			var positions = this.attributes.position.array;
 
 			if ( positions ) {
 
@@ -288,7 +291,7 @@ THREE.BufferGeometry.prototype = {
 
 			}
 
-			var positions = this.attributes[ 'position' ].array;
+			var positions = this.attributes.position.array;
 
 			if ( positions ) {
 
@@ -347,15 +350,17 @@ THREE.BufferGeometry.prototype = {
 
 			if ( attributes.normal === undefined ) {
 
-				attributes.normal = new THREE.BufferAttribute( new Float32Array( positions.length ), 3 );
+				this.addAttribute( 'normal', new THREE.BufferAttribute( new Float32Array( positions.length ), 3 ) );
 
 			} else {
 
 				// reset existing normals to zero
 
-				for ( var i = 0, il = attributes.normal.array.length; i < il; i ++ ) {
+				var normals = attributes.normal.array;
+
+				for ( var i = 0, il = normals.length; i < il; i ++ ) {
 
-					attributes.normal.array[ i ] = 0;
+					normals[ i ] = 0;
 
 				}
 
@@ -481,37 +486,30 @@ THREE.BufferGeometry.prototype = {
 		// based on http://www.terathon.com/code/tangent.html
 		// (per vertex tangents)
 
-		if ( this.attributes[ 'index' ] === undefined ||
-			 this.attributes[ 'position' ] === undefined ||
-			 this.attributes[ 'normal' ] === undefined ||
-			 this.attributes[ 'uv' ] === undefined ) {
+		if ( this.attributes.index === undefined ||
+			 this.attributes.position === undefined ||
+			 this.attributes.normal === undefined ||
+			 this.attributes.uv === undefined ) {
 
 			console.warn( 'Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()' );
 			return;
 
 		}
 
-		var indices = this.attributes[ 'index' ].array;
-		var positions = this.attributes[ 'position' ].array;
-		var normals = this.attributes[ 'normal' ].array;
-		var uvs = this.attributes[ 'uv' ].array;
+		var indices = this.attributes.index.array;
+		var positions = this.attributes.position.array;
+		var normals = this.attributes.normal.array;
+		var uvs = this.attributes.uv.array;
 
 		var nVertices = positions.length / 3;
 
-		if ( this.attributes[ 'tangent' ] === undefined ) {
-
-			var nTangentElements = 4 * nVertices;
-
-			this.attributes[ 'tangent' ] = {
+		if ( this.attributes.tangent === undefined ) {
 
-				itemSize: 4,
-				array: new Float32Array( nTangentElements )
-
-			};
+			this.addAttribute( 'tangent', new THREE.BufferAttribute( new Float32Array( 4 * nVertices ), 4 ) );
 
 		}
 
-		var tangents = this.attributes[ 'tangent' ].array;
+		var tangents = this.attributes.tangent.array;
 
 		var tan1 = [], tan2 = [];
 
@@ -601,13 +599,19 @@ THREE.BufferGeometry.prototype = {
 		var j, jl;
 		var iA, iB, iC;
 
-		var offsets = this.offsets;
+		if ( this.drawcalls.length === 0 ) {
 
-		for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
+			this.addDrawCall( 0, indices.length, 0 );
 
-			var start = offsets[ j ].start;
-			var count = offsets[ j ].count;
-			var index = offsets[ j ].index;
+		}
+
+		var drawcalls = this.drawcalls;
+
+		for ( j = 0, jl = drawcalls.length; j < jl; ++ j ) {
+
+			var start = drawcalls[ j ].start;
+			var count = drawcalls[ j ].count;
+			var index = drawcalls[ j ].index;
 
 			for ( i = start, il = start + count; i < il; i += 3 ) {
 
@@ -653,11 +657,11 @@ THREE.BufferGeometry.prototype = {
 
 		}
 
-		for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
+		for ( j = 0, jl = drawcalls.length; j < jl; ++ j ) {
 
-			var start = offsets[ j ].start;
-			var count = offsets[ j ].count;
-			var index = offsets[ j ].index;
+			var start = drawcalls[ j ].start;
+			var count = drawcalls[ j ].count;
+			var index = drawcalls[ j ].index;
 
 			for ( i = start, il = start + count; i < il; i += 3 ) {
 
@@ -690,8 +694,8 @@ THREE.BufferGeometry.prototype = {
 
 		var s = Date.now();
 
-		var indices = this.attributes[ 'index' ].array;
-		var vertices = this.attributes[ 'position' ].array;
+		var indices = this.attributes.index.array;
+		var vertices = this.attributes.position.array;
 
 		var verticesCount = ( vertices.length / 3 );
 		var facesCount = ( indices.length / 3 );
@@ -794,7 +798,7 @@ THREE.BufferGeometry.prototype = {
 
 	normalizeNormals: function () {
 
-		var normals = this.attributes[ 'normal' ].array;
+		var normals = this.attributes.normal.array;
 
 		var x, y, z, n;
 
@@ -825,18 +829,11 @@ THREE.BufferGeometry.prototype = {
 
 		/* Create a copy of all attributes for reordering. */
 		var sortedAttributes = {};
-		var types = [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
 		for ( var attr in this.attributes ) {
 			if ( attr == 'index' )
 				continue;
 			var sourceArray = this.attributes[ attr ].array;
-			for ( var i = 0, il = types.length; i < il; i ++ ) {
-				var type = types[ i ];
-				if ( sourceArray instanceof type ) {
-					sortedAttributes[ attr ] = new type( this.attributes[ attr ].itemSize * vertexCount );
-					break;
-				}
-			}
+			sortedAttributes[ attr ] = new sourceArray.constructor( this.attributes[ attr ].itemSize * vertexCount );
 		}
 
 		/* Move attribute positions based on the new index map */
@@ -925,34 +922,10 @@ THREE.BufferGeometry.prototype = {
 
 		var geometry = new THREE.BufferGeometry();
 
-		var types = [ Int8Array, Uint8Array, Uint8ClampedArray, Int16Array, Uint16Array, Int32Array, Uint32Array, Float32Array, Float64Array ];
-
 		for ( var attr in this.attributes ) {
 
 			var sourceAttr = this.attributes[ attr ];
-			var sourceArray = sourceAttr.array;
-
-			var attribute = {
-
-				itemSize: sourceAttr.itemSize,
-				array: null
-
-			};
-
-			for ( var i = 0, il = types.length; i < il; i ++ ) {
-
-				var type = types[ i ];
-
-				if ( sourceArray instanceof type ) {
-
-					attribute.array = new type( sourceArray );
-					break;
-
-				}
-
-			}
-
-			geometry.attributes[ attr ] = attribute;
+			geometry.addAttribute( attr, sourceAttr.clone() );
 
 		}
 

+ 2 - 2
src/core/Geometry.js

@@ -136,8 +136,8 @@ THREE.Geometry.prototype = {
 
 		var addFace = function ( a, b, c ) {
 
-			var vertexNormals = normals !== undefined ? [ tempNormals[ a ], tempNormals[ b ], tempNormals[ c ] ] : [];
-			var vertexColors = colors !== undefined ? [ scope.colors[ a ], scope.colors[ b ], scope.colors[ c ] ] : [];
+			var vertexNormals = normals !== undefined ? [ tempNormals[ a ].clone(), tempNormals[ b ].clone(), tempNormals[ c ].clone() ] : [];
+			var vertexColors = colors !== undefined ? [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ] : [];
 
 			scope.faces.push( new THREE.Face3( a, b, c, vertexNormals, vertexColors ) );
 			scope.faceVertexUvs[ 0 ].push( [ tempUVs[ a ], tempUVs[ b ], tempUVs[ c ] ] );

+ 11 - 34
src/core/Object3D.js

@@ -357,6 +357,7 @@ THREE.Object3D.prototype = {
 		if ( index !== - 1 ) {
 
 			object.parent = undefined;
+
 			object.dispatchEvent( { type: 'removed' } );
 
 			this.children.splice( index, 1 );
@@ -395,25 +396,16 @@ THREE.Object3D.prototype = {
 
 	getObjectById: function ( id, recursive ) {
 
+		if ( this.id === id ) return this;
+
 		for ( var i = 0, l = this.children.length; i < l; i ++ ) {
 
 			var child = this.children[ i ];
+			var object = child.getObjectById( id, recursive );
 
-			if ( child.id === id ) {
-
-				return child;
-
-			}
-
-			if ( recursive === true ) {
+			if ( object !== undefined ) {
 
-				child = child.getObjectById( id, recursive );
-
-				if ( child !== undefined ) {
-
-					return child;
-
-				}
+				return object;
 
 			}
 
@@ -425,25 +417,16 @@ THREE.Object3D.prototype = {
 
 	getObjectByName: function ( name, recursive ) {
 
+		if ( this.name === name ) return this;
+
 		for ( var i = 0, l = this.children.length; i < l; i ++ ) {
 
 			var child = this.children[ i ];
+			var object = child.getObjectByName( name, recursive );
 
-			if ( child.name === name ) {
+			if ( object !== undefined ) {
 
-				return child;
-
-			}
-
-			if ( recursive === true ) {
-
-				child = child.getObjectByName( name, recursive );
-
-				if ( child !== undefined ) {
-
-					return child;
-
-				}
+				return object;
 
 			}
 
@@ -706,12 +689,6 @@ THREE.Object3D.prototype = {
 
 		return object;
 
-	},
-
-	dispose: function () {
-
-		this.dispatchEvent( { type: 'dispose' } );
-
 	}
 
 };

+ 2 - 0
src/core/Projector.js

@@ -273,6 +273,8 @@ THREE.Projector = function () {
 
 			} else if ( object instanceof THREE.Mesh || object instanceof THREE.Line || object instanceof THREE.Sprite ) {
 
+				if ( object.material.visible === false ) return;
+
 				if ( object.frustumCulled === false || _frustum.intersectsObject( object ) === true ) {
 
 					_object = getNextObjectInPool();

+ 74 - 0
src/extras/audio/Audio.js

@@ -0,0 +1,74 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.Audio = function ( listener ) {
+
+	THREE.Object3D.call( this );
+
+	this.type = 'Audio';
+
+	this.context = listener.context;
+	this.source = this.context.createBufferSource();
+
+	this.gain = this.context.createGain();
+	this.gain.connect( this.context.destination );
+
+	this.panner = this.context.createPanner();
+	this.panner.connect( this.gain );
+
+};
+
+THREE.Audio.prototype = Object.create( THREE.Object3D.prototype );
+
+THREE.Audio.prototype.load = function ( file ) {
+
+	var scope = this;
+
+	var request = new XMLHttpRequest();
+	request.open( 'GET', file, true );
+	request.responseType = 'arraybuffer';
+	request.onload = function ( e ) {
+
+		scope.context.decodeAudioData( this.response, function ( buffer ) {
+
+			scope.source.buffer = buffer;
+			scope.source.connect( scope.panner );
+			scope.source.start();
+
+		} );
+
+	};
+	request.send();
+
+	return this;
+
+};
+
+THREE.Audio.prototype.setRefDistance = function ( value ) {
+
+	this.panner.refDistance = value;
+
+};
+
+THREE.Audio.prototype.setRolloffFactor = function ( value ) {
+
+	this.panner.rolloffFactor = value;
+
+};
+
+THREE.Audio.prototype.updateMatrixWorld = ( function () {
+	
+	var position = new THREE.Vector3();
+
+	return function ( force ) {
+
+		THREE.Object3D.prototype.updateMatrixWorld.call( this, force );
+
+		position.setFromMatrixPosition( this.matrixWorld );
+
+		this.panner.setPosition( position.x, position.y, position.z );
+
+	};
+
+} )();

+ 47 - 0
src/extras/audio/AudioListener.js

@@ -0,0 +1,47 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.AudioListener = function () {
+
+	THREE.Object3D.call( this );
+
+	this.type = 'AudioListener';
+
+	this.context = new AudioContext();
+
+};
+
+THREE.AudioListener.prototype = Object.create( THREE.Object3D.prototype );
+
+THREE.AudioListener.prototype.updateMatrixWorld = ( function () {
+
+	var position = new THREE.Vector3();
+	var quaternion = new THREE.Quaternion();
+	var scale = new THREE.Vector3();
+
+	var orientation = new THREE.Vector3();
+	var velocity = new THREE.Vector3();
+
+	var positionPrev = new THREE.Vector3();
+
+	return function ( force ) {
+	
+		THREE.Object3D.prototype.updateMatrixWorld.call( this, force );
+
+		var listener = this.context.listener;
+
+		this.matrixWorld.decompose( position, quaternion, scale );
+
+		orientation.set( 0, 0, -1 ).applyQuaternion( quaternion );
+		velocity.subVectors( position, positionPrev );
+
+		listener.setPosition( position.x, position.y, position.z );
+		listener.setOrientation( orientation.x, orientation.y, orientation.z, this.up.x, this.up.y, this.up.z );
+		listener.setVelocity( velocity.x, velocity.y, velocity.z );
+
+		positionPrev.copy( position );
+
+	};
+
+} )();

+ 1 - 2
src/extras/geometries/ExtrudeGeometry.js

@@ -193,7 +193,6 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
 	function getBevelVec( inPt, inPrev, inNext ) {
 
 		var EPSILON = 0.0000000001;
-		var sign = THREE.Math.sign;
 		
 		// computes for inPt the corresponding point inPt' on a new contour
 		//   shiftet by 1 unit (length of normalized vector) to the left
@@ -259,7 +258,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
 				if ( v_prev_x < - EPSILON ) {
 					if ( v_next_x < - EPSILON ) { direction_eq = true; }
 				} else {
-					if ( sign(v_prev_y) == sign(v_next_y) ) { direction_eq = true; }
+					if ( Math.sign(v_prev_y) == Math.sign(v_next_y) ) { direction_eq = true; }
 				}
 			}
 

+ 7 - 5
examples/js/wip/benchmark/PlaneBufferGeometry.js → src/extras/geometries/PlaneBufferGeometry.js

@@ -7,6 +7,8 @@ THREE.PlaneBufferGeometry = function ( width, height, widthSegments, heightSegme
 
 	THREE.BufferGeometry.call( this );
 
+	this.type = 'PlaneBufferGeometry';
+
 	this.parameters = {
 		width: width,
 		height: height,
@@ -58,7 +60,7 @@ THREE.PlaneBufferGeometry = function ( width, height, widthSegments, heightSegme
 
 	offset = 0;
 
-	var indices = new Uint16Array( gridX * gridY * 6 );
+	var indices = new ( ( vertices.length / 3 ) > 65535 ? Uint32Array : Uint16Array )( gridX * gridY * 6 );
 
 	for ( var iy = 0; iy < gridY; iy ++ ) {
 
@@ -83,10 +85,10 @@ THREE.PlaneBufferGeometry = function ( width, height, widthSegments, heightSegme
 
 	}
 
-	this.attributes[ 'index' ] = { array: indices, itemSize: 1 };
-	this.attributes[ 'position' ] = { array: vertices, itemSize: 3 };
-	this.attributes[ 'normal' ] = { array: normals, itemSize: 3 };
-	this.attributes[ 'uv' ] = { array: uvs, itemSize: 2 };
+	this.addAttribute( 'index', new THREE.BufferAttribute( indices, 1 ) );
+	this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
+	this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
+	this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
 
 };
 

+ 4 - 61
src/extras/geometries/PlaneGeometry.js

@@ -5,10 +5,12 @@
 
 THREE.PlaneGeometry = function ( width, height, widthSegments, heightSegments ) {
 
+	console.info( 'THREE.PlaneGeometry: Consider using THREE.PlaneBufferGeometry for lower memory footprint.' );
+
 	THREE.Geometry.call( this );
 
 	this.type = 'PlaneGeometry';
-	
+
 	this.parameters = {
 		width: width,
 		height: height,
@@ -16,66 +18,7 @@ THREE.PlaneGeometry = function ( width, height, widthSegments, heightSegments )
 		heightSegments: heightSegments
 	};
 
-	var ix, iz;
-	var width_half = width / 2;
-	var height_half = height / 2;
-
-	var gridX = widthSegments || 1;
-	var gridZ = heightSegments || 1;
-
-	var gridX1 = gridX + 1;
-	var gridZ1 = gridZ + 1;
-
-	var segment_width = width / gridX;
-	var segment_height = height / gridZ;
-
-	var normal = new THREE.Vector3( 0, 0, 1 );
-
-	for ( iz = 0; iz < gridZ1; iz ++ ) {
-
-		var y = iz * segment_height - height_half;
-
-		for ( ix = 0; ix < gridX1; ix ++ ) {
-
-			var x = ix * segment_width - width_half;
-
-			this.vertices.push( new THREE.Vector3( x, - y, 0 ) );
-
-		}
-
-	}
-
-	for ( iz = 0; iz < gridZ; iz ++ ) {
-
-		for ( ix = 0; ix < gridX; ix ++ ) {
-
-			var a = ix + gridX1 * iz;
-			var b = ix + gridX1 * ( iz + 1 );
-			var c = ( ix + 1 ) + gridX1 * ( iz + 1 );
-			var d = ( ix + 1 ) + gridX1 * iz;
-
-			var uva = new THREE.Vector2( ix / gridX, 1 - iz / gridZ );
-			var uvb = new THREE.Vector2( ix / gridX, 1 - ( iz + 1 ) / gridZ );
-			var uvc = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - ( iz + 1 ) / gridZ );
-			var uvd = new THREE.Vector2( ( ix + 1 ) / gridX, 1 - iz / gridZ );
-
-			var face = new THREE.Face3( a, b, d );
-			face.normal.copy( normal );
-			face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
-
-			this.faces.push( face );
-			this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvd ] );
-
-			face = new THREE.Face3( b, c, d );
-			face.normal.copy( normal );
-			face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone() );
-
-			this.faces.push( face );
-			this.faceVertexUvs[ 0 ].push( [ uvb.clone(), uvc, uvd.clone() ] );
-
-		}
-
-	}
+	this.fromBufferGeometry( new THREE.PlaneBufferGeometry( width, height, widthSegments, heightSegments ) );
 
 };
 

+ 2 - 0
src/extras/renderers/plugins/LensFlarePlugin.js

@@ -283,6 +283,8 @@ THREE.LensFlarePlugin = function () {
 		_gl.enable( _gl.DEPTH_TEST );
 		_gl.depthMask( true );
 
+		_renderer.resetGLState();
+
 	};
 
 	function createProgram ( shader, precision ) {

+ 3 - 1
src/extras/renderers/plugins/ShadowMapPlugin.js

@@ -45,7 +45,7 @@ THREE.ShadowMapPlugin = function () {
 
 	this.render = function ( scene, camera ) {
 
-		if ( ! ( _renderer.shadowMapEnabled && _renderer.shadowMapAutoUpdate ) ) return;
+		if ( _renderer.shadowMapEnabled === false || _renderer.shadowMapAutoUpdate === false ) return;
 
 		this.update( scene, camera );
 
@@ -330,6 +330,8 @@ THREE.ShadowMapPlugin = function () {
 
 		}
 
+		_renderer.resetGLState();
+
 	};
 	
 	function projectObject(scene, object,shadowCamera){

+ 4 - 0
src/materials/Material.js

@@ -33,6 +33,8 @@ THREE.Material = function () {
 
 	this.overdraw = 0; // Overdrawn pixels (typically between 0 and 1) for fixing antialiasing gaps in CanvasRenderer
 
+	this.visible = true;
+
 	this.needsUpdate = true;
 
 };
@@ -185,6 +187,8 @@ THREE.Material.prototype = {
 
 		material.overdraw = this.overdraw;
 
+		material.visible = this.visible;
+
 		return material;
 
 	},

+ 0 - 6
src/math/Math.js

@@ -122,12 +122,6 @@ THREE.Math = {
 
 	},
 
-	sign: function ( x ) {
-
-		return ( x < 0 ) ? - 1 : ( x > 0 ) ? 1 : 0;
-
-	},
-
 	degToRad: function () {
 
 		var degreeToRadiansFactor = Math.PI / 180;

+ 89 - 131
src/renderers/WebGLRenderer.js

@@ -412,6 +412,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 	this.addPostPlugin = function ( plugin ) {
 
 		plugin.init( this, lights, _webglObjects, _webglObjectsImmediate );
+
 		this.renderPluginsPost.push( plugin );
 
 	};
@@ -419,6 +420,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 	this.addPrePlugin = function ( plugin ) {
 
 		plugin.init( this, lights, _webglObjects, _webglObjectsImmediate );
+
 		this.renderPluginsPre.push( plugin );
 
 	};
@@ -511,13 +513,17 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	// Events
 	
-	var onObjectDispose = function ( event ) {
+	var onObjectRemoved = function ( event ) {
 
 		var object = event.target;
 
-		object.removeEventListener( 'dispose', onObjectDispose );
+		object.traverse( function ( child ) {
+
+			child.removeEventListener( 'remove', onObjectRemoved );
 
-		removeObject( object )
+			removeObject( child );
+
+		} );
 
 	};
 
@@ -588,14 +594,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( geometry.__webglCustomAttributesList !== undefined ) {
 
-			var attributes = geometry.__webglCustomAttributesList;
-			var keys = Object.keys( attributes );
+			for ( var name in geometry.__webglCustomAttributesList ) {
 
-			for ( var i = 0; i < keys.length; i ++ ) {
-
-				var name = keys[ i ];
-
-				_gl.deleteBuffer( attributes[ name ].buffer );
+				_gl.deleteBuffer( geometry.__webglCustomAttributesList[ name ].buffer );
 
 			}
 
@@ -611,16 +612,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( geometry instanceof THREE.BufferGeometry ) {
 
-			var attributes = geometry.attributes;
-			var keys = Object.keys( attributes );
-
-			for ( var i = 0; i < keys.length; i ++ ) {
+			for ( var name in geometry.attributes ) {
 
-				var name = keys[ i ];
+				if ( geometry.attributes[ name ].buffer !== undefined ) {
 
-				if ( attributes[ name ].buffer !== undefined ) {
-
-					_gl.deleteBuffer( attributes[ name ].buffer );
+					_gl.deleteBuffer( geometry.attributes[ name ].buffer );
 
 				}
 
@@ -794,11 +790,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			}
 
-			var keys = Object.keys( material.attributes );
-
-			for ( var i = 0; i < keys.length; i ++ ) {
+			for ( var name in material.attributes ) {
 
-				var name = keys[ i ];
 				var attribute = material.attributes[ name ];
 
 				if ( ! attribute.__webglInitialized || attribute.createUniqueBuffers ) {
@@ -941,23 +934,17 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			}
 
-			var keys = Object.keys( material.attributes );
-
-			for ( var i = 0; i < keys.length; i ++ ) {
+			for ( var name in material.attributes ) {
 
 				// Do a shallow copy of the attribute object so different geometryGroup chunks use different
 				// attribute buffers which are correctly indexed in the setMeshBuffers function
 
-				var name = keys[ i ];
 				var originalAttribute = material.attributes[ name ];
 
 				var attribute = {};
 
-				var keys2 = Object.keys( originalAttribute );
-
-				for ( var j = 0; j < keys2.length; j ++ ) {
+				for ( var property in originalAttribute ) {
 
-					var property = keys2[ j ];
 					attribute[ property ] = originalAttribute[ property ];
 
 				}
@@ -2306,12 +2293,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 	function setDirectBuffers( geometry ) {
 
 		var attributes = geometry.attributes;
+		var attributesKeys = geometry.attributesKeys;
 
-		var keys = Object.keys( attributes );
-
-		for ( var i = 0; i < keys.length; i ++ ) {
+		for ( var i = 0, l = attributesKeys.length; i < l; i ++ ) {
 
-			var attributeName = keys[ i ];
+			var attributeName = attributesKeys[ i ];
 			var attributeItem = attributes[ attributeName ];
 
 			if ( attributeItem.buffer === undefined ) {
@@ -2435,28 +2421,34 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
-	function setupVertexAttributes( material, programAttributes, geometryAttributes, startIndex ) {
+	function setupVertexAttributes( material, program, geometry, startIndex ) {
 
-		var keys = Object.keys( programAttributes );
+		var geometryAttributes = geometry.attributes;
 
-		for ( var i = 0; i < keys.length; i ++ ) {
+		var programAttributes = program.attributes;
+		var programAttributesKeys = program.attributesKeys;
 
-			var attributeName = keys[ i ];
+		for ( var i = 0, l = programAttributesKeys.length; i < l; i ++ ) {
+
+			var attributeName = programAttributesKeys[ i ];
 
-			var attributeItem = geometryAttributes[ attributeName ];
 			var attributePointer = programAttributes[ attributeName ];
 
 			if ( attributePointer >= 0 ) {
 
-				if ( attributeItem ) {
+				var attributeItem = geometryAttributes[ attributeName ];
+
+				if ( attributeItem !== undefined ) {
 
 					var attributeSize = attributeItem.itemSize;
 
 					_gl.bindBuffer( _gl.ARRAY_BUFFER, attributeItem.buffer );
+
 					enableAttribute( attributePointer );
+
 					_gl.vertexAttribPointer( attributePointer, attributeSize, _gl.FLOAT, false, 0, startIndex * attributeSize * 4 ); // 4 bytes per Float32
 
-				} else if ( material.defaultAttributeValues ) {
+				} else if ( material.defaultAttributeValues !== undefined ) {
 
 					if ( material.defaultAttributeValues[ attributeName ].length === 2 ) {
 
@@ -2480,14 +2472,13 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	this.renderBufferDirect = function ( camera, lights, fog, material, geometry, object ) {
 
+		if ( material.visible === false ) return;
+
 		var linewidth, a, attribute;
 		var attributeItem, attributeName, attributePointer, attributeSize;
 
 		var program = setProgram( camera, lights, fog, material, object );
 
-		var programAttributes = program.attributes;
-		var geometryAttributes = geometry.attributes;
-
 		var updateBuffers = false,
 			wireframeBit = material.wireframe ? 1 : 0,
 			geometryHash = ( geometry.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
@@ -2509,7 +2500,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		if ( object instanceof THREE.Mesh ) {
 
-			var index = geometryAttributes[ 'index' ];
+			var index = geometry.attributes.index;
 
 			if ( index ) {
 
@@ -2535,7 +2526,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					if ( updateBuffers ) {
 
-						setupVertexAttributes( material, programAttributes, geometryAttributes, 0 );
+						setupVertexAttributes( material, program, geometry, 0 );
 						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
 
 					}
@@ -2560,7 +2551,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 						if ( updateBuffers ) {
 
-							setupVertexAttributes( material, programAttributes, geometryAttributes, startIndex );
+							setupVertexAttributes( material, program, geometry, startIndex );
 							_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
 
 						}
@@ -2583,7 +2574,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( updateBuffers ) {
 
-					setupVertexAttributes( material, programAttributes, geometryAttributes, 0 );
+					setupVertexAttributes( material, program, geometry, 0 );
 
 				}
 
@@ -2605,11 +2596,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			if ( updateBuffers ) {
 
-				setupVertexAttributes( material, programAttributes, geometryAttributes, 0 );
+				setupVertexAttributes( material, program, geometry, 0 );
 
 			}
 
-			var position = geometryAttributes[ 'position' ];
+			var position = geometry.attributes.position;
 
 			// render particles
 
@@ -2624,7 +2615,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			setLineWidth( material.linewidth );
 
-			var index = geometryAttributes[ 'index' ];
+			var index = geometry.attributes.index;
 
 			if ( index ) {
 
@@ -2650,7 +2641,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 					if ( updateBuffers ) {
 
-						setupVertexAttributes( material, programAttributes, geometryAttributes, 0 );
+						setupVertexAttributes( material, program, geometry, 0 );
 						_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
 
 					}
@@ -2674,7 +2665,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 						if ( updateBuffers ) {
 
-							setupVertexAttributes( material, programAttributes, geometryAttributes, startIndex );
+							setupVertexAttributes( material, program, geometry, startIndex );
 							_gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
 
 						}
@@ -2696,11 +2687,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 				if ( updateBuffers ) {
 
-					setupVertexAttributes( material, programAttributes, geometryAttributes, 0 );
+					setupVertexAttributes( material, program, geometry, 0 );
 
 				}
 
-				var position = geometryAttributes[ 'position' ];
+				var position = geometry.attributes.position;
 
 				_gl.drawArrays( mode, 0, position.array.length / 3 );
 
@@ -2715,6 +2706,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
 
+		if ( material.visible === false ) return;
+
 		var linewidth, a, attribute, i, il;
 
 		var program = setProgram( camera, lights, fog, material, object );
@@ -2796,7 +2789,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 					enableAttribute( attributes.color );
 					_gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
 
-				} else if ( material.defaultAttributeValues ) {
+				} else if ( material.defaultAttributeValues !== undefined ) {
 
 
 					_gl.vertexAttrib3fv( attributes.color, material.defaultAttributeValues.color );
@@ -2835,7 +2828,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 					enableAttribute( attributes.uv );
 					_gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
 
-				} else if ( material.defaultAttributeValues ) {
+				} else if ( material.defaultAttributeValues !== undefined ) {
 
 
 					_gl.vertexAttrib2fv( attributes.uv, material.defaultAttributeValues.uv );
@@ -2852,7 +2845,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 					enableAttribute( attributes.uv2 );
 					_gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 );
 
-				} else if ( material.defaultAttributeValues ) {
+				} else if ( material.defaultAttributeValues !== undefined ) {
 
 
 					_gl.vertexAttrib2fv( attributes.uv2, material.defaultAttributeValues.uv2 );
@@ -3163,7 +3156,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	};
 
-
 	// Rendering
 
 	this.render = function ( scene, camera, renderTarget, forceClear ) {
@@ -3384,38 +3376,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		for ( var i = 0, il = plugins.length; i < il; i ++ ) {
 
-			// reset state for plugin (to start from clean slate)
-
-			_currentProgram = null;
-			_currentCamera = null;
-
-			_oldBlending = - 1;
-			_oldDepthTest = - 1;
-			_oldDepthWrite = - 1;
-			_oldDoubleSided = - 1;
-			_oldFlipSided = - 1;
-			_currentGeometryGroupHash = - 1;
-			_currentMaterialId = - 1;
-
-			_lightsNeedUpdate = true;
-
 			plugins[ i ].render( scene, camera, _currentWidth, _currentHeight );
 
-			// reset state after plugin (anything could have changed)
-
-			_currentProgram = null;
-			_currentCamera = null;
-
-			_oldBlending = - 1;
-			_oldDepthTest = - 1;
-			_oldDepthWrite = - 1;
-			_oldDoubleSided = - 1;
-			_oldFlipSided = - 1;
-			_currentGeometryGroupHash = - 1;
-			_currentMaterialId = - 1;
-
-			_lightsNeedUpdate = true;
-
 		}
 
 	};
@@ -3592,11 +3554,11 @@ THREE.WebGLRenderer = function ( parameters ) {
 		if ( object.__webglInit === undefined ) {
 
 			object.__webglInit = true;
-			object.addEventListener( 'dispose', onObjectDispose );
-
 			object._modelViewMatrix = new THREE.Matrix4();
 			object._normalMatrix = new THREE.Matrix3();
 
+			object.addEventListener( 'removed', onObjectRemoved );
+
 		}
 		
 		var geometry = object.geometry;
@@ -3616,12 +3578,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			} else if ( object instanceof THREE.Mesh ) {
 				
-				if ( object.__webglActive !== undefined ) {
-
-					removeObject( object, scene );
-
-				}
-				
 				initGeometryGroups(scene, object, geometry);
 
 			} else if ( object instanceof THREE.Line ) {
@@ -3870,11 +3826,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	function areCustomAttributesDirty( material ) {
 
-		var keys = Object.keys( material.attributes );
-
-		for ( var i = 0; i < keys.length; i ++ ) {
-
-			var name = keys[ i ];
+		for ( var name in material.attributes ) {
 
 			if ( material.attributes[ name ].needsUpdate ) return true;
 
@@ -3886,11 +3838,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 	function clearCustomAttributes( material ) {
 
-		var keys = Object.keys( material.attributes );
-
-		for ( var i = 0; i < keys.length; i ++ ) {
-
-			var name = keys[ i ];
+		for ( var name in material.attributes ) {
 
 			material.attributes[ name ].needsUpdate = false;
 
@@ -3914,6 +3862,10 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
+		delete object.__webglInit;
+		delete object._modelViewMatrix;
+		delete object._normalMatrix;
+
 		delete object.__webglActive;
 
 	};
@@ -4072,31 +4024,21 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-		var keys;
-
 		if ( material.defines !== undefined ) {
 
-			keys = Object.keys( material.defines );
-
-			for ( var i = 0; i < keys.length; i ++ ) {
+			for ( var name in material.defines ) {
 
-				var d = keys[ i ];
-
-				chunks.push( d );
-				chunks.push( material.defines[ d ] );
+				chunks.push( name );
+				chunks.push( material.defines[ name ] );
 
 			}
 
 		}
 
-		keys = Object.keys( parameters );
-
-		for ( var i = 0; i < keys.length; i ++ ) {
-
-			var p = keys[ i ];
+		for ( var name in parameters ) {
 
-			chunks.push( p );
-			chunks.push( parameters[ p ] );
+			chunks.push( name );
+			chunks.push( parameters[ name ] );
 
 		}
 
@@ -4132,7 +4074,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		material.program = program;
 
-		var attributes = material.program.attributes;
+		var attributes = program.attributes;
 
 		if ( material.morphTargets ) {
 
@@ -4140,7 +4082,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 			var id, base = 'morphTarget';
 
-			for ( i = 0; i < _this.maxMorphTargets; i ++ ) {
+			for ( var i = 0; i < _this.maxMorphTargets; i ++ ) {
 
 				id = base + i;
 
@@ -4176,11 +4118,8 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		material.uniformsList = [];
 
-		keys = Object.keys( material.__webglShader.uniforms );
+		for ( var u in material.__webglShader.uniforms ) {
 
-		for ( var i = 0; i < keys.length; i ++ ) {
-
-			var u = keys[ i ];
 			var location = material.program.uniforms[ u ];
 
 			if ( location ) {
@@ -6276,7 +6215,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		}
 
-	};
+	}
 
 	function setDefaultGLState () {
 
@@ -6299,7 +6238,26 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 		_gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
 
-	};
+	}
+
+	function resetGLState() {
+
+		_currentProgram = null;
+		_currentCamera = null;
+
+		_oldBlending = - 1;
+		_oldDepthTest = - 1;
+		_oldDepthWrite = - 1;
+		_oldDoubleSided = - 1;
+		_oldFlipSided = - 1;
+		_currentGeometryGroupHash = - 1;
+		_currentMaterialId = - 1;
+
+		_lightsNeedUpdate = true;
+
+	}
+
+	this.resetGLState = resetGLState;
 
 	// default plugins (order is important)
 

+ 8 - 8
src/renderers/shaders/UniformsUtils.js

@@ -6,13 +6,13 @@ THREE.UniformsUtils = {
 
 	merge: function ( uniforms ) {
 
-		var u, p, tmp, merged = {};
+		var merged = {};
 
-		for ( u = 0; u < uniforms.length; u ++ ) {
+		for ( var u = 0; u < uniforms.length; u ++ ) {
 
-			tmp = this.clone( uniforms[ u ] );
+			var tmp = this.clone( uniforms[ u ] );
 
-			for ( p in tmp ) {
+			for ( var p in tmp ) {
 
 				merged[ p ] = tmp[ p ];
 
@@ -26,15 +26,15 @@ THREE.UniformsUtils = {
 
 	clone: function ( uniforms_src ) {
 
-		var u, p, parameter, parameter_src, uniforms_dst = {};
+		var uniforms_dst = {};
 
-		for ( u in uniforms_src ) {
+		for ( var u in uniforms_src ) {
 
 			uniforms_dst[ u ] = {};
 
-			for ( p in uniforms_src[ u ] ) {
+			for ( var p in uniforms_src[ u ] ) {
 
-				parameter_src = uniforms_src[ u ][ p ];
+				var parameter_src = uniforms_src[ u ][ p ];
 
 				if ( parameter_src instanceof THREE.Color ||
 					 parameter_src instanceof THREE.Vector2 ||

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

@@ -361,6 +361,7 @@ THREE.WebGLProgram = ( function () {
 		}
 
 		this.attributes = cacheAttributeLocations( _gl, program, identifiers );
+		this.attributesKeys = Object.keys( this.attributes );
 
 		//
 

+ 29 - 0
src/textures/VideoTexture.js

@@ -0,0 +1,29 @@
+/**
+ * @author mrdoob / http://mrdoob.com/
+ */
+
+THREE.VideoTexture = function ( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
+
+	THREE.Texture.call( this, video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy );
+
+	this.generateMipmaps = false;
+
+	var scope = this;
+
+	var update = function () {
+
+		requestAnimationFrame( update );
+
+		if ( video.readyState === video.HAVE_ENOUGH_DATA ) {
+
+			scope.needsUpdate = true;
+
+		}
+
+	};
+
+	update();
+
+};
+
+THREE.VideoTexture.prototype = Object.create( THREE.Texture.prototype );

+ 1 - 0
utils/build/externs/common.js

@@ -1,3 +1,4 @@
+var AudioContext;
 var console;
 var module;
 var JSON;

+ 1 - 0
utils/build/includes/canvas.json

@@ -48,6 +48,7 @@
 	"src/materials/SpriteCanvasMaterial.js",
 	"src/textures/Texture.js",
 	"src/textures/DataTexture.js",
+	"src/textures/VideoTexture.js",
 	"src/objects/Group.js",
 	"src/objects/Line.js",
 	"src/objects/Mesh.js",

+ 1 - 0
utils/build/includes/common.json

@@ -68,6 +68,7 @@
 	"src/textures/CubeTexture.js",
 	"src/textures/CompressedTexture.js",
 	"src/textures/DataTexture.js",
+	"src/textures/VideoTexture.js",
 	"src/objects/Group.js",
 	"src/objects/PointCloud.js",
 	"src/objects/Line.js",

+ 3 - 0
utils/build/includes/extras.json

@@ -3,6 +3,8 @@
 	"src/extras/ImageUtils.js",
 	"src/extras/SceneUtils.js",
 	"src/extras/FontUtils.js",
+	"src/extras/audio/Audio.js",
+	"src/extras/audio/AudioListener.js",
 	"src/extras/core/Curve.js",
 	"src/extras/core/CurvePath.js",
 	"src/extras/core/Gyroscope.js",
@@ -31,6 +33,7 @@
 	"src/extras/geometries/ShapeGeometry.js",
 	"src/extras/geometries/LatheGeometry.js",
 	"src/extras/geometries/PlaneGeometry.js",
+	"src/extras/geometries/PlaneBufferGeometry.js",
 	"src/extras/geometries/RingGeometry.js",
 	"src/extras/geometries/SphereGeometry.js",
 	"src/extras/geometries/TextGeometry.js",

+ 1 - 0
utils/build/includes/webgl.json

@@ -59,6 +59,7 @@
 	"src/textures/CubeTexture.js",
 	"src/textures/CompressedTexture.js",
 	"src/textures/DataTexture.js",
+	"src/textures/VideoTexture.js",
 	"src/objects/PointCloud.js",
 	"src/objects/Group.js",
 	"src/objects/Line.js",

+ 7 - 5
utils/exporters/blender/2.65/scripts/addons/io_mesh_threejs/export_threejs.py

@@ -827,6 +827,7 @@ def generate_indices_and_weights(meshes, option_skinning):
     weights = []
 
     armature, armature_object = get_armature()
+    bone_names = [bone.name for bone in armature_object.pose.bones]
 
     for mesh, object in meshes:
 
@@ -854,9 +855,10 @@ def generate_indices_and_weights(meshes, option_skinning):
 
             for group in vertex.groups:
                 index = group.group
-                weight = group.weight
+                if object.vertex_groups[index].name in bone_names:
+                    weight = group.weight 
 
-                bone_array.append( (index, weight) )
+                    bone_array.append( (index, weight) )
                 
             bone_array.sort(key = operator.itemgetter(1), reverse=True)
             
@@ -879,11 +881,11 @@ def generate_indices_and_weights(meshes, option_skinning):
                             break
 
                     if found != 1:
-                        indices.append('0')
+                        indices.append('-1')
                         weights.append('0')
 
                 else:
-                    indices.append('0')
+                    indices.append('-1')
                     weights.append('0')
     
     
@@ -2696,4 +2698,4 @@ def save(operator, context, filepath = "",
                     option_frame_step,
                     option_frame_index_as_time)
 
-    return {'FINISHED'}
+    return {'FINISHED'}

+ 8 - 4
utils/exporters/maya/plug-ins/threeJsFileTranslator.py

@@ -30,6 +30,7 @@ class ThreeJsWriter(object):
 
         self.verticeOffset = 0
         self.uvOffset = 0
+        self.normalOffset = 0
         self.vertices = []
         self.materials = []
         self.faces = []
@@ -128,6 +129,7 @@ class ThreeJsWriter(object):
             self._exportFaces(mesh)
             self.verticeOffset += len(mesh.getPoints())
             self.uvOffset += mesh.numUVs()
+            self.normalOffset += mesh.numNormals()
         if self.options['normals']:
             print("Exporting normals")
             self._exportNormals(mesh)
@@ -141,7 +143,7 @@ class ThreeJsWriter(object):
 
         if self.options['materials']:
             for engine in mesh.listConnections(type='shadingEngine'):
-                if sets(engine, isMember=face):
+                if sets(engine, isMember=face) or sets(engine, isMember=mesh):
                     for material in engine.listConnections(type='lambert'):
                         if self._materialIndices.has_key(material.name()):
                             return self._materialIndices[material.name()]
@@ -204,7 +206,7 @@ class ThreeJsWriter(object):
 
     def _exportFaceVertexNormals(self, face):
         for i in range(face.polygonVertexCount()):
-            self.faces.append(face.normalIndex(i))
+            self.faces.append(face.normalIndex(i) + self.normalOffset)
 
     def _exportNormals(self, mesh):
         for normal in mesh.getNormals():
@@ -268,9 +270,11 @@ class ThreeJsWriter(object):
             self._exportFile(result, f, "Specular")
 
     def _exportFile(self, result, mapFile, mapType):
-        fName = os.path.basename(mapFile.ftn.get())
+        src = mapFile.ftn.get()
+        targetDir = os.path.dirname(self.path)
+        fName = os.path.basename(src)
         if self.options['copyTextures']:
-            shutil.copy2(mapFile.ftn.get(), os.path.dirname(self.path) + "/" + fName)
+            shutil.copy2(src, os.path.join(targetDir, fName))
         result["map" + mapType] = fName
         result["map" + mapType + "Repeat"] = [1, 1]
         result["map" + mapType + "Wrap"] = ["repeat", "repeat"]

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