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,