vsandbox.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. #include "TEngine.h"
  2. #include <stdlib.h>
  3. #include "vsandbox.h"
  4. #include "TDrawHelpers.h"
  5. #include "table_texture.cpp"
  6. #include "reset_images.cpp"
  7. extern unsigned int sand_texture[];
  8. CVSandBox::CVSandBox( int simw, int simh ) {
  9. m_autoPaintStatus = -1;
  10. m_vGravity.set( 0, 0 );
  11. m_sandGrid = new CVSand_Grid( simw/SANDGRID_DIV+1, simh/SANDGRID_DIV+1 );
  12. m_litBackground = new TDWORD[ BG_SIZE * BG_SIZE ];
  13. };
  14. CVSandBox::~CVSandBox() {
  15. delete m_sandGrid;
  16. delete [] m_litBackground;
  17. };
  18. void CVSandBox::autoPaintToResetTarget( int index, int type ) {
  19. CTSurface_RGBA8888 freset, sub;
  20. freset.setAsReference( reset_images, 64, 512, 64, eTSURFACEFORMAT_RGBA8888 );
  21. sub.setReference( &freset, 0, index*64, 64, 64 );
  22. autoPaintTo( sub, type, 30 );
  23. };
  24. void CVSandBox::autoPaintTo( CTSurface_RGBA8888 &target, int type, int power ) {
  25. if (target.getData()==0) return; // cannot continue
  26. if (type==-1) m_autoPaintType = rand()%4; else m_autoPaintType= type; // 4 = autopaint- scratch
  27. m_autoPaintTarget.create( m_sandGrid->width(), m_sandGrid->height(), eTSURFACEFORMAT_RGBA8888 );
  28. CTDrawHelpers::linearScaleImage( &target, &m_autoPaintTarget, 0);
  29. m_autoPaintStatus = 0;
  30. TDWORD *t = (TDWORD*)m_autoPaintTarget.getData();
  31. int i;
  32. int r,g,b;
  33. // preprocess
  34. for (int y=0; y<m_sandGrid->height(); y++) {
  35. for (int x=0; x<m_sandGrid->width(); x++) {
  36. //*t = (((*t&255) | (((*t)>>8)&255) | (((*t)>>8)&255) * 65536) / (256*3));
  37. r = *t&255;
  38. g = (((*t)>>8)&255)&255;
  39. b = (((*t)>>16)&255)&255;
  40. r = 255-r;
  41. g = 255-g;
  42. b = 255-b;
  43. i = tmath_sqrt( r*r+g*g+b*b )*power; // amount, ..was 70
  44. if (i<0) i =0 ;
  45. *t = (TDWORD)i;
  46. t++;
  47. }
  48. };
  49. };
  50. void CVSandBox::shake( int dirx, int diry ) {
  51. m_sandGrid->selective_soften(0); // first, run the soften.
  52. m_sandGrid->selective_soften(0); // last, run the soften.
  53. };
  54. void CVSandBox::markAllChanged() {
  55. // mark everything changed.
  56. SVSandNode *mark = m_sandGrid->smap();
  57. SVSandNode *mark_target = mark + m_sandGrid->width() * m_sandGrid->height();
  58. while (mark!=mark_target) {
  59. mark->checksum = 8787;
  60. mark++;
  61. };
  62. };
  63. void CVSandBox::relightBg(int mul) {
  64. TDWORD *s = (TDWORD*)table_texture;
  65. mul = (mul*3/4)+FP_VAL/4;
  66. for (int i=0; i<256*256; i++) m_litBackground[i] =
  67. (((s[i]&255)*mul)>>FP_BITS) |
  68. (((((s[i]>>8)&255)*mul)>>FP_BITS)<<8) |
  69. (((((s[i]>>16)&255)*mul)>>FP_BITS)<<16) |
  70. 0xFF000000;
  71. markAllChanged();
  72. };
  73. void CVSandBox::autoPaintStep() {
  74. switch (m_autoPaintType) {
  75. case 4:
  76. //m_ = eSANDTOOL_SCRATCH_TO_TARGET;
  77. if (m_autoPaintStatus<m_sandGrid->height()) {
  78. int rval;
  79. SVSandNode *g = m_sandGrid->smap()+m_autoPaintStatus*m_sandGrid->width();
  80. SVSandNode *g_target = g+m_sandGrid->width();
  81. while (g!=g_target) {
  82. g->amount = 16000+((rand()&255)<<6);
  83. g++;
  84. };
  85. }
  86. m_autoPaintStatus++;
  87. break;
  88. default:
  89. case 0:
  90. {
  91. TDWORD *t = (TDWORD*)m_autoPaintTarget.getData();
  92. SVSandNode *g = m_sandGrid->smap();
  93. SVSandNode *g_target = g+m_sandGrid->width()*m_sandGrid->height();
  94. while (g!=g_target) {
  95. if ((*t>>8) == (m_autoPaintStatus&127)) g->amount = *t;
  96. g++;
  97. t++;
  98. }
  99. m_autoPaintStatus++;
  100. if (m_autoPaintStatus>128*3) m_autoPaintStatus = -1;
  101. }
  102. break;
  103. case 1:
  104. {
  105. TDWORD *t = (TDWORD*)m_autoPaintTarget.getData();
  106. SVSandNode *g = m_sandGrid->smap();
  107. int v = m_autoPaintStatus%(m_sandGrid->height() +90);
  108. for (int y=0; y<m_sandGrid->height(); y++)
  109. for (int x=0; x<m_sandGrid->width(); x++) {
  110. if (y+((*t)>>8) == v) {
  111. g->amount = *t;
  112. }
  113. t++;
  114. g++;
  115. };
  116. m_autoPaintStatus++;
  117. if (m_autoPaintStatus>(m_sandGrid->height()+90)*3) m_autoPaintStatus = -1;
  118. break;
  119. }
  120. case 2:
  121. {
  122. TDWORD *t = (TDWORD*)m_autoPaintTarget.getData();
  123. SVSandNode *g = m_sandGrid->smap();
  124. int v = m_autoPaintStatus%(m_sandGrid->width() +90);
  125. for (int y=0; y<m_sandGrid->height(); y++)
  126. for (int x=0; x<m_sandGrid->width(); x++) {
  127. if (x+((*t)>>8) == v) {
  128. g->amount = *t;
  129. }
  130. t++;
  131. g++;
  132. };
  133. m_autoPaintStatus++;
  134. if (m_autoPaintStatus>(m_sandGrid->width()+90)*3) m_autoPaintStatus = -1;
  135. break;
  136. }
  137. }
  138. };
  139. int CVSandBox::run( int fixedFrameTime ) {
  140. for (int f=0; f<2; f++) if (m_autoPaintStatus>=0) autoPaintStep();
  141. m_sandGrid->run( m_vGravity, m_vLight, m_bgLight );
  142. return 1;
  143. };
  144. void CVSandBox::setLight(int x, int y) {
  145. m_vLight.set(x,y*2);
  146. int l = m_vLight.length();
  147. if (l>FP_VAL*3) {
  148. //m_vLight.setLength( FP_VAL*3/2);
  149. m_vLight.m_x = tmath_fpmuldiv( m_vLight.m_x, FP_VAL*3, l);
  150. m_vLight.m_y = tmath_fpmuldiv( m_vLight.m_y, FP_VAL*3, l);
  151. }
  152. l/=3;
  153. int bgLight = tmath_fpdiv(FP_VAL*2, tmath_fpmul(l,l));
  154. if (bgLight>FP_VAL) bgLight = FP_VAL;
  155. m_bgLight = bgLight;
  156. relightBg( (FP_VAL+ bgLight)/2 );
  157. };
  158. void CVSandBox::drawGridItem( TDWORD *target,int pitch, SVSandNode *node, int u, int v ) {
  159. int y;
  160. TDWORD *t_target;
  161. int s1 = (node[0].amount);
  162. int s2 = (node[1].amount);
  163. int s1inc = (node[m_sandGrid->width()].amount - s1);
  164. int s2inc = (node[m_sandGrid->width()+1].amount - s2);
  165. int l1 = (node[0].light);
  166. int l2 = (node[1].light);
  167. int l1inc = (node[m_sandGrid->width()].light - l1);
  168. int l2inc = (node[m_sandGrid->width()+1].light - l2);
  169. s1<<=SANDGRID_DIV_BITS;
  170. s2<<=SANDGRID_DIV_BITS;
  171. l1<<=SANDGRID_DIV_BITS;
  172. l2<<=SANDGRID_DIV_BITS;
  173. int a;
  174. TDWORD tecol;
  175. int inners, innersinc;
  176. int innerl, innerlinc;
  177. TDWORD *bg;
  178. for (y=0; y<SANDGRID_DIV; y++) {
  179. t_target = target+SANDGRID_DIV;
  180. bg = &m_litBackground[(v&255)<<8];
  181. inners = s1<<SANDGRID_DIV_BITS;
  182. innersinc = (s2-s1); //>>SANDGRID_DIV_BITS;
  183. innerl = l1<<SANDGRID_DIV_BITS;
  184. innerlinc = (l2-l1);//>>SANDGRID_DIV_BITS;
  185. while (target!=t_target) {
  186. tecol = sand_texture[ ((((v&127)<<7) | (u&127)) + ((inners>>SANDGRID_SAND_SHR)*3600))&16383];
  187. a = ((inners)>>11)-(tecol>>26);
  188. if (a>0) {
  189. if (a>=255) {
  190. *target = (((tecol&255)*innerl) >> SANDGRID_LIGHT_SHR) |
  191. (((((tecol>>8)&255)*innerl) >> SANDGRID_LIGHT_SHR)<<8) |
  192. (((((tecol>>16)&255)*innerl) >> SANDGRID_LIGHT_SHR)<<16) |
  193. 0xFF000000;
  194. } else {
  195. *target = ((((((tecol&255)*innerl) >> SANDGRID_LIGHT_SHR)*a) + ((bg[u&255]&255)*(255^a)))>>8) |
  196. ((((((((tecol>>8)&255)*innerl) >> SANDGRID_LIGHT_SHR)*a) + (((bg[u&255]>>8)&255)*(255^a)))>>8)<<8) |
  197. ((((((((tecol>>16)&255)*innerl) >> SANDGRID_LIGHT_SHR)*a) + (((bg[u&255]>>16)&255)*(255^a)))>>8)<<16) |
  198. 0xFF000000;
  199. };
  200. } else {
  201. *target = bg[u&255];
  202. };
  203. innerl+=innerlinc;
  204. inners+=innersinc;
  205. target++;
  206. u++;
  207. };
  208. u -= SANDGRID_DIV;
  209. v++;
  210. target-=SANDGRID_DIV;
  211. target+=pitch;
  212. s1+=s1inc;
  213. s2+=s2inc;
  214. l1+=l1inc;
  215. l2+=l2inc;
  216. };
  217. };
  218. int CVSandBox::render( CTSurface_RGBA8888 &target, int *bound_rect ) {
  219. int rval = 0;
  220. int tt;
  221. int sgw = m_sandGrid->width();
  222. SVSandNode *sdata = m_sandGrid->smap();
  223. for (tt=0; tt<m_sandGrid->width()*m_sandGrid->height(); tt++) {
  224. sdata->renderCheck= sdata->checksum;
  225. sdata->checksum = ((TSDWORD)sdata->light) ^ (((TSDWORD)(sdata->amount>>11))<<16); //^sdata->dir.m_x^sdata->dir.m_y;
  226. sdata++;
  227. };
  228. if (bound_rect) {
  229. bound_rect[0] = 1000; // minx
  230. bound_rect[1] = 0; // maxx
  231. bound_rect[2] = 1000; // miny
  232. bound_rect[3] = 0; // maxy
  233. };
  234. for (int y=0; y<m_sandGrid->height()-1; y++) {
  235. sdata = m_sandGrid->smap() + sgw * y;
  236. TDWORD *t = (TDWORD*)target.getData() + target.getPitch() * (y*SANDGRID_DIV);
  237. for (int x=0; x<sgw-1; x++) {
  238. // render check
  239. if ((sdata[0].checksum != sdata[0].renderCheck) ||
  240. (sdata[1].checksum != (sdata[1].renderCheck)) ||
  241. (sdata[sgw].checksum != (sdata[sgw].renderCheck)) ||
  242. (sdata[sgw+1].checksum != (sdata[sgw+1].renderCheck))
  243. ) {
  244. if (bound_rect) {
  245. if (x<bound_rect[0]) bound_rect[0] =x;
  246. if (x>bound_rect[1]) bound_rect[1] =x;
  247. if (y<bound_rect[2]) bound_rect[2] =y;
  248. if (y>bound_rect[3]) bound_rect[3] =y;
  249. };
  250. rval = 1;
  251. drawGridItem( t, target.getPitch(), sdata,x*SANDGRID_DIV,y*SANDGRID_DIV );
  252. }
  253. t+=SANDGRID_DIV;
  254. sdata++;
  255. }
  256. };
  257. if (bound_rect) {
  258. bound_rect[0] *= SANDGRID_DIV;
  259. bound_rect[1] *= SANDGRID_DIV;
  260. bound_rect[2] *= SANDGRID_DIV;
  261. bound_rect[3] *= SANDGRID_DIV;
  262. }
  263. return rval;
  264. };