Finish the foundation, provide basic functionality
authorLukas <ljiriste@student.42prague.com>
Wed, 8 Nov 2023 09:14:55 +0000 (10:14 +0100)
committerLukas <ljiriste@student.42prague.com>
Wed, 8 Nov 2023 09:14:55 +0000 (10:14 +0100)
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
color.h
fractol.h
main.c
vect2.c [new file with mode: 0644]
vect2.h [new file with mode: 0644]

diff --git a/color.c b/color.c
index aa85feec9a97e09af7ffb9ecbbb19f9eaef19220..a146089d0efa026f284a3159f62e24dc29a4e487 100644 (file)
--- 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 bc2efd38dfc4e37ac273f8d31a26fcbb0eea2505..8a67ca0b1b7ed45ffc02bfed955bb2f0a423bec3 100644 (file)
--- 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
index 00dfdf1c2f71b3b9158ea24c1800b49bd032def8..51d1ff1c5f7df47c8d327a320262fe24f677ffa1 100644 (file)
--- 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 9afdb6fd43f887dd186f33707ff5c4b654b7b103..2302ee1ffebb4b8605c7afa51ef681cc77bb7da6 100644 (file)
--- a/main.c
+++ b/main.c
 #include <X11/keysym.h>
 #include <limits.h>
 #include <stdlib.h>
+#include <math.h>
 #include <mlx.h>
 #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 (file)
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 (file)
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