Creating an Animated POV-Ray Image
================================

The POV Scene Description File

The scene description file must be written with animation commands built-in to the translate vectors of the scene description file so that as POV-Ray renders the frames of the animation, the animated object appears to move.

The key to creating POV animations is the built-in variable "clock".

Here is a simple animation and the scene file from which it is rendered...

[vect_demo.gif]
  #include "colors.inc"    // The include files contain
  #include "shapes.inc"    // pre-defined scene elements
  #include "stones.inc"

  light_source { <2, 4, -3> color White}
  light_source { <-2, 12, 23> color White}

  camera {
    location <0, 2, -5>
    look_at  < 0, 0, 0>
	angle 50
  }

	sphere { <0,0,0> , 1 
	   pigment { color Blue } 
	   translate <clock,0,0>
	}

	plane { y*1 ,-1 
	   pigment { color Red } 
	}

The sphere has a translation that looks like "translate <clock,0,0>". This uses the clock value to determine the location of the sphere on the x-axis. Once translation has been setup, the file is rendered something like this...

xpov +h120 +w160 +i anim_demo.pov +kff20 +oxtest +a

This is the absolute shortest form of an animation I know of. We need to examine the various switches on this command line...

xpov This is the call to the POV-Ray renderer on my Linux machine.
+h120 Set the height of the frame images to 120 pixels.
+w160 Set the width of the frame images to 160 pixels.
+i anim_demo.pov Provide the name of the scene file we are animating.
+kff20 Sets the final frame value to 20 neatly dividing the default clock value (0.0 - 1.0) into twenty values.
+oxtest Provide a name for the output frame images: xtest01.tga, xtest02.tga, xtest03.tga,...,xtest20.tga
+a Use anti-aliasing while rendering images.

When the rendering is done you will have...

xtest01.tga  xtest06.tga  xtest11.tga  xtest16.tga
xtest02.tga  xtest07.tga  xtest12.tga  xtest17.tga
xtest03.tga  xtest08.tga  xtest13.tga  xtest18.tga
xtest04.tga  xtest09.tga  xtest14.tga  xtest19.tga
xtest05.tga  xtest10.tga  xtest15.tga  xtest20.tga

Converting TGA Files to GIF Format

TGA files cannot be used in an animated GIF so we need to convert them. By far the quickest way to do this is by using the ImageMagick tools. In particular I use mogrify (one of the utilities included with ImageMagick) to convert from TGA to GIF format.

Here is the command I use...

mogrify -format gif x*.tga

then you will have...

xtest01.gif  xtest06.gif  xtest11.gif  xtest16.gif
xtest01.tga  xtest06.tga  xtest11.tga  xtest16.tga
xtest02.gif  xtest07.gif  xtest12.gif  xtest17.gif
xtest02.tga  xtest07.tga  xtest12.tga  xtest17.tga
xtest03.gif  xtest08.gif  xtest13.gif  xtest18.gif
xtest03.tga  xtest08.tga  xtest13.tga  xtest18.tga
xtest04.gif  xtest09.gif  xtest14.gif  xtest19.gif
xtest04.tga  xtest09.tga  xtest14.tga  xtest19.tga
xtest05.gif  xtest10.gif  xtest15.gif  xtest20.gif
xtest05.tga  xtest10.tga  xtest15.tga  xtest20.tga

You can see that a GIF file has been created for each of the original TGA files. We now combine the GIF files into a single animated GIF. For this we need yet another tool...

Combining Separate GIF Images into a Single Animated Graphic

I have the "whirlgif" program stored under my own directory so the command line looks like this...

~/whirlgif/whirlgif -o anim_demo.gif x*.gif

This command is simple. It calls the "whirlgif" program and uses the output file flag "-0" to specify the new animated GIF as "anim_demo.gif". It then directs the whirlgif program to collect the "x*.gif" files to make the animation. Since the "x*.gif" are numbered, "whirlgif" reads the files in numeric order as it compiles the animation.

Viewing the Animation

Viewing the resulting animation is fairly simple with "xanim".

xanim mouse_anim.gif

Multi-Stage Animations

Sometimes you may want to construct animations by creating separate series of frames and combining them all at a later time. Here is a command I have used to do exactly that...

xpov +h120 +w160 +itest.pov +ki0.0 +kf2.0 +kfi1 +kff20 +ox.tga +a

Let's look at this in a bit more detail...

xpov This is the call to the POV-Ray renderer on my Linux machine.
+h120 Set the height of the frame images to 120 pixels.
+w160 Set the width of the frame images to 160 pixels.
+i test.pov Provide the name of the scene file we are animating.
+ki0.0 Set the initial clock value to 0.0.
+kf2.0 Set the final clock value to 0.0.
(This is necessary otherwise the clock runs only from 0.0 to 1.0 and we need the values over 1.0 in the mouse demonstration loop.)
+kfi0 Set the initial frame number to 0.
+kff20 Set the final frame number to 20.
+a Use anti-aliasing while rendering images.

Most of these we saw in the earlier demonstration. The ones that we use in creating multi-stage animations are...

+ki0.0 Set the initial clock value to 0.0.
+kf2.0 Set the final clock value to 0.0.
(This is necessary otherwise the clock runs only from 0.0 to 1.0 and we need the values over 1.0 in the mouse demonstration loop.)
+kfi0 Set the initial frame number to 0.
+kff20 Set the final frame number to 20.

The "clock" Values

By default the POV-Ray clock value runs from 0.0 to 1.0. Look at the translation in the example we've already seen...

translate

[vect_demo.gif]
  #include "colors.inc"    // The include files contain
  #include "shapes.inc"    // pre-defined scene elements
  #include "stones.inc"

  light_source { <2, 4, -3> color White}
  light_source { <-2, 12, 23> color White}

  //background { color White }

  camera {
    location <0, 3, -8>
    look_at  < 0, 0, 0>
	angle 50
  }

sphere { <0,0,-2> , 1
	pigment { color Yellow }
	translate <-clock,0,0>
}

sphere { <0,0,0> , 1
	pigment { color Blue }
	translate <clock,0,0>
}

sphere { <1,0,2> , 1
	pigment { color Yellow }
	translate <-clock,0,0>
}

sphere { <-1,0,4> , 1
	pigment { color Blue }
	translate <clock,0,0>
}

plane { y*1 ,-1
	pigment { color Red }
}

The interesting points in this demonstration are the relationships between the declared location of the spheres and the translation parameters.

Lets look at the object definition for the blue sphere that is furthest back in the scene...

sphere { <-1,0,4> , 1
	pigment { color Blue }
	translate <clock,0,0>
}

First, notice that the sphere's location at <-1,0,4> places it one unit to the left of the origin on the X axis. Then the translate <clock,0,0> changes it's location in relationship to it's original location specification.

This means that as the clock value varies (remember, by default it changes from 0.0 to 1.0) it is divided into twenty parts...

(0.0, 0.05, 0.10, 0.15, . . . , 0.95, 1.00)

if we specify +kff20 on the command line.

Since the demonstration animation shows four spheres, each at a different origination point and each travelling in a different direction we wonder how we can possibly cause a single sphere to travel the same vectors.

There are a few different ways to do this. One employs the #if construct and the other uses multi-stage animations. The multi-stage approach may be the easiest to set up so lets look at it first.

Multi-Stage Animations

We'll use a single sphere and change the translate vector and render it four times while outputting frames 1-10, 11-20, 21-30, and 31-40.

For each successive rendering, we change the sphere's origin, color (for the purposes of this demonstration only) and translation vector as shown in the table below...

[vect_demo.gif]
sphere { <origin> , 1
	pigment { color color }
	translate <translate>
}
origintranslatecolorcommand
<0,0,0><clock,0,0>Yellow+kfi1 +kff10
<1,0,0><-clock,0,0>Blue+kfi11 +kff20
<0,0,0><-clock,0,0>Green+kfi21 +kff30
<-1,0,0><clock,0,0>Magenta+kfi31 +kff40

The command lines will then look like these...

xpov +h90 +w120 +i anim_demo.pov +kfi1 +kff10 +oxtest +a
xpov +h90 +w120 +i anim_demo.pov +kfi11 +kff20 +oxtest +a
xpov +h90 +w120 +i anim_demo.pov +kfi21 +kff30 +oxtest +a
xpov +h90 +w120 +i anim_demo.pov +kfi31 +kff40 +oxtest +a

The resulting image frames are all kept in the same directory and we use the mogrify and whirlgif commands as shown previously to output our animation.

Animations Using Conditional Statements

POV-Ray 3.0 provides an additional way that allows us to control animations. It is through the use of the if...else construct.

[vect_demo.gif]
#if (1*clock <= 1)
  sphere { <1*clock,0,0>, 1
	 pigment { color Red }
  }
#else
  sphere { <1,1*clock,0>, 1
	 pigment { color Blue }
  }
#end

Here we see the direction of motion change based on the clock value. By default the clock value runs from 0.0 to 1.0 but by specifying differently on the command line, we can control the clock variable and then make decisions based it's value. A command line that directs POV-Ray to use values beyond thedefault looks like this...

xpov +h90 +w120 +i anim_demo.pov +ki0.0 +kf2.0 +kfi1 +kff20 +oxtest +a

As you see in this command line, we specify the clock to have an initial value ("+ki0.0") of 0.0, as it would have by default. (Since this is the default starting value for clock we would not have had to insert this particular specification but it is included here for completeness.) we then specify the final clock value ("+kf2.0")as 2.0. In the body of our scene file we test the clock value in the if (1*clock < 1) and if it returns true, the translate vector is varied along the X axis. When the variation goes above 1, the else statement comes into effect and the values of the Y portion of the translation vector provide apparent motion in an upward direction.

You may also note that after the lateral travel along X, the value change along the Y axis begins with 1.0. This causes a jump from <1.0, 0.0, 0.0> to <1.0, 1.0, 0.0>and a jerkiness is seen in the motion of the sphere. We will ignore the fact that no object in nature would behave this way naturally. So if we want the sphere to lift in s smooth manner, we need to adjust the clock value as the Y value varies by subtracting 1 from it. Here is the results of just that...

[vect_demo.gif]
#if (1*clock <= 1)
  sphere { <1*clock,0,0>, 1
	 pigment { color Red }
  }
#else
  sphere { <1,1*clock,0>, 1
	 pigment { color Blue }
  }
#end
[vect_demo.gif]
#if (1*clock <= 1)
  sphere { <1*clock,0,0>, 1
	 pigment { color Red }
  }
#else
  sphere { <1,1*clock-1,0>, 1
	 pigment { color Blue }
  }
#end