DEVELOPMENT ENVIRONMENT

~alex/mandelbrot-set-gen

ref: 03d3348a745b77e464e2e830ad7bd8cef5bfdff0 mandelbrot-set-gen/src/main.c -rw-r--r-- 3.7 KiB
03d3348aAlejandro Laguna fix: visual not appearing without event a month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
#include "SDL3/SDL.h"
#include "mandelbrot.h"
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_init.h>
#include <SDL3/SDL_oldnames.h>
#include <SDL3/SDL_rect.h>
#include <SDL3/SDL_render.h>
#include <SDL3/SDL_surface.h>
#include <SDL3/SDL_video.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

// TODO: GPU shadering option
// TODO: flexible window size
// TODO: maybe? change colors

#define WINDOW_TITLE "Mandelbrot Visualization"
#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600

static int points[WINDOW_WIDTH * WINDOW_HEIGHT];

typedef struct position_s {
    double x_min;
    double x_max;
    double y_min;
    double y_max;
} position_t;

void calculate_points(position_t* pos) {
    int max_iter = 100;
    for (int py = 0; py < WINDOW_HEIGHT; py++) {
        for (int px = 0; px < WINDOW_WIDTH; px++) {
            double cr = pos->x_min + (pos->x_max - pos->x_min) * px / (WINDOW_WIDTH - 1);
            double ci = pos->y_min + (pos->y_max - pos->y_min) * py / (WINDOW_HEIGHT - 1);
            points[py * WINDOW_WIDTH + px] = mandelbrot_iterations(cr, ci, max_iter);
        }
    }
}

void draw_points(SDL_Surface* surface) {
    for (int py = 0; py < WINDOW_HEIGHT; py++) {
        for (int px = 0; px < WINDOW_WIDTH; px++) {
            int r, g, b;
            get_color(points[py * WINDOW_WIDTH + px], 100, &r, &g, &b);
            SDL_WriteSurfacePixel(surface, px, py, r, g, b, 255);
        }
    }
};

int main(void) {
    if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) {
        fprintf(stderr, "SDL_Init failed: %s\n", SDL_GetError());
        return -1;
    }

    SDL_Window* window =
        SDL_CreateWindow(WINDOW_TITLE, WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_HIDDEN);
    if (window == NULL) {
        fprintf(stderr, "CreateWindowAndRenderer failed: %s\n", SDL_GetError());
        SDL_Quit();
        return -1;
    }

    SDL_Surface* surface = SDL_GetWindowSurface(window);
    if (!surface) {
        return -1;
    }
    SDL_Event e;
    bool running = true;
    SDL_UpdateWindowSurface(window);
    SDL_ShowWindow(window);
    position_t position;
    position.x_min = -2.0;
    position.x_max = 1.0;
    position.y_min = -1.2;
    position.y_max = 1.2;

    bool pos_updated = true;
    while (running) {
        while (SDL_PollEvent(&e)) {
            if (e.type == SDL_EVENT_QUIT) {
                running = false;
            }
            if (e.type == SDL_EVENT_MOUSE_WHEEL) {
                // 1. Get mouse pixel position
                float mx, my;
                SDL_GetMouseState(&mx, &my);

                double cr =
                    position.x_min + (position.x_max - position.x_min) * mx / (WINDOW_WIDTH - 1);
                double ci =
                    position.y_min + (position.y_max - position.y_min) * my / (WINDOW_HEIGHT - 1);

                double range_y = position.y_max - position.y_min;

                float factor = (e.wheel.y > 0) ? 0.9f : 1.1f;
                double new_height = range_y * factor;
                double aspect = (double)WINDOW_WIDTH / WINDOW_HEIGHT;
                double new_width = new_height * aspect;

                position.x_min = cr - (double)mx / (WINDOW_WIDTH - 1) * new_width;
                position.x_max = position.x_min + new_width;
                position.y_min = ci - (double)my / (WINDOW_HEIGHT - 1) * new_height;
                position.y_max = position.y_min + new_height;
                pos_updated = true;
            }
        }
        if (pos_updated) {
            calculate_points(&position);
            pos_updated = false;
        }
        draw_points(surface);
        SDL_UpdateWindowSurface(window);
        SDL_Delay(16);
    }

    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}