watergen.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright (c) 2011 Nokia Corporation.
  3. */
  4. #include <QDebug.h>
  5. #include <math.h>
  6. #include "watergen.h"
  7. #define WATER_COLOR_R 33
  8. #define WATER_COLOR_G 88
  9. #define WATER_COLOR_B 255
  10. #define NORMAL_CALCULATION_DISTANCE 8
  11. const int winct[9][2] = {
  12. { 2 , 2 },
  13. { 1 , 4 },
  14. { 2 , 4 },
  15. { 4 , 3 },
  16. { 6 , 2 },
  17. { 4 , 5 },
  18. { 2 , 8 },
  19. { 4 , 7 },
  20. { 7 , 5 },
  21. };
  22. WaterGen::WaterGen() {
  23. // Generate cosinetable for waves
  24. for (int f=0; f<WATERGEN_TABLE_LENGTH; f++) {
  25. cosineTable[f] = 65000- 2*(int)abs(( cosf( (float)f*3.14159f / (float)WATERGEN_TABLE_LENGTH ) )*65000.0f );
  26. };
  27. waveHeightMap = 0;
  28. initializedWidth = 0;
  29. initializedHeight = 0;
  30. waveComponents = 0;
  31. waveComponentAmount = 0;
  32. reinitWaves( 9 );
  33. };
  34. WaterGen::~WaterGen() {
  35. if (waveHeightMap) delete [] waveHeightMap;
  36. waveHeightMap = 0;
  37. reinitWaves( 0 );
  38. };
  39. void WaterGen::reinitWaves( int amount, bool static_waves ) {
  40. if (waveComponents) delete waveComponents;
  41. waveComponents = 0;
  42. waveComponentAmount = amount;
  43. if (amount<1) return;
  44. waveComponents = new SWaveComponent[ waveComponentAmount ];
  45. for (int w=0; w<waveComponentAmount; w++) {
  46. SWaveComponent *wc = waveComponents+w;
  47. if (static_waves) {
  48. wc->xm = winct[w][0];
  49. wc->ym = winct[w][1];
  50. } else {
  51. int total = 2+w;
  52. int part = (((rand() & 255) * total) >> 8);
  53. wc->xm = 1+part;
  54. wc->ym = 1+(total - part);
  55. }
  56. wc->amplitude = 65000/( (abs(wc->xm ) + abs(wc->ym) -3)*2 );
  57. wc->movingSpeed = 8000+12*wc->amplitude;
  58. wc->currentPos = (rand() & 255)<<8;
  59. };
  60. // output the waves
  61. if (!static_waves) {
  62. /*
  63. qDebug() << "const int winct[10][2] = {";
  64. for (int w=0; w<waveComponentAmount; w++) {
  65. qDebug() << "{ " << waveComponents[w].xm << "," << waveComponents[w].ym << " },";
  66. };
  67. qDebug() << "}";
  68. */
  69. }
  70. };
  71. inline unsigned long resample_alpha( int x, int y, unsigned long *source ) {
  72. source += (((y>>8)&255)<<8) + ((x>>8)&255);
  73. x = ((x&255));
  74. y = ((y&255));
  75. return ((( ((source[0]>>24)*(255^x) + (source[1]>>24)*x) * (255^y) ) +
  76. ( ((source[256]>>24)*(255^x) + (source[257]>>24)*x) * (y) ) ) >> 16);
  77. }
  78. unsigned long resample( int x, int y, unsigned long *source ) {
  79. unsigned long *pos = source + (((y>>8)&255)<<8) + ((x>>8)&255);
  80. x = ((x&255)>>1);
  81. y = ((y&255)>>1);
  82. int negofsx = 128-x;
  83. return (
  84. (((( (((((pos[0]&0x00FF00FF)*(negofsx)) + ((pos[1]&0x00FF00FF)*(x)) ) >> 7)&0x00FF00FF) * (128-y)) +
  85. ( (((((pos[256]&0x00FF00FF)*(negofsx)) + ((pos[257]&0x00FF00FF)*(x)) ) >> 7)&0x00FF00FF) * y)) >> 7) & 0x00FF00FF) |
  86. ((((( ((((((pos[0]>>8)&0x00FF00FF)*(negofsx)) + (((pos[1]>>8)&0x00FF00FF)*(x)) ) >> 7)&0x00FF00FF) * (128-y)) +
  87. ( ((((((pos[256]>>8)&0x00FF00FF)*(negofsx)) + (((pos[257]>>8)&0x00FF00FF)*(x)) ) >> 7)&0x00FF00FF) * y)) >> 7) & 0x00FF00FF) << 8));
  88. }
  89. unsigned long resample_loop( int x, int y, unsigned long *source ) {
  90. unsigned long c1, c2, c3, c4;
  91. c1 = source[(((y>>8)&255)<<8) + ((x>>8)&255)];
  92. c2 = source[((((y>>8)+1)&255)<<8) + ((x>>8)&255)];
  93. c3 = source[(((y>>8)&255)<<8) + (((x>>8)+1)&255)];
  94. c4 = source[((((y>>8)+1)&255)<<8) + (((x>>8)+1)&255)];
  95. x = ((x&255)>>1);
  96. y = ((y&255)>>1);
  97. int negofsx = 128-x;
  98. return (
  99. (((( (((((c1&0x00FF00FF)*(negofsx)) + ((c3&0x00FF00FF)*(x)) ) >> 7)&0x00FF00FF) * (128-y)) +
  100. ( (((((c2&0x00FF00FF)*(negofsx)) + ((c4&0x00FF00FF)*(x)) ) >> 7)&0x00FF00FF) * y)) >> 7) & 0x00FF00FF) |
  101. ((((( ((((((c1>>8)&0x00FF00FF)*(negofsx)) + (((c3>>8)&0x00FF00FF)*(x)) ) >> 7)&0x00FF00FF) * (128-y)) +
  102. ( ((((((c2>>8)&0x00FF00FF)*(negofsx)) + (((c4>>8)&0x00FF00FF)*(x)) ) >> 7)&0x00FF00FF) * y)) >> 7) & 0x00FF00FF) << 8));
  103. }
  104. void WaterGen::generate(QImage &targetImage, QImage &reflection, const float timePassed) {
  105. if (initializedWidth!=targetImage.width() ||
  106. initializedHeight!=targetImage.height() ||
  107. waveHeightMap == 0) {
  108. if (waveHeightMap) delete [] waveHeightMap;
  109. initializedWidth = targetImage.width();
  110. initializedHeight = targetImage.height();
  111. waveHeightMap = new int[ initializedWidth * initializedHeight ];
  112. };
  113. // generate waveHeight
  114. memset( waveHeightMap, 0, 4*initializedWidth * initializedHeight );
  115. int x, y;
  116. int mx, my;
  117. int mx_inc, my_inc;
  118. int spos;
  119. int ftime = (int)(timePassed * 65536.0f );
  120. int a;
  121. int *h;
  122. for (int w=0; w<waveComponentAmount; w++) {
  123. SWaveComponent *wc = waveComponents + w;
  124. wc->currentPos+=((ftime * wc->movingSpeed)>>16);
  125. // run the wave here.
  126. spos = wc->currentPos;
  127. a = (wc->amplitude>>6);
  128. mx_inc = (wc->xm<<16) / initializedWidth;
  129. my_inc = (wc->ym<<16) / initializedHeight;
  130. h = waveHeightMap;
  131. my = 0;
  132. for (y=0; y<initializedHeight; y++) {
  133. mx = 0;
  134. for (x=0; x<initializedWidth; x++) {
  135. *h+=((cosineTable[ ((spos+mx+my)>>6) & WATERGEN_TABLE_AND ]*a)>>12);
  136. h++;
  137. mx+=mx_inc;
  138. };
  139. my+=my_inc;
  140. }
  141. };
  142. int waveand = (targetImage.width() - 1);
  143. unsigned long tecol, mask;
  144. unsigned long *refl = (unsigned long*)reflection.bits();
  145. for (y=0; y<initializedHeight; y++) {
  146. unsigned long *t_pix = (unsigned long*)targetImage.bits() + y*targetImage.bytesPerLine()/4;
  147. for (x=0; x<initializedWidth; x++) {
  148. a = ((x-NORMAL_CALCULATION_DISTANCE)&waveand);
  149. spos = ((x+NORMAL_CALCULATION_DISTANCE)&waveand);
  150. mx = -waveHeightMap[ a + ((y-NORMAL_CALCULATION_DISTANCE)&waveand)*initializedWidth ] +
  151. -waveHeightMap[ a + y*initializedWidth ] +
  152. -waveHeightMap[ a + ((y+NORMAL_CALCULATION_DISTANCE)&waveand)*initializedWidth ] +
  153. waveHeightMap[ spos + ((y-NORMAL_CALCULATION_DISTANCE)&waveand)*initializedWidth ] +
  154. waveHeightMap[ spos + y*initializedWidth ] +
  155. waveHeightMap[ spos + ((y+NORMAL_CALCULATION_DISTANCE)&waveand)*initializedWidth ];
  156. a = ((y-NORMAL_CALCULATION_DISTANCE)&waveand)*initializedWidth;
  157. spos = ((y+NORMAL_CALCULATION_DISTANCE)&waveand)*initializedWidth;
  158. my = -waveHeightMap[ a + ((x-NORMAL_CALCULATION_DISTANCE)&waveand) ] +
  159. -waveHeightMap[ a + x ] +
  160. -waveHeightMap[ a + ((x+NORMAL_CALCULATION_DISTANCE)&waveand) ] +
  161. waveHeightMap[ spos + ((x-NORMAL_CALCULATION_DISTANCE)&waveand) ] +
  162. waveHeightMap[ spos + x ] +
  163. waveHeightMap[ spos + ((x+NORMAL_CALCULATION_DISTANCE)&waveand) ];
  164. a = resample_alpha( 32768+(mx>>1), 32768+(my>>1), refl );
  165. tecol = refl[ (((y + (my>>9))&255)<<8) | ((x+(mx>>9))&255) ];
  166. spos = ((a-128)<<1) + 196;
  167. if (spos<128) spos = 128;
  168. if (spos>255) spos = 255;
  169. tecol = ((((tecol&0x00FF00FF) * spos)>>8)&0x00FF00FF) |
  170. ((((((tecol>>8)&0x00FF00FF) * spos)>>8)&0x00FF00FF)<<8);
  171. a-=(128);
  172. if (a>0) {
  173. tecol = ((tecol&0xFEFEFEFE)>>1) + (a|(a<<8)|(a<<16));
  174. mask = (tecol&0x80808080);
  175. tecol |= (mask-(mask>>7));
  176. tecol = ((tecol&0x7F7F7F7F)<<1);
  177. }
  178. *t_pix = tecol | 0xFF000000;
  179. t_pix++;
  180. };
  181. };
  182. };