Add swaying effect to the grass.
diff --git a/libs/rs/Android.mk b/libs/rs/Android.mk
index 6b11a25..375cf6c 100644
--- a/libs/rs/Android.mk
+++ b/libs/rs/Android.mk
@@ -90,6 +90,7 @@
 	rsObjectBase.cpp \
 	rsMatrix.cpp \
         rsMesh.cpp \
+	rsNoise.cpp \
 	rsProgram.cpp \
 	rsProgramFragment.cpp \
 	rsProgramFragmentStore.cpp \
diff --git a/libs/rs/java/Grass/res/raw/grass.c b/libs/rs/java/Grass/res/raw/grass.c
index f6dae81..83c8fed 100644
--- a/libs/rs/java/Grass/res/raw/grass.c
+++ b/libs/rs/java/Grass/res/raw/grass.c
@@ -17,12 +17,11 @@
 #pragma stateFragment(PFBackground)
 #pragma stateFragmentStore(PFSBackground)
 
-#define WVGA_PORTRAIT_WIDTH 480.0f
-#define WVGA_PORTRAIT_HEIGHT 762.0f
-
 #define RSID_STATE 0
 #define RSID_FRAME_COUNT 0
 #define RSID_BLADES_COUNT 1
+#define RSID_WIDTH 2
+#define RSID_HEIGHT 3
 
 #define RSID_TEXTURES 1
 #define RSID_SKY_TEXTURE_NIGHT 0
@@ -33,7 +32,7 @@
 
 #define RSID_BLADES 2
 #define BLADE_STRUCT_FIELDS_COUNT 12
-#define BLADE_STRUCT_DEGREE 0
+#define BLADE_STRUCT_ANGLE 0
 #define BLADE_STRUCT_SIZE 1
 #define BLADE_STRUCT_XPOS 2
 #define BLADE_STRUCT_YPOS 3
@@ -46,7 +45,9 @@
 #define BLADE_STRUCT_S 10
 #define BLADE_STRUCT_B 11
 
-#define TESSELATION 4.0f
+#define TESSELATION 2.0f
+
+#define MAX_BEND 0.09f
 
 #define MIDNIGHT 0.0f
 #define MORNING 0.375f
@@ -70,31 +71,30 @@
     color(1.0f, 1.0f, 1.0f, a);
 }
 
-void drawNight() {
+void drawNight(int width, int height) {
     bindTexture(NAMED_PFBackground, 0, loadI32(RSID_TEXTURES, RSID_SKY_TEXTURE_NIGHT));
-    // NOTE: Hacky way to draw the night sky
-    drawRect(WVGA_PORTRAIT_WIDTH - 512.0f, -32.0f, WVGA_PORTRAIT_WIDTH, 1024.0f - 32.0f, 0.0f);
+    drawRect(width - 512.0f, -32.0f, width, 1024.0f - 32.0f, 0.0f);
 }
 
-void drawSunrise() {
+void drawSunrise(int width, int height) {
     bindTexture(NAMED_PFBackground, 0, loadI32(RSID_TEXTURES, RSID_SKY_TEXTURE_SUNRISE));
-    drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
+    drawRect(0.0f, 0.0f, width, height, 0.0f);
 }
 
-void drawNoon() {
+void drawNoon(int width, int height) {
     bindTexture(NAMED_PFBackground, 0, loadI32(RSID_TEXTURES, RSID_SKY_TEXTURE_NOON));
-    drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
+    drawRect(0.0f, 0.0f, width, height, 0.0f);
 }
 
-void drawSunset() {
+void drawSunset(int width, int height) {
     bindTexture(NAMED_PFBackground, 0, loadI32(RSID_TEXTURES, RSID_SKY_TEXTURE_SUNSET));
-    drawRect(0.0f, 0.0f, WVGA_PORTRAIT_WIDTH, WVGA_PORTRAIT_HEIGHT, 0.0f);
+    drawRect(0.0f, 0.0f, width, height, 0.0f);
 }
 
-void drawBlade(int index, float now) {
+void drawBlade(int index, float now, int frameCount) {
     float offset = loadF(RSID_BLADES, index + BLADE_STRUCT_OFFSET);
     float scale = loadF(RSID_BLADES, index + BLADE_STRUCT_SCALE);
-    float degree = loadF(RSID_BLADES, index + BLADE_STRUCT_DEGREE);
+    float angle = loadF(RSID_BLADES, index + BLADE_STRUCT_ANGLE);
     float hardness = loadF(RSID_BLADES, index + BLADE_STRUCT_HARDNESS);
     
     float xpos = loadF(RSID_BLADES, index + BLADE_STRUCT_XPOS);
@@ -124,38 +124,43 @@
 
     hsb(h, s, lerpf(0, b, newB), 1.0f);
 
-    float targetDegree = 0.0f; // TODO Compute
-    degree += (targetDegree - degree) * 0.3f;
+    float newAngle = turbulencef2(xpos * 0.006f, frameCount * 0.006f, 4.0f) - 0.5f;
+    newAngle /= 2.0f;
+    angle = clampf(angle + (newAngle + offset - angle) * 0.15f, -MAX_BEND, MAX_BEND);
 
-    float angle = PI / 2.0f;
+    float currentAngle = PI / 2.0f;
 
-    float currentX = xpos;
-    float currentY = ypos;
+    float bottomX = xpos;
+    float bottomY = ypos;
 
     int i = size * TESSELATION;
     float lx = lengthX / TESSELATION;
     float ly = lengthY / TESSELATION;
-    float ss = 2.0f / i + scale / TESSELATION;
-    float sh = 0.7f / TESSELATION;
+    float ss = 4.0f / i + scale / TESSELATION;
+    float sh = 0.5f / TESSELATION;
+    float d = angle * hardness / TESSELATION;
 
     for ( ; i > 0; i--) {
-        float nextX = currentX - cosf(angle) * size * lx;
-        float nextY = currentY - sinf(angle) * size * ly;
-        angle += degree * hardness;
+        float topX = bottomX - cosf(currentAngle) * size * lx;
+        float topY = bottomY - sinf(currentAngle) * size * ly;
+        currentAngle += d;
 
-        drawQuad(nextX + (i - 1) * ss, nextY, 0.0f,
-                 nextX - (i - 1) * ss, nextY, 0.0f,
-                 currentX - i * ss, currentY + sh, 0.0f,
-                 currentX + i * ss, currentY + sh, 0.0f);
+        float spi = (i - 1) * ss;
+        float si = i * ss;
 
-        currentX = nextX;
-        currentY = nextY;
+        drawQuad(topX + spi, topY, 0.0f,
+                 topX - spi, topY, 0.0f,
+                 bottomX - si, bottomY + sh, 0.0f,
+                 bottomX + si, bottomY + sh, 0.0f);
+
+        bottomX = topX;
+        bottomY = topY;
     }
-    
-    storeF(RSID_BLADES, index + BLADE_STRUCT_DEGREE, degree);
+
+    storeF(RSID_BLADES, index + BLADE_STRUCT_ANGLE, angle);
 }
 
-void drawBlades(float now) {
+void drawBlades(float now, int frameCount) {
     // For anti-aliasing
     bindProgramFragmentStore(NAMED_PFSGrass);
     bindProgramFragment(NAMED_PFGrass);
@@ -166,40 +171,37 @@
 
     int i = 0;
     for ( ; i < count; i += BLADE_STRUCT_FIELDS_COUNT) {
-        drawBlade(i, now);
+        drawBlade(i, now, frameCount);
     }
 }
 
 int main(int launchID) {
+    int width = loadI32(RSID_STATE, RSID_WIDTH);
+    int height = loadI32(RSID_STATE, RSID_HEIGHT);
+
     int frameCount = loadI32(RSID_STATE, RSID_FRAME_COUNT);
     float now = time(frameCount);
     alpha(1.0f);
 
     if (now >= MIDNIGHT && now < MORNING) {
-        drawNight();
+        drawNight(width, height);
         alpha(normf(MIDNIGHT, MORNING, now));
-        drawSunrise();
-    }
-    
-    if (now >= MORNING && now < AFTERNOON) {
-        drawSunrise();
+        drawSunrise(width, height);
+    } else if (now >= MORNING && now < AFTERNOON) {
+        drawSunrise(width, height);
         alpha(normf(MORNING, AFTERNOON, now));
-        drawNoon();
-    }
-
-    if (now >= AFTERNOON && now < DUSK) {
-        drawNoon();
+        drawNoon(width, height);
+    } else if (now >= AFTERNOON && now < DUSK) {
+        drawNoon(width, height);
         alpha(normf(AFTERNOON, DUSK, now));
-        drawSunset();
-    }
-    
-    if (now >= DUSK) {
-        drawNight();
+        drawSunset(width, height);
+    } else if (now >= DUSK) {
+        drawNight(width, height);
         alpha(1.0f - normf(DUSK, 1.0f, now));
-        drawSunset();
+        drawSunset(width, height);
     }
 
-    drawBlades(now);
+    drawBlades(now, frameCount);
 
     frameCount++;
     storeI32(RSID_STATE, RSID_FRAME_COUNT, frameCount);
diff --git a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
index 2511150..7092133 100644
--- a/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
+++ b/libs/rs/java/Grass/src/com/android/grass/rs/GrassRS.java
@@ -39,6 +39,8 @@
     private static final int RSID_STATE = 0;
     private static final int RSID_STATE_FRAMECOUNT = 0;
     private static final int RSID_STATE_BLADES_COUNT = 1;
+    private static final int RSID_STATE_WIDTH = 2;
+    private static final int RSID_STATE_HEIGHT = 3;
 
     private static final int RSID_SKY_TEXTURES = 1;
     private static final int SKY_TEXTURES_COUNT = 5;
@@ -46,7 +48,7 @@
     private static final int RSID_BLADES = 2;
     private static final int BLADES_COUNT = 100;
     private static final int BLADE_STRUCT_FIELDS_COUNT = 12;
-    private static final int BLADE_STRUCT_DEGREE = 0;
+    private static final int BLADE_STRUCT_ANGLE = 0;
     private static final int BLADE_STRUCT_SIZE = 1;
     private static final int BLADE_STRUCT_XPOS = 2;
     private static final int BLADE_STRUCT_YPOS = 3;
@@ -129,10 +131,12 @@
     }
 
     private void createScriptStructures() {
-        final int[] data = new int[2];
+        final int[] data = new int[4];
         mState = Allocation.createSized(mRS, USER_I32, data.length);
         data[RSID_STATE_FRAMECOUNT] = 0;
         data[RSID_STATE_BLADES_COUNT] = BLADES_COUNT;
+        data[RSID_STATE_WIDTH] = mWidth;
+        data[RSID_STATE_HEIGHT] = mHeight;
         mState.data(data);
 
         final float[] blades = new float[BLADES_COUNT * BLADE_STRUCT_FIELDS_COUNT];
@@ -145,7 +149,7 @@
 
     private void createBlade(float[] blades, int index) {
         //noinspection PointlessArithmeticExpression
-        blades[index + BLADE_STRUCT_DEGREE] = 0.0f;
+        blades[index + BLADE_STRUCT_ANGLE] = 0.0f;
         blades[index + BLADE_STRUCT_SIZE] = random(4.0f) + 4.0f;
         blades[index + BLADE_STRUCT_XPOS] = random(mWidth);
         blades[index + BLADE_STRUCT_YPOS] = mHeight;
diff --git a/libs/rs/rsNoise.cpp b/libs/rs/rsNoise.cpp
new file mode 100644
index 0000000..764dc1a
--- /dev/null
+++ b/libs/rs/rsNoise.cpp
@@ -0,0 +1,256 @@
+/*
+ * This implementation of the noise functions was ported from the Java
+ * implementation by Jerry Huxtable (http://www.jhlabs.com) under
+ * Apache License 2.0 (see http://jhlabs.com/ip/filters/download.html)
+ *
+ * Original header:
+ *
+ * Copyright 2006 Jerry Huxtable
+ *
+ * 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.
+ */
+
+#include "rsNoise.h"
+
+#include <math.h>
+#include <stdlib.h>
+#include <time.h>
+
+namespace android {
+namespace renderscript {
+
+#define B 0x100
+#define BM 0xff
+#define N 0x1000
+
+static int p[B + B + 2];
+static float g3[B + B + 2][3];
+static float g2[B + B + 2][2];
+static float g1[B + B + 2];
+static bool noise_start = true;
+
+#define lerpf(start, stop, amount) start + (stop - start) * amount
+
+static inline float noise_sCurve(float t)
+{
+    return t * t * (3.0f - 2.0f * t);
+}
+
+inline void SC_normalizef2(float v[])
+{
+    float s = (float)sqrtf(v[0] * v[0] + v[1] * v[1]);
+    v[0] = v[0] / s;
+    v[1] = v[1] / s;
+}
+
+inline void SC_normalizef3(float v[])
+{
+    float s = (float)sqrtf(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;
+}
+
+static void noise_init()
+{
+    int i, j, k;
+    
+    for (i = 0; i < B; i++) {
+        p[i] = i;
+        
+        g1[i] = (float)((rand() % (B + B)) - B) / B;
+        
+        for (j = 0; j < 2; j++)
+            g2[i][j] = (float)((rand() % (B + B)) - B) / B;
+        SC_normalizef2(g2[i]);
+        
+        for (j = 0; j < 3; j++)
+            g3[i][j] = (float)((rand() % (B + B)) - B) / B;
+        SC_normalizef3(g3[i]);
+    }
+    
+    for (i = B-1; i >= 0; i--) {
+        k = p[i];
+        p[i] = p[j = rand() % B];
+        p[j] = k;
+    }
+    
+    for (i = 0; i < B + 2; i++) {
+        p[B + i] = p[i];
+        g1[B + i] = g1[i];
+        for (j = 0; j < 2; j++)
+            g2[B + i][j] = g2[i][j];
+        for (j = 0; j < 3; j++)
+            g3[B + i][j] = g3[i][j];
+    }
+}
+
+float SC_noisef(float x)
+{
+    srand(time(NULL));
+    int bx0, bx1;
+    float rx0, rx1, sx, t, u, v;
+    
+    if (noise_start) {
+        noise_start = false;
+        noise_init();
+    }
+    
+    t = x + N;
+    bx0 = ((int)t) & BM;
+    bx1 = (bx0+1) & BM;
+    rx0 = t - (int)t;
+    rx1 = rx0 - 1.0f;
+    
+    sx = noise_sCurve(rx0);
+    
+    u = rx0 * g1[p[bx0]];
+    v = rx1 * g1[p[bx1]];
+    return 2.3f * lerpf(u, v, sx);
+}
+
+float SC_noisef2(float x, float y)
+{
+    srand(time(NULL));
+    int bx0, bx1, by0, by1, b00, b10, b01, b11;
+    float rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v;
+    float *q;
+    int i, j;
+    
+    if (noise_start) {
+        noise_start = false;
+        noise_init();
+    }
+    
+    t = x + N;
+    bx0 = ((int)t) & BM;
+    bx1 = (bx0+1) & BM;
+    rx0 = t - (int)t;
+    rx1 = rx0 - 1.0f;
+	
+    t = y + N;
+    by0 = ((int)t) & BM;
+    by1 = (by0+1) & BM;
+    ry0 = t - (int)t;
+    ry1 = ry0 - 1.0f;
+	
+    i = p[bx0];
+    j = p[bx1];
+    
+    b00 = p[i + by0];
+    b10 = p[j + by0];
+    b01 = p[i + by1];
+    b11 = p[j + by1];
+    
+    sx = noise_sCurve(rx0);
+    sy = noise_sCurve(ry0);
+    
+    q = g2[b00]; u = rx0 * q[0] + ry0 * q[1];
+    q = g2[b10]; v = rx1 * q[0] + ry0 * q[1];
+    a = lerpf(u, v, sx);
+    
+    q = g2[b01]; u = rx0 * q[0] + ry1 * q[1];
+    q = g2[b11]; v = rx1 * q[0] + ry1 * q[1];
+    b = lerpf(u, v, sx);
+    
+    return 1.5f*lerpf(a, b, sy);
+}
+
+float SC_noisef3(float x, float y, float z)
+{
+    srand(time(NULL));
+    int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+    float rx0, rx1, ry0, ry1, rz0, rz1, sy, sz, a, b, c, d, t, u, v;
+    float *q;
+    int i, j;
+    
+    if (noise_start) {
+        noise_start = false;
+        noise_init();
+    }
+    
+    t = x + N;
+    bx0 = ((int)t) & BM;
+    bx1 = (bx0+1) & BM;
+    rx0 = t - (int)t;
+    rx1 = rx0 - 1.0f;
+    
+    t = y + N;
+    by0 = ((int)t) & BM;
+    by1 = (by0+1) & BM;
+    ry0 = t - (int)t;
+    ry1 = ry0 - 1.0f;
+	
+    t = z + N;
+    bz0 = ((int)t) & BM;
+    bz1 = (bz0+1) & BM;
+    rz0 = t - (int)t;
+    rz1 = rz0 - 1.0f;
+	
+    i = p[bx0];
+    j = p[bx1];
+    
+    b00 = p[i + by0];
+    b10 = p[j + by0];
+    b01 = p[i + by1];
+    b11 = p[j + by1];
+    
+    t  = noise_sCurve(rx0);
+    sy = noise_sCurve(ry0);
+    sz = noise_sCurve(rz0);
+    
+    q = g3[b00 + bz0]; u = rx0 * q[0] + ry0 * q[1] + rz0 * q[2];
+    q = g3[b10 + bz0]; v = rx1 * q[0] + ry0 * q[1] + rz0 * q[2];
+    a = lerpf(u, v, t);
+    
+    q = g3[b01 + bz0]; u = rx0 * q[0] + ry1 * q[1] + rz0 * q[2];
+    q = g3[b11 + bz0]; v = rx1 * q[0] + ry1 * q[1] + rz0 * q[2];
+    b = lerpf(u, v, t);
+    
+    c = lerpf(a, b, sy);
+    
+    q = g3[b00 + bz1]; u = rx0 * q[0] + ry0 * q[1] + rz1 * q[2];
+    q = g3[b10 + bz1]; v = rx1 * q[0] + ry0 * q[1] + rz1 * q[2];
+    a = lerpf(u, v, t);
+    
+    q = g3[b01 + bz1]; u = rx0 * q[0] + ry1 * q[1] + rz1 * q[2];
+    q = g3[b11 + bz1]; v = rx1 * q[0] + ry1 * q[1] + rz1 * q[2];
+    b = lerpf(u, v, t);
+    
+    d = lerpf(a, b, sy);
+    
+    return 1.5f*lerpf(c, d, sz);
+}
+
+float SC_turbulencef2(float x, float y, float octaves)
+{
+    srand(time(NULL));
+    float t = 0.0f;
+    
+    for (float f = 1.0f; f <= octaves; f *= 2)
+        t += fabs(SC_noisef2(f * x, f * y)) / f;
+    return t;
+}
+
+float SC_turbulencef3(float x, float y, float z, float octaves)
+{
+    srand(time(NULL));
+    float t = 0.0f;
+    
+    for (float f = 1.0f; f <= octaves; f *= 2)
+        t += fabs(SC_noisef3(f * x, f * y, f * z)) / f;
+    return t;
+}
+
+}
+}
\ No newline at end of file
diff --git a/libs/rs/rsNoise.h b/libs/rs/rsNoise.h
new file mode 100644
index 0000000..9040751
--- /dev/null
+++ b/libs/rs/rsNoise.h
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+#ifndef ANDROID_RS_NOISE_H
+#define ANDROID_RS_NOISE_H
+
+// ---------------------------------------------------------------------------
+namespace android {
+namespace renderscript {
+
+void SC_normalizef2(float v[]);
+void SC_normalizef3(float v[]);
+float SC_noisef(float x);
+float SC_noisef2(float x, float y);
+float SC_noisef3(float x, float y, float z);
+float SC_turbulencef2(float x, float y, float octaves);
+float SC_turbulencef3(float x, float y, float z, float octaves);
+
+}
+}
+
+#endif
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index e4979ea..561cde6 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -17,6 +17,7 @@
 #include "rsContext.h"
 #include "rsScriptC.h"
 #include "rsMatrix.h"
+#include "rsNoise.h"
 
 #include "acc/acc.h"
 #include "utils/String8.h"
@@ -748,6 +749,16 @@
         "float", "(float, float, float)" },
     { "mapf", (void *)&SC_mapf,
         "float", "(float, float, float, float, float)" },
+    { "noisef", (void *)&SC_noisef,
+        "float", "(float)" },
+    { "noisef2", (void *)&SC_noisef2,
+        "float", "(float, float)" },
+    { "noisef3", (void *)&SC_noisef3,
+        "float", "(float, float, float)" },
+    { "turbulencef2", (void *)&SC_turbulencef2,
+        "float", "(float, float, float)" },
+    { "turbulencef3", (void *)&SC_turbulencef3,
+        "float", "(float, float, float, float)" },
 
     // time
     { "second", (void *)&SC_second,