diff --git a/examples/scene_test.html b/examples/scene_test.html index c8bb6a90..5564f551 100644 --- a/examples/scene_test.html +++ b/examples/scene_test.html @@ -44,13 +44,26 @@ padding:0.1em 0.3em; width:3em; text-align: center; - /* - font-size:0.8em; + display:none; + } + + .shadow { -moz-box-shadow: 0px 0px 5px #000; -webkit-box-shadow: 0px 0px 5px #000; box-shadow: 0px 0px 5px #000; - */ - display:none; + } + + #progressbar { + text-align: center; + background: white; + width: 250px; + height: 10px; + } + + #bar { + background:#d00; + width:50px; + height:10px; } .enabled { @@ -70,6 +83,48 @@ a { color:red } canvas { pointer-events:none; z-index:10; } #log { position:absolute; top:0; display:block; text-align:left; z-index:1000; pointer-events:none; } + + #scene_explorer { + background:transparent; + color:#fff; + width:200px; + position:absolute; + text-align:left; + top:0px; + z-index:200; + overflow:auto; + } + + #section_exp { + background:rgba(0,0,50,0.5); + padding:0.5em 0; + display:none; + } + + #scene_explorer h3 { + font-size:1em; + padding:0; + margin:0; + color:orange; + } + + #scene_explorer a { + color:#555; + font-weight:bold; + text-decoration:none; + font-size:1.2em; + font-family:Monospace; + } + #scene_explorer a:hover { + background:#555; + color:rgba(0,0,50,1); + } + + .part { + display:none; + padding:0 0 0.5em 2em; + } + @@ -77,10 +132,19 @@
three.js - scene loader test
+ +
+ [+] +
+
Loading ... -
Start
+ +
+
+
Start
+

@@ -115,6 +179,39 @@
 				
 			}
 			
+			function handle_update( result, pieces ) {
+				
+				refreshSceneView( result );
+				renderer.initWebGLObjects( result.scene );
+				
+				var m, material, count = 0;
+				
+				for ( m in result.materials ) {
+				
+					material = result.materials[ m ];
+					if ( ! ( material instanceof THREE.MeshFaceMaterial ) ) {
+						
+						if( !material.program ) {
+						
+							console.log(m);
+							renderer.initMaterial( material, result.scene.lights, result.scene.fog );
+							
+							count += 1;
+							if( count > pieces ) {
+								
+								//console.log("xxxxxxxxx");
+								break;
+							
+							}
+							
+						}
+						
+					}
+					
+				}
+				
+			}
+			
 			function init() {
 
 				container = document.createElement( 'div' );
@@ -133,9 +230,30 @@
 
 				setInterval( loop, 1000/60 );
 
+				var callback_progress = function( progress, result ) {
+				
+					var bar = 250, 
+						total = progress.total_models + progress.total_textures,
+						loaded = progress.loaded_models + progress.loaded_textures;
+					
+					if ( total )
+						bar = Math.floor( bar * loaded / total );
+					
+					$( "bar" ).style.width = bar + "px";
+					
+					count = 0;
+					for ( var m in result.materials ) count++;
+
+					handle_update( result, Math.floor( count/total ) );
+					
+				}
+				
 				var callback_sync = function( result ) {
 				
 					/*
+					
+					// uncomment to see progressive scene loading
+					
 					scene = result.scene;
 					camera = result.currentCamera;
 					
@@ -146,6 +264,8 @@
 					
 					*/
 
+					//handle_update( result, 1 );
+					
 				}
 				
 				var callback_async = function( result ) {
@@ -160,21 +280,29 @@
 					mat_veyron[ 3 ][ 0 ] = result.materials[ "glass" ];
 					mat_veyron[ 4 ][ 0 ] = result.materials[ "chrome" ];
 					mat_veyron[ 5 ][ 0 ] = result.materials[ "chrome" ];
+					mat_veyron[ 6 ][ 0 ] = result.materials[ "backlights" ];
+					mat_veyron[ 7 ][ 0 ] = result.materials[ "backsignals" ];
 					
 					$( "message" ).style.display = "none";
+					$( "progressbar" ).style.display = "none";
 					$( "start" ).style.display = "block";
 					$( "start" ).className = "enabled";
 					
+					handle_update( result, 1 );
+					
 				}
 				
 				$( "progress" ).style.display = "block";
-				SceneUtils.loadScene( "scenes/test_scene.js", callback_sync, callback_async );
+				SceneUtils.loadScene( "scenes/test_scene.js", callback_sync, callback_async, callback_progress );
 
 				stats = new Stats();
 				stats.domElement.style.position = 'absolute';
 				stats.domElement.style.top = '0px';
+				stats.domElement.style.right = '0px';
 				stats.domElement.style.zIndex = 100;
 				container.appendChild( stats.domElement );
+				
+				$( "plus_exp" ).addEventListener( 'click', createToggle( "exp" ), false );
 
 			}
 
@@ -263,6 +391,79 @@
 
 			}
 
+			// Scene explorer user interface
+			
+			function toggle( id ) {
+				
+				var scn = $( "section_" + id ).style,
+					btn = $( "plus_" + id );
+				
+				if ( scn.display == "block" ) {
+				
+					scn.display = "none";
+					btn.innerHTML = "[+]";
+					
+				}
+				else {
+					
+					scn.display = "block";
+					btn.innerHTML = "[-]";
+					
+				}
+					
+			}
+			
+			function createToggle( label ) { return function() { toggle( label ) } };
+			
+			function refreshSceneView( result ) {
+				
+				$( "section_exp" ).innerHTML = generateSceneView( result );
+
+				var config = [ "obj", "geo", "mat", "tex", "lit", "cam" ];
+				
+				for ( var i = 0; i < config.length; i++ )
+					$( "plus_" + config[i] ).addEventListener( 'click', createToggle( config[i] ), false );
+
+			}
+			
+			function generateSection( label, id, objects ) {
+				
+				var html = "";
+				
+				html += "

[+] " + label + "

"; + html += "
"; + + for( var o in objects ) { + + html += o + "
"; + + } + html += "
"; + + return html; + + } + + function generateSceneView( result ) { + + var config = [ + [ "Objects", "obj", result.objects ], + [ "Geometries", "geo", result.geometries ], + [ "Materials", "mat", result.materials ], + [ "Textures", "tex", result.textures ], + [ "Lights", "lit", result.lights ], + [ "Cameras", "cam", result.cameras ] + ]; + + var html = ""; + + for ( var i = 0; i < config.length; i++ ) + html += generateSection( config[i][0], config[i][1], config[i][2] ); + + return html; + + } + diff --git a/examples/scenes/test_scene.js b/examples/scenes/test_scene.js index 0a63075e..e0907f11 100644 --- a/examples/scenes/test_scene.js +++ b/examples/scenes/test_scene.js @@ -206,6 +206,7 @@ var scene = { "materials": { + /* "basic_red": { "type": "MeshBasicMaterial", "parameters": { color: 0xff0000, wireframe: true } @@ -215,16 +216,27 @@ var scene = { "type": "MeshBasicMaterial", "parameters": { color: 0x007711, wireframe: true } }, - - "basic_gray": { + + "basic_blue": { "type": "MeshBasicMaterial", - "parameters": { color: 0x666666, wireframe: true } + "parameters": { color: 0x0000ff, wireframe: true } }, - + "basic_black": { "type": "MeshBasicMaterial", "parameters": { color: 0x000000, wireframe: true } }, + + "phong_white": { + "type": "MeshPhongMaterial", + "parameters": { color: 0xaaaaaa } + }, + */ + + "basic_gray": { + "type": "MeshBasicMaterial", + "parameters": { color: 0x666666, wireframe: true } + }, "basic_white": { "type": "MeshBasicMaterial", @@ -236,11 +248,6 @@ var scene = { "parameters": { color: 0xffffff, shading: "flat" } }, - "basic_blue": { - "type": "MeshBasicMaterial", - "parameters": { color: 0x0000ff, wireframe: true } - }, - "lambert_red": { "type": "MeshLambertMaterial", "parameters": { color: 0xff0000 } @@ -256,11 +263,6 @@ var scene = { "parameters": { color: 0x0055aa } }, - "phong_white": { - "type": "MeshPhongMaterial", - "parameters": { color: 0xaaaaaa } - }, - "phong_orange": { "type": "MeshPhongMaterial", "parameters": { color:0x000000, specular: 0xaa5500 } @@ -296,6 +298,16 @@ var scene = { "parameters": { color: 0x050505 } }, + "backlights": { + "type": "MeshLambertMaterial", + "parameters": { color: 0xff0000, opacity: 0.5 } + }, + + "backsignals": { + "type": "MeshLambertMaterial", + "parameters": { color: 0xffbb00, opacity: 0.5 } + }, + "textured_bg": { "type": "MeshBasicMaterial", "parameters": { color: 0xffffff, map: "texture_bg" } diff --git a/src/extras/SceneUtils.js b/src/extras/SceneUtils.js index 55a3953c..666fa51b 100644 --- a/src/extras/SceneUtils.js +++ b/src/extras/SceneUtils.js @@ -1,6 +1,6 @@ var SceneUtils = { - loadScene : function( url, callback_sync, callback_async ) { + loadScene : function( url, callback_sync, callback_async, callback_progress ) { var worker = new Worker( url ); worker.postMessage( 0 ); @@ -14,6 +14,7 @@ var SceneUtils = { materials, data, loader, counter_models, counter_textures, + total_models, total_textures, result; data = event.data; @@ -90,7 +91,6 @@ var SceneUtils = { handle_mesh( geo, id ); counter_models -= 1; - //console.log( "models to load:", counter_models ); async_callback_gate(); @@ -100,6 +100,17 @@ var SceneUtils = { function async_callback_gate() { + var progress = { + + total_models: total_models, + total_textures: total_textures, + loaded_models: total_models - counter_models, + loaded_textures: total_textures - counter_textures + + }; + + callback_progress( progress, result ); + if( counter_models == 0 && counter_textures == 0 ) { callback_async( result ); @@ -108,6 +119,119 @@ var SceneUtils = { }; + var callback_texture = function( images ) { + + counter_textures -= 1; + async_callback_gate(); + + }; + + // first go synchronous elements + + // cameras + + for( dc in data.cameras ) { + + c = data.cameras[ dc ]; + + if ( c.type == "perspective" ) { + + camera = new THREE.Camera( c.fov, c.aspect, c.near, c.far ); + + } else if ( c.type == "ortho" ) { + + camera = new THREE.Camera(); + camera.projectionMatrix = THREE.Matrix4.makeOrtho( c.left, c.right, c.top, c.bottom, c.near, c.far ); + + } + + p = c.position; + t = c.target; + camera.position.set( p[0], p[1], p[2] ); + camera.target.position.set( t[0], t[1], t[2] ); + + result.cameras[ dc ] = camera; + + } + + // lights + + for( dl in data.lights ) { + + l = data.lights[ dl ]; + + if ( l.type == "directional" ) { + + p = l.direction; + + light = new THREE.DirectionalLight(); + light.position.set( p[0], p[1], p[2] ); + light.position.normalize(); + + } else if ( l.type == "point" ) { + + p = l.position; + + light = new THREE.PointLight(); + light.position.set( p[0], p[1], p[2] ); + + } + + c = l.color; + i = l.intensity || 1; + light.color.setRGB( c[0] * i, c[1] * i, c[2] * i ); + + result.scene.addLight( light ); + + result.lights[ dl ] = light; + + } + + // fogs + + for( df in data.fogs ) { + + f = data.fogs[ df ]; + + if ( f.type == "linear" ) { + + fog = new THREE.Fog( 0x000000, f.near, f.far ); + + } else if ( f.type == "exp2" ) { + + fog = new THREE.FogExp2( 0x000000, f.density ); + + } + + c = f.color; + fog.color.setRGB( c[0], c[1], c[2] ); + + result.fogs[ df ] = fog; + + } + + // defaults + + if ( result.cameras && data.defaults.camera ) { + + result.currentCamera = result.cameras[ data.defaults.camera ]; + + } + + if ( result.fogs && data.defaults.fog ) { + + result.scene.fog = result.fogs[ data.defaults.fog ]; + + } + + c = data.defaults.bgcolor; + result.bgColor = new THREE.Color(); + result.bgColor.setRGB( c[0], c[1], c[2] ); + + result.bgColorAlpha = data.defaults.bgalpha; + + // now come potentially asynchronous elements + // geometries // count how many models will be loaded asynchronously @@ -124,6 +248,8 @@ var SceneUtils = { } + total_models = counter_models; + for( dg in data.geometries ) { g = data.geometries[ dg ]; @@ -194,13 +320,7 @@ var SceneUtils = { } - var callback_texture = function( images ) { - - counter_textures -= 1; - //console.log( "textures to load:", counter_textures ); - async_callback_gate(); - - }; + total_textures = counter_textures; for( dt in data.textures ) { @@ -266,108 +386,6 @@ var SceneUtils = { handle_objects(); - // lights - - for( dl in data.lights ) { - - l = data.lights[ dl ]; - - if ( l.type == "directional" ) { - - p = l.direction; - - light = new THREE.DirectionalLight(); - light.position.set( p[0], p[1], p[2] ); - light.position.normalize(); - - } else if ( l.type == "point" ) { - - p = l.position; - - light = new THREE.PointLight(); - light.position.set( p[0], p[1], p[2] ); - - } - - c = l.color; - i = l.intensity || 1; - light.color.setRGB( c[0] * i, c[1] * i, c[2] * i ); - - result.scene.addLight( light ); - - result.lights[ dl ] = light; - - } - - // cameras - - for( dc in data.cameras ) { - - c = data.cameras[ dc ]; - - if ( c.type == "perspective" ) { - - camera = new THREE.Camera( c.fov, c.aspect, c.near, c.far ); - - } else if ( c.type == "ortho" ) { - - camera = new THREE.Camera(); - camera.projectionMatrix = THREE.Matrix4.makeOrtho( c.left, c.right, c.top, c.bottom, c.near, c.far ); - - } - - p = c.position; - t = c.target; - camera.position.set( p[0], p[1], p[2] ); - camera.target.position.set( t[0], t[1], t[2] ); - - result.cameras[ dc ] = camera; - - } - - // fogs - - for( df in data.fogs ) { - - f = data.fogs[ df ]; - - if ( f.type == "linear" ) { - - fog = new THREE.Fog( 0x000000, f.near, f.far ); - - } else if ( f.type == "exp2" ) { - - fog = new THREE.FogExp2( 0x000000, f.density ); - - } - - c = f.color; - fog.color.setRGB( c[0], c[1], c[2] ); - - result.fogs[ df ] = fog; - - } - - // defaults - - if ( result.cameras && data.defaults.camera ) { - - result.currentCamera = result.cameras[ data.defaults.camera ]; - - } - - if ( result.fogs && data.defaults.fog ) { - - result.scene.fog = result.fogs[ data.defaults.fog ]; - - } - - c = data.defaults.bgcolor; - result.bgColor = new THREE.Color(); - result.bgColor.setRGB( c[0], c[1], c[2] ); - - result.bgColorAlpha = data.defaults.bgalpha; - // synchronous callback callback_sync( result ); diff --git a/src/renderers/WebGLRenderer.js b/src/renderers/WebGLRenderer.js index bee6bf4d..5a67fe44 100644 --- a/src/renderers/WebGLRenderer.js +++ b/src/renderers/WebGLRenderer.js @@ -711,19 +711,16 @@ THREE.WebGLRenderer = function ( parameters ) { }; - this.renderBuffer = function ( camera, lights, fog, material, geometryChunk, object ) { - - var program, u, identifiers, attributes, parameters, maxLightCount, linewidth, primitives; - + this.initMaterial = function( material, lights, fog ) { + if ( !material.program ) { + var u, identifiers, parameters, maxLightCount; + if ( material instanceof THREE.MeshDepthMaterial ) { setMaterialShaders( material, THREE.ShaderLib[ 'depth' ] ); - material.uniforms.mNear.value = camera.near; - material.uniforms.mFar.value = camera.far; - } else if ( material instanceof THREE.MeshNormalMaterial ) { setMaterialShaders( material, THREE.ShaderLib[ 'normal' ] ); @@ -732,26 +729,18 @@ THREE.WebGLRenderer = function ( parameters ) { setMaterialShaders( material, THREE.ShaderLib[ 'basic' ] ); - refreshUniformsCommon( material, fog ); - } else if ( material instanceof THREE.MeshLambertMaterial ) { setMaterialShaders( material, THREE.ShaderLib[ 'lambert' ] ); - refreshUniformsCommon( material, fog ); - } else if ( material instanceof THREE.MeshPhongMaterial ) { setMaterialShaders( material, THREE.ShaderLib[ 'phong' ] ); - refreshUniformsCommon( material, fog ); - } else if ( material instanceof THREE.LineBasicMaterial ) { setMaterialShaders( material, THREE.ShaderLib[ 'basic' ] ); - refreshUniformsLine( material, fog ); - } // heuristics to create shader parameters according to lights in the scene @@ -773,6 +762,14 @@ THREE.WebGLRenderer = function ( parameters ) { cacheAttributeLocations( material.program, [ "position", "normal", "uv", "tangent" ] ); } + + }; + + this.renderBuffer = function ( camera, lights, fog, material, geometryChunk, object ) { + + var program, u, identifiers, attributes, parameters, maxLightCount, linewidth, primitives; + + this.initMaterial( material, lights, fog ); program = material.program; @@ -813,6 +810,12 @@ THREE.WebGLRenderer = function ( parameters ) { } + if ( material instanceof THREE.MeshDepthMaterial ) { + + material.uniforms.mNear.value = camera.near; + material.uniforms.mFar.value = camera.far; + } + setUniforms( program, material.uniforms ); attributes = program.attributes;