Previous:Are POV-Ray Macros a Function or a Macro? Main Index Next:Returning Values Via Parameters

#### Returning a Value Like a Function

POV-Ray macros have a variety of uses. Like most macros, they provide a parameterized way to insert arbitrary code into a scene file. However most POV-Ray macros will be used like functions or procedures in a traditional programming language. This is especially true because the POV-Ray language has no user-defined functions or procedures. Macros are designed to fill all of these roles.

When the body of a macro consists of statements that create an entire item such as an object, texture, etc. then the macro acts like a function which returns a single value. The `Make_Frame` macro example in the section "Invoking Macros" above is such a macro which returns a value that is an object. Here are some examples of how you might invoke it.

     union {  //make a union of two objects

       object{ Make_Frame(8,10,7,9,1) translate  20*x}

       object{ Make_Frame(8,10,7,9,1) translate -20*x}

     }

     #declare BigFrame = object{ Make_Frame(8,10,7,9,1)}

     #declare SmallFrame = object{ Make_Frame(5,4,4,3,0.5)}

Because no type checking is performed on parameters and because the expression syntax for floats, vectors, and colors is identical, you can create clever macros which work on all three. See the sample scene `MACRO3.POV` which includes this macro to interpolate values.

    // Define the macro.  Parameters are:

    //   T:  Middle value of time

    //   T1: Initial time

    //   T2: Final time

    //   P1: Initial position (may be float, vector or color)

    //   P2: Final position (may be float, vector or color)

    //   Result is a value between P1 and P2 in the same proportion

    //    as T is between T1 and T2.

    #macro Interpolate(T,T1,T2,P1,P2)

       (P1+(T1+T/(T2-T1))*(P2-P1))

    #end

You might invoke it with `P1` and `P2` as floats, vectors, or colors as follows.

      sphere{

        Interpolate(I,0,15,<2,3,4>,<9,8,7>),  //center location is vector

        Interpolate(I,0,15,3.0,5.5)           //radius is float

        pigment{

          color Interpolate(I,0,15,rgb<1,1,0>,rgb<0,1,1>)

        }

      }

As the float value `I` varies from 0 to 15, the location, radius, and color of the sphere vary accordingly.

There is a danger in using macros as functions. In a traditional programming language function, the result to be returned is actually assigned to a temporary variable and the invoking code treats it as a variable of a given type. However macro substitution may result in invalid or undesired syntax. Note the definition of the macro `Interpolate` above has an outermost set of parentheses. If those parentheses are omitted, it will not matter in the examples above, but what if you do this...

     #declare Value = Interpolate(I,0,15,3.0,5.5)*15;

The end result is as if you had done...

     #declare Value = P1+(T1+T/(T2-T1))*(P2-P1) * 15;

which is syntactically legal but not mathematically correct because the `P1` term is not multiplied. The parentheses in the original example solves this problem. The end result is as if you had done...

     #declare Value = (P1+(T1+T/(T2-T1))*(P2-P1)) * 15;

which is correct.

Previous:Are POV-Ray Macros a Function or a Macro? Main Index Next:Returning Values Via Parameters