提交 0824c15a 编写于 作者: Z zz85

Curves refactored - addition of curve path, tangent finding, along with other...

Curves refactored - addition of curve path, tangent finding, along with other bend changes and enhancements i may not remember
上级 3ddb5686
因为 它太大了无法显示 source diff 。你可以改为 查看blob
此差异已折叠。
......@@ -92,10 +92,10 @@ THREE.Curve.prototype.getLengths = function ( divisions ) {
if ( !divisions ) divisions = 200;
if ( this.cacheLengths && ( this.cacheLengths.length == divisions + 1 ) ) {
if ( this.cacheArcLengths && ( this.cacheArcLengths.length == divisions + 1 ) ) {
//console.log( "cached", this.cacheLengths );
return this.cacheLengths;
//console.log( "cached", this.cacheArcLengths );
return this.cacheArcLengths;
}
......@@ -114,7 +114,7 @@ THREE.Curve.prototype.getLengths = function ( divisions ) {
}
this.cacheLengths = cache;
this.cacheArcLengths = cache;
return cache; // { sums: cache, sum:sum }; Sum is in the last element.
......@@ -216,8 +216,15 @@ THREE.Curve.prototype.getNormalVector = function( t ) {
THREE.Curve.prototype.getTangent = function( t ) {
var delta = 0.0001;
var pt1 = this.getPoint(t-delta);
var pt2 = this.getPoint(t+delta);
var t1 = t-delta;
var t2 = t+delta;
// Capping in case of danger
if (t1<0) t1 = 0;
if (t2>1) t2 = 1;
var pt1 = this.getPoint(t1);
var pt2 = this.getPoint(t2);
var vec = new THREE.Vector2();
vec.sub(pt2, pt1);
......@@ -229,35 +236,26 @@ THREE.Curve.prototype.getTangent = function( t ) {
var __vec1 = new THREE.Vector2(); // tmp Vector
/**************************************************************
* Curved Path - a curve path is simply a array of connected
* curves, but retains the api of a curve
**************************************************************/
/**************************************************************
* Line
**************************************************************/
THREE.LineCurve = function ( v1, v2 ) {
if (!(v1 instanceof THREE.Vector2 )) {
// Fall back for old constuctor signature - should be removed over time
THREE.LineCurve.oldConstructor.apply(this, arguments);
return;
}
this.v1 = v1;
this.v2 = v2;
};
THREE.LineCurve.oldConstruct = function ( x1, y1, x2, y2 ) {
//instanceof THREE.Vector2 oldConstruct.apply(this);
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
};
THREE.LineCurve.oldConstructor = function ( x1, y1, x2, y2 ) {
this.constructor(new THREE.Vector2(x1, y1), new THREE.Vector2(x2, y2));
};
THREE.LineCurve.prototype = new THREE.Curve();
......@@ -267,10 +265,10 @@ THREE.LineCurve.prototype.getPoint = function ( t ) {
var tmpVector = new THREE.Vector2();
tmpVector.sub(this.v2, this.v1);
tmpVector.multiplyScalar(t);
tmpVector.multiplyScalar(t).addSelf(this.v1);
return tmpVector;
// var dx = this.x2 - this.x1;
// var dx = this.x2 - this.x1;
// var dy = this.y2 - this.y1;
//
// var tx = this.x1 + dx * t;
......@@ -280,6 +278,11 @@ THREE.LineCurve.prototype.getPoint = function ( t ) {
};
// Line curve is linear, so we can overwrite default getPointAt
THREE.LineCurve.prototype.getPointAt = function ( u ) {
return this.getPoint( u );
};
THREE.LineCurve.prototype.getTangent = function( t ) {
__vec1.sub(this.v2, this.v1);
......@@ -293,27 +296,19 @@ THREE.LineCurve.prototype.getTangent = function( t ) {
THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
if (!(v1 instanceof THREE.Vector2 )) {
var args = Array.prototype.slice.call(arguments);
v0 = new THREE.Vector2(args[0], args[1]);
v1 = new THREE.Vector2(args[2], args[3]);
v2 = new THREE.Vector2(args[4], args[5]);
}
this.v0 = v0;
this.v1 = v1;
this.v2 = v2;
};
THREE.QuadraticBezierCurve.old = function ( x0, y0, x1, y1, x2, y2 ) {
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
};
THREE.QuadraticBezierCurve.prototype = new THREE.Curve();
THREE.QuadraticBezierCurve.prototype.constructor = THREE.QuadraticBezierCurve;
......@@ -365,6 +360,14 @@ THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
if (!(v1 instanceof THREE.Vector2 )) {
var args = Array.prototype.slice.call(arguments);
v0 = new THREE.Vector2(args[0], args[1]);
v1 = new THREE.Vector2(args[2], args[3]);
v2 = new THREE.Vector2(args[4], args[5]);
v3 = new THREE.Vector2(args[6], args[7]);
}
this.v0 = v0;
this.v1 = v1;
this.v2 = v2;
......@@ -372,22 +375,6 @@ THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
};
THREE.CubicBezierCurve.old = function ( x0, y0, x1, y1, x2, y2, x3, y3 ) {
this.x0 = x0;
this.y0 = y0;
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
this.x3 = x3;
this.y3 = y3;
};
THREE.CubicBezierCurve.prototype = new THREE.Curve();
THREE.CubicBezierCurve.prototype.constructor = THREE.CubicBezierCurve;
......
/**
* @author zz85 / http://www.lab4games.net/zz85/blog
*
**/
/**************************************************************
* Curved Path - a curve path is simply a array of connected
* curves, but retains the api of a curve
**************************************************************/
THREE.CurvePath = function () {
this.curves = [];
this.bends = [];
};
THREE.CurvePath.prototype = new THREE.Curve();
THREE.CurvePath.prototype.constructor = THREE.CurvePath;
THREE.CurvePath.prototype.add = function (curve) {
this.curves.push (curve);
};
THREE.CurvePath.prototype.checkConnection = function() {
};
// add a line curve if start and end of lines are not connected.
THREE.CurvePath.prototype.closePath = function() {
};
// To get accurate point with reference to
// entire path distance at time t,
// following has to be done
// 1. Length of each sub path have to be known
// 2. Locate and identify type of curve
// 3. Get t for the curve
// 4. Return curve.getPointAt(t')
THREE.CurvePath.prototype.getPoint = function( t ) {
var d = t * this.getLength();
var curveLengths = this.getCurveLengths();
var i = 0, diff, curve;
// To think about boundaries points.
while ( i < curveLengths.length ) {
if ( curveLengths[ i ] >= d ) {
diff = curveLengths[ i ] - d;
curve = this.curves[ i ];
var u = 1 - diff / curve.getLength();
return curve.getPointAt( u );
break;
}
i++;
}
return null;
// loop where sum != 0, sum > d , sum+1 <d
};
/*
THREE.CurvePath.prototype.getTangent = function( t ) {
};*/
// we cannot use the default THREE.Curve getPoint() with getLength() because in
// THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
// getPoint() depends on getLength
THREE.CurvePath.prototype.getLength = function() {
var lens = this.getCurveLengths();
return lens[lens.length-1];
};
// Compute lengths and cache them
// We cannot overwrite getLengths() because UtoT mapping uses it.
THREE.CurvePath.prototype.getCurveLengths = function() {
// We use cache values if curves and cache array are same length
if (this.cacheLengths && this.cacheLengths.length==this.curves.length) {
return this.cacheLengths;
};
// Get length of subsurve
// Push sums into cached array
var lengths = [], sums = 0;
var i, il = this.curves.length;
for ( i = 0; i < il ; i++ ) {
sums += this.curves[ i ].getLength();
lengths.push( sums );
}
this.cacheLengths = lengths;
return lengths;
};
// Returns min and max coordinates, as well as centroid
THREE.CurvePath.prototype.getBoundingBox = function () {
var points = this.getPoints();
var maxX, maxY;
var minX, minY;
maxX = maxY = Number.NEGATIVE_INFINITY;
minX = minY = Number.POSITIVE_INFINITY;
var p, i, il, sum;
sum = new THREE.Vector2();
for ( i = 0, il = points.length; i < il; i ++ ) {
p = points[ i ];
if ( p.x > maxX ) maxX = p.x;
else if ( p.x < minX ) minX = p.x;
if ( p.y > maxY ) maxY = p.y;
else if ( p.y < maxY ) minY = p.y;
sum.addSelf( p.x, p.y );
}
return {
minX: minX,
minY: minY,
maxX: maxX,
maxY: maxY,
centroid: sum.divideScalar( il )
};
};
/**************************************************************
* Create Geometries Helpers
**************************************************************/
/// Generate geometry from path points (for Line or ParticleSystem objects)
THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
var pts = this.getPoints( divisions, true );
return this.createGeometry( pts );
};
// Generate geometry from equidistance sampling along the path
THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
var pts = this.getSpacedPoints( divisions, true );
return this.createGeometry( pts );
};
THREE.CurvePath.prototype.createGeometry = function( points ) {
var geometry = new THREE.Geometry();
for( var i = 0; i < points.length; i ++ ) {
geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( points[ i ].x, points[ i ].y, 0 ) ) );
}
return geometry;
};
/**************************************************************
* Bend / Wrap Helper Methods
**************************************************************/
// Wrap path / Bend modifiers?
THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
this.bends.push(bendpath);
};
THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
var i, il;
if (!bends) {
bends = this.bends;
}
for (i=0, il=bends.length; i<il;i++) {
oldPts = this.getWrapPoints( oldPts, bends[i] );
}
return oldPts;
};
THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
var oldPts = this.getSpacedPoints( segments );
var i, il;
if (!bends) {
bends = this.bends;
}
for (i=0, il=bends.length; i<il;i++) {
oldPts = this.getWrapPoints( oldPts, bends[i] );
}
return oldPts;
};
// This returns getPoints() bend/wrapped around the contour of a path.
// Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
THREE.CurvePath.prototype.getWrapPoints = function (oldPts, path ) {
var bounds = this.getBoundingBox();
var i, il, p, oldX, oldY, xNorm;
for ( i = 0, il = oldPts.length; i < il; i ++ ) {
p = oldPts[ i ];
oldX = p.x;
oldY = p.y;
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 );
// check for out of bounds?
var pathPt = path.getPoint( xNorm );
var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
p.x = pathPt.x + normal.x;
p.y = pathPt.y + normal.y;
}
return oldPts;
};
......@@ -68,6 +68,8 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
var extrudePath = options.path !== undefined ? options.path : null;
var extrudePts, extrudeByPath = false;
var useSpacedPoints = options.useSpacedPoints !== undefined ? options.useSpacedPoints : false;
if ( extrudePath ) {
......@@ -106,11 +108,14 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
}
var shapePoints = shape.extractAllPoints( curveSegments ); // use shape.extractAllSpacedPoints( curveSegments ) for points with equal divisions
var shapePoints;
if (!useSpacedPoints) {
shapePoints = shape.extractAllPoints( curveSegments ); //
} else {
// QN - Would it be better to pass useSpacePoints parameter to shape, just like bendpath ?
shapePoints = shape.extractAllSpacedPoints( curveSegments ) // for points with equal divisions
}
var vertices = shapePoints.shape;
var holes = shapePoints.holes;
......@@ -143,6 +148,7 @@ THREE.ExtrudeGeometry.prototype.addShape = function( shape, options ) {
var faces = THREE.Shape.Utils.triangulateShape ( vertices, holes );
//var faces = THREE.Shape.Utils.triangulate2( vertices, holes );
// Would it be better to move points after triangulation?
// shapePoints = shape.extractAllPointsWithBend( curveSegments, bendPath );
// vertices = shapePoints.shape;
// holes = shapePoints.holes;
......
......@@ -6,18 +6,25 @@
THREE.Path = function ( points ) {
this.actions = [];
this.curves = [];
this.bends = [];
THREE.CurvePath.call(this);
this.actions = [];
if ( points ) {
this.fromPoints( points );
}
};
THREE.Path.prototype = new THREE.CurvePath();
THREE.Path.prototype.constructor = THREE.Path;
THREE.PathActions = {
MOVE_TO: 'moveTo',
......@@ -66,10 +73,10 @@ THREE.Path.prototype.lineTo = function ( x, y ) {
var x0 = lastargs[ lastargs.length - 2 ];
var y0 = lastargs[ lastargs.length - 1 ];
var curve = new THREE.LineCurve( x0, y0, x, y );
var curve = new THREE.LineCurve( new THREE.Vector2(x0, y0), new THREE.Vector2(x, y) );
this.curves.push( curve );
this.actions.push( { action: THREE.PathActions.LINE_TO, args: args, curve: curve } );
this.actions.push( { action: THREE.PathActions.LINE_TO, args: args } );
};
......@@ -82,13 +89,11 @@ THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
var x0 = lastargs[ lastargs.length - 2 ];
var y0 = lastargs[ lastargs.length - 1 ];
var curve = new THREE.QuadraticBezierCurve( x0, y0, aCPx, aCPy, aX, aY );
var curve = new THREE.QuadraticBezierCurve( new THREE.Vector2(x0, y0), new THREE.Vector2(aCPx, aCPy), new THREE.Vector2(aX, aY) );
this.curves.push( curve );
this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args, curve: curve } );
this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args } );
//console.log( curve, curve.getPoints(), curve.getSpacedPoints() );
//console.log( curve.getPointAt(0), curve.getPointAt(0), curve.getUtoTmapping(0), curve.getSpacedPoints() );
};
......@@ -103,12 +108,13 @@ THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y,
var x0 = lastargs[ lastargs.length - 2 ];
var y0 = lastargs[ lastargs.length - 1 ];
var curve = new THREE.CubicBezierCurve( x0, y0, aCP1x, aCP1y,
aCP2x, aCP2y,
aX, aY );
var curve = new THREE.CubicBezierCurve( new THREE.Vector2(x0, y0),
new THREE.Vector2(aCP1x, aCP1y),
new THREE.Vector2(aCP2x, aCP2y),
new THREE.Vector2(aX, aY) );
this.curves.push( curve );
this.actions.push( { action: THREE.PathActions.BEZIER_CURVE_TO, args: args, curve: curve } );
this.actions.push( { action: THREE.PathActions.BEZIER_CURVE_TO, args: args } );
};
......@@ -126,9 +132,7 @@ THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
var curve = new THREE.SplineCurve( npts );
this.curves.push( curve );
this.actions.push( { action: THREE.PathActions.CSPLINE_THRU, args: args, curve: curve } );
//console.log( curve, curve.getPoints(), curve.getSpacedPoints() );
this.actions.push( { action: THREE.PathActions.CSPLINE_THRU, args: args } );
};
......@@ -165,11 +169,11 @@ THREE.Path.prototype.getSpacedPoints = function ( divisions, closedPath ) {
}
if ( closedPath ) {
points.push( points[ 0 ] );
}
// if ( closedPath ) {
//
// points.push( points[ 0 ] );
//
// }
return points;
......@@ -371,224 +375,9 @@ THREE.Path.prototype.getPoints = function( divisions, closedPath ) {
};
// Returns min and max coordinates, as well as centroid
THREE.Path.prototype.getBoundingBox = function () {
var points = this.getPoints();
var maxX, maxY;
var minX, minY;
maxX = maxY = Number.NEGATIVE_INFINITY;
minX = minY = Number.POSITIVE_INFINITY;
var p, i, il, sum;
sum = new THREE.Vector2();
for ( i = 0, il = points.length; i < il; i ++ ) {
p = points[ i ];
if ( p.x > maxX ) maxX = p.x;
else if ( p.x < minX ) minX = p.x;
if ( p.y > maxY ) maxY = p.y;
else if ( p.y < maxY ) minY = p.y;
sum.addSelf( p.x, p.y );
}
return {
minX: minX,
minY: minY,
maxX: maxX,
maxY: maxY,
centroid: sum.divideScalar( il )
};
};
// To get accurate point with reference to
// entire path distance at time t,
// following has to be done
// 1. Length of each sub path have to be known
// 2. Locate and identify type of curve
// 3. Get t for the curve
// 4. Return curve.getPointAt(t')
THREE.Path.prototype.getPoint = function( t ) {
var d = t * this.getLength();
var curveLengths = this.sums;
var i = 0, diff, curve;
// To think about boundaries points.
while ( i < curveLengths.length ) {
if ( curveLengths[ i ] >= d ) {
diff = curveLengths[ i ] - d;
curve = this.curves[ i ];
var u = 1 - diff / curve.getLength();
return curve.getPointAt( u );
break;
}
i++;
}
return null;
// loop where sum != 0, sum > d , sum+1 <d
};
// Compute lengths and cache them
THREE.Path.prototype.getLength = function() {
// Loop all actions/path
// Push sums into cached array
var lengths = [], sums = 0;
var i, il = this.curves.length;
for ( i = 0; i < il ; i++ ) {
sums += this.curves[ i ].getLength();
lengths.push( sums );
}
this.sums = lengths;
return sums;
};
/// Generate geometry from path points (for Line or ParticleSystem objects)
THREE.Path.prototype.createPointsGeometry = function( divisions ) {
var pts = this.getPoints( divisions, true );
return this.createGeometry( pts );
};
// Generate geometry from equidistance sampling along the path
THREE.Path.prototype.createSpacedPointsGeometry = function( divisions ) {
var pts = this.getSpacedPoints( divisions, true );
return this.createGeometry( pts );
};
THREE.Path.prototype.createGeometry = function( points ) {
var geometry = new THREE.Geometry();
for( var i = 0; i < points.length; i ++ ) {
geometry.vertices.push( new THREE.Vertex( new THREE.Vector3( points[ i ].x, points[ i ].y, 0 ) ) );
}
return geometry;
};
// ALL THINGS BELOW TO BE REFACTORED
// Wrap path / Bend modifiers?
THREE.Path.prototype.addWrapPath = function ( bendpath ) {
this.bends.push(bendpath);
};
THREE.Path.prototype.getTransformedPoints = function( segments, bends ) {
var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
var i, il;
if (!bends) {
bends = this.bends;
}
for (i=0, il=bends.length; i<il;i++) {
oldPts = this.getWrapPoints( oldPts, bends[i] );
}
return oldPts;
};
THREE.Path.prototype.getTransformedSpacedPoints = function( segments, bends ) {
var oldPts = this.getSpacedPoints( segments );
var i, il;
if (!bends) {
bends = this.bends;
}
for (i=0, il=bends.length; i<il;i++) {
oldPts = this.getWrapPoints( oldPts, bends[i] );
}
return oldPts;
};
THREE.Path.prototype.getWrapPoints = function (oldPts, path ) {
var bounds = this.getBoundingBox();
var i, il, p, oldX, oldY, xNorm;
for ( i = 0, il = oldPts.length; i < il; i ++ ) {
p = oldPts[ i ];
oldX = p.x;
oldY = p.y;
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 );
// check for out of bounds?
var pathPt = path.getPoint( xNorm );
var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
p.x = pathPt.x + normal.x;
p.y = pathPt.y + normal.y;
}
return oldPts;
};
// Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
// This returns getPoints() bend/wrapped around the contour of a path.
// This was used for testing purposes. Should be removed soon.
THREE.Path.prototype.transform = function( path, segments ) {
var bounds = this.getBoundingBox();
......
......@@ -53,7 +53,7 @@ THREE.Shape.prototype.getSpacedPointsHoles = function ( divisions ) {
for ( i = 0; i < il; i ++ ) {
holesPts[ i ] = this.holes[ i ].getSpacedPoints( divisions, this.bends );
holesPts[ i ] = this.holes[ i ].getTransformedSpacedPoints( divisions, this.bends );
}
......
......@@ -60,22 +60,47 @@ THREE.TextGeometry = function ( text, parameters ) {
}
// path = new THREE.CubicBezierCurve( new THREE.Vector2(0, 0),
// new THREE.Vector2(100, 100), new THREE.Vector2(200, 100), new THREE.Vector2(500, 0));
// // Bend Testings.
//
//path = new THREE.QuadraticBezierCurve( 0, 0, bounds.maxX/2, 50, bounds.maxX , 0);
// var path = new THREE.CurvePath();
//
// path.add(new THREE.CubicBezierCurve(
// new THREE.Vector2(0, 0),
// new THREE.Vector2(10, 100),
// new THREE.Vector2(200, -10),
// new THREE.Vector2(300, 0)
// ));
//
// path.add(new THREE.QuadraticBezierCurve(
// new THREE.Vector2(300, 0),
// new THREE.Vector2(450, -10),
// new THREE.Vector2(500, 100)
// ));
//
// parameters.bendPath = path;
//path = new THREE.LineCurve( 0, 0, 400, 0);
//path = new THREE.LineCurve( new THREE.Vector2(0, 0), new THREE.Vector2(400, 100));
// var path = new THREE.CurvePath();
// path.add(new THREE.LineCurve( 0, 0, 250, 0));
// path.add(new THREE.LineCurve( 250, 0, 300, 200));
//
// parameters.bendPath = path;
// var bend = new THREE.Path();
// bend.moveTo(0,0);
// bend.quadraticCurveTo( 500, 100, 1000, 0 );
// var path = new THREE.SplineCurve([
// new THREE.Vector2(0, 0),
// new THREE.Vector2(100, 40),
// new THREE.Vector2(200, 0),
// new THREE.Vector2(400, 20)
// ]);
//
// console.log(path);
//
// path = new THREE.LineCurve( new THREE.Vector2(0, 0), new THREE.Vector2(400, 100));
// parameters.bendPath = path;
// var bend = new THREE.Path();
// bend.moveTo(0,0);
// bend.quadraticCurveTo( 500, 100, 1000, 0 );
//
// parameters.bendPath = bend;
......
......@@ -96,6 +96,7 @@ EXTRAS_FILES = [
'extras/cameras/TrackballCamera.js',
'extras/cameras/QuakeCamera.js',
'extras/geometries/Curve.js',
'extras/geometries/CurvePath.js',
'extras/geometries/Path.js',
'extras/geometries/Shape.js',
'extras/geometries/TextPath.js',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册