Browse Source

Refactor TNB calculations into THREE.TubeGeometry.FrenetFrames

zz85 13 years ago
parent
commit
569ba0f707
1 changed files with 126 additions and 96 deletions
  1. 126 96
      src/extras/geometries/TubeGeometry.js

+ 126 - 96
src/extras/geometries/TubeGeometry.js

@@ -25,62 +25,166 @@ THREE.TubeGeometry = function( path, segments, radius, segmentsRadius, closed, d
 	this.grid = [];
 
 	var scope = this,
-		tangent = new THREE.Vector3(),
-		normal = new THREE.Vector3(),
-		binormal = new THREE.Vector3(),
-
-		vec = new THREE.Vector3(),
-		mat = new THREE.Matrix4(),
 
-		tangents = [],
-		normals = [],
-		binormals = [],
+		tangent,
+		normal,
+		binormal,
 
 		numpoints = this.segments + 1,
-		theta,
-		epsilon = 0.0001,
-		smallest,
+		
 		x, y, z,
 		tx, ty, tz,
 		u, v,
-		p1, p2,
+
 		cx, cy,
-		pos, pos2,
+		pos, pos2 = new THREE.Vector3(),
 		i, j,
 		ip, jp,
 		a, b, c, d,
 		uva, uvb, uvc, uvd;
 
-	// expose internals
+	var frames = new THREE.TubeGeometry.FrenetFrames(path, segments, closed),
+		tangents = frames.tangents,
+		normals = frames.normals,
+		binormals = frames.binormals;
+
+	// proxy internals
 	this.tangents = tangents;
 	this.normals = normals;
 	this.binormals = binormals;
 
-
+	
 	function vert( x, y, z ) {
 
 		return scope.vertices.push( new THREE.Vertex( new THREE.Vector3( x, y, z ) ) ) - 1;
 
 	}
 
+
+
+
+	// consruct the grid
+
+	for ( i = 0; i < numpoints; i++ ) {
+
+		this.grid[ i ] = [];
+
+		u = i / ( numpoints - 1 );
+
+		pos = path.getPointAt( u );
+
+		tangent = tangents[ i ];
+		normal = normals[ i ];
+		binormal = binormals[ i ];
+
+		if ( this.debug ) {
+
+			this.debug.add(new THREE.ArrowHelper(tangent, pos, radius, 0x0000ff));	
+			this.debug.add(new THREE.ArrowHelper(normal, pos, radius, 0xff0000));
+			this.debug.add(new THREE.ArrowHelper(binormal, pos, radius, 0x00ff00));
+
+		}
+
+		for ( j = 0; j < this.segmentsRadius; j++ ) {
+
+			v = j / this.segmentsRadius * 2 * Math.PI;
+
+			cx = -this.radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
+			cy = this.radius * Math.sin( v );
+
+            pos2.copy( pos );
+            pos2.x += cx * normal.x + cy * binormal.x;
+            pos2.y += cx * normal.y + cy * binormal.y;
+            pos2.z += cx * normal.z + cy * binormal.z;
+
+            this.grid[ i ][ j ] = vert( pos2.x, pos2.y, pos2.z );
+
+		}
+	}
+
+
+	// construct the mesh
+
+	for ( i = 0; i < this.segments; i++ ) {
+
+		for ( j = 0; j < this.segmentsRadius; j++ ) {
+
+			ip = ( closed ) ? (i + 1) % this.segments : i + 1;
+			jp = (j + 1) % this.segmentsRadius;
+
+			a = this.grid[ i ][ j ];		// *** NOT NECESSARILY PLANAR ! ***
+			b = this.grid[ ip ][ j ];
+			c = this.grid[ ip ][ jp ];
+			d = this.grid[ i ][ jp ];
+
+			uva = new THREE.UV( i / this.segments, j / this.segmentsRadius );
+			uvb = new THREE.UV( ( i + 1 ) / this.segments, j / this.segmentsRadius );
+			uvc = new THREE.UV( ( i + 1 ) / this.segments, ( j + 1 ) / this.segmentsRadius );
+			uvd = new THREE.UV( i / this.segments, ( j + 1 ) / this.segmentsRadius );
+
+			this.faces.push( new THREE.Face4( a, b, c, d ) );
+			this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvc, uvd ] );
+
+		}
+	}
+
+	this.computeCentroids();
+	this.computeFaceNormals();
+	this.computeVertexNormals();
+
+};
+
+THREE.TubeGeometry.prototype = new THREE.Geometry();
+THREE.TubeGeometry.prototype.constructor = THREE.TubeGeometry;
+
+
+// For computing of Frenet frames, exposing the tangents, normals and binormals the spline
+THREE.TubeGeometry.FrenetFrames = function(path, segments, closed) {
+
+	var 
+		tangent = new THREE.Vector3(),
+		normal = new THREE.Vector3(),
+		binormal = new THREE.Vector3(),
+
+		tangents = [],
+		normals = [],
+		binormals = [],
+
+		vec = new THREE.Vector3(),
+		mat = new THREE.Matrix4(),
+
+		numpoints = segments + 1,
+		theta,
+		epsilon = 0.0001,
+		smallest,
+
+		tx, ty, tz,
+		i, u, v;
+
+
+	// expose internals
+	this.tangents = tangents;
+	this.normals = normals;
+	this.binormals = binormals;
+
 	// compute the tangent vectors for each segment on the path
 
 	for ( i = 0; i < numpoints; i++ ) {
 
 		u = i / ( numpoints - 1 );
 
-		tangents[ i ] = this.path.getTangentAt( u );
+		tangents[ i ] = path.getTangentAt( u );
 		tangents[ i ].normalize();
 
 	}
 
 	initialNormal3();
 
-	function initialNormal1() {
+	function initialNormal1(lastBinormal) {
 		// fixed start binormal. Has dangers of 0 vectors
 		normals[ 0 ] = new THREE.Vector3();
 		binormals[ 0 ] = new THREE.Vector3();
-		var lastBinormal = new THREE.Vector3( 0, 0, 1 );
+		if (lastBinormal===undefined) lastBinormal = new THREE.Vector3( 0, 0, 1 );
 		normals[ 0 ].cross( lastBinormal, tangents[ 0 ] ).normalize();
 		binormals[ 0 ].cross( tangents[ 0 ], normals[ 0 ] ).normalize();
 	}
@@ -90,7 +194,7 @@ THREE.TubeGeometry = function( path, segments, radius, segmentsRadius, closed, d
 		// This uses the Frenet-Serret formula for deriving binormal
 		var t2 = path.getTangentAt( epsilon );
 
-		normals[ 0 ] = new THREE.Vector3().sub( t2, tangents[ 0 ] ).normalize()
+		normals[ 0 ] = new THREE.Vector3().sub( t2, tangents[ 0 ] ).normalize();
 		binormals[ 0 ] = new THREE.Vector3().cross( tangents[ 0 ], normals[ 0 ] );
 
 		normals[ 0 ].cross( binormals[ 0 ], tangents[ 0 ] ).normalize(); // last binormal x tangent
@@ -157,7 +261,7 @@ THREE.TubeGeometry = function( path, segments, radius, segmentsRadius, closed, d
 
 	// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
 
-	if ( this.closed ) {
+	if ( closed ) {
 
 		theta = Math.acos( normals[ 0 ].dot( normals[ numpoints-1 ] ) );
 		theta /= ( numpoints - 1 );
@@ -177,78 +281,4 @@ THREE.TubeGeometry = function( path, segments, radius, segmentsRadius, closed, d
 		}
 
 	}
-
-
-	// consruct the grid
-
-	for ( i = 0; i < numpoints; i++ ) {
-
-		this.grid[ i ] = [];
-
-		u = i / ( numpoints - 1 );
-
-		pos = this.path.getPointAt( u );
-
-		tangent = tangents[ i ];
-		normal = normals[ i ];
-		binormal = binormals[ i ];
-
-		if ( this.debug ) {
-
-			this.debug.add(new THREE.ArrowHelper(tangent, pos, radius, 0x0000ff));	
-			this.debug.add(new THREE.ArrowHelper(normal, pos, radius, 0xff0000));
-			this.debug.add(new THREE.ArrowHelper(binormal, pos, radius, 0x00ff00));
-
-		}
-
-		for ( j = 0; j < this.segmentsRadius; j++ ) {
-
-			v = j / this.segmentsRadius * 2 * Math.PI;
-
-			cx = -this.radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
-			cy = this.radius * Math.sin( v );
-
-            pos2 = new THREE.Vector3().copy( pos );
-            pos2.x += cx * normal.x + cy * binormal.x;
-            pos2.y += cx * normal.y + cy * binormal.y;
-            pos2.z += cx * normal.z + cy * binormal.z;
-
-            this.grid[ i ][ j ] = vert( pos2.x, pos2.y, pos2.z );
-
-		}
-	}
-
-
-	// construct the mesh
-
-	for ( i = 0; i < this.segments; i++ ) {
-
-		for ( j = 0; j < this.segmentsRadius; j++ ) {
-
-			ip = ( closed ) ? (i + 1) % this.segments : i + 1;
-			jp = (j + 1) % this.segmentsRadius;
-
-			a = this.grid[ i ][ j ];		// *** NOT NECESSARILY PLANAR ! ***
-			b = this.grid[ ip ][ j ];
-			c = this.grid[ ip ][ jp ];
-			d = this.grid[ i ][ jp ];
-
-			uva = new THREE.UV( i / this.segments, j / this.segmentsRadius );
-			uvb = new THREE.UV( ( i + 1 ) / this.segments, j / this.segmentsRadius );
-			uvc = new THREE.UV( ( i + 1 ) / this.segments, ( j + 1 ) / this.segmentsRadius );
-			uvd = new THREE.UV( i / this.segments, ( j + 1 ) / this.segmentsRadius );
-
-			this.faces.push( new THREE.Face4( a, b, c, d ) );
-			this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvc, uvd ] );
-
-		}
-	}
-
-	this.computeCentroids();
-	this.computeFaceNormals();
-	this.computeVertexNormals();
-
-};
-
-THREE.TubeGeometry.prototype = new THREE.Geometry();
-THREE.TubeGeometry.prototype.constructor = THREE.TubeGeometry;
+};