diff src/paranormal-ng/cmaps.c @ 2078:1fa3c8cd366a

paranormal-ng: a GL visualiser. lots to do, most stuff won't work, but hey, this will do cool stuff too soon
author William Pitcock <nenolod@atheme.org>
date Mon, 15 Oct 2007 06:20:13 -0500
parents
children f1b6f1b2cdb3
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/paranormal-ng/cmaps.c	Mon Oct 15 06:20:13 2007 -0500
@@ -0,0 +1,202 @@
+/*
+ * paranormal: iterated pipeline-driven visualization plugin
+ * Copyright (c) 2006, 2007 William Pitcock <nenolod@dereferenced.org>
+ * Portions copyright (c) 2001 Jamie Gennis <jgennis@mindspring.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; under version 2 of the License.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#include "paranormal.h"
+#include "actuators.h"
+
+#include "libcalc/calc.h"
+
+#define STD_CMAP_OPTS { "low_index", "The lowest index of the \
+color map that should be altered", OPT_TYPE_COLOR_INDEX, { ival: 0 } },\
+{ "high_index", "The highest index of the color map that should be \
+altered", OPT_TYPE_COLOR_INDEX, { ival: 255 } }
+
+static struct pn_color black = {0, 0, 0};
+static struct pn_color white = {255, 255, 255};
+
+/* **************** cmap generation funcs **************** */
+static void
+cmap_gen_gradient (int step, const struct pn_color *a,
+		   const struct pn_color *b,
+		   struct pn_color *c)
+{
+  c->r = a->r + step * ((((float)b->r) - ((float)a->r)) / 256.0);
+  c->g = a->g + step * ((((float)b->g) - ((float)a->g)) / 256.0);
+  c->b = a->b + step * ((((float)b->b) - ((float)a->b)) / 256.0);
+}
+
+/* **************** cmap_gradient **************** */
+static struct pn_actuator_option_desc cmap_gradient_opts[] =
+{
+  STD_CMAP_OPTS,
+  { "lcolor", "The low color used in the gradient generation",
+    OPT_TYPE_COLOR, { cval: {0, 0, 0} } },
+  { "hcolor", "The high color used in the gradient generation",
+    OPT_TYPE_COLOR, { cval: {0, 0, 0} } },
+  { NULL }
+};
+
+static void
+cmap_gradient_exec (const struct pn_actuator_option *opts,
+		    gpointer data)
+{
+  int i;
+
+  for (i=opts[0].val.ival; i<=opts[1].val.ival; i++)
+    cmap_gen_gradient (((i-opts[0].val.ival)<<8)/(opts[1].val.ival
+						  - opts[0].val.ival),
+		       &opts[2].val.cval, &opts[3].val.cval,
+		       &pn_image_data->cmap[i]);
+}
+
+struct pn_actuator_desc builtin_cmap_gradient =
+{
+  "cmap_gradient",
+  "Normal colourmap",
+  "Sets the colormap to a gradient going from <lcolor> to "
+  "<hcolor>",
+  0, cmap_gradient_opts,
+  NULL, NULL, cmap_gradient_exec
+};
+
+/* **************** cmap_bwgradient **************** */
+static struct pn_actuator_option_desc cmap_bwgradient_opts[] =
+{
+  STD_CMAP_OPTS,
+  { "color", "The intermediate color to use in the gradient",
+    OPT_TYPE_COLOR, { cval: {191, 191, 191} } },
+  { NULL }
+};
+
+static void
+cmap_bwgradient_exec (const struct pn_actuator_option *opts,
+		      gpointer data)
+{
+  int i;
+
+  for (i=opts[0].val.ival; i<128 && i<=opts[1].val.ival; i++)
+    cmap_gen_gradient (i<<1, &black, &opts[2].val.cval,
+		       &pn_image_data->cmap[i]);
+
+  for (i=128; i<256 && i<=opts[1].val.ival; i++)
+    cmap_gen_gradient ((i-128)<<1, &opts[2].val.cval, &white,
+		       &pn_image_data->cmap[i]);
+}
+    
+struct pn_actuator_desc builtin_cmap_bwgradient =
+{
+  "cmap_bwgradient",
+  "Value-based colourmap",
+  "Sets the colormap to a gradient going from black to "
+  "white, via an intermediate color",
+  0, cmap_bwgradient_opts,
+  NULL, NULL, cmap_bwgradient_exec
+};
+
+/* **************** cmap_dynamic **************** */
+static struct pn_actuator_option_desc cmap_dynamic_opts[] =
+{
+  STD_CMAP_OPTS,
+  { "script", "The script to run on each step.",
+    OPT_TYPE_STRING, { sval: "red = red + 0.01; blue = blue + 0.01; green = green + 0.01;" } },
+  { NULL }
+};
+
+typedef struct {
+  expression_t *expr;
+  symbol_dict_t *dict;
+} PnDynamicColourmapData;
+
+static void
+cmap_dynamic_init(gpointer *data)
+{
+  *data = g_new0(PnDynamicColourmapData, 1);
+}
+
+static void
+cmap_dynamic_cleanup(gpointer data)
+{
+  PnDynamicColourmapData *d = (PnDynamicColourmapData *) data;
+
+  if (d->expr)
+    expr_free(d->expr);
+  if (d->dict)
+    dict_free(d->dict);
+
+  g_free(d);
+}
+
+static void
+cmap_dynamic_exec(const struct pn_actuator_option *opts,
+		  gpointer data)
+{
+  PnDynamicColourmapData *d = (PnDynamicColourmapData *) data;
+  gint i, j;
+  gdouble *rf, *bf, *gf, *inf;
+  gint rn, bn, gn;
+
+  if (!d->dict && !d->expr)
+    {
+       d->dict = dict_new();
+       if (!d->dict)
+         return;
+
+       d->expr = expr_compile_string(opts[2].val.sval, d->dict);
+       if (!d->expr)
+         {
+           dict_free(d->dict);
+           d->dict = NULL;
+           return;
+         }
+    }
+
+  rf = dict_variable(d->dict, "red");
+  gf = dict_variable(d->dict, "green");
+  bf = dict_variable(d->dict, "blue");
+  inf = dict_variable(d->dict, "index");
+
+  for (i = opts[0].val.ival; i < 255 && i <= opts[1].val.ival; i++)
+    {
+       *inf = ((gdouble)i / 255.0);
+
+       expr_execute(d->expr, d->dict);
+
+       /* Convert rf/bf/gf to realworld values. */
+       rn = (gdouble)(*rf * 255);
+       gn = (gdouble)(*gf * 255);
+       bn = (gdouble)(*bf * 255);
+
+       pn_image_data->cmap[i].r = rn;
+       pn_image_data->cmap[i].g = gn;
+       pn_image_data->cmap[i].b = bn;
+    }
+}
+
+struct pn_actuator_desc builtin_cmap_dynamic =
+{
+  "cmap_dynamic",
+  "Dynamic Colourmap",
+  "Scriptable colourmap modifier.",
+  0, cmap_dynamic_opts,
+  cmap_dynamic_init, cmap_dynamic_cleanup, cmap_dynamic_exec
+};