Fract'ol - Fractal Generator

This program is aimed at drawing, manipulating, and exploring fractals. It contains a total of seven fractals, some based upon the julia and mandelbrot fractal.

Through this project I learned better use of structs and a good understanding of the MLX library as a whole.

It features the following fractals: Julia, Mandelbrot, Burning Ship,

Sierpinski Carpet, Tricorn, Julia Cubed, and Mandelbrot Cubed.

This project uses my libft library and the MLX graphic library.

Runs on Mac


Compiling:

-> make

-> ./fractol (To get the list of the fractals and the controls.)

-> ./fractol

Controls:

Move: Arrow Keys

Zoom: Page Up & Page Down

Mouse Zoom: Scrool Wheel

Iteration: Left Click & (+ -) Keys

Zoom Reset: Space Bar

Julia Activate: Right Click

Color Change: Num Key 1-3

Hue Change: Num Key 4 & 5

Git Repo

main.c

#include "fractol.h" static int close_window(t_a *exp) { mlx_destroy_window(exp->mlx, exp->win); exit(EXIT_SUCCESS); } void makewindow(t_a *exp) { exp->mlx = mlx_init(); exp->win = mlx_new_window(exp->mlx, WIDTH, HEIGHT, "Fractol"); exp->img = mlx_new_image(exp->mlx, WIDTH, HEIGHT); exp->imgpointer = mlx_get_data_addr(exp->img, &(exp->bpp), &(exp->s1), &(exp->endian)); initfractol(exp); whichfractol(exp); mlx_put_image_to_window(exp->mlx, exp->win, exp->img, 0, 0); printxandy(exp); mlx_key_hook(exp->win, keyhooks, exp); mlx_mouse_hook(exp->win, mousehook, exp); mlx_hook(exp->win, 6, 0, motion, exp); mlx_hook(exp->win, 17, 0, close_window, exp); mlx_loop(exp->mlx); } void controls(int i) { ft_putendl("Fractols:\n1. julia\n2. mandel\n3. ship\n4. carpet"); ft_putendl("5. tricorn\n6. juliacubed \n7. mandelcubed\nControls:"); ft_putendl("Move: Arrow Keys\nZoom: Page Up & Page Down"); ft_putendl("Mouse Zoom: Scrool Wheel"); ft_putendl("Iteration: Left Click & (+ -) Keys"); ft_putendl("Zoom Reset: Space Bar\nJulia Activate: Right Click"); ft_putendl("Color Change: Num Key 1-3\nHue Change: Num Key 4 & 5"); if (i == 2) exit(1); } void ft_errorcheck(char *str, t_a *exp) { if ((!(ft_strcmp(str, "mandel") == 0)) && (!(ft_strcmp(str, "julia") == 0)) && (!(ft_strcmp(str, "ship") == 0)) && (!(ft_strcmp(str, "carpet") == 0)) && (!(ft_strcmp(str, "tricorn") == 0)) && (!(ft_strcmp(str, "juliacubed") == 0)) && (!(ft_strcmp(str, "mandelcubed") == 0))) controls(2); if (ft_strcmp(str, "julia") == 0) exp->fractol = 1; if (ft_strcmp(str, "mandel") == 0) exp->fractol = 2; if (ft_strcmp(str, "ship") == 0) exp->fractol = 3; if (ft_strcmp(str, "carpet") == 0) exp->fractol = 4; if (ft_strcmp(str, "tricorn") == 0) exp->fractol = 5; if (ft_strcmp(str, "juliacubed") == 0) exp->fractol = 6; if (ft_strcmp(str, "mandelcubed") == 0) exp->fractol = 7; } int main(int argc, char **argv) { t_a *exp; if (argc < 2) { ft_putendl("Error - Not Enough Input"); controls(2); } if (!(exp = (t_a *)ft_memalloc(sizeof(t_a)))) return (0); exp->color = 1; if (argc == 2) { ft_errorcheck(argv[1], exp); controls(1); makewindow(exp); } else controls(1); }

init.c

#include "fractol.h" void juliainit(t_a *exp) { exp->zoom = 1; exp->movex = 0; exp->movey = 0; exp->maxinter = 15; exp->cre = -0.7; exp->cim = 0.27015; } void mandelinit(t_a *exp) { exp->zoom = 1; exp->movex = 0; exp->movey = 0; exp->maxinter = 15; } void shipinit(t_a *exp) { exp->zoom = 1; exp->movex = 0; exp->movey = 0; exp->maxinter = 15; } void carpetinit(t_a *exp) { exp->zoom = 1; exp->movex = 0; exp->movey = 0; exp->maxinter = 3; } void initfractol(t_a *exp) { if (exp->fractol == 1) juliainit(exp); if (exp->fractol == 2) mandelinit(exp); if (exp->fractol == 3) shipinit(exp); if (exp->fractol == 4) carpetinit(exp); if (exp->fractol == 5) mandelinit(exp); if (exp->fractol == 6) juliainit(exp); if (exp->fractol == 7) mandelinit(exp); }

hooks.c

#include "fractol.h" int mousehook(int mousekey, int x, int y, t_a *exp) { if (x > 0 && y > 0 && x < WIDTH && y < HEIGHT) { if (mousekey == 5) zoomin(x, y, exp); else if (mousekey == 4) zoomout(x, y, exp); else if (mousekey == 1) exp->maxinter += 5; else if (mousekey == 2) { if (exp->movemouse == 1) exp->movemouse = 0; else exp->movemouse = 1; } whichfractol(exp); mlx_put_image_to_window(exp->mlx, exp->win, exp->img, 0, 0); printxandy(exp); } return (0); } int keyhooks3(int key, t_a *exp) { if (key == 49) retrydraw(exp); if (key == 18) { exp->color = 1; retrydraw(exp); } else if (key == 126) exp->movey += .2 / exp->zoom; else if (key == 125) exp->movey -= .2 / exp->zoom; else if (key == 124) exp->movex += .2 / exp->zoom; else if (key == 123) exp->movex -= .2 / exp->zoom; return (0); } int keyhooks2(int key, t_a *exp) { if (key == 19) { exp->color = 0x247812; retrydraw(exp); } if (key == 20) { exp->color = 2000; retrydraw(exp); } if (key == 21) { exp->color += 50; retrydraw(exp); } if (key == 23) { exp->color -= 10; retrydraw(exp); } return (0); } int keyhooks(int key, t_a *exp) { if (!(exp->win)) return (0); if (key == 53) { ft_putendl("Exiting"); exit(0); } else if (key == 116) exp->zoom *= pow(1.001, 70); else if (key == 121) exp->zoom /= pow(1.001, 70); else if (key == 24) exp->maxinter += 5; else if (key == 27) exp->maxinter -= 5; keyhooks2(key, exp); keyhooks3(key, exp); whichfractol(exp); mlx_put_image_to_window(exp->mlx, exp->win, exp->img, 0, 0); printxandy(exp); return (0); }

whichfractol.c

#include "fractol.h" void whichfractol(t_a *exp) { if (exp->fractol == 1) juliafx(exp); if (exp->fractol == 2) mandelfx(exp); if (exp->fractol == 3) shipfx(exp); if (exp->fractol == 4) carpetfx(exp); if (exp->fractol == 5) tricornfx(exp); if (exp->fractol == 6) juliacubedfx(exp); if (exp->fractol == 7) mandelcubedfx(exp); } void zoomin(int x, int y, t_a *exp) { x -= WIDTH / 2; y -= HEIGHT / 2; exp->x2 = ((exp->x - x) - WIDTH) / ((double)HEIGHT * 2); exp->y2 = ((exp->y - y) - HEIGHT) / (((double)WIDTH * 2) + y); exp->zoom *= pow(1.001, 70); exp->movex -= exp->x2; exp->movey -= exp->y2; } void zoomout(int x, int y, t_a *exp) { x -= WIDTH / 2; y -= HEIGHT / 2; exp->x2 = ((exp->x - x) - WIDTH) / ((double)HEIGHT * 2); exp->y2 = ((exp->y - y) - HEIGHT) / (((double)WIDTH * 2) + y); exp->zoom /= pow(1.001, 70); exp->movex -= exp->x2; exp->movey -= exp->y2; } int motion(int x, int y, t_a *exp) { if (x > 0 && y > 0 && x < WIDTH && y < HEIGHT) { if ((exp->fractol == 1 || exp->fractol == 6) && exp->movemouse == 1) { exp->clickx = x; exp->clicky = y; exp->cre = ((exp->clickx - exp->x) - WIDTH) / (((double)HEIGHT * 2) + exp->y); exp->cim = ((exp->clicky + exp->y) - HEIGHT) / ((double)HEIGHT * 2); whichfractol(exp); mlx_put_image_to_window(exp->mlx, exp->win, exp->img, 0, 0); printxandy(exp); } } return (0); }

color.c

#include "fractol.h" void putimage(t_a *exp, int x, int y, int color) { int i; i = (x * (exp->bpp / 8)) + (y * exp->s1); exp->imgpointer[i] = color; exp->imgpointer[++i] = color >> 8; exp->imgpointer[++i] = color >> 16; } unsigned int colormagic(int i, double x, double y) { unsigned int color; double magic; double i2; t_c c; magic = sqrt(x * x + y * y); i2 = i + 1 - (log(2) / magic) / log(2); c.chan[0] = (unsigned char)(sin(0.026 * i2 + 4) * 230 + 25); c.chan[1] = (unsigned char)(sin(0.023 * i2 + 2) * 230 + 25); c.chan[2] = (unsigned char)(sin(0.01 * i2 + 1) * 230 + 25); color = (c.chan[0] << 16) + (c.chan[1] << 8) + (c.chan[2] + 255); return (color); } int printxandy(t_a *exp) { char *txt1; char *txt2; char *zoom; char *maxinter; zoom = ft_itoa(exp->zoom); maxinter = ft_itoa(exp->maxinter); txt1 = ft_strjoin("Inter: ", maxinter); txt2 = ft_strjoin("Zoom: ", zoom); mlx_string_put(exp->mlx, exp->win, 10, 5, 0xFFFFFF, txt1); mlx_string_put(exp->mlx, exp->win, 10, 20, 0xFFFFFF, txt2); ft_strdel(&txt1); ft_strdel(&txt2); ft_strdel(&zoom); ft_strdel(&maxinter); return (0); } void retrydraw(t_a *exp) { mlx_put_image_to_window(exp->mlx, exp->win, exp->img, 0, 0); mlx_destroy_image(exp->mlx, exp->img); exp->img = mlx_new_image(exp->mlx, WIDTH, HEIGHT); exp->imgpointer = mlx_get_data_addr(exp->img, &(exp->bpp), &(exp->s1), &(exp->endian)); initfractol(exp); whichfractol(exp); mlx_put_image_to_window(exp->mlx, exp->win, exp->img, 0, 0); printxandy(exp); }

fractol1.c

#include "fractol.h" static void juliamagic(t_a *exp) { exp->oldre = exp->newre; exp->oldim = exp->newim; exp->newre = exp->oldre * exp->oldre - exp->oldim * exp->oldim + exp->cre; exp->newim = 2 * exp->oldre * exp->oldim + exp->cim; } void juliafx(t_a *exp) { exp->y = -1; while (++exp->y < HEIGHT) { exp->x = -1; while (++exp->x < WIDTH) { exp->newre = 1.5 * (exp->x - WIDTH / 2) / (0.5 * exp->zoom * WIDTH) + exp->movex; exp->newim = (exp->y - HEIGHT / 2) / (0.5 * exp->zoom * HEIGHT) + exp->movey; exp->i = -1; while (++exp->i < exp->maxinter) { juliamagic(exp); if ((exp->newre * exp->newre + exp->newim) > 4) break ; } if (exp->i < exp->maxinter) putimage(exp, exp->x, exp->y, (colormagic((exp->i * exp->color), exp->x, exp->y))); else putimage(exp, exp->x, exp->y, 0x000000); } } } static void juliacubedfun(t_a *exp) { exp->oldre = exp->newre; exp->oldim = exp->newim; exp->newre = (exp->oldre * exp->oldre * exp->oldre) - (exp->oldim * exp->oldim * exp->oldre) - (2 * exp->oldre * exp->oldim * exp->oldim) + exp->cre; exp->newim = (3 * exp->oldre * exp->oldre * exp->oldim) - (exp->oldim * exp->oldim * exp->oldim) + exp->cim; } void juliacubedfx(t_a *exp) { exp->y = -1; while (++exp->y < HEIGHT) { exp->x = -1; while (++exp->x < WIDTH) { exp->newre = 1.5 * (exp->x - WIDTH / 2) / (0.5 * exp->zoom * WIDTH) + exp->movex; exp->newim = (exp->y - HEIGHT / 2) / (0.5 * exp->zoom * HEIGHT) + exp->movey; exp->i = -1; while (++exp->i < exp->maxinter) { juliacubedfun(exp); if ((exp->newre * exp->newre + exp->newim) > 4) break ; } if (exp->i < exp->maxinter) putimage(exp, exp->x, exp->y, (colormagic((exp->i * exp->color), exp->x, exp->y))); else putimage(exp, exp->x, exp->y, 0x000000); } } }

fractol2.c

#include "fractol.h" static void shipmagic(t_a *exp) { exp->oldre = exp->newre; exp->oldim = exp->newim; exp->newre = exp->oldre * exp->oldre - exp->oldim * exp->oldim + exp->pr; exp->newim = fabs(2 * exp->oldre * exp->oldim) + exp->pi; } static void shipassign(t_a *exp) { exp->oldim = 0; exp->oldre = exp->oldim; exp->newim = exp->oldre; exp->newre = exp->newim; } void shipfx(t_a *exp) { exp->y = -1; while (++exp->y < HEIGHT) { exp->x = -1; while (++exp->x < WIDTH) { exp->pr = 1.5 * (exp->x - WIDTH / 2) / (0.5 * exp->zoom * WIDTH) + exp->movex; exp->pi = (exp->y - HEIGHT / 2) / (0.5 * exp->zoom * HEIGHT) + exp->movey; shipassign(exp); exp->i = -1; while (++exp->i < exp->maxinter) { shipmagic(exp); if ((exp->newre * exp->newre + exp->newim * exp->newim) > 4) break ; } if (exp->i < exp->maxinter) putimage(exp, exp->x, exp->y, (colormagic((exp->color * exp->i), exp->x, exp->y))); else putimage(exp, exp->x, exp->y, 200); } } } int isfilled(int x, int y, t_a *exp) { while (x > 0 || y > 0) { if (exp->maxinter < 5) exp->maxinter = 5; if (x % (int)exp->maxinter == 1 && y % (int)exp->maxinter == 1) return (0); x /= 3; y /= 3; } return (1); } void carpetfx(t_a *exp) { int x; int y; y = -1; while (++y < HEIGHT) { x = -1; while (++x < WIDTH) { if (isfilled(x, y, exp) == 1) putimage(exp, x, y, 0xFF0000); else putimage(exp, x, y, 0); } } }

fractol3.c

#include "fractol.h" static void mandelassign(t_a *exp) { exp->oldim = 0; exp->oldre = exp->oldim; exp->newim = exp->oldre; exp->newre = exp->newim; } static void mandelmagic(t_a *exp) { exp->oldre = exp->newre; exp->oldim = exp->newim; exp->newre = exp->oldre * exp->oldre - exp->oldim * exp->oldim + exp->pr; exp->newim = 2 * exp->oldre * exp->oldim + exp->pi; } void mandelfx(t_a *exp) { exp->y = -1; while (++exp->y < HEIGHT) { exp->x = -1; while (++exp->x < WIDTH) { exp->pr = 1.5 * (exp->x - WIDTH / 2) / (0.5 * exp->zoom * WIDTH) + exp->movex; exp->pi = (exp->y - HEIGHT / 2) / (0.5 * exp->zoom * HEIGHT) + exp->movey; mandelassign(exp); exp->i = -1; while (++exp->i < exp->maxinter) { mandelmagic(exp); if ((exp->newre * exp->newre + exp->newim * exp->newim) > 4) break ; } if (exp->i < exp->maxinter) putimage(exp, exp->x, exp->y, (colormagic((exp->color * exp->i), exp->x, exp->y))); else putimage(exp, exp->x, exp->y, 200); } } } static void mandelfun(t_a *exp) { exp->oldre = exp->newre; exp->oldim = exp->newim; exp->newre = (exp->oldre * exp->oldre * exp->oldre) - (exp->oldim * exp->oldre * exp->oldim) - (2 * exp->oldre * exp->oldim * exp->oldim) + exp->pr; exp->newim = (2 * exp->oldre * exp->oldre * exp->oldim) - (exp->oldim * exp->oldim * exp->oldim) + exp->pi; } void mandelcubedfx(t_a *exp) { exp->y = -1; while (++exp->y < HEIGHT) { exp->x = -1; while (++exp->x < WIDTH) { exp->pr = 1.5 * (exp->x - WIDTH / 2) / (0.5 * exp->zoom * WIDTH) + exp->movex; exp->pi = (exp->y - HEIGHT / 2) / (0.5 * exp->zoom * HEIGHT) + exp->movey; mandelassign(exp); exp->i = -1; while (++exp->i < exp->maxinter) { mandelfun(exp); if ((exp->newre * exp->newre + exp->newim * exp->newim) > 4) break ; } if (exp->i < exp->maxinter) putimage(exp, exp->x, exp->y, (colormagic((exp->color * exp->i), exp->x, exp->y))); else putimage(exp, exp->x, exp->y, 200); } } }

fractol4.c

#include "fractol.h" static void mandelassign(t_a *exp) { exp->oldim = 0; exp->oldre = exp->oldim; exp->newim = exp->oldre; exp->newre = exp->newim; } static void tricornmagic(t_a *exp) { exp->oldre = exp->newre; exp->oldim = exp->newim * -1; exp->newre = exp->oldre * exp->oldre - exp->oldim * exp->oldim + exp->pr; exp->newim = 2 * exp->oldre * exp->oldim + exp->pi; } void tricornfx(t_a *exp) { exp->y = -1; while (++exp->y < HEIGHT) { exp->x = -1; while (++exp->x < WIDTH) { exp->pr = 1.5 * (exp->x - WIDTH / 2) / (0.5 * exp->zoom * WIDTH) + exp->movex; exp->pi = (exp->y - HEIGHT / 2) / (0.5 * exp->zoom * HEIGHT) + exp->movey; mandelassign(exp); exp->i = -1; while (++exp->i < exp->maxinter) { tricornmagic(exp); if ((exp->newre * exp->newre + exp->newim * exp->newim) > 4) break ; } if (exp->i < exp->maxinter) putimage(exp, exp->x, exp->y, (colormagic((exp->color * exp->i), exp->x, exp->y))); else putimage(exp, exp->x, exp->y, 200); } } }

fractol.h

#ifndef FRACTOL_H # define FRACTOL_H # include <stdlib.h> # include <fcntl.h> # include <math.h> # include "../libft/libft.h" # include "../minilibx/mlx.h" # define HEIGHT 700 # define WIDTH 700 typedef struct s_a { void *mlx; void *win; void *img; char *imgpointer; int bpp; int s1; int endian; int color; int fractol; double **map; double x; double y; double zoom; double movex; double movey; double cre; double cim; double oldre; double oldim; double newre; double newim; double pr; double pi; int maxinter; int i; double clickx; double clicky; double tmpx; double tmpy; int movemouse; double x2; double y2; } t_a; typedef struct s_color { unsigned char chan[3]; } t_c; void putimage(t_a *exp, int x, int y, int color); unsigned int colormagic(int i, double x, double y); int printxandy(t_a *exp); void retrydraw(t_a *exp); void juliainit(t_a *exp); void mandelinit(t_a *exp); void shipinit(t_a *exp); void carpetinit(t_a *exp); void initfractol(t_a *exp); int mousehook(int mousekey, int x, int y, t_a *exp); int keyhooks3(int key, t_a *exp); int keyhooks2(int key, t_a *exp); int keyhooks(int key, t_a *exp); int isfilled(int x, int y, t_a *exp); void carpetfx(t_a *exp); void tricornfx(t_a *exp); void juliafx(t_a *exp); void mandelfx(t_a *exp); void shipfx(t_a *exp); void juliacubedfx(t_a *exp); void mandelcubedfx(t_a *exp); void whichfractol(t_a *exp); void retrydraw(t_a *exp); void zoomin(int x, int y, t_a *exp); void zoomout(int x, int y, t_a *exp); int motion(int x, int y, t_a *exp); void makewindow(t_a *exp); void ft_errorcheck(char *str, t_a *exp); void controls(int i); #endif

Makefile

NAME = fractol CC = gcc FLAGS = -Wall -Wextra -Werror FLAGS2 = -L minilibx -lmlx -framework OpenGL -framework AppKit SRC = srcs/main.c srcs/fractol1.c srcs/fractol2.c srcs/fractol3.c srcs/fractol4.c srcs/hooks.c srcs/init.c srcs/whichfractol.c srcs/color.c LIBFT_DIR = libft LIBS = libft/libft.a OBJS = $(SRC:.c=.o) HEADER = fdf.h all: $(NAME) $(LIBS): make -C $(LIBFT_DIR) $(NAME): $(SRC) $(LIBS) $(CC) $(FLAGS) $(FLAGS2) $(SRC) $(LIBS) -o fractol clean: $(MAKE) -C $(LIBFT_DIR) clean rm -rf $(OBJS) fclean: clean $(MAKE) -C $(LIBFT_DIR) fclean rm -f $(NAME) re: fclean all