HowTo:Create animations

From POV-Wiki
Jump to navigation Jump to search

Animation is the rapid display of a sequence of images in order to create an illusion of movement (see Wikipedia:Animation). POV-Ray can be used to create such a sequence of images. Creating these images in POV-Ray may be very different from using other graphical tools that you are used to. As with other forms of animation, small sequences can be done quite easily, but when animations grow, a little planning and preparation goes a long way so:

  • Define what it is that interests you (what type of animations do you want to produce)
  • Establish which categories of tool you will need
  • Identify applications that address those needs, attempting to minimise the number of different applications you'll have to learn
  • Join the various communities that use those tools so that you can keep abreast of changes that may impact you


Basics

POV-Ray provides a number of features to help produce a sequence of individual still images but does not put them together into an animation. You'll therefore need a separate piece of software to assemble the animation. There are lots of application programs available that will do this, including several free and open source products. You'll need to pick one that can generate the animation file format you wish to produce, e.g. AVI, MPEG, FLI/FLC, QuickTime, or animated GIF files (popularly used on Web pages). Try Googling animation utilities.

When animating, we use the ini-file (or equivalent command line options) to tell the renderer what frames to render, and what clock values the renderer should use. Our scene file can then use settings such as the clock variable to control the generation of a particular image or 'frame' in the sequence.

+W150
+H150         
Input_File_Name=robot.pov
Initial_Frame=1
Final_Frame=30
Initial_Clock=0
Final_Clock=1

When using the above INI-file, POV-Ray will render 30 frames and the clock variable will run from 0 to 1. The clock setting as defined in the ini-file or on the command line will be available when your scene is parsed at render time as the variable 'clock'. If not specified, the value of the clock variable will pass from 0 to 1 through the animation sequence. The frame number will be available to your scene file as the variable 'frame_number'. To be of interest something should change during the animation, often with each frame. This change is usually controlled by using the clock variable or the frame_number variable in your scene file.

Animating objects

To animate a ball we could use the clock variable to control its attributes, position, orientation etc. For example:

sphere { <0,clock,0>,1 pigment {rgb 1}}
 or
sphere { <0,0,0>,1 translate <0,clock,0> pigment {rgb 1}}

Both examples move a sphere up the Y-axis by a fixed amount per frame.

 sphere { <0,0,0>,0.5*(1+clock) pigment {rgb 1}}

Increases the radius of the sphere from 0.5 units to 1 unit as the animation sequence progresses.

Animating object properties

More interesting behaviour is possible is you imagine everything can be animated. Allthough impossible in the real world you can show how a piece of glass would look if it's index of refraction would slowly change.

Animating the camera

Animating a camera requires some planning when complex movements are required. Smooth movement is possible if you can specify a 'neat' set of position functions, and a flyby look-and-feel is possible if you also take into account gravity, speed and acceleration, so you can adjust the 'roll' of the camera according to the current down direction. This dynamical downdirection is a lineair combination of the gravity vector, and the centrifugal forces caused by direction changes.

Creating complex behaviour

Birds 2 02.gif

When you want to show complex behaviour in your animation, you will have a lot of programming to do. Sometimes however it is not necessary to define everything in detail. Sometimes simple sets of rules (working on a simple set of variables) wil exhibit complex behavior which will nonetheless be recognizable.

It is possible to define an array of object, say birds or fish, setting up variables for position, orientation and speed, and creating a macro to draw them (with this orientation and speed). Now every time a frame is rendered you call the macro which draws all birds or fish, and call a macro which calculates the new state for every object (position, speed) and stores it for use in the next frame. This calculation macro is in fact a simple set of -more or less- high-level rules. Changing these rules, you setup behavior, not exact positions for the objects. You can 'guide' each bird, not exactly, but with simple rules like "stay above the ground" and "if you are going to collide, turn left a bit" you have some control. These sets of rules will generate almost random behavior, which has recognizable dynamics like flocking for birds, traffic-jamming for cars, or bending in the 'wind' for trees.

State variables

The state variables are the core of this method, and you will need to carefully analyse the behavior of the object you are trying to mimic. You the capture these in a simple data structure. You might create something like this:

#declare Blocation = array[max_birds];
#declare Bvelocity = array[max_birds];
#declare Bphase = array[max_birds];

The amount of detail in the dissemination of the object tends to grow in time, see below for further explanation of the phase-parameter.

To make this work you will need to 'transfer' the state of the objects (birds) from each frame to the next. This can easily be done using macro's to write out, and readback the variables to a file on disk. The following macro's can be easily extended to save and load more complex data-sets.

#macro SaveState()    
       #fopen wfile "state.txt" write
       #local i = 0;
       # while (i<max_birds)
               #write ( wfile, Blocation[i], ",", Bvelocity[i], "," , Bphase[i], ",")
               #local i=i+1;                
       #end     
       #fclose file     
#end    

#macro LoadState()    
       #fopen rfile "state.txt" read
       #local i = 0;
       #while (i<max_birds)
               #read ( rfile, Blocation[i] ,Bvelocity[i], Bphase[i] )
               #local i=i+1;                
       #end         
       #fclose file
#end

Drawing the objects

You will need a macro or set of macros to draw the objects into the scene. The macro to draw the object will have to take into account all relevant parameters. For instance a bird rolls when taking a turn, according with it's changing down-vector. Also the wings will have a current state (a phase) which determines where the wings are in the up-down direction.

Rules

In the main file you will want to execute some 'business rules' for every bird to define it's solitary behaviour, and maybe you will want to run some other rules for each bird-pair, so social behaviour can be controlled. These rules act on the state variables, but can also gather information elsewhere provided the variables needed are in scope.

You can embed these rules in a macro which you run each frame. In this macro you could create some intermediate variables, deduced from the state variables to make the rule definition somewhat more comfortable. In the example above, we could define a speed, which is easier to compare than a velocity vector.

#local Speed = vlength(Bvelocity[i]);

Now further on you can create a rule to stop birds from stalling:

// Do not stall
#if (Speed<1) 
    #declare Bvelocity[i]=Bvelocity[i]*1.2; 
#end

Detailed control

As said you cannot control these objects at the position-level using these rules. At rendertime you have access to all the variables so you could do extra checks and 'force then around'. However this will not work at parse-time. Suppose you create a scene with mountains and buildings, and want to add some birds. Now when the birds calculate their 'next move' the information about buildings and mountains is NOT available. Detailed interaction with the scene requires capturing behaviour in rules, and creating an environment where data about say buildings and mountains can be stored. Now the extra rules can act on this data.

More to try

  • You could consider animating things like fish, cars, trees, houses and much more.
  • Try animating different species with specific interactions.

Cyclic animations

Suppose you want to make an animation that loops, so that after the last frame has been rendered it should hop back to the first frame and play everything again. To make the jump from the last to the first frame seamless, the animation must end with exactly the same scene as it started with, i.e. parsing the file with clock = 0 and clock = 1 must generate the same image. When animating this however, you will find a slight glitch in the animation: since the first and last frame are identical it will look like like the animation stops for a while. You could prevent this simply by deleting the last frame after you have rendered them, or only render a subset of the frames to leave out the last one, but POV-ray offers a much better solution. Simply add

Cyclic_Animation=On

to the INI-file, or +KC to the command line. POV-ray will now automatically do the following:

  • Increase the number of frames by one (so if you chose to have 50 frames in the animation, POV-ray will make it 51)
  • but not render the last frame (so you'll still only get 50 images rendered, since the 51st one would be identical to the first)

When these images are compiled into a looping animation, you'll get a nice, smooth, and glitch-free animation. For example, here's how to create an Ogg Theora video file.