Pārlūkot izejas kodu

added raycasting pointcloud example. fixed raycasting issues.

fixed example
mschuetz 11 gadi atpakaļ
vecāks
revīzija
c0d3d4ffe4

+ 1 - 0
examples/index.html

@@ -158,6 +158,7 @@
 				"webgl_interactive_cubes_gpu",
 				"webgl_interactive_draggablecubes",
 				"webgl_interactive_particles",
+				"webgl_interactive_raycasting_pointcloud",
 				"webgl_interactive_voxelpainter",
 				"webgl_kinect",
 				"webgl_lensflares",

+ 344 - 0
examples/webgl_interactive_raycasting_pointcloud.html

@@ -0,0 +1,344 @@
+<!doctype html>
+<html lang="en">
+	<head>
+		<title>three.js webgl - interactive - raycasting - pointcloud</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 {
+				color: #ffffff;
+				background-color: #000000;
+				margin: 0px;
+				overflow: hidden;
+			}
+			#info {
+				position: absolute;
+				top: 0px;
+				width: 100%;
+				padding: 5px;
+				font-family: Monospace;
+				font-size: 13px;
+				text-align: center;
+				font-weight: bold;
+			}
+			a {
+				color: #fff;
+			}
+		</style>
+	</head>
+
+	<body>
+		<div id="container"></div>
+		<div id="info"><a href="http://threejs.org" target="_blank">three.js</a> webgl - interactive - raycasting - pointcloud </div>
+
+		<script src="../build/three.min.js"></script>
+
+		<script src="js/Detector.js"></script>
+		<script src="js/libs/stats.min.js"></script>
+
+		<script>
+
+			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
+
+			var renderer, scene, camera, stats;
+			var pointclouds;
+			var projector, raycaster, intersects;
+			var mouse = { x: 1, y: 1 };
+			var vector = new THREE.Vector3();
+			var intersection = null;
+			var spheres = [];
+			var spheresIndex = 0;
+			var clock;
+			
+			var threshold = 0.1;
+			var pointSize = 0.01;
+			var width = 150;
+			var length = 150;
+			var rotateY = new THREE.Matrix4().makeRotationY( 0.005 );
+
+			init();
+			animate();
+			
+			function generatePointCloudGeometry( color, width, length ){
+			
+				var geometry = new THREE.BufferGeometry();
+				var numPoints = width*length;
+				
+				var positions = new Float32Array( numPoints*3 );
+				var colors = new Float32Array( numPoints*3 );
+				
+				var k = 0;
+				for( var i = 0; i < width; i++ ) { 
+					for( var j = 0; j < length; j++ ) {
+						var u = i / width;
+						var v = j / length;
+						var x = u - 0.5;
+						var y = ( Math.cos( u * Math.PI * 8 ) + Math.sin( v * Math.PI * 8 ) ) / 20;
+						var z = v - 0.5;
+						
+						positions[ 3 * k ] = x;
+						positions[ 3 * k + 1 ] = y;
+						positions[ 3 * k + 2 ] = z;
+						
+						var intensity = ( y + 0.1 ) * 5;
+						colors[ 3 * k ] = color.r * intensity;
+						colors[ 3 * k + 1 ] = color.g * intensity;
+						colors[ 3 * k + 2 ] = color.b * intensity;
+						k++;
+					}
+				}
+				
+				geometry.addAttribute( 'position', new THREE.Float32Attribute( positions, 3 ) );
+				geometry.addAttribute( 'color', new THREE.Float32Attribute( colors, 3 ) );
+				geometry.computeBoundingBox();
+				
+				return geometry;
+				
+			}
+			
+			function generatePointcloud( color, width, length ) {
+			
+				var geometry = generatePointCloudGeometry( color, width, length );
+				
+				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: true } );
+				var pointcloud = new THREE.PointCloud( geometry, material );
+				
+				return pointcloud;
+				
+			}
+			
+			function generateIndexedPointcloud( color, width, length ) {
+			
+				var geometry = generatePointCloudGeometry( color, width, length );
+				var numPoints = width * length;
+				var indices = new Uint16Array( numPoints );
+				
+				var k = 0;
+				for( var i = 0; i < width; i++ ) {
+					for( var j = 0; j < length; j++ ) {
+						indices[ k ] = k;
+						k++;
+					}
+				}
+				
+				geometry.addAttribute( 'index', new THREE.Uint16Attribute( indices, 1 ) );
+				
+				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: true } );
+				var pointcloud = new THREE.PointCloud( geometry, material );
+				
+				return pointcloud;
+				
+			}
+			
+			function generateIndexedWithOffsetPointcloud( color, width, length ){
+			
+				var geometry = generatePointCloudGeometry( color, width, length );
+				var numPoints = width * length;
+				var indices = new Uint16Array( numPoints );
+				
+				var k = 0;
+				for( var i = 0; i < width; i++ ){
+					for( var j = 0; j < length; j++ ) {
+						indices[ k ] = k;
+						k++;
+					}
+				}
+				
+				geometry.addAttribute( 'index', new THREE.Uint16Attribute( indices, 1 ) );
+				
+				var offset = { start: 0, count: indices.length, index: 0 };
+				geometry.offsets.push( offset );
+				
+				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: true } );
+				var pointcloud = new THREE.PointCloud( geometry, material );
+				
+				return pointcloud;
+				
+			}
+			
+			function generateRegularPointcloud( color, width, length ) {
+			
+				var geometry = new THREE.Geometry();
+				var numPoints = width * length;
+				
+				var colors = [];
+				
+				var k = 0;
+				for( var i = 0; i < width; i++ ) {
+					for( var j = 0; j < length; j++ ) {
+						var u = i / width;
+						var v = j / length;
+						var x = u - 0.5;
+						var y = ( Math.cos( u * Math.PI * 8 ) + Math.sin( v * Math.PI * 8) ) / 20;
+						var z = v - 0.5;	
+						var v = new THREE.Vector3( x,y,z );
+						
+						var intensity = ( y + 0.1 ) * 7;
+						colors[ 3 * k ] = color.r * intensity;
+						colors[ 3 * k + 1 ] = color.g * intensity;
+						colors[ 3 * k + 2 ] = color.b * intensity;
+						
+						geometry.vertices.push( v );
+						colors[ k ] = ( color.clone().multiplyScalar( intensity ) );
+						
+						k++;
+					}
+				}
+				
+				geometry.colors = colors;
+				geometry.computeBoundingBox();
+				
+				var material = new THREE.PointCloudMaterial( { size: pointSize, vertexColors: true } );
+				var pointcloud = new THREE.PointCloud( geometry, material );
+				
+				return pointcloud;
+				
+			}
+
+			function init() {
+
+				container = document.getElementById( 'container' );
+
+				scene = new THREE.Scene();
+				
+				clock = new THREE.Clock();
+
+				camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 );
+				camera.applyMatrix( new THREE.Matrix4().makeTranslation( 0,0,20 ) );
+				camera.applyMatrix( new THREE.Matrix4().makeRotationX( -0.5 ) );
+
+				//
+
+				pcBuffer = generatePointcloud( new THREE.Color( 1,0,0 ), width, length );
+				pcBuffer.scale.set( 10,10,10 );
+				pcBuffer.position.set( -5,0,5 );
+				scene.add( pcBuffer );
+					
+				var pcIndexed = generateIndexedPointcloud( new THREE.Color( 0,1,0 ), width, length );
+				pcIndexed.scale.set( 10,10,10 );
+				pcIndexed.position.set( 5,0,5 );
+				scene.add( pcIndexed );
+			
+				var pcIndexedOffset = generateIndexedWithOffsetPointcloud( new THREE.Color( 0,1,1 ), width, length );
+				pcIndexedOffset.scale.set( 10,10,10 );
+				pcIndexedOffset.position.set( 5,0,-5 );
+				scene.add( pcIndexedOffset );
+				
+				var pcRegular = generateRegularPointcloud( new THREE.Color( 1,0,1 ), width, length );
+				pcRegular.scale.set( 10,10,10 );
+				pcRegular.position.set( -5,0,-5 );
+				scene.add( pcRegular );
+                
+				pointclouds = [ pcBuffer, pcIndexed, pcIndexedOffset, pcRegular ];
+				
+				//
+				
+				var sphereGeometry = new THREE.SphereGeometry( 0.1, 32, 32 );
+				var sphereMaterial = new THREE.MeshBasicMaterial( { color: 0xff0000, shading: THREE.FlatShading } );
+				
+				for ( var i = 0; i < 40; i++ ) { 
+				
+					var sphere = new THREE.Mesh( sphereGeometry, sphereMaterial );
+					scene.add( sphere );
+					spheres.push( sphere );
+				
+				}
+
+				//
+
+				renderer = new THREE.WebGLRenderer();
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+				container.appendChild( renderer.domElement );
+
+				//
+
+				projector = new THREE.Projector();
+				raycaster = new THREE.Raycaster();
+				raycaster.params.PointCloud.threshold = threshold;
+
+				//
+
+				stats = new Stats();
+				stats.domElement.style.position = 'absolute';
+				stats.domElement.style.top = '0px';
+				container.appendChild( stats.domElement );
+
+				//
+
+				window.addEventListener( 'resize', onWindowResize, false );
+				document.addEventListener( 'mousemove', onDocumentMouseMove, false );
+				
+			}
+
+			function onDocumentMouseMove( event ) {
+
+				event.preventDefault();
+
+				mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
+				mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
+
+			}
+
+			function onWindowResize() {
+
+				camera.aspect = window.innerWidth / window.innerHeight;
+				camera.updateProjectionMatrix();
+
+				renderer.setSize( window.innerWidth, window.innerHeight );
+
+			}
+
+			function animate() {
+
+				requestAnimationFrame( animate );
+
+				render();
+				stats.update();
+
+			}
+			
+			var toggle = 0;
+			
+			function render() { 
+			
+				camera.applyMatrix( rotateY );
+				camera.updateMatrixWorld( true );
+				
+				vector.set( mouse.x, mouse.y, 0.1 );
+
+				projector.unprojectVector( vector, camera );
+
+				raycaster.ray.set( camera.position, vector.sub( camera.position ).normalize() );
+			    
+				var intersections = raycaster.intersectObjects( pointclouds );
+				intersection = ( intersections.length ) > 0 ? intersections[ 0 ] : null;
+				
+				if ( toggle > 0.02 && intersection !== null) {
+					
+					spheres[ spheresIndex ].position.copy( intersection.point );
+					spheres[ spheresIndex ].scale.set( 1, 1, 1 );
+					spheresIndex = ( spheresIndex + 1 ) % spheres.length;
+					
+					toggle = 0;
+				
+				}
+				
+				for ( var i = 0; i < spheres.length; i++ ) {
+					
+					var sphere = spheres[ i ];
+					sphere.scale.multiplyScalar( 0.98 );
+					sphere.scale.clampScalar( 0.01, 1 );
+				
+				}
+				
+				toggle += clock.getDelta();
+
+				renderer.render( scene, camera );
+			}
+
+		</script>
+
+	</body>
+
+</html>

+ 26 - 21
src/core/Raycaster.js

@@ -14,12 +14,14 @@
 		this.near = near || 0;
 		this.far = far || Infinity;
 
-		this.params = {};
-		this.params.Sprite = {};
-		this.params.Mesh = {};
-		this.params.PointCloud = {threshold: 1};
-		this.params.LOD = {};
-		this.params.Line = {};
+		this.params = {
+			Sprite: {},
+			Mesh: {},
+			PointCloud: { threshold: 1 },
+			LOD: {},
+			Line: {}
+		};
+		
 	};
 
 	var sphere = new THREE.Sphere();
@@ -82,8 +84,8 @@
 				
 			}
 			
+			var localThreshold = threshold / ( ( object.scale.x + object.scale.y + object.scale.z ) / 3 );
 			var pos = new THREE.Vector3();
-			var intersectPoint = new THREE.Vector3();
 
 			if ( geometry instanceof THREE.BufferGeometry ) {
 			
@@ -123,10 +125,11 @@
 								positions[ a * 3 + 2 ]
 							);
 							
-							var rayPointDistance = localRay.distanceToPoint( pos, intersectPoint );
-							
-							if ( rayPointDistance < threshold ) {
-							
+							var rayPointDistance = localRay.distanceToPoint( pos );
+
+							if ( rayPointDistance < localThreshold ) {
+								
+								var intersectPoint = localRay.closestPointToPoint( pos );
 								intersectPoint.applyMatrix4( object.matrixWorld );
 								var distance = raycaster.ray.origin.distanceTo( intersectPoint );
 							
@@ -158,11 +161,12 @@
 							positions[ 3 * i + 1 ], 
 							positions[ 3 * i + 2 ]
 						);
-						
-						var rayPointDistance = localRay.distanceToPoint( pos, intersectPoint );
 
-						if ( rayPointDistance < threshold ) {
-						
+						var rayPointDistance = localRay.distanceToPoint( pos );
+
+						if ( rayPointDistance < localThreshold ) {
+							
+							var intersectPoint = localRay.closestPointToPoint( pos );
 							intersectPoint.applyMatrix4( object.matrixWorld );
 							var distance = raycaster.ray.origin.distanceTo( intersectPoint );
 							
@@ -170,7 +174,7 @@
 							
 								distance: distance,
 								distanceToRay: rayPointDistance,
-								point: intersectPoint.clone(),
+								point: intersectPoint,
 								index: i,
 								face: null,
 								object: object
@@ -189,12 +193,13 @@
 
 				for ( var i = 0; i < vertices.length; i ++ ) {
 
-					var v = vertices[ i ];
-					
-					var rayPointDistance = localRay.distanceToPoint( v, intersectPoint );
-					
-					if ( rayPointDistance < threshold ) {
+					pos = vertices[ i ];
 					
+					var rayPointDistance = localRay.distanceToPoint( pos );
+
+					if ( rayPointDistance < localThreshold ) {
+						
+						var intersectPoint = localRay.closestPointToPoint( pos );
 						intersectPoint.applyMatrix4( object.matrixWorld );
 						var distance = raycaster.ray.origin.distanceTo( intersectPoint );
 						

+ 6 - 10
src/math/Ray.js

@@ -73,25 +73,21 @@ THREE.Ray.prototype = {
 
 		var v1 = new THREE.Vector3();
 
-		return function ( point, optionalIntersectionPoint ) {
-		
-			var v = ( optionalIntersectionPoint !== undefined ) ? optionalIntersectionPoint : v1;
+		return function ( point ) {
 
-			var directionDistance = v.subVectors( point, this.origin ).dot( this.direction );
+			var directionDistance = v1.subVectors( point, this.origin ).dot( this.direction );
 
 			// point behind the ray
 
 			if ( directionDistance < 0 ) {
 
-				v.copy( this.origin );
+				return this.origin.distanceTo( point );
 
-			} else {
-			
-				v.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
-			
 			}
 
-			return v.distanceTo( point );
+			v1.copy( this.direction ).multiplyScalar( directionDistance ).add( this.origin );
+
+			return v1.distanceTo( point );
 
 		};