commit 65f622c17c32666c4122ea4c9f9fe35692a3657c
Author: Leszek Koltunski <leszek@koltunski.pl>
Date:   Mon Aug 6 14:26:36 2018 +0100

    Progress with Effects3D app - merge Matrix effects

diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index eabb591..872f56b 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -34,7 +34,6 @@
         <activity android:name=".olimpic.OlimpicActivity" />  
         <activity android:name=".cubes.CubesActivity" />       
         <activity android:name=".quaternion.QuaternionActivity" />          
-        <activity android:name=".matrix3d.Matrix3DActivity" />
         <activity android:name=".effects3d.Effects3DActivity" />
         <activity android:name=".effects3d.Effects3DActivity2"/>
         <activity android:name=".plainmonalisa.PlainMonaLisaActivity" />
diff --git a/src/main/java/org/distorted/examples/TableOfContents.java b/src/main/java/org/distorted/examples/TableOfContents.java
index 7732ec5..13934c9 100644
--- a/src/main/java/org/distorted/examples/TableOfContents.java
+++ b/src/main/java/org/distorted/examples/TableOfContents.java
@@ -53,7 +53,6 @@ import org.distorted.examples.bitmaptree.BitmapTreeActivity;
 import org.distorted.examples.starwars.StarWarsActivity;
 import org.distorted.examples.cubes.CubesActivity;
 import org.distorted.examples.quaternion.QuaternionActivity;
-import org.distorted.examples.matrix3d.Matrix3DActivity;
 import org.distorted.examples.effects3d.Effects3DActivity;
 import org.distorted.examples.plainmonalisa.PlainMonaLisaActivity;
 import org.distorted.examples.save.SaveActivity;
@@ -261,15 +260,6 @@ public class TableOfContents extends ListActivity
       data.add(item);
       activityMapping.put(i++, CubesActivity.class);
    }
-   
-   {
-      final Map<String, Object> item = new HashMap<>();
-      item.put(ITEM_IMAGE, R.drawable.icon_example_matrix3d);
-      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_matrix3d));
-      item.put(ITEM_SUBTITLE, getText(R.string.example_matrix3d_subtitle));
-      data.add(item);
-      activityMapping.put(i++, Matrix3DActivity.class);
-   }
 
    {
       final Map<String, Object> item = new HashMap<>();
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java b/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java
index e0c9b2a..e59de16 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java
@@ -43,9 +43,9 @@ public class Effects3DActivity extends Activity
   private static final int COLOR_ON  = 0xff0000ff;
   private static final int COLOR_INAC= 0xff00ff00;
 
-  private int mNumCols = 10;
-  private int mNumRows = 10;
-  private int mNumSlic =  1;
+  private int mNumCols = 1;
+  private int mNumRows = 1;
+  private int mNumSlic = 1;
   private boolean mGridInitialized;
   private NumberPicker mColsPicker, mRowsPicker, mSlicPicker;
   private boolean[] mShape;
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DActivity2.java b/src/main/java/org/distorted/examples/effects3d/Effects3DActivity2.java
index 36c2b9a..00222e9 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DActivity2.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DActivity2.java
@@ -47,7 +47,7 @@ import java.io.InputStream;
 
 public class Effects3DActivity2 extends AppCompatActivity
   {
-  public static final int NUM_TABS = 3;
+  public static final int NUM_TABS = 4;
 
   private int mNumCols;
   private int mNumRows;
@@ -267,7 +267,8 @@ public class Effects3DActivity2 extends AppCompatActivity
 
   public int getScreenWidth()
     {
-    return 0;
+    Effects3DRenderer r = ((Effects3DSurfaceView)findViewById(R.id.effects3dSurfaceView)).getRenderer();
+    return r.getWidth();
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -285,12 +286,18 @@ public class Effects3DActivity2 extends AppCompatActivity
 
     renderer.setCenter( mCenterX, mCenterY, mCenterZ );
     renderer.setRegion( mRegionX, mRegionY, mRegionR );
-    renderer.mQuat1.set(0,0,0,1);
-    renderer.mQuat2.set(0,0,0,1);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
-// 'second screen' methods
+
+  void resetMatrixEffects()
+    {
+    Effects3DSurfaceView view = findViewById(R.id.effects3dSurfaceView);
+    Effects3DRenderer renderer= view.getRenderer();
+
+    renderer.resetMatrixEffects();
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public DistortedEffects getEffects()
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DEffect.java b/src/main/java/org/distorted/examples/effects3d/Effects3DEffect.java
index 53ed8e2..79d1cf4 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DEffect.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DEffect.java
@@ -189,8 +189,9 @@ class Effects3DEffect implements SeekBar.OnSeekBarChangeListener
                               float sinAnorm = (float)Math.sin(qa/2)/len;
                               mSta4.set(sinAnorm*qx,sinAnorm*qy,sinAnorm*qz, cosA);
                               break;
-      case MOVE             : float sw = mAct.get().getScreenWidth()/50.0f;
-                              float sh = mAct.get().getScreenWidth()/50.0f;
+      case MOVE             : float scr= mAct.get().getScreenWidth();
+                              float sw = scr/20000.0f;
+                              float sh = scr/20000.0f;
                               float xm = (mInter[0]-50)*sw;
                               float ym = (mInter[1]-50)*sh;
                               float zm = (mInter[2]-50)*(sw+sh)/2;
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java b/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
index 219370b..873dfd8 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
@@ -24,22 +24,9 @@ import android.graphics.BitmapFactory;
 import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
-import org.distorted.library.effect.FragmentEffectAlpha;
-import org.distorted.library.effect.FragmentEffectBrightness;
-import org.distorted.library.effect.FragmentEffectChroma;
-import org.distorted.library.effect.FragmentEffectContrast;
-import org.distorted.library.effect.FragmentEffectSaturation;
 import org.distorted.library.effect.MatrixEffectMove;
 import org.distorted.library.effect.MatrixEffectQuaternion;
 import org.distorted.library.effect.MatrixEffectScale;
-import org.distorted.library.effect.PostprocessEffectBlur;
-import org.distorted.library.effect.PostprocessEffectGlow;
-import org.distorted.library.effect.VertexEffectDeform;
-import org.distorted.library.effect.VertexEffectDistort;
-import org.distorted.library.effect.VertexEffectPinch;
-import org.distorted.library.effect.VertexEffectSink;
-import org.distorted.library.effect.VertexEffectSwirl;
-import org.distorted.library.effect.VertexEffectWave;
 import org.distorted.library.main.Distorted;
 import org.distorted.library.main.DistortedEffects;
 import org.distorted.library.main.DistortedNode;
@@ -73,6 +60,7 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
     private boolean mShowingCenter=false;
     private boolean mShowingRegion=false;
     private float mFactorObj, mFactorReg;
+    private int mWidth;
 
     Static4D mQuat1, mQuat2;
     int mScreenMin;
@@ -104,12 +92,11 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
       DistortedEffects centerEffects     = new DistortedEffects();
       DistortedEffects regionEffects     = new DistortedEffects();
 
-      MeshObject meshO   = act.getMesh();
+      MeshObject mesh    = act.getMesh();
       MeshFlat quad      = new MeshFlat(1,1);
 
       mObjWidth = mObjectTexture.getWidth();
       mObjHeight= mObjectTexture.getHeight();
-      int objDepth = mObjectTexture.getDepth(meshO);
 
       mQuat1 = new Static4D(0,0,0,1);  // unity
       mQuat2 = new Static4D(0,0,0,1);  // quaternions
@@ -124,23 +111,15 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
       mScreen = new DistortedScreen();
       mScreen.setProjection(FOV, NEAR);
       mScreen.attach(mBackgroundTexture, backgroundEffects, quad );
-      mScreen.attach(mObjectTexture    , objectEffects    , meshO);
+      mScreen.attach(mObjectTexture    , objectEffects    , mesh );
 
       int regionSize = mRegionTexture.getWidth();
-      Static3D rotateObj = new Static3D( (float)mObjWidth/2, (float)mObjHeight/2, -(float)objDepth/2 );
       mRotateCen = new Static3D(0 ,0, 0);
 
-      MatrixEffectQuaternion quat1obj = new MatrixEffectQuaternion(mQuat1,  rotateObj);
-      MatrixEffectQuaternion quat2obj = new MatrixEffectQuaternion(mQuat2,  rotateObj);
       MatrixEffectQuaternion quat1cen = new MatrixEffectQuaternion(mQuat1, mRotateCen);
       MatrixEffectQuaternion quat2cen = new MatrixEffectQuaternion(mQuat2, mRotateCen);
       MatrixEffectMove centerMove = new MatrixEffectMove(mCenterPoint);
 
-      objectEffects.apply( new MatrixEffectMove(mMoveObject));
-      objectEffects.apply( new MatrixEffectScale(mScaleObject) );
-      objectEffects.apply(quat1obj);
-      objectEffects.apply(quat2obj);
-
       centerEffects.apply(quat1cen);
       centerEffects.apply(quat2cen);
       centerEffects.apply( new MatrixEffectMove(mMoveCenter) );
@@ -155,11 +134,38 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
       regionEffects.apply( new MatrixEffectScale(mRegionScalePoint) );
       regionEffects.apply( new MatrixEffectMove(new Static3D( -regionSize/2 , -regionSize/2 , 0)) );
 
+      resetMatrixEffects();
+
       // quite tricky: move the background exactly to the FAR plane! (see DistortedOutputSurface.setProjection() )
       backgroundEffects.apply(new MatrixEffectMove(mMoveBackground) );
       backgroundEffects.apply(new MatrixEffectScale(mScaleBackground) );
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    void resetMatrixEffects()
+      {
+      Effects3DActivity2 act = (Effects3DActivity2)mView.getContext();
+
+      DistortedEffects objectEffects= act.getEffects();
+      MeshObject mesh  = act.getMesh();
+
+      int objDepth = mObjectTexture.getDepth(mesh);
+
+      Static3D rotateObj = new Static3D( (float)mObjWidth/2, (float)mObjHeight/2, -(float)objDepth/2 );
+
+      MatrixEffectQuaternion quat1obj = new MatrixEffectQuaternion(mQuat1,  rotateObj);
+      MatrixEffectQuaternion quat2obj = new MatrixEffectQuaternion(mQuat2,  rotateObj);
+
+      objectEffects.apply( new MatrixEffectMove(mMoveObject));
+      objectEffects.apply( new MatrixEffectScale(mScaleObject) );
+      objectEffects.apply(quat1obj);
+      objectEffects.apply(quat2obj);
+
+      mQuat1.set(0,0,0,1);
+      mQuat2.set(0,0,0,1);
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     void showRegionAndCenter(boolean showRegion, boolean showCenter)
@@ -181,6 +187,13 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
         }
       }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public int getWidth()
+      {
+      return mWidth;
+      }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
     void setCenter(float x, float y, float z)
@@ -215,6 +228,7 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
 
     public void onSurfaceChanged(GL10 glUnused, int width, int height)
       {
+      mWidth = width;
       mScreenMin = width<height ? width:height;
 
       float factorCen;
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DTab.java b/src/main/java/org/distorted/examples/effects3d/Effects3DTab.java
index 39a4d5d..85deba4 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DTab.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DTab.java
@@ -69,17 +69,22 @@ public class Effects3DTab extends Fragment implements AdapterView.OnItemSelected
 
     switch(position)
       {
-      case 0: mTab     = R.layout.effects3dtab1;
+      case 0: mTab     = R.layout.effects3dtab0;
+              mLayout  = R.id.effects3dlayout0;
+              mSpinner = R.id.effects3dspinner0;
+              mType    = EffectType.MATRIX;
+              break;
+      case 1: mTab     = R.layout.effects3dtab1;
               mLayout  = R.id.effects3dlayout1;
               mSpinner = R.id.effects3dspinner1;
               mType    = EffectType.VERTEX;
               break;
-      case 1: mTab     = R.layout.effects3dtab2;
+      case 2: mTab     = R.layout.effects3dtab2;
               mLayout  = R.id.effects3dlayout2;
               mSpinner = R.id.effects3dspinner2;
               mType    = EffectType.FRAGMENT;
               break;
-      case 2: mTab     = R.layout.effects3dtab3;
+      case 3: mTab     = R.layout.effects3dtab3;
               mLayout  = R.id.effects3dlayout3;
               mSpinner = R.id.effects3dspinner3;
               mType    = EffectType.POSTPROCESS;
@@ -87,9 +92,12 @@ public class Effects3DTab extends Fragment implements AdapterView.OnItemSelected
       }
 
     Effects3DActivity2 act = (Effects3DActivity2)getActivity();
-    act.setTab(position, this);
 
-    mEffects = act.getEffects();
+    if( act!=null )
+      {
+      act.setTab(position, this);
+      mEffects = act.getEffects();
+      }
 
     createEffectNames(mType);
     mEffectStrings = new String[mEffectNames.length];
@@ -99,8 +107,7 @@ public class Effects3DTab extends Fragment implements AdapterView.OnItemSelected
       mEffectStrings[i] = mEffectNames[i].name();
       }
 
-    View rootView = inflater.inflate( mTab, container, false);
-    return rootView;
+    return inflater.inflate( mTab, container, false);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -221,6 +228,11 @@ public class Effects3DTab extends Fragment implements AdapterView.OnItemSelected
 
     resetData();
     act.resetData();
+
+    if( mType==EffectType.MATRIX )
+      {
+      act.resetMatrixEffects();
+      }
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DTabViewPager.java b/src/main/java/org/distorted/examples/effects3d/Effects3DTabViewPager.java
index 13741b5..5a4072b 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DTabViewPager.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DTabViewPager.java
@@ -49,11 +49,12 @@ public class Effects3DTabViewPager extends FragmentPagerAdapter
     {
     if( position>=0 && position<Effects3DActivity2.NUM_TABS )
       {
+      Effects3DTab tab = new Effects3DTab();
+
       Bundle bundle = new Bundle();
       bundle.putInt("position", position);
-
-      Effects3DTab tab = new Effects3DTab();
       tab.setArguments(bundle);
+
       return tab;
       }
 
@@ -75,9 +76,10 @@ public class Effects3DTabViewPager extends FragmentPagerAdapter
     {
     switch (position)
       {
-      case 0 : return mAct.get().getString(R.string.type_vertex);
-      case 1 : return mAct.get().getString(R.string.type_fragment);
-      case 2 : return mAct.get().getString(R.string.type_postprocess);
+      case 0 : return mAct.get().getString(R.string.type_matrix);
+      case 1 : return mAct.get().getString(R.string.type_vertex);
+      case 2 : return mAct.get().getString(R.string.type_fragment);
+      case 3 : return mAct.get().getString(R.string.type_postprocess);
       default: return null;
       }
     }
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java
deleted file mode 100644
index 2e3add0..0000000
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java
+++ /dev/null
@@ -1,345 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.matrix3d;
-
-import android.app.Activity;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.opengl.GLSurfaceView;
-import android.os.Bundle;
-import android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.LinearLayout;
-import android.widget.Spinner;
-
-import org.distorted.examples.R;
-import org.distorted.library.effect.EffectName;
-import org.distorted.library.effect.EffectType;
-import org.distorted.library.main.Distorted;
-import org.distorted.library.main.DistortedEffects;
-import org.distorted.library.main.MeshCubes;
-import org.distorted.library.main.MeshObject;
-import org.distorted.library.main.DistortedTexture;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class Matrix3DActivity extends Activity implements AdapterView.OnItemSelectedListener
-  {
-  private DistortedTexture mTexture;
-  private MeshObject mMesh;
-  private DistortedEffects mEffects;
-
-  private ArrayList<Matrix3DEffect> mList;
-  private int mEffectAdd;
-
-  private EffectName[] mEffectNames;
-
-  private static boolean mSupportsCenter;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  @Override
-  protected void onCreate(Bundle savedState)
-    {
-    super.onCreate(savedState);
-
-    mList = new ArrayList<>();
-
-    createEffectNames();
-
-    mEffects = new DistortedEffects();
-    mMesh    = new MeshCubes(1,1,1);
-    mTexture = new DistortedTexture(100,100);
-
-    setEffectView();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void createEffectNames()
-    {
-    EffectType type = EffectType.MATRIX;
-
-    EffectName[] names = EffectName.values();
-
-    int numEffects=0;
-
-    for(int i=0; i<names.length; i++)
-      if( names[i].getType() == type ) numEffects++;
-
-    mEffectNames = new EffectName[numEffects];
-
-    numEffects=0;
-
-    for(int i=0; i<names.length; i++)
-      if( names[i].getType() == type )
-        {
-        mEffectNames[numEffects++] = names[i];
-        }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public DistortedEffects getEffects()
-    {
-    return mEffects;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public DistortedTexture getTexture()
-    {
-    return mTexture;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public MeshObject getMesh()
-    {
-    return mMesh;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void setRegion(float x, float y, float r)
-    {
-
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void setCenter(float x, float y, float z)
-    {
-
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public static void setSupportsRegion(boolean supports)
-    {
-
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public static void setSupportsCenter(boolean supports)
-    {
-    mSupportsCenter = supports;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public Bitmap getBitmap()
-    {
-    Bitmap bmp;
-
-    InputStream is = getResources().openRawResource(R.raw.grid);
-
-    try
-      {
-      bmp = BitmapFactory.decodeStream(is);
-      }
-    finally
-      {
-      try
-        {
-        is.close();
-        }
-      catch(IOException e) { }
-      }
-
-    return bmp;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int getWidth()
-    {
-    return mTexture==null ? 0: mTexture.getWidth();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int getHeight()
-    {
-    return mTexture==null ? 0: mTexture.getHeight();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int getDepth()
-    {
-    return mTexture==null ? 0: mTexture.getDepth(mMesh);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public int getScreenWidth()
-    {
-    Matrix3DRenderer r = ((Matrix3DSurfaceView)findViewById(R.id.matrix3dSurfaceView)).getRenderer();
-    return r.getWidth();
-    }
-
-//////////////////////////////////////////////////////////////////////////////////
-
-  public void onItemSelected(AdapterView<?> parent, View view, int pos, long id)
-    {
-    switch(parent.getId())
-      {
-      case R.id.matrix3dspinner: mEffectAdd = pos;
-                                 break;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void onNothingSelected(AdapterView<?> parent)
-    {
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void resetData()
-    {
-    mSupportsCenter=false;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setEffectView()
-    {
-    resetData();
-
-    final View view = getLayoutInflater().inflate(R.layout.matrix3dlayout, null);
-
-    setContentView(view);
-
-    String[] effects = new String[mEffectNames.length];
-
-    for(int i=0; i<mEffectNames.length; i++) effects[i] = mEffectNames[i].name();
-
-    Spinner effectSpinner = (Spinner)findViewById(R.id.matrix3dspinner );
-    effectSpinner.setOnItemSelectedListener(this);
-
-    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);
-
-    mEffectAdd = 0;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void newEffect(View v)
-    {
-    Matrix3DEffect eff = new Matrix3DEffect(mEffectNames[mEffectAdd], this);
-    mList.add(eff);
-
-    LinearLayout layout = (LinearLayout)findViewById(R.id.matrix3dlayout);
-    View view = eff.createView();
-    layout.addView(view);
-
-    if( mSupportsCenter )
-      {
-      View center = eff.createCenter();
-      layout.addView(center);
-      }
-
-    eff.apply(mEffects);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void removeAll(View v)
-    {
-    mList.clear();
-    LinearLayout layout = (LinearLayout)findViewById(R.id.matrix3dlayout);
-    layout.removeAllViews();
-    mEffects.abortByType(EffectType.MATRIX);
-
-    resetData();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void remove(View v)
-    {
-    for(Matrix3DEffect effect: mList)
-      {
-      if( effect.thisView(v) )
-        {
-        LinearLayout layout = (LinearLayout)findViewById(R.id.matrix3dlayout);
-        View view;
-
-        view = effect.getEffect();
-        if( view!=null ) layout.removeView(view);
-        view = effect.getCenter();
-        if( view!=null ) layout.removeView(view);
-        view = effect.getRegion();
-        if( view!=null ) layout.removeView(view);
-
-        mEffects.abortById(effect.getId());
-        mList.remove(effect);
-
-        resetData();
-
-        break;
-        }
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// Overrides
-
-  @Override
-  protected void onPause()
-    {
-    GLSurfaceView mView = (GLSurfaceView)findViewById(R.id.matrix3dSurfaceView);
-    if( mView!=null ) mView.onPause();
-
-    Distorted.onPause();
-    super.onPause();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-  @Override
-  protected void onResume()
-    {
-    super.onResume();
-    GLSurfaceView mView = (GLSurfaceView)findViewById(R.id.matrix3dSurfaceView);
-    if( mView!=null ) mView.onResume();
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-  @Override
-  protected void onDestroy()
-    {
-    Distorted.onDestroy();
-    super.onDestroy();
-    }
-
-  }
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DEffect.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DEffect.java
deleted file mode 100644
index 9f9b1aa..0000000
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DEffect.java
+++ /dev/null
@@ -1,724 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.matrix3d;
-
-import android.view.View;
-import android.widget.SeekBar;
-import android.widget.TextView;
-
-import org.distorted.examples.R;
-import org.distorted.library.effect.Effect;
-import org.distorted.library.effect.EffectName;
-import org.distorted.library.effect.EffectType;
-import org.distorted.library.effect.FragmentEffectAlpha;
-import org.distorted.library.effect.FragmentEffectBrightness;
-import org.distorted.library.effect.FragmentEffectChroma;
-import org.distorted.library.effect.FragmentEffectContrast;
-import org.distorted.library.effect.FragmentEffectSaturation;
-import org.distorted.library.effect.MatrixEffectMove;
-import org.distorted.library.effect.MatrixEffectQuaternion;
-import org.distorted.library.effect.MatrixEffectRotate;
-import org.distorted.library.effect.MatrixEffectScale;
-import org.distorted.library.effect.MatrixEffectShear;
-import org.distorted.library.effect.VertexEffectDeform;
-import org.distorted.library.effect.VertexEffectDistort;
-import org.distorted.library.effect.VertexEffectPinch;
-import org.distorted.library.effect.VertexEffectSink;
-import org.distorted.library.effect.VertexEffectSwirl;
-import org.distorted.library.effect.VertexEffectWave;
-import org.distorted.library.main.DistortedEffects;
-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.Dynamic5D;
-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 org.distorted.library.type.Static5D;
-
-import java.lang.ref.WeakReference;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class Matrix3DEffect implements SeekBar.OnSeekBarChangeListener
-  {
-  private WeakReference<Matrix3DActivity> mAct;
-
-  private EffectName 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 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 Dynamic3D mCenterDyn;
-  private Static3D  mCenterSta;
-
-  private View mButton, mEffect, mCenter, mRegion;
-  private long mId;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// requires knowledge about effect nature
-
-  void apply(DistortedEffects effects)
-    {
-    Effect effect=null;
-
-    switch(mName)
-      {
-      case ROTATE           : effect = new MatrixEffectRotate      (mDyn1, mDyn3, mCenterDyn); break;
-      case QUATERNION       : effect = new MatrixEffectQuaternion  (mDyn4,        mCenterDyn); break;
-      case MOVE             : effect = new MatrixEffectMove        (mDyn3                   ); break;
-      case SCALE            : effect = new MatrixEffectScale       (mDyn3                   ); break;
-      case SHEAR            : effect = new MatrixEffectShear       (mDyn3,        mCenterDyn); break;
-
-      case DISTORT          : effect = new VertexEffectDistort     (mDyn3, mCenterDyn, mRegionDyn); break;
-      case DEFORM           : effect = new VertexEffectDeform      (mDyn3, mCenterDyn, mRegionDyn); break;
-      case SINK             : effect = new VertexEffectSink        (mDyn1, mCenterDyn, mRegionDyn); break;
-      case PINCH            : effect = new VertexEffectPinch       (mDyn2, mCenterDyn, mRegionDyn); break;
-      case SWIRL            : effect = new VertexEffectSwirl       (mDyn1, mCenterDyn, mRegionDyn); break;
-      case WAVE             : effect = new VertexEffectWave        (mDyn5, mCenterDyn, mRegionDyn); break;
-
-      case ALPHA            : effect = new FragmentEffectAlpha     (mDyn1,        mRegionDyn, false); break;
-      case SMOOTH_ALPHA     : effect = new FragmentEffectAlpha     (mDyn1,        mRegionDyn, true ); break;
-      case CHROMA           : effect = new FragmentEffectChroma    (mDyn1, mDyn3, mRegionDyn, false); break;
-      case SMOOTH_CHROMA    : effect = new FragmentEffectChroma    (mDyn1, mDyn3, mRegionDyn, true ); break;
-      case BRIGHTNESS       : effect = new FragmentEffectBrightness(mDyn1,        mRegionDyn, false); break;
-      case SMOOTH_BRIGHTNESS: effect = new FragmentEffectBrightness(mDyn1,        mRegionDyn, true ); break;
-      case SATURATION       : effect = new FragmentEffectSaturation(mDyn1,        mRegionDyn, false); break;
-      case SMOOTH_SATURATION: effect = new FragmentEffectSaturation(mDyn1,        mRegionDyn, true ); break;
-      case CONTRAST         : effect = new FragmentEffectContrast  (mDyn1,        mRegionDyn, false); break;
-      case SMOOTH_CONTRAST  : effect = new FragmentEffectContrast  (mDyn1,        mRegionDyn, true ); break;
-      }
-
-    if( effect!=null )
-      {
-      effects.apply(effect);
-      mId = effect.getID();
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// requires knowledge about effect nature
-
-  private void fillStatics()
-    {
-    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;
-                              mSta1.set(an);
-                              mSta3.set(rx,ry,rz);
-                              break;
-      case QUATERNION       : float qx = (mInter[0]-50)/ 50.0f;
-                              float qy = (mInter[1]-50)/ 50.0f;
-                              float qz = (mInter[2]-50)/ 50.0f;
-                              float qa = (mInter[3]-50)*3.1415f/50;
-                              float cosA = (float)Math.cos(qa/2);
-                              float len = (float)Math.sqrt(qx*qx+qy*qy+qz*qz);
-                              float sinAnorm = (float)Math.sin(qa/2)/len;
-                              mSta4.set(sinAnorm*qx,sinAnorm*qy,sinAnorm*qz, cosA);
-                              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)/10.0f;
-                              float ys = (mInter[1]-50)/10.0f;
-                              float zs = (mInter[2]-50)/10.0f;
-                              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 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;
-                              float y2 = (mInter[1]-50)*l2;
-                              float z2 = (mInter[2]-50)*180 / 50;
-                              float w2 = (mInter[3]-50)*180 / 50;
-                              float v2 = (mInter[4]-50)*180 / 50;
-                              mSta5.set(x2,y2,z2,w2,v2);
-                              break;
-      case SWIRL            : mSta1.set( 3.6f*(mInter[0]-50) );
-                              break;
-      case SINK             : mSta1.set(mInter[0] > 50 ? 50.0f/(100.01f-mInter[0]) : mInter[0] / 50.0f);
-                              break;
-      case PINCH            : float dp = mInter[0] > 50 ? 50.0f/(100.01f-mInter[0]) : mInter[0] / 50.0f;
-                              float ap = (mInter[1]-50)*180 / 50;
-                              mSta2.set(dp,ap);
-                              break;
-
-      case ALPHA            :
-      case SMOOTH_ALPHA     : mSta1.set(mInter[0]/100.0f);
-                              break;
-      case SATURATION       :
-      case SMOOTH_SATURATION:
-      case CONTRAST         :
-      case SMOOTH_CONTRAST  :
-      case BRIGHTNESS       :
-      case SMOOTH_BRIGHTNESS: mSta1.set(mInter[0] > 50 ? 50.0f/(100.01f-mInter[0]) : mInter[0] / 50.0f);
-                              break;
-      case CHROMA           :
-      case SMOOTH_CHROMA    : mSta1.set(mInter[0]/100.0f);
-                              mSta3.set(mInter[1]/100.0f,
-                                        mInter[2]/100.0f,
-                                        mInter[3]/100.0f);
-                              break;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setDefaultInter()
-    {
-    switch(mDimension)
-      {
-      case 5: mInter[4] = 50;
-      case 4: mInter[3] = 50;
-      case 3: mInter[2] = 50;
-      case 2: mInter[1] = 50;
-      case 1: mInter[0] = 50;
-      }
-
-    if( mName==EffectName.ROTATE || mName==EffectName.QUATERNION )
-      {
-      mInter[1]= 100;
-      }
-    if( mName==EffectName.SCALE )
-      {
-      mInter[0]= 60;
-      mInter[1]= 60;
-      mInter[2]= 60;
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setText()
-    {
-    String text = mName.name();
-
-    if( mSta1 !=null )
-      {
-      float f1 = ((int)(mSta1.get1()*100))/100.0f;
-      text += " "+f1;
-      }
-
-    if( mSta2 !=null )
-      {
-      float f1 = ((int)(mSta2.get1()*100))/100.0f;
-      float f2 = ((int)(mSta2.get2()*100))/100.0f;
-      text += " ("+f1+","+f2+")";
-      }
-
-    if( mSta3 !=null )
-      {
-      float f1 = ((int)(mSta3.get1()*100))/100.0f;
-      float f2 = ((int)(mSta3.get2()*100))/100.0f;
-      float f3 = ((int)(mSta3.get3()*100))/100.0f;
-      text += " ("+f1+","+f2+","+f3+")";
-      }
-
-    if( mSta4 !=null )
-      {
-      float f1 = ((int)(mSta4.get1()*100))/100.0f;
-      float f2 = ((int)(mSta4.get2()*100))/100.0f;
-      float f3 = ((int)(mSta4.get3()*100))/100.0f;
-      float f4 = ((int)(mSta4.get4()*100))/100.0f;
-      text += " ("+f1+","+f2+","+f3+","+f4+")";
-      }
-
-    if( mSta5 !=null )
-      {
-      float f1 = ((int)(mSta5.get1()*100))/100.0f;
-      float f2 = ((int)(mSta5.get2()*100))/100.0f;
-      float f3 = ((int)(mSta5.get3()*100))/100.0f;
-      float f4 = ((int)(mSta5.get4()*100))/100.0f;
-      float f5 = ((int)(mSta5.get5()*100))/100.0f;
-      text += " ("+f1+","+f2+","+f3+","+f4+","+f5+")";
-      }
-
-    mText.setText(text);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void fillCenterStatics()
-    {
-    Matrix3DActivity act = mAct.get();
-
-    float x = (mInterCenter[0]*0.012f - 0.1f)*act.getWidth();
-    float y = (mInterCenter[1]*0.012f - 0.1f)*act.getHeight();
-    float z = (mInterCenter[2]*0.012f - 0.1f)*act.getDepth();
-
-    mCenterSta.set(x,y,z);
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setDefaultCenterInter()
-    {
-    mInterCenter[0] = 50;
-    mInterCenter[1] = 50;
-    mInterCenter[2] = 50;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void setCenterText()
-    {
-    int f0 = (int)mCenterSta.get1();
-    int f1 = (int)mCenterSta.get2();
-    int f2 = (int)mCenterSta.get3();
-
-    mTextCenter.setText("center ("+f0+","+f1+","+f2+")");
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  private void fillRegionStatics()
-    {
-    Matrix3DActivity act = mAct.get();
-
-    float factorX = act.getWidth() / 100.0f;
-    float factorY = act.getHeight()/ 100.0f;
-
-    int deduct = (mName.getType() == EffectType.VERTEX ? 50:0);
-
-    float  x = (mInterRegion[0]-deduct)*factorX;
-    float  y = (mInterRegion[1]-deduct)*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.get1();
-    int f1 = (int)mRegionSta.get2();
-    int f2 = (int)mRegionSta.get3();
-    int f3 = (int)mRegionSta.get4();
-
-    mTextRegion.setText("region ("+f0+","+f1+","+f2+","+f3+")");
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  Matrix3DEffect(EffectName name, Matrix3DActivity act)
-    {
-    mAct = new WeakReference<>(act);
-    mName = name;
-
-    mDyn1 = null;
-    mDyn2 = null;
-    mDyn3 = null;
-    mDyn4 = null;
-    mDyn5 = null;
-    mSta1 = null;
-    mSta2 = null;
-    mSta3 = null;
-    mSta4 = null;
-    mSta5 = null;
-
-    mDimension = mName.getDimension();
-
-    switch(mDimension)
-      {
-      case 1 : mDyn1 = new Dynamic1D();
-               mSta1 = new Static1D(0);
-               mDyn1.add(mSta1);
-               break;
-      case 2 : mDyn2 = new Dynamic2D();
-               mSta2 = new Static2D(0,0);
-               mDyn2.add(mSta2);
-               break;
-      case 3 : mDyn3 = new Dynamic3D();
-               mSta3 = new Static3D(0,0,0);
-               mDyn3.add(mSta3);
-               break;
-      case 4 : if( mName == EffectName.QUATERNION )
-                 {
-                 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);
-               mDyn5.add(mSta5);
-               break;
-      default: throw new RuntimeException("unsupported effect");
-      }
-
-    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[3];
-    mSeekCenterID= new int[3];
-    mCenterDyn   = new Dynamic3D();
-    mCenterSta   = new Static3D(0,0,0);
-    mCenterDyn.add(mCenterSta);
-
-    mButton = null;
-    mEffect = null;
-    mCenter = null;
-    mRegion = null;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  View createView()
-    {
-    SeekBar[] seek = new SeekBar[mDimension];
-
-    Matrix3DActivity act = mAct.get();
-
-    switch(mDimension)
-      {
-      case 1 : mEffect    = act.getLayoutInflater().inflate(R.layout.effect1d, null);
-               mText      = (TextView)mEffect.findViewById(R.id.effect1dText);
-               seek[0]    = (SeekBar)mEffect.findViewById(R.id.effect1dbar1);
-               mSeekID[0] = seek[0].getId();
-               mButton    = mEffect.findViewById(R.id.button1dRemove);
-               break;
-      case 2 : mEffect    = act.getLayoutInflater().inflate(R.layout.effect2d, null);
-               mText      = (TextView)mEffect.findViewById(R.id.effect2dText);
-               seek[0]    = (SeekBar)mEffect.findViewById(R.id.effect2dbar1);
-               seek[1]    = (SeekBar)mEffect.findViewById(R.id.effect2dbar2);
-               mSeekID[0] = seek[0].getId();
-               mSeekID[1] = seek[1].getId();
-               mButton    = mEffect.findViewById(R.id.button2dRemove);
-               break;
-      case 3 : mEffect    = act.getLayoutInflater().inflate(R.layout.effect3d, null);
-               mText      = (TextView)mEffect.findViewById(R.id.effect3dText);
-               seek[0]    = (SeekBar)mEffect.findViewById(R.id.effect3dbar1);
-               seek[1]    = (SeekBar)mEffect.findViewById(R.id.effect3dbar2);
-               seek[2]    = (SeekBar)mEffect.findViewById(R.id.effect3dbar3);
-               mSeekID[0] = seek[0].getId();
-               mSeekID[1] = seek[1].getId();
-               mSeekID[2] = seek[2].getId();
-               mButton    = mEffect.findViewById(R.id.button3dRemove);
-               break;
-      case 4 : mEffect    = act.getLayoutInflater().inflate(R.layout.effect4d, null);
-               mText      = (TextView)mEffect.findViewById(R.id.effect4dText);
-               seek[0]    = (SeekBar)mEffect.findViewById(R.id.effect4dbar1);
-               seek[1]    = (SeekBar)mEffect.findViewById(R.id.effect4dbar2);
-               seek[2]    = (SeekBar)mEffect.findViewById(R.id.effect4dbar3);
-               seek[3]    = (SeekBar)mEffect.findViewById(R.id.effect4dbar4);
-               mSeekID[0] = seek[0].getId();
-               mSeekID[1] = seek[1].getId();
-               mSeekID[2] = seek[2].getId();
-               mSeekID[3] = seek[3].getId();
-               mButton    = mEffect.findViewById(R.id.button4dRemove);
-               break;
-      case 5 : mEffect    = act.getLayoutInflater().inflate(R.layout.effect5d, null);
-               mText      = (TextView)mEffect.findViewById(R.id.effect5dText);
-               seek[0]    = (SeekBar)mEffect.findViewById(R.id.effect5dbar1);
-               seek[1]    = (SeekBar)mEffect.findViewById(R.id.effect5dbar2);
-               seek[2]    = (SeekBar)mEffect.findViewById(R.id.effect5dbar3);
-               seek[3]    = (SeekBar)mEffect.findViewById(R.id.effect5dbar4);
-               seek[4]    = (SeekBar)mEffect.findViewById(R.id.effect5dbar5);
-               mSeekID[0] = seek[0].getId();
-               mSeekID[1] = seek[1].getId();
-               mSeekID[2] = seek[2].getId();
-               mSeekID[3] = seek[3].getId();
-               mSeekID[4] = seek[4].getId();
-               mButton    = mEffect.findViewById(R.id.button5dRemove);
-               break;
-      default: android.util.Log.e("Matrix3DEffect", "dimension "+mDimension+" not supported!");
-               return null;
-      }
-
-    setDefaultInter();
-
-    for(int i=0; i<mDimension; i++)
-      {
-      seek[i].setOnSeekBarChangeListener(this);
-      seek[i].setProgress( mInter[i] );
-      }
-
-    Matrix3DActivity.setSupportsRegion(mName.supportsRegion());
-    Matrix3DActivity.setSupportsCenter(mName.supportsCenter());
-
-    return mEffect;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  View createRegion()
-    {
-    Matrix3DActivity act = mAct.get();
-
-    mRegion = act.getLayoutInflater().inflate(R.layout.effectregion, null);
-
-    SeekBar[] seek = new SeekBar[4];
-
-    seek[0] = (SeekBar)mRegion.findViewById(R.id.effectRegionBarX );
-    seek[1] = (SeekBar)mRegion.findViewById(R.id.effectRegionBarY );
-    seek[2] = (SeekBar)mRegion.findViewById(R.id.effectRegionBarRX);
-    seek[3] = (SeekBar)mRegion.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)mRegion.findViewById(R.id.effectRegionText);
-
-    setDefaultRegionInter();
-
-    for(int i=0; i<4; i++)
-      {
-      seek[i].setOnSeekBarChangeListener(this);
-      seek[i].setProgress( mInterRegion[i] );
-      }
-
-    act.setRegion(mRegionSta.get1(),mRegionSta.get2(),mRegionSta.get3());
-
-    return mRegion;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  View createCenter()
-    {
-    Matrix3DActivity act = mAct.get();
-
-    mCenter = act.getLayoutInflater().inflate(R.layout.effectcenter, null);
-
-    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<3; i++)
-      {
-      seek[i].setOnSeekBarChangeListener(this);
-      seek[i].setProgress( mInterCenter[i] );
-      }
-
-    act.setCenter(mCenterSta.get1(),mCenterSta.get2(),mCenterSta.get3());
-
-    return mCenter;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  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 ( mDimension>=5 && bar.getId()==mSeekID[4] )
-      {
-      mInter[4] = 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();
-      }
-    if( bar.getId() == mSeekCenterID[2] )
-      {
-      mInterCenter[2] = progress;
-      fillCenterStatics();
-      setCenterText();
-      }
-
-    if( fromUser )
-      {
-      Matrix3DActivity.setSupportsRegion(mName.supportsRegion());
-      Matrix3DActivity.setSupportsCenter(mName.supportsCenter());
-
-      Matrix3DActivity act = mAct.get();
-
-      act.setCenter(mCenterSta.get1(),mCenterSta.get2(),mCenterSta.get3());
-      act.setRegion(mRegionSta.get1(),mRegionSta.get2(),mRegionSta.get3());
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  boolean thisView(View v)
-    {
-    return v==mButton;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public long getId()
-    {
-    return mId;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public View getEffect()
-    {
-    return mEffect;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public View getRegion()
-    {
-    return mRegion;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public View getCenter()
-    {
-    return mCenter;
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void onStartTrackingTouch(SeekBar bar) { }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public void onStopTrackingTouch(SeekBar bar)  { }
-  }
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
deleted file mode 100644
index 272e08a..0000000
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
+++ /dev/null
@@ -1,101 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.matrix3d;
-
-import android.opengl.GLSurfaceView;
-
-import org.distorted.library.main.Distorted;
-import org.distorted.library.main.DistortedScreen;
-import org.distorted.library.main.DistortedTexture;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class Matrix3DRenderer implements GLSurfaceView.Renderer
-{
-    private GLSurfaceView mView;
-    private DistortedTexture mTexture;
-    private DistortedScreen mScreen;
-
-    private int mWidth, mHeight;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    Matrix3DRenderer(GLSurfaceView v)
-      {
-      mView = v;
-      Matrix3DActivity act = (Matrix3DActivity)v.getContext();
-      mTexture= act.getTexture();
-      mScreen = new DistortedScreen();
-      mScreen.attach(mTexture,act.getEffects(),act.getMesh());
-      mScreen.setProjection(60.0f,0.1f);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void onDrawFrame(GL10 glUnused)
-      {
-      mScreen.render( System.currentTimeMillis() );
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public int getWidth()
-      {
-      return mWidth;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public int getHeight()
-      {
-      return mHeight;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void onSurfaceChanged(GL10 glUnused, int width, int height)
-      {
-      mWidth = width;
-      mHeight= height;
-
-      mScreen.resize(width, height);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
-      {
-      Matrix3DActivity act = (Matrix3DActivity)mView.getContext();
-
-      mTexture.setTexture(act.getBitmap());
-
-      try
-        {
-        Distorted.onCreate(mView.getContext());
-        }
-      catch(Exception ex)
-        {
-        android.util.Log.e("Matrix3D", ex.getMessage() );
-        }
-      }
-}
\ No newline at end of file
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DSurfaceView.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DSurfaceView.java
deleted file mode 100644
index a6529c9..0000000
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DSurfaceView.java
+++ /dev/null
@@ -1,57 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////////////////////
-// 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.matrix3d;
-
-import android.app.ActivityManager;
-import android.content.Context;
-import android.content.pm.ConfigurationInfo;
-import android.opengl.GLSurfaceView;
-import android.util.AttributeSet;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class Matrix3DSurfaceView extends GLSurfaceView
-  {
-  private Matrix3DRenderer mRenderer;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-   
-  public Matrix3DSurfaceView(Context context, AttributeSet attrs)
-    {
-    super(context, attrs);
-      
-    if(!isInEditMode())
-      {
-      mRenderer = new Matrix3DRenderer(this);
-      final ActivityManager activityManager     = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
-      final ConfigurationInfo configurationInfo = activityManager.getDeviceConfigurationInfo();
-      setEGLContextClientVersion( (configurationInfo.reqGlEsVersion>>16) >= 3 ? 3:2 );
-      setRenderer(mRenderer);
-      }
-    }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-  public Matrix3DRenderer getRenderer()
-    {
-    return mRenderer;
-    }
-  }
-
diff --git a/src/main/res/layout/effects3dtab0.xml b/src/main/res/layout/effects3dtab0.xml
new file mode 100644
index 0000000..f4326fd
--- /dev/null
+++ b/src/main/res/layout/effects3dtab0.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="42dp"
+            android:layout_gravity="center"
+            android:orientation="horizontal">
+
+            <Button
+                android:id="@+id/buttonAdd"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="newEffect"
+                android:text="@string/Add"
+                />
+
+            <TextView
+                android:id="@+id/textView0"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/New"
+                android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+            <Spinner
+                android:id="@+id/effects3dspinner0"
+                android:layout_width="0dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="0.5"/>
+
+            <Button
+                android:id="@+id/buttonRemove"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="removeAll"
+                android:text="@string/reset"
+                />
+
+        </LinearLayout>
+
+        <View
+            android:layout_height="4dip"
+            android:background="#777777"
+            android:layout_width="match_parent"
+            />
+
+        <ScrollView
+            android:id="@+id/effects3dscrollView"
+            android:layout_width="match_parent"
+            android:layout_height="0dp"
+            android:layout_weight="0.80"
+            >
+
+            <LinearLayout
+                android:id="@+id/effects3dlayout0"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="vertical" >
+            </LinearLayout>
+
+        </ScrollView>
+
+</LinearLayout>
diff --git a/src/main/res/layout/effects3dtab1.xml b/src/main/res/layout/effects3dtab1.xml
index 5ef4533..2bd4de2 100644
--- a/src/main/res/layout/effects3dtab1.xml
+++ b/src/main/res/layout/effects3dtab1.xml
@@ -19,7 +19,7 @@
                 />
 
             <TextView
-                android:id="@+id/textViewFragment"
+                android:id="@+id/textView1"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="@string/New"
diff --git a/src/main/res/layout/effects3dtab2.xml b/src/main/res/layout/effects3dtab2.xml
index 6dc81b2..1d57baf 100644
--- a/src/main/res/layout/effects3dtab2.xml
+++ b/src/main/res/layout/effects3dtab2.xml
@@ -19,7 +19,7 @@
                 />
 
             <TextView
-                android:id="@+id/textViewFragment"
+                android:id="@+id/textView2"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="@string/New"
diff --git a/src/main/res/layout/effects3dtab3.xml b/src/main/res/layout/effects3dtab3.xml
index ce79dc7..9608b29 100644
--- a/src/main/res/layout/effects3dtab3.xml
+++ b/src/main/res/layout/effects3dtab3.xml
@@ -19,7 +19,7 @@
                 />
 
             <TextView
-                android:id="@+id/textViewFragment"
+                android:id="@+id/textView3"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:text="@string/New"
diff --git a/src/main/res/layout/matrix3dlayout.xml b/src/main/res/layout/matrix3dlayout.xml
deleted file mode 100644
index 22beee0..0000000
--- a/src/main/res/layout/matrix3dlayout.xml
+++ /dev/null
@@ -1,72 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:orientation="vertical" >
-
-    <org.distorted.examples.matrix3d.Matrix3DSurfaceView
-        android:id="@+id/matrix3dSurfaceView"
-        android:layout_width="fill_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1" />
-
-    <LinearLayout
-        android:orientation="horizontal"
-        android:layout_width="match_parent"
-        android:layout_height="50dp"
-        android:layout_gravity="center">
-
-        <Button
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/Add"
-            android:id="@+id/buttonAdd"
-            android:onClick="newEffect"
-            />
-
-        <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:text="@string/New"
-            android:id="@+id/textView10"/>
-
-        <Spinner
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:id="@+id/matrix3dspinner"
-            android:layout_weight="0.5"/>
-
-        <Button
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:text="@string/reset"
-            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/matrix3dscrollView"
-        android:layout_width="match_parent"
-        android:layout_height="0dp"
-        android:layout_weight="0.82"
-        >
-
-        <LinearLayout
-            android:id="@+id/matrix3dlayout"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical" >
-        </LinearLayout>
-
-    </ScrollView>
-
-</LinearLayout>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index e490cbf..1d6c850 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -74,6 +74,7 @@
     <string name="oit">OIT</string>
     <string name="screen">Screen</string>
     <string name="framebuffer">Framebuffer</string>
+    <string name="matrixautomatic">Automatic Matrix Effects</string>
 
     <string name="quality0">Highest</string>
     <string name="quality1">High</string>
@@ -142,8 +143,6 @@
     <string name="example_cubes_subtitle">Tests the DistortedCubes render target.</string>
     <string name="example_quaternion">Quaternion</string>
     <string name="example_quaternion_subtitle">Random rotations using quaternions.</string>
-    <string name="example_matrix3d">Matrix Effects</string>
-    <string name="example_matrix3d_subtitle">Test results of Matrix effects on a 3D object.</string>
     <string name="example_effects3d">Generic Test</string>
     <string name="example_effects3d_subtitle">Apply any Effect to a 3D object.</string>
     <string name="example_plainmonalisa">SurfaceView</string>
