├── README.md
├── complex_math.c
├── julia.c
├── Makefile
├── mandelbrot.c
├── burning.c
├── params.c
├── fractol.h
├── hooks.c
└── ft_fractol.c
/README.md:
--------------------------------------------------------------------------------
1 | # FRACT-OL
2 |
Fract-ol project developed for the 42School in a Ubuntu environment.
3 | In the mandatory part we need to present the Julia and Mandelbrot Fractal Sets.
4 |
5 | 
6 | 
7 |
8 | For the bonus we are asked to choose another Set and I chose the Burning Ship (calculated by only using the real part of the Mandelbrot calculations).
9 |
10 |
11 | 
12 |
13 | ## Features
14 | * Render different fractals: mandelbrot, julia, burning ship
15 | * Change to different color schemes
16 | * The mouse wheel zooms in and out, almost infinitely (within the limits of the computer)
17 | * Move the image with the arrow keys
18 | * Reset to the inicial image/ reset zoom
19 |
20 | ## Compiling and running
21 | Run `make` then run it with `./fractol [fractal]`. Possible fractals are: `julia`, `mandelbrot`,
22 | `burning`. Cycle color-schemes with `+` and `-` on the right numpad. Zoom in and out with the
23 | mousewheel.
24 |
--------------------------------------------------------------------------------
/complex_math.c:
--------------------------------------------------------------------------------
1 | /* ************************************************************************** */
2 | /* */
3 | /* ::: :::::::: */
4 | /* complex_math.c :+: :+: :+: */
5 | /* +:+ +:+ +:+ */
6 | /* By: fvieira +#+ +:+ +#+ */
7 | /* +#+#+#+#+#+ +#+ */
8 | /* Created: 2022/12/02 13:53:17 by fvieira #+# #+# */
9 | /* Updated: 2022/12/02 13:53:19 by fvieira ### ########.fr */
10 | /* */
11 | /* ************************************************************************** */
12 |
13 | #include "fractol.h"
14 |
15 | t_complex add(t_complex a, t_complex b)
16 | {
17 | t_complex c;
18 |
19 | c.x = a.x + b.x;
20 | c.y = a.y + b.y;
21 | return (c);
22 | }
23 |
24 | t_complex sqr(t_complex a)
25 | {
26 | t_complex c;
27 |
28 | c.x = a.x * a.x - a.y * a.y;
29 | c.y = 2 * a.x * a.y;
30 | return (c);
31 | }
32 |
33 | t_complex mappoint(t_fractal *fractal, double x, double y)
34 | {
35 | t_complex c;
36 | double l;
37 |
38 | if (fractal->width < fractal->height)
39 | l = fractal->height * fractal->zoom;
40 | else
41 | l = fractal->width * fractal->zoom;
42 | x += fractal->xarrow ;
43 | y += fractal->yarrow ;
44 | c.x = 2 * fractal->radius * (x - fractal->width / 2) / l;
45 | c.y = 2 * fractal->radius * (y - fractal->height / 2) / l;
46 | return (c);
47 | }
48 |
--------------------------------------------------------------------------------
/julia.c:
--------------------------------------------------------------------------------
1 | /* ************************************************************************** */
2 | /* */
3 | /* ::: :::::::: */
4 | /* julia.c :+: :+: :+: */
5 | /* +:+ +:+ +:+ */
6 | /* By: fvieira +#+ +:+ +#+ */
7 | /* +#+#+#+#+#+ +#+ */
8 | /* Created: 2022/11/30 11:27:09 by fvieira #+# #+# */
9 | /* Updated: 2022/11/30 11:27:13 by fvieira ### ########.fr */
10 | /* */
11 | /* ************************************************************************** */
12 |
13 | #include "fractol.h"
14 |
15 | int my_mlx_pixel_put(t_fractal *fractal, int x, int y, int color)
16 | {
17 | char *dst;
18 |
19 | dst = fractal->addr + (y * fractal->line_length + x
20 | * (fractal->bits_per_pixel / 8));
21 | *(unsigned int *)dst = color;
22 | return (0);
23 | }
24 |
25 | void juliaset(t_fractal *julia)
26 | {
27 | int i;
28 | t_complex z0;
29 | t_complex z1;
30 |
31 | julia->x = 0;
32 | while (++julia->x <= julia->width)
33 | {
34 | julia->y = 0;
35 | while (++julia->y <= julia->height)
36 | {
37 | z0 = mappoint(julia, julia->x, julia->y);
38 | i = 1;
39 | while (i++ <= julia->iterations)
40 | {
41 | z1 = add(sqr(z0), julia->c);
42 | if (z1.x * z1.x + z1.y * z1.y > julia->radius * julia->radius)
43 | {
44 | my_mlx_pixel_put(julia, julia->x,
45 | julia->y, julia->color * i);
46 | break ;
47 | }
48 | z0 = z1;
49 | }
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # **************************************************************************** #
2 | # #
3 | # ::: :::::::: #
4 | # Makefile :+: :+: :+: #
5 | # +:+ +:+ +:+ #
6 | # By: fvieira +#+ +:+ +#+ #
7 | # +#+#+#+#+#+ +#+ #
8 | # Created: 2022/11/28 17:05:55 by fvieira #+# #+# #
9 | # Updated: 2023/01/23 14:34:39 by fvieira ### ########.fr #
10 | # #
11 | # **************************************************************************** #
12 |
13 | NAME = fractol
14 |
15 | CC = cc
16 |
17 | CFLAGS = -Wall -Werror -Wextra -g
18 | MLXFLAGS = -L ./minilibx-linux -lmlx -Ilmlx -lXext -lX11
19 | LIBFT = ./libft/libft.a
20 |
21 | SRC = ft_fractol.c \
22 | julia.c \
23 | complex_math.c \
24 | hooks.c \
25 | mandelbrot.c \
26 | params.c \
27 | burning.c \
28 |
29 |
30 | all: $(NAME)
31 |
32 | $(NAME): $(SRC:.c=.o)
33 | $(MAKE) --no-print-directory -C ./libft
34 | echo "\033[1m LIBFT done \033[0m"
35 | $(MAKE) --no-print-directory -C ./minilibx-linux
36 | echo "\033[1m MiniLibX done \033[0m"
37 | $(CC) $(CFLAGS) -lm $(SRC) $(LIBFT) $(MLXFLAGS) -o $(NAME)
38 | echo "\033[1m Ready to FRACT-OL \033[0m"
39 |
40 | clean:
41 | $(MAKE) clean -C ./libft
42 | rm -rf $(SRC:.c=.o)
43 | echo "OBJ deleted"
44 |
45 | fclean: clean
46 | $(MAKE) fclean -C ./libft
47 | rm -rf $(NAME)
48 | echo "$(NAME) deleted"
49 |
50 | re: fclean all
51 |
52 | .PHONY: all, clean, fclean, re, bonus
53 |
54 | .SILENT:
55 |
--------------------------------------------------------------------------------
/mandelbrot.c:
--------------------------------------------------------------------------------
1 | /* ************************************************************************** */
2 | /* */
3 | /* ::: :::::::: */
4 | /* mandelbrot.c :+: :+: :+: */
5 | /* +:+ +:+ +:+ */
6 | /* By: fvieira +#+ +:+ +#+ */
7 | /* +#+#+#+#+#+ +#+ */
8 | /* Created: 2022/12/06 22:12:18 by fvieira #+# #+# */
9 | /* Updated: 2022/12/06 22:12:21 by fvieira ### ########.fr */
10 | /* */
11 | /* ************************************************************************** */
12 |
13 | #include "fractol.h"
14 |
15 | void minimandel(int x, int y, t_fractal *mandel)
16 | {
17 | int i;
18 | double z0;
19 | double z1;
20 | double tempz0;
21 |
22 | i = 0;
23 | mandel->c.x = (x + mandel->xarrow) / mandel->zoom
24 | * (0.47 + 2.0) / (mandel->width - 1) - 2.0;
25 | mandel->c.y = (y + mandel->yarrow) / mandel->zoom
26 | * (1.12 + 1.12) / (mandel->width - 1) - 1.12;
27 | z0 = mandel->c.x;
28 | z1 = mandel->c.y;
29 | while (i++ < mandel->iterations)
30 | {
31 | tempz0 = z0 * z0 - z1 * z1 + mandel->c.x;
32 | z1 = 2.0 * z0 * z1 + mandel->c.y;
33 | z0 = tempz0;
34 | if (z0 * z0 + z1 * z1 > 4)
35 | {
36 | my_mlx_pixel_put(mandel, (int) x, (int) y, (mandel->color * i));
37 | break ;
38 | }
39 | }
40 | }
41 |
42 | void mandelbrotset(t_fractal *mandel)
43 | {
44 | int x;
45 | int y;
46 |
47 | x = -1;
48 | while (++x <= mandel->width)
49 | {
50 | y = -1;
51 | while (++y <= mandel->height)
52 | {
53 | minimandel(x, y, mandel);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/burning.c:
--------------------------------------------------------------------------------
1 | /* ************************************************************************** */
2 | /* */
3 | /* ::: :::::::: */
4 | /* burning.c :+: :+: :+: */
5 | /* +:+ +:+ +:+ */
6 | /* By: fvieira +#+ +:+ +#+ */
7 | /* +#+#+#+#+#+ +#+ */
8 | /* Created: 2022/12/08 17:16:00 by fvieira #+# #+# */
9 | /* Updated: 2022/12/08 17:16:11 by fvieira ### ########.fr */
10 | /* */
11 | /* ************************************************************************** */
12 |
13 | #include "fractol.h"
14 |
15 | void miniburning(int x, int y, t_fractal *burning)
16 | {
17 | int i;
18 | double z0;
19 | double z1;
20 | double tempz0;
21 |
22 | i = 0;
23 | burning->c.x = (x + burning->xarrow) / burning->zoom
24 | * (1.0 + 2.5) / (burning->width - 1) - 2.5;
25 | burning->c.y = (y + burning->yarrow) / burning->zoom
26 | * (1.0 + 1.0) / (burning->width - 1) - 1.0;
27 | z0 = burning->c.x;
28 | z1 = burning->c.y;
29 | while (i++ < burning->iterations)
30 | {
31 | tempz0 = z0 * z0 - z1 * z1 + burning->c.x;
32 | z1 = fabs(2.0 * z0 * z1) + burning->c.y;
33 | z0 = tempz0;
34 | if (z0 * z0 + z1 * z1 > 4)
35 | {
36 | my_mlx_pixel_put(burning, (int) x, (int) y, (burning->color * i));
37 | break ;
38 | }
39 | }
40 | }
41 |
42 | void burningset(t_fractal *burning)
43 | {
44 | int x;
45 | int y;
46 |
47 | x = -1;
48 | while (++x <= burning->width)
49 | {
50 | y = -1;
51 | while (++y <= burning->height)
52 | {
53 | miniburning(x, y, burning);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/params.c:
--------------------------------------------------------------------------------
1 | /* ************************************************************************** */
2 | /* */
3 | /* ::: :::::::: */
4 | /* params.c :+: :+: :+: */
5 | /* +:+ +:+ +:+ */
6 | /* By: fvieira +#+ +:+ +#+ */
7 | /* +#+#+#+#+#+ +#+ */
8 | /* Created: 2022/12/08 13:13:19 by fvieira #+# #+# */
9 | /* Updated: 2022/12/08 13:13:20 by fvieira ### ########.fr */
10 | /* */
11 | /* ************************************************************************** */
12 |
13 | #include "fractol.h"
14 |
15 | void mandelbrot_param(t_fractal *fractal, char *name)
16 | {
17 | fractal->width = 1280;
18 | fractal->height = 720;
19 | fractal->iterations = 150;
20 | fractal->zoom = 1;
21 | fractal->x = 0;
22 | fractal->y = 0;
23 | fractal->xarrow = 0;
24 | fractal->yarrow = 270;
25 | fractal->color = 0xccf1ff;
26 | fractal->name = name;
27 | }
28 |
29 | void julia_param(t_fractal *fractal, char *name)
30 | {
31 | fractal->width = 1280;
32 | fractal->height = 720;
33 | fractal->c.x = -0.7;
34 | fractal->c.y = 0.27015;
35 | fractal->radius = 3;
36 | fractal->iterations = 150;
37 | fractal->zoom = 1;
38 | fractal->x = 0;
39 | fractal->y = 0;
40 | fractal->xarrow = 0;
41 | fractal->yarrow = 0;
42 | fractal->color = 0xccf1ff;
43 | fractal->name = name;
44 | }
45 |
46 | void burning_param(t_fractal *fractal, char *name)
47 | {
48 | fractal->width = 1280;
49 | fractal->height = 720;
50 | fractal->iterations = 150;
51 | fractal->zoom = 8.157307;
52 | fractal->x = 0;
53 | fractal->y = 0;
54 | fractal->xarrow = 1710.0;
55 | fractal->yarrow = 4530.0;
56 | fractal->color = 0xccf1ff;
57 | fractal->name = name;
58 | }
59 |
--------------------------------------------------------------------------------
/fractol.h:
--------------------------------------------------------------------------------
1 | /* ************************************************************************** */
2 | /* */
3 | /* ::: :::::::: */
4 | /* fractol.h :+: :+: :+: */
5 | /* +:+ +:+ +:+ */
6 | /* By: fvieira +#+ +:+ +#+ */
7 | /* +#+#+#+#+#+ +#+ */
8 | /* Created: 2022/11/28 17:09:50 by fvieira #+# #+# */
9 | /* Updated: 2022/11/28 17:09:52 by fvieira ### ########.fr */
10 | /* */
11 | /* ************************************************************************** */
12 |
13 | #ifndef FRACTOL_H
14 | # define FRACTOL_H
15 |
16 | # include "libft/libft.h"
17 | # include "minilibx-linux/mlx.h"
18 | # include
19 | # include
20 |
21 | # define ESC 65307
22 |
23 | # define LEFT 65361
24 | # define UP 65362
25 | # define RIGHT 65363
26 | # define DOWN 65364
27 | # define R 114
28 | # define Z 122
29 | # define PLUS 65451
30 | # define MINUS 65453
31 |
32 | typedef struct imaginary {
33 | double x;
34 | double y;
35 | } t_complex;
36 |
37 | t_complex sqr(t_complex a);
38 | t_complex add(t_complex a, t_complex b);
39 |
40 | typedef struct s_fractal {
41 | char *name;
42 | void *img;
43 | void *addr;
44 | int bits_per_pixel;
45 | int line_length;
46 | int endian;
47 | void *mlx;
48 | void *win;
49 | int width;
50 | int height;
51 | t_complex c;
52 | double zoom;
53 | double x;
54 | double y;
55 | double xarrow;
56 | double yarrow;
57 | double radius;
58 | int iterations;
59 | int color;
60 | } t_fractal;
61 |
62 | t_complex mappoint(t_fractal *julia, double x, double y);
63 |
64 | void juliaset(t_fractal *julia);
65 | void mandelbrotset(t_fractal *mandel);
66 | void burningset(t_fractal *burning);
67 |
68 | int my_mlx_pixel_put(t_fractal *fractal, int x, int y, int color);
69 |
70 | void fractalsetup(t_fractal *fractal);
71 |
72 | void mandelbrot_param(t_fractal *fractal, char *name);
73 | void julia_param(t_fractal *fractal, char *name);
74 | void burning_param(t_fractal *fractal, char *name);
75 |
76 | void ft_zoom(double x, double y, t_fractal *fractal);
77 | void ft_dezoom(double x, double y, t_fractal *fractal);
78 | int key_hook(int keycode, t_fractal *fractal);
79 | int mouse_hook(int key_code, int x, int y, t_fractal *fractal);
80 | int close_game(t_fractal *fractal);
81 |
82 | int freeall(t_fractal *fractal);
83 | #endif
--------------------------------------------------------------------------------
/hooks.c:
--------------------------------------------------------------------------------
1 | /* ************************************************************************** */
2 | /* */
3 | /* ::: :::::::: */
4 | /* hooks.c :+: :+: :+: */
5 | /* +:+ +:+ +:+ */
6 | /* By: fvieira +#+ +:+ +#+ */
7 | /* +#+#+#+#+#+ +#+ */
8 | /* Created: 2022/12/08 13:15:37 by fvieira #+# #+# */
9 | /* Updated: 2022/12/08 13:15:42 by fvieira ### ########.fr */
10 | /* */
11 | /* ************************************************************************** */
12 |
13 | #include "fractol.h"
14 |
15 | void ft_zoom(double x, double y, t_fractal *fractal)
16 | {
17 | fractal->x = (x / fractal->zoom) - (x / (fractal->zoom * 1.3));
18 | fractal->y = (y / fractal->zoom) - (y / (fractal->zoom * 1.3));
19 | fractal->zoom *= 1.3;
20 | fractal->iterations++;
21 | }
22 |
23 | void ft_dezoom(double x, double y, t_fractal *fractal)
24 | {
25 | fractal->x = (x / fractal->zoom) - (x / (fractal->zoom / 1.3));
26 | fractal->y = (y / fractal->zoom) - (y / (fractal->zoom / 1.3));
27 | fractal->zoom /= 1.3;
28 | fractal->iterations--;
29 | }
30 |
31 | int close_game(t_fractal *fractal)
32 | {
33 | freeall(fractal);
34 | exit(EXIT_SUCCESS);
35 | return (EXIT_SUCCESS);
36 | }
37 |
38 | int key_hook(int keycode, t_fractal *fractal)
39 | {
40 | if (keycode == ESC)
41 | close_game(fractal);
42 | else if (keycode == LEFT)
43 | fractal->xarrow -= 30;
44 | else if (keycode == DOWN)
45 | fractal->yarrow += 30;
46 | else if (keycode == RIGHT)
47 | fractal->xarrow += 30;
48 | else if (keycode == UP)
49 | fractal->yarrow -= 30;
50 | else if (keycode == PLUS)
51 | fractal->color += 100;
52 | else if (keycode == MINUS)
53 | fractal->color -= 100;
54 | else if (keycode == R)
55 | {
56 | ft_printf("Reset time!\n");
57 | julia_param(fractal, fractal->name);
58 | }
59 | else if (keycode == Z)
60 | fractal->zoom = 1;
61 | if (keycode != ESC)
62 | fractalsetup(fractal);
63 | return (0);
64 | }
65 |
66 | int mouse_hook(int key_code, int x, int y, t_fractal *fractal)
67 | {
68 | if (key_code == 1 && !ft_strncmp(fractal->name, "julia", 5))
69 | {
70 | fractal->c.x = ((double) x / fractal->width * 4 - 2);
71 | fractal->c.y = ((double) y / fractal->height * 3 - 1.5);
72 | fractal->zoom = 1;
73 | }
74 | else if (key_code == 4)
75 | ft_zoom(((double) x / fractal->width * 1000 - 500),
76 | ((double) y / fractal->height * 1000 - 500), fractal);
77 | else if (key_code == 5)
78 | ft_dezoom(((double) x / fractal->width * 1000 - 500),
79 | ((double) y / fractal->height * 1000 - 500), fractal);
80 | fractalsetup(fractal);
81 | return (0);
82 | }
83 |
--------------------------------------------------------------------------------
/ft_fractol.c:
--------------------------------------------------------------------------------
1 | /* ************************************************************************** */
2 | /* */
3 | /* ::: :::::::: */
4 | /* ft_fractol.c :+: :+: :+: */
5 | /* +:+ +:+ +:+ */
6 | /* By: fvieira +#+ +:+ +#+ */
7 | /* +#+#+#+#+#+ +#+ */
8 | /* Created: 2022/11/28 17:09:36 by fvieira #+# #+# */
9 | /* Updated: 2022/11/28 17:09:41 by fvieira ### ########.fr */
10 | /* */
11 | /* ************************************************************************** */
12 |
13 | #include "fractol.h"
14 |
15 | void fractalsetup(t_fractal *fractal)
16 | {
17 | mlx_destroy_image(fractal->mlx, fractal->img);
18 | fractal->img = mlx_new_image(fractal->mlx, fractal->width, fractal->height);
19 | fractal->addr = mlx_get_data_addr(fractal->img, &fractal->bits_per_pixel,
20 | &fractal->line_length, &fractal->endian);
21 | if (!ft_strncmp(fractal->name, "julia", 5))
22 | juliaset(fractal);
23 | else if (!ft_strncmp(fractal->name, "mandelbrot", 10))
24 | mandelbrotset(fractal);
25 | else if (!ft_strncmp(fractal->name, "burning", 7))
26 | burningset(fractal);
27 | mlx_put_image_to_window(fractal->mlx, fractal->win, fractal->img, 0, 0);
28 | }
29 |
30 | void wronginputs(void)
31 | {
32 | ft_printf("Unrecognized input!!! \nThis program only takes the ");
33 | ft_printf("parameters: \'julia\', \'mandelbrot\' or ");
34 | ft_printf("\'burning\' to display any of these fractal types!");
35 | exit(1);
36 | }
37 |
38 | int freeall(t_fractal *fractal)
39 | {
40 | mlx_destroy_image(fractal->mlx, fractal->img);
41 | mlx_destroy_window(fractal->mlx, fractal->win);
42 | mlx_destroy_display(fractal->mlx);
43 | free(fractal->mlx);
44 | exit(0);
45 | }
46 |
47 | int main(int argc, char **argv)
48 | {
49 | t_fractal fractal;
50 |
51 | if (argc == 2)
52 | {
53 | if (!ft_strncmp(argv[1], "mandelbrot", 10) && ft_strlen(argv[1]) == 10)
54 | mandelbrot_param(&fractal, argv[1]);
55 | else if (!ft_strncmp(argv[1], "julia", 5) && ft_strlen(argv[1]) == 5)
56 | julia_param(&fractal, argv[1]);
57 | else if (!ft_strncmp(argv[1], "burning", 7) && ft_strlen(argv[1]) == 7)
58 | burning_param(&fractal, argv[1]);
59 | fractal.mlx = mlx_init();
60 | fractal.win = mlx_new_window(fractal.mlx, fractal.width,
61 | fractal.height, fractal.name);
62 | fractal.img = mlx_new_image(fractal.mlx, fractal.width, fractal.height);
63 | fractalsetup(&fractal);
64 | mlx_key_hook(fractal.win, key_hook, &fractal);
65 | mlx_mouse_hook(fractal.win, mouse_hook, &fractal);
66 | mlx_hook(fractal.win, 17, 1L << 17, close_game, &fractal);
67 | mlx_loop(fractal.mlx);
68 | }
69 | else
70 | wronginputs();
71 | return (0);
72 | }
73 |
--------------------------------------------------------------------------------