Advertisement
Guest User

Untitled

a guest
Oct 23rd, 2019
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.79 KB | None | 0 0
  1. #include <random>
  2. #include <iostream>
  3. #include <iomanip>
  4. #include <fstream>
  5.  
  6. #include <GL/gl.h>
  7. #include <GL/glut.h>
  8.  
  9. // Rozmiar macierzy, musi być 2^n + 1
  10. const int size = 257;
  11. // Stopień definiujący zaokrąglanie obrazu
  12. // Większa wartość daje więcej punktów i "płynniejszy" obraz
  13. int range = 98;
  14. // Początkowy kąt kamery
  15. float angle = 0;
  16. // Skala obrazu
  17. const float scaling = 0.5f;
  18. // Funkcja określająca czas odświeżania widoku
  19. const int refreshMills = 16;
  20. // Macierz przechowująca obraz
  21. int map[size][size];
  22.  
  23. // Funkcja zwracająca losowo wartość RGB
  24. int rnd(int min = 0, int max = 255)
  25. {
  26. return min + (rand() % static_cast<int>(max - min + 1));
  27. }
  28.  
  29. // Inicjalizacja losowymi wartościami rogów
  30. void init()
  31. {
  32. map[0][0] = rnd();
  33. map[0][size - 1] = rnd();
  34. map[size - 1][0] = rnd();
  35. map[size - 1][size - 1] = rnd();
  36. }
  37.  
  38. // Krok "Diamentowy" algorytmu Diamond-Square
  39. void diamond(int sideLength)
  40. {
  41. // Podział boku na pół
  42. int halfSide = sideLength / 2;
  43.  
  44. // Podwójna pętla iterująca po kolejnych kwadratach powstałych na skutek podziału
  45. for (int y = 0; y < size / (sideLength-1); y++)
  46. {
  47. for (int x = 0; x < size / (sideLength-1); x++)
  48. {
  49. // Wyznaczenie środka aktualnego kwadratu
  50. int center_x = x*(sideLength-1) + halfSide;
  51. int center_y = y*(sideLength-1) + halfSide;
  52. //Uśrednienie wartości koloru na podstawie jego sąsiadów
  53. int avg = (map[x*(sideLength - 1)][y*(sideLength - 1)] +
  54. map[x*(sideLength - 1)][(y+1) * (sideLength - 1)] +
  55. map[(x + 1) * (sideLength - 1)][y*(sideLength - 1)] +
  56. map[(x + 1) * (sideLength - 1)][(y + 1) * (sideLength - 1)])
  57. / 4.0f;
  58. // Ustawienie koloru aktualnego kwadratu, bazując na kolorze uśrednionym
  59. map[center_x][center_y] = avg + rnd(-range, range);
  60. }
  61. }
  62.  
  63. }
  64.  
  65. // Funkcja uśredniająca, eliminuje przypadki
  66. // W których punkty nie są całkowite, bądź wykraczają poza macierz
  67. // Przypisuje do macierzy wartości ograniczone przez jej rozmiar
  68. void average(int x, int y, int sideLength)
  69. {
  70. // Zmienne pomocnicze
  71. float counter = 0;
  72. float accumulator = 0;
  73.  
  74. int halfSide = sideLength / 2;
  75.  
  76. // Jeżeli x nie posiada wartości
  77. if (x != 0)
  78. {
  79. counter += 1.0f;
  80. accumulator += map[y][x - halfSide];
  81. }
  82. // jeżeli y nie posiada wartości
  83. if (y != 0)
  84. {
  85. counter += 1.0f;
  86. accumulator += map[y - halfSide][x];
  87. }
  88. // Jeżeli x wykracza poza zakres
  89. if (x != size - 1)
  90. {
  91. counter += 1.0f;
  92. accumulator += map[y][x + halfSide];
  93. }
  94. // Jeżeli y wykracza poza zakres
  95. if (y != size - 1)
  96. {
  97. counter += 1.0f;
  98. accumulator += map[y + halfSide][x];
  99. }
  100. // Przypisanie poprawwionej wartości do macierzy
  101. map[y][x] = (accumulator / counter) + rnd(-range, range);
  102. }
  103.  
  104. // Krok "Kwadratowy" algorytmu Diamond-Square
  105. void square(int sideLength)
  106. {
  107. // Podział boku na pół
  108. int halfLength = sideLength / 2;
  109. // Podwójna pętla iterująca po kolejnych kwadratach powstałych na skutek podziału
  110. for (int y = 0; y < size / (sideLength - 1); y++)
  111. {
  112. for (int x = 0; x < size / (sideLength - 1); x++)
  113. {
  114. // Góra kwadratu
  115. average(x*(sideLength - 1) + halfLength, y*(sideLength - 1), sideLength);
  116. // Prawo kwadratu
  117. average((x + 1)*(sideLength - 1), y*(sideLength - 1) + halfLength, sideLength);
  118. // Dół kwadratu
  119. average(x*(sideLength - 1) + halfLength, (y+1)*(sideLength - 1), sideLength);
  120. // Lewo kwadratu
  121. average(x*(sideLength - 1), y*(sideLength - 1) + halfLength, sideLength);
  122. }
  123. }
  124. }
  125.  
  126. // Główna funkcja wywołujaca algorytm Diamond-Square
  127. // Wywołuje kolejne iteracje kroków "Diament" i "Kwadrat"
  128. void fractal()
  129. {
  130. // Startowe wywołanie algorytmu, podział macierzy na 4 części
  131. int sideLength = size/2;
  132. diamond(size);
  133. square(size);
  134. // Zmniejszenie zakresu o połowę
  135. range /= 2;
  136.  
  137. // Pętla wykonująca kolejne iteracje
  138. // dopóki aktualny kwadrat ma rozmiar większy od piksela
  139. while (sideLength >= 2)
  140. {
  141. diamond(sideLength + 1);
  142. square(sideLength + 1);
  143. sideLength /= 2;
  144. range /= 2;
  145. }
  146. }
  147.  
  148. // Pomocnicza funkcja zaorkąglająca wartości
  149. void clamp(int* val, int min, int max)
  150. {
  151. if (*val < min) *val = min;
  152. if (*val > max) *val = max;
  153. }
  154.  
  155. // Pomocnicza funkcja zaorkąglająca wszystkie wartości w macierzy
  156. void clamp_map()
  157. {
  158. for (int i = 0; i < size; i++)
  159. {
  160. for (int j = 0; j < size; j++)
  161. {
  162. clamp(&map[i][j], 0, 255);
  163. }
  164. }
  165. }
  166.  
  167. // Funkcja renderująca obraz z macierzy na ekran
  168. void render()
  169. {
  170. // Inicjalizacja zmiennej przechowującej kolor
  171. int color;
  172. // Wyczyszczenie ekranu
  173. glClear(GL_COLOR_BUFFER_BIT);
  174. // Ustalenie rozmiaru pojedyńczego punktu
  175. glPointSize(3);
  176. // Wypełnienie obrazu punktami z macierzy
  177. glBegin(GL_POINTS);
  178. for (int i = 0; i < size; i++)
  179. {
  180. for (int j = 0; j < size; j++)
  181. {
  182. // Przypisanie koloru z macierzy
  183. color = map[j][i];
  184. glColor3ub(color, color, color);
  185. // Narysowanie kwadratu o zadanym kolorze
  186. glVertex2f(i * 100.0f/size, j * 100.0f/size);
  187. }
  188. }
  189.  
  190. // Zakończenie renderowania
  191. glEnd();
  192. glFlush();
  193. }
  194.  
  195. // Parametry horizontal i vertical (szerokość i wysokość okna) są
  196. // przekazywane do funkcji za każdym razem, gdy zmieni się rozmiar okna
  197. void ChangeSize(GLsizei horizontal, GLsizei vertical)
  198. {
  199. // Deklaracja zmiennej AspectRatio określającej proporcję wymiarów okna
  200. GLfloat AspectRatio;
  201. // Zabezpieczenie przed dzieleniem przez 0
  202. if (vertical == 0) vertical = 1;
  203. // Ustawienie wielkościokna okna urządzenia (Viewport)
  204. // W tym przypadku od (0,0) do (horizontal, vertical)
  205. glViewport(0, 0, horizontal, vertical);
  206. // Określenie układu współrzędnych obserwatora
  207. glMatrixMode(GL_PROJECTION);
  208. // Określenie przestrzeni ograniczającej
  209. glLoadIdentity();
  210. // Wyznaczenie współczynnika proporcji okna
  211. AspectRatio = (GLfloat)horizontal / (GLfloat)vertical;
  212. // Gdy okno na ekranie nie jest kwadratem wymagane jest
  213. // określenie okna obserwatora.
  214. // Pozwala to zachować właściwe proporcje rysowanego obiektu
  215. // Do określenia okna obserwatora służy funkcja glOrtho(...)
  216. if (horizontal <= vertical) glOrtho(0, 100.0, 100.0 / AspectRatio, 0, 1.0, -1.0);
  217. else glOrtho(0, 100.0*AspectRatio, 100.0, 0, 1.0, -1.0);
  218. // Określenie układu współrzędnych
  219. glMatrixMode(GL_MODELVIEW);
  220. glLoadIdentity();
  221.  
  222. }
  223.  
  224. // Zmiana zachowania przy pomocy klawiszy
  225. void handle_input(unsigned char key, int x, int y)
  226. {
  227. switch (key)
  228. {
  229. // Zamknięcie programu klawiszem ESC
  230. case 27:
  231. glutDestroyWindow(glutGetWindow());
  232. exit(0);
  233. break;
  234. // Generacja nowego obrazu klawiszem SPACE
  235. case 32:
  236. range = 196;
  237. init();
  238. fractal();
  239. clamp_map();
  240. glutPostRedisplay();
  241. break;
  242. // Zmiana shadingu klawiszami 1,2,3
  243. case '1':
  244. glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
  245. break;
  246. case '2':
  247. glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
  248. break;
  249. case '3':
  250. glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
  251. break;
  252. }
  253. }
  254.  
  255. // Inicjalizacja OpenGL
  256. void initGL() {
  257. // Ustawienia koloru czarnego dla tła
  258. glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  259. // Ustawienie głębokości renderowania na maksymalną
  260. glClearDepth(1.0f);
  261. // Uruchomienie i konfiguracja testów głębokości (z-culling)
  262. glEnable(GL_DEPTH_TEST);
  263. glDepthFunc(GL_LEQUAL);
  264. // Uruchomienie wygładzania
  265. glShadeModel(GL_SMOOTH);
  266. // Korekcja perspektywy
  267. glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
  268. }
  269.  
  270.  
  271. // Funkcja odświerzająca widok po upływie czasu
  272. void timer(int value) {
  273. glutPostRedisplay();
  274. glutTimerFunc(refreshMills, timer, 0);
  275. }
  276.  
  277. // Funcja zwracająca losową wartość typu float
  278. float randomFloat()
  279. {
  280. float r3 = 0 + static_cast <float> (rand()) / (static_cast <float> (RAND_MAX / (0.7f - 0)));
  281. return r3;
  282. }
  283.  
  284. // Funkcja konwertująca kolor na jego czarno-biały odpowiednik
  285. void monoColor(float color)
  286. {
  287. glColor3ub(color, color, color);
  288. }
  289.  
  290. // Funkcja wywoływana w momencie, kiedy wykonywany jest repaint okna
  291. void display() {
  292. // Czyszczenie koloru i głębokości
  293. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  294. // Aktywacja widoku modelu dla macierzy
  295. glMatrixMode(GL_MODELVIEW);
  296. // Reset widoku modelu
  297. glLoadIdentity();
  298. // Przesunięcie w lewo i wokół osi
  299. glTranslatef(0, -0.3f, -1.5f);
  300. glRotatef(90, 0, 0, 1);
  301. glRotatef(60, 0, 1, 0);
  302. glRotatef(angle += 0.5f, 0, 0, 1);
  303. // Rysowanie piramidowych trójkątów
  304. glBegin(GL_TRIANGLES);
  305. for (int y = 0; y < size - 1; y++)
  306. {
  307. for (int x = 0; x < size - 1; x++)
  308. {
  309. // Uśrednienie wartości dla pośrednich punktów
  310. float midpoint_value = (map[y][x] + map[y][x + 1] + map[y + 1][x] + map[y + 1][x + 1])/4.0f;
  311. float midpoint_x = 1.0f / size * (x + 0.5f);
  312. float midpoint_y = 1.0f / size * (y + 0.5f);
  313.  
  314. // Góra
  315. monoColor(map[y][x]);
  316. glVertex3f(1.0f / size*x - 0.5f, 1.0f / size*y - 0.5f, 1.0f / 256 * map[y][x]);
  317.  
  318. monoColor(midpoint_value);
  319. glVertex3f(midpoint_x - 0.5f, midpoint_y - 0.5f, 1.0f / 256 * midpoint_value );
  320.  
  321. monoColor(map[y][x + 1]);
  322. glVertex3f(1.0f / size*(x + 1) - 0.5f, 1.0f / size*y - 0.5f, 1.0f / 256 * map[y][x + 1]);
  323.  
  324. // Lewo
  325. monoColor(map[y][x]);
  326. glVertex3f(1.0f / size*x - 0.5f, 1.0f / size*y - 0.5f, 1.0f / 256 * map[y][x]);
  327.  
  328. monoColor(map[y + 1][x]);
  329. glVertex3f(1.0f / size*x - 0.5f, 1.0f / size*(y + 1) - 0.5f, 1.0f / 256 * map[y + 1][x]);
  330.  
  331. monoColor(midpoint_value);
  332. glVertex3f(midpoint_x - 0.5f, midpoint_y - 0.5f, 1.0f / 256 * midpoint_value);
  333.  
  334. // Dół
  335. monoColor(map[y + 1][x + 1]);
  336. glVertex3f(1.0f / size*(x+1) - 0.5f, 1.0f / size*(y+1) - 0.5f, 1.0f / 256 * map[y+1][x+1]);
  337.  
  338. monoColor(map[y + 1][x]);
  339. glVertex3f(1.0f / size*x - 0.5f, 1.0f / size*(y + 1) - 0.5f, 1.0f / 256 * map[y+1][x]);
  340.  
  341. monoColor(midpoint_value);
  342. glVertex3f(midpoint_x - 0.5f, midpoint_y - 0.5f, 1.0f / 256 * midpoint_value);
  343.  
  344. // Prawo
  345. monoColor(map[y][x + 1]);
  346. glVertex3f(1.0f / size*(x + 1) - 0.5f, 1.0f / size*y - 0.5f, 1.0f / 256 * map[y][x + 1]);
  347.  
  348. monoColor(midpoint_value);
  349. glVertex3f(midpoint_x - 0.5f, midpoint_y - 0.5f, 1.0f / 256 * midpoint_value);
  350.  
  351. monoColor(map[y + 1][x + 1]);
  352. glVertex3f(1.0f / size*(x + 1) - 0.5f, 1.0f / size*(y + 1) - 0.5f, 1.0f / 256 * map[y+1][x+1]);
  353. }
  354. }
  355.  
  356. // Zakończenie rysowania trójkątów
  357. glEnd();
  358. // Zmiana buforów klatek
  359. glutSwapBuffers();
  360. }
  361.  
  362. // Funkcja obslugująca zmianę rozmiaru okna
  363. void reshape(GLsizei width, GLsizei height) {
  364. if (height == 0) height = 1;
  365. GLfloat aspect = (GLfloat)width / (GLfloat)height;
  366. glViewport(0, 0, width, height);
  367. glMatrixMode(GL_PROJECTION);
  368. glLoadIdentity();
  369. gluPerspective(45.0f, aspect, 0.1f, 100.0f);
  370. }
  371.  
  372.  
  373. int main(int argc, char** argv) {
  374.  
  375. init();
  376. fractal();
  377. clamp_map();
  378.  
  379. glutInit(&argc, argv);
  380. glutInitDisplayMode(GLUT_DOUBLE);
  381. glutInitWindowSize(640, 480);
  382. glutInitWindowPosition(50, 50);
  383. glutCreateWindow("Fraktal Plazmowy 3-D");
  384. glutDisplayFunc(display);
  385. glutReshapeFunc(reshape);
  386. glutKeyboardFunc(handle_input);
  387. initGL();
  388. glutTimerFunc(0, timer, 0);
  389. glutMainLoop();
  390.  
  391. return 0;
  392. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement