commit 522eebc82426698baa3d86c6fd01fd92a6894432
Author: Leszek Koltunski <leszek@distorted.org>
Date:   Tue Oct 18 00:36:19 2016 +0100

    Add Static5D and Dynamic5D.

diff --git a/src/main/java/org/distorted/library/type/Data5D.java b/src/main/java/org/distorted/library/type/Data5D.java
new file mode 100644
index 0000000..bfc76ae
--- /dev/null
+++ b/src/main/java/org/distorted/library/type/Data5D.java
@@ -0,0 +1,31 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2016 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Distorted.                                                               //
+//                                                                                               //
+// Distorted is free software: you can redistribute it and/or modify                             //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Distorted is distributed in the hope that it will be useful,                                  //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.library.type;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Marker Interface implemented by Static5D and Dynamic5D.
+ * <p>
+ * The point: so we can pass either Static and Dynamic to EffectQueues in a single parameter.
+ */
+public interface Data5D
+  {
+
+  }
diff --git a/src/main/java/org/distorted/library/type/Dynamic1D.java b/src/main/java/org/distorted/library/type/Dynamic1D.java
index 4d2e3e8..0e7386d 100644
--- a/src/main/java/org/distorted/library/type/Dynamic1D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic1D.java
@@ -48,7 +48,7 @@ public class Dynamic1D extends Dynamic implements Data1D
     {
     float[] nx;
    
-    public VectorNoise()
+    VectorNoise()
       {
       nx = new float[NUM_NOISE]; 
       nx[0] = mRnd.nextFloat();
diff --git a/src/main/java/org/distorted/library/type/Dynamic2D.java b/src/main/java/org/distorted/library/type/Dynamic2D.java
index 29ec507..c634cb7 100644
--- a/src/main/java/org/distorted/library/type/Dynamic2D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic2D.java
@@ -50,7 +50,7 @@ public class Dynamic2D extends Dynamic implements Data2D
     float[] nx;
     float[] ny;
    
-    public VectorNoise()
+    VectorNoise()
       {
       nx = new float[NUM_NOISE]; 
       nx[0] = mRnd.nextFloat();
diff --git a/src/main/java/org/distorted/library/type/Dynamic3D.java b/src/main/java/org/distorted/library/type/Dynamic3D.java
index 8c5a734..dda2bf0 100644
--- a/src/main/java/org/distorted/library/type/Dynamic3D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic3D.java
@@ -52,7 +52,7 @@ public class Dynamic3D extends Dynamic implements Data3D
     float[] ny;
     float[] nz;
    
-    public VectorNoise()
+    VectorNoise()
       {
       nx = new float[NUM_NOISE]; 
       nx[0] = mRnd.nextFloat();
diff --git a/src/main/java/org/distorted/library/type/Dynamic4D.java b/src/main/java/org/distorted/library/type/Dynamic4D.java
index 0e27ba4..68e2d1f 100644
--- a/src/main/java/org/distorted/library/type/Dynamic4D.java
+++ b/src/main/java/org/distorted/library/type/Dynamic4D.java
@@ -54,7 +54,7 @@ public class Dynamic4D extends Dynamic implements Data4D
     float[] nz;
     float[] nw;
    
-    public VectorNoise()
+    VectorNoise()
       {
       nx = new float[NUM_NOISE]; 
       nx[0] = mRnd.nextFloat();
@@ -82,7 +82,7 @@ public class Dynamic4D extends Dynamic implements Data4D
   private Vector<VectorNoise> vn;
   private VectorNoise tmpN;
   
-  private float mFactor1, mFactor2, mFactor3; // used in Noise only. Those are noise factors; 1=noise of the (vec1X,vec1Y,vec1Z,vec1W) vector; 2=noise of (vec2X,vec2Y,vec2Z,vec2W) and same for vec3.
+  private float mFactor1, mFactor2, mFactor3; // used in Noise only. FactorN = noise factor of vecN.
   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)
   private float vec2X,vec2Y,vec2Z,vec2W;      // vector perpendicular to v(t) and to vec1.
   private float vec3X,vec3Y,vec3Z,vec3W;      // vector perpendicular to v(t) and to vec1.
@@ -311,7 +311,7 @@ public class Dynamic4D extends Dynamic implements Data4D
       float aw = 6*vc.aw*time+2*vc.bw;
      
       float v_sq = vx*vx+vy*vy+vz*vz+vw*vw;
-      float delta = (vx*ax+vy*ay+vz*az*vw*vw)/v_sq;
+      float delta = (vx*ax+vy*ay+vz*az+vw*aw)/v_sq;
      
       vec1X = ax-delta*vx;
       vec1Y = ay-delta*vy;
@@ -332,10 +332,10 @@ public class Dynamic4D extends Dynamic implements Data4D
       float coeff31 = vw/v_sq;
       float coeff32 = vec1W/vec1_sq;
       float coeff33 = vec2W/vec2_sq;
-      vec2X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X;
-      vec2Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y;
-      vec2Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z;
-      vec2W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W;
+      vec3X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X;
+      vec3Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y;
+      vec3Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z;
+      vec3W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W;
      
       float vec3_sq = vec3X*vec3X+vec3Y*vec3Y+vec3Z*vec3Z+vec3W*vec3W;
      
@@ -392,10 +392,10 @@ public class Dynamic4D extends Dynamic implements Data4D
         float coeff31 = vw/v_sq;
         float coeff32 = vec1W/vec1_sq;
         float coeff33 = vec2W/vec2_sq;
-        vec2X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X;
-        vec2Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y;
-        vec2Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z;
-        vec2W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W;
+        vec3X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X;
+        vec3Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y;
+        vec3Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z;
+        vec3W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W;
      
         float vec3_sq = vec3X*vec3X+vec3Y*vec3Y+vec3Z*vec3Z+vec3W*vec3W;
      
diff --git a/src/main/java/org/distorted/library/type/Dynamic5D.java b/src/main/java/org/distorted/library/type/Dynamic5D.java
new file mode 100644
index 0000000..bb76a8e
--- /dev/null
+++ b/src/main/java/org/distorted/library/type/Dynamic5D.java
@@ -0,0 +1,893 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2016 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Distorted.                                                               //
+//                                                                                               //
+// Distorted is free software: you can redistribute it and/or modify                             //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Distorted is distributed in the hope that it will be useful,                                  //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.library.type;
+
+import java.util.Vector;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/** 
+* A 5-dimensional implementation of the Dynamic class to interpolate between a list
+* of Static5Ds.
+*/
+
+public class Dynamic5D extends Dynamic implements Data5D
+  {
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// the coefficients of the X(t), Y(t), Z(t), W(t), V(t) polynomials: X(t) = ax*T^3 + bx*T^2 + cx*t + dx  etc.
+// (x,y,z,w,v) is the vector tangent to the path.
+// (vx,vy,vz,vw,vv) is the original vector from vv (copied here so when interpolating we can see if it is 
+// still valid and if not - rebuild the Cache
+  
+  private class VectorCache
+    {
+    float ax, bx, cx, dx;
+    float ay, by, cy, dy;
+    float az, bz, cz, dz;
+    float aw, bw, cw, dw;
+    float av, bv, cv, dv;
+   
+    float x,y,z,w,v;
+    float vx,vy,vz,vw,vv;
+    }
+  
+  private class VectorNoise
+    {
+    float[] nx;
+    float[] ny;
+    float[] nz;
+    float[] nw;
+    float[] nv;
+   
+    VectorNoise()
+      {
+      nx = new float[NUM_NOISE]; 
+      nx[0] = mRnd.nextFloat();
+      for(int i=1; i<NUM_NOISE; i++) nx[i] = nx[i-1] + mRnd.nextFloat();
+      float sum = nx[NUM_NOISE-1] + mRnd.nextFloat();
+      for(int i=0; i<NUM_NOISE; i++) nx[i] /=sum;
+     
+      ny = new float[NUM_NOISE];
+      for(int i=0; i<NUM_NOISE; i++) ny[i] = mRnd.nextFloat()-0.5f;
+     
+      nz = new float[NUM_NOISE];
+      for(int i=0; i<NUM_NOISE; i++) nz[i] = mRnd.nextFloat()-0.5f;
+     
+      nw = new float[NUM_NOISE];
+      for(int i=0; i<NUM_NOISE; i++) nw[i] = mRnd.nextFloat()-0.5f;  
+
+      nv = new float[NUM_NOISE];
+      for(int i=0; i<NUM_NOISE; i++) nv[i] = mRnd.nextFloat()-0.5f;  
+      }
+    }
+  
+  private Vector<VectorCache> vc;
+  private VectorCache tmp1, tmp2;
+
+  private Vector<Static5D> vv;
+  private Static5D prev, curr, next;
+  
+  private Vector<VectorNoise> vn;
+  private VectorNoise tmpN;
+  
+  private float mFactor1, mFactor2, mFactor3, mFactor4;  // used in Noise only. FactorN = noise factor of vector vecN.
+  private float vec1X,vec1Y,vec1Z,vec1W,vec1V; //
+  private float vec2X,vec2Y,vec2Z,vec2W,vec2V; // 4 noise vectors.
+  private float vec3X,vec3Y,vec3Z,vec3W,vec3V; // 
+  private float vec4X,vec4Y,vec4Z,vec4W,vec4V; // 
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  synchronized void createNoise()
+    {
+    if( vn==null )
+      {  
+      vn = new Vector<>();
+      for(int i=0; i<numPoints; i++) vn.add(new VectorNoise());
+      }
+    }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// no array bounds checking!
+  
+  private void vec(int c)
+    {
+    int p = c>0 ? c-1: numPoints-1;
+    int n = c<numPoints-1 ? c+1: 0;
+    
+    prev = vv.elementAt(p);
+    curr = vv.elementAt(c);
+    next = vv.elementAt(n);
+
+    tmp1 = vc.elementAt(c);
+    
+    float px = curr.x - prev.x;
+    float py = curr.y - prev.y;
+    float pz = curr.z - prev.z;
+    float pw = curr.w - prev.w;
+    float pv = curr.v - prev.v;
+    float nx = next.x - curr.x;
+    float ny = next.y - curr.y;
+    float nz = next.z - curr.z;
+    float nw = next.w - curr.w;
+    float nv = next.v - curr.v;
+     
+    float d = nx*nx+ny*ny+nz*nz+nw*nw+nv*nv;
+    
+    if( d>0 )
+      {
+      float q = (float)Math.sqrt((px*px+py*py+pz*pz+pw*pw+pv*pv)/d);
+      
+      if( q>1 )
+        {
+        tmp1.x = nx+px/q;
+        tmp1.y = ny+py/q;
+        tmp1.z = nz+pz/q;
+        tmp1.w = nw+pw/q;
+        tmp1.v = nv+pv/q;
+        }
+      else
+        {
+        tmp1.x = px+nx*q;
+        tmp1.y = py+ny*q;
+        tmp1.z = pz+nz*q;
+        tmp1.w = pw+nw*q;
+        tmp1.v = pv+nv*q;
+        }
+      }
+    else
+      {
+      tmp1.x = 0.0f;
+      tmp1.y = 0.0f;
+      tmp1.z = 0.0f;  
+      tmp1.w = 0.0f;
+      tmp1.v = 0.0f;
+      }
+    }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+  
+  private void recomputeCache()
+    {  
+    if( numPoints==1 )
+      {
+      tmp1= vc.elementAt(0);
+      curr= vv.elementAt(0);
+        
+      tmp1.ax = tmp1.ay = tmp1.az = tmp1.aw = tmp1.av = 0.0f;
+      tmp1.bx = tmp1.by = tmp1.bz = tmp1.bw = tmp1.bv = 0.0f;
+      tmp1.cx = curr.x;
+      tmp1.cy = curr.y;
+      tmp1.cz = curr.z;
+      tmp1.cw = curr.w;
+      tmp1.cv = curr.v;
+      tmp1.dx = tmp1.dy = tmp1.dz = tmp1.dw = tmp1.dv = 0.0f;
+      }
+    else if( numPoints==2 )
+      {
+      tmp1= vc.elementAt(0);
+      tmp2= vc.elementAt(1);
+      curr= vv.elementAt(0);
+      next= vv.elementAt(1);
+      
+      tmp1.ax = tmp1.ay = tmp1.az = tmp1.aw = tmp1.av = 0.0f;
+      tmp1.bx = tmp1.by = tmp1.bz = tmp1.bw = tmp1.bv = 0.0f;
+      tmp1.cx = next.x - curr.x;
+      tmp1.cy = next.y - curr.y;
+      tmp1.cz = next.z - curr.z;
+      tmp1.cw = next.w - curr.w;
+      tmp1.cv = next.v - curr.v;
+      tmp1.dx = curr.x;
+      tmp1.dy = curr.y;
+      tmp1.dz = curr.z;
+      tmp1.dw = curr.w;
+      tmp1.dv = curr.v;
+      
+      tmp2.ax = tmp2.ay = tmp2.az = tmp2.aw = tmp2.av = 0.0f;
+      tmp2.bx = tmp2.by = tmp2.bz = tmp2.bw = tmp2.bv = 0.0f;
+      tmp2.cx = curr.x - next.x;
+      tmp2.cy = curr.y - next.y;
+      tmp2.cz = curr.z - next.z;
+      tmp2.cw = curr.w - next.w;
+      tmp2.cv = curr.v - next.v;
+      tmp2.dx = next.x;
+      tmp2.dy = next.y;
+      tmp2.dz = next.z;
+      tmp2.dw = next.w;
+      tmp2.dv = next.v;
+      }
+    else
+      {
+      int i, n;  
+      
+      for(i=0; i<numPoints; i++) vec(i);
+   
+      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);
+      
+        tmp1.vx = curr.x;
+        tmp1.vy = curr.y;
+        tmp1.vz = curr.z;
+        tmp1.vw = curr.w;
+        tmp1.vv = curr.v;
+        
+        tmp1.ax =  2*curr.x +   tmp1.x - 2*next.x + tmp2.x;
+        tmp1.bx = -3*curr.x - 2*tmp1.x + 3*next.x - tmp2.x;
+        tmp1.cx = tmp1.x;
+        tmp1.dx = curr.x;
+      
+        tmp1.ay =  2*curr.y +   tmp1.y - 2*next.y + tmp2.y;
+        tmp1.by = -3*curr.y - 2*tmp1.y + 3*next.y - tmp2.y;
+        tmp1.cy = tmp1.y;
+        tmp1.dy = curr.y;
+      
+        tmp1.az =  2*curr.z +   tmp1.z - 2*next.z + tmp2.z;
+        tmp1.bz = -3*curr.z - 2*tmp1.z + 3*next.z - tmp2.z;
+        tmp1.cz = tmp1.z;
+        tmp1.dz = curr.z;
+        
+        tmp1.aw =  2*curr.w +   tmp1.w - 2*next.w + tmp2.w;
+        tmp1.bw = -3*curr.w - 2*tmp1.w + 3*next.w - tmp2.w;
+        tmp1.cw = tmp1.w;
+        tmp1.dw = curr.w;
+        
+        tmp1.av =  2*curr.v +   tmp1.v - 2*next.v + tmp2.v;
+        tmp1.bv = -3*curr.v - 2*tmp1.v + 3*next.v - tmp2.v;
+        tmp1.cv = tmp1.v;
+        tmp1.dv = curr.v;
+        }
+      }
+   
+    cacheDirty = false;
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private float noise(float time,int vecNum)
+    {
+    float lower, upper, len;  
+    float d = time*(NUM_NOISE+1);
+    int index = (int)d;
+    if( index>=NUM_NOISE+1 ) index=NUM_NOISE;
+    tmpN = vn.elementAt(vecNum);
+   
+    float t = d-index;
+    t = t*t*(3-2*t);
+   
+    switch(index)
+      {
+      case 0        : mFactor1 = mNoise*tmpN.ny[0]*t;
+                      mFactor2 = mNoise*tmpN.nz[0]*t;
+                      mFactor3 = mNoise*tmpN.nw[0]*t;
+                      mFactor4 = mNoise*tmpN.nv[0]*t;
+                      return time + mNoise*(d*tmpN.nx[0]-time);
+      case NUM_NOISE: mFactor1= mNoise*tmpN.ny[NUM_NOISE-1]*(1-t);
+                      mFactor2= mNoise*tmpN.nz[NUM_NOISE-1]*(1-t);
+                      mFactor3= mNoise*tmpN.nw[NUM_NOISE-1]*(1-t);
+                      mFactor4= mNoise*tmpN.nv[NUM_NOISE-1]*(1-t);
+                      len = ((float)NUM_NOISE)/(NUM_NOISE+1);
+                      lower = len + mNoise*(tmpN.nx[NUM_NOISE-1]-len);  
+                      return (1.0f-lower)*(d-NUM_NOISE) + lower;
+      default       : float ya,yb;
+                      yb = tmpN.ny[index  ];
+                      ya = tmpN.ny[index-1];
+                      mFactor1 = mNoise*((yb-ya)*t+ya);
+                      yb = tmpN.nz[index  ];
+                      ya = tmpN.nz[index-1];
+                      mFactor2 = mNoise*((yb-ya)*t+ya);
+                      yb = tmpN.nw[index  ];
+                      ya = tmpN.nw[index-1];
+                      mFactor3 = mNoise*((yb-ya)*t+ya);
+                      yb = tmpN.nv[index  ];
+                      ya = tmpN.nv[index-1];
+                      mFactor4 = mNoise*((yb-ya)*t+ya);
+   
+                      len = ((float)index)/(NUM_NOISE+1);
+                      lower = len + mNoise*(tmpN.nx[index-1]-len);   
+                      len = ((float)index+1)/(NUM_NOISE+1); 
+                      upper = len + mNoise*(tmpN.nx[index  ]-len);
+            
+                      return (upper-lower)*(d-index) + lower; 
+      }
+    }
+     
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// v is the speed vector (i.e. position p(t) differentiated by time)
+// a is the acceleration vector (differentiate once more)
+//
+// Now we construct orthogonal basis with Gram-Schmidt:  
+//
+// vec1 = a-delta*v 
+//    where delta = (v*a)/|v|^2
+// vec2 = (0,0,1,0,0) - coeff1*(vx,vy,vz,vw,vv) - coeff2*(vec1x,vec1y,vec1z,vec1w,vec1v)                                     
+//    where coeff1 = vz/|v|^2, coeff2 = vec1Z/|vec1|^2
+// vec3 = (0,0,0,1,0) - coeff1*(vx,vy,vz,vw,vv) - coeff2*(vec1x,vec1y,vec1z,vec1w,vec1v) - coeff3*(vec2x,vec2y,vec2z,vec2w,vec2v)  
+//    where coeff1 = vw/|v|^2, coeff2 = vec1W/|vec1|^2, coeff3 = vec2W/|vec2|^2
+// vec4 = (0,0,0,0,1) - coeff1*(vx,vy,vz,vw,vv) - coeff2*(vec1x,vec1y,vec1z,vec1w,vec1v) - coeff3*(vec2x,vec2y,vec2z,vec2w,vec2v) - coeff4*(vec3x,vec3y,vec3z,vec3w,vec3v) 
+//    where coeff1 = vv/|v|^2, coeff2 = vec1V/|vec1|^2, coeff3 = vec2V/|vec2|^2, coeff4 = vec3V/|vec3|^2
+//
+// this is going to fail if by chance v(t) happens to be one of the standard (0,...,1,...,0) vectors of the orthonormal base!
+ 
+  private void setUpVectors(float time,VectorCache vc)
+    {
+    if( vc!=null )
+      {
+      float vx = (3*vc.ax*time+2*vc.bx)*time+vc.cx;
+      float vy = (3*vc.ay*time+2*vc.by)*time+vc.cy;
+      float vz = (3*vc.az*time+2*vc.bz)*time+vc.cz;
+      float vw = (3*vc.aw*time+2*vc.bw)*time+vc.cw;
+      float vv = (3*vc.av*time+2*vc.bv)*time+vc.cv;
+     
+      float ax = 6*vc.ax*time+2*vc.bx;
+      float ay = 6*vc.ay*time+2*vc.by;
+      float az = 6*vc.az*time+2*vc.bz;
+      float aw = 6*vc.aw*time+2*vc.bw;
+      float av = 6*vc.av*time+2*vc.bv;
+     
+      float v_sq = vx*vx+vy*vy+vz*vz+vw*vw+vv*vv;
+      float delta = (vx*ax+vy*ay+vz*az+vw*aw+vv*av)/v_sq;
+     
+      vec1X = ax-delta*vx;
+      vec1Y = ay-delta*vy;
+      vec1Z = az-delta*vz;
+      vec1W = aw-delta*vw;
+      vec1V = av-delta*vv;
+     
+      // construct vec2, vec3 and vec4. Cross product does not work in 5th dimension!
+      float vec1_sq = vec1X*vec1X+vec1Y*vec1Y+vec1Z*vec1Z+vec1W*vec1W+vec1V*vec1V;
+      float coeff21 = vz/v_sq;
+      float coeff22 = vec1Z/vec1_sq;
+      vec2X = 0.0f - coeff21*vx - coeff22*vec1X;
+      vec2Y = 0.0f - coeff21*vy - coeff22*vec1Y;
+      vec2Z = 1.0f - coeff21*vz - coeff22*vec1Z;
+      vec2W = 0.0f - coeff21*vw - coeff22*vec1W;
+      vec2V = 0.0f - coeff21*vv - coeff22*vec1V;
+     
+      float vec2_sq = vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z+vec2W*vec2W+vec2V*vec2V;
+      float coeff31 = vw/v_sq;
+      float coeff32 = vec1W/vec1_sq;
+      float coeff33 = vec2W/vec2_sq;
+      vec3X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X;
+      vec3Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y;
+      vec3Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z;
+      vec3W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W;
+      vec3V = 0.0f - coeff31*vv - coeff32*vec1V - coeff33*vec2V;
+     
+      float vec3_sq = vec3X*vec3X+vec3Y*vec3Y+vec3Z*vec3Z+vec3W*vec3W+vec3V*vec3V;
+      float coeff41 = vv/v_sq;
+      float coeff42 = vec1V/vec1_sq;
+      float coeff43 = vec2V/vec2_sq;
+      float coeff44 = vec3V/vec3_sq;
+      vec4X = 0.0f - coeff41*vx - coeff42*vec1X - coeff43*vec2X - coeff44*vec3X;
+      vec4Y = 0.0f - coeff41*vy - coeff42*vec1Y - coeff43*vec2Y - coeff44*vec3Y;
+      vec4Z = 0.0f - coeff41*vz - coeff42*vec1Z - coeff43*vec2Z - coeff44*vec3Z;
+      vec4W = 0.0f - coeff41*vw - coeff42*vec1W - coeff43*vec2W - coeff44*vec3W;
+      vec4V = 1.0f - coeff41*vv - coeff42*vec1V - coeff43*vec2V - coeff44*vec3V;
+     
+      float vec4_sq = vec4X*vec4X+vec4Y*vec4Y+vec4Z*vec4Z+vec4W*vec4W+vec4V*vec4V;
+
+      float len1 = (float)Math.sqrt(v_sq/vec1_sq);   
+      float len2 = (float)Math.sqrt(v_sq/vec2_sq);   
+      float len3 = (float)Math.sqrt(v_sq/vec3_sq);
+      float len4 = (float)Math.sqrt(v_sq/vec4_sq);
+     
+      vec1X*=len1;
+      vec1Y*=len1;
+      vec1Z*=len1;
+      vec1W*=len1;
+      vec1V*=len1;
+     
+      vec2X*=len2;
+      vec2Y*=len2;
+      vec2Z*=len2;
+      vec2W*=len2;
+      vec2V*=len2;
+     
+      vec3X*=len3;
+      vec3Y*=len3;
+      vec3Z*=len3;
+      vec3W*=len3;
+      vec3V*=len3;
+     
+      vec4X*=len4;
+      vec4Y*=len4;
+      vec4Z*=len4;
+      vec4W*=len4;
+      vec4V*=len4;
+      }
+    else
+      {
+      curr = vv.elementAt(0);
+      next = vv.elementAt(1); 
+     
+      float vx = (next.x-curr.x);
+      float vy = (next.y-curr.y);
+      float vz = (next.z-curr.z);
+      float vw = (next.w-curr.w);
+      float vv = (next.v-curr.v);
+     
+      float b = (float)Math.sqrt(vx*vx+vy*vy+vz*vz+vw*vw);
+     
+      if( b>0.0f )
+        {
+        vec1X = vx*vv/b;
+        vec1Y = vy*vv/b;
+        vec1Z = vz*vv/b;
+        vec1W = vw*vv/b;
+        vec1V = -b;
+      
+        float v_sq = vx*vx+vy*vy+vz*vz+vw*vw+vv*vv;
+     
+        // construct vec2, vec3 and vec4. Cross product does not work in 5th dimension!
+        float vec1_sq = vec1X*vec1X+vec1Y*vec1Y+vec1Z*vec1Z+vec1W*vec1W+vec1V*vec1V;
+        float coeff21 = vz/v_sq;
+        float coeff22 = vec1Z/vec1_sq;
+        vec2X = 0.0f - coeff21*vx - coeff22*vec1X;
+        vec2Y = 0.0f - coeff21*vy - coeff22*vec1Y;
+        vec2Z = 1.0f - coeff21*vz - coeff22*vec1Z;
+        vec2W = 0.0f - coeff21*vw - coeff22*vec1W;
+        vec2V = 0.0f - coeff21*vv - coeff22*vec1V;
+     
+        float vec2_sq = vec2X*vec2X+vec2Y*vec2Y+vec2Z*vec2Z+vec2W*vec2W+vec2V*vec2V;
+        float coeff31 = vw/v_sq;
+        float coeff32 = vec1W/vec1_sq;
+        float coeff33 = vec2W/vec2_sq;
+        vec3X = 0.0f - coeff31*vx - coeff32*vec1X - coeff33*vec2X;
+        vec3Y = 0.0f - coeff31*vy - coeff32*vec1Y - coeff33*vec2Y;
+        vec3Z = 0.0f - coeff31*vz - coeff32*vec1Z - coeff33*vec2Z;
+        vec3W = 1.0f - coeff31*vw - coeff32*vec1W - coeff33*vec2W;
+        vec3V = 0.0f - coeff31*vv - coeff32*vec1V - coeff33*vec2V;
+     
+        float vec3_sq = vec3X*vec3X+vec3Y*vec3Y+vec3Z*vec3Z+vec3W*vec3W+vec3V*vec3V;
+        float coeff41 = vv/v_sq;
+        float coeff42 = vec1V/vec1_sq;
+        float coeff43 = vec2V/vec2_sq;
+        float coeff44 = vec3V/vec3_sq;
+        vec4X = 0.0f - coeff41*vx - coeff42*vec1X - coeff43*vec2X - coeff44*vec3X;
+        vec4Y = 0.0f - coeff41*vy - coeff42*vec1Y - coeff43*vec2Y - coeff44*vec3Y;
+        vec4Z = 0.0f - coeff41*vz - coeff42*vec1Z - coeff43*vec2Z - coeff44*vec3Z;
+        vec4W = 0.0f - coeff41*vw - coeff42*vec1W - coeff43*vec2W - coeff44*vec3W;
+        vec4V = 1.0f - coeff41*vv - coeff42*vec1V - coeff43*vec2V - coeff44*vec3V;
+     
+        float vec4_sq = vec4X*vec4X+vec4Y*vec4Y+vec4Z*vec4Z+vec4W*vec4W+vec4V*vec4V;
+
+        float len1 = (float)Math.sqrt(v_sq/vec1_sq);    
+        float len2 = (float)Math.sqrt(v_sq/vec2_sq);    
+        float len3 = (float)Math.sqrt(v_sq/vec3_sq);
+        float len4 = (float)Math.sqrt(v_sq/vec4_sq);
+     
+        vec1X*=len1;
+        vec1Y*=len1;
+        vec1Z*=len1;
+        vec1W*=len1;
+        vec1V*=len1;
+     
+        vec2X*=len2;
+        vec2Y*=len2;
+        vec2Z*=len2;
+        vec2W*=len2;
+        vec2V*=len2;
+     
+        vec3X*=len3;
+        vec3Y*=len3;
+        vec3Z*=len3;
+        vec3W*=len3;
+        vec3V*=len3;
+     
+        vec4X*=len4;
+        vec4Y*=len4;
+        vec4Z*=len4;
+        vec4W*=len4;
+        vec4V*=len4;
+        }
+      else
+        {
+        vec1X = vv;
+        vec1Y = 0.0f;
+        vec1Z = 0.0f;
+        vec1W = 0.0f;
+        vec1V = 0.0f;
+      
+        vec2X = 0.0f;
+        vec2Y = vv;
+        vec2Z = 0.0f;
+        vec2W = 0.0f;
+        vec2V = 0.0f;
+      
+        vec3X = 0.0f;
+        vec3Y = 0.0f;
+        vec3Z = vv;
+        vec3W = 0.0f;
+        vec3V = 0.0f;
+      
+        vec4X = 0.0f;
+        vec4Y = 0.0f;
+        vec4Z = 0.0f;
+        vec4W = vv;
+        vec4V = 0.0f;
+        }
+      }
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// PUBLIC API
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Default constructor.
+ */
+  public Dynamic5D()
+    {
+    vv = new Vector<>();
+    vc = new Vector<>();
+    vn = null;
+    numPoints = 0;
+    cacheDirty = false;
+    mMode = MODE_LOOP;
+    mDuration = 0;
+    mCount = 0.5f;
+    mNoise = 0.0f;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Default constructor.
+ *
+ * @param duration number of milliseconds it takes to do a full loop/path from first vector to the
+ *                 last and back to the first
+ * @param count    number of loops/paths we will do; mCount = 1.5 means we go from the first vector
+ *                 to the last, back to first, and to the last again.
+ */
+  public Dynamic5D(int duration, float count)
+    {
+    vv = new Vector<>();
+    vc = new Vector<>();
+    vn = null;
+    numPoints = 0;
+    cacheDirty = false;
+    mMode = MODE_LOOP;
+    mDuration = duration;
+    mCount = count;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Returns the location'th Static5D.
+ *   
+ * @param location the index of the Point we are interested in.
+ * @return The Static5D, if 0<=location&lt;getNumPoints(), or null otherwise.
+ */  
+  public synchronized Static5D getPoint(int location)
+    {
+    return (location>=0 && location<numPoints) ? vv.elementAt(location) : null;  
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Resets the location'th Point.
+ * 
+ * @param location the index of the Point we are setting.
+ * @param x New value of its first float.
+ */
+  public synchronized void setPoint(int location, float x, float y, float z, float w, float v)
+    {
+    if( location>=0 && location<numPoints )
+      {
+      curr = vv.elementAt(location);
+   
+      if( curr!=null )
+        {
+        curr.set(x,y,z,w,v);
+        cacheDirty=true;
+        }
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds a new Static5D to the end of our list of Points to interpolate through.
+ * <p>   
+ * Only a reference to the Point gets added to the List; this means that one can add a Point 
+ * here, and later on {@link Static5D#set(float,float,float,float,float)} it to some new value and
+ * the change will be seamlessly reflected in the interpolated path.  
+ * <p>
+ * A Point can be added multiple times.
+ *   
+ * @param v The Point to add.
+ */    
+  public synchronized void add(Static5D v)
+    {
+    if( v!=null )
+      {
+      vv.add(v);
+        
+      if( vn!=null ) vn.add(new VectorNoise());
+       
+       switch(numPoints)
+         {
+         case 0: break;
+         case 1: setUpVectors(0.0f,null);
+                 break;
+         case 2: vc.add(new VectorCache());
+                 vc.add(new VectorCache());
+                 vc.add(new VectorCache());
+                 break;
+         default:vc.add(new VectorCache());
+         }
+
+       numPoints++;
+       cacheDirty = true;
+       }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Adds a new Static5D to the location'th place in our List of Points to interpolate through.
+ *   
+ * @param location Index in our List to add the new Point at.
+ * @param v The Static5D to add.
+ */  
+  public synchronized void add(int location, Static5D v)
+    {
+    if( v!=null )
+      {
+      vv.add(location, v);
+      
+      if( vn!=null ) vn.add(new VectorNoise());
+      
+      switch(numPoints)
+        {
+        case 0: break;
+        case 1: setUpVectors(0.0f,null);
+                break;
+        case 2: vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                vc.add(new VectorCache());
+                break;
+        default:vc.add(location,new VectorCache());
+        }
+
+      numPoints++;
+      cacheDirty = true;
+      }
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Removes all occurrences of Point v from the List of Points to interpolate through.  
+ * 
+ * @param v The Point to remove.
+ * @return <code>true</code> if we have removed at least one Point.
+ */
+  public synchronized boolean remove(Static5D v)
+    {
+    int n = vv.indexOf(v);
+    boolean found = false;
+   
+    while( n>=0 ) 
+      {
+      vv.remove(n);
+     
+      if( vn!=null ) vn.remove(0);
+     
+      switch(numPoints)
+        {
+        case 0:
+        case 1: 
+        case 2: break;
+        case 3: vc.removeAllElements();
+                setUpVectors(0.0f,null);
+                break;
+        default:vc.remove(n);
+        }
+
+      numPoints--;
+      found = true;
+      n = vv.indexOf(v);
+      }
+   
+    if( found ) 
+      {
+      cacheDirty=true;
+      }
+   
+    return found;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Removes a location'th Point from the List of Points we interpolate through.
+ * 
+ * @param location index of the Point we want to remove. 
+ * @return <code>true</code> if location is valid, i.e. if 0<=location&lt;getNumPoints().
+ */
+  public synchronized boolean remove(int location)
+    {
+    if( location>=0 && location<numPoints ) 
+      {
+      vv.removeElementAt(location);
+       
+      if( vn!=null ) vn.remove(0);
+      
+      switch(numPoints)
+        {
+        case 0:
+        case 1: 
+        case 2: break;
+        case 3: vc.removeAllElements();
+                setUpVectors(0.0f,null);
+                break;
+        default:vc.removeElementAt(location);
+        }
+
+      numPoints--;
+      cacheDirty = true; 
+      return true;
+      }
+
+    return false;
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Removes all Points.
+ */
+  public synchronized void removeAll()
+    {
+    numPoints = 0;
+    vv.removeAllElements();
+    vc.removeAllElements();
+    cacheDirty = false;
+   
+    if( vn!=null ) vn.removeAllElements();
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Writes the results of interpolation between the Points at time 'time' to the passed float buffer.
+ * <p>
+ * Since this is a 5-dimensional Dynamic, the resulting interpolated Static5D gets written
+ * to five locations in the buffer: buffer[offset],...,buffer[offset+4]. 
+ * 
+ * @param buffer Float buffer we will write the resulting Static5D to.
+ * @param offset Offset in the buffer where to write the result.
+ * @param time Time of interpolation. Time=0.0 would return the first Point, Time=0.5 - the last,
+ *             time=1.0 - the first again, and time 0.1 would be 1/5 of the way between the first and the last Points.
+ */    
+  public synchronized void interpolate(float[] buffer, int offset, float time)
+    {  
+    switch(numPoints)
+      {
+      case 0: buffer[offset  ] = 0.0f;
+              buffer[offset+1] = 0.0f;
+              buffer[offset+2] = 0.0f;
+              buffer[offset+3] = 0.0f;
+              buffer[offset+4] = 0.0f;
+              break;
+      case 1: curr = vv.elementAt(0);
+              buffer[offset  ] = curr.x;
+              buffer[offset+1] = curr.y;
+              buffer[offset+2] = curr.z;
+              buffer[offset+3] = curr.w;
+              buffer[offset+4] = curr.v;
+              break;
+      case 2: curr = vv.elementAt(0);
+              next = vv.elementAt(1);
+            
+              if( mMode==MODE_LOOP || mMode==MODE_PATH ) time = (time>0.5f ? 2-2*time : 2*time);
+             
+              if( vn!=null )
+                {
+                time = noise(time,0);
+            
+                buffer[offset  ] = (next.x-curr.x)*time + curr.x + (vec1X*mFactor1 + vec2X*mFactor2 + vec3X*mFactor3 + vec4X*mFactor4);
+                buffer[offset+1] = (next.y-curr.y)*time + curr.y + (vec1Y*mFactor1 + vec2Y*mFactor2 + vec3Y*mFactor3 + vec4Y*mFactor4);
+                buffer[offset+2] = (next.z-curr.z)*time + curr.z + (vec1Z*mFactor1 + vec2Z*mFactor2 + vec3Z*mFactor3 + vec4Z*mFactor4);
+                buffer[offset+3] = (next.w-curr.w)*time + curr.w + (vec1W*mFactor1 + vec2W*mFactor2 + vec3W*mFactor3 + vec4W*mFactor4); 
+                buffer[offset+4] = (next.v-curr.v)*time + curr.v + (vec1V*mFactor1 + vec2V*mFactor2 + vec3V*mFactor3 + vec4V*mFactor4); 
+                }
+              else
+                {
+                buffer[offset  ] = (next.x-curr.x)*time + curr.x;
+                buffer[offset+1] = (next.y-curr.y)*time + curr.y;
+                buffer[offset+2] = (next.z-curr.z)*time + curr.z;
+                buffer[offset+3] = (next.w-curr.w)*time + curr.w;
+                buffer[offset+4] = (next.v-curr.v)*time + curr.v;
+                }
+                
+              break;
+      default:float t = time;
+        
+              switch(mMode)
+                {
+                case MODE_LOOP: time = time*numPoints;
+                                break;
+                case MODE_PATH: time = (time<=0.5f) ? 2*time*(numPoints-1) : 2*(1-time)*(numPoints-1);
+                                break;
+                case MODE_JUMP: time = time*(numPoints-1);
+                                break;
+                }
+     
+              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
+                  {
+                  int vecNext;   
+                  mVecCurr = vecCurr;
+                       
+                  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;                
+                    }
+     
+                  next = vv.elementAt(vecNext);
+                  tmp2 = vc.elementAt(vecNext);
+              
+                  if( tmp2.vx!=next.x || tmp2.vy!=next.y || tmp2.vz!=next.z || tmp2.vw!=next.w || tmp2.vv!=next.v ) recomputeCache();
+                  }
+            
+                tmp1 = vc.elementAt(vecCurr);
+               
+                if( vn!=null )
+                  {
+                  time = noise(time,vecCurr);
+              
+                  setUpVectors(time,tmp1);
+                 
+                  buffer[offset  ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx + (vec1X*mFactor1 + vec2X*mFactor2 + vec3X*mFactor3 + vec4X*mFactor4);
+                  buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy + (vec1Y*mFactor1 + vec2Y*mFactor2 + vec3Y*mFactor3 + vec4Y*mFactor4);
+                  buffer[offset+2]= ((tmp1.az*time+tmp1.bz)*time+tmp1.cz)*time+tmp1.dz + (vec1Z*mFactor1 + vec2Z*mFactor2 + vec3Z*mFactor3 + vec4Z*mFactor4);
+                  buffer[offset+3]= ((tmp1.aw*time+tmp1.bw)*time+tmp1.cw)*time+tmp1.dw + (vec1W*mFactor1 + vec2W*mFactor2 + vec3W*mFactor3 + vec4W*mFactor4);
+                  buffer[offset+4]= ((tmp1.av*time+tmp1.bv)*time+tmp1.cv)*time+tmp1.dv + (vec1V*mFactor1 + vec2V*mFactor2 + vec3V*mFactor3 + vec4V*mFactor4);
+                  }
+                else
+                  {
+                  buffer[offset  ]= ((tmp1.ax*time+tmp1.bx)*time+tmp1.cx)*time+tmp1.dx;
+                  buffer[offset+1]= ((tmp1.ay*time+tmp1.by)*time+tmp1.cy)*time+tmp1.dy;
+                  buffer[offset+2]= ((tmp1.az*time+tmp1.bz)*time+tmp1.cz)*time+tmp1.dz;
+                  buffer[offset+3]= ((tmp1.aw*time+tmp1.bw)*time+tmp1.cw)*time+tmp1.dw;
+                  buffer[offset+4]= ((tmp1.av*time+tmp1.bv)*time+tmp1.cv)*time+tmp1.dv;
+                  }
+ 
+                break;
+                }
+      }
+    }  
+
+  }
+///////////////////////////////////////////////////////////////////////////////////////////////////
+//
diff --git a/src/main/java/org/distorted/library/type/Static5D.java b/src/main/java/org/distorted/library/type/Static5D.java
new file mode 100644
index 0000000..a52ff8a
--- /dev/null
+++ b/src/main/java/org/distorted/library/type/Static5D.java
@@ -0,0 +1,116 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// Copyright 2016 Leszek Koltunski                                                               //
+//                                                                                               //
+// This file is part of Distorted.                                                               //
+//                                                                                               //
+// Distorted is free software: you can redistribute it and/or modify                             //
+// it under the terms of the GNU General Public License as published by                          //
+// the Free Software Foundation, either version 2 of the License, or                             //
+// (at your option) any later version.                                                           //
+//                                                                                               //
+// Distorted is distributed in the hope that it will be useful,                                  //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of                                //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                                 //
+// GNU General Public License for more details.                                                  //
+//                                                                                               //
+// You should have received a copy of the GNU General Public License                             //
+// along with Distorted.  If not, see <http://www.gnu.org/licenses/>.                            //
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+package org.distorted.library.type;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * A 5-dimensional data structure containing five floats. The floats have no particular meaning; 
+ * when this data structure is used in Dynamics, we can think of it as a 5-dimensional Point
+ * a few of which the Dynamic interpolates between.
+ */
+
+public class Static5D extends Static4D implements Data5D
+  {
+  float v;
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor that initialises the value of the five floats to (vx,vy,vz,vw,vv).   
+ *   
+ * @param vx value of the first float.
+ * @param vy value of the second float.
+ * @param vz value of the third float.
+ * @param vw value of the fourth float.
+ * @param vv value of the fifth float.
+ */ 
+  public Static5D(int vx, int vy, int vz, int vw, int vv)
+    {
+    super(vx,vy,vz,vw);
+    v = vv;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Constructor that initialises the value of the five floats to (vx,vy,vz,vw,vv).   
+ *   
+ * @param vx value of the first float.
+ * @param vy value of the second float.
+ * @param vz value of the third float.
+ * @param vw value of the fourth float.
+ * @param vv value of the fifth float.
+ */ 
+  public Static5D(float vx, float vy, float vz, float vw, float vv)
+    {
+    super(vx,vy,vz,vw);
+    v = vv;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Reset the value of the floats to (vx,vy,vz,vw,vv).
+ * 
+ * @param vx new value of the first float
+ * @param vy new value of the second float
+ * @param vz new value of the third float
+ * @param vw new value of the fourth float
+ * @param vv new value of the fifth float
+ */
+  public void set(int vx, int vy, int vz, int vw, int vv)
+    {
+    x = vx;
+    y = vy;
+    z = vz;
+    w = vw;
+    v = vv;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Reset the value of the floats to (vx,vy,vz,vw,vv).
+ * 
+ * @param vx new value of the first float
+ * @param vy new value of the second float
+ * @param vz new value of the third float
+ * @param vw new value of the fourth float
+ * @param vv new value of the fifth float
+ */
+  public void set(float vx, float vy, float vz, float vw, float vv)
+    {
+    x = vx;
+    y = vy;
+    z = vz;
+    w = vw;
+    v = vv;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+/**
+ * Return the value of the fifth float contained.
+ * 
+ * @return The fifth float.
+ */
+  public float getV()
+    {
+    return v;
+    }
+  
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// end of class   
+  }
