• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2009 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma version(1)
16 
17 #pragma rs java_package_name(com.android.wallpaper.fall)
18 
19 #include "rs_graphics.rsh"
20 
21 #define LEAVES_TEXTURES_COUNT 8
22 #define LEAF_SIZE 0.55f
23 #define LEAVES_COUNT 14
24 
25 // Things we need to set from the application
26 float g_glWidth;
27 float g_glHeight;
28 float g_meshWidth;
29 float g_meshHeight;
30 float g_xOffset;
31 float g_rotate;
32 
33 rs_program_vertex g_PVWater;
34 rs_program_vertex g_PVSky;
35 
36 rs_program_fragment g_PFSky;
37 rs_program_store g_PFSLeaf;
38 rs_program_fragment g_PFBackground;
39 
40 rs_allocation g_TLeaves;
41 rs_allocation g_TRiverbed;
42 
43 rs_mesh g_WaterMesh;
44 
45 typedef struct Constants {
46     float4 Drop01;
47     float4 Drop02;
48     float4 Drop03;
49     float4 Drop04;
50     float4 Drop05;
51     float4 Drop06;
52     float4 Drop07;
53     float4 Drop08;
54     float4 Drop09;
55     float4 Drop10;
56     float4 Offset;
57     float Rotate;
58 } Constants_t;
59 
60 Constants_t *g_Constants;
61 rs_program_store g_PFSBackground;
62 
63 //float skyOffsetX;
64 //float skyOffsetY;
65 static float g_DT;
66 static int64_t g_LastTime;
67 
68 typedef struct Drop {
69     float ampS;
70     float ampE;
71     float spread;
72     float x;
73     float y;
74 } Drop_t;
75 static Drop_t gDrops[10];
76 static int gMaxDrops;
77 
78 typedef struct Leaves {
79     float x;
80     float y;
81     float scale;
82     float angle;
83     float spin;
84     float u1;
85     float u2;
86     float altitude;
87     float rippled;
88     float deltaX;
89     float deltaY;
90     int newLeaf;
91 } Leaves_t;
92 
93 static Leaves_t gLeavesStore[LEAVES_COUNT];
94 static Leaves_t* gLeaves[LEAVES_COUNT];
95 static Leaves_t* gNextLeaves[LEAVES_COUNT];
96 
97 void initLeaves() {
98     Leaves_t *leaf = gLeavesStore;
99     // globals haven't been set at this point yet. We need to find the correct
100     // function index to call this, we can wait until reflection works
101     float width = 2; //g_glWidth;
102     float height = 3.333; //g_glHeight;
103 
104     int i;
105     for (i = 0; i < LEAVES_COUNT; i ++) {
106         gLeaves[i] = leaf;
107         int sprite = rsRand(LEAVES_TEXTURES_COUNT);
108         leaf->x = rsRand(-width, width);
109         leaf->y = rsRand(-height * 0.5f, height * 0.5f);
110         leaf->scale = rsRand(0.4f, 0.5f);
111         leaf->angle = rsRand(0.0f, 360.0f);
112         leaf->spin = degrees(rsRand(-0.02f, 0.02f)) * 0.25f;
113         leaf->u1 = (float)sprite / (float) LEAVES_TEXTURES_COUNT;
114         leaf->u2 = (float)(sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
115         leaf->altitude = -1.0f;
116         leaf->rippled = 1.0f;
117         leaf->deltaX = rsRand(-0.01f, 0.01f);
118         leaf->deltaY = -rsRand(0.036f, 0.044f);
119         leaf++;
120     }
121 }
122 
123 void init() {
124     int ct;
125     gMaxDrops = 10;
126     for (ct=0; ct<gMaxDrops; ct++) {
127         gDrops[ct].ampS = 0;
128         gDrops[ct].ampE = 0;
129         gDrops[ct].spread = 1;
130     }
131 
132     initLeaves();
133     g_LastTime = rsUptimeMillis();
134     g_DT = 0.1f;
135 }
136 
137 static void updateDrop(int ct) {
138     gDrops[ct].spread += 30.f * g_DT;
139     gDrops[ct].ampE = gDrops[ct].ampS / gDrops[ct].spread;
140 }
141 
142 static void drop(int x, int y, float s) {
143     int ct;
144     int iMin = 0;
145     float minAmp = 10000.f;
146     for (ct = 0; ct < gMaxDrops; ct++) {
147         if (gDrops[ct].ampE < minAmp) {
148             iMin = ct;
149             minAmp = gDrops[ct].ampE;
150         }
151     }
152     gDrops[iMin].ampS = s;
153     gDrops[iMin].spread = 0;
154     gDrops[iMin].x = x;
155     gDrops[iMin].y = g_meshHeight - y - 1;
156     updateDrop(iMin);
157 }
158 
159 static void generateRipples() {
160     int ct;
161     for (ct = 0; ct < gMaxDrops; ct++) {
162         Drop_t * d = &gDrops[ct];
163         float *v = (float*)&g_Constants->Drop01;
164         v += ct*4;
165         *(v++) = d->x;
166         *(v++) = d->y;
167         *(v++) = d->ampE * 0.12f;
168         *(v++) = d->spread;
169     }
170     g_Constants->Offset.x = g_xOffset;
171 
172     for (ct = 0; ct < gMaxDrops; ct++) {
173         updateDrop(ct);
174     }
175 }
176 
177 static void genLeafDrop(Leaves_t *leaf, float amp) {
178     float nx = (leaf->x + g_glWidth * 0.5f) / g_glWidth;
179     float ny = (leaf->y + g_glHeight * 0.5f) / g_glHeight;
180     drop(nx * g_meshWidth, g_meshHeight - ny * g_meshHeight, amp);
181 }
182 
183 static int drawLeaf(Leaves_t *leaf) {
184 
185     float x = leaf->x;
186     float y = leaf->y;
187 
188     float u1 = leaf->u1;
189     float u2 = leaf->u2;
190 
191     float a = leaf->altitude;
192     float s = leaf->scale;
193     float r = leaf->angle;
194 
195     float tz = 0.0f;
196     if (a > 0.0f) {
197         tz = -a;
198     }
199 
200     rs_matrix4x4 matrix;
201     if (a > 0.0f) {
202 
203         float alpha = 1.0f;
204         if (a >= 0.4f) alpha = 1.0f - (a - 0.4f) / 0.1f;
205 
206         rsgProgramFragmentConstantColor(g_PFSky, 0.0f, 0.0f, 0.0f, alpha * 0.15f);
207 
208         rsMatrixLoadIdentity(&matrix);
209         if (!g_rotate) {
210             rsMatrixTranslate(&matrix, x - g_xOffset * 2, y, 0);
211         } else {
212             rsMatrixTranslate(&matrix, x, y, 0);
213             rsMatrixRotate(&matrix, 90.0f, 0.0f, 0.0f, 1.0f);
214         }
215 
216         float shadowOffet = a * 0.2f;
217 
218         rsMatrixScale(&matrix, s, s, 1.0f);
219         rsMatrixRotate(&matrix, r, 0.0f, 0.0f, 1.0f);
220         rsgProgramVertexLoadModelMatrix(&matrix);
221 
222         rsgDrawQuadTexCoords(-LEAF_SIZE, -LEAF_SIZE, 0, u1, 1.0f,
223                            LEAF_SIZE, -LEAF_SIZE, 0, u2, 1.0f,
224                            LEAF_SIZE,  LEAF_SIZE, 0, u2, 0.0f,
225                           -LEAF_SIZE,  LEAF_SIZE, 0, u1, 0.0f);
226 
227         rsgProgramFragmentConstantColor(g_PFSky, 1.0f, 1.0f, 1.0f, alpha);
228     } else {
229         rsgProgramFragmentConstantColor(g_PFSky, 1.0f, 1.0f, 1.0f, 1.0f);
230     }
231 
232     rsMatrixLoadIdentity(&matrix);
233     if (!g_rotate) {
234         rsMatrixTranslate(&matrix, x - g_xOffset * 2, y, tz);
235     } else {
236         rsMatrixTranslate(&matrix, x, y, tz);
237         rsMatrixRotate(&matrix, 90.0f, 0.0f, 0.0f, 1.0f);
238     }
239     rsMatrixScale(&matrix, s, s, 1.0f);
240     rsMatrixRotate(&matrix, r, 0.0f, 0.0f, 1.0f);
241     rsgProgramVertexLoadModelMatrix(&matrix);
242 
243     rsgDrawQuadTexCoords(-LEAF_SIZE, -LEAF_SIZE, 0, u1, 1.0f,
244                        LEAF_SIZE, -LEAF_SIZE, 0, u2, 1.0f,
245                        LEAF_SIZE,  LEAF_SIZE, 0, u2, 0.0f,
246                       -LEAF_SIZE,  LEAF_SIZE, 0, u1, 0.0f);
247 
248     float spin = leaf->spin;
249     if (a <= 0.0f) {
250         float rippled = leaf->rippled;
251         if (rippled < 0.0f) {
252             genLeafDrop(leaf, 1.5f);
253             //drop(((x + g_glWidth * 0.5f) / g_glWidth) * meshWidth,
254             //     meshHeight - ((y + g_glHeight * 0.5f) / g_glHeight) * meshHeight, 1);
255             spin *= 0.25f;
256             leaf->spin = spin;
257             leaf->rippled = 1.0f;
258         }
259         leaf->x = x + leaf->deltaX * g_DT;
260         leaf->y = y + leaf->deltaY * g_DT;
261         r += spin;
262         leaf->angle = r;
263     } else {
264         a -= 0.15f * g_DT;
265         leaf->altitude = a;
266         r += spin * 2.0f;
267         leaf->angle = r;
268     }
269 
270     int newLeaf = 0;
271     if (-LEAF_SIZE * s + x > g_glWidth || LEAF_SIZE * s + x < -g_glWidth ||
272             LEAF_SIZE * s + y < -g_glHeight * 0.5f) {
273 
274         int sprite = rsRand(LEAVES_TEXTURES_COUNT);
275 
276         leaf->x = rsRand(-g_glWidth, g_glWidth);
277         leaf->y = rsRand(-g_glHeight * 0.5f, g_glHeight * 0.5f);
278 
279         leaf->scale = rsRand(0.4f, 0.5f);
280         leaf->spin = degrees(rsRand(-0.02f, 0.02f)) * 0.35f;
281         leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
282         leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
283         leaf->altitude = 0.7f;
284         leaf->rippled = -1.0f;
285         leaf->deltaX = rsRand(-0.01f, 0.01f);
286         leaf->deltaY = -rsRand(0.036f, 0.044f);
287         leaf->newLeaf = 1;
288         newLeaf = 1;
289     }
290     return newLeaf;
291 }
292 
293 static void drawLeaves() {
294     rsgBindProgramFragment(g_PFSky);
295     rsgBindProgramStore(g_PFSLeaf);
296     rsgBindProgramVertex(g_PVSky);
297     rsgBindTexture(g_PFSky, 0, g_TLeaves);
298 
299     int newLeaves = 0;
300     int i = 0;
301     for ( ; i < LEAVES_COUNT; i += 1) {
302         if (drawLeaf(gLeaves[i])) {
303             newLeaves = 1;
304 
305         }
306     }
307 
308     if (newLeaves > 0) {
309         int index = 0;
310 
311         // Copy all the old leaves to the beginning of gNextLeaves
312         for (i=0; i < LEAVES_COUNT; i++) {
313             if (gLeaves[i]->newLeaf == 0) {
314                 gNextLeaves[index] = gLeaves[i];
315                 index++;
316             }
317         }
318 
319         // Now copy all the newly falling leaves to the end of gNextLeaves
320         for (i=0; i < LEAVES_COUNT; i++) {
321             if (gLeaves[i]->newLeaf > 0) {
322                 gNextLeaves[index] = gLeaves[i];
323                 gNextLeaves[index]->newLeaf = 0;
324                 index++;
325             }
326         }
327 
328         // And move everything in gNextLeaves back to gLeaves
329         for (i=0; i < LEAVES_COUNT; i++) {
330             gLeaves[i] = gNextLeaves[i];
331         }
332     }
333 
334     rs_matrix4x4 matrix;
335     rsMatrixLoadIdentity(&matrix);
336     rsgProgramVertexLoadModelMatrix(&matrix);
337 }
338 
339 static void drawRiverbed() {
340     rsgBindProgramFragment(g_PFBackground);
341     rsgBindProgramStore(g_PFSBackground);
342     rsgBindTexture(g_PFBackground, 0, g_TRiverbed);
343     rsgDrawMesh(g_WaterMesh);
344 }
345 
346 void addDrop(int x, int y) {
347     drop(x, y, 2);
348 }
349 
350 int root(void) {
351     rsgClearColor(0.f, 0.f, 0.f, 1.f);
352 
353     // Compute dt in seconds.
354     int64_t newTime = rsUptimeMillis();
355     g_DT = (newTime - g_LastTime) * 0.001f;
356     g_DT = min(g_DT, 0.2f);
357     g_LastTime = newTime;
358 
359     g_Constants->Rotate = (float) g_rotate;
360 
361     int ct;
362     int add = 0;
363     for (ct = 0; ct < gMaxDrops; ct++) {
364         if (gDrops[ct].ampE < 0.005f) {
365             add = 1;
366         }
367     }
368 
369     if (add) {
370         int i = (int)rsRand(LEAVES_COUNT);
371         genLeafDrop(gLeaves[i], rsRand(0.3f) + 0.1f);
372     }
373 
374     rsgBindProgramVertex(g_PVWater);
375     generateRipples();
376     rsgAllocationSyncAll(rsGetAllocation(g_Constants));
377     drawRiverbed();
378 
379     drawLeaves();
380 
381     return 50;
382 }
383