diff options
Diffstat (limited to 'src/modules/julia')
-rw-r--r-- | src/modules/julia/Makefile.am | 4 | ||||
-rw-r--r-- | src/modules/julia/julia.c | 117 |
2 files changed, 121 insertions, 0 deletions
diff --git a/src/modules/julia/Makefile.am b/src/modules/julia/Makefile.am new file mode 100644 index 0000000..54a9228 --- /dev/null +++ b/src/modules/julia/Makefile.am @@ -0,0 +1,4 @@ +noinst_LIBRARIES = libjulia.a +libjulia_a_SOURCES = julia.c +libjulia_a_CFLAGS = @ROTOTILLER_CFLAGS@ +libjulia_a_CPPFLAGS = @ROTOTILLER_CFLAGS@ -I@top_srcdir@/src diff --git a/src/modules/julia/julia.c b/src/modules/julia/julia.c new file mode 100644 index 0000000..1afb3cc --- /dev/null +++ b/src/modules/julia/julia.c @@ -0,0 +1,117 @@ +#include <stdint.h> +#include <inttypes.h> +#include <math.h> + +#include "fb.h" +#include "rototiller.h" + +/* Copyright (C) 2017 Vito Caputo <vcaputo@pengaru.com> */ + +/* Julia set renderer - see https://en.wikipedia.org/wiki/Julia_set, morphing just means to vary C. */ + +/* TODO: explore using C99 complex.h and its types? */ + +static inline unsigned julia_iter(float real, float imag, float creal, float cimag, unsigned max_iters) +{ + unsigned i; + float newr, newi; + + for (i = 1; i < max_iters; i++) { + newr = real * real - imag * imag; + newi = imag * real; + newi += newi; + + newr += creal; + newi += cimag; + + if ((newr * newr + newi * newi) > 4.0) + return i; + + real = newr; + imag = newi; + } + + return 0; +} + +/* Draw a morphing Julia set */ +static void julia(fb_fragment_t *fragment) +{ + static uint32_t colors[] = { + /* this palette is just something I slapped together, definitely needs improvement. TODO */ + 0x000000, + 0x000044, + 0x000088, + 0x0000aa, + 0x0000ff, + 0x0044ff, + 0x0088ff, + 0x00aaff, + 0x00ffff, + 0x44ffaa, + 0x88ff88, + 0xaaff44, + 0xffff00, + 0xffaa00, + 0xff8800, + 0xff4400, + 0xff0000, + 0xaa0000, + 0x880000, + 0x440000, + 0x440044, + 0x880088, + 0xaa00aa, + 0xff00ff, + 0xff4400, + 0xff8800, + 0xffaa00, + 0xffff00, + 0xaaff44, + 0x88ff88, + 0x44ffaa, + 0x00ffff, + 0x00aaff, + 0x0088ff, + 0xff4400, + 0xff00ff, + 0xaa00aa, + 0x880088, + 0x440044, + + }; + static float rr; + + unsigned x, y; + unsigned stride = fragment->stride / 4, width = fragment->width, height = fragment->height; + uint32_t *buf = fragment->buf; + float real, imag; + float realstep = 3.6f / (float)width, imagstep = 3.6f / (float)height; + + /* Rather than just sweeping creal,cimag from -2.0-+2.0, I try to keep things confined + * to an interesting (visually) range. TODO: could certainly use refinement. + */ + float realscale = 0.01f * cosf(rr) + 0.01f; + float imagscale = 0.01f * sinf(rr * 3.0f) + 0.01f; + float creal = (1.01f + (realscale * cosf(1.5f*M_PI+rr) + realscale)) * cosf(rr * .3f); + float cimag = (1.01f + (imagscale * sinf(rr * 3.0f) + imagscale)) * sinf(rr); + + /* Complex plane confined to {-1.8 - 1.8} on both axis (slightly zoomed), no dynamic zooming is performed. */ + for (imag = 1.8, y = 0; y < height; y++, imag += -imagstep) { + for (real = -1.8, x = 0; x < width; x++, buf++, real += realstep) { + *buf = colors[julia_iter(real, imag, creal, cimag, sizeof(colors) / sizeof(*colors))]; + } + + buf += stride; + } + + rr += .01; +} + +rototiller_renderer_t julia_renderer = { + .render = julia, + .name = "julia", + .description = "Julia set fractal morpher", + .author = "Vito Caputo <vcaputo@pengaru.com>", + .license = "GPLv2", +}; |