Change the code without much to show for it
authorLukas Jiriste <ljiriste@student.42prague.com>
Wed, 17 Jan 2024 14:02:12 +0000 (15:02 +0100)
committerLukas Jiriste <ljiriste@student.42prague.com>
Wed, 17 Jan 2024 14:02:12 +0000 (15:02 +0100)
Change the code so that adding partial picture construction is easier in
the future. Changes also support drawing in worse resolution.
Needs refactoring of main.c and possible checking the header files.

Libft
color.c
color.h
event_handling.c
fractol.h
main.c

diff --git a/Libft b/Libft
index 988bd412d9b3d0681457c4c169d398c273d0c6ff..00bb2e3124c52f1269675bb28175de780ffe9c6e 160000 (submodule)
--- a/Libft
+++ b/Libft
@@ -1 +1 @@
-Subproject commit 988bd412d9b3d0681457c4c169d398c273d0c6ff
+Subproject commit 00bb2e3124c52f1269675bb28175de780ffe9c6e
diff --git a/color.c b/color.c
index c7651e668bf502f724f9900dce2d74a400f6c0ca..00810009d6f45301ba5f2f5e4f5e53a069a87ee8 100644 (file)
--- a/color.c
+++ b/color.c
@@ -6,12 +6,12 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2023/11/11 18:50:32 by ljiriste          #+#    #+#             */
-/*   Updated: 2023/11/11 18:51:07 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/01/17 12:19:22 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
-#include <stddef.h>
 #include "color.h"
+#include <stddef.h>
 
 t_color        to_color(unsigned int num)
 {
diff --git a/color.h b/color.h
index b4f5f16a6702bcf5380f409524a5abcb3aa24110..cf2fa4d271553c6c4e630a342593f3cddb860fe9 100644 (file)
--- a/color.h
+++ b/color.h
@@ -6,13 +6,15 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2023/11/11 18:51:23 by ljiriste          #+#    #+#             */
-/*   Updated: 2023/11/11 18:51:25 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/01/17 12:20:02 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
 #ifndef COLOR_H
 # define COLOR_H
 
+# include <stddef.h>
+
 struct s_color
 {
        unsigned char   a;
index f6d6c3917a84399b83dc495b1f7c9e3dcc64b87c..b122286f678286a99878efc3e10a870d96692034 100644 (file)
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2023/12/05 19:35:01 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/01/17 10:31:31 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/01/17 14:42:38 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -25,17 +25,17 @@ int handle_key_press(int keycode, t_session *s)
        if (keycode == XK_Escape)
                close_win(s);
        else if (keycode == XK_Up || keycode == XK_w)
-               move_view(0, MOVE_AMOUNT, s);
+               move_view(s, 0, MOVE_AMOUNT);
        else if (keycode == XK_Left || keycode == XK_a)
-               move_view(-MOVE_AMOUNT, 0, s);
+               move_view(s, -MOVE_AMOUNT, 0);
        else if (keycode == XK_Down || keycode == XK_s)
-               move_view(0, -MOVE_AMOUNT, s);
+               move_view(s, 0, -MOVE_AMOUNT);
        else if (keycode == XK_Right || keycode == XK_d)
-               move_view(MOVE_AMOUNT, 0, s);
+               move_view(s, MOVE_AMOUNT, 0);
        else if (keycode == XK_KP_Add)
-               change_zoom(&s->view, (t_vect2){.x = s->img.width / 2, .y = s->img.height / 2}, ZOOM_IN);
+               change_zoom(s, (t_vect2){.x = s->img.width / 2, .y = s->img.height / 2}, ZOOM_IN);
        else if (keycode == XK_KP_Subtract)
-               change_zoom(&s->view, (t_vect2){.x = s->img.width / 2, .y = s->img.height / 2}, ZOOM_OUT);
+               change_zoom(s, (t_vect2){.x = s->img.width / 2, .y = s->img.height / 2}, ZOOM_OUT);
        if (keycode != XK_Escape)
                draw_fractal(s);
        return (0);
@@ -44,9 +44,9 @@ int   handle_key_press(int keycode, t_session *s)
 int    handle_mouse_press(int button, int x, int y, t_session *s)
 {
        if (button == Button4)
-               change_zoom(&s->view, (t_vect2){.x = x, .y = y}, ZOOM_OUT);
+               change_zoom(s, (t_vect2){.x = x, .y = y}, ZOOM_OUT);
        else if (button == Button5)
-               change_zoom(&s->view, (t_vect2){.x = x, .y = y}, ZOOM_IN);
+               change_zoom(s, (t_vect2){.x = x, .y = y}, ZOOM_IN);
        if (button == Button4 || button == Button5)
                draw_fractal(s);
        return (0);
@@ -60,10 +60,9 @@ int  handle_mouse_press(int button, int x, int y, t_session *s)
  */
 int    no_event_handle(t_session *s)
 {
-       if (s->view.resolution < 1)
+       if (s->img.undersample > 1)
        {
-               s->view.draw_whole = 0;
-               s->view.resolution *= 2;
+               --s->img.undersample;
                draw_fractal(s);
        }
        return (0);
index 7524676230eebc6a70d476ae576f2bb547619d60..b67781204eca560d951715f66e755d5ff408e1d1 100644 (file)
--- a/fractol.h
+++ b/fractol.h
@@ -6,7 +6,7 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2023/11/11 18:51:29 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/01/16 14:01:51 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/01/17 14:43:55 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
@@ -26,6 +26,8 @@ struct s_img
        int             endian;
        int             width;
        int             height;
+       t_mat   calced;
+       int             undersample;
 };
 typedef struct s_img   t_img;
 
@@ -35,8 +37,6 @@ struct s_view
        t_color (*palette)(double);
        t_vect2 window_coord;
        t_vect2 pixel_size;
-       double  resolution;
-       int             draw_whole;
 };
 typedef struct s_view  t_view;
 
@@ -52,9 +52,10 @@ typedef struct s_session     t_session;
 int    handle_key_press(int keycode, t_session *s);
 int    handle_mouse_press(int button, int x, int y, t_session *s);
 int    no_event_handle(t_session *s);
-int    draw_fractal(t_session *s);
-void   change_zoom(t_view *view, t_vect2 invariant, double d_zoom);
-void   move_view(float move_amount_right, float move_amount_up, t_session *s);
+void   process_pixel_group(t_session *s, int x, int y);
+void   draw_fractal(t_session *s);
+void   change_zoom(t_session *s, t_vect2 invariant, double d_zoom);
+void   move_view(t_session *s, float move_amount_right, float move_amount_up);
 int    close_win(t_session *s);
 
 #endif
diff --git a/main.c b/main.c
index f397d53c63a8dc89ac1237602c9e8cb2247528bf..26df455fb5afda857e6a06eab6fc01e06fb49f15 100644 (file)
--- a/main.c
+++ b/main.c
@@ -6,21 +6,22 @@
 /*   By: ljiriste <marvin@42.fr>                    +#+  +:+       +#+        */
 /*                                                +#+#+#+#+#+   +#+           */
 /*   Created: 2023/10/27 14:29:26 by ljiriste          #+#    #+#             */
-/*   Updated: 2024/01/17 10:29:34 by ljiriste         ###   ########.fr       */
+/*   Updated: 2024/01/17 14:49:49 by ljiriste         ###   ########.fr       */
 /*                                                                            */
 /* ************************************************************************** */
 
-#include <X11/X.h>
-#include <X11/keysym.h>
-#include <mlx.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <math.h>
-#include "libft.h"
-#include "fractol.h"
 #include "complex.h"
 #include "color.h"
 #include "vect2.h"
+#include "fractol.h"
+#include "libft.h"
+#include <mlx.h>
+#include <math.h>
+#include <stdbool.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <X11/keysym.h>
+#include <X11/X.h>
 
 int    close_win(t_session *s)
 {
@@ -28,11 +29,16 @@ int close_win(t_session *s)
        return (0);
 }
 
+void   *get_pixel(t_img *img, int x, int y)
+{
+       return (img->addr + y * img->bpl + x * img->bpp / CHAR_BIT);
+}
+
 void   ft_putpx_img(t_img *img, int x, int y, t_color c)
 {
        char    *px_addr;
 
-       px_addr = img->addr + y * img->bpl + x * img->bpp / CHAR_BIT;
+       px_addr = get_pixel(img, x, y);
        if (img->endian)
        {
                px_addr[0] = c.a;
@@ -50,15 +56,6 @@ void ft_putpx_img(t_img *img, int x, int y, t_color c)
        return ;
 }
 
-int    is_black(t_img *img, int x, int y)
-{
-       char    *px_addr;
-
-       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)
 {
        mlx_destroy_display(s->mlx);
@@ -66,10 +63,10 @@ void        free_session(t_session *s)
        return ;
 }
 
-double mandelbrot(double x, double y, double resolution)
+double mandelbrot(double x, double y)
 {
        const double    threshold = 1000;
-       const double    log2 = log(2);
+       const double    detail = 10;
        int                             count;
        t_complex               c;
        t_complex               z;
@@ -81,21 +78,83 @@ double      mandelbrot(double x, double y, double resolution)
        z.i = 0;
        if (complex_norm(c) > 4)
                return (0.01);
-       while (complex_norm(z) < threshold && count < 100 * resolution)
+       while (complex_norm(z) < threshold && count < 100 * detail)
        {
                z = complex_add(complex_mul(z, z), c);
                ++count;
        }
-       if (count == 100 * resolution)
+       if (count == 100 * detail)
                return (-1);
-       return (fmod((count + 1 - log(log(complex_norm(z)) / log2) / log2) / 100., 1.));
+       return (fmod((count + 1 - log(log(complex_norm(z)) / log(2)) / log(2)) / 100., 1.));
+}
+
+t_color        get_img_pixel_color(t_img *img, int x, int y)
+{
+       char    *px_addr;
+       t_color c;
+
+       px_addr = get_pixel(img, x, y);
+       if (img->endian)
+       {
+               c.a = px_addr[0];
+               c.r = px_addr[1];
+               c.g = px_addr[2];
+               c.b = px_addr[3];
+       }
+       else
+       {
+               c.a = px_addr[3];
+               c.r = px_addr[2];
+               c.g = px_addr[1];
+               c.b = px_addr[0];
+       }
+       return (c);
 }
 
-int    draw_fractal(t_session *s)
+t_color        get_color(t_session *s, int x, int y)
+{
+       double  palette_param;
+
+       if (!*(bool *)ft_mat_access(&s->img.calced, x, y))
+       {
+               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);
+               return (s->view.palette(palette_param));
+       }
+       else
+       {
+               return (get_img_pixel_color(&s->img, x, y));
+       }
+}
+
+void   process_pixel_group(t_session *s, int x, int y)
+{
+       int     i;
+       int     j;
+       t_color color;
+
+       color = get_color(s, x, y);
+       i = 0;
+       while (i < s->img.undersample && x + i < s->img.width)
+       {
+               j = 0;
+               while (j < s->img.undersample && y + j < s->img.height)
+               {
+                       if (!*(bool *)ft_mat_access(&s->img.calced, x + i, y + j))
+                               ft_putpx_img(&s->img, x + i, y + j, color);
+                       ++j;
+               }
+               ++i;
+       }
+       *(bool *)ft_mat_access(&s->img.calced, x, y) = 1;
+       return ;
+}
+
+void   draw_fractal(t_session *s)
 {
        int             x;
        int             y;
-       double  palette_param;
 
        x = 0;
        while (x < s->img.width)
@@ -103,45 +162,77 @@ int       draw_fractal(t_session *s)
                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;
+                       process_pixel_group(s, x, y);
+                       y += s->img.undersample;
                }
-               ++x;
+               x += s->img.undersample;
        }
        mlx_put_image_to_window(s->mlx, s->win, s->img.img, 0, 0);
-       return (0);
 }
 
-void   change_zoom(t_view *view, t_vect2 invariant, double d_zoom)
+void   erase_calced(t_mat *mat)
 {
-       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;
+       size_t  i;
+       size_t  j;
+
+       i = 0;
+       while (i < mat->rows)
+       {
+               j = 0;
+               while (j < mat->cols)
+               {
+                       *(bool *)ft_mat_access(mat, i, j) = false;
+                       ++j;
+               }
+               ++i;
+       }
+       return ;
+}
+
+void   change_zoom(t_session *s, t_vect2 invariant, double d_zoom)
+{
+       s->view.pixel_size.x /= d_zoom;
+       s->view.pixel_size.y /= d_zoom;
+       s->view.window_coord.x += s->view.pixel_size.x * invariant.x * (d_zoom - 1);
+       s->view.window_coord.y -= s->view.pixel_size.y * invariant.y * (d_zoom - 1);
+       erase_calced(&s->img.calced);
+       s->img.undersample = 2;
        return ;
 }
 
 // move_amount is ratio of move distance to length one can see
-void   move_view(float move_amount_right, float move_amount_up, t_session *s)
+void   move_view(t_session *s, float move_amount_right, float move_amount_up)
 {
        s->view.window_coord.x += move_amount_right * s->img.height * s->view.pixel_size.x;
        s->view.window_coord.y += move_amount_up * s->img.height * s->view.pixel_size.y;
-       s->view.draw_whole = 1;
+       erase_calced(&s->img.calced);
+       s->img.undersample = 2;
        return ;
 }
 
-void   init_view(t_session *s)
+// Something like this function should be added to Libft
+// with maybe additional argument (void *) of the filler
+t_arr_stat     construct_mat(t_mat *mat, size_t rows, size_t cols)
+{
+       t_vec           filler_vec;
+       bool            filler;
+       size_t          i;
+       t_arr_stat      res;
+
+       filler = false;
+       ft_vec_init(&filler_vec, sizeof(bool));
+       i = 0;
+       while (i < cols)
+       {
+               ft_vec_append(&filler_vec, &filler);
+               ++i;
+       }
+       res = ft_mat_insert_row(mat, &filler_vec, rows - 1);
+       ft_vec_free(&filler_vec, NULL);
+       return (res);
+}
+
+static void    init_view(t_session *s)
 {
        s->view.fractal = mandelbrot;
        s->view.palette = tri_color;
@@ -149,37 +240,49 @@ void      init_view(t_session *s)
        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 = 10;
-       s->view.draw_whole = 1;
        return ;
 }
 
+void   init_session(t_session *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);
+       ft_mat_init(&s->img.calced, sizeof(bool));
+       construct_mat(&s->img.calced, s->img.height, s->img.width);
+       init_view(s);
+       s->img.undersample = 2;
+}
+
 void   parse_args(int argc, char **argv, t_session *s)
 {
        if (argc == 0)
                free(argv);
        s->img.width = 500;
        s->img.height = 500;
-       init_view(s);
        return ;
 }
 
+void   cleanup(t_session *s)
+{
+       ft_mat_free(&s->img.calced, NULL);
+       mlx_destroy_image(s->mlx, s->img.img);
+       free_session(s);
+}
+
 int    main(int argc, char **argv)
 {
        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);
+       init_session(&s);
        mlx_hook(s.win, KeyPress, KeyPressMask, handle_key_press, &s);
        mlx_hook(s.win, ButtonPress, ButtonPressMask, handle_mouse_press, &s);
        mlx_hook(s.win, DestroyNotify, NoEventMask, close_win, &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);
+       cleanup(&s);
        return (0);
 }