commit 56cbe1cf58df2e85da2e76650f154b5b78d09fa9
Author: Leszek Koltunski <leszek@distorted.org>
Date:   Fri Jul 8 02:04:22 2016 +0100

    Re-write Vertex3D to provide similar functionality to Fragment3D (displaying the center and region bitmaps still missing)

diff --git a/src/main/java/org/distorted/examples/fragment3d/Fragment3DEffect.java b/src/main/java/org/distorted/examples/fragment3d/Fragment3DEffect.java
index 8807a62..1df4506 100644
--- a/src/main/java/org/distorted/examples/fragment3d/Fragment3DEffect.java
+++ b/src/main/java/org/distorted/examples/fragment3d/Fragment3DEffect.java
@@ -268,7 +268,7 @@ public class Fragment3DEffect implements SeekBar.OnSeekBarChangeListener
                mSeekID[2] = seek[2].getId();
                mSeekID[3] = seek[3].getId();
                break;
-      default: android.util.Log.e("Fragment3DEffect", "dimension "+mDimension+" not supported!");
+      default: android.util.Log.e("Vertex3DEffect", "dimension "+mDimension+" not supported!");
                return null;
       }
 
diff --git a/src/main/java/org/distorted/examples/vertex3d/Vertex3DActivity.java b/src/main/java/org/distorted/examples/vertex3d/Vertex3DActivity.java
index cf7aa59..e82a2b0 100644
--- a/src/main/java/org/distorted/examples/vertex3d/Vertex3DActivity.java
+++ b/src/main/java/org/distorted/examples/vertex3d/Vertex3DActivity.java
@@ -29,11 +29,8 @@ import android.widget.ArrayAdapter;
 import android.widget.Button;
 import android.widget.LinearLayout;
 import android.widget.NumberPicker;
-import android.widget.SeekBar;
-import android.widget.SeekBar.OnSeekBarChangeListener;
 import android.widget.Spinner;
 import android.widget.TableRow;
-import android.widget.TextView;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
@@ -41,12 +38,18 @@ import org.distorted.library.DistortedBitmap;
 import org.distorted.library.DistortedCubes;
 import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectNames;
+import org.distorted.library.EffectTypes;
+import org.distorted.library.type.Dynamic1D;
+import org.distorted.library.type.Dynamic2D;
+import org.distorted.library.type.Dynamic3D;
+import org.distorted.library.type.Dynamic4D;
+
+import java.util.ArrayList;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
 public class Vertex3DActivity extends Activity
-                              implements OnSeekBarChangeListener,
-                                         View.OnClickListener,
+                              implements View.OnClickListener,
                                          AdapterView.OnItemSelectedListener
   {
   private static final int COLOR_OFF = 0xffffe81f;
@@ -56,48 +59,34 @@ public class Vertex3DActivity extends Activity
 
   // fields needed for the first 'pick-a-shape' screen
   //
-  private int mNumCols = 3;
-  private int mNumRows = 3;
+  private int mNumCols = 10;
+  private int mNumRows = 10;
   private NumberPicker mColsPicker, mRowsPicker;
-  private LinearLayout mLay;
   private boolean[] mShape;
   private DistortedObject mObject;
   private int mObjectType;
   private int mBitmap;
 
-  // fields needed for the second 'apply vertex effects' screen
-  //
-  private SeekBar bar;
-  private TextView textDeform, textDistort, textSink, textSwirl, textCenter;
-  private int deformX, deformY, deformZ;
-  private int distortX, distortY, distortZ;
-  private int sinkA;
-  private int swirlA;
-  private int centerX, centerY;
-
-  private float fdeformX, fdeformY, fdeformZ;
-  private float fdistortX, fdistortY, fdistortZ;
-  private float fsinkA;
-  private float fswirlA;
-  private float fcenterX, fcenterY;
-  private EffectNames[] effects = new EffectNames[4];
-
+  private ArrayList<Vertex3DEffect> mEffects;
+  private int mEffectAdd;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-    
+
   @Override
   protected void onCreate(Bundle savedState)
     {
     super.onCreate(savedState);
 
+    mEffects = new ArrayList<>();
+
     setContentView(R.layout.objectpickerlayout);
 
     mColsPicker = (NumberPicker)findViewById(R.id.objectpicker_cols);
     mRowsPicker = (NumberPicker)findViewById(R.id.objectpicker_rows);
 
-    mColsPicker.setMaxValue(10);
+    mColsPicker.setMaxValue(15);
     mColsPicker.setMinValue( 0);
-    mRowsPicker.setMaxValue(10);
+    mRowsPicker.setMaxValue(15);
     mRowsPicker.setMinValue( 0);
 
     mColsPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener()
@@ -145,20 +134,20 @@ public class Vertex3DActivity extends Activity
 
   private void setGrid()
     {
-    mLay = (LinearLayout)findViewById(R.id.objectpicker_buttongrid);
+    LinearLayout lay = (LinearLayout)findViewById(R.id.objectpicker_buttongrid);
 
-    int width = mLay.getWidth();
-    int height= mLay.getHeight();
+    int width = lay.getWidth();
+    int height= lay.getHeight();
     int w = mNumCols>0 ? (width / mNumCols) -10 : 0;
     int h = mNumRows>0 ? (height/ mNumRows) -10 : 0;
     int size= w<h ? w:h;
     int pad = size/20;
 
-    mLay.removeAllViews();
+    lay.removeAllViews();
 
     mShape = new boolean[mNumRows*mNumCols];
 
-    TableRow.LayoutParams p = new android.widget.TableRow.LayoutParams();
+    TableRow.LayoutParams p = new TableRow.LayoutParams();
 
     p.rightMargin  = pad;
     p.leftMargin   = pad;
@@ -183,7 +172,7 @@ public class Vertex3DActivity extends Activity
         mShape[rows*mNumCols+cols] = true;
         }
 
-      mLay.addView(tr);
+      lay.addView(tr);
       }
     }
 
@@ -196,31 +185,31 @@ public class Vertex3DActivity extends Activity
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void onClick(View view)
+  public int getBitmap()
     {
-    Button tmp = (Button)view;
-    int id = tmp.getId();
-    mShape[id] = !mShape[id];
-    tmp.setBackgroundColor(mShape[id] ? COLOR_ON:COLOR_OFF);
+    return mBitmap;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public int getBitmap()
+  public void onClick(View view)
     {
-    return mBitmap;
+    Button tmp = (Button)view;
+    int id = tmp.getId();
+    mShape[id] = !mShape[id];
+    tmp.setBackgroundColor(mShape[id] ? COLOR_ON:COLOR_OFF);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void Continue(View v)
     {
+    firstScreen = false;
+
     if( mObjectType==1 )
       {
-      firstScreen = false;
       mObject = new DistortedBitmap(100,100,mNumCols);
-      setContentView(R.layout.vertex3dlayout);
-      Default(null);
+      setVertexView();
       }
     else
       {
@@ -250,8 +239,7 @@ public class Vertex3DActivity extends Activity
 
     mObject = new DistortedCubes(mNumCols, str, 10);
 
-    setContentView(R.layout.vertex3dlayout);
-    Default(null);
+    setVertexView();
     }
 
 
@@ -261,7 +249,8 @@ public class Vertex3DActivity extends Activity
     {
     switch(parent.getId())
       {
-      case R.id.objectpicker_spinnerType  : mObjectType = pos; break;
+      case R.id.objectpicker_spinnerType  : mObjectType = pos;
+                                            break;
       case R.id.objectpicker_spinnerBitmap: switch(pos)
                                               {
                                               case 0: mBitmap = R.raw.face; break;
@@ -270,6 +259,8 @@ public class Vertex3DActivity extends Activity
                                               case 3: mBitmap = R.raw.grid; break;
                                               }
                                             break;
+      case R.id.vertex3dspinner           : mEffectAdd = pos;
+                                            break;
       }
     }
 
@@ -280,282 +271,91 @@ public class Vertex3DActivity extends Activity
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// 'second screen' methods
 
-  public void Default(View view)
+  public int getWidth()
     {
-    effects[0] = EffectNames.DEFORM;
-    effects[1] = EffectNames.DISTORT;
-    effects[2] = EffectNames.SINK;
-    effects[3] = EffectNames.SWIRL;
-    
-    deformX = 50;
-    deformY = 50;
-    deformZ = 50;
-
-    distortX = 50;
-    distortY = 50;
-    distortZ = 50;
-
-    sinkA =  50;
-    swirlA = 50;
-
-    centerX = 50;
-    centerY = 50;
-
-    textCenter = (TextView)findViewById(R.id.vertex3dcenterText);
-    computeCenter();
-    setCenterText();
-
-    setBar(R.id.vertex3dcenterX, centerX);
-    setBar(R.id.vertex3dcenterY, centerY);
-
-    addViews();
-    }
-    
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-  private void addViews()
-    {
-    LinearLayout layout = (LinearLayout)findViewById(R.id.vertex3dlayout);
-    
-    layout.removeAllViews();
-      
-    View deform = getLayoutInflater().inflate(R.layout.vertex3ddeform , null);
-    View distort= getLayoutInflater().inflate(R.layout.vertex3ddistort, null);
-    View sink   = getLayoutInflater().inflate(R.layout.vertex3dsink   , null);
-    View swirl  = getLayoutInflater().inflate(R.layout.vertex3dswirl  , null);
-     
-    for( int i=effects.length-1 ; i>=0 ; i-- )
-      {
-      switch(effects[i])
-        {
-        case DEFORM : layout.addView(deform , 0); break;
-        case DISTORT: layout.addView(distort, 0); break;
-        case SINK   : layout.addView(sink   , 0); break;
-        case SWIRL  : layout.addView(swirl  , 0); break;
-        }
-      }
-      
-    textDeform = (TextView)findViewById(R.id.vertex3ddeformText);
-    textDistort= (TextView)findViewById(R.id.vertex3ddistortText);
-    textSink   = (TextView)findViewById(R.id.vertex3dsinkText);
-    textSwirl  = (TextView)findViewById(R.id.vertex3dswirlText);
-     
-    setDeformText();
-    setDistortText();
-    setSinkText();
-    setSwirlText();
-      
-    setBar(R.id.vertex3ddeformBar1, deformX);
-    setBar(R.id.vertex3ddeformBar2, deformY);
-    setBar(R.id.vertex3ddeformBar3, deformZ);
-
-    setBar(R.id.vertex3ddistortBar1, distortX);
-    setBar(R.id.vertex3ddistortBar2, distortY);
-    setBar(R.id.vertex3ddistortBar3, distortZ);
-      
-    setBar(R.id.vertex3dsinkBar1, sinkA);
-
-    setBar(R.id.vertex3dswirlBar1, swirlA);
-
-    Vertex3DSurfaceView view = (Vertex3DSurfaceView)findViewById(R.id.vertex3dSurfaceView);
-    view.getRenderer().setOrder(effects);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void moveUp(EffectNames name)
-    {
-    int len = effects.length-1;
-    int index = -1;
-
-    for(int i=0; i<=len; i++)
-      {
-      if( effects[i]==name )
-        {
-        index=i;
-        break;
-        }
-      }
-
-    if( index==0 )
-      {
-      for(int i=0; i<len; i++)
-        effects[i] = effects[i+1];
-
-      effects[len] = name;
-      }
-    else if( index>0 )
-      {
-      effects[index]   = effects[index-1];
-      effects[index-1] = name;
-      }
-
-    addViews();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void ButtonDeform(View v)
-    {
-    moveUp(EffectNames.DEFORM);
+    return mObject==null ? 0: mObject.getWidth();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void ButtonDistort(View v)
+  public int getHeight()
     {
-    moveUp(EffectNames.DISTORT);
+    return mObject==null ? 0: mObject.getHeight();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
+// 'second screen' methods
 
-  public void ButtonSink(View v)
-    {
-    moveUp(EffectNames.SINK);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void ButtonSwirl(View v)
-    {
-    moveUp(EffectNames.SWIRL);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setBar(int id, int value)
-    {
-    bar = (SeekBar)findViewById(id);
-    bar.setOnSeekBarChangeListener(this);
-    bar.setProgress(value);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void computeDeform()
-    {
-    Vertex3DSurfaceView view = (Vertex3DSurfaceView)findViewById(R.id.vertex3dSurfaceView);
-    Vertex3DRenderer renderer = view.getRenderer();
-
-    fdeformX = (deformX-50)*renderer.mScreenMin/200.0f;
-    fdeformY = (deformY-50)*renderer.mScreenMin/200.0f;
-    fdeformZ = (deformZ-50)*renderer.mScreenMin/200.0f;
-
-    renderer.setDeform( fdeformX, fdeformY, fdeformZ );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setDeformText()
-    {
-    fdeformX = ((int)(100*fdeformX))/100.0f;
-    fdeformY = ((int)(100*fdeformY))/100.0f;
-    fdeformZ = ((int)(100*fdeformZ))/100.0f;
-
-    textDeform.setText("deform("+fdeformX+" , "+fdeformY+" , "+fdeformZ+")");
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void computeDistort()
-    {
-    Vertex3DSurfaceView view = (Vertex3DSurfaceView)findViewById(R.id.vertex3dSurfaceView);
-    Vertex3DRenderer renderer = view.getRenderer();
-
-    fdistortX = (distortX-50)*renderer.mScreenMin/200.0f;
-    fdistortY = (distortY-50)*renderer.mScreenMin/200.0f;
-    fdistortZ = (distortZ-50)*renderer.mScreenMin/200.0f;
-
-    renderer.setDistort(fdistortX, fdistortY, fdistortZ);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setDistortText()
-    {
-    fdistortX = ((int)(100*fdistortX))/100.0f;
-    fdistortY = ((int)(100*fdistortY))/100.0f;
-    fdistortZ = ((int)(100*fdistortZ))/100.0f;
-
-    textDistort.setText("distort("+fdistortX+" , "+fdistortY+" , "+fdistortZ+")");
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void computeSink()
-    {
-    Vertex3DSurfaceView view = (Vertex3DSurfaceView)findViewById(R.id.vertex3dSurfaceView);
-
-    fsinkA = (sinkA>= 50 ? 0.18f*sinkA-8.0f : 0.018f*sinkA + 0.1f);
-
-    view.getRenderer().setSink( fsinkA );
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setSinkText()
-    {
-    fsinkA = ((int)(100*fsinkA))/100.0f;
-
-    textSink.setText("sink("+fsinkA+")");
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void computeSwirl()
-    {
-    Vertex3DSurfaceView view = (Vertex3DSurfaceView)findViewById(R.id.vertex3dSurfaceView);
-
-    fswirlA = (swirlA-50)*3.6f;
-
-    view.getRenderer().setSwirl( fswirlA );
-    }
-    
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setSwirlText()
+  private void setVertexView()
     {
-    fswirlA = ((int)(100*fswirlA))/100.0f;
+    final View view = getLayoutInflater().inflate(R.layout.vertex3dlayout, null);
 
-    textSwirl.setText("swirl("+fswirlA+")");
-    }
+    setContentView(view);
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    String[] effects = new String[] { "DISTORT",
+                                      "DEFORM",
+                                      "SINK",
+                                      "SWIRL" };
 
-  private void computeCenter()
-    {
-    Vertex3DSurfaceView view = (Vertex3DSurfaceView)findViewById(R.id.vertex3dSurfaceView);
+    Spinner effectSpinner = (Spinner)findViewById(R.id.vertex3dspinner );
+    effectSpinner.setOnItemSelectedListener(this);
 
-    fcenterX = centerX;
-    fcenterY = centerY;
+    ArrayAdapter<String> adapterEffect = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, effects);
+    adapterEffect.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+    effectSpinner.setAdapter(adapterEffect);
 
-    view.getRenderer().setCenter( fcenterX, fcenterY );
+    mEffectAdd = 0;
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  private void setCenterText()
+  public void newEffect(View v)
     {
-    fcenterX = ((int)(100*fcenterX))/100.0f;
-    fcenterY = ((int)(100*fcenterY))/100.0f;
+    EffectNames name;
 
-    textCenter.setText("center("+fcenterX+","+fcenterY+")");
-    }
+    switch(mEffectAdd)
+      {
+      case 0 : name = EffectNames.DISTORT; break;
+      case 1 : name = EffectNames.DEFORM ; break;
+      case 2 : name = EffectNames.SINK   ; break;
+      case 3 : name = EffectNames.SWIRL  ; break;
+      default: return;
+      }
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
+    Vertex3DEffect eff = new Vertex3DEffect(name, this);
+    mEffects.add(eff);
 
-  public float getCenterX()
-    {
-    return fcenterX;
+    LinearLayout layout = (LinearLayout)findViewById(R.id.vertex3dlayout);
+    View view = eff.createView();
+    layout.addView(view);
+    View center = eff.createCenter();
+    layout.addView(center);
+    View region = eff.createRegion();
+    layout.addView(region);
+
+    Dynamic1D dyn1 = eff.getDyn1();
+    Dynamic2D cent = eff.getCenter();
+    Dynamic3D dyn3 = eff.getDyn3();
+    Dynamic4D regi = eff.getRegion();
+
+    switch(mEffectAdd)
+      {
+      case 0: mObject.distort(dyn3, cent, regi); break;
+      case 1: mObject.deform (dyn3, cent      ); break;
+      case 2: mObject.sink   (dyn1, cent, regi); break;
+      case 3: mObject.swirl  (dyn1, cent, regi); break;
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public float getCenterY()
+  public void removeAll(View v)
     {
-    return fcenterY;
+    mEffects.clear();
+    LinearLayout layout = (LinearLayout)findViewById(R.id.vertex3dlayout);
+    layout.removeAllViews();
+    mObject.abortEffects(EffectTypes.VERTEX);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -601,31 +401,5 @@ public class Vertex3DActivity extends Activity
     Distorted.onDestroy();
     super.onDestroy();
     }
-    
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-  public void onProgressChanged(SeekBar bar, int progress, boolean fromUser)
-    {
-    switch (bar.getId())
-      {
-      case R.id.vertex3dcenterX     : centerX = progress; computeCenter() ; setCenterText()  ; break;
-      case R.id.vertex3dcenterY     : centerY = progress; computeCenter() ; setCenterText()  ; break;
-      case R.id.vertex3ddeformBar1  : deformX = progress; computeDeform() ; setDeformText()  ; break;
-      case R.id.vertex3ddeformBar2  : deformY = progress; computeDeform() ; setDeformText()  ; break;
-      case R.id.vertex3ddeformBar3  : deformZ = progress; computeDeform() ; setDeformText()  ; break;
-      case R.id.vertex3ddistortBar1 : distortX= progress; computeDistort(); setDistortText() ; break;
-      case R.id.vertex3ddistortBar2 : distortY= progress; computeDistort(); setDistortText() ; break;
-      case R.id.vertex3ddistortBar3 : distortZ= progress; computeDistort(); setDistortText() ; break;
-      case R.id.vertex3dsinkBar1    : sinkA   = progress; computeSink()   ; setSinkText()    ; break;
-      case R.id.vertex3dswirlBar1   : swirlA  = progress; computeSwirl()  ; setSwirlText()   ; break;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void onStartTrackingTouch(SeekBar bar) { }
-    
-///////////////////////////////////////////////////////////////////////////////////////////////////
 
-  public void onStopTrackingTouch(SeekBar bar)  { }
   }
diff --git a/src/main/java/org/distorted/examples/vertex3d/Vertex3DEffect.java b/src/main/java/org/distorted/examples/vertex3d/Vertex3DEffect.java
new file mode 100644
index 0000000..581f00e
--- /dev/null
+++ b/src/main/java/org/distorted/examples/vertex3d/Vertex3DEffect.java
@@ -0,0 +1,461 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.examples.vertex3d;
+
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+import org.distorted.examples.R;
+import org.distorted.library.EffectNames;
+import org.distorted.library.type.Dynamic1D;
+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;
+import org.distorted.library.type.Static3D;
+import org.distorted.library.type.Static4D;
+
+import java.lang.ref.WeakReference;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class Vertex3DEffect implements SeekBar.OnSeekBarChangeListener
+  {
+  private WeakReference<Vertex3DActivity> mAct;
+
+  private EffectNames mName;
+  private int[] mInter;
+  private int[] mInterRegion;
+  private int[] mInterCenter;
+  private int[] mSeekID;
+  private int[] mSeekRegionID;
+  private int[] mSeekCenterID;
+  private int mDimension;
+  private TextView mText,mTextRegion,mTextCenter;
+
+  private Dynamic1D mDyn1;
+  private Dynamic3D mDyn3;
+  private Static1D  mSta1;
+  private Static3D  mSta3;
+  private Dynamic4D mRegionDyn;
+  private Static4D  mRegionSta;
+  private Dynamic2D mCenterDyn;
+  private Static2D  mCenterSta;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void fillCenterStatics()
+    {
+    Vertex3DActivity act = mAct.get();
+
+    float x = (mInterCenter[0]*0.014f - 0.2f)*act.getWidth();
+    float y = (mInterCenter[1]*0.014f - 0.2f)*act.getHeight();
+    mCenterSta.set(x,y);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void setDefaultCenterInter()
+    {
+    mInterCenter[0] = 50;
+    mInterCenter[1] = 50;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void setCenterText()
+    {
+    int f0 = (int)mCenterSta.getX();
+    int f1 = (int)mCenterSta.getY();
+
+    mTextCenter.setText("center ("+f0+","+f1+")");
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void fillRegionStatics()
+    {
+    Vertex3DActivity act = mAct.get();
+
+    float factorX = act.getWidth() / 100.0f;
+    float factorY = act.getHeight()/ 100.0f;
+
+    float  x = (mInterRegion[0]-50)*factorX;
+    float  y = (mInterRegion[1]-50)*factorY;
+    float rx =  mInterRegion[2]    *factorX;
+    float ry =  mInterRegion[3]    *factorY;
+
+    mRegionSta.set(x,y,rx,ry);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void setDefaultRegionInter()
+    {
+    mInterRegion[0] = 50;
+    mInterRegion[1] = 50;
+    mInterRegion[2] = 50;
+    mInterRegion[3] = 50;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void setRegionText()
+    {
+    int f0 = (int)mRegionSta.getX();
+    int f1 = (int)mRegionSta.getY();
+    int f2 = (int)mRegionSta.getZ();
+    int f3 = (int)mRegionSta.getW();
+
+    mTextRegion.setText("region ("+f0+","+f1+","+f2+","+f3+")");
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void fillStatics()
+    {
+    switch(mName)
+      {
+      case DISTORT:
+      case DEFORM : Vertex3DActivity act = mAct.get();
+                    float l = act.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);
+                    break;
+      case SINK   : mSta1.set(mInter[0] > 50 ? 50.0f/(100.01f-mInter[0]) : mInter[0] / 50.0f);
+                    break;
+      case SWIRL  : mSta1.set( 3.6f*(mInter[0]-50) );
+                    break;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void setDefaultInter()
+    {
+    switch(mName)
+      {
+      case DISTORT:
+      case DEFORM : mInter[0] = 50;
+                    mInter[1] = 50;
+                    mInter[2] = 50;
+                    break;
+      case SINK   :
+      case SWIRL  : mInter[0] = 50;
+                    break;
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  private void setText()
+    {
+    String text = mName.name();
+
+    if( mName==EffectNames.DISTORT || mName==EffectNames.DEFORM)
+      {
+      int f1 = (int)mSta3.getX();
+      int f2 = (int)mSta3.getY();
+      int f3 = (int)mSta3.getZ();
+      text += " ("+f1+","+f2+","+f3+")";
+      }
+    else
+      {
+      float f1 = ((int)(mSta1.getX()*100))/100.0f;
+      text += " ("+f1+")";
+      }
+
+    mText.setText(text);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Vertex3DEffect(EffectNames name, Vertex3DActivity act)
+    {
+    mAct = new WeakReference<>(act);
+    mName = name;
+
+    if( mName==EffectNames.SINK || mName==EffectNames.SWIRL )
+      {
+      mDimension = 1;
+      mDyn1 = new Dynamic1D();
+      mSta1 = new Static1D(0);
+      mDyn1.add(mSta1);
+      mDyn3 = null;
+      }
+    else
+      {
+      mDimension = 3;
+      mDyn3 = new Dynamic3D();
+      mSta3 = new Static3D(0,0,0);
+      mDyn3.add(mSta3);
+      mDyn1 = null;
+      }
+
+    mInter = new int[mDimension];
+    mSeekID= new int[mDimension];
+
+    mInterRegion = new int[4];
+    mSeekRegionID= new int[4];
+    mRegionDyn   = new Dynamic4D();
+    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);
+    mCenterDyn.add(mCenterSta);
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Dynamic1D getDyn1()
+    {
+    return mDyn1;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Dynamic3D getDyn3()
+    {
+    return mDyn3;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Dynamic4D getRegion()
+    {
+    return mRegionDyn;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public Dynamic2D getCenter()
+    {
+    return mCenterDyn;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public View createView()
+    {
+    View effect;
+    SeekBar[] seek = new SeekBar[mDimension];
+
+    Vertex3DActivity act = mAct.get();
+
+    switch(mDimension)
+      {
+      case 1 : effect     = act.getLayoutInflater().inflate(R.layout.effect1d, null);
+               mText      = (TextView)effect.findViewById(R.id.effect1dText);
+               seek[0]    = (SeekBar)effect.findViewById(R.id.effect1dbar1);
+               mSeekID[0] = seek[0].getId();
+               break;
+      case 2 : effect     = act.getLayoutInflater().inflate(R.layout.effect2d, null);
+               mText      = (TextView)effect.findViewById(R.id.effect2dText);
+               seek[0]    = (SeekBar)effect.findViewById(R.id.effect2dbar1);
+               seek[1]    = (SeekBar)effect.findViewById(R.id.effect2dbar2);
+               mSeekID[0] = seek[0].getId();
+               mSeekID[1] = seek[1].getId();
+               break;
+      case 3 : effect     = act.getLayoutInflater().inflate(R.layout.effect3d, null);
+               mText      = (TextView)effect.findViewById(R.id.effect3dText);
+               seek[0]    = (SeekBar)effect.findViewById(R.id.effect3dbar1);
+               seek[1]    = (SeekBar)effect.findViewById(R.id.effect3dbar2);
+               seek[2]    = (SeekBar)effect.findViewById(R.id.effect3dbar3);
+               mSeekID[0] = seek[0].getId();
+               mSeekID[1] = seek[1].getId();
+               mSeekID[2] = seek[2].getId();
+               break;
+      case 4 : effect     = act.getLayoutInflater().inflate(R.layout.effect4d, null);
+               mText      = (TextView)effect.findViewById(R.id.effect4dText);
+               seek[0]    = (SeekBar)effect.findViewById(R.id.effect4dbar1);
+               seek[1]    = (SeekBar)effect.findViewById(R.id.effect4dbar2);
+               seek[2]    = (SeekBar)effect.findViewById(R.id.effect4dbar3);
+               seek[3]    = (SeekBar)effect.findViewById(R.id.effect4dbar4);
+               mSeekID[0] = seek[0].getId();
+               mSeekID[1] = seek[1].getId();
+               mSeekID[2] = seek[2].getId();
+               mSeekID[3] = seek[3].getId();
+               break;
+      default: android.util.Log.e("Vertex3DEffect", "dimension "+mDimension+" not supported!");
+               return null;
+      }
+
+    setDefaultInter();
+    fillStatics();
+    setText();
+
+    for(int i=0; i<mDimension; i++)
+      {
+      seek[i].setOnSeekBarChangeListener(this);
+      seek[i].setProgress( mInter[i] );
+      }
+
+    return effect;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public View createRegion()
+    {
+    Vertex3DActivity act = mAct.get();
+
+    View region = act.getLayoutInflater().inflate(R.layout.effectregion, null);
+
+    SeekBar[] seek = new SeekBar[4];
+
+    seek[0] = (SeekBar)region.findViewById(R.id.effectRegionBarX );
+    seek[1] = (SeekBar)region.findViewById(R.id.effectRegionBarY );
+    seek[2] = (SeekBar)region.findViewById(R.id.effectRegionBarRX);
+    seek[3] = (SeekBar)region.findViewById(R.id.effectRegionBarRY);
+
+    mSeekRegionID[0] = seek[0].getId();
+    mSeekRegionID[1] = seek[1].getId();
+    mSeekRegionID[2] = seek[2].getId();
+    mSeekRegionID[3] = seek[3].getId();
+
+    mTextRegion    = (TextView)region.findViewById(R.id.effectRegionText);
+
+    setDefaultRegionInter();
+    fillRegionStatics();
+    setRegionText();
+
+    for(int i=0; i<4; i++)
+      {
+      seek[i].setOnSeekBarChangeListener(this);
+      seek[i].setProgress( mInterRegion[i] );
+      }
+
+    return region;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public View createCenter()
+    {
+    Vertex3DActivity act = mAct.get();
+
+    View center = act.getLayoutInflater().inflate(R.layout.effectcenter, null);
+
+    SeekBar[] seek = new SeekBar[2];
+
+    seek[0] = (SeekBar)center.findViewById(R.id.effectCenterBarX );
+    seek[1] = (SeekBar)center.findViewById(R.id.effectCenterBarY );
+
+    mSeekCenterID[0] = seek[0].getId();
+    mSeekCenterID[1] = seek[1].getId();
+
+    mTextCenter    = (TextView)center.findViewById(R.id.effectCenterText);
+
+    setDefaultCenterInter();
+    fillCenterStatics();
+    setCenterText();
+
+    for(int i=0; i<2; i++)
+      {
+      seek[i].setOnSeekBarChangeListener(this);
+      seek[i].setProgress( mInterCenter[i] );
+      }
+
+    return center;
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void onProgressChanged(SeekBar bar, int progress, boolean fromUser)
+    {
+    if ( mDimension>=1 && bar.getId()==mSeekID[0] )
+      {
+      mInter[0] = progress;
+      fillStatics();
+      setText();
+      }
+    if ( mDimension>=2 && bar.getId()==mSeekID[1] )
+      {
+      mInter[1] = progress;
+      fillStatics();
+      setText();
+      }
+    if ( mDimension>=3 && bar.getId()==mSeekID[2] )
+      {
+      mInter[2] = progress;
+      fillStatics();
+      setText();
+      }
+    if ( mDimension>=4 && bar.getId()==mSeekID[3] )
+      {
+      mInter[3] = progress;
+      fillStatics();
+      setText();
+      }
+
+    if( bar.getId() == mSeekRegionID[0] )
+      {
+      mInterRegion[0] = progress;
+      fillRegionStatics();
+      setRegionText();
+      }
+    if( bar.getId() == mSeekRegionID[1] )
+      {
+      mInterRegion[1] = progress;
+      fillRegionStatics();
+      setRegionText();
+      }
+    if( bar.getId() == mSeekRegionID[2] )
+      {
+      mInterRegion[2] = progress;
+      fillRegionStatics();
+      setRegionText();
+      }
+    if( bar.getId() == mSeekRegionID[3] )
+      {
+      mInterRegion[3] = progress;
+      fillRegionStatics();
+      setRegionText();
+      }
+
+    if( bar.getId() == mSeekCenterID[0] )
+      {
+      mInterCenter[0] = progress;
+      fillCenterStatics();
+      setCenterText();
+      }
+    if( bar.getId() == mSeekCenterID[1] )
+      {
+      mInterCenter[1] = progress;
+      fillCenterStatics();
+      setCenterText();
+      }
+    }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void onStartTrackingTouch(SeekBar bar) { }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public void onStopTrackingTouch(SeekBar bar)  { }
+  }
diff --git a/src/main/java/org/distorted/examples/vertex3d/Vertex3DRenderer.java b/src/main/java/org/distorted/examples/vertex3d/Vertex3DRenderer.java
index def9bf0..562ac10 100644
--- a/src/main/java/org/distorted/examples/vertex3d/Vertex3DRenderer.java
+++ b/src/main/java/org/distorted/examples/vertex3d/Vertex3DRenderer.java
@@ -27,16 +27,9 @@ import android.opengl.GLSurfaceView;
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
 import org.distorted.library.DistortedBitmap;
-import org.distorted.library.DistortedCubes;
 import org.distorted.library.DistortedObject;
-import org.distorted.library.EffectNames;
 import org.distorted.library.EffectTypes;
-import org.distorted.library.type.Dynamic1D;
-import org.distorted.library.type.Dynamic2D;
-import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.DynamicQuat;
-import org.distorted.library.type.Static1D;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
@@ -50,128 +43,26 @@ import javax.microedition.khronos.opengles.GL10;
 
 class Vertex3DRenderer implements GLSurfaceView.Renderer
 {
-    private static final int SIZE = 100;
-
     private GLSurfaceView mView;
     private DistortedObject mObject;
-    private DistortedBitmap mCenter;
-    private float mFactorCen, mFactorObj;
-
+    private DistortedBitmap mBackground;
     private int mObjWidth, mObjHeight;
-
     private DynamicQuat mQuatInt1, mQuatInt2;
-
-    private EffectNames[] order;
-
-    private Dynamic2D mCenterInter;
-    private Dynamic3D mDeformInter, mDistortInter, mMoveInter;
-    private Dynamic1D mSinkInter, mSwirlInter;
-
-    private Static2D mCenterPoint;
-    private Static3D mDeformPoint, mDistortPoint, mMovePoint;
-    private Static1D mSinkPoint, mSwirlPoint;
-
     Static4D mQuat1, mQuat2;
     int mScreenMin;
 
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void setDeform(float x, float y, float z)
-      {
-      mDeformPoint.set(x, y, z);
-      }
-    
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void setDistort(float x, float y, float z)
-      {
-      mDistortPoint.set(x, y, z);
-      }
-     
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void setSink(float s)
-      {
-      mSinkPoint.set(s);
-      }
-    
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void setSwirl(float s)
-      {
-      mSwirlPoint.set(s);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void setCenter(float x, float y)
-      {
-      x = (0.012f*x-0.1f)*mObjWidth;
-      y = (0.012f*y-0.1f)*mObjHeight;
-
-      mCenterPoint.set(x,y);
-      mMovePoint.set(mFactorObj*x,mFactorObj*y,0);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void setOrder(EffectNames[] effects)
-      {
-      order = effects;
-      setVertexEffects();
-      }
-      
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void setVertexEffects()
-      {
-      mObject.abortEffects(EffectTypes.VERTEX);
-
-      for( int i=0; i<=order.length-1 ; i++ )
-        {
-        switch(order[i])
-          {
-          case DEFORM : mObject.deform( mDeformInter , mCenterInter) ; break;
-          case DISTORT: mObject.distort(mDistortInter, mCenterInter) ; break;
-          case SINK   : mObject.sink(   mSinkInter   , mCenterInter) ; break;
-          case SWIRL  : mObject.swirl(  mSwirlInter  , mCenterInter) ; break;
-          }
-        }
-      }
-    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     public Vertex3DRenderer(GLSurfaceView v)
       {
       mView = v;
 
-      mObject = ((Vertex3DActivity)v.getContext()).getObject();
-      mCenter = new DistortedBitmap(SIZE, SIZE, 1);
+      mObject     = ((Vertex3DActivity)v.getContext()).getObject();
+      mBackground = new DistortedBitmap(100, 100, 1);
 
       mObjWidth = mObject.getWidth();
       mObjHeight= mObject.getHeight();
 
-      mCenterPoint = new Static2D(0,0);
-      mMovePoint   = new Static3D(0,0,0);
-      mDeformPoint = new Static3D(0,0,0);
-      mDistortPoint= new Static3D(1,1,1);
-      mSwirlPoint  = new Static1D(0);
-      mSinkPoint   = new Static1D(1);
-
-      mCenterInter  = new Dynamic2D();
-      mDeformInter  = new Dynamic3D();
-      mDistortInter = new Dynamic3D();
-      mMoveInter    = new Dynamic3D();
-      mSwirlInter   = new Dynamic1D();
-      mSinkInter    = new Dynamic1D();
-
-      mCenterInter.add(mCenterPoint);
-      mMoveInter.add(mMovePoint);
-      mDeformInter.add(mDeformPoint);
-      mDistortInter.add(mDistortPoint);
-      mSwirlInter.add(mSwirlPoint);
-      mSinkInter.add(mSinkPoint);
-
       mQuat1 = new Static4D(0,0,0,1);  // unity
       mQuat2 = new Static4D(0,0,0,1);  // quaternions
 
@@ -183,78 +74,62 @@ class Vertex3DRenderer implements GLSurfaceView.Renderer
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-   
-    public void onDrawFrame(GL10 glUnused) 
+
+    public void onDrawFrame(GL10 glUnused)
       {
       GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
 
       long time = System.currentTimeMillis();
 
+      mBackground.draw(time);
       mObject.draw(time);
-      mCenter.draw(time);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+
+    public void onSurfaceChanged(GL10 glUnused, int width, int height)
       {
       mScreenMin = width<height ? width:height;
 
       mObject.abortEffects(EffectTypes.MATRIX);
-      mCenter.abortEffects(EffectTypes.MATRIX);
-
-      int centerSize = mCenter.getWidth();
+      mBackground.abortEffects(EffectTypes.MATRIX);
+      float factorObj;
 
       if( width*mObjHeight > height*mObjWidth ) // screen is more 'horizontal' than the Object
         {
-        mFactorObj = (0.70f*height)/mObjHeight;
-        mFactorCen = (0.15f*height)/centerSize;
+        factorObj = (0.80f*height)/mObjHeight;
         }
       else
         {
-        mFactorObj = (0.70f*width)/mObjWidth;
-        mFactorCen = (0.15f*width)/centerSize;
+        factorObj = (0.80f*width)/mObjWidth;
         }
 
-      Vertex3DActivity act = (Vertex3DActivity)mView.getContext();
-      float cX = act.getCenterX();
-      float cY = act.getCenterY();
-
-      cX = (0.012f*cX-0.1f)*mObjWidth;
-      cY = (0.012f*cY-0.1f)*mObjHeight;
-
-      mMovePoint.set(cX*mFactorObj,cY*mFactorObj,0);
-
       Static3D rotateObj = new Static3D(mObjWidth/2,mObjHeight/2, 0);
 
-      mObject.move( new Static3D( (width-mFactorObj*mObjWidth)/2 , (height-mFactorObj*mObjHeight)/2 , 0) );
-      mObject.scale(mFactorObj);
+      mObject.move( new Static3D( (width-factorObj*mObjWidth)/2 , (height-factorObj*mObjHeight)/2 , 0) );
+      mObject.scale(factorObj);
       mObject.quaternion(mQuatInt1, rotateObj);
       mObject.quaternion(mQuatInt2, rotateObj);
 
-      Static3D rotateCen = new Static3D(width/2,height/2, 0);
+      int backgroundSize = mBackground.getWidth();
+      float factorBackX = ((float)width)/backgroundSize;
+      float factorBackY = ((float)height)/backgroundSize;
 
-      mCenter.quaternion(mQuatInt1, rotateCen);
-      mCenter.quaternion(mQuatInt2, rotateCen);
-      mCenter.move( new Static3D( (width -mFactorCen*centerSize-mFactorObj*mObjWidth )/2 ,
-                                  (height-mFactorCen*centerSize-mFactorObj*mObjHeight)/2 , 10) );
-      mCenter.move(mMoveInter);
-      mCenter.scale(mFactorCen);
+      mBackground.move(new Static3D( -width/2, -height/2,-factorObj*(mObjWidth+mObjHeight)/2) );
+      mBackground.scale(new Static3D(2*factorBackX, 2*factorBackY, 1.0f) );
 
-      setVertexEffects();
-
-      Distorted.onSurfaceChanged(width, height); 
+      Distorted.onSurfaceChanged(width, height);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
       {
       Vertex3DActivity act = (Vertex3DActivity)mView.getContext();
 
       InputStream is1 = act.getResources().openRawResource(act.getBitmap());
-      InputStream is2 = act.getResources().openRawResource(R.raw.center);
+      InputStream is2 = act.getResources().openRawResource(R.raw.water);
 
       Bitmap bitmap1,bitmap2;
         
@@ -274,8 +149,8 @@ class Vertex3DRenderer implements GLSurfaceView.Renderer
         }  
       
       mObject.setBitmap(bitmap1);
-      mCenter.setBitmap(bitmap2);
-
+      mBackground.setBitmap(bitmap2)
+      ;
       try
         {
         Distorted.onSurfaceCreated(mView.getContext());
@@ -285,4 +160,4 @@ class Vertex3DRenderer implements GLSurfaceView.Renderer
         android.util.Log.e("Vertex3D", ex.getMessage() );
         }
       }
-}
+}
\ No newline at end of file
diff --git a/src/main/res/layout/effectcenter.xml b/src/main/res/layout/effectcenter.xml
new file mode 100644
index 0000000..7524943
--- /dev/null
+++ b/src/main/res/layout/effectcenter.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+              android:id="@+id/effectCenterLayout"
+              android:layout_width="match_parent"
+              android:layout_height="wrap_content"
+              android:orientation="vertical">
+
+    <TextView
+        android:id="@+id/effectCenterText"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="5dp"
+        android:layout_marginStart="5dp"
+        android:layout_marginTop="3dp"
+        />
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent">
+
+        <SeekBar
+            android:id="@+id/effectCenterBarX"
+            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="0.5"/>
+
+        <SeekBar
+            android:id="@+id/effectCenterBarY"
+            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="0.5"/>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/src/main/res/layout/vertex3ddeform.xml b/src/main/res/layout/vertex3ddeform.xml
deleted file mode 100644
index 72c3f6f..0000000
--- a/src/main/res/layout/vertex3ddeform.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                          android:id="@+id/vertex3dRowDeform"
-                          android:orientation="horizontal"
-                          android:layout_width="match_parent"
-                          android:layout_height="wrap_content"
-                >
-
-                <LinearLayout
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="0.70"
-                    android:orientation="vertical" >
-
-                    <TextView
-                        android:id="@+id/vertex3ddeformText"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginStart="5dp"
-                        android:layout_marginTop="3dp"
-                        />
-
-                    <SeekBar
-                        android:id="@+id/vertex3ddeformBar1"
-                        android:layout_width="fill_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="end"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginLeft="5dp"
-                        android:layout_marginRight="5dp" />
-
-                    <SeekBar
-                        android:id="@+id/vertex3ddeformBar2"
-                        android:layout_width="fill_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="end"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginLeft="5dp"
-                        android:layout_marginRight="5dp" />
-
-                    <SeekBar
-                        android:id="@+id/vertex3ddeformBar3"
-                        android:layout_width="fill_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="end"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginLeft="5dp"
-                        android:layout_marginRight="5dp" />
-
-                </LinearLayout>
-
-                <Button
-                    android:id="@+id/vertex3dUpDeform"
-                    android:layout_width="60dp"
-                    android:layout_height="fill_parent"
-                    android:onClick="ButtonDeform"
-                    android:text="@string/Up" />
-
-            </LinearLayout>
\ No newline at end of file
diff --git a/src/main/res/layout/vertex3ddistort.xml b/src/main/res/layout/vertex3ddistort.xml
deleted file mode 100644
index 272d1de..0000000
--- a/src/main/res/layout/vertex3ddistort.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                          android:id="@+id/vertex3dRowDistort"
-                          android:layout_width="match_parent"
-                          android:layout_height="wrap_content"
-                          android:orientation="horizontal"
-                >
-
-                <LinearLayout
-                    android:layout_width="0dp"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="0.8"
-                    android:orientation="vertical" >
-
-                    <TextView
-                        android:id="@+id/vertex3ddistortText"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginStart="5dp"
-                        android:layout_marginTop="3dp"
-                        />
-
-                    <SeekBar
-                        android:id="@+id/vertex3ddistortBar1"
-                        android:layout_width="fill_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginLeft="5dp"
-                        android:layout_marginRight="5dp" />
-
-                    <SeekBar
-                        android:id="@+id/vertex3ddistortBar2"
-                        android:layout_width="fill_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginLeft="5dp"
-                        android:layout_marginRight="5dp" />
-
-                    <SeekBar
-                        android:id="@+id/vertex3ddistortBar3"
-                        android:layout_width="fill_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginLeft="5dp"
-                        android:layout_marginRight="5dp" />
-
-                </LinearLayout>
-
-                <Button
-                    android:id="@+id/vertex3dUpDistort"
-                    android:layout_width="60dp"
-                    android:layout_height="fill_parent"
-                    android:onClick="ButtonDistort"
-                    android:text="@string/Up" />
-
-            </LinearLayout>
diff --git a/src/main/res/layout/vertex3dlayout.xml b/src/main/res/layout/vertex3dlayout.xml
index f036bec..3df32ea 100644
--- a/src/main/res/layout/vertex3dlayout.xml
+++ b/src/main/res/layout/vertex3dlayout.xml
@@ -13,65 +13,52 @@
     <LinearLayout
         android:orientation="horizontal"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="5dp"
-        android:background="@android:color/holo_green_dark">
+        android:layout_height="50dp"
+        android:layout_gravity="center">
 
-        <LinearLayout
-            android:orientation="vertical"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"
-            android:layout_weight="0.8">
-
-            <TextView
-                android:id="@+id/vertex3dcenterText"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_marginEnd="5dp"
-                android:layout_marginStart="5dp"
-                android:layout_marginTop="3dp"
-                />
-
-            <LinearLayout
-                android:orientation="horizontal"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                >
-
-                <SeekBar
-                    android:layout_width="fill_parent"
-                    android:layout_height="wrap_content"
-                    android:id="@+id/vertex3dcenterX"
-                    android:layout_weight="0.5"
-                    android:paddingLeft="5dp"
-                    android:paddingRight="3dp"/>
+        <Button
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/Add"
+            android:id="@+id/buttonAdd"
+            android:onClick="newEffect"
+            />
 
-                <SeekBar
-                    android:layout_width="fill_parent"
-                    android:layout_height="wrap_content"
-                    android:id="@+id/vertex3dcenterY"
-                    android:layout_weight="0.5"
-                    android:paddingLeft="3dp"
-                    android:paddingRight="5dp"/>
-            </LinearLayout>
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:text="@string/New"
+            android:id="@+id/textView10"/>
 
-        </LinearLayout>
+        <Spinner
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/vertex3dspinner"
+            android:layout_weight="0.5"/>
 
         <Button
-            android:id="@+id/buttonDefault"
-            android:layout_width="60dp"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:onClick="Default"
-            android:text="@string/reset"
-            android:layout_gravity="right"
-            android:layout_marginTop="3dp"/>
+            android:text="@string/RemoveAll"
+            android:id="@+id/buttonRemove"
+            android:onClick="removeAll"
+            />
+
     </LinearLayout>
 
+    <View
+        android:layout_height="4dip"
+        android:background="#777777"
+        android:layout_width="match_parent"
+        />
+
     <ScrollView
         android:id="@+id/vertex3dscrollView"
         android:layout_width="match_parent"
         android:layout_height="0dp"
-        android:layout_weight="0.82" >
+        android:layout_weight="0.82"
+        >
 
         <LinearLayout
             android:id="@+id/vertex3dlayout"
diff --git a/src/main/res/layout/vertex3dsink.xml b/src/main/res/layout/vertex3dsink.xml
deleted file mode 100644
index be10755..0000000
--- a/src/main/res/layout/vertex3dsink.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                          android:id="@+id/vertex3dRowSink"
-                          android:orientation="horizontal"
-                          android:layout_width="match_parent"
-                          android:layout_height="wrap_content"
-                >
-
-                <LinearLayout
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="0.70"
-                    android:orientation="vertical" >
-
-                    <TextView
-                        android:id="@+id/vertex3dsinkText"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginStart="5dp"
-                        android:layout_marginTop="3dp"
-                        />
-
-                    <SeekBar
-                        android:id="@+id/vertex3dsinkBar1"
-                        android:layout_width="fill_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="end"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginLeft="5dp"
-                        android:layout_marginRight="5dp" />
-
-                </LinearLayout>
-
-                <Button
-                    android:id="@+id/vertex3dUpSink"
-                    android:layout_width="60dp"
-                    android:layout_height="fill_parent"
-                    android:onClick="ButtonSink"
-                    android:text="@string/Up" />
-
-            </LinearLayout>
-           
\ No newline at end of file
diff --git a/src/main/res/layout/vertex3dswirl.xml b/src/main/res/layout/vertex3dswirl.xml
deleted file mode 100644
index 8fee5b5..0000000
--- a/src/main/res/layout/vertex3dswirl.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                          android:id="@+id/vertex3dRowSwirl"
-                          android:orientation="horizontal"
-                          android:layout_width="match_parent"
-                          android:layout_height="wrap_content"
-                >
-
-                <LinearLayout
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="0.70"
-                    android:orientation="vertical" >
-
-                    <TextView
-                        android:id="@+id/vertex3dswirlText"
-                        android:layout_width="wrap_content"
-                        android:layout_height="wrap_content"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginStart="5dp"
-                        android:layout_marginTop="3dp"
-                        />
-
-                    <SeekBar
-                        android:id="@+id/vertex3dswirlBar1"
-                        android:layout_width="fill_parent"
-                        android:layout_height="wrap_content"
-                        android:layout_gravity="end"
-                        android:layout_marginEnd="5dp"
-                        android:layout_marginLeft="5dp"
-                        android:layout_marginRight="5dp" />
-
-                </LinearLayout>
-
-                <Button
-                    android:id="@+id/vertex3dUpSwirl"
-                    android:layout_width="60dp"
-                    android:layout_height="fill_parent"
-                    android:onClick="ButtonSwirl"
-                    android:text="@string/Up" />
-
-            </LinearLayout>
\ No newline at end of file
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 46f78af..ff9e533 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -99,7 +99,7 @@
     <string name="example_vertex3d_subtitle">Test results of Vertex effects on a 3D object.</string>
     <string name="example_fragment3d">Fragment Effects</string>
     <string name="example_fragment3d_subtitle">Test results of Fragment effects on a 3D object.</string>
-    <string name="example_plainmonalisa">PlainMonaLisa</string>
+    <string name="example_plainmonalisa">SurfaceView</string>
     <string name="example_plainmonalisa_subtitle">MonaLisa rendered on a plain SurfaceView</string>
     <string name="example_save">Save to PNG</string>
     <string name="example_save_subtitle">Saving the output to a PNG file.</string>
