1 /**
  2  * @author zz85 / http://www.lab4games.net/zz85/blog
  3  * Extensible curve object
  4  * 
  5  * Some common of Curve methods
  6  * .getPoint(t), getTangent(t)
  7  * .getPointAt(u), getTagentAt(u)
  8  * .getPoints(), .getSpacedPoints()
  9  * .getLength()
 10  * .updateArcLengths()
 11  *
 12  * This file contains following classes:
 13  *
 14  * -- 2d classes --
 15  * THREE.Curve
 16  * THREE.LineCurve
 17  * THREE.QuadraticBezierCurve
 18  * THREE.CubicBezierCurve
 19  * THREE.SplineCurve
 20  * THREE.ArcCurve
 21  * THREE.EllipseCurve
 22  *
 23  * -- 3d classes --
 24  * THREE.LineCurve3
 25  * THREE.QuadraticBezierCurve3
 26  * THREE.CubicBezierCurve3
 27  * THREE.SplineCurve3
 28  * THREE.ClosedSplineCurve3
 29  *
 30  * A series of curves can be represented as a THREE.CurvePath
 31  *
 32  **/
 33 
 34 /**************************************************************
 35  *	Abstract Curve base class
 36  **************************************************************/
 37 
 38 /**@constructor*/
 39 THREE.Curve = function () {
 40 
 41 };
 42 
 43 // Virtual base class method to overwrite and implement in subclasses
 44 //	- t [0 .. 1]
 45 
 46 THREE.Curve.prototype.getPoint = function ( t ) {
 47 
 48 	console.log( "Warning, getPoint() not implemented!" );
 49 	return null;
 50 
 51 };
 52 
 53 // Get point at relative position in curve according to arc length
 54 // - u [0 .. 1]
 55 
 56 THREE.Curve.prototype.getPointAt = function ( u ) {
 57 
 58 	var t = this.getUtoTmapping( u );
 59 	return this.getPoint( t );
 60 
 61 };
 62 
 63 // Get sequence of points using getPoint( t )
 64 
 65 THREE.Curve.prototype.getPoints = function ( divisions ) {
 66 
 67 	if ( !divisions ) divisions = 5;
 68 
 69 	var d, pts = [];
 70 
 71 	for ( d = 0; d <= divisions; d ++ ) {
 72 
 73 		pts.push( this.getPoint( d / divisions ) );
 74 
 75 	}
 76 
 77 	return pts;
 78 
 79 };
 80 
 81 // Get sequence of points using getPointAt( u )
 82 
 83 THREE.Curve.prototype.getSpacedPoints = function ( divisions ) {
 84 
 85 	if ( !divisions ) divisions = 5;
 86 
 87 	var d, pts = [];
 88 
 89 	for ( d = 0; d <= divisions; d ++ ) {
 90 
 91 		pts.push( this.getPointAt( d / divisions ) );
 92 
 93 	}
 94 
 95 	return pts;
 96 
 97 };
 98 
 99 // Get total curve arc length
100 
101 THREE.Curve.prototype.getLength = function () {
102 
103 	var lengths = this.getLengths();
104 	return lengths[ lengths.length - 1 ];
105 
106 };
107 
108 // Get list of cumulative segment lengths
109 
110 THREE.Curve.prototype.getLengths = function ( divisions ) {
111 
112 	if ( !divisions ) divisions = (this.__arcLengthDivisions) ? (this.__arcLengthDivisions): 200;
113 
114 	if ( this.cacheArcLengths 
115 		&& ( this.cacheArcLengths.length == divisions + 1 ) 
116 		&& !this.needsUpdate) {
117 
118 		//console.log( "cached", this.cacheArcLengths );
119 		return this.cacheArcLengths;
120 
121 	}
122 
123 	this.needsUpdate = false;
124 
125 	var cache = [];
126 	var current, last = this.getPoint( 0 );
127 	var p, sum = 0;
128 
129 	cache.push( 0 );
130 
131 	for ( p = 1; p <= divisions; p ++ ) {
132 
133 		current = this.getPoint ( p / divisions );
134 		sum += current.distanceTo( last );
135 		cache.push( sum );
136 		last = current;
137 
138 	}
139 
140 	this.cacheArcLengths = cache;
141 
142 	return cache; // { sums: cache, sum:sum }; Sum is in the last element.
143 
144 };
145 
146 
147 THREE.Curve.prototype.updateArcLengths = function() {
148 	this.needsUpdate = true;
149 	this.getLengths();
150 };
151 
152 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equi distance
153 
154 THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) {
155 
156 	var arcLengths = this.getLengths();
157 
158 	var i = 0, il = arcLengths.length;
159 
160 	var targetArcLength; // The targeted u distance value to get
161 
162 	if ( distance ) {
163 
164 		targetArcLength = distance;
165 
166 	} else {
167 
168 		targetArcLength = u * arcLengths[ il - 1 ];
169 
170 	}
171 
172 	//var time = Date.now();
173 
174 	// binary search for the index with largest value smaller than target u distance
175 
176 	var low = 0, high = il - 1, comparison;
177 
178 	while ( low <= high ) {
179 
180 		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
181 
182 		comparison = arcLengths[ i ] - targetArcLength;
183 
184 		if ( comparison < 0 ) {
185 
186 			low = i + 1;
187 			continue;
188 
189 		} else if ( comparison > 0 ) {
190 
191 			high = i - 1;
192 			continue;
193 
194 		} else {
195 
196 			high = i;
197 			break;
198 
199 			// DONE
200 
201 		}
202 
203 	}
204 
205 	i = high;
206 
207 	//console.log('b' , i, low, high, Date.now()- time);
208 
209 	if ( arcLengths[ i ] == targetArcLength ) {
210 
211 		var t = i / ( il - 1 );
212 		return t;
213 
214 	}
215 
216 	// we could get finer grain at lengths, or use simple interpolatation between two points
217 
218 	var lengthBefore = arcLengths[ i ];
219     var lengthAfter = arcLengths[ i + 1 ];
220 
221     var segmentLength = lengthAfter - lengthBefore;
222 
223     // determine where we are between the 'before' and 'after' points
224 
225     var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
226 
227     // add that fractional amount to t
228 
229     var t = ( i + segmentFraction ) / ( il -1 );
230 
231 	return t;
232 
233 };
234 
235 
236 // In 2D space, there are actually 2 normal vectors,
237 // and in 3D space, infinte
238 // TODO this should be depreciated.
239 THREE.Curve.prototype.getNormalVector = function( t ) {
240 
241 	var vec = this.getTangent( t );
242 
243 	return new THREE.Vector2( -vec.y , vec.x );
244 
245 };
246 
247 // Returns a unit vector tangent at t
248 // In case any sub curve does not implement its tangent / normal finding,
249 // we get 2 points with a small delta and find a gradient of the 2 points
250 // which seems to make a reasonable approximation
251 
252 THREE.Curve.prototype.getTangent = function( t ) {
253 
254 	var delta = 0.0001;
255 	var t1 = t - delta;
256 	var t2 = t + delta;
257 
258 	// Capping in case of danger
259 
260 	if ( t1 < 0 ) t1 = 0;
261 	if ( t2 > 1 ) t2 = 1;
262 
263 	var pt1 = this.getPoint( t1 );
264 	var pt2 = this.getPoint( t2 );
265 	
266 	var vec = pt2.clone().subSelf(pt1);
267 	return vec.normalize();
268 
269 };
270 
271 
272 THREE.Curve.prototype.getTangentAt = function ( u ) {
273 
274 	var t = this.getUtoTmapping( u );
275 	return this.getTangent( t );
276 
277 };
278 
279 /**************************************************************
280  *	Line
281  **************************************************************/
282 
283 /**@constructor*/
284 THREE.LineCurve = function ( v1, v2 ) {
285 
286 	this.v1 = v1;
287 	this.v2 = v2;
288 
289 };
290 
291 THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
292 
293 THREE.LineCurve.prototype.getPoint = function ( t ) {
294 
295 	var point = this.v2.clone().subSelf(this.v1);
296 	point.multiplyScalar( t ).addSelf( this.v1 );
297 
298 	return point;
299 
300 };
301 
302 // Line curve is linear, so we can overwrite default getPointAt
303 
304 THREE.LineCurve.prototype.getPointAt = function ( u ) {
305 
306 	return this.getPoint( u );
307 
308 };
309 
310 THREE.LineCurve.prototype.getTangent = function( t ) {
311 
312 	var tangent = this.v2.clone().subSelf(this.v1);
313 
314 	return tangent.normalize();
315 
316 };
317 
318 /**************************************************************
319  *	Quadratic Bezier curve
320  **************************************************************/
321 
322 
323 /**@constructor*/
324 THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
325 
326 	this.v0 = v0;
327 	this.v1 = v1;
328 	this.v2 = v2;
329 
330 };
331 
332 THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
333 
334 
335 THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
336 
337 	var tx, ty;
338 
339 	tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
340 	ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
341 
342 	return new THREE.Vector2( tx, ty );
343 
344 };
345 
346 
347 THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
348 
349 	var tx, ty;
350 
351 	tx = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x );
352 	ty = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y );
353 
354 	// returns unit vector
355 
356 	var tangent = new THREE.Vector2( tx, ty );
357 	tangent.normalize();
358 
359 	return tangent;
360 
361 };
362 
363 
364 /**************************************************************
365  *	Cubic Bezier curve
366  **************************************************************/
367 
368 /**@constructor*/
369 THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
370 
371 	this.v0 = v0;
372 	this.v1 = v1;
373 	this.v2 = v2;
374 	this.v3 = v3;
375 
376 };
377 
378 THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
379 
380 THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
381 
382 	var tx, ty;
383 
384 	tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
385 	ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
386 
387 	return new THREE.Vector2( tx, ty );
388 
389 };
390 
391 THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
392 
393 	var tx, ty;
394 
395 	tx = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
396 	ty = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
397 
398 	var tangent = new THREE.Vector2( tx, ty );
399 	tangent.normalize();
400 
401 	return tangent;
402 
403 };
404 
405 
406 /**************************************************************
407  *	Spline curve
408  **************************************************************/
409 
410 /**@constructor*/
411 THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
412 
413 	this.points = (points == undefined) ? [] : points;
414 
415 };
416 
417 THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
418 
419 THREE.SplineCurve.prototype.getPoint = function ( t ) {
420 
421 	var v = new THREE.Vector2();
422 	var c = [];
423 	var points = this.points, point, intPoint, weight;
424 	point = ( points.length - 1 ) * t;
425 
426 	intPoint = Math.floor( point );
427 	weight = point - intPoint;
428 
429 	c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
430 	c[ 1 ] = intPoint;
431 	c[ 2 ] = intPoint  > points.length - 2 ? points.length -1 : intPoint + 1;
432 	c[ 3 ] = intPoint  > points.length - 3 ? points.length -1 : intPoint + 2;
433 
434 	v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
435 	v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
436 
437 	return v;
438 
439 };
440 
441 /**************************************************************
442  *	Ellipse curve
443  **************************************************************/
444 
445 /**@constructor*/
446 THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius,
447 							aStartAngle, aEndAngle,
448 							aClockwise ) {
449 
450 	this.aX = aX;
451 	this.aY = aY;
452 
453 	this.xRadius = xRadius;
454 	this.yRadius = yRadius;
455 
456 	this.aStartAngle = aStartAngle;
457 	this.aEndAngle = aEndAngle;
458 
459 	this.aClockwise = aClockwise;
460 
461 };
462 
463 THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
464 
465 THREE.EllipseCurve.prototype.getPoint = function ( t ) {
466 
467 	var deltaAngle = this.aEndAngle - this.aStartAngle;
468 
469 	if ( !this.aClockwise ) {
470 
471 		t = 1 - t;
472 
473 	}
474 
475 	var angle = this.aStartAngle + t * deltaAngle;
476 
477 	var tx = this.aX + this.xRadius * Math.cos( angle );
478 	var ty = this.aY + this.yRadius * Math.sin( angle );
479 
480 	return new THREE.Vector2( tx, ty );
481 
482 };
483 
484 /**************************************************************
485  *	Arc curve
486  **************************************************************/
487 
488 /**@constructor*/
489 THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
490 
491 	THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
492 };
493 
494 THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );
495 
496 
497 /**************************************************************
498  *	Utils
499  **************************************************************/
500 
501 THREE.Curve.Utils = {
502 
503 	tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
504 
505 		return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
506 
507 	},
508 
509 	// Puay Bing, thanks for helping with this derivative!
510 
511 	tangentCubicBezier: function (t, p0, p1, p2, p3 ) {
512 
513 		return -3 * p0 * (1 - t) * (1 - t)  +
514 			3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
515 			6 * t *  p2 * (1-t) - 3 * t * t * p2 +
516 			3 * t * t * p3;
517 	},
518 
519 
520 	tangentSpline: function ( t, p0, p1, p2, p3 ) {
521 
522 		// To check if my formulas are correct
523 
524 		var h00 = 6 * t * t - 6 * t; 	// derived from 2t^3 − 3t^2 + 1
525 		var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
526 		var h01 = -6 * t * t + 6 * t; 	// − 2t3 + 3t2
527 		var h11 = 3 * t * t - 2 * t;	// t3 − t2
528 
529 		return h00 + h10 + h01 + h11;
530 
531 	},
532 
533 	// Catmull-Rom
534 
535 	interpolate: function( p0, p1, p2, p3, t ) {
536 
537 		var v0 = ( p2 - p0 ) * 0.5;
538 		var v1 = ( p3 - p1 ) * 0.5;
539 		var t2 = t * t;
540 		var t3 = t * t2;
541 		return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
542 
543 	}
544 
545 };
546 
547 
548 // TODO: Transformation for Curves?
549 
550 /**************************************************************
551  *	3D Curves
552  **************************************************************/
553 
554 // A Factory method for creating new curve subclasses
555 
556 THREE.Curve.create = function ( constructor, getPointFunc ) {
557 
558 	constructor.prototype = Object.create( THREE.Curve.prototype );
559 	constructor.prototype.getPoint = getPointFunc;
560 
561 	return constructor;
562 
563 };
564 
565 
566 /**************************************************************
567  *	Line3D
568  **************************************************************/
569 
570 /**@memberOf THREE.Curve
571 @function
572 @name LineCurve3*/
573 THREE.LineCurve3 = THREE.Curve.create(
574 
575 	function ( v1, v2 ) {
576 
577 		this.v1 = v1;
578 		this.v2 = v2;
579 
580 	},
581 
582 	function ( t ) {
583 
584 		var r = new THREE.Vector3();
585 
586 
587 		r.sub( this.v2, this.v1 ); // diff
588 		r.multiplyScalar( t );
589 		r.addSelf( this.v1 );
590 
591 		return r;
592 
593 	}
594 
595 );
596 
597 
598 /**************************************************************
599  *	Quadratic Bezier 3D curve
600  **************************************************************/
601 
602 /**@memberOf THREE.Curve
603 @function
604 @name QuadraticBezierCurve3*/
605 THREE.QuadraticBezierCurve3 = THREE.Curve.create(
606 
607 	function ( v0, v1, v2 ) {
608 
609 		this.v0 = v0;
610 		this.v1 = v1;
611 		this.v2 = v2;
612 
613 	},
614 
615 	function ( t ) {
616 
617 		var tx, ty, tz;
618 
619 		tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
620 		ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
621 		tz = THREE.Shape.Utils.b2( t, this.v0.z, this.v1.z, this.v2.z );
622 
623 		return new THREE.Vector3( tx, ty, tz );
624 
625 	}
626 
627 );
628 
629 
630 
631 /**************************************************************
632  *	Cubic Bezier 3D curve
633  **************************************************************/
634 
635 /**@memberOf THREE.Curve
636 @function
637 @name CubicBezierCurve3*/
638 THREE.CubicBezierCurve3 = THREE.Curve.create(
639 
640 	function ( v0, v1, v2, v3 ) {
641 
642 		this.v0 = v0;
643 		this.v1 = v1;
644 		this.v2 = v2;
645 		this.v3 = v3;
646 
647 	},
648 
649 	function ( t ) {
650 
651 		var tx, ty, tz;
652 
653 		tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
654 		ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
655 		tz = THREE.Shape.Utils.b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z );
656 
657 		return new THREE.Vector3( tx, ty, tz );
658 
659 	}
660 
661 );
662 
663 
664 
665 /**************************************************************
666  *	Spline 3D curve
667  **************************************************************/
668 
669 
670 /**@memberOf THREE.Curve
671 @function
672 @name SplineCurve3*/
673 THREE.SplineCurve3 = THREE.Curve.create(
674 
675 	function ( points /* array of Vector3 */) {
676 
677 		this.points = (points == undefined) ? [] : points;
678 
679 	},
680 
681 	function ( t ) {
682 
683 		var v = new THREE.Vector3();
684 		var c = [];
685 		var points = this.points, point, intPoint, weight;
686 		point = ( points.length - 1 ) * t;
687 
688 		intPoint = Math.floor( point );
689 		weight = point - intPoint;
690 
691 		c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
692 		c[ 1 ] = intPoint;
693 		c[ 2 ] = intPoint  > points.length - 2 ? points.length - 1 : intPoint + 1;
694 		c[ 3 ] = intPoint  > points.length - 3 ? points.length - 1 : intPoint + 2;
695 
696 		var pt0 = points[ c[0] ],
697 			pt1 = points[ c[1] ],
698 			pt2 = points[ c[2] ],
699 			pt3 = points[ c[3] ];
700 
701 		v.x = THREE.Curve.Utils.interpolate(pt0.x, pt1.x, pt2.x, pt3.x, weight);
702 		v.y = THREE.Curve.Utils.interpolate(pt0.y, pt1.y, pt2.y, pt3.y, weight);
703 		v.z = THREE.Curve.Utils.interpolate(pt0.z, pt1.z, pt2.z, pt3.z, weight);
704 
705 		return v;
706 
707 	}
708 
709 );
710 
711 
712 // THREE.SplineCurve3.prototype.getTangent = function(t) {
713 // 		var v = new THREE.Vector3();
714 // 		var c = [];
715 // 		var points = this.points, point, intPoint, weight;
716 // 		point = ( points.length - 1 ) * t;
717 
718 // 		intPoint = Math.floor( point );
719 // 		weight = point - intPoint;
720 
721 // 		c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
722 // 		c[ 1 ] = intPoint;
723 // 		c[ 2 ] = intPoint  > points.length - 2 ? points.length - 1 : intPoint + 1;
724 // 		c[ 3 ] = intPoint  > points.length - 3 ? points.length - 1 : intPoint + 2;
725 
726 // 		var pt0 = points[ c[0] ],
727 // 			pt1 = points[ c[1] ],
728 // 			pt2 = points[ c[2] ],
729 // 			pt3 = points[ c[3] ];
730 
731 // 	// t = weight;
732 // 	v.x = THREE.Curve.Utils.tangentSpline( t, pt0.x, pt1.x, pt2.x, pt3.x );
733 // 	v.y = THREE.Curve.Utils.tangentSpline( t, pt0.y, pt1.y, pt2.y, pt3.y );
734 // 	v.z = THREE.Curve.Utils.tangentSpline( t, pt0.z, pt1.z, pt2.z, pt3.z );
735 
736 // 	return v;
737 		
738 // }
739 
740 /**************************************************************
741  *	Closed Spline 3D curve
742  **************************************************************/
743 
744 
745 /**@memberOf THREE.Curve
746 @function
747 @name ClosedSplineCurve3*/
748 THREE.ClosedSplineCurve3 = THREE.Curve.create(
749 
750 	function ( points /* array of Vector3 */) {
751 
752 		this.points = (points == undefined) ? [] : points;
753 
754 	},
755 
756     function ( t ) {
757 
758         var v = new THREE.Vector3();
759         var c = [];
760         var points = this.points, point, intPoint, weight;
761         point = ( points.length - 0 ) * t;
762             // This needs to be from 0-length +1
763 
764         intPoint = Math.floor( point );
765         weight = point - intPoint;
766             
767         intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
768         c[ 0 ] = ( intPoint - 1 ) % points.length;
769         c[ 1 ] = ( intPoint ) % points.length;
770         c[ 2 ] = ( intPoint + 1 ) % points.length;
771         c[ 3 ] = ( intPoint + 2 ) % points.length;
772 
773         v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
774         v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
775         v.z = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].z, points[ c[ 1 ] ].z, points[ c[ 2 ] ].z, points[ c[ 3 ] ].z, weight );
776         
777         return v;
778 
779     }
780 
781 );
782 

nike free rn new balance hombre baratas cinturones gucci ugg rebajas cinturon gucci ray ban baratas nike cortez peuterey mujer christian louboutin madrid mbt zapatos gafas ray ban baratas mbt ofertas air max blancas mbt barcelona nike air max 90 woolrich barcelona nike mujer botas ugg gafas de sol carrera aratas air max 2016 baratas oakley baratas nike air max 2016

mbt skor nike sverige louboutin skor hollister sverige polo ralph lauren skjorta woolrich jacka dam canada goose jacka woolrich jacka ray ban rea canada goose rea michael kors rea new balance skor ralph lauren skjorta new balance rea uggs sverige lacoste rea christian louboutin skor moncler jacka nike shox barbour jacka uggs rea