Water live wallpaper now runs correctly in landscape.
[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 RSID_RIPPLE_MAP 1
21 #define RSID_REFRACTION_MAP 2
22
23 #define LEAVES_TEXTURES_COUNT 4
24
25 #define LEAF_SIZE 0.55f
26
27 #define REFRACTION 1.333f
28 #define DAMP 3
29
30 #define DROP_RADIUS 2
31 // The higher, the smaller the ripple
32 #define RIPPLE_HEIGHT 10.0f
33
34 float skyOffsetX;
35 float skyOffsetY;
36
37 int lastDrop;
38
39 struct vert_s {
40     float x;
41     float y;
42     float z;
43     float s;
44     float t;
45     float nx;
46     float ny;
47     float nz;
48 };
49
50 int offset(int x, int y, int width) {
51     return x + 1 + (y + 1) * (width + 2);
52 }
53
54 void initLeaves() {
55     if (State->isPreview) lastDrop = uptimeMillis();
56
57     struct Leaves_s *leaf = Leaves;
58     int leavesCount = State->leavesCount;
59     float width = State->glWidth;
60     float height = State->glHeight;
61
62     int i;
63     for (i = 0; i < leavesCount; i ++) {
64         int sprite = randf(LEAVES_TEXTURES_COUNT);
65         leaf->x = randf2(-width * 0.5f, width * 0.5f);
66         leaf->y = randf2(-height * 0.5f, height * 0.5f);
67         leaf->scale = randf2(0.4f, 0.5f);
68         leaf->angle = randf2(0.0f, 360.0f);
69         leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.25f;
70         leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
71         leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
72         leaf->altitude = -1.0f;
73         leaf->rippled = 1.0f;
74         leaf->deltaX = randf2(-0.02f, 0.02f) / 60.0f;
75         leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
76         leaf++;
77     }
78 }
79
80 void dropWithStrength(int x, int y, int r, int s) {
81     int width = State->meshWidth;
82     int height = State->meshHeight;
83
84     if (x < r) x = r;
85     if (y < r) y = r;
86     if (x >= width - r) x = width - r - 1;
87     if (y >= height - r) y = height - r - 1;
88
89     x = width - x;
90
91     int rippleMapSize = State->rippleMapSize;
92     int index = State->rippleIndex;
93     int origin = offset(0, 0, width);
94
95     int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
96     int sqr = r * r;
97     float invs = 1.0f / s;
98
99     int h = 0;
100     for ( ; h < r; h += 1) {
101         int sqv = h * h;
102         int yn = origin + (y - h) * (width + 2);
103         int yp = origin + (y + h) * (width + 2);
104         int w = 0;
105         for ( ; w < r; w += 1) {
106             int squ = w * w;
107             if (squ + sqv < sqr) {
108                 int v = -sqrtf((sqr - (squ + sqv)) << 16) * invs;
109                 current[yn + x + w] = v;
110                 current[yp + x + w] = v;
111                 current[yn + x - w] = v;
112                 current[yp + x - w] = v;
113             }
114         }
115     }
116 }
117
118 void drop(int x, int y, int r) {
119     dropWithStrength(x, y, r, 1);
120 }
121
122 void updateRipples() {
123     int rippleMapSize = State->rippleMapSize;
124     int width = State->meshWidth;
125     int height = State->meshHeight;
126     int index = State->rippleIndex;
127     int origin = offset(0, 0, width);
128
129     int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
130     int* next = loadArrayI32(RSID_RIPPLE_MAP, (1 - index) * rippleMapSize + origin);
131
132     State->rippleIndex = 1 - index;
133
134     int a = 1;
135     int b = width + 2;
136     int h = height;
137     while (h) {
138         int w = width;
139         while (w) {
140             int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - *next;
141             *next = droplet - (droplet >> DAMP);
142             current += 1;
143             next += 1;
144             w -= 1;
145         }
146         current += 2;
147         next += 2;
148         h -= 1;
149     }
150 }
151
152 int refraction(int d, int wave, int *map) {
153     int i = d;
154     if (i < 0) i = -i;
155     if (i > 512) i = 512;
156     int w = (wave + 0x10000) >> 8;
157     w &= ~(w >> 31);
158     int r = (map[i] * w) >> 3;
159     if (d < 0) {
160         return -r;
161     }
162     return r;
163 }
164
165 void generateRipples() {
166     int rippleMapSize = State->rippleMapSize;
167     int width = State->meshWidth;
168     int height = State->meshHeight;
169     int index = State->rippleIndex;
170     int origin = offset(0, 0, width);
171
172     int b = width + 2;
173
174     int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
175     int *map = loadArrayI32(RSID_REFRACTION_MAP, 0);
176     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
177     struct vert_s *vert = (struct vert_s *)vertices;
178
179     float fw = 1.0f / width;
180     float fh = 1.0f / height;
181     float fy = (1.0f / 512.0f) * (1.0f / RIPPLE_HEIGHT);
182
183     int h = height - 1;
184     while (h >= 0) {
185         int w = width - 1;
186         int wave = *current;
187         int offset = h * width;
188         struct vert_s *vtx = vert + offset + w;
189
190         while (w >= 0) {
191             int nextWave = current[1];
192             int dx = nextWave - wave;
193             int dy = current[b] - wave;
194
195             int offsetx = refraction(dx, wave, map) >> 16;
196             int u = (width - w) + offsetx;
197             u &= ~(u >> 31);
198             if (u >= width) u = width - 1;
199
200             int offsety = refraction(dy, wave, map) >> 16;
201             int v = (height - h) + offsety;
202             v &= ~(v >> 31);
203             if (v >= height) v = height - 1;
204
205             vtx->s = u * fw;
206             vtx->t = v * fh;
207             vtx->z = dy * fy;
208             vtx --;
209
210             w -= 1;
211             current += 1;
212             wave = nextWave;
213         }
214         h -= 1;
215         current += 2;
216     }
217
218     // Compute the normals for lighting
219     int y = 0;
220     for ( ; y < (height-1); y += 1) {
221         int x = 0;
222         int yOffset = y * width;
223         struct vert_s *v = vert;
224         v += y * width;
225
226         for ( ; x < (width-1); x += 1) {
227             struct vec3_s n1, n2, n3;
228             vec3Sub(&n1, (struct vec3_s *)&(v+1)->x, (struct vec3_s *)&v->x);
229             vec3Sub(&n2, (struct vec3_s *)&(v+width)->x, (struct vec3_s *)&v->x);
230             vec3Cross(&n3, &n1, &n2);
231             vec3Norm(&n3);
232
233             // Average of previous normal and N1 x N2
234             vec3Sub(&n1, (struct vec3_s *)&(v+width+1)->x, (struct vec3_s *)&v->x);
235             vec3Cross(&n2, &n1, &n2);
236             vec3Add(&n3, &n3, &n2);
237             vec3Norm(&n3);
238
239             v->nx = n3.x;
240             v->ny = n3.y;
241             v->nz = -n3.z;
242             v += 1;
243
244             // reset Z
245             //vertices[(yOffset + x) << 3 + 7] = 0.0f;
246         }
247     }
248 }
249
250 void drawLeaf(struct Leaves_s *leaf, int meshWidth, int meshHeight, float glWidth, float glHeight,
251         int rotate) {
252
253     float x = leaf->x;
254     float x1 = x - LEAF_SIZE;
255     float x2 = x + LEAF_SIZE;
256
257     float y = leaf->y;
258     float y1 = y - LEAF_SIZE;
259     float y2 = y + LEAF_SIZE;
260
261     float u1 = leaf->u1;
262     float u2 = leaf->u2;
263
264     float z1 = 0.0f;
265     float z2 = 0.0f;
266     float z3 = 0.0f;
267     float z4 = 0.0f;
268
269     float a = leaf->altitude;
270     float s = leaf->scale;
271     float r = leaf->angle;
272
273     float tz = 0.0f;
274     if (a > 0.0f) {
275         tz = -a;
276     }
277
278     x1 -= x;
279     x2 -= x;
280     y1 -= y;
281     y2 -= y;
282     
283     float matrix[16];    
284
285     if (a > 0.0f) {
286         color(0.0f, 0.0f, 0.0f, 0.15f);
287
288         if (rotate) {
289             matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
290         } else {
291             matrixLoadIdentity(matrix);
292         }
293         matrixTranslate(matrix, x, y, 0.0f);
294         matrixScale(matrix, s, s, 1.0f);
295         matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
296         vpLoadModelMatrix(matrix);
297
298         drawQuadTexCoords(x1, y1, z1, u1, 1.0f,
299                           x2, y1, z2, u2, 1.0f,
300                           x2, y2, z3, u2, 0.0f,
301                           x1, y2, z4, u1, 0.0f);
302
303         float alpha = 1.0f;
304         if (a >= 0.4f) alpha = 1.0f - (a - 0.5f) / 0.1f;
305         color(1.0f, 1.0f, 1.0f, alpha);
306     } else {
307         color(1.0f, 1.0f, 1.0f, 1.0f);
308     }
309
310     if (rotate) {
311         matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
312     } else {
313         matrixLoadIdentity(matrix);
314     }
315     matrixTranslate(matrix, x, y, tz);
316     matrixScale(matrix, s, s, 1.0f);
317     matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
318     vpLoadModelMatrix(matrix);
319
320     drawQuadTexCoords(x1, y1, z1, u1, 1.0f,
321                       x2, y1, z2, u2, 1.0f,
322                       x2, y2, z3, u2, 0.0f,
323                       x1, y2, z4, u1, 0.0f);
324
325     float spin = leaf->spin;
326     if (a <= 0.0f) {
327         float rippled = leaf->rippled;
328         if (rippled < 0.0f) {
329             drop(((x + glWidth * 0.5f) / glWidth) * meshWidth,
330                  meshHeight - ((y + glHeight * 0.5f) / glHeight) * meshHeight, 1);
331             spin /= 4.0f;
332             leaf->spin = spin;
333             leaf->rippled = 1.0f;
334         }
335         leaf->x = x + leaf->deltaX;
336         leaf->y = y + leaf->deltaY;
337         r += spin;
338         leaf->angle = r;
339     } else {
340         a -= 0.005f;
341         leaf->altitude = a;
342         r += spin * 2.0f;
343         leaf->angle = r;
344     }
345
346     if (-LEAF_SIZE * s + x > glWidth / 2.0f || LEAF_SIZE * s + x < -glWidth / 2.0f ||
347             LEAF_SIZE * s + y < -glHeight / 2.0f) {
348
349         int sprite = randf(LEAVES_TEXTURES_COUNT);
350         leaf->x = randf2(-glWidth * 0.5f, glWidth * 0.5f);
351         leaf->y = randf2(-glHeight * 0.5f, glHeight * 0.5f);
352         leaf->scale = randf2(0.4f, 0.5f);
353         leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.25f;
354         leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
355         leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
356         leaf->altitude = 0.6f;
357         leaf->rippled = -1.0f;
358         leaf->deltaX = randf2(-0.02f, 0.02f) / 60.0f;
359         leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
360     }
361 }
362
363 void drawLeaves() {
364     bindProgramFragment(NAMED_PFSky);
365     bindProgramFragmentStore(NAMED_PFSLeaf);
366     bindProgramVertex(NAMED_PVSky);
367     bindTexture(NAMED_PFSky, 0, NAMED_TLeaves);
368
369     color(1.0f, 1.0f, 1.0f, 1.0f);
370
371     int leavesCount = State->leavesCount;
372     int width = State->meshWidth;
373     int height = State->meshHeight;
374     float glWidth = State->glWidth;
375     float glHeight = State->glHeight;
376     int rotate = State->rotate;
377
378     struct Leaves_s *leaf = Leaves;
379
380     int i = 0;
381     for ( ; i < leavesCount; i += 1) {
382         drawLeaf(leaf, width, height, glWidth, glHeight, rotate);
383         leaf += 1;
384     }
385
386     float matrix[16];
387     matrixLoadIdentity(matrix);
388     vpLoadModelMatrix(matrix);
389 }
390
391 void drawRiverbed() {
392     bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
393
394     drawSimpleMesh(NAMED_WaterMesh);
395 }
396
397 void drawSky() {
398     color(1.0f, 1.0f, 1.0f, 0.8f);
399
400     bindProgramFragment(NAMED_PFSky);
401     bindProgramFragmentStore(NAMED_PFSLeaf);
402     bindTexture(NAMED_PFSky, 0, NAMED_TSky);
403
404     float x = skyOffsetX + State->skySpeedX;
405     float y = skyOffsetY + State->skySpeedY;
406
407     if (x > 1.0f) x = 0.0f;
408     if (x < -1.0f) x = 0.0f;
409     if (y > 1.0f) y = 0.0f;
410
411     skyOffsetX = x;
412     skyOffsetY = y;
413
414     float matrix[16];
415     matrixLoadTranslate(matrix, x, y, 0.0f);
416     vpLoadTextureMatrix(matrix);
417
418     drawSimpleMesh(NAMED_WaterMesh);
419
420     matrixLoadIdentity(matrix);
421     vpLoadTextureMatrix(matrix);
422 }
423
424 void drawLighting() {
425     ambient(0.0f, 0.0f, 0.0f, 1.0f);
426     diffuse(0.0f, 0.0f, 0.0f, 1.0f);
427     specular(0.44f, 0.44f, 0.44f, 1.0f);
428     shininess(40.0f);
429
430     bindProgramFragmentStore(NAMED_PFSBackground);
431     bindProgramFragment(NAMED_PFLighting);
432     bindProgramVertex(NAMED_PVLight);
433
434     drawSimpleMesh(NAMED_WaterMesh);
435 }
436
437 void drawNormals() {
438     int width = State->meshWidth;
439     int height = State->meshHeight;
440
441     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
442
443     bindProgramVertex(NAMED_PVSky);
444     bindProgramFragment(NAMED_PFLighting);
445
446     color(1.0f, 0.0f, 0.0f, 1.0f);
447
448     float scale = 1.0f / 10.0f;
449     int y = 0;
450     for ( ; y < height; y += 1) {
451         int yOffset = y * width;
452         int x = 0;
453         for ( ; x < width; x += 1) {
454             int offset = (yOffset + x) << 3;
455             float vx = vertices[offset + 5];
456             float vy = vertices[offset + 6];
457             float vz = vertices[offset + 7];
458             float nx = vertices[offset + 0];
459             float ny = vertices[offset + 1];
460             float nz = vertices[offset + 2];
461             drawLine(vx, vy, vz, vx + nx * scale, vy + ny * scale, vz + nz * scale);
462         }
463     }
464 }
465
466 int main(int index) {
467     if (Drop->dropX != -1) {
468         drop(Drop->dropX, Drop->dropY, DROP_RADIUS);
469         Drop->dropX = -1;
470         Drop->dropY = -1;
471     }
472     
473     if (State->isPreview) {
474         int now = uptimeMillis();
475         if (now - lastDrop > 2000) {
476             float x = randf(State->meshWidth);
477             float y = randf(State->meshHeight);
478
479             drop(x, y, DROP_RADIUS);
480
481             lastDrop = now;
482         }
483     }
484
485     updateRipples();
486     generateRipples();
487     updateSimpleMesh(NAMED_WaterMesh);
488
489     if (State->rotate) {
490         float matrix[16];
491         matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
492         vpLoadModelMatrix(matrix);
493     }
494
495     drawRiverbed();
496     drawSky();
497     drawLighting();
498     drawLeaves();
499     //drawNormals();
500
501     return 1;
502 }