6.1.9  Spline Identifiers

Splines give you a way to define 'pathways' through your scenes. You specify a series of points, and POV-Ray interpolates to make a curve connecting them. Every point along the spline has a numerical value. A good example of a spline is the path of a moving object: the spline itself would be the path traced out by the object and the 'parameter' would be time; as time changes the object's position moves along the spline.
Therefore, given a time reference you could use this spline to find the position of the object. In fact, splines are very well suited to animation.

The syntax is:

SPLINE_DECLARATION:
  #declare IDENTIFIER =
    spline {
      [SPLINE_IDENTIFIER] |
      [SPLINE_TYPE] |
      [Val_1, <Point_1>[,]
       Val_2, <Point_2>[,]
       ...
       Val_n, <Point_n>]
    }

SPLINE_TYPE:
  linear_spline | quadratic_spline | cubic_spline | natural_spline

SPLINE_USAGE:
  MySpline(Val) | MySpline(Val, SPLINE_TYPE)

The first item gives the type of interpolation.
In a linear_spline, straight lines connect each point.
In a quadratic_spline, a smooth curve defined by a second-order polynomial connects each point.
In cubic_spline and natural_spline, a smooth curve defined by a third-order polynomial connects each point.
The default is linear_spline.

Following this are a number of float values each followed by a position vector, all separated by commas. Val_1, Val_2, etc, are the value of the spline parameter at each specific point. The points need not be in order of their parameter values. If two points have the same parameter value, the second point will replace the first. Beyond the range of the lowest and highest parameter values, the spline position is fixed at the endpoints.

Note: Because of the way cubic_splines are defined: the first and last points are tangents rather than points on the spline, cubic_spline interpolation is only valid between the second and next-to-last points. For all other spline types, interpolation is valid from the first point to the last point. For t-values outside the valid range, POV-Ray returns the value of the nearest valid point.

To use a spline, you place the spline identifier followed by the parameter (in parentheses) wherever you would normally put a vector, similar to a macro. Splines behave mostly like three-dimensional vectors.
Here is an example:

camera { location <0,2,-2> look_at 0 }
light_source { <-5,30,-10> 1 }
#declare MySpline =
  spline {
    cubic_spline
    -.25, <0,0,-1>
    0.00, <1,0,0>
    0.25, <0,0,1>
    0.50, <-1,0,0>
    0.75, <0,0,-1>
    1.00, <1,0,0>
    1.25, <0,0,1>
  }

#declare ctr = 0;
#while (ctr < 1)
  sphere {
    MySpline(ctr),.25
    pigment { rgb <1-ctr,ctr,0> }
  }
  #declare ctr = ctr + 0.01;
#end

You can also have POV-Ray evaluate a spline as if it were a different type of spline by specifying the type of spline after the value to interpolate at, for example:

sphere{ <2,0,2>, .25 pigment{rgb MySpline(clock, linear_spline)}}

Splines are 'intelligent' when it comes to returning vectors. The vector with the most components in the spline determines the size of the returned vector. This allows vectors from two to five components to be returned by splines.

Also, function splines take the vector size into account. That is, a function containing a spline with five components will also return a five component vector (aka a color), a function containing a spline with two components will only return a two component vector and so on.

6.1.9.1  Splines and Macros

You can pass functions to macros, how to do this is best explained by an example

  #macro Foo( Bar, Val )
    #declare Y = Bar(Val).y;
  #end

  #declare myspline = spline { 
      1, <4,5> 
      3, <5,5> 
      5, <6,5>
  }

  Foo(myspline, 2)

  #debug str(Y,5,5)
  #debug "\n"