Update water with new wave physics.
diff --git a/res/raw/distort.rs b/res/raw/distort.rs
new file mode 100644
index 0000000..3158a04
--- /dev/null
+++ b/res/raw/distort.rs
@@ -0,0 +1,545 @@
+// Copyright (C) 2009 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#pragma version(1)
+#pragma stateVertex(PVSky)
+#pragma stateFragment(PFBackground)
+#pragma stateStore(PFSBackground)
+
+#define RSID_RIPPLE_MAP 1
+#define RSID_REFRACTION_MAP 2
+
+#define LEAVES_TEXTURES_COUNT 4
+
+#define LEAF_SIZE 0.55f
+
+#define REFRACTION 1.333f
+#define DAMP 3
+
+#define DROP_RADIUS 2
+// The higher, the smaller the ripple
+#define RIPPLE_HEIGHT 10.0f
+
+float skyOffsetX;
+float skyOffsetY;
+
+int lastDrop;
+
+struct vert_s {
+    float x;
+    float y;
+    float z;
+    float s;
+    float t;
+    float nx;
+    float ny;
+    float nz;
+};
+
+struct drop_s {
+    float amp;
+    float phase;
+    float x;
+    float y;
+};
+struct drop_s gDrops[10];
+
+int offset(int x, int y, int width) {
+    return x + 1 + (y + 1) * (width + 2);
+}
+
+void init() {
+    gDrops[0].amp = 0.2f;
+    gDrops[0].phase = 0;
+}
+
+void initLeaves() {
+    if (State->isPreview) lastDrop = uptimeMillis();
+
+    struct Leaves_s *leaf = Leaves;
+    int leavesCount = State->leavesCount;
+    float width = State->glWidth;
+    float height = State->glHeight;
+
+    int i;
+    for (i = 0; i < leavesCount; i ++) {
+        int sprite = randf(LEAVES_TEXTURES_COUNT);
+        leaf->x = randf2(-width * 0.5f, width * 0.5f);
+        leaf->y = randf2(-height * 0.5f, height * 0.5f);
+        leaf->scale = randf2(0.4f, 0.5f);
+        leaf->angle = randf2(0.0f, 360.0f);
+        leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.25f;
+        leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
+        leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
+        leaf->altitude = -1.0f;
+        leaf->rippled = 1.0f;
+        leaf->deltaX = randf2(-0.02f, 0.02f) / 60.0f;
+        leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
+        leaf++;
+    }
+}
+
+void dropWithStrength(int x, int y, int r, int s) {
+    int width = State->meshWidth;
+    int height = State->meshHeight;
+
+    if (x < r) x = r;
+    if (y < r) y = r;
+    if (x >= width - r) x = width - r - 1;
+    if (y >= height - r) y = height - r - 1;
+
+    x = width - x;
+
+    int rippleMapSize = State->rippleMapSize;
+    int index = State->rippleIndex;
+    int origin = offset(0, 0, width);
+
+    int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
+    int sqr = r * r;
+    float invs = 1.0f / s;
+
+    int h = 0;
+    for ( ; h < r; h += 1) {
+        int sqv = h * h;
+        int yn = origin + (y - h) * (width + 2);
+        int yp = origin + (y + h) * (width + 2);
+        int w = 0;
+        for ( ; w < r; w += 1) {
+            int squ = w * w;
+            if (squ + sqv < sqr) {
+                int v = -sqrtf((sqr - (squ + sqv)) << 16) * invs;
+                current[yn + x + w] = v;
+                current[yp + x + w] = v;
+                current[yn + x - w] = v;
+                current[yp + x - w] = v;
+            }
+        }
+    }
+}
+
+void drop(int x, int y, int r) {
+    dropWithStrength(x, y, r, 1);
+}
+
+void updateRipples() {
+    int rippleMapSize = State->rippleMapSize;
+    int width = State->meshWidth;
+    int height = State->meshHeight;
+    int index = State->rippleIndex;
+    int origin = offset(0, 0, width);
+
+    int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
+    int* next = loadArrayI32(RSID_RIPPLE_MAP, (1 - index) * rippleMapSize + origin);
+
+    State->rippleIndex = 1 - index;
+
+    int a = 1;
+    int b = width + 2;
+    int h = height;
+    while (h) {
+        int w = width;
+        while (w) {
+            int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - *next;
+            *next = droplet - (droplet >> DAMP);
+            current += 1;
+            next += 1;
+            w -= 1;
+        }
+        current += 2;
+        next += 2;
+        h -= 1;
+    }
+}
+
+int refraction(int d, int wave, int *map) {
+    int i = d;
+    if (i < 0) i = -i;
+    if (i > 512) i = 512;
+    int w = (wave + 0x10000) >> 8;
+    w &= ~(w >> 31);
+    int r = (map[i] * w) >> 3;
+    if (d < 0) {
+        return -r;
+    }
+    return r;
+}
+
+void generateRipples() {
+    int rippleMapSize = State->rippleMapSize;
+    int width = State->meshWidth;
+    int height = State->meshHeight;
+    int index = State->rippleIndex;
+    int origin = offset(0, 0, width);
+
+    int b = width + 2;
+
+    int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
+    int *map = loadArrayI32(RSID_REFRACTION_MAP, 0);
+    float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
+    struct vert_s *vert = (struct vert_s *)vertices;
+
+    float fw = 1.0f / width;
+    float fh = 1.0f / height;
+    float fy = (1.0f / 512.0f) * (1.0f / RIPPLE_HEIGHT);
+/*
+    int h = height - 1;
+    while (h >= 0) {
+        int w = width - 1;
+        int wave = *current;
+        int offset = h * width;
+        struct vert_s *vtx = vert + offset + w;
+
+        while (w >= 0) {
+            int nextWave = current[1];
+            int dx = nextWave - wave;
+            int dy = current[b] - wave;
+
+            int offsetx = refraction(dx, wave, map) >> 16;
+            int u = (width - w) + offsetx;
+            u &= ~(u >> 31);
+            if (u >= width) u = width - 1;
+
+            int offsety = refraction(dy, wave, map) >> 16;
+            int v = (height - h) + offsety;
+            v &= ~(v >> 31);
+            if (v >= height) v = height - 1;
+
+            vtx->s = u * fw;
+            vtx->t = v * fh;
+            vtx->z = dy * fy;
+            debugF("es", vtx->s);
+            vtx --;
+
+            w -= 1;
+            current += 1;
+            wave = nextWave;
+        }
+        h -= 1;
+        current += 2;
+    }
+*/
+    {
+        gDrops[0].x = width / 2;
+        gDrops[0].y = height / 2;
+
+        int x, y;
+        struct vert_s *vtx = vert;
+        for (y=0; y < height; y++) {
+            for (x=0; x < width; x++) {
+                struct drop_s * d = &gDrops[0];
+                float z = 0;
+
+                {
+                    float dx = d->x - x;
+                    float dy = d->y - y;
+                    float dist = sqrtf(dx*dx + dy*dy);
+                    z = sinf(dist + d->phase) * d->amp;
+
+                    vtx->s = (float)x / width;
+                    vtx->t = (float)y / height;
+                    vtx->z = z;
+                    vtx ++;
+                }
+            }
+        }
+        gDrops[0].phase += 0.02;
+    }
+
+    // Compute the normals for lighting
+    int y = 0;
+    for ( ; y < (height-1); y += 1) {
+        int x = 0;
+        int yOffset = y * width;
+        struct vert_s *v = vert;
+        v += y * width;
+
+        for ( ; x < (width-1); x += 1) {
+            struct vec3_s n1, n2, n3;
+            vec3Sub(&n1, (struct vec3_s *)&(v+1)->x, (struct vec3_s *)&v->x);
+            vec3Sub(&n2, (struct vec3_s *)&(v+width)->x, (struct vec3_s *)&v->x);
+            vec3Cross(&n3, &n1, &n2);
+            vec3Norm(&n3);
+
+            // Average of previous normal and N1 x N2
+            vec3Sub(&n1, (struct vec3_s *)&(v+width+1)->x, (struct vec3_s *)&v->x);
+            vec3Cross(&n2, &n1, &n2);
+            vec3Add(&n3, &n3, &n2);
+            vec3Norm(&n3);
+
+            v->nx = n3.x;
+            v->ny = n3.y;
+            v->nz = -n3.z;
+            v->s += v->nx * 0.01;
+            v->t += v->ny * 0.01;
+            v += 1;
+
+            // reset Z
+            //vertices[(yOffset + x) << 3 + 7] = 0.0f;
+        }
+    }
+}
+
+void drawLeaf(struct Leaves_s *leaf, int meshWidth, int meshHeight, float glWidth, float glHeight,
+        int rotate) {
+
+    float x = leaf->x;
+    float x1 = x - LEAF_SIZE;
+    float x2 = x + LEAF_SIZE;
+
+    float y = leaf->y;
+    float y1 = y - LEAF_SIZE;
+    float y2 = y + LEAF_SIZE;
+
+    float u1 = leaf->u1;
+    float u2 = leaf->u2;
+
+    float z1 = 0.0f;
+    float z2 = 0.0f;
+    float z3 = 0.0f;
+    float z4 = 0.0f;
+
+    float a = leaf->altitude;
+    float s = leaf->scale;
+    float r = leaf->angle;
+
+    float tz = 0.0f;
+    if (a > 0.0f) {
+        tz = -a;
+    }
+
+    x1 -= x;
+    x2 -= x;
+    y1 -= y;
+    y2 -= y;
+
+    float matrix[16];
+
+    if (a > 0.0f) {
+        color(0.0f, 0.0f, 0.0f, 0.15f);
+
+        if (rotate) {
+            matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
+        } else {
+            matrixLoadIdentity(matrix);
+        }
+        matrixTranslate(matrix, x, y, 0.0f);
+        matrixScale(matrix, s, s, 1.0f);
+        matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
+        vpLoadModelMatrix(matrix);
+
+        drawQuadTexCoords(x1, y1, z1, u1, 1.0f,
+                          x2, y1, z2, u2, 1.0f,
+                          x2, y2, z3, u2, 0.0f,
+                          x1, y2, z4, u1, 0.0f);
+
+        float alpha = 1.0f;
+        if (a >= 0.4f) alpha = 1.0f - (a - 0.5f) / 0.1f;
+        color(1.0f, 1.0f, 1.0f, alpha);
+    } else {
+        color(1.0f, 1.0f, 1.0f, 1.0f);
+    }
+
+    if (rotate) {
+        matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
+    } else {
+        matrixLoadIdentity(matrix);
+    }
+    matrixTranslate(matrix, x, y, tz);
+    matrixScale(matrix, s, s, 1.0f);
+    matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
+    vpLoadModelMatrix(matrix);
+
+    drawQuadTexCoords(x1, y1, z1, u1, 1.0f,
+                      x2, y1, z2, u2, 1.0f,
+                      x2, y2, z3, u2, 0.0f,
+                      x1, y2, z4, u1, 0.0f);
+
+    float spin = leaf->spin;
+    if (a <= 0.0f) {
+        float rippled = leaf->rippled;
+        if (rippled < 0.0f) {
+            drop(((x + glWidth * 0.5f) / glWidth) * meshWidth,
+                 meshHeight - ((y + glHeight * 0.5f) / glHeight) * meshHeight, 1);
+            spin /= 4.0f;
+            leaf->spin = spin;
+            leaf->rippled = 1.0f;
+        }
+        leaf->x = x + leaf->deltaX;
+        leaf->y = y + leaf->deltaY;
+        r += spin;
+        leaf->angle = r;
+    } else {
+        a -= 0.005f;
+        leaf->altitude = a;
+        r += spin * 2.0f;
+        leaf->angle = r;
+    }
+
+    if (-LEAF_SIZE * s + x > glWidth / 2.0f || LEAF_SIZE * s + x < -glWidth / 2.0f ||
+            LEAF_SIZE * s + y < -glHeight / 2.0f) {
+
+        int sprite = randf(LEAVES_TEXTURES_COUNT);
+        leaf->x = randf2(-glWidth * 0.5f, glWidth * 0.5f);
+        leaf->y = randf2(-glHeight * 0.5f, glHeight * 0.5f);
+        leaf->scale = randf2(0.4f, 0.5f);
+        leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.25f;
+        leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
+        leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
+        leaf->altitude = 0.6f;
+        leaf->rippled = -1.0f;
+        leaf->deltaX = randf2(-0.02f, 0.02f) / 60.0f;
+        leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
+    }
+}
+
+void drawLeaves() {
+    bindProgramFragment(NAMED_PFSky);
+    bindProgramFragmentStore(NAMED_PFSLeaf);
+    bindProgramVertex(NAMED_PVSky);
+    bindTexture(NAMED_PFSky, 0, NAMED_TLeaves);
+
+    color(1.0f, 1.0f, 1.0f, 1.0f);
+
+    int leavesCount = State->leavesCount;
+    int width = State->meshWidth;
+    int height = State->meshHeight;
+    float glWidth = State->glWidth;
+    float glHeight = State->glHeight;
+    int rotate = State->rotate;
+
+    struct Leaves_s *leaf = Leaves;
+
+    int i = 0;
+    for ( ; i < leavesCount; i += 1) {
+        drawLeaf(leaf, width, height, glWidth, glHeight, rotate);
+        leaf += 1;
+    }
+
+    float matrix[16];
+    matrixLoadIdentity(matrix);
+    vpLoadModelMatrix(matrix);
+}
+
+void drawRiverbed() {
+    bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
+
+    drawSimpleMesh(NAMED_WaterMesh);
+}
+
+void drawSky() {
+    color(1.0f, 1.0f, 1.0f, 0.4f);
+
+    bindProgramFragment(NAMED_PFSky);
+    bindProgramFragmentStore(NAMED_PFSLeaf);
+    bindTexture(NAMED_PFSky, 0, NAMED_TSky);
+
+    float x = skyOffsetX + State->skySpeedX;
+    float y = skyOffsetY + State->skySpeedY;
+
+    if (x > 1.0f) x = 0.0f;
+    if (x < -1.0f) x = 0.0f;
+    if (y > 1.0f) y = 0.0f;
+
+    skyOffsetX = x;
+    skyOffsetY = y;
+
+    float matrix[16];
+    matrixLoadTranslate(matrix, x, y, 0.0f);
+    vpLoadTextureMatrix(matrix);
+
+    drawSimpleMesh(NAMED_WaterMesh);
+
+    matrixLoadIdentity(matrix);
+    vpLoadTextureMatrix(matrix);
+}
+
+void drawLighting() {
+    ambient(0.0f, 0.0f, 0.0f, 1.0f);
+    diffuse(0.0f, 0.0f, 0.0f, 1.0f);
+    specular(0.44f, 0.44f, 0.44f, 1.0f);
+    shininess(40.0f);
+
+    bindProgramFragmentStore(NAMED_PFSBackground);
+    bindProgramFragment(NAMED_PFLighting);
+    bindProgramVertex(NAMED_PVLight);
+
+    drawSimpleMesh(NAMED_WaterMesh);
+}
+
+void drawNormals() {
+    int width = State->meshWidth;
+    int height = State->meshHeight;
+
+    float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
+
+    bindProgramVertex(NAMED_PVSky);
+    bindProgramFragment(NAMED_PFLighting);
+
+    color(1.0f, 0.0f, 0.0f, 1.0f);
+
+    float scale = 1.0f / 10.0f;
+    int y = 0;
+    for ( ; y < height; y += 1) {
+        int yOffset = y * width;
+        int x = 0;
+        for ( ; x < width; x += 1) {
+            int offset = (yOffset + x) << 3;
+            float vx = vertices[offset + 5];
+            float vy = vertices[offset + 6];
+            float vz = vertices[offset + 7];
+            float nx = vertices[offset + 0];
+            float ny = vertices[offset + 1];
+            float nz = vertices[offset + 2];
+            drawLine(vx, vy, vz, vx + nx * scale, vy + ny * scale, vz + nz * scale);
+        }
+    }
+}
+
+int main(int index) {
+    if (Drop->dropX != -1) {
+        drop(Drop->dropX, Drop->dropY, DROP_RADIUS);
+        Drop->dropX = -1;
+        Drop->dropY = -1;
+    }
+
+    if (State->isPreview) {
+        int now = uptimeMillis();
+        if (now - lastDrop > 2000) {
+            float x = randf(State->meshWidth);
+            float y = randf(State->meshHeight);
+
+            drop(x, y, DROP_RADIUS);
+
+            lastDrop = now;
+        }
+    }
+
+    updateRipples();
+    generateRipples();
+    updateSimpleMesh(NAMED_WaterMesh);
+
+    if (State->rotate) {
+        float matrix[16];
+        matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
+        vpLoadModelMatrix(matrix);
+    }
+
+    drawRiverbed();
+    //drawSky();
+    drawLighting();
+    //drawLeaves();
+    //drawNormals();
+
+    return 1;
+}
diff --git a/res/raw/fall.rs b/res/raw/fall.rs
index a54e3b5..326f326 100644
--- a/res/raw/fall.rs
+++ b/res/raw/fall.rs
@@ -17,25 +17,12 @@
 #pragma stateFragment(PFBackground)
 #pragma stateStore(PFSBackground)
 
-#define RSID_RIPPLE_MAP 1
-#define RSID_REFRACTION_MAP 2
-
 #define LEAVES_TEXTURES_COUNT 4
-
 #define LEAF_SIZE 0.55f
 
-#define REFRACTION 1.333f
-#define DAMP 3
-
-#define DROP_RADIUS 2
-// The higher, the smaller the ripple
-#define RIPPLE_HEIGHT 10.0f
-
 float skyOffsetX;
 float skyOffsetY;
 
-int lastDrop;
-
 struct vert_s {
     float x;
     float y;
@@ -47,13 +34,29 @@
     float nz;
 };
 
-int offset(int x, int y, int width) {
-    return x + 1 + (y + 1) * (width + 2);
+struct drop_s {
+    float amp;
+    float spread;
+    float invSpread;
+    float x;
+    float y;
+};
+struct drop_s gDrops[10];
+int gNextDrop;
+int gMaxDrops;
+
+void init() {
+    int ct;
+    gMaxDrops = 10;
+    for (ct=0; ct<gMaxDrops; ct++) {
+        gDrops[ct].amp = 0;
+        gDrops[ct].spread = 1;
+        gDrops[ct].invSpread = 1 / gDrops[ct].spread;
+    }
+    gNextDrop = 0;
 }
 
 void initLeaves() {
-    if (State->isPreview) lastDrop = uptimeMillis();
-
     struct Leaves_s *leaf = Leaves;
     int leavesCount = State->leavesCount;
     float width = State->glWidth;
@@ -77,89 +80,14 @@
     }
 }
 
-void dropWithStrength(int x, int y, int r, int s) {
-    int width = State->meshWidth;
-    int height = State->meshHeight;
-
-    if (x < r) x = r;
-    if (y < r) y = r;
-    if (x >= width - r) x = width - r - 1;
-    if (y >= height - r) y = height - r - 1;
-
-    x = width - x;
-
-    int rippleMapSize = State->rippleMapSize;
-    int index = State->rippleIndex;
-    int origin = offset(0, 0, width);
-
-    int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
-    int sqr = r * r;
-    float invs = 1.0f / s;
-
-    int h = 0;
-    for ( ; h < r; h += 1) {
-        int sqv = h * h;
-        int yn = origin + (y - h) * (width + 2);
-        int yp = origin + (y + h) * (width + 2);
-        int w = 0;
-        for ( ; w < r; w += 1) {
-            int squ = w * w;
-            if (squ + sqv < sqr) {
-                int v = -sqrtf((sqr - (squ + sqv)) << 16) * invs;
-                current[yn + x + w] = v;
-                current[yp + x + w] = v;
-                current[yn + x - w] = v;
-                current[yp + x - w] = v;
-            }
-        }
-    }
-}
-
-void drop(int x, int y, int r) {
-    dropWithStrength(x, y, r, 1);
-}
-
-void updateRipples() {
-    int rippleMapSize = State->rippleMapSize;
-    int width = State->meshWidth;
-    int height = State->meshHeight;
-    int index = State->rippleIndex;
-    int origin = offset(0, 0, width);
-
-    int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
-    int* next = loadArrayI32(RSID_RIPPLE_MAP, (1 - index) * rippleMapSize + origin);
-
-    State->rippleIndex = 1 - index;
-
-    int a = 1;
-    int b = width + 2;
-    int h = height;
-    while (h) {
-        int w = width;
-        while (w) {
-            int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - *next;
-            *next = droplet - (droplet >> DAMP);
-            current += 1;
-            next += 1;
-            w -= 1;
-        }
-        current += 2;
-        next += 2;
-        h -= 1;
-    }
-}
-
-int refraction(int d, int wave, int *map) {
-    int i = d;
-    if (i < 0) i = -i;
-    if (i > 512) i = 512;
-    int w = (wave + 0x10000) >> 8;
-    w &= ~(w >> 31);
-    int r = (map[i] * w) >> 3;
-    if (d < 0) {
-        return -r;
-    }
-    return r;
+void drop(int x, int y, float s) {
+    gDrops[gNextDrop].amp = s;
+    gDrops[gNextDrop].spread = 0.5f;
+    gDrops[gNextDrop].x = x;
+    gDrops[gNextDrop].y = State->meshHeight - y - 1;
+    gNextDrop++;
+    if (gNextDrop >= gMaxDrops)
+        gNextDrop = 0;
 }
 
 void generateRipples() {
@@ -167,52 +95,42 @@
     int width = State->meshWidth;
     int height = State->meshHeight;
     int index = State->rippleIndex;
-    int origin = offset(0, 0, width);
 
-    int b = width + 2;
-
-    int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
-    int *map = loadArrayI32(RSID_REFRACTION_MAP, 0);
     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
     struct vert_s *vert = (struct vert_s *)vertices;
 
     float fw = 1.0f / width;
     float fh = 1.0f / height;
-    float fy = (1.0f / 512.0f) * (1.0f / RIPPLE_HEIGHT);
+    {
+        int x, y, ct;
+        struct vert_s *vtx = vert;
+        for (y=0; y < height; y++) {
+            for (x=0; x < width; x++) {
+                struct drop_s * d = &gDrops[0];
+                float z = 0;
 
-    int h = height - 1;
-    while (h >= 0) {
-        int w = width - 1;
-        int wave = *current;
-        int offset = h * width;
-        struct vert_s *vtx = vert + offset + w;
-
-        while (w >= 0) {
-            int nextWave = current[1];
-            int dx = nextWave - wave;
-            int dy = current[b] - wave;
-
-            int offsetx = refraction(dx, wave, map) >> 16;
-            int u = (width - w) + offsetx;
-            u &= ~(u >> 31);
-            if (u >= width) u = width - 1;
-
-            int offsety = refraction(dy, wave, map) >> 16;
-            int v = (height - h) + offsety;
-            v &= ~(v >> 31);
-            if (v >= height) v = height - 1;
-
-            vtx->s = u * fw;
-            vtx->t = v * fh;
-            vtx->z = dy * fy;
-            vtx --;
-
-            w -= 1;
-            current += 1;
-            wave = nextWave;
+                for (ct = 0; ct < gMaxDrops; ct++) {
+                    float dx = d->x - x;
+                    float dy = d->y - y;
+                    float dist = sqrtf(dx*dx + dy*dy);
+                    if (dist < d->spread && d->amp) {
+                        float a = d->amp * d->invSpread;
+                        a *= dist * d->invSpread;
+                        z += sinf(d->spread - dist) * a;
+                    }
+                    d++;
+                }
+                vtx->s = (float)x * fw;
+                vtx->t = (float)y * fh;
+                vtx->z = z;
+                vtx ++;
+            }
         }
-        h -= 1;
-        current += 2;
+        for (ct = 0; ct < gMaxDrops; ct++) {
+            gDrops[ct].spread += 1;
+            gDrops[ct].invSpread = 1 / gDrops[ct].spread;
+            gDrops[ct].amp = maxf(gDrops[ct].amp - 0.01f, 0);
+        }
     }
 
     // Compute the normals for lighting
@@ -239,6 +157,8 @@
             v->nx = n3.x;
             v->ny = n3.y;
             v->nz = -n3.z;
+            v->s += v->nx * 0.005;
+            v->t += v->ny * 0.005;
             v += 1;
 
             // reset Z
@@ -279,8 +199,8 @@
     x2 -= x;
     y1 -= y;
     y2 -= y;
-    
-    float matrix[16];    
+
+    float matrix[16];
 
     if (a > 0.0f) {
         color(0.0f, 0.0f, 0.0f, 0.15f);
@@ -395,7 +315,7 @@
 }
 
 void drawSky() {
-    color(1.0f, 1.0f, 1.0f, 0.8f);
+    color(1.0f, 1.0f, 1.0f, 0.5f);
 
     bindProgramFragment(NAMED_PFSky);
     bindProgramFragmentStore(NAMED_PFSLeaf);
@@ -465,24 +385,28 @@
 
 int main(int index) {
     if (Drop->dropX != -1) {
-        drop(Drop->dropX, Drop->dropY, DROP_RADIUS);
+        drop(Drop->dropX, Drop->dropY, 1);
         Drop->dropX = -1;
         Drop->dropY = -1;
     }
-    
-    if (State->isPreview) {
-        int now = uptimeMillis();
-        if (now - lastDrop > 2000) {
-            float x = randf(State->meshWidth);
-            float y = randf(State->meshHeight);
 
-            drop(x, y, DROP_RADIUS);
+    int ct;
+    float amp = 0;
+    for (ct = 0; ct < gMaxDrops; ct++) {
+        amp += gDrops[ct].amp;
+    }
 
-            lastDrop = now;
+    if (State->isPreview || (amp < 0.2f)) {
+        float x = randf(State->meshWidth);
+        float y = randf(State->meshHeight);
+
+        if (State->isPreview) {
+            drop(x, y, 1.f);
+        } else {
+            drop(x, y, 0.2f);
         }
     }
 
-    updateRipples();
     generateRipples();
     updateSimpleMesh(NAMED_WaterMesh);
 
diff --git a/src/com/android/wallpaper/fall/FallRS.java b/src/com/android/wallpaper/fall/FallRS.java
index f68262e..46c72ea 100644
--- a/src/com/android/wallpaper/fall/FallRS.java
+++ b/src/com/android/wallpaper/fall/FallRS.java
@@ -53,7 +53,6 @@
     private static final int RSID_TEXTURE_SKY = 2;
 
     private static final int RSID_RIPPLE_MAP = 1;
-    private static final int RSID_REFRACTION_MAP = 2;
     private static final int RSID_LEAVES = 3;
     private static final int RSID_DROP = 4;
 
@@ -94,7 +93,6 @@
     private WorldState mWorldState;
 
     private Allocation mRippleMap;
-    private Allocation mRefractionMap;
 
     private Allocation mLeaves;
     private Type mLeavesType;
@@ -143,7 +141,6 @@
 
         script.bindAllocation(mState, RSID_STATE);
         script.bindAllocation(mRippleMap, RSID_RIPPLE_MAP);
-        script.bindAllocation(mRefractionMap, RSID_REFRACTION_MAP);
         script.bindAllocation(mLeaves, RSID_LEAVES);
         script.bindAllocation(mDropState, RSID_DROP);
 
@@ -214,7 +211,6 @@
 
         createState(rippleMapSize);
         createRippleMap(rippleMapSize);
-        createRefractionMap();
         createLeaves();
     }
 
@@ -223,17 +219,6 @@
         mLeaves = Allocation.createTyped(mRS, mLeavesType);
     }
 
-    private void createRefractionMap() {
-        final int[] refractionMap = new int[513];
-        float ir = 1.0f / 1.333f;
-        for (int i = 0; i < refractionMap.length; i++) {
-            float d = (float) Math.tan(Math.asin(Math.sin(Math.atan(i * (1.0f / 256.0f))) * ir));
-            refractionMap[i] = (int) Math.floor(d * (1 << 16) + 0.5f);
-        }
-        mRefractionMap = Allocation.createSized(mRS, USER_I32(mRS), refractionMap.length);
-        mRefractionMap.data(refractionMap);
-    }
-
     private void createRippleMap(int rippleMapSize) {
         final int[] rippleMap = new int[rippleMapSize * 2];
         mRippleMap = Allocation.createSized(mRS, USER_I32(mRS), rippleMap.length);
diff --git a/src/com/android/wallpaper/fall/FallView.java b/src/com/android/wallpaper/fall/FallView.java
index 871ca16..25c7efb 100644
--- a/src/com/android/wallpaper/fall/FallView.java
+++ b/src/com/android/wallpaper/fall/FallView.java
@@ -45,7 +45,7 @@
     public boolean onTouchEvent(MotionEvent event) {
         switch (event.getAction()) {
             case MotionEvent.ACTION_DOWN:
-            case MotionEvent.ACTION_MOVE:
+            //case MotionEvent.ACTION_MOVE:
                 mRender.addDrop(event.getX(), event.getY());
                 try {
                     Thread.sleep(16);