Project

General

Profile

« Previous | Next » 

Revision 649544b8

Added by Leszek Koltunski over 7 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