├── 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 | ![Julia Set Fractal](https://user-images.githubusercontent.com/53185699/212414778-16072951-224e-48be-bcec-8b60590ccc1e.png) 6 | ![Mandelbrot Set Fractal](https://user-images.githubusercontent.com/53185699/212414859-cf0b3d61-0881-4420-8696-48cc9569d244.png) 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 | ![Burning Ship Fractal](https://user-images.githubusercontent.com/53185699/212414692-fa75a51d-b250-4d30-a061-4fde8f8bbdf3.png) 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 | --------------------------------------------------------------------------------