فهرست منبع

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

Mr.doob 12 سال پیش
والد
کامیت
23e9bc9962
3فایلهای تغییر یافته به همراه762 افزوده شده و 231 حذف شده
  1. 336 229
      examples/js/Octree.js
  2. 31 2
      examples/webgl_octree.html
  3. 395 0
      examples/webgl_octree_raycasting.html

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 336 - 229
examples/js/Octree.js


+ 31 - 2
examples/webgl_octree.html

@@ -6,7 +6,8 @@
 		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
 		<style>
 			body {
-				background-color: #ffffff;
+				font-family: Monospace;
+				background-color: #f0f0f0;
 				margin: 0px;
 				overflow: hidden;
 			}
@@ -55,8 +56,20 @@
 				document.body.appendChild( renderer.domElement );
 			
 				// create octree
-			
+				
 				octree = new THREE.Octree( {
+					// when undeferred = true, objects are inserted immediately
+					// instead of being deferred until next octree.update() call
+					// this may decrease performance as it forces a matrix update
+					undeferred: false,
+					// set the max depth of tree
+					depthMax: Infinity,
+					// max number of objects before nodes split or merge
+					objectsThreshold: 8,
+					// percent between 0 and 1 that nodes will overlap each other
+					// helps insert objects that lie over more than one node
+					overlapPct: 0.15,
+					// pass the scene to visualize the octree
 					scene: scene
 				} );
 			
@@ -67,6 +80,18 @@
 					new THREE.MeshBasicMaterial( { color: 0x00FF00, transparent: true, opacity: 0.4 } )
 				);
 				scene.add( searchMesh );
+				
+				// info
+				
+				var info = document.createElement( 'div' );
+				info.style.position = 'absolute';
+				info.style.top = '0';
+				info.style.width = '100%';
+				info.style.textAlign = 'center';
+				info.style.padding = '10px';
+				info.style.background = '#FFFFFF';
+				info.innerHTML = '<a href="http://threejs.org" target="_blank">three.js</a> webgl - octree (sparse & dynamic) - by <a href="http://github.com/collinhover/threeoctree" target="_blank">collinhover</a>';
+				document.body.appendChild( info );
 
 			}
 
@@ -86,6 +111,10 @@
 				// render results
 			
 				render();
+				
+				// update octree to add deferred objects
+				
+				octree.update();
 
 			}
 		

+ 395 - 0
examples/webgl_octree_raycasting.html

@@ -0,0 +1,395 @@
+<!DOCTYPE html>
+<html>
+<head>
+	<title>three.js webgl - octree raycasting</title>
+    <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+    <meta name="description" content="">
+	<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
+	<style>
+		body {
+			font-family: Monospace;
+			background-color: #f0f0f0;
+			margin: 0px;
+			overflow: hidden;
+		}
+	</style>
+
+</head>
+
+<body>
+
+    <script type="text/javascript" src="../build/three.min.js"></script>
+    <script type="text/javascript" src="js/Octree.js"></script>
+	<script type="text/javascript" src="js/controls/TrackballControls.js"></script>
+	<script type="text/javascript" src="js/libs/stats.min.js"></script>
+	<script>
+		
+		var camera, scene, renderer;
+
+		var controls, stats;
+		
+		var tracker;
+		
+		var octree;
+		
+		var objects = [];
+		var objectsSearch = [];
+		var totalFaces = 0;
+		
+		var simpleMeshCount = 2000;
+		var radius = 100;
+		var radiusMax = radius * 10;
+		var radiusMaxHalf = radiusMax * 0.5;
+		var radiusSearch = radius * 0.75;
+		
+		var baseColor = 0x333333;
+		var foundColor = 0x12C0E3;
+		var intersectColor = 0x00D66B;
+		
+		var clock = new THREE.Clock();
+		var searchDelay = 1;
+		var searchInterval = 0;
+		var useOctree = true;
+		
+		var projector;
+		
+		var mouse = new THREE.Vector2();
+		var intersected;
+
+		init();
+		animate();
+
+		function init() {
+			
+			// standard three scene, camera, renderer
+
+			scene = new THREE.Scene();
+
+			camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, radius * 100 );
+			camera.position.z = radius * 10;
+			scene.add( camera );
+
+			renderer = new THREE.WebGLRenderer();
+			renderer.setSize( window.innerWidth, window.innerHeight );
+
+			document.body.appendChild( renderer.domElement );
+			
+			// create octree
+			
+			octree = new THREE.Octree( {
+				// uncomment below to see the octree (may kill the fps)
+				//scene: scene,
+				// when undeferred = true, objects are inserted immediately
+				// instead of being deferred until next octree.update() call
+				// this may decrease performance as it forces a matrix update
+				undeferred: false,
+				// set the max depth of tree
+				depthMax: Infinity,
+				// max number of objects before nodes split or merge
+				objectsThreshold: 8,
+				// percent between 0 and 1 that nodes will overlap each other
+				// helps insert objects that lie over more than one node
+				overlapPct: 0.15
+			} );
+			
+			// lights
+			
+			var ambient = new THREE.AmbientLight( 0x101010 );
+			scene.add( ambient );
+
+			var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
+			directionalLight.position.set( 1, 1, 2 ).normalize();
+			scene.add( directionalLight );
+			
+			// create all objects
+			
+			var simpleGeometry = new THREE.CubeGeometry( 1, 1, 1 );
+			
+			for ( var i = 0; i < simpleMeshCount - 1; i++ ) {
+				
+				totalFaces += simpleGeometry.faces.length;
+				
+				var simpleMaterial = new THREE.MeshBasicMaterial();
+				simpleMaterial.color.setHex( baseColor );
+				
+				modifyOctree( simpleGeometry, simpleMaterial, false, true, true, true );
+				
+			}
+			
+			var loader = new THREE.JSONLoader();
+			
+			loader.load( 'obj/lucy/Lucy100k_slim.js', function ( geometry ) {
+
+				geometry.computeVertexNormals();
+				totalFaces += geometry.faces.length;
+				
+				var material = new THREE.MeshPhongMaterial( { ambient: 0x030303, color: 0x030303, specular: 0x030303, shininess: 30 } );
+				
+				modifyOctree( geometry, material, true );
+				
+			} );
+			
+			// projector for click intersection
+			
+			projector = new THREE.Projector();
+			
+			// camera controls
+			
+			controls = new THREE.TrackballControls( camera );
+			controls.rotateSpeed = 1.0;
+			controls.zoomSpeed = 1.2;
+			controls.panSpeed = 0.8;
+			controls.noZoom = false;
+			controls.noPan = false;
+			controls.staticMoving = true;
+			controls.dynamicDampingFactor = 0.3;
+			
+			// info
+			
+			var info = document.createElement( 'div' );
+			info.style.position = 'absolute';
+			info.style.top = '0';
+			info.style.width = '100%';
+			info.style.textAlign = 'center';
+			info.style.padding = '10px';
+			info.style.background = '#FFFFFF';
+			info.innerHTML = '<a href="http://threejs.org" target="_blank">three.js</a> webgl - octree (raycasting performance) - by <a href="http://github.com/collinhover/threeoctree" target="_blank">collinhover</a><br><small style="opacity:0.5">Lucy model from <a href="http://graphics.stanford.edu/data/3Dscanrep/">Stanford 3d scanning repository</a>(decimated with <a href="http://meshlab.sourceforge.net/">Meshlab</a>)</small>';
+			document.body.appendChild( info );
+			
+			// stats
+			
+			stats = new Stats();
+			stats.domElement.style.position = 'absolute';
+			stats.domElement.style.top = '0';
+			stats.domElement.style.left = '0';
+			stats.domElement.style.zIndex = 100;
+			
+			document.body.appendChild( stats.domElement );
+			
+			// bottom container
+			
+			var container = document.createElement( 'div' );
+			container.style.position = 'absolute';
+			container.style.bottom = '0';
+			container.style.width = '100%';
+			container.style.textAlign = 'center';
+			document.body.appendChild( container );
+			
+			// tracker
+			
+			tracker = document.createElement( 'div' );
+			tracker.style.width = '100%';
+			tracker.style.padding = '10px';
+			tracker.style.background = '#FFFFFF';
+			container.appendChild( tracker );
+			
+			// octree use toggle
+			
+			var toggle = document.createElement( 'div' );
+			toggle.style.position = 'absolute';
+			toggle.style.bottom = '100%';
+			toggle.style.width = '100%';
+			toggle.style.padding = '10px';
+			toggle.style.background = '#FFFFFF';
+			container.appendChild( toggle );
+			
+			var checkbox = document.createElement('input');
+			checkbox.type = "checkbox";
+			checkbox.name = "octreeToggle";
+			checkbox.value = "value";
+			checkbox.id = "octreeToggle";
+			checkbox.checked = true;
+
+			var label = document.createElement('label')
+			label.htmlFor = "octreeToggle";
+			label.appendChild(document.createTextNode('Use Octree') );
+
+			toggle.appendChild(checkbox);
+			toggle.appendChild(label);
+			
+			// events
+
+			checkbox.addEventListener( 'click', toggleOctree, false );
+			renderer.domElement.addEventListener( 'mousemove', onDocumentMouseMove, false );
+
+			window.addEventListener( 'resize', onWindowResize, false );
+
+		}
+		
+		function toggleOctree () {
+			
+			useOctree = !useOctree;
+			
+		}
+
+		function animate() {
+
+			// note: three.js includes requestAnimationFrame shim
+			
+			requestAnimationFrame( animate );
+			
+			render();
+			
+			stats.update();
+
+		}
+		
+		function render() {
+
+			controls.update();
+
+			renderer.render( scene, camera );
+			
+			// update octree post render
+			// this ensures any objects being added
+			// have already had their matrices updated
+			
+			octree.update();
+
+		}
+		
+		function modifyOctree( geometry, material, useFaces, randomPosition, randomRotation, randomScale ) {
+			
+			var mesh;
+			
+			if ( geometry ) {
+				
+				// create new object
+				
+				mesh = new THREE.Mesh( geometry, material );
+				
+				// give new object a random position, rotation, and scale
+				
+				if ( randomPosition ) {
+				
+					mesh.position.set( Math.random() * radiusMax - radiusMaxHalf, Math.random() * radiusMax - radiusMaxHalf, Math.random() * radiusMax - radiusMaxHalf );
+				
+				}
+				
+				if ( randomRotation ) {
+					
+					mesh.rotation.set( Math.random() * 2 * Math.PI, Math.random() * 2 * Math.PI, Math.random() * 2 * Math.PI );
+				
+				}
+				
+				if ( randomScale ) {
+					
+					mesh.scale.x = mesh.scale.y = mesh.scale.z = Math.random() * radius * 0.1 + radius * 0.05;
+					
+				}
+				
+				// add new object to octree and scene
+				// NOTE: octree object insertion is deferred until after the next render cycle
+				
+				octree.add( mesh, { useFaces: useFaces } );
+				scene.add( mesh );
+				
+				// store object
+				
+				objects.push( mesh );
+				
+				/*
+				
+				// octree details to console
+				
+				console.log( ' ============================================================================================================');
+				console.log( ' OCTREE: ', octree );
+				console.log( ' ... depth ', octree.depth, ' vs depth end?', octree.depthEnd() );
+				console.log( ' ... num nodes: ', octree.nodeCountEnd() );
+				console.log( ' ... total objects: ', octree.objectCountEnd(), ' vs tree objects length: ', octree.objects.length );
+				console.log( ' ============================================================================================================');
+				console.log( ' ');
+				
+				// print full octree structure to console
+				
+				octree.toConsole();
+				
+				*/
+				
+			}
+			
+		}
+		
+		function onWindowResize() {
+
+			camera.aspect = window.innerWidth / window.innerHeight;
+			camera.updateProjectionMatrix();
+
+			renderer.setSize( window.innerWidth, window.innerHeight );
+
+		}
+
+		function onDocumentMouseMove( event ) {
+
+			event.preventDefault();
+
+			mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
+			mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
+			
+			var vector = new THREE.Vector3( mouse.x, mouse.y, 0.5 );
+			projector.unprojectVector( vector, camera );
+
+			var raycaster = new THREE.Raycaster( camera.position, vector.sub( camera.position ).normalize() );
+			var octreeObjects;
+			var numObjects;
+			var numFaces = 0;
+			var intersections;
+			
+			if ( useOctree ) {
+					
+				octreeObjects = octree.search( raycaster.ray.origin, raycaster.ray.far, true, raycaster.ray.direction );
+				
+				intersections = raycaster.intersectOctreeObjects( octreeObjects );
+				
+				numObjects = octreeObjects.length;
+				
+				for ( var i = 0, il = numObjects; i < il; i++ ) {
+					
+					numFaces += octreeObjects[ i ].faces.length;
+					
+				}
+				
+			}
+			else {
+				
+				intersections = raycaster.intersectObjects( objects );
+				numObjects = objects.length;
+				numFaces = totalFaces;
+				
+			}
+			
+			if ( intersections.length > 0 ) {
+
+				if ( intersected != intersections[ 0 ].object ) {
+
+					if ( intersected ) intersected.material.color.setHex( baseColor );
+
+					intersected = intersections[ 0 ].object;
+					intersected.material.color.setHex( intersectColor );
+
+				}
+
+				document.body.style.cursor = 'pointer';
+
+			}
+			else if ( intersected ) {
+				
+				intersected.material.color.setHex( baseColor );
+				intersected = null;
+
+				document.body.style.cursor = 'auto';
+
+			}
+			
+			// update tracker
+			
+			tracker.innerHTML = ( useOctree ? 'Octree search' : 'Search without octree' ) + ' using infinite ray from camera found [ ' + numObjects + ' / ' + objects.length + ' ] objects, [ ' + numFaces + ' / ' + totalFaces + ' ] faces, and [ ' + intersections.length + ' ] intersections.';
+			
+		}
+
+	</script>
+
+</body>
+
+</html>

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است