Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <SDL2/SDL.h>
- #include <stdio.h>
- #include <time.h>
- #include <math.h>
- #define TITLE "Fractal"
- bool quit = false;
- uint fps = 60;
- uint minframetime = 1000 / fps;
- uint16_t window_size = 512;
- int convergenceSpeed[512][512];
- typedef struct ColorRGBA {
- int R, G, B, A;
- } colors[10];
- struct Point {
- float x, y;
- };
- Point c = { -0.9, 0 };
- int zoom = window_size / 4;
- int roundOffPrecision = 1;
- void events(SDL_Window *window);
- void draw(SDL_Renderer *renderer);
- int computeConvergenceForPoint(int x, int y);
- void computeConvergence();
- float roundOff(float value);
- uint rainbow(uint n);
- uint wave(uint n);
- int main(int argc, char **argv) {
- SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS);
- SDL_Window *window =
- SDL_CreateWindow(
- TITLE,
- SDL_WINDOWPOS_CENTERED,
- SDL_WINDOWPOS_CENTERED,
- window_size,
- window_size,
- SDL_WINDOW_OPENGL);
- int display_index = SDL_GetWindowDisplayIndex(window);
- SDL_DisplayMode mode;
- if (SDL_GetDesktopDisplayMode(display_index, &mode) == 0) {
- fps = mode.refresh_rate;
- minframetime = 1000 / fps;
- }
- SDL_Renderer *renderer =
- SDL_CreateRenderer(
- window,
- -1,
- SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
- computeConvergence();
- while (!quit) {
- int start = SDL_GetTicks();
- events(window);
- draw(renderer);
- SDL_RenderPresent(renderer);
- int time = SDL_GetTicks() - start;
- int sleepTime = minframetime - time;
- if (sleepTime > 0) {
- SDL_Delay(sleepTime);
- }
- }
- SDL_DestroyRenderer(renderer);
- SDL_DestroyWindow(window);
- SDL_Quit();
- return 0;
- }
- void events(SDL_Window *window) {
- SDL_Event event;
- while (SDL_PollEvent(&event) != 0) {
- if (event.type == SDL_QUIT) {
- quit = true;
- }
- // code for zooming
- else if (event.type == SDL_KEYDOWN) {
- SDL_Keycode keycode = event.key.keysym.sym;
- switch (keycode) {
- // PgUp is zooming in
- case SDLK_PAGEUP:
- printf("PgUp key pressed\n");
- zoom *= 2;
- computeConvergence();
- break;
- // PgDown is zooming out
- case SDLK_PAGEDOWN:
- printf("PgDown key pressed\n");
- zoom /= 2;
- computeConvergence();
- break;
- // 0 is for resetting precision
- case SDLK_0:
- printf("0 key pressed\n");
- roundOffPrecision = 1;
- computeConvergence();
- break;
- // 1 is for increasing precision
- case SDLK_1:
- printf("1 key pressed\n");
- roundOffPrecision++;
- computeConvergence();
- break;
- }
- }
- }
- }
- void draw(SDL_Renderer *renderer) {
- SDL_SetRenderDrawColor(renderer, 255, 236, 179, 255);
- SDL_RenderClear(renderer);
- SDL_SetRenderDrawColor(renderer, 100, 221, 23, 255);
- // x axis
- SDL_RenderDrawLine(renderer, 0, 512 / 2, 512, 512 / 2);
- // y axis
- SDL_RenderDrawLine(renderer, 512 / 2, 0, 512 / 2, 512);
- // draw the fractal based on convergenceSpeed
- for (int x = 0; x < window_size; x++) {
- for (int y = 0; y < window_size; y++) {
- if (convergenceSpeed[x][y] > 0) {
- uint color = (uint)convergenceSpeed[x][y];
- unsigned int red = (color & 0x00ff0000) >> 16;
- unsigned int green = (color & 0x0000ff00) >> 8;
- unsigned int blue = (color & 0x000000ff);
- SDL_SetRenderDrawColor(renderer, red, green, blue, 255);
- SDL_RenderDrawPoint(renderer, x, y);
- }
- }
- }
- }
- int computeConvergenceForPoint(int x, int y) {
- // current Z
- Point Zc;
- Zc.x = ((float)(x) - (float)(window_size) / 2) / zoom;
- Zc.y = -((float)(y) - (float)(window_size) / 2) / zoom;
- // initial Z, precedent Z, next Z
- Point Z0 = Zc, Zp, Zn;
- for (int i = 1; i <= 100; i++) {
- Zn.x = Zc.x * Zc.x - Zc.y * Zc.y + c.x;
- Zn.y = 2 * Zc.x * Zc.y + c.y;
- // First check if it converged
- // If Zc = Zn then it converged
- if (roundOff(Zc.x) == roundOff(Zn.x) && roundOff(Zc.y) == roundOff(Zn.y)) return rainbow(i);
- // Second check if it converged
- // There is a case in which Z starts alternating, that means Zp = Zn
- if (roundOff(Zp.x) == roundOff(Zn.x) && roundOff(Zp.y) == roundOff(Zn.y)) return rainbow(i);
- Zp = Zc;
- Zc = Zn;
- // Check if it diverged
- if (abs(Zc.x) > 512 || abs(Zc.y) > 512) return 0x00FF00;
- }
- return 0x00FF00;
- }
- void computeConvergence() {
- for (int x = 0; x < window_size; x++) {
- for (int y = 0; y < window_size; y++) {
- convergenceSpeed[x][y] = computeConvergenceForPoint(x, y);
- if (convergenceSpeed[x][y] == 100) {
- printf("(%d %d)\n", x, y);
- }
- }
- }
- }
- float roundOff(float value) {
- float pow_10 = pow(10.0f, (float)roundOffPrecision);
- return round(value * pow_10);
- }
- uint rainbow(uint n) {
- return (wave(n) << 16) + (wave(n + 85) << 8) + wave(n + 170);
- }
- uint wave(uint n) {
- return int(125 * sin(n / 15) + 126);
- }
Advertisement
Add Comment
Please, Sign In to add comment