am a5fd2012: Update app icon

* commit 'a5fd2012726ae576fe317905ef190a7b3a7e8640':
  Update app icon
diff --git a/res/raw/bg_vs.glsl b/res/raw/bg_vs.glsl
index d604369..d83c5f1 100644
--- a/res/raw/bg_vs.glsl
+++ b/res/raw/bg_vs.glsl
@@ -2,5 +2,5 @@
 
 void main() {
     color = ATTRIB_color;
-    gl_Position = vec4(ATTRIB_position.x + ATTRIB_offsetX, ATTRIB_position.y, 0.0, 1.0);
+    gl_Position = vec4(ATTRIB_position.x, ATTRIB_position.y, 0.0, 1.0);
 }
\ No newline at end of file
diff --git a/res/raw/bgmesh.csv b/res/raw/bgmesh.csv
new file mode 100644
index 0000000..56ca0b4
--- /dev/null
+++ b/res/raw/bgmesh.csv
@@ -0,0 +1,48 @@
+-1.5,1.0,0.08,0.335,0.406
+-1.5,-0.2,0.137,0.176,0.225
+-1.05,0.3,0.0,0.088,0.135
+-1.5,1.0,0.08,0.335,0.406
+-1.05,0.3,0.0,0.088,0.135
+-0.6,0.4,0.0,0.184,0.233
+-1.5,1.0,0.08,0.335,0.406
+-0.6,0.4,0.0,0.184,0.233
+0.0,1.0,0.133,0.404,0.478
+0.0,1.0,0.133,0.404,0.478
+-0.6,0.4,0.0,0.184,0.233
+0.3,0.4,0.0,0.124,0.178
+0.0,1.0,0.133,0.404,0.478
+0.3,0.4,0.0,0.124,0.178
+1.5,1.0,0.002,0.173,0.231
+1.5,1.0,0.002,0.173,0.231
+0.3,0.4,0.0,0.124,0.178
+1.5,-1.0,0.0,0.088,0.135
+0.3,0.4,0.0,0.124,0.178
+-0.6,0.4,0.0,0.184,0.233
+0.0,0.2,0.0,0.088,0.135
+0.3,0.4,0.0,0.124,0.178
+0.0,0.2,0.0,0.088,0.135
+1.5,-1.0,0.0,0.088,0.135
+0.0,0.2,0.0,0.088,0.135
+-0.6,0.4,0.0,0.184,0.233
+-0.6,0.1,0.002,0.196,0.233
+-0.6,0.1,0.002,0.196,0.233
+-0.6,0.4,0.0,0.184,0.233
+-1.05,0.3,0.0,0.088,0.135
+-1.05,0.3,0.0,0.088,0.135
+-1.5,-0.2,0.137,0.176,0.225
+-0.6,0.1,0.002,0.196,0.233
+-0.45,-0.3,0.002,0.059,0.09
+-0.6,0.1,0.002,0.196,0.233
+-1.5,-0.2,0.137,0.176,0.225
+-0.45,-0.3,0.002,0.059,0.09
+-1.5,-0.2,0.137,0.176,0.225
+-1.5,-1.0,0.204,0.212,0.218
+1.5,-1.0,0.0,0.088,0.135
+-0.45,-0.3,0.002,0.059,0.09
+-1.5,-1.0,0.204,0.212,0.218
+0.0,0.2,0.0,0.088,0.135
+-0.6,0.1,0.002,0.196,0.233
+-0.45,-0.3,0.002,0.059,0.09
+1.5,-1.0,0.0,0.088,0.135
+0.0,0.2,0.0,0.088,0.135
+-0.45,-0.3,0.002,0.059,0.09
\ No newline at end of file
diff --git a/src/com/android/noisefield/NoiseFieldRS.java b/src/com/android/noisefield/NoiseFieldRS.java
index 3962e0a..2ea4878 100644
--- a/src/com/android/noisefield/NoiseFieldRS.java
+++ b/src/com/android/noisefield/NoiseFieldRS.java
@@ -20,15 +20,25 @@
 import android.renderscript.Mesh.Primitive;
 import android.renderscript.ProgramStore.BlendDstFunc;
 import android.renderscript.ProgramStore.BlendSrcFunc;
+import android.os.Bundle;
+import android.app.WallpaperManager;
 import android.util.Log;
+import android.view.MotionEvent;
+import java.io.InputStreamReader;
+import java.io.InputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.util.ArrayList;
 
 public class NoiseFieldRS {
+    public static String LOG_TAG = "NoiseField";
 
     private Resources mRes;
     private RenderScriptGL mRS;
     private ScriptC_noisefield mScript;
-    int mHeight;
-    int mWidth;
+    private int mHeight;
+    private int mWidth;
+    private boolean mTouchDown;
     private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
 
     private ScriptField_VpConsts mPvConsts;
@@ -41,7 +51,6 @@
     public void init(int dpi, RenderScriptGL rs,
                      Resources res, int width, int height) {
         mDensityDPI = dpi;
-
         mRS = rs;
         mRes = res;
 
@@ -53,13 +62,12 @@
 
         Mesh.AllocationBuilder smb2 = new Mesh.AllocationBuilder(mRS);
 
-        mDotParticles = new ScriptField_Particle(mRS, 150);
+        mDotParticles = new ScriptField_Particle(mRS, 83);
         smb2.addVertexAllocation(mDotParticles.getAllocation());
 
         smb2.addIndexSetType(Mesh.Primitive.POINT);
         mScript = new ScriptC_noisefield(mRS, mRes, R.raw.noisefield);
 
-
         mDotMesh = smb2.create();
         mScript.set_dotMesh(mDotMesh);
         mScript.bind_dotParticles(mDotParticles);
@@ -111,125 +119,44 @@
 
     private void createBackgroundMesh() {
         // The composition and colors of the background mesh were plotted on paper and photoshop
-        // first then translated to the code you see below. Points and colors are not random.
+        // first then translated to the csv file in raw. Points and colors are not random.
+        ArrayList<String> meshData = new ArrayList<String>();
+        InputStream inputStream = mRes.openRawResource(R.raw.bgmesh);
+        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
+        try {
+            String line;
+            while ((line = reader.readLine()) != null) {
+                meshData.add(line);
+            }
+        } catch (IOException e) {
+            Log.e(LOG_TAG, "Unable to load background mesh from csv file.");
+        } finally {
+            try {
+                inputStream.close();
+            } catch (IOException e) {
+                Log.e(LOG_TAG, "Unable to close background mesh csv file.");
+            }
+        }
 
-        mVertexColors = new ScriptField_VertexColor_s(mRS, 48);
-        Float3 a = new Float3(-1.5f, 1.0f, 0.0f);
-        Float3 b = new Float3(0.0f, 1.0f, 0.0f);
-        Float3 c = new Float3(1.5f, 1.0f, 0.0f);
-        Float3 d = new Float3(-1.05f, 0.3f, 0.0f);
-        Float3 e = new Float3(-0.6f, 0.4f, 0.0f);
-        Float3 f = new Float3(0.3f, 0.4f, 0.0f);
-        Float3 g = new Float3(0.0f, 0.2f, 0.0f);
-        Float3 h = new Float3(-0.6f, 0.1f, 0.0f);
-        Float3 i = new Float3(-1.5f, -0.2f, 0.0f);
-        Float3 j = new Float3(-0.45f, -0.3f, 0.0f);
-        Float3 k = new Float3(-1.5f, -1.0f, 0.0f);
-        Float3 l = new Float3(1.5f, -1.0f, 0.0f);
-        mVertexColors.set_position(0, a, false);
-        mVertexColors.set_color(0, (new Float4(0.08f,0.335f,0.406f, 1.0f)), false);
-        mVertexColors.set_position(1, i, false);
-        mVertexColors.set_color(1, (new Float4(0.137f,0.176f,0.225f, 1.0f)), false);
-        mVertexColors.set_position(2, d, false);
-        mVertexColors.set_color(2, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(3, a, false);
-        mVertexColors.set_color(3, (new Float4(0.08f,0.335f,0.406f, 1.0f)), false);
-        mVertexColors.set_position(4, d, false);
-        mVertexColors.set_color(4, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(5, e, false);
-        mVertexColors.set_color(5, (new Float4(0.0f,0.184f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(6, a, false);
-        mVertexColors.set_color(6, (new Float4(0.08f,0.335f,0.406f, 1.0f)), false);
-        mVertexColors.set_position(7, e, false);
-        mVertexColors.set_color(7, (new Float4(0.0f,0.184f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(8, b, false);
-        mVertexColors.set_color(8, (new Float4(0.133f,0.404f,0.478f, 1.0f)), false);
-        mVertexColors.set_position(9, b, false);
-        mVertexColors.set_color(9, (new Float4(0.133f,0.404f,0.478f, 1.0f)), false);
-        mVertexColors.set_position(10, e, false);
-        mVertexColors.set_color(10, (new Float4(0.0f,0.184f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(11, f, false);
-        mVertexColors.set_color(11, (new Float4(0.0f,0.124f,0.178f, 1.0f)), false);
-        mVertexColors.set_position(12, b, false);
-        mVertexColors.set_color(12, (new Float4(0.133f,0.404f,0.478f, 1.0f)), false);
-        mVertexColors.set_position(13, f, false);
-        mVertexColors.set_color(13, (new Float4(0.0f,0.124f,0.178f, 1.0f)), false);
-        mVertexColors.set_position(14, c, false);
-        mVertexColors.set_color(14, (new Float4(0.002f,0.173f,0.231f, 1.0f)), false);
-        mVertexColors.set_position(15, c, false);
-        mVertexColors.set_color(15, (new Float4(0.002f,0.173f,0.231f, 1.0f)), false);
-        mVertexColors.set_position(16, f, false);
-        mVertexColors.set_color(16, (new Float4(0.0f,0.124f,0.178f, 1.0f)), false);
-        mVertexColors.set_position(17, l, false);
-        mVertexColors.set_color(17, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(18, f, false);
-        mVertexColors.set_color(18, (new Float4(0.0f,0.124f,0.178f, 1.0f)), false);
-        mVertexColors.set_position(19, e, false);
-        mVertexColors.set_color(19, (new Float4(0.0f,0.184f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(20, g, false);
-        mVertexColors.set_color(20, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(21, f, false);
-        mVertexColors.set_color(21, (new Float4(0.0f,0.124f,0.178f, 1.0f)), false);
-        mVertexColors.set_position(22, g, false);
-        mVertexColors.set_color(22, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(23, l, false);
-        mVertexColors.set_color(23, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(24, g, false);
-        mVertexColors.set_color(24, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(25, e, false);
-        mVertexColors.set_color(25, (new Float4(0.0f,0.184f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(26, h, false);
-        mVertexColors.set_color(26, (new Float4(0.002f,0.196f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(27, h, false);
-        mVertexColors.set_color(27, (new Float4(0.002f,0.196f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(28, e, false);
-        mVertexColors.set_color(28, (new Float4(0.0f,0.184f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(29, d, false);
-        mVertexColors.set_color(29, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(30, d, false);
-        mVertexColors.set_color(30, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(31, i, false);
-        mVertexColors.set_color(31, (new Float4(0.137f,0.176f,0.225f, 1.0f)), false);
-        mVertexColors.set_position(32, h, false);
-        mVertexColors.set_color(32, (new Float4(0.002f,0.196f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(33, j, false);
-        mVertexColors.set_color(33, (new Float4(0.002f,0.059f,0.09f, 1.0f)), false);
-        mVertexColors.set_position(34, h, false);
-        mVertexColors.set_color(34, (new Float4(0.002f,0.196f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(35, i, false);
-        mVertexColors.set_color(35, (new Float4(0.137f,0.176f,0.225f, 1.0f)), false);
-        mVertexColors.set_position(36, j, false);
-        mVertexColors.set_color(36, (new Float4(0.002f,0.059f,0.09f, 1.0f)), false);
-        mVertexColors.set_position(37, i, false);
-        mVertexColors.set_color(37, (new Float4(0.137f,0.176f,0.225f, 1.0f)), false);
-        mVertexColors.set_position(38, k, false);
-        mVertexColors.set_color(38, (new Float4(0.204f,0.212f,0.218f, 1.0f)), false);
-        mVertexColors.set_position(39, l, false);
-        mVertexColors.set_color(39, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(40, j, false);
-        mVertexColors.set_color(40, (new Float4(0.002f,0.059f,0.09f, 1.0f)), false);
-        mVertexColors.set_position(41, k, false);
-        mVertexColors.set_color(41, (new Float4(0.204f,0.212f,0.218f, 1.0f)), false);
-        mVertexColors.set_position(42, g, false);
-        mVertexColors.set_color(42, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(43, h, false);
-        mVertexColors.set_color(43, (new Float4(0.002f,0.196f,0.233f, 1.0f)), false);
-        mVertexColors.set_position(44, j, false);
-        mVertexColors.set_color(44, (new Float4(0.002f,0.059f,0.09f, 1.0f)), false);
-        mVertexColors.set_position(45, l, false);
-        mVertexColors.set_color(45, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(46, g, false);
-        mVertexColors.set_color(46, (new Float4(0.0f,0.088f,0.135f, 1.0f)), false);
-        mVertexColors.set_position(47, j, false);
-        mVertexColors.set_color(47, (new Float4(0.002f,0.059f,0.09f, 1.0f)), false);
-
+        int meshDataSize = meshData.size();
+        mVertexColors = new ScriptField_VertexColor_s(mRS, meshDataSize);
+        for (int i=0; i<meshDataSize; i++) {
+            String line = (String) meshData.get(i);
+            String[] values = line.split(",");
+            float xPos = Float.parseFloat(values[0]);
+            float yPos = Float.parseFloat(values[1]);
+            float red = Float.parseFloat(values[2]);
+            float green = Float.parseFloat(values[3]);
+            float blue = Float.parseFloat(values[4]);
+            mVertexColors.set_position(i, new Float3(xPos, yPos, 0.0f), false);
+            mVertexColors.set_color(i, new Float4(red, green, blue, 1.0f), false);
+        }
         mVertexColors.copyAll();
 
         Mesh.AllocationBuilder backgroundBuilder = new Mesh.AllocationBuilder(mRS);
         backgroundBuilder.addIndexSetType(Primitive.TRIANGLE);
         backgroundBuilder.addVertexAllocation(mVertexColors.getAllocation());
         mScript.set_gBackgroundMesh(backgroundBuilder.create());
-
         mScript.bind_vertexColors(mVertexColors);
     }
 
@@ -250,7 +177,6 @@
         ProgramVertex programVertexBackground = backgroundBuilder.create();
         mScript.set_vertBg(programVertexBackground);
 
-
         updateProjectionMatrices();
 
         ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS);
@@ -298,15 +224,33 @@
 
     public void stop() {
         mRS.bindRootScript(null);
-
-    }
-
-    public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
-        mScript.set_xOffset(xOffset - 0.5f);
     }
 
     public void resize(int w, int h) {
 
     }
 
-}
+    public void onTouchEvent(MotionEvent ev) {
+        int act = ev.getActionMasked();
+        if (act == MotionEvent.ACTION_UP || act == MotionEvent.ACTION_POINTER_UP) {
+            if(mTouchDown){
+                mTouchDown = false;
+                mScript.set_touchDown(mTouchDown);
+            }
+            return;
+        } else if(   act == MotionEvent.ACTION_DOWN
+                  || act == MotionEvent.ACTION_MOVE
+                  || act == MotionEvent.ACTION_POINTER_DOWN) {
+            int pcount = ev.getPointerCount();
+
+            if(!mTouchDown){
+                mTouchDown = true;
+                mScript.set_touchDown(mTouchDown);
+            }
+            if(pcount > 0){
+                // just send first pointer position
+                mScript.invoke_touch(ev.getX(0), ev.getY(0));
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/noisefield/NoiseFieldView.java b/src/com/android/noisefield/NoiseFieldView.java
index aa9bf6a..8a5e95f 100644
--- a/src/com/android/noisefield/NoiseFieldView.java
+++ b/src/com/android/noisefield/NoiseFieldView.java
@@ -27,7 +27,6 @@
             mRender = new NoiseFieldRS();
             mRender.init(240, mRS, getResources(), w, h);
         }
-
     }
 
     @Override
@@ -39,4 +38,4 @@
         }
     }
 
-}
+}
\ No newline at end of file
diff --git a/src/com/android/noisefield/NoiseFieldWallpaper.java b/src/com/android/noisefield/NoiseFieldWallpaper.java
index 09661cf..08a6769 100644
--- a/src/com/android/noisefield/NoiseFieldWallpaper.java
+++ b/src/com/android/noisefield/NoiseFieldWallpaper.java
@@ -10,6 +10,8 @@
 import android.util.DisplayMetrics;
 import android.view.SurfaceHolder;
 import android.view.WindowManager;
+import android.util.Log;
+import android.view.MotionEvent;
 
 public class NoiseFieldWallpaper extends WallpaperService {
 
@@ -21,7 +23,7 @@
     private class RenderScriptEngine extends Engine {
         private RenderScriptGL mRenderScript = null;
         private NoiseFieldRS mWallpaperRS = null;
-        private int densityDPI;
+        private int mDensityDPI;
 
         @Override
         public void onCreate(SurfaceHolder surfaceHolder) {
@@ -33,7 +35,7 @@
             DisplayMetrics metrics = new DisplayMetrics();
             ((WindowManager) getApplication().getSystemService(Service.WINDOW_SERVICE))
                     .getDefaultDisplay().getMetrics(metrics);
-            densityDPI = metrics.densityDpi;
+            mDensityDPI = metrics.densityDpi;
         }
 
         @Override
@@ -71,7 +73,10 @@
         }
 
         @Override
-        public void onSurfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
+        public void onSurfaceChanged(SurfaceHolder surfaceHolder,
+                                     int format,
+                                     int width,
+                                     int height) {
             super.onSurfaceChanged(surfaceHolder, format, width, height);
 
             if (mRenderScript != null) {
@@ -80,7 +85,7 @@
 
             if (mWallpaperRS == null) {
                 mWallpaperRS = new NoiseFieldRS();
-                mWallpaperRS.init(densityDPI, mRenderScript, getResources(), width, height);
+                mWallpaperRS.init(mDensityDPI, mRenderScript, getResources(), width, height);
                 mWallpaperRS.start();
             }
 
@@ -88,12 +93,9 @@
         }
 
         @Override
-        public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
-                boolean resultRequested) {
-            if (mWallpaperRS != null) {
-                // return mWallpaperRS.onCommand(action, x, y, z, extras, resultRequested);
-            }
-            return null;
+        public void onTouchEvent(MotionEvent ev) {
+            super.onTouchEvent(ev);
+            mWallpaperRS.onTouchEvent(ev);
         }
 
         @Override
@@ -107,11 +109,5 @@
                 }
             }
         }
-
-        @Override
-        public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
-                float yOffsetStep, int xPixelOffset, int yPixelOffset) {
-            mWallpaperRS.setOffset(xOffset, yOffset, xPixelOffset, yPixelOffset);
-        }
     }
 }
diff --git a/src/com/android/noisefield/noisefield.rs b/src/com/android/noisefield/noisefield.rs
index f6b16d8..751f603 100644
--- a/src/com/android/noisefield/noisefield.rs
+++ b/src/com/android/noisefield/noisefield.rs
@@ -49,7 +49,7 @@
 rs_mesh gBackgroundMesh;
 
 float densityDPI;
-float xOffset = 0.0;
+bool touchDown = false;
 
 #define B 0x100
 #define BM 0xff
@@ -60,30 +60,31 @@
 static float g2[B + B + 2][2];
 static float g1[B + B + 2];
 
-static float noise_sCurve(float t)
-{
+// used for motion easing from touch to non-touch state
+static float touchInfluence = 0;
+
+static float touchX = 0;
+static float touchY = 0;
+
+static float noise_sCurve(float t) {
     return t * t * (3.0f - 2.0f * t);
 }
 
-static void normalizef2(float v[])
-{
+static void normalizef2(float v[]) {
     float s = (float)sqrt(v[0] * v[0] + v[1] * v[1]);
     v[0] = v[0] / s;
     v[1] = v[1] / s;
 }
 
-static void normalizef3(float v[])
-{
+static void normalizef3(float v[]) {
     float s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
     v[0] = v[0] / s;
     v[1] = v[1] / s;
     v[2] = v[2] / s;
 }
 
-void init()
-{
+void init() {
     int i, j, k;
-
     for (i = 0; i < B; i++) {
         p[i] = i;
 
@@ -114,8 +115,7 @@
     }
 }
 
-static float noisef2(float x, float y)
-{
+static float noisef2(float x, float y) {
     int bx0, bx1, by0, by1, b00, b10, b01, b11;
     float rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v;
     float *q;
@@ -155,10 +155,10 @@
     return 1.5f * mix(a, b, sy);
 }
 
-void positionParticles(){
+void positionParticles() {
     Particle_t* particle = dotParticles;
     int size = rsAllocationGetDimX(rsGetAllocation(dotParticles));
-    for(int i=0; i<size; i++){
+    for(int i=0; i<size; i++) {
         particle->position.x = rsRand(-1.0f, 1.0f);
         particle->position.y = rsRand(-1.0f, 1.0f);
         particle->speed = rsRand(0.0002f, 0.02f);
@@ -171,16 +171,26 @@
     }
 }
 
-int root(){
-    rsgClearColor(0.0, 0.0, 0.0, 1.0f);
-
-    VertexColor* vert = vertexColors;
-    int size = rsAllocationGetDimX(rsGetAllocation(vertexColors));
-    for(int i=0; i<size; i++){
-        vert->offsetX = xOffset;
-        vert++;
+void touch(float x, float y) {
+    bool landscape = rsgGetWidth() > rsgGetHeight();
+    float wRatio;
+    float hRatio;
+    if(!landscape){
+        wRatio = 1.0;
+        hRatio = rsgGetHeight()/rsgGetWidth();
+    } else {
+        hRatio = 1.0;
+        wRatio = rsgGetWidth()/rsgGetHeight();
     }
 
+    touchInfluence = 1.0;
+    touchX = x/rsgGetWidth() * wRatio * 2 - wRatio;
+    touchY = -(y/rsgGetHeight() * hRatio * 2 - hRatio);
+}
+
+int root() {
+    rsgClearColor(0.0, 0.0, 0.0, 1.0f);
+    int size = rsAllocationGetDimX(rsGetAllocation(vertexColors));
     rsgBindProgramVertex(vertDots);
     rsgBindProgramFragment(fragDots);
     rsgBindTexture(fragDots, 0, textureDot);
@@ -194,11 +204,13 @@
     // dots
     Particle_t* particle = dotParticles;
     size = rsAllocationGetDimX(rsGetAllocation(dotParticles));
-    for(int i=0; i<size; i++){
+    float rads;
+    float speed;
 
+    for(int i=0; i<size; i++) {
         if(particle->life < 0 || particle->position.x < -1.2 ||
            particle->position.x >1.2 || particle->position.y < -1.7 ||
-           particle->position.y >1.7){
+           particle->position.y >1.7) {
             particle->position.x = rsRand(-1.0f, 1.0f);
             particle->position.y = rsRand(-1.0f, 1.0f);
             particle->speed = rsRand(0.0002f, 0.02f);
@@ -209,35 +221,52 @@
             particle->alpha = particle->alphaStart;
         }
 
+        float touchDist = sqrt(pow(touchX - particle->position.x, 2) +
+                               pow(touchY - particle->position.y, 2));
+
         float noiseval = noisef2(particle->position.x, particle->position.y);
+        if(touchDown || touchInfluence > 0.0) {
+            if(touchDown){
+                touchInfluence = 1.0;
+            }
+            rads = atan2(touchX - particle->position.x + noiseval,
+                         touchY - particle->position.y + noiseval);
+            if(touchDist != 0){
+                speed = ( (0.25 + (noiseval * particle->speed + 0.01)) / touchDist * 0.3 );
+                speed = speed * touchInfluence;
+            } else {
+                speed = .3;
+            }
+            particle->position.x += cos(rads) * speed * 0.2;
+            particle->position.y += sin(rads) * speed * 0.2;
+        }
 
-        float speed = noiseval * particle->speed + 0.01;
         float angle = 360 * noiseval * particle->wander;
-        float rads = angle * 3.14159265 / 180.0;
+        speed = noiseval * particle->speed + 0.01;
+        rads = angle * 3.14159265 / 180.0;
 
-        particle->position.x += cos(rads) * speed * 0.24;
-        particle->position.y += sin(rads) * speed * 0.24;
+        particle->position.x += cos(rads) * speed * 0.33;
+        particle->position.y += sin(rads) * speed * 0.33;
 
         particle->life--;
         particle->death++;
 
         float dist = sqrt(particle->position.x*particle->position.x +
                           particle->position.y*particle->position.y);
-        if(dist < 0.95){
+        if(dist < 0.95) {
             dist = 0;
             particle->alphaStart *= (1-dist);
-
         } else {
             dist = dist-0.95;
-            if(particle->alphaStart < 1.0f){
+            if(particle->alphaStart < 1.0f) {
                 particle->alphaStart +=0.01;
                 particle->alphaStart *= (1-dist);
             }
         }
 
-        if(particle->death < 101){
+        if(particle->death < 101) {
             particle->alpha = (particle->alphaStart)*(particle->death)/100.0;
-        } else if(particle->life < 101){
+        } else if(particle->life < 101) {
             particle->alpha = particle->alpha*particle->life/100.0;
         } else {
             particle->alpha = particle->alphaStart;
@@ -246,6 +275,8 @@
         particle++;
     }
 
+    if(touchInfluence > 0) {
+        touchInfluence-=0.01;
+    }
     return 35;
-
-}
+}
\ No newline at end of file