commit 630703d1ce1690d67b55fd6b8e7f6f2f59680f35
Author: leszek <leszek@koltunski.pl>
Date:   Wed Apr 26 00:08:35 2017 +0100

    Revert "Major refactoring: convert the Matrix Effects to be independent of the resolution of the surface we render to."
    
    This reverts commit d79a56d3bc6cc7a22b21abeb180353a1818bd6ad.

diff --git a/src/main/java/org/distorted/examples/bean/BeanRenderer.java b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
index 03543bc..3e3ab34 100644
--- a/src/main/java/org/distorted/examples/bean/BeanRenderer.java
+++ b/src/main/java/org/distorted/examples/bean/BeanRenderer.java
@@ -102,11 +102,24 @@ class BeanRenderer implements GLSurfaceView.Renderer
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      float qx = (float)width /bmpWidth;
-      float qy = (float)height/bmpHeight;
-
       mEffects.abortEffects(EffectTypes.MATRIX);
-      mEffects.scale(  qx<qy ? (new Static3D(1,qx/qy,1)) : (new Static3D(qy/qx,1,1)) );
+         
+      if( (float)bmpHeight/bmpWidth > (float)height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        float factor = (float)height/bmpHeight;
+
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        float factor = (float)width/bmpWidth;
+
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
+        }
       
       mScreen.resize(width, height);
       }
diff --git a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
index 824327c..1d24c2e 100644
--- a/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
+++ b/src/main/java/org/distorted/examples/catanddog/CatAndDogRenderer.java
@@ -134,56 +134,26 @@ class CatAndDogRenderer implements GLSurfaceView.Renderer
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       {
-      // 1 cycle = 10000 ms = 10 seconds long
-      int duration = 10000;
-
-      // First abort all effect we might have had before
-      // (we will if we got here from a brief stay in the background)
-      mEffects.abortEffects(EffectTypes.MATRIX);
-
-      // Now start applying the effects. Matrix effects are, like the name suggests, multiplications
-      // of the Mesh by certain Projective Transformation Matrix. As such, those are - confusingly -
-      // applied in exactly the opposite order than given, i.e. here the last SCALE would be the
-      // first effect applied to each vertex of our Mesh, followed by a ROTATION, and only then by
-      // the MOVE !
-
-      // MOVES /////////
-      // Now, after the SCALE and ROTATE, the center of our Mesh is still exactly at the center of
-      // the Screen. Thus we move the Mesh back and forth between (0.5,0.5,0) and (-0.5,-0.5,0) ,
-      // i.e. between the lower right and upper left corners of the screen.
+      int duration = 10000;   // 10 seconds
+      
       Dynamic3D diMove = new Dynamic3D(duration,0.0f);
-      Static3D lowerRight = new Static3D( +0.5f, +0.5f, 0);
-      Static3D upperLeft  = new Static3D( -0.5f, -0.5f, 0);
-      diMove.add(lowerRight);
-      diMove.add(upperLeft);
-      mEffects.move(diMove);
-
-      // ROTATION //////
-      // Now, after the SCALE, our Texture is positioned at the center of the screen - coords (0,0,0).
-      // Rotate the whole Mesh around this point, along the (0,0,1) axis (i.e. vector perpendicular to
-      // the surface of the screen) starting from 0 degrees to 360 and back.
+      diMove.add(new Static3D(width-bmpWidth,height-bmpHeight,0));
+      diMove.add(new Static3D(0,0,0));
+      
+      Dynamic3D diScale = new Dynamic3D(duration,0.0f);
+      diScale.add(new Static3D(1,1,1));
+      diScale.add(new Static3D(0.33f,0.33f,1));
+      
       Dynamic1D diRotate = new Dynamic1D(duration,0.0f);
       diRotate.add(new Static1D(  0));
       diRotate.add(new Static1D(360));
-      Static3D axis = new Static3D(0,0,1);
-      Static3D center = new Static3D(0,0,0);
-      mEffects.rotate( diRotate, axis, center );
-
-      // SCALING ///////
-      // Before we apply any effects, at the very start, out Mesh skinned by the 'Cat and Dog' texture
-      // fills up the whole Screen. First we need to scale it down so that the resolution of the
-      // original 'Cat and Dog' bitmap are preserved, (qx/qy part) and also apply a Dynamic switching
-      // the size from 80% of the Screen to 20% and back.
-      Dynamic3D diScale = new Dynamic3D(duration,0.0f);
-      float qx = (float)width /bmpWidth;
-      float qy = (float)height/bmpHeight;
-      float start_scale = 0.8f;
-      float end_scale   = 0.2f;
-      diScale.add(qx<qy ? (new Static3D( start_scale,start_scale*qx/qy,1)) : (new Static3D(start_scale*qy/qx,start_scale,1)));
-      diScale.add(qx<qy ? (new Static3D( end_scale  ,end_scale  *qx/qy,1)) : (new Static3D(end_scale  *qy/qx,end_scale  ,1)));
+      
+      mEffects.abortEffects(EffectTypes.MATRIX);
+
+      mEffects.move(diMove);
       mEffects.scale(diScale);
+      mEffects.rotate( diRotate, new Static3D(0,0,1), new Static3D(bmpWidth/2,bmpHeight/2,0) );
 
-      // Finally, tell the Screen itself the underlying OpenGL surface has changed dimensions.
       mScreen.resize(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 a017430..5152a28 100644
--- a/src/main/java/org/distorted/examples/check/CheckRenderer.java
+++ b/src/main/java/org/distorted/examples/check/CheckRenderer.java
@@ -88,11 +88,24 @@ class CheckRenderer implements GLSurfaceView.Renderer
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      float qx = (float)width /bmpWidth;
-      float qy = (float)height/bmpHeight;
-
       mEffects.abortEffects(EffectTypes.MATRIX);
-      mEffects.scale(  qx<qy ? (new Static3D(1,qx/qy,1)) : (new Static3D(qy/qx,1,1)) );
+      
+      if( (float)bmpHeight/bmpWidth > (float)height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        float factor = (float)height/bmpHeight;
+
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        float factor = (float)width/bmpWidth;
+
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
+        }
       
       mScreen.resize(width, height);
       }
diff --git a/src/main/java/org/distorted/examples/deform/DeformRenderer.java b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
index 5e39283..26f91bb 100644
--- a/src/main/java/org/distorted/examples/deform/DeformRenderer.java
+++ b/src/main/java/org/distorted/examples/deform/DeformRenderer.java
@@ -100,6 +100,7 @@ class DeformRenderer implements GLSurfaceView.Renderer
       fpsTexture.setTexture(fpsBitmap);
       fpsCanvas = new Canvas(fpsBitmap);
       fpsEffects = new DistortedEffects();
+      fpsEffects.move( new Static3D(5,5,0) );
 
       mPaint = new Paint();
       mPaint.setAntiAlias(true);
@@ -107,7 +108,6 @@ class DeformRenderer implements GLSurfaceView.Renderer
       mPaint.setTextSize(0.7f*fpsH);
 
       stretchEffects = new DistortedEffects();
-      stretchEffects.scale(0.5f);
 
       mRegion = new Static4D(0,0,0,0);
 
@@ -205,10 +205,6 @@ class DeformRenderer implements GLSurfaceView.Renderer
      scrHeight = height;
      scrWidth  = width;
 
-     fpsEffects.abortAllEffects();
-     fpsEffects.move(  new Static3D( -0.5f + (fpsW/2 + 5.0f)/width, -0.5f + (fpsH/2 + 5.0f)/height,0.0f) );
-     fpsEffects.scale( new Static3D( (float)fpsW/width, (float)fpsH/height, 1.0f) );
-
      mRegion.set3(mRadius*scrWidth);
 
      Canvas stretchCanvas;
@@ -235,6 +231,9 @@ class DeformRenderer implements GLSurfaceView.Renderer
      if( stretchTexture==null ) stretchTexture = new DistortedTexture(w,h);
      stretchTexture.setTexture(stretchBitmap);
 
+     stretchEffects.abortAllEffects();
+     stretchEffects.move( new Static3D(scrWidth/4,scrHeight/4,0) );
+
      mScreen.detachAll();
      mScreen.attach(stretchTexture,stretchEffects,stretchMesh);
      mScreen.attach(fpsTexture,fpsEffects,fpsMesh);
@@ -270,19 +269,18 @@ class DeformRenderer implements GLSurfaceView.Renderer
      if( xt>scrWidth/2 ) xt=scrWidth/2;
      if( yt<0 ) yt=0;
      if( yt>scrHeight/2 ) yt=scrHeight/2;
+      
+     touchPoint.set(xt,yt,0);
 
      switch(mMode)
        {
        case DISTORT: vDistort[0].set(0,0,0);
-                     touchPoint.set(xt,yt,0);
                      mLastEffect = stretchEffects.distort( mMovingDistortDynamic, touchPoint, mRegion);
                      break;
        case DEFORM : vDeform[0].set(0,0,0);
-                     touchPoint.set(xt,yt,0);
                      mLastEffect = stretchEffects.deform( mMovingDeformDynamic, touchPoint, mRegion);
                      break;
        case SHEAR  : vShear[0].set(0,0,0);
-                     touchPoint.set( (float)xt/scrWidth, (float)yt/scrHeight,0);
                      mLastEffect = stretchEffects.shear(mMovingShearDynamic, touchPoint);
                      break;
        }
diff --git a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
index 34080db..14158bc 100644
--- a/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
+++ b/src/main/java/org/distorted/examples/differentbitmaps/DifferentBitmapsRenderer.java
@@ -105,81 +105,85 @@ class DifferentBitmapsRenderer implements GLSurfaceView.Renderer
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////
    
-   public void onDrawFrame(GL10 glUnused)
+    public void onDrawFrame(GL10 glUnused) 
       {
       mScreen.render( System.currentTimeMillis() );
       }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
-   public void onSurfaceChanged(GL10 glUnused, int width, int height)
-     {
-     for(int i=NUM-1; i>=0; i--)
-       {
-       mEffects[i].abortEffects(EffectTypes.MATRIX);
-       }
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      {  
+      for(int i=NUM-1; i>=0; i--) 
+        {   
+        mEffects[i].abortEffects(EffectTypes.MATRIX);
+        }
       
-     float qx = (float)width /bmpWidth;
-     float qy = (float)height/bmpHeight;
-
-     if( qx > NUM*qy )  // screen more 'horizontal' than NUM bitmaps next to each other
-       {
-       for(int i=0; i<NUM; i++)
-         {
-         mEffects[i].move( new Static3D( qy*((0.5f+i)/NUM-0.5f), 0, 0) );
-         mEffects[i].scale( new Static3D( qy/qx, 1, 1) );
-         }
-       }
-     else
-       {
-       for(int i=0; i<NUM; i++)
-         {
-         mEffects[i].move( new Static3D( (0.5f+i)/NUM-0.5f, 0, 0) );
-         mEffects[i].scale( new Static3D( 1.0f/NUM, (qx/qy)/NUM, 1) );
-         }
-       }
+      if( (float)bmpHeight/(NUM*bmpWidth) > (float)height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        float factor = (float)height/bmpHeight;
+
+        for(int i=NUM-1; i>=0; i--) 
+          {
+          mEffects[i].move( new Static3D((width-NUM*w)/2 +i*w ,0,0) );
+          mEffects[i].scale(factor);
+          }
+        }
+      else
+        {
+        int w = width/NUM;  
+        int h = (width*bmpHeight)/(bmpWidth*NUM);
+        float factor = (float)width/(bmpWidth*NUM);
+
+        for(int i=NUM-1; i>=0; i--) 
+          {
+          mEffects[i].move( new Static3D(i*w,(height-h)/2,0) );
+          mEffects[i].scale(factor);
+          }
+        }
          
-     mScreen.resize(width, height);
-     }
+      mScreen.resize(width, height);
+      }
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
-   public void onSurfaceCreated(GL10 glUnused, EGLConfig config)
-     {
-     Bitmap bitmap0= readBitmap(R.raw.dog);
-     Bitmap bitmap1= readBitmap(R.raw.face);
-     Bitmap bitmap2= readBitmap(R.raw.cat);
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      Bitmap bitmap0= readBitmap(R.raw.dog);
+      Bitmap bitmap1= readBitmap(R.raw.face);
+      Bitmap bitmap2= readBitmap(R.raw.cat);
       
-     bmpHeight = bitmap0.getHeight();
-     bmpWidth  = bitmap0.getWidth();
+      bmpHeight = bitmap0.getHeight();
+      bmpWidth  = bitmap0.getWidth();
 
-     if( mTexture==null )
-       {
-       mTexture = new DistortedTexture[NUM];
+      if( mTexture==null )
+        {
+        mTexture = new DistortedTexture[NUM];
 
-       for(int i=0; i<NUM; i++)
-         mTexture[i] = new DistortedTexture(bmpWidth,bmpHeight);
-       }
+        for(int i=0; i<NUM; i++)
+          mTexture[i] = new DistortedTexture(bmpWidth,bmpHeight);
+        }
 
-     mTexture[0].setTexture(bitmap0);
-     mTexture[1].setTexture(bitmap1);
-     mTexture[2].setTexture(bitmap2);
+      mTexture[0].setTexture(bitmap0);
+      mTexture[1].setTexture(bitmap1);
+      mTexture[2].setTexture(bitmap2);
 
-     MeshFlat mesh = new MeshFlat(30,30*bmpHeight/bmpWidth);
+      MeshFlat mesh = new MeshFlat(30,30*bmpHeight/bmpWidth);
 
-     mScreen.detachAll();
-     for(int i=NUM-1; i>=0; i--) mScreen.attach(mTexture[i], mEffects[i], mesh);
+      mScreen.detachAll();
+      for(int i=NUM-1; i>=0; i--) mScreen.attach(mTexture[i], mEffects[i], mesh);
 
-     DistortedEffects.enableEffect(EffectNames.SINK);
-     DistortedEffects.enableEffect(EffectNames.DISTORT);
+      DistortedEffects.enableEffect(EffectNames.SINK);
+      DistortedEffects.enableEffect(EffectNames.DISTORT);
 
-     try
-       {
-       Distorted.onCreate(mView.getContext());
-       }
-     catch(Exception ex)
-       {
-       android.util.Log.e("Renderer", ex.getMessage() );
-       }
-     }
+      try
+        {
+        Distorted.onCreate(mView.getContext());
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Renderer", ex.getMessage() );
+        }
+      }
 }
diff --git a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
index 5e7cade..4a074aa 100644
--- a/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
+++ b/src/main/java/org/distorted/examples/differenteffects/DifferentEffectsRenderer.java
@@ -111,24 +111,28 @@ class DifferentEffectsRenderer implements GLSurfaceView.Renderer
        {
        mEffects[i].abortEffects(EffectTypes.MATRIX);
        }
-
-     float qx = (float)width /bmpWidth;
-     float qy = (float)height/bmpHeight;
-
-     if( qx > NUM*qy )  // screen more 'horizontal' than NUM bitmaps next to each other
+      
+     if( (float)bmpHeight/(NUM*bmpWidth) > (float)height/width )
        {
-       for(int i=0; i<NUM; i++)
+       int w = (height*bmpWidth)/bmpHeight;
+       float factor = (float)height/bmpHeight;
+
+       for(int i=NUM-1; i>=0; i--)
          {
-         mEffects[i].move( new Static3D( qy*((0.5f+i)/NUM-0.5f), 0, 0) );
-         mEffects[i].scale( new Static3D( qy/qx, 1, 1) );
+         mEffects[i].move( new Static3D((width-NUM*w)/2 +i*w , 0, 0) );
+         mEffects[i].scale(factor);
          }
        }
      else
        {
-       for(int i=0; i<NUM; i++)
+       int w = width/NUM;
+       int h = (width*bmpHeight)/(bmpWidth*NUM);
+       float factor = (float)width/(bmpWidth*NUM);
+
+       for(int i=NUM-1; i>=0; i--)
          {
-         mEffects[i].move( new Static3D( (0.5f+i)/NUM-0.5f, 0, 0) );
-         mEffects[i].scale( new Static3D( 1.0f/NUM, (qx/qy)/NUM, 1) );
+         mEffects[i].move( new Static3D(i*w, (height-h)/2, 0) );
+         mEffects[i].scale(factor);
          }
        }
        
diff --git a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
index 7124790..3fb43d5 100644
--- a/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
+++ b/src/main/java/org/distorted/examples/effectqueue/EffectQueueRenderer.java
@@ -34,8 +34,10 @@ import org.distorted.library.MeshFlat;
 import org.distorted.library.DistortedTexture;
 import org.distorted.library.Distorted;
 import org.distorted.library.EffectNames;
+import org.distorted.library.EffectTypes;
 import org.distorted.library.message.EffectListener;
 import org.distorted.library.message.EffectMessage;
+import org.distorted.library.type.Static3D;
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
@@ -125,6 +127,8 @@ class EffectQueueRenderer implements GLSurfaceView.Renderer, EffectListener
 
   public void onSurfaceChanged(GL10 glUnused, int width, int height)
     {
+    mEffects.abortEffects(EffectTypes.MATRIX);
+    mEffects.scale( new Static3D((float)width/texWidth,(float)height/texHeight,1) );
     mScreen.resize(width,height);
     mView.setScreenSize(width,height);
     }
diff --git a/src/main/java/org/distorted/examples/fbo/FBORenderer.java b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
index 855e5a7..c255df2 100644
--- a/src/main/java/org/distorted/examples/fbo/FBORenderer.java
+++ b/src/main/java/org/distorted/examples/fbo/FBORenderer.java
@@ -103,11 +103,24 @@ class FBORenderer implements GLSurfaceView.Renderer
     
    public void onSurfaceChanged(GL10 glUnused, int width, int height)
       { 
-      float qx = (float)width /lisaWidth;
-      float qy = (float)height/lisaHeight;
-
       mEffects.abortEffects(EffectTypes.MATRIX);
-      mEffects.scale(  qx<qy ? (new Static3D(1,qx/qy,1)) : (new Static3D(qy/qx,1,1)) );
+         
+      if( (float)lisaHeight/lisaWidth > (float)height/width )
+        {
+        int w = (height*lisaWidth)/lisaHeight;
+        float factor = (float)height/lisaHeight;
+
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
+        }
+      else
+        {
+        int h = (width*lisaHeight)/lisaWidth;
+        float factor = (float)width/lisaWidth;
+
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
+        }
       
       mScreen.resize(width, height);
       }
@@ -151,6 +164,8 @@ class FBORenderer implements GLSurfaceView.Renderer
       mGridTexture.setTexture(bitmap2);
       DistortedEffects gridEffects = new DistortedEffects();
 
+      mEffects.abortAllEffects();
+
       mRoot = new DistortedNode(mLisaTexture, mEffects,new MeshFlat(1,1));
       mRoot.attach(mGridTexture,gridEffects,new MeshCubes(10,10,false));
 
@@ -159,14 +174,17 @@ class FBORenderer implements GLSurfaceView.Renderer
       mScreen.detachAll();
       mScreen.attach(mRoot);
 
-      gridEffects.scale(0.5f);
+      float factor = lisaWidth/(2.0f*gridWidth);
+
+      gridEffects.move( new Static3D( (lisaWidth-factor*gridWidth)/2,(lisaHeight-factor*gridHeight)/2,0) );
+      gridEffects.scale(factor);
 
       Dynamic1D rotDyn = new Dynamic1D(12000,0.0f);
       rotDyn.add(new Static1D(  0));
       rotDyn.add(new Static1D(360));
       rotDyn.setMode(Dynamic.MODE_JUMP);
 
-      gridEffects.rotate(rotDyn, new Static3D(1,0,0), new Static3D(0,0,1.0f/10) );
+      gridEffects.rotate(rotDyn, new Static3D(1,0,0), new Static3D(gridWidth/2,gridHeight/2,gridHeight/10) );
 
       Dynamic1D sinkDyn = new Dynamic1D(3000,0.0f);
       sinkDyn.add(new Static1D(1.0f));
diff --git a/src/main/java/org/distorted/examples/girl/GirlRenderer.java b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
index 687dd6b..bc9f8dc 100644
--- a/src/main/java/org/distorted/examples/girl/GirlRenderer.java
+++ b/src/main/java/org/distorted/examples/girl/GirlRenderer.java
@@ -159,11 +159,24 @@ class GirlRenderer implements GLSurfaceView.Renderer
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      float qx = (float)width /bmpWidth;
-      float qy = (float)height/bmpHeight;
-
       mEffects.abortEffects(EffectTypes.MATRIX);
-      mEffects.scale(  qx<qy ? (new Static3D(1,qx/qy,1)) : (new Static3D(qy/qx,1,1)) );
+      
+      if( (float)bmpHeight/bmpWidth > (float)height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        float factor = (float)height/bmpHeight;
+
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        float factor = (float)width/bmpWidth;
+
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
+        }
       
       mScreen.resize(width, height);
       }
diff --git a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
index 60e5593..0e39620 100644
--- a/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
+++ b/src/main/java/org/distorted/examples/listener/ListenerRenderer.java
@@ -110,11 +110,24 @@ class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
       { 
-      float qx = (float)width /bmpWidth;
-      float qy = (float)height/bmpHeight;
-
       mEffects.abortEffects(EffectTypes.MATRIX);
-      mEffects.scale(  qx<qy ? (new Static3D(1,qx/qy,1)) : (new Static3D(qy/qx,1,1)) );
+         
+      if( (float)bmpHeight/bmpWidth > (float)height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        float factor = (float)height/bmpHeight;
+
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        float factor = (float)width/bmpWidth;
+
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
+        }
       
       mScreen.resize(width, height);
       }
diff --git a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
index ce8ece8..4d7da15 100644
--- a/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
+++ b/src/main/java/org/distorted/examples/monalisa/MonaLisaRenderer.java
@@ -86,12 +86,23 @@ class MonaLisaRenderer implements GLSurfaceView.Renderer
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
     public void onSurfaceChanged(GL10 glUnused, int width, int height) 
-      {
-      float qx = (float)width /bmpWidth;
-      float qy = (float)height/bmpHeight;
-
+      { 
       mEffects.abortEffects(EffectTypes.MATRIX);
-      mEffects.scale(  qx<qy ? (new Static3D(1,qx/qy,1)) : (new Static3D(qy/qx,1,1)) );
+
+      if( (float)bmpHeight/bmpWidth > (float)height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        float factor = (float)height/bmpHeight;
+        mEffects.move( new Static3D((width-w)/2,0,0) );
+        mEffects.scale(factor);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        float factor = (float)width/bmpWidth;
+        mEffects.move( new Static3D(0,(height-h)/2,0) );
+        mEffects.scale(factor);
+        }
 
       mScreen.resize(width, height);
       }
diff --git a/src/main/java/org/distorted/examples/sink/SinkRenderer.java b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
index 0eda525..a112098 100644
--- a/src/main/java/org/distorted/examples/sink/SinkRenderer.java
+++ b/src/main/java/org/distorted/examples/sink/SinkRenderer.java
@@ -78,13 +78,26 @@ class SinkRenderer implements GLSurfaceView.Renderer
 ///////////////////////////////////////////////////////////////////////////////////////////////////
     
   public void onSurfaceChanged(GL10 glUnused, int width, int height) 
-    {
-    float qx = (float)width /bmpWidth;
-    float qy = (float)height/bmpHeight;
-
+    { 
     mEffects.abortEffects(EffectTypes.MATRIX);
-    mEffects.scale(  qx<qy ? (new Static3D(1,qx/qy,1)) : (new Static3D(qy/qx,1,1)) );
+         
+    if( (float)bmpHeight/bmpWidth > (float)height/width )
+      {
+      int w = (height*bmpWidth)/bmpHeight;
+      float factor = (float)height/bmpHeight;
 
+      mEffects.move( new Static3D((width-w)/2,0,0) );
+      mEffects.scale( factor );
+      }
+    else
+      {
+      int h = (width*bmpHeight)/bmpWidth;
+      float factor = (float)width/bmpWidth;
+
+      mEffects.move( new Static3D(0,(height-h)/2,0) );
+      mEffects.scale( factor );
+      }
+      
     mScreen.resize(width, height);
     }
 
diff --git a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
index e8ad3c0..ff45820 100644
--- a/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
+++ b/src/main/java/org/distorted/examples/starwars/StarWarsRenderer.java
@@ -207,26 +207,27 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
     if( mCrawlBackgroundTexture!=null ) mCrawlBackgroundTexture.markForDeletion();
     mCrawlBackgroundTexture = new DistortedTexture(w,(int)(h*Math.sin(angleA)/Math.sin(angleB)));
        
-    int randomTime;
-    float randomX, randomY, randomS, randomAlpha1, randomAlpha2;
-
-    float starScaleX = (float)mStarTexture.getWidth()/w;
-    float starScaleY = (float)mStarTexture.getHeight()/h;
-
+    int randomA, randomX, randomY, randomTime;
+    float randomS, randomAlpha1, randomAlpha2;
+       
+    Static3D center = new Static3D(0,0,0);
+    Static3D axis   = new Static3D(0,0,1);
     Static1D alphaNoise = new Static1D(0.4f);
 
     for(int i=0; i<NUM_STARS; i++)
       {
-      randomX = mRnd.nextFloat() -0.5f;
-      randomY = mRnd.nextFloat() -0.5f;
+      randomX = mRnd.nextInt(w);
+      randomY = mRnd.nextInt(h);
       randomS = 0.2f+ 0.8f*mRnd.nextFloat();
+      randomA = (int)(180*mRnd.nextFloat());
       randomAlpha1 = 0.2f + 0.8f*mRnd.nextFloat();
       randomAlpha2 = 0.8f + 0.2f*mRnd.nextFloat();
       randomTime = 500+mRnd.nextInt(2000);
       
       mStarEffects[i].move( new Static3D(randomX,randomY,0) );
-      mStarEffects[i].scale( new Static3D(randomS*starScaleX, randomS*starScaleY, 1) );
-
+      mStarEffects[i].scale(randomS);
+      mStarEffects[i].rotate( new Static1D(randomA), axis, center );
+      
       Dynamic1D di = new Dynamic1D(randomTime,0.0f);
       di.setNoise(alphaNoise);
       di.add(new Static1D(randomAlpha1));
@@ -236,17 +237,16 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
       
       mScreen.attach(mStarTexture, mStarEffects[i], mQuad);
       }
-
-    float qx = (float)mGFFATexture.getWidth()/w;
-    float qy = (float)mGFFATexture.getHeight()/h;
-
+      
+    float scale = (0.5f*w/mGFFATexture.getWidth());
+    
     Dynamic1D di = new Dynamic1D(6000,0.5f);
     di.add(new Static1D(1.0f));
     di.add(new Static1D(1.0f));
     di.add(new Static1D(0.0f));
     
-    mGFFAEffects.move( new Static3D(qx/2-0.3f,qy/2-0.16f,0) );
-    mGFFAEffects.scale( new Static3D(qx,qy,1) );
+    mGFFAEffects.move( new Static3D(w/5,h/3,0) );
+    mGFFAEffects.scale( new Static3D(scale,scale,scale) );
     mGFFAEffects.alpha(di);
       
     mScreen.attach(mGFFATexture, mGFFAEffects, mQuad);
@@ -380,18 +380,23 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
         mScreen.detach(mGFFAEffects);
         mGFFATexture.markForDeletion();
 
-        float qx= (float)mScreen.getWidth() /mLogoTexture.getWidth() ;
-        float qy= (float)mScreen.getHeight()/mLogoTexture.getHeight();
-
-        float initSize= 3.0f;
-        float finaSize= 0.1f;
+        int screenW=mScreen.getWidth();
+        int screenH=mScreen.getHeight();
+        
+        int logoW = mLogoTexture.getWidth();
+        int logoH = mLogoTexture.getHeight();
+      
+        int initSize= (int)(3.0f*screenW/logoW);
+        int finaSize= (int)(0.1f*screenW/logoW);
       
         Dynamic3D di = new Dynamic3D(10000,0.5f);
-        di.add(qx<qy ? (new Static3D(initSize,initSize*qx/qy,1)) : (new Static3D(initSize*qy/qx,initSize,1)));
-        di.add(qx<qy ? (new Static3D(finaSize,finaSize*qx/qy,1)) : (new Static3D(finaSize*qy/qx,finaSize,1)));
+        di.add(new Static3D(initSize,initSize,1));
+        di.add(new Static3D(finaSize,finaSize,1));
 
+        mLogoEffects.move( new Static3D(screenW/2,screenH/2,0) );
         mLogoEffects.scale(di);
-
+        mLogoEffects.move( new Static3D(-logoW/2,-logoH/2,0) );
+      
         mScreen.attach(mLogoTexture, mLogoEffects,mQuad);
         mLogoEffects.registerForMessages(this);
         }
@@ -407,21 +412,20 @@ class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
         int backH  = mCrawlBackgroundTexture.getHeight();
         float scale= (float)screenW/crawlW;
 
-        //mCrawlBackgroundEffects.move( new Static3D(0,screenH-backH,0) );
-        mCrawlBackgroundEffects.rotate( new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(0.5f,1.0f,0.0f) );
-        mCrawlBackgroundEffects.scale( new Static3D(1.0f, (float)backH/screenH,1.0f) );
+        mCrawlBackgroundEffects.move( new Static3D(0,screenH-backH,0) );
+        mCrawlBackgroundEffects.rotate( new Static1D(CRAWL_ANGLE), new Static3D(1,0,0), new Static3D(screenW/2,backH,0) );
 
         final int transpDist = 5;
         Static4D region = new Static4D(screenW/2,(1-transpDist)*backH,transpDist*backH,transpDist*backH);
-        //mCrawlBackgroundEffects.alpha(new Static1D(1-transpDist*0.6f), region, true);
+        mCrawlBackgroundEffects.alpha(new Static1D(1-transpDist*0.6f), region, true);
 
         Dynamic3D di = new Dynamic3D(70000,0.5f);
         di.add(new Static3D(screenW/2,+backH       , 0));
         di.add(new Static3D(screenW/2,-scale*crawlH, 0));
 
-        //mCrawlEffects.move(di);
-        //mCrawlEffects.scale( new Static3D(scale,scale,scale) );
-        //mCrawlEffects.move( new Static3D(-crawlW/2,0,0) );
+        mCrawlEffects.move(di);
+        mCrawlEffects.scale( new Static3D(scale,scale,scale) );
+        mCrawlEffects.move( new Static3D(-crawlW/2,0,0) );
         
         mBackground = mScreen.attach(mCrawlBackgroundTexture, mCrawlBackgroundEffects,mQuad);
         mBackground.attach(mCrawlTexture, mCrawlEffects,mQuad);
