summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2022-06-07 19:02:35 -0700
committerVito Caputo <vcaputo@pengaru.com>2022-06-07 21:12:34 -0700
commitd944160f1d6a25710b298442972a8562ffc62942 (patch)
tree1712b8768ac97db6b28b2065638454c8a6b54f84 /src/modules
parent6d1d7f95529d826ea916ac80d236f5e8616daf64 (diff)
modules/moire: implement rudimentary moire module
This introduces a very naive unoptimized moire interference pattern module, it's rather slow complete with a sqrtf() per pixel per center.
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/Makefile.am2
-rw-r--r--src/modules/moire/Makefile.am3
-rw-r--r--src/modules/moire/moire.c173
3 files changed, 177 insertions, 1 deletions
diff --git a/src/modules/Makefile.am b/src/modules/Makefile.am
index d00ac7b..83adbc5 100644
--- a/src/modules/Makefile.am
+++ b/src/modules/Makefile.am
@@ -1 +1 @@
-SUBDIRS = blinds checkers compose drizzle flui2d julia meta2d montage pixbounce plasma plato ray roto rtv shapes snow sparkler spiro stars submit swab swarm voronoi
+SUBDIRS = blinds checkers compose drizzle flui2d julia meta2d moire montage pixbounce plasma plato ray roto rtv shapes snow sparkler spiro stars submit swab swarm voronoi
diff --git a/src/modules/moire/Makefile.am b/src/modules/moire/Makefile.am
new file mode 100644
index 0000000..9d72068
--- /dev/null
+++ b/src/modules/moire/Makefile.am
@@ -0,0 +1,3 @@
+noinst_LTLIBRARIES = libmoire.la
+libmoire_la_SOURCES = moire.c
+libmoire_la_CPPFLAGS = -I@top_srcdir@/src
diff --git a/src/modules/moire/moire.c b/src/modules/moire/moire.c
new file mode 100644
index 0000000..1678170
--- /dev/null
+++ b/src/modules/moire/moire.c
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2022 - Vito Caputo - <vcaputo@pengaru.com>
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <math.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "til.h"
+#include "til_fb.h"
+#include "til_module_context.h"
+
+#define MOIRE_DEFAULT_CENTERS 2
+
+typedef struct moire_setup_t {
+ til_setup_t til_setup;
+ unsigned n_centers;
+} moire_setup_t;
+
+typedef struct moire_center_t {
+ float x, y;
+ float seed;
+ float dir;
+} moire_center_t;
+
+typedef struct moire_context_t {
+ til_module_context_t til_module_context;
+ moire_setup_t setup;
+ moire_center_t centers[];
+} moire_context_t;
+
+static moire_setup_t moire_default_setup = {
+ .n_centers = MOIRE_DEFAULT_CENTERS,
+};
+
+
+static til_module_context_t * moire_create_context(unsigned seed, unsigned ticks, unsigned n_cpus, til_setup_t *setup)
+{
+ moire_context_t *ctxt;
+
+ if (!setup)
+ setup = &moire_default_setup.til_setup;
+
+ ctxt = til_module_context_new(sizeof(moire_context_t) + ((moire_setup_t *)setup)->n_centers * sizeof(moire_center_t), seed, n_cpus);
+ if (!ctxt)
+ return NULL;
+
+ ctxt->setup = *(moire_setup_t *)setup;
+
+ for (unsigned i = 0; i < ((moire_setup_t *)setup)->n_centers; i++) {
+ ctxt->centers[i].seed = rand_r(&seed) * (1.f / (float)RAND_MAX) * 2 * M_PI;
+ ctxt->centers[i].dir = (rand_r(&seed) * (2.f / (float)RAND_MAX) - 1.f);
+ ctxt->centers[i].x = cosf(ctxt->centers[i].seed + (float)ticks * .001f * ctxt->centers[i].dir);
+ ctxt->centers[i].y = sinf(ctxt->centers[i].seed + (float)ticks * .001f * ctxt->centers[i].dir);
+ }
+
+ return &ctxt->til_module_context;
+}
+
+
+static void moire_prepare_frame(til_module_context_t *context, unsigned ticks, til_fb_fragment_t *fragment, til_fragmenter_t *res_fragmenter)
+{
+ moire_context_t *ctxt = (moire_context_t *)context;
+
+ *res_fragmenter = til_fragmenter_slice_per_cpu;
+
+ for (unsigned i = 0; i < ctxt->setup.n_centers; i++) {
+ ctxt->centers[i].x = cosf(ctxt->centers[i].seed + (float)ticks * .001f * ctxt->centers[i].dir);
+ ctxt->centers[i].y = sinf(ctxt->centers[i].seed + (float)ticks * .001f * ctxt->centers[i].dir);
+ }
+}
+
+
+static void moire_render_fragment(til_module_context_t *context, unsigned ticks, unsigned cpu, til_fb_fragment_t *fragment)
+{
+ moire_context_t *ctxt = (moire_context_t *)context;
+ float xf = 2.f / (float)fragment->frame_width;
+ float yf = 2.f / (float)fragment->frame_height;
+ float cx, cy;
+
+ /* TODO: optimize */
+ cy = yf * (float)fragment->y - 1.f;
+ for (int y = fragment->y; y < fragment->y + fragment->height; y++, cy += yf) {
+
+ cx = xf * (float)fragment->x - 1.f;
+ for (int x = fragment->x; x < fragment->x + fragment->width; x++, cx += xf) {
+ int filled = 0;
+
+ for (unsigned i = 0; i < ctxt->setup.n_centers; i++) {
+ float dx, dy;
+
+ dx = cx - ctxt->centers[i].x;
+ dy = cy - ctxt->centers[i].y;
+
+ if (cosf(sqrtf(dx * dx + dy * dy) * 50.f) < 0.f)
+ filled ^= 1;
+ }
+
+ if (filled)
+ til_fb_fragment_put_pixel_unchecked(fragment, TIL_FB_DRAW_FLAG_TEXTURABLE, x, y, 0xffffffff);
+ else if (!fragment->cleared)
+ til_fb_fragment_put_pixel_unchecked(fragment, 0, x, y, 0x00000000);
+ }
+ }
+}
+
+
+static int moire_setup(const til_settings_t *settings, til_setting_t **res_setting, const til_setting_desc_t **res_desc, til_setup_t **res_setup)
+{
+ const char *centers;
+ const char *values[] = {
+ "2",
+ "3",
+ "4",
+ "5",
+ NULL
+ };
+ int r;
+
+ r = til_settings_get_and_describe_value(settings,
+ &(til_setting_desc_t){
+ .name = "Number of radial centers",
+ .key = "centers",
+ .regex = "\\.[0-9]+",
+ .preferred = TIL_SETTINGS_STR(MOIRE_DEFAULT_CENTERS),
+ .values = values,
+ .annotations = NULL
+ },
+ &centers,
+ res_setting,
+ res_desc);
+ if (r)
+ return r;
+
+ if (res_setup) {
+ moire_setup_t *setup;
+
+ setup = til_setup_new(sizeof(*setup), (void(*)(til_setup_t *))free);
+ if (!setup)
+ return -ENOMEM;
+
+ sscanf(centers, "%u", &setup->n_centers);
+
+ *res_setup = &setup->til_setup;
+ }
+
+ return 0;
+}
+
+
+til_module_t moire_module = {
+ .create_context = moire_create_context,
+ .prepare_frame = moire_prepare_frame,
+ .render_fragment = moire_render_fragment,
+ .setup = moire_setup,
+ .name = "moire",
+ .description = "2D Moire interference patterns (threaded)",
+ .author = "Vito Caputo <vcaputo@pengaru.com>",
+ .flags = TIL_MODULE_OVERLAYABLE,
+};
© All Rights Reserved