浏览代码

Merge pull request #2 from mrdoob/dev

mrdoob/three.js dev into Lowfab/three.js dev
Arthur Silber 10 年之前
父节点
当前提交
e0a515a4b7
共有 95 个文件被更改,包括 1520 次插入1415 次删除
  1. 1 1
      bower.json
  2. 123 75
      build/three.js
  3. 87 88
      build/three.min.js
  4. 4 2
      docs/api/extras/helpers/EdgesHelper.html
  5. 1 2
      docs/api/math/Matrix4.html
  6. 2 4
      editor/js/Script.js
  7. 19 9
      editor/js/Sidebar.Geometry.js
  8. 0 6
      editor/js/Viewport.js
  9. 3 1
      examples/index.html
  10. 8 5
      examples/js/ShaderDeferred.js
  11. 36 66
      examples/js/ShaderSkin.js
  12. 17 41
      examples/js/ShaderTerrain.js
  13. 16 23
      examples/js/SkyShader.js
  14. 19 4
      examples/js/effects/VREffect.js
  15. 2 2
      examples/js/math/Lut.js
  16. 11 11
      examples/js/postprocessing/AdaptiveToneMappingPass.js
  17. 26 63
      examples/js/shaders/NormalDisplacementShader.js
  18. 6 5
      examples/misc_fps.html
  19. 3 0
      examples/models/json/pressure.json
  20. 二进制
      examples/textures/MaryOculus.webm
  21. 1 0
      examples/textures/MaryOculus.webm.nfo
  22. 5 0
      examples/textures/decal/LICENSE.TXT
  23. 二进制
      examples/textures/decal/decal-diffuse.png
  24. 二进制
      examples/textures/decal/decal-normal.jpg
  25. 168 0
      examples/vr_video.html
  26. 1 1
      examples/webgl_animation_skinning_morph.html
  27. 1 1
      examples/webgl_decals.html
  28. 2 2
      examples/webgl_effects_parallaxbarrier.html
  29. 1 0
      examples/webgl_interactive_cubes_gpu.html
  30. 10 32
      examples/webgl_loader_scene.html
  31. 3 4
      examples/webgl_materials_lightmap.html
  32. 3 0
      examples/webgl_materials_normaldisplacementmap.html
  33. 1 1
      examples/webgl_mirror.html
  34. 13 24
      examples/webgl_shaders_sky.html
  35. 30 16
      examples/webgl_shaders_tonemapping.html
  36. 1 1
      examples/webgl_terrain_dynamic.html
  37. 2 2
      src/Three.js
  38. 17 16
      src/core/BufferGeometry.js
  39. 38 16
      src/core/Geometry.js
  40. 1 3
      src/core/Object3D.js
  41. 6 8
      src/extras/FontUtils.js
  42. 223 220
      src/extras/animation/Animation.js
  43. 98 101
      src/extras/animation/KeyFrameAnimation.js
  44. 7 5
      src/extras/animation/MorphAnimation.js
  45. 57 2
      src/extras/audio/Audio.js
  46. 0 7
      src/extras/audio/AudioListener.js
  47. 0 1
      src/extras/core/Path.js
  48. 1 9
      src/extras/geometries/ExtrudeGeometry.js
  49. 0 1
      src/extras/geometries/ParametricGeometry.js
  50. 1 2
      src/extras/geometries/PolyhedronGeometry.js
  51. 1 2
      src/extras/geometries/ShapeGeometry.js
  52. 2 6
      src/extras/geometries/TubeGeometry.js
  53. 11 2
      src/extras/helpers/EdgesHelper.js
  54. 0 2
      src/extras/helpers/VertexNormalsHelper.js
  55. 0 2
      src/extras/helpers/VertexTangentsHelper.js
  56. 0 1
      src/extras/objects/MorphBlendMesh.js
  57. 3 3
      src/loaders/BufferGeometryLoader.js
  58. 16 14
      src/loaders/JSONLoader.js
  59. 3 2
      src/loaders/ObjectLoader.js
  60. 1 1
      src/math/Matrix3.js
  61. 1 1
      src/math/Matrix4.js
  62. 1 1
      src/math/Spline.js
  63. 15 6
      src/math/Vector2.js
  64. 10 0
      src/math/Vector3.js
  65. 11 0
      src/math/Vector4.js
  66. 1 1
      src/objects/Mesh.js
  67. 0 1
      src/objects/MorphAnimMesh.js
  68. 29 45
      src/renderers/WebGLRenderer.js
  69. 1 1
      src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl
  70. 1 1
      src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl
  71. 1 1
      src/renderers/shaders/ShaderChunk/color_fragment.glsl
  72. 4 4
      src/renderers/shaders/ShaderChunk/envmap_fragment.glsl
  73. 1 1
      src/renderers/shaders/ShaderChunk/fog_fragment.glsl
  74. 1 1
      src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl
  75. 0 3
      src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl
  76. 2 2
      src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl
  77. 17 57
      src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl
  78. 1 1
      src/renderers/shaders/ShaderChunk/linear_to_gamma_fragment.glsl
  79. 1 1
      src/renderers/shaders/ShaderChunk/map_fragment.glsl
  80. 1 1
      src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl
  81. 3 3
      src/renderers/shaders/ShaderChunk/shadowmap_fragment.glsl
  82. 43 18
      src/renderers/shaders/ShaderLib.js
  83. 1 1
      src/renderers/webgl/plugins/ShadowMapPlugin.js
  84. 1 0
      src/textures/Texture.js
  85. 64 18
      utils/build/build.js
  86. 2 2
      utils/build/package.json
  87. 87 79
      utils/exporters/blender/addons/io_three/__init__.py
  88. 1 0
      utils/exporters/blender/addons/io_three/constants.py
  89. 4 12
      utils/exporters/blender/addons/io_three/exporter/_json.py
  90. 27 55
      utils/exporters/blender/addons/io_three/exporter/api/animation.py
  91. 7 3
      utils/exporters/blender/addons/io_three/exporter/api/material.py
  92. 58 123
      utils/exporters/blender/addons/io_three/exporter/api/mesh.py
  93. 9 11
      utils/exporters/blender/addons/io_three/exporter/geometry.py
  94. 0 43
      utils/exporters/blender/addons/io_three/exporter/utilities.py
  95. 2 0
      utils/exporters/blender/tests/scripts/exporter.py

+ 1 - 1
bower.json

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

文件差异内容过多而无法显示
+ 123 - 75
build/three.js


文件差异内容过多而无法显示
+ 87 - 88
build/three.min.js


+ 4 - 2
docs/api/extras/helpers/EdgesHelper.html

@@ -27,10 +27,12 @@
 		</code>
 		</code>
 
 
 		<h2>Constructor</h2>
 		<h2>Constructor</h2>
-		<h3>[name]( [page:Object3D object], [page:Color color] )</h3>
+		<h3>[name]( [page:Object3D object], [page:Color color], [page:Float thresholdAngle] )</h3>
 		<div>
 		<div>
 		object -- Object of which to draw edges <br />
 		object -- Object of which to draw edges <br />
-		color -- Color of the edges.
+		color -- Color of the edges.<br />
+		thresholdAngle -- the minimim angle (in degrees), between the face normals of adjacent faces, that is required to render an edge. Default is 0.1.
+
 		</div>
 		</div>
 		<div>
 		<div>
 		Creates a [page:Line], showing only the "hard" edges of the passed object; specifically, no edge will be drawn between faces which are adjacent and coplanar (or nearly coplanar).
 		Creates a [page:Line], showing only the "hard" edges of the passed object; specifically, no edge will be drawn between faces which are adjacent and coplanar (or nearly coplanar).

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

@@ -165,8 +165,7 @@
 
 
 		<h3>[method:Array decompose]( [page:Vector3 translation], [page:Quaternion quaternion], [page:Vector3 scale] )</h3>
 		<h3>[method:Array decompose]( [page:Vector3 translation], [page:Quaternion quaternion], [page:Vector3 scale] )</h3>
 		<div>
 		<div>
-		Decomposes this matrix into the *translation*, *quaternion* and *scale* components.<br />
-		If parameters are not passed, new instances will be created.
+		Decomposes this matrix into the *translation*, *quaternion* and *scale* components.
 		</div>
 		</div>
 
 
 		<h3>[method:Matrix4 makeTranslation]( [page:Float x], [page:Float y], [page:Float z] ) [page:Matrix4 this]</h3>
 		<h3>[method:Matrix4 makeTranslation]( [page:Float x], [page:Float y], [page:Float z] ) [page:Matrix4 this]</h3>

+ 2 - 4
editor/js/Script.js

@@ -89,14 +89,12 @@ var Script = function ( editor ) {
 
 
 			}
 			}
 
 
-			for ( var i = 0; i < widgets.length; i ++ ) {
+			while ( widgets.length > 0 ) {
 
 
-				codemirror.removeLineWidget( widgets[ i ] );
+				codemirror.removeLineWidget( widgets.shift() );
 
 
 			}
 			}
 
 
-			widgets.length = 0;
-
 			//
 			//
 
 
 			try {
 			try {

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

@@ -17,13 +17,14 @@ Sidebar.Geometry = function ( editor ) {
 
 
 	var geometryType = new UI.Text().setTextTransform( 'uppercase' );
 	var geometryType = new UI.Text().setTextTransform( 'uppercase' );
 	container.addStatic( geometryType );
 	container.addStatic( geometryType );
-	
+
 	// Actions
 	// Actions
-	
+
 	var objectActions = new UI.Select().setPosition('absolute').setRight( '8px' ).setFontSize( '11px' );
 	var objectActions = new UI.Select().setPosition('absolute').setRight( '8px' ).setFontSize( '11px' );
 	objectActions.setOptions( {
 	objectActions.setOptions( {
 
 
 		'Actions': 'Actions',
 		'Actions': 'Actions',
+		'Center': 'Center',
 		'Flatten': 'Flatten'
 		'Flatten': 'Flatten'
 
 
 	} );
 	} );
@@ -34,26 +35,35 @@ Sidebar.Geometry = function ( editor ) {
 	} );
 	} );
 	objectActions.onChange( function ( event ) {
 	objectActions.onChange( function ( event ) {
 
 
+		var action = this.getValue();
+
 		var object = editor.selected;
 		var object = editor.selected;
+		var geometry = object.geometry;
 
 
-		switch ( this.getValue() ) {
+		if ( confirm( action + ' ' + object.name + '?' ) === false ) return;
 
 
-			case 'Flatten':
+		switch ( action ) {
+
+			case 'Center':
 
 
-				var object = editor.selected;
+				var offset = geometry.center();
 
 
-				if ( confirm( 'Flatten ' + object.name + '?' ) === false ) return;
+				object.position.sub( offset );
 
 
-				var geometry = object.geometry;
+				editor.signals.geometryChanged.dispatch( geometry );
+				editor.signals.objectChanged.dispatch( object );
+
+				break;
+
+			case 'Flatten':
 
 
 				geometry.applyMatrix( object.matrix );
 				geometry.applyMatrix( object.matrix );
-				geometry.verticesNeedUpdate = true;
-				geometry.normalsNeedUpdate = true;
 
 
 				object.position.set( 0, 0, 0 );
 				object.position.set( 0, 0, 0 );
 				object.rotation.set( 0, 0, 0 );
 				object.rotation.set( 0, 0, 0 );
 				object.scale.set( 1, 1, 1 );
 				object.scale.set( 1, 1, 1 );
 
 
+				editor.signals.geometryChanged.dispatch( geometry );
 				editor.signals.objectChanged.dispatch( object );
 				editor.signals.objectChanged.dispatch( object );
 
 
 				break;
 				break;

+ 0 - 6
editor/js/Viewport.js

@@ -370,12 +370,6 @@ var Viewport = function ( editor ) {
 
 
 		transformControls.update();
 		transformControls.update();
 
 
-		if ( object.geometry !== undefined ) {
-
-			selectionBox.update( object );
-
-		}
-
 		if ( object instanceof THREE.PerspectiveCamera ) {
 		if ( object instanceof THREE.PerspectiveCamera ) {
 
 
 			object.updateProjectionMatrix();
 			object.updateProjectionMatrix();

+ 3 - 1
examples/index.html

@@ -358,6 +358,7 @@
 				"webgl_shadowmap",
 				"webgl_shadowmap",
 				"webgl_shadowmap_performance",
 				"webgl_shadowmap_performance",
 				"webgl_shadowmap_viewer",
 				"webgl_shadowmap_viewer",
+				"webgl_shadowmesh",
 				"webgl_sprites",
 				"webgl_sprites",
 				"webgl_terrain_dynamic",
 				"webgl_terrain_dynamic",
 				"webgl_test_memory",
 				"webgl_test_memory",
@@ -371,7 +372,8 @@
 				"webgldeferred_pointlights"
 				"webgldeferred_pointlights"
 			],
 			],
 			"vr": [
 			"vr": [
-				"vr_cubes"
+				"vr_cubes",
+				"vr_video"
 			],
 			],
 			"css3d": [
 			"css3d": [
 				"css3d_molecules",
 				"css3d_molecules",

+ 8 - 5
examples/js/ShaderDeferred.js

@@ -187,7 +187,8 @@ THREE.ShaderDeferred = {
 
 
 				"const float opacity = 1.0;",
 				"const float opacity = 1.0;",
 
 
-				"gl_FragColor = vec4( diffuse, opacity );",
+				"vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+				"vec4 diffuseColor = vec4( diffuse, opacity );",
 
 
 				THREE.ShaderChunk[ "map_fragment" ],
 				THREE.ShaderChunk[ "map_fragment" ],
 				THREE.ShaderChunk[ "alphatest_fragment" ],
 				THREE.ShaderChunk[ "alphatest_fragment" ],
@@ -195,6 +196,8 @@ THREE.ShaderDeferred = {
 				THREE.ShaderChunk[ "lightmap_fragment" ],
 				THREE.ShaderChunk[ "lightmap_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
 
 
+				"outgoingLight = diffuseColor.rgb;",
+
 				"#ifdef USE_ENVMAP",
 				"#ifdef USE_ENVMAP",
 
 
 					"vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
 					"vec2 texCoord = gl_FragCoord.xy / vec2( viewWidth, viewHeight );",
@@ -230,15 +233,15 @@ THREE.ShaderDeferred = {
 
 
 					"if ( combine == 1 ) {",
 					"if ( combine == 1 ) {",
 
 
-						"gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );",
+						"outgoingLight = mix( outgoingLight, cubeColor.xyz, specularStrength * reflectivity );",
 
 
 					"} else if ( combine == 2 ) {",
 					"} else if ( combine == 2 ) {",
 
 
-						"gl_FragColor.xyz += cubeColor.xyz * specularStrength * reflectivity;",
+						"outgoingLight += cubeColor.xyz * specularStrength * reflectivity;",
 
 
 					"} else {",
 					"} else {",
 
 
-						"gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );",
+						"outgoingLight = mix( outgoingLight, diffuseColor.xyz * cubeColor.xyz, specularStrength * reflectivity );",
 
 
 					"}",
 					"}",
 
 
@@ -267,7 +270,7 @@ THREE.ShaderDeferred = {
 
 
 				// diffuse color
 				// diffuse color
 
 
-				"gl_FragColor.x = vec3_to_float( compressionScale * gl_FragColor.xyz );",
+				"gl_FragColor.x = vec3_to_float( compressionScale * outgoingLight );",
 
 
 				// specular color
 				// specular color
 
 

+ 36 - 66
examples/js/ShaderSkin.js

@@ -159,12 +159,13 @@ THREE.ShaderSkin = {
 
 
 			"void main() {",
 			"void main() {",
 
 
-				"gl_FragColor = vec4( vec3( 1.0 ), opacity );",
+				"vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+				"vec4 diffuseColor = vec4( diffuse, opacity );",
 
 
 				"vec4 colDiffuse = texture2D( tDiffuse, vUv );",
 				"vec4 colDiffuse = texture2D( tDiffuse, vUv );",
 				"colDiffuse.rgb *= colDiffuse.rgb;",
 				"colDiffuse.rgb *= colDiffuse.rgb;",
 
 
-				"gl_FragColor = gl_FragColor * colDiffuse;",
+				"diffuseColor = diffuseColor * colDiffuse;",
 
 
 				"vec3 normal = normalize( vNormal );",
 				"vec3 normal = normalize( vNormal );",
 				"vec3 viewPosition = normalize( vViewPosition );",
 				"vec3 viewPosition = normalize( vViewPosition );",
@@ -190,12 +191,11 @@ THREE.ShaderSkin = {
 
 
 				// point lights
 				// point lights
 
 
-				"vec3 specularTotal = vec3( 0.0 );",
+				"vec3 totalSpecularLight = vec3( 0.0 );",
+				"vec3 totalDiffuseLight = vec3( 0.0 );",
 
 
 				"#if MAX_POINT_LIGHTS > 0",
 				"#if MAX_POINT_LIGHTS > 0",
 
 
-					"vec3 pointTotal = vec3( 0.0 );",
-
 					"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 					"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 
 
 						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
 						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
@@ -212,8 +212,8 @@ THREE.ShaderSkin = {
 
 
 						"float pointSpecularWeight = KS_Skin_Specular( normal, lVector, viewPosition, uRoughness, uSpecularBrightness );",
 						"float pointSpecularWeight = KS_Skin_Specular( normal, lVector, viewPosition, uRoughness, uSpecularBrightness );",
 
 
-						"pointTotal    += attenuation * diffuse * pointLightColor[ i ] * pointDiffuseWeight;",
-						"specularTotal += attenuation * specular * pointLightColor[ i ] * pointSpecularWeight * specularStrength;",
+						"totalDiffuseLight += attenuation * pointLightColor[ i ] * pointDiffuseWeight;",
+						"totalSpecularLight += attenuation * specular * pointLightColor[ i ] * pointSpecularWeight * specularStrength;",
 
 
 					"}",
 					"}",
 
 
@@ -223,8 +223,6 @@ THREE.ShaderSkin = {
 
 
 				"#if MAX_DIR_LIGHTS > 0",
 				"#if MAX_DIR_LIGHTS > 0",
 
 
-					"vec3 dirTotal = vec3( 0.0 );",
-
 					"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 					"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 
 
 						"vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );",
 						"vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );",
@@ -233,10 +231,10 @@ THREE.ShaderSkin = {
 						"float dirDiffuseWeightHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
 						"float dirDiffuseWeightHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
 						"vec3 dirDiffuseWeight = mix( vec3 ( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), uWrapRGB );",
 						"vec3 dirDiffuseWeight = mix( vec3 ( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), uWrapRGB );",
 
 
-						"float dirSpecularWeight =  KS_Skin_Specular( normal, dirVector, viewPosition, uRoughness, uSpecularBrightness );",
+						"float dirSpecularWeight = KS_Skin_Specular( normal, dirVector, viewPosition, uRoughness, uSpecularBrightness );",
 
 
-						"dirTotal 	   += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;",
-						"specularTotal += specular * directionalLightColor[ i ] * dirSpecularWeight * specularStrength;",
+						"totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;",
+						"totalSpecularLight += specular * directionalLightColor[ i ] * dirSpecularWeight * specularStrength;",
 
 
 					"}",
 					"}",
 
 
@@ -246,8 +244,6 @@ THREE.ShaderSkin = {
 
 
 				"#if MAX_HEMI_LIGHTS > 0",
 				"#if MAX_HEMI_LIGHTS > 0",
 
 
-					"vec3 hemiTotal = vec3( 0.0 );",
-
 					"for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
 					"for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
 
 
 						"vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );",
 						"vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );",
@@ -255,7 +251,7 @@ THREE.ShaderSkin = {
 						"float dotProduct = dot( normal, lVector );",
 						"float dotProduct = dot( normal, lVector );",
 						"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
 						"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
 
 
-						"hemiTotal += diffuse * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+						"totalDiffuseLight += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
 
 
 						// specular (sky light)
 						// specular (sky light)
 
 
@@ -267,34 +263,21 @@ THREE.ShaderSkin = {
 						"vec3 lVectorGround = -lVector;",
 						"vec3 lVectorGround = -lVector;",
 						"hemiSpecularWeight += KS_Skin_Specular( normal, lVectorGround, viewPosition, uRoughness, uSpecularBrightness );",
 						"hemiSpecularWeight += KS_Skin_Specular( normal, lVectorGround, viewPosition, uRoughness, uSpecularBrightness );",
 
 
-						"specularTotal += specular * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight ) * hemiSpecularWeight * specularStrength;",
+						"totalSpecularLight += specular * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight ) * hemiSpecularWeight * specularStrength;",
 
 
 					"}",
 					"}",
 
 
 				"#endif",
 				"#endif",
 
 
-				// all lights contribution summation
-
-				"vec3 totalLight = vec3( 0.0 );",
-
-				"#if MAX_DIR_LIGHTS > 0",
-					"totalLight += dirTotal;",
-				"#endif",
-
-				"#if MAX_POINT_LIGHTS > 0",
-					"totalLight += pointTotal;",
-				"#endif",
-
-				"#if MAX_HEMI_LIGHTS > 0",
-					"totalLight += hemiTotal;",
-				"#endif",
-
-				"gl_FragColor.xyz = gl_FragColor.xyz * ( totalLight + ambientLightColor * diffuse ) + specularTotal;",
+				"outgoingLight += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor * diffuse ) + totalSpecularLight;",
 
 
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 
+				"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
+
 			"}"
 			"}"
 
 
 		].join("\n"),
 		].join("\n"),
@@ -468,9 +451,9 @@ THREE.ShaderSkin = {
 
 
 			"void main() {",
 			"void main() {",
 
 
-				"gl_FragColor = vec4( 1.0 );",
+				"vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+				"vec4 diffuseColor = vec4( diffuse, opacity );",
 
 
-				"vec4 mColor = vec4( diffuse, opacity );",
 				"vec4 mSpecular = vec4( specular, opacity );",
 				"vec4 mSpecular = vec4( specular, opacity );",
 
 
 				"vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
 				"vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
@@ -480,7 +463,7 @@ THREE.ShaderSkin = {
 				"vec4 colDiffuse = texture2D( tDiffuse, vUv );",
 				"vec4 colDiffuse = texture2D( tDiffuse, vUv );",
 				"colDiffuse *= colDiffuse;",
 				"colDiffuse *= colDiffuse;",
 
 
-				"gl_FragColor = gl_FragColor * colDiffuse;",
+				"diffuseColor *= colDiffuse;",
 
 
 				"mat3 tsb = mat3( vTangent, vBinormal, vNormal );",
 				"mat3 tsb = mat3( vTangent, vBinormal, vNormal );",
 				"vec3 finalNormal = tsb * normalTex;",
 				"vec3 finalNormal = tsb * normalTex;",
@@ -490,12 +473,11 @@ THREE.ShaderSkin = {
 
 
 				// point lights
 				// point lights
 
 
-				"vec3 specularTotal = vec3( 0.0 );",
+				"vec3 totalDiffuseLight = vec3( 0.0 );",
+				"vec3 totalSpecularLight = vec3( 0.0 );",
 
 
 				"#if MAX_POINT_LIGHTS > 0",
 				"#if MAX_POINT_LIGHTS > 0",
 
 
-					"vec4 pointTotal = vec4( vec3( 0.0 ), 1.0 );",
-
 					"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 					"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 
 
 						"vec3 pointVector = normalize( vPointLight[ i ].xyz );",
 						"vec3 pointVector = normalize( vPointLight[ i ].xyz );",
@@ -503,10 +485,10 @@ THREE.ShaderSkin = {
 
 
 						"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
 						"float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
 
 
-						"pointTotal  += pointDistance * vec4( pointLightColor[ i ], 1.0 ) * ( mColor * pointDiffuseWeight );",
+						"totalDiffuseLight += pointDistance * pointLightColor[ i ] * pointDiffuseWeight;",
 
 
 						"if ( passID == 1 )",
 						"if ( passID == 1 )",
-							"specularTotal += pointDistance * mSpecular.xyz * pointLightColor[ i ] * KS_Skin_Specular( normal, pointVector, viewPosition, uRoughness, uSpecularBrightness );",
+							"totalSpecularLight += pointDistance * mSpecular.xyz * pointLightColor[ i ] * KS_Skin_Specular( normal, pointVector, viewPosition, uRoughness, uSpecularBrightness );",
 
 
 					"}",
 					"}",
 
 
@@ -516,40 +498,27 @@ THREE.ShaderSkin = {
 
 
 				"#if MAX_DIR_LIGHTS > 0",
 				"#if MAX_DIR_LIGHTS > 0",
 
 
-					"vec4 dirTotal = vec4( vec3( 0.0 ), 1.0 );",
-
 					"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 					"for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 
 
 						"vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );",
 						"vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );",
 
 
 						"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
 						"float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
 
 
-						"dirTotal  += vec4( directionalLightColor[ i ], 1.0 ) * ( mColor * dirDiffuseWeight );",
+						"totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;",
 
 
 						"if ( passID == 1 )",
 						"if ( passID == 1 )",
-							"specularTotal += mSpecular.xyz * directionalLightColor[ i ] * KS_Skin_Specular( normal, dirVector, viewPosition, uRoughness, uSpecularBrightness );",
+							"totalSpecularLight += mSpecular.xyz * directionalLightColor[ i ] * KS_Skin_Specular( normal, dirVector, viewPosition, uRoughness, uSpecularBrightness );",
 
 
 					"}",
 					"}",
 
 
 				"#endif",
 				"#endif",
 
 
-				// all lights contribution summation
 
 
-				"vec4 totalLight = vec4( vec3( 0.0 ), opacity );",
-
-				"#if MAX_DIR_LIGHTS > 0",
-					"totalLight += dirTotal;",
-				"#endif",
-
-				"#if MAX_POINT_LIGHTS > 0",
-					"totalLight += pointTotal;",
-				"#endif",
-
-				"gl_FragColor = gl_FragColor * totalLight;",
+				"outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + totalSpecularLight );",
 
 
 				"if ( passID == 0 ) {",
 				"if ( passID == 0 ) {",
 
 
-					"gl_FragColor = vec4( sqrt( gl_FragColor.xyz ), gl_FragColor.w );",
+					"outgoingLight = sqrt( outgoingLight );",
 
 
 				"} else if ( passID == 1 ) {",
 				"} else if ( passID == 1 ) {",
 
 
@@ -557,11 +526,11 @@ THREE.ShaderSkin = {
 
 
 					"#ifdef VERSION1",
 					"#ifdef VERSION1",
 
 
-						"vec3 nonblurColor = sqrt( gl_FragColor.xyz );",
+						"vec3 nonblurColor = sqrt(outgoingLight );",
 
 
 					"#else",
 					"#else",
 
 
-						"vec3 nonblurColor = gl_FragColor.xyz;",
+						"vec3 nonblurColor = outgoingLight;",
 
 
 					"#endif",
 					"#endif",
 
 
@@ -578,20 +547,19 @@ THREE.ShaderSkin = {
 					//"gl_FragColor = vec4( vec3( 0.25, 0.6, 0.8 ) * nonblurColor + vec3( 0.15, 0.25, 0.2 ) * blur1Color + vec3( 0.15, 0.15, 0.0 ) * blur2Color + vec3( 0.45, 0.0, 0.0 ) * blur3Color, gl_FragColor.w );",
 					//"gl_FragColor = vec4( vec3( 0.25, 0.6, 0.8 ) * nonblurColor + vec3( 0.15, 0.25, 0.2 ) * blur1Color + vec3( 0.15, 0.15, 0.0 ) * blur2Color + vec3( 0.45, 0.0, 0.0 ) * blur3Color, gl_FragColor.w );",
 
 
 
 
-					"gl_FragColor = vec4( vec3( 0.22,  0.437, 0.635 ) * nonblurColor + ",
+					"outgoingLight = vec3( vec3( 0.22,  0.437, 0.635 ) * nonblurColor + ",
 										 "vec3( 0.101, 0.355, 0.365 ) * blur1Color + ",
 										 "vec3( 0.101, 0.355, 0.365 ) * blur1Color + ",
 										 "vec3( 0.119, 0.208, 0.0 )   * blur2Color + ",
 										 "vec3( 0.119, 0.208, 0.0 )   * blur2Color + ",
 										 "vec3( 0.114, 0.0,   0.0 )   * blur3Color + ",
 										 "vec3( 0.114, 0.0,   0.0 )   * blur3Color + ",
-										 "vec3( 0.444, 0.0,   0.0 )   * blur4Color",
-										 ", gl_FragColor.w );",
+										 "vec3( 0.444, 0.0,   0.0 )   * blur4Color );",
 
 
-					"gl_FragColor.xyz *= pow( colDiffuse.xyz, vec3( 0.5 ) );",
+					"outgoingLight *= sqrt( colDiffuse.xyz );",
 
 
-					"gl_FragColor.xyz += ambientLightColor * diffuse * colDiffuse.xyz + specularTotal;",
+					"outgoingLight += ambientLightColor * diffuse * colDiffuse.xyz + totalSpecularLight;",
 
 
 					"#ifndef VERSION1",
 					"#ifndef VERSION1",
 
 
-						"gl_FragColor.xyz = sqrt( gl_FragColor.xyz );",
+						"outgoingLight = sqrt( outgoingLight );",
 
 
 					"#endif",
 					"#endif",
 
 
@@ -599,6 +567,8 @@ THREE.ShaderSkin = {
 
 
 				THREE.ShaderChunk[ "fog_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 
+				"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
 			"}"
 			"}"
 
 
 		].join("\n"),
 		].join("\n"),

+ 17 - 41
examples/js/ShaderTerrain.js

@@ -118,7 +118,8 @@ THREE.ShaderTerrain = {
 
 
 			"void main() {",
 			"void main() {",
 
 
-				"gl_FragColor = vec4( vec3( 1.0 ), opacity );",
+				"vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+				"vec4 diffuseColor = vec4( diffuse, opacity );",
 
 
 				"vec3 specularTex = vec3( 1.0 );",
 				"vec3 specularTex = vec3( 1.0 );",
 
 
@@ -137,15 +138,15 @@ THREE.ShaderTerrain = {
 					"colDiffuse1.xyz = inputToLinear( colDiffuse1.xyz );",
 					"colDiffuse1.xyz = inputToLinear( colDiffuse1.xyz );",
 					"colDiffuse2.xyz = inputToLinear( colDiffuse2.xyz );",
 					"colDiffuse2.xyz = inputToLinear( colDiffuse2.xyz );",
 
 
-					"gl_FragColor = gl_FragColor * mix ( colDiffuse1, colDiffuse2, 1.0 - texture2D( tDisplacement, uvBase ) );",
+					"diffuseColor *= mix ( colDiffuse1, colDiffuse2, 1.0 - texture2D( tDisplacement, uvBase ) );",
 
 
 				" } else if( enableDiffuse1 ) {",
 				" } else if( enableDiffuse1 ) {",
 
 
-					"gl_FragColor = gl_FragColor * texture2D( tDiffuse1, uvOverlay );",
+					"diffuseColor *= texture2D( tDiffuse1, uvOverlay );",
 
 
 				"} else if( enableDiffuse2 ) {",
 				"} else if( enableDiffuse2 ) {",
 
 
-					"gl_FragColor = gl_FragColor * texture2D( tDiffuse2, uvOverlay );",
+					"diffuseColor *= texture2D( tDiffuse2, uvOverlay );",
 
 
 				"}",
 				"}",
 
 
@@ -158,13 +159,13 @@ THREE.ShaderTerrain = {
 				"vec3 normal = normalize( finalNormal );",
 				"vec3 normal = normalize( finalNormal );",
 				"vec3 viewPosition = normalize( vViewPosition );",
 				"vec3 viewPosition = normalize( vViewPosition );",
 
 
+				"vec3 totalDiffuseLight = vec3( 0.0 );",
+				"vec3 totalSpecularLight = vec3( 0.0 );",
+
 				// point lights
 				// point lights
 
 
 				"#if MAX_POINT_LIGHTS > 0",
 				"#if MAX_POINT_LIGHTS > 0",
 
 
-					"vec3 pointDiffuse = vec3( 0.0 );",
-					"vec3 pointSpecular = vec3( 0.0 );",
-
 					"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 					"for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 
 
 						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
 						"vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
@@ -181,8 +182,8 @@ THREE.ShaderTerrain = {
 
 
 						"float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
 						"float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
 
 
-						"pointDiffuse += attenuation * pointLightColor[ i ] * diffuse * pointDiffuseWeight;",
-						"pointSpecular += attenuation * pointLightColor[ i ] * specular * pointSpecularWeight * pointDiffuseWeight;",
+						"totalDiffuseLight += attenuation * pointLightColor[ i ] * pointDiffuseWeight;",
+						"totalSpecularLight += attenuation * pointLightColor[ i ] * specular * pointSpecularWeight * pointDiffuseWeight;",
 
 
 					"}",
 					"}",
 
 
@@ -205,8 +206,8 @@ THREE.ShaderTerrain = {
 
 
 						"float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, shininess ), 0.0 );",
 						"float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, shininess ), 0.0 );",
 
 
-						"dirDiffuse += directionalLightColor[ i ] * diffuse * dirDiffuseWeight;",
-						"dirSpecular += directionalLightColor[ i ] * specular * dirSpecularWeight * dirDiffuseWeight;",
+						"totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;",
+						"totalSpecularLight += directionalLightColor[ i ] * specular * dirSpecularWeight * dirDiffuseWeight;",
 
 
 					"}",
 					"}",
 
 
@@ -228,7 +229,7 @@ THREE.ShaderTerrain = {
 						"float dotProduct = dot( normal, lVector );",
 						"float dotProduct = dot( normal, lVector );",
 						"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
 						"float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
 
 
-						"hemiDiffuse += diffuse * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
+						"totalDiffuseLight += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
 
 
 						// specular (sky light)
 						// specular (sky light)
 
 
@@ -246,45 +247,20 @@ THREE.ShaderTerrain = {
 						"float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
 						"float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
 						"hemiSpecularWeight += specularTex.r * max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );",
 						"hemiSpecularWeight += specularTex.r * max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );",
 
 
-						"hemiSpecular += specular * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight ) * hemiSpecularWeight * hemiDiffuseWeight;",
+						"totalSpecularLight += specular * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight ) * hemiSpecularWeight * hemiDiffuseWeight;",
 
 
 					"}",
 					"}",
 
 
 				"#endif",
 				"#endif",
 
 
-				// all lights contribution summation
-
-				"vec3 totalDiffuse = vec3( 0.0 );",
-				"vec3 totalSpecular = vec3( 0.0 );",
-
-				"#if MAX_DIR_LIGHTS > 0",
-
-					"totalDiffuse += dirDiffuse;",
-					"totalSpecular += dirSpecular;",
-
-				"#endif",
-
-				"#if MAX_HEMI_LIGHTS > 0",
-
-					"totalDiffuse += hemiDiffuse;",
-					"totalSpecular += hemiSpecular;",
-
-				"#endif",
-
-				"#if MAX_POINT_LIGHTS > 0",
-
-					"totalDiffuse += pointDiffuse;",
-					"totalSpecular += pointSpecular;",
-
-				"#endif",
-
-				//"gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * diffuse ) + totalSpecular;",
-				"gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * diffuse + totalSpecular );",
+				"outgoingLight += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor + totalSpecularLight );",
 
 
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 
+				"gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
 			"}"
 			"}"
 
 
 		].join("\n"),
 		].join("\n"),

+ 16 - 23
examples/js/SkyShader.js

@@ -1,16 +1,16 @@
 /**
 /**
  * @author zz85 / https://github.com/zz85
  * @author zz85 / https://github.com/zz85
- * 
- * Based on "A Practical Analytic Model for Daylight" 
+ *
+ * Based on "A Practical Analytic Model for Daylight"
  * aka The Preetham Model, the de facto standard analytic skydome model
  * aka The Preetham Model, the de facto standard analytic skydome model
  * http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
  * http://www.cs.utah.edu/~shirley/papers/sunsky/sunsky.pdf
- * 
+ *
  * First implemented by Simon Wallner
  * First implemented by Simon Wallner
  * http://www.simonwallner.at/projects/atmospheric-scattering
  * http://www.simonwallner.at/projects/atmospheric-scattering
- * 
+ *
  * Improved by Martin Upitis
  * Improved by Martin Upitis
  * http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
  * http://blenderartists.org/forum/showthread.php?245954-preethams-sky-impementation-HDR
- * 
+ *
  * Three.js integration by zz85 http://twitter.com/blurspline
  * Three.js integration by zz85 http://twitter.com/blurspline
 */
 */
 
 
@@ -30,13 +30,11 @@ THREE.ShaderLib['sky'] = {
 	vertexShader: [
 	vertexShader: [
 
 
 		"varying vec3 vWorldPosition;",
 		"varying vec3 vWorldPosition;",
-		"varying vec2 vUv;",
 
 
 		"void main() {",
 		"void main() {",
 
 
 			"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
 			"vec4 worldPosition = modelMatrix * vec4( position, 1.0 );",
 			"vWorldPosition = worldPosition.xyz;",
 			"vWorldPosition = worldPosition.xyz;",
-			"vUv = uv;",
 
 
 			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
 			"gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
 
 
@@ -46,12 +44,9 @@ THREE.ShaderLib['sky'] = {
 
 
 	fragmentShader: [
 	fragmentShader: [
 
 
-
 		"uniform sampler2D skySampler;",
 		"uniform sampler2D skySampler;",
 		"uniform vec3 sunPosition;",
 		"uniform vec3 sunPosition;",
 		"varying vec3 vWorldPosition;",
 		"varying vec3 vWorldPosition;",
-		"varying vec2 vUv;",
-
 
 
 		"vec3 cameraPos = vec3(0., 0., 0.);",
 		"vec3 cameraPos = vec3(0., 0., 0.);",
 		"// uniform sampler2D sDiffuse;",
 		"// uniform sampler2D sDiffuse;",
@@ -67,7 +62,6 @@ THREE.ShaderLib['sky'] = {
 		"uniform float mieCoefficient;",
 		"uniform float mieCoefficient;",
 		"uniform float mieDirectionalG;",
 		"uniform float mieDirectionalG;",
 
 
-
 		"vec3 sunDirection = normalize(sunPosition);",
 		"vec3 sunDirection = normalize(sunPosition);",
 		"float reileighCoefficient = reileigh;",
 		"float reileighCoefficient = reileigh;",
 
 
@@ -165,9 +159,9 @@ THREE.ShaderLib['sky'] = {
 			"// luminance =  1.0 ;// vWorldPosition.y / 450000. + 0.5; //sunPosition.y / 450000. * 1. + 0.5;",
 			"// luminance =  1.0 ;// vWorldPosition.y / 450000. + 0.5; //sunPosition.y / 450000. * 1. + 0.5;",
 
 
 			 "// gl_FragColor = vec4(sunfade, sunfade, sunfade, 1.0);",
 			 "// gl_FragColor = vec4(sunfade, sunfade, sunfade, 1.0);",
-			
+
 			"reileighCoefficient = reileighCoefficient - (1.0* (1.0-sunfade));",
 			"reileighCoefficient = reileighCoefficient - (1.0* (1.0-sunfade));",
-			
+
 			"float sunE = sunIntensity(dot(sunDirection, up));",
 			"float sunE = sunIntensity(dot(sunDirection, up));",
 
 
 			"// extinction (absorbtion + out scattering) ",
 			"// extinction (absorbtion + out scattering) ",
@@ -210,7 +204,7 @@ THREE.ShaderLib['sky'] = {
 			"vec2 uv = vec2(phi, theta) / vec2(2.0*pi, pi) + vec2(0.5, 0.0);",
 			"vec2 uv = vec2(phi, theta) / vec2(2.0*pi, pi) + vec2(0.5, 0.0);",
 			"// vec3 L0 = texture2D(skySampler, uv).rgb+0.1 * Fex;",
 			"// vec3 L0 = texture2D(skySampler, uv).rgb+0.1 * Fex;",
 			"vec3 L0 = vec3(0.1) * Fex;",
 			"vec3 L0 = vec3(0.1) * Fex;",
-			
+
 			"// composition + solar disc",
 			"// composition + solar disc",
 			"//if (cosTheta > sunAngularDiameterCos)",
 			"//if (cosTheta > sunAngularDiameterCos)",
 			"float sundisk = smoothstep(sunAngularDiameterCos,sunAngularDiameterCos+0.00002,cosTheta);",
 			"float sundisk = smoothstep(sunAngularDiameterCos,sunAngularDiameterCos+0.00002,cosTheta);",
@@ -219,25 +213,25 @@ THREE.ShaderLib['sky'] = {
 
 
 
 
 			"vec3 whiteScale = 1.0/Uncharted2Tonemap(vec3(W));",
 			"vec3 whiteScale = 1.0/Uncharted2Tonemap(vec3(W));",
-			
+
 			"vec3 texColor = (Lin+L0);   ",
 			"vec3 texColor = (Lin+L0);   ",
 			"texColor *= 0.04 ;",
 			"texColor *= 0.04 ;",
 			"texColor += vec3(0.0,0.001,0.0025)*0.3;",
 			"texColor += vec3(0.0,0.001,0.0025)*0.3;",
-			
+
 			"float g_fMaxLuminance = 1.0;",
 			"float g_fMaxLuminance = 1.0;",
 			"float fLumScaled = 0.1 / luminance;     ",
 			"float fLumScaled = 0.1 / luminance;     ",
 			"float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (g_fMaxLuminance * g_fMaxLuminance)))) / (1.0 + fLumScaled); ",
 			"float fLumCompressed = (fLumScaled * (1.0 + (fLumScaled / (g_fMaxLuminance * g_fMaxLuminance)))) / (1.0 + fLumScaled); ",
 
 
 			"float ExposureBias = fLumCompressed;",
 			"float ExposureBias = fLumCompressed;",
-		   
+
 			"vec3 curr = Uncharted2Tonemap((log2(2.0/pow(luminance,4.0)))*texColor);",
 			"vec3 curr = Uncharted2Tonemap((log2(2.0/pow(luminance,4.0)))*texColor);",
 			"vec3 color = curr*whiteScale;",
 			"vec3 color = curr*whiteScale;",
 
 
 			"vec3 retColor = pow(color,vec3(1.0/(1.2+(1.2*sunfade))));",
 			"vec3 retColor = pow(color,vec3(1.0/(1.2+(1.2*sunfade))));",
 
 
-			
+
 			"gl_FragColor.rgb = retColor;",
 			"gl_FragColor.rgb = retColor;",
-				
+
 			"gl_FragColor.a = 1.0;",
 			"gl_FragColor.a = 1.0;",
 		"}",
 		"}",
 
 
@@ -250,9 +244,9 @@ THREE.Sky = function () {
 	var skyShader = THREE.ShaderLib[ "sky" ];
 	var skyShader = THREE.ShaderLib[ "sky" ];
 	var skyUniforms = THREE.UniformsUtils.clone( skyShader.uniforms );
 	var skyUniforms = THREE.UniformsUtils.clone( skyShader.uniforms );
 
 
-	var skyMat = new THREE.ShaderMaterial( { 
-		fragmentShader: skyShader.fragmentShader, 
-		vertexShader: skyShader.vertexShader, 
+	var skyMat = new THREE.ShaderMaterial( {
+		fragmentShader: skyShader.fragmentShader,
+		vertexShader: skyShader.vertexShader,
 		uniforms: skyUniforms,
 		uniforms: skyUniforms,
 		side: THREE.BackSide
 		side: THREE.BackSide
 	} );
 	} );
@@ -265,5 +259,4 @@ THREE.Sky = function () {
 	this.mesh = skyMesh;
 	this.mesh = skyMesh;
 	this.uniforms = skyUniforms;
 	this.uniforms = skyUniforms;
 
 
-
 };
 };

+ 19 - 4
examples/js/effects/VREffect.js

@@ -74,16 +74,31 @@ THREE.VREffect = function ( renderer, done ) {
 			return;
 			return;
 		}
 		}
 		// Regular render mode if not HMD
 		// Regular render mode if not HMD
+		if ( scene instanceof Array ) scene = scene[ 0 ];
 		renderer.render.apply( this._renderer, arguments );
 		renderer.render.apply( this._renderer, arguments );
 	};
 	};
 
 
 	this.renderStereo = function( scene, camera, renderTarget, forceClear ) {
 	this.renderStereo = function( scene, camera, renderTarget, forceClear ) {
 
 
+		var sceneLeft, sceneRight;
+
+		if ( scene instanceof Array ) {
+
+			sceneLeft = scene[ 0 ];
+			sceneRight = scene[ 1 ];
+
+		} else {
+
+			sceneLeft = scene;
+			sceneRight = scene;
+
+		}
+
 		var leftEyeTranslation = this.leftEyeTranslation;
 		var leftEyeTranslation = this.leftEyeTranslation;
 		var rightEyeTranslation = this.rightEyeTranslation;
 		var rightEyeTranslation = this.rightEyeTranslation;
 		var renderer = this._renderer;
 		var renderer = this._renderer;
-		var rendererWidth = renderer.context.drawingBufferWidth;
-		var rendererHeight = renderer.context.drawingBufferHeight;
+		var rendererWidth = renderer.context.drawingBufferWidth / renderer.getPixelRatio();
+		var rendererHeight = renderer.context.drawingBufferHeight / renderer.getPixelRatio();
 		var eyeDivisionLine = rendererWidth / 2;
 		var eyeDivisionLine = rendererWidth / 2;
 
 
 		renderer.enableScissorTest( true );
 		renderer.enableScissorTest( true );
@@ -105,12 +120,12 @@ THREE.VREffect = function ( renderer, done ) {
 		// render left eye
 		// render left eye
 		renderer.setViewport( 0, 0, eyeDivisionLine, rendererHeight );
 		renderer.setViewport( 0, 0, eyeDivisionLine, rendererHeight );
 		renderer.setScissor( 0, 0, eyeDivisionLine, rendererHeight );
 		renderer.setScissor( 0, 0, eyeDivisionLine, rendererHeight );
-		renderer.render( scene, cameraLeft );
+		renderer.render( sceneLeft, cameraLeft );
 
 
 		// render right eye
 		// render right eye
 		renderer.setViewport( eyeDivisionLine, 0, eyeDivisionLine, rendererHeight );
 		renderer.setViewport( eyeDivisionLine, 0, eyeDivisionLine, rendererHeight );
 		renderer.setScissor( eyeDivisionLine, 0, eyeDivisionLine, rendererHeight );
 		renderer.setScissor( eyeDivisionLine, 0, eyeDivisionLine, rendererHeight );
-		renderer.render( scene, cameraRight );
+		renderer.render( sceneRight, cameraRight );
 
 
 		renderer.enableScissorTest( false );
 		renderer.enableScissorTest( false );
 
 

+ 2 - 2
examples/js/math/Lut.js

@@ -300,7 +300,7 @@ THREE.Lut.prototype = {
 		contextTitle.fillText( this.legend.labels.title.toString() + this.legend.labels.um.toString(), borderThickness, this.legend.labels.fontsize + borderThickness );
 		contextTitle.fillText( this.legend.labels.title.toString() + this.legend.labels.um.toString(), borderThickness, this.legend.labels.fontsize + borderThickness );
 
 
 		var txtTitle = new THREE.Texture( canvasTitle );
 		var txtTitle = new THREE.Texture( canvasTitle );
-
+		txtTitle.minFilter = THREE.LinearFilter;
 		txtTitle.needsUpdate = true;
 		txtTitle.needsUpdate = true;
 
 
 		var spriteMaterialTitle = new THREE.SpriteMaterial( { map: txtTitle, useScreenCoordinates: false } );
 		var spriteMaterialTitle = new THREE.SpriteMaterial( { map: txtTitle, useScreenCoordinates: false } );
@@ -385,7 +385,7 @@ THREE.Lut.prototype = {
 				contextTick.fillText( value.toString(), borderThickness, this.legend.labels.fontsize + borderThickness );
 				contextTick.fillText( value.toString(), borderThickness, this.legend.labels.fontsize + borderThickness );
 
 
 				var txtTick = new THREE.Texture( canvasTick );
 				var txtTick = new THREE.Texture( canvasTick );
-
+				txtTick.minFilter = THREE.LinearFilter;
 				txtTick.needsUpdate = true;
 				txtTick.needsUpdate = true;
 
 
 				var spriteMaterialTick = new THREE.SpriteMaterial( { map: txtTick, useScreenCoordinates: false } );
 				var spriteMaterialTick = new THREE.SpriteMaterial( { map: txtTick, useScreenCoordinates: false } );

+ 11 - 11
examples/js/postprocessing/AdaptiveToneMappingPass.js

@@ -16,7 +16,7 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 	this.luminanceRT = null;
 	this.luminanceRT = null;
 	this.previousLuminanceRT = null;
 	this.previousLuminanceRT = null;
 	this.currentLuminanceRT = null;
 	this.currentLuminanceRT = null;
-	
+
 	if ( THREE.CopyShader === undefined )
 	if ( THREE.CopyShader === undefined )
 		console.error( "THREE.AdaptiveToneMappingPass relies on THREE.CopyShader" );
 		console.error( "THREE.AdaptiveToneMappingPass relies on THREE.CopyShader" );
 
 
@@ -39,7 +39,7 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 
 
 	this.materialLuminance = new THREE.ShaderMaterial( {
 	this.materialLuminance = new THREE.ShaderMaterial( {
 
 
-		uniforms: THREE.LuminosityShader.uniforms,
+		uniforms: THREE.UniformsUtils.clone( THREE.LuminosityShader.uniforms ),
 		vertexShader: THREE.LuminosityShader.vertexShader,
 		vertexShader: THREE.LuminosityShader.vertexShader,
 		fragmentShader: THREE.LuminosityShader.fragmentShader,
 		fragmentShader: THREE.LuminosityShader.fragmentShader,
 		blending: THREE.NoBlending,
 		blending: THREE.NoBlending,
@@ -72,15 +72,15 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 			"uniform sampler2D currentLum;",
 			"uniform sampler2D currentLum;",
 			"uniform float delta;",
 			"uniform float delta;",
 			"uniform float tau;",
 			"uniform float tau;",
-			
+
 			"void main() {",
 			"void main() {",
 
 
 				"vec4 lastLum = texture2D( lastLum, vUv, MIP_LEVEL_1X1 );",
 				"vec4 lastLum = texture2D( lastLum, vUv, MIP_LEVEL_1X1 );",
 				"vec4 currentLum = texture2D( currentLum, vUv, MIP_LEVEL_1X1 );",
 				"vec4 currentLum = texture2D( currentLum, vUv, MIP_LEVEL_1X1 );",
-				
+
 				"float fLastLum = lastLum.r;",
 				"float fLastLum = lastLum.r;",
 				"float fCurrentLum = currentLum.r;",
 				"float fCurrentLum = currentLum.r;",
-				
+
 				//The adaption seems to work better in extreme lighting differences
 				//The adaption seems to work better in extreme lighting differences
 				//if the input luminance is squared.
 				//if the input luminance is squared.
 				"fCurrentLum *= fCurrentLum;",
 				"fCurrentLum *= fCurrentLum;",
@@ -95,7 +95,7 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 
 
 	this.materialAdaptiveLum = new THREE.ShaderMaterial( {
 	this.materialAdaptiveLum = new THREE.ShaderMaterial( {
 
 
-		uniforms: this.adaptLuminanceShader.uniforms,
+		uniforms: THREE.UniformsUtils.clone( this.adaptLuminanceShader.uniforms ),
 		vertexShader: this.adaptLuminanceShader.vertexShader,
 		vertexShader: this.adaptLuminanceShader.vertexShader,
 		fragmentShader: this.adaptLuminanceShader.fragmentShader,
 		fragmentShader: this.adaptLuminanceShader.fragmentShader,
 		defines: this.adaptLuminanceShader.defines,
 		defines: this.adaptLuminanceShader.defines,
@@ -107,7 +107,7 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 
 
 	this.materialToneMap = new THREE.ShaderMaterial( {
 	this.materialToneMap = new THREE.ShaderMaterial( {
 
 
-		uniforms: THREE.ToneMapShader.uniforms,
+		uniforms: THREE.UniformsUtils.clone( THREE.ToneMapShader.uniforms ),
 		vertexShader: THREE.ToneMapShader.vertexShader,
 		vertexShader: THREE.ToneMapShader.vertexShader,
 		fragmentShader: THREE.ToneMapShader.fragmentShader,
 		fragmentShader: THREE.ToneMapShader.fragmentShader,
 		blending: THREE.NoBlending
 		blending: THREE.NoBlending
@@ -120,7 +120,7 @@ THREE.AdaptiveToneMappingPass = function ( adaptive, resolution ) {
 	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.camera = new THREE.OrthographicCamera( -1, 1, 1, -1, 0, 1 );
 	this.scene  = new THREE.Scene();
 	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.scene.add( this.quad );
 
 
 };
 };
@@ -160,7 +160,7 @@ THREE.AdaptiveToneMappingPass.prototype = {
 		this.quad.material = this.materialToneMap;
 		this.quad.material = this.materialToneMap;
 		this.materialToneMap.uniforms.tDiffuse.value = readBuffer;
 		this.materialToneMap.uniforms.tDiffuse.value = readBuffer;
 		renderer.render( this.scene, this.camera, writeBuffer, this.clear );
 		renderer.render( this.scene, this.camera, writeBuffer, this.clear );
-		
+
 	},
 	},
 
 
 	reset: function( renderer ) {
 	reset: function( renderer ) {
@@ -184,7 +184,7 @@ THREE.AdaptiveToneMappingPass.prototype = {
 		//We only need mipmapping for the current luminosity because we want a down-sampled version to sample in our adaptive shader
 		//We only need mipmapping for the current luminosity because we want a down-sampled version to sample in our adaptive shader
 		pars.minFilter = THREE.LinearMipMapLinearFilter;
 		pars.minFilter = THREE.LinearMipMapLinearFilter;
 		this.currentLuminanceRT = new THREE.WebGLRenderTarget( this.resolution, this.resolution, pars );
 		this.currentLuminanceRT = new THREE.WebGLRenderTarget( this.resolution, this.resolution, pars );
-		
+
 		if ( this.adaptive ) {
 		if ( this.adaptive ) {
 			this.materialToneMap.defines["ADAPTED_LUMINANCE"] = "";
 			this.materialToneMap.defines["ADAPTED_LUMINANCE"] = "";
 			this.materialToneMap.uniforms.luminanceMap.value = this.luminanceRT;
 			this.materialToneMap.uniforms.luminanceMap.value = this.luminanceRT;
@@ -261,4 +261,4 @@ THREE.AdaptiveToneMappingPass.prototype = {
 		}
 		}
 	}
 	}
 
 
-};
+};

+ 26 - 63
examples/js/shaders/NormalDisplacementShader.js

@@ -134,7 +134,8 @@ THREE.NormalDisplacementShader = {
 		"void main() {",
 		"void main() {",
 			THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 			THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 
 
-		"	gl_FragColor = vec4( vec3( 1.0 ), opacity );",
+		"	vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+		"	vec4 diffuseColor = vec4( diffuse, opacity );",
 
 
 		"	vec3 specularTex = vec3( 1.0 );",
 		"	vec3 specularTex = vec3( 1.0 );",
 
 
@@ -149,11 +150,11 @@ THREE.NormalDisplacementShader = {
 		"			vec4 texelColor = texture2D( tDiffuse, vUv );",
 		"			vec4 texelColor = texture2D( tDiffuse, vUv );",
 		"			texelColor.xyz *= texelColor.xyz;",
 		"			texelColor.xyz *= texelColor.xyz;",
 
 
-		"			gl_FragColor = gl_FragColor * texelColor;",
+		"			diffuseColor *= texelColor;",
 
 
 		"		#else",
 		"		#else",
 
 
-		"			gl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );",
+		"			diffuseColor *= texture2D( tDiffuse, vUv );",
 
 
 		"		#endif",
 		"		#endif",
 
 
@@ -166,11 +167,11 @@ THREE.NormalDisplacementShader = {
 		"			vec4 aoColor = texture2D( tAO, vUv );",
 		"			vec4 aoColor = texture2D( tAO, vUv );",
 		"			aoColor.xyz *= aoColor.xyz;",
 		"			aoColor.xyz *= aoColor.xyz;",
 
 
-		"			gl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;",
+		"			diffuseColor.rgb *= aoColor.xyz;",
 
 
 		"		#else",
 		"		#else",
 
 
-		"			gl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;",
+		"			diffuseColor.rgb *= texture2D( tAO, vUv ).xyz;",
 
 
 		"		#endif",
 		"		#endif",
 
 
@@ -193,13 +194,13 @@ THREE.NormalDisplacementShader = {
 		"	vec3 normal = normalize( finalNormal );",
 		"	vec3 normal = normalize( finalNormal );",
 		"	vec3 viewPosition = normalize( vViewPosition );",
 		"	vec3 viewPosition = normalize( vViewPosition );",
 
 
+		"	vec3 totalDiffuseLight = vec3( 0.0 );",
+		"	vec3 totalSpecularLight = vec3( 0.0 );",
+
 			// point lights
 			// point lights
 
 
 		"	#if MAX_POINT_LIGHTS > 0",
 		"	#if MAX_POINT_LIGHTS > 0",
 
 
-		"		vec3 pointDiffuse = vec3( 0.0 );",
-		"		vec3 pointSpecular = vec3( 0.0 );",
-
 		"		for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 		"		for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
 
 
 		"			vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
 		"			vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
@@ -226,7 +227,7 @@ THREE.NormalDisplacementShader = {
 
 
 		"			#endif",
 		"			#endif",
 
 
-		"			pointDiffuse += pointDistance * pointLightColor[ i ] * diffuse * pointDiffuseWeight;",
+		"			totalDiffuseLight += pointDistance * pointLightColor[ i ] * pointDiffuseWeight;",
 
 
 					// specular
 					// specular
 
 
@@ -237,7 +238,7 @@ THREE.NormalDisplacementShader = {
 		"			float specularNormalization = ( shininess + 2.0 ) / 8.0;",
 		"			float specularNormalization = ( shininess + 2.0 ) / 8.0;",
 
 
 		"			vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( pointVector, pointHalfVector ), 0.0 ), 5.0 );",
 		"			vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( pointVector, pointHalfVector ), 0.0 ), 5.0 );",
-		"			pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;",
+		"			totalSpecularLight += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;",
 
 
 		"		}",
 		"		}",
 
 
@@ -247,9 +248,6 @@ THREE.NormalDisplacementShader = {
 
 
 		"	#if MAX_SPOT_LIGHTS > 0",
 		"	#if MAX_SPOT_LIGHTS > 0",
 
 
-		"		vec3 spotDiffuse = vec3( 0.0 );",
-		"		vec3 spotSpecular = vec3( 0.0 );",
-
 		"		for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
 		"		for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
 
 
 		"			vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
 		"			vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
@@ -282,7 +280,7 @@ THREE.NormalDisplacementShader = {
 
 
 		"				#endif",
 		"				#endif",
 
 
-		"				spotDiffuse += spotDistance * spotLightColor[ i ] * diffuse * spotDiffuseWeight * spotEffect;",
+		"				totalDiffuseLight += spotDistance * spotLightColor[ i ] * spotDiffuseWeight * spotEffect;",
 
 
 						// specular
 						// specular
 
 
@@ -293,7 +291,7 @@ THREE.NormalDisplacementShader = {
 		"				float specularNormalization = ( shininess + 2.0 ) / 8.0;",
 		"				float specularNormalization = ( shininess + 2.0 ) / 8.0;",
 
 
 		"				vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( spotVector, spotHalfVector ), 0.0 ), 5.0 );",
 		"				vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( spotVector, spotHalfVector ), 0.0 ), 5.0 );",
-		"				spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * spotDistance * specularNormalization * spotEffect;",
+		"				totalSpecularLight += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * spotDistance * specularNormalization * spotEffect;",
 
 
 		"			}",
 		"			}",
 
 
@@ -305,9 +303,6 @@ THREE.NormalDisplacementShader = {
 
 
 		"	#if MAX_DIR_LIGHTS > 0",
 		"	#if MAX_DIR_LIGHTS > 0",
 
 
-		"		vec3 dirDiffuse = vec3( 0.0 );",
-		"		vec3 dirSpecular = vec3( 0.0 );",
-
 		"		for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 		"		for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
 
 
 		"			vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
 		"			vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
@@ -328,7 +323,7 @@ THREE.NormalDisplacementShader = {
 
 
 		"			#endif",
 		"			#endif",
 
 
-		"			dirDiffuse += directionalLightColor[ i ] * diffuse * dirDiffuseWeight;",
+		"			totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;",
 
 
 					// specular
 					// specular
 
 
@@ -339,7 +334,7 @@ THREE.NormalDisplacementShader = {
 		"			float specularNormalization = ( shininess + 2.0 ) / 8.0;",
 		"			float specularNormalization = ( shininess + 2.0 ) / 8.0;",
 
 
 		"			vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );",
 		"			vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );",
-		"			dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
+		"			totalSpecularLight += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
 
 
 		"		}",
 		"		}",
 
 
@@ -349,9 +344,6 @@ THREE.NormalDisplacementShader = {
 
 
 		"	#if MAX_HEMI_LIGHTS > 0",
 		"	#if MAX_HEMI_LIGHTS > 0",
 
 
-		"		vec3 hemiDiffuse = vec3( 0.0 );",
-		"		vec3 hemiSpecular = vec3( 0.0 );",
-
 		"		for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
 		"		for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
 
 
 		"			vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );",
 		"			vec4 lDirection = viewMatrix * vec4( hemisphereLightDirection[ i ], 0.0 );",
@@ -364,7 +356,7 @@ THREE.NormalDisplacementShader = {
 
 
 		"			vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
 		"			vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
 
 
-		"			hemiDiffuse += diffuse * hemiColor;",
+		"			totalDiffuseLight += hemiColor;",
 
 
 					// specular (sky light)
 					// specular (sky light)
 
 
@@ -387,52 +379,19 @@ THREE.NormalDisplacementShader = {
 
 
 		"			vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );",
 		"			vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );",
 		"			vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );",
 		"			vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );",
-		"			hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );",
+		"			totalSpecularLight += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );",
 
 
 		"		}",
 		"		}",
 
 
-		"	#endif",
-
-			// all lights contribution summation
-
-		"	vec3 totalDiffuse = vec3( 0.0 );",
-		"	vec3 totalSpecular = vec3( 0.0 );",
-
-		"	#if MAX_DIR_LIGHTS > 0",
-
-		"		totalDiffuse += dirDiffuse;",
-		"		totalSpecular += dirSpecular;",
-
-		"	#endif",
-
-		"	#if MAX_HEMI_LIGHTS > 0",
-
-		"		totalDiffuse += hemiDiffuse;",
-		"		totalSpecular += hemiSpecular;",
-
-		"	#endif",
-
-		"	#if MAX_POINT_LIGHTS > 0",
-
-		"		totalDiffuse += pointDiffuse;",
-		"		totalSpecular += pointSpecular;",
-
-		"	#endif",
-
-		"	#if MAX_SPOT_LIGHTS > 0",
-
-		"		totalDiffuse += spotDiffuse;",
-		"		totalSpecular += spotSpecular;",
-
 		"	#endif",
 		"	#endif",
 
 
 		"	#ifdef METAL",
 		"	#ifdef METAL",
 
 
-		"		gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * diffuse + totalSpecular );",
+		"		outgoingLight += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor + totalSpecularLight );",
 
 
 		"	#else",
 		"	#else",
 
 
-		"		gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * diffuse ) + totalSpecular;",
+		"		outgoingLight += diffuseColor.xyz * ( totalDiffuseLight + ambientLightColor ) + totalSpecularLight;",
 
 
 		"	#endif",
 		"	#endif",
 
 
@@ -440,13 +399,15 @@ THREE.NormalDisplacementShader = {
 
 
 		"		vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
 		"		vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
 
 
+		"		vec3 worldNormal = inverseTransformDirection( normal, viewMatrix );",
+
 		"		#ifdef ENVMAP_MODE_REFLECTION",
 		"		#ifdef ENVMAP_MODE_REFLECTION",
 
 
-		"			vec3 vReflect = reflect( cameraToVertex, normal );",
+		"			vec3 vReflect = reflect( cameraToVertex, worldNormal );",
 
 
 		"		#else",
 		"		#else",
 
 
-		"			vec3 vReflect = refract( cameraToVertex, normal, refractionRatio );",
+		"			vec3 vReflect = refract( cameraToVertex, worldNormal, refractionRatio );",
 
 
 		"		#endif",
 		"		#endif",
 
 
@@ -458,7 +419,7 @@ THREE.NormalDisplacementShader = {
 
 
 		"		#endif",
 		"		#endif",
 
 
-		"		gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * reflectivity );",
+		"		outgoingLight = mix( outgoingLight, cubeColor.xyz, specularTex.r * reflectivity );",
 
 
 		"	}",
 		"	}",
 
 
@@ -466,6 +427,8 @@ THREE.NormalDisplacementShader = {
 			THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
 			THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
 			THREE.ShaderChunk[ "fog_fragment" ],
 			THREE.ShaderChunk[ "fog_fragment" ],
 
 
+		"	gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
 		"}"
 		"}"
 
 
 	].join("\n"),
 	].join("\n"),

+ 6 - 5
examples/misc_fps.html

@@ -163,7 +163,7 @@
 								var actualHeight = hits[0].distance - birdsEye;
 								var actualHeight = hits[0].distance - birdsEye;
 
 
 								// collision: stick to the surface if landing on it
 								// collision: stick to the surface if landing on it
-								
+
 								if( ( motion.velocity.y <= 0 ) && ( Math.abs( actualHeight ) < kneeDeep ) ) {
 								if( ( motion.velocity.y <= 0 ) && ( Math.abs( actualHeight ) < kneeDeep ) ) {
 									motion.position.y -= actualHeight;
 									motion.position.y -= actualHeight;
 									motion.velocity.y = 0;
 									motion.velocity.y = 0;
@@ -185,9 +185,9 @@
 							// limit the tilt at ±0.4 radians
 							// limit the tilt at ±0.4 radians
 
 
 							motion.rotation.x = Math.max( -0.4, Math.min ( +0.4, motion.rotation.x ) );
 							motion.rotation.x = Math.max( -0.4, Math.min ( +0.4, motion.rotation.x ) );
-							
+
 							// wrap horizontal rotation to 0...2π
 							// wrap horizontal rotation to 0...2π
-							
+
 							motion.rotation.y += tau; motion.rotation.y %= tau;
 							motion.rotation.y += tau; motion.rotation.y %= tau;
 
 
 							timeLeft -= dt;
 							timeLeft -= dt;
@@ -233,6 +233,7 @@
 				var placeholder = new THREE.Object3D();
 				var placeholder = new THREE.Object3D();
 
 
 				var texture = THREE.ImageUtils.loadTexture( textureUrl );
 				var texture = THREE.ImageUtils.loadTexture( textureUrl );
+				texture.minFilter = THREE.LinearFilter;
 				texture.anisotropy = textureQuality;
 				texture.anisotropy = textureQuality;
 
 
 				var loader = new THREE.JSONLoader();
 				var loader = new THREE.JSONLoader();
@@ -256,7 +257,7 @@
 			var camera = new THREE.PerspectiveCamera( 60, 1, 0.1, 9000 );
 			var camera = new THREE.PerspectiveCamera( 60, 1, 0.1, 9000 );
 
 
 			var scene = new THREE.Scene();
 			var scene = new THREE.Scene();
-			
+
 			scene.add( camera );
 			scene.add( camera );
 
 
 			scene.add( makeSkybox( [
 			scene.add( makeSkybox( [
@@ -294,7 +295,7 @@
 
 
 					// call our game loop with the time elapsed since last rendering, in ms
 					// call our game loop with the time elapsed since last rendering, in ms
 					gameLoop( timeElapsed );
 					gameLoop( timeElapsed );
-					
+
 					renderer.render( scene, camera );
 					renderer.render( scene, camera );
 					requestAnimationFrame( render );
 					requestAnimationFrame( render );
 				};
 				};

文件差异内容过多而无法显示
+ 3 - 0
examples/models/json/pressure.json


二进制
examples/textures/MaryOculus.webm


+ 1 - 0
examples/textures/MaryOculus.webm.nfo

@@ -0,0 +1 @@
+ffmpeg -i MaryOculus.mp4 -vf scale=2048:1024 -b:v 20M -threads 4 -an MaryOculus7.webm

+ 5 - 0
examples/textures/decal/LICENSE.TXT

@@ -0,0 +1,5 @@
+decal-diffuse.png
+decal-normal.jpg
+
+Licensed under a CC0 1.0 Universal (CC0 1.0) Public Domain Dedication License:
+http://creativecommons.org/publicdomain/zero/1.0/

二进制
examples/textures/decal/decal-diffuse.png


二进制
examples/textures/decal/decal-normal.jpg


+ 168 - 0
examples/vr_video.html

@@ -0,0 +1,168 @@
+<!DOCTYPE html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - vr video</title>
+		<meta charset="utf-8">
+		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+		<style>
+			body {
+				font-family: Monospace;
+				background-color: #f0f0f0;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				position: absolute;
+				top: 10px;
+				width: 100%;
+				color: #fff;
+				text-align: center;
+			}
+			a {
+				color: #ff0
+			}
+		</style>
+	</head>
+	<body>
+		<div id="container"></div>
+		<div id="info">
+			<a href="http://threejs.org" target="_blank">three.js</a> webgl - vr video<br />
+			stereoscopic panoramic render by <a href="http://pedrofe.com/rendering-for-oculus-rift-with-arnold/" target="_blank">pedrofe</a>. scene from <a href="http://www.meryproject.com/" target="_blank">mery project</a>.
+		</div>
+
+		<script src="../build/three.min.js"></script>
+		<script src="js/effects/VREffect.js"></script>
+		<script src="js/controls/VRControls.js"></script>
+
+		<script>
+
+			var camera, sceneLeft, sceneRight, renderer;
+			var video, texture;
+
+			var controls, effect;
+
+			init();
+			animate();
+
+			function init() {
+
+				var container = document.getElementById( 'container' );
+				container.addEventListener( 'click', function () {
+
+					video.play();
+					effect.setFullScreen( true );
+
+				} );
+
+				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 2000 );
+
+				// video
+
+				video = document.createElement( 'video' );
+				video.loop = true;
+				video.src = 'textures/MaryOculus.webm';
+				video.play();
+
+				texture = new THREE.VideoTexture( video );
+				texture.minFilter = THREE.LinearFilter;
+				texture.format = THREE.RGBFormat;
+				texture.generateMipmaps = false;
+
+				// left
+
+				sceneLeft = new THREE.Scene();
+
+				var geometry = new THREE.SphereGeometry( 500, 60, 40 );
+				geometry.applyMatrix( new THREE.Matrix4().makeScale( -1, 1, 1 ) );
+
+				var uvs = geometry.faceVertexUvs[ 0 ];
+
+				for ( var i = 0; i < uvs.length; i ++ ) {
+
+					for ( var j = 0; j < 3; j ++ ) {
+
+						uvs[ i ][ j ].x *= 0.5;
+
+					}
+
+				}
+
+				var material = new THREE.MeshBasicMaterial( { map: texture } );
+
+				var mesh = new THREE.Mesh( geometry, material );
+				mesh.rotation.y = - Math.PI / 2;
+				sceneLeft.add( mesh );
+
+				// right
+
+				sceneRight = new THREE.Scene();
+
+				var geometry = new THREE.SphereGeometry( 500, 60, 40 );
+				geometry.applyMatrix( new THREE.Matrix4().makeScale( -1, 1, 1 ) );
+
+				var uvs = geometry.faceVertexUvs[ 0 ];
+
+				for ( var i = 0; i < uvs.length; i ++ ) {
+
+					for ( var j = 0; j < 3; j ++ ) {
+
+						uvs[ i ][ j ].x *= 0.5;
+						uvs[ i ][ j ].x += 0.5;
+
+					}
+
+				}
+
+				var material = new THREE.MeshBasicMaterial( { map: texture } );
+
+				var mesh = new THREE.Mesh( geometry, material );
+				mesh.rotation.y = - Math.PI / 2;
+				sceneRight.add( mesh );
+
+				//
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setClearColor( 0x101010 );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				container.appendChild( renderer.domElement );
+
+				//
+
+				controls = new THREE.VRControls( camera );
+
+				effect = new THREE.VREffect( renderer );
+				effect.setSize( window.innerWidth, window.innerHeight );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				effect.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+				render();
+
+			}
+
+			function render() {
+
+				controls.update();
+
+				effect.render( [ sceneLeft, sceneRight ], camera );
+
+			}
+
+		</script>
+	</body>
+</html>

+ 1 - 1
examples/webgl_animation_skinning_morph.html

@@ -127,7 +127,7 @@
 
 
 				//
 				//
 
 
-				var light = new THREE.DirectionalLight( 0x497f13, 1 );
+				var light = new THREE.DirectionalLight( 0x493f13, 1 );
 				light.position.set( 0, -1, 0 );
 				light.position.set( 0, -1, 0 );
 				scene.add( light );
 				scene.add( light );
 
 

+ 1 - 1
examples/webgl_decals.html

@@ -53,7 +53,7 @@
 			specular: 0x444444,
 			specular: 0x444444,
 			map: decalDiffuse,
 			map: decalDiffuse,
 			normalMap: decalNormal,
 			normalMap: decalNormal,
-			normalScale: new THREE.Vector2( .15, .15 ),
+			normalScale: new THREE.Vector2( 1, 1 ),
 			shininess: 30,
 			shininess: 30,
 			transparent: true,
 			transparent: true,
 			depthTest: true,
 			depthTest: true,

+ 2 - 2
examples/webgl_effects_parallaxbarrier.html

@@ -36,7 +36,7 @@
 	<body>
 	<body>
 		<div id="d">
 		<div id="d">
 			<div id="info">
 			<div id="info">
-				<a href="http://threejs.org" target="_blank">three.js</a> webgl - effects - parallax barrier. 
+				<a href="http://threejs.org" target="_blank">three.js</a> webgl - effects - parallax barrier.
 				texture by <a href="http://www.humus.name/index.php?page=Textures" target="_blank">Humus</a> :
 				texture by <a href="http://www.humus.name/index.php?page=Textures" target="_blank">Humus</a> :
 				<span id="car_info">
 				<span id="car_info">
 					<span id="car_name">Bugatti Veyron model</span>
 					<span id="car_name">Bugatti Veyron model</span>
@@ -245,7 +245,7 @@
 				"Carmine": 	new THREE.MeshPhongMaterial( { color: 0x770000, specular:0xffaaaa, envMap: textureCube, combine: THREE.MultiplyOperation } ),
 				"Carmine": 	new THREE.MeshPhongMaterial( { color: 0x770000, specular:0xffaaaa, envMap: textureCube, combine: THREE.MultiplyOperation } ),
 				"Gold": 	new THREE.MeshPhongMaterial( { color: 0xaa9944, specular:0xbbaa99, shininess:50, envMap: textureCube, combine: THREE.MultiplyOperation } ),
 				"Gold": 	new THREE.MeshPhongMaterial( { color: 0xaa9944, specular:0xbbaa99, shininess:50, envMap: textureCube, combine: THREE.MultiplyOperation } ),
 				"Bronze":	new THREE.MeshPhongMaterial( { color: 0x150505, specular:0xee6600, shininess:10, envMap: textureCube, combine: THREE.MixOperation, reflectivity: 0.25 } ),
 				"Bronze":	new THREE.MeshPhongMaterial( { color: 0x150505, specular:0xee6600, shininess:10, envMap: textureCube, combine: THREE.MixOperation, reflectivity: 0.25 } ),
-				"Chrome": 	new THREE.MeshPhongMaterial( { color: 0xffffff, specular:0xffffff, envMap: textureCube, combine: THREE.Multiply } ),
+				"Chrome": 	new THREE.MeshPhongMaterial( { color: 0xffffff, specular:0xffffff, envMap: textureCube, combine: THREE.MultiplyOperation } ),
 
 
 				"Orange metal": new THREE.MeshLambertMaterial( { color: 0xff6600, envMap: textureCube, combine: THREE.MultiplyOperation } ),
 				"Orange metal": new THREE.MeshLambertMaterial( { color: 0xff6600, envMap: textureCube, combine: THREE.MultiplyOperation } ),
 				"Blue metal": 	new THREE.MeshLambertMaterial( { color: 0x001133, envMap: textureCube, combine: THREE.MultiplyOperation  } ),
 				"Blue metal": 	new THREE.MeshLambertMaterial( { color: 0x001133, envMap: textureCube, combine: THREE.MultiplyOperation  } ),

+ 1 - 0
examples/webgl_interactive_cubes_gpu.html

@@ -75,6 +75,7 @@
 
 
 				pickingScene = new THREE.Scene();
 				pickingScene = new THREE.Scene();
 				pickingTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
 				pickingTexture = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight );
+				pickingTexture.minFilter = THREE.LinearFilter;
 				pickingTexture.generateMipmaps = false;
 				pickingTexture.generateMipmaps = false;
 
 
 				scene.add( new THREE.AmbientLight( 0x555555 ) );
 				scene.add( new THREE.AmbientLight( 0x555555 ) );

+ 10 - 32
examples/webgl_loader_scene.html

@@ -39,15 +39,6 @@
 				display:none;
 				display:none;
 			}
 			}
 
 
-			#start {
-				color:#fff;
-				text-shadow: #000 0px 0px 2px;
-				padding:0.1em 0.3em;
-				width:3em;
-				text-align: center;
-				display:none;
-			}
-
 			.shadow {
 			.shadow {
 				-moz-box-shadow: 0px 0px 5px #000;
 				-moz-box-shadow: 0px 0px 5px #000;
 				-webkit-box-shadow: 0px 0px 5px #000;
 				-webkit-box-shadow: 0px 0px 5px #000;
@@ -97,7 +88,6 @@
 
 
 			<center>
 			<center>
 				<div id="progressbar" class="shadow"><div id="bar" class="shadow"></div></div>
 				<div id="progressbar" class="shadow"><div id="bar" class="shadow"></div></div>
-				<div id="start" class="disabled">Start</div>
 			</center>
 			</center>
 		</div>
 		</div>
 
 
@@ -186,8 +176,6 @@
 				stats.domElement.style.zIndex = 100;
 				stats.domElement.style.zIndex = 100;
 				container.appendChild( stats.domElement );
 				container.appendChild( stats.domElement );
 
 
-				$( "start" ).addEventListener( 'click', onStartClick, false );
-
 				var callbackProgress = function( progress, result ) {
 				var callbackProgress = function( progress, result ) {
 
 
 					var bar = 250,
 					var bar = 250,
@@ -207,8 +195,6 @@
 
 
 					$( "message" ).style.display = "none";
 					$( "message" ).style.display = "none";
 					$( "progressbar" ).style.display = "none";
 					$( "progressbar" ).style.display = "none";
-					$( "start" ).style.display = "block";
-					$( "start" ).className = "enabled";
 
 
 					result.scene.traverse( function ( object ) {
 					result.scene.traverse( function ( object ) {
 
 
@@ -237,6 +223,16 @@
 
 
 					} );
 					} );
 
 
+					//
+
+					$( "progress" ).style.display = "none";
+
+					camera = loaded.currentCamera;
+					camera.aspect = window.innerWidth / window.innerHeight;
+					camera.updateProjectionMatrix();
+
+					scene = loaded.scene;
+
 				}
 				}
 
 
 				$( "progress" ).style.display = "block";
 				$( "progress" ).style.display = "block";
@@ -276,24 +272,6 @@
 
 
 			}
 			}
 
 
-			function setButtonActive( id ) {
-
-				$( "start" ).style.backgroundColor = "green";
-
-			}
-
-			function onStartClick() {
-
-				$( "progress" ).style.display = "none";
-
-				camera = loaded.currentCamera;
-				camera.aspect = window.innerWidth / window.innerHeight;
-				camera.updateProjectionMatrix();
-
-				scene = loaded.scene;
-
-			}
-
 			function onDocumentMouseMove( event ) {
 			function onDocumentMouseMove( event ) {
 
 
 				mouseX = ( event.clientX - windowHalfX );
 				mouseX = ( event.clientX - windowHalfX );

+ 3 - 4
examples/webgl_materials_lightmap.html

@@ -100,14 +100,13 @@
 
 
 				// LIGHTS
 				// LIGHTS
 
 
-				var directionalLight = new THREE.DirectionalLight( 0xffffff, 1.475 );
+				var directionalLight = new THREE.DirectionalLight( 0x333333, 2 );
 				directionalLight.position.set( 100, 100, -100 );
 				directionalLight.position.set( 100, 100, -100 );
 				scene.add( directionalLight );
 				scene.add( directionalLight );
 
 
 
 
-				var hemiLight = new THREE.HemisphereLight( 0xffffff, 0xffffff, 1.25 );
-				hemiLight.color.setHSL( 0.6, 1, 0.75 );
-				hemiLight.groundColor.setHSL( 0.1, 0.8, 0.7 );
+				var hemiLight = new THREE.HemisphereLight( 0xaabbff, 0x040404, 1 );
+
 				hemiLight.position.y = 500;
 				hemiLight.position.y = 500;
 				scene.add( hemiLight );
 				scene.add( hemiLight );
 
 

+ 3 - 0
examples/webgl_materials_normaldisplacementmap.html

@@ -185,6 +185,9 @@
 				var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: false };
 				var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: false };
 				var material1 = new THREE.ShaderMaterial( parameters );
 				var material1 = new THREE.ShaderMaterial( parameters );
 
 
+				// Ensure that ENVMAP_MODE_REFLECTION is defined in shader
+				material1.envMap = reflectionCube;
+
 				var material2 = new THREE.MeshPhongMaterial( {
 				var material2 = new THREE.MeshPhongMaterial( {
 					color: diffuse,
 					color: diffuse,
 					specular: specular,
 					specular: specular,

+ 1 - 1
examples/webgl_mirror.html

@@ -86,7 +86,7 @@
 
 
 				var planeGeo = new THREE.PlaneBufferGeometry( 100.1, 100.1 );
 				var planeGeo = new THREE.PlaneBufferGeometry( 100.1, 100.1 );
 				
 				
-				// MIRORR planes
+				// MIRROR planes
 				groundMirror = new THREE.Mirror( renderer, camera, { clipBias: 0.003, textureWidth: WIDTH, textureHeight: HEIGHT, color: 0x777777 } );
 				groundMirror = new THREE.Mirror( renderer, camera, { clipBias: 0.003, textureWidth: WIDTH, textureHeight: HEIGHT, color: 0x777777 } );
 				
 				
 				var mirrorMesh = new THREE.Mesh( planeGeo, groundMirror.material );
 				var mirrorMesh = new THREE.Mesh( planeGeo, groundMirror.material );

+ 13 - 24
examples/webgl_shaders_sky.html

@@ -20,8 +20,8 @@
 			}
 			}
 
 
 			#info {
 			#info {
-				color:#333;
-				text-shadow: 1px 1px #fff;
+				color:#ccc;
+				text-shadow: 1px 1px rgba(0,0,0,0.25);
 				position: absolute;
 				position: absolute;
 				top: 0px; width: 100%;
 				top: 0px; width: 100%;
 				padding: 5px;
 				padding: 5px;
@@ -29,7 +29,7 @@
 			}
 			}
 
 
 			a {
 			a {
-				color: #333;
+				color: #fff;
 			}
 			}
 
 
 		</style>
 		</style>
@@ -90,7 +90,7 @@
 					mieDirectionalG: 0.8,
 					mieDirectionalG: 0.8,
 					luminance: 1,
 					luminance: 1,
 					inclination: 0.49, // elevation / inclination
 					inclination: 0.49, // elevation / inclination
-					azimuth: 0.25, // Facing front,					
+					azimuth: 0.25, // Facing front,
 					sun: !true
 					sun: !true
 				}
 				}
 
 
@@ -108,8 +108,8 @@
 					var phi = 2 * Math.PI * (effectController.azimuth - 0.5);
 					var phi = 2 * Math.PI * (effectController.azimuth - 0.5);
 
 
 					sunSphere.position.x = distance * Math.cos(phi);
 					sunSphere.position.x = distance * Math.cos(phi);
-					sunSphere.position.y = distance * Math.sin(phi) * Math.sin(theta); 
-					sunSphere.position.z = distance * Math.sin(phi) * Math.cos(theta); 
+					sunSphere.position.y = distance * Math.sin(phi) * Math.sin(theta);
+					sunSphere.position.z = distance * Math.sin(phi) * Math.cos(theta);
 
 
 					sunSphere.visible = effectController.sun;
 					sunSphere.visible = effectController.sun;
 
 
@@ -129,14 +129,14 @@
 				gui.add( effectController, "inclination", 0, 1, 0.0001).onChange( guiChanged );
 				gui.add( effectController, "inclination", 0, 1, 0.0001).onChange( guiChanged );
 				gui.add( effectController, "azimuth", 0, 1, 0.0001).onChange( guiChanged );
 				gui.add( effectController, "azimuth", 0, 1, 0.0001).onChange( guiChanged );
 				gui.add( effectController, "sun").onChange( guiChanged );
 				gui.add( effectController, "sun").onChange( guiChanged );
-				
+
 
 
 				guiChanged();
 				guiChanged();
 
 
 
 
 				camera.lookAt(sunSphere.position)
 				camera.lookAt(sunSphere.position)
 
 
-	
+
 			}
 			}
 
 
 
 
@@ -150,21 +150,10 @@
 
 
 				scene = new THREE.Scene();
 				scene = new THREE.Scene();
 
 
-				var size = 500;
-
-				var geometryLines = new THREE.BoxGeometry( size, size, size );
-	
-				var geometryPlane = new THREE.PlaneGeometry( size * 10, size * 10, 1, 1);
-				geometryPlane.applyMatrix( new THREE.Matrix4().makeRotationX( - Math.PI / 2 ) );
-	
-
-				var materialLines = new THREE.MeshBasicMaterial( { wireframe: true } );
-
-				meshLines = new THREE.Mesh( geometryLines, materialLines );
-
-				// scene.add( meshLines );
-
-				scene.add( new THREE.Mesh( geometryPlane, materialLines ) );
+				var helper = new THREE.GridHelper( 5000, 5000 );
+				helper.color1.setHex( 0xffffff );
+				helper.color2.setHex( 0xffffff );
+				scene.add( helper );
 
 
 				initSky();
 				initSky();
 
 
@@ -206,7 +195,7 @@
 				time = Date.now();
 				time = Date.now();
 
 
 				requestAnimationFrame( animate );
 				requestAnimationFrame( animate );
-				
+
 				controls.update();
 				controls.update();
 
 
 				render();
 				render();

+ 30 - 16
examples/webgl_shaders_tonemapping.html

@@ -85,12 +85,15 @@
 			function init() {
 			function init() {
 
 
 				params = {
 				params = {
-					"Average Luminosity": 0.7,
+					bloomAmount: 1.0,
+					sunLight: 4.0,
+
+					enabled: true,
+					avgLuminance: 0.7,
 					middleGrey: 0.04,
 					middleGrey: 0.04,
 					maxLuminance: 16,
 					maxLuminance: 16,
-					bloomAmount: 1.0,
+
 					adaptionRate: 2.0,
 					adaptionRate: 2.0,
-					sunLight: 4.0,
 				};
 				};
 
 
 				container = document.createElement( 'div' );
 				container = document.createElement( 'div' );
@@ -395,22 +398,24 @@
 				// ldrEffectComposer.addPass( gammaPass );
 				// ldrEffectComposer.addPass( gammaPass );
 
 
 
 
-				var dynamicHdrGui = new dat.GUI();
+				var gui = new dat.GUI();
 
 
 				// dynamicHdrGui.add( params, 'projection', { 'From cam to mesh': 'camera', 'Normal to mesh': 'normal' } );
 				// dynamicHdrGui.add( params, 'projection', { 'From cam to mesh': 'camera', 'Normal to mesh': 'normal' } );
-				dynamicHdrGui.add( params, 'middleGrey', 0, 12 );
-				dynamicHdrGui.add( params, 'maxLuminance', 1, 30 );
-				dynamicHdrGui.add( params, 'adaptionRate', 0.0, 10.0 );
-				dynamicHdrGui.add( params, 'bloomAmount', 0.0, 10.0 );
-				dynamicHdrGui.add( params, 'sunLight', 0.1, 12.0 );
-				// dynamicHdrGui.add( params, 'clear' );
-				dynamicHdrGui.open();
+				var sceneGui = gui.addFolder( 'Scenes' );
+				var toneMappingGui = gui.addFolder( 'ToneMapping' );
+				var adaptiveToneMappingGui = gui.addFolder( 'AdaptiveOnly' );
+
+				sceneGui.add( params, 'bloomAmount', 0.0, 10.0 );
+				sceneGui.add( params, 'sunLight', 0.1, 12.0 );
+
+				toneMappingGui.add( params, 'enabled' );
+				toneMappingGui.add( params, 'middleGrey', 0, 12 );
+				toneMappingGui.add( params, 'avgLuminance', 0.001, 2.0 );
+				toneMappingGui.add( params, 'maxLuminance', 1, 30 );
 
 
-				var ldrGui = new dat.GUI();
-				ldrGui.domElement.style.position = 'absolute';
-				ldrGui.add( params, 'Average Luminosity', 0.001, 2.0 );
-				ldrGui.open();
+				adaptiveToneMappingGui.add( params, 'adaptionRate', 0.0, 10.0 );
 
 
+				gui.open();
 
 
 				window.addEventListener( 'resize', onWindowResize, false );
 				window.addEventListener( 'resize', onWindowResize, false );
 
 
@@ -445,10 +450,19 @@
 					adaptiveLuminanceMat.uniforms.map.value = adaptToneMappingPass.luminanceRT;
 					adaptiveLuminanceMat.uniforms.map.value = adaptToneMappingPass.luminanceRT;
 					currentLuminanceMat.uniforms.map.value = adaptToneMappingPass.currentLuminanceRT;
 					currentLuminanceMat.uniforms.map.value = adaptToneMappingPass.currentLuminanceRT;
 					if ( adaptToneMappingPass.setAverageLuminance ) {
 					if ( adaptToneMappingPass.setAverageLuminance ) {
-						adaptToneMappingPass.setAverageLuminance( params["Average Luminosity"] );
+						adaptToneMappingPass.setAverageLuminance( params.avgLuminance );
 					}
 					}
+					adaptToneMappingPass.enabled = params.enabled;
 					adaptToneMappingPass.setMaxLuminance( params.maxLuminance );
 					adaptToneMappingPass.setMaxLuminance( params.maxLuminance );
 					adaptToneMappingPass.setMiddleGrey( params.middleGrey );
 					adaptToneMappingPass.setMiddleGrey( params.middleGrey );
+
+					hdrToneMappingPass.enabled = params.enabled;
+					hdrToneMappingPass.setMaxLuminance( params.maxLuminance );
+					hdrToneMappingPass.setMiddleGrey( params.middleGrey );
+				
+					ldrToneMappingPass.enabled = params.enabled;
+					ldrToneMappingPass.setMaxLuminance( params.maxLuminance );
+					ldrToneMappingPass.setMiddleGrey( params.middleGrey );
 				}
 				}
 
 
 				directionalLight.intensity = params.sunLight;
 				directionalLight.intensity = params.sunLight;

+ 1 - 1
examples/webgl_terrain_dynamic.html

@@ -606,7 +606,7 @@
 
 
 				var sceneTmp = new THREE.Scene();
 				var sceneTmp = new THREE.Scene();
 
 
-				var meshTmp = new THREE.Mesh( new THREE.PlaneGeometry( SCREEN_WIDTH, SCREEN_HEIGHT ), shaderMaterial );
+				var meshTmp = new THREE.Mesh( new THREE.PlaneBufferGeometry( SCREEN_WIDTH, SCREEN_HEIGHT ), shaderMaterial );
 				meshTmp.position.z = -500;
 				meshTmp.position.z = -500;
 
 
 				sceneTmp.add( meshTmp );
 				sceneTmp.add( meshTmp );

+ 2 - 2
src/Three.js

@@ -2,7 +2,7 @@
  * @author mrdoob / http://mrdoob.com/
  * @author mrdoob / http://mrdoob.com/
  */
  */
 
 
-var THREE = { REVISION: '71dev' };
+var THREE = { REVISION: '72dev' };
 
 
 // browserify support
 // browserify support
 
 
@@ -16,7 +16,7 @@ if ( typeof module === 'object' ) {
 
 
 if ( Math.sign === undefined ) {
 if ( Math.sign === undefined ) {
 
 
-	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign 
+	// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sign
 
 
 	Math.sign = function ( x ) {
 	Math.sign = function ( x ) {
 
 

+ 17 - 16
src/core/BufferGeometry.js

@@ -84,13 +84,13 @@ THREE.BufferGeometry.prototype = {
 
 
 		}
 		}
 
 
-		if ( this.boundingBox instanceof THREE.Box3 ) {
+		if ( this.boundingBox !== null ) {
 
 
 			this.computeBoundingBox();
 			this.computeBoundingBox();
 
 
 		}
 		}
 
 
-		if ( this.boundingSphere instanceof THREE.Sphere ) {
+		if ( this.boundingSphere !== null ) {
 
 
 			this.computeBoundingSphere();
 			this.computeBoundingSphere();
 
 
@@ -100,7 +100,13 @@ THREE.BufferGeometry.prototype = {
 
 
 	center: function () {
 	center: function () {
 
 
-		// TODO
+		this.computeBoundingBox();
+
+		var offset = this.boundingBox.center().negate();
+
+		this.applyMatrix( new THREE.Matrix4().setPosition( offset ) );
+
+		return offset;
 
 
 	},
 	},
 
 
@@ -661,24 +667,18 @@ THREE.BufferGeometry.prototype = {
 	},
 	},
 
 
 	/*
 	/*
-		computeOffsets
-		Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices.
-		This method will effectively rewrite the index buffer and remap all attributes to match the new indices.
-		WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets.
-		indexBufferSize - Defaults to 65535, but allows for larger or smaller chunks.
+	Compute the draw offset for large models by chunking the index buffer into chunks of 65k addressable vertices.
+	This method will effectively rewrite the index buffer and remap all attributes to match the new indices.
+	WARNING: This method will also expand the vertex count to prevent sprawled triangles across draw offsets.
+	size - Defaults to 65535, but allows for larger or smaller chunks.
 	*/
 	*/
-	computeOffsets: function ( indexBufferSize ) {
-
-		var size = indexBufferSize;
-		if ( indexBufferSize === undefined )
-			size = 65535; //WebGL limits type of index buffer values to 16-bit.
+	computeOffsets: function ( size ) {
 
 
-		var s = Date.now();
+		if ( size === undefined ) size = 65535; // WebGL limits type of index buffer values to 16-bit.
 
 
 		var indices = this.attributes.index.array;
 		var indices = this.attributes.index.array;
 		var vertices = this.attributes.position.array;
 		var vertices = this.attributes.position.array;
 
 
-		var verticesCount = ( vertices.length / 3 );
 		var facesCount = ( indices.length / 3 );
 		var facesCount = ( indices.length / 3 );
 
 
 		/*
 		/*
@@ -758,7 +758,8 @@ THREE.BufferGeometry.prototype = {
 
 
 		/* Move all attribute values to map to the new computed indices , also expand the vertice stack to match our new vertexPtr. */
 		/* Move all attribute values to map to the new computed indices , also expand the vertice stack to match our new vertexPtr. */
 		this.reorderBuffers( sortedIndices, revVertexMap, vertexPtr );
 		this.reorderBuffers( sortedIndices, revVertexMap, vertexPtr );
-		this.offsets = offsets;
+		this.offsets = offsets; // TODO: Deprecate
+		this.drawcalls = offsets;
 
 
 		/*
 		/*
 		var orderTime = Date.now();
 		var orderTime = Date.now();

+ 38 - 16
src/core/Geometry.js

@@ -81,18 +81,21 @@ THREE.Geometry.prototype = {
 
 
 		}
 		}
 
 
-		if ( this.boundingBox instanceof THREE.Box3 ) {
+		if ( this.boundingBox !== null ) {
 
 
 			this.computeBoundingBox();
 			this.computeBoundingBox();
 
 
 		}
 		}
 
 
-		if ( this.boundingSphere instanceof THREE.Sphere ) {
+		if ( this.boundingSphere !== null ) {
 
 
 			this.computeBoundingSphere();
 			this.computeBoundingSphere();
 
 
 		}
 		}
 
 
+		this.verticesNeedUpdate = true;
+		this.normalsNeedUpdate = true;
+
 	},
 	},
 
 
 	fromBufferGeometry: function ( geometry ) {
 	fromBufferGeometry: function ( geometry ) {
@@ -151,9 +154,33 @@ THREE.Geometry.prototype = {
 
 
 		if ( indices !== undefined ) {
 		if ( indices !== undefined ) {
 
 
-			for ( var i = 0; i < indices.length; i += 3 ) {
+			var drawcalls = geometry.drawcalls;
+
+			if ( drawcalls.length > 0 ) {
+
+				for ( var i = 0; i < drawcalls.length; i ++ ) {
+
+					var drawcall = drawcalls[ i ];
+
+					var start = drawcall.start;
+					var count = drawcall.count;
+					var index = drawcall.index;
 
 
-				addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
+					for ( var j = start, jl = start + count; j < jl; j += 3 ) {
+
+						addFace( index + indices[ j ], index + indices[ j + 1 ], index + indices[ j + 2 ] );
+
+					}
+
+				}
+
+			} else {
+
+				for ( var i = 0; i < indices.length; i += 3 ) {
+
+					addFace( indices[ i ], indices[ i + 1 ], indices[ i + 2 ] );
+
+				}
 
 
 			}
 			}
 
 
@@ -189,13 +216,9 @@ THREE.Geometry.prototype = {
 
 
 		this.computeBoundingBox();
 		this.computeBoundingBox();
 
 
-		var offset = new THREE.Vector3();
+		var offset = this.boundingBox.center().negate();
 
 
-		offset.addVectors( this.boundingBox.min, this.boundingBox.max );
-		offset.multiplyScalar( - 0.5 );
-
-		this.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
-		this.computeBoundingBox();
+		this.applyMatrix( new THREE.Matrix4().setPosition( offset ) );
 
 
 		return offset;
 		return offset;
 
 
@@ -242,9 +265,8 @@ THREE.Geometry.prototype = {
 			// vertex normals weighted by triangle areas
 			// vertex normals weighted by triangle areas
 			// http://www.iquilezles.org/www/articles/normals/normals.htm
 			// http://www.iquilezles.org/www/articles/normals/normals.htm
 
 
-			var vA, vB, vC, vD;
-			var cb = new THREE.Vector3(), ab = new THREE.Vector3(),
-				db = new THREE.Vector3(), dc = new THREE.Vector3(), bc = new THREE.Vector3();
+			var vA, vB, vC;
+			var cb = new THREE.Vector3(), ab = new THREE.Vector3();
 
 
 			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
 			for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
 
 
@@ -418,7 +440,7 @@ THREE.Geometry.prototype = {
 		// based on http://www.terathon.com/code/tangent.html
 		// based on http://www.terathon.com/code/tangent.html
 		// tangents go to vertices
 		// tangents go to vertices
 
 
-		var f, fl, v, vl, i, il, vertexIndex,
+		var f, fl, v, vl, i, vertexIndex,
 			face, uv, vA, vB, vC, uvA, uvB, uvC,
 			face, uv, vA, vB, vC, uvA, uvB, uvC,
 			x1, x2, y1, y2, z1, z2,
 			x1, x2, y1, y2, z1, z2,
 			s1, s2, t1, t2, r, t, test,
 			s1, s2, t1, t2, r, t, test,
@@ -700,8 +722,8 @@ THREE.Geometry.prototype = {
 		var v, key;
 		var v, key;
 		var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
 		var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
 		var precision = Math.pow( 10, precisionPoints );
 		var precision = Math.pow( 10, precisionPoints );
-		var i,il, face;
-		var indices, k, j, jl, u;
+		var i, il, face;
+		var indices, j, jl;
 
 
 		for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
 		for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
 
 

+ 1 - 3
src/core/Object3D.js

@@ -19,8 +19,6 @@ THREE.Object3D = function () {
 
 
 	this.up = THREE.Object3D.DefaultUp.clone();
 	this.up = THREE.Object3D.DefaultUp.clone();
 
 
-	var scope = this;
-
 	var position = new THREE.Vector3();
 	var position = new THREE.Vector3();
 	var rotation = new THREE.Euler();
 	var rotation = new THREE.Euler();
 	var quaternion = new THREE.Quaternion();
 	var quaternion = new THREE.Quaternion();
@@ -53,7 +51,7 @@ THREE.Object3D = function () {
 		scale: {
 		scale: {
 			enumerable: true,
 			enumerable: true,
 			value: scale
 			value: scale
-		},
+		}
 	} );
 	} );
 
 
 	this.rotationAutoUpdate = true;
 	this.rotationAutoUpdate = true;

+ 6 - 8
src/extras/FontUtils.js

@@ -56,7 +56,7 @@ THREE.FontUtils = {
 		ThreeFont.faces[ family ][ data.cssFontWeight ] = ThreeFont.faces[ family ][ data.cssFontWeight ] || {};
 		ThreeFont.faces[ family ][ data.cssFontWeight ] = ThreeFont.faces[ family ][ data.cssFontWeight ] || {};
 		ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
 		ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
 
 
-		var face = ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
+		ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
 
 
 		return data;
 		return data;
 
 
@@ -64,11 +64,9 @@ THREE.FontUtils = {
 
 
 	drawText: function ( text ) {
 	drawText: function ( text ) {
 
 
-		var characterPts = [], allPts = [];
-
 		// RenderText
 		// RenderText
 
 
-		var i, p,
+		var i,
 			face = this.getFace(),
 			face = this.getFace(),
 			scale = this.size / face.resolution,
 			scale = this.size / face.resolution,
 			offset = 0,
 			offset = 0,
@@ -180,8 +178,8 @@ THREE.FontUtils = {
 						for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
 						for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
 
 
 							var t = i2 / divisions;
 							var t = i2 / divisions;
-							var tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
-							var ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
+							THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
+							THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
 						}
 						}
 
 
 					}
 					}
@@ -211,8 +209,8 @@ THREE.FontUtils = {
 						for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
 						for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
 
 
 							var t = i2 / divisions;
 							var t = i2 / divisions;
-							var tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
-							var ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
+							THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
+							THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
 
 
 						}
 						}
 
 

+ 223 - 220
src/extras/animation/Animation.js

@@ -21,383 +21,386 @@ THREE.Animation = function ( root, data ) {
 
 
 };
 };
 
 
+THREE.Animation.prototype = {
 
 
-THREE.Animation.prototype.keyTypes = [ "pos", "rot", "scl" ];
+	constructor: THREE.Animation,
 
 
+	keyTypes:  [ "pos", "rot", "scl" ],
 
 
-THREE.Animation.prototype.play = function ( startTime, weight ) {
+	play: function ( startTime, weight ) {
 
 
-	this.currentTime = startTime !== undefined ? startTime : 0;
-	this.weight = weight !== undefined ? weight : 1;
+		this.currentTime = startTime !== undefined ? startTime : 0;
+		this.weight = weight !== undefined ? weight : 1;
 
 
-	this.isPlaying = true;
+		this.isPlaying = true;
 
 
-	this.reset();
+		this.reset();
 
 
-	THREE.AnimationHandler.play( this );
+		THREE.AnimationHandler.play( this );
 
 
-};
+	},
 
 
+	stop: function() {
 
 
-THREE.Animation.prototype.stop = function() {
+		this.isPlaying = false;
 
 
-	this.isPlaying = false;
+		THREE.AnimationHandler.stop( this );
 
 
-	THREE.AnimationHandler.stop( this );
+	},
 
 
-};
+	reset: function () {
 
 
-THREE.Animation.prototype.reset = function () {
+		for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
 
 
-	for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
+			var object = this.hierarchy[ h ];
 
 
-		var object = this.hierarchy[ h ];
+			if ( object.animationCache === undefined ) {
 
 
-		if ( object.animationCache === undefined ) {
+				object.animationCache = {
+					animations: {},
+					blending: {
+						positionWeight: 0.0,
+						quaternionWeight: 0.0,
+						scaleWeight: 0.0
+					}
+				};
+			}
 
 
-			object.animationCache = {
-				animations: {},
-				blending: {
-					positionWeight: 0.0,
-					quaternionWeight: 0.0,
-					scaleWeight: 0.0
-				}
-			};
-		}
+			var name = this.data.name;
+			var animations = object.animationCache.animations;
+			var animationCache = animations[ name ];
 
 
-		if ( object.animationCache.animations[this.data.name] === undefined ) {
+			if ( animationCache === undefined ) {
 
 
-			object.animationCache.animations[this.data.name] = {};
-			object.animationCache.animations[this.data.name].prevKey = { pos: 0, rot: 0, scl: 0 };
-			object.animationCache.animations[this.data.name].nextKey = { pos: 0, rot: 0, scl: 0 };
-			object.animationCache.animations[this.data.name].originalMatrix = object.matrix;
+				animationCache = {
+					prevKey: { pos: 0, rot: 0, scl: 0 },
+					nextKey: { pos: 0, rot: 0, scl: 0 },
+					originalMatrix: object.matrix
+				};
 
 
-		}
+				animations[ name ] = animationCache;
 
 
-		var animationCache = object.animationCache.animations[this.data.name];
+			}
 
 
-		// Get keys to match our current time
+			// Get keys to match our current time
 
 
-		for ( var t = 0; t < 3; t ++ ) {
+			for ( var t = 0; t < 3; t ++ ) {
 
 
-			var type = this.keyTypes[ t ];
+				var type = this.keyTypes[ t ];
 
 
-			var prevKey = this.data.hierarchy[ h ].keys[ 0 ];
-			var nextKey = this.getNextKeyWith( type, h, 1 );
+				var prevKey = this.data.hierarchy[ h ].keys[ 0 ];
+				var nextKey = this.getNextKeyWith( type, h, 1 );
 
 
-			while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
+				while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
 
 
-				prevKey = nextKey;
-				nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
+					prevKey = nextKey;
+					nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
 
 
-			}
+				}
+
+				animationCache.prevKey[ type ] = prevKey;
+				animationCache.nextKey[ type ] = nextKey;
 
 
-			animationCache.prevKey[ type ] = prevKey;
-			animationCache.nextKey[ type ] = nextKey;
+			}
 
 
 		}
 		}
 
 
-	}
+	},
 
 
-};
+	resetBlendWeights: function () {
+
+		for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
 
 
-THREE.Animation.prototype.resetBlendWeights = function () {
+			var object = this.hierarchy[ h ];
+			var animationCache = object.animationCache;
 
 
-	for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
+			if ( animationCache !== undefined ) {
 
 
-		var object = this.hierarchy[ h ];
+				var blending = animationCache.blending;
 
 
-		if ( object.animationCache !== undefined ) {
+				blending.positionWeight = 0.0;
+				blending.quaternionWeight = 0.0;
+				blending.scaleWeight = 0.0;
 
 
-			object.animationCache.blending.positionWeight = 0.0;
-			object.animationCache.blending.quaternionWeight = 0.0;
-			object.animationCache.blending.scaleWeight = 0.0;
+			}
 
 
 		}
 		}
 
 
-	}
+	},
 
 
-};
+	update: ( function() {
 
 
-THREE.Animation.prototype.update = (function() {
+		var points = [];
+		var target = new THREE.Vector3();
+		var newVector = new THREE.Vector3();
+		var newQuat = new THREE.Quaternion();
 
 
-	var points = [];
-	var target = new THREE.Vector3();
-	var newVector = new THREE.Vector3();
-	var newQuat = new THREE.Quaternion();
+		// Catmull-Rom spline
 
 
-	// Catmull-Rom spline
+		var interpolateCatmullRom = function ( points, scale ) {
 
 
-	var interpolateCatmullRom = function ( points, scale ) {
+			var c = [], v3 = [],
+			point, intPoint, weight, w2, w3,
+			pa, pb, pc, pd;
 
 
-		var c = [], v3 = [],
-		point, intPoint, weight, w2, w3,
-		pa, pb, pc, pd;
+			point = ( points.length - 1 ) * scale;
+			intPoint = Math.floor( point );
+			weight = point - intPoint;
 
 
-		point = ( points.length - 1 ) * scale;
-		intPoint = Math.floor( point );
-		weight = point - intPoint;
+			c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
+			c[ 1 ] = intPoint;
+			c[ 2 ] = intPoint > points.length - 2 ? intPoint : intPoint + 1;
+			c[ 3 ] = intPoint > points.length - 3 ? intPoint : intPoint + 2;
 
 
-		c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
-		c[ 1 ] = intPoint;
-		c[ 2 ] = intPoint > points.length - 2 ? intPoint : intPoint + 1;
-		c[ 3 ] = intPoint > points.length - 3 ? intPoint : intPoint + 2;
+			pa = points[ c[ 0 ] ];
+			pb = points[ c[ 1 ] ];
+			pc = points[ c[ 2 ] ];
+			pd = points[ c[ 3 ] ];
 
 
-		pa = points[ c[ 0 ] ];
-		pb = points[ c[ 1 ] ];
-		pc = points[ c[ 2 ] ];
-		pd = points[ c[ 3 ] ];
+			w2 = weight * weight;
+			w3 = weight * w2;
 
 
-		w2 = weight * weight;
-		w3 = weight * w2;
+			v3[ 0 ] = interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 );
+			v3[ 1 ] = interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 );
+			v3[ 2 ] = interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 );
 
 
-		v3[ 0 ] = interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 );
-		v3[ 1 ] = interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 );
-		v3[ 2 ] = interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 );
+			return v3;
 
 
-		return v3;
+		};
 
 
-	};
+		var interpolate = function ( p0, p1, p2, p3, t, t2, t3 ) {
 
 
-	var interpolate = function ( p0, p1, p2, p3, t, t2, t3 ) {
+			var v0 = ( p2 - p0 ) * 0.5,
+				v1 = ( p3 - p1 ) * 0.5;
 
 
-		var v0 = ( p2 - p0 ) * 0.5,
-			v1 = ( p3 - p1 ) * 0.5;
+			return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
 
 
-		return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
+		};
 
 
-	};
+		return function ( delta ) {
 
 
-	return function ( delta ) {
+			if ( this.isPlaying === false ) return;
 
 
-		if ( this.isPlaying === false ) return;
+			this.currentTime += delta * this.timeScale;
 
 
-		this.currentTime += delta * this.timeScale;
+			if ( this.weight === 0 )
+				return;
 
 
-		if ( this.weight === 0 )
-			return;
+			//
 
 
-		//
+			var duration = this.data.length;
 
 
-		var duration = this.data.length;
+			if ( this.currentTime > duration || this.currentTime < 0 ) {
 
 
-		if ( this.currentTime > duration || this.currentTime < 0 ) {
+				if ( this.loop ) {
 
 
-			if ( this.loop ) {
+					this.currentTime %= duration;
 
 
-				this.currentTime %= duration;
+					if ( this.currentTime < 0 )
+						this.currentTime += duration;
 
 
-				if ( this.currentTime < 0 )
-					this.currentTime += duration;
+					this.reset();
 
 
-				this.reset();
+				} else {
 
 
-			} else {
+					this.stop();
 
 
-				this.stop();
+				}
 
 
 			}
 			}
 
 
-		}
+			for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
 
 
-		for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
+				var object = this.hierarchy[ h ];
+				var animationCache = object.animationCache.animations[this.data.name];
+				var blending = object.animationCache.blending;
 
 
-			var object = this.hierarchy[ h ];
-			var animationCache = object.animationCache.animations[this.data.name];
-			var blending = object.animationCache.blending;
+				// loop through pos/rot/scl
 
 
-			// loop through pos/rot/scl
+				for ( var t = 0; t < 3; t ++ ) {
 
 
-			for ( var t = 0; t < 3; t ++ ) {
+					// get keys
 
 
-				// get keys
+					var type    = this.keyTypes[ t ];
+					var prevKey = animationCache.prevKey[ type ];
+					var nextKey = animationCache.nextKey[ type ];
 
 
-				var type    = this.keyTypes[ t ];
-				var prevKey = animationCache.prevKey[ type ];
-				var nextKey = animationCache.nextKey[ type ];
+					if ( ( this.timeScale > 0 && nextKey.time <= this.currentTime ) ||
+						( this.timeScale < 0 && prevKey.time >= this.currentTime ) ) {
 
 
-				if ( ( this.timeScale > 0 && nextKey.time <= this.currentTime ) ||
-					( this.timeScale < 0 && prevKey.time >= this.currentTime ) ) {
+						prevKey = this.data.hierarchy[ h ].keys[ 0 ];
+						nextKey = this.getNextKeyWith( type, h, 1 );
 
 
-					prevKey = this.data.hierarchy[ h ].keys[ 0 ];
-					nextKey = this.getNextKeyWith( type, h, 1 );
+						while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
 
 
-					while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
+							prevKey = nextKey;
+							nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
 
 
-						prevKey = nextKey;
-						nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
+						}
+
+						animationCache.prevKey[ type ] = prevKey;
+						animationCache.nextKey[ type ] = nextKey;
 
 
 					}
 					}
 
 
-					animationCache.prevKey[ type ] = prevKey;
-					animationCache.nextKey[ type ] = nextKey;
+					var scale = ( this.currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
 
 
-				}
+					var prevXYZ = prevKey[ type ];
+					var nextXYZ = nextKey[ type ];
 
 
-				var scale = ( this.currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
+					if ( scale < 0 ) scale = 0;
+					if ( scale > 1 ) scale = 1;
 
 
-				var prevXYZ = prevKey[ type ];
-				var nextXYZ = nextKey[ type ];
+					// interpolate
 
 
-				if ( scale < 0 ) scale = 0;
-				if ( scale > 1 ) scale = 1;
+					if ( type === "pos" ) {
 
 
-				// interpolate
+						if ( this.interpolationType === THREE.AnimationHandler.LINEAR ) {
 
 
-				if ( type === "pos" ) {
+							newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
+							newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
+							newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
 
 
-					if ( this.interpolationType === THREE.AnimationHandler.LINEAR ) {
+							// blend
+							var proportionalWeight = this.weight / ( this.weight + blending.positionWeight );
+							object.position.lerp( newVector, proportionalWeight );
+							blending.positionWeight += this.weight;
 
 
-						newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
-						newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
-						newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
+						} else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
+									this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
 
 
-						// blend
-						var proportionalWeight = this.weight / ( this.weight + blending.positionWeight );
-						object.position.lerp( newVector, proportionalWeight );
-						blending.positionWeight += this.weight;
+							points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ];
+							points[ 1 ] = prevXYZ;
+							points[ 2 ] = nextXYZ;
+							points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ];
 
 
-					} else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
-								this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
+							scale = scale * 0.33 + 0.33;
 
 
-						points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ];
-						points[ 1 ] = prevXYZ;
-						points[ 2 ] = nextXYZ;
-						points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ];
+							var currentPoint = interpolateCatmullRom( points, scale );
+							var proportionalWeight = this.weight / ( this.weight + blending.positionWeight );
+							blending.positionWeight += this.weight;
 
 
-						scale = scale * 0.33 + 0.33;
+							// blend
 
 
-						var currentPoint = interpolateCatmullRom( points, scale );
-						var proportionalWeight = this.weight / ( this.weight + blending.positionWeight );
-						blending.positionWeight += this.weight;
+							var vector = object.position;
 
 
-						// blend
+							vector.x = vector.x + ( currentPoint[ 0 ] - vector.x ) * proportionalWeight;
+							vector.y = vector.y + ( currentPoint[ 1 ] - vector.y ) * proportionalWeight;
+							vector.z = vector.z + ( currentPoint[ 2 ] - vector.z ) * proportionalWeight;
 
 
-						var vector = object.position;
-						
-						vector.x = vector.x + ( currentPoint[ 0 ] - vector.x ) * proportionalWeight;
-						vector.y = vector.y + ( currentPoint[ 1 ] - vector.y ) * proportionalWeight;
-						vector.z = vector.z + ( currentPoint[ 2 ] - vector.z ) * proportionalWeight;
+							if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
 
 
-						if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
+								var forwardPoint = interpolateCatmullRom( points, scale * 1.01 );
 
 
-							var forwardPoint = interpolateCatmullRom( points, scale * 1.01 );
+								target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] );
+								target.sub( vector );
+								target.y = 0;
+								target.normalize();
 
 
-							target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] );
-							target.sub( vector );
-							target.y = 0;
-							target.normalize();
+								var angle = Math.atan2( target.x, target.z );
+								object.rotation.set( 0, angle, 0 );
 
 
-							var angle = Math.atan2( target.x, target.z );
-							object.rotation.set( 0, angle, 0 );
+							}
 
 
 						}
 						}
 
 
-					}
+					} else if ( type === "rot" ) {
 
 
-				} else if ( type === "rot" ) {
+						THREE.Quaternion.slerp( prevXYZ, nextXYZ, newQuat, scale );
 
 
-					THREE.Quaternion.slerp( prevXYZ, nextXYZ, newQuat, scale );
+						// Avoid paying the cost of an additional slerp if we don't have to
+						if ( blending.quaternionWeight === 0 ) {
 
 
-					// Avoid paying the cost of an additional slerp if we don't have to
-					if ( blending.quaternionWeight === 0 ) {
+							object.quaternion.copy(newQuat);
+							blending.quaternionWeight = this.weight;
 
 
-						object.quaternion.copy(newQuat);
-						blending.quaternionWeight = this.weight;
+						} else {
 
 
-					} else {
+							var proportionalWeight = this.weight / ( this.weight + blending.quaternionWeight );
+							THREE.Quaternion.slerp( object.quaternion, newQuat, object.quaternion, proportionalWeight );
+							blending.quaternionWeight += this.weight;
 
 
-						var proportionalWeight = this.weight / ( this.weight + blending.quaternionWeight );
-						THREE.Quaternion.slerp( object.quaternion, newQuat, object.quaternion, proportionalWeight );
-						blending.quaternionWeight += this.weight;
+						}
 
 
-					}
+					} else if ( type === "scl" ) {
 
 
-				} else if ( type === "scl" ) {
+						newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
+						newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
+						newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
 
 
-					newVector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
-					newVector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
-					newVector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
+						var proportionalWeight = this.weight / ( this.weight + blending.scaleWeight );
+						object.scale.lerp( newVector, proportionalWeight );
+						blending.scaleWeight += this.weight;
 
 
-					var proportionalWeight = this.weight / ( this.weight + blending.scaleWeight );
-					object.scale.lerp( newVector, proportionalWeight );
-					blending.scaleWeight += this.weight;
+					}
 
 
 				}
 				}
 
 
 			}
 			}
 
 
-		}
-
-		return true;
-
-	};
+			return true;
 
 
-})();
+		};
 
 
+	} )(),
 
 
+	getNextKeyWith: function ( type, h, key ) {
 
 
+		var keys = this.data.hierarchy[ h ].keys;
 
 
+		if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
+			 this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
 
 
-// Get next key with
+			key = key < keys.length - 1 ? key : keys.length - 1;
 
 
-THREE.Animation.prototype.getNextKeyWith = function ( type, h, key ) {
+		} else {
 
 
-	var keys = this.data.hierarchy[ h ].keys;
+			key = key % keys.length;
 
 
-	if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
-		 this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
-
-		key = key < keys.length - 1 ? key : keys.length - 1;
-
-	} else {
+		}
 
 
-		key = key % keys.length;
+		for ( ; key < keys.length; key ++ ) {
 
 
-	}
+			if ( keys[ key ][ type ] !== undefined ) {
 
 
-	for ( ; key < keys.length; key ++ ) {
+				return keys[ key ];
 
 
-		if ( keys[ key ][ type ] !== undefined ) {
-
-			return keys[ key ];
+			}
 
 
 		}
 		}
 
 
-	}
-
-	return this.data.hierarchy[ h ].keys[ 0 ];
+		return this.data.hierarchy[ h ].keys[ 0 ];
 
 
-};
+	},
 
 
-// Get previous key with
+	getPrevKeyWith: function ( type, h, key ) {
 
 
-THREE.Animation.prototype.getPrevKeyWith = function ( type, h, key ) {
+		var keys = this.data.hierarchy[ h ].keys;
 
 
-	var keys = this.data.hierarchy[ h ].keys;
+		if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
+			this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
 
 
-	if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
-		this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
+			key = key > 0 ? key : 0;
 
 
-		key = key > 0 ? key : 0;
+		} else {
 
 
-	} else {
+			key = key >= 0 ? key : key + keys.length;
 
 
-		key = key >= 0 ? key : key + keys.length;
+		}
 
 
-	}
 
 
+		for ( ; key >= 0; key -- ) {
 
 
-	for ( ; key >= 0; key -- ) {
+			if ( keys[ key ][ type ] !== undefined ) {
 
 
-		if ( keys[ key ][ type ] !== undefined ) {
+				return keys[ key ];
 
 
-			return keys[ key ];
+			}
 
 
 		}
 		}
 
 
-	}
+		return this.data.hierarchy[ h ].keys[ keys.length - 1 ];
 
 
-	return this.data.hierarchy[ h ].keys[ keys.length - 1 ];
+	}
 
 
 };
 };

+ 98 - 101
src/extras/animation/KeyFrameAnimation.js

@@ -50,195 +50,192 @@ THREE.KeyFrameAnimation = function ( data ) {
 
 
 };
 };
 
 
+THREE.KeyFrameAnimation.prototype = {
 
 
-THREE.KeyFrameAnimation.prototype.play = function ( startTime ) {
+	constructor: THREE.KeyFrameAnimation,
 
 
-	this.currentTime = startTime !== undefined ? startTime : 0;
+	play: function ( startTime ) {
 
 
-	if ( this.isPlaying === false ) {
+		this.currentTime = startTime !== undefined ? startTime : 0;
 
 
-		this.isPlaying = true;
+		if ( this.isPlaying === false ) {
 
 
-		// reset key cache
+			this.isPlaying = true;
 
 
-		var h, hl = this.hierarchy.length,
-			object,
-			node;
+			// reset key cache
 
 
-		for ( h = 0; h < hl; h ++ ) {
+			var h, hl = this.hierarchy.length,
+				object,
+				node;
 
 
-			object = this.hierarchy[ h ];
-			node = this.data.hierarchy[ h ];
+			for ( h = 0; h < hl; h ++ ) {
 
 
-			if ( node.animationCache === undefined ) {
+				object = this.hierarchy[ h ];
+				node = this.data.hierarchy[ h ];
 
 
-				node.animationCache = {};
-				node.animationCache.prevKey = null;
-				node.animationCache.nextKey = null;
-				node.animationCache.originalMatrix = object.matrix;
+				if ( node.animationCache === undefined ) {
 
 
-			}
+					node.animationCache = {};
+					node.animationCache.prevKey = null;
+					node.animationCache.nextKey = null;
+					node.animationCache.originalMatrix = object.matrix;
+
+				}
+
+				var keys = this.data.hierarchy[h].keys;
 
 
-			var keys = this.data.hierarchy[h].keys;
+				if (keys.length) {
 
 
-			if (keys.length) {
+					node.animationCache.prevKey = keys[ 0 ];
+					node.animationCache.nextKey = keys[ 1 ];
 
 
-				node.animationCache.prevKey = keys[ 0 ];
-				node.animationCache.nextKey = keys[ 1 ];
+					this.startTime = Math.min( keys[0].time, this.startTime );
+					this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
 
 
-				this.startTime = Math.min( keys[0].time, this.startTime );
-				this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
+				}
 
 
 			}
 			}
 
 
+			this.update( 0 );
+
 		}
 		}
 
 
-		this.update( 0 );
+		this.isPaused = false;
 
 
-	}
+		THREE.AnimationHandler.play( this );
 
 
-	this.isPaused = false;
+	},
 
 
-	THREE.AnimationHandler.play( this );
+	stop: function () {
 
 
-};
+		this.isPlaying = false;
+		this.isPaused  = false;
 
 
+		THREE.AnimationHandler.stop( this );
 
 
-THREE.KeyFrameAnimation.prototype.stop = function() {
+		// reset JIT matrix and remove cache
 
 
-	this.isPlaying = false;
-	this.isPaused  = false;
-
-	THREE.AnimationHandler.stop( this );
+		for ( var h = 0; h < this.data.hierarchy.length; h ++ ) {
 
 
-	// reset JIT matrix and remove cache
+			var obj = this.hierarchy[ h ];
+			var node = this.data.hierarchy[ h ];
 
 
-	for ( var h = 0; h < this.data.hierarchy.length; h ++ ) {
-		
-		var obj = this.hierarchy[ h ];
-		var node = this.data.hierarchy[ h ];
+			if ( node.animationCache !== undefined ) {
 
 
-		if ( node.animationCache !== undefined ) {
+				var original = node.animationCache.originalMatrix;
 
 
-			var original = node.animationCache.originalMatrix;
+				original.copy( obj.matrix );
+				obj.matrix = original;
 
 
-			original.copy( obj.matrix );
-			obj.matrix = original;
+				delete node.animationCache;
 
 
-			delete node.animationCache;
+			}
 
 
 		}
 		}
 
 
-	}
-
-};
+	},
 
 
+	update: function ( delta ) {
 
 
-// Update
+		if ( this.isPlaying === false ) return;
 
 
-THREE.KeyFrameAnimation.prototype.update = function ( delta ) {
+		this.currentTime += delta * this.timeScale;
 
 
-	if ( this.isPlaying === false ) return;
+		//
 
 
-	this.currentTime += delta * this.timeScale;
+		var duration = this.data.length;
 
 
-	//
+		if ( this.loop === true && this.currentTime > duration ) {
 
 
-	var duration = this.data.length;
+			this.currentTime %= duration;
 
 
-	if ( this.loop === true && this.currentTime > duration ) {
+		}
 
 
-		this.currentTime %= duration;
+		this.currentTime = Math.min( this.currentTime, duration );
 
 
-	}
+		for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
 
 
-	this.currentTime = Math.min( this.currentTime, duration );
+			var object = this.hierarchy[ h ];
+			var node = this.data.hierarchy[ h ];
 
 
-	for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
+			var keys = node.keys,
+				animationCache = node.animationCache;
 
 
-		var object = this.hierarchy[ h ];
-		var node = this.data.hierarchy[ h ];
 
 
-		var keys = node.keys,
-			animationCache = node.animationCache;
+			if ( keys.length ) {
 
 
+				var prevKey = animationCache.prevKey;
+				var nextKey = animationCache.nextKey;
 
 
-		if ( keys.length ) {
+				if ( nextKey.time <= this.currentTime ) {
 
 
-			var prevKey = animationCache.prevKey;
-			var nextKey = animationCache.nextKey;
+					while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
 
 
-			if ( nextKey.time <= this.currentTime ) {
+						prevKey = nextKey;
+						nextKey = keys[ prevKey.index + 1 ];
 
 
-				while ( nextKey.time < this.currentTime && nextKey.index > prevKey.index ) {
+					}
 
 
-					prevKey = nextKey;
-					nextKey = keys[ prevKey.index + 1 ];
+					animationCache.prevKey = prevKey;
+					animationCache.nextKey = nextKey;
 
 
 				}
 				}
 
 
-				animationCache.prevKey = prevKey;
-				animationCache.nextKey = nextKey;
+				if ( nextKey.time >= this.currentTime ) {
 
 
-			}
+					prevKey.interpolate( nextKey, this.currentTime );
 
 
-			if ( nextKey.time >= this.currentTime ) {
+				} else {
 
 
-				prevKey.interpolate( nextKey, this.currentTime );
+					prevKey.interpolate( nextKey, nextKey.time );
 
 
-			} else {
+				}
 
 
-				prevKey.interpolate( nextKey, nextKey.time );
+				this.data.hierarchy[ h ].node.updateMatrix();
+				object.matrixWorldNeedsUpdate = true;
 
 
 			}
 			}
 
 
-			this.data.hierarchy[ h ].node.updateMatrix();
-			object.matrixWorldNeedsUpdate = true;
-
 		}
 		}
 
 
-	}
-
-};
+	},
 
 
-// Get next key with
+	getNextKeyWith: function ( sid, h, key ) {
 
 
-THREE.KeyFrameAnimation.prototype.getNextKeyWith = function( sid, h, key ) {
+		var keys = this.data.hierarchy[ h ].keys;
+		key = key % keys.length;
 
 
-	var keys = this.data.hierarchy[ h ].keys;
-	key = key % keys.length;
+		for ( ; key < keys.length; key ++ ) {
 
 
-	for ( ; key < keys.length; key ++ ) {
+			if ( keys[ key ].hasTarget( sid ) ) {
 
 
-		if ( keys[ key ].hasTarget( sid ) ) {
+				return keys[ key ];
 
 
-			return keys[ key ];
+			}
 
 
 		}
 		}
 
 
-	}
-
-	return keys[ 0 ];
+		return keys[ 0 ];
 
 
-};
+	},
 
 
-// Get previous key with
+	getPrevKeyWith: function ( sid, h, key ) {
 
 
-THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) {
+		var keys = this.data.hierarchy[ h ].keys;
+		key = key >= 0 ? key : key + keys.length;
 
 
-	var keys = this.data.hierarchy[ h ].keys;
-	key = key >= 0 ? key : key + keys.length;
+		for ( ; key >= 0; key -- ) {
 
 
-	for ( ; key >= 0; key -- ) {
+			if ( keys[ key ].hasTarget( sid ) ) {
 
 
-		if ( keys[ key ].hasTarget( sid ) ) {
+				return keys[ key ];
 
 
-			return keys[ key ];
+			}
 
 
 		}
 		}
 
 
-	}
+		return keys[ keys.length - 1 ];
 
 
-	return keys[ keys.length - 1 ];
+	}
 
 
 };
 };

+ 7 - 5
src/extras/animation/MorphAnimation.js

@@ -50,19 +50,21 @@ THREE.MorphAnimation.prototype = {
 		var interpolation = this.duration / this.frames;
 		var interpolation = this.duration / this.frames;
 		var frame = Math.floor( this.currentTime / interpolation );
 		var frame = Math.floor( this.currentTime / interpolation );
 
 
+		var influences = this.mesh.morphTargetInfluences;
+
 		if ( frame != this.currentFrame ) {
 		if ( frame != this.currentFrame ) {
 
 
-			this.mesh.morphTargetInfluences[ this.lastFrame ] = 0;
-			this.mesh.morphTargetInfluences[ this.currentFrame ] = 1;
-			this.mesh.morphTargetInfluences[ frame ] = 0;
+			influences[ this.lastFrame ] = 0;
+			influences[ this.currentFrame ] = 1;
+			influences[ frame ] = 0;
 
 
 			this.lastFrame = this.currentFrame;
 			this.lastFrame = this.currentFrame;
 			this.currentFrame = frame;
 			this.currentFrame = frame;
 
 
 		}
 		}
 
 
-		this.mesh.morphTargetInfluences[ frame ] = ( this.currentTime % interpolation ) / interpolation;
-		this.mesh.morphTargetInfluences[ this.lastFrame ] = 1 - this.mesh.morphTargetInfluences[ frame ];
+		influences[ frame ] = ( this.currentTime % interpolation ) / interpolation;
+		influences[ this.lastFrame ] = 1 - influences[ frame ];
 
 
 	}
 	}
 
 

+ 57 - 2
src/extras/audio/Audio.js

@@ -10,6 +10,7 @@ THREE.Audio = function ( listener ) {
 
 
 	this.context = listener.context;
 	this.context = listener.context;
 	this.source = this.context.createBufferSource();
 	this.source = this.context.createBufferSource();
+	this.source.onended = this.onEnded.bind(this);
 
 
 	this.gain = this.context.createGain();
 	this.gain = this.context.createGain();
 	this.gain.connect( this.context.destination );
 	this.gain.connect( this.context.destination );
@@ -17,6 +18,11 @@ THREE.Audio = function ( listener ) {
 	this.panner = this.context.createPanner();
 	this.panner = this.context.createPanner();
 	this.panner.connect( this.gain );
 	this.panner.connect( this.gain );
 
 
+	this.autoplay = false;
+
+	this.startTime = 0;
+	this.isPlaying = false;
+
 };
 };
 
 
 THREE.Audio.prototype = Object.create( THREE.Object3D.prototype );
 THREE.Audio.prototype = Object.create( THREE.Object3D.prototype );
@@ -34,8 +40,8 @@ THREE.Audio.prototype.load = function ( file ) {
 		scope.context.decodeAudioData( this.response, function ( buffer ) {
 		scope.context.decodeAudioData( this.response, function ( buffer ) {
 
 
 			scope.source.buffer = buffer;
 			scope.source.buffer = buffer;
-			scope.source.connect( scope.panner );
-			scope.source.start( 0 );
+
+			if( scope.autoplay ) scope.play();
 
 
 		} );
 		} );
 
 
@@ -46,6 +52,49 @@ THREE.Audio.prototype.load = function ( file ) {
 
 
 };
 };
 
 
+THREE.Audio.prototype.play = function () {
+
+	if ( this.isPlaying === true ) {
+
+		THREE.warn( 'THREE.Audio: Audio is already playing.' );
+		return;
+
+	}
+
+	var source = this.context.createBufferSource();
+
+	source.buffer = this.source.buffer;
+	source.loop = this.source.loop;
+	source.onended = this.source.onended;
+	source.connect( this.panner );
+	source.start( 0, this.startTime );
+
+	this.isPlaying = true;
+
+	this.source = source;
+
+};
+
+THREE.Audio.prototype.pause = function () {
+
+	this.source.stop();
+	this.startTime = this.context.currentTime;
+
+};
+
+THREE.Audio.prototype.stop = function () {
+
+	this.source.stop();
+	this.startTime = 0;
+
+};
+
+THREE.Audio.prototype.onEnded = function() {
+
+	this.isPlaying = false;
+
+};
+
 THREE.Audio.prototype.setLoop = function ( value ) {
 THREE.Audio.prototype.setLoop = function ( value ) {
 
 
 	this.source.loop = value;
 	this.source.loop = value;
@@ -64,6 +113,12 @@ THREE.Audio.prototype.setRolloffFactor = function ( value ) {
 
 
 };
 };
 
 
+THREE.Audio.prototype.setVolume = function ( value ) {
+
+	this.gain.gain.value = value;
+
+};
+
 THREE.Audio.prototype.updateMatrixWorld = ( function () {
 THREE.Audio.prototype.updateMatrixWorld = ( function () {
 
 
 	var position = new THREE.Vector3();
 	var position = new THREE.Vector3();

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

@@ -22,9 +22,6 @@ THREE.AudioListener.prototype.updateMatrixWorld = ( function () {
 	var scale = new THREE.Vector3();
 	var scale = new THREE.Vector3();
 
 
 	var orientation = new THREE.Vector3();
 	var orientation = new THREE.Vector3();
-	var velocity = new THREE.Vector3();
-
-	var positionPrev = new THREE.Vector3();
 
 
 	return function ( force ) {
 	return function ( force ) {
 
 
@@ -36,13 +33,9 @@ THREE.AudioListener.prototype.updateMatrixWorld = ( function () {
 		this.matrixWorld.decompose( position, quaternion, scale );
 		this.matrixWorld.decompose( position, quaternion, scale );
 
 
 		orientation.set( 0, 0, -1 ).applyQuaternion( quaternion );
 		orientation.set( 0, 0, -1 ).applyQuaternion( quaternion );
-		velocity.subVectors( position, positionPrev );
 
 
 		listener.setPosition( position.x, position.y, position.z );
 		listener.setPosition( position.x, position.y, position.z );
 		listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
 		listener.setOrientation( orientation.x, orientation.y, orientation.z, up.x, up.y, up.z );
-		listener.setVelocity( velocity.x, velocity.y, velocity.z );
-
-		positionPrev.copy( position );
 
 
 	};
 	};
 
 

+ 0 - 1
src/extras/core/Path.js

@@ -633,7 +633,6 @@ THREE.Path.prototype.toShapes = function( isCCW, noHoles ) {
 			betterShapeHoles[sIdx] = [];
 			betterShapeHoles[sIdx] = [];
 		}
 		}
 		for (var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
 		for (var sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) {
-			var sh = newShapes[sIdx];
 			var sho = newShapeHoles[sIdx];
 			var sho = newShapeHoles[sIdx];
 			for (var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
 			for (var hIdx = 0; hIdx < sho.length; hIdx ++ ) {
 				var ho = sho[hIdx];
 				var ho = sho[hIdx];

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

@@ -123,7 +123,6 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
 
 
 	var ahole, h, hl; // looping of holes
 	var ahole, h, hl; // looping of holes
 	var scope = this;
 	var scope = this;
-	var bevelPoints = [];
 
 
 	var shapesOffset = this.vertices.length;
 	var shapesOffset = this.vertices.length;
 
 
@@ -182,14 +181,11 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
 
 
 	var b, bs, t, z,
 	var b, bs, t, z,
 		vert, vlen = vertices.length,
 		vert, vlen = vertices.length,
-		face, flen = faces.length,
-		cont, clen = contour.length;
+		face, flen = faces.length;
 
 
 
 
 	// Find directions for point movement
 	// Find directions for point movement
 
 
-	var RAD_TO_DEGREES = 180 / Math.PI;
-
 
 
 	function getBevelVec( inPt, inPrev, inNext ) {
 	function getBevelVec( inPt, inPrev, inNext ) {
 
 
@@ -292,10 +288,6 @@ THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
 		//  (j)---(i)---(k)
 		//  (j)---(i)---(k)
 		// console.log('i,j,k', i, j , k)
 		// console.log('i,j,k', i, j , k)
 
 
-		var pt_i = contour[ i ];
-		var pt_j = contour[ j ];
-		var pt_k = contour[ k ];
-
 		contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
 		contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
 
 
 	}
 	}

+ 0 - 1
src/extras/geometries/ParametricGeometry.js

@@ -26,7 +26,6 @@ THREE.ParametricGeometry = function ( func, slices, stacks ) {
 	var i, j, p;
 	var i, j, p;
 	var u, v;
 	var u, v;
 
 
-	var stackCount = stacks + 1;
 	var sliceCount = slices + 1;
 	var sliceCount = slices + 1;
 
 
 	for ( i = 0; i <= stacks; i ++ ) {
 	for ( i = 0; i <= stacks; i ++ ) {

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

@@ -28,7 +28,7 @@ THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) {
 
 
 	}
 	}
 
 
-	var midpoints = [], p = this.vertices;
+	var p = this.vertices;
 
 
 	var faces = [];
 	var faces = [];
 
 
@@ -136,7 +136,6 @@ THREE.PolyhedronGeometry = function ( vertices, indices, radius, detail ) {
 	function subdivide( face, detail ) {
 	function subdivide( face, detail ) {
 
 
 		var cols = Math.pow(2, detail);
 		var cols = Math.pow(2, detail);
-		var cells = Math.pow(4, detail);
 		var a = prepare( that.vertices[ face.a ] );
 		var a = prepare( that.vertices[ face.a ] );
 		var b = prepare( that.vertices[ face.b ] );
 		var b = prepare( that.vertices[ face.b ] );
 		var c = prepare( that.vertices[ face.c ] );
 		var c = prepare( that.vertices[ face.c ] );

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

@@ -59,7 +59,7 @@ THREE.ShapeGeometry.prototype.addShape = function ( shape, options ) {
 
 
 	//
 	//
 
 
-	var i, l, hole, s;
+	var i, l, hole;
 
 
 	var shapesOffset = this.vertices.length;
 	var shapesOffset = this.vertices.length;
 	var shapePoints = shape.extractPoints( curveSegments );
 	var shapePoints = shape.extractPoints( curveSegments );
@@ -108,7 +108,6 @@ THREE.ShapeGeometry.prototype.addShape = function ( shape, options ) {
 
 
 	var vert, vlen = vertices.length;
 	var vert, vlen = vertices.length;
 	var face, flen = faces.length;
 	var face, flen = faces.length;
-	var cont, clen = contour.length;
 
 
 	for ( i = 0; i < vlen; i ++ ) {
 	for ( i = 0; i < vlen; i ++ ) {
 
 

+ 2 - 6
src/extras/geometries/TubeGeometry.js

@@ -42,8 +42,6 @@ THREE.TubeGeometry = function ( path, segments, radius, radialSegments, closed,
 
 
 		numpoints = segments + 1,
 		numpoints = segments + 1,
 
 
-		x, y, z,
-		tx, ty, tz,
 		u, v, r,
 		u, v, r,
 
 
 		cx, cy,
 		cx, cy,
@@ -154,9 +152,7 @@ THREE.TubeGeometry.SinusoidalTaper = function ( u ) {
 // For computing of Frenet frames, exposing the tangents, normals and binormals the spline
 // For computing of Frenet frames, exposing the tangents, normals and binormals the spline
 THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) {
 THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) {
 
 
-	var	tangent = new THREE.Vector3(),
-		normal = new THREE.Vector3(),
-		binormal = new THREE.Vector3(),
+	var	normal = new THREE.Vector3(),
 
 
 		tangents = [],
 		tangents = [],
 		normals = [],
 		normals = [],
@@ -171,7 +167,7 @@ THREE.TubeGeometry.FrenetFrames = function ( path, segments, closed ) {
 		smallest,
 		smallest,
 
 
 		tx, ty, tz,
 		tx, ty, tz,
-		i, u, v;
+		i, u;
 
 
 
 
 	// expose internals
 	// expose internals

+ 11 - 2
src/extras/helpers/EdgesHelper.js

@@ -1,10 +1,19 @@
 /**
 /**
  * @author WestLangley / http://github.com/WestLangley
  * @author WestLangley / http://github.com/WestLangley
+ * @param object THREE.Mesh whose geometry will be used
+ * @param hex line color
+ * @param thresholdAngle the minimim angle (in degrees),
+ * between the face normals of adjacent faces,
+ * that is required to render an edge. A value of 10 means
+ * an edge is only rendered if the angle is at least 10 degrees.
  */
  */
 
 
-THREE.EdgesHelper = function ( object, hex ) {
+THREE.EdgesHelper = function ( object, hex, thresholdAngle ) {
 
 
 	var color = ( hex !== undefined ) ? hex : 0xffffff;
 	var color = ( hex !== undefined ) ? hex : 0xffffff;
+	thresholdAngle = ( thresholdAngle !== undefined ) ? thresholdAngle : 1;
+
+	var thresholdDot = Math.cos( THREE.Math.degToRad( thresholdAngle ) );
 
 
 	var edge = [ 0, 0 ], hash = {};
 	var edge = [ 0, 0 ], hash = {};
 	var sortFunction = function ( a, b ) { return a - b };
 	var sortFunction = function ( a, b ) { return a - b };
@@ -67,7 +76,7 @@ THREE.EdgesHelper = function ( object, hex ) {
 
 
 		var h = hash[ key ];
 		var h = hash[ key ];
 
 
-		if ( h.face2 === undefined || faces[ h.face1 ].normal.dot( faces[ h.face2 ].normal ) < 0.9999 ) { // hardwired const OK
+		if ( h.face2 === undefined || faces[ h.face1 ].normal.dot( faces[ h.face2 ].normal ) <= thresholdDot ) {
 
 
 			var vertex = vertices[ h.vert1 ];
 			var vertex = vertices[ h.vert1 ];
 			coords[ index ++ ] = vertex.x;
 			coords[ index ++ ] = vertex.x;

+ 0 - 2
src/extras/helpers/VertexNormalsHelper.js

@@ -15,8 +15,6 @@ THREE.VertexNormalsHelper = function ( object, size, hex, linewidth ) {
 
 
 	var geometry = new THREE.Geometry();
 	var geometry = new THREE.Geometry();
 
 
-	var vertices = object.geometry.vertices;
-
 	var faces = object.geometry.faces;
 	var faces = object.geometry.faces;
 
 
 	for ( var i = 0, l = faces.length; i < l; i ++ ) {
 	for ( var i = 0, l = faces.length; i < l; i ++ ) {

+ 0 - 2
src/extras/helpers/VertexTangentsHelper.js

@@ -15,8 +15,6 @@ THREE.VertexTangentsHelper = function ( object, size, hex, linewidth ) {
 
 
 	var geometry = new THREE.Geometry();
 	var geometry = new THREE.Geometry();
 
 
-	var vertices = object.geometry.vertices;
-
 	var faces = object.geometry.faces;
 	var faces = object.geometry.faces;
 
 
 	for ( var i = 0, l = faces.length; i < l; i ++ ) {
 	for ( var i = 0, l = faces.length; i < l; i ++ ) {

+ 0 - 1
src/extras/objects/MorphBlendMesh.js

@@ -76,7 +76,6 @@ THREE.MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) {
 		if ( chunks && chunks.length > 1 ) {
 		if ( chunks && chunks.length > 1 ) {
 
 
 			var name = chunks[ 1 ];
 			var name = chunks[ 1 ];
-			var num = chunks[ 2 ];
 
 
 			if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity };
 			if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: - Infinity };
 
 

+ 3 - 3
src/loaders/BufferGeometryLoader.js

@@ -36,7 +36,7 @@ THREE.BufferGeometryLoader.prototype = {
 
 
 		var geometry = new THREE.BufferGeometry();
 		var geometry = new THREE.BufferGeometry();
 
 
-		var attributes = json.attributes;
+		var attributes = json.data.attributes;
 
 
 		for ( var key in attributes ) {
 		for ( var key in attributes ) {
 
 
@@ -47,7 +47,7 @@ THREE.BufferGeometryLoader.prototype = {
 
 
 		}
 		}
 
 
-		var offsets = json.offsets;
+		var offsets = json.data.offsets;
 
 
 		if ( offsets !== undefined ) {
 		if ( offsets !== undefined ) {
 
 
@@ -55,7 +55,7 @@ THREE.BufferGeometryLoader.prototype = {
 
 
 		}
 		}
 
 
-		var boundingSphere = json.boundingSphere;
+		var boundingSphere = json.data.boundingSphere;
 
 
 		if ( boundingSphere !== undefined ) {
 		if ( boundingSphere !== undefined ) {
 
 

+ 16 - 14
src/loaders/JSONLoader.js

@@ -16,8 +16,6 @@ THREE.JSONLoader.prototype.constructor = THREE.JSONLoader;
 
 
 THREE.JSONLoader.prototype.load = function ( url, callback, texturePath ) {
 THREE.JSONLoader.prototype.load = function ( url, callback, texturePath ) {
 
 
-	var scope = this;
-
 	// todo: unify load API to for easier SceneLoader use
 	// todo: unify load API to for easier SceneLoader use
 
 
 	texturePath = texturePath && ( typeof texturePath === 'string' ) ? texturePath : this.extractUrlBase( url );
 	texturePath = texturePath && ( typeof texturePath === 'string' ) ? texturePath : this.extractUrlBase( url );
@@ -42,18 +40,23 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, tex
 				if ( xhr.responseText ) {
 				if ( xhr.responseText ) {
 
 
 					var json = JSON.parse( xhr.responseText );
 					var json = JSON.parse( xhr.responseText );
+					var metadata = json.metadata;
 
 
-					if ( json.metadata !== undefined && json.metadata.version >= 4 ) {
+					if ( metadata !== undefined ) {
 
 
-						console.error( 'THREE.JSONLoader: "' + url + '" should be loaded with THREE.ObjectLoader instead.' );
-						return;
+						if ( metadata.type === 'object' ) {
 
 
-					}
+							THREE.error( 'THREE.JSONLoader: ' + url + ' should be loaded with THREE.ObjectLoader instead.' );
+							return;
+
+						}
+
+						if ( metadata.type === 'scene' ) {
 
 
-					if ( json.metadata !== undefined && json.metadata.type === 'scene' ) {
+							THREE.error( 'THREE.JSONLoader: ' + url + ' seems to be a Scene. Use THREE.SceneLoader instead.' );
+							return;
 
 
-						THREE.error( 'THREE.JSONLoader: "' + url + '" seems to be a Scene. Use THREE.SceneLoader instead.' );
-						return;
+						}
 
 
 					}
 					}
 
 
@@ -62,7 +65,7 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, tex
 
 
 				} else {
 				} else {
 
 
-					THREE.error( 'THREE.JSONLoader: "' + url + '" seems to be unreachable or the file is empty.' );
+					THREE.error( 'THREE.JSONLoader: ' + url + ' seems to be unreachable or the file is empty.' );
 
 
 				}
 				}
 
 
@@ -74,7 +77,7 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, tex
 
 
 			} else {
 			} else {
 
 
-				THREE.error( 'THREE.JSONLoader: Couldn\'t load "' + url + '" (' + xhr.status + ')' );
+				THREE.error( 'THREE.JSONLoader: Couldn\'t load ' + url + ' (' + xhr.status + ')' );
 
 
 			}
 			}
 
 
@@ -112,8 +115,7 @@ THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, tex
 
 
 THREE.JSONLoader.prototype.parse = function ( json, texturePath ) {
 THREE.JSONLoader.prototype.parse = function ( json, texturePath ) {
 
 
-	var scope = this,
-	geometry = new THREE.Geometry(),
+	var geometry = new THREE.Geometry(),
 	scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
 	scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
 
 
 	parseModel( scale );
 	parseModel( scale );
@@ -145,7 +147,7 @@ THREE.JSONLoader.prototype.parse = function ( json, texturePath ) {
 		hasFaceNormal, hasFaceVertexNormal,
 		hasFaceNormal, hasFaceVertexNormal,
 		hasFaceColor, hasFaceVertexColor,
 		hasFaceColor, hasFaceVertexColor,
 
 
-		vertex, face, faceA, faceB, color, hex, normal,
+		vertex, face, faceA, faceB, hex, normal,
 
 
 		uvLayer, uv, u, v,
 		uvLayer, uv, u, v,
 
 

+ 3 - 2
src/loaders/ObjectLoader.js

@@ -85,8 +85,9 @@ THREE.ObjectLoader.prototype = {
 				switch ( data.type ) {
 				switch ( data.type ) {
 
 
 					case 'PlaneGeometry':
 					case 'PlaneGeometry':
+					case 'PlaneBufferGeometry':
 
 
-						geometry = new THREE.PlaneGeometry(
+						geometry = new THREE[ data.type ](
 							data.width,
 							data.width,
 							data.height,
 							data.height,
 							data.widthSegments,
 							data.widthSegments,
@@ -182,7 +183,7 @@ THREE.ObjectLoader.prototype = {
 
 
 					case 'BufferGeometry':
 					case 'BufferGeometry':
 
 
-						geometry = bufferGeometryLoader.parse( data.data );
+						geometry = bufferGeometryLoader.parse( data );
 
 
 						break;
 						break;
 
 

+ 1 - 1
src/math/Matrix3.js

@@ -91,7 +91,7 @@ THREE.Matrix3.prototype = {
 			if ( offset === undefined ) offset = 0;
 			if ( offset === undefined ) offset = 0;
 			if ( length === undefined ) length = array.length;
 			if ( length === undefined ) length = array.length;
 
 
-			for ( var i = 0, j = offset, il; i < length; i += 3, j += 3 ) {
+			for ( var i = 0, j = offset; i < length; i += 3, j += 3 ) {
 
 
 				v1.x = array[ j ];
 				v1.x = array[ j ];
 				v1.y = array[ j + 1 ];
 				v1.y = array[ j + 1 ];

+ 1 - 1
src/math/Matrix4.js

@@ -470,7 +470,7 @@ THREE.Matrix4.prototype = {
 			if ( offset === undefined ) offset = 0;
 			if ( offset === undefined ) offset = 0;
 			if ( length === undefined ) length = array.length;
 			if ( length === undefined ) length = array.length;
 
 
-			for ( var i = 0, j = offset, il; i < length; i += 3, j += 3 ) {
+			for ( var i = 0, j = offset; i < length; i += 3, j += 3 ) {
 
 
 				v1.x = array[ j ];
 				v1.x = array[ j ];
 				v1.y = array[ j + 1 ];
 				v1.y = array[ j + 1 ];

+ 1 - 1
src/math/Spline.js

@@ -125,7 +125,7 @@ THREE.Spline = function ( points ) {
 
 
 		var i, j,
 		var i, j,
 			index, indexCurrent, indexNext,
 			index, indexCurrent, indexNext,
-			linearDistance, realDistance,
+			realDistance,
 			sampling, position,
 			sampling, position,
 			newpoints = [],
 			newpoints = [],
 			tmpVec = new THREE.Vector3(),
 			tmpVec = new THREE.Vector3(),

+ 15 - 6
src/math/Vector2.js

@@ -90,19 +90,19 @@ THREE.Vector2.prototype = {
 
 
 	},
 	},
 
 
-	addVectors: function ( a, b ) {
+	addScalar: function ( s ) {
 
 
-		this.x = a.x + b.x;
-		this.y = a.y + b.y;
+		this.x += s;
+		this.y += s;
 
 
 		return this;
 		return this;
 
 
 	},
 	},
 
 
-	addScalar: function ( s ) {
+	addVectors: function ( a, b ) {
 
 
-		this.x += s;
-		this.y += s;
+		this.x = a.x + b.x;
+		this.y = a.y + b.y;
 
 
 		return this;
 		return this;
 
 
@@ -124,6 +124,15 @@ THREE.Vector2.prototype = {
 
 
 	},
 	},
 
 
+	subScalar: function ( s ) {
+
+		this.x -= s;
+		this.y -= s;
+
+		return this;
+
+	},
+
 	subVectors: function ( a, b ) {
 	subVectors: function ( a, b ) {
 
 
 		this.x = a.x - b.x;
 		this.x = a.x - b.x;

+ 10 - 0
src/math/Vector3.js

@@ -142,6 +142,16 @@ THREE.Vector3.prototype = {
 		return this;
 		return this;
 
 
 	},
 	},
+	
+	subScalar: function ( s ) {
+
+		this.x -= s;
+		this.y -= s;
+		this.z -= s;
+
+		return this;
+
+	},
 
 
 	subVectors: function ( a, b ) {
 	subVectors: function ( a, b ) {
 
 

+ 11 - 0
src/math/Vector4.js

@@ -159,6 +159,17 @@ THREE.Vector4.prototype = {
 
 
 	},
 	},
 
 
+	subScalar: function ( s ) {
+
+		this.x -= s;
+		this.y -= s;
+		this.z -= s;
+		this.w -= s;
+
+		return this;
+
+	},
+
 	subVectors: function ( a, b ) {
 	subVectors: function ( a, b ) {
 
 
 		this.x = a.x - b.x;
 		this.x = a.x - b.x;

+ 1 - 1
src/objects/Mesh.js

@@ -220,7 +220,7 @@ THREE.Mesh.prototype.raycast = ( function () {
 			var isFaceMaterial = this.material instanceof THREE.MeshFaceMaterial;
 			var isFaceMaterial = this.material instanceof THREE.MeshFaceMaterial;
 			var objectMaterials = isFaceMaterial === true ? this.material.materials : null;
 			var objectMaterials = isFaceMaterial === true ? this.material.materials : null;
 
 
-			var a, b, c, d;
+			var a, b, c;
 			var precision = raycaster.precision;
 			var precision = raycaster.precision;
 
 
 			var vertices = geometry.vertices;
 			var vertices = geometry.vertices;

+ 0 - 1
src/objects/MorphAnimMesh.js

@@ -70,7 +70,6 @@ THREE.MorphAnimMesh.prototype.parseAnimations = function () {
 		if ( parts && parts.length > 1 ) {
 		if ( parts && parts.length > 1 ) {
 
 
 			var label = parts[ 1 ];
 			var label = parts[ 1 ];
-			var num = parts[ 2 ];
 
 
 			if ( ! animations[ label ] ) animations[ label ] = { start: Infinity, end: - Infinity };
 			if ( ! animations[ label ] ) animations[ label ] = { start: Infinity, end: - Infinity };
 
 

+ 29 - 45
src/renderers/WebGLRenderer.js

@@ -132,7 +132,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 	 // camera matrices cache
 	 // camera matrices cache
 
 
 	_projScreenMatrix = new THREE.Matrix4(),
 	_projScreenMatrix = new THREE.Matrix4(),
-	_projScreenMatrixPS = new THREE.Matrix4(),
 
 
 	_vector3 = new THREE.Vector3(),
 	_vector3 = new THREE.Vector3(),
 
 
@@ -300,11 +299,9 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	var _vertexShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_FLOAT );
 	var _vertexShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.HIGH_FLOAT );
 	var _vertexShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_FLOAT );
 	var _vertexShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.MEDIUM_FLOAT );
-	var _vertexShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.VERTEX_SHADER, _gl.LOW_FLOAT );
 
 
 	var _fragmentShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_FLOAT );
 	var _fragmentShaderPrecisionHighpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.HIGH_FLOAT );
 	var _fragmentShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_FLOAT );
 	var _fragmentShaderPrecisionMediumpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.MEDIUM_FLOAT );
-	var _fragmentShaderPrecisionLowpFloat = _gl.getShaderPrecisionFormat( _gl.FRAGMENT_SHADER, _gl.LOW_FLOAT );
 
 
 	var getCompressedTextureFormats = ( function () {
 	var getCompressedTextureFormats = ( function () {
 
 
@@ -1020,8 +1017,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 		geometry.__vertexArray = new Float32Array( nvertices * 3 );
 		geometry.__vertexArray = new Float32Array( nvertices * 3 );
 		geometry.__colorArray = new Float32Array( nvertices * 3 );
 		geometry.__colorArray = new Float32Array( nvertices * 3 );
 
 
-		geometry.__sortArray = [];
-
 		geometry.__webglParticleCount = nvertices;
 		geometry.__webglParticleCount = nvertices;
 
 
 		initCustomAttributes( object );
 		initCustomAttributes( object );
@@ -1191,7 +1186,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	function setParticleBuffers ( geometry, hint, object ) {
 	function setParticleBuffers ( geometry, hint, object ) {
 
 
-		var v, c, vertex, offset, index, color,
+		var v, c, vertex, offset, color,
 
 
 		vertices = geometry.vertices,
 		vertices = geometry.vertices,
 		vl = vertices.length,
 		vl = vertices.length,
@@ -1202,15 +1197,12 @@ THREE.WebGLRenderer = function ( parameters ) {
 		vertexArray = geometry.__vertexArray,
 		vertexArray = geometry.__vertexArray,
 		colorArray = geometry.__colorArray,
 		colorArray = geometry.__colorArray,
 
 
-		sortArray = geometry.__sortArray,
-
 		dirtyVertices = geometry.verticesNeedUpdate,
 		dirtyVertices = geometry.verticesNeedUpdate,
-		dirtyElements = geometry.elementsNeedUpdate,
 		dirtyColors = geometry.colorsNeedUpdate,
 		dirtyColors = geometry.colorsNeedUpdate,
 
 
 		customAttributes = geometry.__webglCustomAttributesList,
 		customAttributes = geometry.__webglCustomAttributesList,
 		i, il,
 		i, il,
-		a, ca, cal, value,
+		ca, cal, value,
 		customAttribute;
 		customAttribute;
 
 
 		if ( dirtyVertices ) {
 		if ( dirtyVertices ) {
@@ -1369,7 +1361,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 		customAttributes = geometry.__webglCustomAttributesList,
 		customAttributes = geometry.__webglCustomAttributesList,
 
 
 		i, il,
 		i, il,
-		a, ca, cal, value,
+		ca, cal, value,
 		customAttribute;
 		customAttribute;
 
 
 		if ( dirtyVertices ) {
 		if ( dirtyVertices ) {
@@ -1529,20 +1521,17 @@ THREE.WebGLRenderer = function ( parameters ) {
 		var needsFaceNormals = materialNeedsFaceNormals( material );
 		var needsFaceNormals = materialNeedsFaceNormals( material );
 
 
 		var f, fl, fi, face,
 		var f, fl, fi, face,
-		vertexNormals, faceNormal, normal,
+		vertexNormals, faceNormal,
 		vertexColors, faceColor,
 		vertexColors, faceColor,
 		vertexTangents,
 		vertexTangents,
-		uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
+		uv, uv2, v1, v2, v3, t1, t2, t3, n1, n2, n3,
 		c1, c2, c3,
 		c1, c2, c3,
-		sw1, sw2, sw3, sw4,
-		si1, si2, si3, si4,
-		sa1, sa2, sa3, sa4,
-		sb1, sb2, sb3, sb4,
-		m, ml, i, il,
+		sw1, sw2, sw3,
+		si1, si2, si3,
+		i, il,
 		vn, uvi, uv2i,
 		vn, uvi, uv2i,
 		vk, vkl, vka,
 		vk, vkl, vka,
 		nka, chf, faceVertexNormals,
 		nka, chf, faceVertexNormals,
-		a,
 
 
 		vertexIndex = 0,
 		vertexIndex = 0,
 
 
@@ -1557,7 +1546,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 		offset_skin = 0,
 		offset_skin = 0,
 		offset_morphTarget = 0,
 		offset_morphTarget = 0,
 		offset_custom = 0,
 		offset_custom = 0,
-		offset_customSrc = 0,
 
 
 		value,
 		value,
 
 
@@ -1597,8 +1585,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 		obj_uvs  = geometry.faceVertexUvs[ 0 ],
 		obj_uvs  = geometry.faceVertexUvs[ 0 ],
 		obj_uvs2 = geometry.faceVertexUvs[ 1 ],
 		obj_uvs2 = geometry.faceVertexUvs[ 1 ],
 
 
-		obj_colors = geometry.colors,
-
 		obj_skinIndices = geometry.skinIndices,
 		obj_skinIndices = geometry.skinIndices,
 		obj_skinWeights = geometry.skinWeights,
 		obj_skinWeights = geometry.skinWeights,
 
 
@@ -2021,7 +2007,6 @@ THREE.WebGLRenderer = function ( parameters ) {
 				if ( ! customAttribute.__original.needsUpdate ) continue;
 				if ( ! customAttribute.__original.needsUpdate ) continue;
 
 
 				offset_custom = 0;
 				offset_custom = 0;
-				offset_customSrc = 0;
 
 
 				if ( customAttribute.size === 1 ) {
 				if ( customAttribute.size === 1 ) {
 
 
@@ -2590,7 +2575,7 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 				_this.info.render.calls ++;
 				_this.info.render.calls ++;
 				_this.info.render.vertices += position.array.length / position.itemSize;
 				_this.info.render.vertices += position.array.length / position.itemSize;
-				_this.info.render.faces += position.array.length / ( 3 * position.itemsize );
+				_this.info.render.faces += position.array.length / ( 3 * position.itemSize );
 
 
 			}
 			}
 
 
@@ -4767,29 +4752,29 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	// If uniforms are marked as clean, they don't need to be loaded to the GPU.
 	// If uniforms are marked as clean, they don't need to be loaded to the GPU.
 
 
-	function markUniformsLightsNeedsUpdate ( uniforms, boolean ) {
+	function markUniformsLightsNeedsUpdate ( uniforms, value ) {
 
 
-		uniforms.ambientLightColor.needsUpdate = boolean;
+		uniforms.ambientLightColor.needsUpdate = value;
 
 
-		uniforms.directionalLightColor.needsUpdate = boolean;
-		uniforms.directionalLightDirection.needsUpdate = boolean;
+		uniforms.directionalLightColor.needsUpdate = value;
+		uniforms.directionalLightDirection.needsUpdate = value;
 
 
-		uniforms.pointLightColor.needsUpdate = boolean;
-		uniforms.pointLightPosition.needsUpdate = boolean;
-		uniforms.pointLightDistance.needsUpdate = boolean;
-		uniforms.pointLightDecay.needsUpdate = boolean;
+		uniforms.pointLightColor.needsUpdate = value;
+		uniforms.pointLightPosition.needsUpdate = value;
+		uniforms.pointLightDistance.needsUpdate = value;
+		uniforms.pointLightDecay.needsUpdate = value;
 
 
-		uniforms.spotLightColor.needsUpdate = boolean;
-		uniforms.spotLightPosition.needsUpdate = boolean;
-		uniforms.spotLightDistance.needsUpdate = boolean;
-		uniforms.spotLightDirection.needsUpdate = boolean;
-		uniforms.spotLightAngleCos.needsUpdate = boolean;
-		uniforms.spotLightExponent.needsUpdate = boolean;
-		uniforms.spotLightDecay.needsUpdate = boolean;
+		uniforms.spotLightColor.needsUpdate = value;
+		uniforms.spotLightPosition.needsUpdate = value;
+		uniforms.spotLightDistance.needsUpdate = value;
+		uniforms.spotLightDirection.needsUpdate = value;
+		uniforms.spotLightAngleCos.needsUpdate = value;
+		uniforms.spotLightExponent.needsUpdate = value;
+		uniforms.spotLightDecay.needsUpdate = value;
 
 
-		uniforms.hemisphereLightSkyColor.needsUpdate = boolean;
-		uniforms.hemisphereLightGroundColor.needsUpdate = boolean;
-		uniforms.hemisphereLightDirection.needsUpdate = boolean;
+		uniforms.hemisphereLightSkyColor.needsUpdate = value;
+		uniforms.hemisphereLightGroundColor.needsUpdate = value;
+		uniforms.hemisphereLightDirection.needsUpdate = value;
 
 
 	}
 	}
 
 
@@ -5208,11 +5193,10 @@ THREE.WebGLRenderer = function ( parameters ) {
 
 
 	function setupLights ( lights ) {
 	function setupLights ( lights ) {
 
 
-		var l, ll, light, n,
+		var l, ll, light,
 		r = 0, g = 0, b = 0,
 		r = 0, g = 0, b = 0,
 		color, skyColor, groundColor,
 		color, skyColor, groundColor,
-		intensity,  intensitySq,
-		position,
+		intensity,
 		distance,
 		distance,
 
 
 		zlights = _lights,
 		zlights = _lights,

+ 1 - 1
src/renderers/shaders/ShaderChunk/alphamap_fragment.glsl

@@ -1,5 +1,5 @@
 #ifdef USE_ALPHAMAP
 #ifdef USE_ALPHAMAP
 
 
-	gl_FragColor.a *= texture2D( alphaMap, vUv ).g;
+	diffuseColor.a *= texture2D( alphaMap, vUv ).g;
 
 
 #endif
 #endif

+ 1 - 1
src/renderers/shaders/ShaderChunk/alphatest_fragment.glsl

@@ -1,5 +1,5 @@
 #ifdef ALPHATEST
 #ifdef ALPHATEST
 
 
-	if ( gl_FragColor.a < ALPHATEST ) discard;
+	if ( diffuseColor.a < ALPHATEST ) discard;
 
 
 #endif
 #endif

+ 1 - 1
src/renderers/shaders/ShaderChunk/color_fragment.glsl

@@ -1,5 +1,5 @@
 #ifdef USE_COLOR
 #ifdef USE_COLOR
 
 
-	gl_FragColor = gl_FragColor * vec4( vColor, 1.0 );
+	diffuseColor.rgb *= vColor;
 
 
 #endif
 #endif

+ 4 - 4
src/renderers/shaders/ShaderChunk/envmap_fragment.glsl

@@ -37,7 +37,7 @@
 		sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );
 		sampleUV.y = saturate( flipNormal * reflectVec.y * 0.5 + 0.5 );
 		sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
 		sampleUV.x = atan( flipNormal * reflectVec.z, flipNormal * reflectVec.x ) * RECIPROCAL_PI2 + 0.5;
 		vec4 envColor = texture2D( envMap, sampleUV );
 		vec4 envColor = texture2D( envMap, sampleUV );
-		
+
 	#elif defined( ENVMAP_TYPE_SPHERE )
 	#elif defined( ENVMAP_TYPE_SPHERE )
 		vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));
 		vec3 reflectView = flipNormal * normalize((viewMatrix * vec4( reflectVec, 0.0 )).xyz + vec3(0.0,0.0,1.0));
 		vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );
 		vec4 envColor = texture2D( envMap, reflectView.xy * 0.5 + 0.5 );
@@ -47,15 +47,15 @@
 
 
 	#ifdef ENVMAP_BLENDING_MULTIPLY
 	#ifdef ENVMAP_BLENDING_MULTIPLY
 
 
-		gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * envColor.xyz, specularStrength * reflectivity );
+		outgoingLight = mix( outgoingLight, outgoingLight * envColor.xyz, specularStrength * reflectivity );
 
 
 	#elif defined( ENVMAP_BLENDING_MIX )
 	#elif defined( ENVMAP_BLENDING_MIX )
 
 
-		gl_FragColor.xyz = mix( gl_FragColor.xyz, envColor.xyz, specularStrength * reflectivity );
+		outgoingLight = mix( outgoingLight, envColor.xyz, specularStrength * reflectivity );
 
 
 	#elif defined( ENVMAP_BLENDING_ADD )
 	#elif defined( ENVMAP_BLENDING_ADD )
 
 
-		gl_FragColor.xyz += envColor.xyz * specularStrength * reflectivity;
+		outgoingLight += envColor.xyz * specularStrength * reflectivity;
 
 
 	#endif
 	#endif
 
 

+ 1 - 1
src/renderers/shaders/ShaderChunk/fog_fragment.glsl

@@ -21,6 +21,6 @@
 
 
 	#endif
 	#endif
 	
 	
-	gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );
+	outgoingLight = mix( outgoingLight, fogColor, fogFactor );
 
 
 #endif
 #endif

+ 1 - 1
src/renderers/shaders/ShaderChunk/lightmap_fragment.glsl

@@ -1,5 +1,5 @@
 #ifdef USE_LIGHTMAP
 #ifdef USE_LIGHTMAP
 
 
-	gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );
+	outgoingLight *= diffuseColor.xyz * texture2D( lightMap, vUv2 ).xyz;
 
 
 #endif
 #endif

+ 0 - 3
src/renderers/shaders/ShaderChunk/lights_lambert_pars_vertex.glsl

@@ -1,6 +1,3 @@
-uniform vec3 diffuse;
-uniform vec3 emissive;
-
 uniform vec3 ambientLightColor;
 uniform vec3 ambientLightColor;
 
 
 #if MAX_DIR_LIGHTS > 0
 #if MAX_DIR_LIGHTS > 0

+ 2 - 2
src/renderers/shaders/ShaderChunk/lights_lambert_vertex.glsl

@@ -187,10 +187,10 @@ for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 
 
 #endif
 #endif
 
 
-vLightFront = vLightFront * diffuse + diffuse * ambientLightColor + emissive;
+vLightFront += ambientLightColor;
 
 
 #ifdef DOUBLE_SIDED
 #ifdef DOUBLE_SIDED
 
 
-	vLightBack = vLightBack * diffuse + diffuse * ambientLightColor + emissive;
+	vLightBack += ambientLightColor;
 
 
 #endif
 #endif

+ 17 - 57
src/renderers/shaders/ShaderChunk/lights_phong_fragment.glsl

@@ -28,10 +28,10 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 #endif
 #endif
 
 
-#if MAX_POINT_LIGHTS > 0
+vec3 totalDiffuseLight = vec3( 0.0 );
+vec3 totalSpecularLight = vec3( 0.0 );
 
 
-	vec3 pointDiffuse = vec3( 0.0 );
-	vec3 pointSpecular = vec3( 0.0 );
+#if MAX_POINT_LIGHTS > 0
 
 
 	for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
 	for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {
 
 
@@ -42,7 +42,7 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 		lVector = normalize( lVector );
 		lVector = normalize( lVector );
 
 
-				// diffuse
+		// diffuse
 
 
 		float dotProduct = dot( normal, lVector );
 		float dotProduct = dot( normal, lVector );
 
 
@@ -59,7 +59,7 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 		#endif
 		#endif
 
 
-		pointDiffuse += diffuse * pointLightColor[ i ] * pointDiffuseWeight * attenuation;
+		totalDiffuseLight += pointLightColor[ i ] * pointDiffuseWeight * attenuation;
 
 
 				// specular
 				// specular
 
 
@@ -70,7 +70,7 @@ vec3 viewPosition = normalize( vViewPosition );
 		float specularNormalization = ( shininess + 2.0 ) / 8.0;
 		float specularNormalization = ( shininess + 2.0 ) / 8.0;
 
 
 		vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );
 		vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, pointHalfVector ), 0.0 ), 5.0 );
-		pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * attenuation * specularNormalization;
+		totalSpecularLight += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * attenuation * specularNormalization;
 
 
 	}
 	}
 
 
@@ -78,9 +78,6 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 #if MAX_SPOT_LIGHTS > 0
 #if MAX_SPOT_LIGHTS > 0
 
 
-	vec3 spotDiffuse = vec3( 0.0 );
-	vec3 spotSpecular = vec3( 0.0 );
-
 	for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
 	for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {
 
 
 		vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );
 		vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );
@@ -96,7 +93,7 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 			spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );
 			spotEffect = max( pow( max( spotEffect, 0.0 ), spotLightExponent[ i ] ), 0.0 );
 
 
-					// diffuse
+			// diffuse
 
 
 			float dotProduct = dot( normal, lVector );
 			float dotProduct = dot( normal, lVector );
 
 
@@ -113,9 +110,9 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 			#endif
 			#endif
 
 
-			spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * attenuation * spotEffect;
+			totalDiffuseLight += spotLightColor[ i ] * spotDiffuseWeight * attenuation * spotEffect;
 
 
-					// specular
+			// specular
 
 
 			vec3 spotHalfVector = normalize( lVector + viewPosition );
 			vec3 spotHalfVector = normalize( lVector + viewPosition );
 			float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );
 			float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );
@@ -124,7 +121,7 @@ vec3 viewPosition = normalize( vViewPosition );
 			float specularNormalization = ( shininess + 2.0 ) / 8.0;
 			float specularNormalization = ( shininess + 2.0 ) / 8.0;
 
 
 			vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );
 			vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, spotHalfVector ), 0.0 ), 5.0 );
-			spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * attenuation * specularNormalization * spotEffect;
+			totalSpecularLight += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * attenuation * specularNormalization * spotEffect;
 
 
 		}
 		}
 
 
@@ -134,14 +131,11 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 #if MAX_DIR_LIGHTS > 0
 #if MAX_DIR_LIGHTS > 0
 
 
-	vec3 dirDiffuse = vec3( 0.0 );
-	vec3 dirSpecular = vec3( 0.0 );
-
 	for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 	for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {
 
 
 		vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );
 		vec3 dirVector = transformDirection( directionalLightDirection[ i ], viewMatrix );
 
 
-				// diffuse
+		// diffuse
 
 
 		float dotProduct = dot( normal, dirVector );
 		float dotProduct = dot( normal, dirVector );
 
 
@@ -158,7 +152,7 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 		#endif
 		#endif
 
 
-		dirDiffuse += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;
+		totalDiffuseLight += directionalLightColor[ i ] * dirDiffuseWeight;
 
 
 		// specular
 		// specular
 
 
@@ -190,7 +184,7 @@ vec3 viewPosition = normalize( vViewPosition );
 		// 		dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;
 		// 		dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;
 
 
 		vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );
 		vec3 schlick = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( dirVector, dirHalfVector ), 0.0 ), 5.0 );
-		dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;
+		totalSpecularLight += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;
 
 
 
 
 	}
 	}
@@ -199,9 +193,6 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 #if MAX_HEMI_LIGHTS > 0
 #if MAX_HEMI_LIGHTS > 0
 
 
-	vec3 hemiDiffuse = vec3( 0.0 );
-	vec3 hemiSpecular = vec3( 0.0 );
-
 	for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
 	for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {
 
 
 		vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );
 		vec3 lVector = transformDirection( hemisphereLightDirection[ i ], viewMatrix );
@@ -213,7 +204,7 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 		vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
 		vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );
 
 
-		hemiDiffuse += diffuse * hemiColor;
+		totalDiffuseLight += hemiColor;
 
 
 		// specular (sky light)
 		// specular (sky light)
 
 
@@ -235,49 +226,18 @@ vec3 viewPosition = normalize( vViewPosition );
 
 
 		vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );
 		vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVector, hemiHalfVectorSky ), 0.0 ), 5.0 );
 		vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );
 		vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( max( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 0.0 ), 5.0 );
-		hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );
+		totalSpecularLight += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );
 
 
 	}
 	}
 
 
 #endif
 #endif
 
 
-vec3 totalDiffuse = vec3( 0.0 );
-vec3 totalSpecular = vec3( 0.0 );
-
-#if MAX_DIR_LIGHTS > 0
-
-	totalDiffuse += dirDiffuse;
-	totalSpecular += dirSpecular;
-
-#endif
-
-#if MAX_HEMI_LIGHTS > 0
-
-	totalDiffuse += hemiDiffuse;
-	totalSpecular += hemiSpecular;
-
-#endif
-
-#if MAX_POINT_LIGHTS > 0
-
-	totalDiffuse += pointDiffuse;
-	totalSpecular += pointSpecular;
-
-#endif
-
-#if MAX_SPOT_LIGHTS > 0
-
-	totalDiffuse += spotDiffuse;
-	totalSpecular += spotSpecular;
-
-#endif
-
 #ifdef METAL
 #ifdef METAL
 
 
-	gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * diffuse + totalSpecular );
+	outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + ambientLightColor ) * specular + totalSpecularLight + emissive;
 
 
 #else
 #else
 
 
-	gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * diffuse ) + totalSpecular;
+	outgoingLight += diffuseColor.rgb * ( totalDiffuseLight + ambientLightColor ) + totalSpecularLight + emissive;
 
 
 #endif
 #endif

+ 1 - 1
src/renderers/shaders/ShaderChunk/linear_to_gamma_fragment.glsl

@@ -1,2 +1,2 @@
 
 
-	gl_FragColor.xyz = linearToOutput( gl_FragColor.xyz );
+	outgoingLight = linearToOutput( outgoingLight );

+ 1 - 1
src/renderers/shaders/ShaderChunk/map_fragment.glsl

@@ -4,6 +4,6 @@
 
 
 	texelColor.xyz = inputToLinear( texelColor.xyz );
 	texelColor.xyz = inputToLinear( texelColor.xyz );
 
 
-	gl_FragColor = gl_FragColor * texelColor;
+	diffuseColor *= texelColor;
 
 
 #endif
 #endif

+ 1 - 1
src/renderers/shaders/ShaderChunk/map_particle_fragment.glsl

@@ -1,5 +1,5 @@
 #ifdef USE_MAP
 #ifdef USE_MAP
 
 
-	gl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );
+	diffuseColor *= texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) * offsetRepeat.zw + offsetRepeat.xy );
 
 
 #endif
 #endif

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

@@ -197,11 +197,11 @@
 
 
 			#ifdef SHADOWMAP_CASCADE
 			#ifdef SHADOWMAP_CASCADE
 
 
-				if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];
+				if ( inFrustum && inFrustumCount == 1 ) outgoingLight *= frustumColors[ i ];
 
 
 			#else
 			#else
 
 
-				if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];
+				if ( inFrustum ) outgoingLight *= frustumColors[ i ];
 
 
 			#endif
 			#endif
 
 
@@ -212,6 +212,6 @@
 	// NOTE: I am unsure if this is correct in linear space.  -bhouston, Dec 29, 2014
 	// NOTE: I am unsure if this is correct in linear space.  -bhouston, Dec 29, 2014
 	shadowColor = inputToLinear( shadowColor );
 	shadowColor = inputToLinear( shadowColor );
 
 
-	gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;
+	outgoingLight = outgoingLight * shadowColor;
 
 
 #endif
 #endif

+ 43 - 18
src/renderers/shaders/ShaderLib.js

@@ -77,22 +77,28 @@ THREE.ShaderLib = {
 
 
 			"void main() {",
 			"void main() {",
 
 
-			"	gl_FragColor = vec4( diffuse, opacity );",
+			"	vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+			"	vec4 diffuseColor = vec4( diffuse, opacity );",
 
 
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "map_fragment" ],
 				THREE.ShaderChunk[ "map_fragment" ],
+				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "alphamap_fragment" ],
 				THREE.ShaderChunk[ "alphamap_fragment" ],
 				THREE.ShaderChunk[ "alphatest_fragment" ],
 				THREE.ShaderChunk[ "alphatest_fragment" ],
 				THREE.ShaderChunk[ "specularmap_fragment" ],
 				THREE.ShaderChunk[ "specularmap_fragment" ],
-				THREE.ShaderChunk[ "lightmap_fragment" ],
-				THREE.ShaderChunk[ "color_fragment" ],
+
+			"	outgoingLight = diffuseColor.rgb;", // simple shader
+
+				THREE.ShaderChunk[ "lightmap_fragment" ],		// TODO: Light map on an otherwise unlit surface doesn't make sense.
 				THREE.ShaderChunk[ "envmap_fragment" ],
 				THREE.ShaderChunk[ "envmap_fragment" ],
-				THREE.ShaderChunk[ "shadowmap_fragment" ],
+				THREE.ShaderChunk[ "shadowmap_fragment" ],		// TODO: Shadows on an otherwise unlit surface doesn't make sense.
 
 
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
 				THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
 
 
 				THREE.ShaderChunk[ "fog_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 
+			"	gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
 			"}"
 			"}"
 
 
 		].join("\n")
 		].join("\n")
@@ -165,6 +171,8 @@ THREE.ShaderLib = {
 
 
 		fragmentShader: [
 		fragmentShader: [
 
 
+			"uniform vec3 diffuse;",
+			"uniform vec3 emissive;",
 			"uniform float opacity;",
 			"uniform float opacity;",
 
 
 			"varying vec3 vLightFront;",
 			"varying vec3 vLightFront;",
@@ -188,10 +196,12 @@ THREE.ShaderLib = {
 
 
 			"void main() {",
 			"void main() {",
 
 
-			"	gl_FragColor = vec4( vec3( 1.0 ), opacity );",
+			"	vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+			"	vec4 diffuseColor = vec4( diffuse, opacity );",
 
 
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "map_fragment" ],
 				THREE.ShaderChunk[ "map_fragment" ],
+				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "alphamap_fragment" ],
 				THREE.ShaderChunk[ "alphamap_fragment" ],
 				THREE.ShaderChunk[ "alphatest_fragment" ],
 				THREE.ShaderChunk[ "alphatest_fragment" ],
 				THREE.ShaderChunk[ "specularmap_fragment" ],
 				THREE.ShaderChunk[ "specularmap_fragment" ],
@@ -202,18 +212,17 @@ THREE.ShaderLib = {
 					//"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;",
 					//"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;",
 
 
 			"		if ( gl_FrontFacing )",
 			"		if ( gl_FrontFacing )",
-			"			gl_FragColor.xyz *= vLightFront;",
+			"			outgoingLight += diffuseColor.rgb * vLightFront + emissive;",
 			"		else",
 			"		else",
-			"			gl_FragColor.xyz *= vLightBack;",
+			"			outgoingLight += diffuseColor.rgb * vLightBack + emissive;",
 
 
 			"	#else",
 			"	#else",
 
 
-			"		gl_FragColor.xyz *= vLightFront;",
+			"		outgoingLight += diffuseColor.rgb * vLightFront + emissive;",
 
 
 			"	#endif",
 			"	#endif",
 
 
 				THREE.ShaderChunk[ "lightmap_fragment" ],
 				THREE.ShaderChunk[ "lightmap_fragment" ],
-				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "envmap_fragment" ],
 				THREE.ShaderChunk[ "envmap_fragment" ],
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 
 
@@ -221,6 +230,8 @@ THREE.ShaderLib = {
 
 
 				THREE.ShaderChunk[ "fog_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 
+			"	gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
 			"}"
 			"}"
 
 
 		].join("\n")
 		].join("\n")
@@ -281,7 +292,7 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "skinnormal_vertex" ],
 				THREE.ShaderChunk[ "skinnormal_vertex" ],
 				THREE.ShaderChunk[ "defaultnormal_vertex" ],
 				THREE.ShaderChunk[ "defaultnormal_vertex" ],
 
 
-			"#ifndef FLAT_SHADED",
+			"#ifndef FLAT_SHADED", // Normal computed with derivatives when FLAT_SHADED
 
 
 			"	vNormal = normalize( transformedNormal );",
 			"	vNormal = normalize( transformedNormal );",
 
 
@@ -308,11 +319,10 @@ THREE.ShaderLib = {
 			"#define PHONG",
 			"#define PHONG",
 
 
 			"uniform vec3 diffuse;",
 			"uniform vec3 diffuse;",
-			"uniform float opacity;",
-
 			"uniform vec3 emissive;",
 			"uniform vec3 emissive;",
 			"uniform vec3 specular;",
 			"uniform vec3 specular;",
 			"uniform float shininess;",
 			"uniform float shininess;",
+			"uniform float opacity;",
 
 
 			THREE.ShaderChunk[ "common" ],
 			THREE.ShaderChunk[ "common" ],
 			THREE.ShaderChunk[ "color_pars_fragment" ],
 			THREE.ShaderChunk[ "color_pars_fragment" ],
@@ -330,10 +340,12 @@ THREE.ShaderLib = {
 
 
 			"void main() {",
 			"void main() {",
 
 
-			"	gl_FragColor = vec4( vec3( 1.0 ), opacity );",
+			"	vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+			"	vec4 diffuseColor = vec4( diffuse, opacity );",
 
 
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "map_fragment" ],
 				THREE.ShaderChunk[ "map_fragment" ],
+				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "alphamap_fragment" ],
 				THREE.ShaderChunk[ "alphamap_fragment" ],
 				THREE.ShaderChunk[ "alphatest_fragment" ],
 				THREE.ShaderChunk[ "alphatest_fragment" ],
 				THREE.ShaderChunk[ "specularmap_fragment" ],
 				THREE.ShaderChunk[ "specularmap_fragment" ],
@@ -341,7 +353,6 @@ THREE.ShaderLib = {
 				THREE.ShaderChunk[ "lights_phong_fragment" ],
 				THREE.ShaderChunk[ "lights_phong_fragment" ],
 
 
 				THREE.ShaderChunk[ "lightmap_fragment" ],
 				THREE.ShaderChunk[ "lightmap_fragment" ],
-				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "envmap_fragment" ],
 				THREE.ShaderChunk[ "envmap_fragment" ],
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 
 
@@ -349,6 +360,8 @@ THREE.ShaderLib = {
 
 
 				THREE.ShaderChunk[ "fog_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 
+			"	gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
 			"}"
 			"}"
 
 
 		].join("\n")
 		].join("\n")
@@ -410,15 +423,21 @@ THREE.ShaderLib = {
 
 
 			"void main() {",
 			"void main() {",
 
 
-			"	gl_FragColor = vec4( psColor, opacity );",
+			"	vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+			"	vec4 diffuseColor = vec4( psColor, opacity );",
 
 
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "map_particle_fragment" ],
 				THREE.ShaderChunk[ "map_particle_fragment" ],
-				THREE.ShaderChunk[ "alphatest_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
+				THREE.ShaderChunk[ "alphatest_fragment" ],
+
+			"	outgoingLight = diffuseColor.rgb;", // simple shader
+
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "shadowmap_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 
+			"	gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
 			"}"
 			"}"
 
 
 		].join("\n")
 		].join("\n")
@@ -489,12 +508,18 @@ THREE.ShaderLib = {
 
 
 			"	}",
 			"	}",
 
 
-			"	gl_FragColor = vec4( diffuse, opacity );",
+			"	vec3 outgoingLight = vec3( 0.0 );",	// outgoing light does not have an alpha, the surface does
+			"	vec4 diffuseColor = vec4( diffuse, opacity );",
 
 
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "logdepthbuf_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
 				THREE.ShaderChunk[ "color_fragment" ],
+
+			"	outgoingLight = diffuseColor.rgb;", // simple shader
+
 				THREE.ShaderChunk[ "fog_fragment" ],
 				THREE.ShaderChunk[ "fog_fragment" ],
 
 
+			"	gl_FragColor = vec4( outgoingLight, diffuseColor.a );",	// TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
+
 			"}"
 			"}"
 
 
 		].join("\n")
 		].join("\n")
@@ -551,7 +576,7 @@ THREE.ShaderLib = {
 			"	#endif",
 			"	#endif",
 
 
 			"	float color = 1.0 - smoothstep( mNear, mFar, depth );",
 			"	float color = 1.0 - smoothstep( mNear, mFar, depth );",
-			"	gl_FragColor = vec4( vec3( color ), opacity );",
+			"	gl_FragColor = vec4( vec3( color ), opacity );",   // TODO, this should be pre-multiplied to allow for bright highlights on very transparent objects
 
 
 			"}"
 			"}"
 
 

+ 1 - 1
src/renderers/webgl/plugins/ShadowMapPlugin.js

@@ -63,7 +63,7 @@ THREE.ShadowMapPlugin = function ( _renderer, _lights, _webglObjects, _webglObje
 		var i, il, j, jl, n,
 		var i, il, j, jl, n,
 
 
 		shadowMap, shadowMatrix, shadowCamera,
 		shadowMap, shadowMatrix, shadowCamera,
-		program, buffer, material,
+		buffer, material,
 		webglObject, object, light,
 		webglObject, object, light,
 
 
 		lights = [],
 		lights = [],

+ 1 - 0
src/textures/Texture.js

@@ -11,6 +11,7 @@ THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, f
 	this.uuid = THREE.Math.generateUUID();
 	this.uuid = THREE.Math.generateUUID();
 
 
 	this.name = '';
 	this.name = '';
+	this.sourceFile = '';
 
 
 	this.image = image !== undefined ? image : THREE.Texture.DEFAULT_IMAGE;
 	this.image = image !== undefined ? image : THREE.Texture.DEFAULT_IMAGE;
 	this.mipmaps = [];
 	this.mipmaps = [];

+ 64 - 18
utils/build/build.js

@@ -1,7 +1,7 @@
 var fs = require("fs");
 var fs = require("fs");
 var path = require("path");
 var path = require("path");
 var argparse =  require( "argparse" );
 var argparse =  require( "argparse" );
-var uglify = require("uglify-js2");
+var uglify = require("uglify-js");
 var spawn = require('child_process').spawn;
 var spawn = require('child_process').spawn;
 
 
 function main() {
 function main() {
@@ -14,7 +14,7 @@ function main() {
 	parser.addArgument( ['--amd'], { action: 'storeTrue', defaultValue: false } );
 	parser.addArgument( ['--amd'], { action: 'storeTrue', defaultValue: false } );
 	parser.addArgument( ['--minify'], { action: 'storeTrue', defaultValue: false } );
 	parser.addArgument( ['--minify'], { action: 'storeTrue', defaultValue: false } );
 	parser.addArgument( ['--output'], { defaultValue: '../../build/three.js' } );
 	parser.addArgument( ['--output'], { defaultValue: '../../build/three.js' } );
-	parser.addArgument( ['--sourcemaps'], { action: 'storeTrue', defaultValue: false } );
+	parser.addArgument( ['--sourcemaps'], { action: 'storeTrue', defaultValue: true } );
 
 
 	
 	
 	var args = parser.parseArgs();
 	var args = parser.parseArgs();
@@ -28,13 +28,13 @@ function main() {
 	if ( args.sourcemaps ){
 	if ( args.sourcemaps ){
 
 
 		sourcemap = output + '.map';
 		sourcemap = output + '.map';
-		sourcemapping = '\n//@ sourceMappingURL=' + sourcemap;
+		sourcemapping = '\n//# sourceMappingURL=three.min.js.map';
 
 
 	}
 	}
 
 
 	var buffer = [];
 	var buffer = [];
-	var sources = [];
-			
+	var sources = []; // used for source maps with minification
+
 	if ( args.amd ){
 	if ( args.amd ){
 		buffer.push('function ( root, factory ) {\n\n\tif ( typeof define === \'function\' && define.amd ) {\n\n\t\tdefine( [ \'exports\' ], factory );\n\n\t} else if ( typeof exports === \'object\' ) {\n\n\t\tfactory( exports );\n\n\t} else {\n\n\t\tfactory( root );\n\n\t}\n\n}( this, function ( exports ) {\n\n');
 		buffer.push('function ( root, factory ) {\n\n\tif ( typeof define === \'function\' && define.amd ) {\n\n\t\tdefine( [ \'exports\' ], factory );\n\n\t} else if ( typeof exports === \'object\' ) {\n\n\t\tfactory( exports );\n\n\t} else {\n\n\t\tfactory( root );\n\n\t}\n\n}( this, function ( exports ) {\n\n');
 	};
 	};
@@ -50,17 +50,20 @@ function main() {
 			
 			
 			buffer.push('// File:' + files[ j ]);
 			buffer.push('// File:' + files[ j ]);
 			buffer.push('\n\n');
 			buffer.push('\n\n');
+
+			contents = fs.readFileSync( file, 'utf8' );
+
 			if( file.indexOf( '.glsl') >= 0 ) {
 			if( file.indexOf( '.glsl') >= 0 ) {
-				buffer.push('THREE.ShaderChunk[\'' + path.basename(file, '.glsl') + '\'] = "');
-				buffer.push(fs.readFileSync( file, 'utf8' ));
-				buffer.push('";\n\n');
-			}
-			else {
-				sources.push( file );
-				buffer.push( fs.readFileSync( file, 'utf8' ) );
-				buffer.push('\n');
+
+				contents = 'THREE.ShaderChunk[ \'' +
+					path.basename( file, '.glsl' ) + '\' ] =' +
+					JSON.stringify( contents ) + ';\n';
+
 			}
 			}
 
 
+			sources.push( { file: file, contents: contents } );
+			buffer.push( contents );
+			buffer.push( '\n' );
 		}
 		}
 
 
 	}
 	}
@@ -73,17 +76,60 @@ function main() {
 	
 	
 	if ( !args.minify ){
 	if ( !args.minify ){
 
 
-		fs.writeFileSync( output,temp, 'utf8' );
+		fs.writeFileSync( output, temp, 'utf8' );
 
 
 	} else {
 	} else {
 
 
-		var result = uglify.minify( sources, { outSourceMap: sourcemap } );
-		
-		fs.writeFileSync( output, '// threejs.org/license\n' + result.code + sourcemapping, 'utf8' );
+		var LICENSE = "threejs.org/license";
+
+		// Parsing
+
+		var toplevel = null;
+
+		toplevel = uglify.parse( '// ' + LICENSE + '\n' );
+
+		sources.forEach( function( source ) {
+
+			toplevel = uglify.parse( source.contents, {
+				filename: source.file,
+				toplevel: toplevel
+			} );
+
+		} );
+
+		// Compression
+
+		toplevel.figure_out_scope();
+		var compressor = uglify.Compressor( {} );
+		var compressed_ast = toplevel.transform( compressor );
+
+		// Mangling
+
+		compressed_ast.figure_out_scope();
+		compressed_ast.compute_char_frequency();
+		compressed_ast.mangle_names();
+
+		// Output
+
+		var source_map_options = {
+			file: 'three.min.js',
+			root: 'src'
+		};
+
+		var source_map = uglify.SourceMap( source_map_options )
+		var stream = uglify.OutputStream( {
+			source_map: source_map,
+			comments: new RegExp( LICENSE )
+		} );
+
+		compressed_ast.print( stream );
+		var code = stream.toString();
+
+		fs.writeFileSync( output, code + sourcemapping, 'utf8' );
 
 
 		if ( args.sourcemaps ) {
 		if ( args.sourcemaps ) {
 
 
-			fs.writeFileSync( sourcemap, result.map, 'utf8' );
+			fs.writeFileSync( sourcemap, source_map.toString(), 'utf8' );
 
 
 		}
 		}
 
 

+ 2 - 2
utils/build/package.json

@@ -9,8 +9,8 @@
     },
     },
 
 
     "devDependencies": {
     "devDependencies": {
-    	"uglify-js2": "*",
-    	"argparse" : "*"
+        "uglify-js": "^2.4.17",
+        "argparse" : "*"
     },
     },
     
     
     "repository" : {
     "repository" : {

+ 87 - 79
utils/exporters/blender/addons/io_three/__init__.py

@@ -36,13 +36,10 @@ logging.basicConfig(
     format='%(levelname)s:THREE:%(message)s',
     format='%(levelname)s:THREE:%(message)s',
     level=logging.DEBUG)
     level=logging.DEBUG)
 
 
-SETTINGS_FILE_EXPORT = 'three_settings_export.js'
-
-
 bl_info = {
 bl_info = {
     'name': "Three.js Format",
     'name': "Three.js Format",
-    'author': "repsac, mrdoob, yomotsu, mpk, jpweeks",
-    'version': (1, 3, 1),
+    'author': "repsac, mrdoob, yomotsu, mpk, jpweeks, rkusa",
+    'version': (1, 4, 0),
     'blender': (2, 7, 3),
     'blender': (2, 7, 3),
     'location': "File > Export",
     'location': "File > Export",
     'description': "Export Three.js formatted JSON files.",
     'description': "Export Three.js formatted JSON files.",
@@ -53,6 +50,7 @@ bl_info = {
     'category': 'Import-Export'
     'category': 'Import-Export'
 }
 }
 
 
+
 def _geometry_types():
 def _geometry_types():
     """The valid geometry types that are supported by Three.js
     """The valid geometry types that are supported by Three.js
 
 
@@ -257,88 +255,28 @@ class ThreeObject(bpy.types.Panel):
         row = layout.row()
         row = layout.row()
         row.prop(obj, 'THREE_export', text='Export')
         row.prop(obj, 'THREE_export', text='Export')
 
 
-def get_settings_fullpath():
-    """
-
-    :returns: Full path to the settings file (temp directory)
-
-    """
-    return os.path.join(bpy.app.tempdir, SETTINGS_FILE_EXPORT)
-
-
-def save_settings_export(properties):
-    """Save the current export settings to disk.
-
-    :param properties:
-    :returns: settings
-    :rtype: dict
-
-    """
-    settings = {
-        constants.VERTICES: properties.option_vertices,
-        constants.FACES: properties.option_faces,
-        constants.NORMALS: properties.option_normals,
-        constants.SKINNING: properties.option_skinning,
-        constants.BONES: properties.option_bones,
-        constants.GEOMETRY_TYPE: properties.option_geometry_type,
-
-        constants.MATERIALS: properties.option_materials,
-        constants.UVS: properties.option_uv_coords,
-        constants.FACE_MATERIALS: properties.option_face_materials,
-        constants.MAPS: properties.option_maps,
-        constants.COLORS: properties.option_colors,
-        constants.MIX_COLORS: properties.option_mix_colors,
-
-        constants.SCALE: properties.option_scale,
-        constants.ENABLE_PRECISION: properties.option_round_off,
-        constants.PRECISION: properties.option_round_value,
-        constants.LOGGING: properties.option_logging,
-        constants.COMPRESSION: properties.option_compression,
-        constants.INDENT: properties.option_indent,
-        constants.COPY_TEXTURES: properties.option_copy_textures,
-        constants.TEXTURE_FOLDER: properties.option_texture_folder,
+class ThreeExportSettings(bpy.types.Operator):
+    """Save the current export settings (gets saved in .blend)"""
+    bl_label = "Save Settings"
+    bl_idname = "scene.three_export_settings_set"
 
 
-        constants.SCENE: properties.option_export_scene,
-        #constants.EMBED_GEOMETRY: properties.option_embed_geometry,
-        constants.EMBED_ANIMATION: properties.option_embed_animation,
-        constants.LIGHTS: properties.option_lights,
-        constants.CAMERAS: properties.option_cameras,
-        constants.HIERARCHY: properties.option_hierarchy,
-
-        constants.MORPH_TARGETS: properties.option_animation_morph,
-        constants.ANIMATION: properties.option_animation_skeletal,
-        constants.FRAME_STEP: properties.option_frame_step,
-        constants.FRAME_INDEX_AS_TIME: properties.option_frame_index_as_time,
-        constants.INFLUENCES_PER_VERTEX: properties.option_influences
-    }
+    def execute(self, context):
+        cycles = context.scene.cycles
+        cycles.use_samples_final = True
 
 
-    fname = get_settings_fullpath()
-    logging.debug("Saving settings to %s", fname)
-    with open(fname, 'w') as stream:
-        json.dump(settings, stream)
+        context.scene[constants.EXPORT_SETTINGS_KEY] = set_settings(context.active_operator.properties)
 
 
-    return settings
+        self.report({"INFO"}, "Three Export Settings Saved")
 
 
+        return {"FINISHED"}
 
 
-def restore_settings_export(properties):
-    """Restore the settings (if settings file is found on disk)
-    If not found thend default to paramgers defined in
-    constants.EXPORT_OPTIONS
+def restore_export_settings(properties, settings):
+    """Restore the settings
 
 
     :param properties:
     :param properties:
 
 
     """
     """
 
 
-    settings = {}
-
-    fname = get_settings_fullpath()
-    if os.path.exists(fname) and os.access(fname, os.R_OK):
-        logging.debug("Settings cache found %s", fname)
-        with open(fname, 'r') as fs:
-            settings = json.load(fs)
-    else:
-        logging.debug("No settings file found, using defaults.")
-
     ## Geometry {
     ## Geometry {
     properties.option_vertices = settings.get(
     properties.option_vertices = settings.get(
         constants.VERTICES,
         constants.VERTICES,
@@ -472,6 +410,55 @@ def restore_settings_export(properties):
         constants.EXPORT_OPTIONS[constants.FRAME_INDEX_AS_TIME])
         constants.EXPORT_OPTIONS[constants.FRAME_INDEX_AS_TIME])
     ## }
     ## }
 
 
+def set_settings(properties):
+    """Set the export settings to the correct keys.
+
+    :param properties:
+    :returns: settings
+    :rtype: dict
+
+    """
+    settings = {
+        constants.VERTICES: properties.option_vertices,
+        constants.FACES: properties.option_faces,
+        constants.NORMALS: properties.option_normals,
+        constants.SKINNING: properties.option_skinning,
+        constants.BONES: properties.option_bones,
+        constants.GEOMETRY_TYPE: properties.option_geometry_type,
+
+        constants.MATERIALS: properties.option_materials,
+        constants.UVS: properties.option_uv_coords,
+        constants.FACE_MATERIALS: properties.option_face_materials,
+        constants.MAPS: properties.option_maps,
+        constants.COLORS: properties.option_colors,
+        constants.MIX_COLORS: properties.option_mix_colors,
+
+        constants.SCALE: properties.option_scale,
+        constants.ENABLE_PRECISION: properties.option_round_off,
+        constants.PRECISION: properties.option_round_value,
+        constants.LOGGING: properties.option_logging,
+        constants.COMPRESSION: properties.option_compression,
+        constants.INDENT: properties.option_indent,
+        constants.COPY_TEXTURES: properties.option_copy_textures,
+        constants.TEXTURE_FOLDER: properties.option_texture_folder,
+
+        constants.SCENE: properties.option_export_scene,
+        #constants.EMBED_GEOMETRY: properties.option_embed_geometry,
+        constants.EMBED_ANIMATION: properties.option_embed_animation,
+        constants.LIGHTS: properties.option_lights,
+        constants.CAMERAS: properties.option_cameras,
+        constants.HIERARCHY: properties.option_hierarchy,
+
+        constants.MORPH_TARGETS: properties.option_animation_morph,
+        constants.ANIMATION: properties.option_animation_skeletal,
+        constants.FRAME_STEP: properties.option_frame_step,
+        constants.FRAME_INDEX_AS_TIME: properties.option_frame_index_as_time,
+        constants.INFLUENCES_PER_VERTEX: properties.option_influences
+    }
+
+    return settings
+
+
 def compression_types():
 def compression_types():
     """Supported compression formats
     """Supported compression formats
 
 
@@ -489,6 +476,7 @@ def compression_types():
 
 
     return types
     return types
 
 
+
 def animation_options():
 def animation_options():
     """The supported skeletal animation types
     """The supported skeletal animation types
 
 
@@ -508,6 +496,7 @@ class ExportThree(bpy.types.Operator, ExportHelper):
 
 
     bl_idname = 'export.three'
     bl_idname = 'export.three'
     bl_label = 'Export THREE'
     bl_label = 'Export THREE'
+    bl_options = {'PRESET'}
 
 
     filename_ext = constants.EXTENSION
     filename_ext = constants.EXTENSION
 
 
@@ -692,7 +681,17 @@ class ExportThree(bpy.types.Operator, ExportHelper):
         default=2)
         default=2)
 
 
     def invoke(self, context, event):
     def invoke(self, context, event):
-        restore_settings_export(self.properties)
+        settings = context.scene.get(constants.EXPORT_SETTINGS_KEY)
+        if settings:
+            try:
+                restore_export_settings(self.properties, settings)
+            except AttributeError as e:
+                logging.error("Loading export settings failed:")
+                logging.exception(e)
+                logging.debug("Removed corrupted settings")
+
+                del context.scene[constants.EXPORT_SETTINGS_KEY]
+
         return ExportHelper.invoke(self, context, event)
         return ExportHelper.invoke(self, context, event)
 
 
     @classmethod
     @classmethod
@@ -713,7 +712,7 @@ class ExportThree(bpy.types.Operator, ExportHelper):
         if not self.properties.filepath:
         if not self.properties.filepath:
             raise Exception("filename not set")
             raise Exception("filename not set")
 
 
-        settings = save_settings_export(self.properties)
+        settings = set_settings(self.properties)
         settings['addon_version'] = bl_info['version']
         settings['addon_version'] = bl_info['version']
 
 
         filepath = self.filepath
         filepath = self.filepath
@@ -865,6 +864,15 @@ class ExportThree(bpy.types.Operator, ExportHelper):
         row.prop(self.properties, 'option_indent')
         row.prop(self.properties, 'option_indent')
         ## }
         ## }
 
 
+        ## Operators {
+        has_settings = context.scene.get(constants.EXPORT_SETTINGS_KEY, False)
+        row = layout.row()
+        row.operator(
+            ThreeExportSettings.bl_idname,
+            ThreeExportSettings.bl_label,
+            icon="%s" % "PINNED" if has_settings else "UNPINNED")
+        ## }
+
 
 
 
 
 def menu_func_export(self, context):
 def menu_func_export(self, context):

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

@@ -329,3 +329,4 @@ DBG_COLORS = (0xeeeeee, 0xee0000, 0x00ee00, 0x0000ee,
 
 
 DOUBLE_SIDED = 'doubleSided'
 DOUBLE_SIDED = 'doubleSided'
 
 
+EXPORT_SETTINGS_KEY = 'threeExportSettings'

+ 4 - 12
utils/exporters/blender/addons/io_three/exporter/_json.py

@@ -5,18 +5,10 @@ ROUND = constants.DEFAULT_PRECISION
 
 
 ## THREE override function
 ## THREE override function
 def _json_floatstr(o):
 def _json_floatstr(o):
-    s = str(o)
-
-    if ROUND is None:
-        return s
-
-    if '.' in s and len(s[s.index('.'):]) > ROUND - 1:
-        s = '%.{0}f'.format(ROUND) % o
-        while '.' in s and s[-1] == '0':
-            s = s[:-1] # this actually removes the last '0' from the string
-        if s[-1] == '.': # added this test to avoid leaving '0.' instead of '0.0',
-            s += '0'    # which would throw an error while loading the file
-    return s
+    if ROUND is not None:
+        o = round(o, ROUND)
+        
+    return '%g' % o
 
 
 
 
 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,
 def _make_iterencode(markers, _default, _encoder, _indent, _floatstr,

+ 27 - 55
utils/exporters/blender/addons/io_three/exporter/api/animation.py

@@ -1,7 +1,11 @@
+"""
+Module for handling the parsing of skeletal animation data.
+"""
+
 import math
 import math
 import mathutils
 import mathutils
 from bpy import data, context
 from bpy import data, context
-from .. import constants, logger, utilities
+from .. import constants, logger
 
 
 
 
 def pose_animation(armature, options):
 def pose_animation(armature, options):
@@ -42,22 +46,19 @@ def _parse_action(func, armature, options):
     """
     """
     animations = []
     animations = []
     logger.info("Parsing %d actions", len(data.actions))
     logger.info("Parsing %d actions", len(data.actions))
-    round_off, round_val = utilities.rounding(options)
     for action in data.actions:
     for action in data.actions:
         logger.info("Parsing action %s", action.name)
         logger.info("Parsing action %s", action.name)
-        animation = func(action, armature, options, round_off, round_val)
+        animation = func(action, armature, options)
         animations.append(animation)
         animations.append(animation)
     return animations
     return animations
 
 
 
 
-def _parse_rest_action(action, armature, options, round_off, round_val):
+def _parse_rest_action(action, armature, options):
     """
     """
 
 
     :param action:
     :param action:
     :param armature:
     :param armature:
     :param options:
     :param options:
-    :param round_off:
-    :param round_val:
 
 
     """
     """
     end_frame = action.frame_range[1]
     end_frame = action.frame_range[1]
@@ -91,19 +92,13 @@ def _parse_rest_action(action, armature, options, round_off, round_val):
                                      action, rotation_matrix)
                                      action, rotation_matrix)
             rot = _normalize_quaternion(rot)
             rot = _normalize_quaternion(rot)
 
 
-            if round_off:
-                pos_x, pos_y, pos_z = utilities.round_off(
-                    [pos.x, pos.z, -pos.y], round_val)
-                rot_x, rot_y, rot_z, rot_w = utilities.round_off(
-                    [rot.x, rot.z, -rot.y, rot.w], round_val)
-            else:
-                pos_x, pos_y, pos_z = pos.x, pos.z, -pos.y
-                rot_x, rot_y, rot_z, rot_w = rot.x, rot.z, -rot.y, rot.w
+            pos_x, pos_y, pos_z = pos.x, pos.z, -pos.y
+            rot_x, rot_y, rot_z, rot_w = rot.x, rot.z, -rot.y, rot.w
 
 
             if frame == start_frame:
             if frame == start_frame:
 
 
                 time = (frame * frame_step - start_frame) / fps
                 time = (frame * frame_step - start_frame) / fps
-                #@TODO: missing scale values
+                # @TODO: missing scale values
                 keyframe = {
                 keyframe = {
                     constants.TIME: time,
                     constants.TIME: time,
                     constants.POS: [pos_x, pos_y, pos_z],
                     constants.POS: [pos_x, pos_y, pos_z],
@@ -129,22 +124,22 @@ def _parse_rest_action(action, armature, options, round_off, round_val):
             # MIDDLE-FRAME: needs only one of the attributes,
             # MIDDLE-FRAME: needs only one of the attributes,
             # can be an empty frame (optional frame)
             # can be an empty frame (optional frame)
 
 
-            elif pchange == True or rchange == True:
+            elif pchange is True or rchange is True:
 
 
                 time = (frame * frame_step - start_frame) / fps
                 time = (frame * frame_step - start_frame) / fps
 
 
-                if pchange == True and rchange == True:
+                if pchange is True and rchange is True:
                     keyframe = {
                     keyframe = {
                         constants.TIME: time,
                         constants.TIME: time,
                         constants.POS: [pos_x, pos_y, pos_z],
                         constants.POS: [pos_x, pos_y, pos_z],
                         constants.ROT: [rot_x, rot_y, rot_z, rot_w]
                         constants.ROT: [rot_x, rot_y, rot_z, rot_w]
                     }
                     }
-                elif pchange == True:
+                elif pchange is True:
                     keyframe = {
                     keyframe = {
                         constants.TIME: time,
                         constants.TIME: time,
                         constants.POS: [pos_x, pos_y, pos_z]
                         constants.POS: [pos_x, pos_y, pos_z]
                     }
                     }
-                elif rchange == True:
+                elif rchange is True:
                     keyframe = {
                     keyframe = {
                         constants.TIME: time,
                         constants.TIME: time,
                         constants.ROT: [rot_x, rot_y, rot_z, rot_w]
                         constants.ROT: [rot_x, rot_y, rot_z, rot_w]
@@ -160,7 +155,7 @@ def _parse_rest_action(action, armature, options, round_off, round_val):
 
 
     animation = {
     animation = {
         constants.HIERARCHY: hierarchy,
         constants.HIERARCHY: hierarchy,
-        constants.LENGTH:frame_length / fps,
+        constants.LENGTH: frame_length / fps,
         constants.FPS: fps,
         constants.FPS: fps,
         constants.NAME: action.name
         constants.NAME: action.name
     }
     }
@@ -168,20 +163,18 @@ def _parse_rest_action(action, armature, options, round_off, round_val):
     return animation
     return animation
 
 
 
 
-def _parse_pose_action(action, armature, options, round_off, round_val):
+def _parse_pose_action(action, armature, options):
     """
     """
 
 
     :param action:
     :param action:
     :param armature:
     :param armature:
     :param options:
     :param options:
-    :param round_off:
-    :param round_val:
 
 
     """
     """
-    #@TODO: this seems to fail in batch mode meaning the
-    #       user has to have th GUI open. need to improve
-    #       this logic to allow batch processing, if Blender
-    #       chooses to behave....
+    # @TODO: this seems to fail in batch mode meaning the
+    #        user has to have th GUI open. need to improve
+    #        this logic to allow batch processing, if Blender
+    #        chooses to behave....
     current_context = context.area.type
     current_context = context.area.type
     context.area.type = 'DOPESHEET_EDITOR'
     context.area.type = 'DOPESHEET_EDITOR'
     context.space_data.mode = 'ACTION'
     context.space_data.mode = 'ACTION'
@@ -285,27 +278,9 @@ def _parse_pose_action(action, armature, options, round_off, round_val):
             schange = True or has_keyframe_at(
             schange = True or has_keyframe_at(
                 channels_scale[bone_index], frame)
                 channels_scale[bone_index], frame)
 
 
-            if round_off:
-                pos = (
-                    utilities.round_off(pos.x, round_val),
-                    utilities.round_off(pos.z, round_val),
-                    -utilities.round_off(pos.y, round_val)
-                )
-                rot = (
-                    utilities.round_off(rot.x, round_val),
-                    utilities.round_off(rot.z, round_val),
-                    -utilities.round_off(rot.y, round_val),
-                    utilities.round_off(rot.w, round_val)
-                )
-                scl = (
-                    utilities.round_off(scl.x, round_val),
-                    utilities.round_off(scl.z, round_val),
-                    utilities.round_off(scl.y, round_val)
-                )
-            else:
-                pos = (pos.x, pos.z, -pos.y)
-                rot = (rot.x, rot.z, -rot.y, rot.w)
-                scl = (scl.x, scl.z, scl.y)
+            pos = (pos.x, pos.z, -pos.y)
+            rot = (rot.x, rot.z, -rot.y, rot.w)
+            scl = (scl.x, scl.z, scl.y)
 
 
             keyframe = {constants.TIME: time}
             keyframe = {constants.TIME: time}
             if frame == start_frame or frame == end_frame:
             if frame == start_frame or frame == end_frame:
@@ -349,7 +324,7 @@ def _parse_pose_action(action, armature, options, round_off, round_val):
 
 
     animation = {
     animation = {
         constants.HIERARCHY: hierarchy,
         constants.HIERARCHY: hierarchy,
-        constants.LENGTH:frame_length,
+        constants.LENGTH: frame_length,
         constants.FPS: fps,
         constants.FPS: fps,
         constants.NAME: action.name
         constants.NAME: action.name
     }
     }
@@ -373,7 +348,7 @@ def _find_channels(action, bone, channel_type):
         for index, group in enumerate(action.groups):
         for index, group in enumerate(action.groups):
             if group.name == bone.name:
             if group.name == bone.name:
                 group_index = index
                 group_index = index
-                #@TODO: break?
+                # @TODO: break?
 
 
         if group_index > -1:
         if group_index > -1:
             for channel in action.groups[group_index].channels:
             for channel in action.groups[group_index].channels:
@@ -426,8 +401,7 @@ def _position(bone, frame, action, armature_matrix):
 
 
         for channel in action.fcurves:
         for channel in action.fcurves:
             data_path = channel.data_path
             data_path = channel.data_path
-            if bone_label in data_path and \
-            "location" in data_path:
+            if bone_label in data_path and "location" in data_path:
                 has_changed = _handle_position_channel(
                 has_changed = _handle_position_channel(
                     channel, frame, position)
                     channel, frame, position)
                 change = change or has_changed
                 change = change or has_changed
@@ -497,8 +471,7 @@ def _rotation(bone, frame, action, armature_matrix):
 
 
         for channel in action.fcurves:
         for channel in action.fcurves:
             data_path = channel.data_path
             data_path = channel.data_path
-            if bone_label in data_path and \
-            "quaternion" in data_path:
+            if bone_label in data_path and "quaternion" in data_path:
                 has_changed = _handle_rotation_channel(
                 has_changed = _handle_rotation_channel(
                     channel, frame, rotation)
                     channel, frame, rotation)
                 change = change or has_changed
                 change = change or has_changed
@@ -602,4 +575,3 @@ def _normalize_quaternion(quat):
         enum.z = quat.z * length
         enum.z = quat.z * length
         enum.w = quat.w * length
         enum.w = quat.w * length
     return enum
     return enum
-

+ 7 - 3
utils/exporters/blender/addons/io_three/exporter/api/material.py

@@ -179,7 +179,7 @@ def light_map(material):
 
 
     """
     """
     logger.debug("material.light_map(%s)", material)
     logger.debug("material.light_map(%s)", material)
-    for texture in _valid_textures(material):
+    for texture in _valid_textures(material, strict_use=False):
         if texture.use_map_color_diffuse and \
         if texture.use_map_color_diffuse and \
         texture.blend_type == MULTIPLY:
         texture.blend_type == MULTIPLY:
             return texture.texture
             return texture.texture
@@ -370,7 +370,7 @@ def wireframe(material):
     return material.type == WIRE
     return material.type == WIRE
 
 
 
 
-def _valid_textures(material):
+def _valid_textures(material, strict_use=True):
     """
     """
 
 
     :param material:
     :param material:
@@ -380,7 +380,11 @@ def _valid_textures(material):
     for texture in material.texture_slots:
     for texture in material.texture_slots:
         if not texture:
         if not texture:
             continue
             continue
-        if texture.texture.type != IMAGE or not texture.use:
+        if strict_use:
+            in_use = texture.use
+        else:
+            in_use = True
+        if texture.texture.type != IMAGE or not in_use:
             continue
             continue
         logger.debug("Valid texture found %s", texture)
         logger.debug("Valid texture found %s", texture)
         yield texture
         yield texture

+ 58 - 123
utils/exporters/blender/addons/io_three/exporter/api/mesh.py

@@ -1,3 +1,9 @@
+"""
+Blender API for querying mesh data. Animation data is also
+handled here since Three.js associates the animation (skeletal,
+morph targets) with the geometry nodes.
+"""
+
 import operator
 import operator
 from bpy import data, types, context
 from bpy import data, types, context
 from . import material, texture, animation
 from . import material, texture, animation
@@ -37,6 +43,7 @@ def skeletal_animation(mesh, options):
 
 
     :param mesh:
     :param mesh:
     :param options:
     :param options:
+    :rtype: []
 
 
     """
     """
     logger.debug("mesh.animation(%s, %s)", mesh, options)
     logger.debug("mesh.animation(%s, %s)", mesh, options)
@@ -47,16 +54,16 @@ def skeletal_animation(mesh, options):
         return []
         return []
 
 
     anim_type = options.get(constants.ANIMATION)
     anim_type = options.get(constants.ANIMATION)
-    #pose_position = armature.data.pose_position
+#    pose_position = armature.data.pose_position
     dispatch = {
     dispatch = {
         constants.POSE: animation.pose_animation,
         constants.POSE: animation.pose_animation,
         constants.REST: animation.rest_animation
         constants.REST: animation.rest_animation
     }
     }
 
 
     func = dispatch[anim_type]
     func = dispatch[anim_type]
-    #armature.data.pose_position = anim_type.upper()
+#    armature.data.pose_position = anim_type.upper()
     animations = func(armature, options)
     animations = func(armature, options)
-    #armature.data.pose_position = pose_position
+#    armature.data.pose_position = pose_position
 
 
     return animations
     return animations
 
 
@@ -67,6 +74,7 @@ def bones(mesh, options):
 
 
     :param mesh:
     :param mesh:
     :param options:
     :param options:
+    :rtype: [], {}
 
 
     """
     """
     logger.debug("mesh.bones(%s)", mesh)
     logger.debug("mesh.bones(%s)", mesh)
@@ -75,15 +83,14 @@ def bones(mesh, options):
     if not armature:
     if not armature:
         return [], {}
         return [], {}
 
 
-    round_off, round_val = utilities.rounding(options)
     anim_type = options.get(constants.ANIMATION)
     anim_type = options.get(constants.ANIMATION)
-    #pose_position = armature.data.pose_position
+#    pose_position = armature.data.pose_position
 
 
     if anim_type == constants.OFF:
     if anim_type == constants.OFF:
-        logger.info("Animation type not set, defaulting "\
-            "to using REST position for the armature.")
+        logger.info("Animation type not set, defaulting "
+                    "to using REST position for the armature.")
         func = _rest_bones
         func = _rest_bones
-        #armature.data.pose_position = "REST"
+#        armature.data.pose_position = "REST"
     else:
     else:
         dispatch = {
         dispatch = {
             constants.REST: _rest_bones,
             constants.REST: _rest_bones,
@@ -91,24 +98,23 @@ def bones(mesh, options):
         }
         }
         logger.info("Using %s for the armature", anim_type)
         logger.info("Using %s for the armature", anim_type)
         func = dispatch[anim_type]
         func = dispatch[anim_type]
-        #armature.data.pose_position = anim_type.upper()
+#        armature.data.pose_position = anim_type.upper()
 
 
-    bones_, bone_map = func(armature, round_off, round_val)
-    #armature.data.pose_position = pose_position
+    bones_, bone_map = func(armature)
+#    armature.data.pose_position = pose_position
 
 
     return (bones_, bone_map)
     return (bones_, bone_map)
 
 
 
 
 @_mesh
 @_mesh
-def buffer_normal(mesh, options):
+def buffer_normal(mesh):
     """
     """
 
 
     :param mesh:
     :param mesh:
-    :param options:
+    :rtype: []
 
 
     """
     """
     normals_ = []
     normals_ = []
-    round_off, round_val = utilities.rounding(options)
 
 
     for face in mesh.tessfaces:
     for face in mesh.tessfaces:
         vert_count = len(face.vertices)
         vert_count = len(face.vertices)
@@ -119,24 +125,20 @@ def buffer_normal(mesh, options):
         for vertex_index in face.vertices:
         for vertex_index in face.vertices:
             normal = mesh.vertices[vertex_index].normal
             normal = mesh.vertices[vertex_index].normal
             vector = (normal.x, normal.y, normal.z)
             vector = (normal.x, normal.y, normal.z)
-            if round_off:
-                vector = utilities.round_off(vector, round_val)
-
             normals_.extend(vector)
             normals_.extend(vector)
 
 
     return normals_
     return normals_
 
 
 
 
 @_mesh
 @_mesh
-def buffer_position(mesh, options):
+def buffer_position(mesh):
     """
     """
 
 
     :param mesh:
     :param mesh:
-    :param options:
+    :rtype: []
 
 
     """
     """
     position = []
     position = []
-    round_off, round_val = utilities.rounding(options)
 
 
     for face in mesh.tessfaces:
     for face in mesh.tessfaces:
         vert_count = len(face.vertices)
         vert_count = len(face.vertices)
@@ -147,35 +149,29 @@ def buffer_position(mesh, options):
         for vertex_index in face.vertices:
         for vertex_index in face.vertices:
             vertex = mesh.vertices[vertex_index]
             vertex = mesh.vertices[vertex_index]
             vector = (vertex.co.x, vertex.co.y, vertex.co.z)
             vector = (vertex.co.x, vertex.co.y, vertex.co.z)
-            if round_off:
-                vector = utilities.round_off(vector, round_val)
-
             position.extend(vector)
             position.extend(vector)
 
 
     return position
     return position
 
 
 
 
 @_mesh
 @_mesh
-def buffer_uv(mesh, options):
+def buffer_uv(mesh):
     """
     """
 
 
     :param mesh:
     :param mesh:
-    :param options:
+    :rtype: []
 
 
     """
     """
+    uvs_ = []
     if len(mesh.uv_layers) is 0:
     if len(mesh.uv_layers) is 0:
-        return
+        return uvs_
     elif len(mesh.uv_layers) > 1:
     elif len(mesh.uv_layers) > 1:
         # if memory serves me correctly buffer geometry
         # if memory serves me correctly buffer geometry
         # only uses one UV layer
         # only uses one UV layer
         logger.warning("%s has more than 1 UV layer", mesh.name)
         logger.warning("%s has more than 1 UV layer", mesh.name)
 
 
-    round_off, round_val = utilities.rounding(options)
-    uvs_ = []
     for uv_data in mesh.uv_layers[0].data:
     for uv_data in mesh.uv_layers[0].data:
         uv_tuple = (uv_data.uv[0], uv_data.uv[1])
         uv_tuple = (uv_data.uv[0], uv_data.uv[1])
-        if round_off:
-            uv_tuple = utilities.round_off(uv_tuple, round_val)
         uvs_.extend(uv_tuple)
         uvs_.extend(uv_tuple)
 
 
     return uvs_
     return uvs_
@@ -195,10 +191,6 @@ def faces(mesh, options):
     logger.info("Has UVs = %s", vertex_uv)
     logger.info("Has UVs = %s", vertex_uv)
     logger.info("Has vertex colours = %s", has_colors)
     logger.info("Has vertex colours = %s", has_colors)
 
 
-    round_off, round_val = utilities.rounding(options)
-    if round_off:
-        logger.debug("Rounding off of vectors set to %s", round_off)
-
     opt_colours = options[constants.COLORS] and has_colors
     opt_colours = options[constants.COLORS] and has_colors
     opt_uvs = options[constants.UVS] and vertex_uv
     opt_uvs = options[constants.UVS] and vertex_uv
     opt_materials = options.get(constants.FACE_MATERIALS)
     opt_materials = options.get(constants.FACE_MATERIALS)
@@ -208,8 +200,8 @@ def faces(mesh, options):
     logger.debug("Materials enabled = %s", opt_materials)
     logger.debug("Materials enabled = %s", opt_materials)
     logger.debug("Normals enabled = %s", opt_normals)
     logger.debug("Normals enabled = %s", opt_normals)
 
 
-    uv_layers = _uvs(mesh, options) if opt_uvs else None
-    vertex_normals = _normals(mesh, options) if opt_normals else None
+    uv_layers = _uvs(mesh) if opt_uvs else None
+    vertex_normals = _normals(mesh) if opt_normals else None
     vertex_colours = vertex_colors(mesh) if opt_colours else None
     vertex_colours = vertex_colors(mesh) if opt_colours else None
 
 
     faces_data = []
     faces_data = []
@@ -252,17 +244,14 @@ def faces(mesh, options):
         if mask[constants.MATERIALS]:
         if mask[constants.MATERIALS]:
             face_data.append(face.material_index)
             face_data.append(face.material_index)
 
 
-        #@TODO: this needs the same optimization as what
-        #       was done for colours and normals
+        # @TODO: this needs the same optimization as what
+        #        was done for colours and normals
         if uv_layers:
         if uv_layers:
             for index, uv_layer in enumerate(uv_layers):
             for index, uv_layer in enumerate(uv_layers):
                 layer = mesh.tessface_uv_textures[index]
                 layer = mesh.tessface_uv_textures[index]
 
 
                 for uv_data in layer.data[face.index].uv:
                 for uv_data in layer.data[face.index].uv:
                     uv_tuple = (uv_data[0], uv_data[1])
                     uv_tuple = (uv_data[0], uv_data[1])
-                    if round_off:
-                        uv_tuple = utilities.round_off(
-                            uv_tuple, round_val)
                     face_data.append(uv_layer.index(uv_tuple))
                     face_data.append(uv_layer.index(uv_tuple))
                     mask[constants.UVS] = True
                     mask[constants.UVS] = True
 
 
@@ -270,8 +259,6 @@ def faces(mesh, options):
             for vertex in face.vertices:
             for vertex in face.vertices:
                 normal = mesh.vertices[vertex].normal
                 normal = mesh.vertices[vertex].normal
                 normal = (normal.x, normal.y, normal.z)
                 normal = (normal.x, normal.y, normal.z)
-                if round_off:
-                    normal = utilities.round_off(normal, round_val)
                 face_data.append(normal_indices[str(normal)])
                 face_data.append(normal_indices[str(normal)])
                 mask[constants.NORMALS] = True
                 mask[constants.NORMALS] = True
 
 
@@ -310,7 +297,6 @@ def morph_targets(mesh, options):
                          frame_step)
                          frame_step)
 
 
     morphs = []
     morphs = []
-    round_off, round_val = utilities.rounding(options)
 
 
     for frame in scene_frames:
     for frame in scene_frames:
         logger.info("Processing data at frame %d", frame)
         logger.info("Processing data at frame %d", frame)
@@ -319,15 +305,7 @@ def morph_targets(mesh, options):
         vertices_ = object_.extract_mesh(obj, options).vertices[:]
         vertices_ = object_.extract_mesh(obj, options).vertices[:]
 
 
         for vertex in vertices_:
         for vertex in vertices_:
-            if round_off:
-                vectors = [
-                    utilities.round_off(vertex.co.x, round_val),
-                    utilities.round_off(vertex.co.y, round_val),
-                    utilities.round_off(vertex.co.z, round_val)
-                ]
-            else:
-                vectors = [vertex.co.x, vertex.co.y, vertex.co.z]
-            morphs[-1].extend(vectors)
+            morphs[-1].extend([vertex.co.x, vertex.co.y, vertex.co.z])
 
 
     context.scene.frame_set(original_frame, 0.0)
     context.scene.frame_set(original_frame, 0.0)
     morphs_detected = False
     morphs_detected = False
@@ -449,17 +427,17 @@ def materials(mesh, options):
 
 
 
 
 @_mesh
 @_mesh
-def normals(mesh, options):
+def normals(mesh):
     """
     """
 
 
     :param mesh:
     :param mesh:
-    :param options:
+    :rtype: []
 
 
     """
     """
-    logger.debug("mesh.normals(%s, %s)", mesh, options)
+    logger.debug("mesh.normals(%s)", mesh)
     normal_vectors = []
     normal_vectors = []
 
 
-    for vector in _normals(mesh, options):
+    for vector in _normals(mesh):
         normal_vectors.extend(vector)
         normal_vectors.extend(vector)
 
 
     return normal_vectors
     return normal_vectors
@@ -544,16 +522,16 @@ def texture_registration(mesh):
 
 
 
 
 @_mesh
 @_mesh
-def uvs(mesh, options):
+def uvs(mesh):
     """
     """
 
 
     :param mesh:
     :param mesh:
-    :param options:
+    :rtype: []
 
 
     """
     """
-    logger.debug("mesh.uvs(%s, %s)", mesh, options)
+    logger.debug("mesh.uvs(%s)", mesh)
     uvs_ = []
     uvs_ = []
-    for layer in _uvs(mesh, options):
+    for layer in _uvs(mesh):
         uvs_.append([])
         uvs_.append([])
         logger.info("Parsing UV layer %d", len(uvs_))
         logger.info("Parsing UV layer %d", len(uvs_))
         for pair in layer:
         for pair in layer:
@@ -594,24 +572,18 @@ def vertex_colors(mesh):
 
 
 
 
 @_mesh
 @_mesh
-def vertices(mesh, options):
+def vertices(mesh):
     """
     """
 
 
     :param mesh:
     :param mesh:
-    :param options:
+    :rtype: []
 
 
     """
     """
-    logger.debug("mesh.vertices(%s, %s)", mesh, options)
+    logger.debug("mesh.vertices(%s)", mesh)
     vertices_ = []
     vertices_ = []
 
 
-    round_off, round_val = utilities.rounding(options)
-
     for vertex in mesh.vertices:
     for vertex in mesh.vertices:
-        vector = (vertex.co.x, vertex.co.y, vertex.co.z)
-        if round_off:
-            vector = utilities.round_off(vector, round_val)
-
-        vertices_.extend(vector)
+        vertices_.extend((vertex.co.x, vertex.co.y, vertex.co.z))
 
 
     return vertices_
     return vertices_
 
 
@@ -740,15 +712,14 @@ def _diffuse_map(mat):
     return diffuse
     return diffuse
 
 
 
 
-def _normals(mesh, options):
+def _normals(mesh):
     """
     """
 
 
     :param mesh:
     :param mesh:
-    :param options:
+    :rtype: []
 
 
     """
     """
     vectors = []
     vectors = []
-    round_off, round_val = utilities.rounding(options)
 
 
     vectors_ = {}
     vectors_ = {}
     for face in mesh.tessfaces:
     for face in mesh.tessfaces:
@@ -756,8 +727,6 @@ def _normals(mesh, options):
         for vertex_index in face.vertices:
         for vertex_index in face.vertices:
             normal = mesh.vertices[vertex_index].normal
             normal = mesh.vertices[vertex_index].normal
             vector = (normal.x, normal.y, normal.z)
             vector = (normal.x, normal.y, normal.z)
-            if round_off:
-                vector = utilities.round_off(vector, round_val)
 
 
             str_vec = str(vector)
             str_vec = str(vector)
             try:
             try:
@@ -769,23 +738,19 @@ def _normals(mesh, options):
     return vectors
     return vectors
 
 
 
 
-def _uvs(mesh, options):
+def _uvs(mesh):
     """
     """
 
 
     :param mesh:
     :param mesh:
-    :param options:
 
 
     """
     """
     uv_layers = []
     uv_layers = []
-    round_off, round_val = utilities.rounding(options)
 
 
     for layer in mesh.uv_layers:
     for layer in mesh.uv_layers:
         uv_layers.append([])
         uv_layers.append([])
 
 
         for uv_data in layer.data:
         for uv_data in layer.data:
             uv_tuple = (uv_data.uv[0], uv_data.uv[1])
             uv_tuple = (uv_data.uv[0], uv_data.uv[1])
-            if round_off:
-                uv_tuple = utilities.round_off(uv_tuple, round_val)
 
 
             if uv_tuple not in uv_layers[-1]:
             if uv_tuple not in uv_layers[-1]:
                 uv_layers[-1].append(uv_tuple)
                 uv_layers[-1].append(uv_tuple)
@@ -853,12 +818,11 @@ def _skinning_data(mesh, bone_map, influences, array_index):
     return manifest
     return manifest
 
 
 
 
-def _pose_bones(armature, round_off, round_val):
+def _pose_bones(armature):
     """
     """
 
 
     :param armature:
     :param armature:
-    :param round_off:
-    :param round_val:
+    :rtype: [], {}
 
 
     """
     """
     bones_ = []
     bones_ = []
@@ -889,44 +853,22 @@ def _pose_bones(armature, round_off, round_val):
         bone_map[bone_count] = bone_count
         bone_map[bone_count] = bone_count
 
 
         pos, rot, scl = bone_matrix.decompose()
         pos, rot, scl = bone_matrix.decompose()
-        if round_off:
-            pos = (
-                utilities.round_off(pos.x, round_val),
-                utilities.round_off(pos.z, round_val),
-                -utilities.round_off(pos.y, round_val)
-            )
-            rot = (
-                utilities.round_off(rot.x, round_val),
-                utilities.round_off(rot.z, round_val),
-                -utilities.round_off(rot.y, round_val),
-                utilities.round_off(rot.w, round_val)
-            )
-            scl = (
-                utilities.round_off(scl.x, round_val),
-                utilities.round_off(scl.z, round_val),
-                utilities.round_off(scl.y, round_val)
-            )
-        else:
-            pos = (pos.x, pos.z, -pos.y)
-            rot = (rot.x, rot.z, -rot.y, rot.w)
-            scl = (scl.x, scl.z, scl.y)
         bones_.append({
         bones_.append({
             constants.PARENT: bone_index,
             constants.PARENT: bone_index,
             constants.NAME: armature_bone.name,
             constants.NAME: armature_bone.name,
-            constants.POS: pos,
-            constants.ROTQ: rot,
-            constants.SCL: scl
+            constants.POS: (pos.x, pos.z, -pos.y),
+            constants.ROTQ: (rot.x, rot.z, -rot.y, rot.w),
+            constants.SCL: (scl.x, scl.z, scl.y)
         })
         })
 
 
     return bones_, bone_map
     return bones_, bone_map
 
 
 
 
-def _rest_bones(armature, round_off, round_val):
+def _rest_bones(armature):
     """
     """
 
 
     :param armature:
     :param armature:
-    :param round_off:
-    :param round_val:
+    :rtype: [], {}
 
 
     """
     """
     bones_ = []
     bones_ = []
@@ -955,21 +897,16 @@ def _rest_bones(armature, round_off, round_val):
                 index += 1
                 index += 1
 
 
         bone_world_pos = armature.matrix_world * bone_pos
         bone_world_pos = armature.matrix_world * bone_pos
-        if round_off:
-            x_axis = utilities.round_off(bone_world_pos.x, round_val)
-            y_axis = utilities.round_off(bone_world_pos.z, round_val)
-            z_axis = -utilities.round_off(bone_world_pos.y, round_val)
-        else:
-            x_axis = bone_world_pos.x
-            y_axis = bone_world_pos.z
-            z_axis = -bone_world_pos.y
+        x_axis = bone_world_pos.x
+        y_axis = bone_world_pos.z
+        z_axis = -bone_world_pos.y
 
 
         logger.debug("Adding bone %s at: %s, %s",
         logger.debug("Adding bone %s at: %s, %s",
                      bone.name, bone_index, bone_index_rel)
                      bone.name, bone_index, bone_index_rel)
         bone_map[bone_count] = bone_index_rel
         bone_map[bone_count] = bone_index_rel
         bone_index_rel += 1
         bone_index_rel += 1
-        #@TODO: the rotq probably should not have these
-        #       hard coded values
+        # @TODO: the rotq probably should not have these
+        #        hard coded values
         bones_.append({
         bones_.append({
             constants.PARENT: bone_index,
             constants.PARENT: bone_index,
             constants.NAME: bone.name,
             constants.NAME: bone.name,
@@ -980,5 +917,3 @@ def _rest_bones(armature, round_off, round_val):
         bone_count += 1
         bone_count += 1
 
 
     return (bones_, bone_map)
     return (bones_, bone_map)
-
-

+ 9 - 11
utils/exporters/blender/addons/io_three/exporter/geometry.py

@@ -1,3 +1,7 @@
+"""
+Module for creating Three.js geometry JSON nodes.
+"""
+
 import os
 import os
 from .. import constants, logger
 from .. import constants, logger
 from . import base_classes, io, api
 from . import base_classes, io, api
@@ -42,11 +46,8 @@ class Geometry(base_classes.BaseNode):
 
 
         key = ''
         key = ''
         for key in (constants.MORPH_TARGETS, constants.ANIMATION):
         for key in (constants.MORPH_TARGETS, constants.ANIMATION):
-            try:
-                self[key]
+            if key in self.keys():
                 break
                 break
-            except KeyError:
-                pass
         else:
         else:
             logger.info("%s has no animation data", self.node)
             logger.info("%s has no animation data", self.node)
             return
             return
@@ -367,7 +368,7 @@ class Geometry(base_classes.BaseNode):
             if not option:
             if not option:
                 continue
                 continue
 
 
-            array = func(self.node, self.options) or []
+            array = func(self.node) or []
             if not array:
             if not array:
                 logger.warning("No array could be made for %s", key)
                 logger.warning("No array could be made for %s", key)
                 continue
                 continue
@@ -382,13 +383,11 @@ class Geometry(base_classes.BaseNode):
         """Parse the geometry to Three.Geometry specs"""
         """Parse the geometry to Three.Geometry specs"""
         if self.options.get(constants.VERTICES):
         if self.options.get(constants.VERTICES):
             logger.info("Parsing %s", constants.VERTICES)
             logger.info("Parsing %s", constants.VERTICES)
-            self[constants.VERTICES] = api.mesh.vertices(
-                self.node, self.options) or []
+            self[constants.VERTICES] = api.mesh.vertices(self.node) or []
 
 
         if self.options.get(constants.NORMALS):
         if self.options.get(constants.NORMALS):
             logger.info("Parsing %s", constants.NORMALS)
             logger.info("Parsing %s", constants.NORMALS)
-            self[constants.NORMALS] = api.mesh.normals(
-                self.node, self.options) or []
+            self[constants.NORMALS] = api.mesh.normals(self.node) or []
 
 
         if self.options.get(constants.COLORS):
         if self.options.get(constants.COLORS):
             logger.info("Parsing %s", constants.COLORS)
             logger.info("Parsing %s", constants.COLORS)
@@ -402,8 +401,7 @@ class Geometry(base_classes.BaseNode):
 
 
         if self.options.get(constants.UVS):
         if self.options.get(constants.UVS):
             logger.info("Parsing %s", constants.UVS)
             logger.info("Parsing %s", constants.UVS)
-            self[constants.UVS] = api.mesh.uvs(
-                self.node, self.options) or []
+            self[constants.UVS] = api.mesh.uvs(self.node) or []
 
 
         if self.options.get(constants.FACES):
         if self.options.get(constants.FACES):
             logger.info("Parsing %s", constants.FACES)
             logger.info("Parsing %s", constants.FACES)

+ 0 - 43
utils/exporters/blender/addons/io_three/exporter/utilities.py

@@ -68,46 +68,3 @@ def rgb2int(rgb):
 
 
     colour = (int(rgb[0]*255) << 16) + (int(rgb[1]*255) << 8) + int(rgb[2]*255)
     colour = (int(rgb[0]*255) << 16) + (int(rgb[1]*255) << 8) + int(rgb[2]*255)
     return colour
     return colour
-
-
-def round_off(value, ndigits=ROUND):
-    """Round off values to specified limit
-
-    :param value: value(s) to round off
-    :param ndigits: limit (Default value = ROUND)
-    :type value: float|list|tuple
-    :return: the same data type that was passed
-    :rtype: float|list|tuple
-
-    """
-    is_tuple = isinstance(value, tuple)
-    is_list = isinstance(value, list)
-
-    value = list(value) if is_tuple else value
-    value = [value] if not is_list and not is_tuple else value
-
-    value = [round(val, ndigits) for val in value]
-
-    if is_tuple:
-        value = tuple(value)
-    elif not is_list:
-        value = value[0]
-
-    return value
-
-
-def rounding(options):
-    """By evaluation the options determine if precision was
-    enabled and what the value is
-
-    :type options: dict
-    :rtype: bool, int
-
-    """
-    round_off_ = options.get(constants.ENABLE_PRECISION)
-    if round_off_:
-        round_val = options[constants.PRECISION]
-    else:
-        round_val = None
-
-    return (round_off_, round_val)

+ 2 - 0
utils/exporters/blender/tests/scripts/exporter.py

@@ -27,6 +27,8 @@ def parse_args():
 
 
 def main():
 def main():
     args = parse_args()
     args = parse_args()
+    args[constants.ENABLE_PRECISION] = True
+    args[constants.INDENT] = True
     if args[constants.SCENE]:
     if args[constants.SCENE]:
         io_three.exporter.export_scene(args['filepath'], args)
         io_three.exporter.export_scene(args['filepath'], args)
     else:
     else:

部分文件因为文件数量过多而无法显示