36 static const char*
fabs_docstring =
"float abs(float x)\nabsolute value of x";
39 static const char*
deg_docstring =
"float deg(float angle)\nradians to degrees";
40 static const char*
rad_docstring =
"float deg(float angle)\ndegrees to radians";
42 static const char*
cosd_docstring =
"float cosd(float angle)\ncosine in degrees";
43 static const char*
sind_docstring =
"float sind(float angle)\nsine in degrees";
44 static const char*
tand_docstring =
"float tand(float angle)\ntangent in degrees";
45 static const char*
acosd_docstring =
"float acosd(float angle)\narc cosine in degrees";
46 static const char*
asind_docstring =
"float asind(float angle)\narc sine in degrees";
47 static const char*
atand_docstring =
"float atand(float angle)\narc tangent in degrees";
49 "float atan2d(float y,float x)\narc tangent in degrees of y/x between -180 and 180";
51 static const char*
cos_docstring =
"float cos(float angle)\ncosine in radians";
52 static const char*
sin_docstring =
"float sin(float angle)\nsine in radians";
53 static const char*
tan_docstring =
"float tan(float angle)\ntangent in radians";
54 static const char*
acos_docstring =
"float acos(float angle)\narc cosine in radians";
55 static const char*
asin_docstring =
"float asin(float angle)\narc sine in radians";
56 static const char*
atan_docstring =
"float atan(float angle)\narc tangent in radians";
57 static const char*
atan2_docstring =
"float atan2(float y,float x)\narc tangent in radians of y/x between -PI and PI";
59 static const char*
cosh_docstring =
"float cosh(float angle)\nhyperbolic cosine in radians";
60 static const char*
sinh_docstring =
"float sinh(float angle)\nhyperbolic sine in radians";
61 static const char*
tanh_docstring =
"float tanh(float angle)\nhyperbolic tangent in radians";
62 static const char*
acosh_docstring =
"float acosh(float angle)\nhyperbolic arc cosine in radians";
63 static const char*
asinh_docstring =
"float asinh(float angle)\nhyperbolic arc sine in radians";
64 static const char*
atanh_docstring =
"float atanh(float angle)\nhyperbolic arc tangent in radians";
66 static const char*
clamp_docstring =
"float clamp(float x,float lo,float hi)\nconstrain x to range [lo,hi]";
67 static const char*
round_docstring =
"float round(float x)\nconstrain x to range [lo,hi]";
68 static const char*
max_docstring =
"float max(float a,float b)\ngreater of a and b";
69 static const char*
min_docstring =
"float min(float a,float b)\nlesser of a and b";
70 static const char*
trunc_docstring =
"float trunc(float a)\nnearest integer towards zero";
72 static const char*
ceil_docstring =
"float ceil(float a)\nnext higher integer";
77 static const char*
exp_docstring =
"float exp(float x)\nE raised to the x power";
78 static const char*
pow_docstring =
"float pow(float x)\nx to the y power, also available as ^";
79 static const char*
log_docstring =
"float log(float x)\nNatural logarithm";
81 static const char*
fmod_docstring =
"float fmod(float x,float y)\nremainder of x/y (also available as % operator)";
83 "float turbulence(vector v,int octaves=6,float lacunarity=2,float gain=.5)\nAbsolute value of each noise term is "
84 "taken. This gives billowy appearance";
86 "color cturbulence(vector v,int octaves=6,float lacunarity=2,float gain=.5)\nAbsolute value of each noise term is "
87 "taken. This gives billowy appearance";
89 "vector vturbulence(vector v,int octaves=6,float lacunarity=2,float gain=.5)\nAbsolute value of each noise term is "
90 "taken. This gives billowy appearance";
92 double compress(
double x,
double lo,
double hi) {
return (hi - lo) *
x + lo; }
93 static const char*
compress_docstring =
"float compress(float x,float lo,float hi)\nRemaps x in [0,1] to [lo,hi]";
95 double expand(
double x,
double lo,
double hi) {
96 if (lo == hi)
return x < lo ? 0 : 1;
97 return (
x - lo) / (hi - lo);
99 static const char*
expand_docstring =
"float expand(float x,float lo,float hi)\nRemaps x in [lo,hi] to [0,1]";
101 double fit(
double x,
double a1,
double b1,
double a2,
double b2) {
105 "float fit(float x,float a1,float b1,float a2,float b2)\nLinearly remaps x in [a1,b1] to [a2,b2]";
108 static const char*
gamma_docstring =
"float gamma(float x, float g)\nGamma correction of x with gamma factor g";
111 static double C = 1 / log(0.5);
112 return pow(
x, log(
b) * C);
115 "float bias(float x, float g)\nVariation of gamma where values less than 0.5 pull the curve down\nand values "
116 "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 x)\nAdjust the contrast. For c from 0 to 0.5, the contrast is decreased. "
126 "For c > 0.5, the contrast is increased.";
129 static const char*
boxstep_docstring =
"float boxstep(float x,float a)\n if x < a then 0 otherwise 1";
133 return x <
a ? 0 : (
x >
b ? 1 : (
x -
a) / (
b -
a));
135 return 1 - (
x <
b ? 0 : (
x >
a ? 1 : (
x -
b) / (
a -
b)));
140 "float linearstep(float x,float a,float b)\n if x < a then 0, if x > b then 1, and\nx transitions linearly "
141 "when < x < b ";
146 if (
x >=
b)
return 1;
147 x = (
x -
a) / (
b -
a);
149 if (
x <=
b)
return 1;
151 x = 1 - (
x -
b) / (
a -
b);
154 return x *
x * (3 - 2 *
x);
157 "float smoothstep(float x,float a,float b)\n if x < a then 0, if x > b then 1, and\nx transitions smoothly "
158 "(cubic) when < x < b";
163 if (
x >=
b)
return 1;
164 x = 1 - (
x -
a) / (
b -
a);
166 if (
x <=
b)
return 1;
168 x = (
x -
b) / (
a -
b);
171 return pow(2, -8 *
x *
x);
174 "float gasussstep(float x,float a,float b)\n if x < a then 0, if x > b then 1, and\nx transitions smoothly "
175 "(exponentially) when < x < b";
177 double remap(
double x,
double source,
double range,
double falloff,
double interp) {
179 falloff = fabs(falloff);
181 if (falloff == 0)
return fabs(
x -
source) < range;
192 switch (
int(interp)) {
202 "remap(float x, float\n"
203 "source, float range, float falloff, float interp)\nGeneral remapping function.\n"
204 "When x is within +/- <i>range</i> of source, the result is one.\n"
205 "The result falls to zero beyond that range over <i>falloff</i> distance.\n"
206 "The falloff shape is controlled by <i>interp</i>. Numeric values\n"
207 "or named constants may be used:\n"
208 " int <b>linear</b>\n"
210 " int <b>smooth</b> = 1\n"
211 " int <b>gaussian</b> = 2\n";
213 double mix(
double x,
double y,
double alpha) {
return x * (1 - alpha) +
y * alpha; }
214 static const char*
mix_docstring =
"mix(float a,float b,float alpha)\nBlend of a and b according to alpha.";
218 hsl[0] += h * (1.0 / 360);
224 if (n < 4)
return 0.0;
226 double h = args[1][0];
227 double s = args[2][0];
228 double i = args[3][0];
231 double m = args[4][0];
239 "color hsi(color x, float h, float s, float i, float map=1)\n"
240 "The hsi function shifts the hue by h\n"
241 "(in degrees) and scales the saturation and intensity by s and i\n"
242 "respectively. An map may be supplied which will control the shift\n"
243 "- the full shift will happen when the map is one and no shift will\n"
244 "happen when the map is zero. The shift will be scaled back for\n"
245 "values between zero and one.";
248 if (n < 4)
return 0.0;
250 double h = args[1][0];
251 double s = args[2][0];
252 double i = args[3][0];
255 double m = args[4][0];
259 double falloff = 1, interp = 0;
260 if (n >= 6) falloff = args[5][0];
261 if (n >= 7) interp = args[6][0];
263 m = -
remap(-m, 1, 0, falloff, interp);
265 m =
remap(m, 1, 0, falloff, interp);
269 float absm = fabs(static_cast<float>(m));
270 s = s * absm + 1 - absm;
271 i = i * absm + 1 - absm;
280 "color midhsi(color x, float h, float s, float i, float map, float falloff=1, int interp=0)\n"
281 "The midhsi function is just like the hsi function except that\n"
282 "the control map is centered around the mid point (value of 0.5)\n"
283 "and can scale the shift in both directions.";
289 double R, G, B, H, S, L,
x,
y, sum, diff;
293 x = R < G ? (R < B ? R : B) : (G < B ? G : B);
294 y = R > G ? (R > B ? R : B) : (G > B ? G : B);
301 return Vec3d(0, 0, L);
313 S = diff / (2 - sum);
320 H = (B - R) / diff + 2;
322 H = (R - G) / diff + 4;
326 return Vec3d(H, S, L);
329 "color rgbtohsl(color rgb)\n"
330 "RGB to HSL color space conversion.\n"
331 "HSL is Hue, Saturation, Lightness (all in range [0..1] )\n"
332 "These functions have also been extended to support rgb and hsl values\n"
333 "outside of the range [0..1] in a reasonable way. For any rgb or\n"
334 "hsl value (except for negative s values), the conversion is\n"
335 "well-defined and reversible.";
341 return x + (
y -
x) * H * 6;
345 return x + (
y -
x) * (4 / 6. - H) * 6;
354 double H, S, L, R, G, B,
x,
y;
359 return Vec3d(L, L, L);
379 return Vec3d(R, G, B);
382 "color hsltorgb(color hsl)\n"
383 "RGB to HSL color space conversion.\n"
384 "HSL is Hue, Saturation, Lightness (all in range [0..1] )\n"
385 "These functions have also been extended to support rgb and hsl values\n"
386 "outside of the range [0..1] in a reasonable way. For any rgb or\n"
387 "hsl value (except for negative s values), the conversion is\n"
388 "well-defined and reversible.";
391 const Vec3d lum(.2126, .7152, .0722);
393 if (result[0] < 0) result[0] = 0;
394 if (result[1] < 0) result[1] = 0;
395 if (result[2] < 0) result[2] = 0;
400 if (n < 2)
return 0.0;
401 return saturate(args[0], args[1][0]);
404 "color saturate(color val, float amt)\n"
405 "Scale saturation of color by amt.\n"
406 "The color is scaled around the rec709 luminance value,\n"
407 "and negative results are clamped at zero.\n";
409 double hash(
int n,
double* args) {
412 for (
int i = 0; i < n; i++) {
415 double frac = frexp(args[i] *
double(M_E * M_PI), &exp);
416 uint32_t s = (uint32_t)(frac * UINT32_MAX) ^ (uint32_t)exp;
419 static const uint32_t M = 1664525, C = 1013904223;
420 seed = seed * M + s + C;
424 seed ^= (seed >> 11);
425 seed ^= (seed << 7) & 0x9d2c5680UL;
426 seed ^= (seed << 15) & 0xefc60000UL;
427 seed ^= (seed >> 18);
430 static unsigned char p[256] = {
431 148, 201, 203, 34, 85, 225, 163, 200, 174, 137, 51, 24, 19, 252, 107, 173, 110, 251, 149, 69, 180, 152,
432 141, 132, 22, 20, 147, 219, 37, 46, 154, 114, 59, 49, 155, 161, 239, 77, 47, 10, 70, 227, 53, 235,
433 30, 188, 143, 73, 88, 193, 214, 194, 18, 120, 176, 36, 212, 84, 211, 142, 167, 57, 153, 71, 159, 151,
434 126, 115, 229, 124, 172, 101, 79, 183, 32, 38, 68, 11, 67, 109, 221, 3, 4, 61, 122, 94, 72, 117,
435 12, 240, 199, 76, 118, 5, 48, 197, 128, 62, 119, 89, 14, 45, 226, 195, 80, 50, 40, 192, 60, 65,
436 166, 106, 90, 215, 213, 232, 250, 207, 104, 52, 182, 29, 157, 103, 242, 97, 111, 17, 8, 175, 254, 108,
437 208, 224, 191, 112, 105, 187, 43, 56, 185, 243, 196, 156, 246, 249, 184, 7, 135, 6, 158, 82, 130, 234,
438 206, 255, 160, 236, 171, 230, 42, 98, 54, 74, 209, 205, 33, 177, 15, 138, 178, 44, 116, 96, 140, 253,
439 233, 125, 21, 133, 136, 86, 245, 58, 23, 1, 75, 165, 92, 217, 39, 0, 218, 91, 179, 55, 238, 170,
440 134, 83, 25, 189, 216, 100, 129, 150, 241, 210, 123, 99, 2, 164, 16, 220, 121, 139, 168, 64, 190, 9,
441 31, 228, 95, 247, 244, 81, 102, 145, 204, 146, 26, 87, 113, 198, 181, 127, 237, 169, 28, 93, 27, 41,
442 231, 248, 78, 162, 13, 186, 63, 66, 131, 202, 35, 144, 222, 223};
448 u2.c[3] =
p[u1.c[0]];
449 u2.c[2] =
p[(u1.c[1] + u2.c[3]) & 0xff];
450 u2.c[1] =
p[(u1.c[2] + u2.c[2]) & 0xff];
451 u2.c[0] =
p[(u1.c[3] + u2.c[1]) & 0xff];
454 return u2.i * (1.0 / UINT32_MAX);
457 "float hash(float seed1,[float seed2, ...])\n"
458 "Like rand, but with no internal seeds. Any number of seeds may be given\n"
459 "and the result will be a random function based on all the seeds.";
466 double p[3] = {args[0][0], args[0][1], args[0][2]};
467 Noise<3, 1>(
p, &result);
468 return .5 * result + .5;
473 for (
int i = 0; i < n; i++)
p[i] = args[i][0];
477 Noise<1, 1>(
p, &result);
480 Noise<2, 1>(
p, &result);
483 Noise<3, 1>(
p, &result);
486 Noise<4, 1>(
p, &result);
492 return .5 * result + .5;
495 "float noise ( vector v ) <br>\n"
496 "float noise ( float x, float y )\n"
497 "float noise ( float x, float y, float z )\n"
498 "float noise ( float x, float y, float z, float w )\n"
499 "Original perlin noise at location (C2 interpolant)";
503 double args[3] = {
p[0],
p[1],
p[2]};
504 Noise<3, 1>(args, &result);
508 "float snoise ( vector v)\n"
509 "signed noise w/ range -1 to 1 formed with original perlin noise at location (C2 interpolant)";
513 double args[3] = {
p[0],
p[1],
p[2]};
514 Noise<3, 3>(args, &result[0]);
518 "vector vnoise ( vector v)\n"
519 "vector noise formed with original perlin noise at location (C2 interpolant)";
523 "color cnoise ( vector v)\n"
524 "color noise formed with original perlin noise at location (C2 interpolant)";
528 double procargs[4] = {args[0][0], args[0][1], args[0][2], args[1][0]};
529 Noise<4, 1>(procargs, &result);
533 "float snoise4 ( vector v,float t)\n"
534 "4D signed noise w/ range -1 to 1 formed with original perlin noise at location (C2 interpolant)";
538 double procargs[4] = {args[0][0], args[0][1], args[0][2], args[1][0]};
539 Noise<4, 3>(procargs, &result[0]);
543 "vector vnoise4 ( vector v,float t)\n"
544 "4D vector noise formed with original perlin noise at location (C2 interpolant)";
548 "color cnoise4 ( vector v,float t)\n"
549 "4D color noise formed with original perlin noise at location (C2 interpolant)";
554 double lacunarity = 2;
562 lacunarity = args[2][0];
564 octaves = int(
clamp(args[1][0], 1, 8));
570 double P[3] = {
p[0],
p[1],
p[2]};
571 FBM<3, 1, true>(P, &result, octaves, lacunarity, gain);
572 return .5 * result + .5;
578 double lacunarity = 2;
586 lacunarity = args[2][0];
588 octaves = int(
clamp(args[1][0], 1, 8));
594 double P[3] = {
p[0],
p[1],
p[2]};
595 FBM<3, 3, true>(P, &result[0], octaves, lacunarity, gain);
604 double lacunarity = 2;
612 lacunarity = args[2][0];
614 octaves = int(
clamp(args[1][0], 1, 8));
620 double P[3] = {
p[0],
p[1],
p[2]};
621 FBM<3, 1, false>(P, &result, octaves, lacunarity, gain);
622 return .5 * result + .5;
625 "float fbm(vector v,int octaves=6,float lacunarity=2,float gain=.5)\n"
626 "fbm (Fractal Brownian Motion) is a multi-frequency noise function. \n"
627 "The base frequency is the same as the \"noise\" function. The total \n"
628 "number of frequencies is controlled by octaves. The lacunarity is the \n"
629 "spacing between the frequencies - a value of 2 means each octave is \n"
630 "twice the previous frequency. The gain< controls how much each \n"
631 "frequency is scaled relative to the previous frequency.";
636 double lacunarity = 2;
644 lacunarity = args[2][0];
646 octaves = int(
clamp(args[1][0], 1, 8));
652 double P[3] = {
p[0],
p[1],
p[2]};
653 FBM<3, 3, false>(P, &result[0], octaves, lacunarity, gain);
656 static const char*
vfbm_docstring =
"vector vfbm(vector vint octaves=6,float lacunarity=2,float gain=.5)";
661 double lacunarity = 2;
670 lacunarity = args[3][0];
672 octaves = int(
clamp(args[2][0], 1, 8));
674 time = static_cast<float>(args[1][0]);
680 double P[4] = {
p[0],
p[1],
p[2], time};
681 FBM<4, 1, false>(P, &result, octaves, lacunarity, gain);
682 return .5 * result + .5;
685 "float fbm4(vector v,float time,int octaves=6,float lacunarity=2,float gain=.5)\n"
686 "fbm (Fractal Brownian Motion) is a multi-frequency noise function. \n"
687 "The base frequency is the same as the \"noise\" function. The total \n"
688 "number of frequencies is controlled by octaves. The lacunarity is the \n"
689 "spacing between the frequencies - a value of 2 means each octave is \n"
690 "twice the previous frequency. The gain< controls how much each \n"
691 "frequency is scaled relative to the previous frequency.";
696 double lacunarity = 2;
705 lacunarity = args[3][0];
707 octaves = int(
clamp(args[2][0], 1, 8));
709 time = static_cast<float>(args[1][0]);
715 double P[4] = {
p[0],
p[1],
p[2], time};
716 FBM<4, 3, false>(P, &result[0], octaves, lacunarity, gain);
719 static const char*
vfbm4_docstring =
"vector vfbm4(vector v,float time,int octaves=6,float lacunarity=2,float gain=.5)";
722 static const char*
cfbm_docstring =
"color cfbm(vector vint octaves=6,float lacunarity=2,float gain=.5)";
725 static const char*
cfbm4_docstring =
"color cfbm4(vector v,float time,int octaves=6,float lacunarity=2,float gain=.5)";
729 double args[3] = {
p[0],
p[1],
p[2]};
730 CellNoise<3, 1>(args, &result);
734 "float cellnoise(vector v)\n"
735 "cellnoise generates a field of constant colored cubes based on the integer location.\n"
736 "This is the same as the prman cellnoise function.";
740 double args[3] = {
p[0],
p[1],
p[2]};
741 CellNoise<3, 3>(args, &result[0]);
745 "color cellnoise(vector v)\n"
746 "cellnoise generates a field of constant colored cubes based on the integer location.\n"
747 "This is the same as the prman cellnoise function.";
751 double args[3] = {
p[0],
p[1],
p[2]};
752 int pargs[3] = {
std::max((
int)1, (
int)period[0]),
755 PNoise<3, 1>(args, pargs, &result);
759 "float pnoise ( vector v, vector period )\n"
774 for (
double i = -1; i <= 1; i++) {
775 for (
double j = -1; j <= 1; j++) {
776 for (
double k = -1; k <= 1; k++, n++) {
787 Vec3d thiscell(floor(
p[0]) + 0.5, floor(
p[1]) + 0.5, floor(
p[2]) + 0.5);
791 Vec3d* end = pos + 27;
793 for (; pos != end; pos++) {
795 double dist = offset.
dot(offset);
812 Vec3d thiscell(floor(
p[0]) + 0.5, floor(
p[1]) + 0.5, floor(
p[2]) + 0.5);
815 Vec3d* end = pos + 27;
817 for (; pos != end; pos++) {
819 double dist = offset.
dot(offset);
825 }
else if (
dist < f2) {
841 double fbmOctaves = 4;
842 double fbmLacunarity = 2;
843 double fbmGain = 0.5;
846 fbmGain = args[6][0];
848 fbmLacunarity = args[5][0];
850 fbmOctaves = args[4][0];
852 fbmScale = args[3][0];
854 jitter =
clamp(args[2][0], 1e-3, 1);
856 type = int(args[1][0]);
864 fbmArgs[1] = fbmOctaves;
865 fbmArgs[2] = fbmLacunarity;
866 fbmArgs[3] = fbmGain;
867 p += fbmScale *
vfbm(4, fbmArgs);
889 return smoothstep(f2 - f1, 0, 0.1 * scalefactor);
896 "float voronoi(vector v, int type=1,float jitter=0.5, float fbmScale=0, int fbmOctaves=4,float fbmLacunarity=2, "
897 "float fbmGain=.5)\n"
898 "voronoi is a cellular noise pattern. It is a jittered variant of cellnoise.";
907 double fbmOctaves = 4;
908 double fbmLacunarity = 2;
909 double fbmGain = 0.5;
912 fbmGain = args[6][0];
914 fbmLacunarity = args[5][0];
916 fbmOctaves = args[4][0];
918 fbmScale = args[3][0];
920 jitter =
clamp(args[2][0], 1e-3, 1);
922 type = int(args[1][0]);
930 fbmArgs[1] = fbmOctaves;
931 fbmArgs[2] = fbmLacunarity;
932 fbmArgs[3] = fbmGain;
933 p += fbmScale *
vfbm(4, fbmArgs);
953 return (f2 - f1) * color;
956 return smoothstep(f2 - f1, 0, 0.1 * scalefactor) * color;
963 "color cvoronoi(vector v, int type=1,float jitter=0.5, float fbmScale=0, int fbmOctaves=4,float fbmLacunarity=2, "
964 "float fbmGain=.5)\n"
965 "returns color in cellular pattern. It is a jittered variant of cellnoise.";
973 double fbmOctaves = 4;
974 double fbmLacunarity = 2;
975 double fbmGain = 0.5;
978 fbmGain = args[5][0];
980 fbmLacunarity = args[4][0];
982 fbmOctaves = args[3][0];
984 fbmScale = args[2][0];
986 jitter =
clamp(args[1][0], 1e-3, 1);
994 fbmArgs[1] = fbmOctaves;
995 fbmArgs[2] = fbmLacunarity;
996 fbmArgs[3] = fbmGain;
997 p += fbmScale *
vfbm(4, fbmArgs);
1006 "color pvoronoi(vector v, int type=1,float jitter=0.5, float fbmScale=0, int fbmOctaves=4,float fbmLacunarity=2, "
1007 "float fbmGain=.5)\n"
1008 "returns center of voronoi cell.";
1018 if (nargs < 1 || nargs > 7) {
1019 node->
addError(
"Wrong number of arguments, should be 1 to 7");
1024 valid &= node->
checkArg(0, ExprType().FP(3).Varying(), envBuilder);
1025 for (
int i = 1; i < nargs; i++) valid &= node->
checkArg(i, ExprType().FP(1).Constant(), envBuilder);
1026 return valid ? ExprType().FP(3).Varying() : ExprType().Error();
1035 int nargs = args.
nargs();
1038 for (
int i = 0; i < nargs; i++)
1039 for (
int j = 0; j < 3; j++) sevArgs[i][j] = args.
inFp<3>(i)[j];
1042 double* out = &args.
outFp;
1043 for (
int i = 0; i < 3; i++) out[i] = result[i];
1052 double dist(
double ax,
double ay,
double az,
double bx,
double by,
double bz) {
1056 return sqrt(
x *
x +
y *
y +
z *
z);
1059 "float dist(vector a, vector b)\n"
1060 "distance between two points";
1062 double length(
const Vec3d& v) {
return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); }
1064 "float length(vector v)\n"
1069 "float hypot(vector v)\n"
1070 "length of 2d vector [x,y]";
1074 "float dot(vector a,vector b)\n"
1075 "vector dot product";
1085 "vector norm(vector v)\n"
1086 "vector scaled to unit length";
1089 return Vec3d(
a[1] *
b[2] -
a[2] *
b[1],
a[2] *
b[0] -
a[0] *
b[2],
a[0] *
b[1] -
a[1] *
b[0]);
1092 "vector cross(vector a,vector b)\n"
1093 "vector cross product";
1097 if (len == 0)
return 0;
1098 return acos(
dot(
a,
b) / len);
1101 "float angle(vector a,vector b)\n"
1102 "angle between two vectors (in radians)";
1106 "vector angle(vector a,vector b)\n"
1107 "normalized vector orthogonal to a and b scaled to unit length";
1110 if (n != 3)
return 0.0;
1111 const Vec3d& P = args[0];
1112 const Vec3d& axis = args[1];
1113 float angle = static_cast<float>(args[2][0]);
1114 double len = axis.
length();
1119 "vector rotate(vector v,vector axis,float angle)\n"
1120 "rotates v around axis by given angle (in radians)";
1124 Vec3d yAxis(0, 1, 0);
1128 "vector up(vector P,vector upvec)\n"
1129 "rotates v such that the Y axis points in the given up direction";
1134 int range = hi - lo + 1;
1135 if (range <= 0)
return lo;
1136 int result = int(
index) % range;
1137 if (result < 0) result += range;
1141 "int cycle(int index, int loRange, int hiRange )\n"
1142 "Cycles through values between loRange and hiRange based on supplied index.\n"
1143 "This is an offset \"mod\" function. The result is rotates v such that the\n"
1144 "Y axis points in the given up direction";
1146 double pick(
int n,
double* params) {
1147 if (n < 3)
return 0;
1152 if (range <= 0)
return loRange;
1153 int numWeights = n - 3;
1154 if (numWeights > range) numWeights = range;
1157 double* cutoffs = (
double*)alloca(
sizeof(
double) * range);
1158 double* weights = (
double*)alloca(
sizeof(
double) * range);
1160 for (
int i = 0; i < range; i++) {
1161 double weight = i < numWeights ? params[i + 3] : 1;
1164 weights[i] = weight;
1167 if (total == 0)
return loRange;
1173 int lo = 0, hi = range - 1;
1175 int m = (lo + hi) / 2;
1176 if (
index <= cutoffs[m])
1183 if (weights[lo] == 0) {
1184 if (lo > 0 && cutoffs[lo] > 0)
1185 while (--lo > 0 && weights[lo] == 0)
1187 else if (lo < range - 1)
1188 while (++lo < range - 1 && weights[lo] == 0)
1196 "int pick(float index, int loRange, int hiRange, [float weights, ...] )\n"
1197 "Picks values randomly between loRange and hiRange based on supplied index (which is\n"
1198 "automatically hashed). The values will be distributed according\n"
1199 "to the supplied weights. Any weights not supplied are assumed to\n"
1204 "color swatch(float index, color choice0, color choice1, color choice2, [...])\n"
1205 "Chooses one of the supplied color choices based on the index (assumed to be in range [0..1]).";
1208 if (n < 3)
return 0;
1209 double key = params[0];
1211 if (key != key)
return 0;
1213 return params[1 + int(
clamp(key * nvals, 0, nvals - 1))];
1216 "float choose(float index,float choice1, float choice2, [...])\n"
1217 "Chooses one of the supplied choices based on the index (assumed to be in range [0..1]).";
1220 if (n < 5)
return 0;
1221 double key = params[0];
1223 if (key != key)
return 0;
1224 int nvals = (n - 1) / 2;
1227 double* cutoffs = (
double*)alloca(
sizeof(
double) * nvals);
1228 double* weights = (
double*)alloca(
sizeof(
double) * nvals);
1230 for (
int i = 0; i < nvals; i++) {
1231 double weight = params[i * 2 + 2];
1234 weights[i] = weight;
1237 if (total == 0)
return params[1];
1243 int lo = 0, hi = nvals - 1;
1245 int m = (lo + hi) / 2;
1246 if (key <= cutoffs[m])
1253 if (weights[lo] == 0) {
1254 if (lo > 0 && cutoffs[lo] > 0)
1255 while (--lo > 0 && weights[lo] == 0)
1257 else if (lo < nvals - 1)
1258 while (++lo < nvals - 1 && weights[lo] == 0)
1263 return params[lo * 2 + 1];
1266 "float wchoose(float index,float choice1, float weight1, float choice2, float weight2, [...] )\n"
1267 "Chooses one of the supplied choices based on the index (assumed to be in range[0..1]).\n"
1268 "The values will be distributed according to the supplied weights.";
1271 if (n < 5)
return 0;
1272 double u =
clamp(params[0], 0, 1);
1273 if (u == 0)
return params[2];
1274 if (u == 1)
return params[n - 2];
1277 u = modf(u * nsegs, &seg);
1278 double*
p = ¶ms[int(seg) + 1];
1281 return 0.5 * (
p[0] * (-u3 + 2 * u2 - u) +
p[1] * (3 * u3 - 5 * u2 + 2) +
p[2] * (-3 * u3 + 4 * u2 + u) +
1285 "float spline(float param,float y1,float y2,float y3,float y4,[...])\n\n"
1286 "Interpolates a set of values to the parameter specified where y1, ..., yn are\n"
1287 "distributed evenly from [0...1]";
1302 if ((nargs - 1) % 3) {
1303 node->
addError(
"Wrong number of arguments, should be multiple of 3 plus 1");
1309 for (
int i = 1; i < nargs; i += 3) {
1319 for (
int i = 1; i < args.
nargs() - 2; i += 3) {
1320 double pos = args.
inFp<1>(i)[0];
1321 double val = args.
inFp<1>(i + 1)[0];
1322 double interpDouble = args.
inFp<1>(i + 2)[0];
1323 int interpInt = (int)interpDouble;
1328 data->
curve.addPoint(pos, val, interpolant);
1330 data->
curve.preparePoints();
1336 double param = args.
inFp<1>(0)[0];
1342 "float curve(float param,float pos0,float val0,int interp0,float pos1,float val1,int interp1,[...])\n\n"
1343 "Interpolates a 1D ramp defined by control points at 'param'. Control points are specified \n"
1344 "by triples of parameters pos_i, val_i, and interp_i. Interpolation codes are \n"
1345 "0 - none, 1 - linear, 2 - smooth, 3 - spline, \n"
1346 "4-monotone (non oscillating spline)";
1352 if ((nargs - 1) % 3) {
1353 node->
addError(
"Wrong number of arguments, should be multiple of 3 plus 1");
1359 for (
int i = 1; i < nargs; i += 3) {
1369 for (
int i = 1; i < args.
nargs() - 2; i += 3) {
1370 double pos = args.
inFp<1>(i)[0];
1372 double interpDouble = args.
inFp<1>(i + 2)[0];
1373 int interpInt = (int)interpDouble;
1378 data->
curve.addPoint(pos, val, interpolant);
1380 data->
curve.preparePoints();
1386 double param = args.
inFp<1>(0)[0];
1388 double* out = &args.
outFp;
1389 for (
int k = 0; k < 3; k++) out[k] = result[k];
1397 "color curve(float param,float pos0,color val0,int interp0,float pos1,color val1,int interp1,[...])\n\n"
1398 "Interpolates color ramp given by control points at 'param'. Control points are specified \n"
1399 "by triples of parameters pos_i, val_i, and interp_i. Interpolation codes are \n"
1400 "0 - none, 1 - linear, 2 - smooth, 3 - spline, \n"
1401 "4 - monotone (non oscillating spline)";
1405 typedef void (*
func)(
double* in,
double* out);
1414 std::string varName = node->
getStrArg(0);
1416 ExprType varType = varNode->
prep(wantScalar, envBuilder);
1417 if (varType.isValid()) {
1424 varType = node->
child(0)->
prep(wantScalar, envBuilder);
1431 return new Data(node->
type().
isFP() ? getTemplatizedOp<Assign, Data::func>(node->
type().
dim()) :
nullptr,
1437 static void f(
double* out,
double* in) {
1438 for (
int k = 0; k < d; k++) out[k] = in[k];
1443 Data* data = static_cast<Data*>(args.
data);
1445 double* out = &args.
outFp;
1449 data->
f(out, &args.
inFp<1>(0)[0]);
1451 throw std::runtime_error(
"getVar does not support non FP types right now got type");
1459 "getVar(string varName,vector defaultValue)\n"
1460 "return value of varName if variable exists, otherwise return defaultValue";
1472 node->
addError(
"Wrong number of arguments, should be GE 1");
1478 for (
int i = 1; i < nargs; ++i)
1486 unsigned int bakeStart = 0;
1487 int searchStart = 0;
1491 std::string& format = data->
format;
1492 std::vector<std::pair<int, int> >& ranges = data->
ranges;
1496 std::size_t percentStart = format.find(
'%', searchStart);
1497 if (percentStart == std::string::npos)
break;
1498 if (percentStart + 1 == format.length()) {
1502 }
else if (format[percentStart + 1] ==
'%') {
1503 searchStart = static_cast<int>(percentStart + 2);
1505 }
else if (format[percentStart + 1] ==
'v' || format[percentStart + 1] ==
'f') {
1506 char c = format[percentStart + 1];
1507 int code = (c ==
'v') ? -1 : -2;
1509 if (bakeStart != percentStart) ranges.push_back(std::pair<int, int>(bakeStart, static_cast<int>(percentStart)));
1510 ranges.push_back(std::pair<int, int>(code, code));
1512 searchStart = static_cast<int>(percentStart + 2);
1513 bakeStart = searchStart;
1523 if (bakeStart != format.length()) ranges.push_back(std::pair<int, int>(bakeStart, static_cast<int>(format.length())));
1525 if (items != args.
nargs() - 1) {
1540 for (
unsigned int i = 0; i < data->
ranges.size(); i++) {
1541 const std::pair<int, int>& range = data->
ranges[i];
1542 if (range.first == -2) {
1543 std::cerr << args.
inFp<1>(item)[0];
1545 }
else if (range.first == -1) {
1546 std::cerr <<
"[" << args.
inFp<3>(item)[0] <<
"," << args.
inFp<3>(item)[1] <<
","
1547 << args.
inFp<3>(item)[2] <<
"]";
1550 std::cerr << data->
format.substr(range.first, range.second - range.first);
1553 std::cerr << std::endl;
1562 "printf(string format,[vec0, vec1, ...])\n"
1563 "Prints out a string to STDOUT, Format parameter allowed is %v";
1590 return new MyData(args.inFp<1>(1)[0]);
1592 virtual void eval(ArgHandle args)
1594 MyData* data=static_cast<MyData*>(args.data);
1599 static const char* testfunc_docstring=
"fdsA";
1606 #define FUNCADOC(name, func) define3(name, ExprFunc(::func), func##_docstring)
1607 #define FUNCDOC(func) define3(#func, ExprFunc(::func), func##_docstring)
1627 #ifndef SEEXPR_WIN32
1639 #define FUNCDOC(func) define3(#func, ExprFunc(SeExpr2::func), func##_docstring)
1640 #define FUNCNDOC(func, min, max) define3(#func, ExprFunc(SeExpr2::func, min, max), func##_docstring)