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 } 381