diff options
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/modules/Makefile.am | 2 | ||||
-rw-r--r-- | src/modules/julia/Makefile.am | 4 | ||||
-rw-r--r-- | src/modules/julia/julia.c | 117 | ||||
-rw-r--r-- | src/rototiller.c | 2 |
7 files changed, 127 insertions, 2 deletions
@@ -4,6 +4,7 @@ rototiller is, rendered entirely in software: sparkler: a fireworks-like particle system with spatial interactions stars: a starfield simulator plasma: an oldskool "plasma" effect + julia: a morphing Julia set (fractal) --- diff --git a/configure.ac b/configure.ac index 728c7ba..9c6eebb 100644 --- a/configure.ac +++ b/configure.ac @@ -17,6 +17,7 @@ AC_CONFIG_FILES([ Makefile src/Makefile src/modules/Makefile + src/modules/julia/Makefile src/modules/plasma/Makefile src/modules/ray/Makefile src/modules/roto/Makefile diff --git a/src/Makefile.am b/src/Makefile.am index b72d41c..928b8d7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ SUBDIRS = modules bin_PROGRAMS = rototiller rototiller_SOURCES = drmsetup.c drmsetup.h fb.c fb.h fps.c fps.h rototiller.c rototiller.h util.c util.h -rototiller_LDADD = @ROTOTILLER_LIBS@ -lm modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/sparkler/libsparkler.a modules/stars/libstars.a +rototiller_LDADD = @ROTOTILLER_LIBS@ -lm modules/julia/libjulia.a modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/sparkler/libsparkler.a modules/stars/libstars.a rototiller_CPPFLAGS = @ROTOTILLER_CFLAGS@ diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am index 2890308..f65ba63 100644 --- a/src/modules/Makefile.am +++ b/src/modules/Makefile.am @@ -1 +1 @@ -SUBDIRS = plasma ray roto sparkler stars +SUBDIRS = julia plasma ray roto sparkler stars 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", +}; diff --git a/src/rototiller.c b/src/rototiller.c index 313cb0c..22d13e2 100644 --- a/src/rototiller.c +++ b/src/rototiller.c @@ -24,6 +24,7 @@ * just two pages we end up twiddling thumbs until the vsync arrives. */ +extern rototiller_renderer_t julia_renderer; extern rototiller_renderer_t plasma_renderer; extern rototiller_renderer_t roto32_renderer; extern rototiller_renderer_t roto64_renderer; @@ -38,6 +39,7 @@ static rototiller_renderer_t *renderers[] = { &sparkler_renderer, &stars_renderer, &plasma_renderer, + &julia_renderer, }; |