Water.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /******************************************************************************/
  4. /******************************************************************************
  5. Lake and River can be saved on MainThread and loaded on BuilderThread.
  6. Use 'WorldAreaSync' for that.
  7. /******************************************************************************/
  8. /******************************************************************************/
  9. bool LakeBase::equal(C LakeBase &src)C {return removed_time==src.removed_time && depth_time==src.depth_time && tex_scale_time==src.tex_scale_time && material_time==src.material_time && polys_time==src.polys_time;}
  10. bool LakeBase::newer(C LakeBase &src)C {return removed_time> src.removed_time || depth_time> src.depth_time || tex_scale_time> src.tex_scale_time || material_time> src.material_time || polys_time> src.polys_time;}
  11. bool LakeBase::getRect(Rect &rect)C
  12. {
  13. bool found=false; REPA(polys){C Memc<Vec> &poly=polys[i]; REPA(poly)Include(rect, found, poly[i].xz());}
  14. return found;
  15. }
  16. uint LakeBase::memUsage()C
  17. {
  18. uint size=0; REPA(polys)size+=polys[i].memUsage();
  19. return size;
  20. }
  21. void LakeBase::setDepth(flt depth) {T.depth=depth; T.depth_time.getUTC();}
  22. bool LakeBase::sync(C LakeBase &src)
  23. {
  24. bool changed=false;
  25. changed|=Sync( removed_time, src. removed_time, removed , src.removed );
  26. changed|=Sync( depth_time, src. depth_time, depth , src.depth );
  27. changed|=Sync(tex_scale_time, src.tex_scale_time, tex_scale, src.tex_scale);
  28. changed|=Sync( material_time, src. material_time, material , src.material );
  29. changed|=Sync( polys_time, src. polys_time, polys , src.polys );
  30. return changed;
  31. }
  32. bool LakeBase::undo(C LakeBase &src)
  33. {
  34. bool changed=false;
  35. changed|=Undo ( removed_time, src. removed_time, removed , src.removed );
  36. changed|=Undo ( depth_time, src. depth_time, depth , src.depth );
  37. changed|=Undo (tex_scale_time, src.tex_scale_time, tex_scale, src.tex_scale);
  38. changed|=Undo ( material_time, src. material_time, material , src.material );
  39. changed|=UndoByTime( polys_time, src. polys_time, polys , src.polys );
  40. return changed;
  41. }
  42. void LakeBase::draw(C Color &color, C Color &depth_color)C
  43. {
  44. if(depth_color.a)
  45. {
  46. VI.color(depth_color);
  47. VI.cull (true);
  48. Vec d(0, -depth, 0);
  49. REPA(polys)
  50. {
  51. C Memc<Vec> &poly=polys[i];
  52. Vec prev=poly.first();
  53. REPA(poly)
  54. {
  55. C Vec &next=poly[i];
  56. VI.quad(prev, prev+d, next+d, next);
  57. prev=next;
  58. }
  59. }
  60. VI.end();
  61. }
  62. /*if(side_width)
  63. {
  64. Color c0=ColorAlpha(color, 0.5),
  65. c1=ColorAlpha(color, 0.0);
  66. REPA(polys)
  67. {
  68. Memc<Vec> &poly=polys[i];
  69. Vec prev=poly.first();
  70. REPA(poly)
  71. {
  72. Vec &next=poly[i],
  73. perp=PerpN(prev.xz()-next.xz()).x0y()*side_width; VI.quad(c0, c1, prev, prev+perp, next+perp, next);
  74. prev=next;
  75. }
  76. }
  77. VI.end();
  78. }*/
  79. REPA(polys)DrawPoly(ConstCast(polys[i]), color, color);
  80. }
  81. bool LakeBase::save(File &f)C
  82. {
  83. f.cmpUIntV(0);
  84. f<<removed<<depth<<tex_scale<<material;
  85. f.cmpUIntV(polys.elms()); FREPA(polys){C Memc<Vec> &poly=polys[i]; poly.saveRaw(f);}
  86. f<<removed_time<<depth_time<<tex_scale_time<<material_time<<polys_time;
  87. return f.ok();
  88. }
  89. bool LakeBase::load(File &f)
  90. {
  91. switch(f.decUIntV())
  92. {
  93. case 0:
  94. {
  95. f>>removed>>depth>>tex_scale>>material;
  96. polys.clear().setNum(f.decUIntV()); FREPA(polys){Memc<Vec> &poly=polys[i]; poly.loadRaw(f);}
  97. f>>removed_time>>depth_time>>tex_scale_time>>material_time>>polys_time;
  98. if(f.ok())return true;
  99. }break;
  100. }
  101. return false;
  102. }
  103. bool LakeBase::load(C Str &name)
  104. {
  105. ReadLock rl(WorldAreaSync);
  106. File f; if(f.readTry(name))return load(f); return false;
  107. }
  108. void RiverBase::Vtx::set(flt radius, C Vec &pos) {T.radius=radius; T.pos=pos;}
  109. bool RiverBase::equal(C RiverBase &src)C {return removed_time==src.removed_time && smooth_time==src.smooth_time && depth_time==src.depth_time && tex_scale_time==src.tex_scale_time && material_time==src.material_time && vtx_edge_time==src.vtx_edge_time;}
  110. bool RiverBase::newer(C RiverBase &src)C {return removed_time> src.removed_time || smooth_time> src.smooth_time || depth_time> src.depth_time || tex_scale_time> src.tex_scale_time || material_time> src.material_time || vtx_edge_time> src.vtx_edge_time;}
  111. bool RiverBase::getRect(Rect &rect)C
  112. {
  113. bool found=false; REPA(vtxs){C Vtx &v=vtxs[i]; Include(rect, found, Rect_C(v.pos.xz(), v.radius));}
  114. return found;
  115. }
  116. uint RiverBase::memUsage()C
  117. {
  118. uint size=vtxs.memUsage()+edges.memUsage();
  119. return size;
  120. }
  121. void RiverBase::setSmooth(byte smooth ) {T.smooth =smooth ; T. smooth_time.getUTC();}
  122. void RiverBase::setDepth(flt depth ) {T.depth =depth ; T. depth_time.getUTC();}
  123. void RiverBase::setTexScale(C Vec2 &tex_scale) {T.tex_scale=tex_scale; T.tex_scale_time.getUTC();}
  124. bool RiverBase::sync(C RiverBase &src)
  125. {
  126. bool changed=false;
  127. changed|=Sync( removed_time, src. removed_time, removed , src.removed );
  128. changed|=Sync( smooth_time, src. smooth_time, smooth , src.smooth );
  129. changed|=Sync( depth_time, src. depth_time, depth , src.depth );
  130. changed|=Sync(tex_scale_time, src.tex_scale_time, tex_scale, src.tex_scale);
  131. changed|=Sync( material_time, src. material_time, material , src.material );
  132. if(Sync(vtx_edge_time, src.vtx_edge_time))
  133. {
  134. changed=true;
  135. vtxs =src.vtxs;
  136. edges=src.edges;
  137. }
  138. return changed;
  139. }
  140. bool RiverBase::undo(C RiverBase &src)
  141. {
  142. bool changed=false;
  143. changed|=Undo( removed_time, src. removed_time, removed , src.removed );
  144. changed|=Undo( smooth_time, src. smooth_time, smooth , src.smooth );
  145. changed|=Undo( depth_time, src. depth_time, depth , src.depth );
  146. changed|=Undo(tex_scale_time, src.tex_scale_time, tex_scale, src.tex_scale);
  147. changed|=Undo( material_time, src. material_time, material , src.material );
  148. if(Undo(vtx_edge_time, src.vtx_edge_time))
  149. {
  150. changed=true;
  151. vtxs =src.vtxs;
  152. edges=src.edges;
  153. }
  154. return changed;
  155. }
  156. void RiverBase::draw(C Color &color, C Color &depth_color)C
  157. {
  158. if(depth_color.a)
  159. {
  160. Vec d(0, -depth, 0);
  161. VI.color(depth_color);
  162. //REPA(vtxs )VI.line (vtxs[i].pos, vtxs[i].pos+d);
  163. REPA(edges)VI.quad (vtxs[edges[i].x].pos, vtxs[edges[i].x].pos+d, vtxs[edges[i].y].pos+d, vtxs[edges[i].y].pos);
  164. VI.end ();
  165. }
  166. if(color.a)
  167. {
  168. VI.color(color);
  169. REPA(edges)VI.line (vtxs[edges[i].x].pos, vtxs[edges[i].y].pos);
  170. VI.end ();
  171. VI.color(color);
  172. REPA(vtxs )VI.dot (vtxs[i].pos);
  173. VI.end ();
  174. }
  175. }
  176. bool RiverBase::save(File &f)C
  177. {
  178. f.cmpUIntV(0);
  179. f<<smooth<<depth<<tex_scale<<material;
  180. vtxs .saveRaw(f);
  181. edges.saveRaw(f);
  182. f<<removed_time<<depth_time<<tex_scale_time<<material_time<<vtx_edge_time;
  183. return f.ok();
  184. }
  185. bool RiverBase::load(File &f)
  186. {
  187. switch(f.decUIntV())
  188. {
  189. case 0:
  190. {
  191. f>>smooth>>depth>>tex_scale>>material;
  192. vtxs .loadRaw(f);
  193. edges.loadRaw(f);
  194. f>>removed_time>>depth_time>>tex_scale_time>>material_time>>vtx_edge_time;
  195. if(f.ok())return true;
  196. }break;
  197. }
  198. return false;
  199. }
  200. bool RiverBase::load(C Str &name)
  201. {
  202. ReadLock rl(WorldAreaSync);
  203. File f; if(f.readTry(name))return load(f); return false;
  204. }
  205. void Lake::setMesh(C Project &proj)
  206. {
  207. // set mesh 2D
  208. int vtxs=0; FREPA(polys)if(polys[i].elms()>=3)vtxs+=polys[i].elms();
  209. MeshBase mesh; mesh.create(vtxs, vtxs, 0, 0, EDGE_FLAG);
  210. vtxs=0;
  211. FREPA(polys)
  212. {
  213. Memc<Vec> &poly=polys[i];
  214. if(poly.elms()>=3)
  215. {
  216. FREPA(poly)
  217. {
  218. mesh.vtx .pos (vtxs+i)=poly[i].xzy();
  219. mesh.edge.ind (vtxs+i).set(vtxs+i, vtxs+(i+1)%poly.elms());
  220. mesh.edge.flag(vtxs+i)=ETQ_R;
  221. }
  222. vtxs+=poly.elms();
  223. }
  224. }
  225. // convert mesh 2D to 3D
  226. mesh.edgeToTri(false);
  227. REPA(mesh.vtx)Swap(mesh.vtx.pos(i).y, mesh.vtx.pos(i).z);
  228. // create water
  229. water_mesh.create(mesh, true, depth, proj.gamePath(material));
  230. }
  231. Lake& Lake::checkMesh(C Project &proj) // set mesh if not set yet
  232. {
  233. if(!water_mesh.is())setMesh(proj);
  234. return T;
  235. }
  236. void Lake::render()
  237. {
  238. water_mesh.draw();
  239. }
  240. void River::setMesh(C Project &proj)
  241. {
  242. // set mesh 2D
  243. MeshBase mesh; mesh.create(vtxs.elms(), edges.elms(), 0, 0, VTX_SIZE);
  244. REPA(vtxs)
  245. {
  246. mesh.vtx.pos (i)=vtxs[i].pos.xzy();
  247. mesh.vtx.size(i)=vtxs[i].radius;
  248. }
  249. REPA(edges)mesh.edge.ind(i)=edges[i];
  250. // convert mesh 2D to 3D
  251. REP(Min(8, smooth))mesh.subdivideEdge();
  252. mesh.inflateEdges();
  253. mesh.quadToTri (0.9993f ); // convert quads to tris because not flat rivers can have quads built of 2 non-coplanar tris
  254. mesh.texScale (tex_scale );
  255. REPA(mesh.vtx)Swap(mesh.vtx.pos(i).y, mesh.vtx.pos(i).z);
  256. // create water
  257. water_mesh.create(mesh, false, depth, proj.gamePath(material));
  258. }
  259. River& River::checkMesh(C Project &proj) // set mesh if not set yet
  260. {
  261. if(!water_mesh.is())setMesh(proj);
  262. return T;
  263. }
  264. void River::render()
  265. {
  266. water_mesh.draw();
  267. }
  268. LakeBase::LakeBase() : removed(false), depth(2), tex_scale(1), material(UIDZero) {}
  269. RiverBase::RiverBase() : removed(false), smooth(0), depth(3), tex_scale(1), material(UIDZero) {}
  270. RiverBase::Vtx::Vtx() : radius(2), pos(0) {}
  271. /******************************************************************************/