PageRenderTime 46ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/LotsaWater/Water.c

https://code.google.com/p/lotsablankers/
C | 298 lines | 210 code | 50 blank | 38 comment | 30 complexity | 3aa6321ecf081e4332c3fe41c1850ab5 MD5 | raw file
  1. #include "Water.h"
  2. #include "LotsaCore/Random.h"
  3. #include <stdlib.h>
  4. #include <math.h>
  5. //const complex cerf(const complex &z);
  6. void InitWaterState(WaterState *self,int max_p,int max_q)
  7. {
  8. self->max_p=max_p;
  9. self->max_q=max_q;
  10. self->apq=malloc(max_p*max_q*sizeof(float));
  11. self->bpq=malloc(max_p*max_q*sizeof(float));
  12. int i=0;
  13. for(int q=0;q<max_q;q++)
  14. for(int p=0;p<max_p;p++)
  15. {
  16. self->apq[i]=self->bpq[i]=0;
  17. i++;
  18. }
  19. }
  20. void InitRandomWaterState(WaterState *self,Water *water)
  21. {
  22. InitWaterState(self,water->max_p,water->max_q);
  23. int i=0;
  24. for(int q=0;q<water->max_q;q++)
  25. for(int p=0;p<water->max_p;p++)
  26. {
  27. if(water->wpq[i]>0)
  28. {
  29. self->apq[i]=0.03*(2*RandomFloat()-1)*expf(-0.01*water->wpq[i]*water->wpq[i]); // boltzmann distribution
  30. self->bpq[i]=0.03*(2*RandomFloat()-1)*expf(-0.01*water->wpq[i]*water->wpq[i]); // should fix the energy
  31. }
  32. else self->apq[i]=self->bpq[i]=0;
  33. i++;
  34. }
  35. }
  36. void InitDripWaterState(WaterState *self,Water *water,float x0,float y0,float d,float ampl)
  37. {
  38. InitWaterState(self,water->max_p,water->max_q);
  39. int i=0;
  40. for(int q=0;q<water->max_q;q++)
  41. for(int p=0;p<water->max_p;p++)
  42. {
  43. self->apq[i]=0;
  44. self->bpq[i]=
  45. ampl*4.0f/(water->wpq[i]*water->lx*water->ly)*
  46. cosf(p*M_PI*x0/water->lx)*cosf(q*M_PI*y0/water->ly)*
  47. expf(-M_PI*M_PI*d*d*(p*p/(water->lx*water->lx)+q*q/(water->ly*water->ly))/4.0f)
  48. /* *0.5*(
  49. cerf(complex((water.lx-x0)/d,float(p)*M_PI*d/(2*water.lx))).re
  50. -cerf(complex(-x0/d,float(p)*M_PI*d/(2*water.lx))).re
  51. )
  52. *0.5*(
  53. cerf(complex((water.ly-y0)/d,float(q)*M_PI*d/(2*water.ly))).re
  54. -cerf(complex(-y0/d,float(q)*M_PI*d/(2*water.ly))).re
  55. )*/;
  56. if(p==0) self->bpq[i]/=2;
  57. if(q==0) self->bpq[i]/=2;
  58. i++;
  59. }
  60. }
  61. /*drip_state::drip_state(float x0,float y0,water &water):water_state(water.max_p,water.max_q)
  62. {
  63. int i=0;
  64. for(int q=0;q<max_q;q++)
  65. for(int p=0;p<max_p;p++)
  66. {
  67. apq[i]=0;
  68. bpq[i]=0.003*4/(water.wpq[i]*water.lx*water.ly)*
  69. (cos(float(p)*M_PI*x0/water.lx)*cos(float(q)*M_PI*y0/water.ly));
  70. if(p==0) bpq[i]/=2;
  71. if(q==0) bpq[i]/=2;
  72. i++;
  73. }
  74. }*/
  75. void CleanupWaterState(WaterState *self)
  76. {
  77. free(self->apq);
  78. free(self->bpq);
  79. }
  80. void InitSimpleWater(Water *self,int w,int h,float v,float b,float lx,float ly)
  81. {
  82. InitWater(self,w,h,w,h,v,b,lx,ly);
  83. }
  84. void InitWater(Water *self,int w,int h,int max_p,int max_q,float v,float b,float lx,float ly)
  85. {
  86. self->w=w;
  87. self->h=h;
  88. self->max_p=max_p;
  89. self->max_q=max_q;
  90. self->t0=0;
  91. InitWaterState(&self->state,max_p,max_q);
  92. self->wpq=malloc(max_p*max_q*sizeof(float));
  93. self->ampl=malloc(max_p*max_q*sizeof(float));
  94. self->sin_px=malloc(w*max_p*sizeof(float));
  95. self->cos_px=malloc(w*max_p*sizeof(float));
  96. self->sin_qy=malloc(h*max_q*sizeof(float));
  97. self->cos_qy=malloc(h*max_q*sizeof(float));
  98. self->z=malloc(w*h*sizeof(float));
  99. self->n=malloc(w*h*sizeof(vec3_t));
  100. self->v=v;
  101. self->b=b;
  102. self->lx=lx;
  103. self->ly=ly;
  104. int i;
  105. i=0;
  106. for(int q=0;q<max_q;q++)
  107. for(int p=0;p<max_p;p++)
  108. {
  109. float discr=p*p/(lx*lx)+q*q/(ly*ly)-b*b*v*v/(4*M_PI*M_PI); //-b*b*v*v/(2*M_PI*M_PI)
  110. if(discr>0) self->wpq[i]=v*M_PI*sqrtf(discr);
  111. else self->wpq[i]=-v*M_PI*sqrtf(-discr);
  112. i++;
  113. }
  114. i=0;
  115. for(int x=0;x<w;x++)
  116. for(int p=0;p<max_p;p++)
  117. {
  118. self->sin_px[i]=p*M_PI/lx*sinf(p*M_PI*x/(float)(w-1));
  119. self->cos_px[i]=cosf(p*M_PI*x/(float)(w-1));
  120. i++;
  121. }
  122. i=0;
  123. for(int y=0;y<h;y++)
  124. for(int q=0;q<max_q;q++)
  125. {
  126. self->sin_qy[i]=q*M_PI/ly*sinf(q*M_PI*y/(float)(h-1));
  127. self->cos_qy[i]=cosf(q*M_PI*y/(float)(h-1));
  128. i++;
  129. }
  130. i=0;
  131. for(int y=0;y<h;y++)
  132. for(int x=0;x<w;x++)
  133. {
  134. self->n[i].z=1;
  135. i++;
  136. }
  137. }
  138. void CleanupWater(Water *self)
  139. {
  140. CleanupWaterState(&self->state);
  141. free(self->wpq);
  142. free(self->ampl);
  143. free(self->sin_px);
  144. free(self->cos_px);
  145. free(self->sin_qy);
  146. free(self->cos_qy);
  147. free(self->z);
  148. free(self->n);
  149. }
  150. void CalculateWaterSurfaceAtTime(Water *self,float t)
  151. {
  152. int i;
  153. float decay=expf(-self->v*self->v*self->b*(t-self->t0)/2);
  154. i=0;
  155. for(int q=0;q<self->max_q;q++)
  156. for(int p=0;p<self->max_p;p++)
  157. {
  158. if(self->wpq[i]>=0)
  159. {
  160. self->ampl[i]=(
  161. self->state.apq[i]*cosf(self->wpq[i]*(t-self->t0))+
  162. self->state.bpq[i]*sinf(self->wpq[i]*(t-self->t0))
  163. )*decay;
  164. }
  165. else
  166. {
  167. self->ampl[i]=self->state.apq[i]*expf(self->wpq[i]*(t-self->t0));
  168. }
  169. i++;
  170. }
  171. i=0;
  172. for(int y=0;y<self->h;y++)
  173. for(int x=0;x<self->w;x++)
  174. {
  175. float z_curr=0;
  176. float ndzdx=0;
  177. float ndzdy=0;
  178. float *sin_px_ptr_start=&self->sin_px[x*self->max_p];
  179. float *cos_px_ptr_start=&self->cos_px[x*self->max_p];
  180. float *sin_qy_ptr=&self->sin_qy[y*self->max_q];
  181. float *cos_qy_ptr=&self->cos_qy[y*self->max_q];
  182. float *ampl_ptr=&self->ampl[0];
  183. for(int q=0;q<self->max_q;q++)
  184. {
  185. float *sin_px_ptr=sin_px_ptr_start;
  186. float *cos_px_ptr=cos_px_ptr_start;
  187. float ampl_cos=0;
  188. float ampl_sin=0;
  189. for(int p=0;p<self->max_p;p++)
  190. {
  191. float ampl=*ampl_ptr++;
  192. ampl_sin+=ampl*(*sin_px_ptr++);
  193. ampl_cos+=ampl*(*cos_px_ptr++);
  194. }
  195. ndzdx+=ampl_sin*(*cos_qy_ptr);
  196. ndzdy+=ampl_cos*(*sin_qy_ptr++);
  197. z_curr+=ampl_cos*(*cos_qy_ptr++);
  198. }
  199. self->z[i]=z_curr;
  200. self->n[i].x=ndzdx;
  201. self->n[i].y=ndzdy;
  202. i++;
  203. }
  204. /* i=0;
  205. for(int y=0;y<self->h;y++)
  206. for(int x=0;x<self->w;x++)
  207. {
  208. if(x==0||x==self->w-1) self->n[i].x=0;
  209. else self->n[i].x=(self->z[i-1]-self->z[i+1])*(self->w-1);
  210. if(y==0||y==self->h-1) self->n[i].y=0;
  211. else n[i].y=(self->z[i-self->w]-self->z[i+self->w])*(self->h-1);
  212. self->n[i].z=2.0;
  213. i++;
  214. }*/
  215. }
  216. void AddWaterStateAtTime(Water *self,WaterState *other,float t)
  217. {
  218. float decay=expf(-self->v*self->v*self->b*(t-self->t0)/2);
  219. int i=0;
  220. for(int q=0;q<self->max_q;q++)
  221. for(int p=0;p<self->max_p;p++)
  222. {
  223. float napq,nbpq;
  224. if(self->wpq[i]>0)
  225. {
  226. napq=
  227. self->state.apq[i]*cosf(self->wpq[i]*(t-self->t0))+
  228. self->state.bpq[i]*sinf(self->wpq[i]*(t-self->t0));
  229. nbpq=
  230. -self->state.apq[i]*sinf(self->wpq[i]*(t-self->t0))+
  231. self->state.bpq[i]*cosf(self->wpq[i]*(t-self->t0));
  232. }
  233. else
  234. {
  235. napq=self->state.apq[i]*expf(self->wpq[i]*(t-self->t0));
  236. nbpq=0;
  237. }
  238. self->state.apq[i]=napq*decay+other->apq[i];
  239. self->state.bpq[i]=nbpq*decay+other->bpq[i];
  240. i++;
  241. }
  242. self->t0=t;
  243. }