| 1 |
module ff; |
|---|
| 2 |
|
|---|
| 3 |
import qd, tools.base, std.math, dglut.vector; |
|---|
| 4 |
alias PI Ï; |
|---|
| 5 |
|
|---|
| 6 |
alias Vector!(float, 6) vec6f; |
|---|
| 7 |
alias Vector!(float, 8) vec8f; |
|---|
| 8 |
|
|---|
| 9 |
float int_pow(float a, int i) { |
|---|
| 10 |
float res = 1f; |
|---|
| 11 |
while (i--) res *= a; |
|---|
| 12 |
return res; |
|---|
| 13 |
} |
|---|
| 14 |
|
|---|
| 15 |
float ps(float f) { return f; } |
|---|
| 16 |
|
|---|
| 17 |
vec4f calcΞ(ref vec4f x, ref vec4f y) { |
|---|
| 18 |
vec4f Ξ = void; |
|---|
| 19 |
// yes it's the right way around. Srsly, look it up in the PDF. |
|---|
| 20 |
for (int i = 0; i < 4; ++i) Ξ.field[i] = atan2(x[i], y[i]); |
|---|
| 21 |
return Ξ; |
|---|
| 22 |
} |
|---|
| 23 |
|
|---|
| 24 |
void linear_0(ref vec4f x, ref vec4f y) { } |
|---|
| 25 |
void sinusoidal_1(ref vec4f x, ref vec4f y) { x = x.sin(); y = y.sin(); } |
|---|
| 26 |
void spherical_2(ref vec4f x, ref vec4f y) { |
|---|
| 27 |
auto sum = x * x + y * y; |
|---|
| 28 |
x /= sum; y /= sum; |
|---|
| 29 |
} |
|---|
| 30 |
void swirl_3(ref vec4f x, ref vec4f y) { |
|---|
| 31 |
auto sum = x * x + y * y; |
|---|
| 32 |
auto sins = sum.sin(), coss = sum.cos(); |
|---|
| 33 |
auto xres = x * sins - y * coss, yres = x * coss + y * sins; |
|---|
| 34 |
x = xres; y = yres; |
|---|
| 35 |
} |
|---|
| 36 |
void horseshoe_4(ref vec4f x, ref vec4f y) { |
|---|
| 37 |
auto xsq = x * x, ysq = y * y, sum = xsq + ysq, r = sum.sqrt(); |
|---|
| 38 |
auto nx = (xsq - ysq), ny = 2 * x * y; |
|---|
| 39 |
x = nx; y = ny; |
|---|
| 40 |
x /= r; y /= r; |
|---|
| 41 |
} |
|---|
| 42 |
void polar_5(ref vec4f x, ref vec4f y) { |
|---|
| 43 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 44 |
x = Ξ / Ï; y = r - vec4f(1); |
|---|
| 45 |
} |
|---|
| 46 |
void handkerchief_6(ref vec4f x, ref vec4f y) { |
|---|
| 47 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(), Ξpr = Ξ + r, Ξmr = Ξ - r; |
|---|
| 48 |
x = Ξpr.sin() * r; y = Ξmr.cos() * r; |
|---|
| 49 |
} |
|---|
| 50 |
void heart_7(ref vec4f x, ref vec4f y) { |
|---|
| 51 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(), Ξr = Ξ * r; |
|---|
| 52 |
x = Ξr.sin() * r; y = -Ξr.cos() * r; |
|---|
| 53 |
} |
|---|
| 54 |
void disc_8(ref vec4f x, ref vec4f y) { |
|---|
| 55 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 56 |
auto Ïr = r * Ï, Ξ_Ï = Ξ / Ï; |
|---|
| 57 |
x = Ïr.sin() * Ξ_Ï; y = Ïr.cos() * Ξ_Ï; |
|---|
| 58 |
} |
|---|
| 59 |
void spiral_9(ref vec4f x, ref vec4f y) { |
|---|
| 60 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 61 |
x = (Ξ.cos() - r.sin()) / r; y = (Ξ.sin() - r.cos()) / r; |
|---|
| 62 |
} |
|---|
| 63 |
void hyperbolic_10(ref vec4f x, ref vec4f y) { |
|---|
| 64 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 65 |
x = Ξ.sin() / r; y = Ξ.cos() * r; |
|---|
| 66 |
} |
|---|
| 67 |
void diamond_11(ref vec4f x, ref vec4f y) { |
|---|
| 68 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 69 |
x = Ξ.sin() * r.cos(); y = Ξ.cos() * r.sin(); |
|---|
| 70 |
} |
|---|
| 71 |
void ex_12(ref vec4f x, ref vec4f y) { |
|---|
| 72 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 73 |
x = (Ξ + r).sin(); y = (Ξ - r).cos(); |
|---|
| 74 |
x *= x*x*r; y *= y*y*r; // ^3 * r |
|---|
| 75 |
} |
|---|
| 76 |
Vector!(byte, 4) Ωs_1, Ωs_2 = void; // intentionally not threadsafe - it's supposed to be random after all |
|---|
| 77 |
// don't worry - enough randomness is created in the point selection. |
|---|
| 78 |
// even if there's threading-related errors, at thousands of hits per pixel |
|---|
| 79 |
// they're completely irrelevant. |
|---|
| 80 |
// this is art, not maths. ;) |
|---|
| 81 |
static this() { |
|---|
| 82 |
foreach (ref Ω; Ωs_1.field) if (Ω >= 0) Ω = 1; else Ω = -1; |
|---|
| 83 |
foreach (ref Ω; Ωs_2.field) if (Ω >= 0) Ω = 1; else Ω = -1; |
|---|
| 84 |
} |
|---|
| 85 |
void julia_13(ref vec4f x, ref vec4f y) { |
|---|
| 86 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 87 |
auto rsqt = r.sqrt(), Ξ_2 = Ξ / 2f; |
|---|
| 88 |
x = Ξ_2.cos() * Ωs_1 * rsqt; |
|---|
| 89 |
y = Ξ_2.sin() * Ωs_2 * rsqt; |
|---|
| 90 |
Ωs_1 *= -1; Ωs_2 *= -1; // "so-called randomness" |
|---|
| 91 |
} |
|---|
| 92 |
void bent_14(ref vec4f x, ref vec4f y) { |
|---|
| 93 |
auto xs = (-x.sgn() + 3) / 2, ys = (-y.sgn() + 3) / 2; // 1/-1 -> -1/1 -> 2/4 -> 1/2 |
|---|
| 94 |
x *= xs; y /= ys; |
|---|
| 95 |
} |
|---|
| 96 |
void waves_15(ref vec4f x, ref vec4f y, float b, float c, float e, float f) { |
|---|
| 97 |
auto |
|---|
| 98 |
nx = x + b * (y / (c*c)).sin(), |
|---|
| 99 |
ny = y + e * (x / (f*f)).sin(); |
|---|
| 100 |
x = nx; y = ny; |
|---|
| 101 |
} |
|---|
| 102 |
void fisheye_16(ref vec4f x, ref vec4f y) { |
|---|
| 103 |
auto r = (x * x + y * y).sqrt(); |
|---|
| 104 |
auto factor = 2f / (r + 1f); |
|---|
| 105 |
auto nx = y * factor, ny = x * factor; |
|---|
| 106 |
x = nx; y = ny; |
|---|
| 107 |
} |
|---|
| 108 |
void popcorn_17(ref vec4f x, ref vec4f y, float c, float f) { |
|---|
| 109 |
x = (x*3).tan().sin() * c + x; y = (y*3).tan().sin() * f + y; |
|---|
| 110 |
} |
|---|
| 111 |
void exponential_18(ref vec4f x, ref vec4f y) { |
|---|
| 112 |
auto ex = (x-1).exp(); |
|---|
| 113 |
x *= Ï; y *= Ï; |
|---|
| 114 |
x = x.cos(); y = y.sin(); |
|---|
| 115 |
x *= ex; y *= ex; |
|---|
| 116 |
} |
|---|
| 117 |
void power_19(ref vec4f x, ref vec4f y) { |
|---|
| 118 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 119 |
auto r_sinΞ = y = Ξ.sin(); |
|---|
| 120 |
for (int i = 0; i < 4; ++i) r_sinΞ.field[i] = pow(r.field[i], r_sinΞ.field[i]); |
|---|
| 121 |
x = Ξ.cos() * r_sinΞ; y *= r_sinΞ; |
|---|
| 122 |
} |
|---|
| 123 |
void cosine_20(ref vec4f x, ref vec4f y) { |
|---|
| 124 |
vec4f ch = void, sh = void; |
|---|
| 125 |
for (int i = 0; i < 4; ++i) { |
|---|
| 126 |
ch.field[i] = cosh(y.field[i]); |
|---|
| 127 |
sh.field[i] = sinh(y.field[i]); |
|---|
| 128 |
} |
|---|
| 129 |
auto cp = Ï * x; |
|---|
| 130 |
x = cp.cos()*ch; y = -cp.sin()*sh; |
|---|
| 131 |
} |
|---|
| 132 |
void rings_21(ref vec4f x, ref vec4f y, float c) { |
|---|
| 133 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 134 |
auto csq = c*c; |
|---|
| 135 |
auto n = r + csq, o = 2f*csq; |
|---|
| 136 |
for (int i = 0; i < 4; ++i) if (n.field[i] > o) n.field[i] -= cast(int)(n.field[i] / o) * o; |
|---|
| 137 |
n -= csq; |
|---|
| 138 |
n += r*(1f-csq); |
|---|
| 139 |
x = Ξ.cos() * n; y = Ξ.sin() * n; |
|---|
| 140 |
} |
|---|
| 141 |
void fan_22(ref vec4f x, ref vec4f y, float c, float f) { |
|---|
| 142 |
auto t = Ï * c * c; |
|---|
| 143 |
auto Ξ = calcΞ(x, y), r = (x * x + y * y).sqrt(); |
|---|
| 144 |
auto test = Ξ + f; |
|---|
| 145 |
for (int i = 0; i < 4; ++i) while (test.field[i] > t) test.field[i] -= t; |
|---|
| 146 |
vec4f v = void; |
|---|
| 147 |
auto t_half = t/2f; |
|---|
| 148 |
for (int i = 0; i < 4; ++i) |
|---|
| 149 |
if (test.field[i] > t_half) v.field[i] = Ξ.field[i] - t_half; |
|---|
| 150 |
else v.field[i] = Ξ.field[i] + t_half; |
|---|
| 151 |
x = v.cos() * r; y = v.sin()*r; |
|---|
| 152 |
} |
|---|
| 153 |
void eyefish_27(ref vec4f x, ref vec4f y) { |
|---|
| 154 |
auto r = (x * x + y * y).sqrt(); |
|---|
| 155 |
auto factor = 2f / (r + 1f); |
|---|
| 156 |
x *= factor; y *= factor; |
|---|
| 157 |
} |
|---|
| 158 |
void bubble_28(ref vec4f x, ref vec4f y) { |
|---|
| 159 |
auto r = (x * x + y * y).sqrt(); |
|---|
| 160 |
auto factor = 4f / (r*r + 4f); |
|---|
| 161 |
x *= factor; y *= factor; |
|---|
| 162 |
} |
|---|
| 163 |
void cylinder_29(ref vec4f x, ref vec4f y) { x = x.sin(); } |
|---|
| 164 |
void tangent_42(ref vec4f x, ref vec4f y) { |
|---|
| 165 |
auto nx = x.sin() / y.cos(); |
|---|
| 166 |
y = y.sin() / x.cos(); x=nx; |
|---|
| 167 |
} |
|---|
| 168 |
void cross_48(ref vec4f x, ref vec4f y) { |
|---|
| 169 |
auto temp = x*x + y*y; |
|---|
| 170 |
auto factor = (1f/(temp*temp)).sqrt(); |
|---|
| 171 |
x *= factor; y *= factor; |
|---|
| 172 |
} |
|---|
| 173 |
|
|---|
| 174 |
const num_functions = 28; |
|---|
| 175 |
void fun(int which, ref vec4f x, ref vec4f y, ref vec6f coeffs) { |
|---|
| 176 |
switch (which) { |
|---|
| 177 |
case 0: linear_0(x, y); break; |
|---|
| 178 |
case 1: sinusoidal_1(x, y); break; |
|---|
| 179 |
case 2: spherical_2(x, y); break; |
|---|
| 180 |
case 3: swirl_3(x, y); break; |
|---|
| 181 |
case 4: horseshoe_4(x, y); break; |
|---|
| 182 |
case 5: polar_5(x, y); break; |
|---|
| 183 |
case 6: handkerchief_6(x, y); break; |
|---|
| 184 |
case 7: heart_7(x, y); break; |
|---|
| 185 |
case 8: disc_8(x, y); break; |
|---|
| 186 |
case 9: spiral_9(x, y); break; |
|---|
| 187 |
case 10: hyperbolic_10(x, y); break; |
|---|
| 188 |
case 11: diamond_11(x, y); break; |
|---|
| 189 |
case 12: ex_12(x, y); break; |
|---|
| 190 |
case 13: julia_13(x, y); break; |
|---|
| 191 |
case 14: bent_14(x, y); break; |
|---|
| 192 |
case 15: waves_15(x, y, coeffs.tuple[1..3], coeffs.tuple[4..6]); break; |
|---|
| 193 |
case 16: fisheye_16(x, y); break; |
|---|
| 194 |
case 17: popcorn_17(x, y, coeffs.tuple[2], coeffs.tuple[5]); break; |
|---|
| 195 |
case 18: exponential_18(x, y); break; |
|---|
| 196 |
case 19: power_19(x, y); break; |
|---|
| 197 |
case 20: cosine_20(x, y); break; |
|---|
| 198 |
case 21: rings_21(x, y, coeffs.tuple[2]); break; |
|---|
| 199 |
case 22: fan_22(x, y, coeffs.tuple[2], coeffs.tuple[5]); break; |
|---|
| 200 |
case 23: eyefish_27(x, y); break; |
|---|
| 201 |
case 24: bubble_28(x, y); break; |
|---|
| 202 |
case 25: cylinder_29(x, y); break; |
|---|
| 203 |
case 26: tangent_42(x, y); break; |
|---|
| 204 |
case 27: cross_48(x, y); break; |
|---|
| 205 |
default: fail; |
|---|
| 206 |
} |
|---|
| 207 |
} |
|---|
| 208 |
|
|---|
| 209 |
import tools.ca_rng; |
|---|
| 210 |
struct variation { |
|---|
| 211 |
vec6f pre; |
|---|
| 212 |
vec6f post; |
|---|
| 213 |
vec3f color; |
|---|
| 214 |
ushort fn; |
|---|
| 215 |
void exec(ref vec4f x, ref vec4f y) { |
|---|
| 216 |
transform(x, y, pre); |
|---|
| 217 |
fun(fn, x, y, pre); |
|---|
| 218 |
transform(x, y, post); |
|---|
| 219 |
} |
|---|
| 220 |
static { |
|---|
| 221 |
void transform(ref vec4f x, ref vec4f y, vec6f coeff) { |
|---|
| 222 |
vec4f nx = x * coeff.field[0] + y * coeff.field[1] + coeff.field[2]; |
|---|
| 223 |
vec4f ny = x * coeff.field[3] + y * coeff.field[4] + coeff.field[5]; |
|---|
| 224 |
x = nx; y = ny; |
|---|
| 225 |
} |
|---|
| 226 |
void random_matrix(ref vec6f v) { |
|---|
| 227 |
auto a = vec2f(0), b = a; |
|---|
| 228 |
a.x = 1; b.y = 1; // identity matrix |
|---|
| 229 |
a.rotate(int_pow(randf(), 3)*360f-180f); b.rotate(int_pow(randf(), 3)*360f-180f); |
|---|
| 230 |
a *= sqrt(randf()*2f); b *= sqrt(randf()*2f); |
|---|
| 231 |
v.field[0..2] = a.field; v.field[2] = randf-0.5f; |
|---|
| 232 |
v.field[3..5] = b.field; v.field[5] = randf-0.5f; |
|---|
| 233 |
} |
|---|
| 234 |
variation rand() { |
|---|
| 235 |
variation res; |
|---|
| 236 |
random_matrix(res.pre); |
|---|
| 237 |
random_matrix(res.post); |
|---|
| 238 |
res.pre *= 2f; res.post /= 2f; |
|---|
| 239 |
auto r = .rand; |
|---|
| 240 |
res.fn = r % num_functions; |
|---|
| 241 |
logln("fn: ", res.fn, ", Pre: ", res.pre, ", Post: ", res.post); |
|---|
| 242 |
res.color = vec3f.rand() / 2f + 0.5f; |
|---|
| 243 |
with (res.color) { |
|---|
| 244 |
auto h = hsv(rgb(r*255f, g*255f, b*255f)); |
|---|
| 245 |
//h.s = 128 + h.s/2; |
|---|
| 246 |
h.v = 128 + h.v/2; |
|---|
| 247 |
auto re = rgb(h); |
|---|
| 248 |
r = re.r/255f; g = re.g/255f; b = re.b/255f; |
|---|
| 249 |
} |
|---|
| 250 |
return res; |
|---|
| 251 |
} |
|---|
| 252 |
} |
|---|
| 253 |
} |
|---|
| 254 |
|
|---|
| 255 |
import tools.array2d; |
|---|
| 256 |
class buffer { |
|---|
| 257 |
array2d!(vec3f) sum; |
|---|
| 258 |
array2d!(long) count; |
|---|
| 259 |
vec6f final_transform; |
|---|
| 260 |
this(int w, int h) { |
|---|
| 261 |
sum = typeof(sum)(w, h); count = typeof(count)(w, h); |
|---|
| 262 |
sum = vec3f(0); |
|---|
| 263 |
final_transform = vec6f.rand() * 0.4f; |
|---|
| 264 |
final_transform.field[2] = final_transform.field[5] = 0f; |
|---|
| 265 |
final_transform.field[0] += 1; final_transform.field[4] += 1; // unit |
|---|
| 266 |
} |
|---|
| 267 |
ulong total_sum; |
|---|
| 268 |
invariant { assert (sum.w == count.w); assert (sum.h == count.h); } |
|---|
| 269 |
void increase (float px, float py, vec3f c) { |
|---|
| 270 |
int nx, ny; |
|---|
| 271 |
with (final_transform) { |
|---|
| 272 |
nx = cast(int) (px * field[0] + py * field[1] + field[2]); |
|---|
| 273 |
ny = cast(int) (px * field[3] + py * field[4] + field[5]); |
|---|
| 274 |
} |
|---|
| 275 |
if (nx<0 || ny<0 || nx!<sum.w || ny!<sum.h) return; |
|---|
| 276 |
sum[nx, ny] = sum[nx, ny] + c; |
|---|
| 277 |
count[nx, ny] = count[nx, ny] + 1; |
|---|
| 278 |
++total_sum; |
|---|
| 279 |
} |
|---|
| 280 |
void render(void delegate(int, int, rgb) callback) { |
|---|
| 281 |
const γ = 2.2; |
|---|
| 282 |
for (int y = 0; y < sum.h; ++y) { |
|---|
| 283 |
// yes, do do this every line |
|---|
| 284 |
auto scale_factor = (1.0 * total_sum) / (sum.w * sum.h); |
|---|
| 285 |
for (int x = 0; x < sum.w; ++x) { |
|---|
| 286 |
real c = count[x, y], f = c / ((scale_factor+1)) + 1; |
|---|
| 287 |
f = log(f); |
|---|
| 288 |
f = pow(f, 1.0/γ); // gamma |
|---|
| 289 |
vec3f cc = sum[x, y] / (c+1) * vec3f(256) * f; |
|---|
| 290 |
foreach (ref entry; cc.field) if (entry>255) entry=255; |
|---|
| 291 |
callback(x, y, rgb(cc.tuple)); |
|---|
| 292 |
} |
|---|
| 293 |
} |
|---|
| 294 |
} |
|---|
| 295 |
void draw() { render((int x, int y, rgb c) { |
|---|
| 296 |
pset(x, y, c); |
|---|
| 297 |
if (!x) { logln(y); flip; events; } |
|---|
| 298 |
}); |
|---|
| 299 |
} |
|---|
| 300 |
import std.stream, std.file; |
|---|
| 301 |
void writePPM(string file) { |
|---|
| 302 |
auto temp = file ~ "_temp"; |
|---|
| 303 |
if (temp.exists()) temp.remove(); |
|---|
| 304 |
with (new File(temp, FileMode.Out)) { |
|---|
| 305 |
ubyte[16384] buffer; |
|---|
| 306 |
size_t cur = 0; |
|---|
| 307 |
void flush() { |
|---|
| 308 |
write(buffer[0 .. cur]); |
|---|
| 309 |
cur = 0; |
|---|
| 310 |
} |
|---|
| 311 |
void dump(rgb c) { |
|---|
| 312 |
buffer[cur++] = c.r; buffer[cur++] = c.g; buffer[cur++] = c.b; |
|---|
| 313 |
if (cur >= buffer.length - 3) flush; |
|---|
| 314 |
} |
|---|
| 315 |
writefln("P6 ", sum.w, " ", sum.h, " ", 255); |
|---|
| 316 |
render((int x, int y, rgb c) { |
|---|
| 317 |
if (!x && (y%16 == 0)) { |
|---|
| 318 |
logln(y, " - ", total_sum); |
|---|
| 319 |
//events; |
|---|
| 320 |
} |
|---|
| 321 |
dump(c); |
|---|
| 322 |
}); |
|---|
| 323 |
flush; |
|---|
| 324 |
close(); |
|---|
| 325 |
} |
|---|
| 326 |
if (file.exists()) file.remove(); |
|---|
| 327 |
temp.rename(file); |
|---|
| 328 |
} |
|---|
| 329 |
} |
|---|
| 330 |
|
|---|
| 331 |
vec6f delegate(float) vecbezier(vec6f[] fields) { |
|---|
| 332 |
auto values = new float[][6]; |
|---|
| 333 |
foreach (vec; fields) foreach (i, v; vec.field) values[i] ~= v; |
|---|
| 334 |
auto bzrs = values /map/ &multibezier; |
|---|
| 335 |
return (typeof(bzrs) bs, float x) { |
|---|
| 336 |
vec6f res = void; |
|---|
| 337 |
foreach (i, ref field; res.field) field = bs[i](x); |
|---|
| 338 |
return res; |
|---|
| 339 |
} /fix/ bzrs; |
|---|
| 340 |
} |
|---|
| 341 |
|
|---|
| 342 |
import std.string, std.stdio, std.date, tools.threadpool, tools.threads, tools.functional, tools.log: logln; |
|---|
| 343 |
import splines; |
|---|
| 344 |
void main(string[] args) { |
|---|
| 345 |
auto start = getUTCtime(), seedval = cast(ushort) start; |
|---|
| 346 |
if (args.length > 1) seedval = atoi(args[1]); |
|---|
| 347 |
int[] subseeds; auto transition = 0.0; |
|---|
| 348 |
if (args.length > 2) subseeds = args[2].split(",") /map/ (string s) { return cast(int) atoi(s); }; |
|---|
| 349 |
if (args.length > 4) transition = atoi(args[4]) * 1f / atoi(args[3]); |
|---|
| 350 |
string file; |
|---|
| 351 |
if (args.length > 5) file = args[5]; |
|---|
| 352 |
logln("Seed: ", seedval); |
|---|
| 353 |
seed(seedval); |
|---|
| 354 |
vec_randf = &randf; |
|---|
| 355 |
int width = 8192, height = 8192; |
|---|
| 356 |
//screen(width, height, 0, false); |
|---|
| 357 |
|
|---|
| 358 |
auto tp = new Threadpool(5); |
|---|
| 359 |
|
|---|
| 360 |
auto buf = new buffer(width, height); |
|---|
| 361 |
float[32] xs, ys; // (<= 256), so we can use one rand call to determine all four points |
|---|
| 362 |
vec3f[32] colors; |
|---|
| 363 |
for (int i = 0; i < 32; ++i) colors[i] = vec3f(xs [i] = ys [i] = 0f); |
|---|
| 364 |
variation[] vars; |
|---|
| 365 |
for (int i = 0; i < 3; ++i) vars ~= variation.rand(); |
|---|
| 366 |
vec6f delegate(float)[] var_pre_generators, var_post_generators; |
|---|
| 367 |
if (subseeds.length) { |
|---|
| 368 |
vec6f[][] targets_pre, targets_post; |
|---|
| 369 |
targets_pre.length = targets_post.length = vars.length; |
|---|
| 370 |
foreach (subseed; subseeds) { |
|---|
| 371 |
if (!subseed) { |
|---|
| 372 |
foreach (i, var; vars) { |
|---|
| 373 |
targets_pre[i] ~= var.pre; |
|---|
| 374 |
targets_post[i] ~= var.post; |
|---|
| 375 |
} |
|---|
| 376 |
continue; |
|---|
| 377 |
} |
|---|
| 378 |
seed(subseed); |
|---|
| 379 |
foreach (i, var; vars) { |
|---|
| 380 |
vec6f my_pre, my_post; |
|---|
| 381 |
variation.random_matrix(my_pre); variation.random_matrix(my_post); |
|---|
| 382 |
targets_pre[i] ~= my_pre; targets_post[i] ~= my_post; |
|---|
| 383 |
} |
|---|
| 384 |
} |
|---|
| 385 |
logln("Building generators"); |
|---|
| 386 |
foreach (i, var; vars) { |
|---|
| 387 |
var_pre_generators ~= vecbezier(targets_pre[i]); |
|---|
| 388 |
var_post_generators ~= vecbezier(targets_post[i]); |
|---|
| 389 |
} |
|---|
| 390 |
logln("Transitioning"); |
|---|
| 391 |
foreach (i, ref var; vars) { |
|---|
| 392 |
var.pre = var_pre_generators[i](transition); |
|---|
| 393 |
var.post = var_post_generators[i](transition); |
|---|
| 394 |
} |
|---|
| 395 |
} |
|---|
| 396 |
|
|---|
| 397 |
flip = false; |
|---|
| 398 |
TLS!(long) count; New(count, { return new long; }); |
|---|
| 399 |
long total_count() { |
|---|
| 400 |
long res; |
|---|
| 401 |
count.each((long l) { res += l; }); |
|---|
| 402 |
return res; |
|---|
| 403 |
} |
|---|
| 404 |
TLS!(Generator) gen; New(gen, { return new Generator(23); }); |
|---|
| 405 |
logln("Setup done"); |
|---|
| 406 |
void iterate(ref int iter) { |
|---|
| 407 |
union IntUbyteConv { int i; ubyte[4] bf; } |
|---|
| 408 |
IntUbyteConv cv = void; cv.i = gen()(); |
|---|
| 409 |
foreach (ref p; cv.bf) p %= xs.length; |
|---|
| 410 |
vec4f cxs = void, cys = void; |
|---|
| 411 |
foreach (k, bogus; cxs.tuple) { |
|---|
| 412 |
cxs.tuple[k] = xs[cv.bf[k]]; |
|---|
| 413 |
cys.tuple[k] = ys[cv.bf[k]]; |
|---|
| 414 |
} |
|---|
| 415 |
scope(exit) { |
|---|
| 416 |
iter++; |
|---|
| 417 |
if (iter == vars.length) iter = 0; |
|---|
| 418 |
} |
|---|
| 419 |
|
|---|
| 420 |
vars[iter].exec(cxs, cys); |
|---|
| 421 |
foreach (k, p; cv.bf) { |
|---|
| 422 |
xs[p] = cxs[k]; ys[p] = cys[k]; // write-back |
|---|
| 423 |
auto |
|---|
| 424 |
x = xs[p] * (width/2) + (width/2), |
|---|
| 425 |
y = ys[p] * (height/2) + (height/2); |
|---|
| 426 |
colors[p] = (colors[p] + vars[iter].color) * 0.5; |
|---|
| 427 |
buf.increase(x, y, colors[p]); |
|---|
| 428 |
} |
|---|
| 429 |
count() += 4; // four points at a time |
|---|
| 430 |
} |
|---|
| 431 |
MessageMultiChannel!(bool, false, true) stop; New(stop); |
|---|
| 432 |
foreach (bogus; tp.threads) tp.addTask({ |
|---|
| 433 |
int iter; |
|---|
| 434 |
while (true) { |
|---|
| 435 |
iterate(iter); |
|---|
| 436 |
if (stop.active) { stop.get; return; } |
|---|
| 437 |
} |
|---|
| 438 |
}); |
|---|
| 439 |
auto last_count = total_count(); |
|---|
| 440 |
bool halted; |
|---|
| 441 |
void halt() { if (halted) return; foreach (bogus; tp.threads) stop.put(true); halted = true; } |
|---|
| 442 |
scope(exit) halt; |
|---|
| 443 |
long last_dumped = 0; |
|---|
| 444 |
while (true) { |
|---|
| 445 |
//logln("Drawing"); |
|---|
| 446 |
buf.draw; |
|---|
| 447 |
float t = (getUTCtime() - start) / 1000f; |
|---|
| 448 |
writefln(total_count, " / ", t, "s -> ", total_count / t, " iter/s"); |
|---|
| 449 |
/*if (total_count() > 1024*1024*2) { |
|---|
| 450 |
halt; |
|---|
| 451 |
buf.draw; |
|---|
| 452 |
if (args.length > 4) { |
|---|
| 453 |
string file_nr = args[4]; |
|---|
| 454 |
while (file_nr.length < 4) file_nr = "0"~file_nr; |
|---|
| 455 |
file ~= file_nr~".bmp"; |
|---|
| 456 |
} |
|---|
| 457 |
if (file) SDL_SaveBMP(display.target, file); |
|---|
| 458 |
break; |
|---|
| 459 |
}*/ |
|---|
| 460 |
yield(); |
|---|
| 461 |
} |
|---|
| 462 |
} |
|---|