Browse Source

Projector.unprojectVector() apparently working
Work in progress refactoring ClickResolver.js to Ray.js

Mr.doob 14 years ago
parent
commit
b57169bc84
6 changed files with 111 additions and 168 deletions
  1. 3 0
      TODO
  2. 26 39
      examples/camera_orthographic.html
  3. 27 17
      examples/interactive_spheres.html
  4. 26 0
      src/core/Ray.js
  5. 17 112
      src/hci/ClickResolver.js
  6. 12 0
      src/renderers/Projector.js

+ 3 - 0
TODO

@@ -5,6 +5,9 @@ Core
 Examples
 * DOMRenderer example
 
+Examples/Geometry/Primitives
+* Create more primitives. http://code.google.com/p/ogre-procedural/source/browse/#hg/library/src
+
 Materials
 * MeshBitmapSphereMappingMaterial. http://en.wikipedia.org/wiki/Sphere_mapping
 * MeshBitmapCubeMappingMaterial. http://en.wikipedia.org/wiki/Cube_mapping

+ 26 - 39
examples/camera_orthographic.html

@@ -27,37 +27,11 @@
 			var SCREEN_WIDTH = window.innerWidth;
 			var SCREEN_HEIGHT = window.innerHeight;
 
-			var container;
-			var stats;
-
-			var camera;
-			var scene;
-			var renderer;
-
-			var cube, plane;
-
-			var mouseX = 0;
-			var mouseXOnMouseDown = 0;
-
-			var windowHalfX = window.innerWidth / 2;
-			var windowHalfY = window.innerHeight / 2;
-
-			var moveForward = false,
-			moveBackwards = false,
-			moveUp = false,
-			moveDown = false,
-			moveLeft = false,
-			moveRight = false,
-
-			yawLeft = false,
-			yawRight = false,
-			pitchUp = false,
-			pitchDown = false,
-			rollLeft = false,
-			rollRight = false;
+			var container, stats;
+			var camera, scene, renderer;
 
 			init();
-			setInterval(loop, 1000/60);
+			setInterval( loop, 1000 / 60 );
 
 			function init() {
 
@@ -67,22 +41,37 @@
 				camera = new THREE.Camera( 45, SCREEN_WIDTH / SCREEN_HEIGHT, 1, 10000 );
 				camera.projectionMatrix = THREE.Matrix4.makeOrtho( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, -2000, 1000 );
 				camera.position.x = 200;
-				camera.position.y = 150;
+				camera.position.y = 100;
 				camera.position.z = 200;
 
 				scene = new THREE.Scene();
 
-				// Plane
+				// Grid
+
+				var geometry = new THREE.Geometry();
+				geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( - 500, 0, 0 ) ) );
+				geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( 500, 0, 0 ) ) );
 
-				plane = new THREE.Mesh( new Plane( 1000, 1000, 20, 20 ), new THREE.MeshColorStrokeMaterial( 0x000000, 0.2 ) );
-				plane.rotation.x = - 90 * ( Math.PI / 180 );
-				scene.addObject( plane );
+				for ( var i = 0; i <= 20; i ++ ) {
 
-				geometry = new Cube( 50, 50, 50 );
+					var line = new THREE.Line( geometry, new THREE.LineColorMaterial( 0x000000, 0.2 ) );
+					line.position.z = ( i * 50 ) - 500;
+					scene.addObject( line );
 
-				for (var i = 0; i < 100; i ++ ) {
+					var line = new THREE.Line( geometry, new THREE.LineColorMaterial( 0x000000, 0.2 ) );
+					line.position.x = ( i * 50 ) - 500;
+					line.rotation.y = 90 * Math.PI / 180;
+					scene.addObject( line );
 
-					cube = new THREE.Mesh(geometry, new THREE.MeshColorFillMaterial( 0xffffff, Math.random() * 0.5 + 0.5 ) );
+				}
+
+				// Cubes
+
+				var geometry = new Cube( 50, 50, 50 );
+
+				for ( var i = 0; i < 100; i ++ ) {
+
+					var cube = new THREE.Mesh( geometry, new THREE.MeshColorFillMaterial( 0xffffff, Math.random() * 0.5 + 0.5 ) );
 					cube.overdraw = true;
 
 					cube.scale.y = Math.floor( Math.random() * 2 + 1 );
@@ -126,8 +115,6 @@
 
 			}
 
-			//
-
 			function loop() {
 
 				var timer = new Date().getTime() * 0.0001;

+ 27 - 17
examples/interactive_spheres.html

@@ -75,11 +75,7 @@
 
 			var cube, plane;
 
-			var targetRotation = 0;
-			var targetRotationOnMouseDown = 0;
-
-			var mouseX = 0;
-			var mouseXOnMouseDown = 0;
+			var mouseX = 0, mouseY = 0, projector;
 
 			var windowHalfX = window.innerWidth / 2;
 			var windowHalfY = window.innerHeight / 2;
@@ -130,7 +126,7 @@
 				cube.position.y = 150;
 				scene.addObject(cube);
 
-				geometry2 = new Sphere( 100 );
+				geometry2 = new Sphere( 100, 20, 20 );
 
 				for (var i = 0, l = geometry2.faces.length; i < l; i++) {
 
@@ -148,12 +144,11 @@
 				cube2.position.z = 300;
 				scene.addObject(cube2);
 
-				/*
 				var geometry = new THREE.Geometry();
 
 				for (var i = 0; i < 100; i ++) {
 
-					var v = new THREE.Vector3( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 );
+					var v = new THREE.Vector3( Math.random() * 1000 - 500, Math.random() * 1000 - 500, Math.random() * 1000 - 500 );
 
 					var v0 = new THREE.Vertex( new THREE.Vector3( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ) );
 					var v1 = new THREE.Vertex( new THREE.Vector3( Math.random() * 100 - 50, Math.random() * 100 - 50, Math.random() * 100 - 50 ) );
@@ -172,10 +167,11 @@
 				geometry.computeCentroids();
 
 				var mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial() );
-				mesh.doubleSided = true;
-				mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
+				// mesh.doubleSided = true;
+				// mesh.scale.x = mesh.scale.y = mesh.scale.z = 2;
 				scene.addObject(mesh);
-				*/
+
+				projector = new THREE.Projector();
 
 				renderer = new THREE.CanvasRenderer();
 				renderer.setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
@@ -188,30 +184,44 @@
 				container.appendChild(stats.domElement);
 
 				document.addEventListener('mousedown', onDocumentMouseDown, false);
+				// document.addEventListener('mousemove', onDocumentMouseMove, false);
 			}
 
 			function onDocumentMouseDown( event ) {
 
 				event.preventDefault();
 
-				document.getElementById("msg").innerHTML = ""; 
+				document.getElementById("msg").innerHTML = "";
+
+				clickResolver.findIntersectInScene( event.clientX / window.innerWidth, event.clientY / window.innerHeight );
+
+				var vector = projector.unprojectVector( new THREE.Vector3( ( event.clientX / window.innerWidth ) * 2 - 1, - ( event.clientY / window.innerHeight ) * 2 + 1, 0.95 ), camera );
+
+				var particle = new THREE.Particle( new THREE.ParticleCircleMaterial( 0xff0000 ) );
+				particle.position = vector;
 
-				clickResolver.findIntersectInScene(
-						event.clientX/window.innerWidth,
-						event.clientY/window.innerHeight);
+				scene.addObject( particle );
+			}
+
+			function onDocumentMouseMove( event ) {
+
+				mouseX = event.clientX / window.innerWidth;
+				mouseY = event.clientY / window.innerHeight;
 
 			}
 
 			var radius = 600;
 			var theta = 0;
-			
+
 			function loop() {
 
-				theta += 1;
+				theta += 0.2;
 				camera.position.x = radius * Math.sin( theta * Math.PI / 360 );
 				// camera.position.y = radius * Math.sin( theta * Math.PI / 360 );
 				camera.position.z = radius * Math.cos( theta * Math.PI / 360 );
 
+				// clickResolver.findIntersectInScene( mouseX, mouseY );
+
 				renderer.render(scene, camera);
 				stats.update();
 			}

+ 26 - 0
src/core/Ray.js

@@ -0,0 +1,26 @@
+/**
+ * @author mr.doob / http://mrdoob.com/
+ */
+
+THREE.Ray = new function ( origin, direction ) {
+
+	this.origin = origin || new THREE.Vector3();
+	this.direction = direction || new THREE.Vector3();
+
+}
+
+THREE.Ray.prototype = {
+
+	intersectScene: function ( scene ) {
+	
+		
+	
+	},
+	
+	intersectFace: function ( face ) {
+	
+		
+	
+	}
+
+};

+ 17 - 112
src/hci/ClickResolver.js

@@ -4,7 +4,7 @@ THREE.ClickResolver = function( camera, scene ) {
 	this.camera = camera;
 	this.scene  = scene;
 	this._debug = false;
-	
+
 };
 
 THREE.ClickResolver.prototype = {
@@ -56,124 +56,62 @@ THREE.ClickResolver.prototype = {
 		var coordAtZIndex = new THREE.Vector3();
 
 		rayToZIndex.sub( this.camera.target.position, this.camera.position ).setLength( targetZIndex );
-		
+
 		maxVisibleYatZIndex = rayToZIndex.length() * Math.tan( this.camera.fov * Math.PI / 360 );
 		maxVisibleXatZIndex = maxVisibleYatZIndex  * this.camera.aspect;
-		
+
 		left.cross( this.camera.up, rayToZIndex );
 		up  .cross( rayToZIndex, left );
-		
+
 		return coordAtZIndex.add( this.camera.position, rayToZIndex ).
 			addSelf( left.setLength( maxVisibleXatZIndex * ( 1 - 2 * xPercent ))).
 			addSelf( up  .setLength( maxVisibleYatZIndex * ( 1 - 2 * yPercent )));
-	},
-	
-	
-	logPoint: function( scene, v, hex ) {
-		
-		if ( this._debug ) {
-			
-			var p = new THREE.Particle( new THREE.ParticleCircleMaterial( hex, 0.5 ) );
-			p.position = v.clone();
-			p.scale.x = p.scale.y = p.scale.z = 5;
-			
-			scene.addObject( p );
-		}
-	},
-	
-	
-	logLine: function( scene, s, e, hex ) {
-
-		if ( this._debug ) {
-
-			this.logPoint( scene, s.clone(), 0x000000 );
-			
-			var lg = new THREE.Geometry();
-			
-			lg.vertices[0] = new THREE.Vertex( s.clone() );
-			lg.vertices[1] = new THREE.Vertex( e.clone() );
-			
-			scene.addObject( new THREE.Line( lg, new THREE.LineColorMaterial( hex, 0.5 ) ) );
-		}
 
 	},
-	
-	
+
 	getIntersectingFaces: function( scene, camera, object3d, linePoint, lineDir ) {
-		
+
 		var intersect = {
 			face     : null,
 			point    : null,
 			distance : Number.MAX_VALUE
 		};
-		
+
 		var geometry = object3d.geometry;
 		var matrix = object3d.matrix;
-		
+
 		for ( f = 0; f < geometry.faces.length; f++ ) {
-			
+
 			var face = geometry.faces[ f ];
-			
+
 			// if ( !face.selectable ) continue;
-			
+
 			var a = matrix.transform( geometry.vertices[ face.a ].position.clone() );
 			var b = matrix.transform( geometry.vertices[ face.b ].position.clone() );
 			var c = matrix.transform( geometry.vertices[ face.c ].position.clone() );
-			var d = face.d ? matrix.transform( geometry.vertices[ face.d ].position.clone() ) : null;
-			
+			var d = face instanceof THREE.Face4 ? matrix.transform( geometry.vertices[ face.d ].position.clone() ) : null;
+
 			var lineStart = linePoint.clone();
 			var lineDirection = lineDir.clone();
 			var dot = face.normal.dot( lineDirection );
-			
-			if ( this._debug ) {
-
-				this.logLine( scene, a, new THREE.Vector3().add( a, new THREE.Vector3().addSelf( face.normal ).multiplyScalar( 100 ) ), 0x0000FF );
-				this.logLine( scene, lineStart, lineStart.clone().addSelf( lineDirection ), 0x55FF88 );
-				this.logPoint( scene, a, 0xFF0000 ); // r
-				this.logPoint( scene, b, 0x00FF00 ); // g
-				this.logPoint( scene, c, 0x0000FF ); // b
-				if ( d ) this.logPoint( scene, d, 0xFFFF00 ); // y
-			}
 
 			if ( dot < 0 ) { // Math.abs( dot ) > 0.0001
 
 				var s = face.normal.dot( new THREE.Vector3().sub( a, lineStart ) ) / dot;
 				var planeIntersect = lineStart.addSelf( lineDirection.multiplyScalar( s ) );
 
-				// if ( this._debug ) this.logPoint( scene, planeIntersect, 0x808080 );
-
-				if ( d == null ) {
-
-					/*
-					var ab = isInsideBoundary( planeIntersect, a, b, c );
-					var bc = isInsideBoundary( planeIntersect, b, c, a );
-					var ca = isInsideBoundary( planeIntersect, c, a, b );
-
-					if ( ab && bc && ca ) {
-					*/
+				if ( face instanceof THREE.Face3 ) {
 
-					// console.log( f, ab, bc, ca );
+					if ( pointInFace3( planeIntersect, a, b, c ) ) {
 
-					if ( pointInFace3Fast( planeIntersect, a, b, c ) ) {
-
-						if ( this._debug ) this.logPoint( scene, planeIntersect, 0x0000ff );
 						logIntersect( planeIntersect, face );
 
 					}
 
-				} else {
-
-					/*
-					var ab = isInsideBoundary( planeIntersect, a, b, c );
-					var bc = isInsideBoundary( planeIntersect, b, c, d );
-					var cd = isInsideBoundary( planeIntersect, c, d, a );
-					var da = isInsideBoundary( planeIntersect, d, a, b );
+				} else if ( face instanceof THREE.Face4 ) {
 
-					if ( ab && bc && cd && da ) {
-					*/
-					if ( pointInFace4( planeIntersect, a, b, c, d ) ) {
+					if ( pointInFace3( planeIntersect, a, b, d ) || pointInFace3( planeIntersect, b, c, d ) ) {
 
-						if ( this._debug ) this.logPoint( scene, planeIntersect, 0x000000 );
 						logIntersect( planeIntersect, face );
 
 					}
@@ -198,28 +136,10 @@ THREE.ClickResolver.prototype = {
 
 		}
 
-		/*
-		function isInsideBoundary( pointOnPlaneToCheck, pointInside, boundaryPointA, boundaryPointB ) {
-
-			var toB = boundaryPointB.clone().subSelf( boundaryPointA );
-			var toI = pointInside.clone().subSelf( boundaryPointA );
-			var pointMid = toB.setLength( toI.dot( toB ) ).addSelf( boundaryPointA );
-			var pointMirror = pointMid.subSelf( pointInside ).multiplyScalar( 2 ).addSelf( pointInside );
-
-			return pointOnPlaneToCheck.distanceToSquared( pointInside ) < pointOnPlaneToCheck.distanceToSquared( pointMirror );
-		}
-		*/
-
 		// http://www.blackpawn.com/texts/pointinpoly/default.html
 
 		function pointInFace3( p, a, b, c ) {
 
-			return sameSide( p, a, b, c ) && sameSide( p, b, a, c ) && sameSide( p, c, a, b );
-
-		}
-
-		function pointInFace3Fast( p, a, b, c ) {
-
 			var v0 = c.clone().subSelf( a ), v1 = b.clone().subSelf( a ), v2 = p.clone().subSelf( a ),
 			dot00 = v0.dot( v0 ), dot01 = v0.dot( v1 ), dot02 = v0.dot( v2 ), dot11 = v1.dot( v1 ), dot12 = v1.dot( v2 ),
 
@@ -231,22 +151,7 @@ THREE.ClickResolver.prototype = {
 
 		}
 
-		function pointInFace4( p, a, b, c, d ) {
-
-			return sameSide( p, a, b, c ) && sameSide( p, b, c, d ) && sameSide( p, c, d, a ) && sameSide( p, c, a, b );
-
-		}
-
-		function sameSide( p1, p2, a, b ) {
-
-			var cp1 = new THREE.Vector3().cross( b.clone().subSelf( a ), p1.clone().subSelf( a ) );
-			var cp2 = new THREE.Vector3().cross( b.clone().subSelf( a ), p2.clone().subSelf( a ) );
-			return cp1.dot( cp2 ) >= 0;
-
-		}
-
 		return intersect;
 	}
 
-
 };

+ 12 - 0
src/renderers/Projector.js

@@ -238,4 +238,16 @@ THREE.Projector = function() {
 
 	};
 
+	this.unprojectVector = function ( vector, camera ) {
+
+		var vector2 = vector.clone(),
+		matrix = new THREE.Matrix4();
+
+		matrix.multiply( THREE.Matrix4.makeInvert( camera.matrix ), THREE.Matrix4.makeInvert( camera.projectionMatrix ) );
+		matrix.transform( vector2 );
+
+		return vector2;
+
+	};
+
 };