commit 3c70973c0a410a8e4fc894e8fa0fdb148ca6499d
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Tue Jun 13 13:04:47 2017 +0100

    Fix 'Bitmap Tree' APP. Now  28 out of 31 APPs work.

diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 8000bc0..381151c 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -30,7 +30,7 @@
         <activity android:name=".differentbitmaps.DifferentBitmapsActivity" />    
         <activity android:name=".effectqueue.EffectQueueActivity" />
         <activity android:name=".check.CheckActivity" />    
-        <activity android:name=".fbo.FBOActivity" />    
+        <activity android:name=".bitmaptree.BitmapTreeActivity" />
         <activity android:name=".starwars.StarWarsActivity" />      
         <activity android:name=".olimpic.OlimpicActivity" />  
         <activity android:name=".cubes.CubesActivity" />       
diff --git a/src/main/java/org/distorted/examples/TableOfContents.java b/src/main/java/org/distorted/examples/TableOfContents.java
index 0e41e7b..b2de6c6 100644
--- a/src/main/java/org/distorted/examples/TableOfContents.java
+++ b/src/main/java/org/distorted/examples/TableOfContents.java
@@ -50,7 +50,7 @@ import org.distorted.examples.differentbitmaps.DifferentBitmapsActivity;
 import org.distorted.examples.effectqueue.EffectQueueActivity;
 import org.distorted.examples.check.CheckActivity;
 import org.distorted.examples.bean.BeanActivity;
-import org.distorted.examples.fbo.FBOActivity;
+import org.distorted.examples.bitmaptree.BitmapTreeActivity;
 import org.distorted.examples.starwars.StarWarsActivity;
 import org.distorted.examples.cubes.CubesActivity;
 import org.distorted.examples.quaternion.QuaternionActivity;
@@ -216,10 +216,10 @@ public class TableOfContents extends ListActivity
    {
       final Map<String, Object> item = new HashMap<>();
       item.put(ITEM_IMAGE, R.drawable.icon_example_fbo);
-      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_fbo));
-      item.put(ITEM_SUBTITLE, getText(R.string.example_fbo_subtitle));
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_bitmaptree));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_bitmaptree_subtitle));
       data.add(item);
-      activityMapping.put(i++, FBOActivity.class);
+      activityMapping.put(i++, BitmapTreeActivity.class);
    }
       
    {
diff --git a/src/main/java/org/distorted/examples/bitmaptree/BitmapTreeActivity.java b/src/main/java/org/distorted/examples/bitmaptree/BitmapTreeActivity.java
new file mode 100644
index 0000000..a830e35
--- /dev/null
+++ b/src/main/java/org/distorted/examples/bitmaptree/BitmapTreeActivity.java
@@ -0,0 +1,125 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.bitmaptree;
+
+import org.distorted.examples.R;
+import org.distorted.library.main.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class BitmapTreeActivity extends Activity
+{
+    private boolean mDepth;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle savedState)
+      {
+      super.onCreate(savedState);
+      setContentView(R.layout.bitmaptreelayout);
+
+      if( savedState==null )
+        {
+        mDepth = true;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      BitmapTreeSurfaceView view = (BitmapTreeSurfaceView) this.findViewById(R.id.bitmaptreeSurfaceView);
+
+      view.onPause();
+      Distorted.onPause();
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      BitmapTreeSurfaceView view = (BitmapTreeSurfaceView) this.findViewById(R.id.bitmaptreeSurfaceView);
+
+      super.onResume();
+      view.onResume();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void DepthYes(View v)
+      {
+      BitmapTreeSurfaceView view = (BitmapTreeSurfaceView) this.findViewById(R.id.bitmaptreeSurfaceView);
+      BitmapTreeRenderer renderer = view.getRenderer();
+
+      renderer.setDepth(true);
+      mDepth = true;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void DepthNo(View v)
+      {
+      BitmapTreeSurfaceView view = (BitmapTreeSurfaceView) this.findViewById(R.id.bitmaptreeSurfaceView);
+      BitmapTreeRenderer renderer = view.getRenderer();
+
+      renderer.setDepth(false);
+      mDepth = false;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void onSaveInstanceState(Bundle savedInstanceState)
+      {
+      super.onSaveInstanceState(savedInstanceState);
+      savedInstanceState.putBoolean("depth", mDepth);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    @Override
+    public void onRestoreInstanceState(Bundle savedInstanceState)
+      {
+      super.onRestoreInstanceState(savedInstanceState);
+
+      mDepth = savedInstanceState.getBoolean("depth");
+
+      if(mDepth) DepthYes(null);
+      else       DepthNo(null);
+      }
+
+}
diff --git a/src/main/java/org/distorted/examples/bitmaptree/BitmapTreeRenderer.java b/src/main/java/org/distorted/examples/bitmaptree/BitmapTreeRenderer.java
new file mode 100644
index 0000000..127bf42
--- /dev/null
+++ b/src/main/java/org/distorted/examples/bitmaptree/BitmapTreeRenderer.java
@@ -0,0 +1,228 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.bitmaptree;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distorted.examples.R;
+
+import org.distorted.library.effect.EffectName;
+import org.distorted.library.effect.FragmentEffectChroma;
+import org.distorted.library.effect.MatrixEffectMove;
+import org.distorted.library.effect.MatrixEffectRotate;
+import org.distorted.library.effect.MatrixEffectScale;
+import org.distorted.library.effect.VertexEffectSink;
+import org.distorted.library.main.DistortedEffects;
+import org.distorted.library.main.DistortedFramebuffer;
+import org.distorted.library.main.DistortedNode;
+import org.distorted.library.main.DistortedScreen;
+import org.distorted.library.main.Distorted;
+import org.distorted.library.main.MeshCubes;
+import org.distorted.library.main.MeshFlat;
+import org.distorted.library.main.DistortedTexture;
+import org.distorted.library.type.Dynamic;
+import org.distorted.library.type.Dynamic1D;
+import org.distorted.library.type.Static1D;
+import org.distorted.library.type.Static3D;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES30;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class BitmapTreeRenderer implements GLSurfaceView.Renderer
+{
+   private GLSurfaceView mView;
+   private DistortedEffects mEffects;
+   private DistortedTexture mLisaTexture, mGridTexture;
+   private DistortedScreen mScreen;
+   private DistortedNode mRoot;
+   private MeshFlat mMeshFlat;
+   private MeshCubes mMeshCubes;
+   private int lisaHeight, lisaWidth;
+   private boolean mDepth;
+   private Static3D mScale, mMove;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   BitmapTreeRenderer(GLSurfaceView v)
+      {
+      mView   = v;
+      mDepth  = true;
+      mScale  = new Static3D(1,1,1);
+      mMove   = new Static3D(0,0,0);
+      Dynamic1D chromaDyn = new Dynamic1D(5000,0.0f);
+      chromaDyn.add(new Static1D(0.0f));
+      chromaDyn.add(new Static1D(0.8f));
+
+      mEffects= new DistortedEffects();
+      mEffects.apply(new MatrixEffectMove(mMove));
+      mEffects.apply(new MatrixEffectScale(mScale));
+      mEffects.apply(new FragmentEffectChroma(chromaDyn, new Static3D(0,0,1)));
+
+      mScreen = new DistortedScreen(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private void setDepthPriv()
+     {
+     if( mDepth ) mRoot.glEnable (GLES30.GL_DEPTH_TEST);
+     else         mRoot.glDisable(GLES30.GL_DEPTH_TEST);
+
+     mRoot.glDepthMask(mDepth);
+
+     // we can also, to save memory, delete/recreate
+     // the depth buffer each time. This is optional.
+     mRoot.enableDepthStencil(mDepth ? DistortedFramebuffer.DEPTH_NO_STENCIL:DistortedFramebuffer.NO_DEPTH_NO_STENCIL);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   void setDepth(boolean depth)
+      {
+      mDepth = depth;
+      if( mRoot!=null ) setDepthPriv();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   public void onDrawFrame(GL10 glUnused)
+      {
+      mScreen.render(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+   public void onSurfaceChanged(GL10 glUnused, int width, int height)
+      { 
+      if( (float)lisaHeight/lisaWidth > (float)height/width )
+        {
+        int w = (height*lisaWidth)/lisaHeight;
+        float factor = (float)height/lisaHeight;
+
+        mMove.set((width-w)/2,0,0);
+        mScale.set(factor,factor,factor);
+        }
+      else
+        {
+        int h = (width*lisaHeight)/lisaWidth;
+        float factor = (float)width/lisaWidth;
+
+        mMove.set(0,(height-h)/2,0);
+        mScale.set(factor,factor,factor);
+        }
+      
+      mScreen.resize(width, height);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
+      {
+      // TODO
+      // This appears to be needed in case we create the app anew with NO DEPTH
+      // (i.e. we set 'no depth' and then rotate screen). Investigate.
+      GLES30.glEnable(GLES30.GL_CULL_FACE);
+      GLES30.glCullFace(GLES30.GL_BACK);
+      GLES30.glFrontFace(GLES30.GL_CW);
+
+      InputStream is1 = mView.getContext().getResources().openRawResource(R.raw.monalisa);
+      InputStream is2 = mView.getContext().getResources().openRawResource(R.raw.grid);
+      
+      Bitmap bitmap1, bitmap2;
+       
+      try 
+        {
+        bitmap1 = BitmapFactory.decodeStream(is1);
+        bitmap2 = BitmapFactory.decodeStream(is2);
+        } 
+      finally 
+        {
+        try 
+          {
+          is1.close();
+          is2.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      lisaWidth     = bitmap1.getWidth();
+      lisaHeight    = bitmap1.getHeight();
+      int gridWidth = bitmap2.getWidth();
+      int gridHeight= bitmap2.getHeight();
+
+      if( mLisaTexture==null ) mLisaTexture = new DistortedTexture(lisaWidth,lisaHeight);
+      if( mGridTexture==null ) mGridTexture = new DistortedTexture(gridWidth,gridHeight);
+      mLisaTexture.setTexture(bitmap1);
+      mGridTexture.setTexture(bitmap2);
+      DistortedEffects gridEffects = new DistortedEffects();
+
+      final int GRID = 10;
+
+      if( mMeshFlat==null ) mMeshFlat = new MeshFlat(1,1);
+      if( mMeshCubes==null) mMeshCubes= new MeshCubes(GRID,GRID,1);
+
+      mRoot = new DistortedNode(mLisaTexture, mEffects, mMeshFlat);
+      mRoot.attach(mGridTexture,gridEffects,mMeshCubes);
+
+      setDepthPriv();
+
+      mScreen.detachAll();
+      mScreen.attach(mRoot);
+
+      float factor = lisaWidth/(2.0f*gridWidth);
+      MatrixEffectMove move = new MatrixEffectMove( new Static3D((lisaWidth-factor*gridWidth)/2,(lisaHeight-factor*gridHeight)/2, gridWidth/(2.0f*GRID)));
+      MatrixEffectScale scale = new MatrixEffectScale( new Static3D(factor,factor,factor) );
+      gridEffects.apply(move);
+      gridEffects.apply(scale);
+
+      Dynamic1D rotDyn = new Dynamic1D(12000,0.0f);
+      rotDyn.add(new Static1D(  0));
+      rotDyn.add(new Static1D(360));
+      rotDyn.setMode(Dynamic.MODE_JUMP);
+      MatrixEffectRotate rotate = new MatrixEffectRotate(rotDyn, new Static3D(1,0,0), new Static3D(gridWidth/2,gridHeight/2,gridWidth/(2*GRID)));
+      gridEffects.apply(rotate);
+
+      Dynamic1D sinkDyn = new Dynamic1D(3000,0.0f);
+      sinkDyn.add(new Static1D(1.0f));
+      sinkDyn.add(new Static1D(0.3f));
+      VertexEffectSink sink = new VertexEffectSink(sinkDyn, new Static3D(gridWidth/2,gridHeight/2, 0));
+      gridEffects.apply(sink);
+
+      DistortedEffects.enableEffect(EffectName.SINK);
+      DistortedEffects.enableEffect(EffectName.CHROMA);
+
+      try
+        {
+        Distorted.onCreate(mView.getContext());
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("BitmapTree", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distorted/examples/bitmaptree/BitmapTreeSurfaceView.java b/src/main/java/org/distorted/examples/bitmaptree/BitmapTreeSurfaceView.java
new file mode 100644
index 0000000..19577f6
--- /dev/null
+++ b/src/main/java/org/distorted/examples/bitmaptree/BitmapTreeSurfaceView.java
@@ -0,0 +1,52 @@
+///////////////////////////////////////////////////////////////////////////////////////////////////
+// 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.bitmaptree;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.util.AttributeSet;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class BitmapTreeSurfaceView extends GLSurfaceView
+{
+    private BitmapTreeRenderer mRenderer;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public BitmapTreeSurfaceView(Context context, AttributeSet attrs)
+      {
+      super(context, attrs);
+
+      if(!isInEditMode())
+        {
+        mRenderer = new BitmapTreeRenderer(this);
+        setRenderer(mRenderer);
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public BitmapTreeRenderer getRenderer()
+      {
+      return mRenderer;
+      }
+}
+
diff --git a/src/main/java/org/distorted/examples/fbo/FBOActivity.java b/src/main/java/org/distorted/examples/fbo/FBOActivity.java
deleted file mode 100644
index db64da0..0000000
--- a/src/main/java/org/distorted/examples/fbo/FBOActivity.java
+++ /dev/null
@@ -1,125 +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.fbo;
-
-import org.distorted.examples.R;
-import org.distorted.library.main.Distorted;
-
-import android.app.Activity;
-import android.os.Bundle;
-import android.view.View;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-public class FBOActivity extends Activity 
-{
-    private boolean mDepth;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    @Override
-    protected void onCreate(Bundle savedState)
-      {
-      super.onCreate(savedState);
-      setContentView(R.layout.fbolayout);
-
-      if( savedState==null )
-        {
-        mDepth = true;
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    @Override
-    protected void onPause() 
-      {
-      FBOSurfaceView view = (FBOSurfaceView) this.findViewById(R.id.fboSurfaceView);
-
-      view.onPause();
-      Distorted.onPause();
-      super.onPause();
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    @Override
-    protected void onResume() 
-      {
-      FBOSurfaceView view = (FBOSurfaceView) this.findViewById(R.id.fboSurfaceView);
-
-      super.onResume();
-      view.onResume();
-      }
-    
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-    @Override
-    protected void onDestroy() 
-      {
-      Distorted.onDestroy();  
-      super.onDestroy();
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void DepthYes(View v)
-      {
-      FBOSurfaceView view = (FBOSurfaceView) this.findViewById(R.id.fboSurfaceView);
-      FBORenderer renderer = view.getRenderer();
-
-      renderer.setDepth(true);
-      mDepth = true;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public void DepthNo(View v)
-      {
-      FBOSurfaceView view = (FBOSurfaceView) this.findViewById(R.id.fboSurfaceView);
-      FBORenderer renderer = view.getRenderer();
-
-      renderer.setDepth(false);
-      mDepth = false;
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public void onSaveInstanceState(Bundle savedInstanceState)
-      {
-      super.onSaveInstanceState(savedInstanceState);
-      savedInstanceState.putBoolean("depth", mDepth);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    @Override
-    public void onRestoreInstanceState(Bundle savedInstanceState)
-      {
-      super.onRestoreInstanceState(savedInstanceState);
-
-      mDepth = savedInstanceState.getBoolean("depth");
-
-      if(mDepth) DepthYes(null);
-      else       DepthNo(null);
-      }
-
-}
diff --git a/src/main/java/org/distorted/examples/fbo/FBORenderer.java b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
deleted file mode 100644
index ac834f8..0000000
--- a/src/main/java/org/distorted/examples/fbo/FBORenderer.java
+++ /dev/null
@@ -1,227 +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.fbo;
-
-import java.io.IOException;
-import java.io.InputStream;
-
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
-
-import org.distorted.examples.R;
-
-import org.distorted.library.effect.EffectName;
-import org.distorted.library.effect.FragmentEffectChroma;
-import org.distorted.library.effect.MatrixEffectMove;
-import org.distorted.library.effect.MatrixEffectRotate;
-import org.distorted.library.effect.MatrixEffectScale;
-import org.distorted.library.effect.VertexEffectSink;
-import org.distorted.library.main.DistortedEffects;
-import org.distorted.library.main.DistortedFramebuffer;
-import org.distorted.library.main.DistortedNode;
-import org.distorted.library.main.DistortedScreen;
-import org.distorted.library.main.Distorted;
-import org.distorted.library.main.MeshCubes;
-import org.distorted.library.main.MeshFlat;
-import org.distorted.library.main.DistortedTexture;
-import org.distorted.library.type.Dynamic;
-import org.distorted.library.type.Dynamic1D;
-import org.distorted.library.type.Static1D;
-import org.distorted.library.type.Static3D;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.opengl.GLES30;
-import android.opengl.GLSurfaceView;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class FBORenderer implements GLSurfaceView.Renderer 
-{
-   private GLSurfaceView mView;
-   private DistortedEffects mEffects;
-   private DistortedTexture mLisaTexture, mGridTexture;
-   private DistortedScreen mScreen;
-   private DistortedNode mRoot;
-   private MeshFlat mMeshFlat;
-   private MeshCubes mMeshCubes;
-   private int lisaHeight, lisaWidth;
-   private boolean mDepth;
-   private Static3D mScale, mMove;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   FBORenderer(GLSurfaceView v)
-      {
-      mView   = v;
-      mDepth  = true;
-      mEffects= new DistortedEffects();
-      mScale  = new Static3D(1,1,1);
-      mMove   = new Static3D(0,0,0);
-      mEffects.apply(new MatrixEffectMove(mMove));
-      mEffects.apply(new MatrixEffectScale(mScale));
-      mScreen = new DistortedScreen(mView);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   private void setDepthPriv()
-     {
-     if( mDepth ) mRoot.glEnable (GLES30.GL_DEPTH_TEST);
-     else         mRoot.glDisable(GLES30.GL_DEPTH_TEST);
-
-     mRoot.glDepthMask(mDepth);
-
-     // we can also, to save memory, delete/recreate
-     // the depth buffer each time. This is optional.
-     mRoot.enableDepthStencil(mDepth ? DistortedFramebuffer.DEPTH_NO_STENCIL:DistortedFramebuffer.NO_DEPTH_NO_STENCIL);
-     }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-   void setDepth(boolean depth)
-      {
-      mDepth = depth;
-      if( mRoot!=null ) setDepthPriv();
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-   
-   public void onDrawFrame(GL10 glUnused)
-      {
-      mScreen.render(System.currentTimeMillis());
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-   public void onSurfaceChanged(GL10 glUnused, int width, int height)
-      { 
-      if( (float)lisaHeight/lisaWidth > (float)height/width )
-        {
-        int w = (height*lisaWidth)/lisaHeight;
-        float factor = (float)height/lisaHeight;
-
-        mMove.set((width-w)/2,0,0);
-        mScale.set(factor,factor,factor);
-        }
-      else
-        {
-        int h = (width*lisaHeight)/lisaWidth;
-        float factor = (float)width/lisaWidth;
-
-        mMove.set(0,(height-h)/2,0);
-        mScale.set(factor,factor,factor);
-        }
-      
-      mScreen.resize(width, height);
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-    
-   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
-      {
-      GLES30.glEnable(GLES30.GL_CULL_FACE);
-      GLES30.glCullFace(GLES30.GL_BACK);
-      GLES30.glFrontFace(GLES30.GL_CW);
-
-      InputStream is1 = mView.getContext().getResources().openRawResource(R.raw.monalisa);
-      InputStream is2 = mView.getContext().getResources().openRawResource(R.raw.grid);
-      
-      Bitmap bitmap1, bitmap2;
-       
-      try 
-        {
-        bitmap1 = BitmapFactory.decodeStream(is1);
-        bitmap2 = BitmapFactory.decodeStream(is2);
-        } 
-      finally 
-        {
-        try 
-          {
-          is1.close();
-          is2.close();
-          } 
-        catch(IOException e) { }
-        }  
-      
-      lisaWidth     = bitmap1.getWidth();
-      lisaHeight    = bitmap1.getHeight();
-      int gridWidth = bitmap2.getWidth();
-      int gridHeight= bitmap2.getHeight();
-
-      if( mLisaTexture==null ) mLisaTexture = new DistortedTexture(lisaWidth,lisaHeight);
-      if( mGridTexture==null ) mGridTexture = new DistortedTexture(gridWidth,gridHeight);
-      mLisaTexture.setTexture(bitmap1);
-      mGridTexture.setTexture(bitmap2);
-      DistortedEffects gridEffects = new DistortedEffects();
-
-      mEffects.abortAllEffects();
-
-      final int GRID = 10;
-
-      if( mMeshFlat==null ) mMeshFlat = new MeshFlat(1,1);
-      if( mMeshCubes==null) mMeshCubes= new MeshCubes(GRID,GRID,1);
-
-      mRoot = new DistortedNode(mLisaTexture, mEffects, mMeshFlat);
-      mRoot.attach(mGridTexture,gridEffects,mMeshCubes);
-
-      setDepthPriv();
-
-      mScreen.detachAll();
-      mScreen.attach(mRoot);
-
-      float factor = lisaWidth/(2.0f*gridWidth);
-      MatrixEffectMove move = new MatrixEffectMove( new Static3D((lisaWidth-factor*gridWidth)/2,(lisaHeight-factor*gridHeight)/2, gridWidth/(2.0f*GRID)));
-      MatrixEffectScale scale = new MatrixEffectScale( new Static3D(factor,factor,factor) );
-      gridEffects.apply(move);
-      gridEffects.apply(scale);
-
-      Dynamic1D rotDyn = new Dynamic1D(12000,0.0f);
-      rotDyn.add(new Static1D(  0));
-      rotDyn.add(new Static1D(360));
-      rotDyn.setMode(Dynamic.MODE_JUMP);
-      MatrixEffectRotate rotate = new MatrixEffectRotate(rotDyn, new Static3D(1,0,0), new Static3D(gridWidth/2,gridHeight/2,gridWidth/(2*GRID)));
-      gridEffects.apply(rotate);
-
-      Dynamic1D sinkDyn = new Dynamic1D(3000,0.0f);
-      sinkDyn.add(new Static1D(1.0f));
-      sinkDyn.add(new Static1D(0.3f));
-      VertexEffectSink sink = new VertexEffectSink(sinkDyn, new Static3D(gridWidth/2,gridHeight/2, 0));
-      gridEffects.apply(sink);
-
-      Dynamic1D chromaDyn = new Dynamic1D(5000,0.0f);
-      chromaDyn.add(new Static1D(0.0f));
-      chromaDyn.add(new Static1D(1.0f));
-      FragmentEffectChroma chroma = new FragmentEffectChroma(chromaDyn, new Static3D(0,0,1));
-      mEffects.apply(chroma);
-
-      DistortedEffects.enableEffect(EffectName.SINK);
-      DistortedEffects.enableEffect(EffectName.CHROMA);
-
-      try
-        {
-        Distorted.onCreate(mView.getContext());
-        }
-      catch(Exception ex)
-        {
-        android.util.Log.e("FBO", ex.getMessage() );
-        }
-      }
-}
diff --git a/src/main/java/org/distorted/examples/fbo/FBOSurfaceView.java b/src/main/java/org/distorted/examples/fbo/FBOSurfaceView.java
deleted file mode 100644
index c346d89..0000000
--- a/src/main/java/org/distorted/examples/fbo/FBOSurfaceView.java
+++ /dev/null
@@ -1,52 +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.fbo;
-
-import android.content.Context;
-import android.opengl.GLSurfaceView;
-import android.util.AttributeSet;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-class FBOSurfaceView extends GLSurfaceView 
-{
-    private FBORenderer mRenderer;
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-   
-    public FBOSurfaceView(Context context, AttributeSet attrs)
-      {
-      super(context, attrs);
-
-      if(!isInEditMode())
-        {
-        mRenderer = new FBORenderer(this);
-        setRenderer(mRenderer);
-        }
-      }
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-    public FBORenderer getRenderer()
-      {
-      return mRenderer;
-      }
-}
-
diff --git a/src/main/res/layout/bitmaptreelayout.xml b/src/main/res/layout/bitmaptreelayout.xml
new file mode 100644
index 0000000..c3c80dc
--- /dev/null
+++ b/src/main/res/layout/bitmaptreelayout.xml
@@ -0,0 +1,45 @@
+<?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.bitmaptree.BitmapTreeSurfaceView
+        android:id="@+id/bitmaptreeSurfaceView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <LinearLayout
+        android:id="@+id/linearLayout1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center|fill_horizontal"
+        android:orientation="vertical">
+
+        <RadioGroup
+            android:id="@+id/radioGroup1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal">
+
+            <RadioButton
+                android:id="@+id/depthYesButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:checked="true"
+                android:onClick="DepthYes"
+                android:text="@string/DepthYes"/>
+
+            <RadioButton
+                android:id="@+id/depthNoButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="DepthNo"
+                android:text="@string/DepthNo"/>
+
+        </RadioGroup>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/src/main/res/layout/fbolayout.xml b/src/main/res/layout/fbolayout.xml
deleted file mode 100644
index fd1afe1..0000000
--- a/src/main/res/layout/fbolayout.xml
+++ /dev/null
@@ -1,45 +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.fbo.FBOSurfaceView
-        android:id="@+id/fboSurfaceView"
-        android:layout_width="fill_parent"
-        android:layout_height="0dp"
-        android:layout_weight="1" />
-
-    <LinearLayout
-        android:id="@+id/linearLayout1"
-        android:layout_width="fill_parent"
-        android:layout_height="wrap_content"
-        android:gravity="center|fill_horizontal"
-        android:orientation="vertical">
-
-        <RadioGroup
-            android:id="@+id/radioGroup1"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="horizontal">
-
-            <RadioButton
-                android:id="@+id/depthYesButton"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:checked="true"
-                android:onClick="DepthYes"
-                android:text="@string/DepthYes"/>
-
-            <RadioButton
-                android:id="@+id/depthNoButton"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:onClick="DepthNo"
-                android:text="@string/DepthNo"/>
-
-        </RadioGroup>
-
-    </LinearLayout>
-
-</LinearLayout>
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
index 5649caf..7383b44 100644
--- a/src/main/res/values/strings.xml
+++ b/src/main/res/values/strings.xml
@@ -113,8 +113,8 @@
     <string name="example_effectqueue_subtitle">Add, remove and list all effects currently acting on a Bitmap.</string>
     <string name="example_check">Check</string>  
     <string name="example_check_subtitle">Check the maximum number of effects (separately for vertex and fragment shaders) we can apply to a single bitmap.</string>
-    <string name="example_fbo">Bitmap Tree</string>  
-    <string name="example_fbo_subtitle">Render one bitmap on top of another.</string>
+    <string name="example_bitmaptree">Bitmap Tree</string>
+    <string name="example_bitmaptree_subtitle">Render one bitmap on top of another.</string>
     <string name="example_starwars">Star Wars</string>  
     <string name="example_starwars_subtitle">Shows how to create the opening crawl from Star Wars Episode IV.</string>
     <string name="example_olimpic">Olimpic Rings</string>  
