// This work is licensed under the Creative Commons Attribution-ShareAlike 3.0 Unported License. // To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/3.0/ or send a // letter to Creative Commons, 444 Castro Street, Suite 900, Mountain View, California, 94041, USA. // Persistence of Vision Ray Tracer version 3.8 Include File. (povr version ONLY) // File: functions.inc // Last updated: 11 February 2021 // Description: This file contains the f_ function hooks inbuilt and c++ // compiled functions. Plus the definition for some F_ functions defined // with the scene description language. Many of the latter were in POV-Ray // previously in math.inc as 'sind()' et cetera looking like language keywords // when they are not. #ifndef(Functions_Inc_Temp) #declare Functions_Inc_Temp = version; #version 3.8; // For povr adding 'unoffical' makes some sense, but warnings then ugly. #ifdef(View_POV_Include_Stack) # debug "including function.inc\n" #end // Inbuilt function name to internal function hooks follow as well as // some limited documentation regarding each function. #declare f_gradient = function { internal(0) } // was f_algbr_cyl1 (*_gradient existed as 3 pattern wrapped X|Y|Z below) // Returns a point's location on the gradient. The gradient is defined by the // specified origin based vector. Internally the gradient vector is normalized. // See the gradient pattern documentation for more information. // Location parameters: x, y, z // Three extra parameters for the origin based gradient direction vector: // 1. Gradient vector x value. // 2. Gradient vector y value. // 3. Gradient vector z value. #declare f_noise_cubed = function { internal(1) } // was f_algbr_cyl2 --> f_dents inbuilt // (f_dents existed as pattern wrapped dents originally) // Returns a point's noise cubed pattern value. In POV-Ray v3.7/v3.8 there are // two dents patterns. One for normal perturbation which is much more dents // like and another for map use. This function in returning a value mimics the // second kind and in povr it is called f_noise_cubed. The scalar value version // was always really noise * noise * noise. // Parameters: x, y, z // Three extra parameter required: // 1. Integer value indicating which underlying noise generator to use. // Currently only values of 1-3 where 2 is POV-Ray's current default. // 2. The mode. 0 is the old dents like behavior and matches the pattern // noise_cubed pattern - which was always what it was really doing. Mode 1 // applies some pow() function shaping to exaggerate the isolation of "not near // zero" regions. Mode 2 and 3 are the same as 0 and 1 except three different // and skewed returned noise values are cubed. In other words, the returned // value is value1 * value2 * value3; Modes 2 and 3 good at creating much more // isolated regions of values >0.0. // 3. A scale factor for the return noise distribution. A value of 1.0 is the // default of not adjusting the noise generators returned distribution of // values. If after a dents like look, however, it can be useful to use a value // > 1.0 so values are clipped at 0.0 and 1.0 ahead of the cubing. Noise // generator 1.0 does this by default, but 2 and 3 do not. // For a good start on an isosurface dents implementation using this function // as a basis see: F_dents. It mimics the normal perturbation method, but // actually denting the base isosurface shape inward or outward with respect // to the normal. #declare f_radial = function { internal(2) } // was f_algbr_cyl3 (existed as pattern wrapped below) // Returns a point's radial pattern value. The rotation is left handed about // the y axis. Values start at 0.0 for +x and move to 1.0 rotating around the y // axis again to +x. For example, at -x (half a complete rotation) the value // returned is 0.5. // The core function here is atan2(z,x) like f_th(). Both of these functions // take x,y and z arguments but use only x and z. The x and z values are // swapped internally for f_radial relative to the inbuilt f_th() function. // This means f_radial() 'starts' - is at 0.0 - for +x where f_th() starts at // +z. // This function, like the inbuilt radial pattern, fixes a forever standing bug // in POV-Ray itself when using non-integer values as discovered by Bill Walker // in 2019. // Parameters: x, y, z #declare f_remap = function { internal(3) } // was f_algbr_cyl4 // Returns re-mapped and range normalized value. Given input values are mapped // to a non-regular triangular wave of values to create more zero threshold // crossings. This enables the formation of layered isosurface shapes at // particular sub-values of a functions returning value continuous over some // range. For even numbers of zero remap targets(2), values will ramp to -1.0 // on and hold there on both ends of the remap. For odd numbers of targets(2), // the values will start at -1.0 on the lower value end ramping down and // through the first/lowest value target heading toward 1.0 and ramp up to and // hold at 1.0 on the highest zero value remap target end. Between targets the // values ramp between -1 and +1 peaks. // Parameters: // 1. Incoming value to map to weighted triangular peaked wave -1 to 1 and back // to -1. // 2. Number of zero values in the re-map. Minimum of 2. If you need only one // zero value you can use the original function. Maximum of 8 zero remap // targets. // 3. Threshold to use for shell thickness values. Using 0.0 returns weighted // triangular values meaning longer peak to peak intervals will form thicker // shapes. When greater than 0.0, normalized negative value shells are created // around the zero transition aligning with the 'value thickness' of the // shortest peak to peak interval. If the incoming values are linear the // normalization will be exact. If non-linear, results likely more normalized, // but, yes, not exact. Deemed too expensive to do these calculations on the fly. // 4-11. Two to eight re-mapped crossing values specified with parameters. // These are usually constant values. NOTE! These must be ordered from lowest // valued zero crossing input to to highest value crossing for reliable // results. #declare f_cylinder = function { internal(4) } // Was f_bicorn // Returns a point's value relative to a cylinder. Points at the surface of the // cylinder have a zero values. Points within are more and more negative // approaching the y axis. Points outside cylinder are ever more positive the // farther one moves from the cylinders surface. // Cylinder about the Y axis matching the cylindrical pattern's orientation. // Meaning x, z parameters are only ones used by default. Switch / swizzle y // with x or z to orient about another axis. // Note too the values here are not clamped like the cylindrical pattern's and // so this function is more typically useful function and isosurface work. // Parameters: x, y, z // One extra parameter required: // 1. Radius about the y axis. #declare f_cone = function { internal(5) } // Was f_bifolia // Returns a point's value relative to a dual cone. // Parameters: x, y, z // One extra parameter required: // 1. Radius. // The dual cone is oriented around the Y axis matching the f_cone and // cylindrical pattern's orientation. The dual cone tips are at points the // abs(y) of at +-1.0. To scale the cone, scale y. The y parameter divided by 2 // is 2x taller, for example. #declare f_granite23 = function { internal(6) } // was f_blob // Experimental function for granite like pattern. Similar to the pattern{} form // of the granite pattern except noise generators two and three are alternated on // each internal loop. The aim is fewer, obvious noise generator artifacts. Being // experimental this implementation plays with a collection of post filters inside // the inbuilt code which are able to create some interesting results. // These post processing flags, in any final representation, should likely be // passed using a compressed flags as double float format. The functions for // handling such flags has not yet been created. // Parameters: x, y, z // Six extra parameters used a trailing treatment switches taken in order. // 1. If != 0, Invert granite23 pattern result. // 2. If != 0, Apply a dents like pow(value,3) treatment. Old paper. // 3. If != 0, Invert current value // 4. If != 0, Apply cube root filter to exaggerate range. Cool with 2. // 5. If != 0, Invert current value // 6. If != 0, Scaling of the value if other than 0.0. #declare f_mult1to8pairs = function { internal(7) } // was f_blob2 // Multiply 1 to 8 value pairs. Various return filters after multiplication. // Special multiplication methods which account for incoming signs and roots to // assist with gradients. Intent is also a set up with compilers will be able // to better optimize for simd instructions. // Parameters: // 1. Number of value pairs. // 2. The specialized multiplication to use. If 0, Negative times negative is // negative after sqrt of multiplication. All other polarity combinations // result in a positive value. If 1, Multiply pairs normally. If 2, Multiply // pairs normally, sqrt of fabs then restore polarity of original // multiplication (gradient assist). // 3. If 0, The returned value is the minimum of all pair products. If 1, The // maximum of all. Add 10 to this return method and get the treatment, but // instead a map index value returned. The index value returned will be the // smallest (1-8 multiplied input pairs) / 10.0. // 4-11. One to eight first in pair values. // 12-19. One to eight second in pair values. // The specialized multiplications 0 and 2 get a post multiply square root for // more accurate shapes. Without a small positive bump like +0.005 ahead of // isosurface use shapes look like harsher f_max1to8pairs result at about 2x // the cost. // With the small positive bump the sharp seams often seen with max are // nicely softened AND the performance measure with the full 8 pairs input is // about 12.5% faster. TODO. Should this bump be an additional parameter? #declare f_max1to8pairs = function { internal(8) } // was f_boy_surface // Max of 1 to 8 pairs of values. Various return filters of 1 to 8 max values. // Parameters: // 1. Number of value pairs. // 2. Specialized max related methods. Currently unused. Magnitude, sign // retaining modes? // 3. If 0, The returned value is the minimum of all pair maximums. If 1, The // maximum of all. Add 10 to this return method and get the treatment but // instead a map index value returned. The index value returned will be the // smallest (1-8 max input pairs) / 10.0. // 4-11. One to eight first in pair values. // 12-19. One to eight second in pair values. #declare f_min1to8pairs = function { internal(9) } // was f_comma // Min of 1 to 8 pairs of values. Various return filters of 1 to 8 min values. // Parameters: // 1. Number of value pairs. // 2. Specialized min related methods. Currently unused. Magnitude, sign // retaining modes? // 3. If 0, The returned value is the minimum of all pair minimums. If 1, The // maximum of all. Add 10 to this return method and get the treatment but // instead a map index value returned. The index value returned will be the // smallest (1-8 input min input pairs) / 10.0. // 4-11. One to eight first in pair values. // 12-19. One to eight second in pair values. #declare f_morph2to9fncts = function { internal(10) } // was f_cross_ellipsoids // Weights and sums function values for morphing. Allows simple morphing of one // funtion into another (f_sphere to f_box) for two inputs and can morphing up // to nine input functions. Nine chosen to allow functional set ups for the three // x,y,z axis. // Sums and averages input values according to the weights. Can morph in place // or along a gradient. The math to control the morphing - set the weights - // done outside this function. The weights themselves can be set up as // 1/function-count or similar. Internally, they get totaled and the particular // functions contribution is its weight against the total. // A good starting place with the negative and positive clamp values is -1 and // 1 unless you know the max negative values with the torus minor radius for // example in which case start with +- that value. If too many shapes, or too // much of some shapes are disappearing lower the positive clamp some more. You // can of course set the clamps to large values to avoid clamping altogether - // most used when morphing from one shape to another. // The use of a pre-filter in the code can cause false max gradient warnings. // Parameters: // 1. Count of value inputs from 2 to 9. If set to 0, returns a map value where // index value returned is the smallest (1-9 input) / 10.0 and the associated // weight is > 0.0. // 2. Clamp on how negative any given function contribution can be. // 3. Clamp on how positive any given function contribution can be. This one // more important than (2) because letting any given function's positive, // outside the shape, values get too large really limits what can be // accomplished with respect to morphing. In fact, internal to // f_morph2to9fncts(), the value specified is modified to be // value/non-zero-weights. // 4-12. Input values (function calls) as parameters. // 13-21. Weights as portion of the sum of all weights. #declare f_labsweep = function { internal(11) } // was f_crossed_trough // Linear sweep of a function about the origin. Sweeps from point A to point B // returning a modified x, y or z value. This enables us to code either // directly on the function about origin call, which can see modifiers. Or, we // can code up each as its own X,Y or X function to which we can apply pattern // modifiers. In testing, the former simpler to code, less flexible and // slower. The latter, approach more difficult to code, more flexible and about // 20% faster when using the same modifiers for the same result. // Parameters: x, y, z // Seven extra parameter required: // 1. If 0, return new x. If 1, return new y. If 2, return new z. // 2. Point A's x value. // 3. Point A's y value. // 4. Point A's z value. // 5. Point B's x value. // 6. Point B's y value. // 7. Point B's z value. #declare f_agate = function { internal(12) } // was f_cubic_saddle // Inbuilt agate pattern implementation. Implementation, in allowing more access // to internal settings, is much more flexible. To match the default // pattern agate use: f_agate(x,y,z,2,1.0,0.77,6,0.5,2.0,2) which matches // pattern agate when everything defaulted in the continuous pattern map // implementation. With the pattern internal octaves, omega and lambda are set // with the keywords it_octaves, it_omega and it_lambda. Here parameters 4, 5 // and 6. The values are mapped to a sine wave. // Parameters: x, y, z // Seven additional parameters required: // 1. 0,1 or 2 for x, y or z agate alignment. Pattern{}'s agate always uses z // or (2). // 2. Turbulence multiplier. Formerly called agate_turb now it_frequency in the // pattern version. (1.0). // 3. Power exponent for pow(). Hard coded to 0.77 in the pattern version. // 4. Number of octaves for the turbulence call. Pattern version defaults to 6. // Valid values are integers 1 to 10. // 5. Omega value for the turbulence call. Pattern version defaults to 0.5. // 6. Lambda value for the turbulence call. Pattern version defaults to 2.0. // Valid values are -10.0 to 10.0. // 7. The noise generator to use. Valid integer values 1-3. Pattern agate uses // pattern or global setting. #declare f_onion = function { internal(13) } // was f_cushion // Inbuilt onion pattern implementation. Similar to the pattern{} map version // but offering a few more options for directly calculated wave types and // return ranges. Using f_onion(0,0,0,1.0,0,0) matches the pattern{onion} // results. // Parameters: x, y, z // Three extra parameter required: // 1. Onion layer depth. Very large values offer one layer, 0+ spherical // gradient. If there used with f_remap(), for example, can create onions with // layers of varying spaces and optionally thicknesses too. // 2. Wave type. 0 = traditional ramp. 1 = triangular. As with the pattern{} // triangle_wave modifier it effectively halves the thickness (doubles the // frequency). // 3. If 1.0, returns values in a -1 to 1 range instead of traditional 0 to 1 // range. #declare f_sign = function { internal(14) } // was f_devils_curve // Returns 1 for >=0 and -1 for <0. See too f_sign0() for something handling // zero specially. // Parameters: // 1. Input value. #declare f_sign0 = function { internal(15) } // was f_devils_curve2d // Returns 1, 0 or -1 based upon input value. More complex than the f_sign() // function in that 0 is returned as 0, 1 or -1. Further, there is phase offset // capability identical to POV-Ray / Povr's continuous pattern wave modifier // 'phase.' // Parameters: // 1. Input Value // 2. Treatment for 0. If 0, zero values return 0. If -1 zero values return -1. // If 1, zero values return 1 like f_sign() default. // 3. Offset value. Excepting how 0 treatment is changed given the parameter 2 // setting, returns 1 for >0 and -1 for <0 after the parameter 3 offset is // applied. #declare f_cbrt = function { internal(16) } // was f_dupin_cyclid // Returns cube root(s) of passed value. Here partly making available the c++ // standard library's cube root function std::cbrt(). The expected application // is gradient reduction. Unlike sqrt(), this function can handle negative and // positive input values returning a negative cube root if the input value is // negative. // Three parameters: // 1. Input value. // 2. Mode. If 0, runs the std::cbrt straight up on all incoming values. If the // mode is set to 1, the std::cbrt function is run only when the values are // >1.0. This latter mode aimed at gradients where working with functions with // higher powers and the values tend to really grow away from the 0.0 // threshold. The cube root of magnitudes <1.0 of course tend to create larger // values below abs(1.0) often creating a buckle in the gradient values and // poorer gradients near 0.0. // 3. Number of additional cube roots - if any. Given we are taking the cube root // this is almost always 0. #declare f_ellipsoid = function { internal(17) } // Returns inside negative ellipsoid values. Previously f_ellipsoid() only // worked for isosurfaces of threshold 1.0 and the axis scaling was inverted. // In other words, it was not a general function thought relatively fast. // Changed in povr May 14, 2020 to align with standard root/threshold behavior. // Further, extended to pass exponent as this enables some f_superellipsoid // results at a much lower compute cost. // Parameters: x, y, z // Six extra parameters required: // 1. If 0, calculations are done with double floats. Otherwise with single // floats. The latter often a lot faster with not much loss in accuracy. // 2. The x scale // 3. The y scale // 4. The z scale // 5. The pow() exponent to use. For a proper ellipsoid use 2.0. For an // octahedron use 1.0. For an inward curvature from axises use values < 1.0. // For Rounded box to round use values >2.0. The exponent here not locked at // 2.0 offers some results like that of the superellipsoid at less compute // expense. // 6. The number of times to take the sqrt() internally to reduce the gradient. // 1 a good starting point. Usually more than 2 not worth it. 0 for very round // results works fine. #declare f_polyhedron = function { internal(18) } // was f_enneper // Returns inside negative polyhedron values. When using x,y,z or f_gradient() // the gradients are projected onto normalized input vectors. This is useful // because it often allows for some normalization of the scaling. // #declare normScale = 3/(3+2*) // f_polyhedron(x*normScale,y,z*normScale,5, // f_gradient(-1,0,1)*normScale,0,0,0, // 0,0,0,0, // 0,0,0,0) // When using the map values often one axis (y say) needs to be set to 0.0 and // other play might be required. Unsure how useful the map values will be in // practice... // Parameters: x, y, z as x, y z or passed f_gradient()s on arbitrary axises. // Thirteen additional parameters required: // 1. Count of input gradients. 3 to use only x,y,z. Max is 15. If the value // is set negative a map value equal to the largest absolute input value // divided by 16 is return. If first smallest, 1/16. // 2-13. Up to 12 input axis gradients. See f_gradient function, but any value // input method allowed. #declare f_lame = function { internal(19) } // was f_flange_cover // Returns lame() given up to eight input gradients. If all exponents ==1, // look at more efficient f_polyhedron alternative. Generally if exponents are // <1.0 introduces an inward / concave curvature. If 1, flat faces, If >1 // outward / convex curvature. See f_polyhedron comments on normalized scaling // with x,y,z projects onto normalized vectors. // Parameters: // 1. Number of input gradients. Up to eight. If the value is set negative a // map value equal to the largest absolute input value divided by 10 is return. // If first smallest, 1/10. // 2. If 0 does calculations as doubles, otherwise as floats for performance // less accuracy. Here whether floats help depends a lot of the exponents. // Mixed 0.6 to 1.6 on 5 gradients 31.019 -> 28.882 ---> -6.89% going to single // floats. // 3. The number of times to take the sqrt() internally to reduce the gradient. // A value of 1 a good starting point. Usually more than 2 not worth it. 0 for // very round results works fine. // 4-11. One to eight input gradient values. // 12-19. One to eight matching pow() exponent values. #declare f_signpow = function { internal(20) } // was f_folium_surface // Returns signed power of input. In all cases the pow() function is run // against the absolute value of the input. If the input value was negative a // negative result is returned. If positive, a positive result is returned. // Usually the two exponents will be the same. However, the thought is with // gradients or complex implicit csg, being able to use different exponents for // incoming positive and negative values could sometimes be very useful. // Parameters: // 1. Input value. // 2. Exponent to apply to >= 0.0 values. // 3. Exponent to apply to < 0.0 values. #declare f_signsqrt = function { internal(21) } // was f_folium_surface2d // Returns signed square root. The sqrt function is run against the absolute // value of the input. The incoming sign is applied to the result. So // f_signsqrt(-9) will return -3. // Parameters: // 1. Input value. #declare f_hypot = function { internal(22) } // was f_glob // Access to c++ std::hypot function. Exposes the C++ standard hypot library // function which encapsulates the common sqrt(x*x + y*y) calculation. // NOTE! In testing this function runs significantly slower than does a raw // form so probably using f_hypot_raw() is faster. No difference seen in // testing value wise, but maybe... Might be std::hypot is faster with some // implementations depending upon optmizations. // Parameters: // 1. First value (ie x) // 2. Second value (ie y) #declare f_turbulence = function { internal(23) } // was f_heart // Access the internal Turbulence() function. Functions return a single float // value. Parameter (1) provides for a method to get three substantially // different values about any given point in space. In other words, a way - for // example - to get a vector turbulence with three calls, one each for x,y,z. // Example use: function { f_turbulence(x,y,z,0,2,1,0,1,6,0.5,2.0,2) } // Parameters: x, y, z // 8 extra parameter required: // 1. 0,1 or 2 for x, y or z result. // 2. The noise generator to use. Valid values 1-3. // 3. Scale returned internal turbulence() value for magnitude / (frequency for // fmod inputs). Using 1.0 results in no scaling. This operation is the last // performed before returning. // 4. Normalization. // 0 - None. Distribution will be centered at 0.0 with deviation // depending upon turbulence settings of octaves, omega and lambda. // 1 - Adjust to 0 to 1, 0.5 centered distribution. Not clamped. If the // passed deviation value not 'large enough' values can go outside the 0 to 1 // range. See (3). // 2 - Adjust to -1 to +1, 0.0 centered distribution. Not clamped. See // (2,4). // 3 - Basically (1) with hard clamping such that values below 0 are at 0 // and values larger than 1 are at 1. // 4 - Basically (2) with hard clamping such that values below -1 are at -1 // and values larger than +1 are at +1. // 5,7 - triangle, cycloidal to 0 to +1 range, respectively. // 6,8 - triangle, cycloidal to -1 to +1 range, respectively. // 5. Deviation. With default turbulence controls this will be 1 - and often // less practically. This value should be the deviation as returned from // turbulence(), ahead of any distribution adjustments. The value passed only // used if (4) has a 1-4 value. // 6. Number of octaves for the turbulence call. Pattern version defaults to 6. // Valid values are integers 2 through 10. // 7. Omega damping factor octave to octave for the turbulence call. Pattern // version defaults to 0.5. // 8. Lambda value for the turbulence call. Pattern version defaults to 2.0. // Values between -10.0 and 10.0 are valid. #declare f_bump = function { internal(24) } // was f_helical_torus // Returns and bump function value of value passed. The bump function 'bumps' // values > -1 and < 1. Other input values are ignored. Meaning values outside // that range result in a 0 return value. // The f_bump function is intended to be a helper function used with other // functions to achieve a locally shaped result. // Parameters: // 1. Input value as provided by a base function. // 2. Power of 2.0 exponent integer multiplier. For the typical rounded dome // use 1.0. Higher values tend to square off or sharpen the result. Up to 20 // usually OK. // 3. If 0, the value is returned straight up which means the maximum value is // ~= 0.3679. If 1, return value is normalized to 0 to 1 range. If 2, the // return value is normalized to a -1 to 0 range or a 0 to 1 range depending // upon input polarity. #declare f_helix1 = function { internal(25) } // Returns values forming a threaded helix. Helix rotates left handed, // upwarded, around the y axis and is unbounded in y. The number of threads is // setable. // It is possible to set the period(1) very small and the shape parameter(5) // large to get vertical columns placed around the y axis in a number equal to // the number to threads. // // Example: // #declare Fn04 = function (x,y,z) { // f_helix1(x,y,z,2,5,0.1,0.3,1,2,45) // } // #declare Iso99 = isosurface { // //function { f_boxb(x,y,z,0.6,1.1,0.6,0,0,0,Fn04(x,y,z),0.01) } // function { Fn04(f_gradient(x,y,z,1,-1,0), // f_gradient(x,y,z,0,1,1), // f_gradient(x,y,z,0,-1,1)) // } // Parameters: x, y, z // Seven extra parameters required: // 1. Number of helixes - e.g. 2 for a double helix // 2. Period - is related to the number of turns per unit length // 3. Minor radius // 4. Major radius // 5. Shape parameter. If this is greater than 1 then the tube becomes fatter // in the y direction // 6. Cross section type. Between 0 and 3. 0-square, 1-circle, 2-diamond, // 3-concave-diamond. // 7. Cross section rotation angle (degrees). E.g. if you choose a square cross // section and rotate it by 45 degrees you get a diamond cross section. #declare f_helix2 = function { internal(26) } // Returns values for single thread helix. Helix rotates left handed, upwarded, // around the y axis and is unbounded in y. // Parameters: x, y, z // Five extra parameters required: // 1. Period - is related to the number of turns per unit length // 2. Minor radius // 3. Major radius // 4. Cross section type. Between 0 and 3. 0-square, 1-circle, 2-diamond, // 3-concave-diamond. // 5. Cross section rotation angle (degrees). E.g. if you choose a square cross // section and rotate it by 45 degrees you get a diamond cross section. #declare f_length = function { internal(27) } // Was f_hex_x // Returns the length of the x,y,z vector. This function is exactly the same as // f_r in operation. The f_r version is coded using C++ math. This version uses // POV-Ray's 3D vector method length(). For the same point in space the results // should be identical with a DBL_epsilon tolerance. // Parameters: x, y, z #declare f_normal = function { internal(28) } // Was f_hex_y // Returns normal vector's x, y or z. The technique used internally matches // that used by the isosurface shape to determine the normal. // The current method matches the common method used with implicit equations // and in form it's the method the scale value based normal perturbation // mechanism uses. This method has a slight bias due the sampling bias though // with good gradients it's not a practical issue. // TODO Review the normal mechanism. By gut think the dx,dy,dz should perhaps // be based somewhat on the incoming ray to get the inside outside surface // normal directions / polarity right in all situations. Is there a reasonable, // less biased sampling approach? // If not "at" the surface (internal 0 value), where their must be a gradient // to find a root, it's possible for the sampling to lock up / misfire so to // speak if say the sample are all even as might happen at a spheres center // position. Generally meaning to use this, or any dx,dy,dz based value // sampling, one must be roughly aware the local values are changing i x ,y and // z directions for it to "work." // The single axis normal values returned for paramter(5) options <=2 are // normalized at double accuracy and each x,y or z is returned at full accuracy. // When paramter(5) is 3 the normal vector is normalized prior to encoding. This // must be done due the limited 21 bit space used to store each of the three // values. Further the encoding itself rounds into the 21 bit space. // Parameters: // 1. Function's value at a point. // 2. Function's value at a point where x bumped up by accuracy (like isosurface's). // 3. Function's value at a point where y bumped up. // 4. Function's value at a point where z bumped up. // 5. If 0, returns x value of normal vector. If 1, returns y. If 2, returns z. // If 3, it returns 3 21 bit floats in the double return space to 6 decimal places // which can only be decoded with the inbuilt function f_dec3x_f21(). The option // 3 normal is normalized before encoding to the reduced bit depth. // 6. A nearness value used to fade to non-calculated 0 values away from the 0.0 // threshold surface. #declare f_hetero_mf = function { internal(29) } // Returns value offsets for heterogeneous terrain. Heterogeneous multifractal // values applied to an x, y or z plane to form terrains of various heights and // types. See too: f_ridged and f_ridged_mf. // Parameters: x, y, z // Seven additional parameters required: // 1. H - Positive float. Higher values lower the height and soften (2) effect. // Values around 1.0 (internally 1/H exponent see 2) are used for mountains. // Values < 1.0 get noisy and not of much used in isosurfaces as the gradients // get quite bad. // 2. Lacunarity (gap). This somewhat like the POV-Ray's, turbulence's lambda // value. It's the difference in scale between any two octaves worth of // calculations. The gap between frequencies. Octave increments scaled by // 1/pow(Lac,H)*Oc. Higher values tighten the peak to peak gaps, more or less, // and so lower altitude. Typical values >1.0. // 3. Octaves. The larger the value the more detail in the result. Any // fractional portion / overrun multiplied by the magnitude of the greatest // integer octave calculated - which tends to add extra divots. (Blender calls // octaves detail, which is apt) // 4. Offset. Shifts all values and so terrain up or down. At a value of 0.0 // there will be peaks +-1 more or less. Further if T >0, the smoothing will // be in the middle regions about 0.0 'height'. If the offset is 0.5 say, the // terrain will be in a 0 to 2.0 range more or less. At 0.25, in a -0.5 to 1.5 // range. So, the offset is more or less 2x the value specified. // 5. T - Integer values > 0 will smooth lower altitude terrain if the // isosurface function set up is something like y-(this function). Values of // <=0 do nothing (end up with straight 1/f). Larger values will tend to // round/soften valleys upward significantly and sharpen peaks downward). T = 1 // is a heterogeneous fractal, etc. Notes. With any value >=1 there is an // awkward buckle in normals direction at the most smoothed low frequency (Just // how it works). In implementations previous to povr's Aug 26, 2020 there was // a bug when T got larger than 1, which create near infinite spikes for the // higher frequencies - added clamping. // 6. The noise generator to use. Values of 1,2 or 3 valid. 2 or 4 most useful // because they are not clamped at -+1 as is generator 1. // 7. Return value scale. In testing saved +3% over scale in external function // and scaling the value is common. If applying only in a local region using // functions or patter{}s, it's a feature where savings be even more // significant. #declare f_normalized = function { internal(30) } // was f_hunt_surface // Returns the normalized x, y or z vector value. // Parameters: x, y, z /// One extra parameter required: // 1. If 0, returns the x component of the normalized vector. If 1, the y // value. If 2, the z value. #declare f_boom = function { internal(31) } // was f_hyperbolic_torus // Generates a throw after printing 6 float values. Intended as a crude // debugging aid which can be used to create a debug stack trace. It can // be called variously in the parser on some condition. Or one can use // select on a condition while running functions in the vm. // #declare THING1 = 0.111; // #declare THING2 = THING1; // // #declare ABC = f_boom(THING1,THING2,0,0,0,0); // One method to use. // Parameters: // 1. First float value. // 2. Second float value. // 3. Third float value. // 4. Fourth float value. // 5. Fifth float value. // 6. Sixth float value. #declare f_box = function { internal(32) } // was f_isect_ellipsoids // Returns values for a box. See too f_rounded_box, but this form has the // advantage inside the shape of a nice continuous gradient. The return value // is the max of the three dimensional values. // The effect is when (1) is 0 the most negative value is still -1.0, at the 0 // origin. When (1) is 1, the most negative value is the smallest of the three // scaling dimensions. With (1) the gradients of mode 1 are usually better at // the cost of the values drifting around with scale. // Parameters: x, y, z // Seven extra parameters required: // 1. Scaling mode. If 0, the coordinates x,y,z are scaled ahead of subtracting // 1.0. If 1, scaling is subtracted from the coordinates x,y,z. // 2. Scale in x. // 3. Scale in y. // 4. Scale in z. #declare f_length_sqr = function { internal(33) } // was f_kampyle_of_eudoxus // Returns the length of a vector squared. Often able to gain considerable // performance where able to use this function over f_length or f_r as it // avoids the square root function call. // Parameters: x, y, z #declare f_triangle_wave = function { internal(34) } // was f_kampyle_of_eudoxus_2d // Triangle wave value modifier. A helper function implementing a pattern{} // triangle_wave modifier for the passed values. Useful especially when working // with mod() results and isosurfaces or parameterics to restore linear // continuity. // For the full and correct range of return values for a triangle_wave the // input values must change linearly between -1 and 1, -1 and 0 or 0 and 1. // Parameters: // 1. Value. // 2. Mode. // If 0, the result values will range between 0 and 1. // For example, the result will be at 0.0 at values of -1.0, 0.0 // and 1.0; at inputs of -0.5 and 0.5, the result will be 1.0. // If 1, the results will vary between -1 and 0. For example, the // result will be -1.0 at input values of -1.0, 0.0 and 1.0. // The result will be 1.0 for the values -0.5 and 0.5. #declare f_sine_wave = function { internal(35) } // was f_klein_bottle // Sine wave value modifier. A helper function implementing a pattern{} // sine_wave modifier for the passed values. The compete 2*pi sine cycle is // compressed into any given 0-1 range when (2) is set to 0 or 1. The returned // cycle starts and ends at a value of 0.5 when (2) is 0. Where (2) is 1 or 2, // the returned cycle starts and ends at 0.0. // For the full and correct range of return values for a sine_wave the input // values must change linearly between -1 and 1, -1 and 0 or 0 and 1. // This function form was about 14.5 faster than a pattern{} wrapped form of // wave modifier. See f_sine_wavef for a version even faster. // The long shipped F_sine_wave macro returns a result matching (2) set to 2 by // a somewhat different calculation. // Parameters: // 1. Value. // 2. Mode. // If 0, the resulting values will range between 0 and 1 and this // mode matches the pattern{} default. // If 1, the results will vary between -1 and 1 matching the pattern{... // function_interval} result. // If 2, results in magnitude are like 1, but stretched such that the // complete 2*pi sine cycle happens of the -1 to 1 interval. #declare f_scallop_wave = function { internal(36) } // was f_kummer_surface_v1 // Scallop wave value modifier. A helper function implementing a pattern // scallop_wave modifier for the passed values. Unlike the sine_wave modifier, // pi rather than 2*pi(tau) used. Essentially in switching from sine_wave to // scallop_wave the frequency is halved in a way similar to the triangle_wave. // The abs(sine) half cycle is fit to any given 0-1 interval when (2) is set to // 0 or 2. The abs(sine) full cycle is fit to any given 0-1 interval when (2) // is set to 1 or 3. // When (2) is 0 or 2 the magnitude ranges from zero to one. When (2) is 1 or 3 // the returned magnitude ranges from -1 to 1. // For the full and correct range of return values for a scallop_wave the input // values must change linearly between -1 and 1, -1 and 0 or 0 and 1. // The long shipped F_scallop_wave macro returns this result too by a somewhat // different calculation. // Parameters: // 1. Value. // 2. Mode. // If 0, the resulting values will range between 0 and 1 over any 0 to 1 // interval. This mode matches the pattern{} default. // If 1, the results will vary between -1 and 1 matching the pattern{... // function_interval} result. // If 2, results are as with 0 at twice the frequency. // If 3, results are as with 1 at twice the frequency. #declare f_sine_wavef = function { internal(37) } // was f_kummer_surface_v2 // Sine wave value modifier using single floats. This function identical to // f_sine_wave except it uses floats over doubles for the sin calculation // saving 11% is testing. See f_sine_wave() documentation for additional // detail. Unique function because passing flag and the conditional cost added // 3% to double calculation for an 8% savings at floats. This version is less // accurate. // This function form was about 22.7% faster than a pattern{} wrapped form of // wave modifier. // Parameters: // 1. Value. // 2. Mode. 0, 1 or 2. #declare f_scallop_wavef = function { internal(38) } // was f_lemniscate_of_gerono // Scallop wave value modifier using single floats. This function identical to // f_scallop_wave except it uses floats over doubles for the sin calculation // saving 8% is testing. See f_scallop_wave() documentation for more detail. // Unique function because passing flag and the conditional cost added 3% to // double calculation for an 5% savings at floats. This version is less // accurate. // This function form was about 26% faster than a pattern{} wrapped form of wave // modifier. // Parameters: // 1. Value. // 2. Mode. 0, 1, 2 or 3. #declare f_cubic_wave = function { internal(39) } // was f_lemniscate_of_gerono_2d // Cubic wave value modifier. A helper function implementing a pattern{} // cubic_wave modifier for the passed values. Further, the result matches // the povr changed pattern{} cubic_wave modifier in behavior. // The modifier acts like a bump function except using a cubic function to // do the value selection and tapering. Unless the phase of the values is // offset by subtracting or adding a constant to the incoming value, the // peak values returned are centered on 0 at 1.0x and taper to 0.0x at -1 // and +1 about 0. The active interval is 2.0. // The frequency can be changed by multiplying or dividing the incoming // values. // Parameters: // 1. Value. // 2. Mode. // If 0, the returned values will range between 0 and 1 and this mode // matches the pattern{} default. // If 1, the results will vary between -1 and 1 matching the pattern{... // function_interval} result. #declare f_boxb = function { internal(40) } // was f_mesh1 // Boxed bounding of function. Efficient method to create spaces enclosed by // thin shells of negative values. The shells include the original shape and // the bound box. Externally the result looks like an isosurface // max/intersection, however the shape formed is not solid. For example, to see // the inside of the shell created with an isosurface, its bounding shape - or // external bounded_by/clipped_by shape - must cut the passed shape function. //... //#declare Fn00 = function (x,y,z) { // f_boxb(x,y,z,0.6,0.6,1,0.3,0,0,f_cylinder(x,y,z,0.5),0.010) //} //#declare Iso99 = isosurface { // function { Fn00(x,y,z) } // contained_by { box { <-1.1,-1.1,-0.10>,<1.1,1.1,1.1> } } //... // Scaling parameters are similar to f_box's mode 1 internally and both mode 0 // and 1 in effect. // Parameters: x, y, z // Eight extra Parameters required: // 1. Bounding scale x. // 2. Bounding scale y. // 3. Bounding scale z. // 4. Offset for box in x. // 5. Offset for box in y. // 6. Offset for box in z. // 7. Value for the function being box bound. // 8. Scaling about 0 threshold for function being bound. #declare f_wrap = function { internal(41) } // was f_mitre // Wraps input values to range. The function has some relation to the mod() family // of functions except the output range is set by min and max values passed to the // function. // f_wrap(value,min,max,mode) will wrap/shift all values inside or outside the // min to max range into the range min to max. // Four parameters required: // 1. Value. // 2. The min value for output range. // 3. The max value for output range. // 4. Mode. // If 0, the values are mapped to the [min, max) range. Meaning the max // value itself will never be seen even if the input value matches it exactly. // This mimics the behavior of the long shipped f_clamp/F_clamp macro. // If 1, the values are mapped to the full [min, max] range for even // aligned value ranges and to a (min, max) range for odd aligned, mapped // ranges. The min and max values end with a distribution no different than // any other value due the wrapping of values. #declare f_elliptical_cylinder = function { internal(42) } // was f_nodal_cubic // Returns values for an elliptical cylinder. The shape central axis is the y // axis. // Parameters: x, y, z // Three extra parameter required: // 1. The traditional a multiplier of the x axis. // 2. The traditional b multiplier of the z axis. // 3. pow() exponent to use. For a true elliptical cylinder us 2.0. Flat sides // use 1.0. For an inward curvature from axises use values < 1.0. For Rounded // to round use values >2.0. #declare f_elliptical_sphrswp = function { internal(43) } // was f_odd - which was always a duplicate of f_cushion(). // Returns values for an elliptical sphere sweep. The arc returned rotates +- around the y axis. // Parameters: x, y, z // Six extra parameter required: // 1. The traditional a multiplier of the x axis. // 2. The traditional b multiplier of the z axis. // 3. The minor radius, r. // 4. The starting angle. 0 to 360. // 5. The arc angle from the start angle. -360 to 360. // 6. 0 = sweep with optimization. 1 = return 0 to 1 map value matched to // angular rotation of arc. 2 = skip up front in torus filter. (e.g. Using // sweep values for map control) // Notes. Like the f_torus() function the f_elliptical_sphrswp sits around // the y axis at the origin. In other words, it is sitting in the x,z plane. // Angles and directional angles are left handed about y. // With respect to isosurfaces; Gradients are decent, but due the internal // method of calculation, performance is somewhat volatile. Larger r values // tend to run more slowly. Rays more orthogonal to the y axis are slower - // sometimes slower than a parametric representation. // The function is close to that of an elliptical torus - a supertoroid with // e1,e2 at 1.0 (spherical) and asymmetric x,z axis values. Also this method // has start and end points - it's an arc even when closed. There means there // is slightly less continuity / smoothness at the cap spheres than elsewhere // in each arc. #declare f_planar = function { internal(44) } // was f_ovals_of_cassini // Returns a negative value region about 0. To duplicate the pattern{} planar // use function { -max(0.0,f_planar(y,1,1)) }. This is effectively a shell // function - and very useful as such. For example, to get the shell of a // sphere pass f_sphere(...) as the first value argument instead of say y. // Three input parameters: // 1. Input value. Usually x, y or z. However, it can be any +-gradient value // set > than the scaling factor (2). // 2. The scaling factor. The value thickness of the returned negative region // will be twice this value. // 3. The normalization mode. If 0, an input zero value is normalized to return // -1.0 no matter the scaling. If 1, the scaling factor sets the most negative // return value at an input of 0. #declare f_paraboloid = function { internal(45) } // Returns values for paraboloid(s). At a y magnitude of 1.0 the radius will be // 1.0. To flatten or elongate to, creating a different radius at y==1, // multiply to make larger or divide the incoming y to make the radius at y==1 // smaller. // This function as an isosurface shape - especially the open forms - often // require global_settings{shadow_tolerance } feature of povr to // eliminated shadow artifacts. // Parameters: x, y, z // Two extra parameter required: // 1. Dual paraboloids flag. If 0 get one y+ oriented paraboloid above the x,z // plane. If the incoming y is negated can flip the direction to y- below the // x,z plane. If this flag is 1, the absolute value of y is taken internally // and both upward and downward facing parabolid are created. // 2. If 0, an internal cbrt() is taken for values greater than abs(1.0). This // helps greatly with gradients where values get larger than one in magnitude // (at 3+ -17%). It flattens the exponential. If working tightly around one // there is almost no difference in performance (and little with gradients) // with or without (-2%). The option to turn it off is provided primarily so // users can get traditional paraboloid values, if they need them. #declare f_quilt_cubic = function { internal(46) } // was f_parabolic_torus // Roughly returns internal quilt_cubic result. The inputs 2,3,4,5 can be // thought of as the start and end on curve points for a Bezier cubic curve. // Inputs 6 and 7 the y offset for control points where the x positions are // fixed equal distance between the end points. // Unlike traditional Bezier segments the function's curve continues outside // the start and end points. // The results are identical to the internal quilt_cubic function used with the // quilted and tiled normal perturbation patterns when the inputs 2,3,4 and 5 // are: 0, 0, 1, 1. The quilted/tiled control0 and control1 values being inputs // 6 and 7 here. // Seven input parameters required: // 1. An input value for the function. // 2. The xlo "starting" position through which the curve must pass. // 3. The ylo "starting" position through which the curve must pass. // 4. The xhi "starting" position through which the curve must pass. // 5. The yhi "starting" position through which the curve must pass. // 6. The y value for the "left/nearer-start" control point. // 7. The y value for the "right/nearer-end" control point. #declare f_ph = function { internal(47) } // Returns angle in radians between y+ and point. For example, at x and z = 0 and // y of 1.0 the returned value is 0.0. Changing y to -1.0 and the returned value // is the maximum of 3.14159 or pi. The polarity of x and z do not matter. These // can be + or - and the returned value is always >=0 and <= pi. At y = 0, a value // of 1.57079 or pi/2.0 is returned. // The ph suffix is short for the somewhat traditional phi. See too f_r and f_th. // Parameters: x, y, z #declare f_dec_nbit3c = function { internal(48) } // was f_pillow // Decode bit depth, -1 to 1, float from 3 channel values. The matched // encoding function is f_enc_nbit3c. See the f_enc_nbit3c documentation for // more detail. // Note. This function can be run on images generated by means other than // encoding with f_enc_nbit3c. One might for example set up a user defined // pigment where R,G and B are generated by different pattern functions. If // these values or some an image created in such a way is used as input one can // simply lie and say the values are encoded normalized. The R, G and B // channels will start with the strongest effect due R, then G and B. The bit // depth large means G and B will have little effect. Smaller bit depths will // increase the effect. // Small bit depths are effectively a way to slightly weight the contributions // of G and then B. If one sets the bit depth to 1 and weights the three // channel inputs by 1/3 we end up with an average pattern functionality with // weights of 1. // Parameters: // 1. The bit depth with which to work. Values or 1 to 17 are currently // supported. // 2. Whether encoded values are in normalized form. // format. 0 = no. 1 = yes. If storing the encoded channels to a format which // 3-5 are the three (R,G and B) channel values. #declare f_enc_nbit3c = function { internal(49) } // was f_piriform // Encode bit depth, -1 to 1, float to 3 channel values. The channel values // are expected to be R,G,B almost always, but any format supporting channels or // image layers OK. The matched decode function is called f_dec_nbit3c. // The df3 format current supports up to 32 bits of depth in a single channel // and that is the maximum available. Most grey scale support allows up to 16 // bits as is true for most of the common image file formats. Internal colors, // except for some special calculations, are also using 32 bit floats. // The color channels internally being at 23 bit depth can each store the 17 // bit max depth channels needed to achieve up to 51 bit total depth values for // height fields, isosurfaces or whatever. This very near the 52 we could get // with a pure double storage. // Until there is some writable format supporting greater than 16 bits per // channel max, file stored depths will be at 16 bits per channel or less. // Several formats support 8, 16 and some a definable bit depth per channel. // Even supposing output support with >16 bit channel depth, Using three 16 bit // channels will burn only 48bits where the three 32 bit per channel float // format of the exr format, for example, would consume 96bits - or twice the // storage. Again, as of this writing, we have support only for exr half floats // per channel. // The method of encoding is that of MegaPOV and POV-Ray's undocumented .hf // function block only implementation, but not limited to 16 bit depth output // and red and green 8 bit channel inputs. In povr the .hf functionality has // been removed. // Note. Do NOT use the exr and hdr high dynamic range images for ecoded file // storage. The current exr support via POV-Ray supports only half (16 bit) // floats - not the max of 32 bit floats per channel exr format itself // supports. The hdr format is 32 bits total for a color in an rgbe format // where e is a shared 8 bit exponent. // Note. One can still effectively use only two channels by setting the third // to 0.0 on the decode/encode function calls. // Parameters: // 1. The bit depth with which to work. Values or 1 to 17 are currently // supported. // 2. Which of three encoded values to return. 0, 1 or 2. NOTE! There is // a secrete channel 3. :-) It returns the effective epsilon value for // the 3 channel number of bits you have selected. Take care NOT to use // it as a color/channel as it's constant for the number of bits. // 3. Whether to normalized the encoded values for storage in a typical image // format. 0 = no. 1 = yes. If storing the encoded channels to a format which // internally is using integer storage for each channel you will want to set // this to 1 to normalize for storage in that integer format. This does take // time as does de-normalizing during decode so if you can store as a float // without normalizing it's faster. // 4. The double value to encode. It should already be normalized to a // -1.0 to 1.0 range if need be - otherwise encoding results are invalid. The // matching decode function to reconstruct is f_dec_nbit3c #declare f_hypot_raw = function { internal(50) } // was f_piriform_2d // Returns the sqrt(x*x + y*y) value. See the inbuilt f_hypot for access to // the standard library's std:hypot, but it was significantly slower in testing // with no appreciable difference in result detected. // Parameters: // 1. First value (ie x) // 2. Second value (ie y) #declare f_upoly = function { internal(51) } // was f_poly4 // Univariate polynomial value at t. Zero to sixteenth order equations are // supported. // This code replaces f_poly4 which worked only to the fourth order and always // returned the surface of revolution about y by negating the polynomial value // internal and adding the sqrt(x^2+z^2). This functionality can be duplicated // by subtracting f_upoly() from f_hypot_raw() or f_hypot(). // Parameters: // 1. The univariate value - 't'. // 2. The order (0-16). // 3. The polynomial constant. // 4-19. The coefficient for the largest order first. The remaining in // descending order. All 16 coefficients must be specified, but those not // needed for the order being evaluated are ignored. #declare f_radial_tubes = function { internal(52) } // was f_polytubes // Helper function to create radial tubes on a surface. This is not a // standalone function for isosurface shapes (not a function having roots at // zero). Rather it is a helper function which enables the creation of a // number of tubes (creates an effective function for tubes) radially about y // axis guided by the surface of a passed (by value at x,y,z) function. // Note. The tubes do not track the original surface but rather an offset // gradients so often end up sort of following the passed surface, but not // exactly. // It's perhaps easiest to understand this function by playing with it. // As set up it is passed a surface function value used along with radial // positions about y to create an effective function for which it needs a // positive threshold (negative offset) to form shapes as with an isosurface. // The offset more or less sets the tube thickness. In practice, it is much // simpler and better/faster to wrap the composite in an f_planar function // where the thickness parameter to it sets the thickness. // By default the radial placement is about the y axis and it always starts at // +x rotating left handed about y to place the remaining tubes. // This function a derivative of functionality buried within the now deleted // f_polytubes in built function. That old function was hard coded to work only // with 4th order polynomials. Further the initial tube position was at -z. // Some example code for creating tubes using a cylinder as the guiding surface. // Two forms for the cylinder are showing the more complicated and not used is // something close to using the old internal fourth order univariate polynomial // specification of f_polytubes. The better one uses the new inbuilt f_cylinder // function. // #declare FnSurface = function (x,y,z) { // f_hypot_raw(x,z) - f_upoly(y,0,+0.5, // -0.6,0.6,-0.4,0.5,0,0,0,0, // 0,0,0,0,0,0,0,0 // ) // } // #declare Fn00 = function { // //f_planar(f_radial_tubes(x,y,z,FnSurface(x,y,z),12,0,1),0.03,1) // 35.4s // f_planar(f_radial_tubes(x,y,z,f_cylinder(x,y,z,0.5),12,0,1),0.03,1) // 32.7s // } // Parameters: x, y, z // Four additional parameters required: // 1. Value for some surface at this x,y,z. // 2. Number of tubes >=1. This number can be quite large. // 3. Rotation in degrees about y, if any. This too left handed about y. // 4. Scale about y. Usual would be 1.0 to evenly space tubes, but partial // radial coverage is OK. Combined with rotation different parts of the surface // can get different tubes (textures). #declare f_dturbulence = function { internal(53) } // was f_quantum // Wrapper for the internal DTurbulence function. Unlike access through the // pigment pattern, the call here is direct. Can return one component of the // x,y,z turbulence vector generated or a complete 3D vector encoded as three // 21 bit floats +-10 to five decimal places. // The 3D 21 bit return is the expected common use case as DTurbulence need // run only once. // Example use: // #declare Fn00 = function (x,y,z,_v,_r) { // f_sphere(x-f_dec3x_f21(_v,5,0), // y-f_dec3x_f21(_v,5,1), // z-f_dec3x_f21(_v,5,2),_r) // } // #declare Fn01 = function (x,y,z) { // Fn00(x,y,z,f_dturbulence(x,y,z,3,0.1,0.1,0.1,6,0.5,2),0.3) // } // #declare Iso99 = isosurface { // function { Fn01(x,y,z) } // contained_by { box { -1.0,1.0 } } // threshold 0 // accuracy 0.0005 // max_gradient 1.5 // pigment { color Green } // } // Parameters: x, y, z // Seven additional parameters: // 1. 0 returns x of turbulence vector result. 1 returns y. 2 returns z. >=3 // returns a complete 3D turbulence vector as 3 21 bit encoded floats in the // double's return space at 5 decimal places to support +-10 range given // turbulence can wander outside the +-1 range. // 2. The input turbulence x vector component. // 3. The input turbulence y vector component. // 4. The input turbulence z vector component. // 5. The number of octaves. 1-10 with 6 a common default. // 6. The omega falloff or damping factor octave to octave. A float // where a common default is 0.5. // 7. The lambda value for the violence of the step octave to octave. This // parameter is a float between 1 and 10. The common default is 2.0. #declare f_rotate2d = function { internal(54) } // <<< Replace with f_rotate2d // Rotation in 2d about x,y or z axis. The two modified values are returned as // two 32 bit floats encoded in a double's space. Decoding must be done with // the f_dec2x_f32 inbuilt function selecting one of the 32 bit floats on each // call. // The angle passed is in +-360 degrees. // When the axis for rotation is x, modified y then z encoded values are // returned. // When the axis for rotation is y, modified x then z encoded values are // returned. // When the axis for rotation is z, modified x then y encoded values are // returned. // Note. The rotations here are actually the inverse left handed rotations // (right handed rotation) one uses with patterns or isosurfaces. This means // if working with a function/pattern for pattern use specify positive values // to get positive left handed rotation about the axis of choice. // If you want rotated coordinates for say some placement of spheres or // whatever about the axis you must negate the passed angle. // Parameters: x, y, z. Note the one corresponding to the axis of rotate is not // used, but probably best to just pass it by habit. // Two additional parameters required: // 1. The axis for the rotation using 0 for x, 1 for y, 2 for z. // 2. The rotation degrees. +-360.0. // Example usage: // #declare Fn00y = function (x,y,z,_r) { f_sphere(x-0.5,y,z,_r) } // #declare Fn01 = function (x,y,z,_v) { // Fn00y(f_dec2x_f32(_v,0),y,f_dec2x_f32(_v,1),0.1) // <--- // } //#declare Iso99 = isosurface { // function { Fn01(x,y,z,f_rotate2d(x,y,z,1,+45.0)) } // <--- // contained_by { box { -1.0,1.0 } } // threshold 0 // accuracy 0.0005 // max_gradient 1.7 // pigment { color Green } //} // Aside: // The default coordinate system in the POV-Ray is left-handed. The positive x, // y and z axes point right, up and forward, respectively. Positive rotation is // left handed about the axis of rotation with thumb pointing toward the more // positive axis values. // The default coordinate system in Moray, for example, is right-handed. The // positive x and y axes point right and up, and the negative z axis points // forward. Positive rotation is right handed about the axis of rotation with // thumb pointing toward more positive axis values. #declare f_hessian_dist = function { internal(55) } // was f_quartic_saddle // Rotated and offset plane about y axis. The rotation is left handed about y // and specified in degrees. A zero rotation and zero offset returns a -z // plane. In other words, along the x axis at z=0 the values transition from // positive to negative when moving in the -z direction. // The Hesse or Hessian normal form is often used to define planes. There is a // similar encoding for lines and it uses a distance formula as a part. The // form for the distance equation makes for a convenient method to specify // planes by rotation and offset relative to the y axis. // It naturally divides regions into positive and negative values with good // gradients. // Coded in raw SDL as a function it is: // // Set up for left handed rotation about y. 0 angle aligns with x. // #declare FnHessianDist = function (x,y,z,Theta,Offset) { // z*cos(radians(Theta)) + x*sin(radians(Theta)) - Offset // } // Parameters: x, y, z // Two extra parameter required: // 1. Angle of rotation, left handed, about y in degrees. // 2. The offset from the y axis. #declare f_quartic_cylinder = function { internal(56) } // Returns values for a quartic cylinder. Here the cylinder bulges outward // at y == 0 in the x,z plane. // Parameters: x, y, z // Two extra parameters required: // 1. The radius of the bulge at y==0 in the x,z plane. // 2. Controls the width of the tube and the vertical scale of the bulge. // Larger values tend toward larger gradients. At 1.0 we end up a sort of dual // bottle like shape. At 0.2 a very strong bulge about y==0 and a narrow neck. // At y==1.0 the value specified here is close, but not exactly, a radius of // this value. #declare f_r = function { internal(57) } // Returns the distance from the 0.0 origin. While it can be thought of as the // radius, r, of a sphere, this function is exactly the same as f_length. This // version is coded using C++ math. The f_length version uses POV-Ray's 3D // vector method length(). For the same point in space the results should be // identical with a DBL_epsilon tolerance. // The r suffix is short for radius. See too f_ph and f_th. // Parameters: x, y, z #declare f_ridge = function { internal(58) } // Ridged surface values. Similarity to f_turbulence() results at default-ish // values (offset 0, ridge 0) given the underlying Noise() and math somewhat // similar too. Intended for modifying or displacing other surfaces by value as // might use a patter{} function. Other functions of interest are f_hetero_mf() // f_ridged_mf() and f_turbulence(). // Parameters: x, y, z // Seven extra parameters required: // 1. Lambda. The turbulence type gap or violence between octaves. Default // usually 2.0. At higher values the result can be quite violent and any // isosurface gradients get quite high too. // 2. Octaves. The larger the value the more detail in the result. Any // fractional portion / overrun multiplied by the magnitude of the greatest // integer octave calculated - which tends to add extra divots. Blender calls // octaves detail, which is apt. Default usually 6. // 3. Omega. The gain from octave to octave. Default usually 0.5. // 4. Offset. Positive values push floors/valleys away from the peaks, negative // values pull them toward the peaks. Zero does neither. // 5. Ridge. Most bumpiness near 0.0. When +- magnitude larger the difference // in bumpiness smoothes out and the height increases. Negative values are // smoother than positive ones overall. // 6. The noise generator to use. Values of 1,2 or 3 valid. 2 or 3 most useful // because they are not clamped at -+1 as is generator 1. // 7. Return value scale. In testing saved +3% over scale in external function // and scaling the value is common. If applying only in a local region using // functions or pattern{}s, it's a feature where savings be even more // significant. #declare f_ridged_mf = function { internal(59) } // Ridged Multifractal surface. It can be used to create multifractal height // fields and patterns. Multifractal refers to their characteristic of having a // fractal dimension which varies with altitude. They are built from summing // noise of a number of frequencies. The f_ridged_mf parameters determine how // many, and which frequencies are to be summed, and how the different // frequencies are weighted in the sum. // An advantage to using these instead of a height_field{} from an image is // that the ridged_mf function domain extends arbitrarily far in, say the x and // z directions, so huge landscapes can be made without losing resolution or // having to tile a height field. Other functions of interest are f_hetero_mf, // f_ridge and f_turbulence. // Parameters: x, y, z // Six extra parameters required: // 1. H is the negative of the exponent of the basic noise frequencies used in // building these functions (each frequency f's amplitude is weighted by the // factor fE- H ). When H is 1, the fractalization is relatively smooth. As H // nears 0, the high frequencies contribute equally with low frequencies. As H // goes negative as specified the high frequencies carry greater weight. // 2. Lacunarity (gap). This somewhat like the POV-Ray's, turbulence's lambda // value. It's the difference in scale between any two octaves worth of // calculations. The gap between frequencies. Octave increments scaled by // 1/pow(Lac,H)*Oc. Higher values tighten the peak to peak gaps, more or less, // and so lower altitude. Typical values >2.0 and should use >1.0 min. // 3. Octaves. Integer values. The larger the value the more detail in the // result. Any fractional portion / overrun multiplied by the magnitude of the // greatest integer octave calculated - which tends to add extra divots. // (Blender calls octaves detail, which is apt) // 4. Offset gives a fractal whose fractal dimension changes from altitude to // altitude. The high frequencies at low altitudes are more damped than at // higher altitudes, so that lower altitudes are smoother than higher areas. // Higher values also lower the peaks. // 5. Gain weights the successive contributions to the accumulated fractal // result to make creases stick up as ridges // 6. The noise generator to use. Values of 1,2 or 3 valid. 2 or 3 most useful // because they are not clamped at -+1 as is generator 1. // 7. Return value scale. In testing saved +3% over scale in external function // and scaling the value is common. If applying only in a local region using // functions or pattern{}s, it's a feature where savings be even more // significant. #declare f_rounded_box = function { internal(60) } // Returns values forming a rounded box. Internal values are negative having a // maximum negative magnitude of the radius. In other words the value ramps 0 // to negative only at the surface and only to a depth of the radius before // maxing out - which isn't the best general behavior. The positive gradients // outside are always linearly increasing which is good. // Parameters: x, y, z // Four extra parameters required: // 1. Radius of curvature. Zero gives square corners, 0.1 gives corners that // match "sphere {0,0.1}" // 2. Scale x // 3. Scale y // 4. Scale z #declare f_sphere = function { internal(61) } // Returns values forming a sphere. Sphere internal values are negative having // a magnitude at the center of -radius parameter. // Parameters: x, y, z // One extra parameter required: // 1. Radius of the sphere. #declare f_enc3x_f21 = function { internal(62) } // was f_spikes // Encodes three floats into a double's storage. The encoding is three 21 bit // floats meaning only six decimal digits of accuracy are available. The // thinking is this will often be plenty for things like normals or curve // control points. It allows the function mechanism to return three values // where normally the return is always a single double value. See f_dec3x_f21 // for the decoding function. // The range is always 2 million steps with an option to encode/decode to/from // a certain number of decimal places. See details for parameter 4. // Input values are rounded with c++ round(). Values larger than the maximum // representable are clamped at the plus or minus maximum. // An example: // #declare Var3xf21 = f_enc3x_f21(-19.3530720,0.3833065,23.7746838,4); // // f_dec3x_f21(Var3xf21,4,0) evaluates to -19.353100 // f_dec3x_f21(Var3xf21,4,1) evaluates to 0.383300 // f_dec3x_f21(Var3xf21,4,2) evaluates to 23.774700 // // #declare Var3xf21 = f_enc3x_f21(-99.9999910,99.9999910,0.0,4); // // f_dec3x_f21(Var3xf21,4,0) evaluates to -100.00000 // f_dec3x_f21(Var3xf21,4,1) evaluates to 100.00000 // f_dec3x_f21(Var3xf21,4,2) evaluates to 0.00000 // The returned "double" might evaluate to some double, but it is noise as // a single value. // The plan is to perhaps internalize this encode function in other inbuilt // functions when it makes sense. Returning a surface normal perhaps. // Parameters: // 1. First double value. // 2. Second double value. // 3. Third double value. // 4. Number of the significant digits allocation to decimal digits. Valid // values are 0 to 6. // 0 -> +-1000000. // 1 -> +-100000.0 // 2 -> +-10000.00 // 3 -> +-1000.000 // 4 -> +-100.0000 // 5 -> +-10.00000 // 6 -> +-1.000000 #declare f_dec3x_f21 = function { internal(63) } // was f_spikes_2d // Decodes three floats from a double's storage. The encoding is three 21 bit // values and only one at a time can be decoded (restored to a true double). // See f_enc3x_f21 for the encoding function which must be used to create the // encoded value this function decodes. Running this against a traditional // double will return who knows what values. // The plan is to perhaps internalize the decode function in other inbuilt // functions when it makes sense. Decoding a surface normal perhaps. // Parameters: // 1. The three 21 bit float encoded double space. // 2. The number of decimal digits. If you want the same value out as encoded // this must match the value used with the f_enc3x_f21 encoding. That said // it need not. If you want to encode to 10.12345 and decode to 101.2345 you // can by encoding with five decimal places and decoding to four. // 3. Which of the three encoded values to decode. Valid index values are 0, 1 // and 2. To get all three encoded values out, three calls to f_dec3x_f21 must // be made. #declare f_spiral = function { internal(64) } // Returns values forming various spiral shapes. This spiral function is NOT // a match for the pattern sprial1 and spiral2 implementations. // Parameters: x, y, z // Six extra parameters required: // 1. Distance between windings. Setting this to 0.3 means that the spiral // is 0.3 pov units further from the origin each time it completes one whole // turn. // 2. Half thickness or radius of the arms/windings. // 3. Outer radius of the spiral. The surface behaves as if it is // contained_by a sphere of this radius. // 4. Cross section type. 0 Square. 1 Sphere. 2 Diamond. 3 Inward diamond. #declare f_range2range = function { internal(65) } // was f_steiners_roman // Adjusts one range of values to another range of values. It also moves the // values outside the incoming range to accommodate the output values. In other // words, it is an inbuilt version of the F_adj_range2 macro. The same method // is used internally as part of the quilted, tiled and furrowed normal // perturbation pattern. // It can be used to select only a portion of the value response of a pattern // or function by changing that portion to cover the entire response range. // For example, it could be used to change the 0-1 value range of the pattern // bozo to that of a standard function internal of -1 to 1 (the 0.5 value of // bozo would be at 0.0). Or it can be used to do the reverse. // In use with functions as input along with min, max for clamping the any part // of the value response for a function can be mapped to the 0-1 range for // typical pattern map use. Though here the mapping mechanism is already // reasonably flexible. // Parameters: // 1. The input value. // 2. The lowest input value of the range to adjust. // 3. The highest input value of the range to adjust. // 4. The lowest output value of the target range. // 5. The highest output value of the target range. #declare f_toupie = function { internal(66) } // was f_strophoid // Returns values forming a toupie (top). Internal values are negative with a // varying magnitude being more negative the more inside the shape the sample // point. // This is only truly an f_toupie function when (4) is equal to 3. The internal // calculations are set up so the gradient is around 1.0 at (4) = 3 or the true // f_toupie. It's < 1.0 where (4) is < 3. Where (4) > 3 it creeps upward; when // (4) = 6 the gradient is around 2.5. At (4) = 12 the gradient sits around // 11.5. // Parameters: x, y, z // Four extra parameters required: // 1. If 0, uses doubles for calculations. If 1, uses floats. Floats less // accurate, but faster. // 2. The major radius. // 3. Sort of the minor radius, but only truly that when the integer // exponent(4) is 2.0 and a torus is the result. Otherwise, it is sort of a // thickness in y parameter. // 4. Integer powers from 1 to 15. Values <1 set at 1. Values >15 mod 16. The // greater this value, the flatter the top and bottom of the shape, though it's // always ever slightly rounded even at large values. For even values, the // larger values tend to fill in the middle/hole more so you more often get a // button like result. // * // f_toupie(x,y,z,0,0.2,0.005,1) - Like a spindle torus intersection / lemon. // f_toupie(x,y,z,0,0.5,0.005,2) - Torus. // f_toupie(x,y,z,0,0.5,0.005,3) - Toupie. Odd exponents above all Toupie like. // f_toupie(x,y,z,0,0.5,0.005,4) - Torus nearly flat top/bottom. Metal washer. // f_toupie(x,y,z,0,0.2,0.005,4) - Torus nearly flat top/bottom. Solid middle // like a button. Even values >4 all of // similar form. #declare f_supertorus = function { internal(67) } // was f_strophoid_2d // Returns values forming a supertorus. Supertorus internal values are negative // with a varying magnitude being more negative the more inside the shape the // sample point. // When parameters 4 and 5 are near 1.0 the gradients are near 1.0 and the // supertorus looks like a torus. As either 4 or 5 approach 0 or 4 or so the // gradients can get quite high. 15 -> 80 say. // Parameters: x, y, z // Five extra parameters required: // 1. If 0, uses double floats to do the calculations. More accurate but often // slower. If 1, uses single floats to do the calculations. See // f_superellipsoid description for more information. Performance differences // between float types are dramatic on many CPUs. // 2. Major radius. // 3. Minor radius. // 4. Square-ish, round, diamond-ish cross section >0, 1, >1 around // supertorus's y axis. // 5. Like 3 in some respects, but changes the supertorus profile into square, // round and diamond. #declare f_superellipsoid = function { internal(68) } // Returns values forming a superellipsoid. Superellipsoid internal values are // negative with a varying magnitude being more negative the more inside the // shape the sample point. // At doubles EW/NS ranges of 0.01 to 4.0 workable. At single floats ranges of // 0.05 to 4.0 workable. // Do NOT take the EW or NS parameters to zero. The gradients become absurd at // or very near zero. Further, if one parameter very small and the other large // gradients can be >100. When both values near 4.0, the gradients also start // to push 100. // Parameters: x, y, z // Five extra parameters required: // 1. If 0, uses double floats to do the calculations. On some hardware and // recent c libraries, this can be slow. Slower than raw coded functions in the // scene description language. If 1, uses single floats for the calculations // which can be as much as 45% faster on some hardware. If working in singles // enough to eliminate the bottleneck. The results ARE less accurate, but often // OK. // 2. EW parameter. // 3. NS parameter. #declare f_th = function { internal(69) } // Returns the atan2(x,z) radian value. For +z the value is 0 radians. The // values change from 0 to -pi at x,z coordinates enveloped in a, one half, // left handed negative rotation about the y axis. The values change from 0 to // +pi at x,z coordinates enveloped in a, one half, left handed positive // rotation about the y axis. In other words, the values are split into // positive and negative sets depending upon the x values being positive or // negative. // The core function here is atan2(x,z) like f_radial(z,x). Both of these // functions take x,y and z arguments, but use only x and z. The x and z values // are swapped internally for f_radial relative to the inbult f_th() function. // This means f_radial() 'starts' - is at 0.0 - for +x, where f_th() starts at // +z. // The th suffix is short for the somewhat traditional theta. See too f_r and // f_ph. // Parameters: x, y, z #declare f_torus = function { internal(70) } // Returns values forming a torus. Internal values are negative with a varying // magnitude being more negative the more inside the shape the sample point. // The actual values are strongly related to the minor radius. // One can get the equivalent of the v38 spindle merge torus by making the // major radius smaller than the minor radius. Further one can get the spindle // intersection by keeping the magnitudes the same as the merge torus but // flipping the major radius value negative -> f_torus(x,y,z,-0.1,0.3). // Aside: Where Major r > minor r sometimes called a ring torus. A major r <= // minor r, merge, sometimes called a dorn torus. // Parameters: x, y, z // Two extra parameters required: // 1. Major radius // 2. Minor radius #declare f_repeat = function { internal(71) } // was f_torus2 // Creates multiple copies of a spacial region. More specifically it creates n // x m multiple copies of function in a modula 3d space / 3d grid. // The base function should be centered at zero and small enough to fit in the // repeated 'cells'. The counts too are in both directions about the // particular axis. So a y count of two means two on each side of y. The deltas // represent the size of each cell in x,y or z. The directions are used to // prune counts in particular directions. Lastly, the cells offset exists so if // you have multiple instances of the isosurface you can make them all look // different with respect to textures. // Parameters: x, y, z // Thirteen extra parameter required: // 1. If 0, return new x. If 1, return new y. If 2, return new z. If 3, // return matched cells pattern equivalent value 0 to 1 interval. If 4, // return matched cells pattern equivalent value -1 to 1 interval. // 2. Count in x. // 3. Count in y. // 4. Count in z. // 5. Delta in x. // 6. Delta in y. // 7. Delta in z. // 8. Direction in x. If 0, count applied +-. If <0, count applied - only. If // >0, count applied + only. // 9. Direction in y. // 10. Direction in z. // 11. Cells pattern offset in x. Randomize to avoid duplicate cell values in // local fmod() regions. // 12. Cells pattern offset in y. // 13. Cells pattern offset in z. #declare f_marble = function { internal(72) } // Was f_torus_gumdrop // Returns values similar to the pattern marble. The generated values are // mapped to a 0 - 1 - 0 triangle wave. To match the povr marble pattern // exactly use the parameters: // NOTE! Perhaps not the final form. Play with this some more! // #declare defaultFreq = (1.0/3.0)*0.1; // f_marble(x,y,z,0,defaultFreq,6,0.5,2.0,2) // Without turbulence the pattern is really gradient x,y,z for (1) at 0,1,2. // The pattern version uses gradient x only as the base. // Any marble pattern can be duplicated with f_agate and aside from the power // function used with f_agate the code is quite similar. // Parameters: x, y, z // Size extra parameters required: // 1. Base gradient orientation to which any turbulence will be applied. 0, 1 // or 2 for x, y or z. // 2. Internal value turbulence scale (frequency). This value can be zero in // which case a simple gradient mapped to a triangle wave is output. // 3. Octaves. Valid values are 1 to 10. Usual default is 6. // 4. Omega. A damping factor from octave to octave. Usual default is 0.5. // 5. Lambda. Higher values create more violent turbulence. Usual default is // 2.0. Valid values from -10 to 10. // 6. Noise generator to use. Values of 1, 2 or 3 valid. Usual default is 2. #declare f_wood = function { internal(73) } // was f_umbrella // Returns values similar to the pattern wood. The generated values are // mapped to a 0 - 1 - 0 triangle wave. To match the povr wood pattern // exactly use the parameters: // NOTE! Not the final form. Play with this some more! Want some way to vary // ring thicknesses... // #declare defaultFreq = (1.0/3.0)*0.1; // f_wood(x,y,z,2,defaultFreq,6,0.5,2.0,2) // Parameters: x, y, z // Size extra parameters required: // 1. Base gradient orientation to which any turbulence will be applied. 0, 1 // or 2 for x, y or z. The usual value is 2 or z. // 2. Internal value turbulence scale (frequency). This value can be zero in // which case a simple cylindrical gradient mapped to a triangle wave is // output. // 3. Octaves. Valid values are 1 to 10. Usual default is 2. // 4. Omega. A damping factor from octave to octave. Usual default is 0.5. // 5. Lambda. Higher values create more violent turbulence. Usual default is // 2.0. Valid values range from -10 to 10. // 6. Noise generator to use. Values of 1, 2 or 3 valid. Usual default is 2. #declare f_enc2x_f32 = function { internal(74) } // was f_witch_of_agnesi // Encodes two 32 bit floats into a double's storage. The encoding is by cast // from a two passed doubles to two floats in the storage for the double. This // involves a reduction in accuacy from at best 17 digits from the double to 9 // digits for the float, but it can somewhat vary. // Use to return or pass two full floats from a function. See f_dec2x_f32 for // the decoding function. // Input values are byt case so unlike the f_dec3x_f121 pair c++11's round() is // not used. One gets for accuracy what they get with a cast from double to // float. The thinking is performance more important in general. // An example: // #declare Var2xf32 = f_enc2x_f32(-19.3530720,0.3833065); // // f_dec2x_f21(Var2xf32,0) evaluates to -19.353100 // f_dec2x_f21(Var2xf32,1) evaluates to 0.383300 // // The returned "double" might evaluate to some double, but it is noise as // a single value. // Parameters: // 1. First double value. // 2. Second double value. #declare f_dec2x_f32 = function { internal(75) } // was f_witch_of_agnesi_2d // Decodes two doubles (at float accuracy) from double's storage. The encoding // is the standard for floats. Only one float value at a time can be decoded // (restored to a true double). See f_enc2x_f32 for the encoding function // which must be used to create the encoded value this function decodes. // Running this against a traditional encoded double will return junk values. // Parameters: // 1. The two 32 bit float encoded double space. // 2. Which of the two encoded values to decode. Valid index values are 0 or 1. // To get all two encoded values out, two calls to f_dec3x_f21 must be made. #declare f_noise3d = function { internal(76) } // Returns noise values at the point. Internally directly accessing the Noise() // function used as the basis for many patterns. See too f_snoise3d() and // f_turbulence(). // Returns values centered at 0.5 in a 0 to 1 range. Values for noise // generators 2 and 3 are not clamped and the value distribution tails do drift // outside the 0 to 1 range. Noise generator 1 is clamped strictly to the 0 - 1 // range, but this often leads to ugly artifacts in patterns or displacements. // Parameters: x, y, z // One extra parameter. // 1. The number of the noise generator to use. (1-3 currently) 2 - usual use. // _doc_skip_ NOTE! internal(77) is currently used for f_pattern. ie pattern {} #declare f_snoise3d = function { internal(78) } // Returns noise values at the point. Internally directly accessing the Noise() // function used as the basis for many patterns. See too f_noise3d() and // f_turbulence(). // Returns values centered at 0.0 in a -1 to 1 range. Values for noise // generators 2 and 3 are not clamped and the value distribution tails do drift // outside the -1 to 1 range. Noise generator 1 is clamped strictly to the -1 // to 1 range, but this often leads to ugly artifacts in patterns or // displacements. // Parameters: x, y, z // One extra parameter required: // 1. noise_generator number (1-3 currently) 2 - usual use. #declare f_npmod = function { internal(79) } // A pattern aware fmod() function. Implements the frequency + phase like mod // function used with pattern{}s. Meaning with f_npmod the value goes to // value/int(value/denominator) instead of 0.0 where the underlying value is // not 0.0, but fmod(value/denominator) is 0.0. // For example, the fmod of a gradient being used to create a function at 0, 1, // 2, and so on, should not snap back to 0.0 at the >=1 integer values if the // underlying function value is not itself 0.0. Doing so creates // discontinuities in values whether used for pattern{}s or // isosurface/parametric shapes - and so visible rendering artifacts. // Parameters: // 1. Value. // 2. Mod denominator. // 3. Multiplier. Useful, for example, when normalizing tilings with f_npmod() // for isosurface use. #declare f_eblob = function { internal(80) } // An exponential blobbing technique. One with good continuity and reasonably // controlled gradients. // The idea of using exp() to blob has been around a long time in different // forms. Maybe 15 years ago, give or take, Tor Olav posted the idea of using a // 1/exp(S*T) form where the tightness (T) was specified for each function // providing a value(S). I've used the method and in many situations it works - // though the gradients tend to get quite high and I find myself always twiddling //with the starting threshold values. // This implementation is currently set up to be used something like: // #declare FnBlob00 = function (x,y,z,Mode,Tightness) { // f_eblob(0.001,4,Mode, // FnSph00(x,y,z),FnSph01(x,y,z), // FnSph02(x,y,z),FnSph03(x,y,z),0,0,0,0, // Tightness,Tightness,Tightness,Tightness,0,0,0,0) // } // The function f_eblob expects the incoming function/shape thresholds to be at // 0.0 - which is usually true. // Nineteen extra parameters: // 1. +- offset between two 1/exp() evaluations. Default of 0.001 almost always // good. // 2. The number of active incoming functions / shapes from 1-8. // 3) The modes. 0 calculates a blobbed value from all the function input // values and strengths. 1 calculates an all pairwise, most negative, // interpolation to come up with pattern *_map values. The maps have a // particular form - similar to the tiling patterns - and for the 4 functions / // shapes version it looks something like: // #declare ColorMap01 = color_map { // [0.000000 ColorPositive] // [0.142857 ColorFn00] // [0.285714 ColorFn01] // [0.285714 ColorFn00] // [0.428571 ColorFn02] // [0.428571 ColorFn00] // [0.571429 ColorFn03] // [0.571429 ColorFn01] // [0.714286 ColorFn02] // [0.714286 ColorFn01] // [0.857143 ColorFn03] // [0.857143 ColorFn02] // [1.000000 ColorFn03] // } // A value of exactly 1.1 provides some debugging feedback by turning off // interpolation where the function/shape is itself negative enough to overcome // the internal threshold. Values >1.1 and <=6.0 currently do a poly_wave pow() // type of interpolation. // 4-11. The function value inputs. Unused are set to 0.0. // 12-19. The matching tightness values >0.0 to 100.0. Unused to 0.0. #declare f_revolution = function { internal(81) } // Rotates 2d cut of an equation values around y axis. This function has // similarities to an internal macro called ROT2D which was used internal to // many of the original inbuilt functions to provide rotation about z then // rotation around the y axis. // Note however, the z axis rotation of the macro ROT2D was not generally // stable and the method used herein for that rotation is different. The angle // for f_revolution treated as more of a post revolution lean. That said, the // result for it can be confusing too if say the internals of a function -like // f_box- are using the absolute values of the x,y,z coordinates internally. // In the f_box case it can lead to interesting shapes similar spouts, which // might be useful. More controllable than it was, but still tricky... // One can do the rotations about x or z by flipped input coordinates The lean // angle will always be // // simple example // #declare Offset = 0.7; // #declare Angle = +30.0; // // #declare Fn02 = function (x,y,z,r) { // f_sphere(f_revolution(x,y,z,Offset,Angle,0), // f_revolution(x,y,z,Offset,Angle,1), // 0,r) // } // // More complex example supporting arcs // #declare Fn00 = // function(x,y,z,_radial,_start,_stop,_offset,_angle,_r) { // select(-(_radial>=_start & _radial<=_stop), // f_sphere(f_revolution(x,y,z,_offset,_angle,0), // f_revolution(x,y,z,_offset,_angle,1), // 0,_r), // min( // f_sphere(f_revolution(x,y,z,_offset,_angle,0), // f_revolution(x,y,z,_offset,_angle,1), // _start-_radial,_r), // f_sphere(f_revolution(x,y,z,_offset,_angle,0), // f_revolution(x,y,z,_offset,_angle,1), // _radial-_stop,_r) // ) // ) // } // #declare Fn03 = function (x,y,z,_start,_stop,_offset,_angle,_r) { // Fn00(x,y,z,f_radial(x,y,z),_start,_stop,_offset,_angle,_r) // } // #declare Offset = 0.7; // #declare Angle = 0.0; // -22.0 // #declare Iso99 = isosurface { // function { Fn03(x,y,z,0.25,0.80,Offset,Angle,0.03) } // ... // Notes on arcs! The implementation supporting arcs above works quite well so // long as the ends are not too close to the start and stop +x locations and // not too close to each other such that they interfere. Much higher gradients // can help extend the range to some extent. Very short arcs are also an issue // as the ends start to get tangled. // Further, the f_radial 0-1 start and stop positions are close, but not exact // and must more or less be dialed in for each type of shape. The gradients are // simply not the same. The jump in gradients caused by the select forces the // use of the new 'report no' feature to avoid meaningless gradient warnings. // Parameters : x ,y ,z // Three extra parameters are required. // 1. Offset for the x axis with internal negation. Meaning to move equation // results in +x one would specify a positive value. // 2. The angle for any z axis rotation prior to rotation about y. This often // as not is 0.0. Here it is more of a post revolution lean angle about the // axis so it generates shapes which are asymmetric. Note is values approach // +-90 there is (supposing an offset (1)) one tends to get two cylinders and // +-z at the offset values. // 3. The x or y value to return - 0|1. If no z axis rotation only need // adjusted x (0). //-------------------- // Isosurface pattern functions... Note, povr working to replace all these with // inbuilt variants. Believe the original f_* versions only caused confusion // and were mostly of limited practical use. // (Old notes) Some of these are not implemented because they require special // parameters that must be specified in the definition. For this reason, you // probably would want to define your own versions of these functions. //-------------------- // f_agate Replaced with inbuilt f_agate. // average Not implemented // f_boxed See inbuilt f_box(). pattern{} wrap or function { -max(0.0,f_box(...)} } // f_bozo Deleted. It was always only f_noise3d. // f_brick Deleted. Not commonly useful. pattern{} wrap user function if needed. // f_bumps Deleted. It was always only f_noise3d. // f_cells Never wrapped herein... Note! It is now available // as modes(4,5) of the inbuilt f_repeat. // f_checker Deleted. Note commonly useful. pattern{} wrap user function if needed. #declare F_crackle = function {pattern {crackle}} // Was f_crackle // f_cylindrical See f_cylinder otherwise {pattern {cylindrical}}) // density_file Not implemented // f_dents Replaced with inbuilt f_noise_cubed. dents and F_dents normal/iso versions. // f_gradientX Three replaced with single inbuilt f_gradient. // f_gradientY // f_gradientZ // f_granite Alternate inbuilt f_granite23 otherwise pattern{} wrap. // image_pattern Not implemented // f_hexagon Deleted. Not commonly useful. pattern{} wrap user function if needed. #declare F_leopard = function {pattern {leopard}} // Was f_leopard //Only the basic mandel pattern is implemented, its variants and //The other fractal patterns are not implemented. // f_mandel Deleted. Never useful reason to wrap just one in {pattern {mandel 25}} // f_marble Replaced by inbuilt f_marble // also sometime as F_marble // object Not implemented // f_onion Replaced by inbuilt f_onion. // pigment_pattern Not implemented // f_planar Replaced by inbuilt f_planar (a shell function) // f_radial Replaced wtih inbuilt f_radial. #declare F_ripples = function {pattern {ripples}} // was f_ripples // f_spherical See f_sphere (r+fsphere()/r) or otherwise user {pattern {spherical}} #declare F_spiral1 = function {pattern {spiral1 2}} // was f_spiral1 #declare F_spiral2 = function {pattern {spiral2 2}} // was f_spiral2 // f_spotted Deleted. It was always only f_noise3d. Further, spotted pattern itself deleted. #declare F_waves = function {pattern {waves}} // was f_waves // f_wood Replaced by inbuilt f_wood // also sometime as F_wood #declare F_wrinkles = function {pattern {wrinkles}} // was f_wrinkles // Waveform functions #declare F_sine_wave = function {sin(x*z*pi)*y} // F_sine_wave(val, amplitude, frequency) #declare F_scallop_wave = function {abs(sin(x*z*pi)*y)} // F_scallop_wave(val, amplitude, frequency) // ------------------------------------------------------------------ // Trig: (POV-Ray proper had these in math.inc without F_ prefix) // ------------------------------------------------------------------ #declare F_sind = function (x) {sin(radians(x))} #declare F_cosd = function (x) {cos(radians(x))} #declare F_tand = function (x) {tan(radians(x))} #declare F_asind = function (x) {degrees(asin(x))} #declare F_acosd = function (x) {degrees(acos(x))} #declare F_atand = function (x) {degrees(atan(x))} #declare F_atan2d = function (x,y) {degrees(atan2(x,y))} // -------------------------------------------------------- // Misc: (POV-Ray proper had these in math.inc without F_ prefix) // -------------------------------------------------------- #declare F_max3 = function (x,y,z) {max(x,y,z)} #declare F_min3 = function (x,y,z) {min(x,y,z)} #declare F_even = function(x) {select(mod(x,2),0,1,0)} #declare F_odd = function(x) {select(mod(x,2),1,0,1)} // F_sqr // Squares the value passed. Usually better to use the inbuilt pow() or just // value*value. #declare F_sqr = function (x) {(x*x)} // F_sgn // Returns the sign of a value. In povr use inbuilt f_sign, f_sign0 instead. #declare F_sgn = function (x) {select(x,-1,0,1)} // F_clip // Range handling clips a number (x) to the range [Min, Max] ([y, z]). Values // above Max return Max, below Min return Min. #declare F_clip = function (x,y,z) {min(z,max(x,y))} // F_clamp // Clamps a number (x) to the range [Min, Max) ([y, z)). Values outside this // range wrap around. Notes! // 1) This function likely should've been called F_wrap (or when lower case // f_wrap) as this more accurately what it does. F_clip, clipping and clamping // are often used synonymously though probably clamping should be used in place // of clipping which means to cut / select... Yes, aware the usage as muddled // outside POV-Ray / povr as inside. // 2) The documentation herein long claimed this clamping was inclusive to // [Min, Max], but the max value was never in the result even when the input // value matched the Max value exactly. // 3) It is better to use the now inbuilt f_wrap. It duplicates this macro for // mode 0. A mode 1, where even aligned wrapped around values do go all the way // to Max where the odd aligned wraps go to 0 at the 'Max'. #declare F_clamp = function (x,y,z) {mod(x-y,z-y) + select(mod(x-y,z-y),z,y)} // Adjusts input values (x) in the range [0, 1] to output values in range // [Rmn,Rmx] ([y, z]). Normally (x) in input range, but it need not be. #declare F_adj_range = function (x,y,z) {x*(z-y)+y} // Adjusts passed (x) values in a specified range [Rmin(y), Rmax(z)] to a new // value relative the specified range [Min(_mn), Max(_mx)]. Normally (x) in // input range, but it need not be. #declare F_adj_range2 = function (x,y,z,_mn,_mx) { ((x-y)/(z-y))*(_mx-_mn)+_mn } // F_dents // A normal vector perturbation dents implementation. The macro implements the type // of dents executed in the normal{} block and more. // Example use: // #declare Fn00 = function (x,y,z) { f_cylinder(x,y,z,0.3) } // #declare Fn01 = function (x,y,z,_scale_dents,_scale_turb,_bump_depth) { // Fn00(x+F_dents(x,y,z,_scale_dents,0,_scale_turb,_bump_depth, // Fn00(x,y,z),Fn00(x+1e-4,y,z),Fn00(x,y+1e-4,z),Fn00(x,y,z+1e-4)), // y+F_dents(x,y,z,_scale_dents,1,_scale_turb,_bump_depth, // Fn00(x,y,z),Fn00(x+1e-4,y,z),Fn00(x,y+1e-4,z),Fn00(x,y,z+1e-4)), // z+F_dents(x,y,z,_scale_dents,2,_scale_turb,_bump_depth, // Fn00(x,y,z),Fn00(x+1e-4,y,z),Fn00(x,y+1e-4,z),Fn00(x,y,z+1e-4)) // )+f_noise3d(x*50,y*50,z*50,2)*0.003 // } // #declare Iso99 = isosurface { // function { Fn01(y,x,z,0.11,21.3,0.1) } // A // //function { Fn01(y,x,z,0.21,11.3,0.2) } // B // //function { Fn01(y,x,z,0.05,12.9,0.1) } // C // ... #declare F_dents = function (x,y,z,_scale_dents,_xyz,_scale_turb,_bump_depth,ptv,ptxv,ptyv,ptzv) { f_noise_cubed(x/_scale_dents,y/_scale_dents,z/_scale_dents,2,0,1) //f_noise_cubed(x/_scale_dents,y/_scale_dents,z/_scale_dents,2,1,1) //f_noise_cubed(x/_scale_dents,y/_scale_dents,z/_scale_dents,2,2,1) //f_noise_cubed(x/_scale_dents,y/_scale_dents,z/_scale_dents,2,3,1) * _bump_depth * abs(f_turbulence(x/_scale_turb,y/_scale_turb,z/_scale_turb,_xyz, 2,1.0,0,1,6,0.5,2.7)) * f_normal(ptv,ptxv,ptyv,ptzv,_xyz,_bump_depth) } //================================= End render time declarations =================================== //--- Self testing: povr +mv3.8 +i #if(input_file_name="functions.inc") #fopen FID "SelfTestFunctionsInc.txt" write #write (FID,"\nExpect value followed by value generated.\nF_ prefixed are pattern/math wrapped equivalents.\n") // f_gradient #write (FID,"\n---\n") #write (FID,concat("f_gradient 0.000000 ",str(f_gradient(+0,0,0,1,0,0),9,-1),"\n")) #write (FID,concat("f_gradient 1.000000 ",str(f_gradient(+1,0,0,1,0,0),9,-1),"\n")) #write (FID,concat("f_gradient -1.000000 ",str(f_gradient(-1,0,0,1,0,0),9,-1),"\n")) #write (FID,concat("f_gradient 0.999849 ",str(f_gradient(0,+0.707,+0.707,0,+1,+1),9,-1),"\n")) #write (FID,concat("f_gradient 9.998490 ",str(f_gradient(0,+7.07,+7.07,0,+1,+1),9,-1),"\n")) #write (FID,concat("f_gradient -0.000000 ",str(f_gradient(0,-0.707,-0.707,0,-1,+1),9,-1),"\n")) #ifdef (F_gradient) #undef F_gradient #end #declare F_gradient = function { pattern { gradient <0,-1,+1> raw_wave } } #write (FID,concat("F_gradient -0.000000 ",str(F_gradient(0,-0.707,-0.707),9,-1)," (raw_wave)\n")) #undef F_gradient #declare F_gradient = function { pattern { gradient <0,-1,+1> } } #write (FID,concat("F_gradient 0.000000 ",str(F_gradient(0,-0.707,-0.707),9,-1)," (0-1 pattern value)\n")) #write (FID,"\n") // f_radial #write (FID,"\n---\n") #write (FID,concat("f_radial 0.000000 ",str(f_radial(+1,+0,+0),9,-1),"\n")) #write (FID,concat("f_radial 0.000000 ",str(f_radial(+0,+1,+0),9,-1),"\n")) #write (FID,concat("f_radial 0.875000 ",str(f_radial(+1,+0,+1),9,-1),"\n")) #write (FID,concat("f_radial 0.750000 ",str(f_radial(+0,+0,+1),9,-1),"\n")) #write (FID,concat("f_radial 0.500000 ",str(f_radial(-1,+0,+0),9,-1),"\n")) #write (FID,concat("f_radial 0.375000 ",str(f_radial(-1,+0,-1),9,-1),"\n")) #write (FID,concat("f_radial 0.000000 ",str(f_radial(+1,+0,-1e-9),9,-1),"\n")) #write (FID,concat("f_radial 1.000000 ",str(f_radial(+1,+0,+1e-9),9,-1),"\n")) #ifdef (F_radial) #undef F_radial #end #declare F_radial = function { pattern { radial raw_wave } } #write (FID,concat("F_radial 0.000000 ",str(F_radial(+1,+0,+0),9,-1)," (raw_wave)\n")) #write (FID,concat("F_radial 0.000000 ",str(F_radial(+0,+1,+0),9,-1)," (raw_wave)\n")) #write (FID,concat("F_radial 0.875000 ",str(F_radial(+1,+0,+1),9,-1)," (raw_wave)\n")) #write (FID,concat("F_radial 0.750000 ",str(F_radial(+0,+0,+1),9,-1)," (raw_wave)\n")) #write (FID,concat("F_radial 0.500000 ",str(F_radial(-1,+0,+0),9,-1)," (raw_wave)\n")) #write (FID,concat("F_radial 0.375000 ",str(F_radial(-1,+0,-1),9,-1)," (raw_wave)\n")) #write (FID,concat("F_radial 0.000000 ",str(F_radial(+1,+0,-1e-9),9,-1)," (raw_wave)\n")) #write (FID,concat("F_radial 1.000000 ",str(F_radial(+1,+0,+1e-9),9,-1)," (raw_wave)\n")) #write (FID,"\n") // f_th #write (FID,"\n---\n") #write (FID,concat("f_th 0.000000 ",str(f_th(+0,+0,+1),9,-1),"\n")) #ifdef (F_atan2) #undef F_atan2 #end #declare F_atan2 = function (x,z) { atan2(x,z) } #write (FID,concat("F_atan2 0.000000 ",str(F_atan2(+0,+1),9,-1),"\n")) #write (FID,concat("f_th 1.570796 ",str(f_th(+1,+0,+0),9,-1),"\n")) #write (FID,concat("f_th -1.570796 ",str(f_th(-1,+0,+0),9,-1),"\n")) #write (FID,concat("f_th 3.141593 ",str(f_th(+0,+0,-1),9,-1),"\n")) #write (FID,concat("F_atan2 3.141593 ",str(F_atan2(+0,-1),9,-1),"\n")) #write (FID,concat("f_th -3.141593 ",str(f_th(+0-1e-9,+0,-1),9,-1),"\n")) #write (FID,concat("f_th 3.141593 ",str(f_th(+0+1e-9,+0,-1),9,-1),"\n")) #write (FID,concat("f_th 0.000000 ",str(f_th(+0,+0,+0),9,-1),"\n")) #write (FID,concat("f_th 0.000000 ",str(f_th(+0,+1,+0),9,-1),"\n")) #write (FID,concat("f_th 0.785398 ",str(f_th(+1,+0,+1),9,-1),"\n")) #write (FID,concat("f_th -2.356194 ",str(f_th(-1,+0,-1),9,-1),"\n")) #write (FID,"\n") // f_cylinder #write (FID,"\n---\n") #write (FID,concat("f_cylinder -1.000000 ",str(f_cylinder(+0,+0,+0,1),9,-1),"\n")) #write (FID,concat("f_cylinder -2.000000 ",str(f_cylinder(+0,+0,+0,2),9,-1),"\n")) #write (FID,concat("f_cylinder 0.000000 ",str(f_cylinder(+1,0,0,1),9,-1),"\n")) #write (FID,concat("f_cylinder -0.000151 ",str(f_cylinder(+0.707,+1,+0.707,1),9,-1),"\n")) #write (FID,concat("f_cylinder 7.998490 ",str(f_cylinder(+7.07,+1,+7.07,2),9,-1),"\n")) #write (FID,concat("f_cylinder 9.000000 ",str(f_cylinder(10,+0,+0,1),9,-1),"\n")) #ifdef (F_cylindrical) #undef F_cylindrical #end #declare F_cylindrical = function { pattern { cylindrical raw_wave } } #write (FID,concat("F_cylinder 0.000000 ",str(F_cylindrical(+1.5,+0,+0),9,-1)," (raw_wave pattern value)\n")) #undef F_cylindrical #declare F_cylindrical = function { pattern { cylindrical } } #write (FID,concat("F_cylinder 0.000000 ",str(F_cylindrical(+1.5,+0,+0),9,-1)," (0-1 pattern value)\n")) #write (FID,concat("F_cylinder 0.500000 ",str(F_cylindrical(+0.5,+0,+0),9,-1)," (0-1 pattern value)\n")) #write (FID,concat("F_cylinder 1.000000 ",str(F_cylindrical(+0.0,+0,+0),9,-1)," (0-1 pattern value)\n")) #write (FID,"\n") // f_length Results should match f_r #write (FID,"\n---\n") #write (FID,concat("f_length 0.000000 ",str(f_length(+0,+0,+0),9,-1),"\n")) #write (FID,concat("f_length 0.500000 ",str(f_length(+0.5,+0.0,+0.0),9,-1),"\n")) #write (FID,concat("f_length 0.600000 ",str(f_length(+0.0,+0.6,+0.0),9,-1),"\n")) #write (FID,concat("f_length 0.700000 ",str(f_length(+0.0,+0.0,+0.7),9,-1),"\n")) #write (FID,concat("f_length 1.000000 ",str(f_length(0.577350,0.577350,0.577350),9,-1),"\n")) #write (FID,"\n") // f_length_sqr #write (FID,"\n---\n") #write (FID,concat("f_length_sqr 12.000000 ",str(f_length_sqr(2,2,2),9,-1),"\n")) #write (FID,"\n") // f_r #write (FID,"\n---\n") #write (FID,concat("f_r 0.000000 ",str(f_r(+0,+0,+0),9,-1),"\n")) #write (FID,concat("f_r 0.500000 ",str(f_r(+0.5,+0.0,+0.0),9,-1),"\n")) #write (FID,concat("f_r 0.600000 ",str(f_r(+0.0,+0.6,+0.0),9,-1),"\n")) #write (FID,concat("f_r 0.700000 ",str(f_r(+0.0,+0.0,+0.7),9,-1),"\n")) #write (FID,concat("f_r 1.000000 ",str(f_r(0.577350,0.577350,0.577350),9,-1),"\n")) #write (FID,concat("f_length ",str(f_length(1.577350,2.577350,3.577350),9,-1)," ",str(f_r(1.577350,2.577350,3.577350),9,-1)," (vs f_r)\n")) #write (FID,"\n") // f_normal #write (FID,"\n---\n") #write (FID,concat("f_normal 0.000000 ",str(f_normal( f_sphere(0,0,0,0.5),f_sphere(0,0,0,0.5),f_sphere(0,0,0,0.5),f_sphere(0,0,0,0.5),0,0.05),9,-1),"\n")) #write (FID,concat("f_normal -1.000000 ",str( f_normal(f_sphere(0.5,0,0,0.5),f_sphere(0.5+1e-4,0,0,0.5),f_sphere(0.5,0+1e-4,0,0.5),f_sphere(0.5,0,0+1e-4,0.5),0,0.05),9,-1),"\n")) #write (FID,concat("f_normal 0.000000 ",str( f_normal(f_sphere(1.5,0,0,0.5),f_sphere(1.5+1e-4,0,0,0.5),f_sphere(1.5,0+1e-4,0,0.5),f_sphere(1.5,0,0+1e-4,0.5),0,0.05),9,-1),"\n")) #write (FID,"-\n") #ifdef (Var3xf21) #undef Var3xf21 #end #declare Var3xf21 = f_normal(f_sphere(0.577350+0e+0,0.577350+0e+0,-0.577350+0e+0,1.0), f_sphere(0.577350+1e-4,0.577350+0e+0,-0.577350+0e+0,1.0), f_sphere(0.577350+0e+0,0.577350+1e-4,-0.577350+0e+0,1.0), f_sphere(0.577350+0e+0,0.577350+0e+0,-0.577350+1e-4,1.0), 3,0.25); #write (FID,concat("f_normal -0.577350 ",str(f_dec3x_f21(Var3xf21,6,0),9,-1)," internal f_enc3x_f21 return (x)\n")) #write (FID,concat("f_normal -0.577350 ",str(f_dec3x_f21(Var3xf21,6,1),9,-1)," internal f_enc3x_f21 return (y)\n")) #write (FID,concat("f_normal -0.577350 ",str(f_dec3x_f21(Var3xf21,6,2),9,-1)," internal f_enc3x_f21 return (z)\n")) #write (FID,"\n") // f_normalized #write (FID,"\n---\n") #write (FID,concat("f_normalized 0.000000 ",str(f_normalized(+0,+0,+0,0),9,-1),"\n")) #write (FID,concat("f_normalized 1.000000 ",str(f_normalized(+0.5,+0.0,+0.0,0),9,-1),"\n")) #write (FID,concat("f_normalized 1.000000 ",str(f_normalized(+0.0,+0.6,+0.0,1),9,-1),"\n")) #write (FID,concat("f_normalized 1.000000 ",str(f_normalized(+0.0,+0.0,+0.7,2),9,-1),"\n")) #write (FID,concat("f_normalized 0.577350 ",str(f_normalized(+1,+1,+1,0),9,-1),"\n")) #write (FID,concat("f_normalized 0.577350 ",str(f_normalized(+1,+1,+1,1),9,-1),"\n")) #write (FID,concat("f_normalized 0.577350 ",str(f_normalized(+1,+1,+1,2),9,-1),"\n")) #write (FID,"\n") // f_mult1to8pairs #write (FID,"\n---\n") #write (FID,concat("f_mult1to8pairs -3.464102 ", // sqrt -12 retain sign str(f_mult1to8pairs(8,0,0,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (neg neg mult, min return)\n")) #write (FID,concat("f_mult1to8pairs 3.741657 ", // sqrt 14 neg*pos is pos str(f_mult1to8pairs(8,0,1,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (neg neg mult, max return)\n")) #write (FID,concat("f_mult1to8pairs 0.000000 ", str(f_mult1to8pairs(8,1,0,+0,+1,+2,+3,+4,+5,+6,+7, +2,+2,+2,+2,+2,+2,+2,+2),9,-1)," (normal mult, min return)\n")) #write (FID,concat("f_mult1to8pairs 14.000000 ", str(f_mult1to8pairs(8,1,1,+0,+1,+2,+3,+4,+5,+6,+7, +2,+2,+2,+2,+2,+2,+2,+2),9,-1)," (normal mult, max return)\n")) #write (FID,concat("f_mult1to8pairs 0.400000 ", str(f_mult1to8pairs(8,1,10,+0,+1,-3,+3,+4,+5,+6,+7, +2,+2,+1,-2,+2,+2,+2,+2),9,-1)," (normal mult, map return)\n")) #write (FID,concat("f_mult1to8pairs -1.414214 ", str(f_mult1to8pairs(8,2,0,-1,+1,+2,+3,+4,+5,-6,+7, +2,+2,+2,+2,+2,+2,-2,+2),9,-1)," (normal mult -> sqrt -> sign, min return)\n")) #write (FID,concat("f_mult1to8pairs 3.741657 ", str(f_mult1to8pairs(8,2,1,+0,+1,+2,+3,-4,+5,+6,+7, +2,+2,+2,+2,+2,+2,-4,+2),9,-1)," (normal mult -> sqrt -> sign, max return)\n")) #write (FID,"\n") //f_max1to8pairs #write (FID,"\n---\n") #write (FID,concat("f_max1to8pairs -2.000000 ", str(f_max1to8pairs(8,0,0,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (Min of all max pairs)\n")) #write (FID,concat("f_max1to8pairs 5.000000 ", str(f_max1to8pairs(8,0,1,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (Max of all max pairs)\n")) #write (FID,concat("f_max1to8pairs 0.700000 ", str(f_max1to8pairs(8,0,10,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (Min of all max pairs - map value)\n")) #write (FID,concat("f_max1to8pairs 0.700000 ", str(f_max1to8pairs(8,0,11,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (Max of all max pairs - map value)\n")) #write (FID,"\n") //f_min1to8pairs #write (FID,"\n---\n") #write (FID,concat("f_min1to8pairs -7.000000 ", str(f_min1to8pairs(8,0,0,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (Min of all min pairs)\n")) #write (FID,concat("f_min1to8pairs 2.000000 ", str(f_min1to8pairs(8,0,1,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (Max of all min pairs)\n")) #write (FID,concat("f_min1to8pairs 0.800000 ", str(f_min1to8pairs(8,0,10,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (Min of all min pairs - map value)\n")) #write (FID,concat("f_min1to8pairs 0.800000 ", str(f_min1to8pairs(8,0,11,+0,+1,+2,+3,+4,+5,-6,-7, +2,-2,+2,+2,+2,+2,-2,+2),9,-1)," (Max of all min pairs - map value)\n")) #write (FID,"\n") // f_bump #write (FID,"\n---\n") #write (FID,concat("f_bump 0.367879 ",str(f_bump(+0.0,1,0),9,-1),"\n")) #write (FID,concat("f_bump 1.000000 ",str(f_bump(+0.0,1,1),9,-1),"\n")) #write (FID,concat("f_bump 1.000000 ",str(f_bump(+0.0,1,2),9,-1),"\n")) #write (FID,concat("f_bump 0.263597 ",str(f_bump(+0.5,1,0),9,-1),"\n")) #write (FID,concat("f_bump 0.716531 ",str(f_bump(+0.5,1,1),9,-1),"\n")) #write (FID,concat("f_bump -0.716531 ",str(f_bump(-0.5,1,2),9,-1),"\n")) #write (FID,concat("f_bump 0.001174 ",str(f_bump(+0.995,16,0),9,-1),"\n")) #write (FID,concat("f_bump 0.003190 ",str(f_bump(+0.995,16,1),9,-1),"\n")) #write (FID,concat("f_bump -0.003190 ",str(f_bump(-0.995,16,2),9,-1),"\n")) #write (FID,concat("f_bump 0.000000 ",str(f_bump(+1.0,1,0),9,-1),"\n")) #write (FID,concat("f_bump 0.000000 ",str(f_bump(+1.0,1,1),9,-1),"\n")) #write (FID,concat("f_bump -0.000000 ",str(f_bump(-1.0,1,2),9,-1),"\n")) #write (FID,concat("f_bump 0.000000 ",str(f_bump(+2.0,1,0),9,-1),"\n")) #write (FID,concat("f_bump 0.000000 ",str(f_bump(+2.0,1,1),9,-1),"\n")) #write (FID,concat("f_bump -0.000000 ",str(f_bump(-2.0,1,2),9,-1),"\n")) #write (FID,"\n") // f_box #write (FID,"\n---\n") #write (FID,concat("f_box -1.000000 ",str(f_box(0,0,0,0,1.0,1.0,1.0),9,-1)," mode 0\n")) #write (FID,concat("f_box -1.000000 ",str(f_box(0,0,0,1,1.0,1.0,1.0),9,-1)," mode 1\n")) #write (FID,concat("f_box -1.000000 ",str(f_box(0,0,0,0,1.0,0.5,1.0),9,-1)," mode 0\n")) #write (FID,concat("f_box -0.500000 ",str(f_box(0,0,0,1,1.0,0.5,1.0),9,-1)," mode 1\n")) #write (FID,concat("f_box -1.000000 ",str(f_box(0,0,0,0,1.0,1.5,1.0),9,-1)," mode 0\n")) #write (FID,concat("f_box -1.000000 ",str(f_box(0,0,0,1,1.0,1.5,1.0),9,-1)," mode 1\n")) #write (FID,"\n") // f_cylinder #write (FID,"\n---\n") #write (FID,concat("f_cylinder -0.800000 ",str(f_cylinder(0,0,0,0.8),9,-1),"\n")) #write (FID,concat("f_cylinder 0.000000 ",str(f_cylinder(0.8,0,0,0.8),9,-1),"\n")) #write (FID,concat("f_cylinder 0.800000 ",str(f_cylinder(1.6,0,0,0.8),9,-1),"\n")) #write (FID,concat("f_cylinder 0.800000 ",str(f_cylinder(1.6,1.0,0,0.8),9,-1),"\n")) #write (FID,"\n") // f_cone #write (FID,"\n---\n") #write (FID,concat("f_cone -0.800000 ",str(f_cone(0,0,0,0.8),9,-1),"\n")) #write (FID,concat("f_cone -0.400000 ",str(f_cone(0,+0.4,0,0.8),9,-1),"\n")) #write (FID,concat("f_cone -0.400000 ",str(f_cone(0,-0.4,0,0.8),9,-1),"\n")) #write (FID,concat("f_cone 0.000000 ",str(f_cone(0,+0.8,0,0.8),9,-1),"\n")) #write (FID,concat("f_cone 0.000000 ",str(f_cone(0,-0.8,0,0.8),9,-1),"\n")) #write (FID,concat("f_cone 0.000000 ",str(f_cone(0.8,0,0,0.8),9,-1),"\n")) #write (FID,concat("f_cone 0.800000 ",str(f_cone(1.6,0,0,0.8),9,-1),"\n")) #write (FID,concat("f_cone 1.800000 ",str(f_cone(1.6,+1.0,0,0.8),9,-1),"\n")) #write (FID,concat("f_cone 1.800000 ",str(f_cone(1.6,-1.0,0,0.8),9,-1),"\n")) #write (FID,"\n") // f_sphere #write (FID,"\n---\n") #write (FID,concat("f_sphere -0.800000 ",str(f_sphere(0,0,0,0.8),9,-1),"\n")) #write (FID,concat("f_sphere 0.000000 ",str(f_sphere(0.8,0,0,0.8),9,-1),"\n")) #write (FID,concat("f_sphere 0.800000 ",str(f_sphere(1.6,0,0,0.8),9,-1),"\n")) #write (FID,"\n") // f_paraboloid #write (FID,"\n---\n") #write (FID,concat("f_paraboloid 0.000000 ",str(f_paraboloid(+0,+0,+0,1,0),9,-1),"\n")) #write (FID,concat("f_paraboloid -1.000000 ",str(f_paraboloid(+0,+1,+0,1,0),9,-1),"\n")) #write (FID,concat("f_paraboloid -1.000000 ",str(f_paraboloid(+0,-1,+0,1,0),9,-1),"\n")) #write (FID,concat("f_paraboloid -0.750000 ",str(f_paraboloid(+0.5,+1,+0,1,0),9,-1),"\n")) #write (FID,concat("f_paraboloid -0.750000 ",str(f_paraboloid(+0.5,-1,+0,1,0),9,-1),"\n")) #write (FID,concat("f_paraboloid 0.000000 ",str(f_paraboloid(+1,+1,+0,1,0),9,-1),"\n")) #write (FID,concat("f_paraboloid 0.000000 ",str(f_paraboloid(+1,-1,+0,1,0),9,-1),"\n")) #write (FID,concat("f_paraboloid 1.442250 ",str(f_paraboloid(+2,+1,+0,1,0),9,-1)," x+2 with cbrt\n")) #write (FID,concat("f_paraboloid 1.442250 ",str(f_paraboloid(+2,-1,+0,1,0),9,-1)," x+2 with cbrt\n")) #write (FID,concat("f_paraboloid 3.000000 ",str(f_paraboloid(+2,+1,+0,1,1),9,-1)," x+2 no cbrt\n")) #write (FID,concat("f_paraboloid 3.000000 ",str(f_paraboloid(+2,-1,+0,1,1),9,-1)," x+2 no cbrt\n")) #write (FID,"\n") // f_rounded_box #write (FID,"\n---\n") #write (FID,concat("f_rounded_box -0.100001 ",str(f_rounded_box(0,0,0,0.1,1,1,1),9,-1),"\n")) #write (FID,concat("f_rounded_box -0.000001 ",str(f_rounded_box(1,0,0,0.1,1,1,1),9,-1),"\n")) #write (FID,concat("f_rounded_box -0.000001 ",str(f_rounded_box(0,1,0,0.1,1,1,1),9,-1),"\n")) #write (FID,concat("f_rounded_box -0.000001 ",str(f_rounded_box(0,0,1,0.1,1,1,1),9,-1),"\n")) #write (FID,concat("f_rounded_box -0.100001 ",str(f_rounded_box(0.5,0,0,0.1,1,1,1),9,-1),"\n")) #write (FID,concat("f_rounded_box -0.100001 ",str(f_rounded_box(0,0.5,0,0.1,1,1,1),9,-1),"\n")) #write (FID,concat("f_rounded_box -0.100001 ",str(f_rounded_box(0,0,0.5,0.1,1,1,1),9,-1),"\n")) #write (FID,concat("f_rounded_box 0.499999 ",str(f_rounded_box(1.5,0,0,0.1,1,1,1),9,-1),"\n")) #write (FID,concat("f_rounded_box 0.499999 ",str(f_rounded_box(0,1.5,0,0.1,1,1,1),9,-1),"\n")) #write (FID,concat("f_rounded_box 0.499999 ",str(f_rounded_box(0,0,1.5,0.1,1,1,1),9,-1),"\n")) #write (FID,"\n") // f_agate #write (FID,"\n---\n") #ifdef (F_agate) #undef F_agate #end #declare F_agate = function { pattern { agate } } #write (FID,concat("f_agate 0.9301307385262627 ",str(f_agate(0.1,0.2,0.3,2,1.0,0.77,6,0.5,2.0,2),19,16),"\n")) #write (FID,concat("F_agate 0.9301307385262627 ",str(F_agate(0.1,0.2,0.3),19,16),"\n")) #write (FID,concat("f_agate 0.0168871058507170 ",str(f_agate(1234567890.0123456789,0.2,0.3,2,1.0,0.77,6,0.5,2.0,2),19,16),"\n")) #write (FID,concat("F_agate 0.0168871058507170 ",str(F_agate(1234567890.0123456789,0.2,0.3),19,16),"\n")) #undef F_agate #declare F_agate = function { pattern { agate it_frequency 2} } #write (FID,concat("f_agate 0.9044277581607145 ",str(f_agate(0.1,0.2,0.3,2,2.0,0.77,6,0.5,2.0,2),19,16)," freq 2\n")) #write (FID,concat("F_agate 0.9044277581607145 ",str(F_agate(0.1,0.2,0.3),19,16)," freq 2\n")) #undef F_agate #declare F_agate = function { pattern { agate it_octaves 2} } #write (FID,concat("f_agate 0.8921130516193988 ",str(f_agate(0.1,0.2,0.3,2,1.0,0.77,2,0.5,2.0,2),19,16)," oct 2\n")) #write (FID,concat("F_agate 0.8921130516193988 ",str(F_agate(0.1,0.2,0.3),19,16)," oct 2\n")) #undef F_agate #declare F_agate = function { pattern { agate it_omega 0.6} } #write (FID,concat("f_agate 0.5995236490468518 ",str(f_agate(0.1,0.2,0.3,2,1.0,0.77,6,0.6,2.0,2),19,16)," omeg 0.6\n")) #write (FID,concat("F_agate 0.5995236490468518 ",str(F_agate(0.1,0.2,0.3),19,16)," omeg 0.6\n")) #undef F_agate #declare F_agate = function { pattern { agate it_lambda 3.3} } #write (FID,concat("f_agate 0.9926258195595942 ",str(f_agate(0.1,0.2,0.3,2,1.0,0.77,6,0.5,3.3,2),19,16)," lam 3.3\n")) #write (FID,concat("F_agate 0.9926258195595942 ",str(F_agate(0.1,0.2,0.3),19,16)," lam 3.3\n")) #write (FID,"\n") // f_average #write (FID,"\n---\n") #ifdef (F_average) #undef F_average #end #declare F_average = function { pigment { average pigment_map { [agate scale 1/6] [agate scale 1/6 inverse] } } } #write (FID,concat("F_average.red 0.5000000000000000 ",str(F_average(0.1,+0.2,0.3).red,19,16)," test average and inverse\n")) #write (FID,concat("F_average.red 0.5000000000000000 ",str(F_average(0.3,-0.2,0.1).red,19,16),"\n")) #write (FID,"\n") // f_onion #write (FID,"\n---\n") #ifdef (F_onion) #undef F_onion #end #declare F_onion = function { pattern { onion } } #write (FID,concat("f_onion 0.000000 ",str(f_onion(0,0,0,1.0,0,0),9,-1)," at 0\n")) #write (FID,concat("F_onion 0.000000 ",str(F_onion(0,0,0),9,-1),"\n")) #write (FID,concat("f_onion 0.000000 ",str(f_onion(1,0,0,1.0,0,0),9,-1)," at x+1\n")) #write (FID,concat("F_onion 0.000000 ",str(F_onion(1,0,0),9,-1)," at x+1\n")) #write (FID,concat("f_onion 0.000000 ",str(f_onion(2,0,0,1.0,0,0),9,-1)," at x+2\n")) #write (FID,concat("F_onion 0.000000 ",str(F_onion(2,0,0),9,-1)," at x+2\n")) #write (FID,concat("f_onion 1.000000 ",str(f_onion(1-1e-9,0,0,1.0,0,0),9,-1)," at x+1-epsilon\n")) #write (FID,concat("F_onion 1.000000 ",str(F_onion(1-1e-9,0,0),9,-1)," at x+1-epsilon\n")) #write (FID,concat("f_onion 1.000000 ",str(f_onion(1,0,0,1.1,0,0),9,-1)," at x+1 fmod denominator at 1.1\n\n")) # #write (FID,concat("f_onion -1.000000 ",str(f_onion(0.0,0,0,1.0,0,1),9,-1)," at x=0.0 returning -1 to 1 range.\n")) #write (FID,concat("f_onion 0.000000 ",str(f_onion(0.5,0,0,1.0,0,1),9,-1)," at x+0.5 returning -1 to 1 range.\n")) #write (FID,concat("f_onion 1.000000 ",str(f_onion(1.0-1e-9,0,0,1.0,0,1),9,-1)," at x+1.0-epsilon returning -1 to 1 range.\n")) #write (FID,concat("f_onion -1.000000 ",str(f_onion(1.0,0,0,1.0,0,1),9,-1)," at x+1.0 returning -1 to 1 range.\n\n")) # #ifdef (F_onion) #undef F_onion #end #declare F_onion = function { pattern { onion triangle_wave } } #write (FID,concat("f_onion 0.000000 ",str(f_onion(0,0.0,0,1.0,1,0),9,-1)," at y=0 triangle wave\n")) #write (FID,concat("f_onion 1.000000 ",str(f_onion(0,0.5,0,1.0,1,0),9,-1)," at y+0.5 triangle wave\n")) #write (FID,concat("f_onion 0.000000 ",str(f_onion(0,1.0-1e-9,0,1.0,1,0),9,-1)," at y+1.0-epsilon triangle wave\n")) #write (FID,concat("f_onion 0.000000 ",str(f_onion(0,1.0,0,1.0,1,0),9,-1)," at y+1.0 triangle wave\n")) #write (FID,concat("f_onion 0.000000 ",str(f_onion(0,1.0+1e-9,0,1.0,1,0),9,-1)," at y+1.0+epsilon triangle wave\n\n")) #write (FID,concat("F_onion 0.000000 ",str(F_onion(0,0.0,0),9,-1)," at y=0 triangle wave\n")) #write (FID,concat("F_onion 1.000000 ",str(F_onion(0,0.5,0),9,-1)," at y+0.5 triangle wave\n")) #write (FID,concat("F_onion 0.000000 ",str(F_onion(0,1.0-1e-9,0),9,-1)," at y+1.0-epsilon triangle wave\n")) #write (FID,concat("F_onion 0.000000 ",str(F_onion(0,1.0+0e-9,0),9,-1)," at y+1.0 triangle wave\n")) #write (FID,concat("F_onion 0.000000 ",str(F_onion(0,1.0+1e-9,0),9,-1)," at y+1.0+epsilon triangle wave\n\n")) # #write (FID,concat("f_onion -1.000000 ",str(f_onion(0,0.0,0,1.0,1,1),9,-1)," at y=0 triangle wave -1 to 1 range.\n")) #write (FID,concat("f_onion 1.000000 ",str(f_onion(0,0.5,0,1.0,1,1),9,-1)," at y+0.5 triangle wave -1 to 1 range.\n")) #write (FID,concat("f_onion -1.000000 ",str(f_onion(0,1.0-1e-9,0,1.0,1,1),9,-1)," at y+1.0-epsilon triangle wave -1 to 1 range.\n")) #write (FID,concat("f_onion -1.000000 ",str(f_onion(0,1.0,0,1.0,1,1),9,-1)," at y+1.0 triangle wave -1 to 1 range.\n")) #write (FID,concat("f_onion -1.000000 ",str(f_onion(0,1.0+1e-9,0,1.0,1,1),9,-1)," at y+1.0+epsilon triangle wave -1 to 1 range.\n")) #write (FID,"\n") // f_npmod #ifdef (F_mod) #undef F_mod #end #declare F_mod = function (x,y) { mod(x,y) } #write (FID,"\n---\n") #write (FID,concat("f_npmod -0.5000000000000000 ",str(f_npmod(-0.5,1,1),19,16)," at -0.50\n")) #write (FID,concat("F_mod -0.5000000000000000 ",str(F_mod(-0.5,1),19,16)," at -0.50\n")) #write (FID,concat("f_npmod 0.0000000000000000 ",str(f_npmod(+0.0,1,1),19,16)," at 0.00\n")) #write (FID,concat("F_mod 0.0000000000000000 ",str(F_mod(+0.0,1),19,16)," at 0.00\n")) #write (FID,concat("f_npmod +0.5000000000000000 ",str(f_npmod(+0.5,1,1),19,16)," at +0.50\n")) #write (FID,concat("F_mod +0.5000000000000000 ",str(F_mod(+0.5,1),19,16)," at +0.50\n")) #write (FID,"-\n") //- #write (FID,concat("f_npmod +0.5000000000000000 ",str(f_npmod(+1.5,1,1),19,16)," at +1.50\n")) #write (FID,concat("F_mod +0.5000000000000000 ",str(F_mod(+1.5,1),19,16)," at +1.50\n")) #write (FID,concat("f_npmod +1.0000000000000000 ",str(f_npmod(+1.0,1,1),19,16)," at +1.00 (*)\n")) #write (FID,concat("F_mod 0.0000000000000000 ",str(F_mod(+1.0,1),19,16)," at +1.00\n")) #write (FID,concat("f_npmod -1.0000000000000000 ",str(f_npmod(-1.0,1,1),19,16)," at -1.00 (*)\n")) #write (FID,concat("F_mod -0.0000000000000000 ",str(F_mod(-1.0,1),19,16)," at -1.00\n")) #write (FID,concat("f_npmod -0.5000000000000000 ",str(f_npmod(-1.5,1,1),19,16)," at -1.50\n")) #write (FID,concat("F_mod -0.5000000000000000 ",str(F_mod(-1.5,1),19,16)," at -1.50\n")) #write (FID,"-\n") #ifdef (F_gradient) #undef F_gradient #end #declare F_gradient = function { pattern { gradient <1,0,0> } } #ifdef (F_gradient_fi) #undef F_gradient_fi #end #declare F_gradient_fi = function { pattern { gradient <1,0,0> function_interval } } #write (FID,concat("F_gradient 1.0000000000000000 ",str(F_gradient(+1.0,0,0),19,16)," at +1.00\n")) #write (FID,concat("F_gradient 0.0000000000000000 ",str(F_gradient(-1.0,0,0),19,16)," at -1.00\n")) #write (FID,concat("F_gradient -1.0000000000000000 ",str(F_gradient_fi(-1.0,0,0),19,16)," at -1.00 function_interval\n")) //- #write (FID,concat("f_npmod 0.0000000000000011 ",str(f_npmod(+1.0+1e-15,1,1),19,16)," at +1.00+1e-15\n")) #write (FID,concat("F_mod 0.0000000000000011 ",str(F_mod(+1.0+1e-15,1),19,16)," at +1.00+1e-15\n")) #write (FID,concat("f_npmod -0.9999999999999990 ",str(f_npmod(-1.0+1e-15,1,1),19,16)," at -1.00+1e-15\n")) #write (FID,concat("F_mod -0.9999999999999990 ",str(F_mod(-1.0+1e-15,1),19,16)," at -1.00+1e-15\n")) //- #write (FID,concat("f_npmod 0.9999999999999990 ",str(f_npmod(+1.0-1e-15,1,1),19,16)," at +1.00-1e-15\n")) #write (FID,concat("F_mod 0.9999999999999990 ",str(F_mod(+1.0-1e-15,1),19,16)," at +1.00-1e-15\n")) #write (FID,concat("f_npmod -0.0000000000000011 ",str(f_npmod(-1.0-1e-15,1,1),19,16)," at -1.00-1e-15\n")) #write (FID,concat("F_mod -0.0000000000000011 ",str(F_mod(-1.0-1e-15,1),19,16)," at -1.00-1e-15\n")) //- #write (FID,concat("f_npmod 1.0000000000000000 ",str(f_npmod(+2.0,1,1),19,16)," at +2.00 (*)\n")) #write (FID,concat("F_mod 0.0000000000000000 ",str(F_mod(+2.0,1),19,16)," at +2.00\n")) #write (FID,concat("f_npmod -1.0000000000000000 ",str(f_npmod(-2.0,1,1),19,16)," at -2.00 (*)\n")) #write (FID,concat("F_mod -0.0000000000000000 ",str(F_mod(-2.0,1),19,16)," at -2.00\n")) #undef F_gradient #declare F_gradient = function { pattern { gradient <1,0,0> } } #write (FID,concat("F_gradient 1.0000000000000000 ",str(F_gradient(+2.0,0,0),19,16)," at +2.00\n")) #write (FID,concat("F_gradient 0.0000000000000000 ",str(F_gradient(-2.0,0,0),19,16)," at -2.00\n")) #write (FID,concat("F_gradient -1.0000000000000000 ",str(F_gradient_fi(-2.0,0,0),19,16)," at -2.00 function_interval\n")) #undef F_gradient #declare F_gradient = function { pattern { gradient <1,0,0> raw_wave } } #write (FID,concat("F_gradient 2.0000000000000000 ",str(F_gradient(+2.0,0,0),19,16)," at +2.00 raw_wave\n")) #write (FID,concat("F_gradient -2.0000000000000000 ",str(F_gradient(-2.0,0,0),19,16)," at -2.00 raw_wave\n")) #write (FID,"\n") // f_remap #write (FID,"\n---\n") #write (FID,concat("f_remap 0.000000 ",str(f_remap(+0.10,8,0, -0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3),9,-1)," at +0.10 (8 targets)\n")) #write (FID,concat("f_remap 1.000000 ",str(f_remap(+0.05,8,0, -0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3),9,-1)," at +0.05 8\n")) #write (FID,concat("f_remap -1.000000 ",str(f_remap(+0.15,8,0, -0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3),9,-1)," at +0.15 8\n")) #write (FID,concat("f_remap -1.000000 ",str(f_remap(-0.45,8,0, -0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3),9,-1)," at -0.45 8\n")) #write (FID,concat("f_remap -1.000000 ",str(f_remap(-0.50,8,0, -0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3),9,-1)," at -0.50 8\n")) #write (FID,concat("f_remap -1.000000 ",str(f_remap(+0.40,8,0, -0.4,-0.3,-0.2,-0.1,0,0.1,0.2,0.3),9,-1)," at +0.40 8\n")) #write (FID,"\n-\n") #write (FID,concat("f_remap -1.000000 ",str(f_remap(-0.35,7,0, -0.3,-0.2,-0.1,0,0.1,0.2,0.3,999),9,-1)," at -0.35\n (7 targets)")) #write (FID,concat("f_remap -1.000000 ",str(f_remap(-0.40,7,0, -0.3,-0.2,-0.1,0,0.1,0.2,0.3,999),9,-1)," at -0.40 7\n")) #write (FID,concat("f_remap 1.000000 ",str(f_remap(+0.35,7,0, -0.3,-0.2,-0.1,0,0.1,0.2,0.3,999),9,-1)," at +0.35 7\n")) #write (FID,concat("f_remap 1.000000 ",str(f_remap(+0.40,7,0, -0.3,-0.2,-0.1,0,0.1,0.2,0.3,999),9,-1)," at +0.407 \n")) #write (FID,"\n-\n") #write (FID,concat("f_remap 0.250000 ",str(f_remap(-0.25,3,1, -1.0,0.0,0.5,99,99,99,99,99),9,-1)," at -0.25 (three targets normalizing)\n")) #write (FID,concat("f_remap 0.750000 ",str(f_remap(-0.50,3,1, -1.0,0.0,0.5,99,99,99,99,99),9,-1)," at -0.50 3\n")) #write (FID,concat("f_remap 1.000000 ",str(f_remap(-2.50,3,1, -1.0,0.0,0.5,99,99,99,99,99),9,-1)," at -2.50 3\n")) #write (FID,concat("f_remap 0.500000 ",str(f_remap(+0.25,3,1, -1.0,0.0,0.5,99,99,99,99,99),9,-1)," at +0.25 3\n")) #write (FID,concat("f_remap 1.000000 ",str(f_remap(+2.50,3,1, -1.0,0.0,0.5,99,99,99,99,99),9,-1)," at +2.50 3\n")) #write (FID,"\n-\n") #write (FID,concat("f_remap 0.250000 ",str(f_remap(-0.25,4,1, -1.0,0.0,0.5,1.0,99,99,99,99),9,-1)," at -0.25 (four targets normalizing)\n")) #write (FID,concat("f_remap 0.750000 ",str(f_remap(-0.50,4,1, -1.0,0.0,0.5,1.0,99,99,99,99),9,-1)," at -0.50 4\n")) #write (FID,concat("f_remap 1.000000 ",str(f_remap(-2.50,4,1, -1.0,0.0,0.5,1.0,99,99,99,99),9,-1)," at -2.50 4\n")) #write (FID,concat("f_remap 0.500000 ",str(f_remap(+0.25,4,1, -1.0,0.0,0.5,1.0,99,99,99,99),9,-1)," at +0.25 4\n")) #write (FID,concat("f_remap 1.000000 ",str(f_remap(+2.50,4,1, -1.0,0.0,0.5,1.0,99,99,99,99),9,-1)," at +2.50 4\n")) #write (FID,"\n") // f_triangle_wave #write (FID,"\n---\n") #write (FID,concat("f_triangle_wave 0.000000 ",str(f_triangle_wave(-2.0,0),9,-1)," at -2.0\n")) #write (FID,concat("f_triangle_wave 1.000000 ",str(f_triangle_wave(-1.5,0),9,-1)," at -1.5\n")) #write (FID,concat("f_triangle_wave 0.000000 ",str(f_triangle_wave(-1.0,0),9,-1)," at -1.0\n")) #write (FID,concat("f_triangle_wave 1.000000 ",str(f_triangle_wave(-0.5,0),9,-1)," at -0.5\n")) #write (FID,concat("f_triangle_wave 0.000000 ",str(f_triangle_wave(+0.0,0),9,-1)," at +0.0\n")) #write (FID,concat("f_triangle_wave 1.000000 ",str(f_triangle_wave(+0.5,0),9,-1)," at +0.5\n")) #write (FID,concat("f_triangle_wave 0.000000 ",str(f_triangle_wave(+1.0,0),9,-1)," at +1.0\n")) #write (FID,concat("f_triangle_wave 1.000000 ",str(f_triangle_wave(+1.5,0),9,-1)," at +1.5\n")) #write (FID,concat("f_triangle_wave 0.000000 ",str(f_triangle_wave(+2.0,0),9,-1)," at +2.0\n")) //- #write (FID,concat("f_triangle_wave -1.000000 ",str(f_triangle_wave(-2.0,1),9,-1)," at -2.0 mode 1\n")) #write (FID,concat("f_triangle_wave 1.000000 ",str(f_triangle_wave(-1.5,1),9,-1)," at -1.5 mode 1\n")) #write (FID,concat("f_triangle_wave -1.000000 ",str(f_triangle_wave(-1.0,1),9,-1)," at -1.0 mode 1\n")) #write (FID,concat("f_triangle_wave 1.000000 ",str(f_triangle_wave(-0.5,1),9,-1)," at -0.5 mode 1\n")) #write (FID,concat("f_triangle_wave -1.000000 ",str(f_triangle_wave(+0.0,1),9,-1)," at +0.0 mode 1\n")) #write (FID,concat("f_triangle_wave 1.000000 ",str(f_triangle_wave(+0.5,1),9,-1)," at +0.5 mode 1\n")) #write (FID,concat("f_triangle_wave -1.000000 ",str(f_triangle_wave(+1.0,1),9,-1)," at +1.0 mode 1\n")) #write (FID,concat("f_triangle_wave 1.000000 ",str(f_triangle_wave(+1.5,1),9,-1)," at +1.5 mode 1\n")) #write (FID,concat("f_triangle_wave -1.000000 ",str(f_triangle_wave(+2.0,1),9,-1)," at +2.0 mode 1\n")) #write (FID,"\n") //- #ifdef (F_triangle_wave) #undef F_triangle_wave #end #declare F_triangle_wave = function { pattern { gradient <1,0,0> triangle_wave } } #write (FID,"\n---\n") #write (FID,concat("F_triangle_wave 0.000000 ",str(F_triangle_wave(-2.0,0,0),9,-1)," at -2.0\n")) #write (FID,concat("F_triangle_wave 1.000000 ",str(F_triangle_wave(-1.5,0,0),9,-1)," at -1.5\n")) #write (FID,concat("F_triangle_wave 0.000000 ",str(F_triangle_wave(-1.0,0,0),9,-1)," at -1.0\n")) #write (FID,concat("F_triangle_wave 1.000000 ",str(F_triangle_wave(-0.5,0,0),9,-1)," at -0.5\n")) #write (FID,concat("F_triangle_wave 0.000000 ",str(F_triangle_wave(+0.0,0,0),9,-1)," at +0.0\n")) #write (FID,concat("F_triangle_wave 1.000000 ",str(F_triangle_wave(+0.5,0,0),9,-1)," at +0.5\n")) #write (FID,concat("F_triangle_wave 0.000000 ",str(F_triangle_wave(+1.0,0,0),9,-1)," at +1.0\n")) #write (FID,concat("F_triangle_wave 1.000000 ",str(F_triangle_wave(+1.5,0,0),9,-1)," at +1.5\n")) #write (FID,concat("F_triangle_wave 0.000000 ",str(F_triangle_wave(+2.0,0,0),9,-1)," at +2.0\n")) #ifdef (F_triangle_wave) #undef F_triangle_wave #end #declare F_triangle_wave = function { pattern { gradient <1,0,0> triangle_wave function_interval } } #write (FID,concat("F_triangle_wave -1.000000 ",str(F_triangle_wave(-2.0,0,0),9,-1)," at -2.0 function_interval\n")) #write (FID,concat("F_triangle_wave 1.000000 ",str(F_triangle_wave(-1.5,0,0),9,-1)," at -1.5 function_interval\n")) #write (FID,concat("F_triangle_wave -1.000000 ",str(F_triangle_wave(-1.0,0,0),9,-1)," at -1.0 function_interval\n")) #write (FID,concat("F_triangle_wave 1.000000 ",str(F_triangle_wave(-0.5,0,0),9,-1)," at -0.5 function_interval\n")) #write (FID,concat("F_triangle_wave -1.000000 ",str(F_triangle_wave(+0.0,0,0),9,-1)," at +0.0 function_interval\n")) #write (FID,concat("F_triangle_wave 1.000000 ",str(F_triangle_wave(+0.5,0,0),9,-1)," at +0.5 function_interval\n")) #write (FID,concat("F_triangle_wave -1.000000 ",str(F_triangle_wave(+1.0,0,0),9,-1)," at +1.0 function_interval\n")) #write (FID,concat("F_triangle_wave 1.000000 ",str(F_triangle_wave(+1.5,0,0),9,-1)," at +1.5 function_interval\n")) #write (FID,concat("F_triangle_wave -1.000000 ",str(F_triangle_wave(+2.0,0,0),9,-1)," at +2.0 function_interval\n")) #write (FID,"\n") // F_sine_wave(val, amplitude, frequency) - Traditional macro formerly named f_sine_wave. #write (FID,"\n---\n") #write (FID,concat("F_sine_wave +1.000000 ",str(F_sine_wave(-1.5,1,1),9,-1)," (Shipped macro) at -1.5\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(-1.0,1,1),9,-1)," (Shipped macro) at -1.0\n")) #write (FID,concat("F_sine_wave -1.000000 ",str(F_sine_wave(-0.5,1,1),9,-1)," (Shipped macro) at -0.5\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(+0.0,1,1),9,-1)," (Shipped macro) at +0.0\n")) #write (FID,concat("F_sine_wave +1.000000 ",str(F_sine_wave(+0.5,1,1),9,-1)," (Shipped macro) at +0.5\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(+1.0,1,1),9,-1)," (Shipped macro) at +1.0\n")) #write (FID,concat("F_sine_wave -1.000000 ",str(F_sine_wave(+1.5,1,1),9,-1)," (Shipped macro) at +1.5\n")) #write (FID,"-\n") #write (FID,concat("f_sine_wave +1.000000 ",str(f_sine_wave(-1.50,2),9,-1)," at -1.50 mode 2\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(-1.00,2),9,-1)," at -1.00 mode 2\n")) #write (FID,concat("f_sine_wave -1.000000 ",str(f_sine_wave(-0.50,2),9,-1)," at -0.50 mode 2\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(+0.00,2),9,-1)," at +0.00 mode 2\n")) #write (FID,concat("f_sine_wave +1.000000 ",str(f_sine_wave(+0.50,2),9,-1)," at +0.50 mode 2\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(+1.00,2),9,-1)," at +1.00 mode 2\n")) #write (FID,concat("f_sine_wave -1.000000 ",str(f_sine_wave(+1.50,2),9,-1)," at +1.50 mode 2\n")) #write (FID,"\n") // f_sine_wave #ifdef (F_sine_wave) #undef F_sine_wave #end #declare F_sine_wave = function { pattern { gradient <1,0,0> sine_wave } } #write (FID,"\n---\n") #write (FID,concat("f_sine_wave 0.500000 ",str(f_sine_wave(-2.00,0),9,-1)," at -2.00\n")) #write (FID,concat("f_sine_wave 1.000000 ",str(f_sine_wave(-1.75,0),9,-1)," at -1.75\n")) #write (FID,concat("f_sine_wave 0.500000 ",str(f_sine_wave(-1.50,0),9,-1)," at -1.50\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(-1.25,0),9,-1)," at -1.25\n")) #write (FID,concat("f_sine_wave 0.500000 ",str(f_sine_wave(-1.00,0),9,-1)," at -1.00\n")) #write (FID,concat("f_sine_wave 1.000000 ",str(f_sine_wave(-0.75,0),9,-1)," at -0.75\n")) #write (FID,concat("f_sine_wave 0.500000 ",str(f_sine_wave(-0.50,0),9,-1)," at -0.50\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(-0.25,0),9,-1)," at -0.25\n")) #write (FID,concat("f_sine_wave 0.500000 ",str(f_sine_wave(+0.00,0),9,-1)," at +0.00\n")) #write (FID,concat("f_sine_wave 1.000000 ",str(f_sine_wave(+0.25,0),9,-1)," at +0.25\n")) #write (FID,concat("f_sine_wave 0.500000 ",str(f_sine_wave(+0.50,0),9,-1)," at +0.50\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(+0.75,0),9,-1)," at +0.75\n")) #write (FID,concat("f_sine_wave 0.500000 ",str(f_sine_wave(+1.00,0),9,-1)," at +1.00\n")) #write (FID,concat("f_sine_wave 1.000000 ",str(f_sine_wave(+1.25,0),9,-1)," at +1.25\n")) #write (FID,concat("f_sine_wave 0.500000 ",str(f_sine_wave(+1.50,0),9,-1)," at +1.50\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(+1.75,0),9,-1)," at +1.75\n")) #write (FID,concat("f_sine_wave 0.500000 ",str(f_sine_wave(+2.00,0),9,-1)," at +2.00\n")) #write (FID,"-\n") #write (FID,concat("F_sine_wave 0.500000 ",str(F_sine_wave(-2.00,0,0),9,-1)," at -2.00\n")) #write (FID,concat("F_sine_wave 1.000000 ",str(F_sine_wave(-1.75,0,0),9,-1)," at -1.75\n")) #write (FID,concat("F_sine_wave 0.500000 ",str(F_sine_wave(-1.50,0,0),9,-1)," at -1.50\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(-1.25,0,0),9,-1)," at -1.25\n")) #write (FID,concat("F_sine_wave 0.500000 ",str(F_sine_wave(-1.00,0,0),9,-1)," at -1.00\n")) #write (FID,concat("F_sine_wave 1.000000 ",str(F_sine_wave(-0.75,0,0),9,-1)," at -0.75\n")) #write (FID,concat("F_sine_wave 0.500000 ",str(F_sine_wave(-0.50,0,0),9,-1)," at -0.50\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(-0.25,0,0),9,-1)," at -0.25\n")) #write (FID,concat("F_sine_wave 0.500000 ",str(F_sine_wave(+0.00,0,0),9,-1)," at +0.00\n")) #write (FID,concat("F_sine_wave 1.000000 ",str(F_sine_wave(+0.25,0,0),9,-1)," at +0.25\n")) #write (FID,concat("F_sine_wave 0.500000 ",str(F_sine_wave(+0.50,0,0),9,-1)," at +0.50\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(+0.75,0,0),9,-1)," at +0.75\n")) #write (FID,concat("F_sine_wave 0.500000 ",str(F_sine_wave(+1.00,0,0),9,-1)," at +1.00\n")) #write (FID,concat("F_sine_wave 1.000000 ",str(F_sine_wave(+1.25,0,0),9,-1)," at +1.25\n")) #write (FID,concat("F_sine_wave 0.500000 ",str(F_sine_wave(+1.50,0,0),9,-1)," at +1.50\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(+1.75,0,0),9,-1)," at +1.75\n")) #write (FID,concat("F_sine_wave 0.500000 ",str(F_sine_wave(+2.00,0,0),9,-1)," at +2.00\n")) #write (FID,"\n") //- #write (FID,"\n---\n") #ifdef (F_sine_wave) #undef F_sine_wave #end #declare F_sine_wave = function { pattern { gradient <1,0,0> sine_wave function_interval } } #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(-2.00,1),9,-1)," at -2.00 mode 1\n")) #write (FID,concat("f_sine_wave 1.000000 ",str(f_sine_wave(-1.75,1),9,-1)," at -1.75 mode 1\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(-1.50,1),9,-1)," at -1.50 mode 1\n")) #write (FID,concat("f_sine_wave -1.000000 ",str(f_sine_wave(-1.25,1),9,-1)," at -1.25 mode 1\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(-1.00,1),9,-1)," at -1.00 mode 1\n")) #write (FID,concat("f_sine_wave 1.000000 ",str(f_sine_wave(-0.75,1),9,-1)," at -0.75 mode 1\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(-0.50,1),9,-1)," at -0.50 mode 1\n")) #write (FID,concat("f_sine_wave -1.000000 ",str(f_sine_wave(-0.25,1),9,-1)," at -0.25 mode 1\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(+0.00,1),9,-1)," at +0.00 mode 1\n")) #write (FID,concat("f_sine_wave 1.000000 ",str(f_sine_wave(+0.25,1),9,-1)," at +0.25 mode 1\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(+0.50,1),9,-1)," at +0.50 mode 1\n")) #write (FID,concat("f_sine_wave -1.000000 ",str(f_sine_wave(+0.75,1),9,-1)," at +0.75 mode 1\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(+1.00,1),9,-1)," at +1.00 mode 1\n")) #write (FID,concat("f_sine_wave 1.000000 ",str(f_sine_wave(+1.25,1),9,-1)," at +1.25 mode 1\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(+1.50,1),9,-1)," at +1.50 mode 1\n")) #write (FID,concat("f_sine_wave -1.000000 ",str(f_sine_wave(+1.75,1),9,-1)," at +1.75 mode 1\n")) #write (FID,concat("f_sine_wave 0.000000 ",str(f_sine_wave(+2.00,1),9,-1)," at +2.00 mode 1\n")) #write (FID,"-\n") #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(-2.00,0,0),9,-1)," at -2.00 function_interval\n")) #write (FID,concat("F_sine_wave 1.000000 ",str(F_sine_wave(-1.75,0,0),9,-1)," at -1.75 function_interval\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(-1.50,0,0),9,-1)," at -1.50 function_interval\n")) #write (FID,concat("F_sine_wave -1.000000 ",str(F_sine_wave(-1.25,0,0),9,-1)," at -1.25 function_interval\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(-1.00,0,0),9,-1)," at -1.00 function_interval\n")) #write (FID,concat("F_sine_wave 1.000000 ",str(F_sine_wave(-0.75,0,0),9,-1)," at -0.75 function_interval\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(-0.50,0,0),9,-1)," at -0.50 function_interval\n")) #write (FID,concat("F_sine_wave -1.000000 ",str(F_sine_wave(-0.25,0,0),9,-1)," at -0.25 function_interval\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(+0.00,0,0),9,-1)," at +0.00 function_interval\n")) #write (FID,concat("F_sine_wave 1.000000 ",str(F_sine_wave(+0.25,0,0),9,-1)," at +0.25 function_interval\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(+0.50,0,0),9,-1)," at +0.50 function_interval\n")) #write (FID,concat("F_sine_wave -1.000000 ",str(F_sine_wave(+0.75,0,0),9,-1)," at +0.75 function_interval\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(+1.00,0,0),9,-1)," at +1.00 function_interval\n")) #write (FID,concat("F_sine_wave 1.000000 ",str(F_sine_wave(+1.25,0,0),9,-1)," at +1.25 function_interval\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(+1.50,0,0),9,-1)," at +1.50 function_interval\n")) #write (FID,concat("F_sine_wave -1.000000 ",str(F_sine_wave(+1.75,0,0),9,-1)," at +1.75 function_interval\n")) #write (FID,concat("F_sine_wave 0.000000 ",str(F_sine_wave(+2.00,0,0),9,-1)," at +2.00 function_interval\n")) #write (FID,"\n") // F_scallop_wave(val, amplitude, frequency) - Traditional macro formerly named f_scallop_wave. #write (FID,"\n---\n") #write (FID,concat("F_scallop_wave +1.000000 ",str(F_scallop_wave(-1.5,1,1),9,-1)," (Shipped macro) at -1.5\n")) #write (FID,concat("F_scallop_wave 0.000000 ",str(F_scallop_wave(-1.0,1,1),9,-1)," (Shipped macro) at -1.0\n")) #write (FID,concat("F_scallop_wave +1.000000 ",str(F_scallop_wave(-0.5,1,1),9,-1)," (Shipped macro) at -0.5\n")) #write (FID,concat("F_scallop_wave 0.000000 ",str(F_scallop_wave(+0.0,1,1),9,-1)," (Shipped macro) at +0.0\n")) #write (FID,concat("F_scallop_wave +1.000000 ",str(F_scallop_wave(+0.5,1,1),9,-1)," (Shipped macro) at +0.5\n")) #write (FID,concat("F_scallop_wave 0.000000 ",str(F_scallop_wave(+1.0,1,1),9,-1)," (Shipped macro) at +1.0\n")) #write (FID,concat("F_scallop_wave +1.000000 ",str(F_scallop_wave(+1.5,1,1),9,-1)," (Shipped macro) at +1.5\n")) #write (FID,"-\n") #write (FID,concat("f_scallop_wave +1.000000 ",str(f_scallop_wave(-1.50,0),9,-1)," at -1.50 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(-1.00,0),9,-1)," at -1.00 mode 2\n")) #write (FID,concat("f_scallop_wave +1.000000 ",str(f_scallop_wave(-0.50,0),9,-1)," at -0.50 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+0.00,0),9,-1)," at +0.00 mode 2\n")) #write (FID,concat("f_scallop_wave +1.000000 ",str(f_scallop_wave(+0.50,0),9,-1)," at +0.50 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+1.00,0),9,-1)," at +1.00 mode 2\n")) #write (FID,concat("f_scallop_wave +1.000000 ",str(f_scallop_wave(+1.50,0),9,-1)," at +1.50 mode 2\n")) #write (FID,"\n") // f_scallop_wave #ifdef (F_scallop_wave) #undef F_scallop_wave #end #declare F_scallop_wave = function { pattern { gradient <1,0,0> scallop_wave } } #write (FID,"\n---\n") #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(-2.00,0),9,-1)," at -2.00\n")) #write (FID,concat("f_scallop_wave 0.707107 ",str(f_scallop_wave(-1.75,0),9,-1)," at -1.75\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-1.50,0),9,-1)," at -1.50\n")) #write (FID,concat("f_scallop_wave 0.707107 ",str(f_scallop_wave(-1.25,0),9,-1)," at -1.25\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(-1.00,0),9,-1)," at -1.00\n")) #write (FID,concat("f_scallop_wave 0.707107 ",str(f_scallop_wave(-0.75,0),9,-1)," at -0.75\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-0.50,0),9,-1)," at -0.50\n")) #write (FID,concat("f_scallop_wave 0.707107 ",str(f_scallop_wave(-0.25,0),9,-1)," at -0.25\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+0.00,0),9,-1)," at +0.00\n")) #write (FID,concat("f_scallop_wave 0.707107 ",str(f_scallop_wave(+0.25,0),9,-1)," at +0.25\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+0.50,0),9,-1)," at +0.50\n")) #write (FID,concat("f_scallop_wave 0.707107 ",str(f_scallop_wave(+0.75,0),9,-1)," at +0.75\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+1.00,0),9,-1)," at +1.00\n")) #write (FID,concat("f_scallop_wave 0.707107 ",str(f_scallop_wave(+1.25,0),9,-1)," at +1.25\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+1.50,0),9,-1)," at +1.50\n")) #write (FID,concat("f_scallop_wave 0.707107 ",str(f_scallop_wave(+1.75,0),9,-1)," at +1.75\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+2.00,0),9,-1)," at +2.00\n")) #write (FID,"-\n") #write (FID,concat("F_scallop_wave 0.000000 ",str(F_scallop_wave(-2.00,0,0),9,-1)," at -2.00\n")) #write (FID,concat("F_scallop_wave 0.707107 ",str(F_scallop_wave(-1.75,0,0),9,-1)," at -1.75\n")) #write (FID,concat("F_scallop_wave 1.000000 ",str(F_scallop_wave(-1.50,0,0),9,-1)," at -1.50\n")) #write (FID,concat("F_scallop_wave 0.707107 ",str(F_scallop_wave(-1.25,0,0),9,-1)," at -1.25\n")) #write (FID,concat("F_scallop_wave 0.000000 ",str(F_scallop_wave(-1.00,0,0),9,-1)," at -1.00\n")) #write (FID,concat("F_scallop_wave 0.707107 ",str(F_scallop_wave(-0.75,0,0),9,-1)," at -0.75\n")) #write (FID,concat("F_scallop_wave 1.000000 ",str(F_scallop_wave(-0.50,0,0),9,-1)," at -0.50\n")) #write (FID,concat("F_scallop_wave 0.707107 ",str(F_scallop_wave(-0.25,0,0),9,-1)," at -0.25\n")) #write (FID,concat("F_scallop_wave 0.000000 ",str(F_scallop_wave(+0.00,0,0),9,-1)," at +0.00\n")) #write (FID,concat("F_scallop_wave 0.707107 ",str(F_scallop_wave(+0.25,0,0),9,-1)," at +0.25\n")) #write (FID,concat("F_scallop_wave 1.000000 ",str(F_scallop_wave(+0.50,0,0),9,-1)," at +0.50\n")) #write (FID,concat("F_scallop_wave 0.707107 ",str(F_scallop_wave(+0.75,0,0),9,-1)," at +0.75\n")) #write (FID,concat("F_scallop_wave 0.000000 ",str(F_scallop_wave(+1.00,0,0),9,-1)," at +1.00\n")) #write (FID,concat("F_scallop_wave 0.707107 ",str(F_scallop_wave(+1.25,0,0),9,-1)," at +1.25\n")) #write (FID,concat("F_scallop_wave 1.000000 ",str(F_scallop_wave(+1.50,0,0),9,-1)," at +1.50\n")) #write (FID,concat("F_scallop_wave 0.707107 ",str(F_scallop_wave(+1.75,0,0),9,-1)," at +1.75\n")) #write (FID,concat("F_scallop_wave 0.000000 ",str(F_scallop_wave(+2.00,0,0),9,-1)," at +2.00\n")) #write (FID,"\n") //- #write (FID,"\n---\n") #ifdef (F_scallop_wave) #undef F_scallop_wave #end #declare F_scallop_wave = function { pattern { gradient <1,0,0> scallop_wave function_interval } } #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(-2.00,1),9,-1)," at -2.00 mode 1\n")) #write (FID,concat("f_scallop_wave 0.414214 ",str(f_scallop_wave(-1.75,1),9,-1)," at -1.75 mode 1\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-1.50,1),9,-1)," at -1.50 mode 1\n")) #write (FID,concat("f_scallop_wave 0.414214 ",str(f_scallop_wave(-1.25,1),9,-1)," at -1.25 mode 1\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(-1.00,1),9,-1)," at -1.00 mode 1\n")) #write (FID,concat("f_scallop_wave 0.414214 ",str(f_scallop_wave(-0.75,1),9,-1)," at -0.75 mode 1\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-0.50,1),9,-1)," at -0.50 mode 1\n")) #write (FID,concat("f_scallop_wave 0.414214 ",str(f_scallop_wave(-0.25,1),9,-1)," at -0.25 mode 1\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(+0.00,1),9,-1)," at +0.00 mode 1\n")) #write (FID,concat("f_scallop_wave 0.414214 ",str(f_scallop_wave(+0.25,1),9,-1)," at +0.25 mode 1\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+0.50,1),9,-1)," at +0.50 mode 1\n")) #write (FID,concat("f_scallop_wave 0.414214 ",str(f_scallop_wave(+0.75,1),9,-1)," at +0.75 mode 1\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(+1.00,1),9,-1)," at +1.00 mode 1\n")) #write (FID,concat("f_scallop_wave 0.414214 ",str(f_scallop_wave(+1.25,1),9,-1)," at +1.25 mode 1\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+1.50,1),9,-1)," at +1.50 mode 1\n")) #write (FID,concat("f_scallop_wave 0.414214 ",str(f_scallop_wave(+1.75,1),9,-1)," at +1.75 mode 1\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(+2.00,1),9,-1)," at +2.00 mode 1\n")) #write (FID,"-\n") #write (FID,concat("F_scallop_wave -1.000000 ",str(F_scallop_wave(-2.00,0,0),9,-1)," at -2.00 function_interval\n")) #write (FID,concat("F_scallop_wave 0.414214 ",str(F_scallop_wave(-1.75,0,0),9,-1)," at -1.75 function_interval\n")) #write (FID,concat("F_scallop_wave 1.000000 ",str(F_scallop_wave(-1.50,0,0),9,-1)," at -1.50 function_interval\n")) #write (FID,concat("F_scallop_wave 0.414214 ",str(F_scallop_wave(-1.25,0,0),9,-1)," at -1.25 function_interval\n")) #write (FID,concat("F_scallop_wave -1.000000 ",str(F_scallop_wave(-1.00,0,0),9,-1)," at -1.00 function_interval\n")) #write (FID,concat("F_scallop_wave 0.414214 ",str(F_scallop_wave(-0.75,0,0),9,-1)," at -0.75 function_interval\n")) #write (FID,concat("F_scallop_wave 1.000000 ",str(F_scallop_wave(-0.50,0,0),9,-1)," at -0.50 function_interval\n")) #write (FID,concat("F_scallop_wave 0.414214 ",str(F_scallop_wave(-0.25,0,0),9,-1)," at -0.25 function_interval\n")) #write (FID,concat("F_scallop_wave -1.000000 ",str(F_scallop_wave(+0.00,0,0),9,-1)," at +0.00 function_interval\n")) #write (FID,concat("F_scallop_wave 0.414214 ",str(F_scallop_wave(+0.25,0,0),9,-1)," at +0.25 function_interval\n")) #write (FID,concat("F_scallop_wave 1.000000 ",str(F_scallop_wave(+0.50,0,0),9,-1)," at +0.50 function_interval\n")) #write (FID,concat("F_scallop_wave 0.414214 ",str(F_scallop_wave(+0.75,0,0),9,-1)," at +0.75 function_interval\n")) #write (FID,concat("F_scallop_wave -1.000000 ",str(F_scallop_wave(+1.00,0,0),9,-1)," at +1.00 function_interval\n")) #write (FID,concat("F_scallop_wave 0.414214 ",str(F_scallop_wave(+1.25,0,0),9,-1)," at +1.25 function_interval\n")) #write (FID,concat("F_scallop_wave 1.000000 ",str(F_scallop_wave(+1.50,0,0),9,-1)," at +1.50 function_interval\n")) #write (FID,concat("F_scallop_wave 0.414214 ",str(F_scallop_wave(+1.75,0,0),9,-1)," at +1.75 function_interval\n")) #write (FID,concat("F_scallop_wave -1.000000 ",str(F_scallop_wave(+2.00,0,0),9,-1)," at +2.00 function_interval\n")) #write (FID,"\n") //- #write (FID,"\n---\n") #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(-2.00,2),9,-1)," at -2.00 mode 2\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-1.75,2),9,-1)," at -1.75 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(-1.50,2),9,-1)," at -1.50 mode 2\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-1.25,2),9,-1)," at -1.25 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(-1.00,2),9,-1)," at -1.00 mode 2\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-0.75,2),9,-1)," at -0.75 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(-0.50,2),9,-1)," at -0.50 mode 2\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-0.25,2),9,-1)," at -0.25 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+0.00,2),9,-1)," at +0.00 mode 2\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+0.25,2),9,-1)," at +0.25 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+0.50,2),9,-1)," at +0.50 mode 2\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+0.75,2),9,-1)," at +0.75 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+1.00,2),9,-1)," at +1.00 mode 2\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+1.25,2),9,-1)," at +1.25 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+1.50,2),9,-1)," at +1.50 mode 2\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+1.75,2),9,-1)," at +1.75 mode 2\n")) #write (FID,concat("f_scallop_wave 0.000000 ",str(f_scallop_wave(+2.00,2),9,-1)," at +2.00 mode 2\n")) #write (FID,"\n") //- #write (FID,"\n---\n") #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(-2.00,3),9,-1)," at -2.00 mode 3\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-1.75,3),9,-1)," at -1.75 mode 3\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(-1.50,3),9,-1)," at -1.50 mode 3\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-1.25,3),9,-1)," at -1.25 mode 3\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(-1.00,3),9,-1)," at -1.00 mode 3\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-0.75,3),9,-1)," at -0.75 mode 3\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(-0.50,3),9,-1)," at -0.50 mode 3\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(-0.25,3),9,-1)," at -0.25 mode 3\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(+0.00,3),9,-1)," at +0.00 mode 3\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+0.25,3),9,-1)," at +0.25 mode 3\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(+0.50,3),9,-1)," at +0.50 mode 3\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+0.75,3),9,-1)," at +0.75 mode 3\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(+1.00,3),9,-1)," at +1.00 mode 3\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+1.25,3),9,-1)," at +1.25 mode 3\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(+1.50,3),9,-1)," at +1.50 mode 3\n")) #write (FID,concat("f_scallop_wave 1.000000 ",str(f_scallop_wave(+1.75,3),9,-1)," at +1.75 mode 3\n")) #write (FID,concat("f_scallop_wave -1.000000 ",str(f_scallop_wave(+2.00,3),9,-1)," at +2.00 mode 3\n")) #write (FID,"\n") // f_cubic_wave #ifdef (F_cubic_wave) #undef F_cubic_wave #end #declare F_cubic_wave = function { pattern { gradient <1,0,0> cubic_wave } } #write (FID,"\n---\n") #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(-2.00,0),9,-1)," at -2.00\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(-1.75,0),9,-1)," at -1.75\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(-1.50,0),9,-1)," at -1.50\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(-1.25,0),9,-1)," at -1.25\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(-1.00,0),9,-1)," at -1.00\n")) #write (FID,concat("f_cubic_wave 0.843750 ",str(f_cubic_wave(-0.75,0),9,-1)," at -0.75\n")) #write (FID,concat("f_cubic_wave 0.500000 ",str(f_cubic_wave(-0.50,0),9,-1)," at -0.50\n")) #write (FID,concat("f_cubic_wave 0.156250 ",str(f_cubic_wave(-0.25,0),9,-1)," at -0.25\n")) #write (FID,concat("f_cubic_wave 0.000000 ",str(f_cubic_wave(+0.00,0),9,-1)," at +0.00\n")) #write (FID,concat("f_cubic_wave 0.156250 ",str(f_cubic_wave(+0.25,0),9,-1)," at +0.25\n")) #write (FID,concat("f_cubic_wave 0.500000 ",str(f_cubic_wave(+0.50,0),9,-1)," at +0.50\n")) #write (FID,concat("f_cubic_wave 0.843750 ",str(f_cubic_wave(+0.75,0),9,-1)," at +0.75\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+1.00,0),9,-1)," at +1.00\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+1.25,0),9,-1)," at +1.25\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+1.50,0),9,-1)," at +1.50\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+1.75,0),9,-1)," at +1.75\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+2.00,0),9,-1)," at +2.00\n")) #write (FID,"-\n") #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(-2.00,0,0),9,-1)," at -2.00\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(-1.75,0,0),9,-1)," at -1.75\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(-1.50,0,0),9,-1)," at -1.50\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(-1.25,0,0),9,-1)," at -1.25\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(-1.00,0,0),9,-1)," at -1.00\n")) #write (FID,concat("F_cubic_wave 0.843750 ",str(F_cubic_wave(-0.75,0,0),9,-1)," at -0.75\n")) #write (FID,concat("F_cubic_wave 0.500000 ",str(F_cubic_wave(-0.50,0,0),9,-1)," at -0.50\n")) #write (FID,concat("F_cubic_wave 0.156250 ",str(F_cubic_wave(-0.25,0,0),9,-1)," at -0.25\n")) #write (FID,concat("F_cubic_wave 0.000000 ",str(F_cubic_wave(+0.00,0,0),9,-1)," at +0.00\n")) #write (FID,concat("F_cubic_wave 0.156250 ",str(F_cubic_wave(+0.25,0,0),9,-1)," at +0.25\n")) #write (FID,concat("F_cubic_wave 0.500000 ",str(F_cubic_wave(+0.50,0,0),9,-1)," at +0.50\n")) #write (FID,concat("F_cubic_wave 0.843750 ",str(F_cubic_wave(+0.75,0,0),9,-1)," at +0.75\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+1.00,0,0),9,-1)," at +1.00\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+1.25,0,0),9,-1)," at +1.25\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+1.50,0,0),9,-1)," at +1.50\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+1.75,0,0),9,-1)," at +1.75\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+2.00,0,0),9,-1)," at +2.00\n")) #write (FID,"\n") //- #ifdef (F_cubic_wave) #undef F_cubic_wave #end #declare F_cubic_wave = function { pattern { gradient <1,0,0> cubic_wave function_interval } } #write (FID,"\n---\n") #write (FID,concat("f_cubic_wave -1.000000 ",str(f_cubic_wave(-2.00,1),9,-1)," at -2.00 mode 1\n")) #write (FID,concat("f_cubic_wave -1.000000 ",str(f_cubic_wave(-1.75,1),9,-1)," at -1.75 mode 1\n")) #write (FID,concat("f_cubic_wave -1.000000 ",str(f_cubic_wave(-1.50,1),9,-1)," at -1.50 mode 1\n")) #write (FID,concat("f_cubic_wave -1.000000 ",str(f_cubic_wave(-1.25,1),9,-1)," at -1.25 mode 1\n")) #write (FID,concat("f_cubic_wave -1.000000 ",str(f_cubic_wave(-1.00,1),9,-1)," at -1.00 mode 1\n")) #write (FID,concat("f_cubic_wave -0.843750 ",str(f_cubic_wave(-0.75,1),9,-1)," at -0.75 mode 1\n")) #write (FID,concat("f_cubic_wave -0.500000 ",str(f_cubic_wave(-0.50,1),9,-1)," at -0.50 mode 1\n")) #write (FID,concat("f_cubic_wave -0.156250 ",str(f_cubic_wave(-0.25,1),9,-1)," at -0.25 mode 1\n")) #write (FID,concat("f_cubic_wave 0.000000 ",str(f_cubic_wave(+0.00,1),9,-1)," at +0.00 mode 1\n")) #write (FID,concat("f_cubic_wave 0.156250 ",str(f_cubic_wave(+0.25,1),9,-1)," at +0.25 mode 1\n")) #write (FID,concat("f_cubic_wave 0.500000 ",str(f_cubic_wave(+0.50,1),9,-1)," at +0.50 mode 1\n")) #write (FID,concat("f_cubic_wave 0.843750 ",str(f_cubic_wave(+0.75,1),9,-1)," at +0.75 mode 1\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+1.00,1),9,-1)," at +1.00 mode 1\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+1.25,1),9,-1)," at +1.25 mode 1\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+1.50,1),9,-1)," at +1.50 mode 1\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+1.75,1),9,-1)," at +1.75 mode 1\n")) #write (FID,concat("f_cubic_wave 1.000000 ",str(f_cubic_wave(+2.00,1),9,-1)," at +2.00 mode 1\n")) #write (FID,"-\n") #write (FID,concat("F_cubic_wave -1.000000 ",str(F_cubic_wave(-2.00,0,0),9,-1)," at -2.00 function_interval\n")) #write (FID,concat("F_cubic_wave -1.000000 ",str(F_cubic_wave(-1.75,0,0),9,-1)," at -1.75 function_interval\n")) #write (FID,concat("F_cubic_wave -1.000000 ",str(F_cubic_wave(-1.50,0,0),9,-1)," at -1.50 function_interval\n")) #write (FID,concat("F_cubic_wave -1.000000 ",str(F_cubic_wave(-1.25,0,0),9,-1)," at -1.25 function_interval\n")) #write (FID,concat("F_cubic_wave -1.000000 ",str(F_cubic_wave(-1.00,0,0),9,-1)," at -1.00 function_interval\n")) #write (FID,concat("F_cubic_wave -0.843750 ",str(F_cubic_wave(-0.75,0,0),9,-1)," at -0.75 function_interval\n")) #write (FID,concat("F_cubic_wave -0.500000 ",str(F_cubic_wave(-0.50,0,0),9,-1)," at -0.50 function_interval\n")) #write (FID,concat("F_cubic_wave -0.156250 ",str(F_cubic_wave(-0.25,0,0),9,-1)," at -0.25 function_interval\n")) #write (FID,concat("F_cubic_wave 0.000000 ",str(F_cubic_wave(+0.00,0,0),9,-1)," at +0.00 function_interval\n")) #write (FID,concat("F_cubic_wave 0.156250 ",str(F_cubic_wave(+0.25,0,0),9,-1)," at +0.25 function_interval\n")) #write (FID,concat("F_cubic_wave 0.500000 ",str(F_cubic_wave(+0.50,0,0),9,-1)," at +0.50 function_interval\n")) #write (FID,concat("F_cubic_wave 0.843750 ",str(F_cubic_wave(+0.75,0,0),9,-1)," at +0.75 function_interval\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+1.00,0,0),9,-1)," at +1.00 function_interval\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+1.25,0,0),9,-1)," at +1.25 function_interval\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+1.50,0,0),9,-1)," at +1.50 function_interval\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+1.75,0,0),9,-1)," at +1.75 function_interval\n")) #write (FID,concat("F_cubic_wave 1.000000 ",str(F_cubic_wave(+2.00,0,0),9,-1)," at +2.00 function_interval\n")) #write (FID,"\n") // f_wrap #write (FID,"\n---\n") #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(-4.0,2,3,0),9,-1)," -4.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(-3.5,2,3,0),9,-1)," -3.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(-3.0,2,3,0),9,-1)," -3.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(-2.5,2,3,0),9,-1)," -2.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(-2.0,2,3,0),9,-1)," -2.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(-1.5,2,3,0),9,-1)," -1.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(-1.0,2,3,0),9,-1)," -1.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(-0.5,2,3,0),9,-1)," -0.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(+0.0,2,3,0),9,-1)," +0.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+0.5,2,3,0),9,-1)," +0.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(+1.0,2,3,0),9,-1)," +1.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+1.5,2,3,0),9,-1)," +1.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(+2.0,2,3,0),9,-1)," +2.0 -> 2,3 <---(lo)\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+2.5,2,3,0),9,-1)," +2.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(+3.0,2,3,0),9,-1)," +3.0 -> 2,3 <---(hi)\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+3.5,2,3,0),9,-1)," +3.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(+4.0,2,3,0),9,-1)," +4.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+4.5,2,3,0),9,-1)," +4.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(+5.0,2,3,0),9,-1)," +5.0 -> 2,3\n")) #write (FID,"-\n") #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(-4.0,2,3,1),9,-1)," -4.0 -> 2,3 This set mode 1\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(-3.5,2,3,1),9,-1)," -3.5 -> 2,3\n")) #write (FID,concat("f_wrap 3.000000 ",str(f_wrap(-3.0,2,3,1),9,-1)," -3.0 -> 2,3 (*)\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(-2.5,2,3,1),9,-1)," -2.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(-2.0,2,3,1),9,-1)," -2.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(-1.5,2,3,1),9,-1)," -1.5 -> 2,3\n")) #write (FID,concat("f_wrap 3.000000 ",str(f_wrap(-1.0,2,3,1),9,-1)," -1.0 -> 2,3 (*)\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(-0.5,2,3,1),9,-1)," -0.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(+0.0,2,3,1),9,-1)," +0.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+0.5,2,3,1),9,-1)," +0.5 -> 2,3\n")) #write (FID,concat("f_wrap 3.000000 ",str(f_wrap(+1.0,2,3,1),9,-1)," +1.0 -> 2,3 (*)\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+1.5,2,3,1),9,-1)," +1.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(+2.0,2,3,1),9,-1)," +2.0 -> 2,3 <---(lo)\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+2.5,2,3,1),9,-1)," +2.5 -> 2,3\n")) #write (FID,concat("f_wrap 3.000000 ",str(f_wrap(+3.0,2,3,1),9,-1)," +3.0 -> 2,3 (*) <---(hi)\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+3.5,2,3,1),9,-1)," +3.5 -> 2,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(+4.0,2,3,1),9,-1)," +4.0 -> 2,3\n")) #write (FID,concat("f_wrap 2.500000 ",str(f_wrap(+4.5,2,3,1),9,-1)," +4.5 -> 2,3\n")) #write (FID,concat("f_wrap 3.000000 ",str(f_wrap(+5.0,2,3,1),9,-1)," +5.0 -> 2,3 (*)\n")) #write (FID,"-\n") #write (FID,concat("f_wrap 3.000000 ",str(f_wrap(-5.0,1,3,1),9,-1)," -5.0 -> 1,3 (*)\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(-4.0,1,3,1),9,-1)," -4.0 -> 1,3\n")) #write (FID,concat("f_wrap 1.000000 ",str(f_wrap(-3.0,1,3,1),9,-1)," -3.0 -> 1,3\n")) #write (FID,concat("f_wrap 2.000000 ",str(f_wrap(-2.0,1,3,1),9,-1)," -2.0 -> 1,3\n")) #write (FID,concat("f_wrap 3.000000 ",str(f_wrap(-1.0,1,3,1),9,-1)," -1.0 -> 1,3 (*)\n")) #write (FID,concat("f_wrap 1.000000 ",str(f_wrap(+1.0,1,3,1),9,-1)," +1.0 -> 1,3\n")) #write (FID,concat("f_wrap 3.000000 ",str(f_wrap(+3.0,1,3,1),9,-1)," +3.0 -> 1,3 (*)\n")) #write (FID,concat("f_wrap 1.000000 ",str(f_wrap(+5.0,1,3,1),9,-1)," +5.0 -> 1,3\n")) #write (FID,concat("f_wrap 3.000000 ",str(f_wrap(+7.0,1,3,1),9,-1)," +7.0 -> 1,3 (*)\n")) #write (FID,"\n") // f_hypot, f_hypot_raw #ifdef (F_hypot) #undef F_hypot #end #declare F_hypot = function (x,y) { sqrt(x*x + y*y) } #write (FID,"\n---\n") #write (FID,concat("f_hypot 2.0000000000000000 ",str(f_hypot(sqrt(2),sqrt(2)),19,16)," (f_hypot std::hypot) \n")) #write (FID,concat("f_hypot_raw 2.0000000000000000 ",str(f_hypot_raw(sqrt(2),sqrt(2)),19,16)," (f_hypot_raw) \n")) #write (FID,concat("F_hypot 2.0000000000000000 ",str(F_hypot(sqrt(2),sqrt(2)),19,16)," (F_hypot as SDL) \n")) #write (FID,"\n") // f_sign, f_sign0 #write (FID,"\n---\n") #write (FID,concat("f_sign 1.000000 ",str(f_sign(0),9,-1)," 0\n")) #write (FID,concat("f_sign 1.000000 ",str(f_sign(+1e-35),9,-1)," +1e-35\n")) #write (FID,concat("f_sign -1.000000 ",str(f_sign(-1e-35),9,-1)," -1e-35\n")) #write (FID,"\n-\n") #write (FID,concat("f_sign0 1.000000 ",str(f_sign0(+1e-35,0,0),9,-1)," +1e-35 \n")) #write (FID,concat("f_sign0 -1.000000 ",str(f_sign0(-1e-35,0,0),9,-1)," -1e-35\n")) #write (FID,concat("f_sign0 0.000000 ",str(f_sign0(0,0,0),9,-1)," 0 return 0\n")) #write (FID,concat("f_sign0 1.000000 ",str(f_sign0(0,+1,0),9,-1)," 0 return 1\n")) #write (FID,concat("f_sign0 -1.000000 ",str(f_sign0(0,-1,0),9,-1)," 0 return -1\n")) #write (FID,"\n-\n") #write (FID,concat("f_sign0 0.000000 ",str(f_sign0(+1e-35,0,-1e-35),9,-1)," +1e-35 offset -1e-35\n")) #write (FID,concat("f_sign0 0.000000 ",str(f_sign0(-1e-35,0,+1e-35),9,-1)," -1e-35 offset +1e-35\n")) #write (FID,concat("f_sign0 -1.000000 ",str(f_sign0(0.0,0,-1e-35),9,-1)," 0.0 offset -1e-35\n")) #write (FID,concat("f_sign0 1.000000 ",str(f_sign0(0.0,0,+1e-35),9,-1)," 0.0 offset +1e-35\n")) #write (FID,"\n") // f_enc3x_f21 and f_dec3x_f21 #write (FID,"\n---\n") #ifdef (Var3xf21) #undef Var3xf21 #end #declare Var3xf21 = f_enc3x_f21(-99.9999910,99.9999910,0.0,4); #write (FID,concat("f_dec3x_f21 -100.00000 ",str(f_dec3x_f21(Var3xf21,4,0),9,-1)," -99.9999910\n")) #write (FID,concat("f_dec3x_f21 100.00000 ",str(f_dec3x_f21(Var3xf21,4,1),9,-1)," 99.9999910\n")) #write (FID,concat("f_dec3x_f21 0.00000 ",str(f_dec3x_f21(Var3xf21,4,2),9,-1)," 0.0\n")) #write (FID,"\n-\n") #ifdef (Var3xf21) #undef Var3xf21 #end #declare Var3xf21 = f_enc3x_f21(-19.3530720,0.3833065,23.7746838,4); #write (FID,concat("f_dec3x_f21 -19.3531000 ",str(f_dec3x_f21(Var3xf21,4,0),9,-1)," -19.3530720\n")) #write (FID,concat("f_dec3x_f21 0.38330000 ",str(f_dec3x_f21(Var3xf21,4,1),9,-1)," 0.3833065\n")) #write (FID,concat("f_dec3x_f21 23.7747000 ",str(f_dec3x_f21(Var3xf21,4,2),9,-1)," 23.7746838\n")) #write (FID,"\n") // f_enc2x_f32 and f_dec2x_f32 #write (FID,"\n---\n") #ifdef (Var2xf32) #undef Var2xf32 #end #declare Var2xf32 = f_enc2x_f32(-19.229435080,12.131785782); #write (FID,concat("f_dec2x_f32 -19.229435 ",str(f_dec2x_f32(Var2xf32,0),10,6)," -19.229435080\n")) #write (FID,concat("f_dec2x_f32 +12.131785 ",str(f_dec2x_f32(Var2xf32,1),10,6)," 12.131785782\n")) #write (FID,"\n-\n") #ifdef (Var2xf32) #undef Var2xf32 #end #declare Var2xf32 = f_enc2x_f32(-24.478796893,7.065430298); #write (FID,concat("f_dec2x_f32 -24.478796 ",str(f_dec2x_f32(Var2xf32,0),10,6)," -24.478796893\n")) #write (FID,concat("f_dec2x_f32 +7.0654302 ",str(f_dec2x_f32(Var2xf32,1),10,7)," 7.065430298\n")) #write (FID,"\n") // f_hessian_dist #write (FID,"\n---\n") #ifdef (FnHessianDist) #undef FnHessianDist #end #declare FnHessianDist = function (x,y,z,_theta,_offset) { z*cos(radians(_theta)) + x*sin(radians(_theta)) - _offset } #write (FID,concat("f_hessian_dist 0.00000 ",str(f_hessian_dist(-1,+1,+1,45,0),9,-1)," hessian\n")) #write (FID,concat("f_hessian_dist +1.00000 ",str(f_hessian_dist(+1,+1,+0,90,0),9,-1)," hessian\n")) #write (FID,concat("f_hessian_dist -1.00000 ",str(f_hessian_dist(-1,+1,+0,90,0),9,-1)," hessian\n")) #write (FID,concat("FnHessianDist 0.00000 ",str(FnHessianDist( -1,+1,+1,45,0),9,-1)," Hessian\n")) #write (FID,concat("FnHessianDist +1.00000 ",str(FnHessianDist( +1,+1,+0,90,0),9,-1)," Hessian\n")) #write (FID,concat("FnHessianDist -1.00000 ",str(FnHessianDist( -1,+1,+0,90,0),9,-1)," Hessian\n")) #write (FID,"\n") // f_upoly #write (FID,"\n---\n") #write (FID,concat("f_upoly 17.00000 ",str(f_upoly(1,16,1.0, 1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1 ),9,-1)," \n")) #write (FID,concat("f_upoly 29.00000 ",str(f_upoly(2,3,1.0, 2,2,2,2,0,0,0,0, 0,0,0,0,0,0,0,0 ),9,-1)," \n")) #write (FID,concat("f_upoly 61.00000 ",str(f_upoly(2,4,1.0, 2,2,2,2,0,0,0,0, 0,0,0,0,0,0,0,0 ),9,-1)," \n")) #write (FID,"\n") // f_rotate2d #write (FID,"\n---\n") #ifdef (Var2xf32) #undef Var2xf32 #end #declare Var2xf32 = f_rotate2d(1,0,0,1,0.0); #write (FID,concat("f_rotate2d 1.000000 ",str(f_dec2x_f32(Var2xf32,0),10,6)," 0.0 rotate\n")) #write (FID,concat("f_rotate2d 0.000000 ",str(f_dec2x_f32(Var2xf32,1),10,6)," (0.0)\n")) #write (FID,"\n-\n") #ifdef (Var2xf32) #undef Var2xf32 #end #declare Var2xf32 = f_rotate2d(1,0,0,1,-45.0); #write (FID,concat("f_rotate2d +0.707107 ",str(f_dec2x_f32(Var2xf32,0),10,6)," -45 rotate\n")) #write (FID,concat("f_rotate2d -0.707107 ",str(f_dec2x_f32(Var2xf32,1),10,6)," (-45)\n")) #write (FID,"\n-\n") #ifdef (Var2xf32) #undef Var2xf32 #end #declare Var2xf32 = f_rotate2d(1,0,0,1,+45.0); #write (FID,concat("f_rotate2d +0.707107 ",str(f_dec2x_f32(Var2xf32,0),10,6)," +45 rotate\n")) #write (FID,concat("f_rotate2d +0.707107 ",str(f_dec2x_f32(Var2xf32,1),10,6)," (+45)\n")) #write (FID,"\n") // f_range2range, F_adj_range2 #write (FID,"\n---\n") #write (FID,concat("f_range2range 0.000000 ",str(f_range2range(+0.5,0.0,1.0,-1.0,1.0),9,6)," (+0.5 -> 0.0) \n")) #write (FID,concat("F_adj_range2 0.000000 ",str(F_adj_range2( +0.5,0.0,1.0,-1.0,1.0),9,6)," (+0.5 -> 0.0) \n")) #write (FID,concat("f_range2range -1.000000 ",str(f_range2range(+0.0,0.0,1.0,-1.0,1.0),9,6)," (+0.0 -> -1.0) \n")) #write (FID,concat("F_adj_range2 -1.000000 ",str(F_adj_range2( +0.0,0.0,1.0,-1.0,1.0),9,6)," (+0.0 -> -1.0) \n")) #write (FID,concat("f_range2range +1.000000 ",str(f_range2range(+1.0,0.0,1.0,-1.0,1.0),9,6)," (+1.0 -> +1.0) \n")) #write (FID,concat("F_adj_range2 +1.000000 ",str(F_adj_range2( +1.0,0.0,1.0,-1.0,1.0),9,6)," (+1.0 -> +1.0) \n")) #write (FID,concat("f_range2range -2.000000 ",str(f_range2range(-0.5,0.0,1.0,-1.0,1.0),9,6)," (-0.5 -> -2.0) \n")) #write (FID,concat("F_adj_range2 -2.000000 ",str(F_adj_range2( -0.5,0.0,1.0,-1.0,1.0),9,6)," (-0.5 -> -2.0) \n")) #write (FID,concat("f_range2range +2.000000 ",str(f_range2range(+1.5,0.0,1.0,-1.0,1.0),9,6)," (+1.5 -> +2.0) \n")) #write (FID,concat("F_adj_range2 +2.000000 ",str(F_adj_range2( +1.5,0.0,1.0,-1.0,1.0),9,6)," (+1.5 -> +2.0) \n")) #write (FID,"\n") // f_f_enc_nbit3c, f_dec_nbit3c #write (FID,"\n---\n") #ifdef (VarValue) #undef VarValue #end #declare VarValue = 0.1234567890123456; #write (FID,concat("f_enc_nbit3c 0.1234558471117947 ",str(f_enc_nbit3c(17,0,0,VarValue),19,16)," 17 0 (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.0000009418933648 ",str(f_enc_nbit3c(17,1,0,VarValue),19,16)," 17 1 (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.0000000000071861 ",str(f_enc_nbit3c(17,2,0,VarValue),19,16)," 17 2 (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.0000000000000001 ",str(f_enc_nbit3c(17,3,0,VarValue),19,16)," 17 3 (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.1234558471117947 ",str(f_enc_nbit3c(17,0,1,VarValue),19,16)," 17 0n (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.1234558471109195 ",str(f_enc_nbit3c(17,1,1,VarValue),19,16)," 17 1n (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.1234558471109195 ",str(f_enc_nbit3c(17,2,1,VarValue),19,16)," 17 2n (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.0000000000000001 ",str(f_enc_nbit3c(17,3,1,VarValue),19,16)," 17 3n (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.1234266481947156 ",str(f_enc_nbit3c(12,0,0,VarValue),19,16)," 12 0 (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.0000301334590319 ",str(f_enc_nbit3c(12,1,0,VarValue),19,16)," 12 1 (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.0000000073568015 ",str(f_enc_nbit3c(12,2,0,VarValue),19,16)," 12 2 (0.123456789012345)\n")) #write (FID,concat("f_enc_nbit3c 0.0000000000017965 ",str(f_enc_nbit3c(12,3,0,VarValue),19,16)," 12 3 (0.123456789012345)\n")) #write (FID,"\n-\n") #ifdef (Color) #undef Color #end #declare Color = ; #write (FID,concat("f_dec_nbit3c 0.1234567890123455 ",str(f_dec_nbit3c(17,0,Color.red,Color.green,Color.blue),19,16)," 17 -n (0.123456789012345)\n")) #write (FID,"\n-\n") #ifdef (Color) #undef Color #end #declare Color = ; #write (FID,concat("f_dec_nbit3c 0.1234567890123455 ",str(f_dec_nbit3c(17,1,Color.red,Color.green,Color.blue),19,16)," 17 +n (0.123456789012345)\n")) #write (FID,"\n") #fclose FID #error "\n\n===Self testing. Stop before render.===\n" #end // End self testing #version Functions_Inc_Temp; #end//functions.inc