From 2d3950fc43370612f87a1243398e5986718518c1 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 8 Nov 2023 10:14:55 +0100 Subject: [PATCH] Finish the foundation, provide basic functionality Make structural changes to project for easier handling and addition of palettes and fractals. Introduce the executable actually working. It draws mandelbrot set. Add zoom in/out functionality. Introduce some color issues (needs investigation). --- color.c | 13 ++++ color.h | 1 + fractol.h | 32 +++++---- main.c | 195 ++++++++++++++++++++++++++++++++---------------------- vect2.c | 4 ++ vect2.h | 12 ++++ 6 files changed, 165 insertions(+), 92 deletions(-) create mode 100644 vect2.c create mode 100644 vect2.h diff --git a/color.c b/color.c index aa85fee..a146089 100644 --- a/color.c +++ b/color.c @@ -42,3 +42,16 @@ t_color double_grad(double normalized_par) return (lin_interp_color(to_color(0x00000000), to_color(0x000000FF), normalized_par / breakpoint)); return (lin_interp_color(to_color(0x000000FF), to_color(0x00FFFF00), (normalized_par - breakpoint) / breakpoint)); } + +t_color tri_color(double np) +{ + if (np < 0) + np = 0; + else if (np > 1) + np = 1; + if (np < 1/3.) + return (lin_interp_color(to_color(0x000000FF), to_color(0x00FFFF00), np * 3)); + if (np < 2/3.) + return (lin_interp_color(to_color(0x00FFFF00), to_color(0x00FF0000), np * 3 - 1)); + return (lin_interp_color(to_color(0x00FF0000), to_color(0x000000FF), np * 3 - 2)); +} diff --git a/color.h b/color.h index bc2efd3..8a67ca0 100644 --- a/color.h +++ b/color.h @@ -14,5 +14,6 @@ typedef struct s_color t_color; t_color lin_interp_color(t_color zero, t_color one, double norm_par); t_color basic_palette(double normalized_par); t_color double_grad(double normalized_par); +t_color tri_color(double np); #endif diff --git a/fractol.h b/fractol.h index 00dfdf1..51d1ff1 100644 --- a/fractol.h +++ b/fractol.h @@ -3,6 +3,8 @@ # define FRACTOL_H # include "libft.h" +# include "color.h" +# include "vect2.h" struct s_img { @@ -11,28 +13,30 @@ struct s_img int bpp; int bpl; int endian; + int width; + int height; }; typedef struct s_img t_img; -struct s_session +struct s_view { - void *mlx; - t_list *windows; - size_t win_count; + double (*fractal)(); + t_color (*palette)(double); + t_vect2 window_coord; + t_vect2 pixel_size; + double resolution; + int draw_whole; }; -typedef struct s_session t_session; +typedef struct s_view t_view; -struct s_window +struct s_session { - t_session *s; - size_t id; + void *mlx; + void *win; + t_img img; + t_view view; }; -typedef struct s_window t_window; +typedef struct s_session t_session; -enum mlx_status -{ - mlx_success, - mlx_window_error, -}; #endif diff --git a/main.c b/main.c index 9afdb6f..2302ee1 100644 --- a/main.c +++ b/main.c @@ -14,11 +14,13 @@ #include #include #include +#include #include #include "libft.h" #include "fractol.h" #include "complex.h" #include "color.h" +#include "vect2.h" void ft_putpx_img(t_img *img, int x, int y, t_color c) { @@ -42,61 +44,35 @@ void ft_putpx_img(t_img *img, int x, int y, t_color c) return ; } -int handle_key_press(int keycode, t_window *w) +int is_black(t_img *img, int x, int y) { - if (keycode == XK_Escape) - mlx_destroy_window(w->s, w->s->windows[w->index]); - return (0); -} + char *px_addr; -int handle_button_rel(int button_code, __attribute__((unused)) t_session *s) -{ - ft_printf("Button_code:\t%i\n", button_code); - return (0); + px_addr = img->addr + y * img->bpl + x * img->bpp / CHAR_BIT; + return (!(px_addr[0] || px_addr[1] || px_addr[2] || px_addr[3])); } + void free_session(t_session *s) { - size_t i; - - i = 0; - while (i < s->win_count) - mlx_destroy_window(s->mlx, s->windows[i]); - free(s->windows); + mlx_destroy_display(s->mlx); free(s->mlx); return ; } -void free_img(t_img *i) -{ - free(i->img); - free(i->addr); - return ; -} - -enum mlx_status add_mlx_window(t_session *s, int x, int y, char *name) -{ - void **tmp; - - tmp = malloc((s->win_count + 1) * sizeof(s->windows)); - if (!tmp) - return (mlx_window_error); - ft_memcpy(tmp, s->windows, s->win_count); - free(s->windows); - s->windows = tmp; - (s->windows)[s->win_count] = mlx_new_window(s->mlx, x, y, name); - if (!(s->windows)[s->win_count]) - return (mlx_window_error); - ++(s->win_count); - return (mlx_success); -} - -t_color mandelbrot(t_complex c, double threshold, int max_count, t_color (*palette)(double)) +double mandelbrot(double x, double y, double resolution) { + double threshold; const double min_threshold = 2.5; + double max_count; int count; + t_complex c; t_complex z; + c.r = x; + c.i = y; + max_count = 100 * resolution; + threshold = 3; if (threshold < min_threshold) threshold = min_threshold; count = 0; @@ -108,61 +84,124 @@ t_color mandelbrot(t_complex c, double threshold, int max_count, t_color (*palet ++count; } if (count == max_count) - count = 0; - return (palette((double)count / max_count)); + return (0); + return (fmod(count / 100., 1.)); } -/* -int main(void) + + +int draw_fractal(t_session *s) { - t_session s; - t_img img; + int x; + int y; + double palette_param; - s.win_count = 0; - s.windows = NULL; - s.mlx = mlx_init(); - add_mlx_window(&s, 1920, 1080, "Hello world!"); - img.img = mlx_new_image(s.mlx, 1920, 1080); - img.addr = mlx_get_data_addr(img.img, &img.bpp, &img.bpl, &img.endian); - mlx_hook(s.windows[0], KeyPress, KeyPressMask, handle_key_press, &(t_window){.s=&s, .index=0}); - mlx_hook(s.windows[0], ButtonRelease, ButtonRelease, handle_button_rel, &s); - mlx_loop(s.mlx); - mlx_destroy_image(s.mlx, img.img); - mlx_destroy_display(s.mlx); - free_img(&img); - free_session(&s); + x = 0; + while (x < s->img.width) + { + y = 0; + while (y < s->img.height) + { + if(!is_black(&s->img, x, y) && !s->view.draw_whole) + { + ++y; + continue ; + } + palette_param = s->view.fractal( + s->view.window_coord.x + s->view.pixel_size.x * x, + s->view.window_coord.y - s->view.pixel_size.y * y, + s->view.resolution); + ft_putpx_img(&s->img, x, y, s->view.palette(palette_param)); + ++y; + } + ++x; + } + mlx_put_image_to_window(s->mlx, s->win, s->img.img, 0, 0); return (0); } -*/ - -typedef struct +void change_zoom(t_view *view, t_vect2 invariant, double d_zoom) { - void *mlx; - void *win; -} t_test; + view->pixel_size.x /= d_zoom; + view->pixel_size.y /= d_zoom; + view->window_coord.x += view->pixel_size.x * invariant.x * (d_zoom - 1); + view->window_coord.y -= view->pixel_size.y * invariant.y * (d_zoom - 1); + view->resolution = 1; + view->draw_whole = 1; + return ; +} -int esc_close(int keycode, t_test *t) +int handle_key_press(int keycode, t_session *s) { if (keycode == XK_Escape) - mlx_destroy_window(t->mlx, t->win); + mlx_destroy_window(s->mlx, s->win); + return (0); +} + +int handle_mouse_press(int button, int x, int y, t_session *s) +{ + double delta_zoom; + + if (button == Button4) + delta_zoom = 0.5; + else if (button == Button5) + delta_zoom = 2; + if (button == Button4 || button == Button5) + { + change_zoom(&s->view, (t_vect2){.x = x, .y = y}, delta_zoom); + draw_fractal(s); + } return (0); } -int no_event(__attribute__((unused)) t_test *t) +int no_event_handle(__attribute__((unused)) t_session *s) { + if (s->view.resolution < 100) + { + s->view.draw_whole = 0; + s->view.resolution *= 2; + draw_fractal(s); + } return (0); } -int main(void) +void init_view(t_session *s) +{ + s->view.fractal = mandelbrot; + s->view.palette = tri_color; + s->view.pixel_size.x = 0.01; + s->view.pixel_size.y = 0.01; + s->view.window_coord.x = -s->img.width / 2 * s->view.pixel_size.x; + s->view.window_coord.y = s->img.height / 2 * s->view.pixel_size.y; + s->view.resolution = 1; + s->view.draw_whole = 1; + return ; +} + +void parse_args(int argc, char **argv, t_session *s) +{ + if (argc == 0) + free(argv); + s->img.width = 1024; + s->img.height = 768; + init_view(s); + return ; +} + +int main(int argc, char **argv) { - t_test t; - - t.mlx = mlx_init(); - t.win = mlx_new_window(t.mlx, 1920, 1080, "TEST"); - mlx_hook(t.win, KeyPress, KeyPressMask, esc_close, &t); - mlx_loop_hook(t.mlx, no_event, &t); - mlx_loop(t.mlx); - mlx_destroy_display(t.mlx); - free(t.mlx); + t_session s; + + parse_args(argc, argv, &s); + s.mlx = mlx_init(); + s.win = mlx_new_window(s.mlx, s.img.width, s.img.height, "Fract-ol"); + s.img.img = mlx_new_image(s.mlx, s.img.width, s.img.height); + s.img.addr = mlx_get_data_addr(s.img.img, &s.img.bpp, &s.img.bpl, &s.img.endian); + mlx_hook(s.win, KeyPress, KeyPressMask, handle_key_press, &s); + mlx_hook(s.win, ButtonPress, ButtonPressMask, handle_mouse_press, &s); + mlx_loop_hook(s.mlx, no_event_handle, &s); + draw_fractal(&s); + mlx_loop(s.mlx); + mlx_destroy_image(s.mlx, s.img.img); + free_session(&s); return (0); } diff --git a/vect2.c b/vect2.c new file mode 100644 index 0000000..865a60e --- /dev/null +++ b/vect2.c @@ -0,0 +1,4 @@ + +#include "vect2.h" + + diff --git a/vect2.h b/vect2.h new file mode 100644 index 0000000..005b3ce --- /dev/null +++ b/vect2.h @@ -0,0 +1,12 @@ + +#ifndef VECT2_H +# define VECT2_H + +struct s_vect2 +{ + double x; + double y; +}; +typedef struct s_vect2 t_vect2; + +#endif -- 2.30.2