Project

General

Profile

Download (23.9 KB) Statistics
| Branch: | Revision:

library / src / main / java / org / distorted / library / type / Dynamic.java @ 291705f6

1 e0a16874 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
2
// Copyright 2016 Leszek Koltunski                                                               //
3
//                                                                                               //
4
// This file is part of Distorted.                                                               //
5
//                                                                                               //
6
// Distorted is free software: you can redistribute it and/or modify                             //
7
// it under the terms of the GNU General Public License as published by                          //
8
// the Free Software Foundation, either version 2 of the License, or                             //
9
// (at your option) any later version.                                                           //
10
//                                                                                               //
11
// Distorted is distributed in the hope that it will be useful,                                  //
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
14
// GNU General Public License for more details.                                                  //
15
//                                                                                               //
16
// You should have received a copy of the GNU General Public License                             //
17
// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
18
///////////////////////////////////////////////////////////////////////////////////////////////////
19
20 a4835695 Leszek Koltunski
package org.distorted.library.type;
21 6a06a912 Leszek Koltunski
22
import java.util.Random;
23 3002bef3 Leszek Koltunski
import java.util.Vector;
24 6a06a912 Leszek Koltunski
25
///////////////////////////////////////////////////////////////////////////////////////////////////
26 ea16dc89 Leszek Koltunski
/** A class to interpolate between a list of Statics.
27 6a06a912 Leszek Koltunski
* <p><ul>
28
* <li>if there is only one Point, just jump to it.
29
* <li>if there are two Points, linearly bounce between them
30
* <li>if there are more, interpolate a loop (or a path!) between them.
31
* </ul>
32
*/
33
34
// The way Interpolation between more than 2 Points is done:
35
// 
36
// Def: let w[i] = (w[i](x), w[i](y), w[i](z)) be the direction and speed we have to be flying at Point P[i]
37
//
38
// time it takes to fly though one segment v[i] --> v[i+1] : 0.0 --> 1.0
39
// w[i] should be parallel to v[i+1] - v[i-1]   (cyclic notation)
40
// |w[i]| proportional to | P[i]-P[i+1] |
41
//
42
// Given that the flight route (X(t), Y(t), Z(t)) from P(i) to P(i+1)  (0<=t<=1) has to satisfy
43
// X(0) = P[i  ](x), Y(0)=P[i  ](y), Z(0)=P[i  ](z), X'(0) = w[i  ](x), Y'(0) = w[i  ](y), Z'(0) = w[i  ](z)
44
// X(1) = P[i+1](x), Y(1)=P[i+1](y), Z(1)=P[i+1](z), X'(1) = w[i+1](x), Y'(1) = w[i+1](y), Z'(1) = w[i+1](z)
45
//
46
// we have the solution:  X(t) = at^3 + bt^2 + ct + d where
47
// a =  2*P[i](x) +   w[i](x) - 2*P[i+1](x) + w[i+1](x)
48
// b = -3*P[i](x) - 2*w[i](x) + 3*P[i+1](x) - w[i+1](x)
49 6a2ebb18 Leszek Koltunski
// c = w[i](x)
50 6a06a912 Leszek Koltunski
// d = P[i](x)
51
//
52
// and similarly Y(t) and Z(t).
53
54 568b29d8 Leszek Koltunski
public abstract class Dynamic
55 6a06a912 Leszek Koltunski
  {
56
  /**
57
   * One revolution takes us from the first vector to the last and back to first through the shortest path. 
58
   */
59
  public static final int MODE_LOOP = 0; 
60
  /**
61
   * We come back from the last to the first vector through the same way we got there.
62
   */
63
  public static final int MODE_PATH = 1; 
64
  /**
65
   * We just jump back from the last point to the first.
66
   */
67
  public static final int MODE_JUMP = 2; 
68 3002bef3 Leszek Koltunski
69
  protected int mDimension;
70 6a06a912 Leszek Koltunski
  protected int numPoints;
71 291705f6 Leszek Koltunski
  protected int mSegment;       // between which pair of points are we currently? (in case of PATH this is a bit complicated!)
72 6a06a912 Leszek Koltunski
  protected boolean cacheDirty; // VectorCache not up to date
73
  protected int mMode;          // LOOP, PATH or JUMP
74 8c893ffc Leszek Koltunski
  protected long mDuration;     // number of milliseconds it takes to do a full loop/path from first vector to the last and back to the first
75 6a06a912 Leszek Koltunski
  protected float mCount;       // number of loops/paths we will do; mCount = 1.5 means we go from the first vector to the last, back to first, and to the last again. 
76 3002bef3 Leszek Koltunski
77
  protected class VectorNoise
78
    {
79
    float[][] n;
80
81 291705f6 Leszek Koltunski
    VectorNoise()
82 3002bef3 Leszek Koltunski
      {
83 291705f6 Leszek Koltunski
      n = new float[mDimension][NUM_NOISE];
84
      }
85 3002bef3 Leszek Koltunski
86 291705f6 Leszek Koltunski
    void computeNoise()
87
      {
88 3002bef3 Leszek Koltunski
      n[0][0] = mRnd.nextFloat();
89
      for(int i=1; i<NUM_NOISE; i++) n[0][i] = n[0][i-1]+mRnd.nextFloat();
90 291705f6 Leszek Koltunski
91 3002bef3 Leszek Koltunski
      float sum = n[0][NUM_NOISE-1] + mRnd.nextFloat();
92
93 291705f6 Leszek Koltunski
      for(int i=0; i<NUM_NOISE; i++)
94 3002bef3 Leszek Koltunski
        {
95 291705f6 Leszek Koltunski
        n[0][i] /=sum;
96
        for(int j=1; j<mDimension; j++) n[j][i] = mRnd.nextFloat()-0.5f;
97 3002bef3 Leszek Koltunski
        }
98
      }
99
    }
100
101
  protected Vector<VectorNoise> vn;
102
  protected float[] mFactor;
103 1e22c248 Leszek Koltunski
  protected float[] mNoise;
104 649544b8 Leszek Koltunski
  protected float[][] baseV;
105
106
  ///////////////////////////////////////////////////////////////////////////////////////////////////
107
  // the coefficients of the X(t), Y(t) and Z(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx  etc.
108
  // (tangent) is the vector tangent to the path.
109
  // (cached) is the original vector from vv (copied here so when interpolating we can see if it is
110
  // still valid and if not - rebuild the Cache
111
112
  protected class VectorCache
113
    {
114
    float[] a;
115
    float[] b;
116
    float[] c;
117
    float[] d;
118
    float[] tangent;
119
    float[] cached;
120
121 291705f6 Leszek Koltunski
    VectorCache()
122 649544b8 Leszek Koltunski
      {
123 291705f6 Leszek Koltunski
      a = new float[mDimension];
124
      b = new float[mDimension];
125
      c = new float[mDimension];
126
      d = new float[mDimension];
127
      tangent = new float[mDimension];
128
      cached = new float[mDimension];
129 649544b8 Leszek Koltunski
      }
130
    }
131
132
  protected Vector<VectorCache> vc;
133
  protected VectorCache tmp1, tmp2;
134 3002bef3 Leszek Koltunski
135 6a2ebb18 Leszek Koltunski
  private float[] buf;
136
  private float[] old;
137
  private static Random mRnd = new Random();
138
  private static final int NUM_NOISE = 5; // used iff mNoise>0.0. Number of intermediary points between each pair of adjacent vectors
139
                                          // where we randomize noise factors to make the way between the two vectors not so smooth.
140
141
//private int lastNon;
142
143 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
144
// hide this from Javadoc
145
  
146 649544b8 Leszek Koltunski
  protected Dynamic()
147 6a06a912 Leszek Koltunski
    {
148
    }
149 8c893ffc Leszek Koltunski
150 649544b8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
151
152
  protected Dynamic(int duration, float count, int dimension)
153
    {
154 291705f6 Leszek Koltunski
    vc         = new Vector<>();
155
    vn         = null;
156
    numPoints  = 0;
157 649544b8 Leszek Koltunski
    cacheDirty = false;
158 291705f6 Leszek Koltunski
    mMode      = MODE_LOOP;
159
    mDuration  = duration;
160
    mCount     = count;
161 649544b8 Leszek Koltunski
    mDimension = dimension;
162 291705f6 Leszek Koltunski
    mSegment   = -1;
163 649544b8 Leszek Koltunski
164 291705f6 Leszek Koltunski
    baseV      = new float[mDimension][mDimension];
165
    buf        = new float[mDimension];
166
    old        = new float[mDimension];
167 649544b8 Leszek Koltunski
    }
168
169 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
170
  
171 e0a16874 Leszek Koltunski
  public void interpolateMain(float[] buffer, int offset, long currentDuration)
172 6a06a912 Leszek Koltunski
    {
173
    if( mDuration<=0.0f ) 
174
      {
175
      interpolate(buffer,offset,mCount-(int)mCount);  
176
      }
177
    else
178
      {
179 c6dec65b Leszek Koltunski
      double x = (double)currentDuration/mDuration;
180 6a06a912 Leszek Koltunski
           
181
      if( x<=mCount || mCount<=0.0f )
182
        {
183 c6dec65b Leszek Koltunski
        interpolate(buffer,offset, (float)(x-(int)x) );
184 6a06a912 Leszek Koltunski
        }
185
      }
186
    }
187
  
188
///////////////////////////////////////////////////////////////////////////////////////////////////
189
190 e0a16874 Leszek Koltunski
  public boolean interpolateMain(float[] buffer, int offset, long currentDuration, long step)
191 6a06a912 Leszek Koltunski
    {
192
    if( mDuration<=0.0f ) 
193
      {
194
      interpolate(buffer,offset,mCount-(int)mCount);
195
      return false;
196
      }
197
     
198 c6dec65b Leszek Koltunski
    double x = (double)currentDuration/mDuration;
199 6a06a912 Leszek Koltunski
           
200
    if( x<=mCount || mCount<=0.0f )
201
      {
202 c6dec65b Leszek Koltunski
      interpolate(buffer,offset, (float)(x-(int)x) );
203 6a06a912 Leszek Koltunski
        
204
      if( currentDuration+step > mDuration*mCount && mCount>0.0f )
205
        {
206
        interpolate(buffer,offset,mCount-(int)mCount);
207
        return true;
208
        }
209
      }
210
    
211
    return false;
212
    }
213 3002bef3 Leszek Koltunski
214
///////////////////////////////////////////////////////////////////////////////////////////////////
215
216
  protected float noise(float time,int vecNum)
217
    {
218
    float lower, upper, len;
219
    float d = time*(NUM_NOISE+1);
220
    int index = (int)d;
221
    if( index>=NUM_NOISE+1 ) index=NUM_NOISE;
222
    VectorNoise tmpN = vn.elementAt(vecNum);
223
224
    float t = d-index;
225
    t = t*t*(3-2*t);
226
227
    switch(index)
228
      {
229 1e22c248 Leszek Koltunski
      case 0        : for(int i=0;i<mDimension-1;i++) mFactor[i] = mNoise[i+1]*tmpN.n[i+1][0]*t;
230
                      return time + mNoise[0]*(d*tmpN.n[0][0]-time);
231
      case NUM_NOISE: for(int i=0;i<mDimension-1;i++) mFactor[i] = mNoise[i+1]*tmpN.n[i+1][NUM_NOISE-1]*(1-t);
232 3002bef3 Leszek Koltunski
                      len = ((float)NUM_NOISE)/(NUM_NOISE+1);
233 1e22c248 Leszek Koltunski
                      lower = len + mNoise[0]*(tmpN.n[0][NUM_NOISE-1]-len);
234 3002bef3 Leszek Koltunski
                      return (1.0f-lower)*(d-NUM_NOISE) + lower;
235
      default       : float ya,yb;
236
237
                      for(int i=0;i<mDimension-1;i++)
238
                        {
239
                        yb = tmpN.n[i+1][index  ];
240
                        ya = tmpN.n[i+1][index-1];
241 1e22c248 Leszek Koltunski
                        mFactor[i] = mNoise[i+1]*((yb-ya)*t+ya);
242 3002bef3 Leszek Koltunski
                        }
243
244
                      len = ((float)index)/(NUM_NOISE+1);
245 1e22c248 Leszek Koltunski
                      lower = len + mNoise[0]*(tmpN.n[0][index-1]-len);
246 3002bef3 Leszek Koltunski
                      len = ((float)index+1)/(NUM_NOISE+1);
247 1e22c248 Leszek Koltunski
                      upper = len + mNoise[0]*(tmpN.n[0][index  ]-len);
248 3002bef3 Leszek Koltunski
249
                      return (upper-lower)*(d-index) + lower;
250
      }
251
    }
252
253 649544b8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
254
// debugging only
255
256
  private void printBase(String str)
257
    {
258
    String s;
259
    float t;
260
261
    for(int i=0; i<mDimension; i++)
262
      {
263
      s = "";
264
265
      for(int j=0; j<mDimension; j++)
266
        {
267
        t = ((int)(1000*baseV[i][j]))/(1000.0f);
268
        s+=(" "+t);
269
        }
270
      android.util.Log.e("dynamic", str+" base "+i+" : " + s);
271
      }
272
    }
273
274
///////////////////////////////////////////////////////////////////////////////////////////////////
275
// debugging only
276
277
  private void checkBase()
278
    {
279 6a2ebb18 Leszek Koltunski
    float tmp, cosA;
280
    float[] len= new float[mDimension];
281
    boolean error=false;
282
283
    for(int i=0; i<mDimension; i++)
284
      {
285
      len[i] = 0.0f;
286
287
      for(int k=0; k<mDimension; k++)
288
        {
289
        len[i] += baseV[i][k]*baseV[i][k];
290
        }
291
292
      if( len[i] == 0.0f || len[0]/len[i] < 0.95f || len[0]/len[i]>1.05f )
293
        {
294
        android.util.Log.e("dynamic", "length of vector "+i+" : "+Math.sqrt(len[i]));
295
        error = true;
296
        }
297
      }
298 649544b8 Leszek Koltunski
299
    for(int i=0; i<mDimension; i++)
300
      for(int j=i+1; j<mDimension; j++)
301
        {
302
        tmp = 0.0f;
303
304
        for(int k=0; k<mDimension; k++)
305
          {
306
          tmp += baseV[i][k]*baseV[j][k];
307
          }
308
309 6a2ebb18 Leszek Koltunski
        cosA = ( (len[i]==0.0f || len[j]==0.0f) ? 0.0f : tmp/(float)Math.sqrt(len[i]*len[j]));
310 649544b8 Leszek Koltunski
311 6a2ebb18 Leszek Koltunski
        if( cosA > 0.05f || cosA < -0.05f )
312
          {
313
          android.util.Log.e("dynamic", "cos angle between vectors "+i+" and "+j+" : "+cosA);
314
          error = true;
315
          }
316 649544b8 Leszek Koltunski
        }
317
318 6a2ebb18 Leszek Koltunski
    if( error ) printBase("");
319 649544b8 Leszek Koltunski
    }
320
321 c6dec65b Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
322
323
  private void checkAngle(int index)
324
    {
325
    float cosA = 0.0f;
326
327
    for(int k=0;k<mDimension; k++)
328
      cosA += baseV[index][k]*old[k];
329
330
    if( cosA<0.0f )
331
      {
332
/*
333
      /// DEBUGGING ////
334
      String s = index+" (";
335
      float t;
336
337
      for(int j=0; j<mDimension; j++)
338
        {
339
        t = ((int)(100*baseV[index][j]))/(100.0f);
340
        s+=(" "+t);
341
        }
342
      s += ") (";
343
344
      for(int j=0; j<mDimension; j++)
345
        {
346
        t = ((int)(100*old[j]))/(100.0f);
347
        s+=(" "+t);
348
        }
349
      s+= ")";
350
351
      android.util.Log.e("dynamic", "kat: " + s);
352
      /// END DEBUGGING ///
353
*/
354
      for(int j=0; j<mDimension; j++)
355
        baseV[index][j] = -baseV[index][j];
356
      }
357
    }
358
359 649544b8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
360
// helper function in case we are interpolating through exactly 2 points
361
362
  protected void computeOrthonormalBase2(Static1D curr, Static1D next)
363
    {
364
    switch(mDimension)
365
      {
366
      case 1: baseV[0][0] = (next.x-curr.x);
367
              break;
368
      case 2: Static2D curr2 = (Static2D)curr;
369
              Static2D next2 = (Static2D)next;
370
              baseV[0][0] = (next2.x-curr2.x);
371
              baseV[0][1] = (next2.y-curr2.y);
372
              break;
373
      case 3: Static3D curr3 = (Static3D)curr;
374
              Static3D next3 = (Static3D)next;
375
              baseV[0][0] = (next3.x-curr3.x);
376
              baseV[0][1] = (next3.y-curr3.y);
377
              baseV[0][2] = (next3.z-curr3.z);
378
              break;
379
      case 4: Static4D curr4 = (Static4D)curr;
380
              Static4D next4 = (Static4D)next;
381
              baseV[0][0] = (next4.x-curr4.x);
382
              baseV[0][1] = (next4.y-curr4.y);
383
              baseV[0][2] = (next4.z-curr4.z);
384
              baseV[0][3] = (next4.w-curr4.w);
385
              break;
386
      case 5: Static5D curr5 = (Static5D)curr;
387
              Static5D next5 = (Static5D)next;
388
              baseV[0][0] = (next5.x-curr5.x);
389
              baseV[0][1] = (next5.y-curr5.y);
390
              baseV[0][2] = (next5.z-curr5.z);
391
              baseV[0][3] = (next5.w-curr5.w);
392
              baseV[0][4] = (next5.v-curr5.v);
393
              break;
394
      default: throw new RuntimeException("Unsupported dimension");
395
      }
396
397
    if( baseV[0][0] == 0.0f )
398
      {
399
      baseV[1][0] = 1.0f;
400
      baseV[1][1] = 0.0f;
401
      }
402
    else
403
      {
404
      baseV[1][0] = 0.0f;
405
      baseV[1][1] = 1.0f;
406
      }
407
408
    for(int i=2; i<mDimension; i++)
409
      {
410
      baseV[1][i] = 0.0f;
411
      }
412
413
    computeOrthonormalBase();
414
    }
415
416 6a2ebb18 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
417
// debugging
418
/*
419
  protected void computeOrthonormalBaseMoreDebug(float time,VectorCache vc)
420
    {
421
    for(int i=0; i<mDimension; i++)
422
      {
423
      baseV[0][i] = (3*vc.a[i]*time+2*vc.b[i])*time+vc.c[i];   // first derivative, i.e. velocity vector
424
      baseV[1][i] =  6*vc.a[i]*time+2*vc.b[i];                 // second derivative,i.e. acceleration vector
425
      }
426
427
    float av=0.0f, vv=0.0f;
428
429
    android.util.Log.e("dyn3D", " ==>  velocity     ("+baseV[0][0]+","+baseV[0][1]+","+baseV[0][2]+")");
430
    android.util.Log.e("dyn3D", " ==>  acceleration ("+baseV[1][0]+","+baseV[1][1]+","+baseV[1][2]+")");
431
432
    for(int k=0; k<mDimension; k++)
433
      {
434
      vv += baseV[0][k]*baseV[0][k];
435
      av += baseV[1][k]*baseV[0][k];
436
      }
437
438
    android.util.Log.e("dyn3D", " ==>  av: "+av+" vv="+vv);
439
440
    av /= vv;
441
442
    for(int k=0;k<mDimension; k++)
443
      {
444
      baseV[1][k] -= av*baseV[0][k];
445
      }
446
447
    android.util.Log.e("dyn3D", " ==>  second base ("+baseV[1][0]+","+baseV[1][1]+","+baseV[1][2]+")");
448
    }
449
*/
450 649544b8 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
451
// helper function in case we are interpolating through more than 2 points
452
453
  protected void computeOrthonormalBaseMore(float time,VectorCache vc)
454
    {
455
    for(int i=0; i<mDimension; i++)
456
      {
457 6a2ebb18 Leszek Koltunski
      baseV[0][i] = (3*vc.a[i]*time+2*vc.b[i])*time+vc.c[i];   // first derivative, i.e. velocity vector
458
      old[i]      = baseV[1][i];
459
      baseV[1][i] =  6*vc.a[i]*time+2*vc.b[i];                 // second derivative,i.e. acceleration vector
460 649544b8 Leszek Koltunski
      }
461
462
    computeOrthonormalBase();
463
    }
464
465
///////////////////////////////////////////////////////////////////////////////////////////////////
466
// When this function gets called, baseV[0] and baseV[1] should have been filled with two mDimension-al
467
// vectors. This function then fills the rest of the baseV array with a mDimension-al Orthonormal base.
468
// (mDimension-2 vectors, pairwise orthogonal to each other and to the original 2). The function always
469
// leaves base[0] alone but generally speaking must adjust base[1] to make it orthogonal to base[0]!
470
// The whole baseV is then used to compute Noise.
471
//
472
// When computing noise of a point travelling along a N-dimensional path, there are three cases:
473
// a) we may be interpolating through 1 point, i.e. standing in place - nothing to do in this case
474
// b) we may be interpolating through 2 points, i.e. travelling along a straight line between them -
475
//    then pass the velocity vector in baseV[0] and anything linearly independent in base[1].
476
//    The output will then be discontinuous in dimensions>2 (sad corollary from the Hairy Ball Theorem)
477
//    but we don't care - we are travelling along a straight line, so velocity (aka baseV[0]!) does
478
//    not change.
479
// c) we may be interpolating through more than 2 points. Then interpolation formulas ensure the path
480
//    will never be a straight line, even locally -> we can pass in baseV[0] and baseV[1] the velocity
481
//    and the acceleration (first and second derivatives of the path) which are then guaranteed to be
482
//    linearly independent. Then we can ensure this is continuous in dimensions <=4. This leaves
483
//    dimension 5 (ATM WAVE is 5-dimensional) discontinuous -> WAVE will suffer from chaotic noise.
484
//
485
// Bear in mind here the 'normal' in 'orthonormal' means 'length equal to the length of the original
486
// velocity vector' (rather than the standard 1)
487
488
  protected void computeOrthonormalBase()
489
    {
490
    int last_non_zero=-1;
491 6a2ebb18 Leszek Koltunski
    float tmp;
492 649544b8 Leszek Koltunski
493 6a2ebb18 Leszek Koltunski
    for(int i=0; i<mDimension; i++)
494
      if( baseV[0][i] != 0.0f )
495 649544b8 Leszek Koltunski
        last_non_zero=i;
496 6a2ebb18 Leszek Koltunski
/*
497
if( last_non_zero != lastNon )
498
  android.util.Log.e("dynamic", "lastNon="+lastNon+" last_non_zero="+last_non_zero);
499
*/
500
501 a36b0cbb Leszek Koltunski
    if( last_non_zero==-1 )                                               ///
502 6a2ebb18 Leszek Koltunski
      {                                                                   //  velocity is the 0 vector -> two
503
      for(int i=0; i<mDimension-1; i++)                                   //  consecutive points we are interpolating
504
        for(int j=0; j<mDimension; j++)                                   //  through are identical -> no noise,
505
          baseV[i+1][j]= 0.0f;                                            //  set the base to 0 vectors.
506
      }                                                                   ///
507 649544b8 Leszek Koltunski
    else
508
      {
509 6a2ebb18 Leszek Koltunski
      for(int i=1; i<mDimension; i++)                                     /// One iteration computes baseV[i][*]
510
        {                                                                 //  (aka b[i]), the i-th orthonormal vector.
511
        buf[i-1]=0.0f;                                                    //
512
                                                                          //  We can use (modified!) Gram-Schmidt.
513
        for(int k=0; k<mDimension; k++)                                   //
514
          {                                                               //
515
          if( i>=2 )                                                      //  b[0] = b[0]
516
            {                                                             //  b[1] = b[1] - (<b[1],b[0]>/<b[0],b[0]>)*b[0]
517
            old[k] = baseV[i][k];                                         //  b[2] = b[2] - (<b[2],b[0]>/<b[0],b[0]>)*b[0] - (<b[2],b[1]>/<b[1],b[1]>)*b[1]
518
            baseV[i][k]= (k==i-(last_non_zero>=i?1:0)) ? 1.0f : 0.0f;     //  b[3] = b[3] - (<b[3],b[0]>/<b[0],b[0]>)*b[0] - (<b[3],b[1]>/<b[1],b[1]>)*b[1] - (<b[3],b[2]>/<b[2],b[2]>)*b[2]
519
            }                                                             //  (...)
520
                                                                          //  then b[i] = b[i] / |b[i]|  ( Here really b[i] = b[i] / (|b[0]|/|b[i]|)
521
          tmp = baseV[i-1][k];                                            //
522
          buf[i-1] += tmp*tmp;                                            //
523
          }                                                               //
524
                                                                          //
525
        for(int j=0; j<i; j++)                                            //
526
          {                                                               //
527
          tmp = 0.0f;                                                     //
528
          for(int k=0;k<mDimension; k++) tmp += baseV[i][k]*baseV[j][k];  //
529
          tmp /= buf[j];                                                  //
530
          for(int k=0;k<mDimension; k++) baseV[i][k] -= tmp*baseV[j][k];  //
531
          }                                                               //
532
                                                                          //
533
        checkAngle(i);                                                    //
534
        }                                                                 /// end compute baseV[i][*]
535
536
      buf[mDimension-1]=0.0f;                                             /// Normalize
537
      for(int k=0; k<mDimension; k++)                                     //
538
        {                                                                 //
539
        tmp = baseV[mDimension-1][k];                                     //
540
        buf[mDimension-1] += tmp*tmp;                                     //
541
        }                                                                 //
542
                                                                          //
543
      for(int i=1; i<mDimension; i++)                                     //
544
        {                                                                 //
545
        tmp = (float)Math.sqrt(buf[0]/buf[i]);                            //
546
        for(int k=0;k<mDimension; k++) baseV[i][k] *= tmp;                //
547
        }                                                                 /// End Normalize
548 649544b8 Leszek Koltunski
      }
549
550 6a2ebb18 Leszek Koltunski
//lastNon = last_non_zero;
551
552 649544b8 Leszek Koltunski
    //printBase("end");
553
    //checkBase();
554
    }
555
556 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
557
// internal debugging only!
558
  
559 a4835695 Leszek Koltunski
  public String print()
560 6a06a912 Leszek Koltunski
    {
561
    return "duration="+mDuration+" count="+mCount+" Noise="+mNoise+" numVectors="+numPoints+" mMode="+mMode;
562
    }
563 3002bef3 Leszek Koltunski
564 6a06a912 Leszek Koltunski
///////////////////////////////////////////////////////////////////////////////////////////////////
565 3002bef3 Leszek Koltunski
566 6a06a912 Leszek Koltunski
  abstract void interpolate(float[] buffer, int offset, float time);
567
568
///////////////////////////////////////////////////////////////////////////////////////////////////
569
// PUBLIC API
570
///////////////////////////////////////////////////////////////////////////////////////////////////
571 8c893ffc Leszek Koltunski
572 6a06a912 Leszek Koltunski
/**
573
 * Sets the mode of the interpolation to Loop, Path or Jump.
574
 * <ul>
575
 * <li>Loop is when we go from the first point all the way to the last, and the back to the first through 
576
 * the shortest way.
577
 * <li>Path is when we come back from the last point back to the first the same way we got there.
578
 * <li>Jump is when we go from first to last and then jump back to the first.
579
 * </ul>
580
 * 
581 568b29d8 Leszek Koltunski
 * @param mode {@link Dynamic#MODE_LOOP}, {@link Dynamic#MODE_PATH} or {@link Dynamic#MODE_JUMP}.
582 6a06a912 Leszek Koltunski
 */
583
584
  public void setMode(int mode)
585
    {
586
    mMode = mode;  
587
    }
588
589
///////////////////////////////////////////////////////////////////////////////////////////////////
590
/**
591 ea16dc89 Leszek Koltunski
 * Returns the number of Statics this Dynamic has been fed with.
592 6a06a912 Leszek Koltunski
 *   
593 ea16dc89 Leszek Koltunski
 * @return the number of Statics we are currently interpolating through.
594 6a06a912 Leszek Koltunski
 */
595
  public synchronized int getNumPoints()
596
    {
597
    return numPoints;  
598
    }
599
600
///////////////////////////////////////////////////////////////////////////////////////////////////
601
/**
602
 * Controls how many times we want to interpolate.
603
 * <p>
604 ea16dc89 Leszek Koltunski
 * Count equal to 1 means 'go from the first Static to the last and back'. Does not have to be an
605 6a06a912 Leszek Koltunski
 * integer - i.e. count=1.5 would mean 'start at the first Point, go to the last, come back to the first, 
606
 * go to the last again and stop'.
607
 * Count<=0 means 'go on interpolating indefinitely'.
608
 * 
609 ea16dc89 Leszek Koltunski
 * @param count the number of times we want to interpolate between our collection of Statics.
610 6a06a912 Leszek Koltunski
 */
611
  public void setCount(float count)
612
    {
613
    mCount = count;  
614
    }
615
616
///////////////////////////////////////////////////////////////////////////////////////////////////
617
/**
618
 * Sets the time it takes to do one full interpolation.
619
 * 
620
 * @param duration Time, in milliseconds, it takes to do one full interpolation, i.e. go from the first 
621
 *                 Point to the last and back. 
622
 */
623
  
624
  public void setDuration(long duration)
625
    {
626
    mDuration = duration;
627
    }
628
629
///////////////////////////////////////////////////////////////////////////////////////////////////
630
// end of DistortedInterpolator
631
  }