qtinio

hmmm objects

Apr 24th, 2019
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 113.83 KB | None | 0 0
  1. /*********************************************************************
  2. Simulation obiektów fizycznych ruchomych np. samochody, statki, roboty, itd.
  3. + obsługa obiektów statycznych np. terrain.
  4. **********************************************************************/
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <fstream>
  9. #include <iostream>
  10. #include <time.h>
  11. #include <windows.h>
  12. #include <gl\gl.h>
  13. #include <gl\glu.h>
  14. #include <iterator>
  15. #include <map>
  16. using namespace std;
  17. #ifndef _OBJECTS__H
  18. #include "objects.h"
  19. #endif
  20. #include "graphics.h"
  21. #include "net.h"
  22.  
  23.  
  24. //#include "vector3D.h"
  25. extern FILE *f;
  26. extern HWND main_window;
  27. extern int procent_uzgodniony;
  28. extern int tim;
  29. extern float wysylka;
  30. extern ViewParameters par_view;
  31. extern map<int, MovableObject*> network_vehicles;
  32. extern CRITICAL_SECTION m_cs;
  33.  
  34.  
  35. extern bool terrain_edition_mode;
  36. //extern Terrain terrain;
  37. //extern int iLiczbaCudzychOb;
  38. //extern MovableObject *CudzeObiekty[1000];
  39.  
  40. //enum ItemTypes { ITEM_COIN, ITEM_BARREL, ITEM_TREE, ITEM_BUILDING, ITEM_POINT, ITEM_EDGE };
  41. char *PRZ_nazwy[32] = { "moneta", "beczka", "drzewo", "punkt", "krawedz" };
  42. //enum TreeSubtypes { TREE_POPLAR, TREE_SPRUCE, TREE_BAOBAB, TREE_FANTAZJA };
  43. char *DRZ_nazwy[32] = { "topola", "swierk", "baobab", "fantazja" };
  44.  
  45. unsigned long __log2(unsigned long x) // w starszej wersji Visuala (< 2013) nie ma funkcji log2() w bibliotece math.h !!!
  46. {
  47. long i = -1;
  48. long y = x;
  49. while (y > 0){
  50. y = y >> 1;
  51. i++;
  52. }
  53. return i;
  54. }
  55.  
  56. MovableObject::MovableObject(Terrain *t) // konstruktor
  57. {
  58.  
  59. terrain = t;
  60.  
  61. //iID = (unsigned int)(clock() % 1000); // identyfikator obiektu
  62. iID = (unsigned int)(rand() % 1000); // identyfikator obiektu
  63. fprintf(f, "Nowy obiekt: iID = %d\n", iID);
  64. state.iID_owner = iID; // identyfikator właściciela obiektu
  65. state.if_autonomous = 0;
  66.  
  67. state.money = 1000; // np. dolarów
  68. state.amount_of_fuel = 10.0; // np. kilogramów paliwa
  69.  
  70. time_of_simulation = 0; // symulowany czas rzeczywisty od początku istnienia obiektu
  71.  
  72. F = 0; // siły działające na obiekt
  73. breaking_degree = 0; // stopień hamowania
  74. if_keep_steer_wheel = false;
  75. steer_wheel_speed = 0;
  76.  
  77. F_max = 6000;
  78. alfa_max = PI*45.0 / 180;
  79. mass_own = 800.0; // masa własna obiektu [kg] (bez paliwa)
  80. state.mass_total = mass_own + state.amount_of_fuel; // masa całkowita
  81. Fy = mass_own*9.81; // siła nacisku na podstawę obiektu (na koła pojazdu)
  82. length = 6.0;
  83. szerokosc = 2.7;
  84. height = 1.0;
  85. clearance = 0.0; // wysokość na której znajduje się podstawa obiektu
  86. front_axis_dist = 1.0; // odległość od przedniej osi do przedniego zderzaka
  87. back_axis_dist = 0.2; // odległość od tylniej osi do tylniego zderzaka
  88. this->wheel_ret_speed = 1;
  89. iID_collider = -1; // na razie brak kolizji
  90.  
  91. //vPos.y = clearance+height/2 + 10;
  92. state.vPos = Vector3(220, clearance + height / 2 + 10, -50);
  93. state.wheel_turn_angle = 0;
  94. radius = sqrt(length*length + szerokosc*szerokosc + height*height) / 2 / 1.15;
  95. //vV_angular = Vector3(0,1,0)*40; // początkowa prędkość kątowa (w celach testowych)
  96.  
  97. //moment_wziecia = 0; // czas ostatniego wziecia przedmiotu
  98. //czas_oczekiwania = 1000000000; //
  99. //item_number = -1;
  100.  
  101. number_of_taking_item = -1;
  102. taking_value = 0;
  103. number_of_renewed_item = -1;
  104.  
  105. // obrót obiektu o kąt 30 stopni względem osi y:
  106. quaternion qObr = AsixToQuat(Vector3(0, 1, 0), 40 * PI / 180.0);
  107. state.qOrient = qObr* state.qOrient;
  108. state.vPos.x = 10;
  109.  
  110. // losowanie umiejętności tak by nie było bardzo słabych i bardzo silnych:
  111. planting_skills = 0.2 + (float)(rand() % 5) / 5;
  112. fuel_collection_skills = 0.2 + (float)(rand() % 5) / 5;
  113. money_collection_skills = 0.2 + (float)(rand() % 5) / 5;
  114. //float suma_um = planting_skills + fuel_collection_skills + money_collection_skills;
  115. //float suma_um_los = 0.7 + 0.8*(float)rand()/RAND_MAX; // losuje umiejetność sumaryczną
  116. //planting_skills *= suma_um_los/suma_um;
  117. //fuel_collection_skills *= suma_um_los/suma_um;
  118. //money_collection_skills *= suma_um_los/suma_um;
  119.  
  120. if_selected = false;
  121. }
  122.  
  123. MovableObject::~MovableObject() // destruktor
  124. {
  125. }
  126.  
  127. void MovableObject::ChangeState(ObjectState __state) // przepisanie podanego stanu
  128. {
  129. state = __state;
  130. }
  131.  
  132. ObjectState MovableObject::State() // metoda zwracająca state obiektu łącznie z iID
  133. {
  134. return state;
  135. }
  136.  
  137.  
  138. void MovableObject::Simulation(float dt) // obliczenie nowego stanu na podstawie dotychczasowego,
  139. { // działających sił i czasu, jaki upłynął od ostatniej symulacji
  140.  
  141. if (dt == 0) return;
  142.  
  143. time_of_simulation += dt; // sumaryczny czas wszystkich symulacji obiektu od jego powstania
  144.  
  145. float tarcie = 0.8; // współczynnik tarcia obiektu o podłoże
  146. float tarcie_obr = tarcie; // tarcie obrotowe (w szczególnych przypadkach może być inne niż liniowe)
  147. float tarcie_toczne = 0.30; // współczynnik tarcia tocznego
  148. float sprezystosc = 0.8; // współczynnik sprężystości (0-brak sprężystości, 1-doskonała sprężystość)
  149. float g = 9.81; // przyspieszenie grawitacyjne
  150. float m = mass_own + state.amount_of_fuel; // masa calkowita
  151.  
  152. Vector3 wPol_pop = state.vPos; // zapisanie poprzedniego położenia
  153.  
  154. // obracam układ współrzędnych lokalnych według kwaterniona orientacji:
  155. Vector3 w_przod = state.qOrient.obroc_wektor(Vector3(1, 0, 0)); // na razie oś obiektu pokrywa się z osią x globalnego układu współrzędnych (lokalna oś x)
  156. Vector3 w_gora = state.qOrient.obroc_wektor(Vector3(0, 1, 0)); // wektor skierowany pionowo w górę od podstawy obiektu (lokalna oś y)
  157. Vector3 w_prawo = state.qOrient.obroc_wektor(Vector3(0, 0, 1)); // wektor skierowany w prawo (lokalna oś z)
  158.  
  159. //fprintf(f,"w_przod = (%f, %f, %f)\n",w_przod.x,w_przod.y,w_przod.z);
  160. //fprintf(f,"w_gora = (%f, %f, %f)\n",w_gora.x,w_gora.y,w_gora.z);
  161. //fprintf(f,"w_prawo = (%f, %f, %f)\n",w_prawo.x,w_prawo.y,w_prawo.z);
  162.  
  163. //fprintf(f,"|w_przod|=%f,|w_gora|=%f,|w_prawo|=%f\n",w_przod.length(),w_gora.length(),w_prawo.length() );
  164. //fprintf(f,"ilo skalar = %f,%f,%f\n",w_przod^w_prawo,w_przod^w_gora,w_gora^w_prawo );
  165. //fprintf(f,"w_przod = (%f, %f, %f) w_gora = (%f, %f, %f) w_prawo = (%f, %f, %f)\n",
  166. // w_przod.x,w_przod.y,w_przod.z,w_gora.x,w_gora.y,w_gora.z,w_prawo.x,w_prawo.y,w_prawo.z);
  167.  
  168.  
  169. // rzutujemy vV na składową w kierunku przodu i pozostałe 2 składowe
  170. // składowa w bok jest zmniejszana przez siłę tarcia, składowa do przodu
  171. // przez siłę tarcia tocznego
  172. Vector3 wV_wprzod = w_przod*(state.vV^w_przod),
  173. wV_wprawo = w_prawo*(state.vV^w_prawo),
  174. wV_wgore = w_gora*(state.vV^w_gora);
  175.  
  176. // dodatkowa normalizacja likwidujaca blad numeryczny:
  177. if (state.vV.length() > 0)
  178. {
  179. float blad_dlugosci = (wV_wprzod + wV_wprawo + wV_wgore).length() / state.vV.length();
  180. wV_wprzod = wV_wprzod / blad_dlugosci;
  181. wV_wprawo = wV_wprawo / blad_dlugosci;
  182. wV_wgore = wV_wgore / blad_dlugosci;
  183. }
  184.  
  185. // rzutujemy prędkość kątową vV_angular na składową w kierunku przodu i pozostałe 2 składowe
  186. Vector3 wV_kat_wprzod = w_przod*(state.vV_angular^w_przod),
  187. wV_kat_wprawo = w_prawo*(state.vV_angular^w_prawo),
  188. wV_kat_wgore = w_gora*(state.vV_angular^w_gora);
  189.  
  190.  
  191. // ograniczenia
  192. if (F > F_max) F = F_max;
  193. if (F < -F_max / 2) F = -F_max / 2;
  194. // ruch kół na skutek kręcenia lub puszczenia kierownicy:
  195. if (steer_wheel_speed != 0)
  196. state.wheel_turn_angle += steer_wheel_speed * dt;
  197. else
  198. if (state.wheel_turn_angle > 0)
  199. {
  200. if (!if_keep_steer_wheel)
  201. state.wheel_turn_angle -= wheel_ret_speed * dt;
  202. if (state.wheel_turn_angle < 0) state.wheel_turn_angle = 0;
  203. }
  204. else if (state.wheel_turn_angle < 0)
  205. {
  206. if (!if_keep_steer_wheel)
  207. state.wheel_turn_angle += wheel_ret_speed * dt;
  208. if (state.wheel_turn_angle > 0) state.wheel_turn_angle = 0;
  209. }
  210. // ograniczenia:
  211. if (state.wheel_turn_angle > alfa_max) state.wheel_turn_angle = alfa_max;
  212. if (state.wheel_turn_angle < -alfa_max) state.wheel_turn_angle = -alfa_max;
  213.  
  214.  
  215.  
  216. // obliczam radius skrętu pojazdu na podstawie kąta skrętu kół, a następnie na podstawie radiusia skrętu
  217. // obliczam prędkość kątową (UPROSZCZENIE! pomijam przyspieszenie kątowe oraz właściwą trajektorię ruchu)
  218. if (Fy > 0)
  219. {
  220. float V_kat_skret = 0;
  221. if (state.wheel_turn_angle != 0)
  222. {
  223. float Rs = sqrt(length*length / 4 + (fabs(length / tan(state.wheel_turn_angle)) + szerokosc / 2)*(fabs(length / tan(state.wheel_turn_angle)) + szerokosc / 2));
  224. V_kat_skret = wV_wprzod.length()*(1.0 / Rs);
  225. }
  226. Vector3 wV_kat_skret = w_gora*V_kat_skret*(state.wheel_turn_angle > 0 ? 1 : -1);
  227. Vector3 wV_kat_wgore2 = wV_kat_wgore + wV_kat_skret;
  228. if (wV_kat_wgore2.length() <= wV_kat_wgore.length()) // skręt przeciwdziała obrotowi
  229. {
  230. if (wV_kat_wgore2.length() > V_kat_skret)
  231. wV_kat_wgore = wV_kat_wgore2;
  232. else
  233. wV_kat_wgore = wV_kat_skret;
  234. }
  235. else
  236. {
  237. if (wV_kat_wgore.length() < V_kat_skret)
  238. wV_kat_wgore = wV_kat_skret;
  239.  
  240. }
  241.  
  242. // tarcie zmniejsza prędkość obrotową (UPROSZCZENIE! zamiast masy winienem wykorzystać moment bezwładności)
  243. float V_kat_tarcie = Fy*tarcie_obr*dt / m / 1.0; // zmiana pr. kątowej spowodowana tarciem
  244. float V_kat_wgore = wV_kat_wgore.length() - V_kat_tarcie;
  245. if (V_kat_wgore < V_kat_skret) V_kat_wgore = V_kat_skret; // tarcie nie może spowodować zmiany zwrotu wektora pr. kątowej
  246. wV_kat_wgore = wV_kat_wgore.znorm()*V_kat_wgore;
  247. }
  248.  
  249.  
  250. Fy = m*g*w_gora.y; // siła docisku do podłoża
  251. if (Fy < 0) Fy = 0;
  252. // ... trzeba ją jeszcze uzależnić od tego, czy obiekt styka się z podłożem!
  253. float Fh = Fy*tarcie*breaking_degree; // siła hamowania (UP: bez uwzględnienia poślizgu)
  254.  
  255. float V_wprzod = wV_wprzod.length();// - dt*Fh/m - dt*tarcie_toczne*Fy/m;
  256. if (V_wprzod < 0) V_wprzod = 0;
  257.  
  258. float V_wprawo = wV_wprawo.length();// - dt*tarcie*Fy/m;
  259. if (V_wprawo < 0) V_wprawo = 0;
  260.  
  261.  
  262. // wjazd lub zjazd:
  263. //vPos.y = terrain.GroundHeight(vPos.x,vPos.z); // najprostsze rozwiązanie - obiekt zmienia wysokość bez zmiany orientacji
  264.  
  265. // 1. gdy wjazd na wklęsłość: wyznaczam wysokości terrainu pod narożnikami obiektu (kołami),
  266. // sprawdzam która trójka
  267. // narożników odpowiada najniżej położonemu środkowi ciężkości, gdy przylega do terrainu
  268. // wyznaczam prędkość podbicia (wznoszenia środka pojazdu spowodowanego wklęsłością)
  269. // oraz prędkość kątową
  270. // 2. gdy wjazd na wypukłość to siła ciężkości wywołuje obrót przy dużej prędkości liniowej
  271.  
  272. // punkty zaczepienia kół (na wysokości podłogi pojazdu):
  273. Vector3 P = state.vPos + w_przod*(length / 2 - front_axis_dist) - w_prawo*szerokosc / 2 - w_gora*height / 2,
  274. Q = state.vPos + w_przod*(length / 2 - front_axis_dist) + w_prawo*szerokosc / 2 - w_gora*height / 2,
  275. R = state.vPos + w_przod*(-length / 2 + back_axis_dist) - w_prawo*szerokosc / 2 - w_gora*height / 2,
  276. S = state.vPos + w_przod*(-length / 2 + back_axis_dist) + w_prawo*szerokosc / 2 - w_gora*height / 2;
  277.  
  278. // pionowe rzuty punktów zacz. kół pojazdu na powierzchnię terrainu:
  279. Vector3 Pt = P, Qt = Q, Rt = R, St = S;
  280. //Pt.y = terrain->GroundHeight(P.x, P.z); Qt.y = terrain->GroundHeight(Q.x, Q.z);
  281. //Rt.y = terrain->GroundHeight(R.x, R.z); St.y = terrain->GroundHeight(S.x, S.z);
  282. Pt.y = terrain->height(P); Qt.y = terrain->height(Q);
  283. Rt.y = terrain->height(R); St.y = terrain->height(S);
  284. Vector3 normPQR = normal_vector(Pt, Rt, Qt), normPRS = normal_vector(Pt, Rt, St), normPQS = normal_vector(Pt, St, Qt),
  285. normQRS = normal_vector(Qt, Rt, St); // normalne do płaszczyzn wyznaczonych przez trójkąty
  286.  
  287. //fprintf(f,"P.y = %f, Pt.y = %f, Q.y = %f, Qt.y = %f, R.y = %f, Rt.y = %f, S.y = %f, St.y = %f\n",
  288. // P.y, Pt.y, Q.y, Qt.y, R.y,Rt.y, S.y, St.y);
  289.  
  290. float sryPQR = ((Qt^normPQR) - normPQR.x*state.vPos.x - normPQR.z*state.vPos.z) / normPQR.y, // wys. środka pojazdu
  291. sryPRS = ((Pt^normPRS) - normPRS.x*state.vPos.x - normPRS.z*state.vPos.z) / normPRS.y, // po najechaniu na skarpę
  292. sryPQS = ((Pt^normPQS) - normPQS.x*state.vPos.x - normPQS.z*state.vPos.z) / normPQS.y, // dla 4 trójek kół
  293. sryQRS = ((Qt^normQRS) - normQRS.x*state.vPos.x - normQRS.z*state.vPos.z) / normQRS.y;
  294. float sry = sryPQR; Vector3 norm = normPQR;
  295. if (sry > sryPRS) { sry = sryPRS; norm = normPRS; }
  296. if (sry > sryPQS) { sry = sryPQS; norm = normPQS; }
  297. if (sry > sryQRS) { sry = sryQRS; norm = normQRS; } // wybór trójkąta o środku najniżej położonym
  298.  
  299.  
  300.  
  301. Vector3 wV_kat_wpoziomie = Vector3(0, 0, 0);
  302. // jesli któreś z kół jest poniżej powierzchni terrainu
  303. if ((P.y <= Pt.y + height / 2 + clearance) || (Q.y <= Qt.y + height / 2 + clearance) ||
  304. (R.y <= Rt.y + height / 2 + clearance) || (S.y <= St.y + height / 2 + clearance))
  305. {
  306. // obliczam powstałą prędkość kątową w lokalnym układzie współrzędnych:
  307. Vector3 wobrot = -norm.znorm()*w_gora*0.6;
  308. wV_kat_wpoziomie = wobrot / dt;
  309. }
  310.  
  311. Vector3 wAg = Vector3(0, -1, 0)*g; // przyspieszenie grawitacyjne
  312.  
  313. // jesli wiecej niz 2 kola sa na ziemi, to przyspieszenie grawitacyjne jest rownowazone przez opor gruntu:
  314. if ((P.y <= Pt.y + height / 2 + clearance) + (Q.y <= Qt.y + height / 2 + clearance) +
  315. (R.y <= Rt.y + height / 2 + clearance) + (S.y <= St.y + height / 2 + clearance) > 2)
  316. {
  317. wAg = wAg +
  318. w_gora*(w_gora^wAg)*-1; //przyspieszenie wynikające z siły oporu gruntu
  319. }
  320. else // w przeciwnym wypadku brak sily docisku
  321. Fy = 0;
  322.  
  323.  
  324.  
  325. // składam z powrotem wektor prędkości kątowej:
  326. //vV_angular = wV_kat_wgore + wV_kat_wprawo + wV_kat_wprzod;
  327. state.vV_angular = wV_kat_wgore + wV_kat_wpoziomie;
  328.  
  329.  
  330. float h = sry + height / 2 + clearance - state.vPos.y; // różnica wysokości jaką trzeba pokonać
  331. float V_podbicia = 0;
  332. if ((h > 0) && (state.vV.y <= 0.01))
  333. V_podbicia = 0.5*sqrt(2 * g*h); // prędkość spowodowana podbiciem pojazdu przy wjeżdżaniu na skarpę
  334. if (h > 0) state.vPos.y = sry + height / 2 + clearance;
  335.  
  336. // lub w przypadku zagłębienia się
  337. //fprintf(f,"sry = %f, vPos.y = %f, dt = %f\n",sry,vPos.y,dt);
  338. //fprintf(f,"normPQR.y = %f, normPRS.y = %f, normPQS.y = %f, normQRS.y = %f\n",normPQR.y,normPRS.y,normPQS.y,normQRS.y);
  339.  
  340.  
  341. Vector3 dwPos = state.vV*dt;//vA*dt*dt/2; // czynnik bardzo mały - im większa częstotliwość symulacji, tym mniejsze znaczenie
  342. state.vPos = state.vPos + dwPos;
  343.  
  344. // korekta położenia w przypadku terrainu cyklicznego (toroidalnego) z uwzględnieniem granic:
  345. if (terrain->if_toroidal_world)
  346. {
  347. if (terrain->border_x > 0)
  348. if (state.vPos.x < -terrain->border_x) state.vPos.x += terrain->border_x*2;
  349. else if (state.vPos.x > terrain->border_x) state.vPos.x -= terrain->border_x*2;
  350. if (terrain->border_z > 0)
  351. if (state.vPos.z < -terrain->border_z) state.vPos.z += terrain->border_z*2;
  352. else if (state.vPos.z > terrain->border_z) state.vPos.z -= terrain->border_z*2;
  353. }
  354. else
  355. {
  356. if (terrain->border_x > 0)
  357. if (state.vPos.x < -terrain->border_x) state.vPos.x = -terrain->border_x;
  358. else if (state.vPos.x > terrain->border_x) state.vPos.x = terrain->border_x;
  359. if (terrain->border_z > 0)
  360. if (state.vPos.z < -terrain->border_z) state.vPos.z = -terrain->border_z;
  361. else if (state.vPos.z > terrain->border_z) state.vPos.z = terrain->border_z;
  362. }
  363.  
  364. // Sprawdzenie czy obiekt może się przemieścić w zadane miejsce: Jeśli nie, to
  365. // przemieszczam obiekt do miejsca zetknięcia, wyznaczam nowe wektory prędkości
  366. // i prędkości kątowej, a następne obliczam nowe położenie na podstawie nowych
  367. // prędkości i pozostałego czasu. Wszystko powtarzam w pętli (pojazd znowu może
  368. // wjechać na przeszkodę). Problem z zaokrąglonymi przeszkodami - konieczne
  369. // wyznaczenie minimalnego kroku.
  370.  
  371.  
  372. Vector3 wV_pop = state.vV;
  373.  
  374. // składam prędkości w różnych kierunkach oraz efekt przyspieszenia w jeden wektor: (problem z przyspieszeniem od siły tarcia -> to przyspieszenie
  375. // może działać krócej niż dt -> trzeba to jakoś uwzględnić, inaczej poazd będzie wężykował)
  376. state.vV = wV_wprzod.znorm()*V_wprzod + wV_wprawo.znorm()*V_wprawo + wV_wgore +
  377. Vector3(0, 1, 0)*V_podbicia + state.vA*dt;
  378. // usuwam te składowe wektora prędkości w których kierunku jazda nie jest możliwa z powodu
  379. // przeskód:
  380. // np. jeśli pojazd styka się 3 kołami z nawierzchnią lub dwoma kołami i środkiem ciężkości to
  381. // nie może mieć prędkości w dół podłogi
  382. if ((P.y <= Pt.y + height / 2 + clearance) || (Q.y <= Qt.y + height / 2 + clearance) ||
  383. (R.y <= Rt.y + height / 2 + clearance) || (S.y <= St.y + height / 2 + clearance)) // jeśli pojazd styka się co najm. jednym kołem
  384. {
  385. Vector3 dwV = wV_wgore + w_gora*(state.vA^w_gora)*dt;
  386. if ((w_gora.znorm() - dwV.znorm()).length() > 1) // jeśli wektor skierowany w dół podłogi
  387. state.vV = state.vV - dwV;
  388. }
  389.  
  390. /*fprintf(f," |wV_wprzod| %f -> %f, |wV_wprawo| %f -> %f, |wV_wgore| %f -> %f |vV| %f -> %f\n",
  391. wV_wprzod.length(), (wV_wprzod.znorm()*V_wprzod).length(),
  392. wV_wprawo.length(), (wV_wprawo.znorm()*V_wprawo).length(),
  393. wV_wgore.length(), (wV_wgore.znorm()*wV_wgore.length()).length(),
  394. wV_pop.length(), vV.length()); */
  395.  
  396. // składam przyspieszenia liniowe od sił napędzających i od sił oporu:
  397. state.vA = (w_przod*F) / m*(Fy > 0)*(state.amount_of_fuel > 0) // od sił napędzających
  398. - wV_wprzod.znorm()*(Fh / m + tarcie_toczne*Fy / m)*(V_wprzod > 0.01) // od hamowania i tarcia tocznego (w kierunku ruchu)
  399. - wV_wprawo.znorm()*tarcie*Fy / m*(V_wprawo > 0.01) // od tarcia w kierunku prost. do kier. ruchu
  400. + wAg; // od grawitacji
  401.  
  402.  
  403. // utrata paliwa:
  404. state.amount_of_fuel -= (fabs(F))*(Fy > 0)*dt / 20000;
  405. if (state.amount_of_fuel < 0)state.amount_of_fuel = 0;
  406. state.mass_total = mass_own + state.amount_of_fuel;
  407.  
  408.  
  409. // obliczenie nowej orientacji:
  410. Vector3 w_obrot = state.vV_angular*dt;// + vA_angular*dt*dt/2;
  411. quaternion q_obrot = AsixToQuat(w_obrot.znorm(), w_obrot.length());
  412. //fprintf(f,"w_obrot = (x=%f, y=%f, z=%f) \n",w_obrot.x, w_obrot.y, w_obrot.z );
  413. //fprintf(f,"q_obrot = (w=%f, x=%f, y=%f, z=%f) \n",q_obrot.w, q_obrot.x, q_obrot.y, q_obrot.z );
  414. state.qOrient = q_obrot* state.qOrient;
  415. //fprintf(f,"Pol = (%f, %f, %f) V = (%f, %f, %f) A = (%f, %f, %f) V_kat = (%f, %f, %f) ID = %d\n",
  416. // vPos.x,vPos.y,vPos.z,vV.x,vV.y,vV.z,vA.x,vA.y,vA.z,vV_angular.x,vV_angular.y,vV_angular.z,iID);
  417.  
  418. Item **wsk_prz = NULL;
  419. long liczba_prz_w_prom = terrain->ItemsInRadius(&wsk_prz, state.vPos, this->radius * 2);
  420. // Generuję listę wskaźników przedmiotów w sąsiedztwie symulowanego o radiusiu 2.2, gdyż
  421. // w przypadku obiektów mniejszych wystarczy 2.0 (zakładając, że inny obiekt ma promień co najwyżej taki sam),
  422. // a w przypadku większych to symulator tego większego powinien wcześniej wykryć kolizję
  423. MovableObject **wsk_ob = NULL;
  424. long liczba_ob_w_radiusiu = terrain->ObjectsInRadius(&wsk_ob, state.vPos, this->radius * 2.2 + state.vV.length()*dt);
  425.  
  426. // wykrywanie kolizji z drzewami:
  427. // wykrywanie kolizji z drzewami z użyciem tablicy obszarów:
  428. Vector3 wWR = state.vPos - wPol_pop; // wektor jaki przemierzył pojazd w tym cyklu
  429. Vector3 wWR_zn = wWR.znorm();
  430. float fWR = wWR.length();
  431. for (long i = 0; i < liczba_prz_w_prom; i++)
  432. {
  433. Item *prz = wsk_prz[i];
  434. if (prz->type == ITEM_TREE)
  435. {
  436. // bardzo duze uproszczenie -> traktuje pojazd jako kulę
  437. Vector3 wPolDrz = prz->vPos;
  438. wPolDrz.y = (wPolDrz.y + prz->value > state.vPos.y ? state.vPos.y : wPolDrz.y + prz->value);
  439. float radius_drzewa = prz->param_f[0] * prz->diameter / 2;
  440. if ((wPolDrz - state.vPos).length() < radius*0.8 + radius_drzewa) // jesli kolizja
  441. {
  442. // od wektora predkosci odejmujemy jego rzut na direction od punktu styku do osi drzewa:
  443. // jesli pojazd juz wjechal w ITEM_TREE, to nieco zwiekszamy poprawke
  444. // punkt styku znajdujemy laczac krawedz pojazdu z osia drzewa odcinkiem
  445. // do obu prostopadlym
  446. Vector3 dP = (wPolDrz - state.vPos).znorm(); // wektor, w ktorego kierunku ruch jest niemozliwy
  447. float k = state.vV^dP;
  448. if (k > 0) // jesli jest skladowa predkosci w strone drzewa
  449. {
  450. Vector3 wV_pocz = state.vV;
  451. //vV = wV_pocz - dP*k*(1 + sprezystosc); // odjecie skladowej + odbicie sprezyste
  452.  
  453.  
  454.  
  455. // Uwzględnienie obrotu:
  456. // początkowa energia kinetyczna ruchu zamienia się w energię kinetyczną ruchu postępowego po
  457. // kolizji i energię ruchu obrotowego:
  458. float cos_alfa = state.vV.znorm() ^ dP; // kosinus kąta pomiędzy kierunkiem pojazda-drzewo a wektorem prędkości poj.
  459.  
  460. // przyjmuję, że im większy kąt, tym więcej energii idzie na obrót
  461. state.vV = wV_pocz - dP*k*(1 + sprezystosc)*cos_alfa;
  462. Vector3 wV_spr = wV_pocz - dP*k * 2*cos_alfa; // wektor prędkości po odbiciu w pełni sprężystym
  463. float fV_spr = wV_spr.length(), fV_pocz = wV_pocz.length();
  464. //float fV = vV.length();
  465. float dE = (fV_pocz*fV_pocz - fV_spr*fV_spr)*state.mass_total / 2;
  466. if (dE > 0) // właściwie nie powinno być inaczej!
  467. {
  468. float I = (length*length + szerokosc*szerokosc)*state.mass_total / 12; // moment bezwładności prostokąta
  469. float omega = sqrt(2 * dE / I); // moduł prędkości kątowej wynikający z reszty energii
  470. state.vV_angular = state.vV_angular + dP.znorm()*wV_pocz.znorm()*omega*sprezystosc;
  471. }
  472.  
  473. } // jeśli wektor prędkości w kierunku drzewa
  474. } // jeśli kolizja
  475. } // jeśli drzewo
  476. else if (prz->type == ITEM_WALL)
  477. {
  478. // bardzo duze uproszczenie -> traktuje pojazd jako kulę
  479. Vector3 A = terrain->p[prz->param_i[0]].vPos, B = terrain->p[prz->param_i[1]].vPos; // punkty tworzące krawędź
  480. A.y += terrain->p[prz->param_i[0]].value;
  481. B.y += terrain->p[prz->param_i[1]].value;
  482.  
  483. Vector3 AB = B - A;
  484. //Vector3 AB_zn = AB.znorm();
  485. Vector3 m_pion = Vector3(0,1,0); // vertical muru
  486. float m_wysokosc = prz->value; // od prostej AB do góry jest polowa wysokości, druga polowa idzie w dół
  487.  
  488. // zanim policzymy to co poniżej, można wykonać prostszy test np. odległości pomiędzy spoziomowanymi odcinkami AB i odcinkiem wPol_pop,vPos
  489. // jeśli ta odległość nie będzie większa niż szerokość muru/2+radius to możliwa kolizja:
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496. int liczba_scian = 4; // ściany boczne
  497. Vector3 m_wlewo; // wektor prostopadły do ściany wgłąb muru
  498. Vector3 m_wprzod; // wektor po długości ściany (ApBp)
  499. float m_dlugosc; // długość ściany
  500. float m_szerokosc; // szerokość muru poprzecznie do ściany
  501. Vector3 Ap, Bp; // początek i koniec ściany
  502. float Ap_y, Bp_y; // wysokości w punktach początkowym i końcowym ściany
  503. bool czy_kolizja_zreal = false; // czy kolizja została zrealizowana
  504.  
  505. for (int sciana = 0; sciana < liczba_scian; sciana++)
  506. {
  507. switch (sciana)
  508. {
  509. case 0: // ściana z prawej strony patrząc od punktu A do B
  510. m_wlewo = (m_pion*AB).znorm(); // wektor jednostkowy w lewo od wektora AB i prostopadle do pionu
  511. m_wprzod = m_wlewo*m_pion;
  512. m_dlugosc = AB^m_wprzod;
  513. m_szerokosc = prz->param_f[0];
  514.  
  515. Ap = A - m_wlewo*m_szerokosc / 2;
  516. Bp = B - m_wlewo*m_szerokosc / 2; // rzut odcinka AB na prawą ścianę muru
  517. Ap_y = A.y;
  518. Bp_y = B.y;
  519. break;
  520. case 1: // ściana kolejna w kier. przeciwnym do ruchu wskazówek zegara (prostopadła do AB, przechodząca przez punkt B)
  521. m_wlewo = -AB.znorm(); // wektor jednostkowy w lewo od wektora AB i prostopadle do pionu
  522. m_wprzod = m_wlewo*m_pion;
  523. m_dlugosc = prz->param_f[0];
  524. m_szerokosc = -AB^m_wlewo;
  525.  
  526. Ap = B - m_wprzod*m_dlugosc / 2;
  527. Bp = B + m_wprzod*m_dlugosc / 2;
  528. Ap_y = Bp_y = B.y;
  529.  
  530. break;
  531. case 2:
  532. m_wlewo = -(m_pion*AB).znorm(); // wektor jednostkowy w lewo od wektora AB i prostopadle do pionu
  533. m_wprzod = m_wlewo*m_pion;
  534. m_dlugosc = -AB^m_wprzod;
  535. m_szerokosc = prz->param_f[0];
  536.  
  537. Ap = B - m_wlewo*m_szerokosc / 2;
  538. Bp = A - m_wlewo*m_szerokosc / 2;
  539. Ap_y = B.y;
  540. Bp_y = A.y;
  541. break;
  542. case 3:
  543. m_wlewo = AB.znorm(); // wektor jednostkowy w lewo od wektora AB i prostopadle do pionu
  544. m_wprzod = m_wlewo*m_pion;
  545. m_dlugosc = prz->param_f[0];
  546. m_szerokosc = AB^m_wlewo;
  547.  
  548. Ap = A - m_wprzod*m_dlugosc / 2;
  549. Bp = A + m_wprzod*m_dlugosc / 2;
  550. Ap_y = Bp_y = A.y;
  551. break;
  552. }
  553.  
  554. //Vector3 Al = A + m_wlewo*m_szerokosc / 2, Bl = B + m_wlewo*m_szerokosc / 2; // rzut odcinka AB na lewą ścianę muru
  555. Vector3 RR = punkt_przec_prostej_z_plaszcz(wPol_pop, state.vPos, -m_wlewo, Ap); // punkt przecięcia wektora ruchu ze ścianą prawą
  556. Vector3 QQ = rzut_punktu_na_pl(state.vPos, m_wlewo, Ap); // rzut prostopadły środka pojazdu na płaszczyznę prawej ściany
  557. float odl_zezn_prawa = (QQ - state.vPos) ^ m_wlewo; // odległość ze znakiem śr.pojazdu od pł. prawej: dodatnia jeśli vPos nie przekracza ściany
  558. //float odl_dokladna = odleglosc_pom_punktem_a_odcinkiem(vPos, Ap, Bp);
  559. float cos_kata_pad = wWR_zn^m_wlewo; // kosinus kąta wekt.ruchu w stos. do normalnej ściany (dodatni, gdy pojazd zmierza do ściany od prawej strony)
  560. //Vector3 Ap_granica_kol = Ap - m_wprzod*radius / cos_kata_pad, Bp_granica_kol = Bp + m_wprzod*radius / cos_kata_pad; // odcinek ApBp powiększony z obu stron
  561.  
  562. bool czy_poprzednio_obiekt_przed_sciana = (((RR - wPol_pop) ^ m_wlewo) > 0); // czy w poprzednim cyklu środek poj. znajdował się przed ścianą
  563. bool czy_QQ_na_scianie = ((QQ - Ap).x*(QQ - Bp).x + (QQ - Ap).z*(QQ - Bp).z < 0);
  564. bool czy_RR_na_scianie = ((RR - Ap).x*(RR - Bp).x + (RR - Ap).z*(RR - Bp).z < 0);
  565.  
  566. if ((czy_poprzednio_obiekt_przed_sciana) && (cos_kata_pad > 0) &&
  567. ((odl_zezn_prawa >= 0) && (odl_zezn_prawa < radius*0.8) && (czy_QQ_na_scianie) || // gdy obiekt lekko nachodzi na ścianę
  568. (odl_zezn_prawa < 0) && (czy_RR_na_scianie)) // gdy obiekt ,,przeleciał'' przez ścianę w ciągu cyklu
  569. )
  570. {
  571. float czy_w_przod = ((wWR_zn^m_wprzod) > 0); // czy skłądowa pozioma wektora ruchu skierowana w przód
  572. Vector3 SS = RR - m_wprzod*(2 * czy_w_przod - 1)*radius / cos_kata_pad; // punkt styku obiektu ze ścianą
  573. float odl_od_A = fabs((SS - Ap) ^ m_wprzod); // odległość od punktu A
  574. float wysokosc_muru_wS = Ap_y + (Bp_y - Ap_y)*odl_od_A / m_dlugosc + m_wysokosc / 2; // wysokość muru w punkcie styku
  575. //bool czy_wysokosc_kol = ((SS - Ap).y - this->height / 2 < wysokosc_muru_wS); // test wysokości - czy kolizja
  576. bool czy_wysokosc_kol = ((SS.y - this->height / 2 < wysokosc_muru_wS) && // test wysokości od góry
  577. (SS.y + this->height / 2 > wysokosc_muru_wS - m_wysokosc)); // od dołu
  578. if (czy_wysokosc_kol)
  579. {
  580. float V_prost_pop = state.vV^m_wlewo;
  581. state.vV = state.vV - m_wlewo*V_prost_pop*(1 + sprezystosc); // zamiana kierunku składowej prędkości prostopadłej do ściany
  582.  
  583. // możemy też część energii kinetycznej
  584.  
  585. // cofamy też obiekt przed ścianę, tak jakby się od niej odbił z ustaloną sprężystością:
  586. float poprawka_polozenia = radius*0.8 - odl_zezn_prawa;
  587. state.vPos = state.vPos - m_wlewo* poprawka_polozenia*(1 + sprezystosc);
  588.  
  589. //fprintf(f, "poj. w scianie, cos_kat = %f, w miejscu %f, Vpop = %f, V = %f\n", cos_kata_pad, odl_od_A / m_dlugosc,
  590. // V_prost_pop, vV^m_wlewo);
  591. czy_kolizja_zreal = true;
  592. break; // wyjście z pętli po ścianach, by nie tracić czasu na dalsze sprawdzanie
  593. }
  594. else
  595. {
  596. int x = 1;
  597. }
  598. } // jeśli wykryto kolizję ze ścianą w przestrzeni 2D
  599. } // po ścianach
  600.  
  601. if (czy_kolizja_zreal == false) // jeśli kolizja nie została jeszcze zrealizowana, sprawdzam kolizję ze ścianą dolną
  602. {
  603. m_wlewo = (m_pion*AB).znorm();
  604. m_szerokosc = prz->param_f[0];
  605. Vector3 N = (AB*m_wlewo).znorm(); // normal_vector do dolnej ściany (zwrot do wewnątrz)
  606. Vector3 Ad = A - m_pion*(m_wysokosc / 2), Bd = B - m_pion*(m_wysokosc / 2); // rzuty pionowe punktów A i B na dolną płaszczyznę
  607. Vector3 RR = punkt_przec_prostej_z_plaszcz(wPol_pop, state.vPos, -N, Ad); // punkt przecięcia wektora ruchu ze ścianą prawą
  608. Vector3 RRR = rzut_punktu_na_prosta(RR, Ad, Bd);
  609. float odl_RR_od_RRR = (RR - RRR).length();
  610. Vector3 QQ = rzut_punktu_na_pl(state.vPos, -N, Ad); // rzut prostopadły środka pojazdu na płaszczyznę prawej ściany
  611. float odl_zezn_prawa = (QQ - state.vPos) ^ N; // odległość ze znakiem śr.pojazdu od płaszczyzny: dodatnia jeśli vPos nie przekracza ściany
  612. float odl_praw = (QQ - state.vPos).length();
  613. float x = (Ad - state.vPos) ^ N;
  614. float xx = (RR - state.vPos) ^ wWR_zn;
  615. Vector3 QQQ = rzut_punktu_na_prosta(QQ, Ad, Bd);
  616. float odl_QQ_od_QQQ = (QQ - QQQ).length();
  617. //float odl_dokladna = odleglosc_pom_punktem_a_odcinkiem(vPos, Ap, Bp);
  618. float cos_kata_pad = wWR_zn^N; // kosinus kąta wekt.ruchu w stos. do normalnej ściany (dodatni, gdy pojazd zmierza do ściany od prawej strony)
  619. //Vector3 Ap_granica_kol = Ap - m_wprzod*radius / cos_kata_pad, Bp_granica_kol = Bp + m_wprzod*radius / cos_kata_pad; // odcinek ApBp powiększony z obu stron
  620.  
  621. bool czy_poprzednio_obiekt_przed_sciana = (((RR - wPol_pop) ^ N) > 0); // czy w poprzednim cyklu środek poj. znajdował się przed ścianą
  622.  
  623. bool czy_QQ_na_scianie = ((QQ - Ad).x*(QQ - Bd).x + (QQ - Ad).z*(QQ - Bd).z < 0) && (odl_QQ_od_QQQ < m_szerokosc / 2);
  624. bool czy_RR_na_scianie = ((RR - Ad).x*(RR - Bd).x + (RR - Ad).z*(RR - Bd).z < 0) && (odl_RR_od_RRR < m_szerokosc / 2);
  625.  
  626.  
  627. //fprintf(f, "nr. cyklu = %d, odl_zezn_prawa = %f, x = %f, QQ = (%f,%f,%f), N = (%f,%f,%f), Ad = (%f,%f,%f), vPos = (%f,%f,%f)\n",
  628. // terrain->number_of_displays, odl_zezn_prawa, x, QQ.x, QQ.y, QQ.z, N.x, N.y, N.z, Ad.x, Ad.y, Ad.z, vPos.x, vPos.y, vPos.z);
  629. //fprintf(f, "nr. cyklu = %d, odl_zezn_prawa = %f, odl do RR = %f, cos_kata_pad = %f\n",
  630. // terrain->number_of_displays, odl_zezn_prawa, xx, cos_kata_pad);
  631. //fprintf(f, "vPos.y = %f, Ad.y = %f\n", vPos.y, Ad.y);
  632.  
  633.  
  634. if ((czy_poprzednio_obiekt_przed_sciana) && (cos_kata_pad > 0) &&
  635. ((odl_zezn_prawa >= 0) && (odl_zezn_prawa < radius*0.8) && (czy_QQ_na_scianie) || // gdy obiekt lekko nachodzi na ścianę
  636. (odl_zezn_prawa < 0) && (czy_RR_na_scianie)) // gdy obiekt ,,przeleciał'' przez ścianę w ciągu cyklu
  637. )
  638. {
  639. float V_prost_pop = state.vV^N;
  640. state.vV = state.vV - N*V_prost_pop*(1 + sprezystosc); // zamiana kierunku składowej prędkości prostopadłej do ściany
  641. float poprawka_polozenia = radius*0.8 - odl_zezn_prawa;
  642. state.vPos = state.vPos - N* poprawka_polozenia*(1 + sprezystosc);
  643. //fclose(f);
  644. czy_kolizja_zreal = true;
  645. }
  646.  
  647.  
  648. }
  649.  
  650. } // jeśli mur
  651. } // for po przedmiotach w radiusiu
  652.  
  653.  
  654. // sprawdzam, czy nie najechałem na monetę lub beczkę z paliwem.
  655. // zakładam, że w jednym cylku symulacji mogę wziąć maksymalnie jeden przedmiot
  656. for (long i = 0; i < liczba_prz_w_prom; i++)
  657. {
  658. Item *prz = wsk_prz[i];
  659.  
  660. if ((prz->to_take == 1) &&
  661. ((prz->vPos - state.vPos + Vector3(0, state.vPos.y - prz->vPos.y, 0)).length() < radius))
  662. {
  663. float odl_nasza = (prz->vPos - state.vPos + Vector3(0, state.vPos.y - prz->vPos.y, 0)).length();
  664.  
  665. long value = prz->value;
  666. taking_value = -1;
  667.  
  668. if (prz->type == ITEM_COIN)
  669. {
  670. bool mozna_wziac = false;
  671. // przy dużej wartości nie mogę samodzielnie podnieść pieniążka bez bratniej pomocy innego pojazdu
  672. // odległość bratniego pojazdu od pieniądza nie może być mniejsza od naszej odległości, gdyż wtedy
  673. // to ten inny pojazd zgarnie monetę:
  674. if (value >= 1000)
  675. {
  676. bool bratnia_pomoc = false;
  677. int kto_pomogl = -1;
  678. for (long k = 0; k < liczba_ob_w_radiusiu; k++)
  679. {
  680. MovableObject *inny = wsk_ob[k];
  681. float odl_bratnia = (inny->state.vPos - prz->vPos).length();
  682. if ((inny->iID != iID) && (odl_bratnia < inny->radius * 2) && (odl_nasza < odl_bratnia))
  683. {
  684. bratnia_pomoc = true;
  685. kto_pomogl = inny->iID;
  686. }
  687. }
  688.  
  689. if (!bratnia_pomoc)
  690. {
  691. sprintf(par_view.inscription1, "nie_mozna_wziac_tak_ciezkiego_pieniazka,_chyba_ze_ktos_podjedzie_i_pomoze.");
  692. mozna_wziac = false;
  693. }
  694. else
  695. {
  696. sprintf(par_view.inscription1, "pojazd_o_ID_%d_pomogl_wziac_monete_o_wartosci_%d", kto_pomogl, value);
  697. mozna_wziac = true;
  698. }
  699. }
  700. else
  701. mozna_wziac = true;
  702.  
  703. if (mozna_wziac)
  704. {
  705. taking_value = (float)value*money_collection_skills*(1-procent_uzgodniony/100);
  706. wysylka = (float)value*money_collection_skills*(procent_uzgodniony / 100);
  707. state.money += (long)taking_value;
  708. }
  709.  
  710. //sprintf(inscription2,"Wziecie_gotowki_o_wartosci_ %d",value);
  711. } // jeśli to ITEM_COIN
  712. else if (prz->type == ITEM_BARREL)
  713. {
  714. taking_value = (float)value*fuel_collection_skills;
  715. state.amount_of_fuel += taking_value;
  716. //sprintf(inscription2,"Wziecie_paliwa_w_ilosci_ %d",value);
  717. }
  718.  
  719. if (taking_value > 0)
  720. {
  721. prz->to_take = 0;
  722. prz->if_taken_by_me = 1;
  723. prz->taking_time = time_of_simulation;
  724.  
  725. // SaveMapToFile informacji, by przekazać ją innym aplikacjom:
  726. number_of_taking_item = prz->index;
  727. }
  728. }
  729. } // po przedmiotach w radiusiu
  730.  
  731.  
  732. // Zamiast listować całą tablicę przedmiotów można by zrobić listę wziętych przedmiotów
  733. for (long i = 0; i < terrain->number_of_items; i++)
  734. {
  735. Item *prz = &terrain->p[i];
  736. if ((prz->to_take == 0) && (prz->if_taken_by_me) && (prz->if_renewable) &&
  737. (time_of_simulation - prz->taking_time >= terrain->time_of_item_renewing))
  738. { // jeśli minął pewnien okres czasu przedmiot może zostać przywrócony
  739. prz->to_take = 1;
  740. prz->if_taken_by_me = 0;
  741. number_of_renewed_item = i;
  742. }
  743. }
  744.  
  745.  
  746.  
  747. // kolizje z innymi obiektami
  748. if (iID_collider == iID) // ktoś o numerze iID_collider wykrył kolizję z naszym pojazdem i poinformował nas o tym
  749.  
  750. {
  751. //fprintf(f,"ktos wykryl kolizje - modyf. predkosci\n",iID_collider);
  752. state.vV = state.vV + vdV_collision; // modyfikuje prędkość o wektor obliczony od drugiego (życzliwego) uczestnika
  753. iID_collider = -1;
  754.  
  755. }
  756. else
  757. {
  758. for (long i = 0; i < liczba_ob_w_radiusiu; i++)
  759. {
  760. MovableObject *inny = wsk_ob[i];
  761.  
  762. if ((state.vPos - inny->state.vPos).length() < radius + inny->radius) // jeśli kolizja
  763. {
  764. // zderzenie takie jak w symulacji kul
  765. Vector3 norm_pl_st = (state.vPos - inny->state.vPos).znorm(); // normal_vector do płaszczyzny stycznej - direction odbicia
  766. float m1 = state.mass_total, m2 = inny->state.mass_total; // masy obiektów
  767. float W1 = state.vV^norm_pl_st, W2 = inny->state.vV^norm_pl_st; // wartosci prędkości
  768. if (W2 > W1) // jeśli obiekty się przybliżają
  769. {
  770.  
  771. float Wns = (m1*W1 + m2*W2) / (m1 + m2); // prędkość po zderzeniu całkowicie niesprężystym
  772. float W1s = ((m1 - m2)*W1 + 2 * m2*W2) / (m1 + m2), // prędkość po zderzeniu całkowicie sprężystym
  773. W2s = ((m2 - m1)*W2 + 2 * m1*W1) / (m1 + m2);
  774. float W1sp = Wns + (W1s - Wns)*sprezystosc; // prędkość po zderzeniu sprężysto-plastycznym
  775. float W2sp = Wns + (W2s - Wns)*sprezystosc;
  776.  
  777. state.vV = state.vV + norm_pl_st*(W1sp - W1); // poprawka prędkości (zakładam, że inny w przypadku drugiego obiektu zrobi to jego własny symulator)
  778. iID_collider = inny->iID;
  779. vdV_collision = norm_pl_st*(W2sp - W2);
  780. //fprintf(f,"wykryto i zreal. kolizje z %d W1=%f,W2=%f,W1s=%f,W2s=%f,m1=%f,m2=%f\n",iID_collider,W1,W2,W1s,W2s,m1,m2);
  781. }
  782. //if (fabs(W2 - W1)*dt < (vPos - inny->vPos).length() < 2*radius) vV = vV + norm_pl_st*(W1sp-W1)*2;
  783. }
  784. }
  785. } // do else
  786. delete wsk_prz;
  787. delete wsk_ob;
  788.  
  789. }
  790.  
  791.  
  792.  
  793. void MovableObject::DrawObject()
  794. {
  795. glPushMatrix();
  796.  
  797. glTranslatef(state.vPos.x, state.vPos.y + clearance, state.vPos.z);
  798.  
  799. quaternion k = state.qOrient.AsixAngle();
  800. //fprintf(f,"quaternion = [%f, %f, %f], w = %f\n",qOrient.x,qOrient.y,qOrient.z,qOrient.w);
  801. //fprintf(f,"os obrotu = [%f, %f, %f], kat = %f\n",k.x,k.y,k.z,k.w*180.0/PI);
  802.  
  803. glRotatef(k.w*180.0 / PI, k.x, k.y, k.z);
  804. glPushMatrix();
  805. glTranslatef(-length / 2, -height / 2, -szerokosc / 2);
  806.  
  807. glScalef(length, height, szerokosc);
  808. glCallList(Cube);
  809. glPopMatrix();
  810. if (this->if_selected)
  811. {
  812. float w = 1.1;
  813. glTranslatef(-length / 2 * w, -height / 2 * w, -szerokosc / 2 * w);
  814. glScalef(length*w, height*w, szerokosc*w);
  815. GLfloat Surface[] = { 2.0f, 0.0f, 0.0f, 1.0f };
  816. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Surface);
  817. glCallList(Cube_skel);
  818. }
  819.  
  820. GLfloat Surface[] = { 2.0f, 2.0f, 1.0f, 1.0f };
  821. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Surface);
  822. glRasterPos2f(0.30, 1.20);
  823. glPrint("%d", iID);
  824. glPopMatrix();
  825. }
  826.  
  827.  
  828.  
  829.  
  830.  
  831. Sektor::Sektor(int _loczek, long _w, long _k, bool czy_mapa)
  832. {
  833. w = _w; k = _k;
  834. liczba_obiektow_ruch = 0;
  835. liczba_obiektow_ruch_max = 10;
  836. wob = new MovableObject*[liczba_obiektow_ruch_max];
  837. number_of_items = 0;
  838. number_of_items_max = 10;
  839. wp = new Item*[number_of_items_max];
  840. liczba_oczek = _loczek;
  841. if (czy_mapa)
  842. {
  843. pamiec_dla_mapy(liczba_oczek,false); // mapa wysokości + normalne + typy_nawierzchni
  844. this->liczba_oczek_wyswietlana = liczba_oczek;
  845. liczba_oczek_wyswietlana_pop = liczba_oczek;
  846. }
  847. else
  848. {
  849. typy_naw = NULL;
  850. mapa_wysokosci = NULL;
  851. Norm = NULL;
  852. poziom_wody = NULL;
  853. this->liczba_oczek_wyswietlana = 1;
  854. liczba_oczek_wyswietlana_pop = 1;
  855. }
  856. typ_naw_sek = 0; // parametry standardowe dla całego sektora brane pod uwagę gdy nie ma dokładnej mapy
  857. wysokosc_gruntu_sek = 0;
  858. poziom_wody_sek = -1e10;
  859.  
  860. mapa_wysokosci_edycja = NULL;
  861. Norm_edycja = NULL;
  862. typy_naw_edycja = NULL;
  863. poziom_wody_edycja = NULL;
  864. //fprintf(f, "Konstruktor: utworzono sektor w = %d, k = %d, mapa = %d\n", w, k, mapa_wysokosci);
  865. this->wysokosc_max = -1e10;
  866. }
  867.  
  868. Sektor::~Sektor()
  869. {
  870. delete wob; // to zawsze jest
  871. delete wp; // to też
  872.  
  873. // natomiast to już nie zawsze:
  874. if (mapa_wysokosci)
  875. zwolnij_pamiec_dla_mapy();
  876. //fprintf(f, "Destruktor: Usunieto sektor w = %d, k = %d\n", w, k);
  877. }
  878.  
  879. void Sektor::pamiec_dla_mapy(int __liczba_oczek, bool czy_edycja)
  880. {
  881. float **__mapa_wysokosci = new float*[__liczba_oczek * 2 + 1];
  882. for (int n = 0; n < __liczba_oczek * 2 + 1; n++)
  883. {
  884. __mapa_wysokosci[n] = new float[__liczba_oczek + 1];
  885. }
  886. int liczba_rozdzielczosci = 1+log2(__liczba_oczek); // liczba map o różnych rozdzielczościach aż do mapy 1x1 (jedno oczko, 4 normalne)
  887. Vector3**** __Norm = new Vector3***[liczba_rozdzielczosci];
  888. for (int rozdz = 0; rozdz < liczba_rozdzielczosci; rozdz++)
  889. {
  890. long loczek = __liczba_oczek / (1 << rozdz);
  891. __Norm[rozdz] = new Vector3**[loczek];
  892. for (int k = 0; k < loczek; k++)
  893. {
  894. __Norm[rozdz][k] = new Vector3*[loczek];
  895. for (int n = 0; n < loczek; n++)
  896. __Norm[rozdz][k][n] = new Vector3[4];
  897. }
  898. }
  899. int **__typy_naw = new int*[__liczba_oczek];
  900. for (int k = 0; k < __liczba_oczek; k++)
  901. {
  902. __typy_naw[k] = new int[__liczba_oczek];
  903. for (int n = 0; n < __liczba_oczek; n++)
  904. __typy_naw[k][n] = 0;
  905. }
  906.  
  907. float **__poziom_wody = new float*[__liczba_oczek];
  908. for (int k = 0; k < __liczba_oczek; k++)
  909. {
  910. __poziom_wody[k] = new float[__liczba_oczek];
  911. for (int n = 0; n < __liczba_oczek; n++)
  912. __poziom_wody[k][n] = -1e10;
  913. }
  914.  
  915.  
  916. if (czy_edycja)
  917. {
  918. mapa_wysokosci_edycja = __mapa_wysokosci;
  919. Norm_edycja = __Norm;
  920. typy_naw_edycja = __typy_naw;
  921. poziom_wody_edycja = __poziom_wody;
  922. liczba_oczek_edycja = __liczba_oczek;
  923. }
  924. else
  925. {
  926. mapa_wysokosci = __mapa_wysokosci;
  927. Norm = __Norm;
  928. typy_naw = __typy_naw;
  929. poziom_wody = __poziom_wody;
  930. liczba_oczek = __liczba_oczek;
  931. }
  932. }
  933.  
  934. void Sektor::zwolnij_pamiec_dla_mapy(bool czy_edycja)
  935. {
  936. float **mapa = mapa_wysokosci;
  937. Vector3 ****__N = Norm;
  938. int **__typy_naw = typy_naw;
  939. float **__poziom_wody = poziom_wody;
  940. long loczek = liczba_oczek;
  941.  
  942. if (czy_edycja)
  943. {
  944. mapa = mapa_wysokosci_edycja;
  945. __N = Norm_edycja;
  946. __typy_naw = typy_naw_edycja;
  947. __poziom_wody = poziom_wody_edycja;
  948. loczek = liczba_oczek_edycja;
  949. mapa_wysokosci_edycja = NULL;
  950. Norm_edycja = NULL;
  951. typy_naw_edycja = NULL;
  952. poziom_wody_edycja = NULL;
  953. }
  954. else
  955. {
  956. mapa_wysokosci = NULL;
  957. Norm = NULL;
  958. typy_naw = NULL;
  959. poziom_wody = NULL;
  960. }
  961.  
  962. if (mapa)
  963. {
  964. for (int ww = 0; ww < loczek * 2 + 1; ww++)
  965. delete mapa[ww];
  966. delete mapa;
  967.  
  968. long liczba_rozdzielczosci = 1 + log2(loczek);
  969. for (int rozdz = 0; rozdz < liczba_rozdzielczosci; rozdz++)
  970. {
  971. for (int i = 0; i < loczek / (1 << rozdz); i++)
  972. {
  973. for (int j = 0; j < loczek / (1 << rozdz); j++)
  974. delete __N[rozdz][i][j];
  975. delete __N[rozdz][i];
  976. }
  977. delete __N[rozdz];
  978. }
  979. delete __N;
  980.  
  981. for (int i = 0; i < loczek; i++)
  982. delete __typy_naw[i];
  983. delete __typy_naw;
  984. for (int i = 0; i < loczek; i++)
  985. delete __poziom_wody[i];
  986. delete __poziom_wody;
  987.  
  988. }
  989. }
  990.  
  991. void Sektor::wstaw_przedmiot(Item *p)
  992. {
  993. if (number_of_items == number_of_items_max) // powiekszenie tablicy
  994. {
  995. Item **wp_nowe = new Item*[2 * number_of_items_max];
  996. for (long i = 0; i < number_of_items; i++) wp_nowe[i] = wp[i];
  997. delete wp;
  998. wp = wp_nowe;
  999. number_of_items_max = 2 * number_of_items_max;
  1000. }
  1001. wp[number_of_items] = p;
  1002. number_of_items++;
  1003. }
  1004.  
  1005. void Sektor::usun_przedmiot(Item *p)
  1006. {
  1007. for (long i = 0; i < this->number_of_items;i++)
  1008. if (this->wp[i] == p){
  1009. wp[i] = wp[number_of_items-1];
  1010. number_of_items--;
  1011. break;
  1012. }
  1013. }
  1014.  
  1015. void Sektor::wstaw_obiekt_ruchomy(MovableObject *o)
  1016. {
  1017. if (liczba_obiektow_ruch == liczba_obiektow_ruch_max)
  1018. {
  1019. MovableObject **wob_nowe = new MovableObject*[2 * liczba_obiektow_ruch_max];
  1020. for (long i = 0; i < liczba_obiektow_ruch; i++) wob_nowe[i] = wob[i];
  1021. delete wob;
  1022. wob = wob_nowe;
  1023. liczba_obiektow_ruch_max = 2 * liczba_obiektow_ruch_max;
  1024. }
  1025. wob[liczba_obiektow_ruch] = o;
  1026. liczba_obiektow_ruch++;
  1027. }
  1028. void Sektor::usun_obiekt_ruchomy(MovableObject *o)
  1029. {
  1030. for (long i = liczba_obiektow_ruch - 1; i >= 0; i--)
  1031. if (wob[i] == o){
  1032. wob[i] = wob[liczba_obiektow_ruch - 1];
  1033. liczba_obiektow_ruch--;
  1034. break;
  1035. }
  1036. }
  1037. // obliczenie wektorów normalnych N do płaszczyzn trójkątów, by nie robić tego każdorazowo przy odrysowywaniu
  1038. void Sektor::oblicz_normalne(float sector_size, bool czy_edycja)
  1039. {
  1040. float **mapa = mapa_wysokosci;
  1041. Vector3 ****__Norm = Norm;
  1042. long loczek = liczba_oczek;
  1043.  
  1044. if (czy_edycja){
  1045. mapa = mapa_wysokosci_edycja;
  1046. __Norm = Norm_edycja;
  1047. loczek = liczba_oczek_edycja;
  1048. }
  1049.  
  1050. if (mapa)
  1051. {
  1052. long liczba_rozdzielczosci = 1 + log2(loczek); // gdy podst. rozdzielczość 16x16, mamy 5 rozdzielczości:
  1053. // 16x16, 8x8, 4x4, 2x2, 1x1
  1054. for (int rozdz = 0; rozdz < liczba_rozdzielczosci; rozdz++)
  1055. {
  1056.  
  1057. //fprintf(f, "znaleziono sektor o w = %d, k = %d\n", sek->w, sek->k);
  1058. long zmn = (1 << rozdz); // zmniejszenie rozdzielczości (potęga dwójki)
  1059. long loczek_rozdz = loczek / zmn; // liczba oczek w danym wariancie rozdzielczości
  1060. float rozmiar_pola = sector_size / loczek; // size pola w danym wariancie rozdzielczości
  1061.  
  1062. // tworze listę wyświetlania rysując poszczególne pola mapy za pomocą trójkątów
  1063. // (po 4 trójkąty na każde pole):
  1064. enum tr{ ABC = 0, ADB = 1, BDE = 2, CBE = 3 };
  1065.  
  1066. Vector3 A, B, C, D, E, N;
  1067.  
  1068. for (long w = 0; w < loczek_rozdz; w++)
  1069. for (long k = 0; k < loczek_rozdz; k++)
  1070. {
  1071. A = Vector3(k*rozmiar_pola, mapa[w * 2 * zmn][k*zmn], w*rozmiar_pola);
  1072. B = Vector3((k + 0.5)*rozmiar_pola, mapa[(w * 2 + 1)*zmn][k*zmn+(zmn>1)*zmn/2], (w + 0.5)*rozmiar_pola);
  1073. C = Vector3((k + 1)*rozmiar_pola, mapa[w * 2 * zmn][(k + 1)*zmn], w*rozmiar_pola);
  1074. D = Vector3(k*rozmiar_pola, mapa[(w + 1) * 2 * zmn][k*zmn], (w + 1)*rozmiar_pola);
  1075. E = Vector3((k + 1)*rozmiar_pola, mapa[(w + 1) * 2 * zmn][(k + 1)*zmn], (w + 1)*rozmiar_pola);
  1076.  
  1077. // tworzę trójkąt ABC w górnej części kwadratu:
  1078. // A o_________o C
  1079. // |. .|
  1080. // | . . |
  1081. // | o B |
  1082. // | . . |
  1083. // |._______.|
  1084. // D o o E
  1085.  
  1086. Vector3 AB = B - A;
  1087. Vector3 BC = C - B;
  1088. N = (AB*BC).znorm();
  1089. //d[w][k][ABC] = -(B^N); // dodatkowo wyznaczam wyraz wolny z równania plaszyzny trójkąta
  1090. __Norm[rozdz][w][k][ABC] = N; // dodatkowo zapisuję normalną do płaszczyzny trójkąta
  1091. // trójkąt ADB:
  1092. Vector3 AD = D - A;
  1093. N = (AD*AB).znorm();
  1094. //d[w][k][ADB] = -(B^N);
  1095. __Norm[rozdz][w][k][ADB] = N;
  1096. // trójkąt BDE:
  1097. Vector3 BD = D - B;
  1098. Vector3 DE = E - D;
  1099. N = (BD*DE).znorm();
  1100. //d[w][k][BDE] = -(B^N);
  1101. __Norm[rozdz][w][k][BDE] = N;
  1102. // trójkąt CBE:
  1103. Vector3 CB = B - C;
  1104. Vector3 BE = E - B;
  1105. N = (CB*BE).znorm();
  1106. //d[w][k][CBE] = -(B^N);
  1107. __Norm[rozdz][w][k][CBE] = N;
  1108. }
  1109. } // po rozdzielczościach (od największej do najmniiejszej
  1110. } // jeśli znaleziono mapę sektora
  1111.  
  1112.  
  1113. // dodatkowo wyznaczana jest maksymalna wysokość:
  1114. if (mapa)
  1115. {
  1116. wysokosc_max = -1e10;
  1117. for (long w = 0; w < loczek; w++)
  1118. for (long k = 0; k < loczek; k++)
  1119. if (mapa[w * 2][k] > wysokosc_max)
  1120. wysokosc_max = mapa[w * 2][k];
  1121. }
  1122. else
  1123. wysokosc_max = 0;
  1124. }
  1125.  
  1126. SectorsArray::SectorsArray()
  1127. {
  1128. liczba_komorek = 1000;
  1129. ogolna_liczba_sektorow = 0;
  1130. komorki = new KomorkaTablicy[liczba_komorek];
  1131. for (long i = 0; i < liczba_komorek; i++)
  1132. {
  1133. komorki[i].liczba_sektorow = 0;
  1134. komorki[i].rozmiar_pamieci = 0;
  1135. komorki[i].sektory = NULL;
  1136. }
  1137. // zainicjowanie indeksów skrajnych sektorów (w celu ułatwienia wyszukiwania istniejących sektorów):
  1138. w_min = 1000000;
  1139. w_max = -1000000;
  1140. k_min = 1000000;
  1141. k_max = -1000000;
  1142. }
  1143.  
  1144. SectorsArray::~SectorsArray()
  1145. {
  1146. for (long i = 0; i < liczba_komorek; i++)
  1147. delete komorki[i].sektory;
  1148. delete komorki;
  1149. }
  1150.  
  1151. // wyznaczanie indeksu komórki na podstawie współrzędnych sektora
  1152. unsigned long SectorsArray::wyznacz_klucz(long w, long k)
  1153. {
  1154. unsigned long kl = abs((w^k + w*(w + 1)*k + k*(k - 1)*w)) % liczba_komorek;
  1155. //if (kl < 0) kl = -kl;
  1156.  
  1157. return kl;
  1158. }
  1159.  
  1160. // znajdowanie sektora (zwraca NULL jeśli nie znaleziono)
  1161. Sektor *SectorsArray::znajdz(long w, long k)
  1162. {
  1163. unsigned long klucz = wyznacz_klucz(w, k);
  1164. Sektor *sektor = NULL;
  1165. //fprintf(f, " znajdowanie sektora - klucz = %d, jest to %d sektorow\n", klucz, komorki[klucz].liczba_sektorow);
  1166. for (long i = 0; i < komorki[klucz].liczba_sektorow; i++)
  1167. {
  1168. Sektor *s = komorki[klucz].sektory[i];
  1169. //fprintf(f, " i=%d, w=%d, k=%d\n", i, s->w, s->k);
  1170. if ((s->w == w) && (s->k == k)) {
  1171. sektor = s;
  1172. break;
  1173. }
  1174. }
  1175. return sektor;
  1176. }
  1177.  
  1178. // wstawianie sektora do tablicy
  1179. Sektor *SectorsArray::wstaw(Sektor *s)
  1180. {
  1181. ogolna_liczba_sektorow++;
  1182.  
  1183. if (ogolna_liczba_sektorow > liczba_komorek) // reorganizacja tablicy (by nie było zbyt dużo konfliktów)
  1184. {
  1185. long stara_liczba_komorek = liczba_komorek;
  1186. KomorkaTablicy *stare_komorki = komorki;
  1187. liczba_komorek = stara_liczba_komorek * 2;
  1188. komorki = new KomorkaTablicy[liczba_komorek];
  1189. for (long i = 0; i < liczba_komorek; i++)
  1190. {
  1191. komorki[i].liczba_sektorow = 0;
  1192. komorki[i].rozmiar_pamieci = 0;
  1193. komorki[i].sektory = NULL;
  1194. }
  1195. for (long i = 0; i < stara_liczba_komorek; i++)
  1196. {
  1197. for (long j = 0; j < stare_komorki[i].liczba_sektorow; j++)
  1198. {
  1199. ogolna_liczba_sektorow--;
  1200. wstaw(stare_komorki[i].sektory[j]);
  1201. }
  1202. delete stare_komorki[i].sektory;
  1203. }
  1204. delete stare_komorki;
  1205. }
  1206.  
  1207. long w = s->w, k = s->k;
  1208. long klucz = wyznacz_klucz(w, k);
  1209. long liczba_sekt = komorki[klucz].liczba_sektorow;
  1210. if (liczba_sekt >= komorki[klucz].rozmiar_pamieci) // jesli brak pamieci, to należy ją powiększyć
  1211. {
  1212. long nowy_rozmiar = (komorki[klucz].rozmiar_pamieci == 0 ? 1 : komorki[klucz].rozmiar_pamieci * 2);
  1213. Sektor **sektory2 = new Sektor*[nowy_rozmiar];
  1214. for (long i = 0; i < komorki[klucz].liczba_sektorow; i++) sektory2[i] = komorki[klucz].sektory[i];
  1215. delete komorki[klucz].sektory;
  1216. komorki[klucz].sektory = sektory2;
  1217. komorki[klucz].rozmiar_pamieci = nowy_rozmiar;
  1218. }
  1219. komorki[klucz].sektory[liczba_sekt] = s;
  1220. komorki[klucz].liczba_sektorow++;
  1221.  
  1222. if (w_min > w) w_min = w;
  1223. if (w_max < w) w_max = w;
  1224. if (k_min > k) k_min = k;
  1225. if (k_max < k) k_max = k;
  1226.  
  1227. return komorki[klucz].sektory[liczba_sekt]; // zwraca wskaźnik do nowoutworzonego sektora
  1228. }
  1229.  
  1230. void SectorsArray::usun(Sektor *s)
  1231. {
  1232. long w = s->w, k = s->k;
  1233. long klucz = wyznacz_klucz(w, k);
  1234. long liczba_sekt = komorki[klucz].liczba_sektorow;
  1235. long index = -1;
  1236. for (long i = 0; i < liczba_sekt; i++)
  1237. {
  1238. Sektor *ss = komorki[klucz].sektory[i];
  1239. if ((ss->w == w) && (ss->k == k)) {
  1240. index = i;
  1241. break;
  1242. }
  1243. }
  1244. if (index > -1){
  1245. komorki[klucz].sektory[index] = komorki[klucz].sektory[liczba_sekt - 1];
  1246. komorki[klucz].liczba_sektorow--;
  1247. }
  1248. }
  1249. //**********************
  1250. // Obiekty nieruchome
  1251. //**********************
  1252. Terrain::Terrain()
  1253. {
  1254. bool czy_z_pliku = 1;
  1255. detail_level = 0.6; // stopień szczegółowości wyświetlania przedmiotów i powierzchni terrainu (1 - pełna, 0 - minimalna)
  1256. number_of_displays = 0;
  1257. ts = new SectorsArray();
  1258.  
  1259. number_of_selected_items_max = 100; // to nie oznacza, że tyle tylko można zaznaczyć przedmiotów, ale że tyle jest miejsca w tablicy, która jest automatycznie powiększana
  1260. selected_items = new long[number_of_selected_items_max]; // tablica zaznaczonych przedmiotów (dodatkowo każdy przedmiot posiada pole z informacją o zaznaczeniu)
  1261. number_of_selected_items = 0;
  1262.  
  1263. if (czy_z_pliku)
  1264. {
  1265. char filename[] = "stozki_2.map";
  1266. int result = OpenMapFromFile(filename);
  1267. if (result == -1)
  1268. {
  1269. char path[1024];
  1270. sprintf(path, "..\\%s", filename);
  1271. int result = OpenMapFromFile(path);
  1272. if (result == -1)
  1273. {
  1274. sprintf(path, "..\\..\\%s", filename);
  1275. int result = OpenMapFromFile(path);
  1276. if (result == -1)
  1277. {
  1278. fprintf(f, "Cannot open terrain map!");
  1279. }
  1280. }
  1281. }
  1282. //OpenMapFromFile("terrain.map");
  1283. }
  1284. else
  1285. {
  1286. sector_size = 480; // długość boku kwadratu w [m]
  1287. time_of_item_renewing = 120;
  1288. if_toroidal_world = false;
  1289. border_x = -1;
  1290. border_z = -1;
  1291. number_of_items = 0;
  1292. number_of_items_max = 10;
  1293.  
  1294. p = new Item[number_of_items_max];
  1295. }
  1296. for (long i = 0; i < number_of_items; i++)
  1297. if (p[i].type == ITEM_TREE)
  1298. {
  1299. //p[i].value = 20;
  1300. //this->PlaceItemInTerrain(&p[i]);
  1301. }
  1302.  
  1303. //SaveMapToFile("mapa4");
  1304. //time_of_item_renewing = 120; // czas [s] po jakim przedmiot jest odnawiany
  1305. }
  1306.  
  1307.  
  1308.  
  1309. int Terrain::SaveMapToFile(char filename[])
  1310. {
  1311. FILE *pl = fopen(filename, "wb");
  1312. if (!pl)
  1313. {
  1314. printf("Nie dalo sie otworzyc pliku %s do zapisu!\n", filename);
  1315. return 0;
  1316. }
  1317. long liczba_sekt = 0;
  1318. for (long i = 0; i < ts->liczba_komorek; i++)
  1319. {
  1320. for (long j = 0; j < ts->komorki[i].liczba_sektorow; j++)
  1321. if (ts->komorki[i].sektory[j]->mapa_wysokosci) liczba_sekt++;
  1322. }
  1323.  
  1324. fwrite(&sector_size, sizeof(float), 1, pl);
  1325. fwrite(&time_of_item_renewing, sizeof(float), 1, pl);
  1326. fwrite(&if_toroidal_world, sizeof(bool), 1, pl);
  1327. fwrite(&border_x, sizeof(float), 1, pl);
  1328. fwrite(&border_z, sizeof(float), 1, pl);
  1329. fwrite(&liczba_sekt, sizeof(long), 1, pl);
  1330. fprintf(f, "jest %d sektorow z mapami wysokosciowych + opisem nawierzchni + poz.wody lub innymi informacjami \n", liczba_sekt);
  1331. for (long i = 0; i < ts->liczba_komorek; i++)
  1332. {
  1333. fprintf(f, " w komorce %d tab.hash jest %d sektorow:\n", i, ts->komorki[i].liczba_sektorow);
  1334. for (long j = 0; j < ts->komorki[i].liczba_sektorow; j++)
  1335. {
  1336. Sektor *s = ts->komorki[i].sektory[j];
  1337. int czy_mapa = (s->mapa_wysokosci != 0 ? 1 : 0);
  1338. bool czy_ogolne_wartosci = (s->typ_naw_sek != 0) && (s->wysokosc_gruntu_sek != 0) && (s->poziom_wody_sek > -1e10);
  1339. if (czy_mapa || czy_ogolne_wartosci)
  1340. {
  1341. fwrite(&ts->komorki[i].sektory[j]->w, sizeof(long), 1, pl);
  1342. fwrite(&ts->komorki[i].sektory[j]->k, sizeof(long), 1, pl);
  1343. int loczek = ts->komorki[i].sektory[j]->liczba_oczek;
  1344. fwrite(&loczek, sizeof(int), 1, pl);
  1345. fwrite(&czy_mapa, sizeof(int), 1, pl);
  1346. if (czy_mapa)
  1347. {
  1348.  
  1349. for (int wx = 0; wx < loczek * 2 + 1; wx++)
  1350. fwrite(ts->komorki[i].sektory[j]->mapa_wysokosci[wx], sizeof(float), loczek + 1, pl);
  1351. for (int w = 0; w < loczek; w++)
  1352. fwrite(ts->komorki[i].sektory[j]->typy_naw[w], sizeof(int), loczek, pl);
  1353. for (int w = 0; w < loczek; w++)
  1354. fwrite(ts->komorki[i].sektory[j]->poziom_wody[w], sizeof(float), loczek, pl);
  1355.  
  1356. fprintf(f, " sekt.%d z mapa, w = %d, k = %d, size = %d\n", j, ts->komorki[i].sektory[j]->w,
  1357. ts->komorki[i].sektory[j]->k, loczek);
  1358. }
  1359. else
  1360. {
  1361. fwrite(&ts->komorki[i].sektory[j]->typ_naw_sek, sizeof(int), 1, pl);
  1362. fwrite(&ts->komorki[i].sektory[j]->wysokosc_gruntu_sek, sizeof(float), 1, pl);
  1363. fwrite(&ts->komorki[i].sektory[j]->poziom_wody_sek, sizeof(float), 1, pl);
  1364. fprintf(f, " sekt.%d bez mapy, w = %d, k = %d, size = %d\n", j, ts->komorki[i].sektory[j]->w,
  1365. ts->komorki[i].sektory[j]->k, loczek);
  1366. }
  1367. } // jeśli jakaś informacja jest w sektorze poza przedmiotami i obiektami ruchomymi
  1368. } // po sektorach
  1369. } // po komórkach tabl.hash
  1370. fwrite(&number_of_items, sizeof(long), 1, pl);
  1371. for (long i = 0; i < number_of_items; i++)
  1372. fwrite(&p[i], sizeof(Item), 1, pl);
  1373. long liczba_par_edycji_fald = 10;
  1374. fwrite(&liczba_par_edycji_fald, sizeof(long), 1, pl);
  1375. for (long i = 0; i < liczba_par_edycji_fald; i++)
  1376. fwrite(&pf_rej[i], sizeof(FoldParams), 1,pl);
  1377.  
  1378. fclose(pl);
  1379.  
  1380.  
  1381. //fstream fbin;
  1382. //fbin.open(filename.c_str(), ios::binary | ios::in | ios::out);
  1383.  
  1384. return 1;
  1385. }
  1386.  
  1387.  
  1388.  
  1389. int Terrain::OpenMapFromFile(char filename[])
  1390. {
  1391. FILE *pl = fopen(filename, "rb");
  1392. if (!pl)
  1393. {
  1394. printf("Nie dalo sie otworzyc pliku %s do odczytu!\n", filename);
  1395. fprintf(f, "Nie dalo sie otworzyc pliku %s do odczytu!\n", filename);
  1396. return -1;
  1397. }
  1398.  
  1399. fread(&sector_size, sizeof(float), 1, pl);
  1400. fread(&time_of_item_renewing, sizeof(float), 1, pl);
  1401. fread(&if_toroidal_world, sizeof(bool), 1, pl);
  1402. fread(&border_x, sizeof(float), 1, pl);
  1403. fread(&border_z, sizeof(float), 1, pl);
  1404.  
  1405. long _liczba_sekt = 0; // czyli liczba sektorów
  1406. fread(&_liczba_sekt, sizeof(long), 1, pl);
  1407.  
  1408. fprintf(f, "\nOdczyt danych o terrainie z pliku %s\n\n", filename);
  1409. fprintf(f, " size sektora = %f\n", sector_size);
  1410. fprintf(f, " czas odnowy przedmiotu = %f\n", time_of_item_renewing);
  1411. fprintf(f, " if_toroidal_world = %d\n", if_toroidal_world);
  1412. fprintf(f, " border_x = %f\n", border_x);
  1413. fprintf(f, " border_z = %f\n", border_z);
  1414. fprintf(f, " liczba sekt. = %d\n", _liczba_sekt);
  1415.  
  1416. for (long i = 0; i < _liczba_sekt; i++)
  1417. {
  1418. long w, k;
  1419. int loczek, czy_mapa = true;
  1420. fread(&w, sizeof(long), 1, pl);
  1421. fread(&k, sizeof(long), 1, pl);
  1422. fread(&loczek, sizeof(int), 1, pl);
  1423. fread(&czy_mapa, sizeof(int), 1, pl); // czy dokładna mapa
  1424. fprintf(f, " mapa w=%d, k=%d, l.oczek = %d\n", w, k, loczek);
  1425.  
  1426. Sektor *o = new Sektor(loczek, w, k, czy_mapa);
  1427. ts->wstaw(o);
  1428. if (czy_mapa)
  1429. {
  1430. for (int wx = 0; wx < loczek * 2 + 1; wx++)
  1431. fread(o->mapa_wysokosci[wx], sizeof(float), loczek + 1, pl);
  1432. for (int w = 0; w < loczek; w++)
  1433. fread(o->typy_naw[w], sizeof(int), loczek, pl);
  1434. for (int w = 0; w < loczek; w++)
  1435. fread(o->poziom_wody[w], sizeof(float), loczek, pl);
  1436. o->oblicz_normalne(sector_size);
  1437. }
  1438. else
  1439. {
  1440. fread(&o->typ_naw_sek, sizeof(int), 1, pl);
  1441. fread(&o->wysokosc_gruntu_sek, sizeof(float), 1, pl);
  1442. fread(&o->poziom_wody_sek, sizeof(float), 1, pl);
  1443. }
  1444. }
  1445. long _liczba_przedm = 0;
  1446. fread(&_liczba_przedm, sizeof(long), 1, pl);
  1447. fprintf(f, "Znaleziono w pliku %s przedmioty w liczbie %d\n", filename, _liczba_przedm);
  1448. fclose(f);
  1449. f = fopen("wzr_log.txt", "a");
  1450. p = new Item[_liczba_przedm];
  1451. for (long i = 0; i < _liczba_przedm; i++)
  1452. {
  1453. fread(&p[i], sizeof(Item), 1, pl);
  1454. fprintf(f, " przedm.%d, type = %d, value = %f\n", i,p[i].type,p[i].value);
  1455. fclose(f);
  1456. f = fopen("wzr_log.txt", "a");
  1457. p[i].index = i;
  1458. InsertItemIntoSectors(&p[i]);
  1459. PlaceItemInTerrain(&p[i]);
  1460. if (p[i].if_selected) {
  1461. p[i].if_selected = 0;
  1462. SelectUnselectItemOrGroup(i);
  1463. }
  1464. }
  1465. this->number_of_items_max = this->number_of_items = _liczba_przedm;
  1466.  
  1467. long liczba_par_edycji_fald;
  1468. fread(&liczba_par_edycji_fald, sizeof(long), 1, pl);
  1469. for (long i = 0; i < liczba_par_edycji_fald; i++)
  1470. fread(&pf_rej[i], sizeof(FoldParams), 1, pl);
  1471.  
  1472. fprintf(f, "Koniec wczytywania danych o terrainie.\n");
  1473. fclose(pl);
  1474. return 1;
  1475. }
  1476.  
  1477. void Terrain::SectorCoordinates(long *w, long *k, float x, float z) // na podstawie wsp. położenia punktu (x,z) zwraca wsp. sektora
  1478. {
  1479. // punkt (x,z) = (0,0) odpowiada środkowi sektora (w,k) = (0,0)
  1480. long _k, _w;
  1481. if (x > 0)
  1482. _k = (long)(x / sector_size + 0.5);
  1483. else
  1484. {
  1485. float _kf = x / sector_size - 0.5;
  1486. _k = (long)(_kf); // przy dodatnich rzutowanie obcina w dół, przy ujemnych w górę!
  1487. if ((long)_kf == _kf) _k++;
  1488. }
  1489. if (z > 0)
  1490. _w = (long)(z / sector_size + 0.5);
  1491. else
  1492. {
  1493. float _wf = z / sector_size - 0.5;
  1494. _w = (long)(_wf);
  1495. if ((long)_wf == _wf) _w++;
  1496. }
  1497.  
  1498. *w = _w; *k = _k;
  1499. }
  1500.  
  1501. void Terrain::SectorBeginPosition(float *x, float *z, long w, long k) // na podstawie współrzędnych sektora (w,k)
  1502. { // zwraca położenie punktu początkowego sektora (x,z)
  1503. float _x = (k - 0.5)*sector_size,
  1504. _z = (w - 0.5)*sector_size;
  1505.  
  1506. (*x) = _x;
  1507. (*z) = _z;
  1508. }
  1509.  
  1510. Terrain::~Terrain()
  1511. {
  1512. for (long i = 0; i < ts->liczba_komorek; i++)
  1513. for (long j = 0; j < ts->komorki[i].liczba_sektorow; j++)
  1514. delete ts->komorki[i].sektory[j];
  1515.  
  1516. delete ts;
  1517. delete p;
  1518. }
  1519.  
  1520. // punkt przecięcia prostej przechodzącej przez punkt pol z górną płaszczyzną najwyżej położonego przedmiotu spośród
  1521. // zaznaczonych. Jeśli żaden nie leży na linii przecięcia, to zwracana jest wartość -1e10.
  1522. float Terrain::HighestSelectedItemHeight(Vector3 pol)
  1523. {
  1524. // szukamy przedmiotów w radiusiu
  1525. Item **wsk_prz = NULL;
  1526. long liczba_prz_w_prom = ItemsInRadius(&wsk_prz, pol, 0);
  1527. float wysokosc_maks = -1e10;
  1528. Item *wsk_min = NULL; // wskaźnik do przedmiotu, od którego liczona jest minimalna wysokość
  1529. for (long i = 0; i < liczba_prz_w_prom; i++)
  1530. if (wsk_prz[i]->if_selected)
  1531. {
  1532. float wys_na_p = ItemPointHeight(pol, wsk_prz[i]);
  1533. //if (wsk_prz[i]->type == ITEM_WALL)
  1534. {
  1535. if (wysokosc_maks < wys_na_p)
  1536. {
  1537. wysokosc_maks = wys_na_p;
  1538. wsk_min = wsk_prz[i];
  1539. }
  1540. }
  1541. }
  1542.  
  1543. delete wsk_prz;
  1544. return wysokosc_maks;
  1545. }
  1546.  
  1547. // iteracyjne wyznaczenie kursora 3D z uwazględnieniem wysokości terrainu i zaznaczonych przedmiotów, na których
  1548. // może leżeć nowo-tworzony przedmiot
  1549. Vector3 Terrain::Cursor3D_CoordinatesWithoutParallax(int X, int Y)
  1550. {
  1551. Vector3 w = Vector3(0, 0, 0);
  1552. float wys_na_prz;
  1553. for (int i = 0; i < 7; i++)
  1554. {
  1555. w = Cursor3dCoordinates(X, Y, w.y);
  1556. wys_na_prz = HighestSelectedItemHeight(w);
  1557. if (wys_na_prz > -1e9)
  1558. w.y = wys_na_prz;
  1559. else
  1560. w.y = GroundHeight(w.x, w.z);
  1561. }
  1562. return w;
  1563. }
  1564.  
  1565. void Terrain::PlaceItemInTerrain(Item *prz) // wyzn. par. przedmiotu w odniesieniu do terrainu
  1566. {
  1567. // uzupełnienie wartości niektórych parametrów przedmiotu:
  1568. prz->if_renewable = 1;
  1569. float grubosc = 0;
  1570. switch (prz->type)
  1571. {
  1572. case ITEM_COIN:
  1573. {
  1574. prz->diameter = powf(prz->value / 100, 0.4);
  1575. grubosc = 0.2*prz->diameter;
  1576.  
  1577. prz->to_take = 1;
  1578. prz->diameter_visual = sqrt(prz->diameter*prz->diameter + grubosc*grubosc);
  1579. break;
  1580. }
  1581. case ITEM_BARREL:
  1582. {
  1583. prz->diameter = powf((float)prz->value / 50, 0.4);
  1584. grubosc = 2 * prz->diameter;
  1585. //prz->vPos.y = grubosc + GroundHeight(prz->vPos.x, prz->vPos.z);
  1586. prz->to_take = 1;
  1587. prz->diameter_visual = sqrt(prz->diameter*prz->diameter + grubosc*grubosc);
  1588. break;
  1589. }
  1590. case ITEM_TREE:
  1591. prz->to_take = 0;
  1592.  
  1593. switch (prz->subtype)
  1594. {
  1595. case TREE_POPLAR:
  1596. {
  1597. prz->diameter = 0.65 + prz->value / 40;
  1598. break;
  1599. }
  1600. case TREE_SPRUCE:
  1601. {
  1602. prz->diameter = prz->value / 10;
  1603. break;
  1604. }
  1605. case TREE_BAOBAB:
  1606. {
  1607. prz->diameter = prz->value / 5;
  1608. break;
  1609. }
  1610. case TREE_FANTAZJA:
  1611. {
  1612. prz->diameter = prz->value / 10;
  1613. break;
  1614. }
  1615. }
  1616. //prz->vPos.y = prz->value + GroundHeight(prz->vPos.x, prz->vPos.z);
  1617. prz->diameter_visual = prz->value;
  1618. grubosc = prz->value;
  1619. break;
  1620. case ITEM_POINT:
  1621. {
  1622. //prz->vPos.y = 0.0 + GroundHeight(prz->vPos.x, prz->vPos.z);
  1623. break;
  1624. }
  1625. } // switch type przedmiotu
  1626.  
  1627. // obliczenie wysokości na jakiej leży przedmiot
  1628. if (prz->param_f[1] > -1e10) // gdy leży on na jakimś innym przedmiocie prz->param_f[1] jest wysokością od której zaczynamy poszukiwania
  1629. { // jeśli schodząc w dół żadnego przedmiotu nie napotkamy, to przedmiot znajdzie się na gruncie
  1630. prz->vPos.y = grubosc + prz->param_f[1];
  1631. prz->vPos.y = grubosc + height(prz->vPos);
  1632. }
  1633. else // gdy leży bezpośrednio na gruncie
  1634. prz->vPos.y = grubosc + GroundHeight(prz->vPos.x, prz->vPos.z);
  1635. }
  1636.  
  1637. long Terrain::InsertItemToArrays(Item prz)
  1638. {
  1639. long ind = number_of_items;
  1640. if (number_of_items >= number_of_items_max) // gdy nowy przedmiot nie mieści się w tablicy przedmiotów
  1641. {
  1642. long nowa_liczba_przedmiotow_max = 2 * number_of_items_max;
  1643. Item *p_nowe = new Item[nowa_liczba_przedmiotow_max];
  1644. for (long i = 0; i < number_of_items; i++) {
  1645. p_nowe[i] = p[i];
  1646. DeleteItemFromSectors(&p[i]); // trzeba to zrobić gdyż zmieniają się wskaźniki !
  1647. InsertItemIntoSectors(&p_nowe[i]);
  1648. }
  1649. delete p;
  1650. p = p_nowe;
  1651. number_of_items_max = nowa_liczba_przedmiotow_max;
  1652. }
  1653. prz.index = ind;
  1654. p[ind] = prz;
  1655.  
  1656. fprintf(f, "Utworzono przedmiot %d index = %d, type = %d (%s)\n", &p[ind], ind, p[ind].type, PRZ_nazwy[p[ind].type]);
  1657. PlaceItemInTerrain(&p[ind]);
  1658. InsertItemIntoSectors(&p[ind]);
  1659. //fprintf(f,"wstawiam przedmiot %d w miejsce (%f, %f, %f)\n",i,terrain.p[ind].vPos.x,terrain.p[ind].vPos.y,terrain.p[ind].vPos.z);
  1660.  
  1661.  
  1662. number_of_items++;
  1663. return ind;
  1664. }
  1665.  
  1666. void Terrain::SelectUnselectItemOrGroup(long nr_prz)
  1667. {
  1668. if (p[nr_prz].group > -1) // zaznaczanie/ odznaczanie grupy
  1669. {
  1670. long group = p[nr_prz].group;
  1671. if (p[nr_prz].if_selected) // odznaczanie grupy
  1672. {
  1673. for (long i = 0; i < number_of_items; i++)
  1674. if (p[i].group == group)
  1675. {
  1676. p[i].if_selected = 0;
  1677. for (long j = 0; j < number_of_selected_items; j++) // przeszukujemy listę zaznaczonych przedmiotów by usunąć zaznaczenie
  1678. {
  1679. if (selected_items[j] == i)
  1680. {
  1681. selected_items[j] = selected_items[number_of_selected_items - 1];
  1682. number_of_selected_items--;
  1683. }
  1684. }
  1685. }
  1686. }
  1687. else // zaznaczanie grupy
  1688. {
  1689. for (long i = 0; i < number_of_items; i++)
  1690. if (p[i].group == group)
  1691. {
  1692. p[i].if_selected = 1;
  1693. if (number_of_selected_items == number_of_selected_items_max) // trzeba powiększyć tablicę
  1694. {
  1695. long *__zazn_przedm = new long[number_of_selected_items_max * 2];
  1696. for (long j = 0; j < number_of_selected_items; j++) __zazn_przedm[j] = selected_items[j];
  1697. delete selected_items;
  1698. selected_items = __zazn_przedm;
  1699. number_of_selected_items_max *= 2;
  1700. }
  1701. selected_items[number_of_selected_items] = i; // wstawiam na koniec listy
  1702. number_of_selected_items++;
  1703. }
  1704. }
  1705. }
  1706. else // zaznaczanie/odznaczanie przedmiotu
  1707. {
  1708. p[nr_prz].if_selected = 1 - p[nr_prz].if_selected;
  1709. char lan[128];
  1710. if (p[nr_prz].if_selected)
  1711. sprintf(lan, "zaznaczono_przedmiot_%d,_razem_%d_zaznaczonych",
  1712. nr_prz, number_of_selected_items + 1);
  1713. else
  1714. sprintf(lan, "odznaczono_przedmiot_%d__wcisnij_SHIFT+RMB_by_odznaczyc_wszystkie", nr_prz);
  1715. SetWindowText(main_window, lan);
  1716. if (p[nr_prz].if_selected) // dodaje do osobnej listy zaznaczonych przedmiotów
  1717. {
  1718. if (number_of_selected_items == number_of_selected_items_max) // trzeba powiększyć tablicę
  1719. {
  1720. long *__zazn_przedm = new long[number_of_selected_items_max * 2];
  1721. for (long i = 0; i < number_of_selected_items; i++) __zazn_przedm[i] = selected_items[i];
  1722. delete selected_items;
  1723. selected_items = __zazn_przedm;
  1724. number_of_selected_items_max *= 2;
  1725. }
  1726. selected_items[number_of_selected_items] = nr_prz; // wstawiam na koniec listy
  1727. number_of_selected_items++;
  1728. }
  1729. else // usuwam z osobnej listy zaznaczonych przedmiotów
  1730. {
  1731. for (long i = 0; i < number_of_selected_items; i++) // przeszukujemy listę zaznaczonych przedmiotów by usunąć zaznaczenie
  1732. {
  1733. if (selected_items[i] == nr_prz)
  1734. {
  1735. selected_items[i] = selected_items[number_of_selected_items - 1];
  1736. number_of_selected_items--;
  1737. }
  1738. }
  1739. }
  1740. }
  1741. }
  1742.  
  1743. // UWAGA! Na razie procedura słaba pod względem obliczeniowym (pętla po przedmiotach x po zaznaczonych przedmiotach)
  1744. // z powodu występowania krawędzi, które są zależne od punktów
  1745. void Terrain::DeleteSelectItems()
  1746. {
  1747. // sprawdzenie czy wśród przeznaczonych do usunięcia są punkty, które mogę być powiązane z krawędziami.
  1748. // Jeśli tak, to krawędzie również należy usunąć - można to zrobić poprzez dołączenie ich do listy zaznaczonych:
  1749. for (long i = 0; i < number_of_selected_items; i++)
  1750. {
  1751. long nr_prz = selected_items[i];
  1752. if (p[nr_prz].type == ITEM_POINT)
  1753. for (long j = 0; j < number_of_items; j++)
  1754. if (((p[j].type == ITEM_EDGE) || (p[j].type == ITEM_WALL)) && (p[j].if_selected == 0) && ((p[j].param_i[0] == nr_prz) || (p[j].param_i[1] == nr_prz)))
  1755. SelectUnselectItemOrGroup(j);
  1756. }
  1757.  
  1758.  
  1759. fprintf(f, "\n\nUsu.prz.: liczba przedm = %d, liczba zazn = %d\n", number_of_items,number_of_selected_items);
  1760. fprintf(f, " lista przedmiotow:\n");
  1761. for (long i = 0; i < number_of_items; i++){
  1762. fprintf(f, "%d: %d (%s) o wartosci %f\n", i, p[i].type,PRZ_nazwy[p[i].type], p[i].value);
  1763. if (p[i].type == ITEM_EDGE)
  1764. fprintf(f, " krawedz pomiedzy punktami %d a %d\n", p[i].param_i[0], p[i].param_i[1]);
  1765. }
  1766.  
  1767. for (long i = 0; i < number_of_selected_items; i++)
  1768. {
  1769. long nr_prz = selected_items[i];
  1770.  
  1771. fprintf(f, " usuwam prz %d: %d (%s) o wartosci %f\n", nr_prz, p[nr_prz].type,PRZ_nazwy[p[nr_prz].type], p[nr_prz].value);
  1772.  
  1773. DeleteItemFromSectors(&p[nr_prz]);
  1774.  
  1775. // usunięcie przedmiotu z listy przedmiotów:
  1776. if (nr_prz != number_of_items - 1)
  1777. {
  1778. DeleteItemFromSectors(&p[number_of_items - 1]);
  1779. p[nr_prz] = p[number_of_items - 1]; // przepisuje w miejsce usuwanego ostatni przedmiot na liście
  1780. p[nr_prz].index = nr_prz;
  1781.  
  1782. // przedmiot ostatni na liście uzyskuje nowy index i jeśli jest to punkt, to trzeba poprawić też odwołania do niego w krawędziach:
  1783. if (p[number_of_items - 1].type == ITEM_POINT)
  1784. for (long j = 0; j < number_of_items;j++)
  1785. if ((p[j].type == ITEM_EDGE) || (p[j].type == ITEM_WALL))
  1786. {
  1787. if (p[j].param_i[0] == number_of_items - 1) p[j].param_i[0] = nr_prz;
  1788. if (p[j].param_i[1] == number_of_items - 1) p[j].param_i[1] = nr_prz;
  1789. }
  1790.  
  1791.  
  1792. InsertItemIntoSectors(&p[nr_prz]); // wstawiam go w sektory
  1793. // zamiana numerów na liście zaznaczonych jeśli ostatnmi na niej występuje:
  1794. if (p[nr_prz].if_selected)
  1795. for (long k = i + 1; k < number_of_selected_items; k++)
  1796. if (selected_items[k] == number_of_items - 1) selected_items[k] = nr_prz;
  1797. }
  1798. // być może trzeba by jeszcze pozamieniać wskaźniki przedmiotów w sektorach
  1799.  
  1800. number_of_items--;
  1801. }
  1802. number_of_selected_items = 0;
  1803.  
  1804. }
  1805.  
  1806. void Terrain::NewMap()
  1807. {
  1808. for (long i = 0; i < ts->liczba_komorek; i++)
  1809. for (long j = 0; j < ts->komorki[i].liczba_sektorow; j++)
  1810. delete ts->komorki[i].sektory[j];
  1811.  
  1812. delete ts;
  1813. delete p;
  1814. this->number_of_items = 0;
  1815. this->number_of_items_max = 10;
  1816. p = new Item[number_of_items_max];
  1817. ts = new SectorsArray();
  1818.  
  1819. number_of_selected_items = 0;
  1820. }
  1821.  
  1822. float Terrain::GroundHeight(float x, float z) // określanie wysokości dla punktu o wsp. (x,z)
  1823. {
  1824. float y = 0; // wysokość standardowa;
  1825.  
  1826. long w, k;
  1827. this->SectorCoordinates(&w, &k, x, z); // w,k - współrzędne sektora, w którym znajduje się punkt (x,z)
  1828.  
  1829. Sektor *s = ts->znajdz(w, k);
  1830.  
  1831. float **mapa = NULL;
  1832. Vector3 ****__Norm = NULL;
  1833. long loczek = 0;
  1834. if (s)
  1835. {
  1836. if (s->mapa_wysokosci_edycja)
  1837. {
  1838. mapa = s->mapa_wysokosci_edycja;
  1839. __Norm = s->Norm_edycja;
  1840. loczek = s->liczba_oczek_edycja;
  1841. }
  1842. else
  1843. {
  1844. mapa = s->mapa_wysokosci;
  1845. __Norm = s->Norm;
  1846. loczek = s->liczba_oczek;
  1847. }
  1848. }
  1849.  
  1850. if (mapa)
  1851. {
  1852. float rozmiar_pola = (float)this->sector_size / loczek;
  1853. float x_pocz_sek, z_pocz_sek; // współrzędne położenia początku sektora
  1854. this->SectorBeginPosition(&x_pocz_sek, &z_pocz_sek, w, k);
  1855. float x_lok = x - x_pocz_sek, z_lok = z - z_pocz_sek; // współrzędne lokalne wewnątrz sektora
  1856. long k_lok = (long)(x_lok / rozmiar_pola), w_lok = (long)(z_lok / rozmiar_pola); // lokalne współrzędne pola w sektorze
  1857.  
  1858.  
  1859. if ((k_lok < 0) || (w_lok < 0))
  1860. {
  1861. fprintf(f,"procedura Terrain::height: k i w lokalne nie moga byc ujemne!\n");
  1862. fclose(f);
  1863. exit(1);
  1864. }
  1865.  
  1866. if ((k_lok > loczek - 1) || (w_lok > loczek - 1))
  1867. {
  1868. fprintf(f, "procedura Terrain::height: k i w lokalne nie moga byc wieksze od liczby oczek - 1!\n");
  1869. fclose(f);
  1870. exit(1);
  1871. }
  1872.  
  1873. // tworzę trójkąt ABC w górnej części kwadratu:
  1874. // A o_________o C
  1875. // |. .|
  1876. // | . . |
  1877. // | o B |
  1878. // | . . |
  1879. // |._______.|
  1880. // D o o E
  1881. // wyznaczam punkt B - środek kwadratu oraz trójkąt, w którym znajduje się punkt
  1882. Vector3 B = Vector3((k_lok + 0.5)*rozmiar_pola, mapa[w_lok * 2 + 1][k_lok], (w_lok + 0.5)*rozmiar_pola);
  1883. enum tr{ ABC = 0, ADB = 1, BDE = 2, CBE = 3 }; // trójkąt w którym znajduje się punkt
  1884. int trojkat = 0;
  1885. if ((B.x > x_lok) && (fabs(B.z - z_lok) < fabs(B.x - x_lok))) trojkat = ADB;
  1886. else if ((B.x < x_lok) && (fabs(B.z - z_lok) < fabs(B.x - x_lok))) trojkat = CBE;
  1887. else if (B.z > z_lok) trojkat = ABC;
  1888. else trojkat = BDE;
  1889.  
  1890. // wyznaczam normalną do płaszczyzny a następnie współczynnik d z równania płaszczyzny
  1891. Vector3 N = __Norm[0][w_lok][k_lok][trojkat];
  1892. float dd = -(B^N); // wyraz wolny z równania plaszyzny trójkąta
  1893. //float y;
  1894. if (N.y > 0) y = (-dd - N.x*x_lok - N.z*z_lok) / N.y;
  1895. else y = 0;
  1896.  
  1897. } // jeśli sektor istnieje i zawiera mapę wysokości
  1898.  
  1899. return y;
  1900. }
  1901.  
  1902. // wysokość na jakiej znajdzie się przecięcie pionowej linii przech. przez pol na górnej powierzchni przedmiotu
  1903. float Terrain::ItemPointHeight(Vector3 pol, Item *prz)
  1904. {
  1905. float wys_na_p = -1e10;
  1906. if (prz->type == ITEM_WALL)
  1907. {
  1908. // sprawdzamy, czy rzut pionowy pol mieści się w prostokącie muru:
  1909. Vector3 A = p[prz->param_i[0]].vPos, B = p[prz->param_i[1]].vPos; // punkty tworzące krawędź
  1910. A.y += p[prz->param_i[0]].value;
  1911. B.y += p[prz->param_i[1]].value;
  1912.  
  1913. Vector3 AB = B - A;
  1914. Vector3 m_pion = Vector3(0, 1, 0); // vertical muru
  1915. float m_wysokosc = prz->value; // od prostej AB do góry jest polowa wysokości, druga polowa idzie w dół
  1916. Vector3 m_wlewo = (m_pion*AB).znorm(); // wektor jednostkowy w lewo od wektora AB i prostopadle do pionu
  1917. float m_szerokosc = prz->param_f[0];
  1918.  
  1919. Vector3 N = (AB*m_wlewo).znorm(); // normal_vector do płaszczyzny górnej muru
  1920. Vector3 R = punkt_przec_prostej_z_plaszcz(pol, pol - m_pion, N, A); // punkt spadku punktu pol na górną pł. muru
  1921. Vector3 RR = rzut_punktu_na_prosta(R, A, B); // rzut punktu R na prostą AB
  1922. bool czy_RR_na_odcAB = (((RR - A) ^ (RR - B)) < 0); // czy punkt ten leży na odcinku AB (mieści się na długości muru)
  1923. Vector3 R_RR = RR - R;
  1924. float odl = fabs(R_RR.x*m_wlewo.x + R_RR.z*m_wlewo.z); // odległość R od osi muru (niewymagająca pierwiastkowania)
  1925. if ((odl < m_szerokosc / 2) && (czy_RR_na_odcAB)) // warunek tego, że rzut pionowy pol mieści się w prostokącie muru
  1926. wys_na_p = (R.y + m_wysokosc / 2); // wysokość punktu pol nad górną pł. muru
  1927. } // jeśli mur
  1928. return wys_na_p;
  1929. }
  1930.  
  1931. // Określenie wysokości nad najbliższym przedmiotem (obiektem ruchomym) lub gruntem patrząc w dół od punktu pol
  1932. // wysokość może być ujemna, co oznacza zagłębienie w gruncie lub przedmiocie
  1933. float Terrain::height(Vector3 pol)
  1934. {
  1935. // szukamy przedmiotów w radiusiu
  1936. Item **wsk_prz = NULL;
  1937. long liczba_prz_w_prom = ItemsInRadius(&wsk_prz, pol, 0);
  1938.  
  1939. float wysokosc_gruntu = GroundHeight(pol.x, pol.z);
  1940. float roznica_wys_min = pol.y-wysokosc_gruntu;
  1941.  
  1942. Item *wsk_min = NULL; // wskaźnik do przedmiotu, od którego liczona jest minimalna wysokość
  1943. for (long i = 0; i < liczba_prz_w_prom; i++)
  1944. {
  1945. float wys_na_p = this->ItemPointHeight(pol, wsk_prz[i]);
  1946. if (wys_na_p > -1e10)
  1947. if (wsk_prz[i]->type == ITEM_WALL)
  1948. {
  1949. float roznica_wys = pol.y - wys_na_p; // wysokość punktu pol nad górną pł. muru
  1950. float m_wysokosc = wsk_prz[i]->value;
  1951. //bool czy_wewn_muru = ((roznica_wys < 0) && (-roznica_wys < m_wysokosc)); // czy punkt pol znajduje się wewnątrz muru
  1952. if ((roznica_wys < roznica_wys_min) &&
  1953. ((roznica_wys > 0) || (-roznica_wys < m_wysokosc))) // ponad murem lub wewnątrz muru (nie pod spodem!)
  1954. {
  1955. roznica_wys_min = roznica_wys;
  1956. wsk_min = wsk_prz[i];
  1957. }
  1958. } // jeśli mur
  1959. }
  1960. delete wsk_prz;
  1961.  
  1962. // Tutaj należałoby jeszcze sprawdzić wysokość nad obiektami ruchomymi
  1963.  
  1964.  
  1965. return pol.y - roznica_wys_min;
  1966. }
  1967.  
  1968. void Terrain::GraphicsInitialization()
  1969. {
  1970.  
  1971.  
  1972. }
  1973.  
  1974.  
  1975. void Terrain::InsertItemIntoSectors(Item *prz)
  1976. {
  1977. // przypisanie przedmniotu do określonego obszaru -> umieszczenie w tablicy wskaźników
  1978. // współrzędne kwadratu opisującego przedmiot:
  1979. float x1 = prz->vPos.x - prz->diameter / 2, x2 = prz->vPos.x + prz->diameter / 2,
  1980. z1 = prz->vPos.z - prz->diameter / 2, z2 = prz->vPos.z + prz->diameter / 2;
  1981.  
  1982. long k1, w1, k2, w2;
  1983. SectorCoordinates(&w1, &k1, x1, z1);
  1984. SectorCoordinates(&w2, &k2, x2, z2);
  1985.  
  1986. //fprintf(f, "wsp. kwadratu opisujacego przedmiot: w1=%d,w2=%d,k1=%d,k2=%d\n", w1, w2, k1, k2);
  1987.  
  1988.  
  1989. // wstawiamy przedmiot w te sektory, w których powinien być widoczny:
  1990. for (long w = w1; w <= w2; w++)
  1991. for (long k = k1; k <= k2; k++)
  1992. {
  1993. fprintf(f, "wstawiam przedmiot %d: %s o wartosci %f i srednicy %f w sektor w = %d, k = %d\n", prz,PRZ_nazwy[prz->type],prz->value, prz->diameter, w, k);
  1994. Sektor *ob = ts->znajdz(w, k);
  1995. if (ob == NULL) { // tworzymy sektor, gdy nie istnieje (można nie tworzyć mapy)
  1996. ob = new Sektor(0, w, k, false);
  1997. ts->wstaw(ob);
  1998. }
  1999. ob->wstaw_przedmiot(prz);
  2000.  
  2001. //fprintf(f, " wstawiono przedmiot w sektor (%d, %d) \n", w, k);
  2002. }
  2003. }
  2004.  
  2005. // Wyszukiwanie wszystkich przedmiotow leżących w okręgu o środku wyznaczonym
  2006. // składowymi x,z wekrora pol i zadanym radiusiu. Przedmioty umieszczane są na
  2007. // liście wskaźników wsk_prz. Później należy zwolnić pamięć:
  2008. // delete wsk_prz;
  2009. // Funkcja zwraca liczbę znalezionych przedmiotów
  2010. long Terrain::ItemsInRadius(Item*** wsk_prz, Vector3 pol, float radius)
  2011. {
  2012. Vector3 pol2D = pol;
  2013. pol2D.y = 0;
  2014. float x1 = pol2D.x - radius, z1 = pol2D.z - radius, x2 = pol2D.x + radius, z2 = pol2D.z + radius;
  2015. long kp1, wp1, kp2, wp2;
  2016. this->SectorCoordinates(&wp1, &kp1, x1, z1);
  2017. this->SectorCoordinates(&wp2, &kp2, x2, z2);
  2018. //fprintf(f,"kp1 = %d, wp1 = %d, kp2 = %d, wp2 = %d\n",kp1,wp1,kp2,wp2);
  2019. float radius_kw = radius*radius;
  2020.  
  2021. Sektor **oby = new Sektor*[(wp2 - wp1 + 1)*(kp2 - kp1 + 1)];
  2022. long liczba_obsz = 0;
  2023.  
  2024. // wyznaczenie sektorów w otoczeniu:
  2025. long liczba_przedm = 0, liczba_prz_max = 0; // wyznaczenie maks. liczby przedmiotów
  2026. for (long w = wp1; w <= wp2; w++)
  2027. for (long k = kp1; k <= kp2; k++)
  2028. {
  2029. Sektor *ob = ts->znajdz(w, k);
  2030. if (ob)
  2031. {
  2032. oby[liczba_obsz++] = ob; // wpicuje obszar do tablicy by ponownie go nie wyszukiwać
  2033. liczba_prz_max += ob->number_of_items;
  2034. }
  2035. }
  2036.  
  2037. //fprintf(f,"liczba_przedm_max = %d\n",liczba_przedm_max);
  2038. //fclose(f);
  2039. //exit(1);
  2040.  
  2041. if (liczba_prz_max > 0)
  2042. {
  2043. (*wsk_prz) = new Item*[liczba_prz_max]; // alokacja pamieci dla wskaźników przedmiotów
  2044. for (long n = 0; n < liczba_obsz; n++)
  2045. {
  2046. Sektor *ob = oby[n];
  2047. for (long i = 0; i < ob->number_of_items; i++)
  2048. {
  2049. float odl_kw = 0;
  2050. if ((ob->wp[i]->type == ITEM_EDGE) || (ob->wp[i]->type == ITEM_WALL)) // przedmioty odcinkowe
  2051. {
  2052. Vector3 A = p[ob->wp[i]->param_i[0]].vPos, B = p[ob->wp[i]->param_i[1]].vPos;
  2053. A.y = 0; B.y = 0;
  2054. float odl = odleglosc_pom_punktem_a_odcinkiem(pol2D, A, B) - ob->wp[i]->param_f[0] / 2;
  2055. if (odl < 0) odl = 0;
  2056. odl_kw = odl*odl;
  2057. }
  2058. else
  2059. odl_kw = (ob->wp[i]->vPos.x - pol2D.x)*(ob->wp[i]->vPos.x - pol2D.x) +
  2060. (ob->wp[i]->vPos.z - pol2D.z)*(ob->wp[i]->vPos.z - pol2D.z) - ob->wp[i]->diameter*ob->wp[i]->diameter / 4;
  2061. if (odl_kw <= radius_kw)
  2062. {
  2063. (*wsk_prz)[liczba_przedm] = ob->wp[i];
  2064. liczba_przedm++;
  2065. }
  2066. }
  2067. }
  2068. } // if maks. liczba przedmiotów > 0
  2069. delete oby;
  2070. return liczba_przedm;
  2071. }
  2072.  
  2073.  
  2074. void Terrain::InsertObjectIntoSectors(MovableObject *ob)
  2075. {
  2076. float x1 = ob->state.vPos.x - ob->radius, x2 = ob->state.vPos.x + ob->radius,
  2077. z1 = ob->state.vPos.z - ob->radius, z2 = ob->state.vPos.z + ob->radius;
  2078.  
  2079. long k1, w1, k2, w2;
  2080. SectorCoordinates(&w1, &k1, x1, z1);
  2081. SectorCoordinates(&w2, &k2, x2, z2);
  2082.  
  2083. //fprintf(f, "wsp. kwadratu opisujacego przedmiot: w1=%d,w2=%d,k1=%d,k2=%d\n", w1, w2, k1, k2);
  2084.  
  2085. // wstawiamy obiekt ruchomy w te sektory, w których powinien być widoczny:
  2086. for (long w = w1; w <= w2; w++)
  2087. for (long k = k1; k <= k2; k++)
  2088. {
  2089. Sektor *obsz = ts->znajdz(w, k);
  2090. if (obsz == NULL) { // tworzymy sektor, gdy nie istnieje (można nie tworzyć mapy)
  2091. obsz = new Sektor(0, w, k, false);
  2092. ts->wstaw(obsz);
  2093. }
  2094. obsz->wstaw_obiekt_ruchomy(ob);
  2095.  
  2096. //fprintf(f, " wstawiono obiekt ruchomy w sektor (%d, %d) \n", w, k);
  2097. }
  2098.  
  2099. }
  2100. void Terrain::DeleteObjectsFromSectors(MovableObject *ob)
  2101. {
  2102. float x1 = ob->state.vPos.x - ob->radius, x2 = ob->state.vPos.x + ob->radius,
  2103. z1 = ob->state.vPos.z - ob->radius, z2 = ob->state.vPos.z + ob->radius;
  2104.  
  2105. long k1, w1, k2, w2;
  2106. SectorCoordinates(&w1, &k1, x1, z1);
  2107. SectorCoordinates(&w2, &k2, x2, z2);
  2108.  
  2109. for (long w = w1; w <= w2; w++)
  2110. for (long k = k1; k <= k2; k++)
  2111. {
  2112. Sektor *obsz = ts->znajdz(w, k);
  2113. if (obsz == NULL) { // to nie powinno się zdarzać!
  2114.  
  2115. }
  2116. else
  2117. {
  2118. obsz->usun_obiekt_ruchomy(ob);
  2119. //fprintf(f, " usunięto obiekt ruchomy z sektora (%d, %d) \n", w, k);
  2120.  
  2121. // można jeszcze sprawdzić czy sektor jest pusty (brak mapy, przedmiotów i ob. ruchomych) i usunąć sektor:
  2122. if ((obsz->liczba_obiektow_ruch == 0) && (obsz->number_of_items == 0) && (obsz->poziom_wody == NULL)&&
  2123. (obsz->typy_naw == NULL) && (obsz->mapa_wysokosci == NULL) && (obsz->mapa_wysokosci_edycja == NULL))
  2124. {
  2125. ts->usun(obsz);
  2126. //delete obsz->wob; // to jest usuwane w destruktorze ( dwie linie dalej!)
  2127. //delete obsz->wp;
  2128. delete obsz;
  2129. }
  2130. }
  2131. //fprintf(f, " usunieto obiekt ruchomy w sektora (%d, %d) \n", w, k);
  2132. }
  2133.  
  2134. }
  2135.  
  2136. void Terrain::DeleteItemFromSectors(Item *prz)
  2137. {
  2138. float x1 = prz->vPos.x - prz->diameter / 2, x2 = prz->vPos.x + prz->diameter / 2,
  2139. z1 = prz->vPos.z - prz->diameter / 2, z2 = prz->vPos.z + prz->diameter / 2;
  2140.  
  2141. long k1, w1, k2, w2;
  2142. SectorCoordinates(&w1, &k1, x1, z1);
  2143. SectorCoordinates(&w2, &k2, x2, z2);
  2144.  
  2145. for (long w = w1; w <= w2; w++)
  2146. for (long k = k1; k <= k2; k++)
  2147. {
  2148. Sektor *sek = ts->znajdz(w, k);
  2149. if (sek == NULL) { // to nie powinno się zdarzać!
  2150.  
  2151. }
  2152. else
  2153. {
  2154. sek->usun_przedmiot(prz);
  2155. fprintf(f, " usunięto przedmiot %d: %s o wartosci %f z sektora (%d, %d) \n", prz, PRZ_nazwy[prz->type],prz->value,w, k);
  2156.  
  2157. // można jeszcze sprawdzić czy sektor jest pusty (brak mapy, przedmiotów i ob. ruchomych) i usunąć sektor:
  2158. if ((sek->liczba_obiektow_ruch == 0) && (sek->number_of_items == 0) &&
  2159. (sek->typy_naw == NULL) && (sek->poziom_wody == NULL) && (sek->mapa_wysokosci == NULL))
  2160. {
  2161. ts->usun(sek);
  2162. //delete obsz->wob; // to jest usuwane w destruktorze ( dwie linie dalej!)
  2163. //delete obsz->wp;
  2164. delete sek;
  2165. }
  2166. }
  2167. }
  2168.  
  2169. }
  2170.  
  2171. long Terrain::ObjectsInRadius(MovableObject*** wsk_ob, Vector3 pol, float radius)
  2172. {
  2173. float x1 = pol.x - radius, z1 = pol.z - radius, x2 = pol.x + radius, z2 = pol.z + radius;
  2174. long kp1, wp1, kp2, wp2;
  2175. this->SectorCoordinates(&wp1, &kp1, x1, z1);
  2176. this->SectorCoordinates(&wp2, &kp2, x2, z2);
  2177. //fprintf(f,"kp1 = %d, wp1 = %d, kp2 = %d, wp2 = %d\n",kp1,wp1,kp2,wp2);
  2178. float radius_kw = radius*radius;
  2179.  
  2180. Sektor **oby = new Sektor*[(wp2 - wp1 + 1)*(kp2 - kp1 + 1)];
  2181. long liczba_obsz = 0;
  2182.  
  2183. long liczba_obiektow = 0, liczba_obiektow_max = 0; // wyznaczenie maks. liczby przedmiotów
  2184. for (long w = wp1; w <= wp2; w++)
  2185. for (long k = kp1; k <= kp2; k++)
  2186. {
  2187. Sektor *ob = ts->znajdz(w, k);
  2188. if (ob)
  2189. {
  2190. oby[liczba_obsz++] = ob; // wpicuje obszar do tablicy by ponownie go nie wyszukiwać
  2191. liczba_obiektow_max += ob->liczba_obiektow_ruch;
  2192. }
  2193. }
  2194.  
  2195. //fprintf(f,"liczba_przedm_max = %d\n",liczba_przedm_max);
  2196. //fclose(f);
  2197. //exit(1);
  2198.  
  2199. if (liczba_obiektow_max > 0)
  2200. {
  2201. (*wsk_ob) = new MovableObject*[liczba_obiektow_max]; // alokacja pamieci dla wskaźników obiektów ruchomych
  2202. for (long n = 0; n < liczba_obsz; n++)
  2203. {
  2204. Sektor *ob = oby[n];
  2205. for (long i = 0; i < ob->liczba_obiektow_ruch; i++)
  2206. {
  2207. float odl_kw = (ob->wob[i]->state.vPos.x - pol.x)*(ob->wob[i]->state.vPos.x - pol.x) +
  2208. (ob->wob[i]->state.vPos.z - pol.z)*(ob->wob[i]->state.vPos.z - pol.z);
  2209. if (odl_kw <= radius_kw)
  2210. {
  2211. (*wsk_ob)[liczba_obiektow] = ob->wob[i];
  2212. liczba_obiektow++;
  2213. }
  2214. }
  2215. }
  2216. } // if maks. liczba przedmiotów > 0
  2217. delete oby;
  2218. return liczba_obiektow;
  2219.  
  2220. }
  2221.  
  2222.  
  2223.  
  2224. /*
  2225. maks. wielkość obiektu w pikselach, widoczna na ekranie, -1 jeśli obiekt w ogóle nie jest widoczny
  2226. */
  2227. float NumberOfVisiblePixels(Vector3 WPol, float diameter)
  2228. {
  2229. // Sprawdzenie, czy jakikolwiek z kluczowych punktów sfery opisujacej przedmiot nie jest widoczny
  2230. // (rysowanie z pominięciem niewidocznych przedmiotów jest znacznie szybsze!)
  2231. bool czy_widoczny = 1;// 0;
  2232. RECT clr;
  2233. GetClientRect(main_window, &clr);
  2234. Vector3 pol_kam = par_view.initial_camera_position - par_view.initial_camera_direction*par_view.distance; // położenie kamery
  2235. //Vector3 vPos = p.vPos;
  2236. Vector3 pkt_klucz_sfery[] = { Vector3(1, 0, 0), Vector3(-1, 0, 0), Vector3(0, 1, 0), // kluczowe punkty sfery widoczności
  2237. Vector3(0, -1, 0), Vector3(0, 0, 1), Vector3(0, 0, -1) };
  2238. const int liczba_pkt_klucz = sizeof(pkt_klucz_sfery) / sizeof(Vector3);
  2239. Vector3 ePol[liczba_pkt_klucz]; // wspolrzedne punktów kluczowych na ekranie (tylko skladowe x,y)
  2240.  
  2241. for (int pkt = 0; pkt<liczba_pkt_klucz; pkt++)
  2242. {
  2243. Vector3 wPol2 = WPol + pkt_klucz_sfery[pkt] * diameter; // położenie wybranego punktu początkowego
  2244. ScreenCoordinates(&ePol[pkt].x, &ePol[pkt].y, &ePol[pkt].z, wPol2); // wyznaczenie współrzędnych ekranu
  2245. float ilo_skal = (wPol2 - pol_kam) ^ par_view.initial_camera_direction; // iloczyn skalarny kierunku od kam do pojazdu i kierunku patrzenia kam
  2246. if ((ePol[pkt].x > clr.left) && (ePol[pkt].x < clr.right) && // jeśli współrzędne ekranu któregokolwiek punktu mieszczą się
  2247. (ePol[pkt].y > clr.top) && (ePol[pkt].y < clr.bottom) && (ilo_skal > 0)) // w oknie i punkt z przodu kamery to może on być widoczny
  2248. czy_widoczny = 1; // (można jeszcze sprawdzić stożek widoczności)
  2249. }
  2250.  
  2251. // sprawdzenie na ile widoczny jest przedmiot - w tym celu wybierana jest jedna z 3 osi sfery o największej
  2252. // ekranowej odległości pomiędzy jej punktami na sferze. Im większa ekranowa odległość, tym więcej szczegółów,
  2253. // jeśli < 1 piksel, to można w ogóle przedmiotu nie rysować, jeśli < 10 piks. to można nie rysować napisu
  2254. float liczba_pix_wid = 0; // szczegółowość w pikselach maksymalnie widocznego rozmiaru przedmiotu
  2255. if (czy_widoczny)
  2256. {
  2257. float odl_x = fabs(ePol[0].x - ePol[1].x), odl_y = fabs(ePol[2].y - ePol[3].y),
  2258. odl_z = fabs(ePol[4].z - ePol[5].z);
  2259. liczba_pix_wid = (odl_x > odl_y ? odl_x : odl_y);
  2260. liczba_pix_wid = (odl_z > liczba_pix_wid ? odl_z : liczba_pix_wid);
  2261. }
  2262.  
  2263. if (czy_widoczny == 0) liczba_pix_wid = -1;
  2264.  
  2265. return liczba_pix_wid;
  2266. }
  2267.  
  2268.  
  2269. void Terrain::DrawObject()
  2270. {
  2271. float radius_widnokregu = 8000;
  2272.  
  2273. // rysowanie powierzchni terrainu:
  2274. //glCallList(TerrainSurface);
  2275. GLfloat GreySurface[] = { 0.7f, 0.7f, 0.7f, 0.3f };
  2276. GLfloat OrangeSurface[] = { 1.0f, 0.8f, 0.0f, 0.7f };
  2277. GLfloat GreenSurface[] = { 0.15f, 0.62f, 0.3f, 1.0f };
  2278.  
  2279. //GLfloat RedSurface[] = { 0.8f, 0.2f, 0.1f, 0.5f };
  2280. //glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, RedSurface);
  2281. //glEnable(GL_BLEND);
  2282. // rysujemy wszystko co jest w okręgu o srednicy 1000 m:
  2283.  
  2284. long liczba_sekt = radius_widnokregu / this->sector_size; // liczba widocznych sektorów
  2285. long wwx, kkx; // współrzędne sektora, w którym znajduje się kamera
  2286. //Vector3 pol_kam = initial_camera_position - initial_camera_direction*distance; // położenie kamery
  2287. Vector3 pol_kam, kierunek_kam, pion_kam;
  2288. CameraSettings(&pol_kam, &kierunek_kam, &pion_kam, par_view); // wyznaczenie położenia kamery i innych jej ustawień
  2289.  
  2290. this->SectorCoordinates(&wwx, &kkx, pol_kam.x, pol_kam.z); // współrzędne sektora w którym znajduje się kamera
  2291. //fprintf(f, "pol. kamery = (%f,%f,%f), sektor (%d, %d)\n", pol_kam.x, pol_kam.y, pol_kam.z, wwx, kkx);
  2292.  
  2293. // kwadratury do rysowania przedmiotów:
  2294. GLUquadricObj *Qcyl = gluNewQuadric();
  2295. GLUquadricObj *Qdisk = gluNewQuadric();
  2296. GLUquadricObj *Qsph = gluNewQuadric();
  2297.  
  2298. for (int ww = wwx - liczba_sekt; ww <= wwx + liczba_sekt; ww++) // po sektorach w otoczeniu kamery
  2299. for (int kk = kkx - liczba_sekt; kk <= kkx + liczba_sekt; kk++)
  2300. {
  2301. //fprintf(f, "szukam sektora o w =%d, k = %d, liczba_sekt = %d\n", ww, kk,liczba_sekt);
  2302. Sektor *sek = ts->znajdz(ww, kk);
  2303. //float pocz_x = -rozmiar_pola*lkolumn / 2, // współrzędne lewego górnego krańca terrainu
  2304. // pocz_z = -rozmiar_pola*lwierszy / 2;
  2305. float pocz_x = (kk-0.5)*sector_size;
  2306. float pocz_z = (ww-0.5)*sector_size;
  2307. if ((sek) && ((sek->mapa_wysokosci)||(sek->mapa_wysokosci_edycja)))
  2308. {
  2309. //fprintf(f, "znaleziono sektor o w = %d, k = %d\n", sek->w, sek->k);
  2310. long loczek = 0;
  2311. float **mapa;
  2312. Vector3 ****__Norm;
  2313. if (sek->mapa_wysokosci_edycja)
  2314. {
  2315. mapa = sek->mapa_wysokosci_edycja;
  2316. __Norm = sek->Norm_edycja;
  2317. loczek = sek->liczba_oczek_edycja;
  2318. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, OrangeSurface);
  2319. }
  2320. else
  2321. {
  2322. mapa = sek->mapa_wysokosci;
  2323. __Norm = sek->Norm;
  2324. loczek = sek->liczba_oczek;
  2325. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreenSurface);
  2326. }
  2327.  
  2328. // Tutaj należy ustalić na ile widoczny (blisko obserwatora) jest sektor i w zal. od tego wybrać rozdzielczość
  2329. float rozmiar_pola_r0 = sector_size / loczek;
  2330. Vector3 pol = Vector3(kk*sector_size, sek->wysokosc_max, ww*sector_size);
  2331.  
  2332. long nr_rozdz = 0; // nr_rozdzielczość: 0 - podstawowa, kolejne numery odpowiadają coraz mniejszym rozdzielczościom
  2333.  
  2334. float liczba_pix_wid = NumberOfVisiblePixels(pol, rozmiar_pola_r0);
  2335. if (liczba_pix_wid < 20/(detail_level + 0.05) > 0)
  2336. nr_rozdz = 1 + (int)log2(20/(detail_level + 0.05) / liczba_pix_wid);
  2337.  
  2338. long zmn = (1<<nr_rozdz); // zmiejszenie rozdzielczości (jeśli sektor daleko od obserwatora)
  2339. if (zmn > loczek)
  2340. {
  2341. zmn = loczek;
  2342. nr_rozdz = log2(loczek);
  2343. }
  2344. //long loczek_nr_rozdz = loczek / zmn; // zmniejszona liczba oczek
  2345.  
  2346. //sek->liczba_oczek_wyswietlana_pop = sek->liczba_oczek_wyswietlana;
  2347. sek->liczba_oczek_wyswietlana_pop = sek->liczba_oczek_wyswietlana;
  2348. sek->liczba_oczek_wyswietlana = loczek / zmn; // rozdzielczość do wyświetlenia
  2349. long loczek_nr_rozdz = sek->liczba_oczek_wyswietlana_pop;
  2350. float rozmiar_pola = sector_size / loczek_nr_rozdz; // size pola dla aktualnej rozdzielczości
  2351. zmn = loczek / loczek_nr_rozdz;
  2352. if (zmn > 0)
  2353. nr_rozdz = log2(zmn);
  2354.  
  2355. Sektor *s_lewy = ts->znajdz(ww, kk - 1), *s_prawy = ts->znajdz(ww, kk + 1), // sektory sąsiednie
  2356. *s_dolny = ts->znajdz(ww + 1, kk), *s_gorny = ts->znajdz(ww - 1, kk);
  2357.  
  2358.  
  2359. // tworze listę wyświetlania rysując poszczególne pola mapy za pomocą trójkątów
  2360. // (po 4 trójkąty na każde pole):
  2361. enum tr{ ABC = 0, ADB = 1, BDE = 2, CBE = 3 };
  2362.  
  2363. Vector3 A, B, C, D, E, N;
  2364. //glNewList(TerrainSurface, GL_COMPILE);
  2365. glBegin(GL_TRIANGLES);
  2366. for (long w = 0; w < loczek_nr_rozdz; w++)
  2367. for (long k = 0; k < loczek_nr_rozdz; k++)
  2368. {
  2369. if (k > 0)
  2370. {
  2371. A = C; // dzięki temu, że poruszamy się z oczka na oczko w określonym kierunku, możemy zaoszczędzić
  2372. D = E; // trochę obliczeń
  2373. }
  2374. else
  2375. {
  2376. A = Vector3(pocz_x + k*rozmiar_pola, mapa[w * 2 * zmn][k*zmn], pocz_z + w*rozmiar_pola);
  2377. D = Vector3(pocz_x + k*rozmiar_pola, mapa[(w + 1) * 2 * zmn][k*zmn], pocz_z + (w + 1)*rozmiar_pola);
  2378. }
  2379. B = Vector3(pocz_x + (k + 0.5)*rozmiar_pola, mapa[(w * 2 + 1)*zmn][k*zmn + (zmn>1)*zmn / 2], pocz_z + (w + 0.5)*rozmiar_pola);
  2380. C = Vector3(pocz_x + (k + 1)*rozmiar_pola, mapa[w * 2 * zmn][(k + 1)*zmn], pocz_z + w*rozmiar_pola);
  2381. E = Vector3(pocz_x + (k + 1)*rozmiar_pola, mapa[(w + 1) * 2 * zmn][(k + 1)*zmn], pocz_z + (w + 1)*rozmiar_pola);
  2382.  
  2383.  
  2384. // dopasowanie brzegów sektora do nr_rozdzielczości sektorów sąsiednich (o ile mają mniejszą rozdzielczość):
  2385. if ((k==0)&&(s_lewy) && (s_lewy->liczba_oczek_wyswietlana < loczek_nr_rozdz))
  2386. {
  2387. //if ((s_lewy->mapa_wysokosci == NULL) && (s_lewy->mapa_wysokosci_edycja == NULL)) s_lewy->liczba_oczek_wyswietlana = 1;
  2388. int iloraz = loczek_nr_rozdz / s_lewy->liczba_oczek_wyswietlana;
  2389. int reszta = w % iloraz;
  2390. if (reszta > 0)
  2391. A.y = mapa[(w - reszta) * 2 * zmn][0] +
  2392. (mapa[(w - reszta + iloraz) * 2 * zmn][0] - mapa[(w - reszta) * 2 * zmn][0])*(float)reszta / iloraz;
  2393. reszta = (w+1) % iloraz;
  2394. if (reszta > 0)
  2395. D.y = mapa[(w + 1 - reszta) * 2 * zmn][0] +
  2396. (mapa[(w + 1 - reszta + iloraz) * 2 * zmn][0] - mapa[(w + 1 - reszta) * 2 * zmn][0])*(float)reszta / iloraz;
  2397. }
  2398. if ((k == loczek_nr_rozdz - 1) && (s_prawy) && (s_prawy->liczba_oczek_wyswietlana < loczek_nr_rozdz))
  2399. {
  2400. int iloraz = loczek_nr_rozdz / s_prawy->liczba_oczek_wyswietlana;
  2401. int reszta = w % iloraz;
  2402. if (reszta > 0)
  2403. C.y = mapa[(w - reszta) * 2 * zmn][loczek_nr_rozdz*zmn] +
  2404. (mapa[(w - reszta + iloraz) * 2 * zmn][loczek_nr_rozdz*zmn] - mapa[(w - reszta) * 2 * zmn][loczek_nr_rozdz*zmn])*(float)reszta / iloraz;
  2405. reszta = (w + 1) % iloraz;
  2406. if (reszta > 0)
  2407. E.y = mapa[(w + 1 - reszta) * 2 * zmn][loczek_nr_rozdz*zmn] +
  2408. (mapa[(w + 1 - reszta + iloraz) * 2 * zmn][loczek_nr_rozdz*zmn] - mapa[(w + 1 - reszta) * 2 * zmn][loczek_nr_rozdz*zmn])*(float)reszta / iloraz;
  2409. }
  2410.  
  2411. if ((w == 0) && (s_gorny) && (s_gorny->liczba_oczek_wyswietlana < loczek_nr_rozdz))
  2412. {
  2413. int iloraz = loczek_nr_rozdz / s_gorny->liczba_oczek_wyswietlana;
  2414. int reszta = k % iloraz;
  2415. if (reszta > 0)
  2416. A.y = mapa[0][(k - reszta)*zmn] + (mapa[0][(k - reszta + iloraz)*zmn] - mapa[0][(k - reszta)*zmn])*(float)reszta / iloraz;
  2417. reszta = (k+1) % iloraz;
  2418. if (reszta > 0)
  2419. C.y = mapa[0][(k + 1 - reszta)*zmn] + (mapa[0][(k + 1 - reszta + iloraz)*zmn] - mapa[0][(k + 1 - reszta)*zmn])*(float)reszta / iloraz;
  2420. }
  2421.  
  2422. if ((w == loczek_nr_rozdz - 1) && (s_dolny) && (s_dolny->liczba_oczek_wyswietlana < loczek_nr_rozdz))
  2423. {
  2424. int iloraz = loczek_nr_rozdz / s_dolny->liczba_oczek_wyswietlana;
  2425. int reszta = k % iloraz;
  2426. if (reszta > 0)
  2427. D.y = mapa[loczek_nr_rozdz*zmn*2][(k - reszta)*zmn] +
  2428. (mapa[loczek_nr_rozdz*zmn * 2][(k - reszta + iloraz)*zmn] - mapa[loczek_nr_rozdz*zmn * 2][(k - reszta)*zmn])*(float)reszta / iloraz;
  2429. reszta = (k + 1) % iloraz;
  2430. if (reszta > 0)
  2431. E.y = mapa[loczek_nr_rozdz*zmn * 2][(k + 1 - reszta)*zmn] +
  2432. (mapa[loczek_nr_rozdz*zmn * 2][(k + 1 - reszta + iloraz)*zmn] - mapa[loczek_nr_rozdz*zmn * 2][(k + 1 - reszta)*zmn])*(float)reszta / iloraz;
  2433. }
  2434. // tworzę trójkąt ABC w górnej części kwadratu:
  2435. // A o_________o C
  2436. // |. .|
  2437. // | . . |
  2438. // | o B |
  2439. // | . . |
  2440. // |._______.|
  2441. // D o o E
  2442.  
  2443. //Vector3 AB = B - A;
  2444. //Vector3 BC = C - B;
  2445. //N = (AB*BC).znorm();
  2446. N = __Norm[nr_rozdz][w][k][ABC];
  2447. glNormal3f(N.x, N.y, N.z);
  2448. glVertex3f(A.x, A.y, A.z);
  2449. glVertex3f(B.x, B.y, B.z);
  2450. glVertex3f(C.x, C.y, C.z);
  2451. //d[w][k][ABC] = -(B^N); // dodatkowo wyznaczam wyraz wolny z równania plaszyzny trójkąta
  2452. //Norm[w][k][ABC] = N; // dodatkowo zapisuję normalną do płaszczyzny trójkąta
  2453. // trójkąt ADB:
  2454. //Vector3 AD = D - A;
  2455. //N = (AD*AB).znorm();
  2456. N = __Norm[nr_rozdz][w][k][ADB];
  2457. glNormal3f(N.x, N.y, N.z);
  2458. glVertex3f(A.x, A.y, A.z);
  2459. glVertex3f(D.x, D.y, D.z);
  2460. glVertex3f(B.x, B.y, B.z);
  2461. //d[w][k][ADB] = -(B^N);
  2462. //Norm[w][k][ADB] = N;
  2463. // trójkąt BDE:
  2464. //Vector3 BD = D - B;
  2465. //Vector3 DE = E - D;
  2466. //N = (BD*DE).znorm();
  2467. N = __Norm[nr_rozdz][w][k][BDE];
  2468. glNormal3f(N.x, N.y, N.z);
  2469. glVertex3f(B.x, B.y, B.z);
  2470. glVertex3f(D.x, D.y, D.z);
  2471. glVertex3f(E.x, E.y, E.z);
  2472. //d[w][k][BDE] = -(B^N);
  2473. //Norm[w][k][BDE] = N;
  2474. // trójkąt CBE:
  2475. //Vector3 CB = B - C;
  2476. //Vector3 BE = E - B;
  2477. //N = (CB*BE).znorm();
  2478. N = __Norm[nr_rozdz][w][k][CBE];
  2479. glNormal3f(N.x, N.y, N.z);
  2480. glVertex3f(C.x, C.y, C.z);
  2481. glVertex3f(B.x, B.y, B.z);
  2482. glVertex3f(E.x, E.y, E.z);
  2483. //d[w][k][CBE] = -(B^N);
  2484. //Norm[w][k][CBE] = N;
  2485. }
  2486. glEnd();
  2487. } // jeśli znaleziono mapę sektora
  2488. else if (sek)
  2489. {
  2490. // ustawienie tekstury:
  2491. // ....
  2492. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreenSurface);
  2493. glBegin(GL_QUADS);
  2494. glNormal3f(0, 1, 0);
  2495. glVertex3f(pocz_x, 0.0, pocz_z);
  2496. glVertex3f(pocz_x, 0.0, pocz_z + sector_size);
  2497. glVertex3f(pocz_x + sector_size, 0.0, pocz_z + sector_size);
  2498. glVertex3f(pocz_x + sector_size, 0.0, pocz_z);
  2499. glEnd();
  2500. } // jeśli nie znaleziono mapy ale znaleziono sektor ze standardową nawierzchnią
  2501. else
  2502. {
  2503. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreenSurface);
  2504. glBegin(GL_QUADS);
  2505. glNormal3f(0, 1, 0);
  2506. glVertex3f(pocz_x, 0.0, pocz_z);
  2507. glVertex3f(pocz_x, 0.0, pocz_z + sector_size);
  2508. glVertex3f(pocz_x + sector_size, 0.0, pocz_z + sector_size);
  2509. glVertex3f(pocz_x + sector_size, 0.0, pocz_z);
  2510. glEnd();
  2511.  
  2512. } // jeśli nie znaleziono sektora
  2513. } // po sektorach
  2514.  
  2515.  
  2516. // RYSOWANIE PRZEDMIOTÓW
  2517. for (int ww = wwx - liczba_sekt; ww <= wwx + liczba_sekt; ww++) // po sektorach w otoczeniu kamery
  2518. for (int kk = kkx - liczba_sekt; kk <= kkx + liczba_sekt; kk++)
  2519. {
  2520. //fprintf(f, "szukam sektora o w =%d, k = %d, liczba_sekt = %d\n", ww, kk,liczba_sekt);
  2521. Sektor *sek = ts->znajdz(ww, kk);
  2522.  
  2523. long liczba_prz = 0;
  2524. if (sek) liczba_prz = sek->number_of_items;
  2525.  
  2526. for (long prz = 0; prz < liczba_prz; prz++)
  2527. {
  2528. Item *p = sek->wp[prz];
  2529. if (p->display_number != this->number_of_displays) // o ile jeszcze nie został wyświetlony w tym cyklu rysowania
  2530. {
  2531. p->display_number = number_of_displays; // by nie wyświetlać wielokrotnie, np. gdy przedmiot jest w wielu sektorach
  2532. float liczba_pix_wid = NumberOfVisiblePixels(p->vPos, p->diameter_visual);
  2533. bool czy_widoczny = (liczba_pix_wid >= 0 ? 1 : 0);
  2534.  
  2535. glPushMatrix();
  2536.  
  2537. glTranslatef(p->vPos.x, p->vPos.y, p->vPos.z);
  2538. //glRotatef(k.w*180.0/PI,k.x,k.y,k.z);
  2539. //glScalef(length,height,szerokosc);
  2540. switch (p->type)
  2541. {
  2542. case ITEM_COIN:
  2543. //gluCylinder(Qcyl,radius1,radius2,height,10,20);
  2544. if (p->to_take)
  2545. {
  2546. GLfloat Surface[] = { 2.0f, 2.0f, 1.0f, 1.0f };
  2547. if (p->if_selected)
  2548. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2549. else
  2550. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Surface);
  2551. glRotatef(90, 1, 0, 0);
  2552. float grubosc = 0.2*p->diameter;
  2553. //gluDisk(Qdisk,0,p->diameter,10,10);
  2554. //gluCylinder(Qcyl,p->diameter,p->diameter,grubosc,10,20);
  2555. if (liczba_pix_wid < (int)3.0 / (detail_level + 0.001)) // przy małych widocznych rozmiarach rysowanie punktu
  2556. {
  2557. glPointSize((int)liczba_pix_wid*0.3);
  2558. glBegin(GL_POINTS);
  2559. glVertex3f(0, 0, 0);
  2560. glEnd();
  2561. }
  2562. else
  2563. {
  2564. int liczba = (int)(liczba_pix_wid*detail_level / 3);
  2565. if (liczba < 5) liczba = 5;
  2566. if (liczba > 15) liczba = 15;
  2567. gluDisk(Qdisk, 0, p->diameter, liczba, liczba * 2);
  2568. gluCylinder(Qcyl, p->diameter, p->diameter, grubosc, liczba, liczba * 2);
  2569. }
  2570. if (liczba_pix_wid > 5)
  2571. {
  2572. glRasterPos2f(0.30, 1.20);
  2573. glPrint("%d", (int)p->value);
  2574. }
  2575. }
  2576. break;
  2577. case ITEM_BARREL:
  2578. //gluCylinder(Qcyl,radius1,radius2,height,10,20);
  2579. if (p->to_take)
  2580. {
  2581. GLfloat Surface[] = { 0.50f, 0.45f, 0.0f, 1.0f };
  2582. if (p->if_selected)
  2583. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2584. else
  2585. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Surface);
  2586. if (liczba_pix_wid < (int)3.0 / (detail_level + 0.001)) // przy małych widocznych rozmiarach rysowanie punktu
  2587. {
  2588. glPointSize((int)liczba_pix_wid*0.3);
  2589. glBegin(GL_POINTS);
  2590. glVertex3f(0, 0, 0);
  2591. glEnd();
  2592. }
  2593. else
  2594. {
  2595. int liczba = (int)(liczba_pix_wid*detail_level / 3);
  2596. if (liczba < 5) liczba = 5;
  2597. if (liczba > 15) liczba = 15;
  2598. glRotatef(90, 1, 0, 0);
  2599.  
  2600. float grubosc = 2 * p->diameter;
  2601. gluDisk(Qdisk, 0, p->diameter, liczba, liczba);
  2602. gluCylinder(Qcyl, p->diameter, p->diameter, grubosc, liczba, liczba * 2);
  2603. }
  2604. if (liczba_pix_wid > 5)
  2605. {
  2606. glRasterPos2f(0.30, 1.20);
  2607. glPrint("%d", (int)p->value);
  2608. }
  2609. }
  2610. break;
  2611. case ITEM_TREE:
  2612. {
  2613. float wariancja_ksztaltu = 0.2; // poprawka wielkości i koloru zależą od położenia (wsp. x,z)
  2614. float wariancja_koloru = 0.2; // wszędzie więc (u różnych klientów) drzewa będą wyglądały tak samo
  2615. float poprawka_kol1 = (2 * fabs(p->vPos.x / 600 - floor(p->vPos.x /600)) - 1)*wariancja_koloru,
  2616. poprawka_kol2 = (2 * fabs(p->vPos.z /600 - floor(p->vPos.z /600)) - 1)*wariancja_koloru;
  2617. switch (p->subtype)
  2618. {
  2619. case TREE_POPLAR:
  2620. {
  2621. GLfloat Surface[] = { 0.5f, 0.5f, 0.0f, 1.0f };
  2622. GLfloat KolorPnia[] = { 0.4 + poprawka_kol1 / 3, 0.6 + poprawka_kol2 / 3, 0.0f, 1.0f };
  2623. GLfloat KolorLisci[] = { 2*poprawka_kol1, 0.9 + 2*poprawka_kol2, 0.0f, 1.0f };
  2624. if (p->if_selected)
  2625. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2626. else
  2627. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorPnia);
  2628. if (liczba_pix_wid < (int)10.0 / (detail_level + 0.001))
  2629. {
  2630. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2631. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorLisci);
  2632. glPointSize((int)liczba_pix_wid*0.3);
  2633. glBegin(GL_POINTS);
  2634. glVertex3f(0, 0, 0);
  2635. glEnd();
  2636. }
  2637. else
  2638. {
  2639. int liczba = (int)(liczba_pix_wid*detail_level / 20);
  2640. if (liczba < 3) liczba = 3;
  2641. if (liczba > 10) liczba = 10;
  2642.  
  2643. glPushMatrix();
  2644. glRotatef(90, 1, 0, 0);
  2645. float poprawka_ksz1 = (2 * fabs(p->vPos.x / 35 - floor(p->vPos.x / 35)) - 1)*wariancja_ksztaltu;
  2646. float poprawka_ksz2 = (2 * fabs(p->vPos.z / 15 - floor(p->vPos.z / 15)) - 1)*wariancja_ksztaltu;
  2647. float height = p->value;
  2648. float sredn = p->param_f[0] * p->diameter*(1 + poprawka_ksz1);
  2649. gluCylinder(Qcyl, sredn / 2, sredn, height*1.1, liczba, liczba * 2);
  2650. glPopMatrix();
  2651.  
  2652. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2653. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorLisci);
  2654. //glTranslatef(0,height,0);
  2655.  
  2656. glScalef(sredn, 3 * (1 + poprawka_ksz2), sredn);
  2657.  
  2658. gluSphere(Qsph, 3.0, liczba * 2, liczba * 2);
  2659. }
  2660. break;
  2661. }
  2662. case TREE_SPRUCE:
  2663. {
  2664. GLfloat KolorPnia[] = { 0.65f, 0.3f, 0.0f, 1.0f };
  2665. GLfloat KolorLisci[] = { 0.0f, 0.70 + poprawka_kol1, 0.2 + poprawka_kol2, 1.0f };
  2666. if (p->if_selected)
  2667. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2668. else
  2669. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorPnia);
  2670. if (liczba_pix_wid < (int)10.0 / (detail_level + 0.001))
  2671. {
  2672. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2673. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorLisci);
  2674. glPointSize((int)liczba_pix_wid*0.3);
  2675. glBegin(GL_POINTS);
  2676. glVertex3f(0, 0, 0);
  2677. glEnd();
  2678.  
  2679. }
  2680. else
  2681. {
  2682. int liczba = (int)(liczba_pix_wid*detail_level / 20);
  2683. if (liczba < 3) liczba = 3;
  2684. if (liczba > 10) liczba = 10;
  2685.  
  2686. glPushMatrix();
  2687. glRotatef(90, 1, 0, 0);
  2688. float height = p->value;
  2689. float radius = p->param_f[0] * p->diameter / 2;
  2690. gluCylinder(Qcyl, radius, radius * 2, height*1.1, liczba, liczba * 2);
  2691.  
  2692. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2693. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorLisci);
  2694. glTranslatef(0, 0, height * 2 / 4);
  2695. gluCylinder(Qcyl, radius * 2, radius * 8, height / 4, liczba, liczba * 2);
  2696. glTranslatef(0, 0, -height * 1 / 4);
  2697. gluCylinder(Qcyl, radius * 2, radius * 6, height / 4, liczba, liczba * 2);
  2698. glTranslatef(0, 0, -height * 1 / 3);
  2699. gluCylinder(Qcyl, 0, radius * 4, height / 3, liczba, liczba * 2);
  2700.  
  2701. glPopMatrix();
  2702. }
  2703. break;
  2704. }
  2705. case TREE_BAOBAB:
  2706. {
  2707. GLfloat KolorPnia[] = { 0.5f, 0.9f, 0.2f, 1.0f };
  2708. GLfloat KolorLisci[] = { 0.0f, 0.9 + poprawka_kol2, 0.2 + poprawka_kol1, 1.0f };
  2709.  
  2710. if (p->if_selected)
  2711. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2712. else
  2713. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorPnia);
  2714.  
  2715. if (liczba_pix_wid < (int)10.0 / (detail_level + 0.001))
  2716. {
  2717. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2718. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorLisci);
  2719. glPointSize((int)liczba_pix_wid*0.3);
  2720. glBegin(GL_POINTS);
  2721. glVertex3f(0, 0, 0);
  2722. glEnd();
  2723. }
  2724. else
  2725. {
  2726. int liczba = (int)(liczba_pix_wid*detail_level / 20);
  2727. if (liczba < 3) liczba = 3;
  2728. if (liczba > 10) liczba = 10;
  2729. glPushMatrix();
  2730. glRotatef(90, 1, 0, 0);
  2731. float height = p->value;
  2732. float sredn = p->param_f[0] * p->diameter;
  2733. gluCylinder(Qcyl, p->diameter / 2, sredn, height*1.1, liczba, liczba * 2);
  2734. glPopMatrix();
  2735.  
  2736. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2737. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorLisci);
  2738. glPushMatrix();
  2739. float s = 2 + height / 20;
  2740. glScalef(s, s / 2, s);
  2741. gluSphere(Qsph, 3, liczba * 2, liczba * 2);
  2742. glPopMatrix();
  2743. glTranslatef(0, -s / 1.5, 0);
  2744. glScalef(s*2.2, s / 2, s*2.2);
  2745. gluSphere(Qsph, 3, liczba, liczba);
  2746. }
  2747. break;
  2748. }
  2749. case TREE_FANTAZJA:
  2750. {
  2751. GLfloat KolorPnia[] = { 0.65f, 0.3f, 0.0f, 1.0f }; // kolor pnia i gałęzi
  2752. GLfloat KolorLisci[] = { 0.5f, 0.65 + poprawka_kol1, 0.2f, 1.0f };
  2753. if (p->if_selected)
  2754. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2755. else
  2756. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorPnia);
  2757.  
  2758. if (liczba_pix_wid < (int)10.0 / (detail_level + 0.001))
  2759. {
  2760. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2761. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorLisci);
  2762. glPointSize((int)liczba_pix_wid*0.3);
  2763. glBegin(GL_POINTS);
  2764. glVertex3f(0, 0, 0);
  2765. glEnd();
  2766. }
  2767. else
  2768. {
  2769. int liczba = (int)(liczba_pix_wid*detail_level / 20);
  2770. if (liczba < 3) liczba = 3;
  2771. if (liczba > 10) liczba = 10;
  2772. glPushMatrix();
  2773. glRotatef(90, 1, 0, 0);
  2774. float height = p->value, radius_podst = p->param_f[0] * p->diameter / 2,
  2775. radius_wierzch = p->param_f[0] * p->diameter / 5;
  2776. gluCylinder(Qcyl, radius_wierzch * 2, radius_podst * 2, height*1.1, liczba, liczba * 2); // rysowanie pnia
  2777. glPopMatrix();
  2778. glPushMatrix();
  2779. // kolor liści
  2780. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2781. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorLisci);
  2782. //glTranslatef(0,height,0);
  2783. float s = 0.5 + height / 15; // średnica listowia
  2784. glScalef(s, s, s);
  2785. gluSphere(Qsph, 3, liczba * 2, liczba * 2); // rysowanie pęku liści na wierzchołku
  2786. glPopMatrix();
  2787.  
  2788. int liczba_gal = (int)(height / 3.5) + (int)(height * 10) % 3; // liczba gałęzi
  2789. float prop_podz = 0.25 + (float)((int)(height * 13) % 10) / 100; // proporcja wysokości na której znajduje się gałąź od poprzedniej galezi lub gruntu
  2790. float prop = 1, wys = 0;
  2791.  
  2792. for (int j = 0; j < liczba_gal; j++)
  2793. {
  2794. glPushMatrix();
  2795. prop *= prop_podz;
  2796. wys += (height - wys)*prop_podz; // wysokość na której znajduje się i-ta gałąź od poziomu gruntu
  2797.  
  2798. float kat = 3.14 * 2 * (float)((int)(wys * 107) % 10) / 10; // kat w/g pnia drzewa
  2799. float sredn = (radius_podst * 2 - wys / height*(radius_podst * 2 - radius_wierzch * 2)) / 2;
  2800. float dlug = sredn * 2 + sqrt(height - wys);
  2801. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2802. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorPnia);
  2803.  
  2804. glTranslatef(0, wys - height, 0);
  2805. glRotatef(kat * 180 / 3.14, 0, 1, 0);
  2806. gluCylinder(Qcyl, sredn, sredn / 2, dlug, liczba, liczba);
  2807. if (p->if_selected) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2808. else glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, KolorLisci);
  2809.  
  2810. float ss = s*sredn / radius_podst * 2 * 1.5;
  2811. glTranslatef(0, 0, dlug + ss * 2);
  2812. glScalef(ss, ss, ss);
  2813. gluSphere(Qsph, 3, liczba, liczba); // rysowanie pęku liści na wierzchołku
  2814.  
  2815. glPopMatrix();
  2816. }
  2817. }
  2818.  
  2819. break;
  2820. } // case Fantazja
  2821.  
  2822. } // switch po typach drzew
  2823. break;
  2824. } // drzewo
  2825. case ITEM_POINT:
  2826. {
  2827. //gluCylinder(Qcyl,radius1,radius2,height,10,20);
  2828. if (terrain_edition_mode)
  2829. {
  2830. GLfloat Surface[] = { 2.0f, 0.0f, 0.0f, 1.0f };
  2831. if (p->if_selected)
  2832. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2833. else
  2834. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Surface);
  2835. //glRotatef(90, 1, 0, 0);
  2836. glTranslatef(0, p->value, 0);
  2837. glPointSize(3);
  2838. glBegin(GL_POINTS);
  2839. glVertex3f(0, 0, 0);
  2840. glEnd();
  2841. glTranslatef(0, -p->value, 0);
  2842. if (liczba_pix_wid > 5)
  2843. {
  2844. glRasterPos2f(0.30, 1.20);
  2845. glPrint("punkt");
  2846. }
  2847. }
  2848. break;
  2849. }
  2850. case ITEM_EDGE:
  2851. {
  2852. //gluCylinder(Qcyl,radius1,radius2,height,10,20);
  2853. if (terrain_edition_mode)
  2854. {
  2855. GLfloat Surface[] = { 2.0f, 0.0f, 0.0f, 1.0f };
  2856. if (p->if_selected)
  2857. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2858. else
  2859. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Surface);
  2860. //glRotatef(90, 1, 0, 0);
  2861. long nr_punktu1 = p->param_i[0], nr_punktu2 = p->param_i[1];
  2862. Vector3 pol = (this->p[nr_punktu1].vPos + this->p[nr_punktu2].vPos) / 2;
  2863. glTranslatef(-p->vPos.x, -p->vPos.y, -p->vPos.z);
  2864. //glTranslatef(-pol.x, -pol.y, -pol.z);
  2865. glLineWidth(2);
  2866.  
  2867. glBegin(GL_LINES);
  2868. glVertex3f(this->p[nr_punktu1].vPos.x, this->p[nr_punktu1].vPos.y + this->p[nr_punktu1].value, this->p[nr_punktu1].vPos.z);
  2869. glVertex3f(this->p[nr_punktu2].vPos.x, this->p[nr_punktu2].vPos.y + this->p[nr_punktu2].value, this->p[nr_punktu2].vPos.z);
  2870. glEnd();
  2871.  
  2872. //glTranslatef(p->vPos.x, p->vPos.y, p->vPos.z);
  2873. glTranslatef(pol.x, pol.y, pol.z);
  2874. if (liczba_pix_wid > 5)
  2875. {
  2876. glRasterPos2f(0.30, 1.20);
  2877. glPrint("krawedz");
  2878. }
  2879. glTranslatef(-pol.x, -pol.y, -pol.z);
  2880. }
  2881. break;
  2882. }
  2883. case ITEM_WALL:
  2884. {
  2885. GLfloat Surface[] = { 0.8f, 0.8f, 0.4f, 1.0f };
  2886. if (p->if_selected)
  2887. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, GreySurface);
  2888. else
  2889. glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, Surface);
  2890. //glRotatef(90, 1, 0, 0);
  2891. long nr_punktu1 = p->param_i[0], nr_punktu2 = p->param_i[1];
  2892. Vector3 pol1 = this->p[nr_punktu1].vPos, pol2 = this->p[nr_punktu2].vPos, vertical = Vector3(0, 1, 0);
  2893. pol1.y += this->p[nr_punktu1].value;
  2894. pol2.y += this->p[nr_punktu2].value;
  2895.  
  2896. Vector3 pol = (pol1 + pol2) / 2;
  2897. Vector3 wprzod = (pol2 - pol1).znorm(); // direction od punktu 1 do punktu 2
  2898. Vector3 wlewo = vertical*wprzod; // direction w lewo, gdyby patrzeć w kierunku wprzod
  2899. float grubosc = p->param_f[0]; // grubość muru
  2900. float height = p->value; // wysokość muru (tzn. grubość w pionie) niezależnie od pionowego umiejscowienia
  2901.  
  2902. //glTranslatef(-pol.x, -pol.y, -pol.z);
  2903. glTranslatef(-p->vPos.x, -p->vPos.y, -p->vPos.z);
  2904.  
  2905. // punkty kluczowe:
  2906. Vector3 A = pol1 - wlewo*grubosc / 2 + vertical*height/2;
  2907. Vector3 B = A + wlewo*grubosc;
  2908. Vector3 C = B - vertical*height;
  2909. Vector3 D = A - vertical*height;
  2910. Vector3 Ap = A + pol2 - pol1, Bp = B + pol2 - pol1,
  2911. Cp = C + pol2 - pol1, Dp = D + pol2 - pol1;
  2912.  
  2913. glBegin(GL_QUADS);
  2914. // sciana ABCD:
  2915. Vector3 N = vertical*wlewo;
  2916. glNormal3f(N.x, N.y, N.z);
  2917. glVertex3f(A.x, A.y, A.z);
  2918. glVertex3f(B.x, B.y, B.z);
  2919. glVertex3f(C.x, C.y, C.z);
  2920. glVertex3f(D.x, D.y, D.z);
  2921.  
  2922. glNormal3f(-N.x, -N.y, -N.z);
  2923. glVertex3f(Ap.x, Ap.y, Ap.z);
  2924. glVertex3f(Dp.x, Dp.y, Dp.z);
  2925. glVertex3f(Cp.x, Cp.y, Cp.z);
  2926. glVertex3f(Bp.x, Bp.y, Bp.z);
  2927.  
  2928. glNormal3f(-wlewo.x, -wlewo.y, -wlewo.z);
  2929. glVertex3f(A.x, A.y, A.z);
  2930. glVertex3f(D.x, D.y, D.z);
  2931. glVertex3f(Dp.x, Dp.y, Dp.z);
  2932. glVertex3f(Ap.x, Ap.y, Ap.z);
  2933.  
  2934. glNormal3f(wlewo.x, wlewo.y, wlewo.z);
  2935. glVertex3f(B.x, B.y, B.z);
  2936. glVertex3f(Bp.x, Bp.y, Bp.z);
  2937. glVertex3f(Cp.x, Cp.y, Cp.z);
  2938. glVertex3f(C.x, C.y, C.z);
  2939.  
  2940. N = wprzod*wlewo;
  2941. glNormal3f(N.x, N.y, N.z);
  2942. glVertex3f(A.x, A.y, A.z);
  2943. glVertex3f(Ap.x, Ap.y, Ap.z);
  2944. glVertex3f(Bp.x, Bp.y, Bp.z);
  2945. glVertex3f(B.x, B.y, B.z);
  2946.  
  2947. glNormal3f(-N.x, -N.y, -N.z);
  2948. glVertex3f(D.x, D.y, D.z);
  2949. glVertex3f(C.x, C.y, C.z);
  2950. glVertex3f(Cp.x, Cp.y, Cp.z);
  2951. glVertex3f(Dp.x, Dp.y, Dp.z);
  2952.  
  2953. glEnd();
  2954. //glTranslatef(p->vPos.x, p->vPos.y, p->vPos.z);
  2955.  
  2956. if (terrain_edition_mode)
  2957. {
  2958. glTranslatef(pol.x, pol.y+height/2, pol.z);
  2959. if (liczba_pix_wid > 5)
  2960. {
  2961. glRasterPos2f(0.30, 1.20);
  2962. glPrint("mur");
  2963. }
  2964. glTranslatef(-pol.x, -pol.y-height/2, -pol.z);
  2965. }
  2966. //fprintf(f, "Narysowano mur pomiedzy punktami %d (%f,%f,%f) a %d (%f,%f,%f)\n", nr_punktu1, pol1.x, pol1.y, pol1.z,
  2967. // nr_punktu2, pol2.x, pol2.y, pol2.z);
  2968. break;
  2969. }
  2970. } // switch po typach przedmiotów
  2971.  
  2972. glPopMatrix();
  2973. } // jeśli przedmiot nie został już wyświetlony w tej funkcji
  2974. } // po przedmiotach z sektora
  2975.  
  2976. } // po sektorach
  2977. gluDeleteQuadric(Qcyl); gluDeleteQuadric(Qdisk); gluDeleteQuadric(Qsph);
  2978. //glCallList(Floor);
  2979. this->number_of_displays++;
  2980. }
Add Comment
Please, Sign In to add comment