mirror of
https://github.com/wahyd4/three.js.git
synced 2026-08-09 04:56:01 +10:00
Prototype text warping to curves/splines
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
////
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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 );
|
||||
|
||||
|
||||
Reference in New Issue
Block a user