summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac1
-rw-r--r--src/Makefile.am2
-rw-r--r--src/modules/Makefile.am2
-rw-r--r--src/modules/spiro/Makefile.am3
-rw-r--r--src/modules/spiro/draw.h16
-rw-r--r--src/modules/spiro/spiro.c155
-rw-r--r--src/rototiller.c2
7 files changed, 179 insertions, 2 deletions
diff --git a/configure.ac b/configure.ac
index 091b6e5..872acec 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,6 +52,7 @@ AC_CONFIG_FILES([
src/modules/rtv/Makefile
src/modules/snow/Makefile
src/modules/sparkler/Makefile
+ src/modules/spiro/Makefile
src/modules/stars/Makefile
src/modules/submit/Makefile
src/modules/swab/Makefile
diff --git a/src/Makefile.am b/src/Makefile.am
index 5446acd..43c79e7 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,4 +4,4 @@ rototiller_SOURCES = fb.c fb.h fps.c fps.h rototiller.c rototiller.h sdl_fb.c se
if ENABLE_DRM
rototiller_SOURCES += drm_fb.c
endif
-rototiller_LDADD = modules/flui2d/libflui2d.a modules/julia/libjulia.a modules/meta2d/libmeta2d.a modules/montage/libmontage.a modules/pixbounce/libpixbounce.a modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/rtv/librtv.a modules/snow/libsnow.a modules/sparkler/libsparkler.a modules/stars/libstars.a modules/submit/libsubmit.a modules/swab/libswab.a libs/grid/libgrid.a libs/ray/libray.a libs/txt/libtxt.a libs/ascii/libascii.a libs/din/libdin.a -lm
+rototiller_LDADD = modules/flui2d/libflui2d.a modules/julia/libjulia.a modules/meta2d/libmeta2d.a modules/montage/libmontage.a modules/pixbounce/libpixbounce.a modules/plasma/libplasma.a modules/ray/libray.a modules/roto/libroto.a modules/rtv/librtv.a modules/snow/libsnow.a modules/sparkler/libsparkler.a modules/spiro/libspiro.a modules/stars/libstars.a modules/submit/libsubmit.a modules/swab/libswab.a libs/grid/libgrid.a libs/ray/libray.a libs/txt/libtxt.a libs/ascii/libascii.a libs/din/libdin.a -lm
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
index a4ff9e7..958d835 100644
--- a/src/modules/Makefile.am
+++ b/src/modules/Makefile.am
@@ -1 +1 @@
-SUBDIRS = flui2d julia meta2d montage pixbounce plasma ray roto rtv snow sparkler stars submit swab
+SUBDIRS = flui2d julia meta2d montage pixbounce plasma ray roto rtv snow sparkler spiro stars submit swab
diff --git a/src/modules/spiro/Makefile.am b/src/modules/spiro/Makefile.am
new file mode 100644
index 0000000..f03d8cd
--- /dev/null
+++ b/src/modules/spiro/Makefile.am
@@ -0,0 +1,3 @@
+noinst_LIBRARIES = libspiro.a
+libspiro_a_SOURCES = draw.h spiro.c
+libspiro_a_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/spiro/draw.h b/src/modules/spiro/draw.h
new file mode 100644
index 0000000..0b68c00
--- /dev/null
+++ b/src/modules/spiro/draw.h
@@ -0,0 +1,16 @@
+#ifndef _DRAW_H
+#define _DRAW_H
+
+#include <stdint.h>
+
+/* helper for scaling rgb colors and packing them into an pixel */
+static inline uint32_t makergb(uint32_t r, uint32_t g, uint32_t b, float intensity)
+{
+ r = (((float)intensity) * r);
+ g = (((float)intensity) * g);
+ b = (((float)intensity) * b);
+
+ return (((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff));
+}
+
+#endif
diff --git a/src/modules/spiro/spiro.c b/src/modules/spiro/spiro.c
new file mode 100644
index 0000000..f6aeddc
--- /dev/null
+++ b/src/modules/spiro/spiro.c
@@ -0,0 +1,155 @@
+#include <math.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "draw.h"
+#include "fb.h"
+#include "rototiller.h"
+
+/* Copyright (C) 2020 Philip J. Freeman <elektron@halo.nu> */
+
+/*
+
+Spirograph Emulator
+
+ refs:
+
+ - https://en.wikipedia.org/wiki/Spirograph#Mathematical_basis
+ - https://en.wikipedia.org/wiki/Unit_circle#Trigonometric_functions_on_the_unit_circle
+*/
+
+typedef struct spiro_context_t {
+ float r;
+ int r_dir;
+ float p;
+ int p_dir;
+} spiro_context_t;
+
+
+static void * spiro_create_context(unsigned num_cpus)
+{
+ spiro_context_t *ctxt;
+ float z;
+
+ ctxt = malloc(sizeof(spiro_context_t));
+ if (!ctxt)
+ return NULL;
+
+ srand(time(NULL) + getpid());
+
+ ctxt->r=.25f+(rand()/(float)RAND_MAX)*.5f;
+ if(ctxt->r>.5f)
+ ctxt->r_dir=-1;
+ else
+ ctxt->r_dir=1;
+ ctxt->p=(rand()/(float)RAND_MAX)*ctxt->r;
+ ctxt->p_dir=ctxt->r_dir*-1;
+#ifdef DEBUG
+ printf("spiro: initial context: r=%f, dir=%i, p=%f, dir=%i\n", ctxt->r, ctxt->r_dir, ctxt->p, ctxt->p_dir);
+#endif
+ return ctxt;
+}
+
+static void spiro_destroy_context(void *context)
+{
+ spiro_context_t *ctxt = context;
+
+ free(context);
+}
+
+
+static void spiro_render_fragment(void *context, unsigned cpu, fb_fragment_t *fragment)
+{
+ spiro_context_t *ctxt = context;
+
+ int width = fragment->width, height = fragment->height;
+
+ int display_R, display_origin_x, display_origin_y;
+
+ /* Based on the fragment's dimensions, calculate the origin and radius of the fixed outer
+ circle, C0. */
+
+ if(width>=height) { // landscape or square aspect ratio
+ display_R=(height-1)*0.5f;
+ display_origin_x=((width-height)*.5f)+display_R;
+ display_origin_y=display_R;
+ } else { // portrait
+ display_R=(width-1)*.5f;
+ display_origin_x=display_R;
+ display_origin_y=((height-width)*.5f)+display_R;
+ }
+
+ /* blank the fragment */
+ fb_fragment_zero(fragment);
+
+ /* plot one spirograph run */
+ float l=ctxt->p/ctxt->r;
+ float k=ctxt->r;
+ for(float t=0.f; t<128*2*M_PI; t+= M_PI/display_R) {
+ float my_x=((1.f-k)*cosf(t))+(l*k*cosf(((1.f-k)/k)*t));
+ float my_y=((1.f-k)*sinf(t))-(l*k*sinf(((1.f-k)/k)*t));
+ int pos_x=display_origin_x+(my_x*display_R);
+ int pos_y=display_origin_y+(my_y*display_R);
+ fb_fragment_put_pixel_unchecked(fragment, pos_x, pos_y,
+ makergb(sinf(M_1_PI*t)*127+128,
+ sinf(M_1_PI*t+(2*M_PI*.333333333333f))*127+128,
+ sinf(M_1_PI*t+(4*M_PI*.333333333333f))*127+128,
+ 0.76));
+ }
+
+#ifdef DEBUG
+ /* plot the origin point */
+ fb_fragment_put_pixel_unchecked(fragment, display_origin_x, display_origin_y,
+ makergb(0xFF, 0xFF, 0x00, 1));
+
+ /* plot the fixed outer circle C0 */
+ for(float a=0.f; a<2*M_PI; a+= M_PI_2/display_R) {
+ int pos_x=display_origin_x+(cosf(a)*display_R);
+ int pos_y=display_origin_y+(sinf(a)*display_R);
+ fb_fragment_put_pixel_unchecked(fragment, pos_x, pos_y,
+ makergb(0xFF, 0xFF, 0x00, 1));
+ }
+
+ /* plot inner circle Ci */
+ fb_fragment_put_pixel_unchecked(fragment, display_origin_x+display_R-(ctxt->r*display_R),
+ display_origin_y, makergb(0xFF, 0xFF, 0x00, 1));
+
+ for(float a=0.f; a<2*M_PI; a+= M_PI_2/display_R) {
+ int pos_x=display_origin_x+display_R-(ctxt->r*display_R)+
+ (cosf(a)*ctxt->r*display_R);
+ int pos_y=display_origin_y+(sinf(a)*ctxt->r*display_R);
+ fb_fragment_put_pixel_unchecked(fragment, pos_x, pos_y,
+ makergb(0xFF, 0xFF, 0x00, 1));
+ }
+
+ /* plot p */
+ fb_fragment_put_pixel_unchecked(fragment, display_origin_x+display_R-(ctxt->r*display_R)+
+ (ctxt->p*display_R), display_origin_y, makergb(0xFF, 0xFF, 0x00, 1));
+#endif
+
+ /* check bounds and increment r & p */
+ float next_r=ctxt->r+(.00001f*ctxt->r_dir);
+ if(next_r >= 1.f || next_r <= 0.f || next_r <= ctxt->p)
+ ctxt->r_dir=ctxt->r_dir*-1;
+ else
+ ctxt->r=ctxt->r+(.00001f*ctxt->r_dir);
+
+ float next_p=ctxt->p+(.0003f*ctxt->p_dir);
+ if(next_p >= ctxt->r || next_p <= 0)
+ ctxt->p_dir=ctxt->p_dir*-1;
+ else
+ ctxt->p=ctxt->p+(.0003f*ctxt->p_dir);
+
+}
+
+rototiller_module_t spiro_module = {
+ .create_context = spiro_create_context,
+ .destroy_context = spiro_destroy_context,
+ .render_fragment = spiro_render_fragment,
+ .name = "spiro",
+ .description = "Spirograph Emulator",
+ .author = "Philip J Freeman <elektron@halo.nu>",
+ .license = "GPLv2",
+};
diff --git a/src/rototiller.c b/src/rototiller.c
index d8fa665..644013b 100644
--- a/src/rototiller.c
+++ b/src/rototiller.c
@@ -43,6 +43,7 @@ extern rototiller_module_t roto_module;
extern rototiller_module_t rtv_module;
extern rototiller_module_t snow_module;
extern rototiller_module_t sparkler_module;
+extern rototiller_module_t spiro_module;
extern rototiller_module_t stars_module;
extern rototiller_module_t submit_module;
extern rototiller_module_t swab_module;
@@ -59,6 +60,7 @@ static const rototiller_module_t *modules[] = {
&rtv_module,
&snow_module,
&sparkler_module,
+ &spiro_module,
&stars_module,
&submit_module,
&swab_module,
© All Rights Reserved