Browse Source

Moved FrenetFrames calculation from TubeBufferGeometry to Curve (#9851)

* Moved FrenetFrames calculation from TubeBufferGeometry to Curve

* Curve: Clean up

* ExtrudeGeometry: Removed reference to TubeGeometry
Michael Herzog 8 years ago
parent
commit
1835f8a06b

+ 4 - 0
docs/api/extras/core/Curve.html

@@ -60,6 +60,10 @@
 		<h3>[method:Vector getTangentAt]( u )</h3>
 		<div>Returns tangent at equidistant point u on the curve</div>
 
+		<h3>[method:Object computeFrenetFrames]( segments, closed )</h3>
+		<div>
+		Generates the Frenet Frames. Used in geometries like [page:TubeGeometry] or [page:ExtrudeGeometry].
+		</div>
 
 		<h2>Source</h2>
 

+ 0 - 15
docs/api/geometries/TubeBufferGeometry.html

@@ -97,21 +97,6 @@
 		An array of [page:Vector3] binormals
 		</div>
 
-
-		<h2>Methods</h2>
-
-
-		<h3>THREE.TubeBufferGeometry.FrenetFrames([page:Curve path], [page:Integer segments], [page:Boolean closed])</h3>
-		<div>
-		path — A path that inherits from the [page:Curve] base class <br />
-		segments — The number of segments that make up the tube <br />
-		closed — Is the tube open or closed
-		</div>
-		<div>
-		A static method that generates the Frenet Frames. This is internally run on any new TubeBufferGeometry and then the
-		generated tangents, normals, and binormals are exposed as properties on the TubeBufferGeometry object.
-		</div>
-
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 0 - 15
docs/api/geometries/TubeGeometry.html

@@ -97,21 +97,6 @@
 		An array of [page:Vector3] binormals
 		</div>
 
-
-		<h2>Methods</h2>
-
-
-		<h3>THREE.TubeGeometry.FrenetFrames([page:Curve path], [page:Integer segments], [page:Boolean closed])</h3>
-		<div>
-		path — A path that inherits from the [page:Curve] base class <br />
-		segments — The number of segments that make up the tube <br />
-		closed — Is the tube open or closed
-		</div>
-		<div>
-		A static method that generates the Frenet Frames. This is internally run on any new TubeGeometry and then the
-		generated tangents, normals, and binormals are exposed as properties on the TubeGeometry object.
-		</div>
-
 		<h2>Source</h2>
 
 		[link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js]

+ 1 - 1
examples/js/ParametricGeometries.js

@@ -112,7 +112,7 @@ THREE.ParametricGeometries.TubeGeometry = function( path, segments, radius, segm
 		cx, cy, pos, pos2 = new THREE.Vector3(),
 		i, j, ip, jp, a, b, c, d, uva, uvb, uvc, uvd;
 
-	var frames = new THREE.TubeGeometry.FrenetFrames( path, segments, closed ),
+	var frames = path.computeFrenetFrames( segments, closed ),
 		tangents = frames.tangents,
 		normals = frames.normals,
 		binormals = frames.binormals;

+ 121 - 0
src/extras/core/Curve.js

@@ -1,3 +1,7 @@
+import { _Math } from '../../math/Math';
+import { Vector3 } from '../../math/Vector3';
+import { Matrix4 } from '../../math/Matrix4';
+
 /**
  * @author zz85 / http://www.lab4games.net/zz85/blog
  * Extensible curve object
@@ -259,6 +263,123 @@ Curve.prototype = {
 		var t = this.getUtoTmapping( u );
 		return this.getTangent( t );
 
+	},
+
+	computeFrenetFrames: function ( segments, closed ) {
+
+		// see http://www.cs.indiana.edu/pub/techreports/TR425.pdf
+
+		var normal = new Vector3();
+
+		var tangents = [];
+		var normals = [];
+		var binormals = [];
+
+		var vec = new Vector3();
+		var mat = new Matrix4();
+
+		var i, u, theta;
+
+		// compute the tangent vectors for each segment on the curve
+
+		for ( i = 0; i <= segments; i ++ ) {
+
+			u = i / segments;
+
+			tangents[ i ] = this.getTangentAt( u );
+			tangents[ i ].normalize();
+
+		}
+
+		// select an initial normal vector perpendicular to the first tangent vector,
+		// and in the direction of the minimum tangent xyz component
+
+		normals[ 0 ] = new Vector3();
+		binormals[ 0 ] = new Vector3();
+		var min = Number.MAX_VALUE;
+		var tx = Math.abs( tangents[ 0 ].x );
+		var ty = Math.abs( tangents[ 0 ].y );
+		var tz = Math.abs( tangents[ 0 ].z );
+
+		if ( tx <= min ) {
+
+			min = tx;
+			normal.set( 1, 0, 0 );
+
+		}
+
+		if ( ty <= min ) {
+
+			min = ty;
+			normal.set( 0, 1, 0 );
+
+		}
+
+		if ( tz <= min ) {
+
+			normal.set( 0, 0, 1 );
+
+		}
+
+		vec.crossVectors( tangents[ 0 ], normal ).normalize();
+
+		normals[ 0 ].crossVectors( tangents[ 0 ], vec );
+		binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
+
+
+		// compute the slowly-varying normal and binormal vectors for each segment on the curve
+
+		for ( i = 1; i <= segments; i ++ ) {
+
+			normals[ i ] = normals[ i - 1 ].clone();
+
+			binormals[ i ] = binormals[ i - 1 ].clone();
+
+			vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
+
+			if ( vec.length() > Number.EPSILON ) {
+
+				vec.normalize();
+
+				theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
+
+				normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
+
+			}
+
+			binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
+
+		}
+
+		// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
+
+		if ( closed === true ) {
+
+			theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
+			theta /= segments;
+
+			if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
+
+				theta = - theta;
+
+			}
+
+			for ( i = 1; i <= segments; i ++ ) {
+
+				// twist a little...
+				normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
+				binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
+
+			}
+
+		}
+
+		return {
+			tangents: tangents,
+			normals: normals,
+			binormals: binormals
+		};
+
 	}
 
 };

+ 2 - 4
src/geometries/ExtrudeGeometry.js

@@ -3,7 +3,6 @@ import { Vector2 } from '../math/Vector2';
 import { Face3 } from '../core/Face3';
 import { Vector3 } from '../math/Vector3';
 import { ShapeUtils } from '../extras/ShapeUtils';
-import { TubeGeometry } from './TubeGeometry';
 
 /**
  * @author zz85 / http://www.lab4games.net/zz85/blog
@@ -22,7 +21,7 @@ import { TubeGeometry } from './TubeGeometry';
  *  bevelSegments: <int>, // number of bevel layers
  *
  *  extrudePath: <THREE.CurvePath> // 3d spline path to extrude shape along. (creates Frames if .frames aren't defined)
- *  frames: <THREE.TubeGeometry.FrenetFrames> // containing arrays of tangents, normals, binormals
+ *  frames: <Object> // containing arrays of tangents, normals, binormals
  *
  *  uvGenerator: <Object> // object that provides UV generator functions
  *
@@ -104,10 +103,9 @@ ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
 
 		// SETUP TNB variables
 
-		// Reuse TNB from TubeGeomtry for now.
 		// TODO1 - have a .isClosed in spline?
 
-		splineTube = options.frames !== undefined ? options.frames : new TubeGeometry.FrenetFrames( extrudePath, steps, false );
+		splineTube = options.frames !== undefined ? options.frames : extrudePath.computeFrenetFrames( steps, false );
 
 		// console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
 

+ 1 - 122
src/geometries/TubeBufferGeometry.js

@@ -1,18 +1,13 @@
 import { BufferGeometry } from '../core/BufferGeometry';
 import { Float32Attribute, Uint16Attribute, Uint32Attribute } from '../core/BufferAttribute';
-import { _Math } from '../math/Math';
 import { Vector2 } from '../math/Vector2';
 import { Vector3 } from '../math/Vector3';
-import { Matrix4 } from '../math/Matrix4';
 
 /**
  * @author Mugen87 / https://github.com/Mugen87
  *
  * Creates a tube which extrudes along a 3d spline.
  *
- * Uses parallel transport frames as described in:
- *
- * http://www.cs.indiana.edu/pub/techreports/TR425.pdf
  */
 
 function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, closed ) {
@@ -34,7 +29,7 @@ function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, clos
 	radialSegments = radialSegments || 8;
 	closed = closed || false;
 
-	var frames = new FrenetFrames( path, tubularSegments, closed );
+	var frames = path.computeFrenetFrames( tubularSegments, closed );
 
 	// expose internals
 
@@ -181,121 +176,5 @@ function TubeBufferGeometry( path, tubularSegments, radius, radialSegments, clos
 TubeBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
 TubeBufferGeometry.prototype.constructor = TubeBufferGeometry;
 
-// For computing of Frenet frames, exposing the tangents, normals and binormals the spline
-
-function FrenetFrames( path, segments, closed ) {
-
-	var	normal = new Vector3();
-
-	var tangents = [];
-	var normals = [];
-	var binormals = [];
-
-	var vec = new Vector3();
-	var mat = new Matrix4();
-
-	var i, u, theta;
-
-	// 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 <= segments; i ++ ) {
-
-		u = i / segments;
-
-		tangents[ i ] = path.getTangentAt( u );
-		tangents[ i ].normalize();
-
-	}
-
-	// select an initial normal vector perpendicular to the first tangent vector,
-	// and in the direction of the minimum tangent xyz component
-
-	normals[ 0 ] = new Vector3();
-	binormals[ 0 ] = new Vector3();
-	var min = Number.MAX_VALUE;
-	var tx = Math.abs( tangents[ 0 ].x );
-	var ty = Math.abs( tangents[ 0 ].y );
-	var tz = Math.abs( tangents[ 0 ].z );
-
-	if ( tx <= min ) {
-
-		min = tx;
-		normal.set( 1, 0, 0 );
-
-	}
-
-	if ( ty <= min ) {
-
-		min = ty;
-		normal.set( 0, 1, 0 );
-
-	}
-
-	if ( tz <= min ) {
-
-		normal.set( 0, 0, 1 );
-
-	}
-
-	vec.crossVectors( tangents[ 0 ], normal ).normalize();
-
-	normals[ 0 ].crossVectors( tangents[ 0 ], vec );
-	binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] );
-
-
-	// compute the slowly-varying normal and binormal vectors for each segment on the path
-
-	for ( i = 1; i <= segments; i ++ ) {
-
-		normals[ i ] = normals[ i - 1 ].clone();
-
-		binormals[ i ] = binormals[ i - 1 ].clone();
-
-		vec.crossVectors( tangents[ i - 1 ], tangents[ i ] );
-
-		if ( vec.length() > Number.EPSILON ) {
-
-			vec.normalize();
-
-			theta = Math.acos( _Math.clamp( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors
-
-			normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) );
-
-		}
-
-		binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
-
-	}
-
-	// if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
-
-	if ( closed ) {
-
-		theta = Math.acos( _Math.clamp( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) );
-		theta /= segments;
-
-		if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) {
-
-			theta = - theta;
-
-		}
-
-		for ( i = 1; i <= segments; i ++ ) {
-
-			// twist a little...
-			normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) );
-			binormals[ i ].crossVectors( tangents[ i ], normals[ i ] );
-
-		}
-
-	}
-
-}
 
 export { TubeBufferGeometry };