Home | History | Annotate | Download | only in fall
      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