Curve.js 14.9 KB
Newer Older
Z
curves  
zz85 已提交
1 2
/**
 * @author zz85 / http://www.lab4games.net/zz85/blog
3 4 5 6
 * Extensible curve object
 *
 * This file contains following classes:
 *
Z
zz85 已提交
7
 * -- 2d classes --
8 9 10 11 12 13
 * THREE.Curve
 * THREE.LineCurve
 * THREE.QuadraticBezierCurve
 * THREE.CubicBezierCurve
 * THREE.SplineCurve
 * THREE.ArcCurve
14
 *
Z
zz85 已提交
15 16 17 18 19
 * -- 3d classes --
 * THREE.LineCurve3
 * THREE.QuadraticBezierCurve3
 * THREE.CubicBezierCurve3
 * THREE.SplineCurve3
Z
curves  
zz85 已提交
20 21 22
 *
 **/

23 24 25 26
/**************************************************************
 *	Abstract Curve base class
 **************************************************************/

27
THREE.Curve = function () {
28

Z
curves  
zz85 已提交
29 30
};

31 32 33 34 35 36
// Virtual base class method to overwrite and implement in subclasses
//	- t [0 .. 1]

THREE.Curve.prototype.getPoint = function ( t ) {

	console.log( "Warning, getPoint() not implemented!" );
Z
curves  
zz85 已提交
37
	return null;
38

Z
curves  
zz85 已提交
39 40
};

41 42 43 44 45 46 47 48
// Get point at relative position in curve according to arc length
// - u [0 .. 1]

THREE.Curve.prototype.getPointAt = function ( u ) {

	var t = this.getUtoTmapping( u );
	return this.getPoint( t );

Z
curves  
zz85 已提交
49 50
};

51 52 53 54 55 56
// Get sequence of points using getPoint( t )

THREE.Curve.prototype.getPoints = function ( divisions ) {

	if ( !divisions ) divisions = 5;

Z
curves  
zz85 已提交
57
	var d, pts = [];
58 59 60 61 62

	for ( d = 0; d <= divisions; d ++ ) {

		pts.push( this.getPoint( d / divisions ) );

Z
curves  
zz85 已提交
63
	};
64

Z
curves  
zz85 已提交
65
	return pts;
66

Z
curves  
zz85 已提交
67 68
};

69 70 71 72 73 74
// Get sequence of points using getPointAt( u )

THREE.Curve.prototype.getSpacedPoints = function ( divisions ) {

	if ( !divisions ) divisions = 5;

Z
curves  
zz85 已提交
75
	var d, pts = [];
76 77 78 79 80

	for ( d = 0; d <= divisions; d ++ ) {

		pts.push( this.getPointAt( d / divisions ) );

Z
curves  
zz85 已提交
81
	};
82

Z
curves  
zz85 已提交
83
	return pts;
84

Z
curves  
zz85 已提交
85 86
};

87 88
// Get total curve length

Z
curves  
zz85 已提交
89
THREE.Curve.prototype.getLength = function () {
90

Z
curves  
zz85 已提交
91
	var lengths = this.getLengths();
92 93
	return lengths[ lengths.length - 1 ];

Z
curves  
zz85 已提交
94 95
};

96 97
// Get list of cumulative segment lengths

98
THREE.Curve.prototype.getLengths = function ( divisions ) {
99 100 101

	if ( !divisions ) divisions = 200;

102
	if ( this.cacheArcLengths && ( this.cacheArcLengths.length == divisions + 1 ) ) {
103

104 105
		//console.log( "cached", this.cacheArcLengths );
		return this.cacheArcLengths;
106

Z
curves  
zz85 已提交
107
	}
108

Z
curves  
zz85 已提交
109
	var cache = [];
110 111 112
	var current, last = this.getPoint( 0 );
	var p, sum = 0;

113 114 115
	cache.push( 0 );

	for ( p = 1; p <= divisions; p ++ ) {
116 117 118 119

		current = this.getPoint ( p / divisions );
		sum += current.distanceTo( last );
		cache.push( sum );
Z
curves  
zz85 已提交
120
		last = current;
121

Z
curves  
zz85 已提交
122
	}
123

124
	this.cacheArcLengths = cache;
125

126 127
	return cache; // { sums: cache, sum:sum }; Sum is in the last element.

Z
curves  
zz85 已提交
128 129
};

130 131
// Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equi distance

132
THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) {
133

Z
zz85 已提交
134
	var arcLengths = this.getLengths();
Z
curves  
zz85 已提交
135

Z
zz85 已提交
136
	var i = 0, il = arcLengths.length;
Z
curves  
zz85 已提交
137

138
	var targetArcLength; // The targeted u distance value to get
139 140 141

	if ( distance ) {

Z
zz85 已提交
142
		targetArcLength = distance;
143

Z
curves  
zz85 已提交
144
	} else {
145

Z
zz85 已提交
146
		targetArcLength = u * arcLengths[ il - 1 ];
147

Z
curves  
zz85 已提交
148
	}
149

Z
zz85 已提交
150
	//var time = Date.now();
151

Z
zz85 已提交
152 153
	// binary search for the index with largest value smaller than target u distance

154 155 156 157 158
	var low = 0, high = il - 1, comparison;

	while ( low <= high ) {

		i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats
Z
zz85 已提交
159 160

	  	comparison = arcLengths[ i ] - targetArcLength;
161 162 163 164 165

	  	if ( comparison < 0 ) {

			low = i + 1;
			continue;
166

167
		} else if ( comparison > 0 ) {
168

169 170
			high = i - 1;
			continue;
171

Z
zz85 已提交
172
		} else {
173

Z
zz85 已提交
174 175
			high = i;
			break;
176

Z
zz85 已提交
177
			// DONE
178

Z
zz85 已提交
179
		}
180

Z
curves  
zz85 已提交
181
	}
182

Z
zz85 已提交
183
	i = high;
184

Z
zz85 已提交
185 186
	//console.log('b' , i, low, high, Date.now()- time);

187 188 189
	if ( arcLengths[ i ] == targetArcLength ) {

		var t = i / ( il - 1 );
Z
zz85 已提交
190
		return t;
191

Z
zz85 已提交
192
	}
193 194 195 196 197 198

	// we could get finer grain at lengths, or use simple interpolatation between two points

	var lengthBefore = arcLengths[ i ];
    var lengthAfter = arcLengths[ i + 1 ];

Z
zz85 已提交
199
    var segmentLength = lengthAfter - lengthBefore;
200

201 202 203 204 205
    // determine where we are between the 'before' and 'after' points

    var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;

    // add that fractional amount to t
206

207
    t = ( i + segmentFraction ) / ( il -1 );
208

Z
curves  
zz85 已提交
209
	return t;
210

Z
curves  
zz85 已提交
211 212
};

213 214
// In case any sub curve does not implement its tangent / normal finding,
// we get 2 points with a small delta and find a gradient of the 2 points
215
// which seems to make a reasonable approximation
Z
zz85 已提交
216 217 218

THREE.Curve.prototype.getNormalVector = function( t ) {

219 220
	var vec = this.getTangent( t );

221
	return new THREE.Vector2( -vec.y , vec.x );
Z
zz85 已提交
222 223 224

};

225
// Returns a unit vector tangent at t
226

227
THREE.Curve.prototype.getTangent = function( t ) {
Z
zz85 已提交
228

229
	var delta = 0.0001;
230 231
	var t1 = t - delta;
	var t2 = t + delta;
Z
zz85 已提交
232

233
	// Capping in case of danger
Z
zz85 已提交
234

235 236
	if ( t1 < 0 ) t1 = 0;
	if ( t2 > 1 ) t2 = 1;
Z
zz85 已提交
237

238 239
	var pt1 = this.getPoint( t1 );
	var pt2 = this.getPoint( t2 );
Z
curves  
zz85 已提交
240

Z
zz85 已提交
241 242 243 244 245
	// var vec = new THREE.Vector2();
	// vec.sub( pt2, pt1 );
	
	var vec = pt1.clone().subSelf(pt2);
	return vec.normalize();
246

247
};
248

Z
curves  
zz85 已提交
249

250 251 252 253
/**************************************************************
 *	Line
 **************************************************************/

Z
zz85 已提交
254
THREE.LineCurve = function ( v1, v2 ) {
255 256 257

	if ( ! ( v1 instanceof THREE.Vector2 ) ) {

258
		// Fall back for old constuctor signature - should be removed over time
Z
curves  
zz85 已提交
259

260
		THREE.LineCurve.oldConstructor.apply( this, arguments );
261
		return;
262

263
	}
Z
zz85 已提交
264 265 266

	this.v1 = v1;
	this.v2 = v2;
267

268
};
269

270
THREE.LineCurve.oldConstructor = function ( x1, y1, x2, y2 ) {
271 272

	this.constructor( new THREE.Vector2( x1, y1 ), new THREE.Vector2( x2, y2 ) );
273

Z
curves  
zz85 已提交
274 275
};

276 277 278 279
THREE.LineCurve.prototype = new THREE.Curve();
THREE.LineCurve.prototype.constructor = THREE.LineCurve;

THREE.LineCurve.prototype.getPoint = function ( t ) {
Z
curves  
zz85 已提交
280

281
	var point = new THREE.Vector2();
282

283 284
	point.sub( this.v2, this.v1 );
	point.multiplyScalar( t ).addSelf( this.v1 );
Z
curves  
zz85 已提交
285

286 287
	return point;

Z
curves  
zz85 已提交
288 289
};

290
// Line curve is linear, so we can overwrite default getPointAt
291

292
THREE.LineCurve.prototype.getPointAt = function ( u ) {
293

294
	return this.getPoint( u );
295

296 297
};

298
THREE.LineCurve.prototype.getTangent = function( t ) {
299 300 301 302 303 304 305

	var tangent = new THREE.Vector2();

	tangent.sub( this.v2, this.v1 );
	tangent.normalize();

	return tangent;
306

Z
curves  
zz85 已提交
307 308
};

309 310 311 312 313
/**************************************************************
 *	Quadratic Bezier curve
 **************************************************************/


Z
zz85 已提交
314
THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
315 316 317 318

	if ( !( v1 instanceof THREE.Vector2 ) ) {

		var args = Array.prototype.slice.call( arguments );
319

320 321 322 323
		v0 = new THREE.Vector2( args[ 0 ], args[ 1 ] );
		v1 = new THREE.Vector2( args[ 2 ], args[ 3 ] );
		v2 = new THREE.Vector2( args[ 4 ], args[ 5 ] );

324
	}
325

Z
zz85 已提交
326 327 328
	this.v0 = v0;
	this.v1 = v1;
	this.v2 = v2;
329

Z
curves  
zz85 已提交
330 331 332 333 334
};

THREE.QuadraticBezierCurve.prototype = new THREE.Curve();
THREE.QuadraticBezierCurve.prototype.constructor = THREE.QuadraticBezierCurve;

335 336 337

THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {

Z
curves  
zz85 已提交
338 339
	var tx, ty;

Z
zz85 已提交
340 341
	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 );
Z
curves  
zz85 已提交
342 343

	return new THREE.Vector2( tx, ty );
344

Z
curves  
zz85 已提交
345 346
};

Z
zz85 已提交
347

348
THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
349

Z
zz85 已提交
350 351 352
	// iterate sub segments
	// 	get lengths for sub segments
	// 	if segment is bezier
353
	//		perform subdivisions
354

Z
zz85 已提交
355
	var tx, ty;
356

Z
zz85 已提交
357 358
	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 );
359

360
	// returns unit vector
361

362 363
	var tangent = new THREE.Vector2( tx, ty );
	tangent.normalize();
364

365
	return tangent;
366

Z
zz85 已提交
367 368 369
};


370 371 372 373
/**************************************************************
 *	Cubic Bezier curve
 **************************************************************/

Z
zz85 已提交
374
THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
375

376
	if ( ! ( v1 instanceof THREE.Vector2 ) ) {
377

378
		var args = Array.prototype.slice.call( arguments );
379

380 381 382 383
		v0 = new THREE.Vector2( args[ 0 ], args[ 1 ] );
		v1 = new THREE.Vector2( args[ 2 ], args[ 3 ] );
		v2 = new THREE.Vector2( args[ 4 ], args[ 5 ] );
		v3 = new THREE.Vector2( args[ 6 ], args[ 7 ] );
384

385 386
	}

Z
zz85 已提交
387 388 389 390
	this.v0 = v0;
	this.v1 = v1;
	this.v2 = v2;
	this.v3 = v3;
391

Z
curves  
zz85 已提交
392
};
393

Z
curves  
zz85 已提交
394 395 396
THREE.CubicBezierCurve.prototype = new THREE.Curve();
THREE.CubicBezierCurve.prototype.constructor = THREE.CubicBezierCurve;

397 398
THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {

Z
curves  
zz85 已提交
399 400
	var tx, ty;

Z
zz85 已提交
401 402
	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 );
Z
curves  
zz85 已提交
403 404

	return new THREE.Vector2( tx, ty );
405

Z
curves  
zz85 已提交
406 407
};

408
THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
Z
zz85 已提交
409 410 411 412 413 414 415

	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 );

	// return normal unit vector
416 417 418 419 420

	var tangent = new THREE.Vector2( tx, ty );
	tangent.normalize();

	return tangent;
Z
zz85 已提交
421 422 423 424

};


425 426 427 428
/**************************************************************
 *	Spline curve
 **************************************************************/

429
THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
430

Z
zz85 已提交
431
	this.points = (points == undefined) ? [] : points;
432

Z
curves  
zz85 已提交
433 434 435
};

THREE.SplineCurve.prototype = new THREE.Curve();
Z
zz85 已提交
436
THREE.SplineCurve.prototype.constructor = THREE.SplineCurve;
Z
curves  
zz85 已提交
437

438
THREE.SplineCurve.prototype.getPoint = function ( t ) {
Z
curves  
zz85 已提交
439 440 441

	var v = new THREE.Vector2();
	var c = [];
442
	var points = this.points, point, intPoint, weight;
Z
curves  
zz85 已提交
443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
	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 ? intPoint : intPoint + 1;
	c[ 3 ] = intPoint > points.length - 3 ? intPoint : 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;

458
};
Z
zz85 已提交
459

460 461 462
/**************************************************************
 *	Arc curve
 **************************************************************/
Z
zz85 已提交
463 464

THREE.ArcCurve = function ( aX, aY, aRadius,
A
alteredq 已提交
465 466 467
							aStartAngle, aEndAngle,
							aClockwise ) {

Z
zz85 已提交
468 469
	this.aX = aX;
	this.aY = aY;
470

Z
zz85 已提交
471
	this.aRadius = aRadius;
472

Z
zz85 已提交
473 474
	this.aStartAngle = aStartAngle;
	this.aEndAngle = aEndAngle;
475

Z
zz85 已提交
476
	this.aClockwise = aClockwise;
477

Z
zz85 已提交
478 479 480 481 482
};

THREE.ArcCurve.prototype = new THREE.Curve();
THREE.ArcCurve.prototype.constructor = THREE.ArcCurve;

483
THREE.ArcCurve.prototype.getPoint = function ( t ) {
Z
zz85 已提交
484 485

	var deltaAngle = this.aEndAngle - this.aStartAngle;
486 487 488

	if ( !this.aClockwise ) {

Z
zz85 已提交
489
		t = 1 - t;
490

Z
zz85 已提交
491
	}
492

Z
zz85 已提交
493 494
	var angle = this.aStartAngle + t * deltaAngle;

495 496
	var tx = this.aX + this.aRadius * Math.cos( angle );
	var ty = this.aY + this.aRadius * Math.sin( angle );
Z
zz85 已提交
497 498 499

	return new THREE.Vector2( tx, ty );

500 501 502 503 504
};

/**************************************************************
 *	Utils
 **************************************************************/
Z
zz85 已提交
505

Z
curves  
zz85 已提交
506
THREE.Curve.Utils = {
507 508 509 510 511

	tangentQuadraticBezier: function ( t, p0, p1, p2 ) {

		return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );

Z
zz85 已提交
512
	},
513

514
	// Puay Bing, thanks for helping with this derivative!
515

Z
zz85 已提交
516
	tangentCubicBezier: function (t, p0, p1, p2, p3 ) {
517

Z
zz85 已提交
518 519
		return -3 * p0 * (1 - t) * (1 - t)  +
			3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
520
			6 * t *  p2 * (1-t) - 3 * t * t * p2 +
Z
zz85 已提交
521 522
			3 * t * t * p3;
	},
523

524 525 526

	tangentSpline: function ( t, p0, p1, p2, p3 ) {

Z
zz85 已提交
527
		// To check if my formulas are correct
528 529

		var h00 = 6 * t * t - 6 * t; 	// derived from 2t^3 − 3t^2 + 1
Z
zz85 已提交
530
		var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
531 532 533
		var h01 = -6 * t * t + 6 * t; 	// − 2t3 + 3t2
		var h11 = 3 * t * t - 2 * t;	// t3 − t2

534
		return h00 + h10 + h01 + h11;
535

Z
zz85 已提交
536
	},
537

Z
curves  
zz85 已提交
538
	// Catmull-Rom
539

Z
curves  
zz85 已提交
540 541 542 543 544 545 546 547 548
	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;

	}
549

Z
curves  
zz85 已提交
550 551 552 553 554 555 556 557 558 559 560
};


/*
getPoint DONE
getLength DONE
getLengths DONE

curve.getPoints(); DONE
curve.getPointAtArcLength(t); DONE
curve.transform(params);
561
curve.getTangentAt(t); DONE
562 563 564 565 566 567
*/

/**************************************************************
 *	3D Curves
 **************************************************************/

568 569 570
// A Factory method for creating new curve subclasses

THREE.Curve.create = function( constructor, getPointFunc ) {
571 572 573

    var subClass = constructor;

574 575 576 577 578 579 580 581
	subClass.prototype = new THREE.Curve();

	subClass.prototype.constructor = constructor;
    subClass.prototype.getPoint = getPointFunc;

	return subClass;

};
582 583 584 585 586 587 588 589


/**************************************************************
 *	Line3D
 **************************************************************/

THREE.LineCurve3 = THREE.Curve.create(

590
	function ( v1, v2 ) {
591

592 593
		this.v1 = v1;
		this.v2 = v2;
594 595

	},
596

597 598
	function ( t ) {

599
		var r = new THREE.Vector3();
600

601

602
		r.sub( this.v2, this.v1 ); // diff
603 604
		r.multiplyScalar( t );
		r.addSelf( this.v1 );
605

606
		return r;
607 608

	}
609

610 611 612 613 614 615 616 617 618
);


/**************************************************************
 *	Quadratic Bezier 3D curve
 **************************************************************/

THREE.QuadraticBezierCurve3 = THREE.Curve.create(

Z
zz85 已提交
619
	function ( v0, v1, v2 ) {
620

621 622 623
		this.v0 = v0;
		this.v1 = v1;
		this.v2 = v2;
624 625

	},
626

627 628 629 630
	function ( t ) {

		var tx, ty, tz;

631 632 633
		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 );
634

635
		return new THREE.Vector3( tx, ty, tz );
636 637

	}
638

Z
zz85 已提交
639
);
Z
zz85 已提交
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682



/**************************************************************
 *	Cubic Bezier 3D curve
 **************************************************************/

THREE.CubicBezierCurve3 = THREE.Curve.create(

	function ( v0, v1, v2, v3 ) {

		this.v0 = v0;
		this.v1 = v1;
		this.v2 = v2;
		this.v3 = v3;

	},

	function ( t ) {

		var tx, ty, tz;

		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 );

	}

);



/**************************************************************
 *	Spline 3D curve
 **************************************************************/


THREE.SplineCurve3 = THREE.Curve.create(

	function ( points /* array of Vector3 */) {

Z
zz85 已提交
683
		this.points = (points == undefined) ? [] : points;
684

Z
zz85 已提交
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
	},

	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 ? intPoint : intPoint + 1;
		c[ 3 ] = intPoint > points.length - 3 ? intPoint : 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 );
		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;

	}

);