Project

General

Profile

« Previous | Next » 

Revision 649544b8

Added by Leszek Koltunski almost 10 years ago

Completely redesign Noise in the Dynamics and move all the complexity to the parent class.

something does not work with it now :)

View differences:

src/main/java/org/distorted/library/type/Dynamic.java
102 102

  
103 103
  protected Vector<VectorNoise> vn;
104 104
  protected float[] mFactor;
105
  protected float[][] baseV;
106
  private float[] buffer;
107

  
108
  ///////////////////////////////////////////////////////////////////////////////////////////////////
109
  // the coefficients of the X(t), Y(t) and Z(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx  etc.
110
  // (tangent) is the vector tangent to the path.
111
  // (cached) is the original vector from vv (copied here so when interpolating we can see if it is
112
  // still valid and if not - rebuild the Cache
113

  
114
  protected class VectorCache
115
    {
116
    float[] a;
117
    float[] b;
118
    float[] c;
119
    float[] d;
120
    float[] tangent;
121
    float[] cached;
122

  
123
    VectorCache(int dim)
124
      {
125
      a = new float[dim];
126
      b = new float[dim];
127
      c = new float[dim];
128
      d = new float[dim];
129
      tangent = new float[dim];
130
      cached = new float[dim];
131
      }
132
    }
133

  
134
  protected Vector<VectorCache> vc;
135
  protected VectorCache tmp1, tmp2;
105 136

  
106 137
///////////////////////////////////////////////////////////////////////////////////////////////////
107 138
// hide this from Javadoc
108 139
  
109
  Dynamic()
140
  protected Dynamic()
141
    {
142
    }
143

  
144
///////////////////////////////////////////////////////////////////////////////////////////////////
145

  
146
  protected Dynamic(int duration, float count, int dimension)
110 147
    {
148
    vc = new Vector<>();
149
    vn = null;
150
    numPoints = 0;
151
    cacheDirty = false;
152
    mMode = MODE_LOOP;
153
    mDuration = duration;
154
    mCount = count;
155
    mDimension = dimension;
156

  
157
    baseV = new float[mDimension][mDimension];
158
    buffer= new float[mDimension];
111 159
    }
112 160

  
113 161
///////////////////////////////////////////////////////////////////////////////////////////////////
......
194 242
      }
195 243
    }
196 244

  
245
///////////////////////////////////////////////////////////////////////////////////////////////////
246
// debugging only
247

  
248
  private void printBase(String str)
249
    {
250
    String s;
251
    float t;
252

  
253
    for(int i=0; i<mDimension; i++)
254
      {
255
      s = "";
256

  
257
      for(int j=0; j<mDimension; j++)
258
        {
259
        t = ((int)(1000*baseV[i][j]))/(1000.0f);
260
        s+=(" "+t);
261
        }
262
      android.util.Log.e("dynamic", str+" base "+i+" : " + s);
263
      }
264
    }
265

  
266
///////////////////////////////////////////////////////////////////////////////////////////////////
267
// debugging only
268

  
269
  private void checkBase()
270
    {
271
    float tmp;
272

  
273
    for(int i=0; i<mDimension; i++)
274
      for(int j=i+1; j<mDimension; j++)
275
        {
276
        tmp = 0.0f;
277

  
278
        for(int k=0; k<mDimension; k++)
279
          {
280
          tmp += baseV[i][k]*baseV[j][k];
281
          }
282

  
283
        android.util.Log.e("dynamic", "vectors "+i+" and "+j+" : "+tmp);
284
        }
285

  
286
    for(int i=0; i<mDimension; i++)
287
      {
288
      tmp = 0.0f;
289

  
290
      for(int k=0; k<mDimension; k++)
291
        {
292
        tmp += baseV[i][k]*baseV[i][k];
293
        }
294

  
295
      android.util.Log.e("dynamic", "length of vector "+i+" : "+Math.sqrt(tmp));
296
      }
297
    }
298

  
299
///////////////////////////////////////////////////////////////////////////////////////////////////
300
// helper function in case we are interpolating through exactly 2 points
301

  
302
  protected void computeOrthonormalBase2(Static1D curr, Static1D next)
303
    {
304
    switch(mDimension)
305
      {
306
      case 1: baseV[0][0] = (next.x-curr.x);
307
              break;
308
      case 2: Static2D curr2 = (Static2D)curr;
309
              Static2D next2 = (Static2D)next;
310
              baseV[0][0] = (next2.x-curr2.x);
311
              baseV[0][1] = (next2.y-curr2.y);
312
              break;
313
      case 3: Static3D curr3 = (Static3D)curr;
314
              Static3D next3 = (Static3D)next;
315
              baseV[0][0] = (next3.x-curr3.x);
316
              baseV[0][1] = (next3.y-curr3.y);
317
              baseV[0][2] = (next3.z-curr3.z);
318
              break;
319
      case 4: Static4D curr4 = (Static4D)curr;
320
              Static4D next4 = (Static4D)next;
321
              baseV[0][0] = (next4.x-curr4.x);
322
              baseV[0][1] = (next4.y-curr4.y);
323
              baseV[0][2] = (next4.z-curr4.z);
324
              baseV[0][3] = (next4.w-curr4.w);
325
              break;
326
      case 5: Static5D curr5 = (Static5D)curr;
327
              Static5D next5 = (Static5D)next;
328
              baseV[0][0] = (next5.x-curr5.x);
329
              baseV[0][1] = (next5.y-curr5.y);
330
              baseV[0][2] = (next5.z-curr5.z);
331
              baseV[0][3] = (next5.w-curr5.w);
332
              baseV[0][4] = (next5.v-curr5.v);
333
              break;
334
      default: throw new RuntimeException("Unsupported dimension");
335
      }
336

  
337
    if( baseV[0][0] == 0.0f )
338
      {
339
      baseV[1][0] = 1.0f;
340
      baseV[1][1] = 0.0f;
341
      }
342
    else
343
      {
344
      baseV[1][0] = 0.0f;
345
      baseV[1][1] = 1.0f;
346
      }
347

  
348
    for(int i=2; i<mDimension; i++)
349
      {
350
      baseV[1][i] = 0.0f;
351
      }
352

  
353
    computeOrthonormalBase();
354
    }
355

  
356
///////////////////////////////////////////////////////////////////////////////////////////////////
357
// helper function in case we are interpolating through more than 2 points
358

  
359
  protected void computeOrthonormalBaseMore(float time,VectorCache vc)
360
    {
361
    for(int i=0; i<mDimension; i++)
362
      {
363
      baseV[0][i] = (3*vc.a[i]*time+2*vc.b[i])*time+vc.c[i];
364
      baseV[1][i] =  6*vc.a[i]*time+2*vc.b[i];
365
      }
366

  
367
    computeOrthonormalBase();
368
    }
369

  
370
///////////////////////////////////////////////////////////////////////////////////////////////////
371
// When this function gets called, baseV[0] and baseV[1] should have been filled with two mDimension-al
372
// vectors. This function then fills the rest of the baseV array with a mDimension-al Orthonormal base.
373
// (mDimension-2 vectors, pairwise orthogonal to each other and to the original 2). The function always
374
// leaves base[0] alone but generally speaking must adjust base[1] to make it orthogonal to base[0]!
375
// The whole baseV is then used to compute Noise.
376
//
377
// When computing noise of a point travelling along a N-dimensional path, there are three cases:
378
// a) we may be interpolating through 1 point, i.e. standing in place - nothing to do in this case
379
// b) we may be interpolating through 2 points, i.e. travelling along a straight line between them -
380
//    then pass the velocity vector in baseV[0] and anything linearly independent in base[1].
381
//    The output will then be discontinuous in dimensions>2 (sad corollary from the Hairy Ball Theorem)
382
//    but we don't care - we are travelling along a straight line, so velocity (aka baseV[0]!) does
383
//    not change.
384
// c) we may be interpolating through more than 2 points. Then interpolation formulas ensure the path
385
//    will never be a straight line, even locally -> we can pass in baseV[0] and baseV[1] the velocity
386
//    and the acceleration (first and second derivatives of the path) which are then guaranteed to be
387
//    linearly independent. Then we can ensure this is continuous in dimensions <=4. This leaves
388
//    dimension 5 (ATM WAVE is 5-dimensional) discontinuous -> WAVE will suffer from chaotic noise.
389
//
390
// Bear in mind here the 'normal' in 'orthonormal' means 'length equal to the length of the original
391
// velocity vector' (rather than the standard 1)
392

  
393
  protected void computeOrthonormalBase()
394
    {
395
    int non_zeros=0;
396
    int last_non_zero=-1;
397
    float value;
398
    for(int i=0; i<mDimension; i++)
399
      {
400
      value = baseV[0][i];
401

  
402
      if( value != 0.0f )
403
        {
404
        non_zeros++;
405
        last_non_zero=i;
406
        }
407
      }
408
                         // velocity is the 0 vector -> two consecutive points we are interpolating
409
    if( non_zeros==0 )   // through are identical -> no noise, set the base to 0 vectors.
410
      {
411
      for(int i=0; i<mDimension-1; i++)
412
        for(int j=0; j<mDimension; j++)
413
          baseV[i+1][j]= 0.0f;
414
      }
415
    else
416
      {
417
      for(int i=0; i<mDimension-1; i++)
418
        for(int j=0; j<mDimension; j++)
419
          {
420
          if( (i<last_non_zero && j==i) || (i>=last_non_zero && j==i+1) )
421
            baseV[i+1][j]= baseV[0][last_non_zero];
422
          else
423
            baseV[i+1][j]= 0.0f;
424
          }
425

  
426
      // That's it if velocity vector is already one of the standard orthonormal
427
      // vectors. Otherwise (i.e. non_zeros>1) velocity is linearly independent
428
      // to what's in baseV right now and we can use (modified!) Gram-Schmidt.
429
      //
430
      // b[0] = b[0]
431
      // b[1] = b[1] - (<b[1],b[0]>/<b[0],b[0]>)*b[0]
432
      // b[2] = b[2] - (<b[2],b[0]>/<b[0],b[0]>)*b[0] - (<b[2],b[1]>/<b[1],b[1]>)*b[1]
433
      // 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]
434
      //
435
      // then b[i] = b[i] / |b[i]|
436

  
437
      if( non_zeros>1 )
438
        {
439
        float tmp;
440

  
441
        for(int i=1; i<mDimension; i++)
442
          {
443
          buffer[i-1]=0.0f;
444

  
445
          for(int k=0; k<mDimension; k++)
446
            {
447
            value = baseV[i-1][k];
448
            buffer[i-1] += value*value;
449
            }
450

  
451
          for(int j=0; j<i; j++)
452
            {
453
            tmp = 0.0f;
454

  
455
            for(int k=0;k<mDimension; k++)
456
              {
457
              tmp += baseV[i][k]*baseV[j][k];
458
              }
459

  
460
            tmp /= buffer[j];
461

  
462
            for(int k=0;k<mDimension; k++)
463
              {
464
              baseV[i][k] -= tmp*baseV[j][k];
465
              }
466
            }
467
          }
468

  
469
        buffer[mDimension-1]=0.0f;
470
        for(int k=0; k<mDimension; k++)
471
          {
472
          value = baseV[mDimension-1][k];
473
          buffer[mDimension-1] += value*value;
474
          }
475

  
476
        for(int i=1; i<mDimension; i++)
477
          {
478
          tmp = (float)Math.sqrt(buffer[0]/buffer[i]);
479

  
480
          for(int k=0;k<mDimension; k++)
481
            {
482
            baseV[i][k] *= tmp;
483
            }
484
          }
485
        }
486
      }
487

  
488
    //printBase("end");
489
    //checkBase();
490
    }
491

  
197 492
///////////////////////////////////////////////////////////////////////////////////////////////////
198 493
// internal debugging only!
199 494
  
src/main/java/org/distorted/library/type/Dynamic1D.java
29 29

  
30 30
public class Dynamic1D extends Dynamic implements Data1D
31 31
  {
32
  
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34
// the coefficients of the X(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx  etc.
35
// (x) is the vector tangent to the path.
36
// (vx) is the original vector from vv (copied here so when interpolating we can see if it is 
37
// still valid and if not - rebuild the Cache
38
   
39
  private class VectorCache
40
    {
41
    float ax, bx, cx, dx;
42
   
43
    float x;
44
    float vx;
45
    }
46

  
47
  private Vector<VectorCache> vc;
48
  private VectorCache tmp1, tmp2;
49
 
50 32
  private Vector<Static1D> vv;
51 33
  private Static1D prev, curr, next;
52 34

  
......
75 57
      
76 58
      if( q>1 )
77 59
        {
78
        tmp1.x = nx+px/q;
60
        tmp1.tangent[0] = nx+px/q;
79 61
        }
80 62
      else
81 63
        {
82
        tmp1.x = px+nx*q;
64
        tmp1.tangent[0] = px+nx*q;
83 65
        }
84 66
      }
85 67
    else
86 68
      {
87
      tmp1.x = 0.0f;
69
      tmp1.tangent[0] = 0.0f;
88 70
      }
89 71
    }
90 72
      
......
97 79
      tmp1= vc.elementAt(0);
98 80
      curr= vv.elementAt(0);
99 81
        
100
      tmp1.ax = 0.0f;
101
      tmp1.bx = 0.0f;
102
      tmp1.cx = curr.x;
103
      tmp1.dx = 0.0f;
82
      tmp1.a[0] = 0.0f;
83
      tmp1.b[0] = 0.0f;
84
      tmp1.c[0] = curr.x;
85
      tmp1.d[0] = 0.0f;
104 86
      }
105 87
    else if( numPoints==2 )
106 88
      {
......
109 91
      curr= vv.elementAt(0);
110 92
      next= vv.elementAt(1);
111 93
          
112
      tmp1.ax = 0.0f;
113
      tmp1.bx = 0.0f;
114
      tmp1.cx = next.x - curr.x;
115
      tmp1.dx = curr.x;
94
      tmp1.a[0] = 0.0f;
95
      tmp1.b[0] = 0.0f;
96
      tmp1.c[0] = next.x - curr.x;
97
      tmp1.d[0] = curr.x;
116 98
      
117
      tmp2.ax = 0.0f;
118
      tmp2.bx = 0.0f;
119
      tmp2.cx = curr.x - next.x;
120
      tmp2.dx = next.x;
99
      tmp2.a[0] = 0.0f;
100
      tmp2.b[0] = 0.0f;
101
      tmp2.c[0] = curr.x - next.x;
102
      tmp2.d[0] = next.x;
121 103
      }
122 104
    else
123 105
      {
......
134 116
        curr= vv.elementAt(i);
135 117
        next= vv.elementAt(n);
136 118
    
137
        tmp1.vx = curr.x;
119
        tmp1.cached[0] = curr.x;
138 120
        
139
        tmp1.ax =  2*curr.x +   tmp1.x - 2*next.x + tmp2.x;
140
        tmp1.bx = -3*curr.x - 2*tmp1.x + 3*next.x - tmp2.x;
141
        tmp1.cx = tmp1.x;
142
        tmp1.dx = curr.x;
121
        tmp1.a[0] =  2*curr.x +   tmp1.tangent[0] - 2*next.x + tmp2.tangent[0];
122
        tmp1.b[0] = -3*curr.x - 2*tmp1.tangent[0] + 3*next.x - tmp2.tangent[0];
123
        tmp1.c[0] = tmp1.tangent[0];
124
        tmp1.d[0] = curr.x;
143 125
        }
144 126
      }
145 127
   
......
154 136
 */
155 137
  public Dynamic1D()
156 138
    {
157
    this(0,0.5f);
139
    super(0,0.5f,1);
140
    vv = new Vector<>();
158 141
    }
159 142

  
160 143
///////////////////////////////////////////////////////////////////////////////////////////////////
......
169 152
 */
170 153
  public Dynamic1D(int duration, float count)
171 154
    {
155
    super(duration,count,1);
172 156
    vv = new Vector<>();
173
    vc = new Vector<>();
174
    vn = null;
175
    numPoints = 0;
176
    cacheDirty = false;
177
    mMode = MODE_LOOP;
178
    mDuration = duration;
179
    mCount = count;
180
    mDimension = 1;
181 157
    }
182 158

  
183 159
///////////////////////////////////////////////////////////////////////////////////////////////////
......
237 213
        {
238 214
        case 0: 
239 215
        case 1: break;
240
        case 2: vc.add(new VectorCache());
241
                vc.add(new VectorCache());
242
                vc.add(new VectorCache());
216
        case 2: vc.add(new VectorCache(1));
217
                vc.add(new VectorCache(1));
218
                vc.add(new VectorCache(1));
243 219
                cacheDirty = true;
244 220
                break;
245
        default:vc.add(new VectorCache());
221
        default:vc.add(new VectorCache(1));
246 222
                cacheDirty = true;
247 223
        }
248 224
     
......
269 245
        {
270 246
        case 0:
271 247
        case 1: break;
272
        case 2: vc.add(new VectorCache());
273
                vc.add(new VectorCache());
274
                vc.add(new VectorCache());
248
        case 2: vc.add(new VectorCache(1));
249
                vc.add(new VectorCache(1));
250
                vc.add(new VectorCache(1));
275 251
                cacheDirty = true;
276 252
                break;
277
        default:vc.add(location,new VectorCache());
253
        default:vc.add(location,new VectorCache(1));
278 254
                cacheDirty = true;
279 255
        }
280 256
      
......
437 413
                  next = vv.elementAt(vecNext);
438 414
                  tmp2 = vc.elementAt(vecNext);
439 415
              
440
                  if( tmp2.vx!=next.x ) recomputeCache();
416
                  if( tmp2.cached[0]!=next.x ) recomputeCache();
441 417
                  }
442 418
             
443 419
                if( vn!=null )
......
446 422
                  }
447 423
            
448 424
                tmp1 = vc.elementAt(vecCurr);
449
                buffer[offset] = ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx;
425
                buffer[offset] = ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0];
450 426
                break;
451 427
                }
452 428
        }
src/main/java/org/distorted/library/type/Dynamic2D.java
29 29

  
30 30
public class Dynamic2D extends Dynamic implements Data2D
31 31
  {
32

  
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34
// the coefficients of the X(t), Y(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx  etc.
35
// (x,y) is the vector tangent to the path.
36
// (vx,vy) is the original vector from vv (copied here so when interpolating we can see if it is 
37
// still valid and if not - rebuild the Cache
38
  
39
  private class VectorCache
40
    {
41
    float ax, bx, cx, dx;
42
    float ay, by, cy, dy;
43
   
44
    float x,y;
45
    float vx,vy;
46
    }
47

  
48
  private Vector<VectorCache> vc;
49
  private VectorCache tmp1, tmp2;
50
   
51 32
  private Vector<Static2D> vv;
52 33
  private Static2D prev, curr, next;
53 34

  
......
78 59
      
79 60
      if( q>1 )
80 61
        {
81
        tmp1.x = nx+px/q;
82
        tmp1.y = ny+py/q;
62
        tmp1.tangent[0] = nx+px/q;
63
        tmp1.tangent[1] = ny+py/q;
83 64
        }
84 65
      else
85 66
        {
86
        tmp1.x = px+nx*q;
87
        tmp1.y = py+ny*q;
67
        tmp1.tangent[0] = px+nx*q;
68
        tmp1.tangent[1] = py+ny*q;
88 69
        }
89 70
      }
90 71
    else
91 72
      {
92
      tmp1.x = 0.0f;
93
      tmp1.y = 0.0f;
73
      tmp1.tangent[0] = 0.0f;
74
      tmp1.tangent[1] = 0.0f;
94 75
      }
95 76
    }
96 77
   
......
103 84
      tmp1= vc.elementAt(0);
104 85
      curr= vv.elementAt(0);
105 86
              
106
      tmp1.ax = tmp1.ay = 0.0f;
107
      tmp1.bx = tmp1.by = 0.0f;
108
      tmp1.cx = curr.x;
109
      tmp1.cy = curr.y;
110
      tmp1.dx = tmp1.dy = 0.0f;
87
      tmp1.a[0] = tmp1.a[1] = 0.0f;
88
      tmp1.b[0] = tmp1.b[1] = 0.0f;
89
      tmp1.c[0] = curr.x;
90
      tmp1.c[1] = curr.y;
91
      tmp1.d[0] = tmp1.d[1] = 0.0f;
111 92
      }
112 93
    else if( numPoints==2 )
113 94
      {
......
116 97
      curr= vv.elementAt(0);
117 98
      next= vv.elementAt(1);
118 99
          
119
      tmp1.ax = tmp1.ay = 0.0f;
120
      tmp1.bx = tmp1.by = 0.0f;
121
      tmp1.cx = next.x - curr.x;
122
      tmp1.cy = next.y - curr.y;
123
      tmp1.dx = curr.x;
124
      tmp1.dy = curr.y;
100
      tmp1.a[0] = tmp1.a[1] = 0.0f;
101
      tmp1.b[0] = tmp1.b[1] = 0.0f;
102
      tmp1.c[0] = next.x - curr.x;
103
      tmp1.c[1] = next.y - curr.y;
104
      tmp1.d[0] = curr.x;
105
      tmp1.d[1] = curr.y;
125 106
      
126
      tmp2.ax = tmp2.ay = 0.0f;
127
      tmp2.bx = tmp2.by = 0.0f;
128
      tmp2.cx = curr.x - next.x;
129
      tmp2.cy = curr.y - next.y;
130
      tmp2.dx = next.x;
131
      tmp2.dy = next.y;
107
      tmp2.a[0] = tmp2.a[1] = 0.0f;
108
      tmp2.b[0] = tmp2.b[1] = 0.0f;
109
      tmp2.c[0] = curr.x - next.x;
110
      tmp2.c[1] = curr.y - next.y;
111
      tmp2.d[0] = next.x;
112
      tmp2.d[1] = next.y;
132 113
      }
133 114
    else
134 115
      {
......
145 126
        curr= vv.elementAt(i);
146 127
        next= vv.elementAt(n);
147 128
      
148
        tmp1.vx = curr.x;
149
        tmp1.vy = curr.y;
150
        
151
        tmp1.ax =  2*curr.x +   tmp1.x - 2*next.x + tmp2.x;
152
        tmp1.bx = -3*curr.x - 2*tmp1.x + 3*next.x - tmp2.x;
153
        tmp1.cx = tmp1.x;
154
        tmp1.dx = curr.x;
155
      
156
        tmp1.ay =  2*curr.y +   tmp1.y - 2*next.y + tmp2.y;
157
        tmp1.by = -3*curr.y - 2*tmp1.y + 3*next.y - tmp2.y;
158
        tmp1.cy = tmp1.y;
159
        tmp1.dy = curr.y;
129
        tmp1.cached[0] = curr.x;
130
        tmp1.cached[1] = curr.y;
131

  
132
        tmp1.a[0] =  2*curr.x +   tmp1.tangent[0] - 2*next.x + tmp2.tangent[0];
133
        tmp1.b[0] = -3*curr.x - 2*tmp1.tangent[0] + 3*next.x - tmp2.tangent[0];
134
        tmp1.c[0] = tmp1.tangent[0];
135
        tmp1.d[0] = curr.x;
136

  
137
        tmp1.a[1] =  2*curr.y +   tmp1.tangent[1] - 2*next.y + tmp2.tangent[1];
138
        tmp1.b[1] = -3*curr.y - 2*tmp1.tangent[1] + 3*next.y - tmp2.tangent[1];
139
        tmp1.c[1] = tmp1.tangent[1];
140
        tmp1.d[1] = curr.y;
160 141
        }
161 142
      }
162 143
    
......
171 152
 */
172 153
  public Dynamic2D()
173 154
    {
174
    this(0,0.5f);
155
    super(0,0.5f,2);
156
    vv = new Vector<>();
175 157
    }
176 158

  
177 159
///////////////////////////////////////////////////////////////////////////////////////////////////
......
186 168
 */
187 169
  public Dynamic2D(int duration, float count)
188 170
    {
171
    super(duration,count,2);
189 172
    vv = new Vector<>();
190
    vc = new Vector<>();
191
    vn = null;
192
    numPoints = 0;
193
    cacheDirty = false;
194
    mMode = MODE_LOOP;
195
    mDuration = duration;
196
    mCount = count;
197
    mDimension = 2;
198 173
    }
199 174

  
200 175
///////////////////////////////////////////////////////////////////////////////////////////////////
......
254 229
        {
255 230
        case 0:
256 231
        case 1: break;
257
        case 2: vc.add(new VectorCache());
258
                vc.add(new VectorCache());
259
                vc.add(new VectorCache());
232
        case 2: vc.add(new VectorCache(2));
233
                vc.add(new VectorCache(2));
234
                vc.add(new VectorCache(2));
260 235
                break;
261
        default:vc.add(new VectorCache());
236
        default:vc.add(new VectorCache(2));
262 237
        }
263 238
     
264 239
      numPoints++;
......
285 260
        {
286 261
        case 0:
287 262
        case 1: break;
288
        case 2: vc.add(new VectorCache());
289
                vc.add(new VectorCache());
290
                vc.add(new VectorCache());
263
        case 2: vc.add(new VectorCache(2));
264
                vc.add(new VectorCache(2));
265
                vc.add(new VectorCache(2));
291 266
                break;
292
        default:vc.add(location,new VectorCache());
267
        default:vc.add(location,new VectorCache(2));
293 268
        }
294 269
      
295 270
      numPoints++;
......
417 392
                {
418 393
                time = noise(time,0);
419 394
              
420
                float dx2 = next.x-curr.x;
421
                float dy2 = next.y-curr.y;
395
                baseV[0][0] = next.x-curr.x;
396
                baseV[0][1] = next.y-curr.y;
422 397
   
423
                buffer[offset  ] = dx2*time + curr.x +dy2*mFactor[0];
424
                buffer[offset+1] = dy2*time + curr.y -dx2*mFactor[0];
398
                buffer[offset  ] = baseV[0][0]*time + curr.x +baseV[0][0]*mFactor[0];
399
                buffer[offset+1] = baseV[0][1]*time + curr.y -baseV[0][1]*mFactor[0];
425 400
                }
426 401
              else
427 402
                {
......
468 443
                  next = vv.elementAt(vecNext);
469 444
                  tmp2 = vc.elementAt(vecNext);
470 445
              
471
                  if( tmp2.vx!=next.x || tmp2.vy!=next.y ) recomputeCache();
446
                  if( tmp2.cached[0]!=next.x || tmp2.cached[1]!=next.y ) recomputeCache();
472 447
                  }
473
              
448

  
449
                tmp1 = vc.elementAt(vecCurr);
450

  
474 451
                if( vn!=null )
475 452
                  {
476 453
                  time = noise(time,vecCurr);
477
                  tmp1 = vc.elementAt(vecCurr);
478
               
479
                  float dx2 = (3*tmp1.ax*time+2*tmp1.bx)*time + tmp1.cx;
480
                  float dy2 = (3*tmp1.ay*time+2*tmp1.by)*time + tmp1.cy;
454

  
455
                  baseV[0][0] = (3*tmp1.a[0]*time+2*tmp1.b[0])*time + tmp1.c[0];
456
                  baseV[0][1] = (3*tmp1.a[1]*time+2*tmp1.b[1])*time + tmp1.c[1];
481 457
                 
482
                  buffer[offset  ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx +dy2*mFactor[0];
483
                  buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy -dx2*mFactor[0];
458
                  buffer[offset  ]= ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0] +baseV[0][0]*mFactor[0];
459
                  buffer[offset+1]= ((tmp1.a[1]*time+tmp1.b[1])*time+tmp1.c[1])*time+tmp1.d[1] -baseV[0][1]*mFactor[0];
484 460
                  } 
485 461
                else
486 462
                  {
487
                  tmp1 = vc.elementAt(vecCurr);
488
                  buffer[offset  ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx;
489
                  buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy;
463
                  buffer[offset  ]= ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0];
464
                  buffer[offset+1]= ((tmp1.a[1]*time+tmp1.b[1])*time+tmp1.c[1])*time+tmp1.d[1];
490 465
                  }
491 466
                
492 467
                break;
src/main/java/org/distorted/library/type/Dynamic3D.java
29 29

  
30 30
public class Dynamic3D extends Dynamic implements Data3D
31 31
  {
32
 
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34
// the coefficients of the X(t), Y(t) and Z(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx  etc.
35
// (x,y,z) is the vector tangent to the path.
36
// (vx,vy,vz) is the original vector from vv (copied here so when interpolating we can see if it is 
37
// still valid and if not - rebuild the Cache
38
  
39
  private class VectorCache
40
    {
41
    float ax, bx, cx, dx;
42
    float ay, by, cy, dy;
43
    float az, bz, cz, dz;
44
   
45
    float x,y,z;
46
    float vx,vy,vz;
47
    }
48

  
49
  private Vector<VectorCache> vc;
50
  private VectorCache tmp1, tmp2;
51

  
52 32
  private Vector<Static3D> vv;
53 33
  private Static3D prev, curr, next;
54 34

  
55
  private float vec1X,vec1Y,vec1Z;   // vector perpendicular to v(t) and in the same plane as v(t) and a(t) (for >2 points only, in case of 2 points this is calculated differently)
56
  private float vec2X,vec2Y,vec2Z;   // vector perpendicular to v(t0 and to vec1.
57

  
58 35
///////////////////////////////////////////////////////////////////////////////////////////////////
59 36
// no array bounds checking!
60 37
  
......
84 61
      
85 62
      if( q>1 )
86 63
        {
87
        tmp1.x = nx+px/q;
88
        tmp1.y = ny+py/q;
89
        tmp1.z = nz+pz/q;
64
        tmp1.tangent[0] = nx+px/q;
65
        tmp1.tangent[1] = ny+py/q;
66
        tmp1.tangent[2] = nz+pz/q;
90 67
        }
91 68
      else
92 69
        {
93
        tmp1.x = px+nx*q;
94
        tmp1.y = py+ny*q;
95
        tmp1.z = pz+nz*q;
70
        tmp1.tangent[0] = px+nx*q;
71
        tmp1.tangent[1] = py+ny*q;
72
        tmp1.tangent[2] = pz+nz*q;
96 73
        }
97 74
      }
98 75
    else
99 76
      {
100
      tmp1.x = 0.0f;
101
      tmp1.y = 0.0f;
102
      tmp1.z = 0.0f;  
77
      tmp1.tangent[0] = 0.0f;
78
      tmp1.tangent[1] = 0.0f;
79
      tmp1.tangent[2] = 0.0f;
103 80
      }
104 81
    }
105 82
    
......
112 89
      tmp1= vc.elementAt(0);
113 90
      curr= vv.elementAt(0);
114 91
        
115
      tmp1.ax = tmp1.ay = tmp1.az = 0.0f;
116
      tmp1.bx = tmp1.by = tmp1.bz = 0.0f;
117
      tmp1.cx = curr.x;
118
      tmp1.cy = curr.y;
119
      tmp1.cz = curr.z;
120
      tmp1.dx = tmp1.dy = tmp1.dz = 0.0f;
92
      tmp1.a[0] = tmp1.a[1] = tmp1.a[2] = 0.0f;
93
      tmp1.b[0] = tmp1.b[1] = tmp1.b[2] = 0.0f;
94
      tmp1.c[0] = curr.x;
95
      tmp1.c[1] = curr.y;
96
      tmp1.c[2] = curr.z;
97
      tmp1.d[0] = tmp1.d[1] = tmp1.d[2] = 0.0f;
121 98
      }
122 99
    else if( numPoints==2 )
123 100
      {
......
126 103
      curr= vv.elementAt(0);
127 104
      next= vv.elementAt(1);
128 105
          
129
      tmp1.ax = tmp1.ay = tmp1.az = 0.0f;
130
      tmp1.bx = tmp1.by = tmp1.bz = 0.0f;
131
      tmp1.cx = next.x - curr.x;
132
      tmp1.cy = next.y - curr.y;
133
      tmp1.cz = next.z - curr.z;
134
      tmp1.dx = curr.x;
135
      tmp1.dy = curr.y;
136
      tmp1.dz = curr.z;
106
      tmp1.a[0] = tmp1.a[1] = tmp1.a[2] = 0.0f;
107
      tmp1.b[0] = tmp1.b[1] = tmp1.b[2] = 0.0f;
108
      tmp1.c[0] = next.x - curr.x;
109
      tmp1.c[1] = next.y - curr.y;
110
      tmp1.c[2] = next.z - curr.z;
111
      tmp1.d[0] = curr.x;
112
      tmp1.d[1] = curr.y;
113
      tmp1.d[2] = curr.z;
137 114
      
138
      tmp2.ax = tmp2.ay = tmp2.az = 0.0f;
139
      tmp2.bx = tmp2.by = tmp2.bz = 0.0f;
140
      tmp2.cx = curr.x - next.x;
141
      tmp2.cy = curr.y - next.y;
142
      tmp2.cz = curr.z - next.z;
143
      tmp2.dx = next.x;
144
      tmp2.dy = next.y;
145
      tmp2.dz = next.z;
115
      tmp2.a[0] = tmp2.a[1] = tmp2.a[2] = 0.0f;
116
      tmp2.b[0] = tmp2.b[1] = tmp2.b[2] = 0.0f;
117
      tmp2.c[0] = curr.x - next.x;
118
      tmp2.c[1] = curr.y - next.y;
119
      tmp2.c[2] = curr.z - next.z;
120
      tmp2.d[0] = next.x;
121
      tmp2.d[1] = next.y;
122
      tmp2.d[2] = next.z;
146 123
      }
147 124
    else
148 125
      {
......
159 136
        curr= vv.elementAt(i);
160 137
        next= vv.elementAt(n);
161 138
      
162
        tmp1.vx = curr.x;
163
        tmp1.vy = curr.y;
164
        tmp1.vz = curr.z;
139
        tmp1.cached[0] = curr.x;
140
        tmp1.cached[1] = curr.y;
141
        tmp1.cached[2] = curr.z;
165 142
        
166
        tmp1.ax =  2*curr.x +   tmp1.x - 2*next.x + tmp2.x;
167
        tmp1.bx = -3*curr.x - 2*tmp1.x + 3*next.x - tmp2.x;
168
        tmp1.cx = tmp1.x;
169
        tmp1.dx = curr.x;
143
        tmp1.a[0] =  2*curr.x +   tmp1.tangent[0] - 2*next.x + tmp2.tangent[0];
144
        tmp1.b[0] = -3*curr.x - 2*tmp1.tangent[0] + 3*next.x - tmp2.tangent[0];
145
        tmp1.c[0] = tmp1.tangent[0];
146
        tmp1.d[0] = curr.x;
170 147
      
171
        tmp1.ay =  2*curr.y +   tmp1.y - 2*next.y + tmp2.y;
172
        tmp1.by = -3*curr.y - 2*tmp1.y + 3*next.y - tmp2.y;
173
        tmp1.cy = tmp1.y;
174
        tmp1.dy = curr.y;
148
        tmp1.a[1] =  2*curr.y +   tmp1.tangent[1] - 2*next.y + tmp2.tangent[1];
149
        tmp1.b[1] = -3*curr.y - 2*tmp1.tangent[1] + 3*next.y - tmp2.tangent[1];
150
        tmp1.c[1] = tmp1.tangent[1];
151
        tmp1.d[1] = curr.y;
175 152
      
176
        tmp1.az =  2*curr.z +   tmp1.z - 2*next.z + tmp2.z;
177
        tmp1.bz = -3*curr.z - 2*tmp1.z + 3*next.z - tmp2.z;
178
        tmp1.cz = tmp1.z;
179
        tmp1.dz = curr.z;
153
        tmp1.a[2] =  2*curr.z +   tmp1.tangent[2] - 2*next.z + tmp2.tangent[2];
154
        tmp1.b[2] = -3*curr.z - 2*tmp1.tangent[2] + 3*next.z - tmp2.tangent[2];
155
        tmp1.c[2] = tmp1.tangent[2];
156
        tmp1.d[2] = curr.z;
180 157
        }
181 158
      }
182 159
   
183 160
    cacheDirty = false;
184 161
    }
185 162

  
186
///////////////////////////////////////////////////////////////////////////////////////////////////
187
// v is the speed vector (i.e. position p(t) differentiated by time)
188
// a is the acceleration vector (differentiate once more)
189
// now what we are doing is compute vec1{X,Y,Z} to be a vector perpendicular to v and in the same plane as both v and a.
190
// vec2{X,Y,Z} would be (v)x(vec1).
191
//  
192
// vec1 = a-delta*v where delta = (v*a)/|v|^2   (see Gram-Schmidt)
193
  
194
  private void setUpVectors(float time,VectorCache vc)
195
    {
196
    if( vc!=null )
197
      {
198
      float vx = (3*vc.ax*time+2*vc.bx)*time+vc.cx;
199
      float vy = (3*vc.ay*time+2*vc.by)*time+vc.cy;
200
      float vz = (3*vc.az*time+2*vc.bz)*time+vc.cz;
201
     
202
      float ax = 6*vc.ax*time+2*vc.bx;
203
      float ay = 6*vc.ay*time+2*vc.by;
204
      float az = 6*vc.az*time+2*vc.bz;
205
     
206
      float v_sq = vx*vx+vy*vy+vz*vz;
207
      float delta = (vx*ax+vy*ay+vz*az)/v_sq;
208
     
209
      vec1X = ax-delta*vx;
210
      vec1Y = ay-delta*vy;
211
      vec1Z = az-delta*vz;
212
     
213
      vec2X = vy*vec1Z-vz*vec1Y;
214
      vec2Y = vz*vec1X-vx*vec1Z;
215
      vec2Z = vx*vec1Y-vy*vec1X;
216
     
217
      float len1 = (float)Math.sqrt(v_sq/(vec1X*vec1X+vec1Y*vec1Y+vec1Z*vec1Z));
218
      float len2 = (float)Math.sqrt(v_sq/(vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z));   
219
     
220
      vec1X*=len1;
221
      vec1Y*=len1;
222
      vec1Z*=len1;
223
     
224
      vec2X*=len2;
225
      vec2Y*=len2;
226
      vec2Z*=len2;
227
      }
228
    else
229
      {
230
      curr = vv.elementAt(0);
231
      next = vv.elementAt(1); 
232
     
233
      float vx = (next.x-curr.x);
234
      float vy = (next.y-curr.y);
235
      float vz = (next.z-curr.z);
236
     
237
      float b = (float)Math.sqrt(vx*vx+vy*vy);
238
     
239
      if( b>0.0f )
240
        {
241
        vec1X = vx*vz/b;
242
        vec1Y = vy*vz/b;
243
        vec1Z = -b;
244
      
245
        vec2X = vy*vec1Z-vz*vec1Y;
246
        vec2Y = vz*vec1X-vx*vec1Z;
247
        vec2Z = vx*vec1Y-vy*vec1X;
248
       
249
        float len2 = (float)Math.sqrt((vx*vx+vy*vy+vz*vz)/(vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z));
250
       
251
        vec2X*=len2;
252
        vec2Y*=len2;
253
        vec2Z*=len2;
254
        }
255
      else
256
        {
257
        vec1X = vz;
258
        vec1Y = 0.0f;
259
        vec1Z = 0.0f;
260
      
261
        vec2X = 0.0f;
262
        vec2Y = vz;
263
        vec2Z = 0.0f;
264
        }
265
      }
266
    }
267
  
268 163
///////////////////////////////////////////////////////////////////////////////////////////////////
269 164
// PUBLIC API
270 165
///////////////////////////////////////////////////////////////////////////////////////////////////
......
273 168
 */
274 169
  public Dynamic3D()
275 170
    {
276
    this(0,0.5f);
171
    super(0,0.5f,3);
172
    vv = new Vector<>();
277 173
    }
278 174

  
279 175
///////////////////////////////////////////////////////////////////////////////////////////////////
......
288 184
 */
289 185
  public Dynamic3D(int duration, float count)
290 186
    {
187
    super(duration,count,3);
291 188
    vv = new Vector<>();
292
    vc = new Vector<>();
293
    vn = null;
294
    numPoints = 0;
295
    cacheDirty = false;
296
    mMode = MODE_LOOP;
297
    mDuration = duration;
298
    mCount = count;
299
    mDimension = 3;
300 189
    }
301 190

  
302 191
///////////////////////////////////////////////////////////////////////////////////////////////////
......
355 244
      switch(numPoints)
356 245
        {
357 246
        case 0: break;
358
        case 1: setUpVectors(0.0f,null);
247
        case 1: computeOrthonormalBase2(vv.elementAt(0),v);
359 248
                break;
360
        case 2: vc.add(new VectorCache());
361
                vc.add(new VectorCache());
362
                vc.add(new VectorCache());
249
        case 2: vc.add(new VectorCache(3));
250
                vc.add(new VectorCache(3));
251
                vc.add(new VectorCache(3));
363 252
                break;
364
        default:vc.add(new VectorCache());
253
        default:vc.add(new VectorCache(3));
365 254
        }
366 255

  
367 256
      numPoints++;
......
387 276
      switch(numPoints)
388 277
        {
389 278
        case 0: break;
390
        case 1: setUpVectors(0.0f,null);
279
        case 1: computeOrthonormalBase2(vv.elementAt(0),v);
391 280
                break;
392
        case 2: vc.add(new VectorCache());
393
                vc.add(new VectorCache());
394
                vc.add(new VectorCache());
281
        case 2: vc.add(new VectorCache(3));
282
                vc.add(new VectorCache(3));
283
                vc.add(new VectorCache(3));
395 284
                break;
396
        default:vc.add(location,new VectorCache());
285
        default:vc.add(location,new VectorCache(3));
397 286
        }
398 287

  
399 288
      numPoints++;
......
425 314
        case 1: 
426 315
        case 2: break;
427 316
        case 3: vc.removeAllElements();
428
                setUpVectors(0.0f,null);
317
                computeOrthonormalBase2(vv.elementAt(0),vv.elementAt(1));
429 318
                break;
430 319
        default:vc.remove(n);
431 320
        }
......
464 353
        case 1: 
465 354
        case 2: break;
466 355
        case 3: vc.removeAllElements();
467
                setUpVectors(0.0f,null);
356
                computeOrthonormalBase2(vv.elementAt(0),vv.elementAt(1));
468 357
                break;
469 358
        default:vc.removeElementAt(location);
470 359
        }
......
525 414
                {
526 415
                time = noise(time,0);
527 416
            
528
                buffer[offset  ] = (next.x-curr.x)*time + curr.x + (vec1X*mFactor[0] + vec2X*mFactor[1]);
529
                buffer[offset+1] = (next.y-curr.y)*time + curr.y + (vec1Y*mFactor[0] + vec2Y*mFactor[1]);
530
                buffer[offset+2] = (next.z-curr.z)*time + curr.z + (vec1Z*mFactor[0] + vec2Z*mFactor[1]);
417
                buffer[offset  ] = (next.x-curr.x)*time + curr.x + (baseV[0][0]*mFactor[0] + baseV[1][0]*mFactor[1]);
418
                buffer[offset+1] = (next.y-curr.y)*time + curr.y + (baseV[0][1]*mFactor[0] + baseV[1][1]*mFactor[1]);
419
                buffer[offset+2] = (next.z-curr.z)*time + curr.z + (baseV[0][2]*mFactor[0] + baseV[1][2]*mFactor[1]);
531 420
                }
532 421
              else
533 422
                {
......
575 464
                  next = vv.elementAt(vecNext);
576 465
                  tmp2 = vc.elementAt(vecNext);
577 466
              
578
                  if( tmp2.vx!=next.x || tmp2.vy!=next.y || tmp2.vz!=next.z ) recomputeCache();
467
                  if( tmp2.cached[0]!=next.x || tmp2.cached[1]!=next.y || tmp2.cached[2]!=next.z ) recomputeCache();
579 468
                  }
580 469
            
581 470
                tmp1 = vc.elementAt(vecCurr);
......
584 473
                  {
585 474
                  time = noise(time,vecCurr);
586 475
              
587
                  setUpVectors(time,tmp1);
476
                  computeOrthonormalBaseMore(time,tmp1);
588 477
                 
589
                  buffer[offset  ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx + (vec1X*mFactor[0] + vec2X*mFactor[1]);
590
                  buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy + (vec1Y*mFactor[0] + vec2Y*mFactor[1]);
591
                  buffer[offset+2]= ((tmp1.az*time+tmp1.bz)*time+tmp1.cz)*time+tmp1.dz + (vec1Z*mFactor[0] + vec2Z*mFactor[1]);
478
                  buffer[offset  ]= ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0] + (baseV[0][0]*mFactor[0] + baseV[1][0]*mFactor[1]);
479
                  buffer[offset+1]= ((tmp1.a[1]*time+tmp1.b[1])*time+tmp1.c[1])*time+tmp1.d[1] + (baseV[0][1]*mFactor[0] + baseV[1][1]*mFactor[1]);
480
                  buffer[offset+2]= ((tmp1.a[2]*time+tmp1.b[2])*time+tmp1.c[2])*time+tmp1.d[2] + (baseV[0][2]*mFactor[0] + baseV[1][2]*mFactor[1]);
592 481
                  }
593 482
                else
594 483
                  {
595
                  buffer[offset  ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx;
596
                  buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy;
597
                  buffer[offset+2]= ((tmp1.az*time+tmp1.bz)*time+tmp1.cz)*time+tmp1.dz;
484
                  buffer[offset  ]= ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0];
485
                  buffer[offset+1]= ((tmp1.a[1]*time+tmp1.b[1])*time+tmp1.c[1])*time+tmp1.d[1];
486
                  buffer[offset+2]= ((tmp1.a[2]*time+tmp1.b[2])*time+tmp1.c[2])*time+tmp1.d[2];
598 487
                  }
599 488
               
600 489
                break;
src/main/java/org/distorted/library/type/Dynamic4D.java
29 29

  
30 30
public class Dynamic4D extends Dynamic implements Data4D
31 31
  {
32
 
33
///////////////////////////////////////////////////////////////////////////////////////////////////
34
// the coefficients of the X(t), Y(t), Z(t), W(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx  etc.
35
// (x,y,z,w) is the vector tangent to the path.
36
// (vx,vy,vz,vw) is the original vector from vv (copied here so when interpolating we can see if it is 
37
// still valid and if not - rebuild the Cache
38
  
39
  private class VectorCache
40
    {
41
    float ax, bx, cx, dx;
42
    float ay, by, cy, dy;
43
    float az, bz, cz, dz;
44
    float aw, bw, cw, dw;
45
   
46
    float x,y,z,w;
47
    float vx,vy,vz,vw;
48
    }
49

  
50
  private Vector<VectorCache> vc;
51
  private VectorCache tmp1, tmp2;
52

  
53 32
  private Vector<Static4D> vv;
54 33
  private Static4D prev, curr, next;
55 34

  
56
  private float vec1X,vec1Y,vec1Z,vec1W;      // vector perpendicular to v(t) and in the same plane as v(t) and a(t) (for >2 points only, in case of 2 points this is calculated differently)
57
  private float vec2X,vec2Y,vec2Z,vec2W;      // vector perpendicular to v(t) and to vec1.
58
  private float vec3X,vec3Y,vec3Z,vec3W;      // vector perpendicular to v(t) and to vec1.
59

  
60 35
///////////////////////////////////////////////////////////////////////////////////////////////////
61 36
// no array bounds checking!
62 37
  
......
88 63
      
89 64
      if( q>1 )
90 65
        {
91
        tmp1.x = nx+px/q;
92
        tmp1.y = ny+py/q;
93
        tmp1.z = nz+pz/q;
94
        tmp1.w = nw+pw/q;
66
        tmp1.tangent[0] = nx+px/q;
67
        tmp1.tangent[1] = ny+py/q;
68
        tmp1.tangent[2] = nz+pz/q;
69
        tmp1.tangent[3] = nw+pw/q;
95 70
        }
96 71
      else
97 72
        {
98
        tmp1.x = px+nx*q;
99
        tmp1.y = py+ny*q;
100
        tmp1.z = pz+nz*q;
101
        tmp1.w = pw+nw*q;
73
        tmp1.tangent[0] = px+nx*q;
74
        tmp1.tangent[1] = py+ny*q;
75
        tmp1.tangent[2] = pz+nz*q;
76
        tmp1.tangent[3] = pw+nw*q;
102 77
        }
103 78
      }
104 79
    else
105 80
      {
106
      tmp1.x = 0.0f;
107
      tmp1.y = 0.0f;
108
      tmp1.z = 0.0f;  
109
      tmp1.w = 0.0f;
81
      tmp1.tangent[0] = 0.0f;
82
      tmp1.tangent[1] = 0.0f;
83
      tmp1.tangent[2] = 0.0f;
84
      tmp1.tangent[3] = 0.0f;
110 85
      }
111 86
    }
112 87
    
......
119 94
      tmp1= vc.elementAt(0);
120 95
      curr= vv.elementAt(0);
121 96
        
122
      tmp1.ax = tmp1.ay = tmp1.az = tmp1.aw = 0.0f;
123
      tmp1.bx = tmp1.by = tmp1.bz = tmp1.bw = 0.0f;
124
      tmp1.cx = curr.x;
125
      tmp1.cy = curr.y;
126
      tmp1.cz = curr.z;
127
      tmp1.cw = curr.w;
128
      tmp1.dx = tmp1.dy = tmp1.dz = tmp1.dw = 0.0f;
97
      tmp1.a[0] = tmp1.a[1] = tmp1.a[2] = tmp1.a[3] = 0.0f;
98
      tmp1.b[0] = tmp1.b[1] = tmp1.b[2] = tmp1.b[3] = 0.0f;
99
      tmp1.c[0] = curr.x;
100
      tmp1.c[1] = curr.y;
101
      tmp1.c[2] = curr.z;
102
      tmp1.c[3] = curr.w;
103
      tmp1.d[0] = tmp1.d[1] = tmp1.d[3] = tmp1.d[3] = 0.0f;
129 104
      }
130 105
    else if( numPoints==2 )
131 106
      {
......
134 109
      curr= vv.elementAt(0);
135 110
      next= vv.elementAt(1);
136 111
      
137
      tmp1.ax = tmp1.ay = tmp1.az = tmp1.aw = 0.0f;
138
      tmp1.bx = tmp1.by = tmp1.bz = tmp1.bw = 0.0f;
139
      tmp1.cx = next.x - curr.x;
140
      tmp1.cy = next.y - curr.y;
141
      tmp1.cz = next.z - curr.z;
142
      tmp1.cw = next.w - curr.w;
143
      tmp1.dx = curr.x;
144
      tmp1.dy = curr.y;
145
      tmp1.dz = curr.z;
146
      tmp1.dw = curr.w;
112
      tmp1.a[0] = tmp1.a[1] = tmp1.a[2] = tmp1.a[3] = 0.0f;
113
      tmp1.b[0] = tmp1.b[1] = tmp1.b[2] = tmp1.b[3] = 0.0f;
114
      tmp1.c[0] = next.x - curr.x;
115
      tmp1.c[1] = next.y - curr.y;
116
      tmp1.c[2] = next.z - curr.z;
117
      tmp1.c[3] = next.w - curr.w;
118
      tmp1.d[0] = curr.x;
119
      tmp1.d[1] = curr.y;
120
      tmp1.d[2] = curr.z;
121
      tmp1.d[3] = curr.w;
147 122
      
148
      tmp2.ax = tmp2.ay = tmp2.az = tmp2.aw = 0.0f;
149
      tmp2.bx = tmp2.by = tmp2.bz = tmp2.bw = 0.0f;
150
      tmp2.cx = curr.x - next.x;
151
      tmp2.cy = curr.y - next.y;
152
      tmp2.cz = curr.z - next.z;
153
      tmp2.cw = curr.w - next.w;
154
      tmp2.dx = next.x;
155
      tmp2.dy = next.y;
156
      tmp2.dz = next.z;
157
      tmp2.dw = next.w;
123
      tmp2.a[0] = tmp2.a[1] = tmp2.a[2] = tmp2.a[3] = 0.0f;
124
      tmp2.b[0] = tmp2.b[1] = tmp2.b[2] = tmp2.b[3] = 0.0f;
125
      tmp2.c[0] = curr.x - next.x;
126
      tmp2.c[1] = curr.y - next.y;
127
      tmp2.c[2] = curr.z - next.z;
128
      tmp2.c[3] = curr.w - next.w;
129
      tmp2.d[0] = next.x;
130
      tmp2.d[1] = next.y;
131
      tmp2.d[2] = next.z;
132
      tmp2.d[3] = next.w;
158 133
      }
159 134
    else
160 135
      {
......
171 146
        curr= vv.elementAt(i);
172 147
        next= vv.elementAt(n);
173 148
      
174
        tmp1.vx = curr.x;
175
        tmp1.vy = curr.y;
176
        tmp1.vz = curr.z;
177
        tmp1.vw = curr.w;
149
        tmp1.cached[0] = curr.x;
150
        tmp1.cached[1] = curr.y;
151
        tmp1.cached[2] = curr.z;
152
        tmp1.cached[3] = curr.w;
178 153
        
179
        tmp1.ax =  2*curr.x +   tmp1.x - 2*next.x + tmp2.x;
180
        tmp1.bx = -3*curr.x - 2*tmp1.x + 3*next.x - tmp2.x;
181
        tmp1.cx = tmp1.x;
182
        tmp1.dx = curr.x;
154
        tmp1.a[0] =  2*curr.x +   tmp1.tangent[0] - 2*next.x + tmp2.tangent[0];
155
        tmp1.b[0] = -3*curr.x - 2*tmp1.tangent[0] + 3*next.x - tmp2.tangent[0];
156
        tmp1.c[0] = tmp1.tangent[0];
157
        tmp1.d[0] = curr.x;
183 158
      
184
        tmp1.ay =  2*curr.y +   tmp1.y - 2*next.y + tmp2.y;
185
        tmp1.by = -3*curr.y - 2*tmp1.y + 3*next.y - tmp2.y;
186
        tmp1.cy = tmp1.y;
187
        tmp1.dy = curr.y;
159
        tmp1.a[1] =  2*curr.y +   tmp1.tangent[1] - 2*next.y + tmp2.tangent[1];
160
        tmp1.b[1] = -3*curr.y - 2*tmp1.tangent[1] + 3*next.y - tmp2.tangent[1];
161
        tmp1.c[1] = tmp1.tangent[1];
162
        tmp1.d[1] = curr.y;
188 163
      
189
        tmp1.az =  2*curr.z +   tmp1.z - 2*next.z + tmp2.z;
190
        tmp1.bz = -3*curr.z - 2*tmp1.z + 3*next.z - tmp2.z;
191
        tmp1.cz = tmp1.z;
192
        tmp1.dz = curr.z;
164
        tmp1.a[2] =  2*curr.z +   tmp1.tangent[2] - 2*next.z + tmp2.tangent[2];
165
        tmp1.b[2] = -3*curr.z - 2*tmp1.tangent[2] + 3*next.z - tmp2.tangent[2];
166
        tmp1.c[2] = tmp1.tangent[2];
167
        tmp1.d[2] = curr.z;
193 168
        
194
        tmp1.aw =  2*curr.w +   tmp1.w - 2*next.w + tmp2.w;
195
        tmp1.bw = -3*curr.w - 2*tmp1.w + 3*next.w - tmp2.w;
196
        tmp1.cw = tmp1.w;
197
        tmp1.dw = curr.w;
169
        tmp1.a[3] =  2*curr.w +   tmp1.tangent[3] - 2*next.w + tmp2.tangent[3];
170
        tmp1.b[3] = -3*curr.w - 2*tmp1.tangent[3] + 3*next.w - tmp2.tangent[3];
171
        tmp1.c[3] = tmp1.tangent[3];
172
        tmp1.d[3] = curr.w;
198 173
        }
199 174
      }
200 175
   
201 176
    cacheDirty = false;
202 177
    }
203 178

  
204
///////////////////////////////////////////////////////////////////////////////////////////////////
205
// v is the speed vector (i.e. position p(t) differentiated by time)
206
// a is the acceleration vector (differentiate once more)
207
//
208
// Now we construct orthogonal basis with Gram-Schmidt:  
209
// vec1 = a-delta*v where delta = (v*a)/|v|^2
210
// vec2 = (0,0,1,0) - coeff1*(vx,vy,vz,vw) - coeff2*(vec1x,vec1y,vec1z,vec1w)                                     where coeff1 = vz/|v|^2, coeff2 = vec1Z/|vec1|^2
211
// vec3 = (0,0,0,1) - coeff1*(vx,vy,vz,vw) - coeff2*(vec1x,vec1y,vec1z,vec1w) - coeff3*(vec2x,vec2y,vec2z,vec2w)  where coeff1 = vw/|v|^2, coeff2 = vec1W/|vec1|^2, coeff3 = vec2W/|vec2|^2
212
    
213
  private void setUpVectors(float time,VectorCache vc)
214
    {
215
    if( vc!=null )
216
      {
217
      float vx = (3*vc.ax*time+2*vc.bx)*time+vc.cx;
218
      float vy = (3*vc.ay*time+2*vc.by)*time+vc.cy;
219
      float vz = (3*vc.az*time+2*vc.bz)*time+vc.cz;
220
      float vw = (3*vc.aw*time+2*vc.bw)*time+vc.cw;
221
     
222
      float ax = 6*vc.ax*time+2*vc.bx;
223
      float ay = 6*vc.ay*time+2*vc.by;
224
      float az = 6*vc.az*time+2*vc.bz;
225
      float aw = 6*vc.aw*time+2*vc.bw;
226
     
227
      float v_sq = vx*vx+vy*vy+vz*vz+vw*vw;
228
      float delta = (vx*ax+vy*ay+vz*az+vw*aw)/v_sq;
229
     
230
      vec1X = ax-delta*vx;
231
      vec1Y = ay-delta*vy;
232
      vec1Z = az-delta*vz;
233
      vec1W = aw-delta*vw;
234
     
235
      float vec1_sq = vec1X*vec1X+vec1Y*vec1Y+vec1Z*vec1Z+vec1W*vec1W;
236
     
237
      // construct vec2 and vec3. Cross product does not work in 4th dimension!
238
      float coeff21 = vz/v_sq;
239
      float coeff22 = vec1Z/vec1_sq;
240
      vec2X = 0.0f - coeff21*vx - coeff22*vec1X;
241
      vec2Y = 0.0f - coeff21*vy - coeff22*vec1Y;
242
      vec2Z = 1.0f - coeff21*vz - coeff22*vec1Z;
243
      vec2W = 0.0f - coeff21*vw - coeff22*vec1W;
244
     
245
      float vec2_sq = vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z+vec2W*vec2W;
246
      float coeff31 = vw/v_sq;
247
      float coeff32 = vec1W/vec1_sq;
248
      float coeff33 = vec2W/vec2_sq;
249
      vec3X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X;
250
      vec3Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y;
251
      vec3Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z;
252
      vec3W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W;
253
     
254
      float vec3_sq = vec3X*vec3X+vec3Y*vec3Y+vec3Z*vec3Z+vec3W*vec3W;
255
     
256
      float len1 = (float)Math.sqrt(v_sq/vec1_sq);   
257
      float len2 = (float)Math.sqrt(v_sq/vec2_sq);   
258
      float len3 = (float)Math.sqrt(v_sq/vec3_sq);
259
     
260
      vec1X*=len1;
261
      vec1Y*=len1;
262
      vec1Z*=len1;
263
      vec1W*=len1;
264
     
265
      vec2X*=len2;
266
      vec2Y*=len2;
267
      vec2Z*=len2;
268
      vec2W*=len2;
269
     
270
      vec3X*=len3;
271
      vec3Y*=len3;
272
      vec3Z*=len3;
273
      vec3W*=len3;
274
      }
275
    else
276
      {
277
      curr = vv.elementAt(0);
278
      next = vv.elementAt(1); 
279
     
280
      float vx = (next.x-curr.x);
281
      float vy = (next.y-curr.y);
282
      float vz = (next.z-curr.z);
283
      float vw = (next.w-curr.w);
284
     
285
      float b = (float)Math.sqrt(vx*vx+vy*vy+vz*vz);
286
     
287
      if( b>0.0f )
288
        {
289
        vec1X = vx*vw/b;
290
        vec1Y = vy*vw/b;
291
        vec1Z = vz*vw/b;
292
        vec1W = -b;
293
      
294
        float v_sq = vx*vx+vy*vy+vz*vz+vw*vw;
295
        float vec1_sq = vec1X*vec1X+vec1Y*vec1Y+vec1Z*vec1Z+vec1W*vec1W;
296
     
297
        // construct vec2 and vec3. Cross product does not work in 4th dimension!
298
        float coeff21 = vz/v_sq;
299
        float coeff22 = vec1Z/vec1_sq;
300
        vec2X = 0.0f - coeff21*vx - coeff22*vec1X;
301
        vec2Y = 0.0f - coeff21*vy - coeff22*vec1Y;
302
        vec2Z = 1.0f - coeff21*vz - coeff22*vec1Z;
303
        vec2W = 0.0f - coeff21*vw - coeff22*vec1W;
304
     
305
        float vec2_sq = vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z+vec2W*vec2W;
306
        float coeff31 = vw/v_sq;
307
        float coeff32 = vec1W/vec1_sq;
308
        float coeff33 = vec2W/vec2_sq;
309
        vec3X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X;
310
        vec3Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y;
311
        vec3Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z;
312
        vec3W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W;
313
     
314
        float vec3_sq = vec3X*vec3X+vec3Y*vec3Y+vec3Z*vec3Z+vec3W*vec3W;
315
     
316
        float len1 = (float)Math.sqrt(v_sq/vec1_sq);    
317
        float len2 = (float)Math.sqrt(v_sq/vec2_sq);    
318
        float len3 = (float)Math.sqrt(v_sq/vec3_sq);
319
     
320
        vec1X*=len1;
321
        vec1Y*=len1;
322
        vec1Z*=len1;
323
        vec1W*=len1;
324
     
325
        vec2X*=len2;
326
        vec2Y*=len2;
327
        vec2Z*=len2;
328
        vec2W*=len2;
329
     
330
        vec3X*=len3;
331
        vec3Y*=len3;
332
        vec3Z*=len3;
333
        vec3W*=len3;
334
        }
335
      else
336
        {
337
        vec1X = vw;
338
        vec1Y = 0.0f;
339
        vec1Z = 0.0f;
340
        vec1W = 0.0f;
341
      
342
        vec2X = 0.0f;
343
        vec2Y = vw;
344
        vec2Z = 0.0f;
345
        vec2W = 0.0f;
346
      
347
        vec3X = 0.0f;
348
        vec3Y = 0.0f;
349
        vec3Z = vw;
350
        vec3W = 0.0f;
351
        }
352
      }
353
    }
354
  
355 179
///////////////////////////////////////////////////////////////////////////////////////////////////
356 180
// PUBLIC API
357 181
///////////////////////////////////////////////////////////////////////////////////////////////////
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff