hero-image

Fract-ol


Fract-ol

A graphical project that generates beautiful, infinite geometric patterns. This implementation stands out by using a single mathematical engine to compute multiple fractal types and leveraging the mlx_loop_hook for continuous, high-speed rendering.

Features

  • Mandelbrot & Julia Sets: Seamlessly toggle between fractal types using unified logic.
  • High-Performance Rendering: Smoothly handles thousands of iterations using the mlx_loop_hook.
  • Infinite Zoom: Fully interactive zoom functionality using the mouse wheel.
  • Color Schemes: Dynamic coloring based on the escape time of each pixel.

Implementation Highlights

1. The “Unified” Math Engine

Instead of writing separate loops for Mandelbrot and Julia, I designed a math_init function. It abstracts the starting parameters (z and c) while keeping the iterative escape-time math identical.

  • Mandelbrot: z starts at 0.0, and c is the current pixel coordinate.
  • Julia: z starts at the pixel coordinate, and c is a constant provided as an argument.
static void	math_init(double x, double y, t_fractol *fractol, t_math *math_obj)
{
	if (fractol->name) // Mandelbrot
	{
		math_obj->z_real = 0.0;
		math_obj->z_imag = 0.0;
		math_obj->c_real = x;
		math_obj->c_imag = y;
	}
	else // Julia
	{
		math_obj->z_real = x;
		math_obj->z_imag = y;
		math_obj->c_real = fractol->julia_cx;
		math_obj->c_imag = fractol->julia_cy;
	}
}

2. High-Performance Loop Hook

To ensure the program remains responsive and renders as fast as the GPU allows, I utilized mlx_loop_hook. This hook constantly calls my render_main function, allowing for real-time updates and the ability to handle thousands of iterations without freezing the UI.

// In main.c
mlx_loop_hook(mlx.mlx, render_main, &mlx); // Continuous high-speed rendering
mlx_loop(mlx.mlx);

3. The Core Fractal Loop

The escape-time logic is contained in fract_math, which calculates whether a point diverges using the formula z = z^2 + c.

t_color	fract_math(double x, double y, t_fractol *fractol)
{
	int	i;
	double	tmp;
	t_math	math_obj;

	i = 0;
	math_init(x * fractol->zoom, y * fractol->zoom, fractol, &math_obj);
	while (i < fractol->iteration)
	{
		if ((math_obj.z_real * math_obj.z_real) + (math_obj.z_imag * math_obj.z_imag) > 4)
			return (coloring(i)); // Point escaped
		tmp = (math_obj.z_real * math_obj.z_real) - (math_obj.z_imag * math_obj.z_imag) + math_obj.c_real;
		math_obj.z_imag = 2 * math_obj.z_real * math_obj.z_imag + math_obj.c_imag;
		math_obj.z_real = tmp;
		i++;
	}
	return (BLACK); // Point is part of the set
}

Usage

1. Compilation

make

2. Run Mandelbrot

./fractol mandelbrot

3. Run Julia

./fractol julia -0.4 0.6

Skills Learned

  • Complex Math: Implementing calculations in the complex plane (z = z^2 + c).
  • Graphic Optimization: Using hooks and memory-mapped address offsets (mlx_get_data_addr) to push pixels efficiently.
  • Event Handling: Managing keyboard and mouse input to create a seamless user interface.
  • Code Abstraction: Reducing code duplication by unifying fractal initialization logic.

👤 Author

arri