summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--flam3.c9
-rw-r--r--flam3.h6
-rw-r--r--genome.c5
-rw-r--r--parser.c4
-rw-r--r--variations.c60
5 files changed, 75 insertions, 9 deletions
diff --git a/flam3.c b/flam3.c
index 08640b0..61cd088 100644
--- a/flam3.c
+++ b/flam3.c
@@ -529,6 +529,10 @@ void flam3_copy_params(flam3_xform * restrict dest, flam3_xform * restrict src,
dest->bcollide_num = src->bcollide_num;
dest->bcollide_a = src->bcollide_a;
break;
+ case VAR_BMOD:
+ dest->bmod_radius = src->bmod_radius;
+ dest->bmod_distance = src->bmod_distance;
+ break;
}
}
@@ -1299,6 +1303,11 @@ static void flam3_print_xform(FILE *f, flam3_xform *x, int final_flag,
fprintf(f, "bcollide_a=\"%g\" ", x->bcollide_a);
break;
+ case VAR_BMOD:
+ fprintf(f, "bmod_radius=\"%g\" ", x->bmod_radius);
+ fprintf(f, "bmod_distance=\"%g\" ", x->bmod_distance);
+ break;
+
default:
/* pass */
break;
diff --git a/flam3.h b/flam3.h
index b26c57a..165fd5e 100644
--- a/flam3.h
+++ b/flam3.h
@@ -144,7 +144,8 @@ typedef enum {
#define VAR_MOBIUS 98
#define VAR_ASTERIA 99
#define VAR_BCOLLIDE 100
-#define flam3_nvariations 101
+#define VAR_BMOD 101
+#define flam3_nvariations 102
#include "vector.h"
#include "random.h"
@@ -377,6 +378,9 @@ typedef struct xform {
/* precalc */
double bcollide_bCa, bcollide_bCn_pi, bcollide_bCa_bCn, bcollide_pi_bCn;
+ /* bmod */
+ double bmod_radius, bmod_distance;
+
int num_active_vars;
double active_var_weights[flam3_nvariations];
int varFunc[flam3_nvariations];
diff --git a/genome.c b/genome.c
index 8221749..c21c102 100644
--- a/genome.c
+++ b/genome.c
@@ -262,6 +262,11 @@ static void random_xform_param (flam3_xform * const xform, const unsigned int i,
xform->bcollide_num = rand_d01(rc)*(1<<16);
xform->bcollide_a = rand_d01(rc);
break;
+
+ case VAR_BMOD:
+ xform->bmod_radius = rand_d01(rc)*(1<<16);
+ xform->bmod_distance = rand_d01(rc)*2;
+ break;
}
}
diff --git a/parser.c b/parser.c
index ca74577..d8f2c94 100644
--- a/parser.c
+++ b/parser.c
@@ -1091,6 +1091,10 @@ static int parse_xform_xml(xmlNode *chld_node,flam3_xform *this_xform, int *num_
this_xform->bcollide_num = flam3_atof(att_str);
} else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"bcollide_a")) {
this_xform->bcollide_a = flam3_atof(att_str);
+ } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"bmod_radius")) {
+ this_xform->bmod_radius = flam3_atof(att_str);
+ } else if (!xmlStrcmp(cur_att->name, (const xmlChar *)"bmod_distance")) {
+ this_xform->bmod_distance = flam3_atof(att_str);
} else {
int v = var2n((char *) cur_att->name);
if (v != flam3_variation_none)
diff --git a/variations.c b/variations.c
index 00d49b7..d828074 100644
--- a/variations.c
+++ b/variations.c
@@ -131,6 +131,7 @@ char *flam3_variation_names[1+flam3_nvariations] = {
"mobius",
"asteria",
"bcollide",
+ "bmod",
0
};
@@ -1861,13 +1862,40 @@ static double2 var99_asteria (const double2 in, const flam3_iter_helper * const
}
}
+/* convert x/y to bipolar coordinate system tau/sigma
+ */
+static double2 toBipolar (const double2 in) {
+ const double sigmasquare = square (in[1]);
+ return (double2) {
+ 0.5 * (log(square (in[0] + 1.0) + sigmasquare) - log(square (in[0] - 1.0) + sigmasquare)),
+ M_PI - atan2(in[1], in[0] + 1.0) - atan2(in[1], 1.0 - in[0])
+ };
+}
+
+/* Convert tau/sigma to x/y
+ */
+static double2 fromBipolar (const double2 in) {
+ const double tau = in[0], sigma = in[1];
+ const double sinht = sinh(tau);
+ const double cosht = cosh(tau);
+ double sins, coss;
+ sincos (sigma, &sins, &coss);
+ const double temp = cosht - coss;
+ if (temp == 0) {
+ return (double2) { HUGE_VAL, HUGE_VAL };
+ } else {
+ return (double2) { sinht / temp, sins / temp };
+ }
+}
+
static double2 var100_bcollide (const double2 in, const flam3_iter_helper * const f, double weight) {
/* from jwildfire: bCollide by Michael Faber,
* http://michaelfaber.deviantart.com/art/bSeries-320574477 */
const flam3_xform *xf = f->xform;
- const double tau = 0.5 * (log(square (in[0] + 1.0) + square (in[1])) - log(square (in[0] - 1.0) + square (in[1])));
- double sigma = M_PI - atan2(in[1], in[0] + 1.0) - atan2(in[1], 1.0 - in[0]);
+ const double2 bipolar = toBipolar (in);
+ const double tau = bipolar[0];
+ double sigma = bipolar[1];
const int alt = (int) (sigma * xf->bcollide_bCn_pi);
if (alt % 2 == 0) {
@@ -1875,12 +1903,26 @@ static double2 var100_bcollide (const double2 in, const flam3_iter_helper * cons
} else {
sigma = alt * xf->bcollide_pi_bCn + fmod(sigma - xf->bcollide_bCa_bCn, xf->bcollide_pi_bCn);
}
- const double sinht = sinh(tau);
- const double cosht = cosh(tau);
- double sins, coss;
- sincos (sigma, &sins, &coss);
- const double temp = cosht - coss;
- return (double2) { weight * sinht / temp, weight * sins / temp };
+ const double2 out = fromBipolar ((double2) { tau, sigma });
+ return weight * out;
+}
+
+static double2 var101_bmod (const double2 in, const flam3_iter_helper * const f, double weight) {
+ /* from jwildfire: bMod by Michael Faber,
+ * http://michaelfaber.deviantart.com/art/bSeries-320574477 */
+ const flam3_xform *xf = f->xform;
+
+ const double2 bipolar = toBipolar (in);
+ double tau = bipolar[0];
+ double sigma = bipolar[1];
+ const double radius = xf->bmod_radius;
+
+ if (tau < radius && -tau < radius) {
+ tau = fmod(tau + radius + xf->bmod_distance * radius, 2.0 * radius) - radius;
+ }
+
+ const double2 out = fromBipolar ((double2) { tau, sigma });
+ return weight * out;
}
/* Precalc functions */
@@ -2335,6 +2377,8 @@ int apply_xform(const flam3_xform * const xf, const double4 p, double4 *q_ret,
accum += var99_asteria (t, &f, weight); break;
case VAR_BCOLLIDE:
accum += var100_bcollide (t, &f, weight); break;
+ case VAR_BMOD:
+ accum += var101_bmod (t, &f, weight); break;
}
}