SeExpr
ExprBuiltins.cpp
Go to the documentation of this file.
1 /*
2 * Copyright Disney Enterprises, Inc. All rights reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License
6 * and the following modification to it: Section 6 Trademarks.
7 * deleted and replaced with:
8 *
9 * 6. Trademarks. This License does not grant permission to use the
10 * trade names, trademarks, service marks, or product names of the
11 * Licensor and its affiliates, except as required for reproducing
12 * the content of the NOTICE file.
13 *
14 * You may obtain a copy of the License at
15 * http://www.apache.org/licenses/LICENSE-2.0
16 */
17 
18 #include <cassert>
19 #include <math.h>
20 #include <stdlib.h>
21 #include <limits.h>
22 #include <algorithm>
23 #include <cfloat>
24 #include "ExprFunc.h"
25 #include "ExprNode.h"
26 #include "Vec.h"
27 #include "Curve.h"
28 #include "ExprBuiltins.h"
29 #include "Platform.h"
30 #include "Noise.h"
31 #include "Interpreter.h"
32 
33 namespace SeExpr2 {
34 
35 static const char* fabs_docstring = "float abs(float x)\nabsolute value of x";
36 
37 // angle conversion functions
38 static const char* deg_docstring = "float deg(float angle)\nradians to degrees";
39 static const char* rad_docstring = "float deg(float angle)\ndegrees to radians";
40 // trig in degrees
41 static const char* cosd_docstring = "float cosd(float angle)\ncosine in degrees";
42 static const char* sind_docstring = "float sind(float angle)\nsine in degrees";
43 static const char* tand_docstring = "float tand(float angle)\ntangent in degrees";
44 static const char* acosd_docstring = "float acosd(float angle)\narc cosine in degrees";
45 static const char* asind_docstring = "float asind(float angle)\narc sine in degrees";
46 static const char* atand_docstring = "float atand(float angle)\narc tangent in degrees";
47 static const char* atan2d_docstring =
48  "float atan2d(float y,float x)\narc tangent in degrees of y/x between -180 and 180";
49 // trig in radians
50 static const char* cos_docstring = "float cos(float angle)\ncosine in radians";
51 static const char* sin_docstring = "float sin(float angle)\nsine in radians";
52 static const char* tan_docstring = "float tan(float angle)\ntangent in radians";
53 static const char* acos_docstring = "float acos(float angle)\narc cosine in radians";
54 static const char* asin_docstring = "float asin(float angle)\narc sine in radians";
55 static const char* atan_docstring = "float atan(float angle)\narc tangent in radians";
56 static const char* atan2_docstring = "float atan2(float y,float x)\narc tangent in radians of y/x between -PI and PI";
57 // hyperbolic trig
58 static const char* cosh_docstring = "float cosh(float angle)\nhyperbolic cosine in radians";
59 static const char* sinh_docstring = "float sinh(float angle)\nhyperbolic sine in radians";
60 static const char* tanh_docstring = "float tanh(float angle)\nhyperbolic tangent in radians";
61 static const char* acosh_docstring = "float acosh(float angle)\nhyperbolic arc cosine in radians";
62 static const char* asinh_docstring = "float asinh(float angle)\nhyperbolic arc sine in radians";
63 static const char* atanh_docstring = "float atanh(float angle)\nhyperbolic arc tangent in radians";
64 // clamping/rounding
65 static const char* clamp_docstring = "float clamp(float x,float lo,float hi)\nconstrain x to range [lo,hi]";
66 static const char* round_docstring = "float round(float x)\nconstrain x to range [lo,hi]";
67 static const char* max_docstring = "float max(float a,float b)\ngreater of a and b";
68 static const char* min_docstring = "float min(float a,float b)\nlesser of a and b";
69 static const char* trunc_docstring = "float trunc(float a)\nnearest integer towards zero";
70 static const char* floor_docstring = "float floor(float a)\nnext lower integer";
71 static const char* ceil_docstring = "float ceil(float a)\nnext higher integer";
72 // misc math
73 static const char* invert_docstring = "float invert(float a)\nDefined as 1-x";
74 static const char* cbrt_docstring = "float cbrt(float x)\ncube root";
75 static const char* sqrt_docstring = "float sqrt(float x)\nsquare root";
76 static const char* exp_docstring = "float exp(float x)\nE raised to the x power";
77 static const char* pow_docstring = "float pow(float x)\nx to the y power, also available as ^";
78 static const char* log_docstring = "float log(float x)\nNatural logarithm";
79 static const char* log10_docstring = "float log10(float x)\nBase 10 logarithm";
80 static const char* fmod_docstring = "float fmod(float x,float y)\nremainder of x/y (also available as % operator)";
81 static const char* turbulence_docstring =
82  "float turbulence(vector v,int octaves=6,float lacunarity=2,float gain=.5)\nAbsolute value of each noise term is "
83  "taken. This gives billowy appearance";
84 static const char* cturbulence_docstring =
85  "color cturbulence(vector v,int octaves=6,float lacunarity=2,float gain=.5)\nAbsolute value of each noise term is "
86  "taken. This gives billowy appearance";
87 static const char* vturbulence_docstring =
88  "vector vturbulence(vector v,int octaves=6,float lacunarity=2,float gain=.5)\nAbsolute value of each noise term is "
89  "taken. This gives billowy appearance";
90 
91 double compress(double x, double lo, double hi) { return (hi - lo) * x + lo; }
92 static const char* compress_docstring = "float compress(float x,float lo,float hi)\nRemaps x in [0,1] to [lo,hi]";
93 
94 double expand(double x, double lo, double hi) {
95  if (lo == hi) return x < lo ? 0 : 1;
96  return (x - lo) / (hi - lo);
97 }
98 static const char* expand_docstring = "float expand(float x,float lo,float hi)\nRemaps x in [lo,hi] to [0,1]";
99 
100 double fit(double x, double a1, double b1, double a2, double b2) {
101  return (x * (b2 - a2) - a1 * b2 + b1 * a2) / (b1 - a1);
102 }
103 static const char* fit_docstring =
104  "float fit(float x,float a1,float b1,float a2,float b2)\nLinearly remaps x in [a1,b1] to [a2,b2]";
105 
106 double gamma(double x, double g) { return pow(x, 1 / g); }
107 static const char* gamma_docstring = "float gamma(float x, float g)\nGamma correction of x with gamma factor g";
108 
109 double bias(double x, double b) {
110  static double C = 1 / log(0.5);
111  return pow(x, log(b) * C);
112 }
113 static const char* bias_docstring =
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))";
116 
117 double contrast(double x, double c) {
118  if (x < 0.5)
119  return 0.5 * bias(1 - c, 2 * x);
120  else
121  return 1 - 0.5 * bias(1 - c, 2 - 2 * x);
122 }
123 static const char* contrast_docstring =
124  "float contrast(float x,float x)\nAdjust the contrast.&nbsp; For c from 0 to 0.5, the contrast is decreased.&nbsp; "
125  "For c &gt; 0.5, the contrast is increased.";
126 
127 double boxstep(double x, double a) { return x < a ? 0.0 : 1.0; }
128 static const char* boxstep_docstring = "float boxstep(float x,float a)\n if x < a then 0 otherwise 1";
129 
130 double linearstep(double x, double a, double b) {
131  if (a < b) {
132  return x < a ? 0 : (x > b ? 1 : (x - a) / (b - a));
133  } else if (a > b) {
134  return 1 - (x < b ? 0 : (x > a ? 1 : (x - b) / (a - b)));
135  }
136  return boxstep(x, a);
137 }
138 static const char* linearstep_docstring =
139  "float linearstep(float x,float a,float b)\n if x &lt; a then 0, if x &gt; b then 1, and\nx transitions linearly "
140  "when &lt; x &lt; b ";
141 
142 double smoothstep(double x, double a, double b) {
143  if (a < b) {
144  if (x < a) return 0;
145  if (x >= b) return 1;
146  x = (x - a) / (b - a);
147  } else if (a > b) {
148  if (x <= b) return 1;
149  if (x > a) return 0;
150  x = 1 - (x - b) / (a - b);
151  } else
152  return boxstep(x, a);
153  return x * x * (3 - 2 * x);
154 }
155 static const char* smoothstep_docstring =
156  "float smoothstep(float x,float a,float b)\n if x &lt; a then 0, if x &gt; b then 1, and\nx transitions smoothly "
157  "(cubic) when &lt; x &lt; b";
158 
159 double gaussstep(double x, double a, double b) {
160  if (a < b) {
161  if (x < a) return 0;
162  if (x >= b) return 1;
163  x = 1 - (x - a) / (b - a);
164  } else if (a > b) {
165  if (x <= b) return 1;
166  if (x > a) return 0;
167  x = (x - b) / (a - b);
168  } else
169  return boxstep(x, a);
170  return pow(2, -8 * x * x);
171 }
172 static const char* gaussstep_docstring =
173  "float gasussstep(float x,float a,float b)\n if x &lt; a then 0, if x &gt; b then 1, and\nx transitions smoothly "
174  "(exponentially) when &lt; x &lt; b";
175 
176 double remap(double x, double source, double range, double falloff, double interp) {
177  range = fabs(range);
178  falloff = fabs(falloff);
179 
180  if (falloff == 0) return fabs(x - source) < range;
181 
182  double a, b;
183  if (x > source) {
184  a = source + range;
185  b = a + falloff;
186  } else {
187  a = source - range;
188  b = a - falloff;
189  }
190 
191  switch (int(interp)) {
192  case 0:
193  return linearstep(x, b, a);
194  case 1:
195  return smoothstep(x, b, a);
196  default:
197  return gaussstep(x, b, a);
198  }
199 }
200 static const char* remap_docstring =
201  "remap(float x, float\n"
202  "source, float range, float falloff, float interp)\nGeneral remapping function.\n"
203  "When x is within +/- <i>range</i> of source, the result is one.\n"
204  "The result falls to zero beyond that range over <i>falloff</i> distance.\n"
205  "The falloff shape is controlled by <i>interp</i>. Numeric values\n"
206  "or named constants may be used:\n"
207  "&nbsp;&nbsp;&nbsp;&nbsp;int <b>linear</b>\n"
208  "= 0\n"
209  "&nbsp;&nbsp;&nbsp;&nbsp;int <b>smooth</b> = 1\n"
210  "&nbsp;&nbsp;&nbsp;&nbsp;int <b>gaussian</b> = 2\n";
211 
212 double mix(double x, double y, double alpha) { return x * (1 - alpha) + y * alpha; }
213 static const char* mix_docstring = "mix(float a,float b,float alpha)\nBlend of a and b according to alpha.";
214 
215 Vec3d hsiAdjust(const Vec3d& rgb, double h, double s, double i) {
216  Vec3d hsl = rgbtohsl(rgb);
217  hsl[0] += h * (1.0 / 360);
218  hsl[1] *= s;
219  return hsltorgb(hsl) * i;
220 }
221 
222 Vec3d hsi(int n, const Vec3d* args) {
223  if (n < 4) return 0.0;
224 
225  double h = args[1][0];
226  double s = args[2][0];
227  double i = args[3][0];
228  if (n >= 5) {
229  // apply mask
230  double m = args[4][0];
231  h *= m;
232  s = (s - 1) * m + 1;
233  i = (i - 1) * m + 1;
234  }
235  return hsiAdjust(args[0], h, s, i);
236 }
237 static const char* hsi_docstring =
238  "color hsi(color x, float h, float s, float i, float map=1)\n"
239  "The hsi function shifts the hue by h\n"
240  "(in degrees) and scales the saturation and intensity by s and i\n"
241  "respectively.&nbsp; An map may be supplied which will control the shift\n"
242  "- the full shift will happen when the map is one and no shift will\n"
243  "happen when the map is zero.&nbsp; The shift will be scaled back for\n"
244  "values between zero and one.";
245 
246 Vec3d midhsi(int n, const Vec3d* args) {
247  if (n < 4) return 0.0;
248 
249  double h = args[1][0];
250  double s = args[2][0];
251  double i = args[3][0];
252  if (n >= 5) {
253  // apply mask
254  double m = args[4][0];
255  // remap from [0..1] to [-1..1]
256  m = m * 2 - 1;
257  // add falloff (if specified)
258  double falloff = 1, interp = 0;
259  if (n >= 6) falloff = args[5][0];
260  if (n >= 7) interp = args[6][0];
261  if (m < 0)
262  m = -remap(-m, 1, 0, falloff, interp);
263  else
264  m = remap(m, 1, 0, falloff, interp);
265 
266  // scale hsi values according to mask (both directions)
267  h *= m;
268  float absm = fabs(m);
269  s = s * absm + 1 - absm;
270  i = i * absm + 1 - absm;
271  if (m < 0) {
272  s = 1 / s;
273  i = 1 / i;
274  }
275  }
276  return hsiAdjust(args[0], h, s, i);
277 }
278 static const char* midhsi_docstring =
279  "color midhsi(color x, float h, float s, float i, float map, float falloff=1, int interp=0)\n"
280  "The midhsi function is just like the hsi function except that\n"
281  "the control map is centered around the mid point (value of 0.5)\n"
282  "and can scale the shift in both directions.";
283 
284 Vec3d rgbtohsl(const Vec3d& rgb) {
285  // RGB to HSL color space conversion
286  // This is based on Foley, Van Dam (2nd ed; p. 595)
287  // but extended to allow rgb values outside of 0..1
288  double R, G, B, H, S, L, x, y, sum, diff;
289  R = rgb[0];
290  G = rgb[1];
291  B = rgb[2];
292  x = R < G ? (R < B ? R : B) : (G < B ? G : B); // min(R,G,B)
293  y = R > G ? (R > B ? R : B) : (G > B ? G : B); // max(R,G,B)
294 
295  // compute lightness = avg of min and max rgb vals
296  sum = x + y;
297  diff = y - x;
298  L = sum / 2;
299  if (diff < 1e-6) // achromatic
300  return Vec3d(0, 0, L);
301 
302  // compute saturation
303  if (L <= .5) {
304  if (x < 0)
305  S = 1 - x;
306  else
307  S = diff / sum;
308  } else {
309  if (y > 1)
310  S = y;
311  else
312  S = diff / (2 - sum);
313  }
314 
315  // compute hue
316  if (R == y)
317  H = (G - B) / diff;
318  else if (G == y)
319  H = (B - R) / diff + 2;
320  else
321  H = (R - G) / diff + 4;
322  H *= 1 / 6.;
323  H -= floor(H); // make sure hue is in range 0..1
324 
325  return Vec3d(H, S, L);
326 }
327 static const char* rgbtohsl_docstring =
328  "color rgbtohsl(color rgb)\n"
329  "RGB to HSL color space conversion.\n"
330  "HSL is Hue, Saturation, Lightness (all in range [0..1] )\n"
331  "These functions have also been extended to support rgb and hsl values\n"
332  "outside of the range [0..1] in a reasonable way.&nbsp; For any rgb or\n"
333  "hsl value (except for negative s values), the conversion is\n"
334  "well-defined and reversible.";
335 
336 static double hslvalue(double x, double y, double H) {
337  H -= floor(H); // make sure hue is in range 0..1
338 
339  if (H < 1 / 6.)
340  return x + (y - x) * H * 6;
341  else if (H < 3 / 6.)
342  return y;
343  else if (H < 4 / 6.)
344  return x + (y - x) * (4 / 6. - H) * 6;
345  else
346  return x;
347 }
348 
349 Vec3d hsltorgb(const Vec3d& hsl) {
350  // HSL to RGB color space conversion
351  // This is based on Foley, Van Dam (2nd ed; p. 596)
352  // but extended to allow rgb values outside of 0..1
353  double H, S, L, R, G, B, x, y;
354  H = hsl[0];
355  S = hsl[1];
356  L = hsl[2];
357  if (S <= 0) // achromatic
358  return Vec3d(L, L, L);
359 
360  // find min/max rgb values
361  if (L < 0.5) {
362  if (S > 1)
363  y = 2 * L + S - 1;
364  else
365  y = L + L * S;
366  } else {
367  if (S > 1)
368  y = S;
369  else
370  y = L + S - L * S;
371  }
372  x = 2 * L - y;
373 
374  // reconstruct rgb from min,max,hue
375  R = hslvalue(x, y, H + (1 / 3.));
376  G = hslvalue(x, y, H);
377  B = hslvalue(x, y, H - (1 / 3.));
378  return Vec3d(R, G, B);
379 }
380 static const char* hsltorgb_docstring =
381  "color hsltorgb(color hsl)\n"
382  "RGB to HSL color space conversion.\n"
383  "HSL is Hue, Saturation, Lightness (all in range [0..1] )\n"
384  "These functions have also been extended to support rgb and hsl values\n"
385  "outside of the range [0..1] in a reasonable way.&nbsp; For any rgb or\n"
386  "hsl value (except for negative s values), the conversion is\n"
387  "well-defined and reversible.";
388 
389 static Vec3d saturate(const Vec3d& Cin, double amt) {
390  const Vec3d lum(.2126,.7152,.0722); // rec709 luminance
391  Vec3d result = Vec3d(Cin.dot(lum) * (1-amt)) + Cin * amt;
392  if (result[0] < 0) result[0] = 0;
393  if (result[1] < 0) result[1] = 0;
394  if (result[2] < 0) result[2] = 0;
395  return result;
396 }
397 
398 Vec3d saturate(int n, const Vec3d* args) {
399  if (n < 2) return 0.0;
400  return saturate(args[0], args[1][0]);
401 }
402 static const char* saturate_docstring =
403  "color saturate(color val, float amt)\n"
404  "Scale saturation of color by amt.\n"
405  "The color is scaled around the rec709 luminance value,\n"
406  "and negative results are clamped at zero.\n";
407 
408 double hash(int n, double* args) {
409  // combine args into a single seed
410  uint32_t seed = 0;
411  for (int i = 0; i < n; i++) {
412  // make irrational to generate fraction and combine xor into 32 bits
413  int exp = 0;
414  double frac = frexp(args[i] * double(M_E * M_PI), &exp);
415  uint32_t s = (uint32_t)(frac * UINT32_MAX) ^ (uint32_t)exp;
416 
417  // blend with seed (constants from Numerical Recipes, attrib. from Knuth)
418  static const uint32_t M = 1664525, C = 1013904223;
419  seed = seed * M + s + C;
420  }
421 
422  // tempering (from Matsumoto)
423  seed ^= (seed >> 11);
424  seed ^= (seed << 7) & 0x9d2c5680UL;
425  seed ^= (seed << 15) & 0xefc60000UL;
426  seed ^= (seed >> 18);
427 
428  // permute
429  static unsigned char p[256] = {
430  148, 201, 203, 34, 85, 225, 163, 200, 174, 137, 51, 24, 19, 252, 107, 173, 110, 251, 149, 69, 180, 152,
431  141, 132, 22, 20, 147, 219, 37, 46, 154, 114, 59, 49, 155, 161, 239, 77, 47, 10, 70, 227, 53, 235,
432  30, 188, 143, 73, 88, 193, 214, 194, 18, 120, 176, 36, 212, 84, 211, 142, 167, 57, 153, 71, 159, 151,
433  126, 115, 229, 124, 172, 101, 79, 183, 32, 38, 68, 11, 67, 109, 221, 3, 4, 61, 122, 94, 72, 117,
434  12, 240, 199, 76, 118, 5, 48, 197, 128, 62, 119, 89, 14, 45, 226, 195, 80, 50, 40, 192, 60, 65,
435  166, 106, 90, 215, 213, 232, 250, 207, 104, 52, 182, 29, 157, 103, 242, 97, 111, 17, 8, 175, 254, 108,
436  208, 224, 191, 112, 105, 187, 43, 56, 185, 243, 196, 156, 246, 249, 184, 7, 135, 6, 158, 82, 130, 234,
437  206, 255, 160, 236, 171, 230, 42, 98, 54, 74, 209, 205, 33, 177, 15, 138, 178, 44, 116, 96, 140, 253,
438  233, 125, 21, 133, 136, 86, 245, 58, 23, 1, 75, 165, 92, 217, 39, 0, 218, 91, 179, 55, 238, 170,
439  134, 83, 25, 189, 216, 100, 129, 150, 241, 210, 123, 99, 2, 164, 16, 220, 121, 139, 168, 64, 190, 9,
440  31, 228, 95, 247, 244, 81, 102, 145, 204, 146, 26, 87, 113, 198, 181, 127, 237, 169, 28, 93, 27, 41,
441  231, 248, 78, 162, 13, 186, 63, 66, 131, 202, 35, 144, 222, 223};
442  union {
443  uint32_t i;
444  unsigned char c[4];
445  } u1, u2;
446  u1.i = seed;
447  u2.c[3] = p[u1.c[0]];
448  u2.c[2] = p[(u1.c[1] + u2.c[3]) & 0xff];
449  u2.c[1] = p[(u1.c[2] + u2.c[2]) & 0xff];
450  u2.c[0] = p[(u1.c[3] + u2.c[1]) & 0xff];
451 
452  // scale to [0.0 .. 1.0]
453  return u2.i * (1.0 / UINT32_MAX);
454 }
455 static const char* hash_docstring =
456  "float hash(float seed1,[float seed2, ...])\n"
457  "Like rand, but with no internal seeds. Any number of seeds may be given\n"
458  "and the result will be a random function based on all the seeds.";
459 
460 double noise(int n, const Vec3d* args) {
461  if (n < 1) return 0;
462  if (n == 1) {
463  // 1 arg = vector arg
464  double result;
465  double p[3] = {args[0][0], args[0][1], args[0][2]};
466  Noise<3, 1>(p, &result);
467  return .5 * result + .5;
468  }
469  // scalar args
470  if (n > 4) n = 4;
471  double p[4];
472  for (int i = 0; i < n; i++) p[i] = args[i][0];
473  double result;
474  switch (n) {
475  case 1:
476  Noise<1, 1>(p, &result);
477  break;
478  case 2:
479  Noise<2, 1>(p, &result);
480  break;
481  case 3:
482  Noise<3, 1>(p, &result);
483  break;
484  case 4:
485  Noise<4, 1>(p, &result);
486  break;
487  default:
488  result = 0;
489  break;
490  }
491  return .5 * result + .5;
492 }
493 static const char* noise_docstring =
494  "float noise ( vector v ) <br>\n"
495  "float noise ( float x, float y )\n"
496  "float noise ( float x, float y, float z )\n"
497  "float noise ( float x, float y, float z, float w )\n"
498  "Original perlin noise at location (C2 interpolant)";
499 
500 double snoise(const Vec3d& p) {
501  double result;
502  double args[3] = {p[0], p[1], p[2]};
503  Noise<3, 1>(args, &result);
504  return result;
505 }
506 static const char* snoise_docstring =
507  "float snoise ( vector v)\n"
508  "signed noise w/ range -1 to 1 formed with original perlin noise at location (C2 interpolant)";
509 
510 Vec3d vnoise(const Vec3d& p) {
511  Vec3d result;
512  double args[3] = {p[0], p[1], p[2]};
513  Noise<3, 3>(args, &result[0]);
514  return result;
515 }
516 static const char* vnoise_docstring =
517  "vector vnoise ( vector v)\n"
518  "vector noise formed with original perlin noise at location (C2 interpolant)";
519 
520 Vec3d cnoise(const Vec3d& p) { return .5 * vnoise(p) + Vec3d(.5); }
521 static const char* cnoise_docstring =
522  "color cnoise ( vector v)\n"
523  "color noise formed with original perlin noise at location (C2 interpolant)";
524 
525 double snoise4(int n, const Vec3d* args) {
526  double result;
527  double procargs[4] = {args[0][0], args[0][1], args[0][2], args[1][0]};
528  Noise<4, 1>(procargs, &result);
529  return result;
530 }
531 static const char* snoise4_docstring =
532  "float snoise4 ( vector v,float t)\n"
533  "4D signed noise w/ range -1 to 1 formed with original perlin noise at location (C2 interpolant)";
534 
535 Vec3d vnoise4(int n, const Vec3d* args) {
536  Vec3d result;
537  double procargs[4] = {args[0][0], args[0][1], args[0][2], args[1][0]};
538  Noise<4, 3>(procargs, &result[0]);
539  return result;
540 }
541 static const char* vnoise4_docstring =
542  "vector vnoise4 ( vector v,float t)\n"
543  "4D vector noise formed with original perlin noise at location (C2 interpolant)";
544 
545 Vec3d cnoise4(int n, const Vec3d* args) { return .5 * vnoise4(n, args) + Vec3d(.5); }
546 static const char* cnoise4_docstring =
547  "color cnoise4 ( vector v,float t)\n"
548  "4D color noise formed with original perlin noise at location (C2 interpolant)";
549 
550 double turbulence(int n, const Vec3d* args) {
551  // args: octaves, lacunarity, gain
552  int octaves = 6;
553  double lacunarity = 2;
554  double gain = 0.5;
555  Vec3d p = 0.0;
556 
557  switch (n) {
558  case 4:
559  gain = args[3][0];
560  case 3:
561  lacunarity = args[2][0];
562  case 2:
563  octaves = int(clamp(args[1][0], 1, 8));
564  case 1:
565  p = args[0];
566  }
567 
568  double result = 0;
569  double P[3] = {p[0], p[1], p[2]};
570  FBM<3, 1, true>(P, &result, octaves, lacunarity, gain);
571  return .5 * result + .5;
572 }
573 
574 Vec3d vturbulence(int n, const Vec3d* args) {
575  // args: octaves, lacunarity, gain
576  int octaves = 6;
577  double lacunarity = 2;
578  double gain = 0.5;
579  Vec3d p = 0.0;
580 
581  switch (n) {
582  case 4:
583  gain = args[3][0];
584  case 3:
585  lacunarity = args[2][0];
586  case 2:
587  octaves = int(clamp(args[1][0], 1, 8));
588  case 1:
589  p = args[0];
590  }
591 
592  Vec3d result;
593  double P[3] = {p[0], p[1], p[2]};
594  FBM<3, 3, true>(P, &result[0], octaves, lacunarity, gain);
595  return result;
596 }
597 
598 Vec3d cturbulence(int n, const Vec3d* args) { return vturbulence(n, args) * .5 + Vec3d(.5); }
599 
600 double fbm(int n, const Vec3d* args) {
601  // args: octaves, lacunarity, gain
602  int octaves = 6;
603  double lacunarity = 2;
604  double gain = 0.5;
605  Vec3d p = 0.0;
606 
607  switch (n) {
608  case 4:
609  gain = args[3][0];
610  case 3:
611  lacunarity = args[2][0];
612  case 2:
613  octaves = int(clamp(args[1][0], 1, 8));
614  case 1:
615  p = args[0];
616  }
617 
618  double result = 0.0;
619  double P[3] = {p[0], p[1], p[2]};
620  FBM<3, 1, false>(P, &result, octaves, lacunarity, gain);
621  return .5 * result + .5;
622 }
623 static const char* fbm_docstring =
624  "float fbm(vector v,int octaves=6,float lacunarity=2,float gain=.5)\n"
625  "fbm (Fractal Brownian Motion) is a multi-frequency noise function. \n"
626  "The base frequency is the same as the \"noise\" function. The total \n"
627  "number of frequencies is controlled by octaves. The lacunarity is the \n"
628  "spacing between the frequencies - a value of 2 means each octave is \n"
629  "twice the previous frequency. The gain< controls how much each \n"
630  "frequency is scaled relative to the previous frequency.";
631 
632 Vec3d vfbm(int n, const Vec3d* args) {
633  // args: octaves, lacunarity, gain
634  int octaves = 6;
635  double lacunarity = 2;
636  double gain = 0.5;
637  Vec3d p = 0.0;
638 
639  switch (n) {
640  case 4:
641  gain = args[3][0];
642  case 3:
643  lacunarity = args[2][0];
644  case 2:
645  octaves = int(clamp(args[1][0], 1, 8));
646  case 1:
647  p = args[0];
648  }
649 
650  Vec3d result = 0.0;
651  double P[3] = {p[0], p[1], p[2]};
652  FBM<3, 3, false>(P, &result[0], octaves, lacunarity, gain);
653  return result;
654 }
655 static const char* vfbm_docstring = "vector vfbm(vector vint octaves=6,float lacunarity=2,float gain=.5)";
656 
657 double fbm4(int n, const Vec3d* args) {
658  // args: octaves, lacunarity, gain
659  int octaves = 6;
660  double lacunarity = 2;
661  double gain = 0.5;
662  Vec3d p = 0.0;
663  float time = 0.0;
664 
665  switch (n) {
666  case 5:
667  gain = args[4][0];
668  case 4:
669  lacunarity = args[3][0];
670  case 3:
671  octaves = int(clamp(args[2][0], 1, 8));
672  case 2:
673  time = args[1][0];
674  case 1:
675  p = args[0];
676  }
677 
678  double result = 0.0;
679  double P[4] = {p[0], p[1], p[2], time};
680  FBM<4, 1, false>(P, &result, octaves, lacunarity, gain);
681  return .5 * result + .5;
682 }
683 static const char* fbm4_docstring =
684  "float fbm4(vector v,float time,int octaves=6,float lacunarity=2,float gain=.5)\n"
685  "fbm (Fractal Brownian Motion) is a multi-frequency noise function. \n"
686  "The base frequency is the same as the \"noise\" function. The total \n"
687  "number of frequencies is controlled by octaves. The lacunarity is the \n"
688  "spacing between the frequencies - a value of 2 means each octave is \n"
689  "twice the previous frequency. The gain< controls how much each \n"
690  "frequency is scaled relative to the previous frequency.";
691 
692 Vec3d vfbm4(int n, const Vec3d* args) {
693  // args: octaves, lacunarity, gain
694  int octaves = 6;
695  double lacunarity = 2;
696  double gain = 0.5;
697  Vec3d p = 0.0;
698  float time = 0.0;
699 
700  switch (n) {
701  case 5:
702  gain = args[4][0];
703  case 4:
704  lacunarity = args[3][0];
705  case 3:
706  octaves = int(clamp(args[2][0], 1, 8));
707  case 2:
708  time = args[1][0];
709  case 1:
710  p = args[0];
711  }
712 
713  Vec3d result = 0.0;
714  double P[4] = {p[0], p[1], p[2], time};
715  FBM<4, 3, false>(P, &result[0], octaves, lacunarity, gain);
716  return result;
717 }
718 static const char* vfbm4_docstring = "vector vfbm4(vector v,float time,int octaves=6,float lacunarity=2,float gain=.5)";
719 
720 Vec3d cfbm(int n, const Vec3d* args) { return vfbm(n, args) * .5 + Vec3d(.5); }
721 static const char* cfbm_docstring = "color cfbm(vector vint octaves=6,float lacunarity=2,float gain=.5)";
722 
723 Vec3d cfbm4(int n, const Vec3d* args) { return vfbm4(n, args) * .5 + Vec3d(.5); }
724 static const char* cfbm4_docstring = "color cfbm4(vector v,float time,int octaves=6,float lacunarity=2,float gain=.5)";
725 
726 double cellnoise(const Vec3d& p) {
727  double result;
728  double args[3] = {p[0], p[1], p[2]};
729  CellNoise<3, 1>(args, &result);
730  return result;
731 }
732 static const char* cellnoise_docstring =
733  "float cellnoise(vector v)\n"
734  "cellnoise generates a field of constant colored cubes based on the integer location.\n"
735  "This is the same as the prman cellnoise function.";
736 
738  Vec3d result;
739  double args[3] = {p[0], p[1], p[2]};
740  CellNoise<3, 3>(args, &result[0]);
741  return result;
742 }
743 static const char* ccellnoise_docstring =
744  "color cellnoise(vector v)\n"
745  "cellnoise generates a field of constant colored cubes based on the integer location.\n"
746  "This is the same as the prman cellnoise function.";
747 
748 double pnoise(const Vec3d& p, const Vec3d& period) {
749  double result;
750  double args[3] = {p[0], p[1], p[2]};
751  int pargs[3] = {max(1,(int)period[0]),
752  max(1,(int)period[1]),
753  max(1,(int)period[2])};
754  PNoise<3, 1>(args, pargs, &result);
755  return result;
756 }
757 static const char* pnoise_docstring =
758  "float pnoise ( vector v, vector period )\n"
759  "periodic noise";
763  double jitter;
765 };
766 
767 static Vec3d* voronoi_points(VoronoiPointData& data, const Vec3d& cell, double jitter) {
768  if (cell == data.cell && jitter == data.jitter) return data.points;
769  data.cell = cell;
770  data.jitter = jitter;
771 
772  int n = 0;
773  for (double i = -1; i <= 1; i++) {
774  for (double j = -1; j <= 1; j++) {
775  for (double k = -1; k <= 1; k++, n++) {
776  Vec3d testcell = cell + Vec3d(i, j, k);
777  data.points[n] = testcell + jitter * (ccellnoise(testcell) - Vec3d(.5));
778  }
779  }
780  }
781  return data.points;
782 }
783 
784 static void voronoi_f1_3d(VoronoiPointData& data, const Vec3d& p, double jitter, double& f1, Vec3d& pos1) {
785  // from Advanced Renderman, page 257
786  Vec3d thiscell(floor(p[0]) + 0.5, floor(p[1]) + 0.5, floor(p[2]) + 0.5);
787 
788  f1 = 1000;
789  Vec3d* pos = voronoi_points(data, thiscell, jitter);
790  Vec3d* end = pos + 27;
791 
792  for (; pos != end; pos++) {
793  Vec3d offset = *pos - p;
794  double dist = offset.dot(offset);
795  if (dist < f1) {
796  f1 = dist;
797  pos1 = *pos;
798  }
799  }
800  f1 = sqrt(f1);
801 }
802 
804  const Vec3d& p,
805  double jitter,
806  double& f1,
807  Vec3d& pos1,
808  double& f2,
809  Vec3d& pos2) {
810  // from Advanced Renderman, page 258
811  Vec3d thiscell(floor(p[0]) + 0.5, floor(p[1]) + 0.5, floor(p[2]) + 0.5);
812  f1 = f2 = 1000;
813  Vec3d* pos = voronoi_points(data, thiscell, jitter);
814  Vec3d* end = pos + 27;
815 
816  for (; pos != end; pos++) {
817  Vec3d offset = *pos - p;
818  double dist = offset.dot(offset);
819  if (dist < f1) {
820  f2 = f1;
821  pos2 = pos1;
822  f1 = dist;
823  pos1 = *pos;
824  } else if (dist < f2) {
825  f2 = dist;
826  pos2 = *pos;
827  }
828  }
829  f1 = sqrt(f1);
830  f2 = sqrt(f2);
831 }
832 
833 Vec3d voronoiFn(VoronoiPointData& data, int n, const Vec3d* args) {
834  // args = p, type, jitter,
835  // fbmScale, fbmOctaves, fbmLacunarity, fbmGain
836  Vec3d p;
837  int type = 1;
838  double jitter = 0.5;
839  double fbmScale = 0;
840  double fbmOctaves = 4;
841  double fbmLacunarity = 2;
842  double fbmGain = 0.5;
843  switch (n) {
844  case 7:
845  fbmGain = args[6][0];
846  case 6:
847  fbmLacunarity = args[5][0];
848  case 5:
849  fbmOctaves = args[4][0];
850  case 4:
851  fbmScale = args[3][0];
852  case 3:
853  jitter = clamp(args[2][0], 1e-3, 1);
854  case 2:
855  type = int(args[1][0]);
856  case 1:
857  p = args[0];
858  }
859 
860  if (fbmScale > 0) {
861  Vec3d fbmArgs[4];
862  fbmArgs[0] = 2 * p;
863  fbmArgs[1] = fbmOctaves;
864  fbmArgs[2] = fbmLacunarity;
865  fbmArgs[3] = fbmGain;
866  p += fbmScale * vfbm(4, fbmArgs);
867  }
868 
869  double f1, f2;
870  Vec3d pos1, pos2;
871  if (type >= 3)
872  voronoi_f1f2_3d(data, p, jitter, f1, pos1, f2, pos2);
873  else
874  voronoi_f1_3d(data, p, jitter, f1, pos1);
875 
876  switch (type) {
877  case 1:
878  pos1[0] += 10;
879  return cellnoise(pos1);
880  case 2:
881  return f1;
882  case 3:
883  return f2;
884  case 4:
885  return f2 - f1;
886  case 5: {
887  float scalefactor = (pos2 - pos1).length() / ((pos1 - p).length() + (pos2 - p).length());
888  return smoothstep(f2 - f1, 0, 0.1 * scalefactor);
889  }
890  }
891 
892  return 0.0;
893 }
894 const static char* voronoi_docstring =
895  "float voronoi(vector v, int type=1,float jitter=0.5, float fbmScale=0, int fbmOctaves=4,float fbmLacunarity=2, "
896  "float fbmGain=.5)\n"
897  "voronoi is a cellular noise pattern. It is a jittered variant of cellnoise.";
898 
899 Vec3d cvoronoiFn(VoronoiPointData& data, int n, const Vec3d* args) {
900  // args = p, type, jitter,
901  // fbmScale, fbmOctaves, fbmLacunarity, fbmGain
902  Vec3d p;
903  int type = 1;
904  double jitter = 0.5;
905  double fbmScale = 0;
906  double fbmOctaves = 4;
907  double fbmLacunarity = 2;
908  double fbmGain = 0.5;
909  switch (n) {
910  case 7:
911  fbmGain = args[6][0];
912  case 6:
913  fbmLacunarity = args[5][0];
914  case 5:
915  fbmOctaves = args[4][0];
916  case 4:
917  fbmScale = args[3][0];
918  case 3:
919  jitter = clamp(args[2][0], 1e-3, 1);
920  case 2:
921  type = int(args[1][0]);
922  case 1:
923  p = args[0];
924  }
925 
926  if (fbmScale > 0) {
927  Vec3d fbmArgs[4];
928  fbmArgs[0] = 2 * p;
929  fbmArgs[1] = fbmOctaves;
930  fbmArgs[2] = fbmLacunarity;
931  fbmArgs[3] = fbmGain;
932  p += fbmScale * vfbm(4, fbmArgs);
933  }
934 
935  double f1, f2;
936  Vec3d pos1, pos2;
937  if (type >= 3)
938  voronoi_f1f2_3d(data, p, jitter, f1, pos1, f2, pos2);
939  else
940  voronoi_f1_3d(data, p, jitter, f1, pos1);
941 
942  Vec3d color = ccellnoise(pos1);
943  switch (type) {
944  case 1:
945  pos1[0] += 10;
946  return color;
947  case 2:
948  return f1 * color;
949  case 3:
950  return f2 * color;
951  case 4:
952  return (f2 - f1) * color;
953  case 5: {
954  float scalefactor = (pos2 - pos1).length() / ((pos1 - p).length() + (pos2 - p).length());
955  return smoothstep(f2 - f1, 0, 0.1 * scalefactor) * color;
956  }
957  }
958 
959  return 0.0;
960 }
961 const static char* cvoronoi_docstring =
962  "color cvoronoi(vector v, int type=1,float jitter=0.5, float fbmScale=0, int fbmOctaves=4,float fbmLacunarity=2, "
963  "float fbmGain=.5)\n"
964  "returns color in cellular pattern. It is a jittered variant of cellnoise.";
965 
966 Vec3d pvoronoiFn(VoronoiPointData& data, int n, const Vec3d* args) {
967  // args = p, jitter,
968  // fbmScale, fbmOctaves, fbmLacunarity, fbmGain
969  Vec3d p;
970  double jitter = 0.5;
971  double fbmScale = 0;
972  double fbmOctaves = 4;
973  double fbmLacunarity = 2;
974  double fbmGain = 0.5;
975  switch (n) {
976  case 6:
977  fbmGain = args[5][0];
978  case 5:
979  fbmLacunarity = args[4][0];
980  case 4:
981  fbmOctaves = args[3][0];
982  case 3:
983  fbmScale = args[2][0];
984  case 2:
985  jitter = clamp(args[1][0], 1e-3, 1);
986  case 1:
987  p = args[0];
988  }
989 
990  if (fbmScale > 0) {
991  Vec3d fbmArgs[4];
992  fbmArgs[0] = 2 * p;
993  fbmArgs[1] = fbmOctaves;
994  fbmArgs[2] = fbmLacunarity;
995  fbmArgs[3] = fbmGain;
996  p += fbmScale * vfbm(4, fbmArgs);
997  }
998 
999  double f1;
1000  Vec3d pos1;
1001  voronoi_f1_3d(data, p, jitter, f1, pos1);
1002  return pos1;
1003 }
1004 const static char* pvoronoi_docstring =
1005  "color pvoronoi(vector v, int type=1,float jitter=0.5, float fbmScale=0, int fbmOctaves=4,float fbmLacunarity=2, "
1006  "float fbmGain=.5)\n"
1007  "returns center of voronoi cell.";
1008 
1009 class CachedVoronoiFunc : public ExprFuncSimple {
1010  public:
1011  typedef Vec3d VoronoiFunc(VoronoiPointData& data, int n, const Vec3d* args);
1013 
1014  virtual ExprType prep(ExprFuncNode* node, bool scalarWanted, ExprVarEnvBuilder& envBuilder) const {
1015  // check number of arguments
1016  int nargs = node->numChildren();
1017  if (nargs < 1 || nargs > 7) {
1018  node->addError("Wrong number of arguments, should be 1 to 7");
1019  return ExprType().Error();
1020  }
1021 
1022  bool valid = true;
1023  valid &= node->checkArg(0, ExprType().FP(3).Varying(), envBuilder);
1024  for (int i = 1; i < nargs; i++) valid &= node->checkArg(i, ExprType().FP(1).Constant(), envBuilder);
1025  return valid ? ExprType().FP(3).Varying() : ExprType().Error();
1026  }
1028  virtual ExprFuncNode::Data* evalConstant(const ExprFuncNode* node, ArgHandle args) const {
1029  return new VoronoiPointData();
1030  }
1031 
1032  virtual void eval(ArgHandle args) {
1033  VoronoiPointData* data = static_cast<VoronoiPointData*>(args.data);
1034  int nargs = args.nargs();
1035  Vec3d* sevArgs = (Vec3d*)alloca(sizeof(Vec3d) * nargs);
1036 
1037  for (int i = 0; i < nargs; i++)
1038  for (int j = 0; j < 3; j++) sevArgs[i][j] = args.inFp<3>(i)[j];
1039 
1040  Vec3d result = _vfunc(*data, nargs, sevArgs);
1041  double* out = &args.outFp;
1042  for (int i = 0; i < 3; i++) out[i] = result[i];
1043  }
1044 
1045  virtual ~CachedVoronoiFunc() {}
1046 
1047  private:
1050 
1051 double dist(double ax, double ay, double az, double bx, double by, double bz) {
1052  double x = ax - bx;
1053  double y = ay - by;
1054  double z = az - bz;
1055  return sqrt(x * x + y * y + z * z);
1056 }
1057 static const char* dist_docstring =
1058  "float dist(vector a, vector b)\n"
1059  "distance between two points";
1060 
1061 double length(const Vec3d& v) { return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); }
1062 static const char* length_docstring =
1063  "float length(vector v)\n"
1064  "length of vector";
1065 
1066 double hypot(double x, double y) { return sqrt(x * x + y * y); }
1067 static const char* hypot_docstring =
1068  "float hypot(vector v)\n"
1069  "length of 2d vector [x,y]";
1070 
1071 double dot(const Vec3d& a, const Vec3d& b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; }
1072 static const char* dot_docstring =
1073  "float dot(vector a,vector b)\n"
1074  "vector dot product";
1075 
1076 Vec3d norm(const Vec3d& a) {
1077  double len = length(a);
1078  if (len == 0)
1079  return 0.0;
1080  else
1081  return a / len;
1082 }
1083 static const char* norm_docstring =
1084  "vector norm(vector v)\n"
1085  "vector scaled to unit length";
1086 
1087 Vec3d cross(const Vec3d& a, const Vec3d& b) {
1088  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]);
1089 }
1090 static const char* cross_docstring =
1091  "vector cross(vector a,vector b)\n"
1092  "vector cross product";
1093 
1094 double angle(const Vec3d& a, const Vec3d& b) {
1095  double len = length(a) * length(b);
1096  if (len == 0) return 0;
1097  return acos(dot(a, b) / len);
1098 }
1099 static const char* angle_docstring =
1100  "float angle(vector a,vector b)\n"
1101  "angle between two vectors (in radians)";
1102 
1103 Vec3d ortho(const Vec3d& a, const Vec3d& b) { return norm(cross(a, b)); }
1104 static const char* ortho_docstring =
1105  "vector angle(vector a,vector b)\n"
1106  "normalized vector orthogonal to a and b scaled to unit length";
1107 
1108 Vec3d rotate(int n, const Vec3d* args) {
1109  if (n != 3) return 0.0;
1110  const Vec3d& P = args[0];
1111  const Vec3d& axis = args[1];
1112  float angle = args[2][0];
1113  double len = axis.length();
1114  if (!len) return P;
1115  return P.rotateBy(axis / len, angle);
1116 }
1117 static const char* rotate_docstring =
1118  "vector rotate(vector v,vector axis,float angle)\n"
1119  "rotates v around axis by given angle (in radians)";
1120 
1121 Vec3d up(const Vec3d& P, const Vec3d& upvec) {
1122  // rotate vec so y-axis points to upvec
1123  Vec3d yAxis(0, 1, 0);
1124  return P.rotateBy(ortho(upvec, yAxis), angle(upvec, yAxis));
1125 }
1126 static const char* up_docstring =
1127  "vector up(vector P,vector upvec)\n"
1128  "rotates v such that the Y axis points in the given up direction";
1129 
1130 double cycle(double index, double loRange, double hiRange) {
1131  int lo = int(loRange);
1132  int hi = int(hiRange);
1133  int range = hi - lo + 1;
1134  if (range <= 0) return lo;
1135  int result = int(index) % range;
1136  if (result < 0) result += range;
1137  return lo + result;
1138 }
1139 static const char* cycle_docstring =
1140  "int cycle(int index, int loRange, int hiRange )\n"
1141  "Cycles through values between loRange and hiRange based on supplied index.\n"
1142  "This is an offset \"mod\" function. The result is rotates v such that the\n"
1143  "Y axis points in the given up direction";
1144 
1145 double pick(int n, double* params) {
1146  if (n < 3) return 0;
1147  double index = hash(1, &params[0]);
1148  int loRange = int(params[1]);
1149  int hiRange = int(params[2]);
1150  int range = hiRange - loRange + 1;
1151  if (range <= 0) return loRange;
1152  int numWeights = n - 3;
1153  if (numWeights > range) numWeights = range;
1154 
1155  // build cutoff points based on weights
1156  double* cutoffs = (double*)alloca(sizeof(double) * range);
1157  double* weights = (double*)alloca(sizeof(double) * range);
1158  double total = 0;
1159  for (int i = 0; i < range; i++) {
1160  double weight = i < numWeights ? params[i + 3] : 1;
1161  total += weight;
1162  cutoffs[i] = total;
1163  weights[i] = weight;
1164  }
1165 
1166  if (total == 0) return loRange;
1167 
1168  // scale value from [0..1] to [0..total] range
1169  index *= total;
1170 
1171  // bsearch cutoff table to find index that spans value
1172  int lo = 0, hi = range - 1;
1173  while (lo < hi) {
1174  int m = (lo + hi) / 2;
1175  if (index <= cutoffs[m])
1176  hi = m;
1177  else
1178  lo = m + 1;
1179  }
1180 
1181  // skip zero-length intervals
1182  if (weights[lo] == 0) {
1183  if (lo > 0 && cutoffs[lo] > 0) // scan backward if possible
1184  while (--lo > 0 && weights[lo] == 0)
1185  ;
1186  else if (lo < range - 1) // else scan forward if possible
1187  while (++lo < range - 1 && weights[lo] == 0)
1188  ;
1189  }
1190 
1191  // add offset and return result
1192  return loRange + lo;
1193 }
1194 static const char* pick_docstring =
1195  "int pick(float index, int loRange, int hiRange, [float weights, ...] )\n"
1196  "Picks values randomly between loRange and hiRange based on supplied index (which is\n"
1197  "automatically hashed).&nbsp; The values will be distributed according\n"
1198  "to the supplied weights.&nbsp; Any weights not supplied are assumed to\n"
1199  "be 1.0.";
1200 
1201 double swatch(int n, double* params) {
1202  return choose(n, params);
1203  }
1204 static const char *swatch_docstring=
1205  "color swatch(float index, color choice0, color choice1, color choice2, [...])\n"
1206  "Chooses one of the supplied color choices based on the index (assumed to be in range [0..1]).";
1207 
1208 double choose(int n, double* params) {
1209  if (n < 3) return 0;
1210  double key = params[0];
1211  // NaN protection
1212  if (key != key) return 0;
1213  int nvals = n - 1;
1214  return params[1 + int(clamp(key * nvals, 0, nvals - 1))];
1215 }
1216 static const char* choose_docstring =
1217  "float choose(float index,float choice1, float choice2, [...])\n"
1218  "Chooses one of the supplied choices based on the index (assumed to be in range [0..1]).";
1219 
1220 double wchoose(int n, double* params) {
1221  if (n < 5) return 0;
1222  double key = params[0];
1223  // NaN protection
1224  if (key != key) return 0;
1225  int nvals = (n - 1) / 2; // nweights = nvals
1226 
1227  // build cutoff points based on weights
1228  double* cutoffs = (double*)alloca(sizeof(double) * nvals);
1229  double* weights = (double*)alloca(sizeof(double) * nvals);
1230  double total = 0;
1231  for (int i = 0; i < nvals; i++) {
1232  double weight = params[i * 2 + 2];
1233  total += weight;
1234  cutoffs[i] = total;
1235  weights[i] = weight;
1236  }
1237 
1238  if (total == 0) return params[1];
1239 
1240  // scale value from [0..1] to [0..total] range
1241  key *= total;
1242 
1243  // bsearch cutoff table to find index that spans value
1244  int lo = 0, hi = nvals - 1;
1245  while (lo < hi) {
1246  int m = (lo + hi) / 2;
1247  if (key <= cutoffs[m])
1248  hi = m;
1249  else
1250  lo = m + 1;
1251  }
1252 
1253  // skip zero-length intervals
1254  if (weights[lo] == 0) {
1255  if (lo > 0 && cutoffs[lo] > 0) // scan backward if possible
1256  while (--lo > 0 && weights[lo] == 0)
1257  ;
1258  else if (lo < nvals - 1) // else scan forward if possible
1259  while (++lo < nvals - 1 && weights[lo] == 0)
1260  ;
1261  }
1262 
1263  // return corresponding value
1264  return params[lo * 2 + 1];
1265 }
1266 static const char* wchoose_docstring =
1267  "float wchoose(float index,float choice1, float weight1, float choice2, float weight2, [...] )\n"
1268  "Chooses one of the supplied choices based on the index (assumed to be in range[0..1]).\n"
1269  "The values will be distributed according to the supplied weights.";
1270 
1271 double spline(int n, double* params) {
1272  if (n < 5) return 0;
1273  double u = clamp(params[0], 0, 1);
1274  if (u == 0) return params[2];
1275  if (u == 1) return params[n - 2];
1276  int nsegs = n - 4;
1277  double seg;
1278  u = modf(u * nsegs, &seg);
1279  double* p = &params[int(seg) + 1];
1280  double u2 = u * u;
1281  double u3 = u2 * u;
1282  return 0.5 * (p[0] * (-u3 + 2 * u2 - u) + p[1] * (3 * u3 - 5 * u2 + 2) + p[2] * (-3 * u3 + 4 * u2 + u) +
1283  p[3] * (u3 - u2));
1284 }
1285 static const char* spline_docstring =
1286  "float spline(float param,float y1,float y2,float y3,float y4,[...])\n\n"
1287  "Interpolates a set of values to the parameter specified where y1, ..., yn are\n"
1288  "distributed evenly from [0...1]";
1289 
1290 template <class T>
1293  virtual ~CurveData() {}
1294 };
1295 
1296 class CurveFuncX : public ExprFuncSimple {
1297  public:
1299 
1300  virtual ExprType prep(ExprFuncNode* node, bool scalarWanted, ExprVarEnvBuilder& envBuilder) const {
1301  // check number of arguments
1302  int nargs = node->numChildren();
1303  if ((nargs - 1) % 3) {
1304  node->addError("Wrong number of arguments, should be multiple of 3 plus 1");
1305  return ExprType().Error();
1306  }
1307 
1308  bool valid = true;
1309  valid &= node->checkArg(0, ExprType().FP(1).Varying(), envBuilder);
1310  for (int i = 1; i < nargs; i += 3) {
1311  valid &= node->checkArg(i, ExprType().FP(1).Constant(), envBuilder);
1312  valid &= node->checkArg(i + 1, ExprType().FP(1).Constant(), envBuilder);
1313  valid &= node->checkArg(i + 2, ExprType().FP(1).Constant(), envBuilder);
1314  }
1315  return valid ? ExprType().FP(1).Varying() : ExprType().Error();
1316  }
1317 
1318  virtual ExprFuncNode::Data* evalConstant(const ExprFuncNode* node, ArgHandle args) const {
1320  for (int i = 1; i < args.nargs() - 2; i += 3) {
1321  double pos = args.inFp<1>(i)[0];
1322  double val = args.inFp<1>(i + 1)[0];
1323  double interpDouble = args.inFp<1>(i + 2)[0];
1324  int interpInt = (int)interpDouble;
1325  Curve<double>::InterpType interpolant = (Curve<double>::InterpType)interpInt;
1326  if (!Curve<double>::interpTypeValid(interpolant)) {
1327  // TODO: fix error checking!
1328  }
1329  data->curve.addPoint(pos, val, interpolant);
1330  }
1331  data->curve.preparePoints();
1332  return data;
1333  }
1334 
1335  virtual void eval(ArgHandle args) {
1336  CurveData<double>* data = static_cast<CurveData<double>*>(args.data);
1337  double param = args.inFp<1>(0)[0];
1338  args.outFp = data->curve.getValue(param);
1339  }
1340 
1341 } curve;
1342 static const char* curve_docstring =
1343  "float curve(float param,float pos0,float val0,int interp0,float pos1,float val1,int interp1,[...])\n\n"
1344  "Interpolates a 1D ramp defined by control points at 'param'. Control points are specified \n"
1345  "by triples of parameters pos_i, val_i, and interp_i. Interpolation codes are \n"
1346  "0 - none, 1 - linear, 2 - smooth, 3 - spline, \n"
1347  "4-monotone (non oscillating spline)";
1348 
1349 class CCurveFuncX : public ExprFuncSimple {
1350  virtual ExprType prep(ExprFuncNode* node, bool wantScalar, ExprVarEnvBuilder& envBuilder) const {
1351  // check number of arguments
1352  int nargs = node->numChildren();
1353  if ((nargs - 1) % 3) {
1354  node->addError("Wrong number of arguments, should be multiple of 3 plus 1");
1355  return ExprType().Error().Varying();
1356  }
1357 
1358  bool valid = true;
1359  valid &= node->checkArg(0, ExprType().FP(1).Varying(), envBuilder);
1360  for (int i = 1; i < nargs; i += 3) {
1361  valid &= node->checkArg(i, ExprType().FP(1).Constant(), envBuilder);
1362  valid &= node->checkArg(i + 1, ExprType().FP(3).Constant(), envBuilder);
1363  valid &= node->checkArg(i + 2, ExprType().FP(1).Constant(), envBuilder);
1364  }
1365  return valid ? ExprType().FP(3).Varying() : ExprType().Error();
1366  }
1367 
1368  virtual ExprFuncNode::Data* evalConstant(const ExprFuncNode* node, ArgHandle args) const {
1369  CurveData<Vec3d>* data = new CurveData<Vec3d>;
1370  for (int i = 1; i < args.nargs() - 2; i += 3) {
1371  double pos = args.inFp<1>(i)[0];
1372  Vec3dRef val(&args.inFp<3>(i + 1)[0]);
1373  double interpDouble = args.inFp<1>(i + 2)[0];
1374  int interpInt = (int)interpDouble;
1375  Curve<Vec3d>::InterpType interpolant = (Curve<Vec3d>::InterpType)interpInt;
1376  if (!Curve<Vec3d>::interpTypeValid(interpolant)) {
1377  // TODO: fix error checking!
1378  }
1379  data->curve.addPoint(pos, val, interpolant);
1380  }
1381  data->curve.preparePoints();
1382  return data;
1383  }
1384 
1385  virtual void eval(ArgHandle args) {
1386  CurveData<Vec3d>* data = static_cast<CurveData<Vec3d>*>(args.data);
1387  double param = args.inFp<1>(0)[0];
1388  Vec3d result = data->curve.getValue(param);
1389  double* out = &args.outFp;
1390  for (int k = 0; k < 3; k++) out[k] = result[k];
1391  }
1392 
1393  public:
1394  CCurveFuncX() : ExprFuncSimple(true) {} // Thread Safe
1395  virtual ~CCurveFuncX() {}
1396 } ccurve;
1397 static const char* ccurve_docstring =
1398  "color curve(float param,float pos0,color val0,int interp0,float pos1,color val1,int interp1,[...])\n\n"
1399  "Interpolates color ramp given by control points at 'param'. Control points are specified \n"
1400  "by triples of parameters pos_i, val_i, and interp_i. Interpolation codes are \n"
1401  "0 - none, 1 - linear, 2 - smooth, 3 - spline, \n"
1402  "4 - monotone (non oscillating spline)";
1403 
1404 class GetVar : public ExprFuncSimple {
1405  struct Data : public ExprFuncNode::Data {
1406  typedef void(*func)(double *in, double* out);
1407  Data(func fIn,int dim) :f(fIn),dim(dim)
1408  {}
1410  int dim;
1411  };
1412 
1413  virtual ExprType prep(ExprFuncNode* node, bool wantScalar, ExprVarEnvBuilder& envBuilder) const {
1414  bool valid = true;
1415  valid &= node->checkArg(0, ExprType().String().Constant(), envBuilder);
1416  std::string varName = node->getStrArg(0);
1417  ExprVarNode* varNode = new ExprVarNode(node->expr(), varName.c_str());
1418  ExprType varType = varNode->prep(wantScalar, envBuilder);
1419  if (varType.isValid()) {
1420  node->removeLastChild(); // remove the useless default argument from the arugment list
1421  node->removeLastChild(); // remove the useless default argument from the arugment list
1422  node->addChild(varNode);
1423  } else {
1424  delete varNode;
1425  node->swapChildren(0, 1); // move the default argument in the beginning
1426  varType = node->child(0)->prep(wantScalar, envBuilder);
1427  node->removeLastChild(); // remove the useless string argument
1428  }
1429  return varType.isValid() ? varType : ExprType().Error();
1430  }
1431 
1432  virtual ExprFuncNode::Data* evalConstant(const ExprFuncNode* node, ArgHandle args) const {
1433  return new Data(node->type().isFP() ? getTemplatizedOp<Assign,Data::func>(node->type().dim()) : nullptr,node->type().dim());
1434  }
1435 
1436  template<int d>
1437  struct Assign{
1438  static void f(double* out,double* in){
1439  for(int k=0;k<d;k++) out[k]=in[k];
1440  }
1441  };
1442 
1443  virtual void eval(ArgHandle args) {
1444  Data* data = static_cast<Data*>(args.data);
1445  assert(data);
1446  double* out=&args.outFp;
1447  //for(int i=0;i<data->dim;i++) std::cerr<<" "<<args.inFp<1>(0)[i];
1448  //std::cerr<<std::endl;
1449  if(data->f) data->f(out,&args.inFp<1>(0)[0]);
1450  else throw std::runtime_error("getVar does not support non FP types right now got type");
1451  }
1452 
1453  public:
1454  GetVar() : ExprFuncSimple(true) {} // Thread Safe
1455  virtual ~GetVar() {}
1456 } getVar;
1457 static const char* getVar_docstring =
1458  "getVar(string varName,vector defaultValue)\n"
1459  "return value of varName if variable exists, otherwise return defaultValue";
1460 
1461 class PrintFuncX : public ExprFuncSimple {
1462  struct Data : public ExprFuncNode::Data {
1463  std::vector<std::pair<int, int> > ranges;
1464  std::string format;
1465  };
1466 
1467  public:
1468  virtual ExprType prep(ExprFuncNode* node, bool wantScalar, ExprVarEnvBuilder& envBuilder) const {
1469  int nargs = node->numChildren();
1470  if (nargs < 1) {
1471  node->addError("Wrong number of arguments, should be GE 1");
1472  return ExprType().Error().Varying();
1473  }
1474 
1475  bool valid = true;
1476  valid &= node->checkArg(0, ExprType().String().Constant(), envBuilder);
1477  for (int i = 1; i < nargs; ++i)
1478  valid &= (node->checkArg(i, ExprType().FP(1), envBuilder) || node->checkArg(i, ExprType().FP(3), envBuilder));
1479  return ExprType().FP(1).Constant();
1480  }
1481 
1482  virtual ExprFuncNode::Data* evalConstant(const ExprFuncNode* node, ArgHandle args) const {
1483  // parse format string
1484  unsigned int bakeStart = 0;
1485  int searchStart = 0;
1486  int needed = 0;
1487  Data* data = new Data;
1488  data->format = args.inStr(0);
1489  std::string& format = data->format;
1490  std::vector<std::pair<int, int> >& ranges = data->ranges;
1491 
1492  int items = 0;
1493  while (1) {
1494  std::size_t percentStart = format.find('%', searchStart);
1495  if (percentStart == std::string::npos) break;
1496  if (percentStart + 1 == format.length()) {
1497  // node->addError("Unexpected end of format string");
1498  delete data;
1499  assert(false);
1500  } else if (format[percentStart + 1] == '%') {
1501  searchStart = percentStart + 2;
1502  continue;
1503  } else if (format[percentStart + 1] == 'v' || format[percentStart + 1] == 'f') {
1504  char c = format[percentStart + 1];
1505  int code = (c == 'v') ? -1 : -2;
1506  needed++;
1507  if (bakeStart != percentStart) ranges.push_back(std::pair<int, int>(bakeStart, percentStart));
1508  ranges.push_back(std::pair<int, int>(code, code));
1509  items++;
1510  searchStart = percentStart + 2;
1511  bakeStart = searchStart;
1512  } else {
1513  // node->addError("Invalid format string, only %v is allowed");
1514  delete data;
1515  // TODO: check that this is correct
1516  // return ExprType().Error().Varying();
1517  // return false;
1518  assert(false);
1519  }
1520  }
1521  if (bakeStart != format.length()) ranges.push_back(std::pair<int, int>(bakeStart, format.length()));
1522 
1523  if (items != args.nargs() - 1) {
1524  // node->addError("Wrong number of arguments for format string");
1525  delete data;
1526  // TODO: check that this is correct
1527  // return ExprType().Error().Varying();
1528  // return false;
1529  assert(false);
1530  }
1531 
1532  return data;
1533  }
1534 
1535  virtual void eval(ArgHandle args) {
1536  Data* data = (Data*)args.data;
1537  int item = 1;
1538  for (unsigned int i = 0; i < data->ranges.size(); i++) {
1539  const std::pair<int, int>& range = data->ranges[i];
1540  if (range.first == -2) {
1541  std::cerr << args.inFp<1>(item)[0];
1542  item++;
1543  } else if (range.first == -1) {
1544  std::cerr << "[" << args.inFp<3>(item)[0] << "," << args.inFp<3>(item)[1] << ","
1545  << args.inFp<3>(item)[2] << "]";
1546  item++;
1547  } else {
1548  std::cerr << data->format.substr(range.first, range.second - range.first);
1549  }
1550  }
1551  std::cerr << std::endl;
1552 
1553  args.outFp = 0;
1554  }
1555 
1556  PrintFuncX() : ExprFuncSimple(false) {} // not thread safe
1557 
1558 } printf;
1559 static const char* printf_docstring =
1560  "printf(string format,[vec0, vec1, ...])\n"
1561  "Prints out a string to STDOUT, Format parameter allowed is %v";
1562 
1563 #if 0
1564 
1565 class TestFunc:public ExprFuncSimple
1566 {
1567  struct MyData:public ExprFuncNode::Data
1568  {
1569  float foo;
1570  MyData(float foo)
1571  :foo(foo)
1572  {}
1573  };
1574 public:
1575  TestFunc()
1576  :ExprFuncSimple(true)
1577  {}
1578  virtual ExprType prep(ExprFuncNode* node,bool scalarWanted,ExprVarEnvBuilder& envBuilder) const
1579  {
1580  bool valid=true;
1581  valid &= node->checkArg(0,ExprType().FP(3).Varying(),envBuilder);
1582  valid &= node->checkArg(1,ExprType().FP(1).Constant(),envBuilder);
1583  return valid ?ExprType().FP(3).Varying():ExprType().Error();
1584  }
1585  virtual ExprFuncNode::Data* evalConstant(ArgHandle args) const
1586  {
1587  //std::cerr<<"evalling const "<<args.inFp<1>(1)<<std::endl;
1588  return new MyData(args.inFp<1>(1)[0]);
1589  }
1590  virtual void eval(ArgHandle args)
1591  {
1592  MyData* data=static_cast<MyData*>(args.data);
1593 
1594  Vec<double,3,true>(&args.outFp)=args.inFp<3>(0)+Vec<double,3,false>(data->foo);
1595  }
1596 } testfunc;
1597 static const char* testfunc_docstring="fdsA";
1598 
1599 #endif
1600 
1602 // functions from math.h (global namespace)
1603 //#define FUNC(func) define(#func, ExprFunc(::func))
1604 #define FUNCADOC(name, func) define3(name, ExprFunc(::func), func##_docstring)
1605 #define FUNCDOC(func) define3(#func, ExprFunc(::func), func##_docstring)
1606  FUNCADOC("abs", fabs);
1607  FUNCDOC(acos);
1608  FUNCDOC(asin);
1609  FUNCDOC(atan);
1610  FUNCDOC(atan2);
1611  FUNCDOC(ceil);
1612  FUNCDOC(cos);
1613  FUNCDOC(cosh);
1614  FUNCDOC(exp);
1615  FUNCDOC(floor);
1616  FUNCDOC(fmod);
1617  FUNCDOC(log);
1618  FUNCDOC(log10);
1619  FUNCDOC(pow);
1620  FUNCDOC(sin);
1621  FUNCDOC(sinh);
1622  FUNCDOC(sqrt);
1623  FUNCDOC(tan);
1624  FUNCDOC(tanh);
1625 #ifndef SEEXPR_WIN32
1626  FUNCDOC(cbrt);
1627  FUNCDOC(asinh);
1628  FUNCDOC(acosh);
1629  FUNCDOC(atanh);
1630  FUNCDOC(trunc);
1631 #endif
1632 // local functions (SeExpr2 namespace)
1633 //#undef FUNC
1634 #undef FUNCDOC
1635 //#define FUNC(func) define(#func, ExprFunc(SeExpr2::func))
1636 //#define FUNCN(func, min, max) define(#func, ExprFunc(SeExpr2::func, min, max))
1637 #define FUNCDOC(func) define3(#func, ExprFunc(SeExpr2::func), func##_docstring)
1638 #define FUNCNDOC(func, min, max) define3(#func, ExprFunc(SeExpr2::func, min, max), func##_docstring)
1639 
1640  // trig
1641  FUNCDOC(deg);
1642  FUNCDOC(rad);
1643  FUNCDOC(cosd);
1644  FUNCDOC(sind);
1645  FUNCDOC(tand);
1646  FUNCDOC(acosd);
1647  FUNCDOC(asind);
1648  FUNCDOC(atand);
1649  FUNCDOC(atan2d);
1650 
1651  // clamping
1652  FUNCDOC(clamp);
1653  FUNCDOC(round);
1654  FUNCDOC(max);
1655  FUNCDOC(min);
1656 
1657  // blending / remapping
1658  FUNCDOC(invert);
1659  FUNCDOC(compress);
1660  FUNCDOC(expand);
1661  FUNCDOC(fit);
1662  FUNCDOC(gamma);
1663  FUNCDOC(bias);
1664  FUNCDOC(contrast);
1665  FUNCDOC(boxstep);
1668  FUNCDOC(gaussstep);
1669  FUNCDOC(remap);
1670  FUNCDOC(mix);
1671  FUNCNDOC(hsi, 4, 5);
1672  FUNCNDOC(midhsi, 5, 7);
1673  FUNCDOC(hsltorgb);
1674  FUNCDOC(rgbtohsl);
1675  FUNCNDOC(saturate, 2, 2);
1676 
1677  // noise
1678  FUNCNDOC(hash, 1, -1);
1679  FUNCNDOC(noise, 1, 4);
1680  FUNCDOC(snoise);
1681  FUNCDOC(vnoise);
1682  FUNCDOC(cnoise);
1683  FUNCNDOC(snoise4, 2, 2);
1684  FUNCNDOC(vnoise4, 2, 2);
1685  FUNCNDOC(cnoise4, 2, 2);
1686  FUNCNDOC(turbulence, 1, 4);
1687  FUNCNDOC(vturbulence, 1, 4);
1688  FUNCNDOC(cturbulence, 1, 4);
1689  FUNCNDOC(fbm, 1, 4);
1690  FUNCNDOC(vfbm, 1, 4);
1691  FUNCNDOC(cfbm, 1, 4);
1692  FUNCDOC(cellnoise);
1694  FUNCDOC(pnoise);
1695  FUNCNDOC(fbm4, 2, 5);
1696  FUNCNDOC(vfbm4, 2, 5);
1697  FUNCNDOC(cfbm4, 2, 5);
1698 
1699  // vectors
1700  FUNCDOC(dist);
1701  FUNCDOC(length);
1702  FUNCDOC(hypot);
1703  FUNCDOC(dot);
1704  FUNCDOC(norm);
1705  FUNCDOC(cross);
1706  FUNCDOC(angle);
1707  FUNCDOC(ortho);
1708  FUNCNDOC(rotate, 3, 3);
1709  FUNCDOC(up);
1710 
1711  // variations
1712  FUNCDOC(cycle);
1713  FUNCNDOC(pick, 3, -1);
1714  FUNCNDOC(choose, 3, -1);
1715  FUNCNDOC(wchoose, 4, -1);
1716  FUNCNDOC(swatch, 3, -1);
1717  FUNCNDOC(spline, 5, -1);
1718 
1719  // FuncX interface
1720  // noise
1721  FUNCNDOC(voronoi, 1, 7);
1722  FUNCNDOC(cvoronoi, 1, 7);
1723  FUNCNDOC(pvoronoi, 1, 6);
1724  // variations
1725  FUNCNDOC(curve, 1, -1);
1726  FUNCNDOC(ccurve, 1, -1);
1727  FUNCNDOC(getVar, 2, 2);
1728  FUNCNDOC(printf, 1, -1);
1729  // FUNCNDOC(testfunc,2,2);
1730 }
1731 }
double cellnoise(const Vec3d &p)
static const char * getVar_docstring
void(* Define3)(const char *name, ExprFunc f, const char *docString)
Definition: ExprFunc.h:65
static const char * max_docstring
static const char * bias_docstring
static const char * atan2_docstring
static const char * remap_docstring
Defined as float g float float float a2
Definition: userdoc.txt:162
CachedVoronoiFunc(VoronoiFunc *vfunc)
static const char * atan2d_docstring
static const char * cfbm_docstring
static const char * log10_docstring
Vec3d hsi(int n, const Vec3d *args)
T_VEC_VALUE rotateBy(const Vec< T, 3, refother > &axis, T angle) const
Definition: Vec.h:349
const ExprType & type() const
The type of the node.
Definition: ExprNode.h:145
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
Vec3d up(const Vec3d &P, const Vec3d &upvec)
SeExpr2::CurveFuncX curve
static const char * acos_docstring
double dot(const Vec3d &a, const Vec3d &b)
double swatch(int n, double *params)
static double hslvalue(double x, double y, double H)
void addError(const std::string &error) const
Register error. This will allow users and sophisticated editors to highlight where in code problem wa...
Definition: ExprNode.h:168
int dim() const
Definition: ExprType.h:160
ExprType & Varying()
Mutate this into a varying lifetime.
Definition: ExprType.h:122
static const char * norm_docstring
static const char * dot_docstring
SeExpr2::CachedVoronoiFunc ExprFuncSimple pvoronoi(pvoronoiFn)
static const char * fit_docstring
Vec3d vfbm(int n, const Vec3d *args)
CachedVoronoiFunc(VoronoiFunc *vfunc)
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
For applying the gamma function to a map adjusts the gamma of all three color channels< br >< br >< h4 >< aname="Curve_Functions"></a > Curve Functions</h4 >< p > Interpolation of parameter values to a set of control points is governed by the following functions</p >< p > color< b > and interp_i Interpolation codes are float float int float pos1
Definition: userdoc.txt:479
static const char * gaussstep_docstring
static const char * sind_docstring
double atan2d(double y, double x)
Definition: ExprBuiltins.h:37
Vec3d ccellnoise(const Vec3d &p)
#define FUNCADOC(name, func)
static const char * ortho_docstring
double invert(double x)
Definition: ExprBuiltins.h:46
double asind(double x)
Definition: ExprBuiltins.h:35
Interpolation curve class for double-&gt;double and double-&gt;Vec3D.
Definition: Curve.h:38
static const char * snoise4_docstring
Vec3d pvoronoiFn(VoronoiPointData &data, int n, const Vec3d *args)
static void voronoi_f1_3d(VoronoiPointData &data, const Vec3d &p, double jitter, double &f1, Vec3d &pos1)
static const char * fabs_docstring
double rad(double angle)
Definition: ExprBuiltins.h:30
static Vec3d * voronoi_points(VoronoiPointData &data, const Vec3d &cell, double jitter)
void swapChildren(size_t i, size_t j)
Swap children, do not use unless you know what you are doing.
Definition: ExprNode.h:123
static const char * vturbulence_docstring
static const char * invert_docstring
static const char * cnoise_docstring
Vec3d hsiAdjust(const Vec3d &rgb, double h, double s, double i)
Vec3d cturbulence(int n, const Vec3d *args)
double round(double x)
Definition: ExprBuiltins.h:41
bool isFP() const
Direct is predicate checks.
Definition: ExprType.h:164
Node that references a variable.
Definition: ExprNode.h:462
void defineBuiltins(ExprFunc::Define define, ExprFunc::Define3 define3)
The result is computed int loRange
Definition: userdoc.txt:322
The result is computed int int hiRange
Definition: userdoc.txt:322
static const char * tan_docstring
Data(func fIn, int dim)
virtual void eval(ArgHandle args)
static const char * expand_docstring
double snoise4(int n, const Vec3d *args)
static const char * snoise_docstring
SeExpr2::PrintFuncX printf
double sind(double x)
Definition: ExprBuiltins.h:32
static const char * sinh_docstring
static const char * wchoose_docstring
double remap(double x, double source, double range, double falloff, double interp)
static const char * mix_docstring
static const char * cvoronoi_docstring
double expand(double x, double lo, double hi)
virtual void eval(ArgHandle args)
static const char * swatch_docstring
ExprFuncNode::Data * data
Definition: ExprFuncX.h:99
static const char * atanh_docstring
static const char * pnoise_docstring
Vec3d vnoise4(int n, const Vec3d *args)
double choose(int n, double *params)
static const char * printf_docstring
double smoothstep(double x, double a, double b)
double pick(int n, double *params)
Vec< double, d, true > inFp(int i)
Definition: ExprFuncX.h:85
static const char * length_docstring
virtual ExprType prep(bool dontNeedScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:102
static const char * trunc_docstring
static const char * hsi_docstring
static const char * cycle_docstring
std::string getStrArg(int n) const
Definition: ExprNode.h:558
static const char * pick_docstring
SeExpr2::CurveData voronoi
double length(const Vec3d &v)
static const char * deg_docstring
double tand(double x)
Definition: ExprBuiltins.h:33
Vec3d cnoise(const Vec3d &p)
virtual ExprType prep(bool wantScalar, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:482
static const char * asin_docstring
static const char * vnoise4_docstring
static const char * acosd_docstring
static const char * atan_docstring
static const char * sin_docstring
double max(double x, double y)
Definition: ExprBuiltins.h:42
static const char * ccurve_docstring
#define FUNCNDOC(func, min, max)
Vec3d voronoiFn(VoronoiPointData &data, int n, const Vec3d *args)
Node that calls a function.
Definition: ExprNode.h:514
static const char * smoothstep_docstring
double bias(double x, double b)
static const char * fbm4_docstring
The result is computed int int< br >< divstyle="margin-left:40px;"> Picks values randomly between loRange and hiRange based on supplied index(which is automatically hashed).&nbsp
static const char * vnoise_docstring
Defined as float g float a1
Definition: userdoc.txt:162
double cycle(double index, double loRange, double hiRange)
static const char * voronoi_docstring
static const char * asind_docstring
Vec< double, 3, false > Vec3d
Definition: Vec.h:368
#define FUNCDOC(func)
Vec3d cfbm4(int n, const Vec3d *args)
static const char * hash_docstring
static const char * rad_docstring
virtual ExprType prep(ExprFuncNode *node, bool scalarWanted, ExprVarEnvBuilder &envBuilder) const
< br > pow($a, 0.5)+$b< br >< br ></div > External variables can also be overridden by local assignment.&nbsp
static const char * pow_docstring
static const char * cnoise4_docstring
double contrast(double x, double c)
static const char * cturbulence_docstring
static const char * curve_docstring
bool checkArg(int argIndex, ExprType type, ExprVarEnvBuilder &envBuilder)
Definition: ExprNode.cpp:572
double min(double x, double y)
Definition: ExprBuiltins.h:43
Between a and b
Definition: userdoc.txt:180
double wchoose(int n, double *params)
double fbm(int n, const Vec3d *args)
double cosd(double x)
Definition: ExprBuiltins.h:31
static const int p[514]
Definition: NoiseTables.h:20
Vec3d vnoise(const Vec3d &p)
double fbm4(int n, const Vec3d *args)
static const char * boxstep_docstring
double dist(double ax, double ay, double az, double bx, double by, double bz)
static const char * cbrt_docstring
static const char * turbulence_docstring
double gamma(double x, double g)
ExprType & Constant()
Mutate this into a constant lifetime.
Definition: ExprType.h:112
static const char * tand_docstring
double linearstep(double x, double a, double b)
static const char * rotate_docstring
static const char * pvoronoi_docstring
void(* Define)(const char *name, ExprFunc f)
Definition: ExprFunc.h:64
base class for custom instance data
Definition: ExprNode.h:564
</pre >< h3 > A simple variable reference</h3 > This is not a very interesting subclass of expression until we add some additional variables Variables on some applications may be very dynamic In this we only need x
Definition: tutorial.txt:108
void(* func)(double *in, double *out)
SeExpr2::GetVar getVar
static const char * acosh_docstring
static const char * choose_docstring
void removeLastChild()
Remove last child and delete the entry.
Definition: ExprNode.h:129
static const char * log_docstring
static const char * cross_docstring
int numChildren() const
Number of children.
Definition: ExprNode.h:114
Vec3d cvoronoiFn(VoronoiPointData &data, int n, const Vec3d *args)
Vec3d cross(const Vec3d &a, const Vec3d &b)
void addChild(ExprNode *child)
Add a child to the child list (for parser use only)
Definition: ExprNode.cpp:88
double mix(double x, double y, double alpha)
T length() const
Euclidean (2) norm.
Definition: Vec.h:194
static const char * cosd_docstring
double fit(double x, double a1, double b1, double a2, double b2)
Vec3d midhsi(int n, const Vec3d *args)
static const char * clamp_docstring
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
static const char * vfbm_docstring
const Expression * expr() const
Access expression.
Definition: ExprNode.h:102
static const char * min_docstring
static const char * vfbm4_docstring
static const char * fmod_docstring
Vec3d vturbulence(int n, const Vec3d *args)
static const char * cellnoise_docstring
When x is within< i > range</i > of source
Definition: userdoc.txt:111
This is the same as the prman cellnoise function< br ></div >< br > float< b > float y< br > float< b > float float z
Definition: userdoc.txt:218
for(int i=0;i &lt;w;i++)
Definition: tutorial.txt:193
static const char * midhsi_docstring
double boxstep(double x, double a)
static const char * round_docstring
static const char * up_docstring
double atand(double x)
Definition: ExprBuiltins.h:36
double clamp(double x, double lo, double hi)
Definition: ExprBuiltins.h:40
double deg(double angle)
Definition: ExprBuiltins.h:29
static const char * fbm_docstring
static const char * ccellnoise_docstring
static void f(double *out, double *in)
static const char * atand_docstring
virtual ExprType prep(ExprFuncNode *node, bool scalarWanted, ExprVarEnvBuilder &envBuilder) const
SeExpr2::CCurveFuncX ccurve
virtual void eval(ArgHandle args)
static const char * exp_docstring
const ExprNode * child(size_t i) const
Get 0 indexed child.
Definition: ExprNode.h:117
static const char * asinh_docstring
Defined as float g float float b1
Definition: userdoc.txt:162
static const char * hsltorgb_docstring
static const char * linearstep_docstring
double hypot(double x, double y)
double turbulence(int n, const Vec3d *args)
std::vector< std::pair< int, int > > ranges
static const char * cfbm4_docstring
double angle(const Vec3d &a, const Vec3d &b)
double snoise(const Vec3d &p)
virtual ExprType prep(ExprFuncNode *node, bool scalarWanted, ExprVarEnvBuilder &envBuilder) const
Vec3d rgbtohsl(const Vec3d &rgb)
virtual void eval(ArgHandle args)
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
double spline(int n, double *params)
double acosd(double x)
Definition: ExprBuiltins.h:34
virtual void eval(ArgHandle args)
static const char * cosh_docstring
static const char * noise_docstring
static const char * contrast_docstring
InterpType
Supported interpolation types.
Definition: Curve.h:43
static const char * floor_docstring
static const char * cos_docstring
Vec3d hsltorgb(const Vec3d &hsl)
ExprType & FP(int d)
Mutate this into a floating point type of dimension d.
Definition: ExprType.h:90
Vec3d rotate(int n, const Vec3d *args)
static const char * saturate_docstring
Vec3d cnoise4(int n, const Vec3d *args)
static void voronoi_f1f2_3d(VoronoiPointData &data, const Vec3d &p, double jitter, double &f1, Vec3d &pos1, double &f2, Vec3d &pos2)
virtual void eval(ArgHandle args)
static const char * angle_docstring
static const char * tanh_docstring
static const char * spline_docstring
static const char * compress_docstring
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
Defined as a *alpha b *alpha< br ></div >< br > float< b > float a
Definition: userdoc.txt:174
Vec3d norm(const Vec3d &a)
static const char * sqrt_docstring
SeExpr2::CachedVoronoiFunc ExprFuncSimple cvoronoi(cvoronoiFn)
T dot(const Vec< T, d, refother > &o) const
Definition: Vec.h:313
static const char * ceil_docstring
double compress(double x, double lo, double hi)
Vec3d vfbm4(int n, const Vec3d *args)
static const char * rgbtohsl_docstring
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
ExprType & Error()
Mutate this into an error type.
Definition: ExprType.h:102
* sin(val)/val" </pre> we would get <pre> | | | | | </pre> or if we did <pre> ./asciiGraph "x-3" </pre> we'd get <pre> | | ------------------------------|----------------- | | | | | </pre> <h2>Implement the subclass</h2> First we subclass Expression and give it a const ructor
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
double pnoise(const Vec3d &p, const Vec3d &period)
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
Vec3d ortho(const Vec3d &a, const Vec3d &b)
This is the same as the prman cellnoise function< br ></div >< br > float< b > float y< br > float< b > float y
Definition: userdoc.txt:218
static const char * dist_docstring
static const char * hypot_docstring
Vec3d VoronoiFunc(VoronoiPointData &data, int n, const Vec3d *args)
double hash(int n, double *args)
Platform-specific classes, functions, and includes.
static const char * gamma_docstring
Variable scope builder is used by the type checking and code gen to track visiblity of variables and ...
Definition: ExprEnv.h:152
double noise(int n, const Vec3d *args)
static Vec3d saturate(const Vec3d &Cin, double amt)
double gaussstep(double x, double a, double b)
Vec3d cfbm(int n, const Vec3d *args)