7 #if !defined(_USE_MATH_DEFINES)
8 #define _USE_MATH_DEFINES
73 "float turbulence(vector v,int octaves=6,float lacunarity=2,float gain=.5)\nAbsolute value of each noise term is "
74 "taken. This gives billowy appearance");
76 "color cturbulence(vector v,int octaves=6,float lacunarity=2,float gain=.5)\nAbsolute value of each noise term is "
77 "taken. This gives billowy appearance");
79 "vector vturbulence(vector v,int octaves=6,float lacunarity=2,float gain=.5)\nAbsolute value of each noise term is "
80 "taken. This gives billowy appearance");
82 double compress(
double x,
double lo,
double hi)
84 return (hi - lo) * x + lo;
88 double expand(
double x,
double lo,
double hi)
91 return x < lo ? 0 : 1;
92 return (x - lo) / (hi - lo);
96 double fit(
double x,
double a1,
double b1,
double a2,
double b2)
98 return (x * (b2 - a2) - a1 * b2 + b1 * a2) / (b1 - a1);
104 return pow(x, 1 / g);
108 double bias(
double x,
double b)
110 static double C = 1 / log(0.5);
111 return pow(x, log(b) * C);
114 "float bias(float x, float g)\nVariation of gamma where values less than 0.5 pull the curve down\nand values "
115 "greater than 0.5 pull the curve up\npow(x,log(b)/log(0.5))");
120 return 0.5 *
bias(1 - c, 2 * x);
122 return 1 - 0.5 *
bias(1 - c, 2 - 2 * x);
125 "float contrast(float x, float c)\nAdjust the contrast. For c from 0 to 0.5, the contrast is decreased. "
126 "For c > 0.5, the contrast is increased.");
130 return x < a ? 0.0 : 1.0;
137 return x < a ? 0 : (x > b ? 1 : (x - a) / (b - a));
139 return 1 - (x < b ? 0 : (x > a ? 1 : (x - b) / (a - b)));
144 "float linearstep(float x, float a, float b)\n if x < a then 0, if x > b then 1, and\nx transitions linearly "
145 "when a < x < b");
154 x = (x - a) / (b - a);
160 x = 1 - (x - b) / (a - b);
163 return x * x * (3 - 2 * x);
166 "float smoothstep(float x,float a,float b)\n if x < a then 0, if x > b then 1, and\nx transitions smoothly "
167 "(cubic) when a < x < b");
176 x = 1 - (x - a) / (b - a);
182 x = (x - b) / (a - b);
185 return pow(2, -8 * x * x);
188 "float gasussstep(float x,float a,float b)\n if x < a then 0, if x > b then 1, and\nx transitions smoothly "
189 "(exponentially) when a < x < b");
191 double remap(
double x,
double source,
double range,
double falloff,
double interp)
194 falloff = fabs(falloff);
197 return fabs(x - source) < range;
209 switch (
int(interp)) {
219 "remap(float x, float source, float range, float falloff, float interp)\n"
220 "General remapping function.\n"
221 "When x is within +/- <i>range</i> of source, the result is one.\n"
222 "The result falls to zero beyond that range over <i>falloff</i> distance.\n"
223 "The falloff shape is controlled by <i>interp</i>. Numeric values\n"
224 "or named constants may be used:\n"
225 " int <b>linear</b> = 0\n"
226 " int <b>smooth</b> = 1\n"
227 " int <b>gaussian</b> = 2\n");
229 double mix(
double x,
double y,
double alpha)
231 return x * (1 - alpha) + y * alpha;
238 hsl[0] += h * (1.0 / 360);
248 double h = args[1][0];
249 double s = args[2][0];
250 double i = args[3][0];
253 double m = args[4][0];
261 "color hsi(color x, float h, float s, float i, float map=1)\n"
262 "The hsi function shifts the hue by h\n"
263 "(in degrees) and scales the saturation and intensity by s and i\n"
264 "respectively. A map may be supplied which will control the shift\n"
265 "- the full shift will happen when the map is one and no shift will\n"
266 "happen when the map is zero. The shift will be scaled back for\n"
267 "values between zero and one.");
274 double h = args[1][0];
275 double s = args[2][0];
276 double i = args[3][0];
279 double m = args[4][0];
286 falloff = args[5][0];
290 m = -
remap(-m, 1, 0, falloff, interp);
292 m =
remap(m, 1, 0, falloff, interp);
296 float absm = fabs(
static_cast<float>(m));
297 s = s * absm + 1 - absm;
298 i = i * absm + 1 - absm;
307 "color midhsi(color x, float h, float s, float i, float map, float falloff=1, int interp=0)\n"
308 "The midhsi function is just like the hsi function except that\n"
309 "the control map is centered around the mid point (value of 0.5)\n"
310 "and can scale the shift in both directions.");
323 double x = R < G ? (R < B ? R : B) : (G < B ? G : B);
324 double y = R > G ? (R > B ? R : B) : (G > B ? G : B);
343 S = diff / (2 - sum);
350 H = (B - R) / diff + 2;
352 H = (R - G) / diff + 4;
359 "color rgbtohsl(color rgb)\n"
360 "RGB to HSL color space conversion.\n"
361 "HSL is Hue, Saturation, Lightness (all in range [0..1] )\n"
362 "These functions have also been extended to support rgb and hsl values\n"
363 "outside of the range [0..1] in a reasonable way. For any rgb or\n"
364 "hsl value (except for negative s values), the conversion is\n"
365 "well-defined and reversible.");
367 static double hslvalue(
double x,
double y,
double H)
372 return x + (y - x) * H * 6;
376 return x + (y - x) * (4 / 6. - H) * 6;
405 double x = 2 * L - y;
408 double R =
hslvalue(x, y, H + (1 / 3.));
410 double B =
hslvalue(x, y, H - (1 / 3.));
414 "color hsltorgb(color hsl)\n"
415 "HSL to RGB color space conversion.\n"
416 "HSL is Hue, Saturation, Lightness (all in range [0..1] )\n"
417 "These functions have also been extended to support rgb and hsl values\n"
418 "outside of the range [0..1] in a reasonable way. For any rgb or\n"
419 "hsl value (except for negative s values), the conversion is\n"
420 "well-defined and reversible.");
424 const Vec3d lum(.2126, .7152, .0722);
439 return saturate(args[0], args[1][0]);
442 "color saturate(color val, float amt)\n"
443 "Scale saturation of color by amt.\n"
444 "The color is scaled around the rec709 luminance value,\n"
445 "and negative results are clamped at zero.\n");
453 std::uniform_real_distribution<>
dis;
466 auto *data =
new Data();
470 if (args.
nargs() >= 1) {
471 a = args.
inFp<1>(0)[0];
473 if (args.
nargs() >= 2) {
474 b = args.
inFp<1>(1)[0];
477 if (args.
nargs() >= 3) {
478 data->gen = std::mt19937(args.
inFp<1>(2)[0]);
480 data->gen = std::mt19937(0);
483 data->dis = std::uniform_real_distribution<>(a, b);
490 args.
outFp = data->dis(data->gen);
500 "float rand ( [float min, float max], [float seed] )\n"
501 "Random number between [min, max] (or [0, 1] if unspecified).\n"
502 "If a seed is supplied, it will be used in addition to the internal seeds and may be used to create multiple distinct generators.");
504 double hash(
int n,
double* args)
508 for (
int i = 0; i < n; i++) {
511 double frac = frexp(args[i] *
double(M_E * M_PI), &exp);
512 uint32_t s = (uint32_t)(frac * UINT32_MAX) ^ (uint32_t)exp;
515 static const uint32_t M = 1664525;
516 static const uint32_t C = 1013904223;
517 seed = seed * M + s + C;
521 seed ^= (seed >> 11);
522 seed ^= (seed << 7) & 0x9d2c5680UL;
523 seed ^= (seed << 15) & 0xefc60000UL;
524 seed ^= (seed >> 18);
527 static std::array<uint8_t, 256>
p{
528 148, 201, 203, 34, 85, 225, 163, 200, 174, 137, 51, 24, 19, 252, 107, 173, 110, 251, 149, 69, 180, 152,
529 141, 132, 22, 20, 147, 219, 37, 46, 154, 114, 59, 49, 155, 161, 239, 77, 47, 10, 70, 227, 53, 235,
530 30, 188, 143, 73, 88, 193, 214, 194, 18, 120, 176, 36, 212, 84, 211, 142, 167, 57, 153, 71, 159, 151,
531 126, 115, 229, 124, 172, 101, 79, 183, 32, 38, 68, 11, 67, 109, 221, 3, 4, 61, 122, 94, 72, 117,
532 12, 240, 199, 76, 118, 5, 48, 197, 128, 62, 119, 89, 14, 45, 226, 195, 80, 50, 40, 192, 60, 65,
533 166, 106, 90, 215, 213, 232, 250, 207, 104, 52, 182, 29, 157, 103, 242, 97, 111, 17, 8, 175, 254, 108,
534 208, 224, 191, 112, 105, 187, 43, 56, 185, 243, 196, 156, 246, 249, 184, 7, 135, 6, 158, 82, 130, 234,
535 206, 255, 160, 236, 171, 230, 42, 98, 54, 74, 209, 205, 33, 177, 15, 138, 178, 44, 116, 96, 140, 253,
536 233, 125, 21, 133, 136, 86, 245, 58, 23, 1, 75, 165, 92, 217, 39, 0, 218, 91, 179, 55, 238, 170,
537 134, 83, 25, 189, 216, 100, 129, 150, 241, 210, 123, 99, 2, 164, 16, 220, 121, 139, 168, 64, 190, 9,
538 31, 228, 95, 247, 244, 81, 102, 145, 204, 146, 26, 87, 113, 198, 181, 127, 237, 169, 28, 93, 27, 41,
539 231, 248, 78, 162, 13, 186, 63, 66, 131, 202, 35, 144, 222, 223};
542 std::array<uint8_t, 4> c;
545 u2.c[3] =
p[u1.c[0]];
546 u2.c[2] =
p[(u1.c[1] + u2.c[3]) & 0xff];
547 u2.c[1] =
p[(u1.c[2] + u2.c[2]) & 0xff];
548 u2.c[0] =
p[(u1.c[3] + u2.c[1]) & 0xff];
551 return u2.i * (1.0 / UINT32_MAX);
554 "float hash(float seed1,[float seed2, ...])\n"
555 "Like rand, but with no internal seeds. Any number of seeds may be given\n"
556 "and the result will be a random function based on all the seeds.");
565 std::array<double, 3>
p {args[0][0], args[0][1], args[0][2]};
566 Noise<3, 1>(
p.data(), &result);
567 return .5 * result + .5;
572 std::array<double, 4>
p {};
573 for (
int i = 0; i < n; i++)
578 Noise<1, 1>(
p.data(), &result);
581 Noise<2, 1>(
p.data(), &result);
584 Noise<3, 1>(
p.data(), &result);
587 Noise<4, 1>(
p.data(), &result);
594 return .5 * result + .5;
597 "float noise ( vector v )\n"
598 "float noise ( float x, float y )\n"
599 "float noise ( float x, float y, float z )\n"
600 "float noise ( float x, float y, float z, float w )\n"
601 "Original perlin noise at location (C2 interpolant)");
606 std::array<double, 3> args {
p[0],
p[1],
p[2]};
607 Noise<3, 1>(args.data(), &result);
611 "float snoise ( vector v)\n"
612 "signed noise w/ range -1 to 1 formed with original perlin noise at location (C2 interpolant)");
617 std::array<double, 3> args {
p[0],
p[1],
p[2]};
618 Noise<3, 3>(args.data(), &result[0]);
622 "vector vnoise ( vector v)\n"
623 "vector noise formed with original perlin noise at location (C2 interpolant)");
630 "color cnoise ( vector v)\n"
631 "color noise formed with original perlin noise at location (C2 interpolant)");
636 std::array<double, 4> procargs {args[0][0], args[0][1], args[0][2], args[1][0]};
637 Noise<4, 1>(procargs.data(), &result);
641 "float snoise4 ( vector v,float t)\n"
642 "4D signed noise w/ range -1 to 1 formed with original perlin noise at location (C2 interpolant)");
647 std::array<double, 4> procargs {args[0][0], args[0][1], args[0][2], args[1][0]};
648 Noise<4, 3>(procargs.data(), &result[0]);
652 "vector vnoise4 ( vector v,float t)\n"
653 "4D vector noise formed with original perlin noise at location (C2 interpolant)");
660 "color cnoise4 ( vector v,float t)\n"
661 "4D color noise formed with original perlin noise at location (C2 interpolant)");
667 double lacunarity = 2;
676 lacunarity = args[2][0];
679 octaves = int(
clamp(args[1][0], 1, 8));
686 std::array<double, 3> P {
p[0],
p[1],
p[2]};
687 FBM<3, 1, true>(P.data(), &result, octaves, lacunarity, gain);
688 return .5 * result + .5;
695 double lacunarity = 2;
704 lacunarity = args[2][0];
707 octaves = int(
clamp(args[1][0], 1, 8));
714 std::array<double, 3> P {
p[0],
p[1],
p[2]};
715 FBM<3, 3, true>(P.data(), &result[0], octaves, lacunarity, gain);
728 double lacunarity = 2;
737 lacunarity = args[2][0];
740 octaves = int(
clamp(args[1][0], 1, 8));
747 std::array<double, 3> P {
p[0],
p[1],
p[2]};
748 FBM<3, 1, false>(P.data(), &result, octaves, lacunarity, gain);
749 return .5 * result + .5;
752 "float fbm(vector v,int octaves=6,float lacunarity=2,float gain=.5)\n"
753 "fbm (Fractal Brownian Motion) is a multi-frequency noise function. \n"
754 "The base frequency is the same as the \"noise\" function. The total "
755 "number of frequencies is controlled by octaves. The lacunarity is the "
756 "spacing between the frequencies - a value of 2 means each octave is "
757 "twice the previous frequency. The gain controls how much each "
758 "frequency is scaled relative to the previous frequency.");
764 double lacunarity = 2;
773 lacunarity = args[2][0];
776 octaves = int(
clamp(args[1][0], 1, 8));
783 std::array<double, 3> P {
p[0],
p[1],
p[2]};
784 FBM<3, 3, false>(P.data(), &result[0], octaves, lacunarity, gain);
793 double lacunarity = 2;
803 lacunarity = args[3][0];
806 octaves = int(
clamp(args[2][0], 1, 8));
809 time =
static_cast<float>(args[1][0]);
816 std::array<double, 4> P {
p[0],
p[1],
p[2], time};
817 FBM<4, 1, false>(P.data(), &result, octaves, lacunarity, gain);
818 return .5 * result + .5;
821 "float fbm4(vector v,float time,int octaves=6,float lacunarity=2,float gain=.5)\n"
822 "fbm (Fractal Brownian Motion) is a multi-frequency noise function. \n"
823 "The base frequency is the same as the \"noise\" function. The total \n"
824 "number of frequencies is controlled by octaves. The lacunarity is the \n"
825 "spacing between the frequencies - a value of 2 means each octave is \n"
826 "twice the previous frequency. The gain controls how much each \n"
827 "frequency is scaled relative to the previous frequency.");
833 double lacunarity = 2;
843 lacunarity = args[3][0];
846 octaves = int(
clamp(args[2][0], 1, 8));
849 time =
static_cast<float>(args[1][0]);
856 std::array<double, 4> P {
p[0],
p[1],
p[2], time};
857 FBM<4, 3, false>(P.data(), &result[0], octaves, lacunarity, gain);
877 std::array<double, 3> args {
p[0],
p[1],
p[2]};
878 CellNoise<3, 1>(args.data(), &result);
882 "float cellnoise(vector v)\n"
883 "cellnoise generates a field of constant colored cubes based on the integer location.\n"
884 "This is the same as the prman cellnoise function.");
889 std::array<double, 3> args {
p[0],
p[1],
p[2]};
890 CellNoise<3, 3>(args.data(), &result[0]);
894 "color cellnoise(vector v)\n"
895 "cellnoise generates a field of constant colored cubes based on the integer location.\n"
896 "This is the same as the prman cellnoise function.");
901 std::array<double, 3> args {
p[0],
p[1],
p[2]};
902 std::array<int, 3> pargs {
std::max((
int)1, (
int)period[0]),
std::max((
int)1, (
int)period[1]),
std::max((
int)1, (
int)period[2])};
903 PNoise<3, 1>(args.data(), pargs.data(), &result);
907 "float pnoise ( vector v, vector period )\n"
918 if (cell == data.
cell && jitter == data.
jitter)
919 return data.
points.data();
924 for (
int i = -1; i <= 1; i++) {
925 for (
int j = -1; j <= 1; j++) {
926 for (
int k = -1; k <= 1; k++, n++) {
932 return data.
points.data();
942 Vec3d *end = pos + 27;
944 for (; pos != end; pos++) {
946 double dist = offset.
dot(offset);
961 Vec3d *end = pos + 27;
963 for (; pos != end; pos++) {
965 double dist = offset.
dot(offset);
971 }
else if (
dist < f2) {
988 double fbmOctaves = 4;
989 double fbmLacunarity = 2;
990 double fbmGain = 0.5;
993 fbmGain = args[6][0];
996 fbmLacunarity = args[5][0];
999 fbmOctaves = args[4][0];
1002 fbmScale = args[3][0];
1005 jitter =
clamp(args[2][0], 1e-3, 1);
1008 type = int(args[1][0]);
1015 std::array<Vec3d, 4> fbmArgs;
1017 fbmArgs[1] = fbmOctaves;
1018 fbmArgs[2] = fbmLacunarity;
1019 fbmArgs[3] = fbmGain;
1020 p += fbmScale *
vfbm(4, fbmArgs.data());
1043 float scalefactor =
static_cast<float>((pos2 - pos1).
length() / ((pos1 -
p).
length() + (pos2 -
p).
length()));
1044 return smoothstep(f2 - f1, 0, 0.1 * scalefactor);
1051 "float voronoi(vector v, int type=1,float jitter=0.5, float fbmScale=0, int fbmOctaves=4,float fbmLacunarity=2, "
1052 "float fbmGain=.5)\n"
1053 "voronoi is a cellular noise pattern. It is a jittered variant of cellnoise.");
1061 double jitter = 0.5;
1062 double fbmScale = 0;
1063 double fbmOctaves = 4;
1064 double fbmLacunarity = 2;
1065 double fbmGain = 0.5;
1068 fbmGain = args[6][0];
1071 fbmLacunarity = args[5][0];
1074 fbmOctaves = args[4][0];
1077 fbmScale = args[3][0];
1080 jitter =
clamp(args[2][0], 1e-3, 1);
1083 type = int(args[1][0]);
1090 std::array<Vec3d, 4> fbmArgs;
1092 fbmArgs[1] = fbmOctaves;
1093 fbmArgs[2] = fbmLacunarity;
1094 fbmArgs[3] = fbmGain;
1095 p += fbmScale *
vfbm(4, fbmArgs.data());
1117 return (f2 - f1) * color;
1119 float scalefactor =
static_cast<float>((pos2 - pos1).
length() / ((pos1 -
p).
length() + (pos2 -
p).
length()));
1120 return smoothstep(f2 - f1, 0, 0.1 * scalefactor) * color;
1127 "color cvoronoi(vector v, int type=1,float jitter=0.5, float fbmScale=0, int fbmOctaves=4,float fbmLacunarity=2, "
1128 "float fbmGain=.5)\n"
1129 "returns color in cellular pattern. It is a jittered variant of cellnoise.");
1136 double jitter = 0.5;
1137 double fbmScale = 0;
1138 double fbmOctaves = 4;
1139 double fbmLacunarity = 2;
1140 double fbmGain = 0.5;
1143 fbmGain = args[5][0];
1146 fbmLacunarity = args[4][0];
1149 fbmOctaves = args[3][0];
1152 fbmScale = args[2][0];
1155 jitter =
clamp(args[1][0], 1e-3, 1);
1162 std::array<Vec3d, 4> fbmArgs;
1164 fbmArgs[1] = fbmOctaves;
1165 fbmArgs[2] = fbmLacunarity;
1166 fbmArgs[3] = fbmGain;
1167 p += fbmScale *
vfbm(4, fbmArgs.data());
1176 "color pvoronoi(vector v, int type=1,float jitter=0.5, float fbmScale=0, int fbmOctaves=4,float fbmLacunarity=2, "
1177 "float fbmGain=.5)\n"
1178 "returns center of voronoi cell.");
1194 if (nargs < 1 || nargs > 7) {
1201 for (
int i = 1; i < nargs; i++)
1214 int nargs = args.
nargs();
1215 auto sevArgs = std::vector<Vec3d>(nargs);
1217 for (
int i = 0; i < nargs; i++)
1218 for (
int j = 0; j < 3; j++)
1219 sevArgs[i][j] = args.
inFp<3>(i)[j];
1221 Vec3d result =
_vfunc(*data, nargs, sevArgs.data());
1222 double *out = &args.
outFp;
1223 for (
int i = 0; i < 3; i++)
1233 double x = a[0] - b[0];
1234 double y = a[1] - b[1];
1235 double z = a[2] - b[2];
1236 return sqrt(x * x + y * y + z * z);
1239 "float dist(vector a, vector b)\n"
1240 "distance between two points");
1244 return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
1247 "float length(vector v)\n"
1248 "length of vector");
1252 return sqrt(x * x + y * y);
1255 "float hypot(vector v)\n"
1256 "length of 2d vector [x,y]");
1260 return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
1263 "float dot(vector a,vector b)\n"
1264 "vector dot product");
1275 "vector norm(vector v)\n"
1276 "vector scaled to unit length");
1280 return {a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]};
1283 "vector cross(vector a,vector b)\n"
1284 "vector cross product");
1291 return acos(
dot(a, b) / len);
1294 "float angle(vector a,vector b)\n"
1295 "angle between two vectors (in radians)");
1302 "vector angle(vector a,vector b)\n"
1303 "normalized vector orthogonal to a and b scaled to unit length");
1309 const Vec3d &P = args[0];
1310 const Vec3d &axis = args[1];
1311 auto angle =
static_cast<float>(args[2][0]);
1312 double len = axis.
length();
1318 "vector rotate(vector v,vector axis,float angle)\n"
1319 "rotates v around axis by given angle (in radians)");
1324 Vec3d yAxis(0, 1, 0);
1328 "vector up(vector P,vector upvec)\n"
1329 "rotates v such that the Y axis points in the given up direction");
1331 double cycle(
double index,
double loRange,
double hiRange)
1333 int lo = int(loRange);
1334 int hi = int(hiRange);
1335 int range = hi - lo + 1;
1338 int result = int(index) % range;
1344 "int cycle(int index, int loRange, int hiRange )\n"
1345 "Cycles through values between loRange and hiRange based on supplied index.\n"
1346 "This is an offset \"mod\" function. "
1347 "The result is computed as ``loRange + value % (hiRange-loRange+1)``.");
1353 double index =
hash(1, ¶ms[0]);
1354 int loRange = int(params[1]);
1355 int hiRange = int(params[2]);
1356 int range = hiRange - loRange + 1;
1359 int numWeights = n - 3;
1360 if (numWeights > range)
1365 auto cutoffs = std::vector<double>(range);
1366 auto weights = std::vector<double>(range);
1368 for (
int i = 0; i < range; i++) {
1369 double weight = i < numWeights ? params[i + 3] : 1;
1372 weights[i] = weight;
1385 int m = (lo + hi) / 2;
1386 if (index <= cutoffs[m])
1393 if (weights[lo] == 0) {
1394 if (lo > 0 && cutoffs[lo] > 0)
1395 while (--lo > 0 && weights[lo] == 0)
1397 else if (lo < range - 1)
1398 while (++lo < range - 1 && weights[lo] == 0)
1403 return loRange + lo;
1406 "int pick(float index, int loRange, int hiRange, [float weights, ...] )\n"
1407 "Picks values randomly between loRange and hiRange based on supplied index (which is\n"
1408 "automatically hashed). The values will be distributed according\n"
1409 "to the supplied weights. Any weights not supplied are assumed to\n"
1414 return choose(n, params);
1417 "color swatch(float index, color choice0, color choice1, color choice2, [...])\n"
1418 "Chooses one of the supplied color choices based on the index (assumed to be in range [0..1]).");
1424 double key = params[0];
1429 return params[1 + int(
clamp(key * nvals, 0, nvals - 1))];
1432 "float choose(float index,float choice1, float choice2, [...])\n"
1433 "Chooses one of the supplied choices based on the index (assumed to be in range [0, 1]).");
1439 double key = params[0];
1443 int nvals = (n - 1) / 2;
1447 auto cutoffs = std::vector<double>(nvals);
1448 auto weights = std::vector<double>(nvals);
1450 for (
int i = 0; i < nvals; i++) {
1451 double weight = params[i * 2 + 2];
1454 weights[i] = weight;
1467 int m = (lo + hi) / 2;
1468 if (key <= cutoffs[m])
1475 if (weights[lo] == 0) {
1476 if (lo > 0 && cutoffs[lo] > 0)
1477 while (--lo > 0 && weights[lo] == 0)
1479 else if (lo < nvals - 1)
1480 while (++lo < nvals - 1 && weights[lo] == 0)
1485 return params[lo * 2 + 1];
1488 "float wchoose(float index,float choice1, float weight1, float choice2, float weight2, [...] )\n"
1489 "Chooses one of the supplied choices based on the index (assumed to be in range [0..1]).\n"
1490 "The values will be distributed according to the supplied weights.");
1496 double u =
clamp(params[0], 0, 1);
1500 return params[n - 2];
1503 u = modf(u * nsegs, &seg);
1504 double *
p = ¶ms[int(seg) + 1];
1507 return 0.5 * (
p[0] * (-u3 + 2 * u2 - u) +
p[1] * (3 * u3 - 5 * u2 + 2) +
p[2] * (-3 * u3 + 4 * u2 + u) +
p[3] * (u3 - u2));
1510 "float spline(float param,float y1,float y2,float y3,float y4,[...])\n\n"
1511 "Interpolates a set of values to the parameter specified where y1, ..., yn are\n"
1512 "distributed evenly from [0..1]");
1536 if ((nargs - 1) % 3) {
1543 for (
int i = 1; i < nargs && valid; i += 3) {
1565 for (
int i = 1; i < args.
nargs() - 2; i += 3) {
1566 double pos = args.
inFp<1>(i)[0];
1567 double val = args.
inFp<1>(i + 1)[0];
1568 double interpDouble = args.
inFp<1>(i + 2)[0];
1569 int interpInt = (int)interpDouble;
1572 assert(
false &&
"ExprFuncNode ERROR: invalid interpolant type!");
1574 data->curve.addPoint(pos, val, interpolant);
1576 data->curve.preparePoints();
1583 double param = args.
inFp<1>(0)[0];
1584 args.
outFp = data->curve.getValue(param);
1589 "float curve(float param,float pos0,float val0,int interp0,float pos1,float val1,int interp1,[...])\n\n"
1590 "Interpolates a 1D ramp defined by control points at 'param'. Control points are specified \n"
1591 "by triples of parameters pos_i, val_i, and interp_i. Interpolation codes are \n"
1592 "0 - none, 1 - linear, 2 - smooth, 3 - spline, \n"
1593 "4 - monotone (non oscillating spline)");
1601 if ((nargs - 1) % 3) {
1608 for (
int i = 1; i < nargs && valid; i += 3) {
1629 for (
int i = 1; i < args.
nargs() - 2; i += 3) {
1630 double pos = args.
inFp<1>(i)[0];
1632 double interpDouble = args.
inFp<1>(i + 2)[0];
1633 int interpInt = (int)interpDouble;
1638 data->curve.addPoint(pos, val, interpolant);
1640 data->curve.preparePoints();
1647 double param = args.
inFp<1>(0)[0];
1648 Vec3d result = data->curve.getValue(param);
1649 double *out = &args.
outFp;
1650 for (
int k = 0; k < 3; k++)
1661 "color curve(float param,float pos0,color val0,int interp0,float pos1,color val1,int interp1,[...])\n\n"
1662 "Interpolates color ramp given by control points at 'param'. Control points are specified \n"
1663 "by triples of parameters pos_i, val_i, and interp_i. Interpolation codes are \n"
1664 "0 - none, 1 - linear, 2 - smooth, 3 - spline, \n"
1665 "4 - monotone (non oscillating spline)");
1670 using func = void (*)(
double *,
double *);
1684 std::string varName = node->
getStrArg(0);
1686 ExprType varType = varNode->prep(wantScalar, envBuilder);
1694 varType = node->
child(0)->
prep(wantScalar, envBuilder);
1702 return new Data(node->
type().
isFP() ? getTemplatizedOp<Assign, Data::func>(node->
type().
dim()) :
nullptr, node->
type().
dim());
1706 static void f(
double *out,
double *in)
1708 for (
int k = 0; k < d; k++)
1717 double *out = &args.
outFp;
1721 data->
f(out, &args.
inFp<1>(0)[0]);
1723 throw std::runtime_error(
"getVar does not support non FP types right now got type");
1733 "getVar(string varName,vector defaultValue)\n"
1734 "return value of varName if variable exists, otherwise return defaultValue");
1756 int searchStart = 0;
1759 std::size_t percentStart = format.find(
'%', searchStart);
1760 if (percentStart == std::string::npos)
1762 if (percentStart + 1 == format.length()) {
1765 }
else if (format[percentStart + 1] ==
'%') {
1766 searchStart =
static_cast<int>(percentStart + 2);
1768 }
else if (format[percentStart + 1] ==
'v' || format[percentStart + 1] ==
'f') {
1776 searchStart =
static_cast<int>(percentStart + 2);
1787 }
else if (items != nargs - 1) {
1798 unsigned int bakeStart = 0;
1799 int searchStart = 0;
1803 std::string &format = data->
format;
1804 std::vector<std::pair<int, int>> &ranges = data->
ranges;
1808 std::size_t percentStart = format.find(
'%', searchStart);
1809 if (percentStart == std::string::npos)
1811 if (percentStart + 1 == format.length()) {
1815 }
else if (format[percentStart + 1] ==
'%') {
1816 searchStart =
static_cast<int>(percentStart + 2);
1818 }
else if (format[percentStart + 1] ==
'v' || format[percentStart + 1] ==
'f') {
1819 char c = format[percentStart + 1];
1820 int code = (c ==
'v') ? -1 : -2;
1822 if (bakeStart != percentStart)
1823 ranges.emplace_back(bakeStart,
static_cast<int>(percentStart));
1824 ranges.emplace_back(code, code);
1826 searchStart =
static_cast<int>(percentStart + 2);
1827 bakeStart = searchStart;
1837 if (bakeStart != format.length())
1838 ranges.emplace_back(bakeStart,
static_cast<int>(format.length()));
1840 if (items != args.
nargs() - 1) {
1856 for (
unsigned int i = 0; i < data->
ranges.size(); i++) {
1857 const std::pair<int, int> &range = data->
ranges[i];
1858 if (range.first == -2) {
1859 std::cerr << args.
inFp<1>(item)[0];
1861 }
else if (range.first == -1) {
1862 std::cerr <<
"[" << args.
inFp<3>(item)[0] <<
"," << args.
inFp<3>(item)[1] <<
"," << args.
inFp<3>(item)[2] <<
"]";
1865 std::cerr << data->
format.substr(range.first, range.second - range.first);
1868 std::cerr << std::endl;
1880 "float printf(string format,[vec0, vec1, ...])\n"
1881 "Prints out a string to STDOUT, Format parameters allowed are \"%v\" and \"%f\".\n"
1882 "Return parameter is empty, but must be assigned to a variable.");
1890 std::string _intSpec {
"diouxXc"};
1891 std::string _doubleSpec {
"eEfFgGaA"};
1892 std::string _strSpec {
"s"};
1912 const std::string &format =
dynamic_cast<const ExprStrNode *
>(node->
child(0))->str();
1914 static const std::string strSpec(
"s");
1915 size_t searchStart = 0;
1918 const size_t specStart = format.find(
'%', searchStart);
1919 if (specStart == std::string::npos)
1921 if (specStart + 1 == format.length()) {
1925 if (format[specStart + 1] ==
'%') {
1926 searchStart = specStart + 2;
1930 const size_t specEnd = format.find_first_of(std::string(_intSpec).append(_doubleSpec).append(_strSpec), specStart);
1931 if (specEnd == std::string::npos) {
1935 if (_strSpec.find(format[specEnd]) != std::string::npos) {
1945 searchStart = specEnd + 1;
1958 result.assign(args.
inStr(0));
1960 std::array<char, 255> fragment {};
1961 size_t searchStart = 0;
1964 const size_t specStart = result.find(
'%', searchStart);
1965 if (specStart == std::string::npos)
1967 if (result[specStart + 1] ==
'%') {
1968 result.erase(specStart, 1);
1969 searchStart = specStart + 1;
1973 const size_t specEnd = result.find_first_of(std::string(_intSpec).append(_doubleSpec).append(_strSpec), specStart);
1974 const std::string &spec = result.substr(specStart, specEnd - specStart + 1);
1976 if (std::string::npos != _intSpec.find(result[specEnd]))
1977 fragLen = snprintf(fragment.data(), 255, spec.c_str(), int(args.
inFp<1>(exprArg++)[0]));
1978 else if (std::string::npos != _doubleSpec.find(result[specEnd]))
1979 fragLen = snprintf(fragment.data(), 255, spec.c_str(), args.
inFp<1>(exprArg++)[0]);
1980 else if (std::string::npos != _strSpec.find(result[specEnd]))
1981 fragLen = snprintf(fragment.data(), 255, spec.c_str(), args.
inStr(exprArg++));
1982 assert(fragLen >= 0);
1984 result.replace(specStart, spec.size(), fragment.data());
1985 searchStart += fragLen + 1;
1988 args.
outStr =
const_cast<char *
>(result.c_str());
1993 "sprintf(string format, [double|string, double|string, ...])\n"
1994 "Returns a string formatted from the given values. See 'man sprintf' for format details.");
2009 :ExprFuncSimple(true)
2011 virtual ExprType
prep(ExprFuncNode* node,
bool scalarWanted,ExprVarEnvBuilder& envBuilder)
const
2014 valid &= node->checkArg(0,ExprType().FP(3).Varying(),envBuilder);
2015 valid &= node->checkArg(1,ExprType().FP(1).Constant(),envBuilder);
2016 return valid ?ExprType().FP(3).Varying():ExprType().Error();
2018 virtual ExprFuncNode::Data*
evalConstant(ArgHandle args)
const
2021 return new MyData(args.inFp<1>(1)[0]);
2023 virtual void eval(ArgHandle args)
2025 MyData* data=
static_cast<MyData*
>(args.data);
2027 Vec<double,3,true>(&args.outFp)=args.inFp<3>(0)+Vec<double,3,false>(data->foo);
2030 static const char* testfunc_docstring=
"fdsA";
2037 #define FUNCADOC(name, func) define3(name, ExprFunc(::func), func##_docstring)
2038 #define FUNCDOC(func) define3(#func, ExprFunc(::func), func##_docstring)
2068 #define FUNCDOC(func) define3(#func, ExprFunc(KSeExpr::func), func##_docstring)
2069 #define FUNCNDOC(func, min, max) define3(#func, ExprFunc(KSeExpr::func, min, max), func##_docstring)
ExprType prep(ExprFuncNode *node, bool, ExprVarEnvBuilder &envBuilder) const override
ExprFuncNode::Data * evalConstant(const ExprFuncNode *, ArgHandle) const override
void eval(ArgHandle args) override
#define FUNCNDOC(func, min, max)
#define FUNCADOC(name, func)
#define QT_TRANSLATE_NOOP(scope, x)
#define QT_TRANSLATE_NOOP_UTF8(scope, x)
static constexpr std::array< int, 514 > p
ExprFuncNode::Data * evalConstant(const ExprFuncNode *, ArgHandle args) const override
void eval(ArgHandle args) override
ExprType prep(ExprFuncNode *node, bool, ExprVarEnvBuilder &envBuilder) const override
ExprFuncNode::Data * evalConstant(const ExprFuncNode *, ArgHandle) const override
CachedVoronoiFunc(VoronoiFunc *vfunc) noexcept
ExprType prep(ExprFuncNode *node, bool, ExprVarEnvBuilder &envBuilder) const override
Vec3d(VoronoiPointData &, int, const Vec3d *) VoronoiFunc
void eval(ArgHandle args) override
ExprFuncNode::Data * evalConstant(const ExprFuncNode *, ArgHandle args) const override
ExprType prep(ExprFuncNode *node, bool, ExprVarEnvBuilder &envBuilder) const override
void eval(ArgHandle args) override
Interpolation curve class for double->double and double->Vec3D.
InterpType
Supported interpolation types.
Node that calls a function.
bool checkArg(int argIndex, const ExprType &type, ExprVarEnvBuilder &envBuilder)
std::string getStrArg(int n) const
ExprFuncNode::Data * data
Vec< double, d, true > inFp(int i)
ExprFuncSimple(const bool threadSafe)
void(*)(const char *, const ExprFunc &, const char *) Define3
void(*)(const char *, const ExprFunc &) Define
virtual ExprType prep(bool dontNeedScalar, ExprVarEnvBuilder &envBuilder)
void swapChildren(size_t i, size_t j)
Swap children, do not use unless you know what you are doing.
const Expression * expr() const
Access expression.
int numChildren() const
Number of children.
void removeLastChild()
Remove last child and delete the entry.
const ExprType & type() const
The type of the node.
void addError(const ErrorCode error, const std::vector< std::string > &ids={}) const
Register error. This will allow users and sophisticated editors to highlight where in code problem wa...
const ExprNode * child(size_t i) const
Get 0 indexed child.
void addChild(ExprNode *child)
Add a child to the child list (for parser use only)
Node that stores a numeric constant.
Node that stores a string.
ExprType & String()
Mutate this into a string type.
ExprType & Constant()
Mutate this into a constant lifetime.
ExprType & Varying()
Mutate this into a varying lifetime.
ExprType & FP(int d)
Mutate this into a floating point type of dimension d.
bool isFP() const
Direct is predicate checks.
ExprType & Error()
Mutate this into an error type.
Variable scope builder is used by the type checking and code gen to track visiblity of variables and ...
Node that references a variable.
ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle) const override
ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const override
void eval(ArgHandle args) override
void eval(ArgHandle args) override
ExprType prep(ExprFuncNode *node, bool, ExprVarEnvBuilder &envBuilder) const override
ExprFuncNode::Data * evalConstant(const ExprFuncNode *, ArgHandle args) const override
void eval(ArgHandle args) override
ExprFuncNode::Data * evalConstant(const ExprFuncNode *, ArgHandle args) const override
ExprType prep(ExprFuncNode *node, bool, ExprVarEnvBuilder &envBuilder) const override
ExprFuncNode::Data * evalConstant(const ExprFuncNode *, ArgHandle) const override
void eval(ArgHandle args) override
ExprType prep(ExprFuncNode *node, bool, ExprVarEnvBuilder &envBuilder) const override
T dot(const Vec< T, d, refother > &o) const
T_VEC_VALUE rotateBy(const Vec< T, 3, refother > &axis, T angle) const
T length() const
Euclidean (2) norm.
KSeExpr_DEFAULT double_t floor(double_t val)
double gamma(double x, double g)
Vec3d cvoronoiFn(VoronoiPointData &data, int n, const Vec3d *args)
static const char * pnoise_docstring
static const char * invert_docstring
static const char * atand_docstring
static const char * vfbm4_docstring
Vec3d pvoronoiFn(VoronoiPointData &data, int n, const Vec3d *args)
double max(double x, double y)
static const char * trunc_docstring
static const char * ceil_docstring
static const char * remap_docstring
static const char * vnoise_docstring
double atan2d(double y, double x)
double gaussstep(double x, double a, double b)
double fit(double x, double a1, double b1, double a2, double b2)
double mix(double x, double y, double alpha)
static const char * voronoi_docstring
static const char * mix_docstring
static const char * fmod_docstring
static const char * cos_docstring
static const char * cross_docstring
double dist(const Vec3d &a, const Vec3d &b)
static const char * pick_docstring
KSeExpr::SPrintFuncX sprintf
static const char * smoothstep_docstring
Vec3d vturbulence(int n, const Vec3d *args)
Vec3d vnoise4(int, const Vec3d *args)
static const char * hypot_docstring
static void voronoi_f1f2_3d(VoronoiPointData &data, const Vec3d &p, double jitter, double &f1, Vec3d &pos1, double &f2, Vec3d &pos2)
static const char * hsi_docstring
static const char * expand_docstring
static const char * noise_docstring
static const char * atan2d_docstring
Vec3d rgbtohsl(const Vec3d &rgb)
double dot(const Vec3d &a, const Vec3d &b)
double fbm4(int n, const Vec3d *args)
static const char * acos_docstring
static const char * hash_docstring
static const char * cycle_docstring
static const char * cfbm4_docstring
Vec3d cfbm(int n, const Vec3d *args)
double bias(double x, double b)
static const char * cellnoise_docstring
KSeExpr::PrintFuncX printf
double pnoise(const Vec3d &p, const Vec3d &period)
static const char * vfbm_docstring
static const char * rad_docstring
Vec3d vfbm(int n, const Vec3d *args)
static const char * asind_docstring
Vec3d cnoise4(int n, const Vec3d *args)
static const char * turbulence_docstring
static const char * compress_docstring
double contrast(double x, double c)
static const char * fit_docstring
double hypot(double x, double y)
static double hslvalue(double x, double y, double H)
double snoise4(int, const Vec3d *args)
double noise(int n, const Vec3d *args)
static const char * acosh_docstring
static const char * rotate_docstring
static const char * pvoronoi_docstring
static const char * atanh_docstring
Vec3d cturbulence(int n, const Vec3d *args)
static const char * cturbulence_docstring
Vec3d norm(const Vec3d &a)
static const char * dist_docstring
static void voronoi_f1_3d(VoronoiPointData &data, const Vec3d &p, double jitter, double &f1, Vec3d &pos1)
static const char * max_docstring
KSeExpr::CurveData voronoi
static const char * vturbulence_docstring
double length(const Vec3d &v)
double fbm(int n, const Vec3d *args)
static const char * printf_docstring
Vec3d hsiAdjust(const Vec3d &rgb, double h, double s, double i)
static const char * min_docstring
static const char * atan2_docstring
static const char * gamma_docstring
double angle(const Vec3d &a, const Vec3d &b)
static const char * midhsi_docstring
static Vec3d * voronoi_points(VoronoiPointData &data, const Vec3d &cell, double jitter)
Vec3d up(const Vec3d &P, const Vec3d &upvec)
static const char * wchoose_docstring
double linearstep(double x, double a, double b)
static const char * log10_docstring
static const char * floor_docstring
static const char * boxstep_docstring
static const char * cvoronoi_docstring
Vec3d voronoiFn(VoronoiPointData &data, int n, const Vec3d *args)
static const char * cbrt_docstring
static const char * choose_docstring
double cycle(double index, double loRange, double hiRange)
static const char * cosd_docstring
double boxstep(double x, double a)
static const char * spline_docstring
static const char * hsltorgb_docstring
double expand(double x, double lo, double hi)
static const char * ccellnoise_docstring
static const char * acosd_docstring
double smoothstep(double x, double a, double b)
static const char * dot_docstring
Vec3d cross(const Vec3d &a, const Vec3d &b)
static const char * curve_docstring
static const char * sin_docstring
static const char * ortho_docstring
double remap(double x, double source, double range, double falloff, double interp)
static const char * sqrt_docstring
static const char * sprintf_docstring
static const char * fbm4_docstring
static const char * log_docstring
double hash(int n, double *args)
double spline(int n, double *params)
static const char * tan_docstring
static const char * angle_docstring
static const char * atan_docstring
static const char * saturate_docstring
double turbulence(int n, const Vec3d *args)
double min(double x, double y)
static const char * snoise4_docstring
static const char * pow_docstring
double snoise(const Vec3d &p)
static const char * clamp_docstring
static const char * cfbm_docstring
static const char * swatch_docstring
static const char * norm_docstring
KSeExpr::CCurveFuncX ccurve
@ InvalidFormatString
Invalid format string, only v or f is allowed.
@ WrongNumberOfArgumentsMultiple3Plus1
"Wrong number of arguments, should be multiple of 3 plus 1"
@ FirstArgumentNotString
"First argument must be a string."
@ WrongNumberOfArguments
"Wrong number of arguments, should be 1 to 7"
@ ExpectedFloatOrFloat3
"Expected float or FP[3]"
@ Unknown
Unknown error (message = %1)
@ WrongNumberOfArguments1Plus
"Wrong number of arguments, should be >= 1"
@ UnexpectedEndOfFormatString
Unexpected end of format string.
@ IncompleteFormatSpecifier
"incomplete format specifier"
@ WrongNumberOfArgumentsForFormatString
Wrong number of arguments for format string.
static const char * fabs_docstring
Vec3d vfbm4(int n, const Vec3d *args)
Vec3d hsltorgb(const Vec3d &hsl)
static const char * contrast_docstring
static const char * ccurve_docstring
static const char * tand_docstring
static const char * linearstep_docstring
static const char * cosh_docstring
static const char * length_docstring
Vec3d rotate(int n, const Vec3d *args)
KSeExpr::CachedVoronoiFunc ExprFuncSimple pvoronoi(pvoronoiFn)
Vec3d cfbm4(int n, const Vec3d *args)
static const char * asinh_docstring
double clamp(double x, double lo, double hi)
static Vec3d saturate(const Vec3d &Cin, double amt)
Vec3d vnoise(const Vec3d &p)
static const char * fbm_docstring
static const char * rand_docstring
Vec3d hsi(int n, const Vec3d *args)
static const char * sinh_docstring
static const char * vnoise4_docstring
KSeExpr::CachedVoronoiFunc ExprFuncSimple cvoronoi(cvoronoiFn)
void defineBuiltins(ExprFunc::Define, ExprFunc::Define3 define3)
double choose(int n, double *params)
double pick(int n, double *params)
static const char * rgbtohsl_docstring
static const char * snoise_docstring
static const char * cnoise_docstring
double swatch(int n, double *params)
static const char * sind_docstring
Vec< double, 3, false > Vec3d
static const char * gaussstep_docstring
double compress(double x, double lo, double hi)
Vec3d ortho(const Vec3d &a, const Vec3d &b)
static const char * deg_docstring
static const char * tanh_docstring
static const char * up_docstring
Vec3d midhsi(int n, const Vec3d *args)
double wchoose(int n, double *params)
double cellnoise(const Vec3d &p)
static const char * exp_docstring
Vec3d ccellnoise(const Vec3d &p)
static const char * getVar_docstring
Vec3d cnoise(const Vec3d &p)
static const char * asin_docstring
static const char * cnoise4_docstring
static const char * bias_docstring
static const char * round_docstring
CurveData(CurveData &&) noexcept=default
~CurveData() override=default
CurveData(const CurveData &)=default
CurveData & operator=(const CurveData &)=default
base class for custom instance data
static void f(double *out, double *in)
void(*)(double *, double *) func
std::vector< std::pair< int, int > > ranges
std::uniform_real_distribution dis
std::array< Vec3d, 27 > points
VoronoiPointData()=default