commit e8b6aa957edc8609da8072aae335ce57a036b903
Author: Leszek Koltunski <leszek@distoretedandroid.org>
Date:   Mon Dec 12 16:47:53 2016 +0000

    Major change in API: separate the GRID from DistortedObject; completely remove classes derived from DistortedObject.

diff --git a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
index 21d9333..63e66f6 100644
--- a/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
+++ b/src/main/java/org/distorted/examples/aroundtheworld/AroundTheWorldRenderer.java
@@ -26,7 +26,7 @@ import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Static3D;
@@ -43,6 +43,7 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer
 {
    private GLSurfaceView mView;
    private DistortedObject mObject;
+   private DistortedBitmapGrid mGrid;
    private AroundTheWorldEffectsManager mEffects;
    private int mObjWidth, mObjHeight;
 
@@ -69,7 +70,7 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer
    public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mObject.draw(System.currentTimeMillis());
+      mObject.draw(System.currentTimeMillis(), mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -118,14 +119,16 @@ class AroundTheWorldRenderer implements GLSurfaceView.Renderer
         catch(IOException e) { }
         }
 
-      mObject = new DistortedBitmap(bitmap.getWidth(),bitmap.getHeight(),30);
 
       mObjWidth = mObject.getWidth();
       mObjHeight= mObject.getHeight();
 
-      mObject.setBitmap(bitmap);
+      mObject = new DistortedObject(mObjWidth,mObjHeight,1);
+      mObject.setTexture(bitmap);
       mEffects.apply(mObject);
 
+      mGrid = new DistortedBitmapGrid(30,30*mObjHeight/mObjWidth);
+
       try
         {
         Distorted.onSurfaceCreated(mView.getContext());
diff --git a/src/main/java/org/distorted/examples/bean/BeanRenderer.java b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
index c2290c9..6577e90 100644
--- a/src/main/java/org/distorted/examples/bean/BeanRenderer.java
+++ b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
@@ -29,7 +29,8 @@ import org.distorted.examples.R;
 
 import org.distorted.library.EffectTypes;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
@@ -44,7 +45,8 @@ import android.opengl.GLSurfaceView;
 class BeanRenderer implements GLSurfaceView.Renderer 
 {
    private GLSurfaceView mView;
-   private DistortedBitmap mBean;
+   private DistortedObject mBean;
+   private DistortedBitmapGrid mGrid;
    private Static3D pLeft, pRight;
    private Dynamic3D dLeft, dRight;
    private Static4D rLeft, rRight;
@@ -88,7 +90,7 @@ class BeanRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mBean.draw(System.currentTimeMillis());
+      mBean.draw(System.currentTimeMillis(), mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -142,10 +144,13 @@ class BeanRenderer implements GLSurfaceView.Renderer
       bmpHeight = bitmap.getHeight();
       bmpWidth  = bitmap.getWidth();
       
-      mBean = new DistortedBitmap(bitmap, 25);
+      mBean = new DistortedObject(bmpWidth, bmpHeight, 1);
+      mBean.setTexture(bitmap);
       mBean.distort(dLeft , pLeft , rLeft );
       mBean.distort(dRight, pRight, rRight);
-      
+
+      mGrid = new DistortedBitmapGrid(25,25*bmpHeight/bmpWidth);
+
       try
         {
         Distorted.onSurfaceCreated(mView.getContext());
diff --git a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
index 9119ace..5475650 100644
--- a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
+++ b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
@@ -27,7 +27,8 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic1D;
 import org.distorted.library.type.Dynamic3D;
@@ -45,7 +46,8 @@ import android.opengl.GLSurfaceView;
 class CatAndDogRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
-    private DistortedBitmap catanddog;
+    private DistortedObject mObject;
+    private DistortedBitmapGrid mGrid;
     private Static4D chromaRegion, alphaRegion;
     private int bmpHeight, bmpWidth;
 
@@ -64,7 +66,7 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      catanddog.draw(System.currentTimeMillis());
+      mObject.draw(System.currentTimeMillis(), mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -91,20 +93,23 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
       
       bmpHeight = bitmap.getHeight();
       bmpWidth  = bitmap.getWidth();
-      
-      catanddog = new DistortedBitmap(bitmap, 30);
+
+      mGrid = new DistortedBitmapGrid(1,1);  // no vertex effects, grid can be a (1x1) quad.
+
+      mObject = new DistortedObject(bmpWidth,bmpHeight,1);
+      mObject.setTexture(bitmap);
 
       Dynamic1D chromaDyn = new Dynamic1D(3000,0.0f);
       chromaDyn.add(new Static1D(1));
       chromaDyn.add(new Static1D(0));
 
-      catanddog.chroma(chromaDyn, new Static3D(1,0,0), chromaRegion ,true);
+      mObject.chroma(chromaDyn, new Static3D(1,0,0), chromaRegion ,true);
 
       Dynamic1D alphaDyn = new Dynamic1D(3000,0.0f);
       alphaDyn.add(new Static1D(1));
       alphaDyn.add(new Static1D(0));
 
-      catanddog.alpha( alphaDyn, alphaRegion, false );
+      mObject.alpha( alphaDyn, alphaRegion, false );
       
       try
         {
@@ -134,11 +139,11 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
       diRotate.add(new Static1D(  0));
       diRotate.add(new Static1D(360));
       
-      catanddog.abortEffects(EffectTypes.MATRIX);
+      mObject.abortEffects(EffectTypes.MATRIX);
 
-      catanddog.move(diMove);
-      catanddog.scale(diScale);
-      catanddog.rotate( diRotate, new Static3D(0,0,1), new Static3D(bmpWidth/2,bmpHeight/2,0) );
+      mObject.move(diMove);
+      mObject.scale(diScale);
+      mObject.rotate( diRotate, new Static3D(0,0,1), new Static3D(bmpWidth/2,bmpHeight/2,0) );
 
       Distorted.onSurfaceChanged(width, height); 
       }
diff --git a/src/main/java/org/distorted/examples/check/CheckRenderer.java b/src/main/java/org/distorted/examples/check/CheckRenderer.java
index cc58b3d..e8809f4 100644
--- a/src/main/java/org/distorted/examples/check/CheckRenderer.java
+++ b/src/main/java/org/distorted/examples/check/CheckRenderer.java
@@ -28,15 +28,14 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic3D;
 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.Dynamic1D;
-import org.distorted.library.type.Dynamic2D;
 
 import android.app.AlertDialog;
 import android.content.Context;
@@ -55,7 +54,8 @@ class CheckRenderer implements GLSurfaceView.Renderer
     private static String compilationTitle;
 
     private GLSurfaceView mView;
-    private DistortedBitmap mSuccess;
+    private DistortedObject mSuccess;
+    private DistortedBitmapGrid mGrid;
     private int bmpHeight, bmpWidth;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -75,7 +75,7 @@ class CheckRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mSuccess.draw(System.currentTimeMillis());
+      mSuccess.draw(System.currentTimeMillis(), mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -126,11 +126,13 @@ class CheckRenderer implements GLSurfaceView.Renderer
         catch(IOException e) { }
         }
 
-      mSuccess = new DistortedBitmap(bitmap, 30);
-
       bmpHeight = bitmap.getHeight();
       bmpWidth  = bitmap.getWidth();
 
+      mSuccess = new DistortedObject(bmpWidth,bmpHeight,1);
+      mSuccess.setTexture(bitmap);
+      mGrid = new DistortedBitmapGrid(30,30*bmpHeight/bmpWidth);
+
       // Try adding 2 Vertex Effects to the Bitmap.
       // This will fail if we have set maxVertexEffects to something < 2.
       //
diff --git a/src/main/java/org/distorted/examples/cubes/CubesActivity.java b/src/main/java/org/distorted/examples/cubes/CubesActivity.java
index 6c9ea03..baf64a0 100644
--- a/src/main/java/org/distorted/examples/cubes/CubesActivity.java
+++ b/src/main/java/org/distorted/examples/cubes/CubesActivity.java
@@ -21,8 +21,9 @@ package org.distorted.examples.cubes;
 
 import org.distorted.library.Distorted;
 import org.distorted.examples.R;
-import org.distorted.library.DistortedCubes;
 import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedObjectGrid;
+import org.distorted.library.DistortedCubesGrid;
 
 import android.app.Activity;
 import android.opengl.GLSurfaceView;
@@ -48,6 +49,7 @@ public class CubesActivity extends Activity implements View.OnClickListener
     private LinearLayout mLay;
     private boolean[] mShape;
     private DistortedObject mObject;
+    private DistortedObjectGrid mGrid;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
@@ -197,7 +199,8 @@ public class CubesActivity extends Activity implements View.OnClickListener
       for(int i=0; i<mNumRows*mNumCols; i++)
         str += mShape[i] ? "1" : "0";
 
-      mObject = new DistortedCubes(mNumCols, str, 10);
+      mGrid = new DistortedCubesGrid(mNumCols, str, false);
+      mObject = new DistortedObject(mNumCols,mNumRows,1);
 
       setContentView(R.layout.cubeslayout);
       }
@@ -208,4 +211,11 @@ public class CubesActivity extends Activity implements View.OnClickListener
       {
       return mObject;
       }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public DistortedObjectGrid getGrid()
+      {
+      return mGrid;
+      }
 }
diff --git a/src/main/java/org/distorted/examples/cubes/CubesRenderer.java b/src/main/java/org/distorted/examples/cubes/CubesRenderer.java
index f93111d..abc5331 100644
--- a/src/main/java/org/distorted/examples/cubes/CubesRenderer.java
+++ b/src/main/java/org/distorted/examples/cubes/CubesRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedObjectGrid;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.DynamicQuat;
 import org.distorted.library.type.Static4D;
@@ -45,6 +46,7 @@ class CubesRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedObject mObject;
+    private DistortedObjectGrid mGrid;
     private int mObjWidth, mObjHeight;
 
     private DynamicQuat mQuatInt1, mQuatInt2;
@@ -58,7 +60,10 @@ class CubesRenderer implements GLSurfaceView.Renderer
       {
       mView = v;
 
-      mObject = ((CubesActivity)v.getContext()).getObject();
+      CubesActivity act = (CubesActivity)v.getContext();
+
+      mObject = act.getObject();
+      mGrid   = act.getGrid();
 
       mObjWidth = mObject.getWidth();
       mObjHeight= mObject.getHeight();
@@ -78,7 +83,7 @@ class CubesRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mObject.draw(System.currentTimeMillis());
+      mObject.draw(System.currentTimeMillis(),mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -131,7 +136,7 @@ class CubesRenderer implements GLSurfaceView.Renderer
         catch(IOException e) { }
         }  
       
-      mObject.setBitmap(bitmap);
+      mObject.setTexture(bitmap);
       
       try
         {
diff --git a/src/main/java/org/distorted/examples/deform/DeformRenderer.java b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
index 1aea7a0..fb58274 100644
--- a/src/main/java/org/distorted/examples/deform/DeformRenderer.java
+++ b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
@@ -23,7 +23,10 @@ import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedObjectGrid;
+import org.distorted.library.DistortedBitmapGrid;
+
 import org.distorted.library.EffectNames;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic3D;
@@ -41,13 +44,13 @@ import android.opengl.GLSurfaceView;
 
 class DeformRenderer implements GLSurfaceView.Renderer 
 {
-   private static final int NUM_VECTORS = 8;
-   private static final int NUM_LINES = 10;
-   private static final int NUM_FRAMES =10;
+   private static final int NUM_VECTORS =  8;
+   private static final int NUM_LINES   = 10;
+   private static final int NUM_FRAMES  = 10;
 
    private GLSurfaceView mView;
-   private DistortedBitmap fps;
-   private DistortedBitmap stretch;
+   private DistortedObject fps, stretch;
+   private DistortedObjectGrid fpsGrid, stretchGrid;
    private Static3D touchPoint;
 
    private Dynamic3D mReleasedDistortDynamic;
@@ -169,15 +172,15 @@ class DeformRenderer implements GLSurfaceView.Renderer
     
       long time = System.currentTimeMillis();
       
-      stretch.draw(time);
+      stretch.draw(time,stretchGrid);
       
       mPaint.setColor(0xffffffff);
       fpsCanvas.drawRect(0, 0, fpsW, fpsH, mPaint);
       mPaint.setColor(0xff000000);
       fpsCanvas.drawText(fpsString, fpsW/2, 5*fpsH/6, mPaint);
       
-      fps.setBitmap(fpsBitmap);
-      fps.draw(time);
+      fps.setTexture(fpsBitmap);
+      fps.draw(time,fpsGrid);
       
       computeFPS(time);
       }
@@ -193,7 +196,7 @@ class DeformRenderer implements GLSurfaceView.Renderer
 
       Distorted.onSurfaceChanged(width, height);
       
-      if( bitmapCreated==false )
+      if( !bitmapCreated )
         {
         createBitmap(scrWidth/2,scrHeight/2);
         stretch.move( new Static3D(scrWidth/4,scrHeight/4,0) );
@@ -231,7 +234,8 @@ class DeformRenderer implements GLSurfaceView.Renderer
       Canvas stretchCanvas;   
       
       mPaint = new Paint();
-      stretch = new DistortedBitmap(w,h, 50);   
+      stretch = new DistortedObject(w,h,1);
+      stretchGrid = new DistortedBitmapGrid(50,50*h/w);
       Bitmap stretchBitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
       stretchCanvas = new Canvas(stretchBitmap);
       
@@ -254,12 +258,14 @@ class DeformRenderer implements GLSurfaceView.Renderer
         
       touchPoint= new Static3D(0,0,0);
         
-      fps = new DistortedBitmap( fpsW, fpsH, 2);
+      fps = new DistortedObject( fpsW, fpsH, 1);
+      fpsGrid = new DistortedBitmapGrid(1,1);
+
       fpsBitmap = Bitmap.createBitmap(fpsW,fpsH, Bitmap.Config.ARGB_8888);
       fpsCanvas = new Canvas(fpsBitmap);
         
-      stretch.setBitmap(stretchBitmap);
-      fps.setBitmap(fpsBitmap);
+      stretch.setTexture(stretchBitmap);
+      fps.setTexture(fpsBitmap);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
index dd0280b..0bb0f35 100644
--- a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
+++ b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
@@ -28,11 +28,11 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Static1D;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
@@ -48,7 +48,8 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
    private static final int NUM = 3;
    
    private GLSurfaceView mView;
-   private DistortedBitmap[] bmp;
+   private DistortedObject[] mObj;
+   private DistortedBitmapGrid mGrid;
    private Static3D mPoint;
    private Dynamic3D dDistort;
    private int bmpHeight, bmpWidth;
@@ -97,7 +98,7 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
       
       long time = System.currentTimeMillis();
       
-      for(int i=NUM-1; i>=0; i--) bmp[i].draw(time); 
+      for(int i=NUM-1; i>=0; i--) mObj[i].draw(time, mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -106,7 +107,7 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
       {  
       for(int i=NUM-1; i>=0; i--) 
         {   
-        bmp[i].abortEffects(EffectTypes.MATRIX);
+        mObj[i].abortEffects(EffectTypes.MATRIX);
         }
       
       if( (float)bmpHeight/(NUM*bmpWidth) > (float)height/width )
@@ -116,8 +117,8 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
 
         for(int i=NUM-1; i>=0; i--) 
           {
-          bmp[i].move( new Static3D((width-NUM*w)/2 +i*w ,0,0) );
-          bmp[i].scale(factor);
+          mObj[i].move( new Static3D((width-NUM*w)/2 +i*w ,0,0) );
+          mObj[i].scale(factor);
           }
         }
       else
@@ -128,8 +129,8 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
 
         for(int i=NUM-1; i>=0; i--) 
           {
-          bmp[i].move( new Static3D(i*w,(height-h)/2,0) );
-          bmp[i].scale(factor);
+          mObj[i].move( new Static3D(i*w,(height-h)/2,0) );
+          mObj[i].scale(factor);
           }
         }
          
@@ -150,18 +151,20 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
       bmpWidth  = bitmap0.getWidth();
       
       // create NUM DistortedBitmaps with shared effects
-      bmp = new DistortedBitmap[NUM];
-      bmp[0] = new DistortedBitmap(bmpWidth, bmpHeight, 30);
+      mObj = new DistortedObject[NUM];
+      mObj[0] = new DistortedObject(bmpWidth, bmpHeight, 1);
       for(int i=1; i<NUM; i++) 
-      bmp[i] = new DistortedBitmap(bmp[0], Distorted.CLONE_VERTEX|Distorted.CLONE_FRAGMENT);
+        mObj[i] = new DistortedObject(mObj[0], Distorted.CLONE_VERTEX|Distorted.CLONE_FRAGMENT);
       
-      bmp[0].setBitmap(bitmap0);
-      bmp[1].setBitmap(bitmap1);
-      bmp[2].setBitmap(bitmap2);
+      mObj[0].setTexture(bitmap0);
+      mObj[1].setTexture(bitmap1);
+      mObj[2].setTexture(bitmap2);
          
-      bmp[0].sink( new Static1D(8), mPoint, new Static4D(0,0,80,80));
-      bmp[0].distort(dDistort,mPoint);
-      
+      mObj[0].sink( new Static1D(8), mPoint, new Static4D(0,0,80,80));
+      mObj[0].distort(dDistort,mPoint);
+
+      mGrid = new DistortedBitmapGrid(30,30*bmpHeight/bmpWidth);
+
       try
         {
         Distorted.onSurfaceCreated(mView.getContext());
diff --git a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
index 173c773..3af2563 100644
--- a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
@@ -28,12 +28,12 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic1D;
 import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Static1D;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
@@ -49,7 +49,8 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
    private static final int NUM = 3;
    
    private GLSurfaceView mView;
-   private DistortedBitmap[] bmp;
+   private DistortedObject[] mObj;
+   private DistortedBitmapGrid mGrid;
    private Static3D pLeft, pRight, pNose1;
    private Static4D RegionEye;
    private Dynamic3D mDI;
@@ -61,12 +62,12 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
       {     
       mView = v;
       
-      // bmp[0] effects
+      // mObj[0] effects
       pLeft = new Static3D(214, 206, 0);
       pRight= new Static3D(390, 212, 0);
       RegionEye = new Static4D(0,0,60,60);
       
-      // bmp[1] effects
+      // mObj[1] effects
       mDI = new Dynamic3D(1000,0.0f);
       mDI.add(new Static3D( 50,0,0));
       mDI.add(new Static3D(-50,0,0));
@@ -83,7 +84,7 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
       
      long time = System.currentTimeMillis();
    
-     for(int i=NUM-1; i>=0; i--) bmp[i].draw(time);
+     for(int i=NUM-1; i>=0; i--) mObj[i].draw(time, mGrid);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -92,7 +93,7 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
      {
      for(int i=NUM-1; i>=0; i--)
        {
-       bmp[i].abortEffects(EffectTypes.MATRIX);
+       mObj[i].abortEffects(EffectTypes.MATRIX);
        }
       
      if( (float)bmpHeight/(NUM*bmpWidth) > (float)height/width )
@@ -102,8 +103,8 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
 
        for(int i=NUM-1; i>=0; i--)
          {
-         bmp[i].move( new Static3D((width-NUM*w)/2 +i*w , 0, 0) );
-         bmp[i].scale(factor);
+         mObj[i].move( new Static3D((width-NUM*w)/2 +i*w , 0, 0) );
+         mObj[i].scale(factor);
          }
        }
      else
@@ -114,8 +115,8 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
 
        for(int i=NUM-1; i>=0; i--)
          {
-         bmp[i].move( new Static3D(i*w, (height-h)/2, 0) );
-         bmp[i].scale(factor);
+         mObj[i].move( new Static3D(i*w, (height-h)/2, 0) );
+         mObj[i].scale(factor);
          }
        }
        
@@ -146,28 +147,30 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
       
      bmpHeight = bitmap.getHeight();
      bmpWidth  = bitmap.getWidth();
+
+     mGrid = new DistortedBitmapGrid(30,30*bmpHeight/bmpWidth);
+
+     mObj = new DistortedObject[NUM];
+     mObj[0] = new DistortedObject(bmpWidth, bmpHeight, 1);
       
-     bmp = new DistortedBitmap[NUM];
-     bmp[0] = new DistortedBitmap(bmpWidth, bmpHeight, 30);
-      
-     for(int i=1; i<NUM; i++) bmp[i] = new DistortedBitmap(bmp[0], Distorted.CLONE_BITMAP);
+     for(int i=1; i<NUM; i++) mObj[i] = new DistortedObject(mObj[0], Distorted.CLONE_BITMAP);
       
      // setting the bitmap once is enough; others are cloned!
-     bmp[0].setBitmap(bitmap);
+     mObj[0].setTexture(bitmap);
 
      Dynamic1D sink = new Dynamic1D(2000,0.0f);
      sink.add(new Static1D( 1));
      sink.add(new Static1D(10));
 
-     bmp[0].sink(sink, pLeft, RegionEye);
-     bmp[0].sink(sink, pRight,RegionEye);
-     bmp[1].distort(mDI, pNose1);
+     mObj[0].sink(sink, pLeft, RegionEye);
+     mObj[0].sink(sink, pRight,RegionEye);
+     mObj[1].distort(mDI, pNose1);
 
      Dynamic1D chromaDyn = new Dynamic1D(3000,0.0f);
      chromaDyn.add(new Static1D(0));
      chromaDyn.add(new Static1D(1));
 
-     bmp[2].chroma(chromaDyn, new Static3D(0,1,0) );
+     mObj[2].chroma(chromaDyn, new Static3D(0,1,0) );
       
      try
        {
diff --git a/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java b/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
index c69147c..d9b1d65 100644
--- a/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
+++ b/src/main/java/org/distorted/examples/dynamic/DynamicRenderer.java
@@ -29,7 +29,8 @@ import android.graphics.Paint.Style;
 import android.opengl.GLES20;
 import android.opengl.GLSurfaceView;
 
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.Distorted;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -37,7 +38,8 @@ import org.distorted.library.Distorted;
 class DynamicRenderer implements GLSurfaceView.Renderer
    {  
    private DynamicSurfaceView mView;
-   private DistortedBitmap mBackground;
+   private DistortedObject mBackground;
+   private DistortedBitmapGrid mGrid;
    private Canvas mCanvas;
    private Bitmap mBitmap;
    private Paint mPaint;
@@ -78,9 +80,10 @@ class DynamicRenderer implements GLSurfaceView.Renderer
      texW = width;
      texH = height;
 
-     mBackground = new DistortedBitmap(texW,texH, 2);
-     mBitmap = Bitmap.createBitmap(texW,texH, Bitmap.Config.ARGB_8888);
-     mCanvas = new Canvas(mBitmap);
+     mGrid       = new DistortedBitmapGrid(1,1);
+     mBackground = new DistortedObject(texW,texH,1);
+     mBitmap     = Bitmap.createBitmap(texW,texH, Bitmap.Config.ARGB_8888);
+     mCanvas     = new Canvas(mBitmap);
 
      Distorted.onSurfaceChanged(texW,texH);
      mView.onSurfaceChanged(texW,texH);
@@ -96,8 +99,8 @@ class DynamicRenderer implements GLSurfaceView.Renderer
       
      mCanvas.drawRect(0, 0, texW, texH, mPaint);
      mView.drawCurve(mCanvas,time);
-     mBackground.setBitmap(mBitmap);
-     mBackground.draw(time);
+     mBackground.setTexture(mBitmap);
+     mBackground.draw(time,mGrid);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
index ee74fa2..5c3789d 100644
--- a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
+++ b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
@@ -29,7 +29,8 @@ import android.graphics.Paint.Style;
 import android.opengl.GLES20;
 import android.opengl.GLSurfaceView;
 
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.Distorted;
 import org.distorted.library.EffectNames;
 import org.distorted.library.EffectTypes;
@@ -49,7 +50,8 @@ public class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListen
   private Paint mPaint;
   private int texWidth, texHeight;
 
-  DistortedBitmap mBackground;
+  DistortedObject mBackground;
+  DistortedBitmapGrid mGrid;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -64,28 +66,30 @@ public class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListen
       
     texWidth = BWID;
     texHeight= BHEI;
+
+    mGrid      = new DistortedBitmapGrid(80,80*texHeight/texWidth);
+    mBackground= new DistortedObject(texWidth,texHeight,1);
+
+    mBackground.addEventListener(this);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
   public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
-    {      
-    mBackground = new DistortedBitmap(texWidth,texHeight, 80);
+    {
     Bitmap bitmap = Bitmap.createBitmap(texWidth,texHeight, Bitmap.Config.ARGB_8888);
-    Canvas canvas = new Canvas(bitmap);  
-      
+    Canvas canvas = new Canvas(bitmap);
+
     mPaint.setColor(0xff008800);
     canvas.drawRect(0, 0, texWidth, texHeight, mPaint);
     mPaint.setColor(0xffffffff);
-         
+
     for(int i=0; i<=NUMLINES ; i++ )
       {
       canvas.drawRect(texWidth*i/NUMLINES - 1,                       0,  texWidth*i/NUMLINES + 1,  texHeight               , mPaint);
-      canvas.drawRect(                      0, texHeight*i/NUMLINES -1,  texWidth               ,  texHeight*i/NUMLINES + 1, mPaint);  
+      canvas.drawRect(                      0, texHeight*i/NUMLINES -1,  texWidth               ,  texHeight*i/NUMLINES + 1, mPaint);
       }
-          
-    mBackground.setBitmap(bitmap);
-    mBackground.addEventListener(this);
+    mBackground.setTexture(bitmap);
 
     try
       {
@@ -93,7 +97,7 @@ public class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListen
       }
     catch(Exception ex)
       {
-      android.util.Log.e("Effects2D", ex.getMessage() );
+      android.util.Log.e("EffectQueue", ex.getMessage() );
       }
     }
 
@@ -112,7 +116,7 @@ public class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListen
   public void onDrawFrame(GL10 glUnused)
     {   
     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
-    mBackground.draw(System.currentTimeMillis());
+    mBackground.draw(System.currentTimeMillis(), mGrid);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java b/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java
index 0a7d981..b1b2a63 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DActivity.java
@@ -38,8 +38,9 @@ import android.widget.TableRow;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
-import org.distorted.library.DistortedCubes;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedCubesGrid;
+import org.distorted.library.DistortedObjectGrid;
 import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectNames;
 import org.distorted.library.EffectTypes;
@@ -66,6 +67,7 @@ public class Effects3DActivity extends Activity
   private NumberPicker mColsPicker, mRowsPicker;
   private boolean[] mShape;
   private DistortedObject mObject;
+  private DistortedObjectGrid mGrid;
   private int mObjectType;
   private int mBitmapID;
   private Bitmap mBitmap;
@@ -220,6 +222,13 @@ public class Effects3DActivity extends Activity
     return mObject;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public DistortedObjectGrid getGrid()
+    {
+    return mGrid;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public static void setSupportsRegion(boolean supports)
@@ -388,7 +397,12 @@ public class Effects3DActivity extends Activity
     if( mObjectType==1 )
       {
       getBitmap();
-      mObject = new DistortedBitmap(mBitmap.getWidth(),mBitmap.getHeight(),mNumCols);
+
+      int w = mBitmap.getWidth();
+      int h = mBitmap.getHeight();
+
+      mObject = new DistortedObject(w,h,1);
+      mGrid   = new DistortedBitmapGrid(mNumCols,mNumCols*h/w);
       setEffectView();
       }
     else
@@ -417,7 +431,8 @@ public class Effects3DActivity extends Activity
     for(int i=0; i<mNumRows*mNumCols; i++)
       str += mShape[i] ? "1" : "0";
 
-    mObject = new DistortedCubes(mNumCols, str, 10);
+    mObject = new DistortedObject(mNumCols,mNumRows,1);
+    mGrid   = new DistortedCubesGrid(mNumCols, str, false);
 
     setEffectView();
     }
diff --git a/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java b/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
index 225a301..eb7d3e7 100644
--- a/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
+++ b/src/main/java/org/distorted/examples/effects3d/Effects3DRenderer.java
@@ -26,8 +26,9 @@ import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedObjectGrid;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.DynamicQuat;
@@ -46,9 +47,11 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedObject mObject;
-    private DistortedBitmap mBackground;
-    private DistortedBitmap mCenter;
-    private DistortedBitmap mRegion;
+    private DistortedObject mBackground;
+    private DistortedObject mCenter;
+    private DistortedObject mRegion;
+    private DistortedBitmapGrid mQuad;
+    private DistortedObjectGrid mGrid;
     private int mObjWidth, mObjHeight, mObjDepth;
     private DynamicQuat mQuatInt1, mQuatInt2;
 
@@ -68,10 +71,14 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
       {
       mView = v;
 
-      mObject     = ((Effects3DActivity)v.getContext()).getObject();
-      mBackground = new DistortedBitmap(100, 100, 1);
-      mCenter     = new DistortedBitmap(100, 100, 1);
-      mRegion     = new DistortedBitmap(100, 100, 1);
+      Effects3DActivity act = (Effects3DActivity)v.getContext();
+
+      mObject     = act.getObject();
+      mGrid       = act.getGrid();
+      mBackground = new DistortedObject(100, 100, 1);
+      mCenter     = new DistortedObject(100, 100, 1);
+      mRegion     = new DistortedObject(100, 100, 1);
+      mQuad       = new DistortedBitmapGrid(1,1);
 
       mObjWidth = mObject.getWidth();
       mObjHeight= mObject.getHeight();
@@ -123,13 +130,13 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
 
       long time = System.currentTimeMillis();
 
-      mBackground.draw(time);
-      mObject.draw(time);
+      mBackground.draw(time,mQuad);
+      mObject.draw(time,mGrid);
 
       if( Effects3DActivity.supportsCenter() )
         {
-        mCenter.draw(time);
-        if( Effects3DActivity.supportsRegion() ) mRegion.draw(time);
+        mCenter.draw(time, mQuad);
+        if( Effects3DActivity.supportsRegion() ) mRegion.draw(time, mQuad);
         }
       }
 
@@ -234,10 +241,10 @@ class Effects3DRenderer implements GLSurfaceView.Renderer
         catch(IOException e) { }
         }  
       
-      mObject.setBitmap( act.getBitmap() );
-      mBackground.setBitmap(bitmap1);
-      mCenter.setBitmap(bitmap2);
-      mRegion.setBitmap(bitmap3);
+      mObject.setTexture( act.getBitmap() );
+      mBackground.setTexture(bitmap1);
+      mCenter.setTexture(bitmap2);
+      mRegion.setTexture(bitmap3);
 
       try
         {
diff --git a/src/main/java/org/distorted/examples/fbo/FBORenderer.java b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
index 69da9b4..24e5d51 100644
--- a/src/main/java/org/distorted/examples/fbo/FBORenderer.java
+++ b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
@@ -29,11 +29,11 @@ import org.distorted.examples.R;
 
 import org.distorted.library.DistortedNode;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic1D;
 import org.distorted.library.type.Static1D;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 
 import android.graphics.Bitmap;
@@ -46,7 +46,7 @@ import android.opengl.GLSurfaceView;
 class FBORenderer implements GLSurfaceView.Renderer 
 {
    private GLSurfaceView mView;
-   private DistortedBitmap mLisa;
+   private DistortedObject mLisa;
    private int lisaHeight, lisaWidth;
     
    private DistortedNode mRoot;
@@ -121,11 +121,13 @@ class FBORenderer implements GLSurfaceView.Renderer
       lisaHeight = bitmap1.getHeight();
       lisaWidth  = bitmap1.getWidth();
       
-      mLisa = new DistortedBitmap(bitmap1, 20);
-      DistortedBitmap text = new DistortedBitmap(bitmap2, 20);
-      
-      mRoot = new DistortedNode(mLisa);
-      mRoot.attach(text);
+      mLisa = new DistortedObject(lisaWidth, lisaHeight, 1);
+      mLisa.setTexture(bitmap1);
+      DistortedObject text = new DistortedObject(bitmap2.getWidth(),bitmap2.getHeight(),1);
+      text.setTexture(bitmap2);
+
+      mRoot = new DistortedNode(mLisa,new DistortedBitmapGrid(1,1));
+      mRoot.attach(text,new DistortedBitmapGrid(20,5));
      
       int textWidth  = text.getWidth();
       int textHeight = text.getHeight();
@@ -153,7 +155,7 @@ class FBORenderer implements GLSurfaceView.Renderer
         }
       catch(Exception ex)
         {
-        android.util.Log.e("MonaLisa", ex.getMessage() );
+        android.util.Log.e("FBO", ex.getMessage() );
         }
       }
 }
diff --git a/src/main/java/org/distorted/examples/flag/FlagRenderer.java b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
index 6661191..8593aae 100644
--- a/src/main/java/org/distorted/examples/flag/FlagRenderer.java
+++ b/src/main/java/org/distorted/examples/flag/FlagRenderer.java
@@ -26,13 +26,12 @@ import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedCubes;
+import org.distorted.library.DistortedCubesGrid;
 import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic;
 import org.distorted.library.type.Dynamic5D;
 import org.distorted.library.type.DynamicQuat;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 import org.distorted.library.type.Static5D;
@@ -49,6 +48,7 @@ class FlagRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedObject mObject;
+    private DistortedCubesGrid mGrid;
     private int mObjWidth, mObjHeight;
     private DynamicQuat mQuatInt1, mQuatInt2;
     private Dynamic5D mWaveDyn;
@@ -63,7 +63,8 @@ class FlagRenderer implements GLSurfaceView.Renderer
       {
       mView = v;
 
-      mObject = new DistortedCubes(50,30,10,false);
+      mGrid = new DistortedCubesGrid(50,30,false);
+      mObject = new DistortedObject(50,30,1);
 
       mObjWidth = mObject.getWidth();
       mObjHeight= mObject.getHeight();
@@ -135,7 +136,7 @@ class FlagRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mObject.draw(System.currentTimeMillis());
+      mObject.draw(System.currentTimeMillis(), mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -188,7 +189,7 @@ class FlagRenderer implements GLSurfaceView.Renderer
         catch(IOException e) { }
         }  
       
-      mObject.setBitmap(bitmap);
+      mObject.setTexture(bitmap);
       
       try
         {
diff --git a/src/main/java/org/distorted/examples/girl/GirlRenderer.java b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
index aeceedb..6dfcc59 100644
--- a/src/main/java/org/distorted/examples/girl/GirlRenderer.java
+++ b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
@@ -28,12 +28,12 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic1D;
 import org.distorted.library.type.Dynamic3D;
 import org.distorted.library.type.Static1D;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
@@ -47,7 +47,8 @@ import android.opengl.GLSurfaceView;
 class GirlRenderer implements GLSurfaceView.Renderer 
 {
     private GLSurfaceView mView;
-    private DistortedBitmap mGirl;
+    private DistortedObject mGirl;
+    private DistortedBitmapGrid mGrid;
     private Static3D pLeft, pRight, pHips;
     private Static4D Region, sinkRegion, HipsRegion;
     private Dynamic3D diL, diR;
@@ -152,7 +153,7 @@ class GirlRenderer implements GLSurfaceView.Renderer
    public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mGirl.draw(System.currentTimeMillis());
+      mGirl.draw(System.currentTimeMillis(),mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -205,8 +206,10 @@ class GirlRenderer implements GLSurfaceView.Renderer
       
       bmpHeight = bitmap.getHeight();
       bmpWidth  = bitmap.getWidth();
-      
-      mGirl = new DistortedBitmap(bitmap, 30);
+
+      mGrid = new DistortedBitmapGrid(30,30*bmpHeight/bmpWidth);
+      mGirl = new DistortedObject(bmpWidth,bmpHeight,1);
+      mGirl.setTexture(bitmap);
 
       mGirl.sink( diSink, pLeft, sinkRegion );
       mGirl.sink( diSink, pRight,sinkRegion );
diff --git a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
index bfa010a..26d1e3b 100644
--- a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
+++ b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
@@ -29,11 +29,11 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectNames;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic3D;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 import org.distorted.library.message.EffectListener;
@@ -51,7 +51,8 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
    private final int NUM_BUBBLES = 12;
 
    private GLSurfaceView mView;
-   private DistortedBitmap water;
+   private DistortedObject mWater;
+   private DistortedBitmapGrid mGrid;
    private int bmpHeight, bmpWidth;
    private Random mRnd;
 
@@ -77,7 +78,7 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
       dDistort.add(new Static3D(0,0,     0));
       dDistort.add(new Static3D(0,0,height));
 
-      return water.distort(dDistort, new Static3D(pointx,pointy,0), new Static4D(0,0,radius,radius));
+      return mWater.distort(dDistort, new Static3D(pointx,pointy,0), new Static4D(0,0,radius,radius));
       }
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -97,30 +98,30 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      water.draw(System.currentTimeMillis());
+      mWater.draw(System.currentTimeMillis(), mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      water.abortEffects(EffectTypes.MATRIX);
+      mWater.abortEffects(EffectTypes.MATRIX);
          
       if( (float)bmpHeight/bmpWidth > (float)height/width )
         {
         int w = (height*bmpWidth)/bmpHeight;
         float factor = (float)height/bmpHeight;
 
-        water.move( new Static3D((width-w)/2,0,0) );
-        water.scale(factor);
+        mWater.move( new Static3D((width-w)/2,0,0) );
+        mWater.scale(factor);
         }
       else
         {
         int h = (width*bmpHeight)/bmpWidth;
         float factor = (float)width/bmpWidth;
 
-        water.move( new Static3D(0,(height-h)/2,0) );
-        water.scale(factor);
+        mWater.move( new Static3D(0,(height-h)/2,0) );
+        mWater.scale(factor);
         }
       
       Distorted.onSurfaceChanged(width, height); 
@@ -152,9 +153,11 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
       
       bmpHeight = bitmap.getHeight();
       bmpWidth  = bitmap.getWidth();
-      
-      water = new DistortedBitmap(bitmap, 50);
-      water.addEventListener(this);
+
+      mGrid  = new DistortedBitmapGrid(50,50*bmpHeight/bmpWidth);
+      mWater = new DistortedObject(bmpWidth,bmpHeight,1);
+      mWater.setTexture(bitmap);
+      mWater.addEventListener(this);
       
       for(int i=0; i<NUM_BUBBLES; i++) randomizeNewBubble();
       
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java
index 4252d6f..dd029ad 100644
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java
+++ b/src/main/java/org/distorted/examples/matrix3d/Matrix3DActivity.java
@@ -32,7 +32,8 @@ import android.widget.Spinner;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedCubes;
+import org.distorted.library.DistortedObjectGrid;
+import org.distorted.library.DistortedCubesGrid;
 import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectNames;
 import org.distorted.library.EffectTypes;
@@ -46,6 +47,7 @@ import java.util.ArrayList;
 public class Matrix3DActivity extends Activity implements AdapterView.OnItemSelectedListener
   {
   private DistortedObject mObject;
+  private DistortedObjectGrid mGrid;
 
   private ArrayList<Matrix3DEffect> mEffects;
   private int mEffectAdd;
@@ -66,7 +68,8 @@ public class Matrix3DActivity extends Activity implements AdapterView.OnItemSele
 
     createEffectNames();
 
-    mObject = new DistortedCubes( 1, "1", 100);
+    mGrid   = new DistortedCubesGrid(1,1,false);
+    mObject = new DistortedObject(1,1,1);
 
     setEffectView();
     }
@@ -102,6 +105,13 @@ public class Matrix3DActivity extends Activity implements AdapterView.OnItemSele
     return mObject;
     }
 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+  public DistortedObjectGrid getGrid()
+    {
+    return mGrid;
+    }
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   public void setRegion(float x, float y, float r)
diff --git a/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java b/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
index 833a592..473de6d 100644
--- a/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
+++ b/src/main/java/org/distorted/examples/matrix3d/Matrix3DRenderer.java
@@ -23,6 +23,7 @@ import android.opengl.GLES20;
 import android.opengl.GLSurfaceView;
 
 import org.distorted.library.Distorted;
+import org.distorted.library.DistortedObjectGrid;
 import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectTypes;
 
@@ -35,6 +36,7 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
 {
     private GLSurfaceView mView;
     private DistortedObject mObject;
+    private DistortedObjectGrid mGrid;
 
     private int mWidth, mHeight;
 
@@ -44,7 +46,10 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
       {
       mView = v;
 
-      mObject= ((Matrix3DActivity)v.getContext()).getObject();
+      Matrix3DActivity act = (Matrix3DActivity)v.getContext();
+
+      mObject= act.getObject();
+      mGrid  = act.getGrid();
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -55,7 +60,7 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
 
       long time = System.currentTimeMillis();
 
-      mObject.draw(time);
+      mObject.draw(time,mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -92,7 +97,7 @@ class Matrix3DRenderer implements GLSurfaceView.Renderer
 
       Matrix3DActivity act = (Matrix3DActivity)mView.getContext();
 
-      mObject.setBitmap( act.getBitmap() );
+      mObject.setTexture(act.getBitmap());
 
       try
         {
diff --git a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
index b8e9b3b..f74b124 100644
--- a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
+++ b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
@@ -27,10 +27,10 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic3D;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
@@ -44,7 +44,8 @@ import android.opengl.GLSurfaceView;
 class MonaLisaRenderer implements GLSurfaceView.Renderer 
 {
     private GLSurfaceView mView;
-    private DistortedBitmap monaLisa;
+    private DistortedObject mObject;
+    private DistortedBitmapGrid mGrid;
     private Static3D pLeft, pRight;
     private Static4D rLeft, rRight;
     private Dynamic3D dLeft, dRight;
@@ -75,28 +76,28 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
     public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      monaLisa.draw(System.currentTimeMillis());
+      mObject.draw(System.currentTimeMillis(),mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      monaLisa.abortEffects(EffectTypes.MATRIX);
+      mObject.abortEffects(EffectTypes.MATRIX);
 
       if( (float)bmpHeight/bmpWidth > (float)height/width )
         {
         int w = (height*bmpWidth)/bmpHeight;
         float factor = (float)height/bmpHeight;
-        monaLisa.move( new Static3D((width-w)/2,0,0) );
-        monaLisa.scale(factor);
+        mObject.move( new Static3D((width-w)/2,0,0) );
+        mObject.scale(factor);
         }
       else
         {
         int h = (width*bmpHeight)/bmpWidth;
         float factor = (float)width/bmpWidth;
-        monaLisa.move( new Static3D(0,(height-h)/2,0) );
-        monaLisa.scale(factor);
+        mObject.move( new Static3D(0,(height-h)/2,0) );
+        mObject.scale(factor);
         }
 
       Distorted.onSurfaceChanged(width, height); 
@@ -127,9 +128,11 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
       bmpHeight = bitmap.getHeight();
       bmpWidth  = bitmap.getWidth();
 
-      monaLisa = new DistortedBitmap(bitmap, 9);
-      monaLisa.distort( dLeft, pLeft , rLeft );
-      monaLisa.distort(dRight, pRight, rRight);
+      mGrid = new DistortedBitmapGrid(9,9*bmpHeight/bmpWidth);
+      mObject = new DistortedObject(bmpWidth,bmpHeight,1);
+      mObject.setTexture(bitmap);
+      mObject.distort( dLeft, pLeft , rLeft );
+      mObject.distort(dRight, pRight, rRight);
 
       try
         {
diff --git a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
index 5d5817d..debe2be 100644
--- a/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/movingeffects/MovingEffectsRenderer.java
@@ -29,7 +29,8 @@ import android.graphics.Paint.Style;
 import android.opengl.GLES20;
 import android.opengl.GLSurfaceView;
 
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.Distorted;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -42,7 +43,9 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
    private Paint mPaint;
    private int texW, texH;
 
-   static DistortedBitmap mBackground;
+   private DistortedBitmapGrid mGrid;
+
+   static DistortedObject mBackground;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -102,7 +105,8 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
      texW = width;
      texH = height;
 
-     mBackground = new DistortedBitmap(texW,texH, 80);
+     mGrid = new DistortedBitmapGrid(80,80*height/width);
+     mBackground = new DistortedObject(texW,texH,1);
      mBitmap = Bitmap.createBitmap(texW,texH, Bitmap.Config.ARGB_8888);
      mCanvas = new Canvas(mBitmap);
 
@@ -122,10 +126,10 @@ class MovingEffectsRenderer implements GLSurfaceView.Renderer
        {
        drawBackground();   
        mView.drawCurve(mCanvas,time);
-       mBackground.setBitmap(mBitmap);  
+       mBackground.setTexture(mBitmap);
        }
       
-     mBackground.draw(time);
+     mBackground.draw(time,mGrid);
      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
index c59c70f..bf3d229 100644
--- a/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
+++ b/src/main/java/org/distorted/examples/olimpic/OlimpicRenderer.java
@@ -33,7 +33,8 @@ import org.distorted.library.DistortedNode;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static1D;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -50,17 +51,18 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
    
    private GLSurfaceView mView;
    private DistortedNode mScreen;
-   private DistortedBitmap mLeaf;
+   private DistortedObject mLeaf;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
    OlimpicRenderer(GLSurfaceView v)
       {     
       mView = v;
-    
-      mLeaf = new DistortedBitmap(LEAF_SIZE,LEAF_SIZE,1);
-      
-      mScreen = new DistortedNode(new DistortedBitmap(9*LEAF_SIZE,9*LEAF_SIZE,1));
+
+      mLeaf = new DistortedObject(LEAF_SIZE,LEAF_SIZE,1);
+      DistortedBitmapGrid grid = new DistortedBitmapGrid(1,1);
+
+      mScreen = new DistortedNode(new DistortedObject(9*LEAF_SIZE,9*LEAF_SIZE,1), grid);
      
       Dynamic1D rot = new Dynamic1D(5000,0.0f);
       rot.setMode(Dynamic1D.MODE_JUMP);
@@ -72,7 +74,7 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
       int[] colors    = new int[] {0,0,1,  0,0,0,  1,0,0,  1,1,0,  0,1,0}; // blue, black, red, yellow, green  
       int[] positions = new int[] {0*LEAF_SIZE,2*LEAF_SIZE,  3*LEAF_SIZE,2*LEAF_SIZE,  6*LEAF_SIZE,2*LEAF_SIZE,  3*LEAF_SIZE/2,9*LEAF_SIZE/2,  9*LEAF_SIZE/2,9*LEAF_SIZE/2};
       
-      DistortedBitmap tmp;
+      DistortedObject tmp;
       Static3D center = new Static3D(3*LEAF_SIZE/2, 3*LEAF_SIZE/2, 0);
       Static3D axis   = new Static3D(0,0,1);
       Static3D moveVector = new Static3D(0,LEAF_SIZE,0);
@@ -81,12 +83,12 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
         {
         if( i==0 )
           {
-          mCircleNode[i] = new DistortedNode(new DistortedBitmap(3*LEAF_SIZE,3*LEAF_SIZE,1));
+          mCircleNode[i] = new DistortedNode(new DistortedObject(3*LEAF_SIZE,3*LEAF_SIZE,1), grid);
         
           for(int j=0; j<NUM_LEAVES; j++)
             {
-            tmp = new DistortedBitmap(mLeaf, Distorted.CLONE_BITMAP);
-            mCircleNode[i].attach(tmp);
+            tmp = new DistortedObject(mLeaf, Distorted.CLONE_BITMAP);
+            mCircleNode[i].attach(tmp,grid);
             tmp.rotate( new Static1D(j*(360/NUM_LEAVES)), axis, center );
             tmp.move(moveVector);
             }
@@ -97,7 +99,7 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
           }
       
         mScreen.attach(mCircleNode[i]);
-        tmp = (DistortedBitmap)mCircleNode[i].getObject();
+        tmp = mCircleNode[i].getObject();
         tmp.move( new Static3D(positions[2*i], positions[2*i+1], 0) );
         tmp.rotate( rot, axis, center );
         tmp.chroma( new Static1D(0.5f), new Static3D(colors[3*i],colors[3*i+1], colors[3*i+2]) );
@@ -116,7 +118,7 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       {
-      DistortedBitmap bmp = (DistortedBitmap)mScreen.getObject();
+      DistortedObject bmp = mScreen.getObject();
       int bmpWidth  = bmp.getWidth();
       int bmpHeight = bmp.getHeight();
      
@@ -164,7 +166,7 @@ class OlimpicRenderer implements GLSurfaceView.Renderer
         catch(IOException e) { }
         }  
       
-      mLeaf.setBitmap(leaf);
+      mLeaf.setTexture(leaf);
       
       try
         {
diff --git a/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java b/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
index aa0a1a3..c05d84f 100644
--- a/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
+++ b/src/main/java/org/distorted/examples/plainmonalisa/RenderThread.java
@@ -31,10 +31,10 @@ import android.view.SurfaceHolder;
 import android.view.SurfaceView;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic3D;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 import org.distorted.examples.R;
@@ -60,7 +60,8 @@ public class RenderThread extends Thread
   private EglCore eglCore;
   private EGLSurface eglSurface;
 
-  private DistortedBitmap monaLisa;
+  private DistortedObject monaLisa;
+  private DistortedBitmapGrid mGrid;
   private int bmpHeight, bmpWidth;
 
   private Static3D pLeft, pRight;
@@ -189,12 +190,15 @@ public class RenderThread extends Thread
       catch(IOException io) {}
       }
 
-    monaLisa = new DistortedBitmap(bmp, 9);
+    bmpHeight = bmp.getHeight();
+    bmpWidth  = bmp.getWidth();
+
+    monaLisa = new DistortedObject(bmpWidth,bmpHeight,1);
     monaLisa.distort( dLeft, pLeft , rLeft );
     monaLisa.distort(dRight, pRight, rRight);
+    monaLisa.setTexture(bmp);
 
-    bmpHeight = bmp.getHeight();
-    bmpWidth  = bmp.getWidth();
+    mGrid= new DistortedBitmapGrid(9,9*bmpHeight/bmpWidth);  // more-or-less square Grid with 9 columns.
 
     try
       {
@@ -247,7 +251,7 @@ public class RenderThread extends Thread
     eglCore.makeCurrent(eglSurface);
 
     GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-    monaLisa.draw(System.currentTimeMillis());
+    monaLisa.draw(System.currentTimeMillis(), mGrid);
 
     eglCore.swapBuffers(eglSurface);
     }
diff --git a/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java b/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
index fd35bfd..50f50b0 100644
--- a/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
+++ b/src/main/java/org/distorted/examples/projection/ProjectionRenderer.java
@@ -23,7 +23,8 @@ import javax.microedition.khronos.egl.EGLConfig;
 import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
@@ -39,7 +40,8 @@ import android.opengl.GLSurfaceView;
 class ProjectionRenderer implements GLSurfaceView.Renderer
 {
    private GLSurfaceView mView;
-   private DistortedBitmap mProjection;
+   private DistortedObject mProjection;
+   private DistortedBitmapGrid mGrid;
 
    private static float mF, mX, mY;
    private static int mWidth, mHeight;
@@ -83,7 +85,7 @@ class ProjectionRenderer implements GLSurfaceView.Renderer
    public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mProjection.draw(System.currentTimeMillis());
+      mProjection.draw(System.currentTimeMillis(), mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -118,7 +120,8 @@ class ProjectionRenderer implements GLSurfaceView.Renderer
     private void setupBitmap(int w, int h)
       {
       Paint paint = new Paint();
-      mProjection = new DistortedBitmap(w,h, 50);
+      mProjection = new DistortedObject(w,h,1);
+      mGrid       = new DistortedBitmapGrid(50,50*h/w);
       Bitmap bmp = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
       Canvas bmpCanvas = new Canvas(bmp);
 
@@ -135,7 +138,7 @@ class ProjectionRenderer implements GLSurfaceView.Renderer
         bmpCanvas.drawRect(               0, h *i/NUMLINES -1,  w               ,  h*i/NUMLINES + 1, paint);
         }
         
-      mProjection.setBitmap(bmp);
+      mProjection.setTexture(bmp);
         
       int min = w<h ? w:h;
         
diff --git a/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java b/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
index bede261..281c6b1 100644
--- a/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
+++ b/src/main/java/org/distorted/examples/quaternion/QuaternionRenderer.java
@@ -31,7 +31,8 @@ import org.distorted.examples.R;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic;
 import org.distorted.library.type.DynamicQuat;
-import org.distorted.library.DistortedCubes;
+import org.distorted.library.DistortedCubesGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.type.Static4D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.Distorted;
@@ -49,7 +50,8 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
   private static final int SIZE = 100;
 	
   private GLSurfaceView mView;
-  private DistortedCubes mCube;
+  private DistortedObject mCube;
+  private DistortedCubesGrid mGrid;
 
   private DynamicQuat mRot;
     
@@ -58,8 +60,9 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
   QuaternionRenderer(GLSurfaceView v)
     {
     mView = v;
-    mCube = new DistortedCubes( 3, "000010000", SIZE);
-      
+    mGrid = new DistortedCubesGrid( 3, "000010000", false);
+    mCube = new DistortedObject(1,1,1);
+
     mRot = new DynamicQuat();
 
     Random rnd = new Random(System.currentTimeMillis());
@@ -87,7 +90,7 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
   public void onDrawFrame(GL10 glUnused) 
     {
     GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-    mCube.draw(System.currentTimeMillis());
+    mCube.draw(System.currentTimeMillis(), mGrid);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -134,7 +137,7 @@ class QuaternionRenderer implements GLSurfaceView.Renderer
       catch(IOException e) { }
       }  
       
-    mCube.setBitmap(bitmap);
+    mCube.setTexture(bitmap);
       
     try
       {
diff --git a/src/main/java/org/distorted/examples/save/SaveRenderer.java b/src/main/java/org/distorted/examples/save/SaveRenderer.java
index fa26c8f..54ec182 100644
--- a/src/main/java/org/distorted/examples/save/SaveRenderer.java
+++ b/src/main/java/org/distorted/examples/save/SaveRenderer.java
@@ -31,7 +31,8 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedObject;
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.DistortedFramebuffer;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic1D;
@@ -51,7 +52,8 @@ import android.os.Environment;
 class SaveRenderer implements GLSurfaceView.Renderer
   {
   private GLSurfaceView mView;
-  private DistortedBitmap mGirl;
+  private DistortedObject mGirl;
+  private DistortedBitmapGrid mGrid;
   private DistortedFramebuffer mOffscreen;
   private Static3D pLeft, pRight;
   private Static4D sinkRegion;
@@ -147,7 +149,7 @@ class SaveRenderer implements GLSurfaceView.Renderer
       {
       mGirl.abortEffects(EffectTypes.MATRIX);
       mGirl.scale(mScaleFactor);
-      mGirl.draw(System.currentTimeMillis(), mOffscreen);
+      mGirl.draw(System.currentTimeMillis(), mGrid, mOffscreen);
       applyMatrixEffects(scrWidth,scrHeight);
 
       int fW =(int)(mScale*bmpWidth);
@@ -162,7 +164,7 @@ class SaveRenderer implements GLSurfaceView.Renderer
       isSaving = false;
       }
 
-    mGirl.draw(System.currentTimeMillis());
+    mGirl.draw(System.currentTimeMillis(), mGrid);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -225,8 +227,10 @@ class SaveRenderer implements GLSurfaceView.Renderer
       
     bmpHeight = bitmap.getHeight();
     bmpWidth  = bitmap.getWidth();
-      
-    mGirl = new DistortedBitmap(bitmap, 30);
+
+    mGrid = new DistortedBitmapGrid(30,30*bmpHeight/bmpWidth);
+    mGirl = new DistortedObject(bmpWidth,bmpHeight,1);
+    mGirl.setTexture(bitmap);
 
     mGirl.sink( diSink, pLeft , sinkRegion);
     mGirl.sink( diSink, pRight, sinkRegion);
diff --git a/src/main/java/org/distorted/examples/sink/SinkRenderer.java b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
index 7274052..a6fccb0 100644
--- a/src/main/java/org/distorted/examples/sink/SinkRenderer.java
+++ b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
@@ -28,11 +28,11 @@ import javax.microedition.khronos.opengles.GL10;
 import org.distorted.examples.R;
 
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedBitmapGrid;
+import org.distorted.library.DistortedObject;
 import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Dynamic1D;
 import org.distorted.library.type.Static1D;
-import org.distorted.library.type.Static2D;
 import org.distorted.library.type.Static3D;
 import org.distorted.library.type.Static4D;
 
@@ -46,7 +46,8 @@ import android.opengl.GLSurfaceView;
 class SinkRenderer implements GLSurfaceView.Renderer 
   {
   private GLSurfaceView mView;
-  private DistortedBitmap sinkBmp;
+  private DistortedObject mObject;
+  private DistortedBitmapGrid mGrid;
   private Static3D pLeft, pRight;
   private Static4D Region;
   private int bmpHeight, bmpWidth;
@@ -67,30 +68,30 @@ class SinkRenderer implements GLSurfaceView.Renderer
   public void onDrawFrame(GL10 glUnused) 
     {
     GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-    sinkBmp.draw(System.currentTimeMillis());
+    mObject.draw(System.currentTimeMillis(), mGrid);
     }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
   public void onSurfaceChanged(GL10 glUnused, int width, int height) 
     { 
-    sinkBmp.abortEffects(EffectTypes.MATRIX);
+    mObject.abortEffects(EffectTypes.MATRIX);
          
     if( (float)bmpHeight/bmpWidth > (float)height/width )
       {
       int w = (height*bmpWidth)/bmpHeight;
       float factor = (float)height/bmpHeight;
 
-      sinkBmp.move( new Static3D((width-w)/2,0,0) );
-      sinkBmp.scale( factor );
+      mObject.move( new Static3D((width-w)/2,0,0) );
+      mObject.scale( factor );
       }
     else
       {
       int h = (width*bmpHeight)/bmpWidth;
       float factor = (float)width/bmpWidth;
 
-      sinkBmp.move( new Static3D(0,(height-h)/2,0) );
-      sinkBmp.scale( factor );
+      mObject.move( new Static3D(0,(height-h)/2,0) );
+      mObject.scale( factor );
       }
       
     Distorted.onSurfaceChanged(width, height); 
@@ -125,9 +126,12 @@ class SinkRenderer implements GLSurfaceView.Renderer
     dSink.add(new Static1D( 1));
     dSink.add(new Static1D(10));
 
-    sinkBmp = new DistortedBitmap(bitmap, 30);
-    sinkBmp.sink( dSink, pLeft, Region);
-    sinkBmp.sink( dSink, pRight,Region);
+    mGrid = new DistortedBitmapGrid(30,30*bmpHeight/bmpWidth);
+    mObject = new DistortedObject(bmpWidth,bmpHeight,1);
+    mObject.setTexture(bitmap);
+    
+    mObject.sink( dSink, pLeft, Region);
+    mObject.sink( dSink, pRight,Region);
       
     try
       {
diff --git a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
index a7c16bd..1b696e2 100644
--- a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
+++ b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
@@ -28,6 +28,7 @@ import javax.microedition.khronos.opengles.GL10;
 
 import org.distorted.examples.R;
 
+import org.distorted.library.DistortedBitmapGrid;
 import org.distorted.library.EffectNames;
 import org.distorted.library.type.Dynamic1D;
 import org.distorted.library.type.Dynamic3D;
@@ -38,7 +39,7 @@ import org.distorted.library.type.Static4D;
 import org.distorted.library.message.EffectListener;
 import org.distorted.library.message.EffectMessage;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedBitmap;
+import org.distorted.library.DistortedObject;
 
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -100,19 +101,22 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
   private final float CRAWL_ANGLE = -30.0f;
    
   private GLSurfaceView mView;
-  private DistortedBitmap mScreen, mGFFA, mLogo, mCrawl, mCrawlBackground;
-  private DistortedBitmap[] mStars;
+  private DistortedObject mScreen, mGFFA, mLogo, mCrawl, mCrawlBackground;
+  private DistortedObject[] mStars;
   private long gffaID, logoID, crawlID;
     
   private Random mRnd = new Random(0);
   private DistortedNode mRoot, mBackground;
-    
+  private DistortedBitmapGrid mQuad;
+
+
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
   StarWarsRenderer(GLSurfaceView v)
     {
     mView = v;
-     
+
+    mQuad = new DistortedBitmapGrid(1,1);
     Distorted.setProjection(60.0f, 0.0f, 0.0f);
     }
 
@@ -154,10 +158,10 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
 
   private void setupScreen(int w, int h)
     {
-    mScreen = new DistortedBitmap(w,h,1);
-    mRoot = new DistortedNode(mScreen);
+    mScreen = new DistortedObject(w,h,1);
+    mRoot = new DistortedNode(mScreen,mQuad);
       
-    mCrawlBackground = new DistortedBitmap(w,(int)(Math.sqrt(3.0)*h),1);
+    mCrawlBackground = new DistortedObject(w,(int)(Math.sqrt(3.0)*h),1);
        
     int randomA, randomX, randomY, randomTime;
     float randomS, randomAlpha1, randomAlpha2;
@@ -188,7 +192,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       
       mStars[i].alpha(di);
       
-      mRoot.attach(mStars[i]);
+      mRoot.attach(mStars[i], mQuad);
       }
       
     float scale = (0.5f*w/mGFFA.getWidth());
@@ -202,7 +206,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     mGFFA.scale( new Static3D(scale,scale,scale) );
     mGFFA.alpha(di);
       
-    mRoot.attach(mGFFA);
+    mRoot.attach(mGFFA, mQuad);
     mGFFA.addEventListener(this); 
     }
     
@@ -240,7 +244,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     paint.setTypeface(tf);     
  
     ///// create GFFA ///////////////////
-    mGFFA  = new DistortedBitmap(GFFA_WIDTH, GFFA_HEIGHT, 1);
+    mGFFA  = new DistortedObject(GFFA_WIDTH, GFFA_HEIGHT, 1);
     bitmapGFFA = Bitmap.createBitmap(GFFA_WIDTH,GFFA_HEIGHT,Bitmap.Config.ARGB_8888);
     bitmapGFFA.eraseColor(0x00000000);
     Canvas gffaCanvas = new Canvas(bitmapGFFA);
@@ -250,13 +254,14 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       gffaCanvas.drawText(mGFFAString[i], 0, (i+1)*(FONT_HEIGHT+VERTICAL_SPACING), paint);  
       }
   
-    mGFFA.setBitmap(bitmapGFFA);
+    mGFFA.setTexture(bitmapGFFA);
       
     ///// create Logo ///////////////////
-    mLogo  = new DistortedBitmap(bitmapLogo, 1);
-      
+    mLogo  = new DistortedObject(bitmapLogo.getWidth(),bitmapLogo.getHeight(),1);
+    mLogo.setTexture(bitmapLogo);
+
     ///// create CRAWL //////////////////
-    mCrawl = new DistortedBitmap(CRAWL_WIDTH, CRAWL_HEIGHT, 1);
+    mCrawl = new DistortedObject(CRAWL_WIDTH, CRAWL_HEIGHT, 1);
     bitmapText = Bitmap.createBitmap(CRAWL_WIDTH,CRAWL_HEIGHT,Bitmap.Config.ARGB_8888);
     bitmapText.eraseColor(0x00000000);
     Canvas textCanvas = new Canvas(bitmapText);
@@ -267,17 +272,18 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       displayJustified(mCRAWLString[i], 0, (i+1)*(FONT_HEIGHT+VERTICAL_SPACING), CRAWL_WIDTH, textCanvas, paint);  
       }
       
-    mCrawl.setBitmap(bitmapText);
+    mCrawl.setTexture(bitmapText);
       
     ///// create Stars ///////////////////
       
-    mStars = new DistortedBitmap[NUM_STARS];
-      
-    mStars[0] = new DistortedBitmap(bitmapStar,1);
+    mStars = new DistortedObject[NUM_STARS];
       
+    mStars[0] = new DistortedObject(bitmapStar.getWidth(),bitmapStar.getHeight(),1);
+    mStars[0].setTexture(bitmapStar);
+
     for(int i=1; i<NUM_STARS; i++)
       {
-      mStars[i] = new DistortedBitmap(mStars[0], Distorted.CLONE_BITMAP|Distorted.CLONE_VERTEX);  
+      mStars[i] = new DistortedObject(mStars[0], Distorted.CLONE_BITMAP|Distorted.CLONE_VERTEX);
       }
       
     gffaID = mGFFA.getID();
@@ -356,7 +362,7 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
         mLogo.scale(di);
         mLogo.move( new Static3D(-logoW/2,-logoH/2,0) );
       
-        mRoot.attach(mLogo);
+        mRoot.attach(mLogo,mQuad);
         mLogo.addEventListener(this);
         }
       else if( objectID==logoID )
@@ -386,8 +392,8 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
         mCrawl.scale( new Static3D(scale,scale,scale) );
         mCrawl.move( new Static3D(-crawlW/2,0,0) );
         
-        mBackground = mRoot.attach(mCrawlBackground);
-        mBackground.attach(mCrawl);
+        mBackground = mRoot.attach(mCrawlBackground,mQuad);
+        mBackground.attach(mCrawl,mQuad);
         mCrawl.addEventListener(this);
         }
       else if( objectID==crawlID )
diff --git a/src/main/java/org/distorted/examples/wind/WindRenderer.java b/src/main/java/org/distorted/examples/wind/WindRenderer.java
index 873ad30..f01de39 100644
--- a/src/main/java/org/distorted/examples/wind/WindRenderer.java
+++ b/src/main/java/org/distorted/examples/wind/WindRenderer.java
@@ -26,9 +26,8 @@ import android.opengl.GLSurfaceView;
 
 import org.distorted.examples.R;
 import org.distorted.library.Distorted;
-import org.distorted.library.DistortedCubes;
+import org.distorted.library.DistortedCubesGrid;
 import org.distorted.library.DistortedObject;
-import org.distorted.library.EffectTypes;
 import org.distorted.library.type.Static1D;
 import org.distorted.library.type.Static3D;
 
@@ -44,6 +43,7 @@ class WindRenderer implements GLSurfaceView.Renderer
 {
    private GLSurfaceView mView;
    private DistortedObject mObject;
+   private DistortedCubesGrid mGrid;
    private WindEffectsManager mEffects;
    private int mObjWidth, mObjHeight;
    private int mWind;
@@ -54,7 +54,8 @@ class WindRenderer implements GLSurfaceView.Renderer
       { 
       mView = view;
 
-      mObject = new DistortedCubes(50,30,10,false);
+      mGrid    = new DistortedCubesGrid(50,30,false);
+      mObject  = new DistortedObject(50,30,1);
       mEffects = new WindEffectsManager(mObject);
 
       mObjWidth = mObject.getWidth();
@@ -74,7 +75,7 @@ class WindRenderer implements GLSurfaceView.Renderer
    public void onDrawFrame(GL10 glUnused) 
       {
       GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
-      mObject.draw(System.currentTimeMillis());
+      mObject.draw(System.currentTimeMillis(),mGrid);
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -121,7 +122,7 @@ class WindRenderer implements GLSurfaceView.Renderer
         catch(IOException e) { }
         }
 
-      mObject.setBitmap(bitmap);
+      mObject.setTexture(bitmap);
 
       try
         {
