1 | /**
|
---|
2 | * Spline from Tween.js, slightly optimized (and trashed)
|
---|
3 | * http://sole.github.com/tween.js/examples/05_spline.html
|
---|
4 | *
|
---|
5 | * @author mrdoob / http://mrdoob.com/
|
---|
6 | * @author alteredq / http://alteredqualia.com/
|
---|
7 | */
|
---|
8 |
|
---|
9 | THREE.Spline = function ( points ) {
|
---|
10 |
|
---|
11 | this.points = points;
|
---|
12 |
|
---|
13 | var c = [], v3 = { x: 0, y: 0, z: 0 },
|
---|
14 | point, intPoint, weight, w2, w3,
|
---|
15 | pa, pb, pc, pd;
|
---|
16 |
|
---|
17 | this.initFromArray = function( a ) {
|
---|
18 |
|
---|
19 | this.points = [];
|
---|
20 |
|
---|
21 | for ( var i = 0; i < a.length; i++ ) {
|
---|
22 |
|
---|
23 | this.points[ i ] = { x: a[ i ][ 0 ], y: a[ i ][ 1 ], z: a[ i ][ 2 ] };
|
---|
24 |
|
---|
25 | }
|
---|
26 |
|
---|
27 | };
|
---|
28 |
|
---|
29 | this.getPoint = function ( k ) {
|
---|
30 |
|
---|
31 | point = ( this.points.length - 1 ) * k;
|
---|
32 | intPoint = Math.floor( point );
|
---|
33 | weight = point - intPoint;
|
---|
34 |
|
---|
35 | c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
|
---|
36 | c[ 1 ] = intPoint;
|
---|
37 | c[ 2 ] = intPoint > this.points.length - 2 ? this.points.length - 1 : intPoint + 1;
|
---|
38 | c[ 3 ] = intPoint > this.points.length - 3 ? this.points.length - 1 : intPoint + 2;
|
---|
39 |
|
---|
40 | pa = this.points[ c[ 0 ] ];
|
---|
41 | pb = this.points[ c[ 1 ] ];
|
---|
42 | pc = this.points[ c[ 2 ] ];
|
---|
43 | pd = this.points[ c[ 3 ] ];
|
---|
44 |
|
---|
45 | w2 = weight * weight;
|
---|
46 | w3 = weight * w2;
|
---|
47 |
|
---|
48 | v3.x = interpolate( pa.x, pb.x, pc.x, pd.x, weight, w2, w3 );
|
---|
49 | v3.y = interpolate( pa.y, pb.y, pc.y, pd.y, weight, w2, w3 );
|
---|
50 | v3.z = interpolate( pa.z, pb.z, pc.z, pd.z, weight, w2, w3 );
|
---|
51 |
|
---|
52 | return v3;
|
---|
53 |
|
---|
54 | };
|
---|
55 |
|
---|
56 | this.getControlPointsArray = function () {
|
---|
57 |
|
---|
58 | var i, p, l = this.points.length,
|
---|
59 | coords = [];
|
---|
60 |
|
---|
61 | for ( i = 0; i < l; i ++ ) {
|
---|
62 |
|
---|
63 | p = this.points[ i ];
|
---|
64 | coords[ i ] = [ p.x, p.y, p.z ];
|
---|
65 |
|
---|
66 | }
|
---|
67 |
|
---|
68 | return coords;
|
---|
69 |
|
---|
70 | };
|
---|
71 |
|
---|
72 | // approximate length by summing linear segments
|
---|
73 |
|
---|
74 | this.getLength = function ( nSubDivisions ) {
|
---|
75 |
|
---|
76 | var i, index, nSamples, position,
|
---|
77 | point = 0, intPoint = 0, oldIntPoint = 0,
|
---|
78 | oldPosition = new THREE.Vector3(),
|
---|
79 | tmpVec = new THREE.Vector3(),
|
---|
80 | chunkLengths = [],
|
---|
81 | totalLength = 0;
|
---|
82 |
|
---|
83 | // first point has 0 length
|
---|
84 |
|
---|
85 | chunkLengths[ 0 ] = 0;
|
---|
86 |
|
---|
87 | if ( !nSubDivisions ) nSubDivisions = 100;
|
---|
88 |
|
---|
89 | nSamples = this.points.length * nSubDivisions;
|
---|
90 |
|
---|
91 | oldPosition.copy( this.points[ 0 ] );
|
---|
92 |
|
---|
93 | for ( i = 1; i < nSamples; i ++ ) {
|
---|
94 |
|
---|
95 | index = i / nSamples;
|
---|
96 |
|
---|
97 | position = this.getPoint( index );
|
---|
98 | tmpVec.copy( position );
|
---|
99 |
|
---|
100 | totalLength += tmpVec.distanceTo( oldPosition );
|
---|
101 |
|
---|
102 | oldPosition.copy( position );
|
---|
103 |
|
---|
104 | point = ( this.points.length - 1 ) * index;
|
---|
105 | intPoint = Math.floor( point );
|
---|
106 |
|
---|
107 | if ( intPoint != oldIntPoint ) {
|
---|
108 |
|
---|
109 | chunkLengths[ intPoint ] = totalLength;
|
---|
110 | oldIntPoint = intPoint;
|
---|
111 |
|
---|
112 | }
|
---|
113 |
|
---|
114 | }
|
---|
115 |
|
---|
116 | // last point ends with total length
|
---|
117 |
|
---|
118 | chunkLengths[ chunkLengths.length ] = totalLength;
|
---|
119 |
|
---|
120 | return { chunks: chunkLengths, total: totalLength };
|
---|
121 |
|
---|
122 | };
|
---|
123 |
|
---|
124 | this.reparametrizeByArcLength = function ( samplingCoef ) {
|
---|
125 |
|
---|
126 | var i, j,
|
---|
127 | index, indexCurrent, indexNext,
|
---|
128 | linearDistance, realDistance,
|
---|
129 | sampling, position,
|
---|
130 | newpoints = [],
|
---|
131 | tmpVec = new THREE.Vector3(),
|
---|
132 | sl = this.getLength();
|
---|
133 |
|
---|
134 | newpoints.push( tmpVec.copy( this.points[ 0 ] ).clone() );
|
---|
135 |
|
---|
136 | for ( i = 1; i < this.points.length; i++ ) {
|
---|
137 |
|
---|
138 | //tmpVec.copy( this.points[ i - 1 ] );
|
---|
139 | //linearDistance = tmpVec.distanceTo( this.points[ i ] );
|
---|
140 |
|
---|
141 | realDistance = sl.chunks[ i ] - sl.chunks[ i - 1 ];
|
---|
142 |
|
---|
143 | sampling = Math.ceil( samplingCoef * realDistance / sl.total );
|
---|
144 |
|
---|
145 | indexCurrent = ( i - 1 ) / ( this.points.length - 1 );
|
---|
146 | indexNext = i / ( this.points.length - 1 );
|
---|
147 |
|
---|
148 | for ( j = 1; j < sampling - 1; j++ ) {
|
---|
149 |
|
---|
150 | index = indexCurrent + j * ( 1 / sampling ) * ( indexNext - indexCurrent );
|
---|
151 |
|
---|
152 | position = this.getPoint( index );
|
---|
153 | newpoints.push( tmpVec.copy( position ).clone() );
|
---|
154 |
|
---|
155 | }
|
---|
156 |
|
---|
157 | newpoints.push( tmpVec.copy( this.points[ i ] ).clone() );
|
---|
158 |
|
---|
159 | }
|
---|
160 |
|
---|
161 | this.points = newpoints;
|
---|
162 |
|
---|
163 | };
|
---|
164 |
|
---|
165 | // Catmull-Rom
|
---|
166 |
|
---|
167 | function interpolate( p0, p1, p2, p3, t, t2, t3 ) {
|
---|
168 |
|
---|
169 | var v0 = ( p2 - p0 ) * 0.5,
|
---|
170 | v1 = ( p3 - p1 ) * 0.5;
|
---|
171 |
|
---|
172 | return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
|
---|
173 |
|
---|
174 | };
|
---|
175 |
|
---|
176 | };
|
---|