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
  

Also available in: Unified diff