瀏覽代碼

Added level-of-details example (and LOD object to compiled lib).

Thanks to empaempa for implementing this feature ;)
alteredq 14 年之前
父節點
當前提交
7ad44b434c
共有 4 個文件被更改,包括 166 次插入6 次删除
  1. 7 5
      build/Three.js
  2. 1 1
      examples/webgl_lights_pointlights.html
  3. 157 0
      examples/webgl_lod.html
  4. 1 0
      utils/build.py

+ 7 - 5
build/Three.js

@@ -132,11 +132,13 @@ THREE.Sound=function(a,b,c,d){THREE.Object3D.call(this);this.isLoaded=!1;this.is
 "audio/mpeg";else if(b.indexOf(".ogg")!==-1)f="audio/ogg";else b.indexOf(".wav")!==-1&&(f="audio/wav");if(this.domElement.canPlayType(f)){f=document.createElement("source");f.src=this.sources[a];this.domElement.THREESound=this;this.domElement.appendChild(f);this.domElement.addEventListener("canplay",this.onLoad,!0);this.domElement.load();break}}};THREE.Sound.prototype=new THREE.Object3D;THREE.Sound.prototype.constructor=THREE.Sound;THREE.Sound.prototype.supr=THREE.Object3D.prototype;
 "audio/mpeg";else if(b.indexOf(".ogg")!==-1)f="audio/ogg";else b.indexOf(".wav")!==-1&&(f="audio/wav");if(this.domElement.canPlayType(f)){f=document.createElement("source");f.src=this.sources[a];this.domElement.THREESound=this;this.domElement.appendChild(f);this.domElement.addEventListener("canplay",this.onLoad,!0);this.domElement.load();break}}};THREE.Sound.prototype=new THREE.Object3D;THREE.Sound.prototype.constructor=THREE.Sound;THREE.Sound.prototype.supr=THREE.Object3D.prototype;
 THREE.Sound.prototype.onLoad=function(){var a=this.THREESound;if(!a.isLoaded){this.removeEventListener("canplay",this.onLoad,!0);a.isLoaded=!0;a.duration=this.duration;a.isPlaying&&a.play()}};THREE.Sound.prototype.addToDOM=function(a){this.isAddedToDOM=!0;a.appendChild(this.domElement)};THREE.Sound.prototype.play=function(a){this.isPlaying=!0;if(this.isLoaded){this.domElement.play();if(a)this.domElement.currentTime=a%this.duration}};THREE.Sound.prototype.pause=function(){this.isPlaying=!1;this.domElement.pause()};
 THREE.Sound.prototype.onLoad=function(){var a=this.THREESound;if(!a.isLoaded){this.removeEventListener("canplay",this.onLoad,!0);a.isLoaded=!0;a.duration=this.duration;a.isPlaying&&a.play()}};THREE.Sound.prototype.addToDOM=function(a){this.isAddedToDOM=!0;a.appendChild(this.domElement)};THREE.Sound.prototype.play=function(a){this.isPlaying=!0;if(this.isLoaded){this.domElement.play();if(a)this.domElement.currentTime=a%this.duration}};THREE.Sound.prototype.pause=function(){this.isPlaying=!1;this.domElement.pause()};
 THREE.Sound.prototype.stop=function(){this.isPlaying=!1;this.domElement.pause();this.domElement.currentTime=0};THREE.Sound.prototype.calculateVolumeAndPan=function(a){a=a.length();this.domElement.volume=a<=this.radius?this.volume*(1-a/this.radius):0};
 THREE.Sound.prototype.stop=function(){this.isPlaying=!1;this.domElement.pause();this.domElement.currentTime=0};THREE.Sound.prototype.calculateVolumeAndPan=function(a){a=a.length();this.domElement.volume=a<=this.radius?this.volume*(1-a/this.radius):0};
-THREE.Sound.prototype.update=function(a,b,c){if(this.matrixAutoUpdate){this.matrix.setPosition(this.position);b=!0}if(b||this.matrixNeedsUpdate){a?this.matrixWorld.multiply(a,this.matrix):this.matrixWorld.copy(this.matrix);this.matrixNeedsUpdate=!1;b=!0}var d=this.children.length;for(a=0;a<d;a++)this.children[a].update(this.matrixWorld,b,c)};THREE.Scene=function(){THREE.Object3D.call(this);this.objects=[];this.lights=[];this.sounds=[];this.fog=null;this.matrixAutoUpdate=!1};
-THREE.Scene.prototype=new THREE.Object3D;THREE.Scene.prototype.constructor=THREE.Scene;THREE.Scene.prototype.supr=THREE.Object3D.prototype;THREE.Scene.prototype.addChild=function(a){this.supr.addChild.call(this,a);this.addChildRecurse(a)};
-THREE.Scene.prototype.addChildRecurse=function(a){if(a instanceof THREE.Light)this.lights.indexOf(a)===-1&&this.lights.push(a);else if(a instanceof THREE.Sound)this.sounds.indexOf(a)===-1&&this.sounds.push(a);else a instanceof THREE.Camera||a instanceof THREE.Bone||this.objects.indexOf(a)===-1&&this.objects.push(a);for(var b=0;b<a.children.length;b++)this.addChildRecurse(a.children[b])};THREE.Scene.prototype.removeChild=function(a){this.supr.removeChild.call(this,a);this.removeChildRecurse(a)};
-THREE.Scene.prototype.removeChildRecurse=function(a){if(a instanceof THREE.Light){var b=this.lights.indexOf(a);b!==-1&&this.lights.splice(b,1)}else if(a instanceof THREE.Sound){b=this.sounds.indexOf(a);b!==-1&&this.sounds.splice(b,1)}else if(!(a instanceof THREE.Camera)){b=this.objects.indexOf(a);b!==-1&&this.objects.splice(b,1)}for(b=0;b<a.children.length;b++)this.removeChildRecurse(a.children[b])};THREE.Scene.prototype.addObject=THREE.Scene.prototype.addChild;
-THREE.Scene.prototype.removeObject=THREE.Scene.prototype.removeChild;THREE.Scene.prototype.addLight=THREE.Scene.prototype.addChild;THREE.Scene.prototype.removeLight=THREE.Scene.prototype.removeChild;THREE.Fog=function(a,b,c){this.color=new THREE.Color(a);this.near=b||1;this.far=c||1E3};THREE.FogExp2=function(a,b){this.color=new THREE.Color(a);this.density=b||2.5E-4};
+THREE.Sound.prototype.update=function(a,b,c){if(this.matrixAutoUpdate){this.matrix.setPosition(this.position);b=!0}if(b||this.matrixNeedsUpdate){a?this.matrixWorld.multiply(a,this.matrix):this.matrixWorld.copy(this.matrix);this.matrixNeedsUpdate=!1;b=!0}var d=this.children.length;for(a=0;a<d;a++)this.children[a].update(this.matrixWorld,b,c)};THREE.LOD=function(){THREE.Object3D.call(this);this.LODs=[]};THREE.LOD.prototype=new THREE.Object3D;THREE.LOD.prototype.constructor=THREE.LOD;
+THREE.LOD.prototype.supr=THREE.Object3D.prototype;THREE.LOD.prototype.add=function(a,b){b===undefined&&(b=0);b=Math.abs(b);for(var c=0;c<this.LODs.length;c++)if(b<this.LODs[c].visibleAtDistance)break;this.LODs.splice(c,0,{visibleAtDistance:b,object3D:a});this.addChild(a)};
+THREE.LOD.prototype.update=function(a,b,c){this.matrixAutoUpdate&&(b|=this.updateMatrix());if(b||this.matrixNeedsUpdate){a?this.matrixWorld.multiply(a,this.matrix):this.matrixWorld.copy(this.matrix);this.matrixNeedsUpdate=!1;b=!0}if(this.LODs.length>1){a=c.matrixWorldInverse;a=-(a.n31*this.position.x+a.n32*this.position.y+a.n33*this.position.z+a.n34);this.LODs[0].object3D.visible=!0;for(var d=1;d<this.LODs.length;d++)if(a>=this.LODs[d].visibleAtDistance){this.LODs[d-1].object3D.visible=!1;this.LODs[d].object3D.visible=
+!0}else break;for(;d<this.LODs.length;d++)this.LODs[d].object3D.visible=!1}for(a=0;a<this.children.length;a++)this.children[a].update(this.matrixWorld,b,c)};THREE.Scene=function(){THREE.Object3D.call(this);this.objects=[];this.lights=[];this.sounds=[];this.fog=null;this.matrixAutoUpdate=!1};THREE.Scene.prototype=new THREE.Object3D;THREE.Scene.prototype.constructor=THREE.Scene;THREE.Scene.prototype.supr=THREE.Object3D.prototype;
+THREE.Scene.prototype.addChild=function(a){this.supr.addChild.call(this,a);this.addChildRecurse(a)};THREE.Scene.prototype.addChildRecurse=function(a){if(a instanceof THREE.Light)this.lights.indexOf(a)===-1&&this.lights.push(a);else if(a instanceof THREE.Sound)this.sounds.indexOf(a)===-1&&this.sounds.push(a);else a instanceof THREE.Camera||a instanceof THREE.Bone||this.objects.indexOf(a)===-1&&this.objects.push(a);for(var b=0;b<a.children.length;b++)this.addChildRecurse(a.children[b])};
+THREE.Scene.prototype.removeChild=function(a){this.supr.removeChild.call(this,a);this.removeChildRecurse(a)};THREE.Scene.prototype.removeChildRecurse=function(a){if(a instanceof THREE.Light){var b=this.lights.indexOf(a);b!==-1&&this.lights.splice(b,1)}else if(a instanceof THREE.Sound){b=this.sounds.indexOf(a);b!==-1&&this.sounds.splice(b,1)}else if(!(a instanceof THREE.Camera)){b=this.objects.indexOf(a);b!==-1&&this.objects.splice(b,1)}for(b=0;b<a.children.length;b++)this.removeChildRecurse(a.children[b])};
+THREE.Scene.prototype.addObject=THREE.Scene.prototype.addChild;THREE.Scene.prototype.removeObject=THREE.Scene.prototype.removeChild;THREE.Scene.prototype.addLight=THREE.Scene.prototype.addChild;THREE.Scene.prototype.removeLight=THREE.Scene.prototype.removeChild;THREE.Fog=function(a,b,c){this.color=new THREE.Color(a);this.near=b||1;this.far=c||1E3};THREE.FogExp2=function(a,b){this.color=new THREE.Color(a);this.density=b||2.5E-4};
 THREE.Projector=function(){function a(O,P){return P.z-O.z}function b(O,P){var V=0,T=1,Y=O.z+O.w,da=P.z+P.w,J=-O.z+O.w,$=-P.z+P.w;if(Y>=0&&da>=0&&J>=0&&$>=0)return!0;else if(Y<0&&da<0||J<0&&$<0)return!1;else{if(Y<0)V=Math.max(V,Y/(Y-da));else da<0&&(T=Math.min(T,Y/(Y-da)));if(J<0)V=Math.max(V,J/(J-$));else $<0&&(T=Math.min(T,J/(J-$)));if(T<V)return!1;else{O.lerpSelf(P,V);P.lerpSelf(O,1-T);return!0}}}var c,d,f=[],g,h,k,j=[],l,n,v=[],p,q,w=[],B=new THREE.Vector4,H=new THREE.Vector4,u=new THREE.Matrix4,
 THREE.Projector=function(){function a(O,P){return P.z-O.z}function b(O,P){var V=0,T=1,Y=O.z+O.w,da=P.z+P.w,J=-O.z+O.w,$=-P.z+P.w;if(Y>=0&&da>=0&&J>=0&&$>=0)return!0;else if(Y<0&&da<0||J<0&&$<0)return!1;else{if(Y<0)V=Math.max(V,Y/(Y-da));else da<0&&(T=Math.min(T,Y/(Y-da)));if(J<0)V=Math.max(V,J/(J-$));else $<0&&(T=Math.min(T,J/(J-$)));if(T<V)return!1;else{O.lerpSelf(P,V);P.lerpSelf(O,1-T);return!0}}}var c,d,f=[],g,h,k,j=[],l,n,v=[],p,q,w=[],B=new THREE.Vector4,H=new THREE.Vector4,u=new THREE.Matrix4,
 I=new THREE.Matrix4,o=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4],M=new THREE.Vector4,e=new THREE.Vector4,ba;this.projectObjects=function(O,P,V){P=[];var T,Y,da;d=0;Y=O.objects;O=0;for(T=Y.length;O<T;O++){da=Y[O];var J;if(!(J=!da.visible))if(J=da instanceof THREE.Mesh){a:{J=void 0;for(var $=da.matrixWorld,ra=-da.geometry.boundingSphere.radius*Math.max(da.scale.x,Math.max(da.scale.y,da.scale.z)),Z=0;Z<6;Z++){J=o[Z].x*$.n14+o[Z].y*$.n24+
 I=new THREE.Matrix4,o=[new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4,new THREE.Vector4],M=new THREE.Vector4,e=new THREE.Vector4,ba;this.projectObjects=function(O,P,V){P=[];var T,Y,da;d=0;Y=O.objects;O=0;for(T=Y.length;O<T;O++){da=Y[O];var J;if(!(J=!da.visible))if(J=da instanceof THREE.Mesh){a:{J=void 0;for(var $=da.matrixWorld,ra=-da.geometry.boundingSphere.radius*Math.max(da.scale.x,Math.max(da.scale.y,da.scale.z)),Z=0;Z<6;Z++){J=o[Z].x*$.n14+o[Z].y*$.n24+
 o[Z].z*$.n34+o[Z].w;if(J<=ra){J=!1;break a}}J=!0}J=!J}if(!J){c=f[d]=f[d]||new THREE.RenderableObject;B.copy(da.position);u.multiplyVector3(B);c.object=da;c.z=B.z;P.push(c);d++}}V&&P.sort(a);return P};this.projectScene=function(O,P,V){var T=[],Y=P.near,da=P.far,J,$,ra,Z,la,ja,fa,sa,m,A,x,t,y,C,D,E;k=n=q=0;P.matrixAutoUpdate&&P.update();u.multiply(P.projectionMatrix,P.matrixWorldInverse);o[0].set(u.n41-u.n11,u.n42-u.n12,u.n43-u.n13,u.n44-u.n14);o[1].set(u.n41+u.n11,u.n42+u.n12,u.n43+u.n13,u.n44+u.n14);
 o[Z].z*$.n34+o[Z].w;if(J<=ra){J=!1;break a}}J=!0}J=!J}if(!J){c=f[d]=f[d]||new THREE.RenderableObject;B.copy(da.position);u.multiplyVector3(B);c.object=da;c.z=B.z;P.push(c);d++}}V&&P.sort(a);return P};this.projectScene=function(O,P,V){var T=[],Y=P.near,da=P.far,J,$,ra,Z,la,ja,fa,sa,m,A,x,t,y,C,D,E;k=n=q=0;P.matrixAutoUpdate&&P.update();u.multiply(P.projectionMatrix,P.matrixWorldInverse);o[0].set(u.n41-u.n11,u.n42-u.n12,u.n43-u.n13,u.n44-u.n14);o[1].set(u.n41+u.n11,u.n42+u.n12,u.n43+u.n13,u.n44+u.n14);

+ 1 - 1
examples/webgl_lights_pointlights.html

@@ -1,7 +1,7 @@
 <!DOCTYPE HTML>
 <!DOCTYPE HTML>
 <html lang="en">
 <html lang="en">
 	<head>
 	<head>
-		<title>three.js webl - lights - point lights</title>
+		<title>three.js webgl - lights - point lights</title>
 		<meta charset="utf-8">
 		<meta charset="utf-8">
 		<style type="text/css">
 		<style type="text/css">
 			body {
 			body {

+ 157 - 0
examples/webgl_lod.html

@@ -0,0 +1,157 @@
+<!DOCTYPE HTML>
+<html lang="en">
+	<head>
+		<title>three.js webgl - level-of-details</title>
+		<meta charset="utf-8">
+		<style type="text/css">
+			body {
+				background:#000;
+				color:#fff;
+				padding:0;
+				margin:0;
+				font-weight: bold;
+				overflow:hidden;
+			}
+			
+			#info {
+				position: absolute;
+				top: 0px; width: 100%;
+				color: #ffffff;
+				padding: 5px;
+				font-family: Monospace;
+				font-size: 13px;
+				text-align: center;
+				z-index:100;
+			}
+			
+			a { color:red }
+			
+		</style>
+	</head>
+
+	<body>
+		<div id="info">
+			<a href="http://github.com/mrdoob/three.js" target="_blank">three.js</a> - level-of-details WebGL example
+		</div>
+
+		
+		<script type="text/javascript" src="js/ThreeLod.js"></script>
+		
+		<script type="text/javascript" src="js/Detector.js"></script>
+		<script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
+		<script type="text/javascript" src="js/Stats.js"></script>
+
+		<script type="text/javascript">
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+			
+			var container, stats;
+
+			var camera, scene, renderer;
+
+			var geometry, objects;
+
+			var mouseX = 0, mouseY = 0;
+
+			var windowHalfX = window.innerWidth / 2;
+			var windowHalfY = window.innerHeight / 2;
+
+			document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+
+			init();
+			animate();
+
+			function init() {
+
+				container = document.createElement( 'div' );
+				document.body.appendChild( container );
+
+				camera = new THREE.Camera( 60, window.innerWidth / window.innerHeight, 1, 15000 );
+				camera.position.z = 300;
+
+				scene = new THREE.Scene();
+				scene.fog = new THREE.Fog( 0x000000, 1, 15000 );
+
+				var light = new THREE.PointLight( 0xff2200 );
+				light.position.set( 0, 0, 0 );
+				scene.addLight( light );
+
+				var light = new THREE.DirectionalLight( 0xffffff );
+				light.position.set( 0, 0, 1 );
+				light.position.normalize();
+				scene.addLight( light );
+
+				var material = new THREE.MeshLambertMaterial( { color: 0xffffff, shading: THREE.FlatShading } );
+				
+				var geometry = [ [ new Sphere( 100, 128, 64 ),	   0 ],
+								 [ new Sphere( 100,  64, 32 ),	 200 ],
+								 [ new Sphere( 100,  32, 16 ),	 400 ],
+								 [ new Sphere( 100,  16,  8 ),  6000 ],
+								 [ new Sphere( 100,   8,  4 ), 12000 ]
+							  ];
+				
+				var i, j, mesh, lod;
+
+				for ( j = 0; j < 2000; j++ ) {
+
+					lod = new THREE.LOD();
+					
+					for ( i = 0; i < geometry.length; i++ ) {
+					
+						mesh = new THREE.Mesh( geometry[ i ][ 0 ], material );
+						mesh.scale.set( 1.5, 1.5, 1.5 );
+						lod.add( mesh, geometry[ i ][ 1 ] );
+						
+					}
+
+					lod.position.x = 15000 * ( 0.5 - Math.random() );
+					lod.position.y =  7500 * ( 0.5 - Math.random() );
+					lod.position.z = 15000 * ( 0.5 - Math.random() );
+					
+					scene.addObject( lod );
+					
+				}
+
+
+
+				renderer = new THREE.WebGLRenderer( { clearColor:0x000000, clearAlpha: 1 } );
+				renderer.setSize( window.innerWidth, window.innerHeight );
+				renderer.sortObjects = false;
+				container.appendChild( renderer.domElement );
+
+			}
+
+			function onDocumentMouseMove(event) {
+
+				mouseX = ( event.clientX - windowHalfX ) * 10;
+				mouseY = ( event.clientY - windowHalfY ) * 10;
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+				render();
+
+			}
+
+			function render() {
+
+				camera.position.x += ( mouseX - camera.position.x ) * .05;
+				camera.position.y += ( - mouseY - camera.position.y ) * .05;
+
+				renderer.render( scene, camera );
+
+			}
+
+			function log( text ) {
+
+				var e = document.getElementById("log");
+				e.innerHTML = text + "<br/>" + e.innerHTML;
+
+			}
+
+		</script>
+
+	</body>
+</html>

+ 1 - 0
utils/build.py

@@ -61,6 +61,7 @@ COMMON_FILES = [
 'objects/SkinnedMesh.js',
 'objects/SkinnedMesh.js',
 'objects/Ribbon.js',
 'objects/Ribbon.js',
 'objects/Sound.js',
 'objects/Sound.js',
+'objects/LOD.js',
 'scenes/Scene.js',
 'scenes/Scene.js',
 'scenes/Fog.js',
 'scenes/Fog.js',
 'scenes/FogExp2.js',
 'scenes/FogExp2.js',