water.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418
  1. #include "game_logic.h"
  2. #include "water.h"
  3. #include "Berusky3d_kofola_interface.h"
  4. WATER_STRUCT wsWater;
  5. extern LEVELINFO Level;
  6. int w_Check_Oclussion(int x, int y, int z)
  7. {
  8. int real;
  9. int xs = x - 1;
  10. int ys = y - 1;
  11. int i, j, c = 0;
  12. if (ys < 0 || ys + 2 > Level.Size[1] || xs < 0 || xs + 2 > Level.Size[0])
  13. return 1;
  14. for (i = xs; i < xs + 3; i++)
  15. for (j = ys; j < ys + 3; j++) {
  16. gl_Logical2Real(i, j, z + 1, &real, &Level);
  17. if (Level.Level[real])
  18. if (Level.Level[real]->p_Object->Class == 2)
  19. c++;
  20. }
  21. if (c > 1)
  22. return 1;
  23. else
  24. return 0;
  25. }
  26. int w_Check_Oclussion_Vertical(int x, int y, int z)
  27. {
  28. int real;
  29. int ys = y - 1;
  30. int j, c = 0;
  31. if (ys < 0 || ys + 3 > Level.Size[1])
  32. return 1;
  33. for (j = ys; j < ys + 3; j++) {
  34. gl_Logical2Real(x, j, z + 1, &real, &Level);
  35. if (Level.Level[real])
  36. if (Level.Level[real]->p_Object->Class == 2)
  37. c++;
  38. }
  39. if (c > 1)
  40. return 1;
  41. else
  42. return 0;
  43. }
  44. int w_Check_Oclussion_Horizontal(int x, int y, int z)
  45. {
  46. int real;
  47. int xs = x - 1;
  48. int i, c = 0;
  49. if (xs < 0 || xs + 3 > Level.Size[0])
  50. return 1;
  51. for (i = xs; i < xs + 3; i++) {
  52. gl_Logical2Real(i, y, z + 1, &real, &Level);
  53. if (Level.Level[real])
  54. if (Level.Level[real]->p_Object->Class == 2)
  55. c++;
  56. }
  57. if (c > 1)
  58. return 1;
  59. else
  60. return 0;
  61. }
  62. int w_Find_Top(int x, int y, int z)
  63. {
  64. int real;
  65. int i;
  66. for (i = y; i < Level.Size[1]; i++) {
  67. gl_Logical2Real(x, i, z + 1, &real, &Level);
  68. if (Level.Level[real])
  69. if (Level.Level[real]->p_Object->Class == 2
  70. && w_Check_Oclussion(x, i, z))
  71. return i - 1;
  72. }
  73. return Level.Size[1] - 1;
  74. }
  75. int w_Find_Bottom(int x, int y, int z)
  76. {
  77. int real;
  78. int i;
  79. for (i = y; i >= 0; i--) {
  80. gl_Logical2Real(x, i, z + 1, &real, &Level);
  81. if (Level.Level[real])
  82. if (Level.Level[real]->p_Object->Class == 2
  83. && w_Check_Oclussion(x, i, z))
  84. return i + 1;
  85. }
  86. return 0;
  87. }
  88. int w_Find_Left(int x, int y, int z)
  89. {
  90. int real;
  91. int i;
  92. for (i = x; i >= 0; i--) {
  93. gl_Logical2Real(i, y, z + 1, &real, &Level);
  94. if (Level.Level[real])
  95. if (Level.Level[real]->p_Object->Class == 2
  96. && w_Check_Oclussion(i, y, z))
  97. return i + 1;
  98. }
  99. return 0;
  100. }
  101. int w_Find_Right(int x, int y, int z)
  102. {
  103. int real;
  104. int i;
  105. for (i = x; i < Level.Size[0]; i++) {
  106. gl_Logical2Real(i, y, z + 1, &real, &Level);
  107. if (Level.Level[real])
  108. if (Level.Level[real]->p_Object->Class == 2
  109. && w_Check_Oclussion(i, y, z))
  110. return i - 1;
  111. }
  112. return Level.Size[0] - 1;
  113. }
  114. float w_Count_Size(WATER_BOUNDARY * pBoundary)
  115. {
  116. return (pBoundary->Top - pBoundary->Bottom) * (pBoundary->Right -
  117. pBoundary->Left);
  118. }
  119. float w_Count_Aspect_Ratio(WATER_BOUNDARY * pBoundary)
  120. {
  121. float a, b;
  122. a = pBoundary->Top - pBoundary->Bottom;
  123. b = pBoundary->Right - pBoundary->Left;
  124. if (a > b)
  125. return b / a;
  126. else
  127. return a / b;
  128. }
  129. void w_Add_Boundary(int Top, int Left, int Bottom, int Right, int Height)
  130. {
  131. float fTop, fLeft, fBottom, fRight, fHeight;
  132. BOD b;
  133. WATER_BOUNDARY *pBoundary = wsWater.pFirst;
  134. if (Left == -1)
  135. return;
  136. kom_get_fyz_souradnice(Left, 0, Top, &b);
  137. fTop = b.z + 1;
  138. fLeft = b.x - 1;
  139. kom_get_fyz_souradnice(Right, Height, Bottom, &b);
  140. fBottom = b.z - 1;
  141. fRight = b.x + 1;
  142. fHeight = b.y;
  143. while (pBoundary) {
  144. if (pBoundary->Top == fTop &&
  145. pBoundary->Left == fLeft &&
  146. pBoundary->Bottom == fBottom &&
  147. pBoundary->Right == fRight && pBoundary->Height == fHeight)
  148. return;
  149. pBoundary = pBoundary->pNext;
  150. }
  151. pBoundary = (WATER_BOUNDARY *) malloc(sizeof(WATER_BOUNDARY));
  152. pBoundary->Top = fTop;
  153. pBoundary->Left = fLeft;
  154. pBoundary->Bottom = fBottom;
  155. pBoundary->Right = fRight;
  156. pBoundary->Height = fHeight;
  157. pBoundary->pNext = NULL;
  158. pBoundary->Size = w_Count_Size(pBoundary);
  159. pBoundary->AspectRatio = w_Count_Aspect_Ratio(pBoundary);
  160. wsWater.iCount++;
  161. if (!wsWater.pFirst) {
  162. wsWater.pFirst = pBoundary;
  163. wsWater.pLast = pBoundary;
  164. return;
  165. }
  166. wsWater.pLast->pNext = pBoundary;
  167. wsWater.pLast = pBoundary;
  168. }
  169. void w_Construct_Boundary(int x, int y, int z)
  170. {
  171. int Top, Left = -1, Bottom, Right = Level.Size[0] + 1, nLeft, nRight;
  172. int i;
  173. Top = w_Find_Top(x, y, z);
  174. Bottom = w_Find_Bottom(x, y, z);
  175. for (i = Bottom; i <= Top; i++) {
  176. nLeft = w_Find_Left(x, i, z);
  177. nRight = w_Find_Right(x, i, z);
  178. if (nLeft > Left)
  179. Left = nLeft;
  180. if (nRight < Right)
  181. Right = nRight;
  182. }
  183. w_Add_Boundary(Top, Left, Bottom, Right, z);
  184. }
  185. void w_Create_Water_Boundaries(void)
  186. {
  187. int real;
  188. int i, j, k;
  189. wsWater.iCount = 0;
  190. wsWater.pFirst = NULL;
  191. wsWater.pLast = NULL;
  192. for (i = 0; i < Level.Size[2]; i += 2)
  193. for (j = 0; j < Level.Size[0]; j++)
  194. for (k = 0; k < Level.Size[1]; k++) {
  195. gl_Logical2Real(j, k, i, &real, &Level);
  196. if (Level.Level[real])
  197. if (Level.Level[real]->p_Object->Class == 12)
  198. w_Construct_Boundary(j, k, i);
  199. }
  200. return;
  201. }
  202. void w_Release_Water_Boundaries(void)
  203. {
  204. WATER_BOUNDARY *pBoundary = wsWater.pFirst;
  205. WATER_BOUNDARY *pLBoundary;
  206. while (pBoundary) {
  207. pLBoundary = pBoundary;
  208. pBoundary = pBoundary->pNext;
  209. kprintf(1, "free((void *) pLBoundary)");
  210. free((void *) pLBoundary);
  211. }
  212. wsWater.iCount = 0;
  213. wsWater.pFirst = NULL;
  214. wsWater.pLast = NULL;
  215. }
  216. void w_Choose_Random_Boundary(WATER_BOUNDARY * pBoundary, float fx, float fy,
  217. float fz)
  218. {
  219. int iBoundary;
  220. int iCount = 0;
  221. WATER_BOUNDARY *pTBoundary = wsWater.pFirst;
  222. while (pTBoundary) {
  223. if (fx >= pTBoundary->Left && fx <= pTBoundary->Right &&
  224. fy >= pTBoundary->Bottom && fy <= pTBoundary->Top &&
  225. fz >= pTBoundary->Height - 0.25f && fz <= pTBoundary->Height + 0.25f)
  226. iCount++;
  227. pTBoundary = pTBoundary->pNext;
  228. }
  229. if (!iCount)
  230. return;
  231. iBoundary = rand() % iCount;
  232. iCount = 0;
  233. pTBoundary = wsWater.pFirst;
  234. while (pTBoundary) {
  235. if (iCount == iBoundary) {
  236. pBoundary->Bottom = pTBoundary->Bottom;
  237. pBoundary->Top = pTBoundary->Top;
  238. pBoundary->Right = pTBoundary->Right;
  239. pBoundary->Left = pTBoundary->Left;
  240. return;
  241. }
  242. iCount++;
  243. pTBoundary = pTBoundary->pNext;
  244. }
  245. }
  246. void w_Choose_Max_Size_Boundary(WATER_BOUNDARY * pBoundary, float fx,
  247. float fy, float fz)
  248. {
  249. int iBoundary;
  250. int iCount = 0;
  251. float max_size = 0;
  252. WATER_BOUNDARY *pTBoundary = wsWater.pFirst;
  253. while (pTBoundary) {
  254. if (fx >= pTBoundary->Left && fx <= pTBoundary->Right &&
  255. fy >= pTBoundary->Bottom && fy <= pTBoundary->Top &&
  256. fz >= pTBoundary->Height - 0.25f && fz <= pTBoundary->Height + 0.25f &&
  257. pTBoundary->Size > max_size) {
  258. iBoundary = iCount;
  259. max_size = pTBoundary->Size;
  260. }
  261. iCount++;
  262. pTBoundary = pTBoundary->pNext;
  263. }
  264. if (!iCount)
  265. return;
  266. iCount = 0;
  267. pTBoundary = wsWater.pFirst;
  268. while (pTBoundary) {
  269. if (iCount == iBoundary) {
  270. pBoundary->Bottom = pTBoundary->Bottom;
  271. pBoundary->Top = pTBoundary->Top;
  272. pBoundary->Right = pTBoundary->Right;
  273. pBoundary->Left = pTBoundary->Left;
  274. return;
  275. }
  276. iCount++;
  277. pTBoundary = pTBoundary->pNext;
  278. }
  279. }
  280. void w_Choose_Size_Heuristics_Boundary(WATER_BOUNDARY * pBoundary, float fx,
  281. float fy, float fz)
  282. {
  283. int iBoundary = -1;
  284. int iCount = 0;
  285. float max_size = 0;
  286. WATER_BOUNDARY *pTBoundary = wsWater.pFirst;
  287. while (pTBoundary) {
  288. if (fx >= pTBoundary->Left && fx <= pTBoundary->Right &&
  289. fy >= pTBoundary->Bottom && fy <= pTBoundary->Top &&
  290. fz >= pTBoundary->Height - 0.25f && fz <= pTBoundary->Height + 0.25f &&
  291. pTBoundary->Size * pTBoundary->AspectRatio > max_size) {
  292. iBoundary = iCount;
  293. max_size = pTBoundary->Size * pTBoundary->AspectRatio;
  294. }
  295. iCount++;
  296. pTBoundary = pTBoundary->pNext;
  297. }
  298. if (!iCount)
  299. return;
  300. iCount = 0;
  301. pTBoundary = wsWater.pFirst;
  302. while (pTBoundary) {
  303. if (iCount == iBoundary) {
  304. pBoundary->Bottom = pTBoundary->Bottom;
  305. pBoundary->Top = pTBoundary->Top;
  306. pBoundary->Right = pTBoundary->Right;
  307. pBoundary->Left = pTBoundary->Left;
  308. return;
  309. }
  310. iCount++;
  311. pTBoundary = pTBoundary->pNext;
  312. }
  313. }
  314. void w_Choose_Best_Boundary(WATER_BOUNDARY * pBoundary, float fx, float fy,
  315. float fz, int Method)
  316. {
  317. switch (Method) {
  318. case WATER_BOUNDARY_METHOD_RANDOM:
  319. w_Choose_Random_Boundary(pBoundary, fx, fy, fz);
  320. break;
  321. case WATER_BOUNDARY_METHOD_MAX_SIZE:
  322. w_Choose_Max_Size_Boundary(pBoundary, fx, fy, fz);
  323. break;
  324. case WATER_BOUNDARY_METHOD_SIZE_HEURISTICS:
  325. w_Choose_Size_Heuristics_Boundary(pBoundary, fx, fy, fz);
  326. break;
  327. }
  328. }