|
@@ -27653,10 +27653,9 @@ THREE.typeface_js = self._typeface_js;
|
|
* .getLength()
|
|
* .getLength()
|
|
* .updateArcLengths()
|
|
* .updateArcLengths()
|
|
*
|
|
*
|
|
- * This file contains following classes:
|
|
|
|
|
|
+ * This following classes subclasses THREE.Curve:
|
|
*
|
|
*
|
|
* -- 2d classes --
|
|
* -- 2d classes --
|
|
- * THREE.Curve
|
|
|
|
* THREE.LineCurve
|
|
* THREE.LineCurve
|
|
* THREE.QuadraticBezierCurve
|
|
* THREE.QuadraticBezierCurve
|
|
* THREE.CubicBezierCurve
|
|
* THREE.CubicBezierCurve
|
|
@@ -27907,1960 +27906,1934 @@ THREE.Curve.prototype.getTangentAt = function ( u ) {
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+
|
|
/**************************************************************
|
|
/**************************************************************
|
|
- * Line
|
|
|
|
|
|
+ * Utils
|
|
**************************************************************/
|
|
**************************************************************/
|
|
|
|
|
|
-THREE.LineCurve = function ( v1, v2 ) {
|
|
|
|
|
|
+THREE.Curve.Utils = {
|
|
|
|
|
|
- this.v1 = v1;
|
|
|
|
- this.v2 = v2;
|
|
|
|
|
|
+ tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
|
|
|
|
|
|
-THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
+ },
|
|
|
|
|
|
-THREE.LineCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
+ // Puay Bing, thanks for helping with this derivative!
|
|
|
|
|
|
- var point = this.v2.clone().sub(this.v1);
|
|
|
|
- point.multiplyScalar( t ).add( this.v1 );
|
|
|
|
|
|
+ tangentCubicBezier: function (t, p0, p1, p2, p3 ) {
|
|
|
|
|
|
- return point;
|
|
|
|
|
|
+ return -3 * p0 * (1 - t) * (1 - t) +
|
|
|
|
+ 3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
|
|
|
|
+ 6 * t * p2 * (1-t) - 3 * t * t * p2 +
|
|
|
|
+ 3 * t * t * p3;
|
|
|
|
+ },
|
|
|
|
|
|
-};
|
|
|
|
|
|
|
|
-// Line curve is linear, so we can overwrite default getPointAt
|
|
|
|
|
|
+ tangentSpline: function ( t, p0, p1, p2, p3 ) {
|
|
|
|
|
|
-THREE.LineCurve.prototype.getPointAt = function ( u ) {
|
|
|
|
|
|
+ // To check if my formulas are correct
|
|
|
|
|
|
- return this.getPoint( u );
|
|
|
|
|
|
+ var h00 = 6 * t * t - 6 * t; // derived from 2t^3 − 3t^2 + 1
|
|
|
|
+ var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
|
|
|
|
+ var h01 = -6 * t * t + 6 * t; // − 2t3 + 3t2
|
|
|
|
+ var h11 = 3 * t * t - 2 * t; // t3 − t2
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ return h00 + h10 + h01 + h11;
|
|
|
|
|
|
-THREE.LineCurve.prototype.getTangent = function( t ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- var tangent = this.v2.clone().sub(this.v1);
|
|
|
|
|
|
+ // Catmull-Rom
|
|
|
|
|
|
- return tangent.normalize();
|
|
|
|
|
|
+ interpolate: function( p0, p1, p2, p3, t ) {
|
|
|
|
+
|
|
|
|
+ var v0 = ( p2 - p0 ) * 0.5;
|
|
|
|
+ var v1 = ( p3 - p1 ) * 0.5;
|
|
|
|
+ var t2 = t * t;
|
|
|
|
+ var t3 = t * t2;
|
|
|
|
+ return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+
|
|
|
|
+// TODO: Transformation for Curves?
|
|
|
|
+
|
|
/**************************************************************
|
|
/**************************************************************
|
|
- * Quadratic Bezier curve
|
|
|
|
|
|
+ * 3D Curves
|
|
**************************************************************/
|
|
**************************************************************/
|
|
|
|
|
|
|
|
+// A Factory method for creating new curve subclasses
|
|
|
|
|
|
-THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
|
|
|
|
|
|
+THREE.Curve.create = function ( constructor, getPointFunc ) {
|
|
|
|
|
|
- this.v0 = v0;
|
|
|
|
- this.v1 = v1;
|
|
|
|
- this.v2 = v2;
|
|
|
|
|
|
+ constructor.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
+ constructor.prototype.getPoint = getPointFunc;
|
|
|
|
+
|
|
|
|
+ return constructor;
|
|
|
|
|
|
};
|
|
};
|
|
|
|
+/**
|
|
|
|
+ * @author zz85 / http://www.lab4games.net/zz85/blog
|
|
|
|
+ *
|
|
|
|
+ **/
|
|
|
|
|
|
-THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
+/**************************************************************
|
|
|
|
+ * Curved Path - a curve path is simply a array of connected
|
|
|
|
+ * curves, but retains the api of a curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
|
|
+THREE.CurvePath = function () {
|
|
|
|
|
|
-THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
+ this.curves = [];
|
|
|
|
+ this.bends = [];
|
|
|
|
+
|
|
|
|
+ this.autoClose = false; // Automatically closes the path
|
|
|
|
+};
|
|
|
|
|
|
- var tx, ty;
|
|
|
|
|
|
+THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
- tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
|
|
|
|
- ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
|
|
|
|
|
|
+THREE.CurvePath.prototype.add = function ( curve ) {
|
|
|
|
|
|
- return new THREE.Vector2( tx, ty );
|
|
|
|
|
|
+ this.curves.push( curve );
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+THREE.CurvePath.prototype.checkConnection = function() {
|
|
|
|
+ // TODO
|
|
|
|
+ // If the ending of curve is not connected to the starting
|
|
|
|
+ // or the next curve, then, this is not a real path
|
|
|
|
+};
|
|
|
|
|
|
-THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
|
|
|
|
-
|
|
|
|
- var tx, ty;
|
|
|
|
|
|
+THREE.CurvePath.prototype.closePath = function() {
|
|
|
|
+ // TODO Test
|
|
|
|
+ // and verify for vector3 (needs to implement equals)
|
|
|
|
+ // Add a line curve if start and end of lines are not connected
|
|
|
|
+ var startPoint = this.curves[0].getPoint(0);
|
|
|
|
+ var endPoint = this.curves[this.curves.length-1].getPoint(1);
|
|
|
|
+
|
|
|
|
+ if (!startPoint.equals(endPoint)) {
|
|
|
|
+ this.curves.push( new THREE.LineCurve(endPoint, startPoint) );
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+};
|
|
|
|
|
|
- tx = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x );
|
|
|
|
- ty = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y );
|
|
|
|
|
|
+// To get accurate point with reference to
|
|
|
|
+// entire path distance at time t,
|
|
|
|
+// following has to be done:
|
|
|
|
|
|
- // returns unit vector
|
|
|
|
|
|
+// 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')
|
|
|
|
|
|
- var tangent = new THREE.Vector2( tx, ty );
|
|
|
|
- tangent.normalize();
|
|
|
|
|
|
+THREE.CurvePath.prototype.getPoint = function( t ) {
|
|
|
|
|
|
- return tangent;
|
|
|
|
|
|
+ var d = t * this.getLength();
|
|
|
|
+ var curveLengths = this.getCurveLengths();
|
|
|
|
+ var i = 0, diff, curve;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ // To think about boundaries points.
|
|
|
|
|
|
|
|
+ while ( i < curveLengths.length ) {
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Cubic Bezier curve
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+ if ( curveLengths[ i ] >= d ) {
|
|
|
|
|
|
-THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
|
|
|
|
|
|
+ diff = curveLengths[ i ] - d;
|
|
|
|
+ curve = this.curves[ i ];
|
|
|
|
|
|
- this.v0 = v0;
|
|
|
|
- this.v1 = v1;
|
|
|
|
- this.v2 = v2;
|
|
|
|
- this.v3 = v3;
|
|
|
|
|
|
+ var u = 1 - diff / curve.getLength();
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ return curve.getPointAt( u );
|
|
|
|
|
|
-THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
|
|
-THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
+ i ++;
|
|
|
|
|
|
- var tx, ty;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
|
|
|
|
- ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
|
|
|
|
|
|
+ return null;
|
|
|
|
|
|
- return new THREE.Vector2( tx, ty );
|
|
|
|
|
|
+ // loop where sum != 0, sum > d , sum+1 <d
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
|
|
|
|
|
|
+/*
|
|
|
|
+THREE.CurvePath.prototype.getTangent = function( t ) {
|
|
|
|
+};*/
|
|
|
|
|
|
- var tx, ty;
|
|
|
|
|
|
|
|
- tx = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
|
|
|
|
- ty = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
|
|
|
|
|
|
+// 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
|
|
|
|
|
|
- var tangent = new THREE.Vector2( tx, ty );
|
|
|
|
- tangent.normalize();
|
|
|
|
|
|
+THREE.CurvePath.prototype.getLength = function() {
|
|
|
|
|
|
- return tangent;
|
|
|
|
|
|
+ var lens = this.getCurveLengths();
|
|
|
|
+ return lens[ lens.length - 1 ];
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+// Compute lengths and cache them
|
|
|
|
+// We cannot overwrite getLengths() because UtoT mapping uses it.
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Spline curve
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+THREE.CurvePath.prototype.getCurveLengths = function() {
|
|
|
|
|
|
-THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
|
|
|
|
|
|
+ // We use cache values if curves and cache array are same length
|
|
|
|
|
|
- this.points = (points == undefined) ? [] : points;
|
|
|
|
|
|
+ if ( this.cacheLengths && this.cacheLengths.length == this.curves.length ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ return this.cacheLengths;
|
|
|
|
|
|
-THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
+ };
|
|
|
|
|
|
-THREE.SplineCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
+ // Get length of subsurve
|
|
|
|
+ // Push sums into cached array
|
|
|
|
|
|
- var v = new THREE.Vector2();
|
|
|
|
- var c = [];
|
|
|
|
- var points = this.points, point, intPoint, weight;
|
|
|
|
- point = ( points.length - 1 ) * t;
|
|
|
|
|
|
+ var lengths = [], sums = 0;
|
|
|
|
+ var i, il = this.curves.length;
|
|
|
|
|
|
- intPoint = Math.floor( point );
|
|
|
|
- weight = point - intPoint;
|
|
|
|
|
|
+ for ( i = 0; i < il; i ++ ) {
|
|
|
|
|
|
- c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
|
|
|
|
- c[ 1 ] = intPoint;
|
|
|
|
- c[ 2 ] = intPoint > points.length - 2 ? points.length -1 : intPoint + 1;
|
|
|
|
- c[ 3 ] = intPoint > points.length - 3 ? points.length -1 : intPoint + 2;
|
|
|
|
|
|
+ sums += this.curves[ i ].getLength();
|
|
|
|
+ lengths.push( sums );
|
|
|
|
|
|
- v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
|
|
|
|
- v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- return v;
|
|
|
|
|
|
+ this.cacheLengths = lengths;
|
|
|
|
+
|
|
|
|
+ return lengths;
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Ellipse curve
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
|
|
-THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius,
|
|
|
|
- aStartAngle, aEndAngle,
|
|
|
|
- aClockwise ) {
|
|
|
|
|
|
|
|
- this.aX = aX;
|
|
|
|
- this.aY = aY;
|
|
|
|
|
|
+// Returns min and max coordinates, as well as centroid
|
|
|
|
|
|
- this.xRadius = xRadius;
|
|
|
|
- this.yRadius = yRadius;
|
|
|
|
|
|
+THREE.CurvePath.prototype.getBoundingBox = function () {
|
|
|
|
|
|
- this.aStartAngle = aStartAngle;
|
|
|
|
- this.aEndAngle = aEndAngle;
|
|
|
|
|
|
+ var points = this.getPoints();
|
|
|
|
|
|
- this.aClockwise = aClockwise;
|
|
|
|
|
|
+ var maxX, maxY, maxZ;
|
|
|
|
+ var minX, minY, minZ;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ maxX = maxY = Number.NEGATIVE_INFINITY;
|
|
|
|
+ minX = minY = Number.POSITIVE_INFINITY;
|
|
|
|
|
|
-THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
+ var p, i, il, sum;
|
|
|
|
|
|
-THREE.EllipseCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
+ var v3 = points[0] instanceof THREE.Vector3;
|
|
|
|
|
|
- var deltaAngle = this.aEndAngle - this.aStartAngle;
|
|
|
|
|
|
+ sum = v3 ? new THREE.Vector3() : new THREE.Vector2();
|
|
|
|
|
|
- if ( !this.aClockwise ) {
|
|
|
|
|
|
+ for ( i = 0, il = points.length; i < il; i ++ ) {
|
|
|
|
|
|
- t = 1 - t;
|
|
|
|
|
|
+ p = points[ i ];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ if ( p.x > maxX ) maxX = p.x;
|
|
|
|
+ else if ( p.x < minX ) minX = p.x;
|
|
|
|
|
|
- var angle = this.aStartAngle + t * deltaAngle;
|
|
|
|
|
|
+ if ( p.y > maxY ) maxY = p.y;
|
|
|
|
+ else if ( p.y < minY ) minY = p.y;
|
|
|
|
|
|
- var tx = this.aX + this.xRadius * Math.cos( angle );
|
|
|
|
- var ty = this.aY + this.yRadius * Math.sin( angle );
|
|
|
|
|
|
+ if ( v3 ) {
|
|
|
|
|
|
- return new THREE.Vector2( tx, ty );
|
|
|
|
|
|
+ if ( p.z > maxZ ) maxZ = p.z;
|
|
|
|
+ else if ( p.z < minZ ) minZ = p.z;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Arc curve
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+ sum.add( p );
|
|
|
|
|
|
-THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
|
|
|
|
-};
|
|
|
|
|
|
+ var ret = {
|
|
|
|
|
|
-THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );
|
|
|
|
|
|
+ minX: minX,
|
|
|
|
+ minY: minY,
|
|
|
|
+ maxX: maxX,
|
|
|
|
+ maxY: maxY,
|
|
|
|
+ centroid: sum.divideScalar( il )
|
|
|
|
|
|
|
|
+ };
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Utils
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+ if ( v3 ) {
|
|
|
|
|
|
-THREE.Curve.Utils = {
|
|
|
|
|
|
+ ret.maxZ = maxZ;
|
|
|
|
+ ret.minZ = minZ;
|
|
|
|
|
|
- tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
|
|
|
|
|
|
+ return ret;
|
|
|
|
|
|
- },
|
|
|
|
|
|
+};
|
|
|
|
|
|
- // Puay Bing, thanks for helping with this derivative!
|
|
|
|
|
|
+/**************************************************************
|
|
|
|
+ * Create Geometries Helpers
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- tangentCubicBezier: function (t, p0, p1, p2, p3 ) {
|
|
|
|
|
|
+/// Generate geometry from path points (for Line or ParticleSystem objects)
|
|
|
|
|
|
- return -3 * p0 * (1 - t) * (1 - t) +
|
|
|
|
- 3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
|
|
|
|
- 6 * t * p2 * (1-t) - 3 * t * t * p2 +
|
|
|
|
- 3 * t * t * p3;
|
|
|
|
- },
|
|
|
|
|
|
+THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
|
|
|
|
|
|
|
|
+ var pts = this.getPoints( divisions, true );
|
|
|
|
+ return this.createGeometry( pts );
|
|
|
|
|
|
- tangentSpline: function ( t, p0, p1, p2, p3 ) {
|
|
|
|
|
|
+};
|
|
|
|
|
|
- // To check if my formulas are correct
|
|
|
|
|
|
+// Generate geometry from equidistance sampling along the path
|
|
|
|
|
|
- var h00 = 6 * t * t - 6 * t; // derived from 2t^3 − 3t^2 + 1
|
|
|
|
- var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
|
|
|
|
- var h01 = -6 * t * t + 6 * t; // − 2t3 + 3t2
|
|
|
|
- var h11 = 3 * t * t - 2 * t; // t3 − t2
|
|
|
|
|
|
+THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
|
|
|
|
|
|
- return h00 + h10 + h01 + h11;
|
|
|
|
|
|
+ var pts = this.getSpacedPoints( divisions, true );
|
|
|
|
+ return this.createGeometry( pts );
|
|
|
|
|
|
- },
|
|
|
|
|
|
+};
|
|
|
|
|
|
- // Catmull-Rom
|
|
|
|
|
|
+THREE.CurvePath.prototype.createGeometry = function( points ) {
|
|
|
|
|
|
- interpolate: function( p0, p1, p2, p3, t ) {
|
|
|
|
|
|
+ var geometry = new THREE.Geometry();
|
|
|
|
|
|
- var v0 = ( p2 - p0 ) * 0.5;
|
|
|
|
- var v1 = ( p3 - p1 ) * 0.5;
|
|
|
|
- var t2 = t * t;
|
|
|
|
- var t3 = t * t2;
|
|
|
|
- return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
|
|
|
|
|
|
+ for ( var i = 0; i < points.length; i ++ ) {
|
|
|
|
+
|
|
|
|
+ geometry.vertices.push( new THREE.Vector3( points[ i ].x, points[ i ].y, points[ i ].z || 0) );
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ return geometry;
|
|
|
|
|
|
|
|
+};
|
|
|
|
|
|
-// TODO: Transformation for Curves?
|
|
|
|
|
|
|
|
/**************************************************************
|
|
/**************************************************************
|
|
- * 3D Curves
|
|
|
|
|
|
+ * Bend / Wrap Helper Methods
|
|
**************************************************************/
|
|
**************************************************************/
|
|
|
|
|
|
-// A Factory method for creating new curve subclasses
|
|
|
|
-
|
|
|
|
-THREE.Curve.create = function ( constructor, getPointFunc ) {
|
|
|
|
|
|
+// Wrap path / Bend modifiers?
|
|
|
|
|
|
- constructor.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
- constructor.prototype.getPoint = getPointFunc;
|
|
|
|
|
|
+THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
|
|
|
|
|
|
- return constructor;
|
|
|
|
|
|
+ this.bends.push( bendpath );
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Line3D
|
|
|
|
- **************************************************************/
|
|
|
|
-
|
|
|
|
-THREE.LineCurve3 = THREE.Curve.create(
|
|
|
|
-
|
|
|
|
- function ( v1, v2 ) {
|
|
|
|
|
|
+ var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
|
|
|
|
+ var i, il;
|
|
|
|
|
|
- this.v1 = v1;
|
|
|
|
- this.v2 = v2;
|
|
|
|
|
|
+ if ( !bends ) {
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ bends = this.bends;
|
|
|
|
|
|
- function ( t ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var r = new THREE.Vector3();
|
|
|
|
|
|
+ for ( i = 0, il = bends.length; i < il; i ++ ) {
|
|
|
|
|
|
|
|
+ oldPts = this.getWrapPoints( oldPts, bends[ i ] );
|
|
|
|
|
|
- r.subVectors( this.v2, this.v1 ); // diff
|
|
|
|
- r.multiplyScalar( t );
|
|
|
|
- r.add( this.v1 );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- return r;
|
|
|
|
|
|
+ return oldPts;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+};
|
|
|
|
|
|
-);
|
|
|
|
|
|
+THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
|
|
|
|
|
|
|
|
+ var oldPts = this.getSpacedPoints( segments );
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Quadratic Bezier 3D curve
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+ var i, il;
|
|
|
|
|
|
-THREE.QuadraticBezierCurve3 = THREE.Curve.create(
|
|
|
|
|
|
+ if ( !bends ) {
|
|
|
|
|
|
- function ( v0, v1, v2 ) {
|
|
|
|
|
|
+ bends = this.bends;
|
|
|
|
|
|
- this.v0 = v0;
|
|
|
|
- this.v1 = v1;
|
|
|
|
- this.v2 = v2;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ for ( i = 0, il = bends.length; i < il; i ++ ) {
|
|
|
|
|
|
- function ( t ) {
|
|
|
|
|
|
+ oldPts = this.getWrapPoints( oldPts, bends[ i ] );
|
|
|
|
|
|
- var tx, ty, tz;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
|
|
|
|
- ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
|
|
|
|
- tz = THREE.Shape.Utils.b2( t, this.v0.z, this.v1.z, this.v2.z );
|
|
|
|
|
|
+ return oldPts;
|
|
|
|
|
|
- return new THREE.Vector3( tx, ty, tz );
|
|
|
|
|
|
+};
|
|
|
|
|
|
- }
|
|
|
|
|
|
+// 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;
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Cubic Bezier 3D curve
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+ for ( i = 0, il = oldPts.length; i < il; i ++ ) {
|
|
|
|
|
|
-THREE.CubicBezierCurve3 = THREE.Curve.create(
|
|
|
|
|
|
+ p = oldPts[ i ];
|
|
|
|
|
|
- function ( v0, v1, v2, v3 ) {
|
|
|
|
|
|
+ oldX = p.x;
|
|
|
|
+ oldY = p.y;
|
|
|
|
|
|
- this.v0 = v0;
|
|
|
|
- this.v1 = v1;
|
|
|
|
- this.v2 = v2;
|
|
|
|
- this.v3 = v3;
|
|
|
|
|
|
+ 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
|
|
|
|
|
|
- function ( t ) {
|
|
|
|
|
|
+ xNorm = path.getUtoTmapping( xNorm, oldX );
|
|
|
|
|
|
- var tx, ty, tz;
|
|
|
|
|
|
+ // check for out of bounds?
|
|
|
|
|
|
- tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
|
|
|
|
- ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
|
|
|
|
- tz = THREE.Shape.Utils.b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z );
|
|
|
|
|
|
+ var pathPt = path.getPoint( xNorm );
|
|
|
|
+ var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
|
|
|
|
|
|
- return new THREE.Vector3( tx, ty, tz );
|
|
|
|
|
|
+ p.x = pathPt.x + normal.x;
|
|
|
|
+ p.y = pathPt.y + normal.y;
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-);
|
|
|
|
|
|
+ return oldPts;
|
|
|
|
|
|
|
|
+};
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * @author alteredq / http://alteredqualia.com/
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+THREE.Gyroscope = function () {
|
|
|
|
+
|
|
|
|
+ THREE.Object3D.call( this );
|
|
|
|
+
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
|
|
|
|
+
|
|
|
|
+THREE.Gyroscope.prototype.updateMatrixWorld = function ( force ) {
|
|
|
|
+
|
|
|
|
+ this.matrixAutoUpdate && this.updateMatrix();
|
|
|
|
+
|
|
|
|
+ // update matrixWorld
|
|
|
|
+
|
|
|
|
+ if ( this.matrixWorldNeedsUpdate || force ) {
|
|
|
|
+
|
|
|
|
+ if ( this.parent ) {
|
|
|
|
+
|
|
|
|
+ this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
|
|
|
|
+
|
|
|
|
+ this.matrixWorld.decompose( this.translationWorld, this.rotationWorld, this.scaleWorld );
|
|
|
|
+ this.matrix.decompose( this.translationObject, this.rotationObject, this.scaleObject );
|
|
|
|
+
|
|
|
|
+ this.matrixWorld.makeFromPositionQuaternionScale( this.translationWorld, this.rotationObject, this.scaleWorld );
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ } else {
|
|
|
|
+
|
|
|
|
+ this.matrixWorld.copy( this.matrix );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ this.matrixWorldNeedsUpdate = false;
|
|
|
|
+
|
|
|
|
+ force = true;
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // update children
|
|
|
|
+
|
|
|
|
+ for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
|
|
|
+
|
|
|
|
+ this.children[ i ].updateMatrixWorld( force );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+THREE.Gyroscope.prototype.translationWorld = new THREE.Vector3();
|
|
|
|
+THREE.Gyroscope.prototype.translationObject = new THREE.Vector3();
|
|
|
|
+THREE.Gyroscope.prototype.rotationWorld = new THREE.Quaternion();
|
|
|
|
+THREE.Gyroscope.prototype.rotationObject = new THREE.Quaternion();
|
|
|
|
+THREE.Gyroscope.prototype.scaleWorld = new THREE.Vector3();
|
|
|
|
+THREE.Gyroscope.prototype.scaleObject = new THREE.Vector3();
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * @author zz85 / http://www.lab4games.net/zz85/blog
|
|
|
|
+ * Creates free form 2d path using series of points, lines or curves.
|
|
|
|
+ *
|
|
|
|
+ **/
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Spline 3D curve
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+THREE.Path = function ( points ) {
|
|
|
|
|
|
|
|
+ THREE.CurvePath.call(this);
|
|
|
|
|
|
-THREE.SplineCurve3 = THREE.Curve.create(
|
|
|
|
|
|
+ this.actions = [];
|
|
|
|
|
|
- function ( points /* array of Vector3 */) {
|
|
|
|
|
|
+ if ( points ) {
|
|
|
|
|
|
- this.points = (points == undefined) ? [] : points;
|
|
|
|
|
|
+ this.fromPoints( points );
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- function ( t ) {
|
|
|
|
-
|
|
|
|
- var v = new THREE.Vector3();
|
|
|
|
- var c = [];
|
|
|
|
- var points = this.points, point, intPoint, weight;
|
|
|
|
- point = ( points.length - 1 ) * t;
|
|
|
|
-
|
|
|
|
- intPoint = Math.floor( point );
|
|
|
|
- weight = point - intPoint;
|
|
|
|
-
|
|
|
|
- c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
|
|
|
|
- c[ 1 ] = intPoint;
|
|
|
|
- c[ 2 ] = intPoint > points.length - 2 ? points.length - 1 : intPoint + 1;
|
|
|
|
- c[ 3 ] = intPoint > points.length - 3 ? points.length - 1 : intPoint + 2;
|
|
|
|
-
|
|
|
|
- var pt0 = points[ c[0] ],
|
|
|
|
- pt1 = points[ c[1] ],
|
|
|
|
- pt2 = points[ c[2] ],
|
|
|
|
- pt3 = points[ c[3] ];
|
|
|
|
-
|
|
|
|
- v.x = THREE.Curve.Utils.interpolate(pt0.x, pt1.x, pt2.x, pt3.x, weight);
|
|
|
|
- v.y = THREE.Curve.Utils.interpolate(pt0.y, pt1.y, pt2.y, pt3.y, weight);
|
|
|
|
- v.z = THREE.Curve.Utils.interpolate(pt0.z, pt1.z, pt2.z, pt3.z, weight);
|
|
|
|
-
|
|
|
|
- return v;
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-);
|
|
|
|
-
|
|
|
|
-
|
|
|
|
-// THREE.SplineCurve3.prototype.getTangent = function(t) {
|
|
|
|
-// var v = new THREE.Vector3();
|
|
|
|
-// var c = [];
|
|
|
|
-// var points = this.points, point, intPoint, weight;
|
|
|
|
-// point = ( points.length - 1 ) * t;
|
|
|
|
-
|
|
|
|
-// intPoint = Math.floor( point );
|
|
|
|
-// weight = point - intPoint;
|
|
|
|
-
|
|
|
|
-// c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
|
|
|
|
-// c[ 1 ] = intPoint;
|
|
|
|
-// c[ 2 ] = intPoint > points.length - 2 ? points.length - 1 : intPoint + 1;
|
|
|
|
-// c[ 3 ] = intPoint > points.length - 3 ? points.length - 1 : intPoint + 2;
|
|
|
|
-
|
|
|
|
-// var pt0 = points[ c[0] ],
|
|
|
|
-// pt1 = points[ c[1] ],
|
|
|
|
-// pt2 = points[ c[2] ],
|
|
|
|
-// pt3 = points[ c[3] ];
|
|
|
|
-
|
|
|
|
-// // t = weight;
|
|
|
|
-// v.x = THREE.Curve.Utils.tangentSpline( t, pt0.x, pt1.x, pt2.x, pt3.x );
|
|
|
|
-// v.y = THREE.Curve.Utils.tangentSpline( t, pt0.y, pt1.y, pt2.y, pt3.y );
|
|
|
|
-// v.z = THREE.Curve.Utils.tangentSpline( t, pt0.z, pt1.z, pt2.z, pt3.z );
|
|
|
|
-
|
|
|
|
-// return v;
|
|
|
|
-
|
|
|
|
-// }
|
|
|
|
|
|
+};
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Closed Spline 3D curve
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
|
|
|
|
|
|
|
|
+THREE.PathActions = {
|
|
|
|
|
|
-THREE.ClosedSplineCurve3 = THREE.Curve.create(
|
|
|
|
|
|
+ MOVE_TO: 'moveTo',
|
|
|
|
+ LINE_TO: 'lineTo',
|
|
|
|
+ QUADRATIC_CURVE_TO: 'quadraticCurveTo', // Bezier quadratic curve
|
|
|
|
+ BEZIER_CURVE_TO: 'bezierCurveTo', // Bezier cubic curve
|
|
|
|
+ CSPLINE_THRU: 'splineThru', // Catmull-rom spline
|
|
|
|
+ ARC: 'arc', // Circle
|
|
|
|
+ ELLIPSE: 'ellipse'
|
|
|
|
+};
|
|
|
|
|
|
- function ( points /* array of Vector3 */) {
|
|
|
|
|
|
+// TODO Clean up PATH API
|
|
|
|
|
|
- this.points = (points == undefined) ? [] : points;
|
|
|
|
|
|
+// Create path using straight lines to connect all points
|
|
|
|
+// - vectors: array of Vector2
|
|
|
|
|
|
- },
|
|
|
|
|
|
+THREE.Path.prototype.fromPoints = function ( vectors ) {
|
|
|
|
|
|
- function ( t ) {
|
|
|
|
|
|
+ this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
|
|
|
|
|
|
- var v = new THREE.Vector3();
|
|
|
|
- var c = [];
|
|
|
|
- var points = this.points, point, intPoint, weight;
|
|
|
|
- point = ( points.length - 0 ) * t;
|
|
|
|
- // This needs to be from 0-length +1
|
|
|
|
|
|
+ for ( var v = 1, vlen = vectors.length; v < vlen; v ++ ) {
|
|
|
|
|
|
- intPoint = Math.floor( point );
|
|
|
|
- weight = point - intPoint;
|
|
|
|
|
|
+ this.lineTo( vectors[ v ].x, vectors[ v ].y );
|
|
|
|
|
|
- intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
|
|
|
|
- c[ 0 ] = ( intPoint - 1 ) % points.length;
|
|
|
|
- c[ 1 ] = ( intPoint ) % points.length;
|
|
|
|
- c[ 2 ] = ( intPoint + 1 ) % points.length;
|
|
|
|
- c[ 3 ] = ( intPoint + 2 ) % points.length;
|
|
|
|
|
|
+ };
|
|
|
|
|
|
- v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
|
|
|
|
- v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
|
|
|
|
- v.z = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].z, points[ c[ 1 ] ].z, points[ c[ 2 ] ].z, points[ c[ 3 ] ].z, weight );
|
|
|
|
|
|
+};
|
|
|
|
|
|
- return v;
|
|
|
|
|
|
+// startPath() endPath()?
|
|
|
|
|
|
- }
|
|
|
|
|
|
+THREE.Path.prototype.moveTo = function ( x, y ) {
|
|
|
|
|
|
-);
|
|
|
|
-/**
|
|
|
|
- * @author zz85 / http://www.lab4games.net/zz85/blog
|
|
|
|
- *
|
|
|
|
- **/
|
|
|
|
|
|
+ var args = Array.prototype.slice.call( arguments );
|
|
|
|
+ this.actions.push( { action: THREE.PathActions.MOVE_TO, args: args } );
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Curved Path - a curve path is simply a array of connected
|
|
|
|
- * curves, but retains the api of a curve
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+};
|
|
|
|
|
|
-THREE.CurvePath = function () {
|
|
|
|
|
|
+THREE.Path.prototype.lineTo = function ( x, y ) {
|
|
|
|
|
|
- this.curves = [];
|
|
|
|
- this.bends = [];
|
|
|
|
-
|
|
|
|
- this.autoClose = false; // Automatically closes the path
|
|
|
|
-};
|
|
|
|
|
|
+ var args = Array.prototype.slice.call( arguments );
|
|
|
|
|
|
-THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
-THREE.CurvePath.prototype.add = function ( curve ) {
|
|
|
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
|
|
+ var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
|
|
this.curves.push( curve );
|
|
this.curves.push( curve );
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.actions.push( { action: THREE.PathActions.LINE_TO, args: args } );
|
|
|
|
|
|
-THREE.CurvePath.prototype.checkConnection = function() {
|
|
|
|
- // TODO
|
|
|
|
- // If the ending of curve is not connected to the starting
|
|
|
|
- // or the next curve, then, this is not a real path
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-THREE.CurvePath.prototype.closePath = function() {
|
|
|
|
- // TODO Test
|
|
|
|
- // and verify for vector3 (needs to implement equals)
|
|
|
|
- // Add a line curve if start and end of lines are not connected
|
|
|
|
- var startPoint = this.curves[0].getPoint(0);
|
|
|
|
- var endPoint = this.curves[this.curves.length-1].getPoint(1);
|
|
|
|
-
|
|
|
|
- if (!startPoint.equals(endPoint)) {
|
|
|
|
- this.curves.push( new THREE.LineCurve(endPoint, startPoint) );
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-// 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 ) {
|
|
|
|
|
|
+THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
|
|
|
|
|
|
- var d = t * this.getLength();
|
|
|
|
- var curveLengths = this.getCurveLengths();
|
|
|
|
- var i = 0, diff, curve;
|
|
|
|
|
|
+ var args = Array.prototype.slice.call( arguments );
|
|
|
|
|
|
- // To think about boundaries points.
|
|
|
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
- while ( i < curveLengths.length ) {
|
|
|
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
- if ( curveLengths[ i ] >= d ) {
|
|
|
|
|
|
+ var curve = new THREE.QuadraticBezierCurve( new THREE.Vector2( x0, y0 ),
|
|
|
|
+ new THREE.Vector2( aCPx, aCPy ),
|
|
|
|
+ new THREE.Vector2( aX, aY ) );
|
|
|
|
+ this.curves.push( curve );
|
|
|
|
|
|
- diff = curveLengths[ i ] - d;
|
|
|
|
- curve = this.curves[ i ];
|
|
|
|
|
|
+ this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args } );
|
|
|
|
|
|
- var u = 1 - diff / curve.getLength();
|
|
|
|
|
|
+};
|
|
|
|
|
|
- return curve.getPointAt( u );
|
|
|
|
|
|
+THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y,
|
|
|
|
+ aCP2x, aCP2y,
|
|
|
|
+ aX, aY ) {
|
|
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
|
|
+ var args = Array.prototype.slice.call( arguments );
|
|
|
|
|
|
- i ++;
|
|
|
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
- return null;
|
|
|
|
|
|
+ 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 );
|
|
|
|
|
|
- // loop where sum != 0, sum > d , sum+1 <d
|
|
|
|
|
|
+ this.actions.push( { action: THREE.PathActions.BEZIER_CURVE_TO, args: args } );
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-/*
|
|
|
|
-THREE.CurvePath.prototype.getTangent = function( t ) {
|
|
|
|
-};*/
|
|
|
|
|
|
+THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
|
|
|
|
|
|
|
|
+ var args = Array.prototype.slice.call( arguments );
|
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
-// 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
|
|
|
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
+//---
|
|
|
|
+ var npts = [ new THREE.Vector2( x0, y0 ) ];
|
|
|
|
+ Array.prototype.push.apply( npts, pts );
|
|
|
|
|
|
-THREE.CurvePath.prototype.getLength = function() {
|
|
|
|
|
|
+ var curve = new THREE.SplineCurve( npts );
|
|
|
|
+ this.curves.push( curve );
|
|
|
|
|
|
- var lens = this.getCurveLengths();
|
|
|
|
- return lens[ lens.length - 1 ];
|
|
|
|
|
|
+ this.actions.push( { action: THREE.PathActions.CSPLINE_THRU, args: args } );
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-// 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;
|
|
|
|
|
|
+// FUTURE: Change the API or follow canvas API?
|
|
|
|
|
|
- for ( i = 0; i < il; i ++ ) {
|
|
|
|
|
|
+THREE.Path.prototype.arc = function ( aX, aY, aRadius,
|
|
|
|
+ aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
- sums += this.curves[ i ].getLength();
|
|
|
|
- lengths.push( sums );
|
|
|
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1].args;
|
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ this.absarc(aX + x0, aY + y0, aRadius,
|
|
|
|
+ aStartAngle, aEndAngle, aClockwise );
|
|
|
|
+
|
|
|
|
+ };
|
|
|
|
|
|
- this.cacheLengths = lengths;
|
|
|
|
|
|
+ THREE.Path.prototype.absarc = function ( aX, aY, aRadius,
|
|
|
|
+ aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
+ this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius,
|
|
|
|
+ aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
- return lengths;
|
|
|
|
|
|
+ var lastargs = this.actions[ this.actions.length - 1].args;
|
|
|
|
+ var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
+ var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ this.absellipse(aX + x0, aY + y0, xRadius, yRadius,
|
|
|
|
+ aStartAngle, aEndAngle, aClockwise );
|
|
|
|
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
|
|
|
|
+THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius,
|
|
|
|
+ aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
-// Returns min and max coordinates, as well as centroid
|
|
|
|
|
|
+ var args = Array.prototype.slice.call( arguments );
|
|
|
|
+ var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius,
|
|
|
|
+ aStartAngle, aEndAngle, aClockwise );
|
|
|
|
+ this.curves.push( curve );
|
|
|
|
|
|
-THREE.CurvePath.prototype.getBoundingBox = function () {
|
|
|
|
|
|
+ var lastPoint = curve.getPoint(aClockwise ? 1 : 0);
|
|
|
|
+ args.push(lastPoint.x);
|
|
|
|
+ args.push(lastPoint.y);
|
|
|
|
|
|
- var points = this.getPoints();
|
|
|
|
|
|
+ this.actions.push( { action: THREE.PathActions.ELLIPSE, args: args } );
|
|
|
|
|
|
- var maxX, maxY, maxZ;
|
|
|
|
- var minX, minY, minZ;
|
|
|
|
|
|
+ };
|
|
|
|
|
|
- maxX = maxY = Number.NEGATIVE_INFINITY;
|
|
|
|
- minX = minY = Number.POSITIVE_INFINITY;
|
|
|
|
|
|
+THREE.Path.prototype.getSpacedPoints = function ( divisions, closedPath ) {
|
|
|
|
|
|
- var p, i, il, sum;
|
|
|
|
|
|
+ if ( ! divisions ) divisions = 40;
|
|
|
|
|
|
- var v3 = points[0] instanceof THREE.Vector3;
|
|
|
|
|
|
+ var points = [];
|
|
|
|
|
|
- sum = v3 ? new THREE.Vector3() : new THREE.Vector2();
|
|
|
|
|
|
+ for ( var i = 0; i < divisions; i ++ ) {
|
|
|
|
|
|
- for ( i = 0, il = points.length; i < il; i ++ ) {
|
|
|
|
|
|
+ points.push( this.getPoint( i / divisions ) );
|
|
|
|
|
|
- p = points[ i ];
|
|
|
|
|
|
+ //if( !this.getPoint( i / divisions ) ) throw "DIE";
|
|
|
|
|
|
- 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 < minY ) minY = p.y;
|
|
|
|
|
|
+ // if ( closedPath ) {
|
|
|
|
+ //
|
|
|
|
+ // points.push( points[ 0 ] );
|
|
|
|
+ //
|
|
|
|
+ // }
|
|
|
|
|
|
- if ( v3 ) {
|
|
|
|
|
|
+ return points;
|
|
|
|
|
|
- if ( p.z > maxZ ) maxZ = p.z;
|
|
|
|
- else if ( p.z < minZ ) minZ = p.z;
|
|
|
|
|
|
+};
|
|
|
|
|
|
- }
|
|
|
|
|
|
+/* Return an array of vectors based on contour of the path */
|
|
|
|
|
|
- sum.add( p );
|
|
|
|
|
|
+THREE.Path.prototype.getPoints = function( divisions, closedPath ) {
|
|
|
|
|
|
|
|
+ if (this.useSpacedPoints) {
|
|
|
|
+ console.log('tata');
|
|
|
|
+ return this.getSpacedPoints( divisions, closedPath );
|
|
}
|
|
}
|
|
|
|
|
|
- var ret = {
|
|
|
|
-
|
|
|
|
- minX: minX,
|
|
|
|
- minY: minY,
|
|
|
|
- maxX: maxX,
|
|
|
|
- maxY: maxY,
|
|
|
|
- centroid: sum.divideScalar( il )
|
|
|
|
|
|
+ divisions = divisions || 12;
|
|
|
|
|
|
- };
|
|
|
|
|
|
+ var points = [];
|
|
|
|
|
|
- if ( v3 ) {
|
|
|
|
|
|
+ var i, il, item, action, args;
|
|
|
|
+ var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
|
|
|
|
+ laste, j,
|
|
|
|
+ t, tx, ty;
|
|
|
|
|
|
- ret.maxZ = maxZ;
|
|
|
|
- ret.minZ = minZ;
|
|
|
|
|
|
+ for ( i = 0, il = this.actions.length; i < il; i ++ ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ item = this.actions[ i ];
|
|
|
|
|
|
- return ret;
|
|
|
|
|
|
+ action = item.action;
|
|
|
|
+ args = item.args;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ switch( action ) {
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Create Geometries Helpers
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+ case THREE.PathActions.MOVE_TO:
|
|
|
|
|
|
-/// Generate geometry from path points (for Line or ParticleSystem objects)
|
|
|
|
|
|
+ points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
|
|
|
|
|
-THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
|
|
|
|
|
|
+ break;
|
|
|
|
|
|
- var pts = this.getPoints( divisions, true );
|
|
|
|
- return this.createGeometry( pts );
|
|
|
|
|
|
+ case THREE.PathActions.LINE_TO:
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
|
|
|
|
|
-// Generate geometry from equidistance sampling along the path
|
|
|
|
|
|
+ break;
|
|
|
|
|
|
-THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
|
|
|
|
|
|
+ case THREE.PathActions.QUADRATIC_CURVE_TO:
|
|
|
|
|
|
- var pts = this.getSpacedPoints( divisions, true );
|
|
|
|
- return this.createGeometry( pts );
|
|
|
|
|
|
+ cpx = args[ 2 ];
|
|
|
|
+ cpy = args[ 3 ];
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ cpx1 = args[ 0 ];
|
|
|
|
+ cpy1 = args[ 1 ];
|
|
|
|
|
|
-THREE.CurvePath.prototype.createGeometry = function( points ) {
|
|
|
|
|
|
+ if ( points.length > 0 ) {
|
|
|
|
|
|
- var geometry = new THREE.Geometry();
|
|
|
|
|
|
+ laste = points[ points.length - 1 ];
|
|
|
|
|
|
- for ( var i = 0; i < points.length; i ++ ) {
|
|
|
|
|
|
+ cpx0 = laste.x;
|
|
|
|
+ cpy0 = laste.y;
|
|
|
|
|
|
- geometry.vertices.push( new THREE.Vector3( points[ i ].x, points[ i ].y, points[ i ].z || 0) );
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
- return geometry;
|
|
|
|
|
|
+ cpx0 = laste[ laste.length - 2 ];
|
|
|
|
+ cpy0 = laste[ laste.length - 1 ];
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ for ( j = 1; j <= divisions; j ++ ) {
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Bend / Wrap Helper Methods
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+ t = j / divisions;
|
|
|
|
|
|
-// Wrap path / Bend modifiers?
|
|
|
|
|
|
+ tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
|
|
|
|
+ ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
|
|
|
|
|
|
-THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
|
|
|
|
|
|
+ points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
- this.bends.push( bendpath );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ break;
|
|
|
|
|
|
-THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
|
|
|
|
|
|
+ case THREE.PathActions.BEZIER_CURVE_TO:
|
|
|
|
|
|
- var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
|
|
|
|
- var i, il;
|
|
|
|
|
|
+ cpx = args[ 4 ];
|
|
|
|
+ cpy = args[ 5 ];
|
|
|
|
|
|
- if ( !bends ) {
|
|
|
|
|
|
+ cpx1 = args[ 0 ];
|
|
|
|
+ cpy1 = args[ 1 ];
|
|
|
|
|
|
- bends = this.bends;
|
|
|
|
|
|
+ cpx2 = args[ 2 ];
|
|
|
|
+ cpy2 = args[ 3 ];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ if ( points.length > 0 ) {
|
|
|
|
|
|
- for ( i = 0, il = bends.length; i < il; i ++ ) {
|
|
|
|
|
|
+ laste = points[ points.length - 1 ];
|
|
|
|
|
|
- oldPts = this.getWrapPoints( oldPts, bends[ i ] );
|
|
|
|
|
|
+ cpx0 = laste.x;
|
|
|
|
+ cpy0 = laste.y;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- return oldPts;
|
|
|
|
|
|
+ laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ cpx0 = laste[ laste.length - 2 ];
|
|
|
|
+ cpy0 = laste[ laste.length - 1 ];
|
|
|
|
|
|
-THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var oldPts = this.getSpacedPoints( segments );
|
|
|
|
|
|
|
|
- var i, il;
|
|
|
|
|
|
+ for ( j = 1; j <= divisions; j ++ ) {
|
|
|
|
|
|
- if ( !bends ) {
|
|
|
|
|
|
+ t = j / divisions;
|
|
|
|
|
|
- bends = this.bends;
|
|
|
|
|
|
+ tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
|
|
|
|
+ ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
- for ( i = 0, il = bends.length; i < il; i ++ ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- oldPts = this.getWrapPoints( oldPts, bends[ i ] );
|
|
|
|
|
|
+ break;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ case THREE.PathActions.CSPLINE_THRU:
|
|
|
|
|
|
- return oldPts;
|
|
|
|
|
|
+ laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
|
|
|
|
+ var spts = [ last ];
|
|
|
|
|
|
-// This returns getPoints() bend/wrapped around the contour of a path.
|
|
|
|
-// Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
|
|
|
|
|
|
+ var n = divisions * args[ 0 ].length;
|
|
|
|
|
|
-THREE.CurvePath.prototype.getWrapPoints = function ( oldPts, path ) {
|
|
|
|
|
|
+ spts = spts.concat( args[ 0 ] );
|
|
|
|
|
|
- var bounds = this.getBoundingBox();
|
|
|
|
|
|
+ var spline = new THREE.SplineCurve( spts );
|
|
|
|
|
|
- var i, il, p, oldX, oldY, xNorm;
|
|
|
|
|
|
+ for ( j = 1; j <= n; j ++ ) {
|
|
|
|
|
|
- for ( i = 0, il = oldPts.length; i < il; i ++ ) {
|
|
|
|
|
|
+ points.push( spline.getPointAt( j / n ) ) ;
|
|
|
|
|
|
- p = oldPts[ i ];
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- oldX = p.x;
|
|
|
|
- oldY = p.y;
|
|
|
|
|
|
+ break;
|
|
|
|
|
|
- xNorm = oldX / bounds.maxX;
|
|
|
|
|
|
+ case THREE.PathActions.ARC:
|
|
|
|
|
|
- // 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
|
|
|
|
|
|
+ var aX = args[ 0 ], aY = args[ 1 ],
|
|
|
|
+ aRadius = args[ 2 ],
|
|
|
|
+ aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
|
|
|
|
+ aClockwise = !!args[ 5 ];
|
|
|
|
|
|
- xNorm = path.getUtoTmapping( xNorm, oldX );
|
|
|
|
|
|
+ var deltaAngle = aEndAngle - aStartAngle;
|
|
|
|
+ var angle;
|
|
|
|
+ var tdivisions = divisions * 2;
|
|
|
|
|
|
- // check for out of bounds?
|
|
|
|
|
|
+ for ( j = 1; j <= tdivisions; j ++ ) {
|
|
|
|
|
|
- var pathPt = path.getPoint( xNorm );
|
|
|
|
- var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
|
|
|
|
|
|
+ t = j / tdivisions;
|
|
|
|
|
|
- p.x = pathPt.x + normal.x;
|
|
|
|
- p.y = pathPt.y + normal.y;
|
|
|
|
|
|
+ if ( ! aClockwise ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ t = 1 - t;
|
|
|
|
|
|
- return oldPts;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ angle = aStartAngle + t * deltaAngle;
|
|
|
|
|
|
-/**
|
|
|
|
- * @author alteredq / http://alteredqualia.com/
|
|
|
|
- */
|
|
|
|
-
|
|
|
|
-THREE.Gyroscope = function () {
|
|
|
|
-
|
|
|
|
- THREE.Object3D.call( this );
|
|
|
|
-
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
|
|
|
|
-
|
|
|
|
-THREE.Gyroscope.prototype.updateMatrixWorld = function ( force ) {
|
|
|
|
-
|
|
|
|
- this.matrixAutoUpdate && this.updateMatrix();
|
|
|
|
-
|
|
|
|
- // update matrixWorld
|
|
|
|
-
|
|
|
|
- if ( this.matrixWorldNeedsUpdate || force ) {
|
|
|
|
-
|
|
|
|
- if ( this.parent ) {
|
|
|
|
-
|
|
|
|
- this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix );
|
|
|
|
-
|
|
|
|
- this.matrixWorld.decompose( this.translationWorld, this.rotationWorld, this.scaleWorld );
|
|
|
|
- this.matrix.decompose( this.translationObject, this.rotationObject, this.scaleObject );
|
|
|
|
-
|
|
|
|
- this.matrixWorld.makeFromPositionQuaternionScale( this.translationWorld, this.rotationObject, this.scaleWorld );
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- } else {
|
|
|
|
-
|
|
|
|
- this.matrixWorld.copy( this.matrix );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- this.matrixWorldNeedsUpdate = false;
|
|
|
|
-
|
|
|
|
- force = true;
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- // update children
|
|
|
|
-
|
|
|
|
- for ( var i = 0, l = this.children.length; i < l; i ++ ) {
|
|
|
|
-
|
|
|
|
- this.children[ i ].updateMatrixWorld( force );
|
|
|
|
-
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-THREE.Gyroscope.prototype.translationWorld = new THREE.Vector3();
|
|
|
|
-THREE.Gyroscope.prototype.translationObject = new THREE.Vector3();
|
|
|
|
-THREE.Gyroscope.prototype.rotationWorld = new THREE.Quaternion();
|
|
|
|
-THREE.Gyroscope.prototype.rotationObject = new THREE.Quaternion();
|
|
|
|
-THREE.Gyroscope.prototype.scaleWorld = new THREE.Vector3();
|
|
|
|
-THREE.Gyroscope.prototype.scaleObject = new THREE.Vector3();
|
|
|
|
-
|
|
|
|
-/**
|
|
|
|
- * @author zz85 / http://www.lab4games.net/zz85/blog
|
|
|
|
- * Creates free form 2d path using series of points, lines or curves.
|
|
|
|
- *
|
|
|
|
- **/
|
|
|
|
|
|
+ tx = aX + aRadius * Math.cos( angle );
|
|
|
|
+ ty = aY + aRadius * Math.sin( angle );
|
|
|
|
|
|
-THREE.Path = function ( points ) {
|
|
|
|
|
|
+ //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
|
|
|
|
|
- THREE.CurvePath.call(this);
|
|
|
|
|
|
+ points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
- this.actions = [];
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- if ( points ) {
|
|
|
|
|
|
+ //console.log(points);
|
|
|
|
|
|
- this.fromPoints( points );
|
|
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ case THREE.PathActions.ELLIPSE:
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var aX = args[ 0 ], aY = args[ 1 ],
|
|
|
|
+ xRadius = args[ 2 ],
|
|
|
|
+ yRadius = args[ 3 ],
|
|
|
|
+ aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
|
|
|
|
+ aClockwise = !!args[ 6 ];
|
|
|
|
|
|
-};
|
|
|
|
|
|
|
|
-THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
|
|
|
|
|
|
+ var deltaAngle = aEndAngle - aStartAngle;
|
|
|
|
+ var angle;
|
|
|
|
+ var tdivisions = divisions * 2;
|
|
|
|
|
|
-THREE.PathActions = {
|
|
|
|
|
|
+ for ( j = 1; j <= tdivisions; j ++ ) {
|
|
|
|
|
|
- MOVE_TO: 'moveTo',
|
|
|
|
- LINE_TO: 'lineTo',
|
|
|
|
- QUADRATIC_CURVE_TO: 'quadraticCurveTo', // Bezier quadratic curve
|
|
|
|
- BEZIER_CURVE_TO: 'bezierCurveTo', // Bezier cubic curve
|
|
|
|
- CSPLINE_THRU: 'splineThru', // Catmull-rom spline
|
|
|
|
- ARC: 'arc', // Circle
|
|
|
|
- ELLIPSE: 'ellipse'
|
|
|
|
-};
|
|
|
|
|
|
+ t = j / tdivisions;
|
|
|
|
|
|
-// TODO Clean up PATH API
|
|
|
|
|
|
+ if ( ! aClockwise ) {
|
|
|
|
|
|
-// Create path using straight lines to connect all points
|
|
|
|
-// - vectors: array of Vector2
|
|
|
|
|
|
+ t = 1 - t;
|
|
|
|
|
|
-THREE.Path.prototype.fromPoints = function ( vectors ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
|
|
|
|
|
|
+ angle = aStartAngle + t * deltaAngle;
|
|
|
|
|
|
- for ( var v = 1, vlen = vectors.length; v < vlen; v ++ ) {
|
|
|
|
|
|
+ tx = aX + xRadius * Math.cos( angle );
|
|
|
|
+ ty = aY + yRadius * Math.sin( angle );
|
|
|
|
|
|
- this.lineTo( vectors[ v ].x, vectors[ v ].y );
|
|
|
|
|
|
+ //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
|
|
|
|
|
- };
|
|
|
|
|
|
+ points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-// startPath() endPath()?
|
|
|
|
|
|
+ //console.log(points);
|
|
|
|
|
|
-THREE.Path.prototype.moveTo = function ( x, y ) {
|
|
|
|
|
|
+ break;
|
|
|
|
|
|
- var args = Array.prototype.slice.call( arguments );
|
|
|
|
- this.actions.push( { action: THREE.PathActions.MOVE_TO, args: args } );
|
|
|
|
|
|
+ } // end switch
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-THREE.Path.prototype.lineTo = function ( x, y ) {
|
|
|
|
|
|
|
|
- var args = Array.prototype.slice.call( arguments );
|
|
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
+ // Normalize to remove the closing point by default.
|
|
|
|
+ var lastPoint = points[ points.length - 1];
|
|
|
|
+ var EPSILON = 0.0000000001;
|
|
|
|
+ if ( Math.abs(lastPoint.x - points[ 0 ].x) < EPSILON &&
|
|
|
|
+ Math.abs(lastPoint.y - points[ 0 ].y) < EPSILON)
|
|
|
|
+ points.splice( points.length - 1, 1);
|
|
|
|
+ if ( closedPath ) {
|
|
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
+ points.push( points[ 0 ] );
|
|
|
|
|
|
- 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 } );
|
|
|
|
|
|
+ return points;
|
|
|
|
|
|
};
|
|
};
|
|
|
|
|
|
-THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
|
|
|
|
|
|
+// Breaks path into shapes
|
|
|
|
|
|
- var args = Array.prototype.slice.call( arguments );
|
|
|
|
|
|
+THREE.Path.prototype.toShapes = function() {
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
+ var i, il, item, action, args;
|
|
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
+ var subPaths = [], lastPath = new THREE.Path();
|
|
|
|
|
|
- var curve = new THREE.QuadraticBezierCurve( new THREE.Vector2( x0, y0 ),
|
|
|
|
- new THREE.Vector2( aCPx, aCPy ),
|
|
|
|
- new THREE.Vector2( aX, aY ) );
|
|
|
|
- this.curves.push( curve );
|
|
|
|
|
|
+ for ( i = 0, il = this.actions.length; i < il; i ++ ) {
|
|
|
|
|
|
- this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args } );
|
|
|
|
|
|
+ item = this.actions[ i ];
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ args = item.args;
|
|
|
|
+ action = item.action;
|
|
|
|
|
|
-THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y,
|
|
|
|
- aCP2x, aCP2y,
|
|
|
|
- aX, aY ) {
|
|
|
|
|
|
+ if ( action == THREE.PathActions.MOVE_TO ) {
|
|
|
|
|
|
- var args = Array.prototype.slice.call( arguments );
|
|
|
|
|
|
+ if ( lastPath.actions.length != 0 ) {
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
+ subPaths.push( lastPath );
|
|
|
|
+ lastPath = new THREE.Path();
|
|
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- 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 } );
|
|
|
|
|
|
+ lastPath[ action ].apply( lastPath, args );
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
|
|
|
|
|
|
+ if ( lastPath.actions.length != 0 ) {
|
|
|
|
|
|
- var args = Array.prototype.slice.call( arguments );
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1 ].args;
|
|
|
|
|
|
+ subPaths.push( lastPath );
|
|
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
-//---
|
|
|
|
- var npts = [ new THREE.Vector2( x0, y0 ) ];
|
|
|
|
- Array.prototype.push.apply( npts, pts );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var curve = new THREE.SplineCurve( npts );
|
|
|
|
- this.curves.push( curve );
|
|
|
|
|
|
+ // console.log(subPaths);
|
|
|
|
|
|
- this.actions.push( { action: THREE.PathActions.CSPLINE_THRU, args: args } );
|
|
|
|
|
|
+ if ( subPaths.length == 0 ) return [];
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ var tmpPath, tmpShape, shapes = [];
|
|
|
|
|
|
-// FUTURE: Change the API or follow canvas API?
|
|
|
|
|
|
+ var holesFirst = !THREE.Shape.Utils.isClockWise( subPaths[ 0 ].getPoints() );
|
|
|
|
+ // console.log("Holes first", holesFirst);
|
|
|
|
|
|
-THREE.Path.prototype.arc = function ( aX, aY, aRadius,
|
|
|
|
- aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
+ if ( subPaths.length == 1) {
|
|
|
|
+ tmpPath = subPaths[0];
|
|
|
|
+ tmpShape = new THREE.Shape();
|
|
|
|
+ tmpShape.actions = tmpPath.actions;
|
|
|
|
+ tmpShape.curves = tmpPath.curves;
|
|
|
|
+ shapes.push( tmpShape );
|
|
|
|
+ return shapes;
|
|
|
|
+ };
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1].args;
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
+ if ( holesFirst ) {
|
|
|
|
|
|
- this.absarc(aX + x0, aY + y0, aRadius,
|
|
|
|
- aStartAngle, aEndAngle, aClockwise );
|
|
|
|
-
|
|
|
|
- };
|
|
|
|
|
|
+ tmpShape = new THREE.Shape();
|
|
|
|
|
|
- THREE.Path.prototype.absarc = function ( aX, aY, aRadius,
|
|
|
|
- aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
- this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
-THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius,
|
|
|
|
- aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
+ for ( i = 0, il = subPaths.length; i < il; i ++ ) {
|
|
|
|
|
|
- var lastargs = this.actions[ this.actions.length - 1].args;
|
|
|
|
- var x0 = lastargs[ lastargs.length - 2 ];
|
|
|
|
- var y0 = lastargs[ lastargs.length - 1 ];
|
|
|
|
|
|
+ tmpPath = subPaths[ i ];
|
|
|
|
|
|
- this.absellipse(aX + x0, aY + y0, xRadius, yRadius,
|
|
|
|
- aStartAngle, aEndAngle, aClockwise );
|
|
|
|
|
|
+ if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
|
|
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
|
|
+ tmpShape.actions = tmpPath.actions;
|
|
|
|
+ tmpShape.curves = tmpPath.curves;
|
|
|
|
|
|
-THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius,
|
|
|
|
- aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
+ shapes.push( tmpShape );
|
|
|
|
+ tmpShape = new THREE.Shape();
|
|
|
|
|
|
- var args = Array.prototype.slice.call( arguments );
|
|
|
|
- var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius,
|
|
|
|
- aStartAngle, aEndAngle, aClockwise );
|
|
|
|
- this.curves.push( curve );
|
|
|
|
|
|
+ //console.log('cw', i);
|
|
|
|
|
|
- var lastPoint = curve.getPoint(aClockwise ? 1 : 0);
|
|
|
|
- args.push(lastPoint.x);
|
|
|
|
- args.push(lastPoint.y);
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- this.actions.push( { action: THREE.PathActions.ELLIPSE, args: args } );
|
|
|
|
|
|
+ tmpShape.holes.push( tmpPath );
|
|
|
|
|
|
- };
|
|
|
|
|
|
+ //console.log('ccw', i);
|
|
|
|
|
|
-THREE.Path.prototype.getSpacedPoints = function ( divisions, closedPath ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- if ( ! divisions ) divisions = 40;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var points = [];
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- for ( var i = 0; i < divisions; i ++ ) {
|
|
|
|
|
|
+ // Shapes first
|
|
|
|
|
|
- points.push( this.getPoint( i / divisions ) );
|
|
|
|
|
|
+ for ( i = 0, il = subPaths.length; i < il; i ++ ) {
|
|
|
|
|
|
- //if( !this.getPoint( i / divisions ) ) throw "DIE";
|
|
|
|
|
|
+ tmpPath = subPaths[ i ];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
|
|
|
|
|
|
- // if ( closedPath ) {
|
|
|
|
- //
|
|
|
|
- // points.push( points[ 0 ] );
|
|
|
|
- //
|
|
|
|
- // }
|
|
|
|
|
|
|
|
- return points;
|
|
|
|
|
|
+ if ( tmpShape ) shapes.push( tmpShape );
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ tmpShape = new THREE.Shape();
|
|
|
|
+ tmpShape.actions = tmpPath.actions;
|
|
|
|
+ tmpShape.curves = tmpPath.curves;
|
|
|
|
|
|
-/* Return an array of vectors based on contour of the path */
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
-THREE.Path.prototype.getPoints = function( divisions, closedPath ) {
|
|
|
|
|
|
+ tmpShape.holes.push( tmpPath );
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ shapes.push( tmpShape );
|
|
|
|
|
|
- if (this.useSpacedPoints) {
|
|
|
|
- console.log('tata');
|
|
|
|
- return this.getSpacedPoints( divisions, closedPath );
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- divisions = divisions || 12;
|
|
|
|
|
|
+ //console.log("shape", shapes);
|
|
|
|
|
|
- var points = [];
|
|
|
|
|
|
+ return shapes;
|
|
|
|
|
|
- var i, il, item, action, args;
|
|
|
|
- var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
|
|
|
|
- laste, j,
|
|
|
|
- t, tx, ty;
|
|
|
|
|
|
+};
|
|
|
|
+/**
|
|
|
|
+ * @author zz85 / http://www.lab4games.net/zz85/blog
|
|
|
|
+ * Defines a 2d shape plane using paths.
|
|
|
|
+ **/
|
|
|
|
|
|
- for ( i = 0, il = this.actions.length; i < il; i ++ ) {
|
|
|
|
|
|
+// STEP 1 Create a path.
|
|
|
|
+// STEP 2 Turn path into shape.
|
|
|
|
+// STEP 3 ExtrudeGeometry takes in Shape/Shapes
|
|
|
|
+// STEP 3a - Extract points from each shape, turn to vertices
|
|
|
|
+// STEP 3b - Triangulate each shape, add faces.
|
|
|
|
|
|
- item = this.actions[ i ];
|
|
|
|
|
|
+THREE.Shape = function () {
|
|
|
|
|
|
- action = item.action;
|
|
|
|
- args = item.args;
|
|
|
|
|
|
+ THREE.Path.apply( this, arguments );
|
|
|
|
+ this.holes = [];
|
|
|
|
|
|
- switch( action ) {
|
|
|
|
|
|
+};
|
|
|
|
|
|
- case THREE.PathActions.MOVE_TO:
|
|
|
|
|
|
+THREE.Shape.prototype = Object.create( THREE.Path.prototype );
|
|
|
|
|
|
- points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
|
|
|
|
|
+// Convenience method to return ExtrudeGeometry
|
|
|
|
|
|
- break;
|
|
|
|
|
|
+THREE.Shape.prototype.extrude = function ( options ) {
|
|
|
|
|
|
- case THREE.PathActions.LINE_TO:
|
|
|
|
|
|
+ var extruded = new THREE.ExtrudeGeometry( this, options );
|
|
|
|
+ return extruded;
|
|
|
|
|
|
- points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
|
|
|
|
|
|
+};
|
|
|
|
|
|
- break;
|
|
|
|
|
|
+// Convenience method to return ShapeGeometry
|
|
|
|
|
|
- case THREE.PathActions.QUADRATIC_CURVE_TO:
|
|
|
|
|
|
+THREE.Shape.prototype.makeGeometry = function ( options ) {
|
|
|
|
|
|
- cpx = args[ 2 ];
|
|
|
|
- cpy = args[ 3 ];
|
|
|
|
|
|
+ var geometry = new THREE.ShapeGeometry( this, options );
|
|
|
|
+ return geometry;
|
|
|
|
|
|
- cpx1 = args[ 0 ];
|
|
|
|
- cpy1 = args[ 1 ];
|
|
|
|
|
|
+};
|
|
|
|
|
|
- if ( points.length > 0 ) {
|
|
|
|
|
|
+// Get points of holes
|
|
|
|
|
|
- laste = points[ points.length - 1 ];
|
|
|
|
|
|
+THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
|
|
|
|
|
|
- cpx0 = laste.x;
|
|
|
|
- cpy0 = laste.y;
|
|
|
|
|
|
+ var i, il = this.holes.length, holesPts = [];
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ for ( i = 0; i < il; i ++ ) {
|
|
|
|
|
|
- laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
+ holesPts[ i ] = this.holes[ i ].getTransformedPoints( divisions, this.bends );
|
|
|
|
|
|
- cpx0 = laste[ laste.length - 2 ];
|
|
|
|
- cpy0 = laste[ laste.length - 1 ];
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ return holesPts;
|
|
|
|
|
|
- for ( j = 1; j <= divisions; j ++ ) {
|
|
|
|
|
|
+};
|
|
|
|
|
|
- t = j / divisions;
|
|
|
|
|
|
+// Get points of holes (spaced by regular distance)
|
|
|
|
|
|
- tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
|
|
|
|
- ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
|
|
|
|
|
|
+THREE.Shape.prototype.getSpacedPointsHoles = function ( divisions ) {
|
|
|
|
|
|
- points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
+ var i, il = this.holes.length, holesPts = [];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ for ( i = 0; i < il; i ++ ) {
|
|
|
|
|
|
- break;
|
|
|
|
|
|
+ holesPts[ i ] = this.holes[ i ].getTransformedSpacedPoints( divisions, this.bends );
|
|
|
|
|
|
- case THREE.PathActions.BEZIER_CURVE_TO:
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- cpx = args[ 4 ];
|
|
|
|
- cpy = args[ 5 ];
|
|
|
|
|
|
+ return holesPts;
|
|
|
|
|
|
- cpx1 = args[ 0 ];
|
|
|
|
- cpy1 = args[ 1 ];
|
|
|
|
|
|
+};
|
|
|
|
|
|
- cpx2 = args[ 2 ];
|
|
|
|
- cpy2 = args[ 3 ];
|
|
|
|
|
|
|
|
- if ( points.length > 0 ) {
|
|
|
|
|
|
+// Get points of shape and holes (keypoints based on segments parameter)
|
|
|
|
|
|
- laste = points[ points.length - 1 ];
|
|
|
|
|
|
+THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
|
|
|
|
|
|
- cpx0 = laste.x;
|
|
|
|
- cpy0 = laste.y;
|
|
|
|
|
|
+ return {
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ shape: this.getTransformedPoints( divisions ),
|
|
|
|
+ holes: this.getPointsHoles( divisions )
|
|
|
|
|
|
- laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
+ };
|
|
|
|
|
|
- cpx0 = laste[ laste.length - 2 ];
|
|
|
|
- cpy0 = laste[ laste.length - 1 ];
|
|
|
|
|
|
+};
|
|
|
|
|
|
- }
|
|
|
|
|
|
+THREE.Shape.prototype.extractPoints = function ( divisions ) {
|
|
|
|
|
|
|
|
+ if (this.useSpacedPoints) {
|
|
|
|
+ return this.extractAllSpacedPoints(divisions);
|
|
|
|
+ }
|
|
|
|
|
|
- for ( j = 1; j <= divisions; j ++ ) {
|
|
|
|
|
|
+ return this.extractAllPoints(divisions);
|
|
|
|
|
|
- t = j / divisions;
|
|
|
|
|
|
+};
|
|
|
|
|
|
- tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
|
|
|
|
- ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
|
|
|
|
|
|
+//
|
|
|
|
+// THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) {
|
|
|
|
+//
|
|
|
|
+// return {
|
|
|
|
+//
|
|
|
|
+// shape: this.transform( bend, divisions ),
|
|
|
|
+// holes: this.getPointsHoles( divisions, bend )
|
|
|
|
+//
|
|
|
|
+// };
|
|
|
|
+//
|
|
|
|
+// };
|
|
|
|
|
|
- points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
+// Get points of shape and holes (spaced by regular distance)
|
|
|
|
|
|
- }
|
|
|
|
|
|
+THREE.Shape.prototype.extractAllSpacedPoints = function ( divisions ) {
|
|
|
|
|
|
- break;
|
|
|
|
|
|
+ return {
|
|
|
|
|
|
- case THREE.PathActions.CSPLINE_THRU:
|
|
|
|
|
|
+ shape: this.getTransformedSpacedPoints( divisions ),
|
|
|
|
+ holes: this.getSpacedPointsHoles( divisions )
|
|
|
|
|
|
- laste = this.actions[ i - 1 ].args;
|
|
|
|
|
|
+ };
|
|
|
|
|
|
- var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
|
|
|
|
- var spts = [ last ];
|
|
|
|
|
|
+};
|
|
|
|
|
|
- var n = divisions * args[ 0 ].length;
|
|
|
|
|
|
+/**************************************************************
|
|
|
|
+ * Utils
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- spts = spts.concat( args[ 0 ] );
|
|
|
|
|
|
+THREE.Shape.Utils = {
|
|
|
|
|
|
- var spline = new THREE.SplineCurve( spts );
|
|
|
|
|
|
+ /*
|
|
|
|
+ contour - array of vector2 for contour
|
|
|
|
+ holes - array of array of vector2
|
|
|
|
+ */
|
|
|
|
|
|
- for ( j = 1; j <= n; j ++ ) {
|
|
|
|
|
|
+ removeHoles: function ( contour, holes ) {
|
|
|
|
|
|
- points.push( spline.getPointAt( j / n ) ) ;
|
|
|
|
|
|
+ var shape = contour.concat(); // work on this shape
|
|
|
|
+ var allpoints = shape.concat();
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ /* For each isolated shape, find the closest points and break to the hole to allow triangulation */
|
|
|
|
|
|
- break;
|
|
|
|
|
|
|
|
- case THREE.PathActions.ARC:
|
|
|
|
|
|
+ var prevShapeVert, nextShapeVert,
|
|
|
|
+ prevHoleVert, nextHoleVert,
|
|
|
|
+ holeIndex, shapeIndex,
|
|
|
|
+ shapeId, shapeGroup,
|
|
|
|
+ h, h2,
|
|
|
|
+ hole, shortest, d,
|
|
|
|
+ p, pts1, pts2,
|
|
|
|
+ tmpShape1, tmpShape2,
|
|
|
|
+ tmpHole1, tmpHole2,
|
|
|
|
+ verts = [];
|
|
|
|
|
|
- var aX = args[ 0 ], aY = args[ 1 ],
|
|
|
|
- aRadius = args[ 2 ],
|
|
|
|
- aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
|
|
|
|
- aClockwise = !!args[ 5 ];
|
|
|
|
|
|
+ for ( h = 0; h < holes.length; h ++ ) {
|
|
|
|
|
|
- var deltaAngle = aEndAngle - aStartAngle;
|
|
|
|
- var angle;
|
|
|
|
- var tdivisions = divisions * 2;
|
|
|
|
|
|
+ hole = holes[ h ];
|
|
|
|
|
|
- for ( j = 1; j <= tdivisions; j ++ ) {
|
|
|
|
|
|
+ /*
|
|
|
|
+ shapeholes[ h ].concat(); // preserves original
|
|
|
|
+ holes.push( hole );
|
|
|
|
+ */
|
|
|
|
|
|
- t = j / tdivisions;
|
|
|
|
|
|
+ Array.prototype.push.apply( allpoints, hole );
|
|
|
|
|
|
- if ( ! aClockwise ) {
|
|
|
|
|
|
+ shortest = Number.POSITIVE_INFINITY;
|
|
|
|
|
|
- t = 1 - t;
|
|
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ // Find the shortest pair of pts between shape and hole
|
|
|
|
|
|
- angle = aStartAngle + t * deltaAngle;
|
|
|
|
|
|
+ // 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.
|
|
|
|
|
|
- tx = aX + aRadius * Math.cos( angle );
|
|
|
|
- ty = aY + aRadius * Math.sin( angle );
|
|
|
|
|
|
+ for ( h2 = 0; h2 < hole.length; h2 ++ ) {
|
|
|
|
|
|
- //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
|
|
|
|
|
+ pts1 = hole[ h2 ];
|
|
|
|
+ var dist = [];
|
|
|
|
|
|
- points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
+ for ( p = 0; p < shape.length; p++ ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ pts2 = shape[ p ];
|
|
|
|
+ d = pts1.distanceToSquared( pts2 );
|
|
|
|
+ dist.push( d );
|
|
|
|
|
|
- //console.log(points);
|
|
|
|
|
|
+ if ( d < shortest ) {
|
|
|
|
|
|
- break;
|
|
|
|
-
|
|
|
|
- case THREE.PathActions.ELLIPSE:
|
|
|
|
|
|
+ shortest = d;
|
|
|
|
+ holeIndex = h2;
|
|
|
|
+ shapeIndex = p;
|
|
|
|
|
|
- var aX = args[ 0 ], aY = args[ 1 ],
|
|
|
|
- xRadius = args[ 2 ],
|
|
|
|
- yRadius = args[ 3 ],
|
|
|
|
- aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
|
|
|
|
- aClockwise = !!args[ 6 ];
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var deltaAngle = aEndAngle - aStartAngle;
|
|
|
|
- var angle;
|
|
|
|
- var tdivisions = divisions * 2;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- for ( j = 1; j <= tdivisions; j ++ ) {
|
|
|
|
|
|
+ //console.log("shortest", shortest, dist);
|
|
|
|
|
|
- t = j / tdivisions;
|
|
|
|
|
|
+ prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
|
|
|
|
+ prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
|
|
|
|
|
|
- if ( ! aClockwise ) {
|
|
|
|
|
|
+ var areaapts = [
|
|
|
|
|
|
- t = 1 - t;
|
|
|
|
|
|
+ hole[ holeIndex ],
|
|
|
|
+ shape[ shapeIndex ],
|
|
|
|
+ shape[ prevShapeVert ]
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ ];
|
|
|
|
|
|
- angle = aStartAngle + t * deltaAngle;
|
|
|
|
|
|
+ var areaa = THREE.FontUtils.Triangulate.area( areaapts );
|
|
|
|
|
|
- tx = aX + xRadius * Math.cos( angle );
|
|
|
|
- ty = aY + yRadius * Math.sin( angle );
|
|
|
|
|
|
+ var areabpts = [
|
|
|
|
|
|
- //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
|
|
|
|
|
|
+ hole[ holeIndex ],
|
|
|
|
+ hole[ prevHoleVert ],
|
|
|
|
+ shape[ shapeIndex ]
|
|
|
|
|
|
- points.push( new THREE.Vector2( tx, ty ) );
|
|
|
|
|
|
+ ];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var areab = THREE.FontUtils.Triangulate.area( areabpts );
|
|
|
|
|
|
- //console.log(points);
|
|
|
|
|
|
+ var shapeOffset = 1;
|
|
|
|
+ var holeOffset = -1;
|
|
|
|
|
|
- break;
|
|
|
|
|
|
+ var oldShapeIndex = shapeIndex, oldHoleIndex = holeIndex;
|
|
|
|
+ shapeIndex += shapeOffset;
|
|
|
|
+ holeIndex += holeOffset;
|
|
|
|
|
|
- } // end switch
|
|
|
|
|
|
+ if ( shapeIndex < 0 ) { shapeIndex += shape.length; }
|
|
|
|
+ shapeIndex %= shape.length;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ if ( holeIndex < 0 ) { holeIndex += hole.length; }
|
|
|
|
+ holeIndex %= hole.length;
|
|
|
|
|
|
|
|
+ prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
|
|
|
|
+ prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
|
|
|
|
|
|
|
|
+ areaapts = [
|
|
|
|
|
|
- // Normalize to remove the closing point by default.
|
|
|
|
- var lastPoint = points[ points.length - 1];
|
|
|
|
- var EPSILON = 0.0000000001;
|
|
|
|
- if ( Math.abs(lastPoint.x - points[ 0 ].x) < EPSILON &&
|
|
|
|
- Math.abs(lastPoint.y - points[ 0 ].y) < EPSILON)
|
|
|
|
- points.splice( points.length - 1, 1);
|
|
|
|
- if ( closedPath ) {
|
|
|
|
|
|
+ hole[ holeIndex ],
|
|
|
|
+ shape[ shapeIndex ],
|
|
|
|
+ shape[ prevShapeVert ]
|
|
|
|
|
|
- points.push( points[ 0 ] );
|
|
|
|
|
|
+ ];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var areaa2 = THREE.FontUtils.Triangulate.area( areaapts );
|
|
|
|
|
|
- return points;
|
|
|
|
|
|
+ areabpts = [
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ hole[ holeIndex ],
|
|
|
|
+ hole[ prevHoleVert ],
|
|
|
|
+ shape[ shapeIndex ]
|
|
|
|
|
|
-// Breaks path into shapes
|
|
|
|
|
|
+ ];
|
|
|
|
|
|
-THREE.Path.prototype.toShapes = function() {
|
|
|
|
|
|
+ var areab2 = THREE.FontUtils.Triangulate.area( areabpts );
|
|
|
|
+ //console.log(areaa,areab ,areaa2,areab2, ( areaa + areab ), ( areaa2 + areab2 ));
|
|
|
|
|
|
- var i, il, item, action, args;
|
|
|
|
|
|
+ if ( ( areaa + areab ) > ( areaa2 + areab2 ) ) {
|
|
|
|
|
|
- var subPaths = [], lastPath = new THREE.Path();
|
|
|
|
|
|
+ // In case areas are not correct.
|
|
|
|
+ //console.log("USE THIS");
|
|
|
|
|
|
- for ( i = 0, il = this.actions.length; i < il; i ++ ) {
|
|
|
|
|
|
+ shapeIndex = oldShapeIndex;
|
|
|
|
+ holeIndex = oldHoleIndex ;
|
|
|
|
|
|
- item = this.actions[ i ];
|
|
|
|
|
|
+ if ( shapeIndex < 0 ) { shapeIndex += shape.length; }
|
|
|
|
+ shapeIndex %= shape.length;
|
|
|
|
|
|
- args = item.args;
|
|
|
|
- action = item.action;
|
|
|
|
|
|
+ if ( holeIndex < 0 ) { holeIndex += hole.length; }
|
|
|
|
+ holeIndex %= hole.length;
|
|
|
|
|
|
- if ( action == THREE.PathActions.MOVE_TO ) {
|
|
|
|
|
|
+ prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
|
|
|
|
+ prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
|
|
|
|
|
|
- if ( lastPath.actions.length != 0 ) {
|
|
|
|
|
|
+ } else {
|
|
|
|
|
|
- subPaths.push( lastPath );
|
|
|
|
- lastPath = new THREE.Path();
|
|
|
|
|
|
+ //console.log("USE THAT ")
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ tmpShape1 = shape.slice( 0, shapeIndex );
|
|
|
|
+ tmpShape2 = shape.slice( shapeIndex );
|
|
|
|
+ tmpHole1 = hole.slice( holeIndex );
|
|
|
|
+ tmpHole2 = hole.slice( 0, holeIndex );
|
|
|
|
|
|
- lastPath[ action ].apply( lastPath, args );
|
|
|
|
|
|
+ // Should check orders here again?
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var trianglea = [
|
|
|
|
|
|
- if ( lastPath.actions.length != 0 ) {
|
|
|
|
|
|
+ hole[ holeIndex ],
|
|
|
|
+ shape[ shapeIndex ],
|
|
|
|
+ shape[ prevShapeVert ]
|
|
|
|
|
|
- subPaths.push( lastPath );
|
|
|
|
|
|
+ ];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var triangleb = [
|
|
|
|
|
|
- // console.log(subPaths);
|
|
|
|
|
|
+ hole[ holeIndex ] ,
|
|
|
|
+ hole[ prevHoleVert ],
|
|
|
|
+ shape[ shapeIndex ]
|
|
|
|
|
|
- if ( subPaths.length == 0 ) return [];
|
|
|
|
|
|
+ ];
|
|
|
|
|
|
- var tmpPath, tmpShape, shapes = [];
|
|
|
|
|
|
+ verts.push( trianglea );
|
|
|
|
+ verts.push( triangleb );
|
|
|
|
|
|
- var holesFirst = !THREE.Shape.Utils.isClockWise( subPaths[ 0 ].getPoints() );
|
|
|
|
- // console.log("Holes first", holesFirst);
|
|
|
|
|
|
+ shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
|
|
|
|
|
|
- if ( subPaths.length == 1) {
|
|
|
|
- tmpPath = subPaths[0];
|
|
|
|
- tmpShape = new THREE.Shape();
|
|
|
|
- tmpShape.actions = tmpPath.actions;
|
|
|
|
- tmpShape.curves = tmpPath.curves;
|
|
|
|
- shapes.push( tmpShape );
|
|
|
|
- return shapes;
|
|
|
|
- };
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- if ( holesFirst ) {
|
|
|
|
|
|
+ return {
|
|
|
|
|
|
- tmpShape = new THREE.Shape();
|
|
|
|
|
|
+ shape:shape, /* shape with no holes */
|
|
|
|
+ isolatedPts: verts, /* isolated faces */
|
|
|
|
+ allpoints: allpoints
|
|
|
|
|
|
- for ( i = 0, il = subPaths.length; i < il; i ++ ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- tmpPath = subPaths[ i ];
|
|
|
|
|
|
|
|
- if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- tmpShape.actions = tmpPath.actions;
|
|
|
|
- tmpShape.curves = tmpPath.curves;
|
|
|
|
|
|
+ triangulateShape: function ( contour, holes ) {
|
|
|
|
|
|
- shapes.push( tmpShape );
|
|
|
|
- tmpShape = new THREE.Shape();
|
|
|
|
|
|
+ var shapeWithoutHoles = THREE.Shape.Utils.removeHoles( contour, holes );
|
|
|
|
|
|
- //console.log('cw', i);
|
|
|
|
|
|
+ var shape = shapeWithoutHoles.shape,
|
|
|
|
+ allpoints = shapeWithoutHoles.allpoints,
|
|
|
|
+ isolatedPts = shapeWithoutHoles.isolatedPts;
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ var triangles = THREE.FontUtils.Triangulate( shape, false ); // True returns indices for points of spooled shape
|
|
|
|
|
|
- tmpShape.holes.push( tmpPath );
|
|
|
|
|
|
+ // To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first.
|
|
|
|
|
|
- //console.log('ccw', i);
|
|
|
|
|
|
+ //console.log( "triangles",triangles, triangles.length );
|
|
|
|
+ //console.log( "allpoints",allpoints, allpoints.length );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var i, il, f, face,
|
|
|
|
+ key, index,
|
|
|
|
+ allPointsMap = {},
|
|
|
|
+ isolatedPointsMap = {};
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ // prepare all points map
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ for ( i = 0, il = allpoints.length; i < il; i ++ ) {
|
|
|
|
|
|
- // Shapes first
|
|
|
|
|
|
+ key = allpoints[ i ].x + ":" + allpoints[ i ].y;
|
|
|
|
|
|
- for ( i = 0, il = subPaths.length; i < il; i ++ ) {
|
|
|
|
|
|
+ if ( allPointsMap[ key ] !== undefined ) {
|
|
|
|
|
|
- tmpPath = subPaths[ i ];
|
|
|
|
|
|
+ console.log( "Duplicate point", key );
|
|
|
|
|
|
- if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
+ allPointsMap[ key ] = i;
|
|
|
|
|
|
- if ( tmpShape ) shapes.push( tmpShape );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- tmpShape = new THREE.Shape();
|
|
|
|
- tmpShape.actions = tmpPath.actions;
|
|
|
|
- tmpShape.curves = tmpPath.curves;
|
|
|
|
|
|
+ // check all face vertices against all points map
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ for ( i = 0, il = triangles.length; i < il; i ++ ) {
|
|
|
|
|
|
- tmpShape.holes.push( tmpPath );
|
|
|
|
|
|
+ face = triangles[ i ];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ for ( f = 0; f < 3; f ++ ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ key = face[ f ].x + ":" + face[ f ].y;
|
|
|
|
|
|
- shapes.push( tmpShape );
|
|
|
|
|
|
+ index = allPointsMap[ key ];
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ if ( index !== undefined ) {
|
|
|
|
|
|
- //console.log("shape", shapes);
|
|
|
|
|
|
+ face[ f ] = index;
|
|
|
|
|
|
- return shapes;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-};
|
|
|
|
-/**
|
|
|
|
- * @author zz85 / http://www.lab4games.net/zz85/blog
|
|
|
|
- * Defines a 2d shape plane using paths.
|
|
|
|
- **/
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-// STEP 1 Create a path.
|
|
|
|
-// STEP 2 Turn path into shape.
|
|
|
|
-// STEP 3 ExtrudeGeometry takes in Shape/Shapes
|
|
|
|
-// STEP 3a - Extract points from each shape, turn to vertices
|
|
|
|
-// STEP 3b - Triangulate each shape, add faces.
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-THREE.Shape = function () {
|
|
|
|
|
|
+ // check isolated points vertices against all points map
|
|
|
|
|
|
- THREE.Path.apply( this, arguments );
|
|
|
|
- this.holes = [];
|
|
|
|
|
|
+ for ( i = 0, il = isolatedPts.length; i < il; i ++ ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ face = isolatedPts[ i ];
|
|
|
|
|
|
-THREE.Shape.prototype = Object.create( THREE.Path.prototype );
|
|
|
|
|
|
+ for ( f = 0; f < 3; f ++ ) {
|
|
|
|
|
|
-// Convenience method to return ExtrudeGeometry
|
|
|
|
|
|
+ key = face[ f ].x + ":" + face[ f ].y;
|
|
|
|
|
|
-THREE.Shape.prototype.extrude = function ( options ) {
|
|
|
|
|
|
+ index = allPointsMap[ key ];
|
|
|
|
|
|
- var extruded = new THREE.ExtrudeGeometry( this, options );
|
|
|
|
- return extruded;
|
|
|
|
|
|
+ if ( index !== undefined ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ face[ f ] = index;
|
|
|
|
|
|
-// Convenience method to return ShapeGeometry
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-THREE.Shape.prototype.makeGeometry = function ( options ) {
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- var geometry = new THREE.ShapeGeometry( this, options );
|
|
|
|
- return geometry;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ return triangles.concat( isolatedPts );
|
|
|
|
|
|
-// Get points of holes
|
|
|
|
|
|
+ }, // end triangulate shapes
|
|
|
|
|
|
-THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
|
|
|
|
|
|
+ /*
|
|
|
|
+ triangulate2 : function( pts, holes ) {
|
|
|
|
|
|
- var i, il = this.holes.length, holesPts = [];
|
|
|
|
|
|
+ // For use with Poly2Tri.js
|
|
|
|
|
|
- for ( i = 0; i < il; i ++ ) {
|
|
|
|
|
|
+ var allpts = pts.concat();
|
|
|
|
+ var shape = [];
|
|
|
|
+ for (var p in pts) {
|
|
|
|
+ shape.push(new js.poly2tri.Point(pts[p].x, pts[p].y));
|
|
|
|
+ }
|
|
|
|
|
|
- holesPts[ i ] = this.holes[ i ].getTransformedPoints( divisions, this.bends );
|
|
|
|
|
|
+ var swctx = new js.poly2tri.SweepContext(shape);
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ for (var h in holes) {
|
|
|
|
+ var aHole = holes[h];
|
|
|
|
+ var newHole = []
|
|
|
|
+ for (i in aHole) {
|
|
|
|
+ newHole.push(new js.poly2tri.Point(aHole[i].x, aHole[i].y));
|
|
|
|
+ allpts.push(aHole[i]);
|
|
|
|
+ }
|
|
|
|
+ swctx.AddHole(newHole);
|
|
|
|
+ }
|
|
|
|
|
|
- return holesPts;
|
|
|
|
|
|
+ var find;
|
|
|
|
+ var findIndexForPt = function (pt) {
|
|
|
|
+ find = new THREE.Vector2(pt.x, pt.y);
|
|
|
|
+ var p;
|
|
|
|
+ for (p=0, pl = allpts.length; p<pl; p++) {
|
|
|
|
+ if (allpts[p].equals(find)) return p;
|
|
|
|
+ }
|
|
|
|
+ return -1;
|
|
|
|
+ };
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ // triangulate
|
|
|
|
+ js.poly2tri.sweep.Triangulate(swctx);
|
|
|
|
|
|
-// Get points of holes (spaced by regular distance)
|
|
|
|
|
|
+ var triangles = swctx.GetTriangles();
|
|
|
|
+ var tr ;
|
|
|
|
+ var facesPts = [];
|
|
|
|
+ for (var t in triangles) {
|
|
|
|
+ tr = triangles[t];
|
|
|
|
+ facesPts.push([
|
|
|
|
+ findIndexForPt(tr.GetPoint(0)),
|
|
|
|
+ findIndexForPt(tr.GetPoint(1)),
|
|
|
|
+ findIndexForPt(tr.GetPoint(2))
|
|
|
|
+ ]);
|
|
|
|
+ }
|
|
|
|
|
|
-THREE.Shape.prototype.getSpacedPointsHoles = function ( divisions ) {
|
|
|
|
|
|
|
|
- var i, il = this.holes.length, holesPts = [];
|
|
|
|
|
|
+ // console.log(facesPts);
|
|
|
|
+ // console.log("triangles", triangles.length, triangles);
|
|
|
|
|
|
- for ( i = 0; i < il; i ++ ) {
|
|
|
|
|
|
+ // Returns array of faces with 3 element each
|
|
|
|
+ return facesPts;
|
|
|
|
+ },
|
|
|
|
+*/
|
|
|
|
|
|
- holesPts[ i ] = this.holes[ i ].getTransformedSpacedPoints( divisions, this.bends );
|
|
|
|
|
|
+ isClockWise: function ( pts ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ return THREE.FontUtils.Triangulate.area( pts ) < 0;
|
|
|
|
|
|
- return holesPts;
|
|
|
|
|
|
+ },
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ // Bezier Curves formulas obtained from
|
|
|
|
+ // http://en.wikipedia.org/wiki/B%C3%A9zier_curve
|
|
|
|
|
|
|
|
+ // Quad Bezier Functions
|
|
|
|
|
|
-// Get points of shape and holes (keypoints based on segments parameter)
|
|
|
|
|
|
+ b2p0: function ( t, p ) {
|
|
|
|
|
|
-THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
|
|
|
|
|
|
+ var k = 1 - t;
|
|
|
|
+ return k * k * p;
|
|
|
|
|
|
- return {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- shape: this.getTransformedPoints( divisions ),
|
|
|
|
- holes: this.getPointsHoles( divisions )
|
|
|
|
|
|
+ b2p1: function ( t, p ) {
|
|
|
|
|
|
- };
|
|
|
|
|
|
+ return 2 * ( 1 - t ) * t * p;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ },
|
|
|
|
|
|
-THREE.Shape.prototype.extractPoints = function ( divisions ) {
|
|
|
|
|
|
+ b2p2: function ( t, p ) {
|
|
|
|
|
|
- if (this.useSpacedPoints) {
|
|
|
|
- return this.extractAllSpacedPoints(divisions);
|
|
|
|
- }
|
|
|
|
|
|
+ return t * t * p;
|
|
|
|
|
|
- return this.extractAllPoints(divisions);
|
|
|
|
|
|
+ },
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ b2: function ( t, p0, p1, p2 ) {
|
|
|
|
|
|
-//
|
|
|
|
-// THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) {
|
|
|
|
-//
|
|
|
|
-// return {
|
|
|
|
-//
|
|
|
|
-// shape: this.transform( bend, divisions ),
|
|
|
|
-// holes: this.getPointsHoles( divisions, bend )
|
|
|
|
-//
|
|
|
|
-// };
|
|
|
|
-//
|
|
|
|
-// };
|
|
|
|
|
|
+ return this.b2p0( t, p0 ) + this.b2p1( t, p1 ) + this.b2p2( t, p2 );
|
|
|
|
+
|
|
|
|
+ },
|
|
|
|
|
|
-// Get points of shape and holes (spaced by regular distance)
|
|
|
|
|
|
+ // Cubic Bezier Functions
|
|
|
|
|
|
-THREE.Shape.prototype.extractAllSpacedPoints = function ( divisions ) {
|
|
|
|
|
|
+ b3p0: function ( t, p ) {
|
|
|
|
|
|
- return {
|
|
|
|
|
|
+ var k = 1 - t;
|
|
|
|
+ return k * k * k * p;
|
|
|
|
|
|
- shape: this.getTransformedSpacedPoints( divisions ),
|
|
|
|
- holes: this.getSpacedPointsHoles( divisions )
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- };
|
|
|
|
|
|
+ b3p1: function ( t, p ) {
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ var k = 1 - t;
|
|
|
|
+ return 3 * k * k * t * p;
|
|
|
|
|
|
-/**************************************************************
|
|
|
|
- * Utils
|
|
|
|
- **************************************************************/
|
|
|
|
|
|
+ },
|
|
|
|
|
|
-THREE.Shape.Utils = {
|
|
|
|
|
|
+ b3p2: function ( t, p ) {
|
|
|
|
|
|
- /*
|
|
|
|
- contour - array of vector2 for contour
|
|
|
|
- holes - array of array of vector2
|
|
|
|
- */
|
|
|
|
|
|
+ var k = 1 - t;
|
|
|
|
+ return 3 * k * t * t * p;
|
|
|
|
|
|
- removeHoles: function ( contour, holes ) {
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- var shape = contour.concat(); // work on this shape
|
|
|
|
- var allpoints = shape.concat();
|
|
|
|
|
|
+ b3p3: function ( t, p ) {
|
|
|
|
|
|
- /* For each isolated shape, find the closest points and break to the hole to allow triangulation */
|
|
|
|
|
|
+ return t * t * t * p;
|
|
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- var prevShapeVert, nextShapeVert,
|
|
|
|
- prevHoleVert, nextHoleVert,
|
|
|
|
- holeIndex, shapeIndex,
|
|
|
|
- shapeId, shapeGroup,
|
|
|
|
- h, h2,
|
|
|
|
- hole, shortest, d,
|
|
|
|
- p, pts1, pts2,
|
|
|
|
- tmpShape1, tmpShape2,
|
|
|
|
- tmpHole1, tmpHole2,
|
|
|
|
- verts = [];
|
|
|
|
|
|
+ b3: function ( t, p0, p1, p2, p3 ) {
|
|
|
|
|
|
- for ( h = 0; h < holes.length; h ++ ) {
|
|
|
|
|
|
+ return this.b3p0( t, p0 ) + this.b3p1( t, p1 ) + this.b3p2( t, p2 ) + this.b3p3( t, p3 );
|
|
|
|
|
|
- hole = holes[ h ];
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- /*
|
|
|
|
- shapeholes[ h ].concat(); // preserves original
|
|
|
|
- holes.push( hole );
|
|
|
|
- */
|
|
|
|
|
|
+};
|
|
|
|
|
|
- Array.prototype.push.apply( allpoints, hole );
|
|
|
|
|
|
+/**************************************************************
|
|
|
|
+ * Line
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- shortest = Number.POSITIVE_INFINITY;
|
|
|
|
|
|
+THREE.LineCurve = function ( v1, v2 ) {
|
|
|
|
|
|
|
|
+ this.v1 = v1;
|
|
|
|
+ this.v2 = v2;
|
|
|
|
|
|
- // 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.
|
|
|
|
|
|
+THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
- for ( h2 = 0; h2 < hole.length; h2 ++ ) {
|
|
|
|
|
|
+THREE.LineCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
- pts1 = hole[ h2 ];
|
|
|
|
- var dist = [];
|
|
|
|
|
|
+ var point = this.v2.clone().sub(this.v1);
|
|
|
|
+ point.multiplyScalar( t ).add( this.v1 );
|
|
|
|
|
|
- for ( p = 0; p < shape.length; p++ ) {
|
|
|
|
|
|
+ return point;
|
|
|
|
|
|
- pts2 = shape[ p ];
|
|
|
|
- d = pts1.distanceToSquared( pts2 );
|
|
|
|
- dist.push( d );
|
|
|
|
|
|
+};
|
|
|
|
|
|
- if ( d < shortest ) {
|
|
|
|
|
|
+// Line curve is linear, so we can overwrite default getPointAt
|
|
|
|
|
|
- shortest = d;
|
|
|
|
- holeIndex = h2;
|
|
|
|
- shapeIndex = p;
|
|
|
|
|
|
+THREE.LineCurve.prototype.getPointAt = function ( u ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ return this.getPoint( u );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+};
|
|
|
|
|
|
- }
|
|
|
|
|
|
+THREE.LineCurve.prototype.getTangent = function( t ) {
|
|
|
|
|
|
- //console.log("shortest", shortest, dist);
|
|
|
|
|
|
+ var tangent = this.v2.clone().sub(this.v1);
|
|
|
|
|
|
- prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
|
|
|
|
- prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
|
|
|
|
|
|
+ return tangent.normalize();
|
|
|
|
|
|
- var areaapts = [
|
|
|
|
|
|
+};/**************************************************************
|
|
|
|
+ * Quadratic Bezier curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- hole[ holeIndex ],
|
|
|
|
- shape[ shapeIndex ],
|
|
|
|
- shape[ prevShapeVert ]
|
|
|
|
|
|
|
|
- ];
|
|
|
|
|
|
+THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
|
|
|
|
|
|
- var areaa = THREE.FontUtils.Triangulate.area( areaapts );
|
|
|
|
|
|
+ this.v0 = v0;
|
|
|
|
+ this.v1 = v1;
|
|
|
|
+ this.v2 = v2;
|
|
|
|
|
|
- var areabpts = [
|
|
|
|
|
|
+};
|
|
|
|
|
|
- hole[ holeIndex ],
|
|
|
|
- hole[ prevHoleVert ],
|
|
|
|
- shape[ shapeIndex ]
|
|
|
|
|
|
+THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
- ];
|
|
|
|
|
|
|
|
- var areab = THREE.FontUtils.Triangulate.area( areabpts );
|
|
|
|
|
|
+THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
- var shapeOffset = 1;
|
|
|
|
- var holeOffset = -1;
|
|
|
|
|
|
+ var tx, ty;
|
|
|
|
|
|
- var oldShapeIndex = shapeIndex, oldHoleIndex = holeIndex;
|
|
|
|
- shapeIndex += shapeOffset;
|
|
|
|
- holeIndex += holeOffset;
|
|
|
|
|
|
+ tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
|
|
|
|
+ ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
|
|
|
|
|
|
- if ( shapeIndex < 0 ) { shapeIndex += shape.length; }
|
|
|
|
- shapeIndex %= shape.length;
|
|
|
|
|
|
+ return new THREE.Vector2( tx, ty );
|
|
|
|
|
|
- if ( holeIndex < 0 ) { holeIndex += hole.length; }
|
|
|
|
- holeIndex %= hole.length;
|
|
|
|
|
|
+};
|
|
|
|
|
|
- prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
|
|
|
|
- prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
|
|
|
|
|
|
|
|
- areaapts = [
|
|
|
|
|
|
+THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
|
|
|
|
|
|
- hole[ holeIndex ],
|
|
|
|
- shape[ shapeIndex ],
|
|
|
|
- shape[ prevShapeVert ]
|
|
|
|
|
|
+ var tx, ty;
|
|
|
|
|
|
- ];
|
|
|
|
|
|
+ tx = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x );
|
|
|
|
+ ty = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y );
|
|
|
|
|
|
- var areaa2 = THREE.FontUtils.Triangulate.area( areaapts );
|
|
|
|
|
|
+ // returns unit vector
|
|
|
|
|
|
- areabpts = [
|
|
|
|
|
|
+ var tangent = new THREE.Vector2( tx, ty );
|
|
|
|
+ tangent.normalize();
|
|
|
|
|
|
- hole[ holeIndex ],
|
|
|
|
- hole[ prevHoleVert ],
|
|
|
|
- shape[ shapeIndex ]
|
|
|
|
|
|
+ return tangent;
|
|
|
|
|
|
- ];
|
|
|
|
|
|
+};/**************************************************************
|
|
|
|
+ * Cubic Bezier curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- var areab2 = THREE.FontUtils.Triangulate.area( areabpts );
|
|
|
|
- //console.log(areaa,areab ,areaa2,areab2, ( areaa + areab ), ( areaa2 + areab2 ));
|
|
|
|
|
|
+THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
|
|
|
|
|
|
- if ( ( areaa + areab ) > ( areaa2 + areab2 ) ) {
|
|
|
|
|
|
+ this.v0 = v0;
|
|
|
|
+ this.v1 = v1;
|
|
|
|
+ this.v2 = v2;
|
|
|
|
+ this.v3 = v3;
|
|
|
|
|
|
- // In case areas are not correct.
|
|
|
|
- //console.log("USE THIS");
|
|
|
|
|
|
+};
|
|
|
|
|
|
- shapeIndex = oldShapeIndex;
|
|
|
|
- holeIndex = oldHoleIndex ;
|
|
|
|
|
|
+THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
- if ( shapeIndex < 0 ) { shapeIndex += shape.length; }
|
|
|
|
- shapeIndex %= shape.length;
|
|
|
|
|
|
+THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
- if ( holeIndex < 0 ) { holeIndex += hole.length; }
|
|
|
|
- holeIndex %= hole.length;
|
|
|
|
|
|
+ var tx, ty;
|
|
|
|
|
|
- prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
|
|
|
|
- prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
|
|
|
|
|
|
+ tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
|
|
|
|
+ ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
|
|
|
|
|
|
- } else {
|
|
|
|
|
|
+ return new THREE.Vector2( tx, ty );
|
|
|
|
|
|
- //console.log("USE THAT ")
|
|
|
|
|
|
+};
|
|
|
|
|
|
- }
|
|
|
|
|
|
+THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
|
|
|
|
|
|
- tmpShape1 = shape.slice( 0, shapeIndex );
|
|
|
|
- tmpShape2 = shape.slice( shapeIndex );
|
|
|
|
- tmpHole1 = hole.slice( holeIndex );
|
|
|
|
- tmpHole2 = hole.slice( 0, holeIndex );
|
|
|
|
|
|
+ var tx, ty;
|
|
|
|
|
|
- // Should check orders here again?
|
|
|
|
|
|
+ tx = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
|
|
|
|
+ ty = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
|
|
|
|
|
|
- var trianglea = [
|
|
|
|
|
|
+ var tangent = new THREE.Vector2( tx, ty );
|
|
|
|
+ tangent.normalize();
|
|
|
|
|
|
- hole[ holeIndex ],
|
|
|
|
- shape[ shapeIndex ],
|
|
|
|
- shape[ prevShapeVert ]
|
|
|
|
|
|
+ return tangent;
|
|
|
|
|
|
- ];
|
|
|
|
|
|
+};/**************************************************************
|
|
|
|
+ * Spline curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- var triangleb = [
|
|
|
|
|
|
+THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
|
|
|
|
|
|
- hole[ holeIndex ] ,
|
|
|
|
- hole[ prevHoleVert ],
|
|
|
|
- shape[ shapeIndex ]
|
|
|
|
|
|
+ this.points = (points == undefined) ? [] : points;
|
|
|
|
|
|
- ];
|
|
|
|
|
|
+};
|
|
|
|
|
|
- verts.push( trianglea );
|
|
|
|
- verts.push( triangleb );
|
|
|
|
|
|
+THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
- shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
|
|
|
|
|
|
+THREE.SplineCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var v = new THREE.Vector2();
|
|
|
|
+ var c = [];
|
|
|
|
+ var points = this.points, point, intPoint, weight;
|
|
|
|
+ point = ( points.length - 1 ) * t;
|
|
|
|
|
|
- return {
|
|
|
|
|
|
+ intPoint = Math.floor( point );
|
|
|
|
+ weight = point - intPoint;
|
|
|
|
|
|
- shape:shape, /* shape with no holes */
|
|
|
|
- isolatedPts: verts, /* isolated faces */
|
|
|
|
- allpoints: allpoints
|
|
|
|
|
|
+ c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
|
|
|
|
+ c[ 1 ] = intPoint;
|
|
|
|
+ c[ 2 ] = intPoint > points.length - 2 ? points.length -1 : intPoint + 1;
|
|
|
|
+ c[ 3 ] = intPoint > points.length - 3 ? points.length -1 : intPoint + 2;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
|
|
|
|
+ v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
|
|
|
|
|
|
|
|
+ return v;
|
|
|
|
|
|
- },
|
|
|
|
|
|
+};/**************************************************************
|
|
|
|
+ * Ellipse curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- triangulateShape: function ( contour, holes ) {
|
|
|
|
|
|
+THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius,
|
|
|
|
+ aStartAngle, aEndAngle,
|
|
|
|
+ aClockwise ) {
|
|
|
|
|
|
- var shapeWithoutHoles = THREE.Shape.Utils.removeHoles( contour, holes );
|
|
|
|
|
|
+ this.aX = aX;
|
|
|
|
+ this.aY = aY;
|
|
|
|
|
|
- var shape = shapeWithoutHoles.shape,
|
|
|
|
- allpoints = shapeWithoutHoles.allpoints,
|
|
|
|
- isolatedPts = shapeWithoutHoles.isolatedPts;
|
|
|
|
|
|
+ this.xRadius = xRadius;
|
|
|
|
+ this.yRadius = yRadius;
|
|
|
|
|
|
- var triangles = THREE.FontUtils.Triangulate( shape, false ); // True returns indices for points of spooled shape
|
|
|
|
|
|
+ this.aStartAngle = aStartAngle;
|
|
|
|
+ this.aEndAngle = aEndAngle;
|
|
|
|
|
|
- // To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first.
|
|
|
|
|
|
+ this.aClockwise = aClockwise;
|
|
|
|
|
|
- //console.log( "triangles",triangles, triangles.length );
|
|
|
|
- //console.log( "allpoints",allpoints, allpoints.length );
|
|
|
|
|
|
+};
|
|
|
|
|
|
- var i, il, f, face,
|
|
|
|
- key, index,
|
|
|
|
- allPointsMap = {},
|
|
|
|
- isolatedPointsMap = {};
|
|
|
|
|
|
+THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
|
|
|
|
|
|
- // prepare all points map
|
|
|
|
|
|
+THREE.EllipseCurve.prototype.getPoint = function ( t ) {
|
|
|
|
|
|
- for ( i = 0, il = allpoints.length; i < il; i ++ ) {
|
|
|
|
|
|
+ var deltaAngle = this.aEndAngle - this.aStartAngle;
|
|
|
|
|
|
- key = allpoints[ i ].x + ":" + allpoints[ i ].y;
|
|
|
|
|
|
+ if ( !this.aClockwise ) {
|
|
|
|
|
|
- if ( allPointsMap[ key ] !== undefined ) {
|
|
|
|
|
|
+ t = 1 - t;
|
|
|
|
|
|
- console.log( "Duplicate point", key );
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var angle = this.aStartAngle + t * deltaAngle;
|
|
|
|
|
|
- allPointsMap[ key ] = i;
|
|
|
|
|
|
+ var tx = this.aX + this.xRadius * Math.cos( angle );
|
|
|
|
+ var ty = this.aY + this.yRadius * Math.sin( angle );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ return new THREE.Vector2( tx, ty );
|
|
|
|
|
|
- // check all face vertices against all points map
|
|
|
|
|
|
+};/**************************************************************
|
|
|
|
+ * Arc curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- for ( i = 0, il = triangles.length; i < il; i ++ ) {
|
|
|
|
|
|
+THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
|
|
|
|
|
|
- face = triangles[ i ];
|
|
|
|
|
|
+ THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
|
|
|
|
+};
|
|
|
|
|
|
- for ( f = 0; f < 3; f ++ ) {
|
|
|
|
|
|
+THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );/**************************************************************
|
|
|
|
+ * Line3D
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- key = face[ f ].x + ":" + face[ f ].y;
|
|
|
|
|
|
+THREE.LineCurve3 = THREE.Curve.create(
|
|
|
|
|
|
- index = allPointsMap[ key ];
|
|
|
|
|
|
+ function ( v1, v2 ) {
|
|
|
|
|
|
- if ( index !== undefined ) {
|
|
|
|
|
|
+ this.v1 = v1;
|
|
|
|
+ this.v2 = v2;
|
|
|
|
|
|
- face[ f ] = index;
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ function ( t ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var r = new THREE.Vector3();
|
|
|
|
|
|
- }
|
|
|
|
|
|
|
|
- // check isolated points vertices against all points map
|
|
|
|
|
|
+ r.subVectors( this.v2, this.v1 ); // diff
|
|
|
|
+ r.multiplyScalar( t );
|
|
|
|
+ r.add( this.v1 );
|
|
|
|
|
|
- for ( i = 0, il = isolatedPts.length; i < il; i ++ ) {
|
|
|
|
|
|
+ return r;
|
|
|
|
|
|
- face = isolatedPts[ i ];
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- for ( f = 0; f < 3; f ++ ) {
|
|
|
|
|
|
+);
|
|
|
|
+/**************************************************************
|
|
|
|
+ * Quadratic Bezier 3D curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- key = face[ f ].x + ":" + face[ f ].y;
|
|
|
|
|
|
+THREE.QuadraticBezierCurve3 = THREE.Curve.create(
|
|
|
|
|
|
- index = allPointsMap[ key ];
|
|
|
|
|
|
+ function ( v0, v1, v2 ) {
|
|
|
|
|
|
- if ( index !== undefined ) {
|
|
|
|
|
|
+ this.v0 = v0;
|
|
|
|
+ this.v1 = v1;
|
|
|
|
+ this.v2 = v2;
|
|
|
|
|
|
- face[ f ] = index;
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ function ( t ) {
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ var tx, ty, tz;
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
|
|
|
|
+ ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
|
|
|
|
+ tz = THREE.Shape.Utils.b2( t, this.v0.z, this.v1.z, this.v2.z );
|
|
|
|
|
|
- return triangles.concat( isolatedPts );
|
|
|
|
|
|
+ return new THREE.Vector3( tx, ty, tz );
|
|
|
|
|
|
- }, // end triangulate shapes
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- /*
|
|
|
|
- triangulate2 : function( pts, holes ) {
|
|
|
|
|
|
+);/**************************************************************
|
|
|
|
+ * Cubic Bezier 3D curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- // For use with Poly2Tri.js
|
|
|
|
|
|
+THREE.CubicBezierCurve3 = THREE.Curve.create(
|
|
|
|
|
|
- var allpts = pts.concat();
|
|
|
|
- var shape = [];
|
|
|
|
- for (var p in pts) {
|
|
|
|
- shape.push(new js.poly2tri.Point(pts[p].x, pts[p].y));
|
|
|
|
- }
|
|
|
|
|
|
+ function ( v0, v1, v2, v3 ) {
|
|
|
|
|
|
- var swctx = new js.poly2tri.SweepContext(shape);
|
|
|
|
|
|
+ this.v0 = v0;
|
|
|
|
+ this.v1 = v1;
|
|
|
|
+ this.v2 = v2;
|
|
|
|
+ this.v3 = v3;
|
|
|
|
|
|
- for (var h in holes) {
|
|
|
|
- var aHole = holes[h];
|
|
|
|
- var newHole = []
|
|
|
|
- for (i in aHole) {
|
|
|
|
- newHole.push(new js.poly2tri.Point(aHole[i].x, aHole[i].y));
|
|
|
|
- allpts.push(aHole[i]);
|
|
|
|
- }
|
|
|
|
- swctx.AddHole(newHole);
|
|
|
|
- }
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- var find;
|
|
|
|
- var findIndexForPt = function (pt) {
|
|
|
|
- find = new THREE.Vector2(pt.x, pt.y);
|
|
|
|
- var p;
|
|
|
|
- for (p=0, pl = allpts.length; p<pl; p++) {
|
|
|
|
- if (allpts[p].equals(find)) return p;
|
|
|
|
- }
|
|
|
|
- return -1;
|
|
|
|
- };
|
|
|
|
|
|
+ function ( t ) {
|
|
|
|
|
|
- // triangulate
|
|
|
|
- js.poly2tri.sweep.Triangulate(swctx);
|
|
|
|
|
|
+ var tx, ty, tz;
|
|
|
|
|
|
- var triangles = swctx.GetTriangles();
|
|
|
|
- var tr ;
|
|
|
|
- var facesPts = [];
|
|
|
|
- for (var t in triangles) {
|
|
|
|
- tr = triangles[t];
|
|
|
|
- facesPts.push([
|
|
|
|
- findIndexForPt(tr.GetPoint(0)),
|
|
|
|
- findIndexForPt(tr.GetPoint(1)),
|
|
|
|
- findIndexForPt(tr.GetPoint(2))
|
|
|
|
- ]);
|
|
|
|
- }
|
|
|
|
|
|
+ tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
|
|
|
|
+ ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
|
|
|
|
+ tz = THREE.Shape.Utils.b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z );
|
|
|
|
|
|
|
|
+ return new THREE.Vector3( tx, ty, tz );
|
|
|
|
|
|
- // console.log(facesPts);
|
|
|
|
- // console.log("triangles", triangles.length, triangles);
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- // Returns array of faces with 3 element each
|
|
|
|
- return facesPts;
|
|
|
|
- },
|
|
|
|
-*/
|
|
|
|
|
|
+);/**************************************************************
|
|
|
|
+ * Spline 3D curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- isClockWise: function ( pts ) {
|
|
|
|
|
|
|
|
- return THREE.FontUtils.Triangulate.area( pts ) < 0;
|
|
|
|
|
|
+THREE.SplineCurve3 = THREE.Curve.create(
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ function ( points /* array of Vector3 */) {
|
|
|
|
|
|
- // Bezier Curves formulas obtained from
|
|
|
|
- // http://en.wikipedia.org/wiki/B%C3%A9zier_curve
|
|
|
|
|
|
+ this.points = (points == undefined) ? [] : points;
|
|
|
|
|
|
- // Quad Bezier Functions
|
|
|
|
|
|
+ },
|
|
|
|
|
|
- b2p0: function ( t, p ) {
|
|
|
|
|
|
+ function ( t ) {
|
|
|
|
|
|
- var k = 1 - t;
|
|
|
|
- return k * k * p;
|
|
|
|
|
|
+ var v = new THREE.Vector3();
|
|
|
|
+ var c = [];
|
|
|
|
+ var points = this.points, point, intPoint, weight;
|
|
|
|
+ point = ( points.length - 1 ) * t;
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ intPoint = Math.floor( point );
|
|
|
|
+ weight = point - intPoint;
|
|
|
|
|
|
- b2p1: function ( t, p ) {
|
|
|
|
|
|
+ c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
|
|
|
|
+ c[ 1 ] = intPoint;
|
|
|
|
+ c[ 2 ] = intPoint > points.length - 2 ? points.length - 1 : intPoint + 1;
|
|
|
|
+ c[ 3 ] = intPoint > points.length - 3 ? points.length - 1 : intPoint + 2;
|
|
|
|
|
|
- return 2 * ( 1 - t ) * t * p;
|
|
|
|
|
|
+ var pt0 = points[ c[0] ],
|
|
|
|
+ pt1 = points[ c[1] ],
|
|
|
|
+ pt2 = points[ c[2] ],
|
|
|
|
+ pt3 = points[ c[3] ];
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ v.x = THREE.Curve.Utils.interpolate(pt0.x, pt1.x, pt2.x, pt3.x, weight);
|
|
|
|
+ v.y = THREE.Curve.Utils.interpolate(pt0.y, pt1.y, pt2.y, pt3.y, weight);
|
|
|
|
+ v.z = THREE.Curve.Utils.interpolate(pt0.z, pt1.z, pt2.z, pt3.z, weight);
|
|
|
|
|
|
- b2p2: function ( t, p ) {
|
|
|
|
|
|
+ return v;
|
|
|
|
|
|
- return t * t * p;
|
|
|
|
|
|
+ }
|
|
|
|
|
|
- },
|
|
|
|
|
|
+);
|
|
|
|
|
|
- b2: function ( t, p0, p1, p2 ) {
|
|
|
|
|
|
|
|
- return this.b2p0( t, p0 ) + this.b2p1( t, p1 ) + this.b2p2( t, p2 );
|
|
|
|
|
|
+// THREE.SplineCurve3.prototype.getTangent = function(t) {
|
|
|
|
+// var v = new THREE.Vector3();
|
|
|
|
+// var c = [];
|
|
|
|
+// var points = this.points, point, intPoint, weight;
|
|
|
|
+// point = ( points.length - 1 ) * t;
|
|
|
|
|
|
- },
|
|
|
|
|
|
+// intPoint = Math.floor( point );
|
|
|
|
+// weight = point - intPoint;
|
|
|
|
|
|
- // Cubic Bezier Functions
|
|
|
|
|
|
+// c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
|
|
|
|
+// c[ 1 ] = intPoint;
|
|
|
|
+// c[ 2 ] = intPoint > points.length - 2 ? points.length - 1 : intPoint + 1;
|
|
|
|
+// c[ 3 ] = intPoint > points.length - 3 ? points.length - 1 : intPoint + 2;
|
|
|
|
|
|
- b3p0: function ( t, p ) {
|
|
|
|
|
|
+// var pt0 = points[ c[0] ],
|
|
|
|
+// pt1 = points[ c[1] ],
|
|
|
|
+// pt2 = points[ c[2] ],
|
|
|
|
+// pt3 = points[ c[3] ];
|
|
|
|
|
|
- var k = 1 - t;
|
|
|
|
- return k * k * k * p;
|
|
|
|
|
|
+// // t = weight;
|
|
|
|
+// v.x = THREE.Curve.Utils.tangentSpline( t, pt0.x, pt1.x, pt2.x, pt3.x );
|
|
|
|
+// v.y = THREE.Curve.Utils.tangentSpline( t, pt0.y, pt1.y, pt2.y, pt3.y );
|
|
|
|
+// v.z = THREE.Curve.Utils.tangentSpline( t, pt0.z, pt1.z, pt2.z, pt3.z );
|
|
|
|
|
|
- },
|
|
|
|
|
|
+// return v;
|
|
|
|
|
|
- b3p1: function ( t, p ) {
|
|
|
|
|
|
+// }/**************************************************************
|
|
|
|
+ * Closed Spline 3D curve
|
|
|
|
+ **************************************************************/
|
|
|
|
|
|
- var k = 1 - t;
|
|
|
|
- return 3 * k * k * t * p;
|
|
|
|
|
|
|
|
- },
|
|
|
|
|
|
+THREE.ClosedSplineCurve3 = THREE.Curve.create(
|
|
|
|
|
|
- b3p2: function ( t, p ) {
|
|
|
|
|
|
+ function ( points /* array of Vector3 */) {
|
|
|
|
|
|
- var k = 1 - t;
|
|
|
|
- return 3 * k * t * t * p;
|
|
|
|
|
|
+ this.points = (points == undefined) ? [] : points;
|
|
|
|
|
|
},
|
|
},
|
|
|
|
|
|
- b3p3: function ( t, p ) {
|
|
|
|
|
|
+ function ( t ) {
|
|
|
|
|
|
- return t * t * t * p;
|
|
|
|
|
|
+ var v = new THREE.Vector3();
|
|
|
|
+ var c = [];
|
|
|
|
+ var points = this.points, point, intPoint, weight;
|
|
|
|
+ point = ( points.length - 0 ) * t;
|
|
|
|
+ // This needs to be from 0-length +1
|
|
|
|
|
|
- },
|
|
|
|
|
|
+ intPoint = Math.floor( point );
|
|
|
|
+ weight = point - intPoint;
|
|
|
|
|
|
- b3: function ( t, p0, p1, p2, p3 ) {
|
|
|
|
|
|
+ intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
|
|
|
|
+ c[ 0 ] = ( intPoint - 1 ) % points.length;
|
|
|
|
+ c[ 1 ] = ( intPoint ) % points.length;
|
|
|
|
+ c[ 2 ] = ( intPoint + 1 ) % points.length;
|
|
|
|
+ c[ 3 ] = ( intPoint + 2 ) % points.length;
|
|
|
|
|
|
- return this.b3p0( t, p0 ) + this.b3p1( t, p1 ) + this.b3p2( t, p2 ) + this.b3p3( t, p3 );
|
|
|
|
|
|
+ v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
|
|
|
|
+ v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
|
|
|
|
+ v.z = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].z, points[ c[ 1 ] ].z, points[ c[ 2 ] ].z, points[ c[ 3 ] ].z, weight );
|
|
|
|
|
|
- }
|
|
|
|
|
|
+ return v;
|
|
|
|
|
|
-};
|
|
|
|
|
|
+ }
|
|
|
|
|
|
-/**
|
|
|
|
|
|
+);/**
|
|
* @author mikael emtinger / http://gomo.se/
|
|
* @author mikael emtinger / http://gomo.se/
|
|
*/
|
|
*/
|
|
|
|
|