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