Browse Source

fix ArrowHelper so that it can deal with normals pointing down [0,-1,0] via creating a unit test (makeBasis).

Ben Houston 12 years ago
parent
commit
ecc72ff599
2 changed files with 63 additions and 4 deletions
  1. 27 4
      src/extras/helpers/ArrowHelper.js
  2. 36 0
      test/unit/math/Matrix4.js

+ 27 - 4
src/extras/helpers/ArrowHelper.js

@@ -42,13 +42,31 @@ THREE.ArrowHelper.prototype = Object.create( THREE.Object3D.prototype );
 
 THREE.ArrowHelper.prototype.setDirection = function ( dir ) {
 
-	var axis = new THREE.Vector3( 0, 1, 0 ).crossSelf( dir );
+	var matrix = THREE.ArrowHelper.__m0;
+	var yAxis = THREE.ArrowHelper.__vYAxis;
+	var yAxisNeg = THREE.ArrowHelper.__vYAxisNeg;
 
-	var radians = Math.acos( new THREE.Vector3( 0, 1, 0 ).dot( dir.clone().normalize() ) );
+	var axis = dir.clone().normalize();
 
-	this.matrix = new THREE.Matrix4().makeRotationAxis( axis.normalize(), radians );
+	if( axis.distanceTo( yAxis ) < 0.001 ) {
 
-	this.rotation.setEulerFromRotationMatrix( this.matrix, this.eulerOrder );
+		matrix.identity();
+
+	}
+	else if( axis.distanceTo( yAxisNeg ) < 0.001 ) {
+
+		matrix.makeRotationZ( Math.PI );
+
+	}
+	else {
+
+		var perpendicularAxis = THREE.ArrowHelper.__v0.copy( yAxis ).crossSelf( axis );
+		var radians = Math.acos( yAxis.dot( axis ) );
+		matrix.makeRotationAxis( perpendicularAxis.normalize(), radians );
+
+	}
+
+	this.rotation.setEulerFromRotationMatrix( matrix, this.eulerOrder );
 
 };
 
@@ -64,3 +82,8 @@ THREE.ArrowHelper.prototype.setColor = function ( hex ) {
 	this.cone.material.color.setHex( hex );
 
 };
+
+THREE.ArrowHelper.__m0 = new THREE.Matrix4();
+THREE.ArrowHelper.__v0 = new THREE.Vector3();
+THREE.ArrowHelper.__vYAxis = new THREE.Vector3( 0, 1, 0 );
+THREE.ArrowHelper.__vYAxisNeg = new THREE.Vector3( 0, -1, 0 );

+ 36 - 0
test/unit/math/Matrix4.js

@@ -217,6 +217,42 @@ test( "transpose", function() {
 	ok( matrixEquals4( b, c ), "Passed!" ); 
 });
 
+// this function is a duplicate of that in ArrowHelper.
+var makeBasis = function ( axis ) {
+
+	var matrix = new THREE.Matrix4();
+
+	if( axis.distanceTo( new THREE.Vector3( 0, 1, 0 ) ) < 0.001 ) {
+		matrix.identity();
+	}
+	else if( axis.distanceTo( new THREE.Vector3( 0, -1, 0 ) ) < 0.001 ) {
+		matrix.makeRotationZ( Math.PI );
+	}
+	else {
+		var perpendicularAxis = new THREE.Vector3( 0, 1, 0 ).crossSelf( axis );
+		perpendicularAxis.normalize();
+		var radians = Math.acos( new THREE.Vector3( 0, 1, 0 ).dot( perpendicularAxis ) );
+		matrix.makeRotationAxis( perpendicularAxis, radians );
+	}
+
+	return matrix;
+}
+
+test( "makeBasis", function() {
+	var axes = [
+		new THREE.Vector3( 1, 0, 0 ), new THREE.Vector3( 0, 1, 0 ), new THREE.Vector3( 0, 0, 1 ),
+		new THREE.Vector3( -1, 0, 0 ), new THREE.Vector3( 0, -1, 0 ), new THREE.Vector3( 0, 0, -1 )
+	];
+
+	var v = new THREE.Vector3( 0, 1, 0 );
+	for( var i = 0, il = axes.length; i < il; i ++ ) {
+		var v0 = axes[i];
+		var m = makeBasis( v0 );
+		var v1 = m.multiplyVector3( v.clone() );
+		ok( v1.distanceTo( v0 ) < 0.001, "Passed!" );
+	}
+});
+
 test( "clone", function() {
 	var a = new THREE.Matrix4( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 );
 	var b = a.clone();