android-2.1_r1 snapshot
[xdandroid:packages_wallpapers_basic.git] / res / raw / fall.rs
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 #pragma stateVertex(PVSky)
17 #pragma stateFragment(PFBackground)
18 #pragma stateStore(PFSBackground)
19
20 #define LEAVES_TEXTURES_COUNT 8
21 #define LEAF_SIZE 0.55f
22 #define LEAVES_COUNT 14
23
24 float skyOffsetX;
25 float skyOffsetY;
26 float g_DT;
27 int g_LastTime;
28
29 struct vert_s {
30     float x;
31     float y;
32     float z;
33     float s;
34     float t;
35 };
36
37 struct drop_s {
38     float ampS;
39     float ampE;
40     float spread;
41     float spread2;
42     float invSpread;
43     float invSpread2;
44     float x;
45     float y;
46 };
47 struct drop_s gDrops[10];
48 int gMaxDrops;
49
50 struct Leaves_s {
51     float x;
52     float y;
53     float scale;
54     float angle;
55     float spin;
56     float u1;
57     float u2;
58     float altitude;
59     float rippled;
60     float deltaX;
61     float deltaY;
62     int newLeaf;
63 };
64
65 struct Leaves_s gLeavesStore[LEAVES_COUNT];
66
67 struct Leaves_s* gLeaves[LEAVES_COUNT];
68
69 struct Leaves_s* gNextLeaves[LEAVES_COUNT];
70
71 void init() {
72     int ct;
73     gMaxDrops = 10;
74     for (ct=0; ct<gMaxDrops; ct++) {
75         gDrops[ct].ampS = 0;
76         gDrops[ct].ampE = 0;
77         gDrops[ct].spread = 1;
78         gDrops[ct].spread2 = gDrops[ct].spread * gDrops[ct].spread;
79         gDrops[ct].invSpread = 1 / gDrops[ct].spread;
80         gDrops[ct].invSpread2 = gDrops[ct].invSpread * gDrops[ct].invSpread;
81     }
82 }
83
84 void initLeaves() {
85     struct Leaves_s *leaf = gLeavesStore;
86     float width = State->glWidth * 2;
87     float height = State->glHeight;
88
89     int i;
90     for (i = 0; i < LEAVES_COUNT; i ++) {
91         gLeaves[i] = leaf;
92         int sprite = randf(LEAVES_TEXTURES_COUNT);
93         leaf->x = randf2(-width * 0.5f, width * 0.5f);
94         leaf->y = randf2(-height * 0.5f, height * 0.5f);
95         leaf->scale = randf2(0.4f, 0.5f);
96         leaf->angle = randf2(0.0f, 360.0f);
97         leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.25f;
98         leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
99         leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
100         leaf->altitude = -1.0f;
101         leaf->rippled = 1.0f;
102         leaf->deltaX = randf2(-0.02f, 0.02f) / 2.0f;
103         leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 2.0f;
104         leaf++;
105     }
106 }
107
108 void updateDrop(int ct) {
109     gDrops[ct].spread += 30.f * g_DT;
110     gDrops[ct].spread2 = gDrops[ct].spread * gDrops[ct].spread;
111     gDrops[ct].invSpread = 1 / gDrops[ct].spread;
112     gDrops[ct].invSpread2 = gDrops[ct].invSpread * gDrops[ct].invSpread;
113     gDrops[ct].ampE = gDrops[ct].ampS * gDrops[ct].invSpread;
114 }
115
116 void drop(int x, int y, float s) {
117     int ct;
118     int iMin = 0;
119     float minAmp = 10000.f;
120     for (ct = 0; ct < gMaxDrops; ct++) {
121         if (gDrops[ct].ampE < minAmp) {
122             iMin = ct;
123             minAmp = gDrops[ct].ampE;
124         }
125     }
126     gDrops[iMin].ampS = s;
127     gDrops[iMin].spread = 0;
128     gDrops[iMin].x = x;
129     gDrops[iMin].y = State->meshHeight - y - 1;
130     updateDrop(iMin);
131 }
132
133 void generateRipples() {
134     int rippleMapSize = State->rippleMapSize;
135     int width = State->meshWidth;
136     int height = State->meshHeight;
137     int index = State->rippleIndex;
138     float ratio = (float)State->meshWidth / State->glWidth;
139     float xShift = State->xOffset * ratio * 2;
140
141     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
142     struct vert_s *vert = (struct vert_s *)vertices;
143
144     float fw = 1.0f / width;
145     float fh = 1.0f / height;
146     int x, y, ct;
147     struct vert_s *v = vert;
148     for (y=0; y < height; y++) {
149         for (x=0; x < width; x++) {
150             struct drop_s * d = &gDrops[0];
151             float z = 0;
152
153             for (ct = 0; ct < gMaxDrops; ct++) {
154                 if (d->ampE > 0.01f) {
155                     float dx = (d->x - xShift) - x;
156                     float dy = d->y - y;
157                     float dist2 = dx*dx + dy*dy;
158                     if (dist2 < d->spread2) {
159                         float dist = sqrtf(dist2);
160                         float a = d->ampE * (dist * d->invSpread);
161                         z += sinf(d->spread - dist) * a;
162                     }
163                 }
164                 d++;
165             }
166             v->z = z;
167             v ++;
168         }
169     }
170     for (ct = 0; ct < gMaxDrops; ct++) {
171         updateDrop(ct);
172     }
173
174     v = vert;
175     for (y = 0; y < height; y += 1) {
176         for (x = 0; x < width; x += 1) {
177             struct vec3_s n1, n2, n3;
178             vec3Sub(&n1, (struct vec3_s *)&(v+1)->x, (struct vec3_s *)&v->x);
179             vec3Sub(&n2, (struct vec3_s *)&(v+width)->x, (struct vec3_s *)&v->x);
180             vec3Cross(&n3, &n1, &n2);
181
182             // Average of previous normal and N1 x N2
183             vec3Sub(&n1, (struct vec3_s *)&(v+width+1)->x, (struct vec3_s *)&v->x);
184             vec3Cross(&n2, &n1, &n2);
185             vec3Add(&n3, &n3, &n2);
186             //vec3Norm(&n3);  // Not necessary for our constrained mesh.
187
188             v->s = (float)x * fw + n3.x;// * 0.2;
189             v->t = (float)y * fh + n3.y;// * 0.2;
190             v->z = 0;
191             v += 1;
192         }
193     }
194 }
195
196 void genLeafDrop(struct Leaves_s *leaf, float amp) {
197     float nx = (leaf->x + State->glWidth * 0.5f) / State->glWidth;
198     float ny = (leaf->y + State->glHeight * 0.5f) / State->glHeight;
199     drop(nx * State->meshWidth, State->meshHeight - ny * State->meshHeight, amp);
200
201 }
202
203 int drawLeaf(struct Leaves_s *leaf) {
204
205     float x = leaf->x;
206     float y = leaf->y;
207
208     float u1 = leaf->u1;
209     float u2 = leaf->u2;
210
211     float a = leaf->altitude;
212     float s = leaf->scale;
213     float r = leaf->angle;
214
215     float tz = 0.0f;
216     if (a > 0.0f) {
217         tz = -a;
218     }
219
220     float matrix[16];
221     if (a > 0.0f) {
222
223         float alpha = 1.0f;
224         if (a >= 0.4f) alpha = 1.0f - (a - 0.4f) / 0.1f;
225
226         color(0.0f, 0.0f, 0.0f, alpha * 0.15f);
227
228         if (State->rotate) {
229             matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
230         } else {
231             matrixLoadIdentity(matrix);
232         }
233
234         float shadowOffet = a / 5;
235
236         matrixTranslate(matrix, (x - State->xOffset * 2) + (shadowOffet / 2), y - shadowOffet, tz);
237         matrixScale(matrix, s, s, 1.0f);
238         matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
239         vpLoadModelMatrix(matrix);
240
241         drawQuadTexCoords(-LEAF_SIZE, -LEAF_SIZE, 0, u1, 1.0f,
242                            LEAF_SIZE, -LEAF_SIZE, 0, u2, 1.0f,
243                            LEAF_SIZE,  LEAF_SIZE, 0, u2, 0.0f,
244                           -LEAF_SIZE,  LEAF_SIZE, 0, u1, 0.0f);
245
246         color(1.0f, 1.0f, 1.0f, alpha);
247     } else {
248         color(1.0f, 1.0f, 1.0f, 1.0f);
249     }
250
251     if (State->rotate) {
252         matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
253     } else {
254         matrixLoadIdentity(matrix);
255     }
256     matrixTranslate(matrix, x - State->xOffset * 2, y, tz);
257     matrixScale(matrix, s, s, 1.0f);
258     matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
259     vpLoadModelMatrix(matrix);
260
261     drawQuadTexCoords(-LEAF_SIZE, -LEAF_SIZE, 0, u1, 1.0f,
262                        LEAF_SIZE, -LEAF_SIZE, 0, u2, 1.0f,
263                        LEAF_SIZE,  LEAF_SIZE, 0, u2, 0.0f,
264                       -LEAF_SIZE,  LEAF_SIZE, 0, u1, 0.0f);
265
266     float spin = leaf->spin;
267     if (a <= 0.0f) {
268         float rippled = leaf->rippled;
269         if (rippled < 0.0f) {
270             genLeafDrop(leaf, 1.5f);
271             //drop(((x + State->glWidth * 0.5f) / State->glWidth) * meshWidth,
272             //     meshHeight - ((y + State->glHeight * 0.5f) / State->glHeight) * meshHeight, 1);
273             spin /= 4.0f;
274             leaf->spin = spin;
275             leaf->rippled = 1.0f;
276         }
277         leaf->x = x + leaf->deltaX * g_DT;
278         leaf->y = y + leaf->deltaY * g_DT;
279         r += spin;
280         leaf->angle = r;
281     } else {
282         a -= 0.15f * g_DT;
283         leaf->altitude = a;
284         r += spin * 2.0f;
285         leaf->angle = r;
286     }
287
288     int newLeaf = 0;
289     if (-LEAF_SIZE * s + x > State->glWidth || LEAF_SIZE * s + x < -State->glWidth ||
290             LEAF_SIZE * s + y < -State->glHeight / 2.0f) {
291
292         int sprite = randf(LEAVES_TEXTURES_COUNT);
293         leaf->x = randf2(-State->glWidth, State->glWidth);
294         leaf->y = randf2(-State->glHeight * 0.5f, State->glHeight * 0.5f);
295
296         leaf->scale = randf2(0.4f, 0.5f);
297         leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.35f;
298         leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
299         leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
300         leaf->altitude = 0.7f;
301         leaf->rippled = -1.0f;
302         leaf->deltaX = randf2(-0.02f, 0.02f) / 2.0f;
303         leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 2.0f;
304         leaf->newLeaf = 1;
305         newLeaf = 1;
306     }
307     return newLeaf;
308 }
309
310 void drawLeaves() {
311     bindProgramFragment(NAMED_PFSky);
312     bindProgramFragmentStore(NAMED_PFSLeaf);
313     bindProgramVertex(NAMED_PVSky);
314     bindTexture(NAMED_PFSky, 0, NAMED_TLeaves);
315
316     color(1.0f, 1.0f, 1.0f, 1.0f);
317
318     int newLeaves = 0;
319     int i = 0;
320     for ( ; i < LEAVES_COUNT; i += 1) {
321         if (drawLeaf(gLeaves[i])) {
322             newLeaves = 1;
323
324         }
325     }
326
327     if (newLeaves > 0) {
328         int index = 0;
329
330         // Copy all the old leaves to the beginning of gNextLeaves
331         for (i=0; i < LEAVES_COUNT; i++) {
332             if (gLeaves[i]->newLeaf == 0) {
333                 gNextLeaves[index] = gLeaves[i];
334                 index++;
335             }
336         }
337
338         // Now copy all the newly falling leaves to the end of gNextLeaves
339         for (i=0; i < LEAVES_COUNT; i++) {
340             if (gLeaves[i]->newLeaf > 0) {
341                 gNextLeaves[index] = gLeaves[i];
342                 gNextLeaves[index]->newLeaf = 0;
343                 index++;
344             }
345         }
346
347         // And move everything in gNextLeaves back to gLeaves
348         for (i=0; i < LEAVES_COUNT; i++) {
349             gLeaves[i] = gNextLeaves[i];
350         }
351     }
352
353     float matrix[16];
354     matrixLoadIdentity(matrix);
355     vpLoadModelMatrix(matrix);
356 }
357
358 void drawRiverbed() {
359     bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
360
361     float matrix[16];
362     matrixLoadScale(matrix, 0.5f * 960.0f / 1024.0f, -1.0f * 800.0f / 1024.0f, 1.0f);
363     matrixTranslate(matrix, State->xOffset, 0.0f, 0.0f);
364     vpLoadTextureMatrix(matrix);
365
366     drawSimpleMesh(NAMED_WaterMesh);
367
368     matrixLoadIdentity(matrix);
369     vpLoadTextureMatrix(matrix);
370 }
371
372 /*
373 void drawSky() {
374     color(1.0f, 1.0f, 1.0f, 0.5f);
375
376     bindProgramFragment(NAMED_PFSky);
377     bindProgramFragmentStore(NAMED_PFSLeaf);
378     bindTexture(NAMED_PFSky, 0, NAMED_TSky);
379
380     float x = skyOffsetX + State->skySpeedX;
381     float y = skyOffsetY + State->skySpeedY;
382
383     if (x > 1.0f) x = 0.0f;
384     if (x < -1.0f) x = 0.0f;
385     if (y > 1.0f) y = 0.0f;
386
387     skyOffsetX = x;
388     skyOffsetY = y;
389
390     float matrix[16];
391     matrixLoadTranslate(matrix, x + State->xOffset, y, 0.0f);
392     vpLoadTextureMatrix(matrix);
393
394     drawSimpleMesh(NAMED_WaterMesh);
395
396     matrixLoadIdentity(matrix);
397     vpLoadTextureMatrix(matrix);
398 }
399 */
400
401 int main(int index) {
402     // Compute dt in seconds.
403     int newTime = uptimeMillis();
404     g_DT = (newTime - g_LastTime) / 1000.f;
405     g_LastTime = newTime;
406     g_DT = minf(g_DT, 0.2f);
407
408
409     if (Drop->dropX != -1) {
410         drop(Drop->dropX, Drop->dropY, 2);
411         Drop->dropX = -1;
412         Drop->dropY = -1;
413     }
414
415     int ct;
416     int add = 0;
417     for (ct = 0; ct < gMaxDrops; ct++) {
418         if (gDrops[ct].ampE < 0.005f) {
419             add = 1;
420         }
421     }
422
423     if (add) {
424         int i = (int)randf(LEAVES_COUNT);
425         genLeafDrop(gLeaves[i], randf(0.3f) + 0.1f);
426     }
427
428     generateRipples();
429     updateSimpleMesh(NAMED_WaterMesh);
430
431     if (State->rotate) {
432         float matrix[16];
433         matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
434         vpLoadModelMatrix(matrix);
435     }
436
437     drawRiverbed();
438     // drawSky();
439     drawLeaves();
440
441     return 30;
442 }