YorKnEz

fractals.cpp

Apr 3rd, 2022 (edited)
110
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.97 KB | None | 0 0
  1. #include <SDL2/SDL.h>
  2. #include <stdio.h>
  3. #include <time.h>
  4. #include <math.h>
  5.  
  6. #define TITLE "Fractal"
  7.  
  8. bool quit = false;
  9.  
  10. uint fps = 60;
  11. uint minframetime = 1000 / fps;
  12. uint16_t window_size = 512;
  13.  
  14. int convergenceSpeed[512][512];
  15.  
  16. typedef struct ColorRGBA {
  17. int R, G, B, A;
  18. } colors[10];
  19.  
  20. struct Point {
  21. float x, y;
  22. };
  23.  
  24. Point c = { -0.9, 0 };
  25. int zoom = window_size / 4;
  26. int roundOffPrecision = 1;
  27.  
  28. void events(SDL_Window *window);
  29.  
  30. void draw(SDL_Renderer *renderer);
  31.  
  32. int computeConvergenceForPoint(int x, int y);
  33.  
  34. void computeConvergence();
  35.  
  36. float roundOff(float value);
  37.  
  38. uint rainbow(uint n);
  39.  
  40. uint wave(uint n);
  41.  
  42. int main(int argc, char **argv) {
  43.  
  44. SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
  45.  
  46. SDL_Window *window =
  47. SDL_CreateWindow(
  48. TITLE,
  49. SDL_WINDOWPOS_CENTERED,
  50. SDL_WINDOWPOS_CENTERED,
  51. window_size,
  52. window_size,
  53. SDL_WINDOW_OPENGL);
  54.  
  55. int display_index = SDL_GetWindowDisplayIndex(window);
  56.  
  57. SDL_DisplayMode mode;
  58.  
  59. if (SDL_GetDesktopDisplayMode(display_index, &mode) == 0) {
  60. fps = mode.refresh_rate;
  61. minframetime = 1000 / fps;
  62. }
  63.  
  64. SDL_Renderer *renderer =
  65. SDL_CreateRenderer(
  66. window,
  67. -1,
  68. SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
  69.  
  70. computeConvergence();
  71.  
  72. while (!quit) {
  73. int start = SDL_GetTicks();
  74.  
  75. events(window);
  76. draw(renderer);
  77.  
  78. SDL_RenderPresent(renderer);
  79.  
  80. int time = SDL_GetTicks() - start;
  81. int sleepTime = minframetime - time;
  82. if (sleepTime > 0) {
  83. SDL_Delay(sleepTime);
  84. }
  85. }
  86.  
  87. SDL_DestroyRenderer(renderer);
  88. SDL_DestroyWindow(window);
  89. SDL_Quit();
  90.  
  91. return 0;
  92. }
  93.  
  94. void events(SDL_Window *window) {
  95. SDL_Event event;
  96.  
  97. while (SDL_PollEvent(&event) != 0) {
  98. if (event.type == SDL_QUIT) {
  99. quit = true;
  100. }
  101. // code for zooming
  102. else if (event.type == SDL_KEYDOWN) {
  103. SDL_Keycode keycode = event.key.keysym.sym;
  104.  
  105. switch (keycode) {
  106. // PgUp is zooming in
  107. case SDLK_PAGEUP:
  108. printf("PgUp key pressed\n");
  109. zoom *= 2;
  110.  
  111. computeConvergence();
  112. break;
  113. // PgDown is zooming out
  114. case SDLK_PAGEDOWN:
  115. printf("PgDown key pressed\n");
  116. zoom /= 2;
  117.  
  118. computeConvergence();
  119. break;
  120. // 0 is for resetting precision
  121. case SDLK_0:
  122. printf("0 key pressed\n");
  123. roundOffPrecision = 1;
  124.  
  125. computeConvergence();
  126. break;
  127. // 1 is for increasing precision
  128. case SDLK_1:
  129. printf("1 key pressed\n");
  130. roundOffPrecision++;
  131.  
  132. computeConvergence();
  133. break;
  134. }
  135. }
  136. }
  137. }
  138.  
  139. void draw(SDL_Renderer *renderer) {
  140. SDL_SetRenderDrawColor(renderer, 255, 236, 179, 255);
  141. SDL_RenderClear(renderer);
  142.  
  143. SDL_SetRenderDrawColor(renderer, 100, 221, 23, 255);
  144. // x axis
  145. SDL_RenderDrawLine(renderer, 0, 512 / 2, 512, 512 / 2);
  146. // y axis
  147. SDL_RenderDrawLine(renderer, 512 / 2, 0, 512 / 2, 512);
  148.  
  149. // draw the fractal based on convergenceSpeed
  150. for (int x = 0; x < window_size; x++) {
  151. for (int y = 0; y < window_size; y++) {
  152. if (convergenceSpeed[x][y] > 0) {
  153. uint color = (uint)convergenceSpeed[x][y];
  154.  
  155. unsigned int red = (color & 0x00ff0000) >> 16;
  156. unsigned int green = (color & 0x0000ff00) >> 8;
  157. unsigned int blue = (color & 0x000000ff);
  158.  
  159. SDL_SetRenderDrawColor(renderer, red, green, blue, 255);
  160. SDL_RenderDrawPoint(renderer, x, y);
  161. }
  162. }
  163. }
  164. }
  165.  
  166. int computeConvergenceForPoint(int x, int y) {
  167. // current Z
  168. Point Zc;
  169.  
  170. Zc.x = ((float)(x) - (float)(window_size) / 2) / zoom;
  171. Zc.y = -((float)(y) - (float)(window_size) / 2) / zoom;
  172.  
  173. // initial Z, precedent Z, next Z
  174. Point Z0 = Zc, Zp, Zn;
  175.  
  176. for (int i = 1; i <= 100; i++) {
  177. Zn.x = Zc.x * Zc.x - Zc.y * Zc.y + c.x;
  178. Zn.y = 2 * Zc.x * Zc.y + c.y;
  179.  
  180. // First check if it converged
  181. // If Zc = Zn then it converged
  182. if (roundOff(Zc.x) == roundOff(Zn.x) && roundOff(Zc.y) == roundOff(Zn.y)) return rainbow(i);
  183.  
  184. // Second check if it converged
  185. // There is a case in which Z starts alternating, that means Zp = Zn
  186. if (roundOff(Zp.x) == roundOff(Zn.x) && roundOff(Zp.y) == roundOff(Zn.y)) return rainbow(i);
  187.  
  188. Zp = Zc;
  189. Zc = Zn;
  190.  
  191. // Check if it diverged
  192. if (abs(Zc.x) > 512 || abs(Zc.y) > 512) return 0x00FF00;
  193. }
  194.  
  195. return 0x00FF00;
  196. }
  197.  
  198. void computeConvergence() {
  199. for (int x = 0; x < window_size; x++) {
  200. for (int y = 0; y < window_size; y++) {
  201. convergenceSpeed[x][y] = computeConvergenceForPoint(x, y);
  202.  
  203. if (convergenceSpeed[x][y] == 100) {
  204. printf("(%d %d)\n", x, y);
  205. }
  206. }
  207. }
  208. }
  209.  
  210. float roundOff(float value) {
  211. float pow_10 = pow(10.0f, (float)roundOffPrecision);
  212. return round(value * pow_10);
  213. }
  214.  
  215. uint rainbow(uint n) {
  216. return (wave(n) << 16) + (wave(n + 85) << 8) + wave(n + 170);
  217. }
  218.  
  219. uint wave(uint n) {
  220. return int(125 * sin(n / 15) + 126);
  221. }
Advertisement
Add Comment
Please, Sign In to add comment