commit 427ab7bfd394c54407b45b4ae194fa826e9638da
Author: Leszek Koltunski <leszek@distorted.org>
Date:   Wed May 25 20:56:12 2016 +0100

    Initial commit

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..59b3f7e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,45 @@
+# built application files
+*.apk
+*.ap_
+
+# files for the dex VM
+*.dex
+
+# Java class files
+*.class
+
+# built native files (uncomment if you build your own)
+# *.o
+# *.so
+
+# generated files
+bin/
+gen/
+
+# Ignore gradle files
+.gradle/
+build/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+# Proguard folder generated by Eclipse
+proguard/
+
+# Eclipse Metadata
+.metadata/
+
+# Mac OS X clutter
+*.DS_Store
+
+# Windows clutter
+Thumbs.db
+
+# Intellij IDEA (see https://intellij-support.jetbrains.com/entries/23393067)
+.idea/workspace.xml
+.idea/tasks.xml
+.idea/datasources.xml
+.idea/dataSources.ids
+
+# yes, ignore the .iml
+*.iml
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..3a58f4c
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,23 @@
+apply plugin: 'com.android.application'
+
+android {
+    compileSdkVersion 22
+    buildToolsVersion "23.0.3"
+
+    defaultConfig {
+        applicationId "org.distortedandroid.examples"
+        minSdkVersion 15
+        targetSdkVersion 23
+    }
+
+    buildTypes {
+        release {
+            minifyEnabled false
+            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
+        }
+    }
+}
+
+dependencies {
+    compile project(':distorted-library')
+}
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..f09a462
--- /dev/null
+++ b/src/main/AndroidManifest.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.distortedandroid.examples"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="23" />
+    <uses-feature android:glEsVersion="0x00020000" android:required="true" />
+
+    <application android:icon="@drawable/icon" android:label="@string/app_name" android:allowBackup="true" android:theme="@android:style/Theme.NoTitleBar.Fullscreen">
+        <activity android:name=".TableOfContents">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <activity android:name=".monalisa.MonaLisaActivity" />
+        <activity android:name=".sink.SinkActivity" />
+        <activity android:name=".bean.BeanActivity" />
+        <activity android:name=".fov.FOVActivity" />
+        <activity android:name=".deform.DeformActivity" />    
+        <activity android:name=".listener.ListenerActivity" />    
+        <activity android:name=".interpolator.InterpolatorActivity" />   
+        <activity android:name=".girl.GirlActivity" />   
+        <activity android:name=".macroblock.MacroblockActivity" /> 
+        <activity android:name=".movingeffects.MovingEffectsActivity" />    
+        <activity android:name=".differenteffects.DifferentEffectsActivity" />    
+        <activity android:name=".differentbitmaps.DifferentBitmapsActivity" />    
+        <activity android:name=".scratchpad.ScratchpadActivity" />    
+        <activity android:name=".check.CheckActivity" />    
+        <activity android:name=".fbo.FBOActivity" />    
+        <activity android:name=".starwars.StarWarsActivity" />      
+        <activity android:name=".olimpic.OlimpicActivity" />  
+        <activity android:name=".cubes.CubesActivity" />       
+        <activity android:name=".quaternion.QuaternionActivity" />          
+        <activity android:name=".effects3d.Effects3DActivity" />  
+    </application>
+</manifest>
diff --git a/src/main/java/org/distortedandroid/examples/TableOfContents.java b/src/main/java/org/distortedandroid/examples/TableOfContents.java
new file mode 100644
index 0000000..2c4e16e
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/TableOfContents.java
@@ -0,0 +1,262 @@
+package org.distortedandroid.examples;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import android.app.Activity;
+import android.app.ListActivity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.util.SparseArray;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.AdapterView.OnItemClickListener;
+import android.widget.SimpleAdapter;
+
+import org.distortedandroid.examples.R;
+import org.distortedandroid.examples.monalisa.MonaLisaActivity;
+import org.distortedandroid.examples.sink.SinkActivity;
+import org.distortedandroid.examples.fov.FOVActivity;
+import org.distortedandroid.examples.deform.DeformActivity;
+import org.distortedandroid.examples.listener.ListenerActivity;
+import org.distortedandroid.examples.interpolator.InterpolatorActivity;
+import org.distortedandroid.examples.girl.GirlActivity;
+import org.distortedandroid.examples.macroblock.MacroblockActivity;
+import org.distortedandroid.examples.movingeffects.MovingEffectsActivity;
+import org.distortedandroid.examples.olimpic.OlimpicActivity;
+import org.distortedandroid.examples.differenteffects.DifferentEffectsActivity;
+import org.distortedandroid.examples.differentbitmaps.DifferentBitmapsActivity;
+import org.distortedandroid.examples.scratchpad.ScratchpadActivity;
+import org.distortedandroid.examples.check.CheckActivity;
+import org.distortedandroid.examples.bean.BeanActivity;
+import org.distortedandroid.examples.fbo.FBOActivity;
+import org.distortedandroid.examples.starwars.StarWarsActivity;
+import org.distortedandroid.examples.cubes.CubesActivity;
+import org.distortedandroid.examples.quaternion.QuaternionActivity;
+import org.distortedandroid.examples.effects3d.Effects3DActivity;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class TableOfContents extends ListActivity 
+  {
+  private static final String ITEM_IMAGE = "item_image";
+  private static final String ITEM_TITLE = "item_title";
+  private static final String ITEM_SUBTITLE = "item_subtitle"; 
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+  @Override
+  public void onCreate(Bundle savedInstanceState) 
+   {
+   super.onCreate(savedInstanceState);
+   setTitle(R.string.toc);
+   setContentView(R.layout.table_of_contents);
+      
+   final List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();
+   final SparseArray<Class<? extends Activity>> activityMapping = new SparseArray<Class<? extends Activity>>();
+      
+   int i = 0;
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_monalisa);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_monalisa));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_monalisa_subtitle));
+      data.add(item);
+      activityMapping.put(i++, MonaLisaActivity.class);        
+   }
+      
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_sink);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_sink));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_sink_subtitle));
+      data.add(item);
+      activityMapping.put(i++, SinkActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_bean);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_bean));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_bean_subtitle));
+      data.add(item);
+      activityMapping.put(i++, BeanActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_fov);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_fov));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_fov_subtitle));
+      data.add(item);
+      activityMapping.put(i++, FOVActivity.class);
+   }
+         
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_deform);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_deform));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_deform_subtitle));
+      data.add(item);
+      activityMapping.put(i++, DeformActivity.class);
+   }
+  
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_listener);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_listener));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_listener_subtitle));
+      data.add(item);
+      activityMapping.put(i++, ListenerActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_interpolator);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_interpolator));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_interpolator_subtitle));
+      data.add(item);
+      activityMapping.put(i++, InterpolatorActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_girl);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_girl));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_girl_subtitle));
+      data.add(item);
+      activityMapping.put(i++, GirlActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_macroblock);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_macroblock));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_macroblock_subtitle));
+      data.add(item);
+      activityMapping.put(i++, MacroblockActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_movingeffects);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_movingeffects));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_movingeffects_subtitle));
+      data.add(item);
+      activityMapping.put(i++, MovingEffectsActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_differenteffects);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_differenteffects));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_differenteffects_subtitle));
+      data.add(item);
+      activityMapping.put(i++, DifferentEffectsActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_differentbitmaps);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_differentbitmaps));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_differentbitmaps_subtitle));
+      data.add(item);
+      activityMapping.put(i++, DifferentBitmapsActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_scratchpad);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_scratchpad));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_scratchpad_subtitle));
+      data.add(item);
+      activityMapping.put(i++, ScratchpadActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_check);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_check));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_check_subtitle));
+      data.add(item);
+      activityMapping.put(i++, CheckActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_fbo);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_fbo));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_fbo_subtitle));
+      data.add(item);
+      activityMapping.put(i++, FBOActivity.class);
+   }
+      
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_starwars);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_starwars));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_starwars_subtitle));
+      data.add(item);
+      activityMapping.put(i++, StarWarsActivity.class);
+   }
+         
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_olimpic);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_olimpic));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_olimpic_subtitle));
+      data.add(item);
+      activityMapping.put(i++, OlimpicActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_quaternion);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_quaternion));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_quaternion_subtitle));
+      data.add(item);
+      activityMapping.put(i++, QuaternionActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_cubes);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_cubes));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_cubes_subtitle));
+      data.add(item);
+      activityMapping.put(i++, CubesActivity.class);
+   }
+   
+   {
+      final Map<String, Object> item = new HashMap<String, Object>();
+      item.put(ITEM_IMAGE, R.drawable.icon_example_matrix3d);
+      item.put(ITEM_TITLE, (i+1)+". "+getText(R.string.example_effects3d));
+      item.put(ITEM_SUBTITLE, getText(R.string.example_effects3d_subtitle));
+      data.add(item);
+      activityMapping.put(i++, Effects3DActivity.class);
+   }
+     
+   final SimpleAdapter dataAdapter = new SimpleAdapter(this, data, R.layout.toc_item, new String[] {ITEM_IMAGE, ITEM_TITLE, ITEM_SUBTITLE}, new int[] {R.id.Image, R.id.Title, R.id.SubTitle});
+   setListAdapter(dataAdapter);  
+      
+   getListView().setOnItemClickListener(new OnItemClickListener() 
+     {
+     @Override
+     public void onItemClick(AdapterView<?> parent, View view, int position, long id) 
+      {
+      final Class<? extends Activity> activityToLaunch = activityMapping.get(position);
+            
+      if (activityToLaunch != null)
+        {
+        final Intent launchIntent = new Intent(TableOfContents.this, activityToLaunch);
+        startActivity(launchIntent);
+        }            
+      }
+     });
+   }  
+  }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distortedandroid/examples/bean/BeanActivity.java b/src/main/java/org/distortedandroid/examples/bean/BeanActivity.java
new file mode 100644
index 0000000..fb247be
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/bean/BeanActivity.java
@@ -0,0 +1,52 @@
+
+package org.distortedandroid.examples.bean;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class BeanActivity extends Activity 
+{
+    private BeanSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new BeanSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/bean/BeanRenderer.java b/src/main/java/org/distortedandroid/examples/bean/BeanRenderer.java
new file mode 100644
index 0000000..fb00191
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/bean/BeanRenderer.java
@@ -0,0 +1,140 @@
+
+package org.distortedandroid.examples.bean;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Interpolator2D;
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float4D;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class BeanRenderer implements GLSurfaceView.Renderer 
+{
+   private GLSurfaceView mView;
+   private DistortedBitmap mBean;
+   private Float2D pLeft, pRight;
+   private Interpolator2D iLeft, iRight;
+   private Float4D rLeft, rRight;
+   private int bmpHeight, bmpWidth;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public BeanRenderer(GLSurfaceView v) 
+      {
+      mView = v;
+     
+      pLeft = new Float2D(100, 199);
+      pRight= new Float2D(230, 150);
+      
+      rLeft = new Float4D(-9,-31,35,35);
+      rRight= new Float4D(-9,-31,35,35);
+     
+      iLeft = new Interpolator2D();
+      iRight= new Interpolator2D();
+     
+      iLeft.setCount(0.0f);
+      iRight.setCount(0.0f);
+      iLeft.setDuration(1500);
+      iRight.setDuration(1500);
+      
+      Float2D p1 = new Float2D(0,0);
+      Float2D p2 = new Float2D(-10,-34);
+      
+      iLeft.add(p1);
+      iLeft.add(p1);
+      iLeft.add(p1);
+      iLeft.add(p1);
+      iLeft.add(p2);
+      iLeft.add(p2);
+      
+      iRight.add(p1);
+      iRight.add(p2);
+      iRight.add(p2);
+      iRight.add(p1);
+      iRight.add(p1);
+      iRight.add(p1);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      mBean.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      mBean.abortAllEffects(Distorted.TYPE_MATR);  
+         
+      if( bmpHeight/bmpWidth > height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        mBean.move((width-w)/2 ,0, 0);
+        mBean.scale((float)height/bmpHeight);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        mBean.move(0 ,(height-h)/2, 0);
+        mBean.scale((float)width/bmpWidth);
+        }
+      
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.bean);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      bmpHeight = bitmap.getHeight();
+      bmpWidth  = bitmap.getWidth();
+      
+      mBean = new DistortedBitmap(bitmap, 10);     
+      mBean.distort(iLeft , rLeft , pLeft );
+      mBean.distort(iRight, rRight, pRight);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Bean", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/bean/BeanSurfaceView.java b/src/main/java/org/distortedandroid/examples/bean/BeanSurfaceView.java
new file mode 100644
index 0000000..0ad5e55
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/bean/BeanSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.bean;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class BeanSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public BeanSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new BeanRenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/check/CheckActivity.java b/src/main/java/org/distortedandroid/examples/check/CheckActivity.java
new file mode 100644
index 0000000..cc9b8ab
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/check/CheckActivity.java
@@ -0,0 +1,121 @@
+
+package org.distortedandroid.examples.check;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.examples.R;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.widget.NumberPicker;
+import android.widget.NumberPicker.OnValueChangeListener;
+import android.view.View;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class CheckActivity extends Activity
+{
+    private NumberPicker mVPicker, mFPicker;
+    private static int maxV, maxF;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      setContentView(R.layout.check1layout);
+       
+      mVPicker = (NumberPicker)findViewById(R.id.check1NumberPickerVertex);
+      mFPicker = (NumberPicker)findViewById(R.id.check1NumberPickerFragment);
+      
+      mVPicker.setMaxValue(1000);
+      mVPicker.setMinValue(   0);
+      mFPicker.setMaxValue(1000);
+      mFPicker.setMinValue(   0);
+     
+      mVPicker.setOnValueChangedListener(new OnValueChangeListener() 
+         {
+         @Override
+         public void onValueChange(NumberPicker picker, int oldVal, int newVal) 
+           { 
+           maxV = newVal;
+           }
+         });
+      
+      mFPicker.setOnValueChangedListener(new OnValueChangeListener() 
+         {
+         @Override
+         public void onValueChange(NumberPicker picker, int oldVal, int newVal) 
+           { 
+           maxF = newVal;
+           }
+         });
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.checkSurfaceView);
+      if( mView!=null ) mView.onPause();
+      
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.checkSurfaceView);
+      if( mView!=null ) mView.onResume();    
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) 
+      {
+      super.onWindowFocusChanged(hasFocus);
+
+      mVPicker.setValue(1);
+      mFPicker.setValue(1);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static int getMaxV()
+      {
+      return maxV;
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static int getMaxF()
+      {
+      return maxF;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void Check(View v)
+      {
+      setContentView(R.layout.check2layout);
+      }     
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/check/CheckRenderer.java b/src/main/java/org/distortedandroid/examples/check/CheckRenderer.java
new file mode 100644
index 0000000..fff846e
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/check/CheckRenderer.java
@@ -0,0 +1,165 @@
+
+package org.distortedandroid.examples.check;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+
+import android.app.AlertDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CheckRenderer implements GLSurfaceView.Renderer 
+{
+    private GLSurfaceView mView;
+    private DistortedBitmap mSuccess;
+    private Float2D pUp, pDown;
+    private Float3D vUp, vDown;
+    
+    private int bmpHeight, bmpWidth;
+    
+    public static String compilationResult;
+    public static String compilationTitle;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public CheckRenderer(GLSurfaceView view) 
+      { 
+      mView = view;
+    
+      Distorted.setMaxVertex(CheckActivity.getMaxV());
+      Distorted.setMaxFragment(CheckActivity.getMaxF());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+    
+      mSuccess.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      mSuccess.abortAllEffects(Distorted.TYPE_MATR);  
+      
+      if( bmpHeight/bmpWidth > height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        mSuccess.move((width-w)/2 ,0, 0);
+        mSuccess.scale((float)height/bmpHeight);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        mSuccess.move(0 ,(height-h)/2, 0);
+        mSuccess.scale((float)width/bmpWidth);
+        }
+      
+      Distorted.onSurfaceChanged(width, height);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {  
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.success);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      bmpHeight = bitmap.getHeight();
+      bmpWidth  = bitmap.getWidth();
+       
+      pDown = new Float2D(bmpWidth/2,        0);
+      pUp   = new Float2D(bmpWidth/2,bmpHeight);
+      
+      vUp   = new Float3D( 0,+bmpHeight,0);
+      vDown = new Float3D( 0,-bmpHeight,0);
+      
+      mSuccess = new DistortedBitmap(bitmap, 30);  
+      mSuccess.deform(  vUp,   pUp, 2000, 0.0f);
+      mSuccess.deform(vDown, pDown, 2000, 0.0f);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        compilationTitle = ex.getClass().getSimpleName();
+        compilationResult= ex.getMessage();
+      
+        String ver;
+      
+        ver = GLES20.glGetString(GLES20.GL_SHADING_LANGUAGE_VERSION);   
+        compilationResult += "\n\nGLSL version: "+(ver==null ? "null" : ver);
+        ver = GLES20.glGetString(GLES20.GL_VERSION);  
+        compilationResult += "\nGL version: "+(ver==null ? "null" : ver);
+        ver = GLES20.glGetString(GLES20.GL_VENDOR);   
+        compilationResult += "\nGL vendor: "+(ver==null ? "null" : ver);
+        ver = GLES20.glGetString(GLES20.GL_RENDERER);    
+        compilationResult += "\nGL renderer: "+(ver==null ? "null" : ver);
+      
+        CheckActivity act = (CheckActivity)mView.getContext();
+      
+        act.runOnUiThread(new Runnable() 
+          {
+          public void run() 
+            {
+            Context context = mView.getContext();
+      
+            AlertDialog.Builder builder = new AlertDialog.Builder(context);
+            builder.setTitle(compilationTitle);
+            builder.setMessage(compilationResult);
+            builder.setCancelable(true);
+           
+            builder.setOnCancelListener(new DialogInterface.OnCancelListener() 
+              {
+              @Override
+              public void onCancel(DialogInterface dialog) 
+                {
+                ((CheckActivity)mView.getContext()).finish();
+                }
+              });
+            
+            AlertDialog alert = builder.create();
+            alert.show();
+            }
+          });
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/check/CheckSurfaceView.java b/src/main/java/org/distortedandroid/examples/check/CheckSurfaceView.java
new file mode 100644
index 0000000..67213e3
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/check/CheckSurfaceView.java
@@ -0,0 +1,37 @@
+
+package org.distortedandroid.examples.check;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.util.AttributeSet;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CheckSurfaceView extends GLSurfaceView 
+{
+    private CheckRenderer renderer;
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public CheckSurfaceView(Context c, AttributeSet attrs) 
+      {
+      super(c, attrs);
+    
+      if(!isInEditMode())
+        {
+        setEGLContextClientVersion(2);
+        
+        if( Build.FINGERPRINT.startsWith("generic") )
+          { 
+          setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+          }
+    
+        renderer = new CheckRenderer(this);
+        setRenderer(renderer);
+        }
+      }
+
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/main/java/org/distortedandroid/examples/cubes/CubesActivity.java b/src/main/java/org/distortedandroid/examples/cubes/CubesActivity.java
new file mode 100644
index 0000000..c0e6941
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/cubes/CubesActivity.java
@@ -0,0 +1,198 @@
+
+package org.distortedandroid.examples.cubes;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.examples.R;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.NumberPicker;
+import android.widget.NumberPicker.OnValueChangeListener;
+import android.widget.TableRow;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class CubesActivity extends Activity implements View.OnClickListener
+{
+    private static int mNumCols = 3;
+    private static int mNumRows = 3;
+    
+    private static final int COLOR_OFF = 0xffffe81f;
+    private static final int COLOR_ON  = 0xff0000ff;
+    
+    private NumberPicker mColsPicker, mRowsPicker;
+    private LinearLayout mLay;
+    private static boolean[] mShape;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle savedState) 
+      {
+      super.onCreate(savedState);
+
+      setContentView(R.layout.cubes1layout);
+      
+      mLay = (LinearLayout)findViewById(R.id.buttongrid);
+      
+      mColsPicker = (NumberPicker)findViewById(R.id.colsPicker);
+      mRowsPicker = (NumberPicker)findViewById(R.id.rowsPicker);
+      
+      mColsPicker.setMaxValue(10);
+      mColsPicker.setMinValue( 0);
+      mRowsPicker.setMaxValue(10);
+      mRowsPicker.setMinValue( 0);
+     
+      mColsPicker.setOnValueChangedListener(new OnValueChangeListener() 
+         {
+         @Override
+         public void onValueChange(NumberPicker picker, int oldVal, int newVal) 
+           { 
+           setGrid();
+           }
+         });
+      
+      mRowsPicker.setOnValueChangedListener(new OnValueChangeListener() 
+         {
+         @Override
+         public void onValueChange(NumberPicker picker, int oldVal, int newVal) 
+           { 
+           setGrid();
+           }
+         });
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static int getCols()
+      {
+      return mNumCols; 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static String getShape()
+      {
+      String str = ""; 
+       
+      for(int i=0; i<mNumRows*mNumCols; i++)
+        str += mShape[i] ? "1" : "0";
+      
+      //android.util.Log.d("CUBES", str);
+      
+      return str; 
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void setGrid()
+      {
+      mNumCols = mColsPicker.getValue();
+      mNumRows = mRowsPicker.getValue();
+      
+      int width = mLay.getWidth();
+      int height= mLay.getHeight();
+      int w = mNumCols>0 ? (width / mNumCols) -10 : 0;
+      int h = mNumRows>0 ? (height/ mNumRows) -10 : 0;
+      int size= w<h ? w:h;
+      int pad = size/20;
+     
+      mLay.removeAllViews();
+      
+      mShape = new boolean[mNumRows*mNumCols];
+
+      TableRow.LayoutParams p = new android.widget.TableRow.LayoutParams();
+          
+      p.rightMargin  = pad;
+      p.leftMargin   = pad;
+      p.topMargin    = pad;
+      p.bottomMargin = pad;
+      p.height       = size;
+      p.width        = size;
+      
+      for (int rows=0; rows<mNumRows; rows++) 
+        {
+        TableRow tr = new TableRow(this);
+        tr.setGravity(Gravity.CENTER);
+        
+        for(int cols=0; cols<mNumCols; cols++) 
+          {
+          Button b = new Button(this);
+          b.setOnClickListener(this);
+          b.setId(rows*mNumCols+cols);
+          b.setLayoutParams(p);          
+          b.setBackgroundColor(COLOR_OFF);
+          tr.addView(b, p);
+          mShape[rows*mNumCols+cols] = false;
+          }
+        
+        mLay.addView(tr);
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onClick(View view) 
+      {
+      Button tmp = (Button)view;  
+      int id = tmp.getId();
+      mShape[id] = !mShape[id];
+      tmp.setBackgroundColor(mShape[id] ? COLOR_ON:COLOR_OFF);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) 
+      {
+      super.onWindowFocusChanged(hasFocus);
+
+      mColsPicker.setValue(mNumCols);
+      mRowsPicker.setValue(mNumRows);
+      
+      if( hasFocus ) setGrid();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.cubesSurfaceView);
+      if( mView!=null ) mView.onPause();
+        
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.cubesSurfaceView);
+      if( mView!=null ) mView.onResume();  
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void Continue(View v)
+      {   
+      setContentView(R.layout.cubes2layout);
+      }     
+}
diff --git a/src/main/java/org/distortedandroid/examples/cubes/CubesRenderer.java b/src/main/java/org/distortedandroid/examples/cubes/CubesRenderer.java
new file mode 100644
index 0000000..abe1e7e
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/cubes/CubesRenderer.java
@@ -0,0 +1,135 @@
+
+package org.distortedandroid.examples.cubes;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.InterpolatorQuat;
+import org.distortedandroid.library.DistortedCubes;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Distorted;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CubesRenderer implements GLSurfaceView.Renderer 
+{
+	private static final int SIZE = 100;
+	
+	private int mCols, mRows;
+	
+    private GLSurfaceView mView;
+    private DistortedCubes mCubes;
+    private InterpolatorQuat mQuatInt1, mQuatInt2;
+    
+    Float4D mQuat1, mQuat2;
+    int mScreenMin;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public CubesRenderer(GLSurfaceView v) 
+      {
+      mView = v;
+      
+      String shape = CubesActivity.getShape();
+      
+      mCols = CubesActivity.getCols();
+      mRows = shape.length() / mCols;
+      
+      mCubes = new DistortedCubes( mCols, shape, SIZE);
+      
+      mQuat1 = new Float4D(0,0,0,1);  // unity
+      mQuat2 = new Float4D(0,0,0,1);  // quaternions
+      
+      mQuatInt1 = new InterpolatorQuat();
+      mQuatInt2 = new InterpolatorQuat();
+      mQuatInt1.setDuration(0);
+      mQuatInt2.setDuration(0);
+      mQuatInt1.setCount(0.5f);
+      mQuatInt2.setCount(0.5f);
+      
+      mQuatInt1.add(mQuat1);
+      mQuatInt2.add(mQuat2);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      mCubes.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      {
+      mScreenMin = width<height ? width:height;
+    	
+      mCubes.abortAllEffects(Distorted.TYPE_MATR);  
+
+      if( mRows/mCols > height/width )
+        {
+        int w = (height*mRows)/mCols;
+        mCubes.move((width-w)/2 ,0, 0);
+        mCubes.scale((float)height/(mRows*SIZE));
+        }  
+      else
+        {   
+        int h = (width*mRows)/mCols;
+        mCubes.move(0 ,(height-h)/2, 0);
+        mCubes.scale((float)width/(mCols*SIZE));
+        }
+    
+      Float3D center = new Float3D(mCols*SIZE/2,mRows*SIZE/2, 0);
+      
+      mCubes.quaternion(center, mQuatInt1);
+      mCubes.quaternion(center, mQuatInt2);
+       
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.grid);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      mCubes.setBitmap(bitmap);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Cubes", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/cubes/CubesSurfaceView.java b/src/main/java/org/distortedandroid/examples/cubes/CubesSurfaceView.java
new file mode 100644
index 0000000..99c9df6
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/cubes/CubesSurfaceView.java
@@ -0,0 +1,109 @@
+
+package org.distortedandroid.examples.cubes;
+
+import org.distortedandroid.examples.R;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.widget.Toast;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class CubesSurfaceView extends GLSurfaceView 
+{
+    int mX, mY;
+    CubesRenderer mRenderer;
+	
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public CubesSurfaceView(Context c, AttributeSet attrs) 
+      {
+      super(c,attrs);
+    
+      mX = -1;
+      mY = -1;
+      
+      if(!isInEditMode())
+        {
+        setEGLContextClientVersion(2);
+        
+        if( Build.FINGERPRINT.startsWith("generic") )
+          { 
+          setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+          }
+    
+        mRenderer = new CubesRenderer(this);
+        
+        setRenderer(mRenderer);
+        
+        Toast.makeText(c, R.string.example_cubes_toast , Toast.LENGTH_SHORT).show();   
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override public boolean onTouchEvent(MotionEvent event) 
+      {
+      int action = event.getAction();
+      int x = (int)event.getX();
+      int y = (int)event.getY();
+           
+      switch(action)
+         {
+         case MotionEvent.ACTION_DOWN: mX = x;
+                                       mY = y;
+                                       break;
+                                       
+         case MotionEvent.ACTION_MOVE: if( mX>=0 && mY>= 0 )
+                                         {
+                                         float px = mY-y;
+                                         float py = mX-x;
+                                         float pz = 0;
+                                         float plen = (float)Math.sqrt(px*px + py*py + pz*pz);
+                                         
+                                         if( plen>0 )
+                                           {
+                                           px /= plen;
+                                           py /= plen;
+                                           pz /= plen;
+
+                                           float cosA = (float)Math.cos(plen*3.14f/mRenderer.mScreenMin);
+                                           float sinA = (float)Math.sqrt(1-cosA*cosA);
+                                         
+                                           mRenderer.mQuat1.set(px*sinA, py*sinA, pz*sinA, cosA);
+                                           }
+                                         }                             
+                                       break;
+                                       
+         case MotionEvent.ACTION_UP  : mX = -1;
+                                       mY = -1;
+        	                           
+                                       float qx = mRenderer.mQuat1.getX();
+                                       float qy = mRenderer.mQuat1.getY();
+                                       float qz = mRenderer.mQuat1.getZ();
+                                       float qw = mRenderer.mQuat1.getW();
+
+                                       float rx = mRenderer.mQuat2.getX();
+                                       float ry = mRenderer.mQuat2.getY();
+                                       float rz = mRenderer.mQuat2.getZ();
+                                       float rw = mRenderer.mQuat2.getW();
+
+                                       float tx = rw*qx - rz*qy + ry*qz + rx*qw;
+                                       float ty = rw*qy + rz*qx + ry*qw - rx*qz;
+                                       float tz = rw*qz + rz*qw - ry*qx + rx*qy;
+                                       float tw = rw*qw - rz*qz - ry*qy - rx*qx;
+                                       
+                                       mRenderer.mQuat1.set(0f, 0f, 0f, 1f);
+                                       mRenderer.mQuat2.set(tx, ty, tz, tw);
+                                       
+                                       break;
+         }
+             
+      return true;
+      }
+         
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/deform/DeformActivity.java b/src/main/java/org/distortedandroid/examples/deform/DeformActivity.java
new file mode 100644
index 0000000..c569864
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/deform/DeformActivity.java
@@ -0,0 +1,124 @@
+
+package org.distortedandroid.examples.deform;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.examples.R;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.RadioButton;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class DeformActivity extends Activity implements OnSeekBarChangeListener
+{
+    private SeekBar barR;
+    private TextView textR;
+    private RadioButton effect;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      setContentView(R.layout.deformlayout);
+       
+      barR = (SeekBar)findViewById(R.id.deformSeekRadius);
+      barR.setOnSeekBarChangeListener(this); 
+        
+      textR = (TextView)findViewById(R.id.deformTextRadius);
+     
+      barR.setProgress(50);
+      
+      textR.setText("Radius: 50");
+      
+      effect = (RadioButton)findViewById(R.id.deformDistortButton);
+      effect.setChecked(true);
+      DeformRenderer.setMode(DeformRenderer.MODE_DISTORT);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      DeformRenderer.onPause();
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.deformSurfaceView);
+      mView.onPause();
+      
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.deformSurfaceView);
+      mView.onResume();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      android.util.Log.e("activity","onDestroy");  
+      
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void Distort(View v)
+      {
+      DeformRenderer.setMode(DeformRenderer.MODE_DISTORT);
+      }     
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void Deform(View v)
+      {
+      DeformRenderer.setMode(DeformRenderer.MODE_DEFORM);
+      }       
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void Shear(View v)
+      {
+      DeformRenderer.setMode(DeformRenderer.MODE_SHEAR);
+      }       
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onProgressChanged(SeekBar bar, int progress, boolean fromUser) 
+      {
+      switch (bar.getId()) 
+        {
+        case R.id.deformSeekRadius: DeformRenderer.setRegionRadius(progress);
+                              textR.setText("Radius: "+progress);
+                              break;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void onStartTrackingTouch(SeekBar bar) { }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void onStopTrackingTouch(SeekBar bar)  { }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/deform/DeformRenderer.java b/src/main/java/org/distortedandroid/examples/deform/DeformRenderer.java
new file mode 100644
index 0000000..8bf698b
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/deform/DeformRenderer.java
@@ -0,0 +1,292 @@
+
+package org.distortedandroid.examples.deform;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Interpolator2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DeformRenderer implements GLSurfaceView.Renderer 
+{
+   public static final int MODE_DISTORT= 0;
+   public static final int MODE_DEFORM = 1;
+   public static final int MODE_SHEAR  = 2;
+    
+   private static final int NUM_VECTORS = 8;
+   private static final int NUMLINES = 10;
+   private static final int NUMFRAMES =10;
+
+   private GLSurfaceView mView;
+   private DistortedBitmap fps;
+   private DistortedBitmap stretch;
+   private Float3D touchPoint;
+   private static Interpolator2D di;
+   private static Float3D[] v;
+   private static Float4D dr;
+   private Canvas fpsCanvas;
+   private Bitmap fpsBitmap, stretchBitmap;
+   private int scrHeight, scrWidth;
+   private Paint mPaint;
+   private int fpsH, fpsW;
+   private String fpsString = "";
+   private long lastTime=0;
+   private long[] durations;
+   private int currDuration;
+   private long shearID=0;
+    
+   private static int mMode = MODE_DISTORT;
+   private static boolean bitmapCreated = false;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public DeformRenderer(GLSurfaceView view) 
+      { 
+      mView = view;
+      
+      dr = new Float4D(0,0,0,0);
+     
+      di = new Interpolator2D();
+      di.setMode(Interpolator2D.MODE_PATH);
+      di.setCount(0.5f);
+      di.setDuration(NUM_VECTORS*500);
+      
+      v = new Float3D[NUM_VECTORS];
+      
+      for(int i=0; i<NUM_VECTORS; i++)
+        {
+        v[i] = new Float3D(0,0,0);  
+        di.add(v[i]);
+        }
+      
+      durations = new long[NUMFRAMES+1];
+      currDuration = 0;
+      
+      for(int i=0; i<NUMFRAMES+1; i++)
+        {
+        durations[i]=0;   
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public static void setMode(int mode)
+      {
+      mMode = mode;  
+      }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public static void setRegionRadius(int r)
+      {
+      dr.set(0,0,r); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static void onPause()
+      {
+      bitmapCreated = false;  
+      }
+      
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+    
+      long time = System.currentTimeMillis();
+      
+      stretch.draw(time);
+      
+      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);
+      
+      computeFPS(time);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      scrHeight = height;
+      scrWidth  = width;
+      
+      Distorted.onSurfaceChanged(width, height);
+      
+      if( bitmapCreated==false )
+        {
+        createBitmap(scrWidth/2,scrHeight/2);
+        stretch.move(scrWidth/4,scrHeight/4,0);
+        fps.move(5,5,0);
+        bitmapCreated=true;
+        }
+      else
+        {
+        stretch.abortAllEffects(Distorted.TYPE_FRAG|Distorted.TYPE_VERT);
+        stretch.abortEffect(shearID);
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {  
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("DeformRenderer", ex.toString() );
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void createBitmap(int w, int h)
+      {  
+      Canvas stretchCanvas;   
+      
+      mPaint = new Paint();
+      stretch = new DistortedBitmap(w,h, 50);   
+      stretchBitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
+      stretchCanvas = new Canvas(stretchBitmap);
+      
+      fpsW = scrWidth/5;
+      fpsH = fpsW/2;
+        
+      mPaint.setAntiAlias(true);
+      mPaint.setTextAlign(Paint.Align.CENTER);
+      mPaint.setTextSize(2*fpsH/3);
+      mPaint.setColor(0xff008800);
+      mPaint.setStyle(Style.FILL);
+      stretchCanvas.drawRect(0, 0, w, h, mPaint);
+      mPaint.setColor(0xffffffff);
+      
+      for(int i=0; i<=NUMLINES ; i++ )
+        {
+        stretchCanvas.drawRect(w*i/NUMLINES - 1,                0,  w*i/NUMLINES + 1,  h               , mPaint);
+        stretchCanvas.drawRect(               0, h *i/NUMLINES -1,  w               ,  h*i/NUMLINES + 1, mPaint);  
+        }
+        
+      touchPoint= new Float3D(0,0,0);
+        
+      fps = new DistortedBitmap( fpsW, fpsH, 2);
+      fpsBitmap = Bitmap.createBitmap(fpsW,fpsH, Bitmap.Config.ARGB_8888);
+      fpsCanvas = new Canvas(fpsBitmap);
+        
+      stretch.setBitmap(stretchBitmap);
+      fps.setBitmap(fpsBitmap);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void down(int x, int y)
+      {
+      stretch.abortAllEffects(Distorted.TYPE_FRAG|Distorted.TYPE_VERT);  
+      stretch.abortEffect(shearID);
+
+      int xt = x-scrWidth/4;
+      int yt = y-scrHeight/4;
+      
+      if( xt<0 ) xt=0;
+      if( xt>scrWidth/2 ) xt=scrWidth/2;
+      if( yt<0 ) yt=0;
+      if( yt>scrHeight/2 ) yt=scrHeight/2;
+      
+      touchPoint.set(xt,yt,0);
+      
+      v[0].set(0,0,0);
+      
+      switch(mMode)
+        {
+        case MODE_DISTORT: stretch.distort(v[0], dr, touchPoint, 0, 0.5f);
+                           break;
+        case MODE_DEFORM : stretch.deform( v[0], touchPoint);
+                           break;
+        case MODE_SHEAR  : shearID = stretch.shear(touchPoint,v[0]);
+                           break;
+        }                   
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void move(int x, int y)
+      {
+      float fx = x;
+      float fy = y;
+      
+      if( mMode==MODE_SHEAR )
+        {
+        fx /= (scrWidth/2);
+        fy /= (scrHeight/2);
+        }
+      
+      v[0].set(fx,fy);
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void up()
+      {
+      stretch.abortAllEffects(Distorted.TYPE_FRAG|Distorted.TYPE_VERT);
+      stretch.abortEffect(shearID);
+      
+      float damp = -0.65f;
+      
+      for(int i=1; i<NUM_VECTORS-1; i++)
+        {
+        v[i].set( v[i-1].getX()*damp, v[i-1].getY()*damp );
+        }
+      v[NUM_VECTORS-1].set(0,0);
+      
+      switch(mMode)
+        {
+        case MODE_DISTORT: stretch.distort(di, dr, touchPoint);
+                           break;
+        case MODE_DEFORM : stretch.deform( di, touchPoint);
+                           break;
+        case MODE_SHEAR  : shearID = stretch.shear(touchPoint,di); 
+                           break;
+        }      
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void computeFPS(long currentTime)
+      {
+      if( lastTime!=0 )
+        {
+        currDuration++;
+        if( currDuration>=NUMFRAMES ) currDuration = 0;  
+        durations[NUMFRAMES] += ((currentTime-lastTime)-durations[currDuration]);
+        durations[currDuration] = currentTime-lastTime;
+
+        fpsString = "" + ((int)(10000.0f*NUMFRAMES/durations[NUMFRAMES]))/10.0f;
+        }
+      
+      lastTime = currentTime;   
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/deform/DeformSurfaceView.java b/src/main/java/org/distortedandroid/examples/deform/DeformSurfaceView.java
new file mode 100644
index 0000000..6847cfd
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/deform/DeformSurfaceView.java
@@ -0,0 +1,61 @@
+
+package org.distortedandroid.examples.deform;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DeformSurfaceView extends GLSurfaceView 
+{
+    private DeformRenderer renderer;
+    private int xTouch, yTouch;
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public DeformSurfaceView(Context c, AttributeSet attrs) 
+      {
+      super(c, attrs);
+    
+      if(!isInEditMode())
+        {
+        setEGLContextClientVersion(2);
+        
+        if( Build.FINGERPRINT.startsWith("generic") )
+          { 
+          setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+          }
+    
+        renderer = new DeformRenderer(this);
+        setRenderer(renderer);
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override public boolean onTouchEvent(MotionEvent event) 
+      {
+      int action = event.getAction();
+      int x = (int)event.getX();
+      int y = (int)event.getY();
+           
+      switch(action)
+         {
+         case MotionEvent.ACTION_DOWN: xTouch =x;
+                                       yTouch =y; 
+                                       renderer.down(x,y);
+                                       break;
+         case MotionEvent.ACTION_MOVE: renderer.move(x-xTouch,y-yTouch);                      
+                                       break;
+         case MotionEvent.ACTION_UP  : renderer.up(); 
+                                       break;
+         }
+             
+      return true;
+      }
+     
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/differentbitmaps/DifferentBitmapsActivity.java b/src/main/java/org/distortedandroid/examples/differentbitmaps/DifferentBitmapsActivity.java
new file mode 100644
index 0000000..ed8d479
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/differentbitmaps/DifferentBitmapsActivity.java
@@ -0,0 +1,51 @@
+
+package org.distortedandroid.examples.differentbitmaps;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class DifferentBitmapsActivity extends Activity 
+{
+    private DifferentBitmapsSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new DifferentBitmapsSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }    
+}
diff --git a/src/main/java/org/distortedandroid/examples/differentbitmaps/DifferentBitmapsRenderer.java b/src/main/java/org/distortedandroid/examples/differentbitmaps/DifferentBitmapsRenderer.java
new file mode 100644
index 0000000..d0ab74a
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/differentbitmaps/DifferentBitmapsRenderer.java
@@ -0,0 +1,156 @@
+
+package org.distortedandroid.examples.differentbitmaps;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.Interpolator2D;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DifferentBitmapsRenderer implements GLSurfaceView.Renderer 
+{
+   private static final int NUM = 3;
+   
+   private GLSurfaceView mView;
+   private DistortedBitmap[] bmp;
+   private Float2D point;
+   private Interpolator2D di;
+   private Float2D[] vec;
+   private int bmpHeight, bmpWidth;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public DifferentBitmapsRenderer(GLSurfaceView v) 
+      {     
+      mView = v;
+     
+      // create shared effects - enlarge the nose and keep moving the whole bitmap left and right.
+      di = new Interpolator2D();
+      di.setCount(0.0f);
+      di.setDuration(3000);
+      vec = new Float2D[2];
+      vec[0] = new Float2D( 25,0);
+      vec[1] = new Float2D(-25,0);
+      di.add(vec[0]);
+      di.add(vec[1]);
+      point = new Float2D(305, 380);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private Bitmap readBitmap(int id)
+     {
+     InputStream is = mView.getContext().getResources().openRawResource(id);
+     Bitmap bitmap=null;
+           
+     try 
+       {
+       bitmap = BitmapFactory.decodeStream(is);
+       } 
+     finally 
+       {
+       try 
+         {
+         is.close();
+         } 
+       catch(IOException e) { }
+       }
+     
+     return bitmap;
+     }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      long time = System.currentTimeMillis();
+      
+      for(int i=NUM-1; i>=0; i--) bmp[i].draw(time); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      {  
+      for(int i=NUM-1; i>=0; i--) 
+        {   
+        bmp[i].abortAllEffects(Distorted.TYPE_MATR);  
+        }
+      
+      if( bmpHeight/(NUM*bmpWidth) > height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+      
+        for(int i=NUM-1; i>=0; i--) 
+          {
+          bmp[i].move( (width-NUM*w)/2 +i*w ,0,0);
+          bmp[i].scale((float)height/bmpHeight);
+          }
+        }
+      else
+        {
+        int w = width/NUM;  
+        int h = (width*bmpHeight)/(bmpWidth*NUM);
+      
+        for(int i=NUM-1; i>=0; i--) 
+          {
+          bmp[i].move(i*w, (height-h)/2, 0);  
+          bmp[i].scale((float)width/(bmpWidth*NUM));
+          }
+        }
+         
+      Distorted.onSurfaceChanged(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);
+      
+      bmpHeight = bitmap0.getHeight();
+      bmpWidth  = bitmap0.getWidth();
+      
+      // create NUM DistortedBitmaps with shared effects
+      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_VERTEX|Distorted.CLONE_FRAGMENT);
+      
+      bmp[0].setBitmap(bitmap0);
+      bmp[1].setBitmap(bitmap1);
+      bmp[2].setBitmap(bitmap2);
+         
+      bmp[0].sink(8.0f, new Float4D(0,0,80,80), point, 0, 0.5f);
+      bmp[0].distort(di,point); 
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Renderer", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/differentbitmaps/DifferentBitmapsSurfaceView.java b/src/main/java/org/distortedandroid/examples/differentbitmaps/DifferentBitmapsSurfaceView.java
new file mode 100644
index 0000000..2c18ca7
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/differentbitmaps/DifferentBitmapsSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.differentbitmaps;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DifferentBitmapsSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public DifferentBitmapsSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new DifferentBitmapsRenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/differenteffects/DifferentEffectsActivity.java b/src/main/java/org/distortedandroid/examples/differenteffects/DifferentEffectsActivity.java
new file mode 100644
index 0000000..fad29aa
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/differenteffects/DifferentEffectsActivity.java
@@ -0,0 +1,51 @@
+
+package org.distortedandroid.examples.differenteffects;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class DifferentEffectsActivity extends Activity 
+{
+    private DifferentEffectsSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new DifferentEffectsSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }    
+}
diff --git a/src/main/java/org/distortedandroid/examples/differenteffects/DifferentEffectsRenderer.java b/src/main/java/org/distortedandroid/examples/differenteffects/DifferentEffectsRenderer.java
new file mode 100644
index 0000000..c4080f1
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/differenteffects/DifferentEffectsRenderer.java
@@ -0,0 +1,154 @@
+
+package org.distortedandroid.examples.differenteffects;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.Interpolator3D;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DifferentEffectsRenderer implements GLSurfaceView.Renderer 
+{
+   private static final int NUM = 3;
+   
+   private GLSurfaceView mView;
+   private DistortedBitmap[] bmp;
+   private Float2D pLeft, pRight, pNose1;
+   private Float4D RegionEye;
+   private Interpolator3D mDI;
+   private Float3D[] vec;
+   private int bmpHeight, bmpWidth;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public DifferentEffectsRenderer(GLSurfaceView v) 
+      {     
+      mView = v;
+      
+      // bmp[0] effects
+      pLeft = new Float2D(214, 206);
+      pRight= new Float2D(390, 212);
+      RegionEye = new Float4D(0,0,60,60);
+      
+      // bmp[1] effects
+      mDI = new Interpolator3D();
+      mDI.setCount(0.0f);
+      mDI.setDuration(1000);
+      vec = new Float3D[2];
+      vec[0] = new Float3D( 50,0,0);
+      vec[1] = new Float3D(-50,0,0);
+      mDI.add(vec[0]);
+      mDI.add(vec[1]);
+      pNose1 = new Float2D(305, 340);
+      
+      // we don't need to prepare anything for bmp[2] effects
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      long time = System.currentTimeMillis();
+   
+      for(int i=NUM-1; i>=0; i--) bmp[i].draw(time);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      for(int i=NUM-1; i>=0; i--) 
+        {   
+        bmp[i].abortAllEffects(Distorted.TYPE_MATR);  
+        }
+      
+      if( bmpHeight/(NUM*bmpWidth) > height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+      
+        for(int i=NUM-1; i>=0; i--) 
+          {
+          bmp[i].move( (width-NUM*w)/2 +i*w ,0, 0);
+          bmp[i].scale((float)height/bmpHeight);
+          }
+        }
+      else
+        {
+        int w = width/NUM;  
+        int h = (width*bmpHeight)/(bmpWidth*NUM);
+      
+        for(int i=NUM-1; i>=0; i--) 
+          {
+          bmp[i].move(i*w, (height-h)/2, 0);  
+          bmp[i].scale((float)width/(bmpWidth*NUM));
+          }
+        }
+       
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.dog);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      bmpHeight = bitmap.getHeight();
+      bmpWidth  = bitmap.getWidth();
+      
+      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);
+      
+      // setting the bitmap once is enough; others are cloned!
+      bmp[0].setBitmap(bitmap);
+         
+      bmp[0].sink(10.0f, RegionEye, pLeft , 2000, 0.0f);
+      bmp[0].sink(10.0f, RegionEye, pRight, 2000, 0.0f);
+      bmp[1].distort(mDI, pNose1);
+      bmp[2].macroblock(50, 3000, 0.0f);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("DifferentEffectsRenderer", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/differenteffects/DifferentEffectsSurfaceView.java b/src/main/java/org/distortedandroid/examples/differenteffects/DifferentEffectsSurfaceView.java
new file mode 100644
index 0000000..7bc7761
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/differenteffects/DifferentEffectsSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.differenteffects;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class DifferentEffectsSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public DifferentEffectsSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new DifferentEffectsRenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/effects3d/Effects3DActivity.java b/src/main/java/org/distortedandroid/examples/effects3d/Effects3DActivity.java
new file mode 100644
index 0000000..898780b
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/effects3d/Effects3DActivity.java
@@ -0,0 +1,369 @@
+
+package org.distortedandroid.examples.effects3d;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.examples.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.opengl.GLSurfaceView;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class Effects3DActivity extends Activity implements OnSeekBarChangeListener
+{
+    public static final int MOVE   =0;
+    public static final int SCALE  =1;
+    public static final int ROTATE =2;
+    public static final int SHEAR  =3;
+	
+    private SeekBar bar;
+    private TextView textMove, textScale, textRotate, textShear;
+    private int moveX, moveY, moveZ;
+    private int scaleX, scaleY, scaleZ;
+    private int rotateX, rotateY, rotateZ, rotateA;
+    private int shearX, shearY, shearZ;
+    
+    private int maxX, maxY, maxZ;
+    
+    private float fmoveX, fmoveY, fmoveZ;
+    private float fscaleX, fscaleY, fscaleZ;
+    private float frotateX, frotateY, frotateZ, frotateA;
+    private float fshearX, fshearY, fshearZ;
+    
+    private int[] effects = new int[4];
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      setContentView(R.layout.effects3dlayout);
+      Default(null);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void Default(View view)
+      {
+      effects[0] = MOVE;
+      effects[1] = SCALE;
+      effects[2] = ROTATE;
+      effects[3] = SHEAR;
+    
+      moveX = 50;
+      moveY = 50;
+      moveZ = 50;
+      
+      scaleX = 50;
+      scaleY = 50;
+      scaleZ = 50;
+      
+      rotateX = 100;
+      rotateY =  50;
+      rotateZ =  50;
+      rotateA =  50;
+      
+      shearX = 50;
+      shearY = 50;
+      shearZ = 50;
+      
+      addViews();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    private void addViews()
+      {
+      LinearLayout layout = (LinearLayout)findViewById(R.id.matrix3dlayout);
+    
+      layout.removeAllViews();
+      
+      View move   = getLayoutInflater().inflate(R.layout.effects3dmove   , null);
+      View scale  = getLayoutInflater().inflate(R.layout.effects3dscale  , null);
+      View rotate = getLayoutInflater().inflate(R.layout.effects3drotate , null);
+      View shear  = getLayoutInflater().inflate(R.layout.effects3dshear  , null);
+     
+      for( int i=effects.length-1 ; i>=0 ; i-- )
+        {
+        switch(effects[i])
+          {
+          case MOVE  : layout.addView(move   , 0); break; 
+          case SCALE : layout.addView(scale  , 0); break;
+          case ROTATE: layout.addView(rotate , 0); break;
+          case SHEAR : layout.addView(shear  , 0); break;
+          }
+        }
+      
+      textMove  = (TextView)findViewById(R.id.matrix3dmoveText);
+      textScale = (TextView)findViewById(R.id.matrix3dscaleText);
+      textRotate= (TextView)findViewById(R.id.matrix3drotateText);
+      textShear = (TextView)findViewById(R.id.matrix3dshearText);
+     
+      setMoveText();
+      setScaleText();
+      setRotateText();
+      setShearText();
+      
+      setBar(R.id.matrix3dmoveBar1, moveX);
+      setBar(R.id.matrix3dmoveBar2, moveY);
+      setBar(R.id.matrix3dmoveBar3, moveZ);
+      
+      setBar(R.id.matrix3dscaleBar1, scaleX);
+      setBar(R.id.matrix3dscaleBar2, scaleY);
+      setBar(R.id.matrix3dscaleBar3, scaleZ);
+      
+      setBar(R.id.matrix3drotateBar1, rotateX);
+      setBar(R.id.matrix3drotateBar2, rotateY);
+      setBar(R.id.matrix3drotateBar3, rotateZ);
+      setBar(R.id.matrix3drotateBar4, rotateA);
+      
+      setBar(R.id.matrix3dshearBar1, shearX);
+      setBar(R.id.matrix3dshearBar2, shearY);
+      setBar(R.id.matrix3dshearBar3, shearZ);
+      
+      Effects3DRenderer.setOrder(effects);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void moveUp(int effect)
+      {
+      int len = effects.length-1;	
+      int index = -1;
+      
+      for(int i=0; i<=len; i++)	
+        {
+        if( effects[i]==effect ) 
+          {
+          index=i;
+          break;
+          }
+        }
+      
+      if( index==0 )
+        {
+        for(int i=0; i<len; i++)
+          effects[i] = effects[i+1];
+    	
+        effects[len] = effect;
+        }
+      else if( index>0 )
+        {
+        effects[index]   = effects[index-1];
+        effects[index-1] = effect;
+        }
+      
+      addViews();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void ButtonMove(View v)
+      {
+      moveUp(MOVE); 	
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void ButtonScale(View v)
+      {
+      moveUp(SCALE); 	
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void ButtonRotate(View v)
+      {
+      moveUp(ROTATE); 	
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void ButtonShear(View v)
+      {
+      moveUp(SHEAR); 	
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    private void setBar(int id, int value)
+      {
+      bar = (SeekBar)findViewById(id);
+      bar.setOnSeekBarChangeListener(this); 
+      bar.setProgress(value);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void computeMove()
+      {
+      fmoveX = (moveX-50)*maxX/50.0f;
+      fmoveY = (moveY-50)*maxY/50.0f;
+      fmoveZ = (moveZ-50)*maxZ/50.0f;
+
+      Effects3DRenderer.setMove( fmoveX, fmoveY, fmoveZ);
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void setMoveText()
+      {
+      fmoveX = ((int)(100*fmoveX))/100.0f;
+      fmoveY = ((int)(100*fmoveY))/100.0f;
+      fmoveZ = ((int)(100*fmoveZ))/100.0f;
+      
+      textMove.setText("move("+fmoveX+" , "+fmoveY+" , "+fmoveZ+")");
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void computeScale()
+      {
+      fscaleX = (scaleX>50 ? 0.18f : 0.018f)*(scaleX-50)+1;
+      fscaleY = (scaleY>50 ? 0.18f : 0.018f)*(scaleY-50)+1;
+      fscaleZ = (scaleZ>50 ? 0.18f : 0.018f)*(scaleZ-50)+1;
+
+      Effects3DRenderer.setScale(fscaleX, fscaleY, fscaleZ);
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void setScaleText()
+      {
+      fscaleX = ((int)(100*fscaleX))/100.0f;
+      fscaleY = ((int)(100*fscaleY))/100.0f;
+      fscaleZ = ((int)(100*fscaleZ))/100.0f;
+      
+      textScale.setText("scale("+fscaleX+" , "+fscaleY+" , "+fscaleZ+")");
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void computeRotate()
+      {
+      frotateX = (rotateX-50)/50.0f;
+      frotateY = (rotateY-50)/50.0f;
+      frotateZ = (rotateZ-50)/50.0f;
+    
+      Effects3DRenderer.setRotate( frotateA, frotateX, frotateY, frotateZ );
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void setRotateText()
+      {
+      frotateX = ((int)(100*frotateX))/100.0f;
+      frotateY = ((int)(100*frotateY))/100.0f;
+      frotateZ = ((int)(100*frotateZ))/100.0f;
+      
+      frotateA = ((rotateA-50)*180)/50;
+      
+      textRotate.setText("rotate( "+frotateA+" ("+frotateX+","+frotateY+","+frotateZ+") )");
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void computeShear()
+      {
+      fshearX = (shearX-50)/25.0f;
+      fshearY = (shearY-50)/25.0f;
+      fshearZ = (shearZ-50)/25.0f;
+    		
+      Effects3DRenderer.setShear( fshearX, fshearY, fshearZ );
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void setShearText()
+      {
+      fshearX = ((int)(100*fshearX))/100.0f;
+      fshearY = ((int)(100*fshearY))/100.0f;
+      fshearZ = ((int)(100*fshearZ))/100.0f;
+      
+      textShear.setText("shear("+fshearX+" , "+fshearY+" , "+fshearZ+")");	
+      }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.effects3dSurfaceView);
+      mView.onPause(); 
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.effects3dSurfaceView); 
+      mView.onResume();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) 
+      {
+      super.onWindowFocusChanged(hasFocus);
+  
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.effects3dSurfaceView);
+      
+      maxX = mView.getWidth();
+      maxY = mView.getHeight();
+      maxZ = (maxX+maxY)/2;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onProgressChanged(SeekBar bar, int progress, boolean fromUser) 
+      {
+      switch (bar.getId()) 
+        {
+        case R.id.matrix3dmoveBar1  : moveX = progress; computeMove()  ; setMoveText()  ; break;
+        case R.id.matrix3dmoveBar2  : moveY = progress; computeMove()  ; setMoveText()  ; break;
+        case R.id.matrix3dmoveBar3  : moveZ = progress; computeMove()  ; setMoveText()  ; break;
+        
+        case R.id.matrix3dscaleBar1 : scaleX= progress; computeScale() ; setScaleText() ; break;
+        case R.id.matrix3dscaleBar2 : scaleY= progress; computeScale() ; setScaleText() ; break;
+        case R.id.matrix3dscaleBar3 : scaleZ= progress; computeScale() ; setScaleText() ; break;
+        
+        case R.id.matrix3drotateBar1: rotateX=progress; computeRotate(); setRotateText(); break;
+        case R.id.matrix3drotateBar2: rotateY=progress; computeRotate(); setRotateText(); break;
+        case R.id.matrix3drotateBar3: rotateZ=progress; computeRotate(); setRotateText(); break;
+        case R.id.matrix3drotateBar4: rotateA=progress; computeRotate(); setRotateText(); break;
+        
+        case R.id.matrix3dshearBar1 : shearX= progress; computeShear() ; setShearText() ; break;
+        case R.id.matrix3dshearBar2 : shearY= progress; computeShear() ; setShearText() ; break;
+        case R.id.matrix3dshearBar3 : shearZ= progress; computeShear() ; setShearText() ; break;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void onStartTrackingTouch(SeekBar bar) { }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void onStopTrackingTouch(SeekBar bar)  { }
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/effects3d/Effects3DRenderer.java b/src/main/java/org/distortedandroid/examples/effects3d/Effects3DRenderer.java
new file mode 100644
index 0000000..21c99d8
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/effects3d/Effects3DRenderer.java
@@ -0,0 +1,169 @@
+
+package org.distortedandroid.examples.effects3d;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.DistortedCubes;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.Interpolator3D;
+import org.distortedandroid.library.Interpolator4D;
+import org.distortedandroid.library.Distorted;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class Effects3DRenderer implements GLSurfaceView.Renderer 
+{
+    private static final int SIZE = 100;
+	
+    private GLSurfaceView mView;
+    private static DistortedCubes mCube;
+
+    private static int[] order;
+    
+    private static Interpolator3D mMoveInter, mScaleInter, mShearInter;
+    private static Interpolator4D mRotateInter;
+    
+    private static Float3D mZeroPoint, mMovePoint, mScalePoint, mShearPoint;
+    private static Float4D mRotatePoint;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static void setMove(float x, float y, float z)
+      {
+      mMovePoint.set(x, y, z);
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static void setScale(float x, float y, float z)
+      {
+      mScalePoint.set(x, y, z);
+      }
+     
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static void setRotate(float a, float x, float y, float z)
+      {
+      mRotatePoint.set(a, x, y, z);
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static void setShear(float x, float y, float z)
+      {
+      mShearPoint.set(x, y, z);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static void setOrder(int[] effects)
+      {
+      order = effects;
+      setMatrixEffects();
+      }
+      
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public static void setMatrixEffects()
+      {
+      mCube.abortAllEffects(Distorted.TYPE_MATR);  
+	
+      for( int i=0; i<=order.length-1 ; i++ )
+        {
+        switch(order[i])
+          {
+          case Effects3DActivity.MOVE  : mCube.move(mMoveInter)               ; break; 
+          case Effects3DActivity.SCALE : mCube.scale(mScaleInter)             ; break;
+          case Effects3DActivity.ROTATE: mCube.rotate(mZeroPoint,mRotateInter); break;
+          case Effects3DActivity.SHEAR : mCube.shear(mZeroPoint,mShearInter)  ; break;
+          }
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public Effects3DRenderer(GLSurfaceView v) 
+      {
+      mView = v;
+      mCube = new DistortedCubes( 1, "1", SIZE);
+      
+      mZeroPoint  = new Float3D(0,0,0);
+      mMovePoint  = new Float3D(0,0,0);
+      mScalePoint = new Float3D(1,1,1);
+      mShearPoint = new Float3D(0,0,0);
+      mRotatePoint= new Float4D(1,0,0,0);
+      
+      mMoveInter  = new Interpolator3D();
+      mScaleInter = new Interpolator3D();
+      mShearInter = new Interpolator3D();
+      mRotateInter= new Interpolator4D();
+      
+      mMoveInter.add(mMovePoint);
+      mScaleInter.add(mScalePoint);
+      mShearInter.add(mShearPoint);
+      mRotateInter.add(mRotatePoint);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      mCube.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      {
+      setMatrixEffects();
+
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.grid);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      mCube.setBitmap(bitmap);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Quaternion", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/effects3d/Effects3DSurfaceView.java b/src/main/java/org/distortedandroid/examples/effects3d/Effects3DSurfaceView.java
new file mode 100644
index 0000000..4d7ebdf
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/effects3d/Effects3DSurfaceView.java
@@ -0,0 +1,32 @@
+
+package org.distortedandroid.examples.effects3d;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.util.AttributeSet;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class Effects3DSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public Effects3DSurfaceView(Context c, AttributeSet attrs) 
+      {
+      super(c, attrs);
+      
+      if(!isInEditMode())
+        {
+        setEGLContextClientVersion(2);
+        
+        if( Build.FINGERPRINT.startsWith("generic") )
+          { 
+          setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+          }
+        
+        setRenderer(new Effects3DRenderer(this));
+        }
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/fbo/FBOActivity.java b/src/main/java/org/distortedandroid/examples/fbo/FBOActivity.java
new file mode 100644
index 0000000..eb74013
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/fbo/FBOActivity.java
@@ -0,0 +1,52 @@
+
+package org.distortedandroid.examples.fbo;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class FBOActivity extends Activity 
+{
+    private FBOSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new FBOSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/fbo/FBORenderer.java b/src/main/java/org/distortedandroid/examples/fbo/FBORenderer.java
new file mode 100644
index 0000000..68b819e
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/fbo/FBORenderer.java
@@ -0,0 +1,123 @@
+
+package org.distortedandroid.examples.fbo;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.DistortedNode;
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float2D;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class FBORenderer implements GLSurfaceView.Renderer 
+{
+   private GLSurfaceView mView;
+   private DistortedBitmap mLisa, mText;
+   private int lisaHeight, lisaWidth;
+    
+   private DistortedNode mRoot;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public FBORenderer(GLSurfaceView v) 
+      {
+      mView = v;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      mRoot.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      mLisa.abortAllEffects(Distorted.TYPE_MATR);  
+         
+      if( lisaHeight/lisaWidth > height/width )
+        {
+        int w = (height*lisaWidth)/lisaHeight;
+        mLisa.move((width-w)/2 ,0, 0);
+        mLisa.scale((float)height/lisaHeight);
+        }
+      else
+        {
+        int h = (width*lisaHeight)/lisaWidth;
+        mLisa.move(0 ,(height-h)/2, 0);
+        mLisa.scale((float)width/lisaWidth);
+        }
+      
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is1 = mView.getContext().getResources().openRawResource(R.raw.monalisa);
+      InputStream is2 = mView.getContext().getResources().openRawResource(R.raw.fbo);
+      
+      Bitmap bitmap1, bitmap2;
+       
+      try 
+        {
+        bitmap1 = BitmapFactory.decodeStream(is1);
+        bitmap2 = BitmapFactory.decodeStream(is2);
+        } 
+      finally 
+        {
+        try 
+          {
+          is1.close();
+          is2.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      lisaHeight = bitmap1.getHeight();
+      lisaWidth  = bitmap1.getWidth();
+      
+      mLisa = new DistortedBitmap(bitmap1, 20);
+      mText = new DistortedBitmap(bitmap2, 20);
+      
+      android.util.Log.e("FBO", "Lisa hashcode= "+bitmap1.hashCode());
+      
+      mRoot = new DistortedNode(mLisa);
+      mRoot.attach(mText);
+     
+      int textWidth  = mText.getWidth();
+      int textHeight = mText.getHeight();
+      
+      mText.move(lisaWidth/6 , lisaHeight/3, 0);
+      mText.scale(lisaWidth/(1.5f*textWidth));
+      mText.sink(0.5f, new Float2D( textWidth/2, textHeight/2), 5000, 0.0f);
+      mLisa.macroblock(4, 10000, 0.0f);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("MonaLisa", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/fbo/FBOSurfaceView.java b/src/main/java/org/distortedandroid/examples/fbo/FBOSurfaceView.java
new file mode 100644
index 0000000..0a39591
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/fbo/FBOSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.fbo;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class FBOSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public FBOSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new FBORenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/fov/FOVActivity.java b/src/main/java/org/distortedandroid/examples/fov/FOVActivity.java
new file mode 100644
index 0000000..89b450c
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/fov/FOVActivity.java
@@ -0,0 +1,92 @@
+
+package org.distortedandroid.examples.fov;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.examples.R;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class FOVActivity extends Activity implements OnSeekBarChangeListener
+{
+    private SeekBar barFOV;
+    private TextView textFOV;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      setContentView(R.layout.fovlayout);
+       
+      barFOV = (SeekBar)findViewById(R.id.seekFOV);
+      barFOV.setOnSeekBarChangeListener(this); 
+        
+      textFOV = (TextView)findViewById(R.id.textFOV);
+     
+      barFOV.setProgress(50);
+      
+      textFOV.setText("FOV: 50");
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.surfaceViewFOV);
+      mView.onPause();
+      
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.surfaceViewFOV);
+      mView.onResume();    
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onProgressChanged(SeekBar bar, int progress, boolean fromUser) 
+      {
+      switch (bar.getId()) 
+        {
+        case R.id.seekFOV: FOVRenderer.setFOV(progress);
+                           textFOV.setText("FOV: "+progress);
+                           break;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void onStartTrackingTouch(SeekBar bar) { }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void onStopTrackingTouch(SeekBar bar)  { }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/fov/FOVRenderer.java b/src/main/java/org/distortedandroid/examples/fov/FOVRenderer.java
new file mode 100644
index 0000000..d7abdd2
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/fov/FOVRenderer.java
@@ -0,0 +1,116 @@
+
+package org.distortedandroid.examples.fov;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class FOVRenderer implements GLSurfaceView.Renderer 
+{
+   private static final int NUMLINES = 10;
+   
+   private GLSurfaceView mView;
+   private DistortedBitmap fov;
+   private Paint mPaint;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public FOVRenderer(GLSurfaceView view) 
+      { 
+      mView = view;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public static void setFOV(int fov)
+      {
+      Distorted.setFov(fov);
+      }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+     
+      fov.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+   public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      Distorted.onSurfaceChanged(width, height);
+      setupBitmap(width,height);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+   public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {  
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("FOV", ex.getMessage() );
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void setupBitmap(int w, int h)
+      {
+      mPaint = new Paint();
+      fov = new DistortedBitmap(w,h, 50);
+      Bitmap fovBitmap = Bitmap.createBitmap(w,h, Bitmap.Config.ARGB_8888);
+      Canvas fovCanvas = new Canvas(fovBitmap);    
+
+      mPaint.setColor(0xff008800);
+      mPaint.setStyle(Style.FILL);
+      fovCanvas.drawRect(0, 0, w, h, mPaint);
+      mPaint.setColor(0xffffffff);
+      
+      for(int i=0; i<=NUMLINES ; i++ )
+        {
+        fovCanvas.drawRect(w*i/NUMLINES - 1,                0,  w*i/NUMLINES + 1,  h               , mPaint);
+        fovCanvas.drawRect(               0, h *i/NUMLINES -1,  w               ,  h*i/NUMLINES + 1, mPaint);  
+        }
+        
+      fov.setBitmap(fovBitmap);
+        
+      int min = w<h ? w:h;
+        
+      Float3D dp3D = new Float3D(0,0,min/5);
+      Float4D dr = new Float4D(0,0,min/5,min/5);
+        
+      Float2D point1 = new Float2D(  w/4,   h/4);
+      Float2D point2 = new Float2D(3*w/4,   h/4);
+      Float2D point3 = new Float2D(  w/4, 3*h/4);
+      Float2D point4 = new Float2D(3*w/4, 3*h/4);
+       
+      fov.distort(dp3D, dr, point1, 0, 0.5f);
+      fov.distort(dp3D, dr, point2, 0, 0.5f);
+      fov.distort(dp3D, dr, point3, 0, 0.5f);
+      fov.distort(dp3D, dr, point4, 0, 0.5f);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/fov/FOVSurfaceView.java b/src/main/java/org/distortedandroid/examples/fov/FOVSurfaceView.java
new file mode 100644
index 0000000..38ebd0f
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/fov/FOVSurfaceView.java
@@ -0,0 +1,37 @@
+
+package org.distortedandroid.examples.fov;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.util.AttributeSet;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class FOVSurfaceView extends GLSurfaceView 
+{
+    private FOVRenderer renderer;
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public FOVSurfaceView(Context c, AttributeSet attrs) 
+      {
+      super(c, attrs);
+    
+      if(!isInEditMode())
+        {
+        setEGLContextClientVersion(2);
+        
+        if( Build.FINGERPRINT.startsWith("generic") )
+          { 
+          setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+          }
+    
+        renderer = new FOVRenderer(this);
+        setRenderer(renderer);
+        }
+      }
+
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
diff --git a/src/main/java/org/distortedandroid/examples/girl/GirlActivity.java b/src/main/java/org/distortedandroid/examples/girl/GirlActivity.java
new file mode 100644
index 0000000..58b6945
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/girl/GirlActivity.java
@@ -0,0 +1,122 @@
+
+package org.distortedandroid.examples.girl;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.examples.R;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class GirlActivity extends Activity  implements OnSeekBarChangeListener
+{
+    private SeekBar barSwing, barSize, barHips;
+    private TextView textSwing, textSize, textHips;
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      
+      setContentView(R.layout.girllayout);
+           
+      textSwing = (TextView)findViewById(R.id.girlTextSwing);
+      textSize  = (TextView)findViewById(R.id.girlTextSize);
+      textHips  = (TextView)findViewById(R.id.girlTextHips);
+
+      barSwing = (SeekBar)findViewById(R.id.girlSeekSwing);
+      barSize  = (SeekBar)findViewById(R.id.girlSeekSize);
+      barHips  = (SeekBar)findViewById(R.id.girlSeekHips);
+      
+      barSwing.setOnSeekBarChangeListener(this); 
+      barSize.setOnSeekBarChangeListener(this); 
+      barHips.setOnSeekBarChangeListener(this); 
+  
+      barSwing.setProgress(0);
+      barSize.setProgress(50);
+      barHips.setProgress(0);
+      
+      textSwing.setText("Swing: 0");
+      textSize.setText("Size: 1.0");
+      textHips.setText("Hips: 0");
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.girlSurfaceView);
+      mView.onPause();
+      
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.girlSurfaceView);
+      mView.onResume();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+   
+///////////////////////////////////////////////////////////////////
+    
+    public void onProgressChanged(SeekBar bar, int progress, boolean fromUser) 
+      {
+      int v;
+      float s;
+      
+      switch (bar.getId()) 
+        {
+        case R.id.girlSeekSwing: v = progress/5;
+                             GirlRenderer.setSwing(v);
+                             textSwing.setText("Swing: "+v);
+                             break;
+        case R.id.girlSeekSize : if( progress> 50)
+                               {
+                            s = (progress-50)/16.0f + 1.0f;
+                               }
+                             else
+                               {
+                            s = 0.015f*progress + 0.25f;
+                               }
+                             GirlRenderer.setSize(s);
+                             textSize.setText("Size: "+(((int)(s*10))/10.0f));
+                             break;     
+        case R.id.girlSeekHips : v = progress/5;
+                             GirlRenderer.setHips(v);
+                             textHips.setText("Hips: "+v);
+                             break;
+        
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public void onStartTrackingTouch(SeekBar bar) { }
+    
+///////////////////////////////////////////////////////////////////
+
+    public void onStopTrackingTouch(SeekBar bar)  { }
+     
+}
diff --git a/src/main/java/org/distortedandroid/examples/girl/GirlRenderer.java b/src/main/java/org/distortedandroid/examples/girl/GirlRenderer.java
new file mode 100644
index 0000000..50cdd1f
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/girl/GirlRenderer.java
@@ -0,0 +1,211 @@
+
+package org.distortedandroid.examples.girl;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float1D;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.Interpolator3D;
+import org.distortedandroid.library.Interpolator1D;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class GirlRenderer implements GLSurfaceView.Renderer 
+{
+    private GLSurfaceView mView;
+    private DistortedBitmap mGirl;
+    private Float2D pLeft, pRight, pHips;
+    private Float4D Region, sinkRegion, HipsRegion;
+    private static Interpolator3D diL, diR;
+    private static Interpolator1D diHips, diSink;
+    private static Float3D v0,v1,v2,v3;
+    private static Float1D d0, d1, s0;
+    
+    private int bmpHeight, bmpWidth;
+    
+    private static int boobsSwing;
+    private static int hipsSwirl;
+    private static float boobsSink;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public GirlRenderer(GLSurfaceView v) 
+      {
+      mView = v;
+      
+      boobsSwing = 0;
+      hipsSwirl  = 0;
+      boobsSink  = 1.0f;
+      
+      pLeft = new Float2D(132, 264);
+      pRight= new Float2D(247, 264);
+      
+      // Make the boobs bigger
+      sinkRegion = new Float4D(0,0,60,60);
+      
+      s0 = new Float1D(boobsSink);
+      
+      diSink = new Interpolator1D(); 
+      diSink.setCount(0.5f);
+      diSink.setDuration(0);
+      diSink.add(s0);
+      
+      // Boobs Movement
+      Region = new Float4D(0,0,45,45);
+      
+      diL = new Interpolator3D();
+      diR = new Interpolator3D();
+      
+      diL.setCount(0.0f);
+      diR.setCount(0.0f);
+      diL.setDuration(1000);
+      diR.setDuration(1000);
+      
+      v0 = new Float3D( 0,-boobsSwing, 0);
+      v1 = new Float3D( boobsSwing, 0, 0);
+      v2 = new Float3D( 0, boobsSwing, 0);
+      v3 = new Float3D(-boobsSwing, 0, 0);
+      
+      diL.add(v0);
+      diL.add(v1);
+      diL.add(v2);
+      diL.add(v3);
+      
+      diR.add(v0);
+      diR.add(v3);
+      diR.add(v2);
+      diR.add(v1);
+      
+      // Movement of the hips
+      pHips = new Float2D(216,505);
+      HipsRegion = new Float4D(0,0,120,120);
+      diHips = new Interpolator1D();
+      
+      d0 = new Float1D(-hipsSwirl);
+      d1 = new Float1D(+hipsSwirl);
+      
+      diHips.add(d0);
+      diHips.add(d1);
+      diHips.setDuration(1000);
+      diHips.setCount(0.0f);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public static void setHips(int s)
+     {      
+     hipsSwirl = s;
+     d0.set(-hipsSwirl);
+     d1.set(+hipsSwirl);
+     }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public static void setSize(float s)
+     {
+     boobsSink = s;
+     s0.set(boobsSink);
+     }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public static void setSwing(int s)
+     {
+     boobsSwing = s; 
+     
+     v0.set( 0,-boobsSwing, 0);
+     v1.set( boobsSwing, 0, 0);
+     v2.set( 0, boobsSwing, 0);
+     v3.set(-boobsSwing, 0, 0);
+     }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      mGirl.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      mGirl.abortAllEffects(Distorted.TYPE_MATR);  
+      
+      if( bmpHeight/bmpWidth > height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        mGirl.move((width-w)/2 ,0, 0);
+        mGirl.scale((float)height/bmpHeight);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        mGirl.move(0 ,(height-h)/2, 0);
+        mGirl.scale((float)width/bmpWidth);
+        }
+      
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {    
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.girl);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      bmpHeight = bitmap.getHeight();
+      bmpWidth  = bitmap.getWidth();
+      
+      mGirl = new DistortedBitmap(bitmap, 30);
+
+      mGirl.sink( diSink, sinkRegion, pLeft );
+      mGirl.sink( diSink, sinkRegion, pRight);
+
+      mGirl.distort(diL, Region, pLeft );
+      mGirl.distort(diR, Region, pRight);
+         
+      mGirl.swirl(diHips, HipsRegion, pHips);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Renderer", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/girl/GirlSurfaceView.java b/src/main/java/org/distortedandroid/examples/girl/GirlSurfaceView.java
new file mode 100644
index 0000000..c033a08
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/girl/GirlSurfaceView.java
@@ -0,0 +1,29 @@
+
+package org.distortedandroid.examples.girl;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.util.AttributeSet;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class GirlSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+  public GirlSurfaceView(Context c, AttributeSet attrs) 
+      {
+      super(c, attrs);
+     
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new GirlRenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/interpolator/InterpolatorActivity.java b/src/main/java/org/distortedandroid/examples/interpolator/InterpolatorActivity.java
new file mode 100644
index 0000000..a80a5d4
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/interpolator/InterpolatorActivity.java
@@ -0,0 +1,159 @@
+package org.distortedandroid.examples.interpolator;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.Interpolator1D;
+import org.distortedandroid.examples.R;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.SeekBar;
+import android.widget.TextView;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+
+///////////////////////////////////////////////////////////////////
+
+public class InterpolatorActivity extends Activity implements OnSeekBarChangeListener
+    {
+    private SeekBar barD, barN;
+    private TextView textD, textN;
+   
+///////////////////////////////////////////////////////////////////
+    @Override
+    protected void onCreate(Bundle savedInstanceState) 
+      {
+      super.onCreate(savedInstanceState);
+      setContentView(R.layout.interpolatorlayout);
+      
+      barD = (SeekBar)findViewById(R.id.interpolatorSeekDuration);
+      barD.setOnSeekBarChangeListener(this); 
+      textD = (TextView)findViewById(R.id.interpolatorTextDuration);
+      
+      barN = (SeekBar)findViewById(R.id.interpolatorSeekNoise);
+      barN.setOnSeekBarChangeListener(this); 
+      textN = (TextView)findViewById(R.id.interpolatorTextNoise);
+      
+      barD.setProgress(50);
+      textD.setText("Duration: 10 s");
+      
+      barN.setProgress(0);
+      textN.setText("Noise: 0.0");
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.interpolatorSurfaceView);
+      mView.onResume();
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    protected void onPause() 
+      {
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.interpolatorSurfaceView);
+      mView.onPause();
+         
+      super.onPause();
+      }
+    
+///////////////////////////////////////////////////////////////////
+    @Override
+    public void onStop()
+      {
+      super.onStop();
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    public void onDestroy()
+      {  
+      Distorted.onDestroy();
+      super.onDestroy();
+      }     
+ 
+///////////////////////////////////////////////////////////////////
+    
+    public void Loop(View v)
+      {
+      InterpolatorSurfaceView.setMode(Interpolator1D.MODE_LOOP);
+      }     
+    
+///////////////////////////////////////////////////////////////////
+
+    public void Path(View v)
+      {
+      InterpolatorSurfaceView.setMode(Interpolator1D.MODE_PATH);
+      }  
+
+///////////////////////////////////////////////////////////////////
+
+    public void Jump(View v)
+      {
+      InterpolatorSurfaceView.setMode(Interpolator1D.MODE_JUMP);
+      }  
+    
+///////////////////////////////////////////////////////////////////
+
+    public void Dim1D(View v)
+      {
+      InterpolatorSurfaceView.setDimension(InterpolatorSurfaceView.DIM_1D);
+      }  
+
+///////////////////////////////////////////////////////////////////
+
+    public void Dim2D(View v)
+      {
+      InterpolatorSurfaceView.setDimension(InterpolatorSurfaceView.DIM_2D);
+      }  
+    
+///////////////////////////////////////////////////////////////////
+
+    public void Dim3DXY(View v)
+      {
+      InterpolatorSurfaceView.setDimension(InterpolatorSurfaceView.DIM_3DXY);
+      }  
+
+///////////////////////////////////////////////////////////////////
+
+    public void Dim3DXZ(View v)
+      {
+      InterpolatorSurfaceView.setDimension(InterpolatorSurfaceView.DIM_3DXZ);
+      }  
+    
+///////////////////////////////////////////////////////////////////
+    
+    public void onProgressChanged(SeekBar bar, int progress, boolean fromUser) 
+      {
+      float v, t; 
+      int i;
+      
+      switch (bar.getId()) 
+        {
+        case R.id.interpolatorSeekDuration: v = progress*200;
+                                            i = (int)(v/100);
+                                            t = i/10.0f;
+                                            InterpolatorSurfaceView.setDuration((int)v);
+                                            textD.setText("Duration: "+(int)t+" s");
+                                            break;
+        case R.id.interpolatorSeekNoise   : InterpolatorSurfaceView.setNoise(progress/100.0f);
+                                            textN.setText("Noise: "+(progress/100.f));
+                                            break;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public void onStartTrackingTouch(SeekBar bar) { }
+    
+///////////////////////////////////////////////////////////////////
+
+    public void onStopTrackingTouch(SeekBar bar)  { }
+    
+///////////////////////////////////////////////////////////////////
+// end of file
+}
diff --git a/src/main/java/org/distortedandroid/examples/interpolator/InterpolatorRenderer.java b/src/main/java/org/distortedandroid/examples/interpolator/InterpolatorRenderer.java
new file mode 100644
index 0000000..d152740
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/interpolator/InterpolatorRenderer.java
@@ -0,0 +1,89 @@
+package org.distortedandroid.examples.interpolator;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Distorted;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class InterpolatorRenderer implements GLSurfaceView.Renderer 
+   {  
+   public static final int BWID = 300;
+   public static final int BHEI = 400;
+   
+   private GLSurfaceView mView;
+   private DistortedBitmap mBackground;
+   private Canvas mCanvas;
+   private Bitmap mBitmap;
+   private Paint mPaint;
+   private int texWidth, texHeight;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public InterpolatorRenderer(GLSurfaceView v)
+     {    
+     mPaint = new Paint();
+     mPaint.setAntiAlias(true);
+     mPaint.setFakeBoldText(true);
+     mPaint.setColor(0xff447da7);
+     mPaint.setStyle(Style.FILL);
+      
+     mView = v;
+      
+     texWidth = BWID;
+     texHeight= BHEI;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+     {   
+     mBackground = new DistortedBitmap(texWidth,texHeight, 2);    
+     mBitmap = Bitmap.createBitmap(texWidth,texHeight, Bitmap.Config.ARGB_8888);
+     mCanvas = new Canvas(mBitmap);
+     
+     try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Renderer", ex.getMessage() );
+        }
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void onSurfaceChanged(GL10 glUnused, int width, int height)
+     {
+     mBackground.abortAllEffects(Distorted.TYPE_MATR);
+     mBackground.scale((float)width/texWidth,(float)height/texHeight,1);
+     Distorted.onSurfaceChanged(width, height);
+     InterpolatorSurfaceView.setScreenSize(width,height);
+     }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   public void onDrawFrame(GL10 glUnused)
+     {   
+     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);               
+       
+     long time = System.currentTimeMillis();
+      
+     mCanvas.drawRect(0, 0, texWidth, texHeight, mPaint);
+     InterpolatorSurfaceView.drawCurve(mCanvas,time);
+     mBackground.setBitmap(mBitmap);
+     mBackground.draw(time);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+  }
diff --git a/src/main/java/org/distortedandroid/examples/interpolator/InterpolatorSurfaceView.java b/src/main/java/org/distortedandroid/examples/interpolator/InterpolatorSurfaceView.java
new file mode 100644
index 0000000..177ddaf
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/interpolator/InterpolatorSurfaceView.java
@@ -0,0 +1,422 @@
+package org.distortedandroid.examples.interpolator;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.view.MotionEvent;
+import android.util.AttributeSet;
+import android.graphics.Canvas;
+import android.graphics.Paint.Style;
+import android.graphics.Paint;
+
+import org.distortedandroid.library.Interpolator1D;
+import org.distortedandroid.library.Interpolator2D;
+import org.distortedandroid.library.Interpolator3D;
+import org.distortedandroid.library.Float1D;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+
+///////////////////////////////////////////////////////////////////
+
+public class InterpolatorSurfaceView extends GLSurfaceView
+    {
+    public static final int DIM_1D   = 0; 
+    public static final int DIM_2D   = 1; 
+    public static final int DIM_3DXY = 2; 
+    public static final int DIM_3DXZ = 3; 
+   
+    private static final int NUM_INTERPOLATIONS= 100;
+    private static final int MAX_VECTORS       =   6;
+   
+    private InterpolatorRenderer mRenderer;
+    private static int xDown,yDown;
+    private static int mScrW, mScrH;
+   
+    private static Interpolator1D di1D;
+    private static Interpolator2D di2D;
+    private static Interpolator3D di3D;
+    
+    private static Paint mPaint;
+    private static int moving;
+    private static Object lock = new Object();
+    private static long mTime = 0;
+    private static int mDuration;
+    private static float mPosition;
+    private static float mNoise;
+    
+    private static int currentDim = DIM_2D;
+    
+    private static Float1D p1D;
+    private static Float2D p2D;
+    private static Float3D p3D;
+    
+    private static float[] mDrawCoord = new float[3];
+      
+///////////////////////////////////////////////////////////////////
+    
+    public InterpolatorSurfaceView(Context c, AttributeSet attrs) 
+      {
+      super(c, attrs);
+      
+      mPaint = new Paint();
+      mPaint.setStyle(Style.FILL);
+      mPaint.setAntiAlias(true);
+      
+      moving    = -1;
+      mDuration = 10000;
+      mPosition = 0;
+      mNoise    = 0.0f;
+      
+      di1D = new Interpolator1D();
+      di1D.setDuration(mDuration);
+      di1D.setNoise(mNoise);
+      
+      di2D = new Interpolator2D();
+      di2D.setDuration(mDuration);
+      di2D.setNoise(mNoise);
+      
+      di3D = new Interpolator3D();
+      di3D.setDuration(mDuration);
+      di3D.setNoise(mNoise);
+        
+      if(!isInEditMode())
+        {
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        
+        setEGLContextClientVersion(2);
+        
+        if( Build.FINGERPRINT.startsWith("generic") ) // when running on the emulator, insert a magic line that is
+          {                                           // supposed to cure the 'no config chosen' crash on emulator startup
+          setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+          }
+        
+        mRenderer = new InterpolatorRenderer(this);
+        setRenderer(mRenderer);
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void setMode(int mode)
+      {
+      di1D.setMode(mode);  
+      di2D.setMode(mode);
+      di3D.setMode(mode);
+      }
+      
+///////////////////////////////////////////////////////////////////
+    
+    public static void setScreenSize(int width, int height)
+      {
+      mScrW = width;
+      mScrH = height;
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void setDuration(int duration)
+      {
+      mDuration = duration;
+      
+      di1D.setDuration(duration);
+      di2D.setDuration(duration);
+      di3D.setDuration(duration);
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void setNoise(float noise)
+      {
+      mNoise = noise;
+      
+      di1D.setNoise(noise);
+      di2D.setNoise(noise);
+      di3D.setNoise(noise);
+      }
+    
+///////////////////////////////////////////////////////////////////
+
+    public static void setDimension(int dim)
+      {
+      if( currentDim != dim )
+        {
+        if( !(currentDim==DIM_3DXY && dim==DIM_3DXZ) && !(currentDim==DIM_3DXZ && dim==DIM_3DXY) )
+          {
+          synchronized(lock)
+            {
+            di1D.removeAll();
+            di2D.removeAll();
+            di3D.removeAll();
+            }
+          }
+      
+        currentDim = dim;
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////
+    
+    public static void drawCurve(Canvas c, long time)
+      {
+      mPosition += (mTime>0 && mDuration>0) ? ((float)(time-mTime)*NUM_INTERPOLATIONS/mDuration) : 0; 
+         
+      synchronized(lock)
+        {
+        switch(currentDim)
+          {
+          case DIM_1D: drawCurve1D(c,time); break;
+          case DIM_2D: drawCurve2D(c,time); break;
+          default    : drawCurve3D(c,time); break;
+          }
+        }
+      
+      mTime = time;
+      }
+
+///////////////////////////////////////////////////////////////////
+      
+    private static void drawCurve1D(Canvas c, long time)
+      {
+      int len = di1D.getNumPoints();   
+        
+      mPaint.setColor(0xff000000);
+      
+      c.drawLine(0, InterpolatorRenderer.BHEI/2, InterpolatorRenderer.BWID, InterpolatorRenderer.BHEI/2, mPaint);
+      c.drawText("x", 0.95f*InterpolatorRenderer.BWID, 0.55f*InterpolatorRenderer.BHEI , mPaint);
+      
+      if( len>=2 )
+        {
+        for(int i=0; i<NUM_INTERPOLATIONS; i++) 
+          {
+          int color = i<=mPosition ? 0xff - ((int)mPosition                   -i)*0xff/(NUM_INTERPOLATIONS-1)  
+                                   : 0xff - ((int)mPosition+NUM_INTERPOLATIONS-i)*0xff/(NUM_INTERPOLATIONS-1);
+         
+          mPaint.setColor( 0xffffff + ((color&0xff)<<24) ); 
+          di1D.interpolate(mDrawCoord,0, (float)i/NUM_INTERPOLATIONS);
+          c.drawCircle(mDrawCoord[0], InterpolatorRenderer.BHEI/2 , 2.0f, mPaint );
+          }
+        }
+     
+      mPaint.setColor(0xffff0000);
+      
+      for(int curr=0; curr<len; curr++)
+        {      
+        p1D = di1D.getPoint(curr);
+        c.drawCircle(p1D.getX(), InterpolatorRenderer.BHEI/2 , 5.0f, mPaint);
+        }   
+      }
+    
+///////////////////////////////////////////////////////////////////
+      
+    private static void drawCurve2D(Canvas c, long time)
+      {
+      int len = di2D.getNumPoints();   
+        
+      mPaint.setColor(0xff000000);
+      
+      c.drawLine(0, InterpolatorRenderer.BHEI/2, InterpolatorRenderer.BWID, InterpolatorRenderer.BHEI/2, mPaint);
+      c.drawLine(InterpolatorRenderer.BWID/2, 0, InterpolatorRenderer.BWID/2, InterpolatorRenderer.BHEI, mPaint);
+      
+      c.drawText("x", 0.95f*InterpolatorRenderer.BWID, 0.55f*InterpolatorRenderer.BHEI , mPaint);
+      c.drawText("y", 0.55f*InterpolatorRenderer.BWID, 0.05f*InterpolatorRenderer.BHEI , mPaint);
+      
+      if( len>=2 )
+        {
+        for(int i=0; i<NUM_INTERPOLATIONS; i++) 
+          {
+          int color = i<=mPosition ? 0xff - ((int)mPosition                   -i)*0xff/(NUM_INTERPOLATIONS-1)  
+                                   : 0xff - ((int)mPosition+NUM_INTERPOLATIONS-i)*0xff/(NUM_INTERPOLATIONS-1);
+         
+          mPaint.setColor( 0xffffff + ((color&0xff)<<24) ); 
+          di2D.interpolate(mDrawCoord,0, (float)i/NUM_INTERPOLATIONS);
+          c.drawCircle(mDrawCoord[0], mDrawCoord[1], 2.0f, mPaint );
+          }
+        }
+     
+      mPaint.setColor(0xffff0000);
+      
+      for(int curr=0; curr<len; curr++)
+        {      
+        p2D = di2D.getPoint(curr);
+        c.drawCircle(p2D.getX(),p2D.getY(), 5.0f, mPaint);
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+      
+    private static void drawCurve3D(Canvas c, long time)
+      {
+      int len = di3D.getNumPoints();   
+      
+      mPaint.setColor(0xff000000);
+      
+      c.drawLine(0, InterpolatorRenderer.BHEI/2, InterpolatorRenderer.BWID, InterpolatorRenderer.BHEI/2, mPaint);
+      c.drawLine(InterpolatorRenderer.BWID/2, 0, InterpolatorRenderer.BWID/2, InterpolatorRenderer.BHEI, mPaint);
+      
+      c.drawText("x", 0.95f*InterpolatorRenderer.BWID, 0.55f*InterpolatorRenderer.BHEI , mPaint);
+      c.drawText( currentDim==DIM_3DXY ? "y" : "z", 0.55f*InterpolatorRenderer.BWID, 0.05f*InterpolatorRenderer.BHEI , mPaint);
+      
+      if( len>=2 )
+        {
+        for(int i=0; i<NUM_INTERPOLATIONS; i++) 
+          {
+          int color = i<=mPosition ? 0xff - ((int)mPosition                   -i)*0xff/(NUM_INTERPOLATIONS-1)  
+                                   : 0xff - ((int)mPosition+NUM_INTERPOLATIONS-i)*0xff/(NUM_INTERPOLATIONS-1);
+         
+          mPaint.setColor( 0xffffff + ((color&0xff)<<24) ); 
+          di3D.interpolate(mDrawCoord,0, (float)i/NUM_INTERPOLATIONS);
+          c.drawCircle(mDrawCoord[0], mDrawCoord[currentDim==DIM_3DXY ? 1:2], 2.0f, mPaint );
+          }
+        }
+     
+      mPaint.setColor(0xffff0000);
+      
+      for(int curr=0; curr<len; curr++)
+        {      
+        p3D = di3D.getPoint(curr);
+        c.drawCircle(p3D.getX(), currentDim==DIM_3DXY ? p3D.getY():p3D.getZ(), 5.0f, mPaint);
+        }   
+      }
+    
+///////////////////////////////////////////////////////////////////
+
+    private void addNewPoint(int x, int y)
+      {
+      float gx,gy,gz;
+      int len;
+      
+      switch(currentDim)
+        {
+        case DIM_1D: len = di1D.getNumPoints();
+                
+                     for(int g=0; g<len; g++)
+                       {
+                       p1D = di1D.getPoint(g);  
+                       gx = p1D.getX();
+                                    
+                       if( (xDown-gx)*(xDown-gx) < (InterpolatorRenderer.BHEI)*(InterpolatorRenderer.BHEI)/100 )
+                         {
+                         moving = g;
+                         break;
+                         }
+                       }
+                     if( moving<0 )
+                       {
+                       synchronized(lock)
+                         {
+                         if( len>=MAX_VECTORS ) di1D.removeAll();
+                         di1D.add(new Float1D(xDown)); 
+                         }
+                       }
+                     break;
+        case DIM_2D: len = di2D.getNumPoints();
+                                 
+                     for(int g=0; g<len; g++)
+                       {
+                       p2D = di2D.getPoint(g);  
+                       gx = p2D.getX();
+                       gy = p2D.getY();
+                                    
+                       if( (xDown-gx)*(xDown-gx) + (yDown-gy)*(yDown-gy) < (InterpolatorRenderer.BHEI)*(InterpolatorRenderer.BHEI)/100 )
+                         {
+                         moving = g;
+                         break;
+                         }
+                       }
+                     if( moving<0 )
+                       {
+                       synchronized(lock)
+                         {
+                         if( len>=MAX_VECTORS ) di2D.removeAll();
+                         di2D.add(new Float2D(xDown,yDown)); 
+                         }
+                       }
+                     break;
+        default    : len = di3D.getNumPoints();
+                                 
+                     for(int g=0; g<len; g++)
+                       {
+                       p3D = di3D.getPoint(g);  
+                       gx = p3D.getX();
+                       gy = p3D.getY();
+                       gz = p3D.getZ();
+                               
+                     if( currentDim==DIM_3DXY )
+                       {
+                       if( (xDown-gx)*(xDown-gx) + (yDown-gy)*(yDown-gy) < (InterpolatorRenderer.BHEI)*(InterpolatorRenderer.BHEI)/100 )
+                         {
+                         moving = g;
+                         break;
+                         }
+                       }
+                     if( currentDim==DIM_3DXZ )
+                       {
+                       if( (xDown-gx)*(xDown-gx) + (yDown-gz)*(yDown-gz) < (InterpolatorRenderer.BHEI)*(InterpolatorRenderer.BHEI)/100 )
+                         {
+                         moving = g;
+                         break;
+                         }
+                       }
+                     }
+                   if( moving<0 )
+                     { 
+                     synchronized(lock)
+                       {
+                       if( len>=MAX_VECTORS ) di3D.removeAll();
+                    
+                       if( currentDim==DIM_3DXY )
+                         {
+                         di3D.add(new Float3D(xDown,yDown,InterpolatorRenderer.BHEI/2));
+                         }
+                       if( currentDim==DIM_3DXZ )
+                         {
+                         di3D.add(new Float3D(xDown,InterpolatorRenderer.BHEI/2,yDown));
+                         }
+                       }
+                     }
+                   break; 
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////
+    
+    @Override public boolean onTouchEvent(MotionEvent event) 
+      {
+      int action = event.getAction();
+          
+      switch(action)
+        {
+        case MotionEvent.ACTION_DOWN: xDown = (int)event.getX()*InterpolatorRenderer.BWID/mScrW; 
+                                      yDown = (int)event.getY()*InterpolatorRenderer.BHEI/mScrH;
+                                      
+                                      addNewPoint(xDown,yDown);
+                                    
+                                      break;
+        case MotionEvent.ACTION_MOVE: if( moving>=0 )
+                                        {
+                                        xDown = (int)event.getX()*InterpolatorRenderer.BWID/mScrW; 
+                                        yDown = (int)event.getY()*InterpolatorRenderer.BHEI/mScrH;
+                                        
+                                        switch(currentDim)
+                                          {
+                                          case DIM_1D  : di1D.setPoint(moving, xDown); 
+                                                         break;
+                                          case DIM_2D  : di2D.setPoint(moving, xDown, yDown);
+                                                         break;
+                                          case DIM_3DXY: di3D.setPoint(moving, xDown, yDown, (int)di3D.getPoint(moving).getZ());
+                                                         break;
+                                          case DIM_3DXZ: di3D.setPoint(moving, xDown, (int)di3D.getPoint(moving).getY(), yDown);
+                                                         break;
+                                          }
+                                        }                           
+                                      break;
+        case MotionEvent.ACTION_UP  : moving = -1;
+                                      break;
+        }
+            
+      return true;
+      }
+ 
+///////////////////////////////////////////////////////////////////
+  }
diff --git a/src/main/java/org/distortedandroid/examples/listener/ListenerActivity.java b/src/main/java/org/distortedandroid/examples/listener/ListenerActivity.java
new file mode 100644
index 0000000..b0c7210
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/listener/ListenerActivity.java
@@ -0,0 +1,52 @@
+
+package org.distortedandroid.examples.listener;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class ListenerActivity extends Activity 
+{
+    private ListenerSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new ListenerSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/listener/ListenerRenderer.java b/src/main/java/org/distortedandroid/examples/listener/ListenerRenderer.java
new file mode 100644
index 0000000..367ac6a
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/listener/ListenerRenderer.java
@@ -0,0 +1,144 @@
+
+package org.distortedandroid.examples.listener;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Random;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.EffectListener;
+import org.distortedandroid.library.EffectMessage;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class ListenerRenderer implements GLSurfaceView.Renderer,EffectListener 
+{
+   private GLSurfaceView mView;
+   private DistortedBitmap water;
+   private int bmpHeight, bmpWidth;
+   private Random mRnd;
+    
+   private final int NUM_BUBBLES = 12;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public ListenerRenderer(GLSurfaceView v) 
+      {
+      Distorted.setMaxVertex(NUM_BUBBLES);   
+      mView = v;
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private long randomizeNewBubble()
+      {
+      int radius   = (int)((0.10f + 0.70f*mRnd.nextFloat())*bmpWidth);            // pop up a bubble of size (radius,height)
+      int height   = (int)((-0.10f + 0.20f*mRnd.nextFloat())*bmpWidth);           // 
+      int pointx   = mRnd.nextInt( (int)(0.8f*bmpWidth)) + (int)(0.1f*bmpWidth);  // at a random place on the bitmap (but not near the edge)
+      int pointy   = mRnd.nextInt( (int)(0.8f*bmpHeight))+ (int)(0.1f*bmpHeight); // 
+      int duration = 1000 + mRnd.nextInt(3000);                                   // for anytime from 3 to 4 seconds 
+        
+      Float3D dp3d = new Float3D(0,0,height);
+      Float2D dp2d = new Float2D(pointx,pointy);
+      Float4D  dr  = new Float4D(0,0,radius,radius);
+     
+      return water.distort(dp3d, dr, dp2d, duration, 1.0f);
+      }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void effectMessage(EffectMessage em, long effectID, int effectType, long bitmapID)
+     {
+     switch(em)
+        {
+        case EFFECT_REMOVED: randomizeNewBubble();
+        default            : break;
+        }
+     }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      water.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      water.abortAllEffects(Distorted.TYPE_MATR);  
+         
+      if( bmpHeight/bmpWidth > height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        water.move((width-w)/2 ,0, 0);
+        water.scale((float)height/bmpHeight);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        water.move(0 ,(height-h)/2, 0);
+        water.scale((float)width/bmpWidth);
+        }
+      
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.water);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      mRnd = new Random(0);
+      
+      bmpHeight = bitmap.getHeight();
+      bmpWidth  = bitmap.getWidth();
+      
+      water = new DistortedBitmap(bitmap, 50);
+      water.addEventListener(this);
+      
+      for(int i=0; i<NUM_BUBBLES; i++) randomizeNewBubble();
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Renderer", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/listener/ListenerSurfaceView.java b/src/main/java/org/distortedandroid/examples/listener/ListenerSurfaceView.java
new file mode 100644
index 0000000..0c5a40f
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/listener/ListenerSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.listener;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class ListenerSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public ListenerSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new ListenerRenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/macroblock/MacroblockActivity.java b/src/main/java/org/distortedandroid/examples/macroblock/MacroblockActivity.java
new file mode 100644
index 0000000..aed30fc
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/macroblock/MacroblockActivity.java
@@ -0,0 +1,51 @@
+
+package org.distortedandroid.examples.macroblock;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class MacroblockActivity extends Activity 
+{
+    private MacroblockSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new MacroblockSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    public void onDestroy()
+      {
+      Distorted.onDestroy();
+      super.onDestroy();
+      }     
+     
+}
diff --git a/src/main/java/org/distortedandroid/examples/macroblock/MacroblockRenderer.java b/src/main/java/org/distortedandroid/examples/macroblock/MacroblockRenderer.java
new file mode 100644
index 0000000..478e30d
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/macroblock/MacroblockRenderer.java
@@ -0,0 +1,124 @@
+package org.distortedandroid.examples.macroblock;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Interpolator1D;
+import org.distortedandroid.library.Interpolator3D;
+import org.distortedandroid.library.Float1D;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class MacroblockRenderer implements GLSurfaceView.Renderer 
+{
+    private GLSurfaceView mView;
+    private DistortedBitmap macroblock;
+    private Float4D Region;
+    private int bmpHeight, bmpWidth;
+    private Float2D traP, macP;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public MacroblockRenderer(GLSurfaceView v) 
+      {   
+      mView = v;
+      
+      Region = new Float4D(0,0,100,100);
+      macP   = new Float2D(530,200);
+      traP   = new Float2D(230,200);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+   
+      macroblock.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {  
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.cat_and_dog);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      bmpHeight = bitmap.getHeight();
+      bmpWidth  = bitmap.getWidth();
+      
+      macroblock = new DistortedBitmap(bitmap, 30);    
+      macroblock.macroblock(  30, Region, macP, 3000, 0.0f);
+      macroblock.alpha     (0.0f, Region, traP, 3000, 0.0f);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Renderer", ex.getMessage() );
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      {
+      int duration = 10000;   
+      
+      Interpolator3D diMove = new Interpolator3D();
+      diMove.setCount(0.0f);
+      diMove.setDuration(duration);
+      diMove.add(new Float3D(width-bmpWidth,height-bmpHeight,0));
+      diMove.add(new Float3D(0,0,0));
+      
+      Interpolator3D diScale = new Interpolator3D();
+      diScale.setCount(0.0f);
+      diScale.setDuration(duration);
+      diScale.add(new Float3D(1,1,1));
+      diScale.add(new Float3D(0.33f,0.33f,1));
+      
+      Interpolator1D diRotate = new Interpolator1D();
+      diRotate.setCount(0.0f);
+      diRotate.setDuration(duration);
+      diRotate.add(new Float1D(  0));
+      diRotate.add(new Float1D(360));
+      
+      macroblock.abortAllEffects(Distorted.TYPE_MATR);   
+
+      macroblock.move(diMove);
+      macroblock.scale(diScale);
+      macroblock.rotate( new Float3D(bmpWidth/2,bmpHeight/2,0), diRotate, 0.0f, 0.0f, 1.0f);
+      
+      Distorted.onSurfaceChanged(width, height); 
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/macroblock/MacroblockSurfaceView.java b/src/main/java/org/distortedandroid/examples/macroblock/MacroblockSurfaceView.java
new file mode 100644
index 0000000..5ad2726
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/macroblock/MacroblockSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.macroblock;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class MacroblockSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public MacroblockSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new MacroblockRenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/monalisa/MonaLisaActivity.java b/src/main/java/org/distortedandroid/examples/monalisa/MonaLisaActivity.java
new file mode 100644
index 0000000..1b40c5f
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/monalisa/MonaLisaActivity.java
@@ -0,0 +1,52 @@
+
+package org.distortedandroid.examples.monalisa;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class MonaLisaActivity extends Activity 
+{
+    private MonaLisaSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new MonaLisaSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/monalisa/MonaLisaRenderer.java b/src/main/java/org/distortedandroid/examples/monalisa/MonaLisaRenderer.java
new file mode 100644
index 0000000..f19ac6d
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/monalisa/MonaLisaRenderer.java
@@ -0,0 +1,117 @@
+
+package org.distortedandroid.examples.monalisa;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class MonaLisaRenderer implements GLSurfaceView.Renderer 
+{
+    private GLSurfaceView mView;
+    private DistortedBitmap monaLisa;
+    private Float2D pLeft, pRight;
+    private Float4D rLeft, rRight;
+    private Float3D vLeft, vRight;
+    private int bmpHeight, bmpWidth;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public MonaLisaRenderer(GLSurfaceView v) 
+      {
+      mView = v;
+      
+      pLeft = new Float2D( 90, 258);
+      pRight= new Float2D(176, 255);
+      
+      rLeft = new Float4D(-10,-10,25,25);
+      rRight= new Float4D( 10, -5,25,25);
+      
+      vLeft = new Float3D(-20,-20,0);
+      vRight= new Float3D( 20,-10,0);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      monaLisa.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      monaLisa.abortAllEffects(Distorted.TYPE_MATR);  
+         
+      if( bmpHeight/bmpWidth > height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        monaLisa.move((width-w)/2 ,0, 0);
+        monaLisa.scale((float)height/bmpHeight);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        monaLisa.move(0 ,(height-h)/2, 0);
+        monaLisa.scale((float)width/bmpWidth);
+        }
+      
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.monalisa);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      bmpHeight = bitmap.getHeight();
+      bmpWidth  = bitmap.getWidth();
+      
+      monaLisa = new DistortedBitmap(bitmap, 10);
+      monaLisa.distort( vLeft, rLeft , pLeft, 1000, 0);
+      monaLisa.distort(vRight, rRight, pRight,1000, 0);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("MonaLisa", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/monalisa/MonaLisaSurfaceView.java b/src/main/java/org/distortedandroid/examples/monalisa/MonaLisaSurfaceView.java
new file mode 100644
index 0000000..6ca748a
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/monalisa/MonaLisaSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.monalisa;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class MonaLisaSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public MonaLisaSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new MonaLisaRenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/movingeffects/MovingEffectsActivity.java b/src/main/java/org/distortedandroid/examples/movingeffects/MovingEffectsActivity.java
new file mode 100644
index 0000000..1c45a49
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/movingeffects/MovingEffectsActivity.java
@@ -0,0 +1,182 @@
+package org.distortedandroid.examples.movingeffects;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.examples.R;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+import android.widget.Toast;
+
+///////////////////////////////////////////////////////////////////
+
+public class MovingEffectsActivity extends Activity
+    {
+    private static final int COLOR_PRESSED   = 0xff0000ff;
+    private static final int COLOR_UNPRESSED = 0x888888ff;
+    private static final String SHOWED_TOAST = "showed_toast";
+
+    Button mAbort, mMacro, mTrans, mSink, mBubble, mSwirl;
+   
+///////////////////////////////////////////////////////////////////
+    @Override
+    protected void onCreate(Bundle savedState) 
+      {
+      super.onCreate(savedState);
+  
+      setContentView(R.layout.movingeffectslayout);
+      
+      mAbort = (Button)findViewById(R.id.movingeffectsAbort);
+      mMacro = (Button)findViewById(R.id.movingeffectsMacro);
+      mTrans = (Button)findViewById(R.id.movingeffectsTrans);
+      mSink  = (Button)findViewById(R.id.movingeffectsSink);
+      mBubble= (Button)findViewById(R.id.movingeffectsBubble);
+      mSwirl= (Button)findViewById(R.id.movingeffectsSwirl);
+      
+      mAbort.setBackgroundColor(COLOR_PRESSED);
+      mMacro.setBackgroundColor(COLOR_UNPRESSED);
+      mTrans.setBackgroundColor(COLOR_UNPRESSED);
+      mSink.setBackgroundColor(COLOR_UNPRESSED);
+      mBubble.setBackgroundColor(COLOR_UNPRESSED);
+      mSwirl.setBackgroundColor(COLOR_UNPRESSED);
+     
+      if ( savedState== null || !savedState.getBoolean(SHOWED_TOAST, false))
+         {
+         Toast.makeText(this, R.string.example_movingeffects_toast , Toast.LENGTH_LONG).show();
+         }   
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.movingeffectsSurfaceView);
+      mView.onResume();
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    protected void onPause() 
+      {
+      Abort(null);   
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.movingeffectsSurfaceView);
+      mView.onPause();
+      
+      super.onPause();
+      }
+    
+///////////////////////////////////////////////////////////////////
+    @Override
+    public void onStop()
+      {
+      super.onStop();
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    public void onDestroy()
+      {
+      Distorted.onDestroy();
+      super.onDestroy();
+      }     
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onSaveInstanceState (Bundle outState)
+      {
+      outState.putBoolean(SHOWED_TOAST, true);
+      }
+     
+///////////////////////////////////////////////////////////////////
+    
+    public void Bubble(View v)
+      {
+      MovingEffectsSurfaceView.Bubble();
+      
+      mAbort.setBackgroundColor(COLOR_UNPRESSED);
+      mMacro.setBackgroundColor(COLOR_UNPRESSED);
+      mTrans.setBackgroundColor(COLOR_UNPRESSED);
+      mSink.setBackgroundColor(COLOR_UNPRESSED);
+      mBubble.setBackgroundColor(COLOR_PRESSED);
+      mSwirl.setBackgroundColor(COLOR_UNPRESSED);
+      }     
+    
+///////////////////////////////////////////////////////////////////
+
+    public void Sink(View v)
+      {
+      MovingEffectsSurfaceView.Sink();
+      
+      mAbort.setBackgroundColor(COLOR_UNPRESSED);
+      mMacro.setBackgroundColor(COLOR_UNPRESSED);
+      mTrans.setBackgroundColor(COLOR_UNPRESSED);
+      mSink.setBackgroundColor(COLOR_PRESSED);
+      mBubble.setBackgroundColor(COLOR_UNPRESSED);
+      mSwirl.setBackgroundColor(COLOR_UNPRESSED);
+      }       
+
+///////////////////////////////////////////////////////////////////
+    
+    public void Transparency(View v)
+      {
+      MovingEffectsSurfaceView.Transparency();
+      
+      mAbort.setBackgroundColor(COLOR_UNPRESSED);
+      mMacro.setBackgroundColor(COLOR_UNPRESSED);
+      mTrans.setBackgroundColor(COLOR_PRESSED);
+      mSink.setBackgroundColor(COLOR_UNPRESSED);
+      mBubble.setBackgroundColor(COLOR_UNPRESSED);
+      mSwirl.setBackgroundColor(COLOR_UNPRESSED);
+      }     
+    
+///////////////////////////////////////////////////////////////////
+
+    public void Macroblock(View v)
+      {
+      MovingEffectsSurfaceView.Macroblock();
+      
+      mAbort.setBackgroundColor(COLOR_UNPRESSED);
+      mMacro.setBackgroundColor(COLOR_PRESSED);
+      mTrans.setBackgroundColor(COLOR_UNPRESSED);
+      mSink.setBackgroundColor(COLOR_UNPRESSED);
+      mBubble.setBackgroundColor(COLOR_UNPRESSED);
+      mSwirl.setBackgroundColor(COLOR_UNPRESSED);
+      }       
+
+///////////////////////////////////////////////////////////////////
+
+    public void Swirl(View v)
+      {
+      MovingEffectsSurfaceView.Swirl();
+      
+      mAbort.setBackgroundColor(COLOR_UNPRESSED);
+      mMacro.setBackgroundColor(COLOR_UNPRESSED);
+      mTrans.setBackgroundColor(COLOR_UNPRESSED);
+      mSink.setBackgroundColor(COLOR_UNPRESSED);
+      mBubble.setBackgroundColor(COLOR_UNPRESSED);
+      mSwirl.setBackgroundColor(COLOR_PRESSED);
+      }       
+    
+///////////////////////////////////////////////////////////////////
+
+    public void Abort(View v)
+      {
+      MovingEffectsSurfaceView.Abort();
+      
+      mAbort.setBackgroundColor(COLOR_PRESSED);
+      mMacro.setBackgroundColor(COLOR_UNPRESSED);
+      mTrans.setBackgroundColor(COLOR_UNPRESSED);
+      mSink.setBackgroundColor(COLOR_UNPRESSED);
+      mBubble.setBackgroundColor(COLOR_UNPRESSED);
+      mSwirl.setBackgroundColor(COLOR_UNPRESSED);
+      }
+
+///////////////////////////////////////////////////////////////////
+// end of file
+}
diff --git a/src/main/java/org/distortedandroid/examples/movingeffects/MovingEffectsRenderer.java b/src/main/java/org/distortedandroid/examples/movingeffects/MovingEffectsRenderer.java
new file mode 100644
index 0000000..0f544c3
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/movingeffects/MovingEffectsRenderer.java
@@ -0,0 +1,109 @@
+package org.distortedandroid.examples.movingeffects;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Distorted;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class MovingEffectsRenderer implements GLSurfaceView.Renderer 
+   {  
+   public static final int NUMLINES = 10;
+   public static final int BWID = 300;
+   public static final int BHEI = 400;
+   
+   private GLSurfaceView mView;
+   public static DistortedBitmap mBackground;
+   private Canvas mCanvas;
+   private Bitmap mBitmap;
+   private Paint mPaint;
+   private int texWidth, texHeight;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public MovingEffectsRenderer(GLSurfaceView v)
+     {    
+     mPaint = new Paint();
+     mPaint.setAntiAlias(true);
+     mPaint.setFakeBoldText(true);
+     mPaint.setStyle(Style.FILL);
+      
+     mView = v;
+      
+     texWidth = BWID;
+     texHeight= BHEI;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private void drawBackground()
+     {
+     mPaint.setColor(0xff008800);
+     mCanvas.drawRect(0, 0, texWidth, texHeight, mPaint);
+     mPaint.setColor(0xffffffff);
+         
+     for(int i=0; i<=NUMLINES ; i++ )
+       {
+       mCanvas.drawRect(texWidth*i/NUMLINES - 2,                       0,  texWidth*i/NUMLINES + 2,  texHeight               , mPaint);
+       mCanvas.drawRect(                      0, texHeight*i/NUMLINES -2,  texWidth               ,  texHeight*i/NUMLINES + 2, mPaint);  
+       } 
+     }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+     {         
+     mBackground = new DistortedBitmap(texWidth,texHeight, 80);   
+     mBitmap = Bitmap.createBitmap(texWidth,texHeight, Bitmap.Config.ARGB_8888);
+     mCanvas = new Canvas(mBitmap); 
+      
+     try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Renderer", ex.getMessage() );
+        }
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void onSurfaceChanged(GL10 glUnused, int width, int height)
+     {
+     mBackground.abortAllEffects(Distorted.TYPE_MATR);   
+     mBackground.scale((float)width/texWidth,(float)height/texHeight,1);
+   
+     Distorted.onSurfaceChanged(width, height);
+     MovingEffectsSurfaceView.setScreenSize(width, height);    
+     }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   public void onDrawFrame(GL10 glUnused)
+     {   
+     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);               
+       
+     long time = System.currentTimeMillis();
+      
+     if (MovingEffectsSurfaceView.getCurrentEffect() == MovingEffectsSurfaceView.EFFECT_POINTS )
+       {
+       drawBackground();   
+       MovingEffectsSurfaceView.drawCurve(mCanvas,time);
+       mBackground.setBitmap(mBitmap);  
+       }
+      
+     mBackground.draw(time);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+}
diff --git a/src/main/java/org/distortedandroid/examples/movingeffects/MovingEffectsSurfaceView.java b/src/main/java/org/distortedandroid/examples/movingeffects/MovingEffectsSurfaceView.java
new file mode 100644
index 0000000..1418a63
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/movingeffects/MovingEffectsSurfaceView.java
@@ -0,0 +1,271 @@
+package org.distortedandroid.examples.movingeffects;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.view.MotionEvent;
+import android.util.AttributeSet;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.Interpolator2D;
+import org.distortedandroid.library.Interpolator3D;
+
+///////////////////////////////////////////////////////////////////
+
+public class MovingEffectsSurfaceView extends GLSurfaceView
+    {
+    private static final int LOOP_TIME = 5000;
+    private static final int NUM_INTERPOLATIONS= 100;
+   
+    public static final int EFFECT_POINTS=0;
+    public static final int EFFECT_BUBBLE=1;
+    public static final int EFFECT_SINK  =2;
+    public static final int EFFECT_TRANS =3;
+    public static final int EFFECT_MACRO =4;
+    public static final int EFFECT_SWIRL =5;
+   
+    private static MovingEffectsRenderer mRenderer;
+    
+    private static int xDown,yDown;
+    private static int mScrW, mScrH;
+    
+    private static Interpolator2D di2D;
+    private static Interpolator3D di3D;
+    private static Float4D dr;
+    
+    private static Paint mPaint;
+    private static int moving;
+    private static Object lock = new Object();
+    private static long mTime = 0;
+    
+    private static int mCurrEffect;
+    
+///////////////////////////////////////////////////////////////////
+    
+    public MovingEffectsSurfaceView(Context c, AttributeSet attrs) 
+      {
+      super(c, attrs);
+          
+      mCurrEffect=EFFECT_POINTS;
+      mPaint = new Paint();
+      mPaint.setStyle(Style.FILL);
+      moving = -1;
+      
+      di2D = new Interpolator2D();
+      di2D.setCount(0.0f);
+      di2D.setDuration(LOOP_TIME);
+      
+      di3D = new Interpolator3D();
+      di3D.add(new Float3D(0,0, 0));
+      di3D.add(new Float3D(0,0,30));
+      
+      dr = new Float4D(0,0,60,60);
+      
+      if(!isInEditMode())
+        {
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        
+        setEGLContextClientVersion(2);
+        
+        if( Build.FINGERPRINT.startsWith("generic") ) // when running on the emulator, insert a magic line that is
+          {                                           // supposed to cure the 'no config chosen' crash on emulator startup
+          setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+          }
+        
+        mRenderer = new MovingEffectsRenderer(this);
+        setRenderer(mRenderer);
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void setScreenSize(int width, int height)
+      {
+      mScrW = width;
+      mScrH = height;
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static int getCurrentEffect()
+      {
+      return mCurrEffect;
+      }
+    
+///////////////////////////////////////////////////////////////////
+    
+    public static void Bubble()
+      {
+      if( mCurrEffect==EFFECT_BUBBLE ) return;     
+      
+      synchronized(lock)
+        {
+        MovingEffectsRenderer.mBackground.abortAllEffects(Distorted.TYPE_FRAG|Distorted.TYPE_VERT);
+        MovingEffectsRenderer.mBackground.distort(di3D, dr, di2D);
+        mCurrEffect = EFFECT_BUBBLE;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void Sink()
+      {
+      if( mCurrEffect==EFFECT_SINK ) return; 
+         
+      synchronized(lock)
+        {
+        MovingEffectsRenderer.mBackground.abortAllEffects(Distorted.TYPE_FRAG|Distorted.TYPE_VERT);
+        MovingEffectsRenderer.mBackground.sink(10.0f, dr, di2D, 0, 0.5f);  
+        mCurrEffect = EFFECT_SINK;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void Macroblock()
+      {
+      if( mCurrEffect==EFFECT_MACRO ) return;   
+         
+      synchronized(lock)
+        {
+        MovingEffectsRenderer.mBackground.abortAllEffects(Distorted.TYPE_FRAG|Distorted.TYPE_VERT);
+        MovingEffectsRenderer.mBackground.macroblock(3, dr, di2D, 0, 0.5f);  
+        mCurrEffect = EFFECT_MACRO;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void Transparency()
+      {
+      if( mCurrEffect==EFFECT_TRANS ) return;   
+      
+      synchronized(lock)
+        {
+        MovingEffectsRenderer.mBackground.abortAllEffects(Distorted.TYPE_FRAG|Distorted.TYPE_VERT);
+        MovingEffectsRenderer.mBackground.smooth_alpha(0.5f, dr, di2D, 0, 0.5f);  
+        mCurrEffect = EFFECT_TRANS;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void Swirl()
+      {
+      if( mCurrEffect==EFFECT_SWIRL ) return;   
+      
+      synchronized(lock)
+        {
+        MovingEffectsRenderer.mBackground.abortAllEffects(Distorted.TYPE_FRAG|Distorted.TYPE_VERT);
+        MovingEffectsRenderer.mBackground.swirl(30, dr, di2D, 0, 0.5f);  
+        mCurrEffect = EFFECT_SWIRL;
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////
+
+    public static void Abort()
+      {
+      synchronized(lock)
+        {
+        MovingEffectsRenderer.mBackground.abortAllEffects(Distorted.TYPE_FRAG|Distorted.TYPE_VERT);  
+        di2D.removeAll();
+        mCurrEffect = EFFECT_POINTS;
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+ 
+    public static void drawCurve(Canvas c, long time)
+      {
+      synchronized(lock)
+        {  
+        int len = di2D.getNumPoints();
+        float[] drawCoord = new float[2];
+        Float2D cu;
+        int lit = mTime> 0 ? (int)((float)(time-mTime)*NUM_INTERPOLATIONS/LOOP_TIME)  : 0; 
+            
+        if( len>=2 )
+          {
+          for(int i=0; i<NUM_INTERPOLATIONS; i++) 
+            {
+            int color = i<=lit ? 0xff - (lit                   -i)*0xff/(NUM_INTERPOLATIONS-1)  
+                               : 0xff - (lit+NUM_INTERPOLATIONS-i)*0xff/(NUM_INTERPOLATIONS-1);
+         
+            mPaint.setColor( 0xffffff + ((color&0xff)<<24) );  
+            di2D.interpolate( drawCoord, 0, (float)i/NUM_INTERPOLATIONS);
+            c.drawCircle(drawCoord[0], drawCoord[1], 2.0f, mPaint );
+            }
+          }
+     
+        mPaint.setColor(0xffff0000);
+      
+        for(int curr=0; curr<len; curr++)
+          {       
+          cu = di2D.getPoint(curr);
+          c.drawCircle(cu.getX(), cu.getY(), 5.0f, mPaint);
+          }
+        
+        if( time-mTime > LOOP_TIME ) mTime = time;
+        }
+      }
+       
+///////////////////////////////////////////////////////////////////
+    
+    @Override public boolean onTouchEvent(MotionEvent event) 
+      {
+      if( mCurrEffect!=EFFECT_POINTS ) return true;   
+      
+      switch(event.getAction())
+        {
+        case MotionEvent.ACTION_DOWN: xDown = (int)event.getX()*MovingEffectsRenderer.BWID/mScrW; 
+                                      yDown = (int)event.getY()*MovingEffectsRenderer.BHEI/mScrH;
+                                    
+                                      float gx, gy;
+                                      Float2D dv;
+                                      int len = di2D.getNumPoints();
+                                 
+                                      for(int g=0; g<len; g++)
+                                        {
+                                        dv = di2D.getPoint(g); 
+                                        gx = dv.getX();
+                                        gy = dv.getY();
+                                    
+                                        if( (xDown-gx)*(xDown-gx) + (yDown-gy)*(yDown-gy) < (MovingEffectsRenderer.BHEI*MovingEffectsRenderer.BHEI)/100 )
+                                          {
+                                          moving = g;
+                                          break;
+                                          }
+                                        }
+                                      if( moving<0 )
+                                        {
+                                        synchronized(lock)
+                                          {
+                                          di2D.add(new Float2D(xDown,yDown)); 
+                                          }
+                                        } 
+                                      break;
+        case MotionEvent.ACTION_MOVE: if( moving>=0 )
+                                        {
+                                        xDown = (int)event.getX()*MovingEffectsRenderer.BWID/mScrW; 
+                                        yDown = (int)event.getY()*MovingEffectsRenderer.BHEI/mScrH;
+                                        di2D.setPoint(moving, xDown, yDown);
+                                        }                           
+                                      break;
+        case MotionEvent.ACTION_UP  : moving = -1;
+                                      break;
+        }
+      return true;
+      }
+ 
+///////////////////////////////////////////////////////////////////
+// end of file
+
+  }
diff --git a/src/main/java/org/distortedandroid/examples/olimpic/OlimpicActivity.java b/src/main/java/org/distortedandroid/examples/olimpic/OlimpicActivity.java
new file mode 100644
index 0000000..5e4d901
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/olimpic/OlimpicActivity.java
@@ -0,0 +1,51 @@
+
+package org.distortedandroid.examples.olimpic;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class OlimpicActivity extends Activity 
+{
+    private OlimpicSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new OlimpicSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }    
+}
diff --git a/src/main/java/org/distortedandroid/examples/olimpic/OlimpicRenderer.java b/src/main/java/org/distortedandroid/examples/olimpic/OlimpicRenderer.java
new file mode 100644
index 0000000..917757a
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/olimpic/OlimpicRenderer.java
@@ -0,0 +1,160 @@
+
+package org.distortedandroid.examples.olimpic;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Interpolator1D;
+import org.distortedandroid.library.DistortedNode;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float1D;
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class OlimpicRenderer implements GLSurfaceView.Renderer 
+{
+   private static final int LEAF_SIZE = 100;
+   private static final int NUM_CIRCLES = 5;
+   private static final int NUM_LEAVES = 8;  
+   
+   private GLSurfaceView mView;
+   private DistortedNode[] mCircleNode;
+   private DistortedNode mScreen;
+   private DistortedBitmap mLeaf;
+   private Interpolator1D mRot;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public 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));
+     
+      mRot = new Interpolator1D();
+      mRot.setMode(Interpolator1D.MODE_JUMP);
+      mRot.setCount(0.0f);
+      mRot.setDuration(5000);
+      mRot.add(new Float1D(  0));
+      mRot.add(new Float1D(360));
+      
+      mCircleNode = new DistortedNode[NUM_CIRCLES];
+    
+      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;
+      Float3D center = new Float3D(3*LEAF_SIZE/2, 3*LEAF_SIZE/2, 0);
+      
+      for(int i=0; i<NUM_CIRCLES; i++)
+        {
+        if( i==0 )
+          {
+          mCircleNode[i] = new DistortedNode(new DistortedBitmap(3*LEAF_SIZE,3*LEAF_SIZE,1));
+        
+          for(int j=0; j<NUM_LEAVES; j++)
+            {
+            tmp = new DistortedBitmap(mLeaf, Distorted.CLONE_BITMAP);
+            mCircleNode[i].attach(tmp);
+            tmp.rotate(center, j*(360/NUM_LEAVES)); 
+            tmp.move(0,LEAF_SIZE,0);
+            }
+          }
+        else
+          {
+          mCircleNode[i] = new DistortedNode(mCircleNode[0], Distorted.CLONE_BITMAP|Distorted.CLONE_CHILDREN); 
+          }
+      
+        mScreen.attach(mCircleNode[i]);
+        tmp = mCircleNode[i].getBitmap();
+        tmp.move(positions[2*i], positions[2*i+1], 0);
+        tmp.rotate( center, mRot, 0.0f, 0.0f, 1.0f);
+        tmp.chroma(0.8f, new Float3D(colors[3*i],colors[3*i+1], colors[3*i+2]));
+        }
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      mScreen.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      {
+      DistortedBitmap bmp = mScreen.getBitmap();
+      int bmpWidth  = bmp.getWidth();
+      int bmpHeight = bmp.getHeight();
+     
+      bmp.abortAllEffects(Distorted.TYPE_MATR); 
+      
+      if( bmpHeight/bmpWidth > height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        bmp.move((width-w)/2 ,0, 0);
+        bmp.scale((float)height/bmpHeight);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        bmp.move(0 ,(height-h)/2, 0);
+        bmp.scale((float)width/bmpWidth);
+        }
+      
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.leaf);
+      Bitmap leaf;
+      
+      try 
+        {
+        leaf = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      mLeaf.setBitmap(leaf);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("DifferentEffectsRenderer", ex.getMessage() );
+        }
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/olimpic/OlimpicSurfaceView.java b/src/main/java/org/distortedandroid/examples/olimpic/OlimpicSurfaceView.java
new file mode 100644
index 0000000..7d5f9ce
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/olimpic/OlimpicSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.olimpic;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class OlimpicSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public OlimpicSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new OlimpicRenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/quaternion/QuaternionActivity.java b/src/main/java/org/distortedandroid/examples/quaternion/QuaternionActivity.java
new file mode 100644
index 0000000..4f774fa
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/quaternion/QuaternionActivity.java
@@ -0,0 +1,51 @@
+
+package org.distortedandroid.examples.quaternion;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class QuaternionActivity extends Activity
+{
+    private QuaternionSurfaceView mView;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new QuaternionSurfaceView(this);
+      setContentView(mView);     
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();  
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/quaternion/QuaternionRenderer.java b/src/main/java/org/distortedandroid/examples/quaternion/QuaternionRenderer.java
new file mode 100644
index 0000000..d18774e
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/quaternion/QuaternionRenderer.java
@@ -0,0 +1,128 @@
+
+package org.distortedandroid.examples.quaternion;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Random;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Interpolator;
+import org.distortedandroid.library.InterpolatorQuat;
+import org.distortedandroid.library.DistortedCubes;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Distorted;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class QuaternionRenderer implements GLSurfaceView.Renderer 
+{
+	private static final int NUM_QUATERNIONS = 5;
+	private static final int SIZE = 100;
+	
+    private GLSurfaceView mView;
+    private DistortedCubes mCube;
+    private Random mRnd = new Random(System.currentTimeMillis());
+    private InterpolatorQuat mRot;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public QuaternionRenderer(GLSurfaceView v) 
+      {
+      mView = v;
+      mCube = new DistortedCubes( 3, "000010000", SIZE);
+      
+      mRot = new InterpolatorQuat();
+      
+      float x,y,z,w, len;
+      
+      for(int i=0; i<NUM_QUATERNIONS; i++)
+        {
+        x = 2*mRnd.nextFloat()-1;  
+        y = 2*mRnd.nextFloat()-1;  
+        z = 2*mRnd.nextFloat()-1;  
+        w = 2*mRnd.nextFloat()-1;  
+    	 
+        len = (float)Math.sqrt( x*x+y*y+z*z+w*w );
+    		
+        mRot.add(new Float4D(x/len,y/len,z/len,w/len));
+        }
+    
+      mRot.setCount(0);
+      mRot.setDuration(8000);
+      mRot.setMode(Interpolator.MODE_LOOP);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      mCube.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      {
+      mCube.abortAllEffects(Distorted.TYPE_MATR);  
+
+      if( width > height )
+        {
+        mCube.move((width-height)/2 ,0, 0);
+        mCube.scale(height/(3.0f*SIZE));
+        }  
+      else
+        {   
+        mCube.move(0 ,(height-width)/2, 0);
+        mCube.scale(width/(3.0f*SIZE));
+        }
+     
+      mCube.quaternion( new Float3D(3*SIZE/2,3*SIZE/2,0), mRot);
+       
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.grid);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      mCube.setBitmap(bitmap);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Quaternion", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/quaternion/QuaternionSurfaceView.java b/src/main/java/org/distortedandroid/examples/quaternion/QuaternionSurfaceView.java
new file mode 100644
index 0000000..1553215
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/quaternion/QuaternionSurfaceView.java
@@ -0,0 +1,31 @@
+
+package org.distortedandroid.examples.quaternion;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class QuaternionSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public QuaternionSurfaceView(Context c) 
+      {
+      super(c);
+      
+      if(!isInEditMode())
+        {
+        setEGLContextClientVersion(2);
+        
+        if( Build.FINGERPRINT.startsWith("generic") )
+          { 
+          setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+          }
+        
+        setRenderer(new QuaternionRenderer(this));
+        }
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/scratchpad/ScratchpadActivity.java b/src/main/java/org/distortedandroid/examples/scratchpad/ScratchpadActivity.java
new file mode 100644
index 0000000..68f152b
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/scratchpad/ScratchpadActivity.java
@@ -0,0 +1,175 @@
+package org.distortedandroid.examples.scratchpad;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.examples.R;
+
+import android.app.Activity;
+import android.opengl.GLSurfaceView;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.SeekBar;
+import android.widget.TextView;
+
+///////////////////////////////////////////////////////////////////
+
+public class ScratchpadActivity extends Activity implements OnSeekBarChangeListener
+    {
+    private static final float D_MULT=200.0f;
+    private static final float C_MULT=  0.1f;
+   
+    private long effectID;
+   
+    private SeekBar barD, barC, barI;
+    private TextView textD, textC, textI;
+   
+///////////////////////////////////////////////////////////////////
+    @Override
+    protected void onCreate(Bundle savedInstanceState) 
+      {
+      super.onCreate(savedInstanceState);
+ 
+      setContentView(R.layout.scratchpadlayout);
+      
+      barD = (SeekBar)findViewById(R.id.scratchpadSeekDuration);
+      barD.setOnSeekBarChangeListener(this); 
+      barC = (SeekBar)findViewById(R.id.scratchpadSeekCount);
+      barC.setOnSeekBarChangeListener(this); 
+      barI = (SeekBar)findViewById(R.id.scratchpadSeekID);
+      barI.setOnSeekBarChangeListener(this); 
+        
+      textD = (TextView)findViewById(R.id.scratchpadTextDuration);
+      textC = (TextView)findViewById(R.id.scratchpadTextCount);
+      textI = (TextView)findViewById(R.id.scratchpadTextID);
+      
+      barD.setProgress(100);
+      barC.setProgress(10);
+      barI.setProgress(0);
+      
+      textD.setText("Dur: 20 s");
+      textC.setText("Cou: 1.0");
+      textI.setText("ID: 0");
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.scratchpadSurfaceView);
+      mView.onResume();
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    protected void onPause() 
+      {
+      GLSurfaceView mView = (GLSurfaceView) this.findViewById(R.id.scratchpadSurfaceView);
+      mView.onPause();
+      
+      super.onPause();
+      }
+    
+///////////////////////////////////////////////////////////////////
+    @Override
+    public void onStop()
+      {
+      super.onStop();
+      }
+
+///////////////////////////////////////////////////////////////////
+    @Override
+    public void onDestroy()
+      {
+      Distorted.onDestroy();
+      super.onDestroy();
+      }     
+ 
+///////////////////////////////////////////////////////////////////
+    
+    public void Distort(View v)
+      {
+      ScratchpadSurfaceView.setEffect(0);
+      }     
+    
+///////////////////////////////////////////////////////////////////
+
+    public void Sink(View v)
+      {
+      ScratchpadSurfaceView.setEffect(1);
+      }       
+
+///////////////////////////////////////////////////////////////////
+    
+    public void Transparency(View v)
+      {
+      ScratchpadSurfaceView.setEffect(2);
+      }     
+    
+///////////////////////////////////////////////////////////////////
+
+    public void Macroblock(View v)
+      {
+      ScratchpadSurfaceView.setEffect(3);
+      }       
+ 
+///////////////////////////////////////////////////////////////////
+
+    public void Brightness(View v)
+      {
+      ScratchpadSurfaceView.setEffect(4);
+      }       
+     
+///////////////////////////////////////////////////////////////////
+
+    public void Print(View v)
+      {
+      ScratchpadRenderer.mBackground.printEffect(effectID);
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public void Abort(View v)
+      {
+      ScratchpadRenderer.mBackground.abortEffect(effectID);
+      }
+
+///////////////////////////////////////////////////////////////////
+    
+    public void onProgressChanged(SeekBar bar, int progress, boolean fromUser) 
+      {
+      float v, t; 
+      int i;
+      
+      switch (bar.getId()) 
+        {
+        case R.id.scratchpadSeekDuration: v = progress*D_MULT;
+                                          i = (int)(v/100);
+                                          t = i/10.0f;
+                                          ScratchpadSurfaceView.setDuration((int)v);
+                                          textD.setText("Dur: "+(int)t+" s");
+                                          break;
+        case R.id.scratchpadSeekCount   : v = progress*C_MULT;
+                                          i = (int)(v*10);
+                                          t = i/10.0f;
+                                          ScratchpadSurfaceView.setCount(v);
+                                          textC.setText("Cou: "+t);
+                                          break;
+        case R.id.scratchpadSeekID      : effectID = progress;
+                                          textI.setText("ID: "+progress);
+                                          break;                        
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public void onStartTrackingTouch(SeekBar bar) { }
+    
+///////////////////////////////////////////////////////////////////
+
+    public void onStopTrackingTouch(SeekBar bar)  { }
+    
+///////////////////////////////////////////////////////////////////
+// end of file
+}
diff --git a/src/main/java/org/distortedandroid/examples/scratchpad/ScratchpadRenderer.java b/src/main/java/org/distortedandroid/examples/scratchpad/ScratchpadRenderer.java
new file mode 100644
index 0000000..ec390e6
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/scratchpad/ScratchpadRenderer.java
@@ -0,0 +1,93 @@
+package org.distortedandroid.examples.scratchpad;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Distorted;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class ScratchpadRenderer implements GLSurfaceView.Renderer 
+   {  
+   public static final int NUMLINES = 10;
+   public static final int BWID = 300;
+   public static final int BHEI = 400;
+   
+   private GLSurfaceView mView;
+   public static DistortedBitmap mBackground;
+   private Paint mPaint;
+   private int texWidth, texHeight;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public ScratchpadRenderer(GLSurfaceView v)
+     {    
+     mPaint = new Paint();
+     mPaint.setAntiAlias(true);
+     mPaint.setFakeBoldText(true);
+     mPaint.setStyle(Style.FILL);
+      
+     mView = v;
+      
+     texWidth = BWID;
+     texHeight= BHEI;
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   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);  
+      
+     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);  
+       }
+          
+     mBackground.setBitmap(bitmap);
+          
+     try
+       {
+       Distorted.onSurfaceCreated(mView);
+       }
+     catch(Exception ex)
+       {
+       android.util.Log.e("Renderer", ex.getMessage() );
+       }
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public void onSurfaceChanged(GL10 glUnused, int width, int height)
+     {
+     mBackground.abortAllEffects(Distorted.TYPE_MATR);   
+     mBackground.scale((float)width/texWidth,(float)height/texHeight,1);
+     Distorted.onSurfaceChanged(width,height);
+     ScratchpadSurfaceView.setScreenSize(width,height);     
+     }
+   
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   public void onDrawFrame(GL10 glUnused)
+     {   
+     GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
+     mBackground.draw(System.currentTimeMillis());
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+}
diff --git a/src/main/java/org/distortedandroid/examples/scratchpad/ScratchpadSurfaceView.java b/src/main/java/org/distortedandroid/examples/scratchpad/ScratchpadSurfaceView.java
new file mode 100644
index 0000000..458ac25
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/scratchpad/ScratchpadSurfaceView.java
@@ -0,0 +1,152 @@
+package org.distortedandroid.examples.scratchpad;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+import android.view.MotionEvent;
+import android.util.AttributeSet;
+
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.Interpolator3D;
+
+///////////////////////////////////////////////////////////////////
+
+public class ScratchpadSurfaceView extends GLSurfaceView
+    {
+    private ScratchpadRenderer mRenderer;
+    private static int mCurrentEffect;
+    private static int mDuration;
+    private static float mCount;
+    private static int mScrW, mScrH;
+    
+    private static Float4D region;
+    private static Float2D  point;
+    
+    private static Interpolator3D di;
+    private static Float3D v0, v1, v2, v3;
+     
+///////////////////////////////////////////////////////////////////
+    
+    public ScratchpadSurfaceView(Context c, AttributeSet attrs) 
+      {
+      super(c, attrs);
+      
+      mDuration = 10000;
+      mCount    = 1.0f;
+      
+      di = new Interpolator3D();
+
+      di.setDuration(mDuration);
+      di.setCount(mCount);
+      
+      if(!isInEditMode())
+        {
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        
+        setEGLContextClientVersion(2);
+        
+        if( Build.FINGERPRINT.startsWith("generic") ) // when running on the emulator, insert a magic line that is
+          {                                           // supposed to cure the 'no config chosen' crash on emulator startup
+          setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+          }
+        
+        mRenderer = new ScratchpadRenderer(this);
+        setRenderer(mRenderer);
+        
+        point = new Float2D(0,0);
+        region= new Float4D(0,0,60,60);
+            
+        int h = 30;
+        int r = 20;
+        
+        v0 = new Float3D( 0, r, h );
+        v1 = new Float3D(-r, 0, h );
+        v2 = new Float3D( 0,-r, h );
+        v3 = new Float3D( r, 0, h );
+        
+        di.add(v0);
+        di.add(v1);
+        di.add(v2);
+        di.add(v3);
+        
+        setEffect(0);  
+        }
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void setScreenSize(int width, int height)
+      {
+      mScrW = width;
+      mScrH = height;
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static int getEffect()
+      {
+      return mCurrentEffect;
+      }
+   
+///////////////////////////////////////////////////////////////////
+
+   public static void setEffect(int effect)
+     {
+     mCurrentEffect = effect;
+     }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void setDuration(int duration)
+      {
+      mDuration = duration;
+      di.setDuration(duration);
+      }
+
+///////////////////////////////////////////////////////////////////
+
+    public static void setCount(float count)
+      {
+      mCount = count;
+      di.setCount(count);
+      }
+  
+///////////////////////////////////////////////////////////////////
+    
+    @Override public boolean onTouchEvent(MotionEvent event) 
+      {
+      int action = event.getAction();
+      int x, y;
+      
+      switch(action)
+      {
+      case MotionEvent.ACTION_DOWN: x = (int)event.getX()*ScratchpadRenderer.BWID/mScrW;
+                                    y = (int)event.getY()*ScratchpadRenderer.BHEI/mScrH;
+                                    point.set(x,y);
+                                              
+                                    switch(mCurrentEffect)
+                                      {
+                                      case 0: ScratchpadRenderer.mBackground.distort(di, region, point); 
+                                           break;
+                                      case 1: ScratchpadRenderer.mBackground.sink(0.3f, region, point, mDuration, mCount); 
+                                           break;
+                                      case 2: ScratchpadRenderer.mBackground.alpha(0.0f, region, point, mDuration, mCount); 
+                                           break;  
+                                      case 3: ScratchpadRenderer.mBackground.macroblock(10, region, point, mDuration, mCount); 
+                                           break;
+                                      case 4: ScratchpadRenderer.mBackground.brightness(0.0f, region, point, mDuration, mCount); 
+                                           break;      
+                                      }
+                                    break;
+      }
+            
+      return true;
+      }
+ 
+///////////////////////////////////////////////////////////////////
+// end of file
+
+  }
diff --git a/src/main/java/org/distortedandroid/examples/sink/SinkActivity.java b/src/main/java/org/distortedandroid/examples/sink/SinkActivity.java
new file mode 100644
index 0000000..b169640
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/sink/SinkActivity.java
@@ -0,0 +1,51 @@
+
+package org.distortedandroid.examples.sink;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class SinkActivity extends Activity 
+{
+    private SinkSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new SinkSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }    
+}
diff --git a/src/main/java/org/distortedandroid/examples/sink/SinkRenderer.java b/src/main/java/org/distortedandroid/examples/sink/SinkRenderer.java
new file mode 100644
index 0000000..4152757
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/sink/SinkRenderer.java
@@ -0,0 +1,111 @@
+
+package org.distortedandroid.examples.sink;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float4D;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SinkRenderer implements GLSurfaceView.Renderer 
+{
+   private GLSurfaceView mView;
+   private DistortedBitmap sinkBmp;
+   private Float2D pLeft, pRight;
+   private Float4D Region;
+   private int bmpHeight, bmpWidth;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public SinkRenderer(GLSurfaceView v) 
+      { 
+      mView = v;
+      
+      pLeft = new Float2D(214, 206);
+      pRight= new Float2D(390, 212);
+      Region= new Float4D(0,0,60,60);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+      
+      sinkBmp.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      sinkBmp.abortAllEffects(Distorted.TYPE_MATR);   
+         
+      if( bmpHeight/bmpWidth > height/width )
+        {
+        int w = (height*bmpWidth)/bmpHeight;
+        sinkBmp.move((width-w)/2 ,0, 0);
+        sinkBmp.scale((float)height/bmpHeight);
+        }
+      else
+        {
+        int h = (width*bmpHeight)/bmpWidth;
+        sinkBmp.move(0 ,(height-h)/2, 0);
+        sinkBmp.scale((float)width/bmpWidth);
+        }
+      
+      Distorted.onSurfaceChanged(width, height); 
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      InputStream is = mView.getContext().getResources().openRawResource(R.raw.dog);
+      Bitmap bitmap;
+        
+      try 
+        {
+        bitmap = BitmapFactory.decodeStream(is);
+        } 
+      finally 
+        {
+        try 
+          {
+          is.close();
+          } 
+        catch(IOException e) { }
+        }  
+      
+      bmpHeight = bitmap.getHeight();
+      bmpWidth  = bitmap.getWidth();
+      
+      sinkBmp = new DistortedBitmap(bitmap, 30);
+      sinkBmp.sink( 10.0f, Region, pLeft, 2000, 0.0f);
+      sinkBmp.sink(10.0f, Region, pRight,2000, 0.0f);
+      
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Sink", ex.getMessage() );
+        }
+      }
+}
diff --git a/src/main/java/org/distortedandroid/examples/sink/SinkSurfaceView.java b/src/main/java/org/distortedandroid/examples/sink/SinkSurfaceView.java
new file mode 100644
index 0000000..ff4de18
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/sink/SinkSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.sink;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class SinkSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public SinkSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new SinkRenderer(this));
+      }
+}
+
diff --git a/src/main/java/org/distortedandroid/examples/starwars/StarWarsActivity.java b/src/main/java/org/distortedandroid/examples/starwars/StarWarsActivity.java
new file mode 100644
index 0000000..1db2a7d
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/starwars/StarWarsActivity.java
@@ -0,0 +1,52 @@
+
+package org.distortedandroid.examples.starwars;
+
+import org.distortedandroid.library.Distorted;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+public class StarWarsActivity extends Activity 
+{
+    private StarWarsSurfaceView mView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onCreate(Bundle icicle) 
+      {
+      super.onCreate(icicle);
+      mView = new StarWarsSurfaceView(this);
+      setContentView(mView);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onPause() 
+      {
+      mView.onPause();  
+      super.onPause();
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onResume() 
+      {
+      super.onResume();
+      mView.onResume();
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    @Override
+    protected void onDestroy() 
+      {
+      Distorted.onDestroy();  
+      super.onDestroy();
+      }
+    
+}
diff --git a/src/main/java/org/distortedandroid/examples/starwars/StarWarsRenderer.java b/src/main/java/org/distortedandroid/examples/starwars/StarWarsRenderer.java
new file mode 100644
index 0000000..a88ad04
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/starwars/StarWarsRenderer.java
@@ -0,0 +1,388 @@
+
+package org.distortedandroid.examples.starwars;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Random;
+
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.opengles.GL10;
+
+import org.distortedandroid.examples.R;
+
+import org.distortedandroid.library.Interpolator1D;
+import org.distortedandroid.library.Interpolator3D;
+import org.distortedandroid.library.DistortedNode;
+import org.distortedandroid.library.Float1D;
+import org.distortedandroid.library.Float2D;
+import org.distortedandroid.library.Float3D;
+import org.distortedandroid.library.Float4D;
+import org.distortedandroid.library.EffectListener;
+import org.distortedandroid.library.EffectMessage;
+import org.distortedandroid.library.Distorted;
+import org.distortedandroid.library.DistortedBitmap;
+
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Typeface;
+import android.opengl.GLES20;
+import android.opengl.GLSurfaceView;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class StarWarsRenderer implements GLSurfaceView.Renderer, EffectListener
+{
+   private final String[] mGFFAString = 
+         
+            { "A long time ago, in a galaxy far,",
+              "far away...." };                    // yes, there really was a four-dot ellipsis
+
+   private final String[] mCRAWLString = 
+      
+            { "It is a period of civil war.",      // in the original 1977 version, there was no 
+              "Rebel spaceships, striking",        // 'Episode IV New Hope' subtitle line before
+              "from a hidden base, have",          // the crawl. Lets keep to the classic.
+              "won their first victory",
+              "against the evil Galactic",
+              "Empire.",
+              "",
+              "During the battle, rebel",
+              "spies managed to steal",
+              "secret plans to the Empire's",
+              "ultimate weapon, the",
+              "DEATH STAR, an armored",
+              "space station with enough",
+              "power to destroy an entire",
+              "planet.",
+              "",
+              "Pursued by the Empire's",
+              "sinister agents, Princess",
+              "Leia races home aboard her",
+              "starship, custodian of the",
+              "stolen plans that can save",
+              "her people and restore",
+              "freedom to the galaxy...." };      // four-dot.
+   
+   private final int NUM_STARS = 40;
+   
+   private final int CRAWL_COLOR = 0xffffe81f;
+   private final int GFFA_COLOR  = 0xff0000ff;
+   private final int FONT_HEIGHT      = 40;
+   private final int VERTICAL_SPACING = 10;
+   private final String CRAWL_TYPEFACE = "News Gothic";
+   
+   private final int CRAWL_WIDTH = 500;
+   private final int CRAWL_HEIGHT= (FONT_HEIGHT+VERTICAL_SPACING)*(mCRAWLString.length+1);
+   
+   private final int GFFA_WIDTH = 600;
+   private final int GFFA_HEIGHT= (FONT_HEIGHT+VERTICAL_SPACING)*(mGFFAString.length+1);
+   
+   private final float CRAWL_ANGLE = -30.0f;
+   
+   private GLSurfaceView mView;
+   private DistortedBitmap mScreen, mGFFA, mLogo, mCrawl, mCrawlBackground;
+   private DistortedBitmap[] mStars;
+   private long gffaID, logoID, crawlID;
+    
+   private Random mRnd = new Random(0);
+   private DistortedNode mRoot, mBackground;
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   public StarWarsRenderer(GLSurfaceView v) 
+     {
+     mView = v;
+     
+     Distorted.setFov(60.0f);
+     }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public void onDrawFrame(GL10 glUnused) 
+      {
+      GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+      GLES20.glClear( GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
+     
+      mRoot.draw(System.currentTimeMillis());
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceChanged(GL10 glUnused, int width, int height) 
+      { 
+      Distorted.onSurfaceChanged(width, height); 
+      setupScreen(width,height);
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+    
+    public void onSurfaceCreated(GL10 glUnused, EGLConfig config) 
+      {
+      setupBitmaps();
+         
+      try
+        {
+        Distorted.onSurfaceCreated(mView);
+        }
+      catch(Exception ex)
+        {
+        android.util.Log.e("Star Wars", ex.getMessage() );
+        }
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void setupScreen(int w, int h)
+      {
+      mScreen = new DistortedBitmap(w,h,1);
+      mRoot = new DistortedNode(mScreen);
+      
+      mCrawlBackground = new DistortedBitmap(w,(int)(Math.sqrt(3.0)*h),1);
+       
+      int randomA, randomX, randomY, randomTime;
+      float randomS, randomAlpha1, randomAlpha2;
+       
+      Float3D rot = new Float3D(0,0,0);
+      
+      for(int i=0; i<NUM_STARS; i++)
+        {
+        randomX = mRnd.nextInt(w);
+        randomY = mRnd.nextInt(h);
+        randomS = 0.2f+ 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);
+      
+        mStars[i].move( randomX,randomY,0);
+        mStars[i].scale(randomS);
+        mStars[i].rotate( rot, randomA);
+      
+        Interpolator1D di = new Interpolator1D();
+        di.setDuration(randomTime);
+        di.setCount(0.0f);
+        di.setNoise(0.3f);
+        di.add(new Float1D(randomAlpha1));
+        di.add(new Float1D(randomAlpha2));
+      
+        mStars[i].alpha(di, null, new Float2D(0,0));
+      
+        mRoot.attach(mStars[i]);
+        }
+      
+      float scale = (float) (0.5f*w/mGFFA.getWidth());
+      
+      Interpolator1D di = new Interpolator1D();
+      di.setDuration(6000);
+      di.setCount(0.5f);
+      di.add(new Float1D(1.0f));
+      di.add(new Float1D(1.0f));
+      di.add(new Float1D(0.0f));
+      
+      mGFFA.move( w/5, h/3, 0);
+      mGFFA.scale(scale);
+      mGFFA.alpha(di, null, new Float2D(0,0));
+      
+      mRoot.attach(mGFFA);
+      mGFFA.addEventListener(this); 
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    private void setupBitmaps()
+      {
+      InputStream is1 = mView.getContext().getResources().openRawResource(R.raw.starwars);
+      InputStream is2 = mView.getContext().getResources().openRawResource(R.raw.star);
+    
+      Bitmap bitmapStar, bitmapGFFA, bitmapLogo, bitmapText;
+        
+      try 
+        {
+        bitmapLogo = BitmapFactory.decodeStream(is1);
+        bitmapStar = BitmapFactory.decodeStream(is2);
+        } 
+      finally 
+        {
+        try 
+          {
+          is1.close();
+          is2.close();
+          } 
+        catch(IOException e) { }
+        } 
+      
+      Paint paint = new Paint();
+      paint.setAntiAlias(true);
+      paint.setTextAlign(Paint.Align.LEFT);
+      paint.setTextSize(FONT_HEIGHT);
+      paint.setColor(GFFA_COLOR);
+      
+      Typeface tf = Typeface.create(CRAWL_TYPEFACE, Typeface.BOLD);
+      paint.setTypeface(tf);     
+ 
+      ///// create GFFA ///////////////////
+      mGFFA  = new DistortedBitmap(GFFA_WIDTH, GFFA_HEIGHT, 1);
+      bitmapGFFA = Bitmap.createBitmap(GFFA_WIDTH,GFFA_HEIGHT,Bitmap.Config.ARGB_8888);
+      bitmapGFFA.eraseColor(0x00000000);
+      Canvas gffaCanvas = new Canvas(bitmapGFFA);
+      
+      for(int i=0; i<mGFFAString.length; i++)
+        {
+        gffaCanvas.drawText(mGFFAString[i], 0, (i+1)*(FONT_HEIGHT+VERTICAL_SPACING), paint);  
+        }
+  
+      mGFFA.setBitmap(bitmapGFFA);
+      
+      ///// create Logo ///////////////////
+      mLogo  = new DistortedBitmap(bitmapLogo, 1);
+      
+      ///// create CRAWL //////////////////
+      mCrawl = new DistortedBitmap(CRAWL_WIDTH, CRAWL_HEIGHT, 1);
+      bitmapText = Bitmap.createBitmap(CRAWL_WIDTH,CRAWL_HEIGHT,Bitmap.Config.ARGB_8888);
+      bitmapText.eraseColor(0x00000000);
+      Canvas textCanvas = new Canvas(bitmapText);
+      paint.setColor(CRAWL_COLOR);
+  
+      for(int i=0; i<mCRAWLString.length; i++)
+        {
+        displayJustified(mCRAWLString[i], 0, (i+1)*(FONT_HEIGHT+VERTICAL_SPACING), CRAWL_WIDTH, textCanvas, paint);  
+        }
+      
+      mCrawl.setBitmap(bitmapText);
+      
+      ///// create Stars ///////////////////
+      
+      mStars = new DistortedBitmap[NUM_STARS];
+      
+      mStars[0] = new DistortedBitmap(bitmapStar,1);
+      
+      for(int i=1; i<NUM_STARS; i++)
+        {
+        mStars[i] = new DistortedBitmap(mStars[0], Distorted.CLONE_BITMAP|Distorted.CLONE_VERTEX);  
+        }
+      
+      gffaID = mGFFA.getID();
+      logoID = mLogo.getID();
+      crawlID= mCrawl.getID();
+      }
+ 
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+   private void displayJustified(String str, int x, int y, int length, Canvas c, Paint paint)
+      { 
+      int len       = str.length();
+      int numspaces = retNumSpaces(str);
+    
+      if( len>0 && str.charAt(len-1) == ' ' ) numspaces--;
+
+      float left=x,w = (numspaces>0 ? (float)(length-paint.measureText(str))/numspaces : 0);
+      String tmp;
+      int begin,end=0;
+
+      while( end<len )
+        {
+        begin=end;
+        end = str.indexOf(' ', begin)+1;
+        if( end<=0 ) end = len;
+
+        tmp = str.substring(begin,end);
+        c.drawText( tmp, left, y, paint);
+        left+= (paint.measureText(tmp)+w);
+        }  
+      }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+   private int retNumSpaces(String str)
+      {
+      int begin=0, ret=0;
+
+      while( true )
+        {
+        begin = str.indexOf(' ', begin) +1;
+
+        if( begin>0 ) ret++;
+        else break;
+        }
+
+      return ret;
+      }
+    
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+    public void effectMessage(EffectMessage em, long effectID, int effectType, long bitmapID)
+      {
+      if( em==EffectMessage.EFFECT_FINISHED )
+        {
+        if( bitmapID == gffaID )
+          {
+          mRoot.detach(mGFFA);   
+          mGFFA.removeEventListener(this);
+       
+          int screenW=mScreen.getWidth();
+          int screenH=mScreen.getHeight();
+        
+          int logoW = mLogo.getWidth();
+          int logoH = mLogo.getHeight();
+      
+          int initSize= (int)(3.0f*screenW/logoW);
+          int finaSize= (int)(0.1f*screenW/logoW);
+      
+          Interpolator3D di = new Interpolator3D();
+      
+          di.add(new Float3D(initSize,initSize,1));
+          di.add(new Float3D(finaSize,finaSize,1));
+          di.setCount(0.5f);
+          di.setDuration(10000);
+      
+          mLogo.move( screenW/2, screenH/2, 0);
+          mLogo.scale(di);
+          mLogo.move( -logoW/2, -logoH/2, 0);
+      
+          mRoot.attach(mLogo);
+          mLogo.addEventListener(this);
+          }
+        else if( bitmapID==logoID )
+          {
+          mRoot.detach(mLogo);   
+          mLogo.removeEventListener(this);
+        
+          int crawlW = mCrawl.getWidth();
+          int crawlH = mCrawl.getHeight();
+          int screenW= mScreen.getWidth();
+          int screenH= mScreen.getHeight();
+          int backH  = mCrawlBackground.getHeight();
+          float scale= (float)screenW/crawlW;
+        
+          Interpolator3D di = new Interpolator3D();
+          di.setCount(0.5f);
+          di.setDuration(60000);
+          di.add(new Float3D(screenW/2,+backH       , 0));
+          di.add(new Float3D(screenW/2,-scale*crawlH, 0));
+        
+          mCrawlBackground.move(0,screenH-backH,0);
+          mCrawlBackground.rotate(new Float3D(screenW/2,backH,0), CRAWL_ANGLE, 1.0f, 0.0f, 0.0f);
+        
+          final int transpDistance = 5;
+          mCrawlBackground.smooth_alpha((1-transpDistance/2)*1.0f, new Float4D(0,0,transpDistance*backH,transpDistance*backH), new Float2D(screenW/2,(1-transpDistance)*backH));
+        
+          mCrawl.move(di);
+          mCrawl.scale(scale);
+          mCrawl.move(-crawlW/2,0,0);
+        
+          mBackground = mRoot.attach(mCrawlBackground);
+          mBackground.attach(mCrawl);
+          mCrawl.addEventListener(this);
+          }
+        else if( bitmapID==crawlID )
+          {
+          mRoot.detach(mBackground);
+          mBackground.detach(mCrawl);
+          mCrawl.removeEventListener(this);
+          }
+        }
+      }
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/main/java/org/distortedandroid/examples/starwars/StarWarsSurfaceView.java b/src/main/java/org/distortedandroid/examples/starwars/StarWarsSurfaceView.java
new file mode 100644
index 0000000..c62ebbc
--- /dev/null
+++ b/src/main/java/org/distortedandroid/examples/starwars/StarWarsSurfaceView.java
@@ -0,0 +1,27 @@
+
+package org.distortedandroid.examples.starwars;
+
+import android.content.Context;
+import android.opengl.GLSurfaceView;
+import android.os.Build;
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+class StarWarsSurfaceView extends GLSurfaceView 
+{
+///////////////////////////////////////////////////////////////////////////////////////////////////
+   
+    public StarWarsSurfaceView(Context context) 
+      {
+      super(context);
+      setEGLContextClientVersion(2);
+        
+      if( Build.FINGERPRINT.startsWith("generic") )
+        { 
+        setEGLConfigChooser(8, 8, 8, 8, 16, 0);   
+        }
+        
+      setRenderer(new StarWarsRenderer(this));
+      }
+}
+
diff --git a/src/main/res/drawable-hdpi/icon.png b/src/main/res/drawable-hdpi/icon.png
new file mode 100644
index 0000000..8a0c263
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_bean.png b/src/main/res/drawable-hdpi/icon_example_bean.png
new file mode 100644
index 0000000..4c478d1
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_bean.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_check.png b/src/main/res/drawable-hdpi/icon_example_check.png
new file mode 100644
index 0000000..3d73dbc
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_check.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_cubes.png b/src/main/res/drawable-hdpi/icon_example_cubes.png
new file mode 100644
index 0000000..4711789
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_cubes.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_deform.png b/src/main/res/drawable-hdpi/icon_example_deform.png
new file mode 100644
index 0000000..ba5d652
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_deform.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_differentbitmaps.png b/src/main/res/drawable-hdpi/icon_example_differentbitmaps.png
new file mode 100644
index 0000000..71ef47e
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_differentbitmaps.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_differenteffects.png b/src/main/res/drawable-hdpi/icon_example_differenteffects.png
new file mode 100644
index 0000000..b536046
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_differenteffects.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_fbo.png b/src/main/res/drawable-hdpi/icon_example_fbo.png
new file mode 100644
index 0000000..fbdeded
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_fbo.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_fov.png b/src/main/res/drawable-hdpi/icon_example_fov.png
new file mode 100644
index 0000000..ecd1a29
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_fov.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_girl.png b/src/main/res/drawable-hdpi/icon_example_girl.png
new file mode 100644
index 0000000..766fe70
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_girl.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_interpolator.png b/src/main/res/drawable-hdpi/icon_example_interpolator.png
new file mode 100644
index 0000000..e1fd4ad
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_interpolator.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_listener.png b/src/main/res/drawable-hdpi/icon_example_listener.png
new file mode 100644
index 0000000..efb8342
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_listener.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_macroblock.png b/src/main/res/drawable-hdpi/icon_example_macroblock.png
new file mode 100644
index 0000000..d03d981
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_macroblock.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_matrix3d.png b/src/main/res/drawable-hdpi/icon_example_matrix3d.png
new file mode 100644
index 0000000..fbd0524
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_matrix3d.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_monalisa.png b/src/main/res/drawable-hdpi/icon_example_monalisa.png
new file mode 100644
index 0000000..052a135
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_monalisa.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_movingeffects.png b/src/main/res/drawable-hdpi/icon_example_movingeffects.png
new file mode 100644
index 0000000..e665850
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_movingeffects.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_olimpic.png b/src/main/res/drawable-hdpi/icon_example_olimpic.png
new file mode 100644
index 0000000..d967eca
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_olimpic.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_quaternion.png b/src/main/res/drawable-hdpi/icon_example_quaternion.png
new file mode 100644
index 0000000..fbd0524
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_quaternion.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_scratchpad.png b/src/main/res/drawable-hdpi/icon_example_scratchpad.png
new file mode 100644
index 0000000..c3edd62
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_scratchpad.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_sink.png b/src/main/res/drawable-hdpi/icon_example_sink.png
new file mode 100644
index 0000000..780736e
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_sink.png differ
diff --git a/src/main/res/drawable-hdpi/icon_example_starwars.png b/src/main/res/drawable-hdpi/icon_example_starwars.png
new file mode 100644
index 0000000..b082f4b
Binary files /dev/null and b/src/main/res/drawable-hdpi/icon_example_starwars.png differ
diff --git a/src/main/res/drawable/icon_border.xml b/src/main/res/drawable/icon_border.xml
new file mode 100644
index 0000000..ff2888f
--- /dev/null
+++ b/src/main/res/drawable/icon_border.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape 
+	xmlns:android="http://schemas.android.com/apk/res/android">	
+	<stroke 
+		android:width="1dp" 
+		android:color="#FFFFFF" />
+	<padding 
+		android:left="1dp" 
+		android:top="1dp" 
+		android:right="1dp"
+    	android:bottom="1dp" />
+</shape>
\ No newline at end of file
diff --git a/src/main/res/layout/check1layout.xml b/src/main/res/layout/check1layout.xml
new file mode 100644
index 0000000..6a2bc6e
--- /dev/null
+++ b/src/main/res/layout/check1layout.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:gravity="center_horizontal"
+    android:orientation="vertical" >
+
+    <TextView
+        android:id="@+id/check1TextView"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="10dp"
+        android:paddingLeft="10dp"
+        android:paddingRight="10dp"
+        android:paddingTop="10dp"
+        android:text="@string/introduction"
+        android:textSize="24sp" />
+
+    <TableLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="15dp"
+        android:paddingTop="15dp" >
+
+        <TableRow
+            android:id="@+id/tableRow1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical|center"
+            android:paddingBottom="5dp"
+            android:paddingTop="5dp" >
+
+            <TextView
+                android:id="@+id/check1TextViewVertex"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingBottom="5dp"
+                android:paddingLeft="5dp"
+                android:paddingRight="5dp"
+                android:paddingTop="5dp"
+                android:text="@string/maxv"
+                android:textSize="32sp" />
+
+            <NumberPicker
+                android:id="@+id/check1NumberPickerVertex"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:orientation="vertical" />
+        </TableRow>
+
+        <TableRow
+            android:id="@+id/tableRow2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical|center"
+            android:paddingBottom="5dp"
+            android:paddingTop="5dp" >
+
+            <TextView
+                android:id="@+id/check1TextViewFragment"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingBottom="5dp"
+                android:paddingLeft="5dp"
+                android:paddingRight="5dp"
+                android:paddingTop="5dp"
+                android:text="@string/maxf"
+                android:textSize="32sp" />
+
+            <NumberPicker
+                android:id="@+id/check1NumberPickerFragment"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:orientation="vertical" />
+        </TableRow>
+    </TableLayout>
+
+    <Button
+        android:id="@+id/check1Button"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0.10"
+        android:onClick="Check"
+        android:text="@string/check"
+        android:textSize="32sp" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/src/main/res/layout/check2layout.xml b/src/main/res/layout/check2layout.xml
new file mode 100644
index 0000000..47df922
--- /dev/null
+++ b/src/main/res/layout/check2layout.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:gravity="center_horizontal"
+    android:onClick="Check"
+    android:orientation="vertical" >
+
+    <org.distortedandroid.examples.check.CheckSurfaceView
+        android:id="@+id/checkSurfaceView"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1.00" />
+
+</LinearLayout>
diff --git a/src/main/res/layout/cubes1layout.xml b/src/main/res/layout/cubes1layout.xml
new file mode 100644
index 0000000..edc0880
--- /dev/null
+++ b/src/main/res/layout/cubes1layout.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:gravity="fill_vertical"
+    android:orientation="vertical" >
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center_vertical|center_horizontal" >
+
+        <NumberPicker
+            android:id="@+id/rowsPicker"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_marginRight="10dp" />
+
+        <NumberPicker
+            android:id="@+id/colsPicker"
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:paddingRight="10dp" />
+
+        <Button
+            android:id="@+id/matrix3dRowMove"
+            android:layout_width="124dp"
+            android:layout_height="match_parent"
+            android:layout_weight="0.64"
+            android:onClick="Continue"
+            android:text="@string/continu" />
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/buttongrid"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:gravity="center"
+        android:orientation="vertical" >
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/src/main/res/layout/cubes2layout.xml b/src/main/res/layout/cubes2layout.xml
new file mode 100644
index 0000000..28ce022
--- /dev/null
+++ b/src/main/res/layout/cubes2layout.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:gravity="center_horizontal"
+    android:orientation="vertical" >
+
+    <org.distortedandroid.examples.cubes.CubesSurfaceView
+        android:id="@+id/cubesSurfaceView"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1.00" />
+
+</LinearLayout>
diff --git a/src/main/res/layout/deformlayout.xml b/src/main/res/layout/deformlayout.xml
new file mode 100644
index 0000000..5eba00c
--- /dev/null
+++ b/src/main/res/layout/deformlayout.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <org.distortedandroid.examples.deform.DeformSurfaceView
+        android:id="@+id/deformSurfaceView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <LinearLayout
+        android:id="@+id/linearLayout1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center|fill_horizontal"
+        android:orientation="vertical" >
+
+        <RadioGroup
+            android:id="@+id/radioGroup1"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal" >
+			
+            <RadioButton
+                android:id="@+id/deformDistortButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:checked="true"
+                android:onClick="Distort"
+                android:text="@string/distort" />
+
+            <RadioButton
+                android:id="@+id/deformDeformButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="Deform"
+                android:text="@string/deform" />
+
+            <RadioButton
+                android:id="@+id/deformShearButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="Shear"
+                android:text="@string/shear" />
+        </RadioGroup>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center_vertical|right"
+            android:orientation="vertical" >
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_vertical"
+                android:orientation="horizontal" >
+
+                <TextView
+                    android:id="@+id/deformTextRadius"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:paddingLeft="15dp"
+                    android:text="Radius"
+                    android:textAppearance="?android:attr/textAppearanceMedium" />
+
+                <SeekBar
+                    android:id="@+id/deformSeekRadius"
+                    android:layout_width="106dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0.65"
+                    android:paddingLeft="20dp"
+                    android:paddingRight="10dp" />
+
+            </LinearLayout>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/src/main/res/layout/effects3dlayout.xml b/src/main/res/layout/effects3dlayout.xml
new file mode 100644
index 0000000..1e5fcc1
--- /dev/null
+++ b/src/main/res/layout/effects3dlayout.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <org.distortedandroid.examples.effects3d.Effects3DSurfaceView
+        android:id="@+id/effects3dSurfaceView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <Button
+        android:id="@+id/button1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:onClick="Default"
+        android:text="@string/Default" />
+
+    <ScrollView
+        android:id="@+id/matrix3dscrollView"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        android:layout_weight="0.82" >
+
+        <LinearLayout
+            android:id="@+id/matrix3dlayout"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:orientation="vertical" >
+        </LinearLayout>
+
+    </ScrollView>
+
+</LinearLayout>
diff --git a/src/main/res/layout/effects3dmove.xml b/src/main/res/layout/effects3dmove.xml
new file mode 100644
index 0000000..6758825
--- /dev/null
+++ b/src/main/res/layout/effects3dmove.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:id="@id/matrix3dRowMove"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal" >
+
+                <LinearLayout
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="0.8"
+                    android:orientation="vertical" >
+
+                    <TextView
+                        android:id="@+id/matrix3dmoveText"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginStart="5dp"
+                        android:layout_marginTop="3dp"
+                        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3dmoveBar1"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3dmoveBar2"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3dmoveBar3"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                </LinearLayout>
+
+                <Button
+                    android:id="@+id/matrix3dUpMove"
+                    android:layout_width="60dp"
+                    android:layout_height="fill_parent"
+                    android:onClick="ButtonMove"
+                    android:text="@string/Up" />
+
+            </LinearLayout>
diff --git a/src/main/res/layout/effects3drotate.xml b/src/main/res/layout/effects3drotate.xml
new file mode 100644
index 0000000..df898da
--- /dev/null
+++ b/src/main/res/layout/effects3drotate.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="utf-8"?>
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:id="@+id/matrix3dRowRotate"
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+
+                <LinearLayout
+                    android:layout_width="0dp"
+                    android:layout_height="match_parent"
+                    android:layout_weight="0.70"
+                    android:orientation="vertical" >
+
+                    <TextView
+                        android:id="@+id/matrix3drotateText"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginStart="5dp"
+                        android:layout_marginTop="3dp"
+                        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3drotateBar4"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3drotateBar1"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3drotateBar2"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3drotateBar3"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                </LinearLayout>
+
+                <Button
+                    android:id="@+id/matrix3dUpRotate"
+                    android:layout_width="60dp"
+                    android:layout_height="fill_parent"
+                    android:onClick="ButtonRotate"
+                    android:text="@string/Up" />
+
+            </LinearLayout>
\ No newline at end of file
diff --git a/src/main/res/layout/effects3dscale.xml b/src/main/res/layout/effects3dscale.xml
new file mode 100644
index 0000000..3c91178
--- /dev/null
+++ b/src/main/res/layout/effects3dscale.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:id="@+id/matrix3dRowScale"
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+
+                <LinearLayout
+                    android:layout_width="0dp"
+                    android:layout_height="match_parent"
+                    android:layout_weight="0.70"
+                    android:orientation="vertical" >
+
+                    <TextView
+                        android:id="@+id/matrix3dscaleText"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginStart="5dp"
+                        android:layout_marginTop="3dp"
+                        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3dscaleBar1"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3dscaleBar2"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3dscaleBar3"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                </LinearLayout>
+
+                <Button
+                    android:id="@+id/matrix3dUpScale"
+                    android:layout_width="60dp"
+                    android:layout_height="fill_parent"
+                    android:onClick="ButtonScale"
+                    android:text="@string/Up" />
+
+            </LinearLayout>
+           
\ No newline at end of file
diff --git a/src/main/res/layout/effects3dshear.xml b/src/main/res/layout/effects3dshear.xml
new file mode 100644
index 0000000..236b462
--- /dev/null
+++ b/src/main/res/layout/effects3dshear.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="utf-8"?>
+            <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+                android:id="@+id/matrix3dRowShear"
+                android:orientation="horizontal"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content" >
+
+                <LinearLayout
+                    android:layout_width="0dp"
+                    android:layout_height="match_parent"
+                    android:layout_weight="0.70"
+                    android:orientation="vertical" >
+
+                    <TextView
+                        android:id="@+id/matrix3dshearText"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginStart="5dp"
+                        android:layout_marginTop="3dp"
+                        android:textAppearance="?android:attr/textAppearanceLarge" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3dshearBar1"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3dshearBar2"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                    <SeekBar
+                        android:id="@+id/matrix3dshearBar3"
+                        android:layout_width="fill_parent"
+                        android:layout_height="wrap_content"
+                        android:layout_gravity="end"
+                        android:layout_marginEnd="5dp"
+                        android:layout_marginLeft="5dp"
+                        android:layout_marginRight="5dp" />
+
+                </LinearLayout>
+
+                <Button
+                    android:id="@+id/matrix3dUpShear"
+                    android:layout_width="60dp"
+                    android:layout_height="fill_parent"
+                    android:onClick="ButtonShear"
+                    android:text="@string/Up" />
+
+            </LinearLayout>
\ No newline at end of file
diff --git a/src/main/res/layout/fovlayout.xml b/src/main/res/layout/fovlayout.xml
new file mode 100644
index 0000000..5a147ba
--- /dev/null
+++ b/src/main/res/layout/fovlayout.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <org.distortedandroid.examples.fov.FOVSurfaceView
+        android:id="@+id/surfaceViewFOV"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <LinearLayout
+        android:id="@+id/linearLayout1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center|fill_horizontal"
+        android:orientation="horizontal"
+        android:paddingBottom="10dp"
+        android:paddingTop="10dp" >
+
+        <TextView
+            android:id="@+id/textFOV"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:paddingLeft="15dp"
+            android:textAppearance="?android:attr/textAppearanceMedium" />
+
+        <SeekBar
+            android:id="@+id/seekFOV"
+            android:layout_width="106dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="0.94"
+            android:paddingLeft="15dp"
+            android:paddingRight="10dp" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/src/main/res/layout/girllayout.xml b/src/main/res/layout/girllayout.xml
new file mode 100644
index 0000000..a923f70
--- /dev/null
+++ b/src/main/res/layout/girllayout.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <org.distortedandroid.examples.girl.GirlSurfaceView
+        android:id="@+id/girlSurfaceView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="0.85" />
+
+    <TableLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingLeft="10dp"
+        android:paddingRight="10dp" >
+
+        <TableRow
+            android:id="@+id/tableRow1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingBottom="5dp"
+            android:paddingTop="5dp" >
+
+            <TextView
+                android:id="@+id/girlTextSwing"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:gravity="center_vertical|center"
+                android:text="@string/swing"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+
+            <SeekBar
+                android:id="@+id/girlSeekSwing"
+                android:layout_width="105dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:paddingLeft="15dp"
+                android:paddingRight="10dp" />
+
+        </TableRow>
+
+        <TableRow
+            android:id="@+id/tableRow2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingBottom="5dp"
+            android:paddingTop="5dp" >
+
+            <TextView
+                android:id="@+id/girlTextSize"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:gravity="center_vertical|center"
+                android:text="@string/size"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+
+            <SeekBar
+                android:id="@+id/girlSeekSize"
+                android:layout_width="106dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:paddingLeft="15dp"
+                android:paddingRight="10dp" />
+
+        </TableRow>
+
+        <TableRow
+            android:id="@+id/tableRow3"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingBottom="5dp"
+            android:paddingTop="5dp" >
+
+            <TextView
+                android:id="@+id/girlTextHips"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:gravity="center_vertical|center"
+                android:text="@string/hips"
+                android:textAppearance="?android:attr/textAppearanceMedium" />
+
+            <SeekBar
+                android:id="@+id/girlSeekHips"
+                android:layout_width="105dp"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                android:paddingLeft="15dp"
+                android:paddingRight="10dp" />
+
+        </TableRow>
+    </TableLayout>
+
+</LinearLayout>
diff --git a/src/main/res/layout/interpolatorlayout.xml b/src/main/res/layout/interpolatorlayout.xml
new file mode 100644
index 0000000..e6487fc
--- /dev/null
+++ b/src/main/res/layout/interpolatorlayout.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:layout_gravity="fill_horizontal"
+    android:gravity="fill_horizontal"
+    android:orientation="vertical" >
+
+    <org.distortedandroid.examples.interpolator.InterpolatorSurfaceView
+        android:id="@+id/interpolatorSurfaceView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+        <RadioGroup
+            android:id="@+id/radioGroup2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="fill_horizontal"
+            android:orientation="horizontal"
+            android:paddingBottom="5dp"
+            android:paddingTop="5dp"
+            android:weightSum="1.0" >
+
+            <RadioButton
+                android:id="@+id/interpolator1D"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="0.25"
+                android:onClick="Dim1D"
+                android:text="@string/dim1D" />
+
+            <RadioButton
+                android:id="@+id/interpolator2D"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="0.25"
+                android:checked="true"
+                android:onClick="Dim2D"
+                android:text="@string/dim2D" />
+
+            <RadioButton
+                android:id="@+id/interpolator3DXY"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="0.25"
+                android:onClick="Dim3DXY"
+                android:text="@string/dim3DXY" />
+
+            <RadioButton
+                android:id="@+id/interpolator3DXZ"
+                android:layout_width="fill_parent"
+                android:layout_height="wrap_content"
+                android:layout_weight="0.25"
+                android:onClick="Dim3DXZ"
+                android:text="@string/dim3DXZ" />
+
+        </RadioGroup>
+
+        <RadioGroup
+            android:id="@+id/radioGroup1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:orientation="horizontal"
+            android:paddingRight="20dp" >
+
+            <RadioButton
+                android:id="@+id/interpolatorLoopButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:checked="true"
+                android:onClick="Loop"
+                android:text="@string/loop" />
+
+            <RadioButton
+                android:id="@+id/interpolatorPathButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:checked="false"
+                android:onClick="Path"
+                android:text="@string/path" />
+
+            <RadioButton
+                android:id="@+id/interpolatorJumpButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:checked="false"
+                android:onClick="Jump"
+                android:text="@string/jump" />
+
+        </RadioGroup>
+
+    <LinearLayout
+        android:id="@+id/linearLayout1"
+        android:layout_width="fill_parent"
+        android:layout_height="80dp"
+        android:layout_gravity="center_vertical"
+        android:gravity="center|fill_horizontal" >
+
+        <TableLayout
+            android:layout_width="wrap_content"
+            android:layout_height="match_parent"
+            android:layout_gravity="center_vertical"
+            android:layout_weight="15"
+            android:gravity="center_vertical" >
+
+            <TableRow
+                android:id="@+id/tableRow1"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center_vertical"
+                android:paddingBottom="5dp"
+                android:paddingTop="5dp" >
+
+                <TextView
+                    android:id="@+id/interpolatorTextDuration"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:layout_weight="5"
+                    android:paddingLeft="10dp"
+                    android:text="@string/duration"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:textSize="12sp" />
+
+                <SeekBar
+                    android:id="@+id/interpolatorSeekDuration"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="12"
+                    android:paddingLeft="5dp"
+                    android:paddingRight="10dp" />
+            </TableRow>
+
+            <TableRow
+                android:id="@+id/tableRow2"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:paddingBottom="5dp"
+                android:paddingTop="5dp" >
+
+                <TextView
+                    android:id="@+id/interpolatorTextNoise"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="center_vertical"
+                    android:layout_weight="5"
+                    android:paddingLeft="10dp"
+                    android:text="@string/noise"
+                    android:textAppearance="?android:attr/textAppearanceMedium"
+                    android:textSize="12sp" />
+
+                <SeekBar
+                    android:id="@+id/interpolatorSeekNoise"
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="12"
+                    android:paddingLeft="5dp"
+                    android:paddingRight="10dp" />
+            </TableRow>
+        </TableLayout>
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/src/main/res/layout/movingeffectslayout.xml b/src/main/res/layout/movingeffectslayout.xml
new file mode 100644
index 0000000..c817ade
--- /dev/null
+++ b/src/main/res/layout/movingeffectslayout.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+
+    <org.distortedandroid.examples.movingeffects.MovingEffectsSurfaceView
+        android:id="@+id/movingeffectsSurfaceView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <LinearLayout
+        android:id="@+id/linearLayout1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:gravity="center|fill_horizontal"
+        android:paddingBottom="10dp"
+        android:paddingTop="10dp" >
+
+        <Button
+            android:id="@+id/movingeffectsSwirl"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="2dp"
+            android:layout_marginRight="2dp"
+            android:layout_weight="0.17"
+            android:onClick="Swirl"
+            android:paddingLeft="5dp"
+            android:paddingRight="5dp"
+            android:text="@string/swirl" />
+
+        <Button
+            android:id="@+id/movingeffectsBubble"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="2dp"
+            android:layout_marginRight="2dp"
+            android:layout_weight="0.17"
+            android:onClick="Bubble"
+            android:paddingLeft="5dp"
+            android:paddingRight="5dp"
+            android:text="@string/bubble" />
+
+        <Button
+            android:id="@+id/movingeffectsSink"
+            android:layout_width="54dp"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="2dp"
+            android:layout_marginRight="2dp"
+            android:layout_weight="0.17"
+            android:onClick="Sink"
+            android:paddingLeft="5dp"
+            android:paddingRight="5dp"
+            android:text="@string/sink" />
+
+        <Button
+            android:id="@+id/movingeffectsTrans"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="2dp"
+            android:layout_marginRight="2dp"
+            android:layout_weight="0.17"
+            android:onClick="Transparency"
+            android:paddingLeft="5dp"
+            android:paddingRight="5dp"
+            android:text="@string/transparency" />
+
+        <Button
+            android:id="@+id/movingeffectsMacro"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="2dp"
+            android:layout_marginRight="2dp"
+            android:layout_weight="0.17"
+            android:onClick="Macroblock"
+            android:paddingLeft="5dp"
+            android:paddingRight="5dp"
+            android:text="@string/macroblock" />
+
+        <Button
+            android:id="@+id/movingeffectsAbort"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginLeft="2dp"
+            android:layout_marginRight="2dp"
+            android:layout_weight="0.17"
+            android:onClick="Abort"
+            android:paddingLeft="5dp"
+            android:paddingRight="5dp"
+            android:text="@string/reset" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/src/main/res/layout/scratchpadlayout.xml b/src/main/res/layout/scratchpadlayout.xml
new file mode 100644
index 0000000..cc4c513
--- /dev/null
+++ b/src/main/res/layout/scratchpadlayout.xml
@@ -0,0 +1,167 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:onClick="Brightness"
+    android:orientation="vertical" >
+
+    <org.distortedandroid.examples.scratchpad.ScratchpadSurfaceView
+        android:id="@+id/scratchpadSurfaceView"
+        android:layout_width="fill_parent"
+        android:layout_height="0dp"
+        android:layout_weight="1" />
+
+    <LinearLayout
+        android:id="@+id/linearLayout1"
+        android:layout_width="fill_parent"
+        android:layout_height="wrap_content"
+        android:layout_weight="0.07"
+        android:gravity="center|fill_horizontal" >
+
+        <RadioGroup
+            android:id="@+id/radioGroup1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:paddingLeft="5dp"
+            android:paddingRight="10dp" >
+			
+            <RadioButton
+                android:id="@+id/scratchpadDistort"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:checked="true"
+                android:onClick="Distort"
+                android:text="@string/distort" />
+
+            <RadioButton
+                android:id="@+id/scratchpadSink"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="Sink"
+                android:text="@string/sink" />
+
+            <RadioButton
+                android:id="@+id/scratchpadTransparency"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="Transparency"
+                android:text="@string/transparency" />
+
+            <RadioButton
+                android:id="@+id/scratchpadMacroblock"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="Macroblock"
+                android:text="@string/macroblock" />
+
+            <RadioButton
+                android:id="@+id/scratchpadBrightness"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:onClick="Brightness"
+                android:text="@string/brightness" />
+
+        </RadioGroup>
+
+        <LinearLayout
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:gravity="center_vertical|right"
+            android:orientation="vertical"
+            android:paddingLeft="10dp"
+            android:paddingRight="5dp" >
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="45dp"
+                android:gravity="center_vertical"
+                android:orientation="horizontal" >
+
+                <TextView
+                    android:id="@+id/scratchpadTextCount"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:text="@string/count"
+                    android:textAppearance="?android:attr/textAppearanceMedium" />
+
+                <SeekBar
+                    android:id="@+id/scratchpadSeekCount"
+                    android:layout_width="105dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:paddingLeft="0dp"
+                    android:paddingRight="3dp" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:gravity="center_vertical"
+                android:orientation="horizontal" >
+
+                <TextView
+                    android:id="@+id/scratchpadTextDuration"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:text="@string/duration"
+                    android:textAppearance="?android:attr/textAppearanceMedium" />
+
+                <SeekBar
+                    android:id="@+id/scratchpadSeekDuration"
+                    android:layout_width="106dp"
+                    android:layout_height="wrap_content"
+                    android:paddingLeft="0dp"
+                    android:paddingRight="3dp" />
+
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:orientation="horizontal" >
+
+                <Button
+                    android:id="@+id/scratchpadButtonPrint"
+                    android:layout_width="24dp"
+                    android:layout_height="match_parent"
+                    android:layout_weight="0.77"
+                    android:onClick="Print"
+                    android:text="@string/print" />
+
+                <Button
+                    android:id="@+id/scratchpadButtonAbort"
+                    android:layout_width="wrap_content"
+                    android:layout_height="match_parent"
+                    android:layout_weight="0.39"
+                    android:onClick="Abort"
+                    android:text="@string/abort" />
+            </LinearLayout>
+
+            <LinearLayout
+                android:layout_width="match_parent"
+                android:layout_height="45dp"
+                android:gravity="center_vertical"
+                android:orientation="horizontal" >
+
+                <TextView
+                    android:id="@+id/scratchpadTextID"
+                    android:layout_width="0dp"
+                    android:layout_height="wrap_content"
+                    android:layout_weight="1"
+                    android:text="@string/id"
+                    android:textAppearance="?android:attr/textAppearanceMedium" />
+
+                <SeekBar
+                    android:id="@+id/scratchpadSeekID"
+                    android:layout_width="110dp"
+                    android:layout_height="wrap_content" />
+
+            </LinearLayout>
+
+        </LinearLayout>
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/src/main/res/layout/table_of_contents.xml b/src/main/res/layout/table_of_contents.xml
new file mode 100644
index 0000000..8cfb19d
--- /dev/null
+++ b/src/main/res/layout/table_of_contents.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+ <LinearLayout 
+ 	xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+        
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:autoLink="web"
+        android:paddingBottom="5dp"
+        android:paddingLeft="5dp"
+        android:paddingRight="5dp"
+        android:paddingTop="5dp"
+        android:text="@string/tocHeader" />
+
+     <ListView 
+     	android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+ </LinearLayout>
diff --git a/src/main/res/layout/toc_item.xml b/src/main/res/layout/toc_item.xml
new file mode 100644
index 0000000..948186e
--- /dev/null
+++ b/src/main/res/layout/toc_item.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+	xmlns:android="http://schemas.android.com/apk/res/android"
+	android:layout_width="match_parent"	
+	android:layout_height="wrap_content"
+	android:orientation="horizontal"
+	android:paddingTop="4dp"
+	android:paddingBottom="4dp">    
+   	<ImageView
+   		android:id="@+id/Image"
+   		android:layout_width="wrap_content"
+   		android:layout_height="wrap_content"
+   		android:layout_margin="8dp"
+   		android:background="@drawable/icon_border"/>
+   	<LinearLayout
+   		android:layout_width="0dp"
+ 		android:layout_height="wrap_content"
+ 		android:layout_weight="1"
+ 		android:orientation="vertical"
+ 		android:layout_gravity="center_vertical">
+		<TextView 
+    		android:id="@+id/Title" 
+    		android:layout_width="match_parent" 
+    		android:layout_height="wrap_content"
+    		android:textStyle="bold"/>
+   		<TextView 
+    		android:id="@+id/SubTitle" 
+    		android:layout_width="wrap_content" 
+    		android:layout_height="wrap_content"/>	       
+ 	</LinearLayout>    
+</LinearLayout>
diff --git a/src/main/res/raw/bean.png b/src/main/res/raw/bean.png
new file mode 100644
index 0000000..8790a8d
Binary files /dev/null and b/src/main/res/raw/bean.png differ
diff --git a/src/main/res/raw/cat.jpg b/src/main/res/raw/cat.jpg
new file mode 100644
index 0000000..05c69a3
Binary files /dev/null and b/src/main/res/raw/cat.jpg differ
diff --git a/src/main/res/raw/cat_and_dog.jpg b/src/main/res/raw/cat_and_dog.jpg
new file mode 100644
index 0000000..c6ae73b
Binary files /dev/null and b/src/main/res/raw/cat_and_dog.jpg differ
diff --git a/src/main/res/raw/dog.jpg b/src/main/res/raw/dog.jpg
new file mode 100644
index 0000000..affcf83
Binary files /dev/null and b/src/main/res/raw/dog.jpg differ
diff --git a/src/main/res/raw/face.jpg b/src/main/res/raw/face.jpg
new file mode 100644
index 0000000..756ebaf
Binary files /dev/null and b/src/main/res/raw/face.jpg differ
diff --git a/src/main/res/raw/fbo.png b/src/main/res/raw/fbo.png
new file mode 100644
index 0000000..2b54f94
Binary files /dev/null and b/src/main/res/raw/fbo.png differ
diff --git a/src/main/res/raw/girl.jpg b/src/main/res/raw/girl.jpg
new file mode 100644
index 0000000..4f91ae5
Binary files /dev/null and b/src/main/res/raw/girl.jpg differ
diff --git a/src/main/res/raw/grid.png b/src/main/res/raw/grid.png
new file mode 100644
index 0000000..c7c171e
Binary files /dev/null and b/src/main/res/raw/grid.png differ
diff --git a/src/main/res/raw/leaf.png b/src/main/res/raw/leaf.png
new file mode 100644
index 0000000..bad0c8f
Binary files /dev/null and b/src/main/res/raw/leaf.png differ
diff --git a/src/main/res/raw/monalisa.jpg b/src/main/res/raw/monalisa.jpg
new file mode 100644
index 0000000..4a10ae4
Binary files /dev/null and b/src/main/res/raw/monalisa.jpg differ
diff --git a/src/main/res/raw/star.jpg b/src/main/res/raw/star.jpg
new file mode 100644
index 0000000..2dbc6eb
Binary files /dev/null and b/src/main/res/raw/star.jpg differ
diff --git a/src/main/res/raw/starwars.png b/src/main/res/raw/starwars.png
new file mode 100644
index 0000000..f81cb03
Binary files /dev/null and b/src/main/res/raw/starwars.png differ
diff --git a/src/main/res/raw/success.png b/src/main/res/raw/success.png
new file mode 100644
index 0000000..69f4a39
Binary files /dev/null and b/src/main/res/raw/success.png differ
diff --git a/src/main/res/raw/water.jpg b/src/main/res/raw/water.jpg
new file mode 100644
index 0000000..ed3ac4c
Binary files /dev/null and b/src/main/res/raw/water.jpg differ
diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml
new file mode 100644
index 0000000..1a28d0a
--- /dev/null
+++ b/src/main/res/values/strings.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>    
+    <string name="app_name">Distorted Android Examples</string>
+    <string name="toc">Table of Contents</string>
+    <string name="tocHeader">Welcome to the Distorted Android Examples!\nPlease take a look at: https://DistortedAndroid.org/</string>
+    
+    <string name="continu">Continue</string>
+    <string name="rows">Rows</string>
+    <string name="cols">Cols</string>
+    <string name="distort">Distort</string>
+    <string name="deform">Deform</string>
+    <string name="shear">Shear</string>
+    <string name="path">Path</string>
+    <string name="loop">Loop</string>
+    <string name="jump">Jump</string>
+    <string name="duration">Duration</string>
+    <string name="reset">Reset</string>
+    <string name="bubble">Bubble</string>
+    <string name="sink">Sink</string>
+    <string name="transparency">Trans</string>
+    <string name="macroblock">Macro</string>
+    <string name="brightness">Bright</string>
+    <string name="swirl">Swirl</string>
+    <string name="print">Print</string>
+    <string name="abort">Abort</string>
+    <string name="count">Count</string>
+    <string name="id">ID</string>
+    <string name="maxv">vertex:</string>
+    <string name="maxf">fragment:</string>
+    <string name="introduction">Set maximum number of vertex and fragment effects and press \'Check\' to see if shaders compile:</string>
+    <string name="check">Check</string>
+    <string name="noise">Noise</string>
+    <string name="swing">Swing</string>
+    <string name="size">Size</string>
+    <string name="hips">Hips</string>
+    <string name="dim1D">1D</string>
+    <string name="dim2D">2D</string>
+    <string name="dim3DXY">3DXY</string>
+    <string name="dim3DXZ">3DXZ</string>
+    <string name="Up">Up</string>
+    <string name="Default">Default</string>
+     
+    <string name="example_monalisa">Mona Lisa</string>  
+    <string name="example_monalisa_subtitle">The basics of Distortions.</string>
+    <string name="example_sink">Dog</string>  
+    <string name="example_sink_subtitle">Learn about sinks.</string>
+    <string name="example_bean">Mr. Bean</string>  
+    <string name="example_bean_subtitle">Interpolation between more than two Points.</string>
+    <string name="example_fov">Field Of View</string>  
+    <string name="example_fov_subtitle">Adjust the Projection Matrix.</string>
+    <string name="example_deform">Deformations and Distortions</string>  
+    <string name="example_deform_subtitle">Deform the whole bitmap or Distort a part of it.</string>
+    <string name="example_listener">DistortedListener</string>  
+    <string name="example_listener_subtitle">Listen on effect events and react on them.</string>
+    <string name="example_interpolator">Interpolator</string>  
+    <string name="example_interpolator_subtitle">Not an effect in itself, but rather a building block for other effects.</string>
+    <string name="example_girl">Girl</string>  
+    <string name="example_girl_subtitle">Distort, Sink and Swirl effects all in one.</string>
+    <string name="example_macroblock">Cat and Dog</string>  
+    <string name="example_macroblock_subtitle">Macroblock, Transparency and Rotation effects.</string>
+    <string name="example_movingeffects">Moving Effects</string>  
+    <string name="example_movingeffects_subtitle">Use the Interpolator to move effects around.</string>
+    <string name="example_differenteffects">Different Effects</string>  
+    <string name="example_differenteffects_subtitle">See how to draw the same bitmap multiple times, each time with different set of effects applied.</string>
+    <string name="example_differentbitmaps">Different Bitmaps</string>  
+    <string name="example_differentbitmaps_subtitle">Draw 3 different bitmaps, apply the same set of effects to each one in one go.</string>
+    <string name="example_scratchpad">Scratchpad</string>  
+    <string name="example_scratchpad_subtitle">Application used as a scratchpad during development of the library. </string>
+    <string name="example_check">Check</string>  
+    <string name="example_check_subtitle">Check the maximum number of effects (separately for vertex and fragment shaders) we can apply to a single bitmap.</string>
+    <string name="example_fbo">Bitmap Tree</string>  
+    <string name="example_fbo_subtitle">Render one bitmap on top of another.</string>
+    <string name="example_starwars">Star Wars</string>  
+    <string name="example_starwars_subtitle">Shows how to create the opening crawl from Star Wars Episode IV.</string>
+    <string name="example_olimpic">Olimpic Rings</string>  
+    <string name="example_olimpic_subtitle">Shows the Chroma effect and Node optimizations.</string>
+    <string name="example_cubes">Cubes</string>  
+    <string name="example_cubes_subtitle">Tests the DistortedCubes render target.</string>
+    <string name="example_quaternion">Quaternion</string>  
+    <string name="example_quaternion_subtitle">Random rotations using quaternions.</string>
+    <string name="example_effects3d">Effects3D</string>  
+    <string name="example_effects3d_subtitle">Test results of all effects on a 3D object.</string>
+    
+    <string name="example_movingeffects_toast">Click on \'RESET\' and define your path by touching the screen. Then click on one of the effects and see it move along your path.</string>
+    <string name="example_cubes_toast">Rotate the cubes by swiping the screen</string>
+</resources>
\ No newline at end of file
diff --git a/src/main/res/values/styles.xml b/src/main/res/values/styles.xml
new file mode 100644
index 0000000..be05db1
--- /dev/null
+++ b/src/main/res/values/styles.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <!--
+     Theme for a wallpaper's setting activity that is designed to be on
+         top of a dark background.
+    -->
+    <style name="WallpaperSettings" parent="@android:style/Theme">
+        <item name="android:windowBackground">@android:drawable/screen_background_dark_transparent</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
+    </style>
+
+    <!--
+         Theme for a wallpaper's setting activity that is designed to be on
+         top of a light background.
+    -->
+    <style name="WallpaperSettingsLight" parent="@android:style/Theme.Light">
+        <item name="android:windowBackground">@android:drawable/screen_background_light_transparent</item>
+        <item name="android:colorBackgroundCacheHint">@null</item>
+        <item name="android:windowIsTranslucent">true</item>
+        <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
+    </style>
+
+</resources>
\ No newline at end of file
