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 <cmath>
20#include <cstdlib>
21#include <limits>
22#include <algorithm>
23#include <cfloat>
24
25#include "ExprFunc.h"
26#include "ExprNode.h"
27#include "Vec.h"
28#include "Curve.h"
29#include "ExprBuiltins.h"
30#include "Platform.h"
31#include "Noise.h"
32#include "Interpreter.h"
33
34namespace SeExpr2 {
36static const char* fabs_docstring = "float abs(float x)\nabsolute value of x";
37
38// angle conversion functions
39static const char* deg_docstring = "float deg(float angle)\nradians to degrees";
40static const char* rad_docstring = "float deg(float angle)\ndegrees to radians";
41// trig in degrees
42static const char* cosd_docstring = "float cosd(float angle)\ncosine in degrees";
43static const char* sind_docstring = "float sind(float angle)\nsine in degrees";
44static const char* tand_docstring = "float tand(float angle)\ntangent in degrees";
45static const char* acosd_docstring = "float acosd(float angle)\narc cosine in degrees";
46static const char* asind_docstring = "float asind(float angle)\narc sine in degrees";
47static const char* atand_docstring = "float atand(float angle)\narc tangent in degrees";
48static const char* atan2d_docstring =
49 "float atan2d(float y,float x)\narc tangent in degrees of y/x between -180 and 180";
50// trig in radians
51static const char* cos_docstring = "float cos(float angle)\ncosine in radians";
52static const char* sin_docstring = "float sin(float angle)\nsine in radians";
53static const char* tan_docstring = "float tan(float angle)\ntangent in radians";
54static const char* acos_docstring = "float acos(float angle)\narc cosine in radians";
55static const char* asin_docstring = "float asin(float angle)\narc sine in radians";
56static const char* atan_docstring = "float atan(float angle)\narc tangent in radians";
57static const char* atan2_docstring = "float atan2(float y,float x)\narc tangent in radians of y/x between -PI and PI";
58// hyperbolic trig
59static const char* cosh_docstring = "float cosh(float angle)\nhyperbolic cosine in radians";
60static const char* sinh_docstring = "float sinh(float angle)\nhyperbolic sine in radians";
61static const char* tanh_docstring = "float tanh(float angle)\nhyperbolic tangent in radians";
62static const char* acosh_docstring = "float acosh(float angle)\nhyperbolic arc cosine in radians";
63static const char* asinh_docstring = "float asinh(float angle)\nhyperbolic arc sine in radians";
64static const char* atanh_docstring = "float atanh(float angle)\nhyperbolic arc tangent in radians";
65// clamping/rounding
66static const char* clamp_docstring = "float clamp(float x,float lo,float hi)\nconstrain x to range [lo,hi]";
67static const char* round_docstring = "float round(float x)\nconstrain x to range [lo,hi]";
68static const char* max_docstring = "float max(float a,float b)\ngreater of a and b";
69static const char* min_docstring = "float min(float a,float b)\nlesser of a and b";
70static const char* trunc_docstring = "float trunc(float a)\nnearest integer towards zero";
71static const char* floor_docstring = "float floor(float a)\nnext lower integer";
72static const char* ceil_docstring = "float ceil(float a)\nnext higher integer";
73// misc math
74static const char* invert_docstring = "float invert(float a)\nDefined as 1-x";
75static const char* cbrt_docstring = "float cbrt(float x)\ncube root";
76static const char* sqrt_docstring = "float sqrt(float x)\nsquare root";
77static const char* exp_docstring = "float exp(float x)\nE raised to the x power";
78static const char* pow_docstring = "float pow(float x)\nx to the y power, also available as ^";
79static const char* log_docstring = "float log(float x)\nNatural logarithm";
80static const char* log10_docstring = "float log10(float x)\nBase 10 logarithm";
81static const char* fmod_docstring = "float fmod(float x,float y)\nremainder of x/y (also available as % operator)";
82static const char* turbulence_docstring =
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";
85static const char* cturbulence_docstring =
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";
88static const char* vturbulence_docstring =
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";
91
92double compress(double x, double lo, double hi) { return (hi - lo) * x + lo; }
93static const char* compress_docstring = "float compress(float x,float lo,float hi)\nRemaps x in [0,1] to [lo,hi]";
94
95double expand(double x, double lo, double hi) {
96 if (lo == hi) return x < lo ? 0 : 1;
97 return (x - lo) / (hi - lo);
98}
99static const char* expand_docstring = "float expand(float x,float lo,float hi)\nRemaps x in [lo,hi] to [0,1]";
100
101double fit(double x, double a1, double b1, double a2, double b2) {
102 return (x * (b2 - a2) - a1 * b2 + b1 * a2) / (b1 - a1);
103}
104static const char* fit_docstring =
105 "float fit(float x,float a1,float b1,float a2,float b2)\nLinearly remaps x in [a1,b1] to [a2,b2]";
106
107double gamma(double x, double g) { return pow(x, 1 / g); }
108static const char* gamma_docstring = "float gamma(float x, float g)\nGamma correction of x with gamma factor g";
109
110double bias(double x, double b) {
111 static double C = 1 / log(0.5);
112 return pow(x, log(b) * C);
113}
114static const char* bias_docstring =
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))";
117
118double contrast(double x, double c) {
119 if (x < 0.5)
120 return 0.5 * bias(1 - c, 2 * x);
121 else
122 return 1 - 0.5 * bias(1 - c, 2 - 2 * x);
123}
124static const char* contrast_docstring =
125 "float contrast(float x,float x)\nAdjust the contrast.&nbsp; For c from 0 to 0.5, the contrast is decreased.&nbsp; "
126 "For c &gt; 0.5, the contrast is increased.";
127
128double boxstep(double x, double a) { return x < a ? 0.0 : 1.0; }
129static const char* boxstep_docstring = "float boxstep(float x,float a)\n if x < a then 0 otherwise 1";
130
131double linearstep(double x, double a, double b) {
132 if (a < b) {
133 return x < a ? 0 : (x > b ? 1 : (x - a) / (b - a));
134 } else if (a > b) {
135 return 1 - (x < b ? 0 : (x > a ? 1 : (x - b) / (a - b)));
136 }
137 return boxstep(x, a);
138}
139static const char* linearstep_docstring =
140 "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 "
141 "when &lt; x &lt; b ";
142
143double smoothstep(double x, double a, double b) {
144 if (a < b) {
145 if (x < a) return 0;
146 if (x >= b) return 1;
147 x = (x - a) / (b - a);
148 } else if (a > b) {
149 if (x <= b) return 1;
150 if (x > a) return 0;
151 x = 1 - (x - b) / (a - b);
152 } else
153 return boxstep(x, a);
154 return x * x * (3 - 2 * x);
155}
156static const char* smoothstep_docstring =
157 "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 "
158 "(cubic) when &lt; x &lt; b";
159
160double gaussstep(double x, double a, double b) {
161 if (a < b) {
162 if (x < a) return 0;
163 if (x >= b) return 1;
164 x = 1 - (x - a) / (b - a);
165 } else if (a > b) {
166 if (x <= b) return 1;
167 if (x > a) return 0;
168 x = (x - b) / (a - b);
169 } else
170 return boxstep(x, a);
171 return pow(2, -8 * x * x);
172}
173static const char* gaussstep_docstring =
174 "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 "
175 "(exponentially) when &lt; x &lt; b";
176
177double remap(double x, double source, double range, double falloff, double interp) {
178 range = fabs(range);
180
181 if (falloff == 0) return fabs(x - source) < range;
182
183 double a, b;
184 if (x > source) {
185 a = source + range;
186 b = a + falloff;
187 } else {
188 a = source - range;
189 b = a - falloff;
190 }
191
192 switch (int(interp)) {
193 case 0:
194 return linearstep(x, b, a);
195 case 1:
196 return smoothstep(x, b, a);
197 default:
198 return gaussstep(x, b, a);
199 }
200}
201static const char* remap_docstring =
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 "&nbsp;&nbsp;&nbsp;&nbsp;int <b>linear</b>\n"
209 "= 0\n"
210 "&nbsp;&nbsp;&nbsp;&nbsp;int <b>smooth</b> = 1\n"
211 "&nbsp;&nbsp;&nbsp;&nbsp;int <b>gaussian</b> = 2\n";
212
213double mix(double x, double y, double alpha) { return x * (1 - alpha) + y * alpha; }
214static const char* mix_docstring = "mix(float a,float b,float alpha)\nBlend of a and b according to alpha.";
215
216Vec3d hsiAdjust(const Vec3d& rgb, double h, double s, double i) {
218 hsl[0] += h * (1.0 / 360);
219 hsl[1] *= s;
220 return hsltorgb(hsl) * i;
221}
222
223Vec3d hsi(int n, const Vec3d* args) {
224 if (n < 4) return 0.0;
225
226 double h = args[1][0];
227 double s = args[2][0];
228 double i = args[3][0];
229 if (n >= 5) {
230 // apply mask
231 double m = args[4][0];
232 h *= m;
233 s = (s - 1) * m + 1;
234 i = (i - 1) * m + 1;
235 }
236 return hsiAdjust(args[0], h, s, i);
237}
238static const char* hsi_docstring =
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.&nbsp; 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.&nbsp; The shift will be scaled back for\n"
245 "values between zero and one.";
246
247Vec3d midhsi(int n, const Vec3d* args) {
248 if (n < 4) return 0.0;
249
250 double h = args[1][0];
251 double s = args[2][0];
252 double i = args[3][0];
253 if (n >= 5) {
254 // apply mask
255 double m = args[4][0];
256 // remap from [0..1] to [-1..1]
257 m = m * 2 - 1;
258 // add falloff (if specified)
259 double falloff = 1, interp = 0;
260 if (n >= 6) falloff = args[5][0];
261 if (n >= 7) interp = args[6][0];
262 if (m < 0)
263 m = -remap(-m, 1, 0, falloff, interp);
264 else
265 m = remap(m, 1, 0, falloff, interp);
266
267 // scale hsi values according to mask (both directions)
268 h *= m;
269 float absm = fabs(static_cast<float>(m));
270 s = s * absm + 1 - absm;
271 i = i * absm + 1 - absm;
272 if (m < 0) {
273 s = 1 / s;
274 i = 1 / i;
275 }
276 }
277 return hsiAdjust(args[0], h, s, i);
278}
279static const char* midhsi_docstring =
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.";
284
286 // RGB to HSL color space conversion
287 // This is based on Foley, Van Dam (2nd ed; p. 595)
288 // but extended to allow rgb values outside of 0..1
289 double R, G, B, H, S, L, x, y, sum, diff;
290 R = rgb[0];
291 G = rgb[1];
292 B = rgb[2];
293 x = R < G ? (R < B ? R : B) : (G < B ? G : B); // min(R,G,B)
294 y = R > G ? (R > B ? R : B) : (G > B ? G : B); // max(R,G,B)
295
296 // compute lightness = avg of min and max rgb vals
297 sum = x + y;
298 diff = y - x;
299 L = sum / 2;
300 if (diff < 1e-6) // achromatic
301 return Vec3d(0, 0, L);
302
303 // compute saturation
304 if (L <= .5) {
305 if (x < 0)
306 S = 1 - x;
307 else
308 S = diff / sum;
309 } else {
310 if (y > 1)
311 S = y;
312 else
313 S = diff / (2 - sum);
314 }
315
316 // compute hue
317 if (R == y)
318 H = (G - B) / diff;
319 else if (G == y)
320 H = (B - R) / diff + 2;
321 else
322 H = (R - G) / diff + 4;
323 H *= 1 / 6.;
324 H -= floor(H); // make sure hue is in range 0..1
325
326 return Vec3d(H, S, L);
327}
328static const char* rgbtohsl_docstring =
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.&nbsp; For any rgb or\n"
334 "hsl value (except for negative s values), the conversion is\n"
335 "well-defined and reversible.";
336
337static double hslvalue(double x, double y, double H) {
338 H -= floor(H); // make sure hue is in range 0..1
339
340 if (H < 1 / 6.)
341 return x + (y - x) * H * 6;
342 else if (H < 3 / 6.)
343 return y;
344 else if (H < 4 / 6.)
345 return x + (y - x) * (4 / 6. - H) * 6;
346 else
347 return x;
348}
349
351 // HSL to RGB color space conversion
352 // This is based on Foley, Van Dam (2nd ed; p. 596)
353 // but extended to allow rgb values outside of 0..1
354 double H, S, L, R, G, B, x, y;
355 H = hsl[0];
356 S = hsl[1];
357 L = hsl[2];
358 if (S <= 0) // achromatic
359 return Vec3d(L, L, L);
360
361 // find min/max rgb values
362 if (L < 0.5) {
363 if (S > 1)
364 y = 2 * L + S - 1;
365 else
366 y = L + L * S;
367 } else {
368 if (S > 1)
369 y = S;
370 else
371 y = L + S - L * S;
372 }
373 x = 2 * L - y;
374
375 // reconstruct rgb from min,max,hue
376 R = hslvalue(x, y, H + (1 / 3.));
377 G = hslvalue(x, y, H);
378 B = hslvalue(x, y, H - (1 / 3.));
379 return Vec3d(R, G, B);
380}
381static const char* hsltorgb_docstring =
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.&nbsp; For any rgb or\n"
387 "hsl value (except for negative s values), the conversion is\n"
388 "well-defined and reversible.";
389
390static Vec3d saturate(const Vec3d& Cin, double amt) {
391 const Vec3d lum(.2126, .7152, .0722); // rec709 luminance
392 Vec3d result = Vec3d(Cin.dot(lum) * (1 - amt)) + Cin * amt;
393 if (result[0] < 0) result[0] = 0;
394 if (result[1] < 0) result[1] = 0;
395 if (result[2] < 0) result[2] = 0;
396 return result;
397}
398
399Vec3d saturate(int n, const Vec3d* args) {
400 if (n < 2) return 0.0;
401 return saturate(args[0], args[1][0]);
402}
403static const char* saturate_docstring =
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";
408
409double hash(int n, double* args) {
410 // combine args into a single seed
411 uint32_t seed = 0;
412 for (int i = 0; i < n; i++) {
413 // make irrational to generate fraction and combine xor into 32 bits
414 int exp = 0;
415 double frac = frexp(args[i] * double(M_E * M_PI), &exp);
417
418 // blend with seed (constants from Numerical Recipes, attrib. from Knuth)
419 static const uint32_t M = 1664525, C = 1013904223;
420 seed = seed * M + s + C;
421 }
422
423 // tempering (from Matsumoto)
424 seed ^= (seed >> 11);
425 seed ^= (seed << 7) & 0x9d2c5680UL;
426 seed ^= (seed << 15) & 0xefc60000UL;
427 seed ^= (seed >> 18);
428
429 // permute
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};
443 union {
444 uint32_t i;
445 unsigned char c[4];
446 } u1, u2;
447 u1.i = seed;
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];
452
453 // scale to [0.0 .. 1.0]
454 return u2.i * (1.0 / UINT32_MAX);
455}
456static const char* hash_docstring =
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.";
460
461double noise(int n, const Vec3d* args) {
462 if (n < 1) return 0;
463 if (n == 1) {
464 // 1 arg = vector arg
465 double result;
466 double p[3] = {args[0][0], args[0][1], args[0][2]};
467 Noise<3, 1>(p, &result);
468 return .5 * result + .5;
469 }
470 // scalar args
471 if (n > 4) n = 4;
472 double p[4];
473 for (int i = 0; i < n; i++) p[i] = args[i][0];
474 double result;
475 switch (n) {
476 case 1:
477 Noise<1, 1>(p, &result);
478 break;
479 case 2:
480 Noise<2, 1>(p, &result);
481 break;
482 case 3:
483 Noise<3, 1>(p, &result);
484 break;
485 case 4:
486 Noise<4, 1>(p, &result);
487 break;
488 default:
489 result = 0;
490 break;
491 }
492 return .5 * result + .5;
493}
494static const char* noise_docstring =
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)";
500
501double snoise(const Vec3d& p) {
502 double result;
503 double args[3] = {p[0], p[1], p[2]};
504 Noise<3, 1>(args, &result);
505 return result;
506}
507static const char* snoise_docstring =
508 "float snoise ( vector v)\n"
509 "signed noise w/ range -1 to 1 formed with original perlin noise at location (C2 interpolant)";
510
511Vec3d vnoise(const Vec3d& p) {
513 double args[3] = {p[0], p[1], p[2]};
514 Noise<3, 3>(args, &result[0]);
515 return result;
516}
517static const char* vnoise_docstring =
518 "vector vnoise ( vector v)\n"
519 "vector noise formed with original perlin noise at location (C2 interpolant)";
520
521Vec3d cnoise(const Vec3d& p) { return .5 * vnoise(p) + Vec3d(.5); }
522static const char* cnoise_docstring =
523 "color cnoise ( vector v)\n"
524 "color noise formed with original perlin noise at location (C2 interpolant)";
525
526double snoise4(int n, const Vec3d* args) {
527 double result;
528 double procargs[4] = {args[0][0], args[0][1], args[0][2], args[1][0]};
530 return result;
531}
532static const char* snoise4_docstring =
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)";
535
536Vec3d vnoise4(int n, const Vec3d* args) {
538 double procargs[4] = {args[0][0], args[0][1], args[0][2], args[1][0]};
540 return result;
541}
542static const char* vnoise4_docstring =
543 "vector vnoise4 ( vector v,float t)\n"
544 "4D vector noise formed with original perlin noise at location (C2 interpolant)";
545
546Vec3d cnoise4(int n, const Vec3d* args) { return .5 * vnoise4(n, args) + Vec3d(.5); }
547static const char* cnoise4_docstring =
548 "color cnoise4 ( vector v,float t)\n"
549 "4D color noise formed with original perlin noise at location (C2 interpolant)";
550
551double turbulence(int n, const Vec3d* args) {
552 // args: octaves, lacunarity, gain
553 int octaves = 6;
554 double lacunarity = 2;
555 double gain = 0.5;
556 Vec3d p = 0.0;
557
558 switch (n) {
559 case 4:
560 gain = args[3][0];
561 case 3:
562 lacunarity = args[2][0];
563 case 2:
564 octaves = int(clamp(args[1][0], 1, 8));
565 case 1:
566 p = args[0];
567 }
568
569 double result = 0;
570 double P[3] = {p[0], p[1], p[2]};
572 return .5 * result + .5;
573}
574
575Vec3d vturbulence(int n, const Vec3d* args) {
576 // args: octaves, lacunarity, gain
577 int octaves = 6;
578 double lacunarity = 2;
579 double gain = 0.5;
580 Vec3d p = 0.0;
581
582 switch (n) {
583 case 4:
584 gain = args[3][0];
585 case 3:
586 lacunarity = args[2][0];
587 case 2:
588 octaves = int(clamp(args[1][0], 1, 8));
589 case 1:
590 p = args[0];
591 }
592
594 double P[3] = {p[0], p[1], p[2]};
596 return result;
597}
598
599Vec3d cturbulence(int n, const Vec3d* args) { return vturbulence(n, args) * .5 + Vec3d(.5); }
600
601double fbm(int n, const Vec3d* args) {
602 // args: octaves, lacunarity, gain
603 int octaves = 6;
604 double lacunarity = 2;
605 double gain = 0.5;
606 Vec3d p = 0.0;
607
608 switch (n) {
609 case 4:
610 gain = args[3][0];
611 case 3:
612 lacunarity = args[2][0];
613 case 2:
614 octaves = int(clamp(args[1][0], 1, 8));
615 case 1:
616 p = args[0];
617 }
618
619 double result = 0.0;
620 double P[3] = {p[0], p[1], p[2]};
622 return .5 * result + .5;
623}
624static const char* fbm_docstring =
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.";
632
633Vec3d vfbm(int n, const Vec3d* args) {
634 // args: octaves, lacunarity, gain
635 int octaves = 6;
636 double lacunarity = 2;
637 double gain = 0.5;
638 Vec3d p = 0.0;
639
640 switch (n) {
641 case 4:
642 gain = args[3][0];
643 case 3:
644 lacunarity = args[2][0];
645 case 2:
646 octaves = int(clamp(args[1][0], 1, 8));
647 case 1:
648 p = args[0];
649 }
650
651 Vec3d result = 0.0;
652 double P[3] = {p[0], p[1], p[2]};
654 return result;
655}
656static const char* vfbm_docstring = "vector vfbm(vector vint octaves=6,float lacunarity=2,float gain=.5)";
657
658double fbm4(int n, const Vec3d* args) {
659 // args: octaves, lacunarity, gain
660 int octaves = 6;
661 double lacunarity = 2;
662 double gain = 0.5;
663 Vec3d p = 0.0;
664 float time = 0.0;
665
666 switch (n) {
667 case 5:
668 gain = args[4][0];
669 case 4:
670 lacunarity = args[3][0];
671 case 3:
672 octaves = int(clamp(args[2][0], 1, 8));
673 case 2:
674 time = static_cast<float>(args[1][0]);
675 case 1:
676 p = args[0];
677 }
678
679 double result = 0.0;
680 double P[4] = {p[0], p[1], p[2], time};
682 return .5 * result + .5;
683}
684static const char* fbm4_docstring =
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.";
692
693Vec3d vfbm4(int n, const Vec3d* args) {
694 // args: octaves, lacunarity, gain
695 int octaves = 6;
696 double lacunarity = 2;
697 double gain = 0.5;
698 Vec3d p = 0.0;
699 float time = 0.0;
700
701 switch (n) {
702 case 5:
703 gain = args[4][0];
704 case 4:
705 lacunarity = args[3][0];
706 case 3:
707 octaves = int(clamp(args[2][0], 1, 8));
708 case 2:
709 time = static_cast<float>(args[1][0]);
710 case 1:
711 p = args[0];
712 }
713
714 Vec3d result = 0.0;
715 double P[4] = {p[0], p[1], p[2], time};
717 return result;
718}
719static const char* vfbm4_docstring = "vector vfbm4(vector v,float time,int octaves=6,float lacunarity=2,float gain=.5)";
720
721Vec3d cfbm(int n, const Vec3d* args) { return vfbm(n, args) * .5 + Vec3d(.5); }
722static const char* cfbm_docstring = "color cfbm(vector vint octaves=6,float lacunarity=2,float gain=.5)";
723
724Vec3d cfbm4(int n, const Vec3d* args) { return vfbm4(n, args) * .5 + Vec3d(.5); }
725static const char* cfbm4_docstring = "color cfbm4(vector v,float time,int octaves=6,float lacunarity=2,float gain=.5)";
726
727double cellnoise(const Vec3d& p) {
728 double result;
729 double args[3] = {p[0], p[1], p[2]};
730 CellNoise<3, 1>(args, &result);
731 return result;
732}
733static const char* cellnoise_docstring =
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.";
737
740 double args[3] = {p[0], p[1], p[2]};
741 CellNoise<3, 3>(args, &result[0]);
742 return result;
743}
744static const char* ccellnoise_docstring =
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.";
748
749double pnoise(const Vec3d& p, const Vec3d& period) {
750 double result;
751 double args[3] = {p[0], p[1], p[2]};
752 int pargs[3] = {std::max((int)1, (int)period[0]),
753 std::max((int)1, (int)period[1]),
754 std::max((int)1, (int)period[2])};
755 PNoise<3, 1>(args, pargs, &result);
756 return result;
757}
758static const char* pnoise_docstring =
759 "float pnoise ( vector v, vector period )\n"
760 "periodic noise";
767
768static Vec3d* voronoi_points(VoronoiPointData& data, const Vec3d& cell, double jitter) {
769 if (cell == data.cell && jitter == data.jitter) return data.points;
770 data.cell = cell;
771 data.jitter = jitter;
772
773 int n = 0;
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++) {
777 Vec3d testcell = cell + Vec3d(i, j, k);
778 data.points[n] = testcell + jitter * (ccellnoise(testcell) - Vec3d(.5));
779 }
780 }
781 }
782 return data.points;
783}
784
785static void voronoi_f1_3d(VoronoiPointData& data, const Vec3d& p, double jitter, double& f1, Vec3d& pos1) {
786 // from Advanced Renderman, page 257
787 Vec3d thiscell(floor(p[0]) + 0.5, floor(p[1]) + 0.5, floor(p[2]) + 0.5);
788
789 f1 = 1000;
790 Vec3d* pos = voronoi_points(data, thiscell, jitter);
791 Vec3d* end = pos + 27;
792
793 for (; pos != end; pos++) {
794 Vec3d offset = *pos - p;
795 double dist = offset.dot(offset);
796 if (dist < f1) {
797 f1 = dist;
798 pos1 = *pos;
799 }
800 }
801 f1 = sqrt(f1);
802}
803
805 const Vec3d& p,
806 double jitter,
807 double& f1,
808 Vec3d& pos1,
809 double& f2,
810 Vec3d& pos2) {
811 // from Advanced Renderman, page 258
812 Vec3d thiscell(floor(p[0]) + 0.5, floor(p[1]) + 0.5, floor(p[2]) + 0.5);
813 f1 = f2 = 1000;
814 Vec3d* pos = voronoi_points(data, thiscell, jitter);
815 Vec3d* end = pos + 27;
816
817 for (; pos != end; pos++) {
818 Vec3d offset = *pos - p;
819 double dist = offset.dot(offset);
820 if (dist < f1) {
821 f2 = f1;
822 pos2 = pos1;
823 f1 = dist;
824 pos1 = *pos;
825 } else if (dist < f2) {
826 f2 = dist;
827 pos2 = *pos;
828 }
829 }
830 f1 = sqrt(f1);
831 f2 = sqrt(f2);
832}
833
834Vec3d voronoiFn(VoronoiPointData& data, int n, const Vec3d* args) {
835 // args = p, type, jitter,
836 // fbmScale, fbmOctaves, fbmLacunarity, fbmGain
837 Vec3d p;
838 int type = 1;
839 double jitter = 0.5;
840 double fbmScale = 0;
841 double fbmOctaves = 4;
842 double fbmLacunarity = 2;
843 double fbmGain = 0.5;
844 switch (n) {
845 case 7:
846 fbmGain = args[6][0];
847 case 6:
848 fbmLacunarity = args[5][0];
849 case 5:
850 fbmOctaves = args[4][0];
851 case 4:
852 fbmScale = args[3][0];
853 case 3:
854 jitter = clamp(args[2][0], 1e-3, 1);
855 case 2:
856 type = int(args[1][0]);
857 case 1:
858 p = args[0];
859 }
860
861 if (fbmScale > 0) {
862 Vec3d fbmArgs[4];
863 fbmArgs[0] = 2 * p;
864 fbmArgs[1] = fbmOctaves;
866 fbmArgs[3] = fbmGain;
867 p += fbmScale * vfbm(4, fbmArgs);
868 }
869
870 double f1, f2;
871 Vec3d pos1, pos2;
872 if (type >= 3)
873 voronoi_f1f2_3d(data, p, jitter, f1, pos1, f2, pos2);
874 else
875 voronoi_f1_3d(data, p, jitter, f1, pos1);
876
877 switch (type) {
878 case 1:
879 pos1[0] += 10;
880 return cellnoise(pos1);
881 case 2:
882 return f1;
883 case 3:
884 return f2;
885 case 4:
886 return f2 - f1;
887 case 5: {
888 float scalefactor = static_cast<float>((pos2 - pos1).length() / ((pos1 - p).length() + (pos2 - p).length()));
889 return smoothstep(f2 - f1, 0, 0.1 * scalefactor);
890 }
891 }
892
893 return 0.0;
894}
895const static char* voronoi_docstring =
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.";
899
900Vec3d cvoronoiFn(VoronoiPointData& data, int n, const Vec3d* args) {
901 // args = p, type, jitter,
902 // fbmScale, fbmOctaves, fbmLacunarity, fbmGain
903 Vec3d p;
904 int type = 1;
905 double jitter = 0.5;
906 double fbmScale = 0;
907 double fbmOctaves = 4;
908 double fbmLacunarity = 2;
909 double fbmGain = 0.5;
910 switch (n) {
911 case 7:
912 fbmGain = args[6][0];
913 case 6:
914 fbmLacunarity = args[5][0];
915 case 5:
916 fbmOctaves = args[4][0];
917 case 4:
918 fbmScale = args[3][0];
919 case 3:
920 jitter = clamp(args[2][0], 1e-3, 1);
921 case 2:
922 type = int(args[1][0]);
923 case 1:
924 p = args[0];
925 }
926
927 if (fbmScale > 0) {
928 Vec3d fbmArgs[4];
929 fbmArgs[0] = 2 * p;
930 fbmArgs[1] = fbmOctaves;
932 fbmArgs[3] = fbmGain;
933 p += fbmScale * vfbm(4, fbmArgs);
934 }
935
936 double f1, f2;
937 Vec3d pos1, pos2;
938 if (type >= 3)
939 voronoi_f1f2_3d(data, p, jitter, f1, pos1, f2, pos2);
940 else
941 voronoi_f1_3d(data, p, jitter, f1, pos1);
942
943 Vec3d color = ccellnoise(pos1);
944 switch (type) {
945 case 1:
946 pos1[0] += 10;
947 return color;
948 case 2:
949 return f1 * color;
950 case 3:
951 return f2 * color;
952 case 4:
953 return (f2 - f1) * color;
954 case 5: {
955 float scalefactor = static_cast<float>((pos2 - pos1).length() / ((pos1 - p).length() + (pos2 - p).length()));
956 return smoothstep(f2 - f1, 0, 0.1 * scalefactor) * color;
957 }
958 }
959
960 return 0.0;
961}
962const static char* cvoronoi_docstring =
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.";
966
967Vec3d pvoronoiFn(VoronoiPointData& data, int n, const Vec3d* args) {
968 // args = p, jitter,
969 // fbmScale, fbmOctaves, fbmLacunarity, fbmGain
970 Vec3d p;
971 double jitter = 0.5;
972 double fbmScale = 0;
973 double fbmOctaves = 4;
974 double fbmLacunarity = 2;
975 double fbmGain = 0.5;
976 switch (n) {
977 case 6:
978 fbmGain = args[5][0];
979 case 5:
980 fbmLacunarity = args[4][0];
981 case 4:
982 fbmOctaves = args[3][0];
983 case 3:
984 fbmScale = args[2][0];
985 case 2:
986 jitter = clamp(args[1][0], 1e-3, 1);
987 case 1:
988 p = args[0];
989 }
990
991 if (fbmScale > 0) {
992 Vec3d fbmArgs[4];
993 fbmArgs[0] = 2 * p;
994 fbmArgs[1] = fbmOctaves;
996 fbmArgs[3] = fbmGain;
997 p += fbmScale * vfbm(4, fbmArgs);
998 }
999
1000 double f1;
1001 Vec3d pos1;
1002 voronoi_f1_3d(data, p, jitter, f1, pos1);
1003 return pos1;
1004}
1005const static char* pvoronoi_docstring =
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.";
1009
1011 public:
1012 typedef Vec3d VoronoiFunc(VoronoiPointData& data, int n, const Vec3d* args);
1014
1016 // check number of arguments
1017 int nargs = node->numChildren();
1018 if (nargs < 1 || nargs > 7) {
1019 node->addError("Wrong number of arguments, should be 1 to 7");
1020 return ExprType().Error();
1021 }
1022
1023 bool valid = true;
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();
1027 }
1028
1030 return new VoronoiPointData();
1031 }
1032
1033 virtual void eval(ArgHandle args) {
1034 VoronoiPointData* data = static_cast<VoronoiPointData*>(args.data);
1035 int nargs = args.nargs();
1036 Vec3d* sevArgs = (Vec3d*)alloca(sizeof(Vec3d) * nargs);
1037
1038 for (int i = 0; i < nargs; i++)
1039 for (int j = 0; j < 3; j++) sevArgs[i][j] = args.inFp<3>(i)[j];
1040
1041 Vec3d result = _vfunc(*data, nargs, sevArgs);
1042 double* out = &args.outFp;
1043 for (int i = 0; i < 3; i++) out[i] = result[i];
1044 }
1045
1047
1048 private:
1051
1052double dist(double ax, double ay, double az, double bx, double by, double bz) {
1053 double x = ax - bx;
1054 double y = ay - by;
1055 double z = az - bz;
1056 return sqrt(x * x + y * y + z * z);
1057}
1058static const char* dist_docstring =
1059 "float dist(vector a, vector b)\n"
1060 "distance between two points";
1061
1062double length(const Vec3d& v) { return sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); }
1063static const char* length_docstring =
1064 "float length(vector v)\n"
1065 "length of vector";
1066
1067double hypot(double x, double y) { return sqrt(x * x + y * y); }
1068static const char* hypot_docstring =
1069 "float hypot(vector v)\n"
1070 "length of 2d vector [x,y]";
1071
1072double dot(const Vec3d& a, const Vec3d& b) { return a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; }
1073static const char* dot_docstring =
1074 "float dot(vector a,vector b)\n"
1075 "vector dot product";
1076
1077Vec3d norm(const Vec3d& a) {
1078 double len = length(a);
1079 if (len == 0)
1080 return 0.0;
1081 else
1082 return a / len;
1083}
1084static const char* norm_docstring =
1085 "vector norm(vector v)\n"
1086 "vector scaled to unit length";
1087
1088Vec3d cross(const Vec3d& a, const Vec3d& b) {
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]);
1090}
1091static const char* cross_docstring =
1092 "vector cross(vector a,vector b)\n"
1093 "vector cross product";
1094
1095double angle(const Vec3d& a, const Vec3d& b) {
1096 double len = length(a) * length(b);
1097 if (len == 0) return 0;
1098 return acos(dot(a, b) / len);
1099}
1100static const char* angle_docstring =
1101 "float angle(vector a,vector b)\n"
1102 "angle between two vectors (in radians)";
1103
1104Vec3d ortho(const Vec3d& a, const Vec3d& b) { return norm(cross(a, b)); }
1105static const char* ortho_docstring =
1106 "vector angle(vector a,vector b)\n"
1107 "normalized vector orthogonal to a and b scaled to unit length";
1108
1109Vec3d rotate(int n, const Vec3d* args) {
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();
1115 if (!len) return P;
1116 return P.rotateBy(axis / len, angle);
1117}
1118static const char* rotate_docstring =
1119 "vector rotate(vector v,vector axis,float angle)\n"
1120 "rotates v around axis by given angle (in radians)";
1121
1122Vec3d up(const Vec3d& P, const Vec3d& upvec) {
1123 // rotate vec so y-axis points to upvec
1124 Vec3d yAxis(0, 1, 0);
1125 return P.rotateBy(ortho(upvec, yAxis), angle(upvec, yAxis));
1126}
1127static const char* up_docstring =
1128 "vector up(vector P,vector upvec)\n"
1129 "rotates v such that the Y axis points in the given up direction";
1130
1131double cycle(double index, double loRange, double hiRange) {
1132 int lo = int(loRange);
1133 int hi = int(hiRange);
1134 int range = hi - lo + 1;
1135 if (range <= 0) return lo;
1136 int result = int(index) % range;
1137 if (result < 0) result += range;
1138 return lo + result;
1139}
1140static const char* cycle_docstring =
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";
1145
1146double pick(int n, double* params) {
1147 if (n < 3) return 0;
1148 double index = hash(1, &params[0]);
1149 int loRange = int(params[1]);
1150 int hiRange = int(params[2]);
1151 int range = hiRange - loRange + 1;
1152 if (range <= 0) return loRange;
1153 int numWeights = n - 3;
1155
1156 // build cutoff points based on weights
1157 double* cutoffs = (double*)alloca(sizeof(double) * range);
1158 double* weights = (double*)alloca(sizeof(double) * range);
1159 double total = 0;
1160 for (int i = 0; i < range; i++) {
1161 double weight = i < numWeights ? params[i + 3] : 1;
1162 total += weight;
1163 cutoffs[i] = total;
1164 weights[i] = weight;
1165 }
1166
1167 if (total == 0) return loRange;
1168
1169 // scale value from [0..1] to [0..total] range
1170 index *= total;
1171
1172 // bsearch cutoff table to find index that spans value
1173 int lo = 0, hi = range - 1;
1174 while (lo < hi) {
1175 int m = (lo + hi) / 2;
1176 if (index <= cutoffs[m])
1177 hi = m;
1178 else
1179 lo = m + 1;
1180 }
1181
1182 // skip zero-length intervals
1183 if (weights[lo] == 0) {
1184 if (lo > 0 && cutoffs[lo] > 0) // scan backward if possible
1185 while (--lo > 0 && weights[lo] == 0)
1186 ;
1187 else if (lo < range - 1) // else scan forward if possible
1188 while (++lo < range - 1 && weights[lo] == 0)
1189 ;
1190 }
1191
1192 // add offset and return result
1193 return loRange + lo;
1194}
1195static const char* pick_docstring =
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).&nbsp; The values will be distributed according\n"
1199 "to the supplied weights.&nbsp; Any weights not supplied are assumed to\n"
1200 "be 1.0.";
1201
1202double swatch(int n, double* params) { return choose(n, params); }
1203static const char* swatch_docstring =
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]).";
1206
1207double choose(int n, double* params) {
1208 if (n < 3) return 0;
1209 double key = params[0];
1210 // NaN protection
1211 if (key != key) return 0;
1212 int nvals = n - 1;
1213 return params[1 + int(clamp(key * nvals, 0, nvals - 1))];
1214}
1215static const char* choose_docstring =
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]).";
1218
1219double wchoose(int n, double* params) {
1220 if (n < 5) return 0;
1221 double key = params[0];
1222 // NaN protection
1223 if (key != key) return 0;
1224 int nvals = (n - 1) / 2; // nweights = nvals
1225
1226 // build cutoff points based on weights
1227 double* cutoffs = (double*)alloca(sizeof(double) * nvals);
1228 double* weights = (double*)alloca(sizeof(double) * nvals);
1229 double total = 0;
1230 for (int i = 0; i < nvals; i++) {
1231 double weight = params[i * 2 + 2];
1232 total += weight;
1233 cutoffs[i] = total;
1234 weights[i] = weight;
1235 }
1236
1237 if (total == 0) return params[1];
1238
1239 // scale value from [0..1] to [0..total] range
1240 key *= total;
1241
1242 // bsearch cutoff table to find index that spans value
1243 int lo = 0, hi = nvals - 1;
1244 while (lo < hi) {
1245 int m = (lo + hi) / 2;
1246 if (key <= cutoffs[m])
1247 hi = m;
1248 else
1249 lo = m + 1;
1250 }
1251
1252 // skip zero-length intervals
1253 if (weights[lo] == 0) {
1254 if (lo > 0 && cutoffs[lo] > 0) // scan backward if possible
1255 while (--lo > 0 && weights[lo] == 0)
1256 ;
1257 else if (lo < nvals - 1) // else scan forward if possible
1258 while (++lo < nvals - 1 && weights[lo] == 0)
1259 ;
1260 }
1261
1262 // return corresponding value
1263 return params[lo * 2 + 1];
1264}
1265static const char* wchoose_docstring =
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.";
1269
1270double spline(int n, double* params) {
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];
1275 int nsegs = n - 4;
1276 double seg;
1277 u = modf(u * nsegs, &seg);
1278 double* p = &params[int(seg) + 1];
1279 double u2 = u * u;
1280 double u3 = u2 * u;
1281 return 0.5 * (p[0] * (-u3 + 2 * u2 - u) + p[1] * (3 * u3 - 5 * u2 + 2) + p[2] * (-3 * u3 + 4 * u2 + u) +
1282 p[3] * (u3 - u2));
1283}
1284static const char* spline_docstring =
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]";
1288
1289template <class T>
1294
1296 public:
1298
1300 // check number of arguments
1301 int nargs = node->numChildren();
1302 if ((nargs - 1) % 3) {
1303 node->addError("Wrong number of arguments, should be multiple of 3 plus 1");
1304 return ExprType().Error();
1305 }
1306
1307 bool valid = true;
1308 valid &= node->checkArg(0, ExprType().FP(1).Varying(), envBuilder);
1309 for (int i = 1; i < nargs; i += 3) {
1310 valid &= node->checkArg(i, ExprType().FP(1).Constant(), envBuilder);
1311 valid &= node->checkArg(i + 1, ExprType().FP(1).Constant(), envBuilder);
1312 valid &= node->checkArg(i + 2, ExprType().FP(1).Constant(), envBuilder);
1313 }
1314 return valid ? ExprType().FP(1).Varying() : ExprType().Error();
1315 }
1316
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;
1326 // TODO: fix error checking!
1327 }
1328 data->curve.addPoint(pos, val, interpolant);
1329 }
1330 data->curve.preparePoints();
1331 return data;
1332 }
1333
1334 virtual void eval(ArgHandle args) {
1335 CurveData<double>* data = static_cast<CurveData<double>*>(args.data);
1336 double param = args.inFp<1>(0)[0];
1337 args.outFp = data->curve.getValue(param);
1338 }
1339
1341static const char* curve_docstring =
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)";
1347
1350 // check number of arguments
1351 int nargs = node->numChildren();
1352 if ((nargs - 1) % 3) {
1353 node->addError("Wrong number of arguments, should be multiple of 3 plus 1");
1354 return ExprType().Error().Varying();
1355 }
1356
1357 bool valid = true;
1358 valid &= node->checkArg(0, ExprType().FP(1).Varying(), envBuilder);
1359 for (int i = 1; i < nargs; i += 3) {
1360 valid &= node->checkArg(i, ExprType().FP(1).Constant(), envBuilder);
1361 valid &= node->checkArg(i + 1, ExprType().FP(3).Constant(), envBuilder);
1362 valid &= node->checkArg(i + 2, ExprType().FP(1).Constant(), envBuilder);
1363 }
1364 return valid ? ExprType().FP(3).Varying() : ExprType().Error();
1365 }
1366
1369 for (int i = 1; i < args.nargs() - 2; i += 3) {
1370 double pos = args.inFp<1>(i)[0];
1371 Vec3dRef val(&args.inFp<3>(i + 1)[0]);
1372 double interpDouble = args.inFp<1>(i + 2)[0];
1373 int interpInt = (int)interpDouble;
1376 // TODO: fix error checking!
1377 }
1378 data->curve.addPoint(pos, val, interpolant);
1379 }
1380 data->curve.preparePoints();
1381 return data;
1382 }
1383
1384 virtual void eval(ArgHandle args) {
1385 CurveData<Vec3d>* data = static_cast<CurveData<Vec3d>*>(args.data);
1386 double param = args.inFp<1>(0)[0];
1387 Vec3d result = data->curve.getValue(param);
1388 double* out = &args.outFp;
1389 for (int k = 0; k < 3; k++) out[k] = result[k];
1390 }
1391
1392 public:
1393 CCurveFuncX() : ExprFuncSimple(true) {} // Thread Safe
1394 virtual ~CCurveFuncX() {}
1396static const char* ccurve_docstring =
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)";
1402
1403class GetVar : public ExprFuncSimple {
1404 struct Data : public ExprFuncNode::Data {
1405 typedef void (*func)(double* in, double* out);
1406 Data(func fIn, int dim) : f(fIn), dim(dim) {}
1408 int dim;
1409 };
1410
1412 bool valid = true;
1413 valid &= node->checkArg(0, ExprType().String().Constant(), envBuilder);
1414 std::string varName = node->getStrArg(0);
1415 ExprVarNode* varNode = new ExprVarNode(node->expr(), varName.c_str());
1417 if (varType.isValid()) {
1418 node->removeLastChild(); // remove the useless default argument from the arugment list
1419 node->removeLastChild(); // remove the useless default argument from the arugment list
1420 node->addChild(varNode);
1421 } else {
1422 delete varNode;
1423 node->swapChildren(0, 1); // move the default argument in the beginning
1424 varType = node->child(0)->prep(wantScalar, envBuilder);
1425 node->removeLastChild(); // remove the useless string argument
1426 }
1427 return varType.isValid() ? varType : ExprType().Error();
1428 }
1429
1431 return new Data(node->type().isFP() ? getTemplatizedOp<Assign, Data::func>(node->type().dim()) : nullptr,
1432 node->type().dim());
1433 }
1434
1435 template <int d>
1436 struct Assign {
1437 static void f(double* out, double* in) {
1438 for (int k = 0; k < d; k++) out[k] = in[k];
1439 }
1440 };
1441
1442 virtual void eval(ArgHandle args) {
1443 Data* data = static_cast<Data*>(args.data);
1444 assert(data);
1445 double* out = &args.outFp;
1446 // for(int i=0;i<data->dim;i++) std::cerr<<" "<<args.inFp<1>(0)[i];
1447 // std::cerr<<std::endl;
1448 if (data->f)
1449 data->f(out, &args.inFp<1>(0)[0]);
1450 else
1451 throw std::runtime_error("getVar does not support non FP types right now got type");
1452 }
1453
1454 public:
1455 GetVar() : ExprFuncSimple(true) {} // Thread Safe
1456 virtual ~GetVar() {}
1458static const char* getVar_docstring =
1459 "getVar(string varName,vector defaultValue)\n"
1460 "return value of varName if variable exists, otherwise return defaultValue";
1461
1463 struct Data : public ExprFuncNode::Data {
1464 std::vector<std::pair<int, int> > ranges;
1465 std::string format;
1466 };
1467
1468 public:
1470 int nargs = node->numChildren();
1471 if (nargs < 1) {
1472 node->addError("Wrong number of arguments, should be GE 1");
1473 return ExprType().Error().Varying();
1474 }
1475
1476 bool valid = true;
1477 valid &= node->checkArg(0, ExprType().String().Constant(), envBuilder);
1478 for (int i = 1; i < nargs; ++i)
1479 valid &=
1480 (node->checkArg(i, ExprType().FP(1), envBuilder) || node->checkArg(i, ExprType().FP(3), envBuilder));
1481 return ExprType().FP(1).Constant();
1482 }
1483
1485 // parse format string
1486 unsigned int bakeStart = 0;
1487 int searchStart = 0;
1488 int needed = 0;
1489 Data* data = new Data;
1490 data->format = args.inStr(0);
1491 std::string& format = data->format;
1492 std::vector<std::pair<int, int> >& ranges = data->ranges;
1493
1494 int items = 0;
1495 while (1) {
1496 std::size_t percentStart = format.find('%', searchStart);
1497 if (percentStart == std::string::npos) break;
1498 if (percentStart + 1 == format.length()) {
1499 // node->addError("Unexpected end of format string");
1500 delete data;
1501 assert(false);
1502 } else if (format[percentStart + 1] == '%') {
1503 searchStart = static_cast<int>(percentStart + 2);
1504 continue;
1505 } else if (format[percentStart + 1] == 'v' || format[percentStart + 1] == 'f') {
1506 char c = format[percentStart + 1];
1507 int code = (c == 'v') ? -1 : -2;
1508 needed++;
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));
1511 items++;
1512 searchStart = static_cast<int>(percentStart + 2);
1514 } else {
1515 // node->addError("Invalid format string, only %v is allowed");
1516 delete data;
1517 // TODO: check that this is correct
1518 // return ExprType().Error().Varying();
1519 // return false;
1520 assert(false);
1521 }
1522 }
1523 if (bakeStart != format.length()) ranges.push_back(std::pair<int, int>(bakeStart, static_cast<int>(format.length())));
1524
1525 if (items != args.nargs() - 1) {
1526 // node->addError("Wrong number of arguments for format string");
1527 delete data;
1528 // TODO: check that this is correct
1529 // return ExprType().Error().Varying();
1530 // return false;
1531 assert(false);
1532 }
1533
1534 return data;
1535 }
1536
1537 virtual void eval(ArgHandle args) {
1538 Data* data = (Data*)args.data;
1539 int item = 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];
1544 item++;
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] << "]";
1548 item++;
1549 } else {
1550 std::cerr << data->format.substr(range.first, range.second - range.first);
1551 }
1552 }
1553 std::cerr << std::endl;
1554
1555 args.outFp = 0;
1556 }
1557
1558 PrintFuncX() : ExprFuncSimple(false) {} // not thread safe
1559
1561static const char* printf_docstring =
1562 "printf(string format,[vec0, vec1, ...])\n"
1563 "Prints out a string to STDOUT, Format parameter allowed is %v";
1564
1565
1566// Format specifier categories for SPrintFuncX
1567static const std::string _intSpec("diouxXc");
1568static const std::string _doubleSpec("eEfFgGaA");
1569static const std::string _strSpec("s");
1570
1572{
1573 struct StringData : public SeExpr2::ExprFuncNode::Data, public std::string
1574 {
1575 };
1576
1577public:
1578 SPrintFuncX() : ExprFuncSimple(false) {} // not thread safe
1579
1581 {
1582 int nargs = node->numChildren();
1583 if (nargs < 1) {
1584 node->addError("Wrong number of arguments, should be >= 1");
1585 return ExprType().Error().Constant();
1586 }
1587 if (! node->checkArg(0, ExprType().String().Constant(), envBuilder)) {
1588 node->addError("First argument must be a string.");
1589 return ExprType().Error().Constant();
1590 }
1591
1592 const std::string& format = static_cast<const ExprStrNode*>(node->child(0))->str();
1593
1594 static const std::string strSpec("s");
1595 size_t searchStart = 0;
1596 size_t exprArg = 1;
1597 while (1) {
1598 const size_t specStart = format.find('%', searchStart);
1599 if (specStart == std::string::npos) break;
1600 if (specStart + 1 == format.length()) {
1601 node->addError("incomplete format specifier");
1602 return ExprType().Error().Constant();
1603 }
1604 if (format[specStart + 1] == '%') {
1605 searchStart = specStart + 2; // Skip "%%"
1606 continue;
1607 }
1608
1609 const size_t specEnd = format.find_first_of(_intSpec + _doubleSpec + _strSpec,
1610 specStart);
1611 if (specEnd == std::string::npos) {
1612 node->addError("incomplete format specifier");
1613 return ExprType().Error().Constant();
1614 }
1615 if (_strSpec.find(format[specEnd]) != std::string::npos) {
1616 if (! node->checkArg(exprArg, ExprType().String(), envBuilder)) {
1617 return ExprType().Error().Constant();
1618 }
1619 }
1620 else {
1621 if (! node->checkArg(exprArg, ExprType().FP(1), envBuilder)) {
1622 return ExprType().Error().Constant();
1623 }
1624 }
1625 ++exprArg;
1626 searchStart = specEnd + 1;
1627 };
1628 return ExprType().String().Constant();
1629 }
1630
1632 {
1633 return new StringData();
1634 }
1635
1636 virtual void eval(ArgHandle args)
1637 {
1638 StringData& result = *reinterpret_cast<StringData*>(args.data);
1639 result.assign(args.inStr(0));
1640
1641 char fragment[255];
1642 size_t searchStart = 0;
1643 size_t exprArg = 1;
1644 while (1) {
1645 const size_t specStart = result.find('%', searchStart);
1646 if (specStart == std::string::npos) break;
1647 if (result[specStart + 1] == '%') {
1648 result.erase(specStart, 1);
1649 searchStart = specStart + 1;
1650 continue;
1651 }
1652
1653 const size_t specEnd = result.find_first_of(_intSpec + _doubleSpec + _strSpec,
1654 specStart);
1655 const std::string& spec = result.substr(specStart, specEnd - specStart + 1);
1656 int fragLen = -1;
1657 if (std::string::npos != _intSpec.find(result[specEnd]))
1658 fragLen = snprintf(fragment, 255, spec.c_str(),
1659 int(args.inFp<1>(exprArg++)[0]));
1660 else if (std::string::npos != _doubleSpec.find(result[specEnd]))
1661 fragLen = snprintf(fragment, 255, spec.c_str(),
1662 args.inFp<1>(exprArg++)[0]);
1663 else if (std::string::npos != _strSpec.find(result[specEnd]))
1664 fragLen = snprintf(fragment, 255, spec.c_str(),
1665 args.inStr(exprArg++));
1666 assert(fragLen >= 0);
1667
1668 result.replace(specStart, spec.size(), fragment);
1669 searchStart += fragLen + 1;
1670 };
1671
1672 args.outStr = const_cast<char*>(result.c_str());
1673 }
1674
1676static const char* sprintf_docstring =
1677 "sprintf(string format, [double|string, double|string, ...])\n"
1678 "Returns a string formatted from the given values. See 'man sprintf' for format details.";
1679
1680
1681#if 0
1682
1683class TestFunc:public ExprFuncSimple
1684{
1685 struct MyData:public ExprFuncNode::Data
1686 {
1687 float foo;
1688 MyData(float foo)
1689 :foo(foo)
1690 {}
1691 };
1692public:
1693 TestFunc()
1694 :ExprFuncSimple(true)
1695 {}
1697 {
1698 bool valid=true;
1699 valid &= node->checkArg(0,ExprType().FP(3).Varying(),envBuilder);
1700 valid &= node->checkArg(1,ExprType().FP(1).Constant(),envBuilder);
1701 return valid ?ExprType().FP(3).Varying():ExprType().Error();
1702 }
1703 virtual ExprFuncNode::Data* evalConstant(ArgHandle args) const
1704 {
1705 //std::cerr<<"evalling const "<<args.inFp<1>(1)<<std::endl;
1706 return new MyData(args.inFp<1>(1)[0]);
1707 }
1708 virtual void eval(ArgHandle args)
1709 {
1710 MyData* data=static_cast<MyData*>(args.data);
1711
1712 Vec<double,3,true>(&args.outFp)=args.inFp<3>(0)+Vec<double,3,false>(data->foo);
1713 }
1714} testfunc;
1715static const char* testfunc_docstring="fdsA";
1716
1717#endif
1718
1720// functions from math.h (global namespace)
1721//#define FUNC(func) define(#func, ExprFunc(::func))
1722#define FUNCADOC(name, func) define3(name, ExprFunc(::func), func##_docstring)
1723#define FUNCDOC(func) define3(#func, ExprFunc(::func), func##_docstring)
1724 FUNCADOC("abs", fabs);
1725 FUNCDOC(acos);
1726 FUNCDOC(asin);
1727 FUNCDOC(atan);
1728 FUNCDOC(atan2);
1729 FUNCDOC(ceil);
1730 FUNCDOC(cos);
1731 FUNCDOC(cosh);
1732 FUNCDOC(exp);
1733 FUNCDOC(floor);
1734 FUNCDOC(fmod);
1735 FUNCDOC(log);
1736 FUNCDOC(log10);
1737 FUNCDOC(pow);
1738 FUNCDOC(sin);
1739 FUNCDOC(sinh);
1740 FUNCDOC(sqrt);
1741 FUNCDOC(tan);
1742 FUNCDOC(tanh);
1743#ifndef SEEXPR_WIN32
1744 FUNCDOC(cbrt);
1745 FUNCDOC(asinh);
1746 FUNCDOC(acosh);
1747 FUNCDOC(atanh);
1748 FUNCDOC(trunc);
1749#endif
1750// local functions (SeExpr2 namespace)
1751//#undef FUNC
1752#undef FUNCDOC
1753//#define FUNC(func) define(#func, ExprFunc(SeExpr2::func))
1754//#define FUNCN(func, min, max) define(#func, ExprFunc(SeExpr2::func, min, max))
1755#define FUNCDOC(func) define3(#func, ExprFunc(SeExpr2::func), func##_docstring)
1756#define FUNCNDOC(func, min, max) define3(#func, ExprFunc(SeExpr2::func, min, max), func##_docstring)
1757
1758 // trig
1759 FUNCDOC(deg);
1760 FUNCDOC(rad);
1761 FUNCDOC(cosd);
1762 FUNCDOC(sind);
1763 FUNCDOC(tand);
1764 FUNCDOC(acosd);
1765 FUNCDOC(asind);
1766 FUNCDOC(atand);
1767 FUNCDOC(atan2d);
1768
1769 // clamping
1770 FUNCDOC(clamp);
1771 FUNCDOC(round);
1772 FUNCDOC(max);
1773 FUNCDOC(min);
1774
1775 // blending / remapping
1776 FUNCDOC(invert);
1778 FUNCDOC(expand);
1779 FUNCDOC(fit);
1780 FUNCDOC(gamma);
1781 FUNCDOC(bias);
1787 FUNCDOC(remap);
1788 FUNCDOC(mix);
1789 FUNCNDOC(hsi, 4, 5);
1790 FUNCNDOC(midhsi, 5, 7);
1793 FUNCNDOC(saturate, 2, 2);
1794
1795 // noise
1796 FUNCNDOC(hash, 1, -1);
1797 FUNCNDOC(noise, 1, 4);
1798 FUNCDOC(snoise);
1799 FUNCDOC(vnoise);
1800 FUNCDOC(cnoise);
1801 FUNCNDOC(snoise4, 2, 2);
1802 FUNCNDOC(vnoise4, 2, 2);
1803 FUNCNDOC(cnoise4, 2, 2);
1804 FUNCNDOC(turbulence, 1, 4);
1805 FUNCNDOC(vturbulence, 1, 4);
1806 FUNCNDOC(cturbulence, 1, 4);
1807 FUNCNDOC(fbm, 1, 4);
1808 FUNCNDOC(vfbm, 1, 4);
1809 FUNCNDOC(cfbm, 1, 4);
1812 FUNCDOC(pnoise);
1813 FUNCNDOC(fbm4, 2, 5);
1814 FUNCNDOC(vfbm4, 2, 5);
1815 FUNCNDOC(cfbm4, 2, 5);
1816
1817 // vectors
1818 FUNCDOC(dist);
1819 FUNCDOC(length);
1820 FUNCDOC(hypot);
1821 FUNCDOC(dot);
1822 FUNCDOC(norm);
1823 FUNCDOC(cross);
1824 FUNCDOC(angle);
1825 FUNCDOC(ortho);
1826 FUNCNDOC(rotate, 3, 3);
1827 FUNCDOC(up);
1828
1829 // variations
1830 FUNCDOC(cycle);
1831 FUNCNDOC(pick, 3, -1);
1832 FUNCNDOC(choose, 3, -1);
1833 FUNCNDOC(wchoose, 4, -1);
1834 FUNCNDOC(swatch, 3, -1);
1835 FUNCNDOC(spline, 5, -1);
1836
1837 // FuncX interface
1838 // noise
1839 FUNCNDOC(voronoi, 1, 7);
1840 FUNCNDOC(cvoronoi, 1, 7);
1841 FUNCNDOC(pvoronoi, 1, 6);
1842 // variations
1843 FUNCNDOC(curve, 1, -1);
1844 FUNCNDOC(ccurve, 1, -1);
1845 FUNCNDOC(getVar, 2, 2);
1846 FUNCNDOC(printf, 1, -1);
1847 // FUNCNDOC(testfunc,2,2);
1848
1849 FUNCNDOC(sprintf, 1, -1);
1850}
1851}
virtual void eval(ArgHandle args)
#define FUNCDOC(func)
virtual ExprType prep(ExprFuncNode *node, bool scalarWanted, ExprVarEnvBuilder &envBuilder) const
#define FUNCNDOC(func, min, max)
#define FUNCADOC(name, func)
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
Platform-specific classes, functions, and includes.
virtual void eval(ArgHandle args)
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
CachedVoronoiFunc(VoronoiFunc *vfunc)
virtual ExprType prep(ExprFuncNode *node, bool scalarWanted, ExprVarEnvBuilder &envBuilder) const
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
Vec3d VoronoiFunc(VoronoiPointData &data, int n, const Vec3d *args)
virtual void eval(ArgHandle args)
virtual void eval(ArgHandle args)
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
virtual ExprType prep(ExprFuncNode *node, bool scalarWanted, ExprVarEnvBuilder &envBuilder) const
Interpolation curve class for double->double and double->Vec3D.
Definition Curve.h:38
InterpType
Supported interpolation types.
Definition Curve.h:43
Node that calls a function.
Definition ExprNode.h:517
Vec< double, d, true > inFp(int i)
Definition ExprFuncX.h:85
ExprFuncNode::Data * data
Definition ExprFuncX.h:99
void(* Define)(const char *name, ExprFunc f)
Definition ExprFunc.h:64
void(* Define3)(const char *name, ExprFunc f, const char *docString)
Definition ExprFunc.h:65
Node that stores a string.
Definition ExprNode.h:502
ExprType & FP(int d)
Mutate this into a floating point type of dimension d.
Definition ExprType.h:90
ExprType & String()
Mutate this into a string type.
Definition ExprType.h:96
ExprType & Error()
Mutate this into an error type.
Definition ExprType.h:102
ExprType & Varying()
Mutate this into a varying lifetime.
Definition ExprType.h:122
ExprType & Constant()
Mutate this into a constant lifetime.
Definition ExprType.h:112
Variable scope builder is used by the type checking and code gen to track visiblity of variables and ...
Definition ExprEnv.h:148
Node that references a variable.
Definition ExprNode.h:465
virtual void eval(ArgHandle args)
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
virtual void eval(ArgHandle args)
virtual ExprFuncNode::Data * evalConstant(const ExprFuncNode *node, ArgHandle args) const
virtual void eval(ArgHandle args)
virtual ExprType prep(ExprFuncNode *node, bool wantScalar, ExprVarEnvBuilder &envBuilder) const
T length() const
Euclidean (2) norm.
Definition Vec.h:211
T dot(const Vec< T, d, refother > &o) const
Definition Vec.h:330
T_VEC_VALUE rotateBy(const Vec< T, 3, refother > &axis, T angle) const
Definition Vec.h:366
Vec3d ortho(const Vec3d &a, const Vec3d &b)
static const char * hypot_docstring
static const char * asind_docstring
Vec3d norm(const Vec3d &a)
SeExpr2::SPrintFuncX sprintf
static const char * dist_docstring
double rad(double angle)
static const char * atan2d_docstring
Vec< double, 3, false > Vec3d
Definition Vec.h:384
static void voronoi_f1_3d(VoronoiPointData &data, const Vec3d &p, double jitter, double &f1, Vec3d &pos1)
static const std::string _doubleSpec("eEfFgGaA")
static const char * sind_docstring
static const char * curve_docstring
static const char * hsi_docstring
static double hslvalue(double x, double y, double H)
static const char * pow_docstring
Vec3d cvoronoiFn(VoronoiPointData &data, int n, const Vec3d *args)
SeExpr2::CachedVoronoiFunc ExprFuncSimple pvoronoi(pvoronoiFn)
SeExpr2::CachedVoronoiFunc ExprFuncSimple cvoronoi(cvoronoiFn)
static const char * tan_docstring
double atan2d(double y, double x)
static const char * pnoise_docstring
double swatch(int n, double *params)
Vec3d up(const Vec3d &P, const Vec3d &upvec)
static const char * vnoise_docstring
static const char * trunc_docstring
static const char * dot_docstring
void defineBuiltins(ExprFunc::Define define, ExprFunc::Define3 define3)
static const char * round_docstring
static const char * remap_docstring
static const char * bias_docstring
double hypot(double x, double y)
static const char * max_docstring
static const std::string _intSpec("diouxXc")
static const char * snoise4_docstring
double boxstep(double x, double a)
double tand(double x)
double snoise4(int n, const Vec3d *args)
static const char * compress_docstring
Vec3d vnoise(const Vec3d &p)
static const char * sin_docstring
double cosd(double x)
static const char * clamp_docstring
static const char * ccurve_docstring
static const char * cbrt_docstring
static const char * vnoise4_docstring
static const char * fbm_docstring
static const char * ceil_docstring
double bias(double x, double b)
static const char * sqrt_docstring
SeExpr2::CCurveFuncX ccurve
double sind(double x)
static const char * fbm4_docstring
static const char * cfbm4_docstring
static const char * sprintf_docstring
static const std::string _strSpec("s")
Vec3d cnoise(const Vec3d &p)
static const char * cycle_docstring
double contrast(double x, double c)
static const char * asin_docstring
static const char * contrast_docstring
static const char * atanh_docstring
static const char * cnoise_docstring
static const char * printf_docstring
double smoothstep(double x, double a, double b)
static const char * spline_docstring
Vec3d cfbm4(int n, const Vec3d *args)
double dot(const Vec3d &a, const Vec3d &b)
double angle(const Vec3d &a, const Vec3d &b)
Vec3d rgbtohsl(const Vec3d &rgb)
static const char * swatch_docstring
static const char * acosh_docstring
static const char * cnoise4_docstring
static const char * midhsi_docstring
double deg(double angle)
static const char * expand_docstring
static const char * cosd_docstring
static const char * turbulence_docstring
static const char * linearstep_docstring
Vec3d vturbulence(int n, const Vec3d *args)
static const char * acosd_docstring
static const char * norm_docstring
static const char * voronoi_docstring
double round(double x)
Vec3d cnoise4(int n, const Vec3d *args)
static const char * saturate_docstring
double mix(double x, double y, double alpha)
static const char * log10_docstring
static const char * atan_docstring
Vec3d hsi(int n, const Vec3d *args)
SeExpr2::CurveData voronoi
static const char * cosh_docstring
Vec3d cturbulence(int n, const Vec3d *args)
double linearstep(double x, double a, double b)
static const char * hsltorgb_docstring
static const char * getVar_docstring
Vec3d hsltorgb(const Vec3d &hsl)
double wchoose(int n, double *params)
double dist(double ax, double ay, double az, double bx, double by, double bz)
double length(const Vec3d &v)
static const char * vturbulence_docstring
static const char * ortho_docstring
static const char * atan2_docstring
double noise(int n, const Vec3d *args)
static const char * ccellnoise_docstring
static const char * fabs_docstring
double fbm(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)
static const char * vfbm_docstring
Vec3d midhsi(int n, const Vec3d *args)
static const char * cfbm_docstring
static Vec3d * voronoi_points(VoronoiPointData &data, const Vec3d &cell, double jitter)
Vec3d vfbm4(int n, const Vec3d *args)
static const char * acos_docstring
double gaussstep(double x, double a, double b)
static const char * boxstep_docstring
static const char * deg_docstring
double hash(int n, double *args)
double remap(double x, double source, double range, double falloff, double interp)
static const char * noise_docstring
Vec3d vnoise4(int n, const Vec3d *args)
Vec3d ccellnoise(const Vec3d &p)
static const char * fit_docstring
double invert(double x)
double turbulence(int n, const Vec3d *args)
Vec3d hsiAdjust(const Vec3d &rgb, double h, double s, double i)
Vec3d cfbm(int n, const Vec3d *args)
static const char * atand_docstring
double max(double x, double y)
Vec3d vfbm(int n, const Vec3d *args)
Vec3d pvoronoiFn(VoronoiPointData &data, int n, const Vec3d *args)
static const char * log_docstring
static const char * cos_docstring
SeExpr2::PrintFuncX printf
static const char * cross_docstring
static const char * choose_docstring
static const char * rotate_docstring
static const char * snoise_docstring
static const char * up_docstring
double compress(double x, double lo, double hi)
static Vec3d saturate(const Vec3d &Cin, double amt)
double pnoise(const Vec3d &p, const Vec3d &period)
static const char * floor_docstring
static const char * vfbm4_docstring
static const char * mix_docstring
static const char * rgbtohsl_docstring
double acosd(double x)
static const char * wchoose_docstring
static const char * pvoronoi_docstring
static const char * sinh_docstring
Vec3d cross(const Vec3d &a, const Vec3d &b)
static const char * rad_docstring
static const char * tand_docstring
double clamp(double x, double lo, double hi)
Vec3d voronoiFn(VoronoiPointData &data, int n, const Vec3d *args)
double min(double x, double y)
static const char * tanh_docstring
static const char * gaussstep_docstring
static const char * fmod_docstring
static const char * hash_docstring
static const char * cellnoise_docstring
static const char * length_docstring
static const char * invert_docstring
static const char * cvoronoi_docstring
double fit(double x, double a1, double b1, double a2, double b2)
double expand(double x, double lo, double hi)
double gamma(double x, double g)
static const char * gamma_docstring
double cellnoise(const Vec3d &p)
Vec3d rotate(int n, const Vec3d *args)
static const char * min_docstring
double snoise(const Vec3d &p)
SeExpr2::CurveFuncX curve
SeExpr2::GetVar getVar
static const char * pick_docstring
static const char * angle_docstring
double atand(double x)
static const char * smoothstep_docstring
static const char * cturbulence_docstring
static const char * exp_docstring
double asind(double x)
double fbm4(int n, const Vec3d *args)
static const char * asinh_docstring
base class for custom instance data
Definition ExprNode.h:570
static void f(double *out, double *in)
void(* func)(double *in, double *out)
Data(func fIn, int dim)
std::vector< std::pair< int, int > > ranges
* 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
</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
For< b ></b >< b ></b >< b > cycle
Definition userdoc.txt:443
Between a and b
Definition userdoc.txt:180
When x is within< i > range</i > of source
Definition userdoc.txt:111
The result is computed int loRange
Definition userdoc.txt:322
< br > pow($a, 0.5)+ $b< br >< br ></div > External variables can also be overridden by local assignment. &nbsp
For< b ></b >< b ></b >< b ></b >< b > spline
Definition userdoc.txt:443
Defined as float g float a1
Definition userdoc.txt:162
Defined as a *alpha b *alpha< br ></div >< br > float< b > float a
Definition userdoc.txt:174
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< b ></b >< b > choose
Definition userdoc.txt:443
The result is computed int int hiRange
Definition userdoc.txt:322
Defined as float g float float b1
Definition userdoc.txt:162
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
Defined as float g float float float a2
Definition userdoc.txt:162
The result is computed int int< br >< div style="margin-left: 40px;"> Picks values randomly between loRange and hiRange based on supplied index(which is automatically hashed). &nbsp
For< b > pick
Definition userdoc.txt:443
For applying the gamma function to a map adjusts the gamma of all three color channels< br >< br >< h4 >< a name="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:459