Browse Source

Prototype text warping to curves/splines

zz85 14 years ago
parent
commit
091126b233

+ 83 - 26
src/extras/geometries/Curve.js

@@ -91,17 +91,19 @@ THREE.Curve.prototype.getLength = function () {
 THREE.Curve.prototype.getLengths = function ( divisions ) {
 
 	if ( !divisions ) divisions = 200;
-
-	if ( this.cacheLengths && ( this.cacheLengths.length == divisions ) ) {
+	
+	if ( this.cacheLengths && ( this.cacheLengths.length == divisions + 1 ) ) {
 
 		//console.log( "cached", this.cacheLengths );
 		return this.cacheLengths;
 
 	}
-
+	
 	var cache = [];
 	var current, last = this.getPoint( 0 );
 	var p, sum = 0;
+	
+	cache.push(0);
 
 	for ( p = 1; p <= divisions; p++ ) {
 
@@ -113,42 +115,89 @@ THREE.Curve.prototype.getLengths = function ( divisions ) {
 	}
 
 	this.cacheLengths = cache;
+	
 	return cache; // { sums: cache, sum:sum }; Sum is in the last element.
 
 };
 
 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equi distance
-
 THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) {
 
-	var lengths = this.getLengths();
-	var i = 0, il = lengths.length;
+	var arcLengths = this.getLengths();
+	var i = 0, il = arcLengths.length;
 
-	var distanceForU;
+	var targetArcLength; // The targetted u distance value to get
 
 	if ( distance ) {
 
-		distanceForU = distance;
+		targetArcLength = distance;
 
 	} else {
 
-		distanceForU = u * lengths[ il - 1 ];
+		targetArcLength = u * arcLengths[ il - 1 ];
 
 	}
 
-	// TODO Should do binary search + sub division + interpolation when needed
-
-	while ( i < il ) {
-
-		if ( lengths[ i ] > distanceForU ) break;
+	// // TODO Should do binary search + sub division + interpolation when needed
+	// time = Date.now();
+	// while ( i < il ) {
+	// 	
+	// 	i++;
+	// 
+	// 	if ( targetArcLength < arcLengths[ i ] ) break;
+	// 
+	// }
+	// 
+	// i--;
+	// console.log('o' , i, Date.now()- time);
+	
+	time = Date.now();
+	// binary search for the index with largest value smaller than target u distance
+	var low=0, high = il-1, comparison;
+
+	while (low <= high) {
+
+		i = Math.floor((low + high) / 2);
+	  	comparison = arcLengths[ i ] - targetArcLength;
+		
+	  	if (comparison < 0) { 
+			low = i + 1; continue; 
+		} else if (comparison > 0) {
+			high = i - 1; continue; 
+		} else {
+			high = i;
+			break;
+			// DONE
+		}
+	
+	}
+	
+	i = high;
+	
+	//console.log('b' , i, low, high, Date.now()- time);
+
+	
+	if (arcLengths[i] == targetArcLength) {
+		var t = i / (il - 1);
+		return t;
+	}
+	
+	// We could get finer grain ar lengths, or use simple interpolatation between two points
+	var lengthBefore = arcLengths[i];
+    var lengthAfter = arcLengths[i+1];
+    var segmentLength = lengthAfter - lengthBefore;
 
-		i++;
+    // determine where we are between the 'before' and 'after' points.
+    var segmentFraction = (targetArcLength - lengthBefore) / segmentLength;
 
-	}
+    // add that fractional amount to t 
+    t = (i + segmentFraction) / (il -1);
 
-	var t = i / il;
 	return t;
-
+	
+	
+	
+	
 };
 
 
@@ -181,6 +230,14 @@ THREE.LineCurve.prototype.getPoint = function ( t ) {
 
 };
 
+THREE.LineCurve.prototype.getNormalVector = function( t ) {
+	tx = this.x2 - this.x1;
+	ty = this.y2 - this.y1;
+
+	// return normal unit vector
+	return new THREE.Vector2( -ty , tx ).unit();
+}
+
 /**************************************************************
  *	Quadratic Bezier curve
  **************************************************************/
@@ -223,14 +280,14 @@ THREE.QuadraticBezierCurve.prototype.getNormalVector = function( t ) {
 
 	var x0, y0, x1, y1, x2, y2;
 
-	x0 = this.actions[ 0 ].args[ 0 ];
-	y0 = this.actions[ 0 ].args[ 1 ];
-
-	x1 = this.actions[ 1 ].args[ 0 ];
-	y1 = this.actions[ 1 ].args[ 1 ];
-
-	x2 = this.actions[ 1 ].args[ 2 ];
-	y2 = this.actions[ 1 ].args[ 3 ];
+	// x0 = this.actions[ 0 ].args[ 0 ];
+	// y0 = this.actions[ 0 ].args[ 1 ];
+	// 
+	// x1 = this.actions[ 1 ].args[ 0 ];
+	// y1 = this.actions[ 1 ].args[ 1 ];
+	// 
+	// x2 = this.actions[ 1 ].args[ 2 ];
+	// y2 = this.actions[ 1 ].args[ 3 ];
 
 	var tx, ty;
 

+ 9 - 1
src/extras/geometries/ExtrudeGeometry.js

@@ -63,6 +63,8 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
 	var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
 
 	var steps = options.steps !== undefined ? options.steps : 1;
+	
+	var bendPath = options.bendPath;
 
 	var extrudePath = options.path !== undefined ? options.path : null;
 	var extrudePts, extrudeByPath = false;
@@ -98,7 +100,9 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
 	var shapesOffset = this.vertices.length;
 
 	var shapePoints = shape.extractAllPoints( curveSegments ); // use shape.extractAllSpacedPoints( curveSegments ) for points with equal divisions
+	shapePoints = shape.extractAllPointsWithBend( curveSegments, bendPath ); 
 
+	
     var vertices = shapePoints.shape;
 	var holes = shapePoints.holes;
 
@@ -129,7 +133,11 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
 
 	var faces = THREE.Shape.Utils.triangulateShape ( vertices, holes );
 	//var faces = THREE.Shape.Utils.triangulate2( vertices, holes );
-
+	
+	// shapePoints = shape.extractAllPointsWithBend( curveSegments, bendPath ); 
+	// 	vertices = shapePoints.shape;
+	// 	holes = shapePoints.holes;
+	
 	//console.log(faces);
 
 	////

+ 23 - 11
src/extras/geometries/Path.js

@@ -517,16 +517,28 @@ THREE.Path.prototype.createGeometry = function( points ) {
 // FUTURE refactor path = an array of lines -> straight, bezier, splines, arc, funcexpr lines
 // Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
 
-THREE.Path.prototype.transform = function( path ) {
+// This returns getPoints() bend/wrapped around the contour of a path.
 
-	path = new THREE.Path();
-	path.moveTo( 0, 0 );
-	path.quadraticCurveTo( 100, 20, 140, 80 );
+THREE.Path.prototype.transform = function( path, segments ) {
 
-	console.log( path.cacheArcLengths() );
-
-	var thisBounds = this.getBoundingBox();
-	var oldPts = this.getPoints();
+	var bounds = this.getBoundingBox();
+	var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
+	
+	// path = new THREE.Path();
+	// path.moveTo( 0, 0 );
+	// path.quadraticCurveTo( 100, 20, 140, 80 );
+	
+	path = new THREE.QuadraticBezierCurve( 0, 0, 150, 100, 400, 0)
+	//path = new THREE.QuadraticBezierCurve( 0, 0,  bounds.maxX/2, 50, bounds.maxX , 0);
+	
+	//path = new THREE.LineCurve( 0, 0,  400, 0);
+	
+
+	//console.log( path.cacheArcLengths() );
+	//path.getLengths(400);
+	//segments = 40;
+	
+	
 
 	var i, il, p, oldX, oldY, xNorm;
 
@@ -537,19 +549,19 @@ THREE.Path.prototype.transform = function( path ) {
 		oldX = p.x;
 		oldY = p.y;
 
-		var xNorm = oldX/ thisBounds.maxX;
+		var xNorm = oldX/ bounds.maxX;
 
 		// If using actual distance, for length > path, requires line extrusions
 		//xNorm = path.getUtoTmapping(xNorm, oldX); // 3 styles. 1) wrap stretched. 2) wrap stretch by arc length 3) warp by actual distance
 
+		xNorm = path.getUtoTmapping(xNorm, oldX );
+		
 		var pathPt = path.getPoint( xNorm );
 		var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
 
 		p.x = pathPt.x + normal.x;
 		p.y = pathPt.y + normal.y;
 
-		//p.x = a * oldX + b * oldY + c;
-		//p.y = d * oldY + e * oldX + f;
 
 	}
 

+ 24 - 8
src/extras/geometries/Shape.js

@@ -30,14 +30,23 @@ THREE.Shape.prototype.extrude = function ( options ) {
 
 // Get points of holes
 
-THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
+THREE.Shape.prototype.getPointsHoles = function ( divisions, bend ) {
 
 
 	var i, il = this.holes.length, holesPts = [];
 
 	for ( i = 0; i < il; i ++ ) {
 
-		holesPts[ i ] = this.holes[ i ].getPoints( divisions );
+		if (bend) {
+			
+			holesPts[ i ] = this.holes[ i ].transform( bend, divisions );
+			
+		} else {
+			
+			holesPts[ i ] = this.holes[ i ].getPoints( divisions );
+		
+		}
+		
 
 	}
 
@@ -75,6 +84,17 @@ THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
 
 };
 
+THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) {
+
+	return {
+
+		shape: this.transform( bend, divisions ),
+		holes: this.getPointsHoles( divisions, bend )
+
+	};
+
+};
+
 // Get points of shape and holes (spaced by regular distance)
 
 THREE.Shape.prototype.extractAllSpacedPoints = function ( divisions ) {
@@ -131,16 +151,13 @@ THREE.Shape.Utils = {
 
 			shortest = Number.POSITIVE_INFINITY;
 
-			// THIS THING NEEDS TO BE DONE CORRECTLY AGAIN :(
-
+			
 			// Find the shortest pair of pts between shape and hole
 
 			// Note: Actually, I'm not sure now if we could optimize this to be faster than O(m*n)
 			// Using distanceToSquared() intead of distanceTo() should speed a little
 			// since running square roots operations are reduced.
-			// http://en.wikipedia.org/wiki/Closest_pair_of_points
-			// http://stackoverflow.com/questions/1602164/shortest-distance-between-points-algorithm
-
+			
 			for ( h2 = 0; h2 < hole.length; h2 ++ ) {
 
 				pts1 = hole[ h2 ];
@@ -276,7 +293,6 @@ THREE.Shape.Utils = {
 			verts.push( triangleb );
 
 			shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
-			//shape = tmpHole1.concat( tmpHole2 );
 
 		}
 

+ 7 - 0
src/extras/geometries/TextGeometry.js

@@ -49,6 +49,13 @@ THREE.TextGeometry = function ( text, parameters ) {
 	if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
 	if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
 	if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
+	
+	
+	var bend = new THREE.Path();
+	bend.moveTo(0,0);
+	bend.quadraticCurveTo( 500, 100, 1000, 0 );
+	
+	parameters.bendPath = bend;
 
 	THREE.ExtrudeGeometry.call( this, textShapes, parameters );