

The Other Walker wrote:
> What do you want to do with the function once you've got it, that you need to
> have it in function form?
That's a good question. My main answer would be, just to see if could be done.
And to try and betterunderstand the real power of function use in SDL.
So, just to put this here  I looked for the source code for implementing
arrays, and couldn't find where it is (yet).
I would think it might be easy to store the image_map data in a 2D array, that
maybe has an identifier name that is Array_filename_ext
At least that way the array could be created using the compiled source code
(fast).
Now, using eval_pigment to get that data into an array is going to be a pretty
roundabout way to get the color data, so I think what you can do is this:
You don't need any objects in the scene, no trace, no eval_pigment.
#declare Fn_Image = function {pigment{image_map}}
And here is where functions get a little bit wonky.
The above function takes a fullcolor pigment pattern as an input.
In order to spit out a scalar value, which is the only allowable way to execute
a function, you need to evaluate only a single color channel at a time.
#declare Image_red = function {Fn_Image (x, y, z).red}
#declare Image_grn = function {Fn_Image (x, y, z).green}
#declare Image_blu = function {Fn_Image (x, y, z).blue}
Now, as you can imagine, whether we're interested in r, g, & b, or x, y, and z 
this can start propagating intermediate functions very rapidly.
One day we might have proper vector functions  but this is just the way it is
right now.
Functions kinda seem magical and complicated at first, but they are easily
learned.
I'd start off by just trying to graph your usual high school functions.
lines, sine waves, parabolas, cubics, etc.
So let's say we do a line.
#declare Line = function (Number) {Number}
Then when we want to evaluate that function, we do:
#for (X, 0, 10)
#local Y = function {Line (X)};
#end
What are the things to notice here:
1. we define "line" as a function, that takes "Number" as its argument (input),
and its output is what is in parentheses  which right now is just "Number" 
the same as the input.
2. in our loop, we define Y as a function of X. What function of X? "Line"
So in goes X, Out pops the value of X, which gets assigned to Y, and we get a
45degree angle line.
Plot some spheres and cylinders or something.
It gets more interesting when you shove the function into a pigment pattern,
because you're using the function as an interface between the coordinates in all
of POVspace and some color value.
So, let's take a pattern like onion.
#declare Onion = function {mod(sqrt(x*x+y*y+z*z), 1.0)}
#declare Rectangle = union {
triangle {<10, 0, 5>, <10, 0, 5>, <10, 0, 5>}
triangle {<10, 0, 5>, <10, 0, 5>, <10, 0, 5> }
}
object {Rectangle pigment {Onion}}
If you're going to want to use infinite patterns, you're going to have to get
nice and cozy with the modulo operator. It basically just gives the fractional
component of a division, ensuring that your function output is always between 0
and 1.
mod(A,B) Value of A modulo B. Returns the remainder after the integer division
of A/B. Formula is mod=((A/B)int(A/B))*B.
http://www.povray.org/documentation/view/3.6.1/228/
So what is sqrt(x*x+y*y+z*z)? It's the 3D distance from the origin to any point
in POVSpace. All the spheres of every radius, all nested together. So as you
go from 0 to 1, your values go from 0 to 1, and then when you go over 1 up to 2,
the fractional components are still 0 to 1. And on and on forever. Onion.
In an isosurface, you're only going to be looking at the surface where the
function equals the threshold value. So, every integer step, where the
fractional part is 0.
0/1 = 0;
1/1 = 1 remainder 0
2/1 = 2 remainder 0
etc.
isosurface {
function {Onion (x, y, z)}
open
threshold 0
max_gradient 1.5
accuracy 0.001
contained_by {box {<4, 4, 0>, <4, 4, 4>}}
pigment {rgb 0.5}
}
The thing to notice here is that the input for the function is the x, y, and z
of POVspace, not the x, y, and z unit vector quantities. The function virtual
machine interprets these identifiers differently than in the rest of SDL.
This is important when you're playing with functions in loops, because if you
define your function with x, y, and z, you can't use those as loop variables.
If you use X, Y and Z, then those are placeholders, like with a macro.
When you pass x, y, and z into the function with a pigment or isosurface, it
works, and when you pass a loop X, Y, or Z into the function, it works that way
too.
Basically you're just using x, y, and z to calculate a single number  think of
it as a grayscale value in any of the patterns.
Once you get the hang of it, you can add a color map, and then you can use 3
different functions for r, g, and b values (and filter and transmit) and average
them together to get a full color pigment pattern.
Post a reply to this message

