commit 334c13fa7d420f7003f5e939af1074d29532f3ce
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Mon Nov 14 17:41:43 2016 +0000

    Make the effect Center be always 3D.

diff --git a/src/main/java/org/distorted/examples/bean/BeanRenderer.java b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
index 9224055..8883917 100644
--- a/src/main/java/org/distorted/examples/bean/BeanRenderer.java
+++ b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
@@ -46,7 +46,7 @@ class BeanRenderer implements GLSurfaceView.Renderer
 {
    private GLSurfaceView mView;
    private DistortedBitmap mBean;
-   private Static2D pLeft, pRight;
+   private Static3D pLeft, pRight;
    private Dynamic3D dLeft, dRight;
    private Static4D rLeft, rRight;
    private int bmpHeight, bmpWidth;
@@ -57,8 +57,8 @@ class BeanRenderer implements GLSurfaceView.Renderer
       {
       mView = v;
      
-      pLeft = new Static2D(106, 192);
-      pRight= new Static2D(230, 150);
+      pLeft = new Static3D(106, 192, 0);
+      pRight= new Static3D(230, 150, 0);
       
       rLeft = new Static4D(-9,-31,35,35);
       rRight= new Static4D(-9,-31,35,35);
diff --git a/src/main/java/org/distorted/examples/check/CheckRenderer.java b/src/main/java/org/distorted/examples/check/CheckRenderer.java
index 69ed994..399d7ce 100644
--- a/src/main/java/org/distorted/examples/check/CheckRenderer.java
+++ b/src/main/java/org/distorted/examples/check/CheckRenderer.java
@@ -137,9 +137,9 @@ class CheckRenderer implements GLSurfaceView.Renderer
       // Even if adding some of the Effects fails, the App will still start - you just won't see
       // the effects that failed to add.
 
-      Dynamic2D dSwirl = new Dynamic2D(2000,0.0f);
-      dSwirl.add(new Static2D(        0, bmpHeight/2));
-      dSwirl.add(new Static2D( bmpWidth, bmpHeight/2));
+      Dynamic3D dSwirl = new Dynamic3D(2000,0.0f);
+      dSwirl.add(new Static3D(        0, bmpHeight/2, 0));
+      dSwirl.add(new Static3D( bmpWidth, bmpHeight/2, 0));
 
       long swirlEffectID = mSuccess.swirl( new Static1D(30), dSwirl, new Static4D( 0,0,40,40) );
 
@@ -152,7 +152,7 @@ class CheckRenderer implements GLSurfaceView.Renderer
       dDeform.add(new Static3D( 0,         0,0));
       dDeform.add(new Static3D( 0,-bmpHeight,0));
 
-      long deformEffectID = mSuccess.deform(dDeform, new Static2D(bmpWidth/2,0) );
+      long deformEffectID = mSuccess.deform(dDeform, new Static3D(bmpWidth/2,0,0) );
 
       if( deformEffectID<0 )
         {
diff --git a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
index 9dac6e2..fb069b4 100644
--- a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
+++ b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
@@ -49,7 +49,7 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
    
    private GLSurfaceView mView;
    private DistortedBitmap[] bmp;
-   private Static2D mPoint;
+   private Static3D mPoint;
    private Dynamic3D dDistort;
    private int bmpHeight, bmpWidth;
     
@@ -63,7 +63,7 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
       dDistort = new Dynamic3D(3000,0.0f);
       dDistort.add(new Static3D( 25,0,0));
       dDistort.add(new Static3D(-25,0,0));
-      mPoint = new Static2D(305, 380);
+      mPoint = new Static3D(305, 380, 0);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
index 9016f3e..16566a9 100644
--- a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
@@ -50,7 +50,7 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
    
    private GLSurfaceView mView;
    private DistortedBitmap[] bmp;
-   private Static2D pLeft, pRight, pNose1;
+   private Static3D pLeft, pRight, pNose1;
    private Static4D RegionEye;
    private Dynamic3D mDI;
    private int bmpHeight, bmpWidth;
@@ -62,15 +62,15 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
       mView = v;
       
       // bmp[0] effects
-      pLeft = new Static2D(214, 206);
-      pRight= new Static2D(390, 212);
+      pLeft = new Static3D(214, 206, 0);
+      pRight= new Static3D(390, 212, 0);
       RegionEye = new Static4D(0,0,60,60);
       
       // bmp[1] effects
       mDI = new Dynamic3D(1000,0.0f);
       mDI.add(new Static3D( 50,0,0));
       mDI.add(new Static3D(-50,0,0));
-      pNose1 = new Static2D(305, 340);
+      pNose1 = new Static3D(305, 340, 0);
       
       // we don't need to prepare anything for bmp[2] effects
       }
diff --git a/src/main/java/org/distorted/examples/effectqueue/EffectQueueSurfaceView.java b/src/main/java/org/distorted/examples/effectqueue/EffectQueueSurfaceView.java
index 63edbb1..cfa21d7 100644
--- a/src/main/java/org/distorted/examples/effectqueue/EffectQueueSurfaceView.java
+++ b/src/main/java/org/distorted/examples/effectqueue/EffectQueueSurfaceView.java
@@ -43,7 +43,7 @@ public class EffectQueueSurfaceView extends GLSurfaceView
   private int mScrW, mScrH;
     
   private Static4D mRegionV, mRegionF;
-  private Static2D mPoint;
+  private Static3D mPoint;
   private Dynamic1D mInterA, mInterB, mInterC, mInterS;
   private Dynamic3D mInterD;
 
@@ -98,7 +98,7 @@ public class EffectQueueSurfaceView extends GLSurfaceView
       mRenderer = new EffectQueueRenderer(this);
       setRenderer(mRenderer);
 
-      mPoint  = new Static2D(0,0);
+      mPoint  = new Static3D(0,0,0);
       mRegionV= new Static4D(0,0,60,60);
       mRegionF= new Static4D(0,0,60,60);
         
@@ -140,7 +140,7 @@ public class EffectQueueSurfaceView extends GLSurfaceView
       {
       case MotionEvent.ACTION_DOWN: x = (int)event.getX()* mRenderer.BWID/mScrW;
                                     y = (int)event.getY()* mRenderer.BHEI/mScrH;
-                                    mPoint.set(x,y);
+                                    mPoint.set(x,y,0);
                                     mRegionF.set(x,y,60,60);
                                     EffectQueueActivity act = (EffectQueueActivity)getContext();
 
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java b/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java
index a155d59..ef0564c 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java
@@ -71,7 +71,7 @@ public class Effects3DActivity extends Activity
 
   private ArrayList<Effects3DEffect> mEffects;
   private int mEffectAdd;
-  private float mCenterX, mCenterY;
+  private float mCenterX, mCenterY, mCenterZ;
   private float mRegionX, mRegionY, mRegionR;
 
   private EffectNames[] mEffectNames;
@@ -321,14 +321,15 @@ public class Effects3DActivity extends Activity
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void setCenter(float x, float y)
+  public void setCenter(float x, float y, float z)
     {
     mCenterX = x;
     mCenterY = y;
+    mCenterZ = z;
 
     Effects3DSurfaceView view = (Effects3DSurfaceView)findViewById(R.id.effects3dSurfaceView);
 
-    view.getRenderer().setCenter( mCenterX, mCenterY );
+    view.getRenderer().setCenter( mCenterX, mCenterY, mCenterZ );
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -345,6 +346,13 @@ public class Effects3DActivity extends Activity
     return mCenterY;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public float getCenterZ()
+    {
+    return mCenterZ;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public float getRegionX()
@@ -450,6 +458,27 @@ public class Effects3DActivity extends Activity
     return mObject==null ? 0: mObject.getHeight();
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getDepth()
+    {
+    return mObject==null ? 0: mObject.getDepth();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getScreenWidth()
+    {
+    return 0;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getScreenHeight()
+    {
+    return 0;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   private void resetData()
@@ -530,7 +559,7 @@ public class Effects3DActivity extends Activity
     Effects3DSurfaceView view = (Effects3DSurfaceView)findViewById(R.id.effects3dSurfaceView);
     Effects3DRenderer renderer= view.getRenderer();
 
-    renderer.setCenter( mCenterX, mCenterY );
+    renderer.setCenter( mCenterX, mCenterY, mCenterZ );
     renderer.setRegion( mRegionX, mRegionY, mRegionR );
     renderer.mQuat1.set(0,0,0,1);
     renderer.mQuat2.set(0,0,0,1);
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DEffect.java b/src/main/java/org/distorted/examples/effects3d/Effects3DEffect.java
index 7de4a91..d91cc30 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DEffect.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DEffect.java
@@ -59,15 +59,17 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
   private Dynamic1D mDyn1;
   private Dynamic2D mDyn2;
   private Dynamic3D mDyn3;
+  private Dynamic4D mDyn4;
   private Dynamic5D mDyn5;
   private Static1D  mSta1;
   private Static2D  mSta2;
   private Static3D  mSta3;
+  private Static4D  mSta4;
   private Static5D  mSta5;
   private Dynamic4D mRegionDyn;
   private Static4D  mRegionSta;
-  private Dynamic2D mCenterDyn;
-  private Static2D  mCenterSta;
+  private Dynamic3D mCenterDyn;
+  private Static3D  mCenterSta;
 
   private View mButton, mEffect, mCenter, mRegion;
   private long mId;
@@ -79,6 +81,12 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
     {
     switch(mName)
       {
+      case ROTATE           : mId = object.rotate    (mDyn4, mCenterDyn); break;
+      case QUATERNION       : mId = object.quaternion(mDyn4, mCenterDyn); break;
+      case MOVE             : mId = object.move      (mDyn3)             ; break;
+      case SCALE            : mId = object.scale     (mDyn3)             ; break;
+      case SHEAR            : mId = object.shear     (mDyn3, mCenterDyn); break;
+
       case DISTORT: mId = object.distort(mDyn3, mCenterDyn, mRegionDyn); break;
       case DEFORM : mId = object.deform (mDyn3, mCenterDyn            ); break;
       case SINK   : mId = object.sink   (mDyn1, mCenterDyn, mRegionDyn); break;
@@ -107,12 +115,37 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
     {
     switch(mName)
       {
+      case ROTATE           : float an = (mInter[0]-50)*180/50;
+                              float rx = (mInter[1]-50)/ 50.0f;
+                              float ry = (mInter[2]-50)/ 50.0f;
+                              float rz = (mInter[3]-50)/ 50.0f;
+                              mSta4.set(an,rx,ry,rz);
+                              break;
+      case QUATERNION       :
+                              break;
+      case MOVE             : float sw = mAct.get().getScreenWidth()/50.0f;
+                              float sh = mAct.get().getScreenWidth()/50.0f;
+                              float xm = (mInter[0]-50)*sw;
+                              float ym = (mInter[1]-50)*sh;
+                              float zm = (mInter[2]-50)*(sw+sh)/2;
+                              mSta3.set(xm,ym,zm);
+                              break;
+      case SCALE            : float xs = (mInter[0]>50 ? 0.18f : 0.018f)*(mInter[0]-50) + 1;
+                              float ys = (mInter[1]>50 ? 0.18f : 0.018f)*(mInter[1]-50) + 1;
+                              float zs = (mInter[2]>50 ? 0.18f : 0.018f)*(mInter[2]-50) + 1;
+                              mSta3.set(xs,ys,zs);
+                              break;
+      case SHEAR            : float xsh = (mInter[0]-50)/25.0f;
+                              float ysh = (mInter[1]-50)/25.0f;
+                              float zsh = (mInter[2]-50)/25.0f;
+                              mSta3.set(xsh,ysh,zsh);
+                              break;
       case DISTORT          :
-      case DEFORM           : float l = mAct.get().getWidth()/50.0f;
-                              float x = (mInter[0]-50)*l;
-                              float y = (mInter[1]-50)*l;
-                              float z = (mInter[2]-50)*l;
-                              mSta3.set(x,y,z);
+      case DEFORM           : float ld = mAct.get().getWidth()/50.0f;
+                              float xd = (mInter[0]-50)*ld;
+                              float yd = (mInter[1]-50)*ld;
+                              float zd = (mInter[2]-50)*ld;
+                              mSta3.set(xd,yd,zd);
                               break;
       case WAVE             : float l2 = mAct.get().getWidth()/50.0f;
                               float x2 = (mInter[0]-50)*l2;
@@ -156,6 +189,8 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
       case 2: mInter[1] = 50;
       case 1: mInter[0] = 50;
       }
+
+    if( mName==EffectNames.ROTATE ) mInter[1]= 100;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -185,6 +220,15 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
       text += " ("+f1+","+f2+","+f3+")";
       }
 
+    if( mSta4 !=null )
+      {
+      float f1 = ((int)(mSta4.getX()*100))/100.0f;
+      float f2 = ((int)(mSta4.getY()*100))/100.0f;
+      float f3 = ((int)(mSta4.getZ()*100))/100.0f;
+      float f4 = ((int)(mSta4.getW()*100))/100.0f;
+      text += " ("+f1+","+f2+","+f3+","+f4+")";
+      }
+
     if( mSta5 !=null )
       {
       float f1 = ((int)(mSta5.getX()*100))/100.0f;
@@ -206,7 +250,9 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
 
     float x = (mInterCenter[0]*0.012f - 0.1f)*act.getWidth();
     float y = (mInterCenter[1]*0.012f - 0.1f)*act.getHeight();
-    mCenterSta.set(x,y);
+    float z = (mInterCenter[2]*0.012f - 0.1f)*act.getDepth();
+
+    mCenterSta.set(x,y,z);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -215,6 +261,7 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
     {
     mInterCenter[0] = 50;
     mInterCenter[1] = 50;
+    mInterCenter[2] = 50;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -223,8 +270,9 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
     {
     int f0 = (int)mCenterSta.getX();
     int f1 = (int)mCenterSta.getY();
+    int f2 = (int)mCenterSta.getZ();
 
-    mTextCenter.setText("center ("+f0+","+f1+")");
+    mTextCenter.setText("center ("+f0+","+f1+","+f2+")");
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -278,10 +326,12 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
     mDyn1 = null;
     mDyn2 = null;
     mDyn3 = null;
+    mDyn4 = null;
     mDyn5 = null;
     mSta1 = null;
     mSta2 = null;
     mSta3 = null;
+    mSta4 = null;
     mSta5 = null;
 
     mDimension = mName.getDimension();
@@ -300,12 +350,21 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
                mSta3 = new Static3D(0,0,0);
                mDyn3.add(mSta3);
                break;
-      case 4 : mDyn3 = new Dynamic3D();
-               mSta3 = new Static3D(0,0,0);
-               mDyn3.add(mSta3);
-               mDyn1 = new Dynamic1D();
-               mSta1 = new Static1D(0);
-               mDyn1.add(mSta1);
+      case 4 : if( mName == EffectNames.QUATERNION || mName == EffectNames.ROTATE )
+                 {
+                 mDyn4 = new Dynamic4D();
+                 mSta4 = new Static4D(0,0,0,0);
+                 mDyn4.add(mSta4);
+                 }
+               else
+                 {
+                 mDyn3 = new Dynamic3D();
+                 mSta3 = new Static3D(0,0,0);
+                 mDyn3.add(mSta3);
+                 mDyn1 = new Dynamic1D();
+                 mSta1 = new Static1D(0);
+                 mDyn1.add(mSta1);
+                 }
                break;
       case 5 : mDyn5 = new Dynamic5D();
                mSta5 = new Static5D(0,0,0,0,0);
@@ -323,10 +382,10 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
     mRegionSta   = new Static4D(0,0,0,0);
     mRegionDyn.add(mRegionSta);
 
-    mInterCenter = new int[2];
-    mSeekCenterID= new int[2];
-    mCenterDyn   = new Dynamic2D();
-    mCenterSta   = new Static2D(0,0);
+    mInterCenter = new int[3];
+    mSeekCenterID= new int[3];
+    mCenterDyn   = new Dynamic3D();
+    mCenterSta   = new Static3D(0,0,0);
     mCenterDyn.add(mCenterSta);
 
     mButton = null;
@@ -395,7 +454,7 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
                mSeekID[4] = seek[4].getId();
                mButton    = mEffect.findViewById(R.id.button5dRemove);
                break;
-      default: android.util.Log.e("Effects3DEffect", "dimension "+mDimension+" not supported!");
+      default: android.util.Log.e("Matrix3DEffect", "dimension "+mDimension+" not supported!");
                return null;
       }
 
@@ -456,25 +515,27 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
 
     mCenter = act.getLayoutInflater().inflate(R.layout.effectcenter, null);
 
-    SeekBar[] seek = new SeekBar[2];
+    SeekBar[] seek = new SeekBar[3];
 
     seek[0] = (SeekBar)mCenter.findViewById(R.id.effectCenterBarX );
     seek[1] = (SeekBar)mCenter.findViewById(R.id.effectCenterBarY );
+    seek[2] = (SeekBar)mCenter.findViewById(R.id.effectCenterBarZ );
 
     mSeekCenterID[0] = seek[0].getId();
     mSeekCenterID[1] = seek[1].getId();
+    mSeekCenterID[2] = seek[2].getId();
 
     mTextCenter = (TextView)mCenter.findViewById(R.id.effectCenterText);
 
     setDefaultCenterInter();
 
-    for(int i=0; i<2; i++)
+    for(int i=0; i<3; i++)
       {
       seek[i].setOnSeekBarChangeListener(this);
       seek[i].setProgress( mInterCenter[i] );
       }
 
-    act.setCenter(mCenterSta.getX(),mCenterSta.getY());
+    act.setCenter(mCenterSta.getX(),mCenterSta.getY(),mCenterSta.getZ());
 
     return mCenter;
     }
@@ -551,6 +612,12 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
       fillCenterStatics();
       setCenterText();
       }
+    if( bar.getId() == mSeekCenterID[2] )
+      {
+      mInterCenter[2] = progress;
+      fillCenterStatics();
+      setCenterText();
+      }
 
     if( fromUser )
       {
@@ -559,7 +626,7 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
 
       Effects3DActivity act = mAct.get();
 
-      act.setCenter(mCenterSta.getX(),mCenterSta.getY());
+      act.setCenter(mCenterSta.getX(),mCenterSta.getY(),mCenterSta.getZ());
       act.setRegion(mRegionSta.getX(),mRegionSta.getY(),mRegionSta.getZ());
       }
     }
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java b/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
index f77f112..225a301 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
@@ -101,9 +101,9 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-    void setCenter(float x, float y)
+    void setCenter(float x, float y, float z)
       {
-      mCenterPoint.set(mFactorObj*x,mFactorObj*y,0);
+      mCenterPoint.set(mFactorObj*x,mFactorObj*y,mFactorObj*z);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/fbo/FBORenderer.java b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
index 9a95cbd..e05683d 100644
--- a/src/main/java/org/distorted/examples/fbo/FBORenderer.java
+++ b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
@@ -139,7 +139,7 @@ class FBORenderer implements GLSurfaceView.Renderer
       sinkDyn.add(new Static1D(1.0f));
       sinkDyn.add(new Static1D(0.5f));
 
-      text.sink(sinkDyn, new Static2D(textWidth/2,textHeight/2));
+      text.sink(sinkDyn, new Static3D(textWidth/2,textHeight/2, 0));
 
       Dynamic1D chromaDyn = new Dynamic1D(10000,0.0f);
       chromaDyn.add(new Static1D(0.0f));
diff --git a/src/main/java/org/distorted/examples/flag/FlagRenderer.java b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
index f41366c..6661191 100644
--- a/src/main/java/org/distorted/examples/flag/FlagRenderer.java
+++ b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
@@ -85,7 +85,7 @@ class FlagRenderer implements GLSurfaceView.Renderer
       mQuatInt1.add(mQuat1);
       mQuatInt2.add(mQuat2);
 
-      Static2D waveCenter = new Static2D(mObjWidth, mObjHeight/2);  // middle of the right edge
+      Static3D waveCenter = new Static3D(mObjWidth, mObjHeight/2, 0);  // middle of the right edge
       Static4D waveRegion = new Static4D(0,0,mObjWidth,mObjWidth);
 
       mObject.wave(mWaveDyn, waveCenter, waveRegion);
diff --git a/src/main/java/org/distorted/examples/fov/FOVRenderer.java b/src/main/java/org/distorted/examples/fov/FOVRenderer.java
index b8dd1ba..c3616de 100644
--- a/src/main/java/org/distorted/examples/fov/FOVRenderer.java
+++ b/src/main/java/org/distorted/examples/fov/FOVRenderer.java
@@ -117,10 +117,10 @@ class FOVRenderer implements GLSurfaceView.Renderer
       Static3D vector = new Static3D(0,0,min/5);
       Static4D region = new Static4D(0,0,min/5,min/5);
 
-      fov.distort(vector, new Static2D(  w/4,   h/4), region);
-      fov.distort(vector, new Static2D(3*w/4,   h/4), region);
-      fov.distort(vector, new Static2D(  w/4, 3*h/4), region);
-      fov.distort(vector, new Static2D(3*w/4, 3*h/4), region);
+      fov.distort(vector, new Static3D(  w/4,   h/4, 0), region);
+      fov.distort(vector, new Static3D(3*w/4,   h/4, 0), region);
+      fov.distort(vector, new Static3D(  w/4, 3*h/4, 0), region);
+      fov.distort(vector, new Static3D(3*w/4, 3*h/4, 0), region);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/girl/GirlRenderer.java b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
index 96c8b1e..cab8f8f 100644
--- a/src/main/java/org/distorted/examples/girl/GirlRenderer.java
+++ b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
@@ -48,7 +48,7 @@ class GirlRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedBitmap mGirl;
-    private Static2D pLeft, pRight, pHips;
+    private Static3D pLeft, pRight, pHips;
     private Static4D Region, sinkRegion, HipsRegion;
     private Dynamic3D diL, diR;
     private Dynamic1D diHips, diSink;
@@ -69,8 +69,8 @@ class GirlRenderer implements GLSurfaceView.Renderer
       hipsSwirl  = 0;
       boobsSink  = 1.0f;
       
-      pLeft = new Static2D(132, 264);
-      pRight= new Static2D(247, 264);
+      pLeft = new Static3D(132, 264, 0);
+      pRight= new Static3D(247, 264, 0);
       
       // Size
       sinkRegion = new Static4D(0,0,60,60);
@@ -102,7 +102,7 @@ class GirlRenderer implements GLSurfaceView.Renderer
       diR.add(v1);
       
       // Lower Movement
-      pHips = new Static2D(216,505);
+      pHips = new Static3D(216,505,0);
       HipsRegion = new Static4D(0,0,120,120);
       diHips = new Dynamic1D(1500,0.0f);
       
diff --git a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
index f5dcfb0..dac4a8e 100644
--- a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
+++ b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
@@ -77,7 +77,7 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
       dDistort.add(new Static3D(0,0,     0));
       dDistort.add(new Static3D(0,0,height));
 
-      return water.distort(dDistort, new Static2D(pointx,pointy), new Static4D(0,0,radius,radius));
+      return water.distort(dDistort, new Static3D(pointx,pointy,0), new Static4D(0,0,radius,radius));
       }
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java
index 2aec555..4252d6f 100644
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java
+++ b/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java
@@ -53,7 +53,7 @@ public class Matrix3DActivity extends Activity implements AdapterView.OnItemSele
   private EffectNames[] mEffectNames;
 
   private static boolean mSupportsCenter;
-  private float mCenterX, mCenterY;
+  private float mCenterX, mCenterY, mCenterZ;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -111,10 +111,11 @@ public class Matrix3DActivity extends Activity implements AdapterView.OnItemSele
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void setCenter(float x, float y)
+  public void setCenter(float x, float y, float z)
     {
     mCenterX = x;
     mCenterY = y;
+    mCenterZ = z;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -183,6 +184,29 @@ public class Matrix3DActivity extends Activity implements AdapterView.OnItemSele
     return mObject==null ? 0: mObject.getHeight();
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getScreenWidth()
+    {
+    Matrix3DRenderer r = ((Matrix3DSurfaceView)findViewById(R.id.matrix3dSurfaceView)).getRenderer();
+    return r.getWidth();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getScreenHeight()
+    {
+    Matrix3DRenderer r = ((Matrix3DSurfaceView)findViewById(R.id.matrix3dSurfaceView)).getRenderer();
+    return r.getHeight();
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public int getDepth()
+    {
+    return mObject==null ? 0: mObject.getDepth();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DEffect.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DEffect.java
index 823970e..6953eff 100644
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DEffect.java
+++ b/src/main/java/org/distorted/examples/matrix3d/Matrix3DEffect.java
@@ -59,15 +59,17 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
   private Dynamic1D mDyn1;
   private Dynamic2D mDyn2;
   private Dynamic3D mDyn3;
+  private Dynamic4D mDyn4;
   private Dynamic5D mDyn5;
   private Static1D  mSta1;
   private Static2D  mSta2;
   private Static3D  mSta3;
+  private Static4D  mSta4;
   private Static5D  mSta5;
   private Dynamic4D mRegionDyn;
   private Static4D  mRegionSta;
-  private Dynamic2D mCenterDyn;
-  private Static2D  mCenterSta;
+  private Dynamic3D mCenterDyn;
+  private Static3D  mCenterSta;
 
   private View mButton, mEffect, mCenter, mRegion;
   private long mId;
@@ -79,11 +81,11 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
     {
     switch(mName)
       {
-      case ROTATE           : break;//object.rotate    (mDyn4, mCenterDyn); break;
-      case QUATERNION       : break;//object.quaternion(mDyn4, mCenterDyn); break;
-      case MOVE             : object.move      (mDyn3)            ; break;
-      case SCALE            : object.scale     (mDyn3)            ; break;
-      case SHEAR            : break;//object.shear     (mDyn3, mCenterDyn); break;
+      case ROTATE           : mId = object.rotate    (mDyn4, mCenterDyn); break;
+      case QUATERNION       : mId = object.quaternion(mDyn4, mCenterDyn); break;
+      case MOVE             : mId = object.move      (mDyn3)             ; break;
+      case SCALE            : mId = object.scale     (mDyn3)             ; break;
+      case SHEAR            : mId = object.shear     (mDyn3, mCenterDyn); break;
 
       case DISTORT: mId = object.distort(mDyn3, mCenterDyn, mRegionDyn); break;
       case DEFORM : mId = object.deform (mDyn3, mCenterDyn            ); break;
@@ -113,22 +115,30 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
     {
     switch(mName)
       {
-      case ROTATE           :
+      case ROTATE           : float an = (mInter[0]-50)*180/50;
+                              float rx = (mInter[1]-50)/ 50.0f;
+                              float ry = (mInter[2]-50)/ 50.0f;
+                              float rz = (mInter[3]-50)/ 50.0f;
+                              mSta4.set(an,rx,ry,rz);
                               break;
       case QUATERNION       :
                               break;
-      case MOVE             : float lm = mAct.get().getWidth()/50.0f;
-                              float xm = (mInter[0]-50)*lm;
-                              float ym = (mInter[1]-50)*lm;
-                              float zm = (mInter[2]-50)*lm;
+      case MOVE             : float sw = mAct.get().getScreenWidth()/50.0f;
+                              float sh = mAct.get().getScreenWidth()/50.0f;
+                              float xm = (mInter[0]-50)*sw;
+                              float ym = (mInter[1]-50)*sh;
+                              float zm = (mInter[2]-50)*(sw+sh)/2;
                               mSta3.set(xm,ym,zm);
                               break;
-      case SCALE            : float xs = (mInter[0])/50.0f;
-                              float ys = (mInter[1])/50.0f;
-                              float zs = (mInter[2])/50.0f;
+      case SCALE            : float xs = (mInter[0]>50 ? 0.18f : 0.018f)*(mInter[0]-50) + 1;
+                              float ys = (mInter[1]>50 ? 0.18f : 0.018f)*(mInter[1]-50) + 1;
+                              float zs = (mInter[2]>50 ? 0.18f : 0.018f)*(mInter[2]-50) + 1;
                               mSta3.set(xs,ys,zs);
                               break;
-      case SHEAR            :
+      case SHEAR            : float xsh = (mInter[0]-50)/25.0f;
+                              float ysh = (mInter[1]-50)/25.0f;
+                              float zsh = (mInter[2]-50)/25.0f;
+                              mSta3.set(xsh,ysh,zsh);
                               break;
       case DISTORT          :
       case DEFORM           : float ld = mAct.get().getWidth()/50.0f;
@@ -179,6 +189,8 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
       case 2: mInter[1] = 50;
       case 1: mInter[0] = 50;
       }
+
+    if( mName==EffectNames.ROTATE ) mInter[1]= 100;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -208,6 +220,15 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
       text += " ("+f1+","+f2+","+f3+")";
       }
 
+    if( mSta4 !=null )
+      {
+      float f1 = ((int)(mSta4.getX()*100))/100.0f;
+      float f2 = ((int)(mSta4.getY()*100))/100.0f;
+      float f3 = ((int)(mSta4.getZ()*100))/100.0f;
+      float f4 = ((int)(mSta4.getW()*100))/100.0f;
+      text += " ("+f1+","+f2+","+f3+","+f4+")";
+      }
+
     if( mSta5 !=null )
       {
       float f1 = ((int)(mSta5.getX()*100))/100.0f;
@@ -229,7 +250,9 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
 
     float x = (mInterCenter[0]*0.012f - 0.1f)*act.getWidth();
     float y = (mInterCenter[1]*0.012f - 0.1f)*act.getHeight();
-    mCenterSta.set(x,y);
+    float z = (mInterCenter[2]*0.012f - 0.1f)*act.getDepth();
+
+    mCenterSta.set(x,y,z);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -238,6 +261,7 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
     {
     mInterCenter[0] = 50;
     mInterCenter[1] = 50;
+    mInterCenter[2] = 50;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -246,8 +270,9 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
     {
     int f0 = (int)mCenterSta.getX();
     int f1 = (int)mCenterSta.getY();
+    int f2 = (int)mCenterSta.getZ();
 
-    mTextCenter.setText("center ("+f0+","+f1+")");
+    mTextCenter.setText("center ("+f0+","+f1+","+f2+")");
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -301,10 +326,12 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
     mDyn1 = null;
     mDyn2 = null;
     mDyn3 = null;
+    mDyn4 = null;
     mDyn5 = null;
     mSta1 = null;
     mSta2 = null;
     mSta3 = null;
+    mSta4 = null;
     mSta5 = null;
 
     mDimension = mName.getDimension();
@@ -323,12 +350,21 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
                mSta3 = new Static3D(0,0,0);
                mDyn3.add(mSta3);
                break;
-      case 4 : mDyn3 = new Dynamic3D();
-               mSta3 = new Static3D(0,0,0);
-               mDyn3.add(mSta3);
-               mDyn1 = new Dynamic1D();
-               mSta1 = new Static1D(0);
-               mDyn1.add(mSta1);
+      case 4 : if( mName == EffectNames.QUATERNION || mName == EffectNames.ROTATE )
+                 {
+                 mDyn4 = new Dynamic4D();
+                 mSta4 = new Static4D(0,0,0,0);
+                 mDyn4.add(mSta4);
+                 }
+               else
+                 {
+                 mDyn3 = new Dynamic3D();
+                 mSta3 = new Static3D(0,0,0);
+                 mDyn3.add(mSta3);
+                 mDyn1 = new Dynamic1D();
+                 mSta1 = new Static1D(0);
+                 mDyn1.add(mSta1);
+                 }
                break;
       case 5 : mDyn5 = new Dynamic5D();
                mSta5 = new Static5D(0,0,0,0,0);
@@ -346,10 +382,10 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
     mRegionSta   = new Static4D(0,0,0,0);
     mRegionDyn.add(mRegionSta);
 
-    mInterCenter = new int[2];
-    mSeekCenterID= new int[2];
-    mCenterDyn   = new Dynamic2D();
-    mCenterSta   = new Static2D(0,0);
+    mInterCenter = new int[3];
+    mSeekCenterID= new int[3];
+    mCenterDyn   = new Dynamic3D();
+    mCenterSta   = new Static3D(0,0,0);
     mCenterDyn.add(mCenterSta);
 
     mButton = null;
@@ -479,25 +515,27 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
 
     mCenter = act.getLayoutInflater().inflate(R.layout.effectcenter, null);
 
-    SeekBar[] seek = new SeekBar[2];
+    SeekBar[] seek = new SeekBar[3];
 
     seek[0] = (SeekBar)mCenter.findViewById(R.id.effectCenterBarX );
     seek[1] = (SeekBar)mCenter.findViewById(R.id.effectCenterBarY );
+    seek[2] = (SeekBar)mCenter.findViewById(R.id.effectCenterBarZ );
 
     mSeekCenterID[0] = seek[0].getId();
     mSeekCenterID[1] = seek[1].getId();
+    mSeekCenterID[2] = seek[2].getId();
 
     mTextCenter = (TextView)mCenter.findViewById(R.id.effectCenterText);
 
     setDefaultCenterInter();
 
-    for(int i=0; i<2; i++)
+    for(int i=0; i<3; i++)
       {
       seek[i].setOnSeekBarChangeListener(this);
       seek[i].setProgress( mInterCenter[i] );
       }
 
-    act.setCenter(mCenterSta.getX(),mCenterSta.getY());
+    act.setCenter(mCenterSta.getX(),mCenterSta.getY(),mCenterSta.getZ());
 
     return mCenter;
     }
@@ -574,6 +612,12 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
       fillCenterStatics();
       setCenterText();
       }
+    if( bar.getId() == mSeekCenterID[2] )
+      {
+      mInterCenter[2] = progress;
+      fillCenterStatics();
+      setCenterText();
+      }
 
     if( fromUser )
       {
@@ -582,7 +626,7 @@ class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
 
       Matrix3DActivity act = mAct.get();
 
-      act.setCenter(mCenterSta.getX(),mCenterSta.getY());
+      act.setCenter(mCenterSta.getX(),mCenterSta.getY(),mCenterSta.getZ());
       act.setRegion(mRegionSta.getX(),mRegionSta.getY(),mRegionSta.getZ());
       }
     }
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
index 23b1147..833a592 100644
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
+++ b/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
@@ -36,6 +36,8 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
     private GLSurfaceView mView;
     private DistortedObject mObject;
 
+    private int mWidth, mHeight;
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     Matrix3DRenderer(GLSurfaceView v)
@@ -56,12 +58,29 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
       mObject.draw(time);
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int getWidth()
+      {
+      return mWidth;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int getHeight()
+      {
+      return mHeight;
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     public void onSurfaceChanged(GL10 glUnused, int width, int height)
       {
       mObject.abortEffects(EffectTypes.MATRIX);
 
+      mWidth = width;
+      mHeight= height;
+
       Distorted.onSurfaceChanged(width, height);
       }
 
diff --git a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
index b4142dc..a94a610 100644
--- a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
+++ b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
@@ -45,7 +45,7 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedBitmap monaLisa;
-    private Static2D pLeft, pRight;
+    private Static3D pLeft, pRight;
     private Static4D rLeft, rRight;
     private Dynamic3D dLeft, dRight;
 
@@ -57,8 +57,8 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
       {
       mView = v;
 
-      pLeft = new Static2D( 90, 258);
-      pRight= new Static2D(176, 255);
+      pLeft = new Static3D( 90, 258, 0);
+      pRight= new Static3D(176, 255, 0);
 
       rLeft = new Static4D(-10,-10,25,25);
       rRight= new Static4D( 10, -5,25,25);
diff --git a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsSurfaceView.java b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsSurfaceView.java
index 4f020d2..ff02771 100644
--- a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsSurfaceView.java
+++ b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsSurfaceView.java
@@ -30,6 +30,7 @@ import android.util.AttributeSet;
 
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic2D;
+import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Dynamic4D;
 import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static2D;
@@ -52,7 +53,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
 
     private static final Object lock = new Object();
 
-    private Dynamic2D di2D;
+    private Dynamic3D di3D;
     private Static4D dr;
     private Dynamic4D mRegion;
 
@@ -75,7 +76,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
       mPaint.setStyle(Style.FILL);
       moving = -1;
       
-      di2D    = new Dynamic2D(LOOP_TIME,0.0f);
+      di3D    = new Dynamic3D(LOOP_TIME,0.0f);
       mRegion = new Dynamic4D(LOOP_TIME,0.0f);
 
       if(!isInEditMode())
@@ -125,7 +126,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
         {
         MovingEffectsRenderer.mBackground.abortEffects(EffectTypes.VERTEX);
         MovingEffectsRenderer.mBackground.abortEffects(EffectTypes.FRAGMENT);
-        MovingEffectsRenderer.mBackground.distort( new Static3D(0,0,mMax/10) , di2D, dr);
+        MovingEffectsRenderer.mBackground.distort( new Static3D(0,0,mMax/10) , di3D, dr);
         mCurrEffect = EFFECT_BUBBLE;
         }
       }
@@ -140,7 +141,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
         {
         MovingEffectsRenderer.mBackground.abortEffects(EffectTypes.VERTEX);
         MovingEffectsRenderer.mBackground.abortEffects(EffectTypes.FRAGMENT);
-        MovingEffectsRenderer.mBackground.sink(new Static1D(10), di2D, dr);
+        MovingEffectsRenderer.mBackground.sink(new Static1D(10), di3D, dr);
         mCurrEffect = EFFECT_SINK;
         }
       }
@@ -185,7 +186,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
         {
         MovingEffectsRenderer.mBackground.abortEffects(EffectTypes.VERTEX);
         MovingEffectsRenderer.mBackground.abortEffects(EffectTypes.FRAGMENT);
-        MovingEffectsRenderer.mBackground.swirl( new Static1D(30), di2D, dr);
+        MovingEffectsRenderer.mBackground.swirl( new Static1D(30), di3D, dr);
         mCurrEffect = EFFECT_SWIRL;
         }
       }
@@ -198,7 +199,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
         {
         MovingEffectsRenderer.mBackground.abortEffects(EffectTypes.VERTEX);
         MovingEffectsRenderer.mBackground.abortEffects(EffectTypes.FRAGMENT);
-        di2D.removeAll();
+        di3D.removeAll();
         mRegion.removeAll();
         mCurrEffect = EFFECT_POINTS;
         }
@@ -210,10 +211,10 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
       {
       synchronized(lock)
         {  
-        int len = di2D.getNumPoints();
+        int len = di3D.getNumPoints();
 
-        float[] drawCoord = new float[2];
-        Static2D cu;
+        float[] drawCoord = new float[3];
+        Static3D cu;
         int lit = mTime> 0 ? (int)((float)(time-mTime)*NUM_POINTS/LOOP_TIME)  : 0;
             
         if( len>=2 )
@@ -226,7 +227,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
                                : 0xff - (lit+NUM_POINTS-i)*0xff/(NUM_POINTS-1);
          
             mPaint.setColor( 0xffffff + ((color&0xff)<<24) );  
-            di2D.interpolateMain( drawCoord, 0, (long)(i*step) );
+            di3D.interpolateMain( drawCoord, 0, (long)(i*step) );
             c.drawCircle(drawCoord[0], drawCoord[1], mSize1, mPaint );
             }
           }
@@ -235,7 +236,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
       
         for(int curr=0; curr<len; curr++)
           {       
-          cu = di2D.getPoint(curr);
+          cu = di3D.getPoint(curr);
           c.drawCircle(cu.getX(), cu.getY(), mSize2, mPaint);
           }
         
@@ -258,11 +259,11 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
                                     
                                       float gx, gy;
                                       Static2D dv;
-                                      int len = di2D.getNumPoints();
+                                      int len = di3D.getNumPoints();
                                  
                                       for(int g=0; g<len; g++)
                                         {
-                                        dv = di2D.getPoint(g); 
+                                        dv = di3D.getPoint(g);
                                         gx = dv.getX();
                                         gy = dv.getY();
                                     
@@ -276,7 +277,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
                                         {
                                         synchronized(lock)
                                           {
-                                          di2D.add(new Static2D(xDown,yDown));
+                                          di3D.add(new Static3D(xDown,yDown,0));
                                           mRegion.add(new Static4D(xDown,yDown,mSizeR,mSizeR));
                                           }
                                         } 
@@ -286,7 +287,7 @@ public class MovingEffectsSurfaceView extends GLSurfaceView
                                         xDown = (int)event.getX();
                                         yDown = (int)event.getY();
 
-                                        di2D.setPoint(moving, xDown, yDown);
+                                        di3D.setPoint(moving, xDown, yDown, 0);
                                         mRegion.setPoint(moving, xDown, yDown, mSizeR, mSizeR);
                                         }                           
                                       break;
diff --git a/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java b/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
index 1ae25e0..eb2db6b 100644
--- a/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
+++ b/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
@@ -63,7 +63,7 @@ public class RenderThread extends Thread
   private DistortedBitmap monaLisa;
   private int bmpHeight, bmpWidth;
 
-  private Static2D pLeft, pRight;
+  private Static3D pLeft, pRight;
   private Static4D rLeft, rRight;
 
   private Dynamic3D dLeft, dRight;
@@ -77,8 +77,8 @@ public class RenderThread extends Thread
     mSurfaceHolder = holder;
     mView = view;
 
-    pLeft = new Static2D( 90, 258);
-    pRight= new Static2D(176, 255);
+    pLeft = new Static3D( 90, 258, 0);
+    pRight= new Static3D(176, 255, 0);
 
     rLeft = new Static4D(-10,-10,25,25);
     rRight= new Static4D( 10, -5,25,25);
diff --git a/src/main/java/org/distorted/examples/save/SaveRenderer.java b/src/main/java/org/distorted/examples/save/SaveRenderer.java
index ed9447e..7ac8ad4 100644
--- a/src/main/java/org/distorted/examples/save/SaveRenderer.java
+++ b/src/main/java/org/distorted/examples/save/SaveRenderer.java
@@ -51,7 +51,7 @@ class SaveRenderer implements GLSurfaceView.Renderer
   {
   private GLSurfaceView mView;
   private DistortedBitmap mGirl;
-  private Static2D pLeft, pRight;
+  private Static3D pLeft, pRight;
   private Static4D sinkRegion;
   private Dynamic1D diSink;
   private Static1D s0;
@@ -70,8 +70,8 @@ class SaveRenderer implements GLSurfaceView.Renderer
       
     boobsSink  = 1.0f;
       
-    pLeft = new Static2D(132, 264);
-    pRight= new Static2D(247, 264);
+    pLeft = new Static3D(132, 264, 0);
+    pRight= new Static3D(247, 264, 0);
       
     sinkRegion = new Static4D(0,0,60,60);
       
diff --git a/src/main/java/org/distorted/examples/sink/SinkRenderer.java b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
index 2a6c83a..d4bbc11 100644
--- a/src/main/java/org/distorted/examples/sink/SinkRenderer.java
+++ b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
@@ -47,7 +47,7 @@ class SinkRenderer implements GLSurfaceView.Renderer
   {
   private GLSurfaceView mView;
   private DistortedBitmap sinkBmp;
-  private Static2D pLeft, pRight;
+  private Static3D pLeft, pRight;
   private Static4D Region;
   private int bmpHeight, bmpWidth;
     
@@ -57,8 +57,8 @@ class SinkRenderer implements GLSurfaceView.Renderer
     { 
     mView = v;
       
-    pLeft = new Static2D(214, 206);
-    pRight= new Static2D(390, 212);
+    pLeft = new Static3D(214, 206, 0);
+    pRight= new Static3D(390, 212, 0);
     Region= new Static4D(0,0,60,60);
     }
 
diff --git a/src/main/res/layout/effectcenter.xml b/src/main/res/layout/effectcenter.xml
index 7524943..b490a61 100644
--- a/src/main/res/layout/effectcenter.xml
+++ b/src/main/res/layout/effectcenter.xml
@@ -26,7 +26,7 @@
             android:layout_marginEnd="5dp"
             android:layout_marginLeft="5dp"
             android:layout_marginRight="5dp"
-            android:layout_weight="0.5"/>
+            android:layout_weight="1.0"/>
 
         <SeekBar
             android:id="@+id/effectCenterBarY"
@@ -35,8 +35,16 @@
             android:layout_marginEnd="5dp"
             android:layout_marginLeft="5dp"
             android:layout_marginRight="5dp"
-            android:layout_weight="0.5"/>
+            android:layout_weight="1.0"/>
 
+        <SeekBar
+            android:id="@+id/effectCenterBarZ"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="5dp"
+            android:layout_marginLeft="5dp"
+            android:layout_marginRight="5dp"
+            android:layout_weight="1.0"/>
     </LinearLayout>
 
 </LinearLayout>
