1 | /**
|
---|
2 | * @author zz85 / http://www.lab4games.net/zz85/blog
|
---|
3 | *
|
---|
4 | **/
|
---|
5 |
|
---|
6 | /**************************************************************
|
---|
7 | * Curved Path - a curve path is simply a array of connected
|
---|
8 | * curves, but retains the api of a curve
|
---|
9 | **************************************************************/
|
---|
10 |
|
---|
11 | THREE.CurvePath = function () {
|
---|
12 |
|
---|
13 | this.curves = [];
|
---|
14 | this.bends = [];
|
---|
15 |
|
---|
16 | this.autoClose = false; // Automatically closes the path
|
---|
17 | };
|
---|
18 |
|
---|
19 | THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
|
---|
20 |
|
---|
21 | THREE.CurvePath.prototype.add = function ( curve ) {
|
---|
22 |
|
---|
23 | this.curves.push( curve );
|
---|
24 |
|
---|
25 | };
|
---|
26 |
|
---|
27 | THREE.CurvePath.prototype.checkConnection = function() {
|
---|
28 | // TODO
|
---|
29 | // If the ending of curve is not connected to the starting
|
---|
30 | // or the next curve, then, this is not a real path
|
---|
31 | };
|
---|
32 |
|
---|
33 | THREE.CurvePath.prototype.closePath = function() {
|
---|
34 | // TODO Test
|
---|
35 | // and verify for vector3 (needs to implement equals)
|
---|
36 | // Add a line curve if start and end of lines are not connected
|
---|
37 | var startPoint = this.curves[0].getPoint(0);
|
---|
38 | var endPoint = this.curves[this.curves.length-1].getPoint(1);
|
---|
39 |
|
---|
40 | if (!startPoint.equals(endPoint)) {
|
---|
41 | this.curves.push( new THREE.LineCurve(endPoint, startPoint) );
|
---|
42 | }
|
---|
43 |
|
---|
44 | };
|
---|
45 |
|
---|
46 | // To get accurate point with reference to
|
---|
47 | // entire path distance at time t,
|
---|
48 | // following has to be done:
|
---|
49 |
|
---|
50 | // 1. Length of each sub path have to be known
|
---|
51 | // 2. Locate and identify type of curve
|
---|
52 | // 3. Get t for the curve
|
---|
53 | // 4. Return curve.getPointAt(t')
|
---|
54 |
|
---|
55 | THREE.CurvePath.prototype.getPoint = function( t ) {
|
---|
56 |
|
---|
57 | var d = t * this.getLength();
|
---|
58 | var curveLengths = this.getCurveLengths();
|
---|
59 | var i = 0, diff, curve;
|
---|
60 |
|
---|
61 | // To think about boundaries points.
|
---|
62 |
|
---|
63 | while ( i < curveLengths.length ) {
|
---|
64 |
|
---|
65 | if ( curveLengths[ i ] >= d ) {
|
---|
66 |
|
---|
67 | diff = curveLengths[ i ] - d;
|
---|
68 | curve = this.curves[ i ];
|
---|
69 |
|
---|
70 | var u = 1 - diff / curve.getLength();
|
---|
71 |
|
---|
72 | return curve.getPointAt( u );
|
---|
73 |
|
---|
74 | break;
|
---|
75 | }
|
---|
76 |
|
---|
77 | i ++;
|
---|
78 |
|
---|
79 | }
|
---|
80 |
|
---|
81 | return null;
|
---|
82 |
|
---|
83 | // loop where sum != 0, sum > d , sum+1 <d
|
---|
84 |
|
---|
85 | };
|
---|
86 |
|
---|
87 | /*
|
---|
88 | THREE.CurvePath.prototype.getTangent = function( t ) {
|
---|
89 | };*/
|
---|
90 |
|
---|
91 |
|
---|
92 | // We cannot use the default THREE.Curve getPoint() with getLength() because in
|
---|
93 | // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
|
---|
94 | // getPoint() depends on getLength
|
---|
95 |
|
---|
96 | THREE.CurvePath.prototype.getLength = function() {
|
---|
97 |
|
---|
98 | var lens = this.getCurveLengths();
|
---|
99 | return lens[ lens.length - 1 ];
|
---|
100 |
|
---|
101 | };
|
---|
102 |
|
---|
103 | // Compute lengths and cache them
|
---|
104 | // We cannot overwrite getLengths() because UtoT mapping uses it.
|
---|
105 |
|
---|
106 | THREE.CurvePath.prototype.getCurveLengths = function() {
|
---|
107 |
|
---|
108 | // We use cache values if curves and cache array are same length
|
---|
109 |
|
---|
110 | if ( this.cacheLengths && this.cacheLengths.length == this.curves.length ) {
|
---|
111 |
|
---|
112 | return this.cacheLengths;
|
---|
113 |
|
---|
114 | };
|
---|
115 |
|
---|
116 | // Get length of subsurve
|
---|
117 | // Push sums into cached array
|
---|
118 |
|
---|
119 | var lengths = [], sums = 0;
|
---|
120 | var i, il = this.curves.length;
|
---|
121 |
|
---|
122 | for ( i = 0; i < il; i ++ ) {
|
---|
123 |
|
---|
124 | sums += this.curves[ i ].getLength();
|
---|
125 | lengths.push( sums );
|
---|
126 |
|
---|
127 | }
|
---|
128 |
|
---|
129 | this.cacheLengths = lengths;
|
---|
130 |
|
---|
131 | return lengths;
|
---|
132 |
|
---|
133 | };
|
---|
134 |
|
---|
135 |
|
---|
136 |
|
---|
137 | // Returns min and max coordinates, as well as centroid
|
---|
138 |
|
---|
139 | THREE.CurvePath.prototype.getBoundingBox = function () {
|
---|
140 |
|
---|
141 | var points = this.getPoints();
|
---|
142 |
|
---|
143 | var maxX, maxY, maxZ;
|
---|
144 | var minX, minY, minZ;
|
---|
145 |
|
---|
146 | maxX = maxY = Number.NEGATIVE_INFINITY;
|
---|
147 | minX = minY = Number.POSITIVE_INFINITY;
|
---|
148 |
|
---|
149 | var p, i, il, sum;
|
---|
150 |
|
---|
151 | var v3 = points[0] instanceof THREE.Vector3;
|
---|
152 |
|
---|
153 | sum = v3 ? new THREE.Vector3() : new THREE.Vector2();
|
---|
154 |
|
---|
155 | for ( i = 0, il = points.length; i < il; i ++ ) {
|
---|
156 |
|
---|
157 | p = points[ i ];
|
---|
158 |
|
---|
159 | if ( p.x > maxX ) maxX = p.x;
|
---|
160 | else if ( p.x < minX ) minX = p.x;
|
---|
161 |
|
---|
162 | if ( p.y > maxY ) maxY = p.y;
|
---|
163 | else if ( p.y < minY ) minY = p.y;
|
---|
164 |
|
---|
165 | if ( v3 ) {
|
---|
166 |
|
---|
167 | if ( p.z > maxZ ) maxZ = p.z;
|
---|
168 | else if ( p.z < minZ ) minZ = p.z;
|
---|
169 |
|
---|
170 | }
|
---|
171 |
|
---|
172 | sum.add( p );
|
---|
173 |
|
---|
174 | }
|
---|
175 |
|
---|
176 | var ret = {
|
---|
177 |
|
---|
178 | minX: minX,
|
---|
179 | minY: minY,
|
---|
180 | maxX: maxX,
|
---|
181 | maxY: maxY,
|
---|
182 | centroid: sum.divideScalar( il )
|
---|
183 |
|
---|
184 | };
|
---|
185 |
|
---|
186 | if ( v3 ) {
|
---|
187 |
|
---|
188 | ret.maxZ = maxZ;
|
---|
189 | ret.minZ = minZ;
|
---|
190 |
|
---|
191 | }
|
---|
192 |
|
---|
193 | return ret;
|
---|
194 |
|
---|
195 | };
|
---|
196 |
|
---|
197 | /**************************************************************
|
---|
198 | * Create Geometries Helpers
|
---|
199 | **************************************************************/
|
---|
200 |
|
---|
201 | /// Generate geometry from path points (for Line or ParticleSystem objects)
|
---|
202 |
|
---|
203 | THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
|
---|
204 |
|
---|
205 | var pts = this.getPoints( divisions, true );
|
---|
206 | return this.createGeometry( pts );
|
---|
207 |
|
---|
208 | };
|
---|
209 |
|
---|
210 | // Generate geometry from equidistance sampling along the path
|
---|
211 |
|
---|
212 | THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
|
---|
213 |
|
---|
214 | var pts = this.getSpacedPoints( divisions, true );
|
---|
215 | return this.createGeometry( pts );
|
---|
216 |
|
---|
217 | };
|
---|
218 |
|
---|
219 | THREE.CurvePath.prototype.createGeometry = function( points ) {
|
---|
220 |
|
---|
221 | var geometry = new THREE.Geometry();
|
---|
222 |
|
---|
223 | for ( var i = 0; i < points.length; i ++ ) {
|
---|
224 |
|
---|
225 | geometry.vertices.push( new THREE.Vector3( points[ i ].x, points[ i ].y, points[ i ].z || 0) );
|
---|
226 |
|
---|
227 | }
|
---|
228 |
|
---|
229 | return geometry;
|
---|
230 |
|
---|
231 | };
|
---|
232 |
|
---|
233 |
|
---|
234 | /**************************************************************
|
---|
235 | * Bend / Wrap Helper Methods
|
---|
236 | **************************************************************/
|
---|
237 |
|
---|
238 | // Wrap path / Bend modifiers?
|
---|
239 |
|
---|
240 | THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
|
---|
241 |
|
---|
242 | this.bends.push( bendpath );
|
---|
243 |
|
---|
244 | };
|
---|
245 |
|
---|
246 | THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
|
---|
247 |
|
---|
248 | var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
|
---|
249 | var i, il;
|
---|
250 |
|
---|
251 | if ( !bends ) {
|
---|
252 |
|
---|
253 | bends = this.bends;
|
---|
254 |
|
---|
255 | }
|
---|
256 |
|
---|
257 | for ( i = 0, il = bends.length; i < il; i ++ ) {
|
---|
258 |
|
---|
259 | oldPts = this.getWrapPoints( oldPts, bends[ i ] );
|
---|
260 |
|
---|
261 | }
|
---|
262 |
|
---|
263 | return oldPts;
|
---|
264 |
|
---|
265 | };
|
---|
266 |
|
---|
267 | THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
|
---|
268 |
|
---|
269 | var oldPts = this.getSpacedPoints( segments );
|
---|
270 |
|
---|
271 | var i, il;
|
---|
272 |
|
---|
273 | if ( !bends ) {
|
---|
274 |
|
---|
275 | bends = this.bends;
|
---|
276 |
|
---|
277 | }
|
---|
278 |
|
---|
279 | for ( i = 0, il = bends.length; i < il; i ++ ) {
|
---|
280 |
|
---|
281 | oldPts = this.getWrapPoints( oldPts, bends[ i ] );
|
---|
282 |
|
---|
283 | }
|
---|
284 |
|
---|
285 | return oldPts;
|
---|
286 |
|
---|
287 | };
|
---|
288 |
|
---|
289 | // This returns getPoints() bend/wrapped around the contour of a path.
|
---|
290 | // Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
|
---|
291 |
|
---|
292 | THREE.CurvePath.prototype.getWrapPoints = function ( oldPts, path ) {
|
---|
293 |
|
---|
294 | var bounds = this.getBoundingBox();
|
---|
295 |
|
---|
296 | var i, il, p, oldX, oldY, xNorm;
|
---|
297 |
|
---|
298 | for ( i = 0, il = oldPts.length; i < il; i ++ ) {
|
---|
299 |
|
---|
300 | p = oldPts[ i ];
|
---|
301 |
|
---|
302 | oldX = p.x;
|
---|
303 | oldY = p.y;
|
---|
304 |
|
---|
305 | xNorm = oldX / bounds.maxX;
|
---|
306 |
|
---|
307 | // If using actual distance, for length > path, requires line extrusions
|
---|
308 | //xNorm = path.getUtoTmapping(xNorm, oldX); // 3 styles. 1) wrap stretched. 2) wrap stretch by arc length 3) warp by actual distance
|
---|
309 |
|
---|
310 | xNorm = path.getUtoTmapping( xNorm, oldX );
|
---|
311 |
|
---|
312 | // check for out of bounds?
|
---|
313 |
|
---|
314 | var pathPt = path.getPoint( xNorm );
|
---|
315 | var normal = path.getTangent( xNorm );
|
---|
316 | normal.set( -normal.y, normal.x ).multiplyScalar( oldY );
|
---|
317 |
|
---|
318 | p.x = pathPt.x + normal.x;
|
---|
319 | p.y = pathPt.y + normal.y;
|
---|
320 |
|
---|
321 | }
|
---|
322 |
|
---|
323 | return oldPts;
|
---|
324 |
|
---|
325 | };
|
---|
326 |
|
---|