</activity>
+ <activity
+ android:label="@string/wallpaper_fall"
+ android:name="com.android.wallpaper.fall.Fall"
+ android:theme="@android:style/Theme.NoTitleBar">
+
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+
+ </activity>
+
<service
android:label="@string/wallpaper_grass"
android:name="com.android.wallpaper.grass.GrassWallpaper"
<meta-data android:name="android.service.wallpaper" android:resource="@xml/galaxy" />
</service>
+ <service
+ android:label="@string/wallpaper_fall"
+ android:name="com.android.wallpaper.fall.FallWallpaper"
+ android:permission="android.permission.BIND_WALLPAPER">
+ <intent-filter>
+ <action android:name="android.service.wallpaper.WallpaperService" />
+ </intent-filter>
+ <meta-data android:name="android.service.wallpaper" android:resource="@xml/fall" />
+ </service>
+
<activity
android:label="@string/clock_settings"
android:name="com.android.wallpaper.polarclock.PolarClockSettings"
--- /dev/null
+// 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 stateFragmentStore(PFSBackground)
+
+#define RSID_STATE 0
+#define RSID_RIPPLE_MAP 1
+#define RSID_REFRACTION_MAP 2
+#define RSID_LEAVES 3
+#define RSID_DROP 4
+
+#define LEAF_STRUCT_FIELDS_COUNT 11
+#define LEAF_STRUCT_X 0
+#define LEAF_STRUCT_Y 1
+#define LEAF_STRUCT_SCALE 2
+#define LEAF_STRUCT_ANGLE 3
+#define LEAF_STRUCT_SPIN 4
+#define LEAF_STRUCT_U1 5
+#define LEAF_STRUCT_U2 6
+#define LEAF_STRUCT_ALTITUDE 7
+#define LEAF_STRUCT_RIPPLED 8
+#define LEAF_STRUCT_DELTAX 9
+#define LEAF_STRUCT_DELTAY 10
+
+#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 g_SkyOffsetX;
+float g_SkyOffsetY;
+
+struct vert_s {
+ float nx;
+ float ny;
+ float nz;
+ float s;
+ float t;
+ float x;
+ float y;
+ float z;
+};
+
+int offset(int x, int y, int width) {
+ return x + 1 + (y + 1) * (width + 2);
+}
+
+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);
+
+ storeI32(RSID_STATE, OFFSETOF_WorldState_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;
+ droplet -= (droplet >> DAMP);
+ *next = droplet;
+ 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 = loadI32(RSID_STATE, OFFSETOF_WorldState_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 = loadTriangleMeshVerticesF(NAMED_WaterMesh);
+ struct vert_s *vert = (struct vert_s *)vertices;
+
+ float fw = 1.f / width;
+ float fh = 1.f / 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;
+ vtx --;
+
+ w -= 1;
+ current += 1;
+ wave = nextWave;
+ }
+ h -= 1;
+ current += 2;
+ }
+
+ // Compute the normals for lighting
+ int y = 0;
+ for ( ; y < height; y += 1) {
+ int x = 0;
+ int yOffset = y * width;
+ struct vert_s *v = vert;
+
+ for ( ; x < width; 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 += 1;
+
+ // reset Z
+ //vertices[(yOffset + x) << 3 + 7] = 0.0f;
+ }
+ }
+}
+
+float averageZ(float x1, float x2, float y1, float y2, float* vertices,
+ int meshWidth, int meshHeight, float glWidth, float glHeight) {
+
+ x1 = ((x1 + glWidth * 0.5f) / glWidth) * meshWidth;
+ x2 = ((x2 + glWidth * 0.5f) / glWidth) * meshWidth;
+ y1 = ((y1 + glHeight * 0.5f) / glHeight) * meshHeight;
+ y2 = ((y2 + glHeight * 0.5f) / 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 += 1) {
+ int x = quadX1;
+ int yOffset = y * meshWidth;
+ for ( ; x < quadX2; x += 1) {
+ z += vertices[(yOffset + x) << 3 + 7];
+ vertexCount += 1;
+ }
+ }
+
+ return 55.0f * z / vertexCount;
+}
+
+void drawLeaf(int index, float* vertices, int meshWidth, int meshHeight,
+ float glWidth, float glHeight) {
+
+ float *leafStruct = loadArrayF(RSID_LEAVES, index);
+
+ float x = leafStruct[LEAF_STRUCT_X];
+ float x1 = x - LEAF_SIZE;
+ float x2 = x + LEAF_SIZE;
+
+ float y = leafStruct[LEAF_STRUCT_Y];
+ float y1 = y - LEAF_SIZE;
+ float y2 = y + LEAF_SIZE;
+
+ float u1 = leafStruct[LEAF_STRUCT_U1];
+ float u2 = leafStruct[LEAF_STRUCT_U2];
+
+ 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 * 0.5f) / glWidth) * meshWidth,
+ meshHeight - ((y + glHeight * 0.5f) / glHeight) * meshHeight,
+ DROP_RADIUS);
+ spin /= 4.0f;
+ leafStruct[LEAF_STRUCT_SPIN] = spin;
+ leafStruct[LEAF_STRUCT_RIPPLED] = 1.0f;
+ } else {
+// dropWithStrength(((x + glWidth / 2.0f) / glWidth) * meshWidth,
+// meshHeight - ((y + glHeight / 2.0f) / glHeight) * meshHeight,
+// 2, 5);
+ }
+ 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) / 60.0f;
+ leafStruct[LEAF_STRUCT_DELTAY] = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
+ }
+}
+
+void drawLeaves() {
+ bindProgramFragment(NAMED_PFBackground);
+ bindProgramFragmentStore(NAMED_PFSLeaf);
+ bindProgramVertex(NAMED_PVSky);
+ bindTexture(NAMED_PFBackground, 0, NAMED_TLeaves);
+
+ int leavesCount = State->leavesCount;
+ int count = leavesCount * LEAF_STRUCT_FIELDS_COUNT;
+ int width = State->meshWidth;
+ int height = State->meshHeight;
+ float glWidth = State->glWidth;
+ float glHeight = State->glHeight;
+
+ float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
+
+ int i = 0;
+ for ( ; i < count; i += LEAF_STRUCT_FIELDS_COUNT) {
+ drawLeaf(i, vertices, width, height, glWidth, glHeight);
+ }
+
+ float matrix[16];
+ matrixLoadIdentity(matrix);
+ vpLoadModelMatrix(matrix);
+}
+
+void drawRiverbed() {
+ bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
+
+ drawTriangleMesh(NAMED_WaterMesh);
+}
+
+void drawSky() {
+ color(1.0f, 1.0f, 1.0f, 0.8f);
+
+ bindProgramFragment(NAMED_PFSky);
+ bindProgramFragmentStore(NAMED_PFSLeaf);
+ bindTexture(NAMED_PFSky, 0, NAMED_TSky);
+
+ float x = g_SkyOffsetX + State->skySpeedX;
+ float y = g_SkyOffsetY + State->skySpeedY;
+
+ if (x > 1.0f) x = 0.0f;
+ if (x < -1.0f) x = 0.0f;
+ if (y > 1.0f) y = 0.0f;
+
+ g_SkyOffsetX = x;
+ g_SkyOffsetY = y;
+
+ float matrix[16];
+ matrixLoadTranslate(matrix, x, y, 0.0f);
+ vpLoadTextureMatrix(matrix);
+
+ drawTriangleMesh(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);
+
+ drawTriangleMesh(NAMED_WaterMesh);
+}
+
+void drawNormals() {
+ int width = State->meshWidth;
+ int height = State->meshHeight;
+
+ float *vertices = loadTriangleMeshVerticesF(NAMED_WaterMesh);
+
+ 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;
+ }
+
+ updateRipples();
+ generateRipples();
+ updateTriangleMesh(NAMED_WaterMesh);
+
+ drawRiverbed();
+ drawSky();
+ drawLighting();
+ drawLeaves();
+ //drawNormals();
+
+ return 1;
+}
<!-- Wallpaper showing a galaxy -->
<string name="wallpaper_galaxy">Galaxy</string>
+
+ <!-- Wallpaper showing leaves floating on water -->
+ <string name="wallpaper_fall">Water</string>
<!-- Wallpaper showing a clock -->
<string name="wallpaper_clock">Polar clock</string>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<!-- The attributes in this XML file provide configuration information -->
+<!-- about the fall wallpaper. -->
+
+<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
+/>
--- /dev/null
+/*
+ * 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.
+ */
+
+package com.android.wallpaper.fall;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Fall extends Activity {
+ private FallView mView;
+
+ @Override
+ public void onCreate(Bundle icicle) {
+ super.onCreate(icicle);
+
+ mView = new FallView(this);
+ setContentView(mView);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ mView.onPause();
+
+ Runtime.getRuntime().exit(0);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.
+ */
+
+package com.android.wallpaper.fall;
+
+import android.renderscript.RenderScript;
+import android.renderscript.ScriptC;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramStore;
+import android.renderscript.ProgramVertex;
+import android.renderscript.Allocation;
+import android.renderscript.Sampler;
+import android.renderscript.Element;
+import android.renderscript.Light;
+import android.renderscript.Type;
+import static android.renderscript.Sampler.Value.LINEAR;
+import static android.renderscript.Sampler.Value.WRAP;
+import static android.renderscript.ProgramStore.DepthFunc.*;
+import static android.renderscript.ProgramStore.BlendDstFunc;
+import static android.renderscript.ProgramStore.BlendSrcFunc;
+import static android.renderscript.ProgramFragment.EnvMode.*;
+import static android.renderscript.Element.*;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import static android.util.MathUtils.*;
+
+import java.util.TimeZone;
+
+import com.android.wallpaper.R;
+import com.android.wallpaper.RenderScriptScene;
+
+class FallRS extends RenderScriptScene {
+ private static final int MESH_RESOLUTION = 48;
+
+ private static final int RSID_STATE = 0;
+
+ private static final int TEXTURES_COUNT = 3;
+ private static final int LEAVES_TEXTURES_COUNT = 4;
+ private static final int RSID_TEXTURE_RIVERBED = 0;
+ private static final int RSID_TEXTURE_LEAVES = 1;
+ 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 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;
+ private static final int LEAF_STRUCT_SCALE = 2;
+ private static final int LEAF_STRUCT_ANGLE = 3;
+ private static final int LEAF_STRUCT_SPIN = 4;
+ private static final int LEAF_STRUCT_U1 = 5;
+ private static final int LEAF_STRUCT_U2 = 6;
+ private static final int LEAF_STRUCT_ALTITUDE = 7;
+ private static final int LEAF_STRUCT_RIPPLED = 8;
+ private static final int LEAF_STRUCT_DELTAX = 9;
+ private static final int LEAF_STRUCT_DELTAY = 10;
+
+ class Leaf {
+ float x;
+ float y;
+ float scale;
+ float angle;
+ float spin;
+ float u1;
+ float u2;
+ float altitude;
+ float rippled;
+ float deltaX;
+ float deltaY;
+ }
+
+ private static final int RSID_DROP = 4;
+
+ private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private ProgramFragment mPfBackground;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private ProgramFragment mPfLighting;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private ProgramFragment mPfSky;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private ProgramStore mPfsBackground;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private ProgramStore mPfsLeaf;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private ProgramVertex mPvLight;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private ProgramVertex mPvSky;
+ private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private Light mLight;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private Sampler mSampler;
+
+ private Allocation mState;
+ private Allocation mDropState;
+ private DropState mDrop;
+ private Type mStateType;
+ private Type mDropType;
+ private int mMeshWidth;
+
+ private int mMeshHeight;
+ @SuppressWarnings({"FieldCanBeLocal"})
+ private RenderScript.TriangleMesh mMesh;
+ private WorldState mWorldState;
+
+ private Allocation mRippleMap;
+ private Allocation mRefractionMap;
+
+ private Allocation mLeaves;
+ private float mGlHeight;
+
+ public FallRS(int width, int height) {
+ super(width, height);
+
+ mOptionsARGB.inScaled = false;
+ mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
+ }
+
+ @Override
+ public void resize(int width, int height) {
+ super.resize(width, height);
+
+ mWorldState.width = width;
+ mWorldState.height = height;
+ mState.data(mWorldState);
+
+ mPvOrthoAlloc.setupOrthoWindow(mWidth, mHeight);
+
+ // TODO: Resize everything else, including the mesh and glHeight
+ }
+
+ @Override
+ protected ScriptC createScript() {
+ createProgramVertex();
+ createProgramFragmentStore();
+ createProgramFragment();
+ createMesh();
+ createScriptStructures();
+ loadTextures();
+
+ ScriptC.Builder sb = new ScriptC.Builder(mRS);
+ sb.setType(mStateType, "State", RSID_STATE);
+ sb.setType(mDropType, "Drop", RSID_DROP);
+ sb.setScript(mResources, R.raw.fall);
+ sb.setRoot(true);
+
+ ScriptC script = sb.create();
+ script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ script.setTimeZone(TimeZone.getDefault().getID());
+
+ 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);
+
+ return script;
+ }
+
+ private void createMesh() {
+ final RenderScript rs = mRS;
+ rs.triangleMeshBegin(Element.NORM_ST_XYZ_F32, Element.INDEX_16);
+
+ int wResolution;
+ int hResolution;
+
+ final int width = mWidth;
+ final int height = mHeight;
+
+ if (width < height) {
+ wResolution = MESH_RESOLUTION;
+ hResolution = (int) (MESH_RESOLUTION * height / (float) width);
+ } else {
+ wResolution = (int) (MESH_RESOLUTION * width / (float) height);
+ hResolution = MESH_RESOLUTION;
+ }
+
+ mGlHeight = 2.0f * height / (float) width;
+ 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 boolean shift = (y & 0x1) == 0;
+ final float yOffset = y * quadHeight - glHeight / 2.0f - quadHeight;
+ final float t = 1.0f - y / (float) hResolution;
+ for (int x = 0; x <= wResolution; x++) {
+ if (shift) {
+ rs.triangleMeshAddVertex_XYZ_ST_NORM(
+ -1.0f + x * quadWidth - quadWidth, yOffset, 0.0f,
+ x / (float) wResolution, t,
+ 0.0f, 0.0f, -1.0f);
+ } else {
+ rs.triangleMeshAddVertex_XYZ_ST_NORM(
+ -1.0f + x * quadWidth - quadWidth * 0.5f, yOffset, 0.0f,
+ x / (float) wResolution, t,
+ 0.0f, 0.0f, -1.0f);
+ }
+ }
+ }
+
+ for (int y = 0; y < hResolution; y++) {
+ final boolean shift = (y & 0x1) == 0;
+ final int yOffset = y * (wResolution + 1);
+ for (int x = 0; x < wResolution; x++) {
+ final int index = yOffset + x;
+ final int iWR1 = index + wResolution + 1;
+ if (shift) {
+ rs.triangleMeshAddTriangle(index, index + 1, iWR1);
+ rs.triangleMeshAddTriangle(index + 1, iWR1 + 1, iWR1);
+ } else {
+ rs.triangleMeshAddTriangle(index, iWR1 + 1, iWR1);
+ rs.triangleMeshAddTriangle(index, index + 1, iWR1 + 1);
+ }
+ }
+ }
+
+ mMesh = rs.triangleMeshCreate();
+ mMesh.setName("WaterMesh");
+
+ mMeshWidth = wResolution + 1;
+ mMeshHeight = hResolution + 1;
+ }
+
+ private void createScriptStructures() {
+ final int rippleMapSize = (mMeshWidth + 2) * (mMeshHeight + 2);
+
+ createState(rippleMapSize);
+ 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);
+ mRippleMap.data(rippleMap);
+ }
+
+ static class WorldState {
+ public int frameCount;
+ public int width;
+ public int height;
+ public int meshWidth;
+ public int meshHeight;
+ public int rippleMapSize;
+ public int rippleIndex;
+ public int leavesCount;
+ public float glWidth;
+ public float glHeight;
+ public float skySpeedX;
+ public float skySpeedY;
+ }
+
+ static class DropState {
+ public int dropX;
+ public int dropY;
+ }
+
+ private void createState(int rippleMapSize) {
+ mWorldState = new WorldState();
+ mWorldState.width = mWidth;
+ mWorldState.height = mHeight;
+ mWorldState.meshWidth = mMeshWidth;
+ mWorldState.meshHeight = mMeshHeight;
+ mWorldState.rippleMapSize = rippleMapSize;
+ mWorldState.rippleIndex = 0;
+ mWorldState.leavesCount = LEAVES_COUNT;
+ mWorldState.glWidth = 2.0f;
+ mWorldState.glHeight = mGlHeight;
+ mWorldState.skySpeedX = random(-0.001f, 0.001f);
+ mWorldState.skySpeedY = random(0.00008f, 0.0002f);
+
+ mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState");
+ mState = Allocation.createTyped(mRS, mStateType);
+ mState.data(mWorldState);
+
+ mDrop = new DropState();
+ mDrop.dropX = -1;
+ mDrop.dropY = -1;
+
+ mDropType = Type.createFromClass(mRS, DropState.class, 1, "DropState");
+ mDropState = Allocation.createTyped(mRS, mDropType);
+ mDropState.data(mDrop);
+ }
+
+ private void createLeaf(float[] leaves, int index) {
+ int sprite = random(LEAVES_TEXTURES_COUNT);
+ //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.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] = -1.0f;
+ leaves[index + LEAF_STRUCT_RIPPLED] = 1.0f;
+ leaves[index + LEAF_STRUCT_DELTAX] = random(-0.02f, 0.02f) / 60.0f;
+ leaves[index + LEAF_STRUCT_DELTAY] = -0.08f * random(0.9f, 1.1f) / 60.0f;
+ }
+
+ private void loadTextures() {
+ final Allocation[] textures = new Allocation[TEXTURES_COUNT];
+ textures[RSID_TEXTURE_RIVERBED] = loadTexture(R.drawable.riverbed, "TRiverbed");
+ textures[RSID_TEXTURE_LEAVES] = loadTextureARGB(R.drawable.leaves, "TLeaves");
+ textures[RSID_TEXTURE_SKY] = loadTextureARGB(R.drawable.clouds, "TSky");
+
+ final int count = textures.length;
+ for (int i = 0; i < count; i++) {
+ final Allocation texture = textures[i];
+ texture.uploadToTexture(0);
+ }
+ }
+
+ private Allocation loadTexture(int id, String name) {
+ final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources,
+ id, RGB_565, false);
+ allocation.setName(name);
+ return allocation;
+ }
+
+ private Allocation loadTextureARGB(int id, String name) {
+ Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
+ final Allocation allocation = Allocation.createFromBitmap(mRS, b, RGBA_8888, false);
+ allocation.setName(name);
+ return allocation;
+ }
+
+ private void createProgramFragment() {
+ Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
+ sampleBuilder.setMin(LINEAR);
+ sampleBuilder.setMag(LINEAR);
+ sampleBuilder.setWrapS(WRAP);
+ sampleBuilder.setWrapT(WRAP);
+ mSampler = sampleBuilder.create();
+
+ ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
+ builder.setTexEnable(true, 0);
+ builder.setTexEnvMode(REPLACE, 0);
+ mPfBackground = builder.create();
+ mPfBackground.setName("PFBackground");
+ mPfBackground.bindSampler(mSampler, 0);
+
+ builder = new ProgramFragment.Builder(mRS, null, null);
+ builder.setTexEnable(false, 0);
+ mPfLighting = builder.create();
+ mPfLighting.setName("PFLighting");
+ mPfLighting.bindSampler(mSampler, 0);
+
+ builder = new ProgramFragment.Builder(mRS, null, null);
+ builder.setTexEnable(true, 0);
+ builder.setTexEnvMode(MODULATE, 0);
+ mPfSky = builder.create();
+ mPfSky.setName("PFSky");
+ mPfSky.bindSampler(mSampler, 0);
+ }
+
+ private void createProgramFragmentStore() {
+ ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null);
+ builder.setDepthFunc(ALWAYS);
+ builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
+ builder.setDitherEnable(false);
+ builder.setDepthMask(true);
+ mPfsBackground = builder.create();
+ mPfsBackground.setName("PFSBackground");
+
+ builder = new ProgramStore.Builder(mRS, null, null);
+ builder.setDepthFunc(ALWAYS);
+ builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA);
+ builder.setDitherEnable(false);
+ builder.setDepthMask(true);
+ mPfsLeaf = builder.create();
+ mPfsLeaf.setName("PFSLeaf");
+ }
+
+ private void createProgramVertex() {
+ mPvOrthoAlloc = new ProgramVertex.MatrixAllocation(mRS);
+ mPvOrthoAlloc.setupProjectionNormalized(mWidth, mHeight);
+
+ mLight = new Light.Builder(mRS).create();
+ mLight.setPosition(0.0f, 2.0f, -8.0f);
+
+ ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
+ builder.addLight(mLight);
+ mPvLight = builder.create();
+ mPvLight.bindAllocation(mPvOrthoAlloc);
+ mPvLight.setName("PVLight");
+
+ builder = new ProgramVertex.Builder(mRS, null, null);
+ builder.setTextureMatrixEnable(true);
+ mPvSky = builder.create();
+ mPvSky.bindAllocation(mPvOrthoAlloc);
+ mPvSky.setName("PVSky");
+ }
+
+ void addDrop(float x, float y) {
+ mDrop.dropX = (int) ((x / mWidth) * mMeshWidth);
+ mDrop.dropY = (int) ((y / mHeight) * mMeshHeight);
+ mDropState.data(mDrop);
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.
+ */
+
+
+package com.android.wallpaper.fall;
+
+import android.content.Context;
+import android.view.SurfaceHolder;
+import android.view.MotionEvent;
+import android.renderscript.RenderScript;
+import android.renderscript.RSSurfaceView;
+
+class FallView extends RSSurfaceView {
+ private FallRS mRender;
+
+ public FallView(Context context) {
+ super(context);
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+ }
+
+ public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+ super.surfaceChanged(holder, format, w, h);
+
+ RenderScript RS = createRenderScript(false);
+ mRender = new FallRS(w, h);
+ mRender.init(RS, getResources());
+ mRender.start();
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_DOWN:
+ case MotionEvent.ACTION_MOVE:
+ mRender.addDrop(event.getX(), event.getY());
+ try {
+ Thread.sleep(16);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ break;
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*
+ * 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.
+ */
+
+package com.android.wallpaper.fall;
+
+import com.android.wallpaper.RenderScriptWallpaper;
+import com.android.wallpaper.RenderScriptScene;
+
+public class FallWallpaper extends RenderScriptWallpaper {
+ protected RenderScriptScene createScene(int width, int height) {
+ return new FallRS(width, height);
+ }
+}
\ No newline at end of file