commit 291705f6b2206f1ff57c286bd840a8f28ef0fe27
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Thu Nov 3 17:21:57 2016 +0000

    re-generate noise after passing each Point.

diff --git a/src/main/java/org/distorted/library/EffectNames.java b/src/main/java/org/distorted/library/EffectNames.java
index 4336b1f..970efaa 100644
--- a/src/main/java/org/distorted/library/EffectNames.java
+++ b/src/main/java/org/distorted/library/EffectNames.java
@@ -136,7 +136,7 @@ public enum EffectNames
    * Directional sinusoidal wave effect. The direction of the wave is given by the 'angle'
    * parameters. Details: {@link DistortedObject#wave(Data5D,Data2D)}
    * <p>
-   * Uniforms: (amplitude,length,offset,angleAlpha,
+   * Uniforms: (amplitude,length,phase,angleAlpha,
    *            angleBeta, UNUSED,centerX,centerY,
    *            regionX,regionY,regionRX,regionRY)
    * <p>
diff --git a/src/main/java/org/distorted/library/type/Dynamic.java b/src/main/java/org/distorted/library/type/Dynamic.java
index 112ce23..9e2a53a 100644
--- a/src/main/java/org/distorted/library/type/Dynamic.java
+++ b/src/main/java/org/distorted/library/type/Dynamic.java
@@ -68,7 +68,7 @@ public abstract class Dynamic
 
   protected int mDimension;
   protected int numPoints;
-  protected int mVecCurr;    
+  protected int mSegment;       // between which pair of points are we currently? (in case of PATH this is a bit complicated!)
   protected boolean cacheDirty; // VectorCache not up to date
   protected int mMode;          // LOOP, PATH or JUMP
   protected long mDuration;     // number of milliseconds it takes to do a full loop/path from first vector to the last and back to the first
@@ -78,18 +78,22 @@ public abstract class Dynamic
     {
     float[][] n;
 
-    VectorNoise(int dim)
+    VectorNoise()
       {
-      n = new float[dim][NUM_NOISE];
+      n = new float[mDimension][NUM_NOISE];
+      }
 
+    void computeNoise()
+      {
       n[0][0] = mRnd.nextFloat();
       for(int i=1; i<NUM_NOISE; i++) n[0][i] = n[0][i-1]+mRnd.nextFloat();
+
       float sum = n[0][NUM_NOISE-1] + mRnd.nextFloat();
-      for(int i=0; i<NUM_NOISE; i++) n[0][i] /=sum;
 
-      for(int j=1; j<dim; j++)
+      for(int i=0; i<NUM_NOISE; i++)
         {
-        for(int i=0; i<NUM_NOISE; i++) n[j][i] = mRnd.nextFloat()-0.5f;
+        n[0][i] /=sum;
+        for(int j=1; j<mDimension; j++) n[j][i] = mRnd.nextFloat()-0.5f;
         }
       }
     }
@@ -114,14 +118,14 @@ public abstract class Dynamic
     float[] tangent;
     float[] cached;
 
-    VectorCache(int dim)
+    VectorCache()
       {
-      a = new float[dim];
-      b = new float[dim];
-      c = new float[dim];
-      d = new float[dim];
-      tangent = new float[dim];
-      cached = new float[dim];
+      a = new float[mDimension];
+      b = new float[mDimension];
+      c = new float[mDimension];
+      d = new float[mDimension];
+      tangent = new float[mDimension];
+      cached = new float[mDimension];
       }
     }
 
@@ -147,18 +151,19 @@ public abstract class Dynamic
 
   protected Dynamic(int duration, float count, int dimension)
     {
-    vc = new Vector<>();
-    vn = null;
-    numPoints = 0;
+    vc         = new Vector<>();
+    vn         = null;
+    numPoints  = 0;
     cacheDirty = false;
-    mMode = MODE_LOOP;
-    mDuration = duration;
-    mCount = count;
+    mMode      = MODE_LOOP;
+    mDuration  = duration;
+    mCount     = count;
     mDimension = dimension;
+    mSegment   = -1;
 
-    baseV = new float[mDimension][mDimension];
-    buf= new float[mDimension];
-    old= new float[mDimension];
+    baseV      = new float[mDimension][mDimension];
+    buf        = new float[mDimension];
+    old        = new float[mDimension];
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/library/type/Dynamic1D.java b/src/main/java/org/distorted/library/type/Dynamic1D.java
index d95e7c1..3cc8861 100644
--- a/src/main/java/org/distorted/library/type/Dynamic1D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic1D.java
@@ -207,18 +207,18 @@ public class Dynamic1D extends Dynamic implements Data1D
       {
       vv.add(v);
      
-      if( vn!=null ) vn.add(new VectorNoise(1));
+      if( vn!=null ) vn.add(new VectorNoise());
        
       switch(numPoints)
         {
         case 0: 
         case 1: break;
-        case 2: vc.add(new VectorCache(1));
-                vc.add(new VectorCache(1));
-                vc.add(new VectorCache(1));
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
                 cacheDirty = true;
                 break;
-        default:vc.add(new VectorCache(1));
+        default:vc.add(new VectorCache());
                 cacheDirty = true;
         }
      
@@ -239,18 +239,18 @@ public class Dynamic1D extends Dynamic implements Data1D
       {
       vv.add(location, v);
       
-      if( vn!=null ) vn.add(new VectorNoise(1));
+      if( vn!=null ) vn.add(new VectorNoise());
              
       switch(numPoints)
         {
         case 0:
         case 1: break;
-        case 2: vc.add(new VectorCache(1));
-                vc.add(new VectorCache(1));
-                vc.add(new VectorCache(1));
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
                 cacheDirty = true;
                 break;
-        default:vc.add(location,new VectorCache(1));
+        default:vc.add(location,new VectorCache());
                 cacheDirty = true;
         }
       
@@ -358,7 +358,7 @@ public class Dynamic1D extends Dynamic implements Data1D
     if( vn==null )
       {
       vn = new Vector<>();
-      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise(mDimension));
+      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise());
 
       if( mDimension>=2 )
         {
@@ -397,49 +397,71 @@ public class Dynamic1D extends Dynamic implements Data1D
               break;
       case 2: curr = vv.elementAt(0);
               next = vv.elementAt(1);
-             
+
+              int segment2= (int)(2*time);
+
               if( mMode==MODE_LOOP || mMode==MODE_PATH ) time = (time>0.5f ? 2-2*time : 2*time);
-             
+
               if( vn!=null )
                 {
+                if( segment2 != mSegment )
+                  {
+                  if(mMode!=MODE_JUMP || mSegment==1) vn.elementAt(0).computeNoise();
+                  mSegment = segment2;
+                  }
+
                 time = noise(time,0);
                 }
              
               buffer[offset] = (next.x-curr.x)*time + curr.x;
               break;
       default:float t = time;
-            
+              int vecCurr, segment;
+
               switch(mMode)
                 {
                 case MODE_LOOP: time = time*numPoints;
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
-                case MODE_PATH: time = (time<=0.5f) ? 2*time*(numPoints-1) : 2*(1-time)*(numPoints-1);
+                case MODE_PATH: segment = (int)(2*t*(numPoints-1));
+
+                                if( t<=0.5f )
+                                  {
+                                  time = 2*t*(numPoints-1);
+                                  vecCurr = segment;
+                                  }
+                                else
+                                  {
+                                  time = 2*(1-t)*(numPoints-1);
+                                  vecCurr = 2*numPoints-3-segment;
+                                  }
                                 break;
                 case MODE_JUMP: time = time*(numPoints-1);
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
+                default       : vecCurr = 0;
+                                segment = 0;
                 }
-      
-              int vecCurr = (int)time;
-              time = time-vecCurr;
-      
+
               if( vecCurr>=0 && vecCurr<numPoints )
                 {
                 if( cacheDirty ) recomputeCache();  // recompute cache if we have added or remove vectors since last computation
-                else if( mVecCurr!= vecCurr )       // ...or if we have just passed a vector and the vector we are currently flying to has changed
+                else if( mSegment!= segment )       // ...or if we have just passed a vector and the vector we are currently flying to has changed
                   {
-                  int vecNext;   
-                  mVecCurr = vecCurr;
-                                
+                  int vecNext;
+
                   switch(mMode)
                     {
-                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1; 
+                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1;
                                     break;
-                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;  
-                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;  
+                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;
+                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;
                                     break;
                     case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
                                     break;
-                    default       : vecNext = 0;                
+                    default       : vecNext = 0;
                     }
               
                   next = vv.elementAt(vecNext);
@@ -447,13 +469,20 @@ public class Dynamic1D extends Dynamic implements Data1D
               
                   if( tmp2.cached[0]!=next.x ) recomputeCache();
                   }
-             
+
+                if( mSegment!= segment && vn!=null ) vn.elementAt(vecCurr).computeNoise();
+
+                mSegment = segment;
+
+                time = time-vecCurr;
+
+                tmp1 = vc.elementAt(vecCurr);
+
                 if( vn!=null )
                   {
                   time = noise(time,vecCurr);
                   }
             
-                tmp1 = vc.elementAt(vecCurr);
                 buffer[offset] = ((tmp1.a[0]*time+tmp1.b[0])*time+tmp1.c[0])*time+tmp1.d[0];
                 break;
                 }
diff --git a/src/main/java/org/distorted/library/type/Dynamic2D.java b/src/main/java/org/distorted/library/type/Dynamic2D.java
index 89c2986..55808f4 100644
--- a/src/main/java/org/distorted/library/type/Dynamic2D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic2D.java
@@ -223,17 +223,17 @@ public class Dynamic2D extends Dynamic implements Data2D
       {
       vv.add(v);
      
-      if( vn!=null ) vn.add(new VectorNoise(2));
+      if( vn!=null ) vn.add(new VectorNoise());
        
       switch(numPoints)
         {
         case 0:
         case 1: break;
-        case 2: vc.add(new VectorCache(2));
-                vc.add(new VectorCache(2));
-                vc.add(new VectorCache(2));
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
                 break;
-        default:vc.add(new VectorCache(2));
+        default:vc.add(new VectorCache());
         }
      
       numPoints++;
@@ -254,17 +254,17 @@ public class Dynamic2D extends Dynamic implements Data2D
       {
       vv.add(location, v);
       
-      if( vn!=null ) vn.add(new VectorNoise(2));
+      if( vn!=null ) vn.add(new VectorNoise());
       
       switch(numPoints)
         {
         case 0:
         case 1: break;
-        case 2: vc.add(new VectorCache(2));
-                vc.add(new VectorCache(2));
-                vc.add(new VectorCache(2));
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
                 break;
-        default:vc.add(location,new VectorCache(2));
+        default:vc.add(location,new VectorCache());
         }
       
       numPoints++;
@@ -376,7 +376,7 @@ public class Dynamic2D extends Dynamic implements Data2D
     if( vn==null )
       {
       vn = new Vector<>();
-      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise(mDimension));
+      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise());
 
       if( mDimension>=2 )
         {
@@ -420,11 +420,19 @@ public class Dynamic2D extends Dynamic implements Data2D
               break;
       case 2: curr = vv.elementAt(0);
               next = vv.elementAt(1);
-               
+
+              int segment2= (int)(2*time);
+
               if( mMode==MODE_LOOP || mMode==MODE_PATH ) time = (time>0.5f ? 2-2*time : 2*time);
-             
+
               if( vn!=null )
                 {
+                if( segment2 != mSegment )
+                  {
+                  if(mMode!=MODE_JUMP || mSegment==1) vn.elementAt(0).computeNoise();
+                  mSegment = segment2;
+                  }
+
                 time = noise(time,0);
               
                 baseV[1][0] = next.x-curr.x;
@@ -441,46 +449,65 @@ public class Dynamic2D extends Dynamic implements Data2D
               
               break;
       default:float t = time;
-        
+              int vecCurr, segment;
+
               switch(mMode)
                 {
                 case MODE_LOOP: time = time*numPoints;
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
-                case MODE_PATH: time = (time<=0.5f) ? 2*time*(numPoints-1) : 2*(1-time)*(numPoints-1);
+                case MODE_PATH: segment = (int)(2*t*(numPoints-1));
+
+                                if( t<=0.5f )
+                                  {
+                                  time = 2*t*(numPoints-1);
+                                  vecCurr = segment;
+                                  }
+                                else
+                                  {
+                                  time = 2*(1-t)*(numPoints-1);
+                                  vecCurr = 2*numPoints-3-segment;
+                                  }
                                 break;
                 case MODE_JUMP: time = time*(numPoints-1);
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
+                default       : vecCurr = 0;
+                                segment = 0;
                 }
-            
-              int vecCurr = (int)time;
-              time = time-vecCurr;
-      
+
               if( vecCurr>=0 && vecCurr<numPoints )
-                { 
-                if( cacheDirty ) recomputeCache();    // recompute cache if we have added or remove vectors since last computation
-                else if( mVecCurr!= vecCurr )         // ...or if we have just passed a vector and the vector we are currently flying to has changed
+                {
+                if( cacheDirty ) recomputeCache();  // recompute cache if we have added or remove vectors since last computation
+                else if( mSegment!= segment )       // ...or if we have just passed a vector and the vector we are currently flying to has changed
                   {
-                  int vecNext;   
-                  mVecCurr = vecCurr;
-                                
+                  int vecNext;
+
                   switch(mMode)
                     {
-                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1; 
+                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1;
                                     break;
-                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;  
-                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;  
+                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;
+                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;
                                     break;
                     case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
                                     break;
-                    default       : vecNext = 0;                
+                    default       : vecNext = 0;
                     }
-              
+
                   next = vv.elementAt(vecNext);
                   tmp2 = vc.elementAt(vecNext);
-              
-                  if( tmp2.cached[0]!=next.x || tmp2.cached[1]!=next.y ) recomputeCache();
+
+                  if( tmp2.cached[0]!=next.x ) recomputeCache();
                   }
 
+                if( mSegment!= segment && vn!=null ) vn.elementAt(vecCurr).computeNoise();
+
+                mSegment = segment;
+
+                time = time-vecCurr;
                 tmp1 = vc.elementAt(vecCurr);
 
                 if( vn!=null )
diff --git a/src/main/java/org/distorted/library/type/Dynamic3D.java b/src/main/java/org/distorted/library/type/Dynamic3D.java
index 747018d..6732b26 100644
--- a/src/main/java/org/distorted/library/type/Dynamic3D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic3D.java
@@ -246,18 +246,18 @@ private float oldTime;
       {
       vv.add(v);
         
-      if( vn!=null ) vn.add(new VectorNoise(3));
+      if( vn!=null ) vn.add(new VectorNoise());
        
       switch(numPoints)
         {
         case 0: break;
         case 1: computeOrthonormalBase2(vv.elementAt(0),v);
                 break;
-        case 2: vc.add(new VectorCache(3));
-                vc.add(new VectorCache(3));
-                vc.add(new VectorCache(3));
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
                 break;
-        default:vc.add(new VectorCache(3));
+        default:vc.add(new VectorCache());
         }
 
       numPoints++;
@@ -278,18 +278,18 @@ private float oldTime;
       {
       vv.add(location, v);
       
-      if( vn!=null ) vn.add(new VectorNoise(3));
+      if( vn!=null ) vn.add(new VectorNoise());
       
       switch(numPoints)
         {
         case 0: break;
         case 1: computeOrthonormalBase2(vv.elementAt(0),v);
                 break;
-        case 2: vc.add(new VectorCache(3));
-                vc.add(new VectorCache(3));
-                vc.add(new VectorCache(3));
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
                 break;
-        default:vc.add(location,new VectorCache(3));
+        default:vc.add(location,new VectorCache());
         }
 
       numPoints++;
@@ -403,7 +403,7 @@ private float oldTime;
     if( vn==null )
       {
       vn = new Vector<>();
-      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise(mDimension));
+      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise());
 
       if( mDimension>=2 )
         {
@@ -452,11 +452,19 @@ private float oldTime;
               break;
       case 2: curr = vv.elementAt(0);
               next = vv.elementAt(1);
-             
+
+              int segment2= (int)(2*time);
+
               if( mMode==MODE_LOOP || mMode==MODE_PATH ) time = (time>0.5f ? 2-2*time : 2*time);
-             
+
               if( vn!=null )
                 {
+                if( segment2 != mSegment )
+                  {
+                  if(mMode!=MODE_JUMP || mSegment==1) vn.elementAt(0).computeNoise();
+                  mSegment = segment2;
+                  }
+
                 time = noise(time,0);
             
                 buffer[offset  ] = (next.x-curr.x)*time + curr.x + (baseV[1][0]*mFactor[0] + baseV[2][0]*mFactor[1]);
@@ -472,45 +480,65 @@ private float oldTime;
              
               break;
       default:float t = time;
-        
+              int vecCurr, segment;
+
               switch(mMode)
                 {
                 case MODE_LOOP: time = time*numPoints;
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
-                case MODE_PATH: time = (time<=0.5f) ? 2*time*(numPoints-1) : 2*(1-time)*(numPoints-1);
+                case MODE_PATH: segment = (int)(2*t*(numPoints-1));
+
+                                if( t<=0.5f )
+                                  {
+                                  time = 2*t*(numPoints-1);
+                                  vecCurr = segment;
+                                  }
+                                else
+                                  {
+                                  time = 2*(1-t)*(numPoints-1);
+                                  vecCurr = 2*numPoints-3-segment;
+                                  }
                                 break;
                 case MODE_JUMP: time = time*(numPoints-1);
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
+                default       : vecCurr = 0;
+                                segment = 0;
                 }
-           
-              int vecCurr = (int)time;
-              time = time-vecCurr;
-      
+
               if( vecCurr>=0 && vecCurr<numPoints )
                 {
-                if( cacheDirty ) recomputeCache();    // recompute cache if we have added or remove vectors since last computation
-                else if( mVecCurr!= vecCurr )         // ...or if we have just passed a vector and the vector we are currently flying to has changed
+                if( cacheDirty ) recomputeCache();  // recompute cache if we have added or remove vectors since last computation
+                else if( mSegment!= segment )       // ...or if we have just passed a vector and the vector we are currently flying to has changed
                   {
-                  int vecNext;   
-                  mVecCurr = vecCurr;
-                       
+                  int vecNext;
+
                   switch(mMode)
                     {
-                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1; 
+                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1;
                                     break;
-                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;  
-                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;  
+                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;
+                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;
                                     break;
                     case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
                                     break;
-                    default       : vecNext = 0;                
+                    default       : vecNext = 0;
                     }
-              
+
                   next = vv.elementAt(vecNext);
                   tmp2 = vc.elementAt(vecNext);
-              
-                  if( tmp2.cached[0]!=next.x || tmp2.cached[1]!=next.y || tmp2.cached[2]!=next.z ) recomputeCache();
+
+                  if( tmp2.cached[0]!=next.x ) recomputeCache();
                   }
+
+                if( mSegment!= segment && vn!=null ) vn.elementAt(vecCurr).computeNoise();
+
+                mSegment = segment;
+
+                time = time-vecCurr;
             
                 tmp1 = vc.elementAt(vecCurr);
                
diff --git a/src/main/java/org/distorted/library/type/Dynamic4D.java b/src/main/java/org/distorted/library/type/Dynamic4D.java
index ba762ab..78f7160 100644
--- a/src/main/java/org/distorted/library/type/Dynamic4D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic4D.java
@@ -255,23 +255,23 @@ public class Dynamic4D extends Dynamic implements Data4D
       {
       vv.add(v);
         
-      if( vn!=null ) vn.add(new VectorNoise(4));
+      if( vn!=null ) vn.add(new VectorNoise());
        
-       switch(numPoints)
-         {
-         case 0: break;
-         case 1: computeOrthonormalBase2(vv.elementAt(0),v);
-                 break;
-         case 2: vc.add(new VectorCache(4));
-                 vc.add(new VectorCache(4));
-                 vc.add(new VectorCache(4));
-                 break;
-         default:vc.add(new VectorCache(4));
-         }
-
-       numPoints++;
-       cacheDirty = true;
-       }
+      switch(numPoints)
+        {
+        case 0: break;
+        case 1: computeOrthonormalBase2(vv.elementAt(0),v);
+                break;
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                break;
+        default:vc.add(new VectorCache());
+        }
+
+      numPoints++;
+      cacheDirty = true;
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -287,18 +287,18 @@ public class Dynamic4D extends Dynamic implements Data4D
       {
       vv.add(location, v);
       
-      if( vn!=null ) vn.add(new VectorNoise(4));
+      if( vn!=null ) vn.add(new VectorNoise());
       
       switch(numPoints)
         {
         case 0: break;
         case 1: computeOrthonormalBase2(vv.elementAt(0),v);
                 break;
-        case 2: vc.add(new VectorCache(4));
-                vc.add(new VectorCache(4));
-                vc.add(new VectorCache(4));
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
                 break;
-        default:vc.add(location,new VectorCache(4));
+        default:vc.add(location,new VectorCache());
         }
 
       numPoints++;
@@ -412,7 +412,7 @@ public class Dynamic4D extends Dynamic implements Data4D
     if( vn==null )
       {
       vn = new Vector<>();
-      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise(mDimension));
+      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise());
 
       if( mDimension>=2 )
         {
@@ -466,11 +466,19 @@ public class Dynamic4D extends Dynamic implements Data4D
               break;
       case 2: curr = vv.elementAt(0);
               next = vv.elementAt(1);
-            
+
+              int segment2= (int)(2*time);
+
               if( mMode==MODE_LOOP || mMode==MODE_PATH ) time = (time>0.5f ? 2-2*time : 2*time);
-             
+
               if( vn!=null )
                 {
+                if( segment2 != mSegment )
+                  {
+                  if(mMode!=MODE_JUMP || mSegment==1) vn.elementAt(0).computeNoise();
+                  mSegment = segment2;
+                  }
+
                 time = noise(time,0);
 
                 buffer[offset  ] = (next.x-curr.x)*time + curr.x + (baseV[1][0]*mFactor[0] + baseV[2][0]*mFactor[1] + baseV[3][0]*mFactor[2]);
@@ -488,45 +496,65 @@ public class Dynamic4D extends Dynamic implements Data4D
                 
               break;
       default:float t = time;
-        
+              int vecCurr, segment;
+
               switch(mMode)
                 {
                 case MODE_LOOP: time = time*numPoints;
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
-                case MODE_PATH: time = (time<=0.5f) ? 2*time*(numPoints-1) : 2*(1-time)*(numPoints-1);
+                case MODE_PATH: segment = (int)(2*t*(numPoints-1));
+
+                                if( t<=0.5f )
+                                  {
+                                  time = 2*t*(numPoints-1);
+                                  vecCurr = segment;
+                                  }
+                                else
+                                  {
+                                  time = 2*(1-t)*(numPoints-1);
+                                  vecCurr = 2*numPoints-3-segment;
+                                  }
                                 break;
                 case MODE_JUMP: time = time*(numPoints-1);
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
+                default       : vecCurr = 0;
+                                segment = 0;
                 }
-     
-              int vecCurr = (int)time;
-              time = time-vecCurr;
-      
+
               if( vecCurr>=0 && vecCurr<numPoints )
                 {
-                if( cacheDirty ) recomputeCache();    // recompute cache if we have added or remove vectors since last computation
-                else if( mVecCurr!= vecCurr )         // ...or if we have just passed a vector and the vector we are currently flying to has changed
+                if( cacheDirty ) recomputeCache();  // recompute cache if we have added or remove vectors since last computation
+                else if( mSegment!= segment )       // ...or if we have just passed a vector and the vector we are currently flying to has changed
                   {
-                  int vecNext;   
-                  mVecCurr = vecCurr;
-                       
+                  int vecNext;
+
                   switch(mMode)
                     {
-                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1; 
+                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1;
                                     break;
-                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;  
-                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;  
+                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;
+                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;
                                     break;
                     case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
                                     break;
-                    default       : vecNext = 0;                
+                    default       : vecNext = 0;
                     }
-     
+
                   next = vv.elementAt(vecNext);
                   tmp2 = vc.elementAt(vecNext);
-              
-                  if( tmp2.cached[0]!=next.x || tmp2.cached[1]!=next.y || tmp2.cached[2]!=next.z || tmp2.cached[3]!=next.w ) recomputeCache();
+
+                  if( tmp2.cached[0]!=next.x ) recomputeCache();
                   }
+
+                if( mSegment!= segment && vn!=null ) vn.elementAt(vecCurr).computeNoise();
+
+                mSegment = segment;
+
+                time = time-vecCurr;
             
                 tmp1 = vc.elementAt(vecCurr);
                
diff --git a/src/main/java/org/distorted/library/type/Dynamic5D.java b/src/main/java/org/distorted/library/type/Dynamic5D.java
index b1ef795..0aef349 100644
--- a/src/main/java/org/distorted/library/type/Dynamic5D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic5D.java
@@ -271,18 +271,18 @@ public class Dynamic5D extends Dynamic implements Data5D
       {
       vv.add(v);
         
-      if( vn!=null ) vn.add(new VectorNoise(5));
+      if( vn!=null ) vn.add(new VectorNoise());
        
       switch(numPoints)
         {
         case 0: break;
         case 1: computeOrthonormalBase2(vv.elementAt(0),v);
                 break;
-        case 2: vc.add(new VectorCache(5));
-                vc.add(new VectorCache(5));
-                vc.add(new VectorCache(5));
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
                 break;
-        default:vc.add(new VectorCache(5));
+        default:vc.add(new VectorCache());
         }
 
       numPoints++;
@@ -303,18 +303,18 @@ public class Dynamic5D extends Dynamic implements Data5D
       {
       vv.add(location, v);
       
-      if( vn!=null ) vn.add(new VectorNoise(5));
+      if( vn!=null ) vn.add(new VectorNoise());
       
       switch(numPoints)
         {
         case 0: break;
         case 1: computeOrthonormalBase2(vv.elementAt(0),v);
                 break;
-        case 2: vc.add(new VectorCache(5));
-                vc.add(new VectorCache(5));
-                vc.add(new VectorCache(5));
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
                 break;
-        default:vc.add(location,new VectorCache(5));
+        default:vc.add(location,new VectorCache());
         }
 
       numPoints++;
@@ -428,7 +428,7 @@ public class Dynamic5D extends Dynamic implements Data5D
     if( vn==null )
       {
       vn = new Vector<>();
-      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise(mDimension));
+      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise());
 
       if( mDimension>=2 )
         {
@@ -487,11 +487,19 @@ public class Dynamic5D extends Dynamic implements Data5D
               break;
       case 2: curr = vv.elementAt(0);
               next = vv.elementAt(1);
-            
+
+              int segment2= (int)(2*time);
+
               if( mMode==MODE_LOOP || mMode==MODE_PATH ) time = (time>0.5f ? 2-2*time : 2*time);
-             
+
               if( vn!=null )
                 {
+                if( segment2 != mSegment )
+                  {
+                  if(mMode!=MODE_JUMP || mSegment==1) vn.elementAt(0).computeNoise();
+                  mSegment = segment2;
+                  }
+
                 time = noise(time,0);
 
                 buffer[offset  ] = (next.x-curr.x)*time + curr.x + (baseV[1][0]*mFactor[0] + baseV[2][0]*mFactor[1] + baseV[3][0]*mFactor[2] + baseV[4][0]*mFactor[3]);
@@ -511,45 +519,65 @@ public class Dynamic5D extends Dynamic implements Data5D
                 
               break;
       default:float t = time;
-        
+              int vecCurr, segment;
+
               switch(mMode)
                 {
                 case MODE_LOOP: time = time*numPoints;
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
-                case MODE_PATH: time = (time<=0.5f) ? 2*time*(numPoints-1) : 2*(1-time)*(numPoints-1);
+                case MODE_PATH: segment = (int)(2*t*(numPoints-1));
+
+                                if( t<=0.5f )
+                                  {
+                                  time = 2*t*(numPoints-1);
+                                  vecCurr = segment;
+                                  }
+                                else
+                                  {
+                                  time = 2*(1-t)*(numPoints-1);
+                                  vecCurr = 2*numPoints-3-segment;
+                                  }
                                 break;
                 case MODE_JUMP: time = time*(numPoints-1);
+                                segment = (int)time;
+                                vecCurr = segment;
                                 break;
+                default       : vecCurr = 0;
+                                segment = 0;
                 }
-     
-              int vecCurr = (int)time;
-              time = time-vecCurr;
-      
+
               if( vecCurr>=0 && vecCurr<numPoints )
                 {
-                if( cacheDirty ) recomputeCache();    // recompute cache if we have added or remove vectors since last computation
-                else if( mVecCurr!= vecCurr )         // ...or if we have just passed a vector and the vector we are currently flying to has changed
+                if( cacheDirty ) recomputeCache();  // recompute cache if we have added or remove vectors since last computation
+                else if( mSegment!= segment )       // ...or if we have just passed a vector and the vector we are currently flying to has changed
                   {
-                  int vecNext;   
-                  mVecCurr = vecCurr;
-                       
+                  int vecNext;
+
                   switch(mMode)
                     {
-                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1; 
+                    case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1;
                                     break;
-                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;  
-                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;  
+                    case MODE_PATH: if( t<0.5f ) vecNext = vecCurr==numPoints-1 ? numPoints-2: vecCurr+1;
+                                    else         vecNext = vecCurr==0 ? 1 : vecCurr-1;
                                     break;
                     case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
                                     break;
-                    default       : vecNext = 0;                
+                    default       : vecNext = 0;
                     }
-     
+
                   next = vv.elementAt(vecNext);
                   tmp2 = vc.elementAt(vecNext);
-              
-                  if( tmp2.cached[0]!=next.x || tmp2.cached[1]!=next.y || tmp2.cached[2]!=next.z || tmp2.cached[3]!=next.w || tmp2.cached[4]!=next.v ) recomputeCache();
+
+                  if( tmp2.cached[0]!=next.x ) recomputeCache();
                   }
+
+                if( mSegment!= segment && vn!=null ) vn.elementAt(vecCurr).computeNoise();
+
+                mSegment = segment;
+
+                time = time-vecCurr;
             
                 tmp1 = vc.elementAt(vecCurr);
                
diff --git a/src/main/res/raw/main_vertex_shader.glsl b/src/main/res/raw/main_vertex_shader.glsl
index 0cc959d..1c97a5d 100644
--- a/src/main/res/raw/main_vertex_shader.glsl
+++ b/src/main/res/raw/main_vertex_shader.glsl
@@ -148,7 +148,7 @@ float degree(in vec4 region, in vec2 S, in vec2 PS)
 // else if v.z >  hH then v.z = (-(1-h)^2 * H^2)/(v.z-(2h-1)H) +H   (function satisfying f(+hH)=+hH, f'(+hH)=1, lim f(x) = +H)
 // else v.z = v.z
 
-void restrict(inout float v)
+void restrictZ(inout float v)
   {
   const float h = 0.7;
   float signV = 2.0*max(0.0,sign(v))-1.0;
@@ -496,7 +496,7 @@ void main()
     else if( vType[i]==WAVE   ) wave   (3*i,v,n);
     }
  
-  restrict(v.z);  
+  restrictZ(v.z);
 #endif
    
   v_Position      = v.xyz;
