Prototype text warping to curves/splines

This commit is contained in:
zz85
2011-08-10 04:14:52 +08:00
parent fd27811b7c
commit 091126b233
5 changed files with 144 additions and 44 deletions
+82 -25
View File
@@ -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
// // 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 ( i < il ) {
if ( lengths[ i ] > distanceForU ) break;
i++;
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;
// 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
View File
@@ -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);
////
+22 -10
View File
@@ -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 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);
var thisBounds = this.getBoundingBox();
var oldPts = this.getPoints();
//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
View File
@@ -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
View File
@@ -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 );