commit 9dacabea625b74ebec9ed6b8ae3b29595610914b
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Dec 16 02:21:14 2019 +0000

    library: Fix DynamicQuat
    cube app: progress with ScrambleEffects

diff --git a/src/main/java/org/distorted/library/effectqueue/EffectQueue.java b/src/main/java/org/distorted/library/effectqueue/EffectQueue.java
index 379a77b..ddfa89b 100644
--- a/src/main/java/org/distorted/library/effectqueue/EffectQueue.java
+++ b/src/main/java/org/distorted/library/effectqueue/EffectQueue.java
@@ -333,6 +333,21 @@ public abstract class EffectQueue implements InternalMaster.Slave
     return mNumEffects;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Effect getEffect(int position)
+    {
+    if( position>=0 && position< mNumEffects )
+      {
+      return mEffects[position];
+      }
+    else
+      {
+      android.util.Log.e("queue", "getEffect: out of range "+position);
+      return null;
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void doWork()
diff --git a/src/main/java/org/distorted/library/type/Dynamic.java b/src/main/java/org/distorted/library/type/Dynamic.java
index 14a4e88..11ca13a 100644
--- a/src/main/java/org/distorted/library/type/Dynamic.java
+++ b/src/main/java/org/distorted/library/type/Dynamic.java
@@ -301,6 +301,19 @@ public abstract class Dynamic
     if( error ) printBase("");
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  int getNext(int curr, float time)
+    {
+    switch(mMode)
+      {
+      case MODE_LOOP: return curr==numPoints-1 ? 0:curr+1;
+      case MODE_PATH: return time<0.5f ? (curr+1) : (curr==0 ? 1 : curr-1);
+      case MODE_JUMP: return curr==numPoints-1 ? 1:curr+1;
+      default       : return 0;
+      }
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void checkAngle(int index)
diff --git a/src/main/java/org/distorted/library/type/Dynamic1D.java b/src/main/java/org/distorted/library/type/Dynamic1D.java
index a658f4e..bfb9859 100644
--- a/src/main/java/org/distorted/library/type/Dynamic1D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic1D.java
@@ -440,20 +440,7 @@ public class Dynamic1D extends Dynamic implements Data1D
                 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;
-
-                  switch(mMode)
-                    {
-                    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;
-                                    break;
-                    case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
-                                    break;
-                    default       : vecNext = 0;
-                    }
-              
+                  int vecNext = getNext(vecCurr,t);
                   next = vv.elementAt(vecNext);
                   tmp2 = vc.elementAt(vecNext);
               
diff --git a/src/main/java/org/distorted/library/type/Dynamic2D.java b/src/main/java/org/distorted/library/type/Dynamic2D.java
index 7c1d76b..914d815 100644
--- a/src/main/java/org/distorted/library/type/Dynamic2D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic2D.java
@@ -473,20 +473,7 @@ public class Dynamic2D extends Dynamic implements Data2D
                 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;
-
-                  switch(mMode)
-                    {
-                    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;
-                                    break;
-                    case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
-                                    break;
-                    default       : vecNext = 0;
-                    }
-
+                  int vecNext = getNext(vecCurr,t);
                   next = vv.elementAt(vecNext);
                   tmp2 = vc.elementAt(vecNext);
 
diff --git a/src/main/java/org/distorted/library/type/Dynamic3D.java b/src/main/java/org/distorted/library/type/Dynamic3D.java
index 79f832a..b0c0569 100644
--- a/src/main/java/org/distorted/library/type/Dynamic3D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic3D.java
@@ -497,20 +497,7 @@ public class Dynamic3D extends Dynamic implements Data3D
                 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;
-
-                  switch(mMode)
-                    {
-                    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;
-                                    break;
-                    case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
-                                    break;
-                    default       : vecNext = 0;
-                    }
-
+                  int vecNext = getNext(vecCurr,t);
                   next = vv.elementAt(vecNext);
                   tmp2 = vc.elementAt(vecNext);
 
diff --git a/src/main/java/org/distorted/library/type/Dynamic4D.java b/src/main/java/org/distorted/library/type/Dynamic4D.java
index 2a8a348..dd4d6a4 100644
--- a/src/main/java/org/distorted/library/type/Dynamic4D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic4D.java
@@ -520,20 +520,7 @@ public class Dynamic4D extends Dynamic implements Data4D
                 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;
-
-                  switch(mMode)
-                    {
-                    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;
-                                    break;
-                    case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
-                                    break;
-                    default       : vecNext = 0;
-                    }
-
+                  int vecNext = getNext(vecCurr,t);
                   next = vv.elementAt(vecNext);
                   tmp2 = vc.elementAt(vecNext);
 
@@ -566,7 +553,7 @@ public class Dynamic4D extends Dynamic implements Data4D
                   buffer[offset+2]= ((tmp1.a[2]*time+tmp1.b[2])*time+tmp1.c[2])*time+tmp1.d[2];
                   buffer[offset+3]= ((tmp1.a[3]*time+tmp1.b[3])*time+tmp1.c[3])*time+tmp1.d[3];
                   }
- 
+
                 break;
                 }
       }
diff --git a/src/main/java/org/distorted/library/type/Dynamic5D.java b/src/main/java/org/distorted/library/type/Dynamic5D.java
index 011ba01..8f28d10 100644
--- a/src/main/java/org/distorted/library/type/Dynamic5D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic5D.java
@@ -543,20 +543,7 @@ public class Dynamic5D extends Dynamic implements Data5D
                 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;
-
-                  switch(mMode)
-                    {
-                    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;
-                                    break;
-                    case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
-                                    break;
-                    default       : vecNext = 0;
-                    }
-
+                  int vecNext= getNext(vecCurr,t);
                   next = vv.elementAt(vecNext);
                   tmp2 = vc.elementAt(vecNext);
 
diff --git a/src/main/java/org/distorted/library/type/DynamicQuat.java b/src/main/java/org/distorted/library/type/DynamicQuat.java
index 07a75a2..6467e54 100644
--- a/src/main/java/org/distorted/library/type/DynamicQuat.java
+++ b/src/main/java/org/distorted/library/type/DynamicQuat.java
@@ -63,40 +63,41 @@ public class DynamicQuat extends Dynamic implements Data4D
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-  
+
   private void recomputeCache()
     {  
     if( numPoints>=2 )
       {
       int i, n;  
-     
+      Static4D cu,ne;
+      VectorCacheQuat vq;
+
       for(i=0; i<numPoints; i++)
         {
         n = i<numPoints-1 ? i+1:0;  
       
-        tmp1= vc.elementAt(i);
-        tmp2= vc.elementAt(n);
-        curr= vv.elementAt(i);
-        next= vv.elementAt(n);
+        vq= vc.elementAt(i);
+        cu= vv.elementAt(i);
+        ne= vv.elementAt(n);
       
-        tmp1.vx = curr.x;
-        tmp1.vy = curr.y;
-        tmp1.vz = curr.z;
-        tmp1.vw = curr.w;
+        vq.vx = cu.x;
+        vq.vy = cu.y;
+        vq.vz = cu.z;
+        vq.vw = cu.w;
     	
-        tmp1.cosOmega = curr.x*next.x + curr.y*next.y + curr.z*next.z + curr.w*next.w;
+        vq.cosOmega = cu.x*ne.x + cu.y*ne.y + cu.z*ne.z + cu.w*ne.w;
       	
-        if( tmp1.cosOmega<0 && n!=0 )  // do not invert the last quaternion even if we'd have to go the long way around!
+        if( vq.cosOmega<0 && n!=0 )  // do not invert the last quaternion even if we'd have to go the long way around!
           {
-          tmp1.cosOmega = -tmp1.cosOmega;
-          next.x = -next.x;
-          next.y = -next.y;
-          next.z = -next.z;
-          next.w = -next.w;
+          vq.cosOmega = -vq.cosOmega;
+          ne.x = -ne.x;
+          ne.y = -ne.y;
+          ne.z = -ne.z;
+          ne.w = -ne.w;
           }
       	
-        tmp1.sinOmega = (float)Math.sqrt(1-tmp1.cosOmega*tmp1.cosOmega);
-        tmp1.omega = arcCos(tmp1.cosOmega);
+        vq.sinOmega = (float)Math.sqrt(1-vq.cosOmega*vq.cosOmega);
+        vq.omega = arcCos(vq.cosOmega);
         }
       }
    
@@ -341,59 +342,69 @@ public class DynamicQuat extends Dynamic implements Data4D
               buffer[offset+3] = curr.w;
               break;
       default:float t = time;
+              int vecCurr, segment;
               float scale0, scale1;
-  
-              if( mMode==MODE_JUMP ) time = time*(numPoints-1);
-              else if( mMode==MODE_PATH || numPoints==2 ) time = (time<=0.5f) ? 2*time*(numPoints-1) : 2*(1-time)*(numPoints-1);
-              else time = time*numPoints;
-              
-              int vecNext, vecCurr = (int)time;
-              time = time-vecCurr;
-      
+
+              switch(mMode)
+                {
+                case MODE_LOOP: time = time*numPoints;
+                                segment = (int)time;
+                                vecCurr = segment;
+                                break;
+                case MODE_PATH: if( t>0.5f ) t = 1.0f-t;
+                                time = 2*t*(numPoints-1);
+                                segment = (int)(2*t*(numPoints-1));
+                                vecCurr = segment;
+                                break;
+                case MODE_JUMP: time = time*(numPoints-1);
+                                segment = (int)time;
+                                vecCurr = segment;
+                                break;
+                default       : vecCurr = 0;
+                                segment = 0;
+                }
+
               if( vecCurr>=0 && vecCurr<numPoints )
                 {
-                if( cacheDirty ) recomputeCache();    // recompute cache if we have added or remove vectors since last computation
-                   
-                switch(mMode)
-                  {
-                  case MODE_LOOP: vecNext = vecCurr==numPoints-1 ? 0:vecCurr+1; 
-                                  break;
-                  case MODE_PATH: if( t<0.5f ) vecNext = vecCurr+1;  
-                                  else         vecNext = vecCurr==0 ? 1 : vecCurr-1;  
-                                  break;
-                  case MODE_JUMP: vecNext = vecCurr==numPoints-1 ? 1:vecCurr+1;
-                                  break;
-                  default       : vecNext = 0;                
-                  }
-     
+                int vecNext = getNext(vecCurr,t);
+
                 curr = vv.elementAt(vecCurr);
-                next = vv.elementAt(vecNext);
                 tmp1 = vc.elementAt(vecCurr);
-                tmp2 = vc.elementAt(vecNext);
-              
-                if( tmp2.vx!=next.x || tmp2.vy!=next.y || tmp2.vz!=next.z || tmp2.vw!=next.w ) recomputeCache();
-               
+                next = vv.elementAt(vecNext);
+
+                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
+                  {
+                  tmp2 = vc.elementAt(vecNext);
+
+                  if( tmp2.vx!=next.x || tmp2.vy!=next.y || tmp2.vz!=next.z || tmp2.vw!=next.w ) recomputeCache();
+                  }
+
+                mSegment = segment;
+
+                time = time-vecCurr;
+
                 if( tmp1.sinOmega==0 )
                   {
-                  scale0 = 0f;
-                  scale1 = 1f;
+                  scale0 = 1f;
+                  scale1 = 0f;
                   }
-                else if( tmp1.cosOmega < 0.99 ) 
+                else if( tmp1.cosOmega < 0.99 )
                   {
                   scale0 = (float)Math.sin( (1f-time)*tmp1.omega ) / tmp1.sinOmega;
                   scale1 = (float)Math.sin(     time *tmp1.omega ) / tmp1.sinOmega;
                   }
-                else 
+                else
                   {
                   scale0 = 1f-time;
                   scale1 = time;
                   }
 
                 buffer[offset  ] = scale0*curr.x + scale1*next.x;
-                buffer[offset+1] = scale0*curr.y + scale1*next.y; 
-                buffer[offset+2] = scale0*curr.z + scale1*next.z; 
-                buffer[offset+3] = scale0*curr.w + scale1*next.w; 
-                
+                buffer[offset+1] = scale0*curr.y + scale1*next.y;
+                buffer[offset+2] = scale0*curr.z + scale1*next.z;
+                buffer[offset+3] = scale0*curr.w + scale1*next.w;
+
                 break;
                 }
       }
