Make the laves follow the ripples
diff --git a/libs/rs/java/Fall/res/raw/fall.c b/libs/rs/java/Fall/res/raw/fall.c
index 56aa506..b18c124 100644
--- a/libs/rs/java/Fall/res/raw/fall.c
+++ b/libs/rs/java/Fall/res/raw/fall.c
@@ -34,6 +34,10 @@
#define RSID_REFRACTION_MAP 2
#define RSID_LEAVES 3
+#define RSID_GL_STATE 4
+#define RSID_GL_WIDTH 0
+#define RSID_GL_HEIGHT 1
+
#define LEAF_STRUCT_FIELDS_COUNT 11
#define LEAF_STRUCT_X 0
#define LEAF_STRUCT_Y 1
@@ -47,7 +51,9 @@
#define LEAF_STRUCT_DELTAX 9
#define LEAF_STRUCT_DELTAY 10
-#define LEAF_SIZE 0.35f
+#define LEAVES_TEXTURES_COUNT 4
+
+#define LEAF_SIZE 0.55f
#define REFRACTION 1.333f
#define DAMP 3
@@ -261,7 +267,7 @@
vertices[(yOffset + x) * 8 + 2] = -n3z;
// reset Z
- vertices[(yOffset + x) * 8 + 7] = 0.0f;
+ //vertices[(yOffset + x) * 8 + 7] = 0.0f;
}
}
}
@@ -271,7 +277,7 @@
int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);
float *vertices = loadTriangleMeshVerticesF(NAMED_mesh);
-
+
bindProgramVertex(NAMED_PVLines);
color(1.0f, 0.0f, 0.0f, 1.0f);
@@ -280,18 +286,50 @@
int yOffset = y * width;
int x = 0;
for ( ; x < width; x++) {
- float vx = vertices[(yOffset + x) * 8 + 5];
- float vy = vertices[(yOffset + x) * 8 + 6];
- float vz = vertices[(yOffset + x) * 8 + 7];
- float nx = vertices[(yOffset + x) * 8 + 0];
- float ny = vertices[(yOffset + x) * 8 + 1];
- float nz = vertices[(yOffset + x) * 8 + 2];
+ int offset = (yOffset + x) * 8;
+ 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 / 10.0f, vy + ny / 10.0f, vz + nz / 10.0f);
}
}
}
-void drawLeaf(int index, int frameCount) {
+float averageZ(float x1, float x2, float y1, float y2, float* vertices,
+ int meshWidth, int meshHeight, float glWidth, float glHeight) {
+
+ x1 = ((x1 + glWidth / 2.0f) / glWidth) * meshWidth;
+ x2 = ((x2 + glWidth / 2.0f) / glWidth) * meshWidth;
+ y1 = ((y1 + glHeight / 2.0f) / glHeight) * meshHeight;
+ y2 = ((y2 + glHeight / 2.0f) / glHeight) * meshHeight;
+
+ int quadX1 = clamp(x1, 0, meshWidth);
+ int quadX2 = clamp(x2, 0, meshWidth);
+ int quadY1 = clamp(y1, 0, meshHeight);
+ int quadY2 = clamp(y2, 0, meshHeight);
+
+ float z = 0.0f;
+ int vertexCount = 0;
+
+ int y = quadY1;
+ for ( ; y < quadY2; y++) {
+ int x = quadX1;
+ int yOffset = y * meshWidth;
+ for ( ; x < quadX2; x++) {
+ z += vertices[(yOffset + x) * 8 + 7];
+ vertexCount++;
+ }
+ }
+
+ return 75.0f * z / vertexCount;
+}
+
+void drawLeaf(int index, int frameCount, float* vertices, int meshWidth, int meshHeight,
+ float glWidth, float glHeight) {
+
float *leafStruct = loadArrayF(RSID_LEAVES, index);
float x = leafStruct[LEAF_STRUCT_X];
@@ -305,10 +343,77 @@
float u1 = leafStruct[LEAF_STRUCT_U1];
float u2 = leafStruct[LEAF_STRUCT_U2];
- drawQuadTexCoords(x1, y1, 0.0f, u1, 1.0f,
- x2, y1, 0.0f, u2, 1.0f,
- x2, y2, 0.0f, u2, 0.0f,
- x1, y2, 0.0f, u1, 0.0f);
+ float z1 = 0.0f;
+ float z2 = 0.0f;
+ float z3 = 0.0f;
+ float z4 = 0.0f;
+
+ float a = leafStruct[LEAF_STRUCT_ALTITUDE];
+ float s = leafStruct[LEAF_STRUCT_SCALE];
+ float r = leafStruct[LEAF_STRUCT_ANGLE];
+
+ float tz = 0.0f;
+ if (a > 0.0f) {
+ tz = -a;
+ } else {
+ z1 = averageZ(x1, x, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight);
+ z2 = averageZ(x, x2, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight);
+ z3 = averageZ(x, x2, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight);
+ z4 = averageZ(x1, x, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight);
+ }
+
+ x1 -= x;
+ x2 -= x;
+ y1 -= y;
+ y2 -= y;
+
+ float matrix[16];
+ 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 = leafStruct[LEAF_STRUCT_SPIN];
+ if (a <= 0.0f) {
+ float rippled = leafStruct[LEAF_STRUCT_RIPPLED];
+ if (rippled < 0.0f) {
+ drop(((x + glWidth / 2.0f) / glWidth) * meshWidth,
+ meshHeight - ((y + glHeight / 2.0f) / glHeight) * meshHeight,
+ DROP_RADIUS);
+ spin /= 4.0f;
+ leafStruct[LEAF_STRUCT_SPIN] = spin;
+ leafStruct[LEAF_STRUCT_RIPPLED] = 1.0f;
+ }
+ leafStruct[LEAF_STRUCT_X] = x + leafStruct[LEAF_STRUCT_DELTAX];
+ leafStruct[LEAF_STRUCT_Y] = y + leafStruct[LEAF_STRUCT_DELTAY];
+ r += spin;
+ leafStruct[LEAF_STRUCT_ANGLE] = r;
+ } else {
+ a -= 0.005f;
+ leafStruct[LEAF_STRUCT_ALTITUDE] = a;
+ r += spin * 2.0f;
+ leafStruct[LEAF_STRUCT_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);
+ leafStruct[LEAF_STRUCT_X] = randf2(-1.0f, 1.0f);
+ leafStruct[LEAF_STRUCT_Y] = glHeight / 2.0f + LEAF_SIZE * 2 * randf(1.0f);
+ leafStruct[LEAF_STRUCT_SCALE] = randf2(0.4f, 0.5f);
+ leafStruct[LEAF_STRUCT_SPIN] = degf(randf2(-0.02f, 0.02f)) / 4.0f;
+ leafStruct[LEAF_STRUCT_U1] = sprite / (float) LEAVES_TEXTURES_COUNT;
+ leafStruct[LEAF_STRUCT_U2] = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
+ leafStruct[LEAF_STRUCT_DELTAX] = randf2(-0.02f, 0.02f) / 100.0f;
+ leafStruct[LEAF_STRUCT_DELTAY] = -0.08f * randf2(0.9f, 1.1f) / 100.0f;
+ }
}
void drawLeaves(int frameCount) {
@@ -318,10 +423,16 @@
int leavesCount = loadI32(RSID_STATE, RSID_LEAVES_COUNT);
int count = leavesCount * LEAF_STRUCT_FIELDS_COUNT;
+ int width = loadI32(RSID_STATE, RSID_MESH_WIDTH);
+ int height = loadI32(RSID_STATE, RSID_MESH_HEIGHT);
+ float glWidth = loadF(RSID_GL_STATE, RSID_GL_WIDTH);
+ float glHeight = loadF(RSID_GL_STATE, RSID_GL_HEIGHT);
+
+ float *vertices = loadTriangleMeshVerticesF(NAMED_mesh);
int i = 0;
for ( ; i < count; i += LEAF_STRUCT_FIELDS_COUNT) {
- drawLeaf(i, frameCount);
+ drawLeaf(i, frameCount, vertices, width, height, glWidth, glHeight);
}
}
@@ -343,6 +454,10 @@
updateTriangleMesh(NAMED_mesh);
}
+ float matrix[16];
+ matrixLoadIdentity(matrix);
+ vpLoadModelMatrix(matrix);
+
bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
drawTriangleMesh(NAMED_mesh);
diff --git a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
index 36c7daa..63e6ed9 100644
--- a/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
+++ b/libs/rs/java/Fall/src/com/android/fall/rs/FallRS.java
@@ -54,7 +54,7 @@
private static final int RSID_STATE_DROP_Y = 8;
private static final int RSID_STATE_RUNNING = 9;
private static final int RSID_STATE_LEAVES_COUNT = 10;
-
+
private static final int TEXTURES_COUNT = 2;
private static final int LEAVES_TEXTURES_COUNT = 4;
private static final int RSID_TEXTURE_RIVERBED = 0;
@@ -65,7 +65,7 @@
private static final int RSID_REFRACTION_MAP = 2;
private static final int RSID_LEAVES = 3;
- private static final int LEAVES_COUNT = 8;
+ private static final int LEAVES_COUNT = 14;
private static final int LEAF_STRUCT_FIELDS_COUNT = 11;
private static final int LEAF_STRUCT_X = 0;
private static final int LEAF_STRUCT_Y = 1;
@@ -79,6 +79,10 @@
private static final int LEAF_STRUCT_DELTAX = 9;
private static final int LEAF_STRUCT_DELTAY = 10;
+ private static final int RSID_GL_STATE = 4;
+ private static final int RSID_STATE_GL_WIDTH = 0;
+ private static final int RSID_STATE_GL_HEIGHT = 1;
+
private boolean mIsRunning = true;
private Resources mResources;
@@ -111,6 +115,8 @@
private Allocation mRippleMap;
private Allocation mRefractionMap;
private Allocation mLeaves;
+
+ private Allocation mGlState;
private float mGlHeight;
public FallRS(int width, int height) {
@@ -146,6 +152,7 @@
mLeaves.destroy();
mPfsLeaf.destroy();
mPfLeaf.destroy();
+ mGlState.destroy();
}
@Override
@@ -176,6 +183,7 @@
mScript.bindAllocation(mRippleMap, RSID_RIPPLE_MAP);
mScript.bindAllocation(mRefractionMap, RSID_REFRACTION_MAP);
mScript.bindAllocation(mLeaves, RSID_LEAVES);
+ mScript.bindAllocation(mGlState, RSID_GL_STATE);
mRS.contextBindRootScript(mScript);
}
@@ -199,14 +207,16 @@
}
mGlHeight = 2.0f * height / (float) width;
- final float quadWidth = 2.0f / (float) wResolution;
- final float quadHeight = mGlHeight / (float) hResolution;
+ final float glHeight = mGlHeight;
+ float quadWidth = 2.0f / (float) wResolution;
+ float quadHeight = glHeight / (float) hResolution;
+
wResolution += 2;
hResolution += 2;
for (int y = 0; y <= hResolution; y++) {
- final float yOffset = y * quadHeight - mGlHeight / 2.0f - quadHeight;
+ final float yOffset = y * quadHeight - glHeight / 2.0f - quadHeight;
final float t = 1.0f - y / (float) hResolution;
for (int x = 0; x <= wResolution; x++) {
rs.triangleMeshAddVertex_XYZ_ST_NORM(
@@ -235,6 +245,47 @@
private void createScriptStructures() {
final int rippleMapSize = (mMeshWidth + 2) * (mMeshHeight + 2);
+ createState(rippleMapSize);
+ createGlState();
+ createRippleMap(rippleMapSize);
+ createRefractionMap();
+ createLeaves();
+ }
+
+ private void createLeaves() {
+ final float[] leaves = new float[LEAVES_COUNT * LEAF_STRUCT_FIELDS_COUNT];
+ mLeaves = Allocation.createSized(mRS, USER_FLOAT, leaves.length);
+ for (int i = 0; i < leaves.length; i += LEAF_STRUCT_FIELDS_COUNT) {
+ createLeaf(leaves, i);
+ }
+ mLeaves.data(leaves);
+ }
+
+ 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, refractionMap.length);
+ mRefractionMap.data(refractionMap);
+ }
+
+ private void createRippleMap(int rippleMapSize) {
+ final int[] rippleMap = new int[rippleMapSize * 2];
+ mRippleMap = Allocation.createSized(mRS, USER_I32, rippleMap.length);
+ }
+
+ private void createGlState() {
+ final float[] meshState = new float[2];
+ mGlState = Allocation.createSized(mRS, USER_FLOAT, meshState.length);
+ meshState[RSID_STATE_GL_WIDTH] = 2.0f;
+ meshState[RSID_STATE_GL_HEIGHT] = mGlHeight;
+ mGlState.data(meshState);
+ }
+
+ private void createState(int rippleMapSize) {
final int[] data = new int[11];
mState = Allocation.createSized(mRS, USER_I32, data.length);
data[RSID_STATE_FRAMECOUNT] = 0;
@@ -244,30 +295,11 @@
data[RSID_STATE_MESH_HEIGHT] = mMeshHeight;
data[RSID_STATE_RIPPLE_MAP_SIZE] = rippleMapSize;
data[RSID_STATE_RIPPLE_INDEX] = 0;
- data[RSID_STATE_DROP_X] = mMeshWidth / 2;
- data[RSID_STATE_DROP_Y] = mMeshHeight / 2;
+ data[RSID_STATE_DROP_X] = -1;
+ data[RSID_STATE_DROP_Y] = -1;
data[RSID_STATE_RUNNING] = 1;
data[RSID_STATE_LEAVES_COUNT] = LEAVES_COUNT;
mState.data(data);
-
- final int[] rippleMap = new int[rippleMapSize * 2];
- mRippleMap = Allocation.createSized(mRS, USER_I32, rippleMap.length);
-
- 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, refractionMap.length);
- mRefractionMap.data(refractionMap);
-
- final float[] leaves = new float[LEAVES_COUNT * LEAF_STRUCT_FIELDS_COUNT];
- mLeaves = Allocation.createSized(mRS, USER_FLOAT, leaves.length);
- for (int i = 0; i < leaves.length; i += LEAF_STRUCT_FIELDS_COUNT) {
- createLeaf(leaves, i);
- }
- mLeaves.data(leaves);
}
private void createLeaf(float[] leaves, int index) {
@@ -275,15 +307,15 @@
//noinspection PointlessArithmeticExpression
leaves[index + LEAF_STRUCT_X] = random(-1.0f, 1.0f);
leaves[index + LEAF_STRUCT_Y] = random(-mGlHeight / 2.0f, mGlHeight / 2.0f);
- leaves[index + LEAF_STRUCT_SCALE] = random(0.3f, 0.4f);
- leaves[index + LEAF_STRUCT_ANGLE] = random(0.0f, (float) (Math.PI * 2.0));
- leaves[index + LEAF_STRUCT_SPIN] = random(-0.02f, 0.02f);
+ leaves[index + LEAF_STRUCT_SCALE] = random(0.4f, 0.5f);
+ leaves[index + LEAF_STRUCT_ANGLE] = random(0.0f, 360.0f);
+ leaves[index + LEAF_STRUCT_SPIN] = degrees(random(-0.02f, 0.02f)) / 4.0f;
leaves[index + LEAF_STRUCT_U1] = sprite / (float) LEAVES_TEXTURES_COUNT;
leaves[index + LEAF_STRUCT_U2] = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
- leaves[index + LEAF_STRUCT_ALTITUDE] = 0.2f;
- leaves[index + LEAF_STRUCT_RIPPLED] = -1.0f;
+ leaves[index + LEAF_STRUCT_ALTITUDE] = -1.0f;
+ leaves[index + LEAF_STRUCT_RIPPLED] = 1.0f;
leaves[index + LEAF_STRUCT_DELTAX] = random(-0.02f, 0.02f) / 100.0f;
- leaves[index + LEAF_STRUCT_DELTAY] = 0.08f * random(0.9f, 1.1f) / 100.0f;
+ leaves[index + LEAF_STRUCT_DELTAY] = -0.08f * random(0.9f, 1.1f) / 100.0f;
}
private void loadTextures() {
diff --git a/libs/rs/rsScriptC_Lib.cpp b/libs/rs/rsScriptC_Lib.cpp
index 1ef6b4e..b46e1cf 100644
--- a/libs/rs/rsScriptC_Lib.cpp
+++ b/libs/rs/rsScriptC_Lib.cpp
@@ -188,6 +188,11 @@
return amount < low ? low : (amount > high ? high : amount);
}
+static int SC_clamp(int amount, int low, int high)
+{
+ return amount < low ? low : (amount > high ? high : amount);
+}
+
static float SC_maxf(float a, float b)
{
return a > b ? a : b;
@@ -826,6 +831,8 @@
"void", "(int)" },
// math
+ { "modf", (void *)&fmod,
+ "float", "(float, float)" },
{ "abs", (void *)&abs,
"int", "(int)" },
{ "absf", (void *)&fabs,
@@ -870,6 +877,8 @@
"int", "(int)" },
{ "sqrf", (void *)&SC_sqrf,
"float", "(float)" },
+ { "clamp", (void *)&SC_clamp,
+ "int", "(int, int, int)" },
{ "clampf", (void *)&SC_clampf,
"float", "(float, float, float)" },
{ "distf2", (void *)&SC_distf2,