Working with the Linux Cluster
POV-Ray Animation

by D.W. Hyatt

Using the Cluster to Create an Animation

The Linux Cluster at TJ can significantly speed up the generation of an animation of POV-Ray images. Using the concept of parallel computation to reduce overall execution time, the cluster can start a number of animation frames on different processors, thus generating the graphics simultaneously rather than waiting for one image to complete before the next one begins.

The general approach recommended here is to use the clock variable to define sequential animation scenes, and then spawn a number of UNIX processes using the command fork(), each of which calls a command line with a slightly different POV-ray scripts that are passed to the system() command. From within a loop, the function sprintf() can be used to create the different commands that POV-Ray will use, passing the +K and +O options the loop variable for the appropriate animation frames. In the example below, the character array str[ ] will contain the povray command with whatever loop variable is being executed.

For instance:
    sprintf (str, "povray +K%d  +Ooutfile%d.ppm", loop, loop);
If the value of loop = 3,
the character string str[ ] =   "povray +K3 +Ooutfile3.ppm".
A call to system( str ) will run povray with a clockvalue of 3 and generate an output file called outfile3.ppm as predicted. Of course, the programmer will have to include the other essential parts of the POV-Ray command to see that the file is actually a PPM file type.

The following code is from the Cluster How To example developed by the sysadmins from 1999-2000.

/* forktest.c */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>

int main(void)
{
  char name[10];
  FILE *outfile;
  unsigned int pnum, i, pid;
  double b=1, c=1;

  nice(5);  // The command "nice" will run the program at a lower priority

  for(pnum=0; pnum<16; pnum++)  // Loop through 16 processes
  {
      /* Fork a duplicate child process that starts running at this location
         but with the inherited values of the variables. */ 

      switch (pid=fork())  
      {
        case -1: /* could not fork */
          printf("uh oh.\n");
          exit(1);
          break;

        case 0: /* child process */
          sprintf(name,"file%d",pnum); // Use sprintf to create file name
          outfile = fopen(name,"w");   // Open file for output
          fprintf(outfile,"I am process %d\nMy PID is #%d",pnum,getpid());
          fclose(outfile);

          for(i=pnum << 16;  pnum+1 << 16; i++) 
          {  // Make garbage computations.  Use bit shift to make huge numbers
            b = sin(b*i)+cos(c*i);
            c = sin(c*i)+cos(b*i);
          }
          exit(0);
        default: /* parent process */
          break;
      }
  }

  return 0;
}
The above code can be compiled on the cluster with the following command line. It invokes the gcc compiler on the source file forktest.c and links in the math libraries (-lm). The output file is forktest.
gcc   forktest.c   -o   forktest   -lm