Browse Source

LOD support in Raycaster. Fixes #3167.

Mr.doob 12 years ago
parent
commit
6cf4fb7bdd
2 changed files with 56 additions and 30 deletions
  1. 11 4
      src/core/Raycaster.js
  2. 45 26
      src/objects/LOD.js

+ 11 - 4
src/core/Raycaster.js

@@ -10,7 +10,7 @@
 		this.ray = new THREE.Ray( origin, direction );
 
 		// normalized ray.direction required for accurate distance calculations
-		if( this.ray.direction.lengthSq() > 0 ) {
+		if ( this.ray.direction.lengthSq() > 0 ) {
 
 			this.ray.direction.normalize();
 
@@ -57,6 +57,13 @@
 
 			} );
 
+		} else if ( object instanceof THREE.LOD ) {
+
+			matrixPosition.getPositionFromMatrix( object.matrixWorld );
+			var distance = raycaster.ray.origin.distanceTo( matrixPosition );
+
+			intersectObject( object.getObjectForDistance( distance ), raycaster, intersects );
+
 		} else if ( object instanceof THREE.Mesh ) {
 
 			// Checking boundingSphere distance to ray
@@ -110,11 +117,11 @@
 
 				// check if we hit the wrong side of a single sided face
 				side = material.side;
-				if( side !== THREE.DoubleSide ) {
+				if ( side !== THREE.DoubleSide ) {
 
 					var planeSign = localRay.direction.dot( facePlane.normal );
 
-					if( ! ( side === THREE.FrontSide ? planeSign < 0 : planeSign > 0 ) ) continue;
+					if ( ! ( side === THREE.FrontSide ? planeSign < 0 : planeSign > 0 ) ) continue;
 
 				}
 
@@ -185,7 +192,7 @@
 		this.ray.set( origin, direction );
 
 		// normalized ray.direction required for accurate distance calculations
-		if( this.ray.direction.length() > 0 ) {
+		if ( this.ray.direction.length() > 0 ) {
 
 			this.ray.direction.normalize();
 

+ 45 - 26
src/objects/LOD.js

@@ -8,26 +8,39 @@ THREE.LOD = function () {
 
 	THREE.Object3D.call( this );
 
-	this.LODs = [];
+	this.objects = [];
 
 };
 
 
 THREE.LOD.prototype = Object.create( THREE.Object3D.prototype );
 
-THREE.LOD.prototype.addLevel = function ( object3D, visibleAtDistance ) {
+THREE.LOD.prototype.addLevel = function ( object, distance ) {
 
-	if ( visibleAtDistance === undefined ) {
+	if ( distance === undefined ) distance = 0;
 
-		visibleAtDistance = 0;
+	distance = Math.abs( distance );
+
+	for ( var l = 0; l < this.objects.length; l ++ ) {
+
+		if ( distance < this.objects[ l ].distance ) {
+
+			break;
+
+		}
 
 	}
 
-	visibleAtDistance = Math.abs( visibleAtDistance );
+	this.objects.splice( l, 0, { distance: distance, object: object } );
+	this.add( object );
+
+};
+
+THREE.LOD.prototype.getObjectForDistance = function ( distance ) {
 
-	for ( var l = 0; l < this.LODs.length; l ++ ) {
+	for ( var i = 1, l = this.objects.length; i < l; i ++ ) {
 
-		if ( visibleAtDistance < this.LODs[ l ].visibleAtDistance ) {
+		if ( distance < this.objects[ i ].distance ) {
 
 			break;
 
@@ -35,46 +48,52 @@ THREE.LOD.prototype.addLevel = function ( object3D, visibleAtDistance ) {
 
 	}
 
-	this.LODs.splice( l, 0, { visibleAtDistance: visibleAtDistance, object3D: object3D } );
-	this.add( object3D );
+	return this.objects[ i - 1 ].object;
 
 };
 
-THREE.LOD.prototype.update = function ( camera ) {
+THREE.LOD.prototype.update = function () {
+
+	var v1 = new THREE.Vector3();
+	var v2 = new THREE.Vector3();
+
+	return function ( camera ) {
+
+		if ( this.objects.length > 1 ) {
 
-	if ( this.LODs.length > 1 ) {
+			v1.getPositionFromMatrix( camera.matrixWorld );
+			v2.getPositionFromMatrix( this.matrixWorld );
 
-		camera.matrixWorldInverse.getInverse( camera.matrixWorld );
+			var distance = v1.distanceTo( v2 );
 
-		var inverse  = camera.matrixWorldInverse;
-		var distance = -( inverse.elements[2] * this.matrixWorld.elements[12] + inverse.elements[6] * this.matrixWorld.elements[13] + inverse.elements[10] * this.matrixWorld.elements[14] + inverse.elements[14] );
+			this.objects[ 0 ].object.visible = true;
 
-		this.LODs[ 0 ].object3D.visible = true;
+			for ( var i = 1, l = this.objects.length; i < l; i ++ ) {
 
-		for ( var l = 1; l < this.LODs.length; l ++ ) {
+				if ( distance >= this.objects[ i ].distance ) {
 
-			if( distance >= this.LODs[ l ].visibleAtDistance ) {
+					this.objects[ i - 1 ].object.visible = false;
+					this.objects[ i     ].object.visible = true;
 
-				this.LODs[ l - 1 ].object3D.visible = false;
-				this.LODs[ l     ].object3D.visible = true;
+				} else {
 
-			} else {
+					break;
 
-				break;
+				}
 
 			}
 
-		}
+			for( ; i < l; i ++ ) {
 
-		for( ; l < this.LODs.length; l ++ ) {
+				this.objects[ i ].object.visible = false;
 
-			this.LODs[ l ].object3D.visible = false;
+			}
 
 		}
 
-	}
+	};
 
-};
+}();
 
 THREE.LOD.prototype.clone = function () {