H_Curve = glsl`
float modI(float a, float b) {
float m=a-floor((a+0.5)/b)*b;
return floor(m+0.5);
}
${rotation_logic.value}
${H_Position.value}
// Two necessary functions.
vec2 H_Curve(float raw_ix) {
// Start near the origin with an identity transform;
vec2 xy = vec2(0., 0.);
// Numbers greater than zero are
bool negative = raw_ix < -.5;
float sign = 1.;
float abs_ix = abs(raw_ix);
if (negative) {
sign = -1.;
abs_ix -= 1.; // Waste a cycle and do zero from both directions.
// Could cause some problems?
}
mat2 rotation = mat2(sign, 0.,
0., sign );
float MAX_ITER = 14.;
// Is the point even or odd? Used to position the up or down direction.
float jag = modI(abs_ix, 2.);
float ix = floor(abs_ix/ 2.0 + 0.1);
// Where we are in the L shape (0, 1, 2, 3);
float a;
for (float i = 16.; i > -.5; i -= 1.) {
float rank_in_layer = floor((ix + .01) / (pow(4., i)));
a = modI(rank_in_layer, 4.);
// This will change a in place.
if (rotation[0][0] * rotation[1][1] * sign < 0.) {
a = 3. - a;
}
vec2 p = H_position(a, rotation);
rotation = rotation * rotations(a);
xy += (p) * pow(2., i - 1.);
}
/* Position the last element */
// No clue what's going on here. The rotation
// functions look like they're a proxy for some kind of logic
// gate or something, but I got it nearly by trial and error.
float last_direction = rotation[1][1];
float is_rotated = rotation[1][1] * rotation[0][0];
if (is_rotated > 0.) {
last_direction *= -1.;
}
if (jag < .5) {last_direction *= -1.;}
xy += vec2(0., .25 * last_direction * sign);
// Some magic involving 2 ** 15 and 2**16 to reshift
// points somewhere close to the origin.
// If not using 16 as the highest point in the loop, this will have to change, too.
float y_shift = 0.;
float x_shift = 0.;
if (negative) {
xy += vec2(pow(2., 16.) + pow(2., 15.) + x_shift, -pow(2., 16.) + y_shift);
} else {
xy += vec2(pow(2., 15.) + x_shift, -pow(2., 16.));
}
return xy;
}
`